Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtTerm / Term / TermAction.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 #ifndef lint
24 #ifdef  VERBOSE_REV_INFO
25 static char rcs_id[] = "$XConsortium: TermAction.c /main/1 1996/04/21 19:15:17 drk $";
26 #endif  /* VERBOSE_REV_INFO */
27 #endif  /* lint */
28
29 /*                                                                      *
30  * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company               *
31  * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
32  * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.                *
33  * (c) Copyright 1993, 1994, 1996 Novell, Inc.                          *
34  * (c) Copyright 1996 Digital Equipment Corporation.                    *
35  * (c) Copyright 1996 FUJITSU LIMITED.                                  *
36  * (c) Copyright 1996 Hitachi.                                          *
37  */
38
39 #include "TermHeader.h"
40 #include "TermPrimDebug.h"
41 #include "TermPrimI.h"
42 #include "TermP.h"
43 #include "TermPrimData.h"
44 /* #include "TermData.h" */
45 #include "TermPrimAction.h"
46 #include "TermAction.h"
47 #include "TermFunction.h"
48 #include "TermPrimSetPty.h"
49 #include "TermSendEsc.h"
50 #ifdef _AIX
51 #include <X11/keysym.h>
52 #endif /* _AIX */
53
54 static char  *KeypadKey[] = { DT_KP_Space, DT_KP_Tab, DT_KP_Enter, DT_KP_F1, 
55                               DT_KP_F2, DT_KP_F3, DT_KP_F4, DT_KP_Equal, 
56                               DT_KP_Multiply, DT_KP_Add, DT_KP_Separator, 
57                               DT_KP_Subtract, DT_KP_Decimal, DT_KP_Divide, 
58                               DT_KP_0, DT_KP_1, DT_KP_2, DT_KP_3, DT_KP_4, 
59                               DT_KP_5, DT_KP_6, DT_KP_7, DT_KP_8, DT_KP_9};
60 static char  *AppKeypadKey[] ={KP_APP_Space, KP_APP_Tab, KP_APP_Enter,KP_APP_F1,
61                               KP_APP_F2, KP_APP_F3, KP_APP_F4, KP_APP_Equal, 
62                               KP_APP_Multiply, KP_APP_Add, KP_APP_Separator,
63                               KP_APP_Subtract, KP_APP_Decimal, KP_APP_Divide,
64                               KP_APP_0, KP_APP_1, KP_APP_2, KP_APP_3, KP_APP_4,
65                               KP_APP_5, KP_APP_6, KP_APP_7, KP_APP_8, KP_APP_9};
66 #ifdef  OBSOLETE
67 static char  *EditKey[] = {ESC_FIND, ESC_INSERT_HERE, ESC_DELETE,
68                            ESC_SELECT, ESC_PREV_SCREEN, ESC_NEXT_SCREEN};
69 static char  *SunEditKey[] = {ESC_FIND_SUN, ESC_INSERT_HERE_SUN, 
70                             ESC_DELETE_SUN, ESC_SELECT_SUN, ESC_PREV_SCREEN_SUN,
71                             ESC_NEXT_SCREEN_SUN};
72 #endif  /* OBSOLETE */
73 void
74 _DtTermWriteEscSeq(Widget w, char *transmitString)
75 {
76     DtTermWidget    tw  = (DtTermWidget)w;
77     DtTermData      td = tw->vt.td;
78
79     if (KEYBOARD_LOCKED(td->tpd->keyboardLocked)) {
80         /* keyboard locked -- ring the bell...
81          */
82         (void) _DtTermPrimBell(w);
83     } else 
84         if ( td->S8C1TMode ) {
85            char *cbuf =malloc(strlen(transmitString)+1);
86            strcpy(cbuf,transmitString) ;
87            cbuf[1] = 0x9B ;
88            (void) _DtTermPrimSendInput(w, (unsigned char *) (cbuf+1),
89                 strlen(cbuf+1));
90            free(cbuf) ;
91          }
92         else {
93            (void) _DtTermPrimSendInput(w, (unsigned char *) transmitString,
94                 strlen(transmitString));
95         }
96     return;
97 }
98
99 typedef struct {
100     const char *string;
101     char value;
102 } EnumType;
103
104 static int
105 stringToEnum(char *c, EnumType *enumTypes, int numEnumTypes)
106 {
107     int i;
108
109     for (i = 0; i < numEnumTypes; i++) {
110         if (!strcmp(enumTypes[i].string, c))
111             return(i);
112     }
113
114     return(-1);
115 }
116
117 \f
118 /*** BREAK ********************************************************************
119  * 
120  *  #####   #####   ######    ##    #    #
121  *  #    #  #    #  #        #  #   #   #
122  *  #####   #    #  #####   #    #  ####
123  *  #    #  #####   #       ######  #  #
124  *  #    #  #   #   #       #    #  #   #
125  *  #####   #    #  ######  #    #  #    #
126  */
127
128 void
129 _DtTermActionBreak(Widget w, XEvent *event, String *params, Cardinal *num_params)
130 {
131     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
132     struct termData *tpd = tw->term.tpd;
133     int msec = 0;
134
135     /* check for keyboardLock... */
136     if (KEYBOARD_LOCKED(tpd->keyboardLocked)) {
137         (void) _DtTermPrimBell(w);
138         return;
139     }
140
141     /* tcsendbreak() , which eventually gets called, has the msec
142        parameter but it never actually gets used, so for now, its a dont care
143      */
144
145     if (tw->term.pty >= 0)
146         (void) _DtTermPrimPtySendBreak(tw->term.pty, msec);
147     return;
148 }
149
150 \f
151 /*** SCROLL *******************************************************************
152  * 
153  *   ####    ####   #####    ####   #       #
154  *  #       #    #  #    #  #    #  #       #
155  *   ####   #       #    #  #    #  #       #
156  *       #  #       #####   #    #  #       #
157  *  #    #  #    #  #   #   #    #  #       #
158  *   ####    ####   #    #   ####   ######  ######
159  */
160
161
162 typedef enum {
163     scrollPage,
164     scrollHalfPage,
165     scrollLine,
166     scrollPixel
167 } ScrollAmount;
168
169 static EnumType scrollUnits[] = {
170     "page",     (char) scrollPage,
171     "halfpage", (char) scrollHalfPage,
172     "line",     (char) scrollLine
173 };
174
175 void
176 _DtTermActionScroll(Widget w, XEvent *event,
177         String *params, Cardinal *num_params)
178 {
179     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
180     struct termData *tpd = tw->term.tpd;
181     int unitsIndex;
182     ScrollAmount units;
183     int count = 1;
184
185     if (*num_params >= 1) {
186         count = strtol(params[0], (char **) 0, 0);
187     }
188
189     if (*num_params >= 2) {
190         unitsIndex = stringToEnum(params[1], scrollUnits,
191                 XtNumber(scrollUnits));
192         if (unitsIndex < 0) {
193             /* no match... */
194             return;
195         }
196         units = (ScrollAmount) scrollUnits[unitsIndex].value;
197     } else {
198         units = scrollLine;
199     }
200
201     /* perform the cursor motion...
202      */
203     switch(units) {
204     case scrollPage:
205             _DtTermFuncScroll(w, count*(tw->term.rows-1), fromAction);
206         break;
207
208     case scrollHalfPage:
209         if (count > 0) {
210             _DtTermFuncScroll(w, count * 
211                   (tw->term.rows - tpd->memoryLockRow) / 2, fromAction);
212         } else {
213             _DtTermFuncScroll(w, 
214                     count * (tw->term.rows - tpd->memoryLockRow) / 2,
215                     fromAction);
216         }
217         break;
218
219     case scrollLine:
220             _DtTermFuncScroll(w, count, fromAction);
221         break;
222     }
223     return;
224 }
225
226 void
227 _DtTermActionBeginningOfBuffer(Widget w, XEvent *event,
228         String *params, Cardinal *num_params)
229 {
230     _DtTermFuncBeginningOfBuffer(w,NULL,1) ;
231     (void) _DtTermPrimCursorOn(w);
232     return;
233 }
234
235 void
236 _DtTermActionEndOfBuffer(Widget w, XEvent *event,
237         String *params, Cardinal *num_params)
238 {
239     _DtTermFuncEndOfBuffer(w,NULL,1) ;
240     (void) _DtTermPrimCursorOn(w);
241     return;
242 }
243
244
245 \f
246 /** HARD/SOFT RESET ***********************************************************
247  *                                       #
248  *  #    #    ##    #####   #####       #    ####    ####   ######   #####
249  *  #    #   #  #   #    #  #    #     #    #       #    #  #          #
250  *  ######  #    #  #    #  #    #    #      ####   #    #  #####      #
251  *  #    #  ######  #####   #    #   #           #  #    #  #          #
252  *  #    #  #    #  #   #   #    #  #       #    #  #    #  #          #
253  *  #    #  #    #  #    #  #####  #         ####    ####   #          #
254  * 
255  * 
256  *  #####   ######   ####   ######   #####
257  *  #    #  #       #       #          #
258  *  #    #  #####    ####   #####      #
259  *  #####   #            #  #          #
260  *  #   #   #       #    #  #          #
261  *  #    #  ######   ####   ######     #
262  */
263 void
264 _DtTermActionHardReset(Widget w, XEvent *event,
265         String *params, Cardinal *num_params)
266 {
267     (void) _DtTermFuncHardReset(w, 0, fromAction);
268 }
269
270 void
271 _DtTermActionSoftReset(Widget w, XEvent *event,
272         String *params, Cardinal *num_params)
273 {
274     (void) _DtTermFuncSoftReset(w, 0, fromAction);
275 }
276
277 \f
278 /*** INSERT CHAR/LINE *********************************************************
279  * 
280  *     #    #    #   ####   ######  #####    #####
281  *     #    ##   #  #       #       #    #     #
282  *     #    # #  #   ####   #####   #    #     #
283  *     #    #  # #       #  #       #####      #
284  *     #    #   ##  #    #  #       #   #      #
285  *     #    #    #   ####   ######  #    #     #
286  * 
287  *                                       #
288  *   ####   #    #    ##    #####       #   #          #    #    #  ######
289  *  #    #  #    #   #  #   #    #     #    #          #    ##   #  #
290  *  #       ######  #    #  #    #    #     #          #    # #  #  #####
291  *  #       #    #  ######  #####    #      #          #    #  # #  #
292  *  #    #  #    #  #    #  #   #   #       #          #    #   ##  #
293  *   ####   #    #  #    #  #    # #        ######     #    #    #  ######
294  */
295
296
297 void
298 _DtTermActionInsertLine(Widget w, XEvent *event,
299         String *params, Cardinal *num_params)
300 {
301     _DtTermFuncInsertLine(w,1,1) ;
302     (void) _DtTermPrimCursorOn(w);
303 }
304
305
306 \f
307 /*** CURSOR MOTION ************************************************************
308  * 
309  *   ####   #    #  #####    ####    ####   #####
310  *  #    #  #    #  #    #  #       #    #  #    #
311  *  #       #    #  #    #   ####   #    #  #    #
312  *  #       #    #  #####        #  #    #  #####
313  *  #    #  #    #  #   #   #    #  #    #  #   #
314  *   ####    ####   #    #   ####    ####   #    #
315  * 
316  * 
317  *  #    #   ####    #####     #     ####   #    #
318  *  ##  ##  #    #     #       #    #    #  ##   #
319  *  # ## #  #    #     #       #    #    #  # #  #
320  *  #    #  #    #     #       #    #    #  #  # #
321  *  #    #  #    #     #       #    #    #  #   ##
322  *  #    #   ####      #       #     ####   #    #
323  */
324
325 typedef enum {
326     cursorForward,
327     cursorBackward,
328     cursorUp,
329     cursorDown
330 } CursorDirection;
331
332 static EnumType cursorDirections[] = {
333     "forward",  (char) cursorForward,
334     "backward", (char) cursorBackward,
335     "up",       (char) cursorUp,
336     "down",     (char) cursorDown
337 };
338
339 void
340 _DtTermActionMoveCursor(Widget w, XEvent *event,
341         String *params, Cardinal *num_params)
342 {
343     int i;
344
345     if (*num_params < 1) {
346         return;
347     }
348
349     /* figure out the direction... */
350     i = stringToEnum(params[0], cursorDirections, XtNumber(cursorDirections));
351     if (i < 0) {
352         /* no match... */
353         return;
354     }
355
356     switch((CursorDirection) cursorDirections[i].value) {
357     case cursorUp:
358         if (((DtTermWidget)w)->vt.td->applicationMode)  
359             (void) _DtTermWriteEscSeq(w, ESC_CURSOR_UP_APP);
360         else
361             (void) _DtTermWriteEscSeq(w, ESC_CURSOR_UP);
362         break;
363
364     case cursorDown:
365         if (((DtTermWidget)w)->vt.td->applicationMode)
366            (void) _DtTermWriteEscSeq(w, ESC_CURSOR_DOWN_APP);
367         else
368            (void) _DtTermWriteEscSeq(w, ESC_CURSOR_DOWN);
369         break;
370
371     case cursorForward:
372         if (((DtTermWidget)w)->vt.td->applicationMode)
373          (void) _DtTermWriteEscSeq(w, ESC_CURSOR_RIGHT_APP);
374         else
375          (void) _DtTermWriteEscSeq(w, ESC_CURSOR_RIGHT);
376         break;
377
378     case cursorBackward:
379         if (((DtTermWidget)w)->vt.td->applicationMode)
380          (void) _DtTermWriteEscSeq(w, ESC_CURSOR_LEFT_APP);
381         else
382          (void) _DtTermWriteEscSeq(w, ESC_CURSOR_LEFT);
383         break;
384     }
385     return;
386 }
387
388
389 void
390 _DtTermActionTab(Widget w, XEvent *event,
391         String *params, Cardinal *num_params)
392 {
393     (void) _DtTermPrimSendInput(w, (unsigned char *) "\t", 1);
394     return;
395 }
396
397 \f
398 /*** FUNCTION KEYS ************************************************************
399  * 
400  *  ######  #    #  #    #   ####    #####     #     ####   #    #
401  *  #       #    #  ##   #  #    #     #       #    #    #  ##   #
402  *  #####   #    #  # #  #  #          #       #    #    #  # #  #
403  *  #       #    #  #  # #  #          #       #    #    #  #  # #
404  *  #       #    #  #   ##  #    #     #       #    #    #  #   ##
405  *  #        ####   #    #   ####      #       #     ####   #    #
406  * 
407  * 
408  *  #    #  ######   #   #   ####
409  *  #   #   #         # #   #
410  *  ####    #####      #     ####
411  *  #  #    #          #         #
412  *  #   #   #          #    #    #
413  *  #    #  ######     #     ####
414  */
415 void
416 _DtTermActionFunctionKeyExecute(Widget w, XEvent *event, String *params,
417         Cardinal *num_params)
418 {
419     Boolean shift = False;
420     long keyNumber;
421     char *ret;
422     int i;
423
424     /* must have a key number, may have a shift/unshift as well... */
425     if (*num_params < 1) {
426         return;
427     }
428
429     /* get a key number... */
430     keyNumber = strtol(params[0], &ret, 0);
431
432
433     /* if we had anything left in the string, the number is bogus... */
434     if (*ret) {
435         return;
436     }
437
438     if (*num_params >= 2) {
439         if (!strcmp(params[1], "UDK")) {
440             shift = True;
441         } else if (!strcmp(params[1], "function")) {
442             shift = False;
443         } else {
444             return;
445         }
446     }
447
448     /* execute the key... */
449     (void) _DtTermFunctionKeyExecute(w, (short) keyNumber, shift);
450     return;
451 }
452
453
454 /**************************************************************************
455  *
456  *  KEYPAD 
457  *
458  */
459
460 static char *kpTypes[] = { "space", "tab",  "enter", "f1",  "f2", "f3", "f4",
461    "equal",   "multiply", "add",  "separator", "subtract", "decimal", "divide",
462    "0",  "1",  "2", "3", "4", "5", "6",  "7", "8", "9"  
463 };
464 static int no_kptypes=sizeof(kpTypes)/sizeof(char *) ;
465
466 void
467 _DtTermActionKeypadKeyExecute(Widget w, XEvent *event, String *params,
468         Cardinal *num_params)
469 {
470     DtTermWidget    tw  = (DtTermWidget)w;
471     Boolean shift = False;
472     long keyNumber;
473     char *ret;
474     int type;
475     DtTermData  td = tw->vt.td;
476
477     if (KEYBOARD_LOCKED(td->tpd->keyboardLocked)) {
478         /* keyboard locked -- ring the bell...
479          */
480         (void) _DtTermPrimBell(w);
481                return ;
482      }
483     /* must have an edit key type... */
484     if (*num_params < 1) {
485         return;
486     }
487 #ifdef _AIX
488     /*
489      * IBM JP kbd specific code. IBM JP kbd requires IM functionality
490      * to recoginze NumLock state + (*,/) key
491      *
492      * The following code is derived from TermPrim/TermPrim.c's
493      * _DtTermPrimActionKeyInput()
494      *
495      */
496     {
497         XKeyEvent     *keyEvent = (XKeyEvent *)event;
498         KeySym        keysym;
499         Status        status;
500         unsigned char string[BUFSIZ];
501         int           nbytes;
502
503         nbytes = XmImMbLookupString(w, keyEvent, (char *) string,
504                         sizeof(string), &keysym, &status);
505
506         /*
507          * Usually we have to take care of the status. Yet, this function is
508          * called only when KP_XX is pressed. So in this case, ignore any
509          * error case..... Please keep your fingers crossed !
510          */
511
512         /*
513          * Hack code........
514          */
515         if ( ( keysym == XK_KP_Add ) || ( keysym == XK_KP_Multiply ) ) {
516             if ( string[0] == '*' )
517                 params[0] = "multiply";
518             else if ( string[0] == '+' )
519                 params[0] = "add";
520         }
521     }
522 #endif /* _AIX */
523
524     type=0;
525     while( strcmp(params[0],kpTypes[type]) && type<= no_kptypes )  type++;
526
527     if (type > no_kptypes) return ;
528
529     if ( tw->vt.td->applicationKPMode ) {
530        _DtTermWriteEscSeq(w,AppKeypadKey[type]);
531      }
532     else {
533        _DtTermPrimSendInput(w,(unsigned char *)KeypadKey[type],
534                           strlen(KeypadKey[type]));
535        if ( type == 2 && tw->term.tpd->autoLineFeed )
536                  _DtTermPrimSendInput(w,(unsigned char *)"\012",1);/* newline */
537      }
538 }
539
540 /***********************************************************************
541  * 
542  *  Edit Keys (Find, Insert Here, Remove, Select, Prev Screen, Next Screen)
543  *
544  */
545
546 typedef enum {
547     findType,   
548     insertType,     
549     selectType,
550     priorType,
551     nextType,
552     deleteType,
553     removeType,
554     helpType,
555     menuType,
556     doType
557 } EditType;
558
559 static EnumType editTypes[] = {
560     "find",     (char) findType,
561     "insert", (char) insertType,     
562     "select",   (char) selectType, 
563     "next",    (char) nextType,    
564     "prior",   (char) priorType,  
565     "delete",  (char) deleteType,
566     "remove",  (char) removeType,
567     "help",    (char) helpType,
568     "menu",    (char) menuType,
569     "do",      (char) doType
570 };
571
572 void
573 _DtTermActionEditKeyExecute(Widget w, XEvent *event, String *params,
574         Cardinal *num_params)
575 {
576     DtTermWidget    tw  = (DtTermWidget)w;
577     Boolean shift = False;
578     long keyNumber;
579     char *ret;
580     int i;
581     DtTermData      td = tw->vt.td;
582
583     if (*num_params < 1) {
584         return;
585     }
586
587     /* figure out the direction... */
588     i = stringToEnum(params[0], editTypes, XtNumber(editTypes));
589     if (i < 0) {
590         /* no match... */
591         return;
592     }
593
594     switch( editTypes[i].value) {
595             case findType:  
596                     if ( tw->vt.sunFunctionKeys == False) {
597                       (void) _DtTermWriteEscSeq(w, ESC_FIND) ;
598                      }
599                     else {
600                       (void) _DtTermWriteEscSeq(w,ESC_FIND_SUN);
601                      }
602                     break;
603             case insertType:
604                     if ( tw->vt.sunFunctionKeys == False) {
605                       (void) _DtTermWriteEscSeq(w, ESC_INSERT_HERE) ;
606                      }
607                     else {
608                       (void) _DtTermWriteEscSeq(w,ESC_INSERT_HERE_SUN);
609                      }
610                     break;
611             case selectType:
612                     if ( tw->vt.sunFunctionKeys == False) {
613                       (void) _DtTermWriteEscSeq(w, ESC_SELECT) ;
614                      }
615                     else {
616                       (void) _DtTermWriteEscSeq(w,ESC_SELECT_SUN);
617                      }
618                     break;
619             case priorType:
620                     if ( tw->vt.sunFunctionKeys == False) {
621                       (void) _DtTermWriteEscSeq(w, ESC_PREV_SCREEN) ;
622                      }
623                     else {
624                       (void) _DtTermWriteEscSeq(w,ESC_PREV_SCREEN_SUN);
625                      }
626                     break;
627             case nextType:
628                     if ( tw->vt.sunFunctionKeys == False) {
629                       (void) _DtTermWriteEscSeq(w, ESC_NEXT_SCREEN) ;
630                      }
631                     else {
632                       (void) _DtTermWriteEscSeq(w,ESC_NEXT_SCREEN_SUN);
633                      }
634                     break;
635             case deleteType:
636             case removeType:
637                     if ( tw->vt.sunFunctionKeys == False) {
638                       (void) _DtTermWriteEscSeq(w, ESC_DELETE) ;
639                      }
640                     else {
641                       (void) _DtTermWriteEscSeq(w,ESC_DELETE_SUN);
642                      }
643                     break;
644
645             case helpType:
646                     if (tw->vt.sunFunctionKeys == False) {
647                         (void) _DtTermWriteEscSeq(w, ESC_HELP);
648                     } else {
649                         (void) _DtTermWriteEscSeq(w, ESC_HELP_SUN);
650                     }
651                     break;
652
653             case menuType:
654                     if (tw->vt.sunFunctionKeys == False) {
655                         (void) _DtTermWriteEscSeq(w, ESC_MENU);
656                     } else {
657                         (void) _DtTermWriteEscSeq(w, ESC_MENU_SUN);
658                     }
659                     break;
660
661             case doType:
662                     if (tw->vt.sunFunctionKeys == False) {
663                         (void) _DtTermWriteEscSeq(w, ESC_DO);
664                     } else {
665                         (void) _DtTermWriteEscSeq(w, ESC_DO_SUN);
666                     }
667                     break;
668        
669        }
670 }