/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* * * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company * * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. * * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc. * * (c) Copyright 1993, 1994, 1996 Novell, Inc. * * (c) Copyright 1996 Digital Equipment Corporation. * * (c) Copyright 1996 FUJITSU LIMITED. * * (c) Copyright 1996 Hitachi. * */ #include "TermHeader.h" #include "TermPrimDebug.h" #include "TermPrimI.h" #include "TermP.h" #include "TermPrimData.h" /* #include "TermData.h" */ #include "TermPrimAction.h" #include "TermAction.h" #include "TermFunction.h" #include "TermPrimSetPty.h" #include "TermSendEsc.h" #ifdef _AIX #include #endif /* _AIX */ static char *KeypadKey[] = { DT_KP_Space, DT_KP_Tab, DT_KP_Enter, DT_KP_F1, DT_KP_F2, DT_KP_F3, DT_KP_F4, DT_KP_Equal, DT_KP_Multiply, DT_KP_Add, DT_KP_Separator, DT_KP_Subtract, DT_KP_Decimal, DT_KP_Divide, DT_KP_0, DT_KP_1, DT_KP_2, DT_KP_3, DT_KP_4, DT_KP_5, DT_KP_6, DT_KP_7, DT_KP_8, DT_KP_9}; static char *AppKeypadKey[] ={KP_APP_Space, KP_APP_Tab, KP_APP_Enter,KP_APP_F1, KP_APP_F2, KP_APP_F3, KP_APP_F4, KP_APP_Equal, KP_APP_Multiply, KP_APP_Add, KP_APP_Separator, KP_APP_Subtract, KP_APP_Decimal, KP_APP_Divide, KP_APP_0, KP_APP_1, KP_APP_2, KP_APP_3, KP_APP_4, KP_APP_5, KP_APP_6, KP_APP_7, KP_APP_8, KP_APP_9}; #ifdef OBSOLETE static char *EditKey[] = {ESC_FIND, ESC_INSERT_HERE, ESC_DELETE, ESC_SELECT, ESC_PREV_SCREEN, ESC_NEXT_SCREEN}; static char *SunEditKey[] = {ESC_FIND_SUN, ESC_INSERT_HERE_SUN, ESC_DELETE_SUN, ESC_SELECT_SUN, ESC_PREV_SCREEN_SUN, ESC_NEXT_SCREEN_SUN}; #endif /* OBSOLETE */ void _DtTermWriteEscSeq(Widget w, char *transmitString) { DtTermWidget tw = (DtTermWidget)w; DtTermData td = tw->vt.td; if (KEYBOARD_LOCKED(td->tpd->keyboardLocked)) { /* keyboard locked -- ring the bell... */ (void) _DtTermPrimBell(w); } else if ( td->S8C1TMode ) { char *cbuf =malloc(strlen(transmitString)+1); strcpy(cbuf,transmitString) ; cbuf[1] = 0x9B ; (void) _DtTermPrimSendInput(w, (unsigned char *) (cbuf+1), strlen(cbuf+1)); free(cbuf) ; } else { (void) _DtTermPrimSendInput(w, (unsigned char *) transmitString, strlen(transmitString)); } return; } typedef struct { const char *string; char value; } EnumType; static int stringToEnum(char *c, EnumType *enumTypes, int numEnumTypes) { int i; for (i = 0; i < numEnumTypes; i++) { if (!strcmp(enumTypes[i].string, c)) return(i); } return(-1); } /*** BREAK ******************************************************************** * * ##### ##### ###### ## # # * # # # # # # # # # * ##### # # ##### # # #### * # # ##### # ###### # # * # # # # # # # # # * ##### # # ###### # # # # */ void _DtTermActionBreak(Widget w, XEvent *event, String *params, Cardinal *num_params) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; struct termData *tpd = tw->term.tpd; int msec = 0; /* check for keyboardLock... */ if (KEYBOARD_LOCKED(tpd->keyboardLocked)) { (void) _DtTermPrimBell(w); return; } /* tcsendbreak() , which eventually gets called, has the msec parameter but it never actually gets used, so for now, its a dont care */ if (tw->term.pty >= 0) (void) _DtTermPrimPtySendBreak(tw->term.pty, msec); return; } /*** SCROLL ******************************************************************* * * #### #### ##### #### # # * # # # # # # # # # * #### # # # # # # # * # # ##### # # # # * # # # # # # # # # # * #### #### # # #### ###### ###### */ typedef enum { scrollPage, scrollHalfPage, scrollLine, scrollPixel } ScrollAmount; static EnumType scrollUnits[] = { { "page", (char) scrollPage, }, { "halfpage", (char) scrollHalfPage, }, { "line", (char) scrollLine }, }; void _DtTermActionScroll(Widget w, XEvent *event, String *params, Cardinal *num_params) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; struct termData *tpd = tw->term.tpd; int unitsIndex; ScrollAmount units; int count = 1; if (*num_params >= 1) { count = strtol(params[0], (char **) 0, 0); } if (*num_params >= 2) { unitsIndex = stringToEnum(params[1], scrollUnits, XtNumber(scrollUnits)); if (unitsIndex < 0) { /* no match... */ return; } units = (ScrollAmount) scrollUnits[unitsIndex].value; } else { units = scrollLine; } /* perform the cursor motion... */ switch(units) { case scrollPage: _DtTermFuncScroll(w, count*(tw->term.rows-1), fromAction); break; case scrollHalfPage: if (count > 0) { _DtTermFuncScroll(w, count * (tw->term.rows - tpd->memoryLockRow) / 2, fromAction); } else { _DtTermFuncScroll(w, count * (tw->term.rows - tpd->memoryLockRow) / 2, fromAction); } break; case scrollLine: _DtTermFuncScroll(w, count, fromAction); break; } return; } void _DtTermActionBeginningOfBuffer(Widget w, XEvent *event, String *params, Cardinal *num_params) { _DtTermFuncBeginningOfBuffer(w,0,1) ; (void) _DtTermPrimCursorOn(w); return; } void _DtTermActionEndOfBuffer(Widget w, XEvent *event, String *params, Cardinal *num_params) { _DtTermFuncEndOfBuffer(w,0,1) ; (void) _DtTermPrimCursorOn(w); return; } /** HARD/SOFT RESET *********************************************************** * # * # # ## ##### ##### # #### #### ###### ##### * # # # # # # # # # # # # # # * ###### # # # # # # # #### # # ##### # * # # ###### ##### # # # # # # # # * # # # # # # # # # # # # # # # * # # # # # # ##### # #### #### # # * * * ##### ###### #### ###### ##### * # # # # # # * # # ##### #### ##### # * ##### # # # # * # # # # # # # * # # ###### #### ###### # */ void _DtTermActionHardReset(Widget w, XEvent *event, String *params, Cardinal *num_params) { (void) _DtTermFuncHardReset(w, 0, fromAction); } void _DtTermActionSoftReset(Widget w, XEvent *event, String *params, Cardinal *num_params) { (void) _DtTermFuncSoftReset(w, 0, fromAction); } /*** INSERT CHAR/LINE ********************************************************* * * # # # #### ###### ##### ##### * # ## # # # # # # * # # # # #### ##### # # # * # # # # # # ##### # * # # ## # # # # # # * # # # #### ###### # # # * * # * #### # # ## ##### # # # # # ###### * # # # # # # # # # # # ## # # * # ###### # # # # # # # # # # ##### * # # # ###### ##### # # # # # # # * # # # # # # # # # # # # ## # * #### # # # # # # # ###### # # # ###### */ void _DtTermActionInsertLine(Widget w, XEvent *event, String *params, Cardinal *num_params) { _DtTermFuncInsertLine(w,1,1) ; (void) _DtTermPrimCursorOn(w); } /*** CURSOR MOTION ************************************************************ * * #### # # ##### #### #### ##### * # # # # # # # # # # # * # # # # # #### # # # # * # # # ##### # # # ##### * # # # # # # # # # # # # * #### #### # # #### #### # # * * * # # #### ##### # #### # # * ## ## # # # # # # ## # * # ## # # # # # # # # # # * # # # # # # # # # # # * # # # # # # # # # ## * # # #### # # #### # # */ typedef enum { cursorForward, cursorBackward, cursorUp, cursorDown } CursorDirection; static EnumType cursorDirections[] = { { "forward", (char) cursorForward, }, { "backward", (char) cursorBackward, }, { "up", (char) cursorUp, }, { "down", (char) cursorDown }, }; void _DtTermActionMoveCursor(Widget w, XEvent *event, String *params, Cardinal *num_params) { int i; if (*num_params < 1) { return; } /* figure out the direction... */ i = stringToEnum(params[0], cursorDirections, XtNumber(cursorDirections)); if (i < 0) { /* no match... */ return; } switch((CursorDirection) cursorDirections[i].value) { case cursorUp: if (((DtTermWidget)w)->vt.td->applicationMode) (void) _DtTermWriteEscSeq(w, ESC_CURSOR_UP_APP); else (void) _DtTermWriteEscSeq(w, ESC_CURSOR_UP); break; case cursorDown: if (((DtTermWidget)w)->vt.td->applicationMode) (void) _DtTermWriteEscSeq(w, ESC_CURSOR_DOWN_APP); else (void) _DtTermWriteEscSeq(w, ESC_CURSOR_DOWN); break; case cursorForward: if (((DtTermWidget)w)->vt.td->applicationMode) (void) _DtTermWriteEscSeq(w, ESC_CURSOR_RIGHT_APP); else (void) _DtTermWriteEscSeq(w, ESC_CURSOR_RIGHT); break; case cursorBackward: if (((DtTermWidget)w)->vt.td->applicationMode) (void) _DtTermWriteEscSeq(w, ESC_CURSOR_LEFT_APP); else (void) _DtTermWriteEscSeq(w, ESC_CURSOR_LEFT); break; } return; } void _DtTermActionTab(Widget w, XEvent *event, String *params, Cardinal *num_params) { (void) _DtTermPrimSendInput(w, (unsigned char *) "\t", 1); return; } /*** FUNCTION KEYS ************************************************************ * * ###### # # # # #### ##### # #### # # * # # # ## # # # # # # # ## # * ##### # # # # # # # # # # # # # * # # # # # # # # # # # # # # * # # # # ## # # # # # # # ## * # #### # # #### # # #### # # * * * # # ###### # # #### * # # # # # # * #### ##### # #### * # # # # # * # # # # # # * # # ###### # #### */ void _DtTermActionFunctionKeyExecute(Widget w, XEvent *event, String *params, Cardinal *num_params) { Boolean shift = False; long keyNumber; char *ret; int i; /* must have a key number, may have a shift/unshift as well... */ if (*num_params < 1) { return; } /* get a key number... */ keyNumber = strtol(params[0], &ret, 0); /* if we had anything left in the string, the number is bogus... */ if (*ret) { return; } if (*num_params >= 2) { if (!strcmp(params[1], "UDK")) { shift = True; } else if (!strcmp(params[1], "function")) { shift = False; } else { return; } } /* execute the key... */ (void) _DtTermFunctionKeyExecute(w, (short) keyNumber, shift); return; } /************************************************************************** * * KEYPAD * */ static char *kpTypes[] = { "space", "tab", "enter", "f1", "f2", "f3", "f4", "equal", "multiply", "add", "separator", "subtract", "decimal", "divide", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static int no_kptypes=sizeof(kpTypes)/sizeof(char *) ; void _DtTermActionKeypadKeyExecute(Widget w, XEvent *event, String *params, Cardinal *num_params) { DtTermWidget tw = (DtTermWidget)w; Boolean shift = False; long keyNumber; char *ret; int type; DtTermData td = tw->vt.td; if (KEYBOARD_LOCKED(td->tpd->keyboardLocked)) { /* keyboard locked -- ring the bell... */ (void) _DtTermPrimBell(w); return ; } /* must have an edit key type... */ if (*num_params < 1) { return; } #ifdef _AIX /* * IBM JP kbd specific code. IBM JP kbd requires IM functionality * to recoginze NumLock state + (*,/) key * * The following code is derived from TermPrim/TermPrim.c's * _DtTermPrimActionKeyInput() * */ { XKeyEvent *keyEvent = (XKeyEvent *)event; KeySym keysym; Status status; unsigned char string[BUFSIZ]; int nbytes; nbytes = XmImMbLookupString(w, keyEvent, (char *) string, sizeof(string), &keysym, &status); /* * Usually we have to take care of the status. Yet, this function is * called only when KP_XX is pressed. So in this case, ignore any * error case..... Please keep your fingers crossed ! */ /* * Hack code........ */ if ( ( keysym == XK_KP_Add ) || ( keysym == XK_KP_Multiply ) ) { if ( string[0] == '*' ) params[0] = "multiply"; else if ( string[0] == '+' ) params[0] = "add"; } } #endif /* _AIX */ type=0; while( strcmp(params[0],kpTypes[type]) && type<= no_kptypes ) type++; if (type > no_kptypes) return ; if ( tw->vt.td->applicationKPMode ) { _DtTermWriteEscSeq(w,AppKeypadKey[type]); } else { _DtTermPrimSendInput(w,(unsigned char *)KeypadKey[type], strlen(KeypadKey[type])); if ( type == 2 && tw->term.tpd->autoLineFeed ) _DtTermPrimSendInput(w,(unsigned char *)"\012",1);/* newline */ } } /*********************************************************************** * * Edit Keys (Find, Insert Here, Remove, Select, Prev Screen, Next Screen) * */ typedef enum { findType, insertType, selectType, priorType, nextType, deleteType, removeType, helpType, menuType, doType } EditType; static EnumType editTypes[] = { { "find", (char) findType, }, { "insert", (char) insertType, }, { "select", (char) selectType, }, { "next", (char) nextType, }, { "prior", (char) priorType, }, { "delete", (char) deleteType, }, { "remove", (char) removeType, }, { "help", (char) helpType, }, { "menu", (char) menuType, }, { "do", (char) doType }, }; void _DtTermActionEditKeyExecute(Widget w, XEvent *event, String *params, Cardinal *num_params) { DtTermWidget tw = (DtTermWidget)w; Boolean shift = False; long keyNumber; char *ret; int i; if (*num_params < 1) { return; } /* figure out the direction... */ i = stringToEnum(params[0], editTypes, XtNumber(editTypes)); if (i < 0) { /* no match... */ return; } switch( editTypes[i].value) { case findType: if ( tw->vt.sunFunctionKeys == False) { (void) _DtTermWriteEscSeq(w, ESC_FIND) ; } else { (void) _DtTermWriteEscSeq(w,ESC_FIND_SUN); } break; case insertType: if ( tw->vt.sunFunctionKeys == False) { (void) _DtTermWriteEscSeq(w, ESC_INSERT_HERE) ; } else { (void) _DtTermWriteEscSeq(w,ESC_INSERT_HERE_SUN); } break; case selectType: if ( tw->vt.sunFunctionKeys == False) { (void) _DtTermWriteEscSeq(w, ESC_SELECT) ; } else { (void) _DtTermWriteEscSeq(w,ESC_SELECT_SUN); } break; case priorType: if ( tw->vt.sunFunctionKeys == False) { (void) _DtTermWriteEscSeq(w, ESC_PREV_SCREEN) ; } else { (void) _DtTermWriteEscSeq(w,ESC_PREV_SCREEN_SUN); } break; case nextType: if ( tw->vt.sunFunctionKeys == False) { (void) _DtTermWriteEscSeq(w, ESC_NEXT_SCREEN) ; } else { (void) _DtTermWriteEscSeq(w,ESC_NEXT_SCREEN_SUN); } break; case deleteType: case removeType: if ( tw->vt.sunFunctionKeys == False) { (void) _DtTermWriteEscSeq(w, ESC_DELETE) ; } else { (void) _DtTermWriteEscSeq(w,ESC_DELETE_SUN); } break; case helpType: if (tw->vt.sunFunctionKeys == False) { (void) _DtTermWriteEscSeq(w, ESC_HELP); } else { (void) _DtTermWriteEscSeq(w, ESC_HELP_SUN); } break; case menuType: if (tw->vt.sunFunctionKeys == False) { (void) _DtTermWriteEscSeq(w, ESC_MENU); } else { (void) _DtTermWriteEscSeq(w, ESC_MENU_SUN); } break; case doType: if (tw->vt.sunFunctionKeys == False) { (void) _DtTermWriteEscSeq(w, ESC_DO); } else { (void) _DtTermWriteEscSeq(w, ESC_DO_SUN); } break; } }