libDtSearch: Coverity 86579
[oweals/cde.git] / cde / lib / DtTerm / Term / TermFunction.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 libraries 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[] = "$TOG: TermFunction.c /main/2 1998/03/16 14:41:27 mgreess $";
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 "TermBuffer.h"
44 #include "TermData.h"
45 #include "TermPrimData.h"
46 #include "TermFunction.h"
47 #include "TermPrimSetPty.h"
48 #include "TermPrimMessageCatI.h"
49 #include "TermPrimParserP.h" 
50 #include "TermParseTable.h"
51
52 static void
53 termFuncErase
54 (
55     Widget         w,
56     int            count,
57     DtEraseMode    eraseSwitch,
58     FunctionSource functionSource
59 );
60
61
62 \f
63 /*** SCROLL *******************************************************************
64  * 
65  *   ####    ####   #####    ####   #       #
66  *  #       #    #  #    #  #    #  #       #
67  *   ####   #       #    #  #    #  #       #
68  *       #  #       #####   #    #  #       #
69  *  #    #  #    #  #   #   #    #  #       #
70  *   ####    ####   #    #   ####   ######  ######
71  */
72 #define EXIT_IF_MARGINS_SET(w) if( (w)->term.tpd->scrollLockTopRow != 0 ||  \
73                                    (w)->term.tpd->scrollLockBottomRow !=    \
74                                              (w)->term.rows-1 )   \
75                                     return;
76
77 static void
78 doScroll(Widget w, short lines)
79 {
80     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
81     struct termData *tpd = tw->term.tpd;
82     short newtop;
83
84     EXIT_IF_MARGINS_SET(tw)
85     newtop = tpd->topRow + lines;
86     /* don't go past top of active buffer or past end of history buffer */
87     if (newtop>0) newtop=0;  
88     if (newtop<-tpd->lastUsedHistoryRow) newtop=-tpd->lastUsedHistoryRow;         
89     /* perform scroll... */
90     (void) _DtTermPrimScrollTextTo(w, newtop);  
91     (void) _DtTermPrimScrollComplete((Widget) tw, True);
92 }
93
94
95 void
96 _DtTermFuncScroll(Widget w, int count, FunctionSource functionSource)
97 {
98     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
99     struct termData *tpd = tw->term.tpd;
100
101     /* make sure the cursor is off... */
102     (void) _DtTermPrimCursorOff(w);
103
104     /* and scroll the text... */
105     (void) doScroll(w, count);
106     (void) _DtTermPrimCursorOn(w);
107     return;
108 }
109
110 void
111 _DtTermFuncBeginningOfBuffer(Widget w, int count, FunctionSource functionSource)
112 {
113     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
114     DtTermWidget vtw = (DtTermWidget) w;
115     struct termData *tpd = tw->term.tpd;
116
117     EXIT_IF_MARGINS_SET(tw)
118     /* make sure the cursor is off... */
119     (void) _DtTermPrimCursorOff(w);
120     (void) _DtTermPrimScrollTextTo(w, -tpd->lastUsedHistoryRow);
121     (void) _DtTermPrimScrollComplete((Widget) tw, True);
122     (void) _DtTermPrimCursorOn(w);
123 }
124
125 void
126 _DtTermFuncEndOfBuffer(Widget w, int count, FunctionSource functionSource)
127 {
128     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
129     struct termData *tpd = tw->term.tpd;
130
131     EXIT_IF_MARGINS_SET(tw)
132     (void) _DtTermPrimCursorOff(w);
133     (void) _DtTermPrimScrollTextTo(w, 0);
134     (void) _DtTermPrimScrollComplete((Widget) tw, True);
135     (void) _DtTermPrimCursorOn(w);
136 }
137
138 \f
139 /*** CLEAR MEMORY / LINE ******************************************************
140  * 
141  *   ####   #       ######    ##    #####
142  *  #    #  #       #        #  #   #    #
143  *  #       #       #####   #    #  #    #
144  *  #       #       #       ######  #####
145  *  #    #  #       #       #    #  #   #
146  *   ####   ######  ######  #    #  #    #
147  * 
148  *                               #
149  *  #    #  ######  #    #      #   #          #    #    #  ######
150  *  ##  ##  #       ##  ##     #    #          #    ##   #  #
151  *  # ## #  #####   # ## #    #     #          #    # #  #  #####
152  *  #    #  #       #    #   #      #          #    #  # #  #
153  *  #    #  #       #    #  #       #          #    #   ##  #
154  *  #    #  ######  #    # #        ######     #    #    #  ######
155  */
156
157 static void
158 clearToEndOfMemory(Widget w)
159 {
160     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
161     struct termData *tpd = tw->term.tpd;
162     int i;
163
164     /* clear from current cursor to end of memory... */
165     if (tpd->cursorRow + tpd->topRow < tpd->lastUsedRow) {
166         /* clear the current line to end of memory... */
167         (void) _DtTermPrimBufferClearLine(tpd->termBuffer,
168                 tpd->topRow + tpd->cursorRow, tpd->cursorColumn);
169         
170         /* clear the next line to the end of memory... */
171         for (i = tpd->topRow + tpd->cursorRow + 1; i < tpd->lastUsedRow; i++)
172             (void) _DtTermPrimBufferClearLine(tpd->termBuffer, i, 0);
173
174         /* render the current line from cursor to end of line... */
175         (void) _DtTermPrimRefreshText(w, tpd->cursorColumn, tpd->cursorRow,
176                 tw->term.columns, tpd->cursorRow);
177
178         /* render the rest of the lines... */
179         if (tpd->cursorRow + 1 < tw->term.rows) {
180             (void) _DtTermPrimRefreshText(w, 0, tpd->cursorRow + 1,
181                     tw->term.columns, tw->term.rows - 1);
182         }
183
184         /* set the lastUsedRow... */
185         if (tpd->cursorRow > tpd->memoryLockRow) {
186             if (tpd->cursorColumn == 0) {
187                 /* don't count the current line -- lastUsedRow is the
188                  * line above...
189                  */
190                 tpd->lastUsedRow = tpd->topRow + tpd->cursorRow;
191             } else {
192                 tpd->lastUsedRow = tpd->topRow + tpd->cursorRow + 1;
193             }
194         } else  {
195             tpd->lastUsedRow = tpd->topRow + tpd->memoryLockRow + 1;
196         }
197     }
198     return;
199 }
200             
201 /*
202 ** Erase characters on the specified row (and clear the enhancements) with
203 ** the appropriate semantics.  For VT class emulators, there are several
204 ** ways to erase characters:
205 **      - from the active position to the end of line
206 **      - erase the specified number of characters starting at the current
207 **        cursor position
208 **      - from the start of the line to the active position
209 **      - erase the entire line
210 **      - from the active position to the end of the buffer
211 **      - erase the specified number of lines starting at the current
212 **        cursor position
213 **      - from the start of the buffer to the active position
214 **      - erase the entire buffer
215 **
216 ** We handle the easy stuff here, and pass the rest to _DtTermBufferErase.
217 */
218 static void
219 termFuncErase
220 (
221     Widget         w,
222     int            count,
223     DtEraseMode    eraseSwitch,
224     FunctionSource functionSource
225 )
226 {
227     DtTermPrimitiveWidget tw  = (DtTermPrimitiveWidget) w;
228     DtTermPrimData        tpd = tw->term.tpd;
229     TermBuffer            tb  = tpd->termBuffer;
230     short row;
231     short col;
232
233     row = tpd->cursorRow + tpd->topRow;
234     col = tpd->cursorColumn;
235     
236     switch(eraseSwitch)
237     {
238       case eraseToEOL:
239         /*
240         ** erase from the current cursor position to the end of the line
241         */
242         _DtTermFuncClearToEndOfLine(w, 1, functionSource);
243         break;
244
245       case eraseLine:
246         /*
247         ** erase the current line
248         */
249         _DtTermFuncClearLine(w, 1, functionSource);
250         break;
251
252       case eraseToEOB:
253         (void) _DtTermFuncClearToEndOfBuffer(w, 1, functionSource);
254         break;
255
256       case eraseFromRow0Col0:
257         /*
258         ** first clear all lines from the top of the screen upto the
259         ** current line...
260         */
261         row = tpd->cursorRow;
262         col = tpd->cursorColumn;
263
264         tpd->cursorColumn = 0;
265         for (tpd->cursorRow = tpd->topRow;
266              tpd->cursorRow < row;
267              tpd->cursorRow++)
268         {
269             _DtTermFuncClearLine(w, 1, functionSource);
270         }
271         tpd->cursorRow    = row;
272         tpd->cursorColumn = col;
273
274         /*
275         ** now clear all characters from col 0 to the current cursor position
276         ** on the current line...
277         */
278         _DtTermBufferErase(((DtTermPrimitiveWidget)w)->term.tpd->termBuffer, 
279                            tpd->cursorRow + tpd->topRow, tpd->cursorColumn,
280                            count, eraseFromCol0);
281
282         (void) _DtTermPrimRefreshText(w, 0, tpd->cursorRow,
283                     tpd->cursorColumn + 1 + (tpd->mbCurMax > 1 ? 1:0),
284                     tpd->cursorRow);
285         break;
286
287       case eraseBuffer:
288         (void) _DtTermFuncClearBuffer(w, 0, functionSource);
289         break;
290
291       case eraseFromCol0:
292         _DtTermBufferErase(((DtTermPrimitiveWidget)w)->term.tpd->termBuffer, 
293                            tpd->cursorRow + tpd->topRow, tpd->cursorColumn,
294                            count, eraseSwitch);
295         (void) _DtTermPrimRefreshText(w, 0, tpd->cursorRow,
296                     tpd->cursorColumn + 1 + (tpd->mbCurMax > 1 ? 1:0),
297                     tpd->cursorRow);
298       case eraseCharCount:
299         _DtTermBufferErase(((DtTermPrimitiveWidget)w)->term.tpd->termBuffer, 
300                            tpd->cursorRow + tpd->topRow, tpd->cursorColumn,
301                            count, eraseSwitch);
302         (void) _DtTermPrimRefreshText(w, 
303                     tpd->cursorColumn - (tpd->mbCurMax > 1 ? 1:0),
304                     tpd->cursorRow,
305                     tpd->cursorColumn + count + (tpd->mbCurMax > 1 ? 1:0),
306                     tpd->cursorRow);
307         break;
308     }
309 }
310
311 void
312 _DtTermFuncEraseInDisplay
313 (
314     Widget         w,
315     int            count,
316     FunctionSource functionSource
317 )
318 {
319     termFuncErase(w, 0, (DtEraseMode)count, functionSource);
320 }
321
322 void
323 _DtTermFuncEraseInLine
324 (
325     Widget         w,
326     int            count,
327     FunctionSource functionSource
328 )
329 {
330     termFuncErase(w, 0, (DtEraseMode)count, functionSource);
331 }
332
333 void
334 _DtTermFuncEraseCharacter
335 (
336     Widget         w,
337     int            count,
338     FunctionSource functionSource
339 )
340 {
341     termFuncErase(w, count, eraseCharCount, functionSource);
342 }
343
344 void
345 _DtTermFuncClearToEndOfBuffer(Widget w, int count, FunctionSource functionSource)
346 {
347     DtTermPrimitiveWidget      tw        = (DtTermPrimitiveWidget) w;
348     DtTermPrimData        tpd        = tw->term.tpd;
349     short trow ;
350
351     /* turn the cursor off... */
352     (void) _DtTermPrimCursorOff(w);
353
354     (void) clearToEndOfMemory(w);
355 }
356
357
358 void
359 _DtTermFuncClearBuffer(Widget w, int count, FunctionSource functionSource)
360 {
361     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
362     DtTermWidget vtw = (DtTermWidget) w;
363     struct termData *tpd = tw->term.tpd;
364     int i;
365
366     /* turn the cursor off... */
367     (void) _DtTermPrimCursorOff(w);
368
369     /* move the cursor to the first line after locked memory... */
370     /* move to cusor column 0 for now so that we will clear the entire
371      * line...
372      */
373     tpd->cursorColumn = 0;
374     tpd->cursorRow = 0;
375
376     /* and clear from the current cursor position to end of memory... */
377     (void) clearToEndOfMemory(w);
378
379     /* and set the final cursor position if origin mode    */
380     if ( vtw->vt.td->originMode) {
381         tpd->cursorRow    = vtw->term.tpd->scrollLockTopRow;
382       }
383 }
384
385
386 void
387 _DtTermFuncClearLine(Widget w, int count, FunctionSource functionSource)
388 {
389     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
390     struct termData *tpd = tw->term.tpd;
391     int lineWidth;
392
393     if (tpd->topRow + tpd->cursorRow < tpd->lastUsedRow) {
394         /* get the current width... */
395         lineWidth = _DtTermPrimBufferGetLineWidth(tpd->termBuffer,
396                         tpd->topRow + tpd->cursorRow);
397         /* clear line... */
398         (void) _DtTermPrimBufferClearLine(tpd->termBuffer,
399                 tpd->topRow + tpd->cursorRow, 0);
400         /* render the line.  We only need to refresh the old line
401          * width...
402          */
403         if (lineWidth > 0)
404             (void) _DtTermPrimRefreshText(w, 0, tpd->cursorRow, lineWidth,
405                     tpd->cursorRow);
406     }
407 }
408
409
410 void
411 _DtTermFuncClearToEndOfLine(Widget w, int count, FunctionSource functionSource)
412 {
413     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
414     struct termData *tpd = tw->term.tpd;
415     int lineWidth;
416
417     if (tpd->topRow + tpd->cursorRow < tpd->lastUsedRow) {
418         /* turn the cursor off... */
419         (void) _DtTermPrimCursorOff(w);
420
421         /* get the current width... */
422         lineWidth = _DtTermPrimBufferGetLineWidth(tpd->termBuffer,
423                         tpd->topRow + tpd->cursorRow);
424         /* clear line... */
425         if (lineWidth > tpd->cursorColumn) {
426             (void) _DtTermPrimBufferClearLine(tpd->termBuffer,
427                     tpd->topRow + tpd->cursorRow, tpd->cursorColumn);
428             /* render the line.  We only need to refresh the old line
429              * width...
430              */
431             (void) _DtTermPrimRefreshText(w, 
432                     tpd->cursorColumn - (tpd->mbCurMax > 1 ? 1 : 0),
433                     tpd->cursorRow,
434                     lineWidth, tpd->cursorRow);
435         }
436         /* if this is the last row, we are not in memory lock land,
437          * and we are in column 0, it is no longer the last used row...
438          */
439         if ((tpd->topRow + tpd->cursorRow == tpd->lastUsedRow - 1) &&
440                 (tpd->cursorColumn == 0) &&
441                 (tpd->cursorRow > tpd->memoryLockRow)) {
442             tpd->lastUsedRow = tpd->topRow + tpd->cursorRow;
443         }
444     }
445 }
446
447 /*
448 ** Delete "count" characters from the buffer, VT class terminals do not
449 ** support delete with wrap, so no need to worry about it.
450 */
451 void
452 _DtTermFuncDeleteChar
453 (
454     Widget         w,
455     int            count,
456     FunctionSource functionSource
457 )
458 {
459     DtTermPrimData tpd = ((DtTermPrimitiveWidget) w)->term.tpd;
460     short          deleteWidth;
461     short          row;
462     short          col;
463
464     row = tpd->topRow + tpd->cursorRow;
465     col = tpd->cursorColumn;
466     
467     if (row < tpd->lastUsedRow && count > 0)
468     {
469         deleteWidth = count;
470         (void) _DtTermPrimCursorOff(w);
471         _DtTermBufferDelete(tpd->termBuffer, &row, &col, &deleteWidth);
472         (void) _DtTermPrimRefreshText(w, col, row,
473                                       ((DtTermPrimitiveWidget) w)->term.columns,
474                                       row);
475
476     }
477 }
478
479 void
480 _DtTermFuncDeleteLine(Widget w, int count, FunctionSource functionSource)
481 {
482     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
483     struct termData *tpd = tw->term.tpd;
484
485     /* we might as well turn the cursor off now, since we will need to
486      * change the cursor column to the left margin when we are done
487      * anyway...
488      */
489     (void) _DtTermPrimCursorOff(w);
490     if (tpd->topRow + tpd->cursorRow < tpd->lastUsedRow) {
491         /* complete any pending scroll if the scroll area has changed... */
492         (void) _DtTermPrimScrollCompleteIfNecessary(w, tpd->cursorRow,
493                 tw->term.rows - 1, count);
494
495         /* clip the line count... */
496         if (count > tpd->scrollLockBottomRow -tpd->scrollLockTopRow +1)
497            count = tpd->scrollLockBottomRow -tpd->scrollLockTopRow +1 ;
498 #ifdef  BOGUS
499         if (tpd->topRow + tpd->cursorRow + count > tpd->lastUsedRow) {
500             count = tpd->lastUsedRow - (tpd->topRow + tpd->cursorRow);
501         }
502 #endif  /* BOBUS */
503         if (tpd->topRow + tpd->cursorRow + count > tpd->scrollLockBottomRow) {
504             count = tpd->scrollLockBottomRow -
505                     (tpd->topRow + tpd->cursorRow) + 1;
506         }
507
508         /* special case out when there is a single line and we are
509          * deleting the top line...
510          */
511         if (((tpd->lastUsedRow == 1) && (tpd->cursorRow == 0)) ||
512             (tpd->cursorRow + 1 == tpd->lastUsedRow)) {
513             /* we need to clear the line, re-render it, and we are done...
514              */
515             (void) _DtTermPrimBufferClearLine(tpd->termBuffer,
516                     tpd->topRow + tpd->cursorRow, 0);
517             (void) _DtTermPrimRefreshText(w, 0, tpd->cursorRow, tw->term.columns,
518                     tpd->cursorRow);
519         } else {
520             /* delete the lines at the cursor...
521              */
522             (void) _DtTermPrimBufferDeleteLine(tpd->termBuffer,
523                     tpd->topRow + tpd->cursorRow, count, tpd->lastUsedRow);
524             /* delete lines at the cursor from the selection... */
525             (void) _DtTermPrimSelectDeleteLines(w,
526                     tpd->lastUsedHistoryRow + tpd->topRow + tpd->cursorRow,
527                     count);
528
529             /* insert the lines we just deleted at the bottom of the
530              * scrolling region...
531              */
532             (void) _DtTermPrimBufferInsertLineFromTB(tpd->termBuffer,
533                     tpd->topRow + tpd->scrollLockBottomRow - count + 1,
534                     count, insertFromBottom);
535             /* insert lines at the bottom of the scrolling region into
536              * the selection...
537              */
538             (void) _DtTermPrimSelectInsertLines(w,
539                     tpd->lastUsedHistoryRow + tpd->topRow +
540                     tpd->scrollLockBottomRow - count + 1, count);
541
542             /* and scroll the text on the screen... */
543             (void) _DtTermPrimScrollTextArea(w, tpd->cursorRow,
544                     tpd->scrollLockBottomRow + 1 - tpd->cursorRow, count);
545         }
546     }
547
548     /* move to the left margin... */
549     tpd->cursorColumn = tpd->leftMargin;
550 }
551
552 \f
553 /** HARD/SOFT RESET ***********************************************************
554  *                                       #
555  *  #    #    ##    #####   #####       #    ####    ####   ######   #####
556  *  #    #   #  #   #    #  #    #     #    #       #    #  #          #
557  *  ######  #    #  #    #  #    #    #      ####   #    #  #####      #
558  *  #    #  ######  #####   #    #   #           #  #    #  #          #
559  *  #    #  #    #  #   #   #    #  #       #    #  #    #  #          #
560  *  #    #  #    #  #    #  #####  #         ####    ####   #          #
561  * 
562  * 
563  *  #####   ######   ####   ######   #####
564  *  #    #  #       #       #          #
565  *  #    #  #####    ####   #####      #
566  *  #####   #            #  #          #
567  *  #   #   #       #    #  #          #
568  *  #    #  ######   ####   ######     #
569  */
570 void
571 _DtTermFuncHardReset(Widget w, int count, FunctionSource functionSource)
572 {
573     DtTermWidget vtw = (DtTermWidget) w;
574     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
575     struct termData *tpd = tw->term.tpd;
576
577     (void) _DtTermPrimScrollComplete(w, True);
578     /* ring the bell... */
579     (void) _DtTermPrimBell(w);
580     (void) _DtTermPrimCursorOn(w);
581      
582     _DtTermFuncSoftReset(w, count, functionSource) ;
583
584     /* Do this after soft reset */
585
586     vtw->term.reverseVideo = False;
587     tpd->topRow = 0 ;
588     tpd->autoLineFeed=False ;
589     vtw->term.jumpScroll = True ;
590     /* auto key repeat is X server issue - do nothing here */
591     _DtTermFuncClearBuffer(w, 0, (FunctionSource) NULL ) ;
592     _DtTermFunctionKeyClear(w) ;
593
594     (void) _DtTermPrimSetCursorVisible(w, True);
595     (void) _DtTermPrimCursorOn(w);  
596     
597     return;
598 }
599
600 void
601 _DtTermFuncSoftReset(Widget w, int count, FunctionSource functionSource)
602 {
603     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
604     struct termData *tpd = tw->term.tpd;
605     DtTermWidget vtw = (DtTermWidget) w;
606     DtTermData td = vtw->vt.td;
607
608     (void) _DtTermPrimScrollComplete(w, True);
609     /* ring the bell... */
610     (void) _DtTermPrimBell(w);
611     /* the following locks don't make sense in the vt context, but
612        I'll initialize them to make sure they're not corrupted in the 
613        "prim" layer
614     */
615     tpd->keyboardLocked.xferPending = False;
616     tpd->keyboardLocked.error       = False;
617     tpd->keyboardLocked.record      = False;
618  
619     /* ANSI and vt220 resets  (from  RM) */
620     tpd->keyboardLocked.escape  = False;
621     _DtTermPrimInsertCharUpdate(w, DtTERM_INSERT_CHAR_OFF);
622
623     /* vt 220 soft resets  (DECRST, DECSTBM, from spec) */
624     tpd->autoWrapRight=True;   /* We are NOT following the vt spec here*/
625     td->originMode=False;
626     td->applicationMode=False;    /* Normal cursor mode */
627     td->applicationKPMode=False;  /* Numeric keypad mode */
628     td->originMode=False;         
629     /* no scroll lock */
630     tpd->memoryLockMode=SCROLL_LOCKoff ;
631     tpd->scrollLockTopRow = 0;
632     tpd->scrollLockBottomRow = tw->term.rows-1;
633     /* cursor state stuff for next restore cursor (DECRC) */
634     td->saveCursor.cursorRow = 0;
635     td->saveCursor.cursorColumn = 0;
636     td->saveCursor.enhFieldState = FIELD_UNPROTECT;
637     td->saveCursor.enhVideoState = (char)0;
638     td->saveCursor.originMode = False;
639     td->saveCursor.enhFgColorState = 0;
640     td->saveCursor.enhBgColorState = 0;
641     td->saveCursor.GL = &td->G0; 
642     td->saveCursor.GR = &td->G0;    
643     td->saveCursor.G0 = RENDER_FONT_NORMAL;
644     td->saveCursor.G1 = RENDER_FONT_LINEDRAW;   
645     td->saveCursor.G2 = RENDER_FONT_NORMAL;
646     td->saveCursor.G3 = RENDER_FONT_NORMAL;
647     td->saveCursor.singleShiftFont = RENDER_FONT_NORMAL; 
648     td->saveCursor.singleShiftPending = False;
649     /* this is saved by termprim td->saveCursor.wrapMode  = False ; */
650
651     /*
652     ** xterm resets (xterm extensions to DECRST
653     ** xterm does not reset this stuff so I won't either    
654     **   td->allow80_132ColMode = False ;
655     **   td->doCursesFixMode = False ; 
656     **   td->marginBellMode  = False ; 
657     **   tpd->logging = False ; 
658     **  when implemented in Term, set "NOT alternate buffer"
659     */
660     vtw->vt.td->reverseWrapMode = False;  /* this is inconsistant with xterm*/
661
662   
663     /* Set the "other" state variables?
664      */
665     /* video... */
666     td->enhVideoState &= ~VIDEO_MASK;
667     (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer,
668               tpd->topRow + tpd->cursorRow, tpd->cursorColumn, enhVideo,
669               td->enhVideoState);
670
671     /* field... */
672     td->enhFieldState = FIELD_UNPROTECT;
673     (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer,
674               tpd->topRow + tpd->cursorRow, tpd->cursorColumn, enhField,
675               td->enhFieldState);
676
677     /* foreground... */
678     td->enhFgColorState = 0;
679     (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer,
680               tpd->topRow + tpd->cursorRow, tpd->cursorColumn, enhFgColor,
681               td->enhFgColorState);
682
683     /* background... */
684     td->enhBgColorState = 0;
685     (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer,
686               tpd->topRow + tpd->cursorRow, tpd->cursorColumn, enhBgColor,
687               td->enhBgColorState);
688
689     /* font... */
690     td->GL = &td->G0;
691     td->GR = &td->G0;
692     td->G0 = FONT_NORMAL;
693     td->G1 = FONT_NORMAL;
694     td->G2 = FONT_NORMAL;
695     td->G3 = FONT_NORMAL;
696     td->enhFontState = *td->GL;
697     (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer,
698               tpd->topRow + tpd->cursorRow, tpd->cursorColumn, enhFont, 
699               td->enhFontState);
700
701     /* reset the parser */
702     {
703       ParserContext context ;
704       context = GetParserContext(w) ;
705       context->stateTable =  _DtTermStateStart ;
706       _DtTermClearParam(w) ;
707     }
708
709     (void) _DtTermPrimSetCursorVisible(w, True);
710     (void) _DtTermPrimCursorOn(w);  
711
712     /* flush any pending text that we have queued up to send down the
713      * pty...
714      */
715     (void) _DtTermPrimPendingTextFlush(tpd->pendingWrite);
716     return;
717 }
718
719 \f
720 /*** INSERT CHAR/LINE *********************************************************
721  * 
722  *     #    #    #   ####   ######  #####    #####
723  *     #    ##   #  #       #       #    #     #
724  *     #    # #  #   ####   #####   #    #     #
725  *     #    #  # #       #  #       #####      #
726  *     #    #   ##  #    #  #       #   #      #
727  *     #    #    #   ####   ######  #    #     #
728  * 
729  *                                       #
730  *   ####   #    #    ##    #####       #   #          #    #    #  ######
731  *  #    #  #    #   #  #   #    #     #    #          #    ##   #  #
732  *  #       ######  #    #  #    #    #     #          #    # #  #  #####
733  *  #       #    #  ######  #####    #      #          #    #  # #  #
734  *  #    #  #    #  #    #  #   #   #       #          #    #   ##  #
735  *   ####   #    #  #    #  #    # #        ######     #    #    #  ######
736  */
737
738 void
739 _DtTermFuncInsertLine(Widget w, int count, FunctionSource functionSource)
740 {
741     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
742     struct termData *tpd = tw->term.tpd;
743     int insertedRows = 0;
744     int moveCount;
745     int src;
746     int i;
747
748     /* as with delete line, turn the cursor off now since we will
749      * pretty much need to turn it off later to change the cursor
750      * column to the left margin...
751      */
752     (void) _DtTermPrimCursorOff(w);
753
754     /* move the cursor to the left column... */
755     tpd->cursorColumn = tpd->leftMargin;
756
757     /* if the cursor is below used memory, we don't need to do anything...
758      */
759     if (tpd->topRow + tpd->cursorRow >= tpd->lastUsedRow) {
760         return;
761     }
762
763     /* complete any pending scroll if the scroll area has changed... */
764     (void) _DtTermPrimScrollCompleteIfNecessary(w, tpd->cursorRow,
765             tw->term.rows - 1, -count);
766
767     /* first, insert any unused memory (from below lastUsedRow)... */
768     if (tpd->lastUsedRow < tpd->bufferRows) {
769         /* the most we can insert from the bottom is the number of lines
770          * not yet used...
771          */
772         moveCount = tpd->bufferRows - tpd->lastUsedRow;
773         if (moveCount > count) {
774             moveCount = count;
775         }
776
777         /* insert them...
778          */
779         (void) _DtTermPrimBufferInsertLineFromTB(tpd->termBuffer,
780                 tpd->topRow + tpd->cursorRow,
781                 moveCount, insertFromBottom);
782         /* inform the selection code that the selection has been moved... */
783         (void) _DtTermPrimSelectInsertLines(w,
784                 tpd->lastUsedHistoryRow + tpd->topRow + tpd->cursorRow,
785                 moveCount);
786
787         /* update screen info and counts... */
788         count -= moveCount;
789         insertedRows += moveCount;
790         tpd->lastUsedRow += moveCount;
791     }
792
793     if (count > 0) {
794         /* insert used memory...
795          */
796         /* first insert as much as we can from above the screen... */
797         if (count > tpd->topRow) {
798             moveCount = tpd->topRow;
799         } else {
800             moveCount = count;
801         }
802
803         if (moveCount > 0) {
804             /* insert them into the buffer before we modify the selecction...
805              */
806             (void) _DtTermPrimBufferInsertLineFromTB(tpd->termBuffer,
807                     tpd->topRow + tpd->cursorRow - moveCount,
808                     moveCount, insertFromTop);
809
810             /* delete the lines at the top of the buffer from the selection...
811              */
812             (void) _DtTermPrimSelectDeleteLines(w, tpd->lastUsedHistoryRow,
813                     moveCount);
814
815             /* insert the lines at the bottom of the buffer in the
816              * selection...
817              */
818             (void) _DtTermPrimSelectInsertLines(w,
819                     tpd->lastUsedHistoryRow + tpd->topRow + tpd->cursorRow -
820                     moveCount, moveCount);
821
822             /* update screen info and counts... */
823             count -= moveCount;
824             insertedRows += moveCount;
825             tpd->topRow -= moveCount;
826         }
827
828         /* now insert whatever else we need from the bottom... */
829         if (count > 0) {
830             /* DKS: we need to clip here so we don't self destruct... */
831             moveCount = count;
832
833             /* insert them... */
834             if ((tpd->cursorRow >= tpd->scrollLockTopRow) &&
835                     (tpd->cursorRow <= tpd->scrollLockBottomRow)) {
836                 /* scroll within the scroll region.  So, take memory
837                  * from the bottom of the scroll region instead of the
838                  * bottom of memory...
839                  */
840                 /* insert lines into the selection... */
841                 (void) _DtTermPrimBufferInsertLine(tpd->termBuffer,
842                         tpd->topRow + tpd->cursorRow, moveCount,
843                         tpd->scrollLockBottomRow - moveCount + 1);
844                 /* then adjust the selection... */
845                 (void) _DtTermPrimSelectInsertLines(w,
846                         tpd->lastUsedHistoryRow + tpd->topRow + tpd->cursorRow,
847                         moveCount);
848             } else {
849                 /* just take the lines from the bottom... */
850                 /* we don't need to delete lines from the bottom since
851                  * that doesn't move the selection...
852                  */
853                 /* insert lines into the selection... */
854                 (void) _DtTermPrimBufferInsertLineFromTB(tpd->termBuffer,
855                         tpd->topRow + tpd->cursorRow, moveCount,
856                         insertFromBottom);
857                 /* then adjust the selection... */
858                 (void) _DtTermPrimSelectInsertLines(w,
859                         tpd->lastUsedHistoryRow + tpd->topRow + tpd->cursorRow,
860                         moveCount);
861             }
862
863             /* update screen info and counts... */
864             count -= moveCount;
865             insertedRows += moveCount;
866         }
867     }
868
869     /* now we need to scroll below us.  Remember, in order to scroll text
870      * down, the count needs to be *negative*...
871      */
872     if ((tpd->cursorRow >= tpd->scrollLockTopRow) &&
873             (tpd->cursorRow <= tpd->scrollLockBottomRow)) {
874         (void) _DtTermPrimScrollTextArea(w, tpd->cursorRow,
875                 tpd->scrollLockBottomRow + 1 - tpd->cursorRow, -insertedRows);
876     } else {
877         (void) _DtTermPrimScrollTextArea(w, tpd->cursorRow,
878                 tw->term.rows - tpd->cursorRow, -insertedRows);
879     }
880 }
881
882
883 \f
884 /*** CURSOR MOTION ************************************************************
885  * 
886  *   ####   #    #  #####    ####    ####   #####
887  *  #    #  #    #  #    #  #       #    #  #    #
888  *  #       #    #  #    #   ####   #    #  #    #
889  *  #       #    #  #####        #  #    #  #####
890  *  #    #  #    #  #   #   #    #  #    #  #   #
891  *   ####    ####   #    #   ####    ####   #    #
892  * 
893  * 
894  *  #    #   ####    #####     #     ####   #    #
895  *  ##  ##  #    #     #       #    #    #  ##   #
896  *  # ## #  #    #     #       #    #    #  # #  #
897  *  #    #  #    #     #       #    #    #  #  # #
898  *  #    #  #    #     #       #    #    #  #   ##
899  *  #    #   ####      #       #     ####   #    #
900  */
901
902
903 void
904 _DtTermFuncTab(Widget w, int count, FunctionSource functionSource)
905 {
906     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w;
907     struct termData *tpd = tw->term.tpd;
908     TermBuffer tBuffer = tpd->termBuffer;
909     short nextTab;
910
911     (void) _DtTermPrimCursorOff(w);
912
913 /* Move to the next tab stop.  Note that this cursor motion is
914  * similar to the right arrow cursor motion in that
915  * it doesn't set the line width until a character is entered.
916  */
917 /* DKS: this code currently enforces tabs at every 8 character
918  * positions.  It needs to be worked on to support the margins/tabs
919  * buffer...
920  */
921    nextTab = _DtTermPrimBufferGetNextTab(tBuffer, tpd->cursorColumn);
922
923    /* check to see if we are past the end of the line... */
924    if ((nextTab <= 0) || (nextTab >= tpd->rightMargin)) {
925        tpd->cursorColumn = tpd->rightMargin;
926    } else {
927        tpd->cursorColumn = nextTab;
928    }
929    return;
930 }
931
932
933
934 /*  The remainder of this file is new for ANSI and should be merged with 
935     the above (some of which may be incorrect for ANSI)
936 */
937
938 /*** VIDEO ENHANCEMENTS *******************************************************
939  *
940  *  #    #     #    #####   ######   ####
941  *  #    #     #    #    #  #       #    #
942  *  #    #     #    #    #  #####   #    #
943  *  #    #     #    #    #  #       #    #
944  *   #  #      #    #    #  #       #    #
945  *    ##       #    #####   ######   ####
946  * 
947  * 
948  *  ######  #    #  #    #    ##    #    #   ####   ######
949  *  #       ##   #  #    #   #  #   ##   #  #    #  #
950  *  #####   # #  #  ######  #    #  # #  #  #       #####
951  *  #       #  # #  #    #  ######  #  # #  #       #        ###
952  *  #       #   ##  #    #  #    #  #   ##  #    #  #        ###
953  *  ######  #    #  #    #  #    #  #    #   ####   ######   ###
954  */
955
956 void
957 _DtTermVideoEnhancement(Widget w,int value)
958 {
959     DtTermPrimitiveWidget      tw        = (DtTermPrimitiveWidget) w;
960     DtTermPrimData        tpd        = tw->term.tpd;
961     DtTermWidget      vtw        = (DtTermWidget) w;
962     DtTermData        td        = vtw->vt.td;
963     ParserContext   context   = GetParserContext(w);
964
965       switch(value) {
966         case 0:
967               /* reset video */
968               td->enhVideoState &= ~VIDEO_MASK ;
969
970               /* reset color */
971               td->enhFgColorState = 0;
972               (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer, 
973                       tpd->topRow + tpd->cursorRow, tpd->cursorColumn,
974                       enhFgColor, td->enhFgColorState);
975               td->enhBgColorState = 0;
976               (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer, 
977                       tpd->topRow + tpd->cursorRow, tpd->cursorColumn,
978                       enhBgColor, td->enhBgColorState);
979               break;
980
981         case 1:  /* Bold... */
982                  td->enhVideoState |= BOLD;
983                  td->enhVideoState &= ~HALF_BRIGHT ;
984                  break;
985          
986         case 2:  /* Half bright... */
987                  td->enhVideoState |= HALF_BRIGHT ;
988                  td->enhVideoState &= ~BOLD ;
989                  break;
990
991         case 4:  /* Underline... */
992                  td->enhVideoState |= UNDERLINE;
993                  break;
994                  
995         case 5:  /* we don't do blink, so use inverse */
996         case 7:  /* Inverse Video... */
997                  td->enhVideoState |= INVERSE ;
998                  break;
999
1000         case 8:  /* Secure Video... */
1001                  td->enhVideoState |= SECURE ;
1002                  break;
1003
1004         case 22: /* Half bright off... */
1005                  td->enhVideoState &= ~HALF_BRIGHT ;
1006                  td->enhVideoState &= ~BOLD ;
1007                  break;
1008
1009         case 24: /* Underline off... */
1010                  td->enhVideoState &= ~UNDERLINE  ;
1011                  break;
1012
1013         case 25: /* we don't do blink, so use inverse */
1014
1015         case 27: /* Inverse Video off... */
1016                  td->enhVideoState &= ~INVERSE ;
1017                  break;
1018
1019         case 28: /* Secure Video off... */
1020                  td->enhVideoState &= ~SECURE ;
1021                  break;
1022
1023         case 30:
1024         case 31:
1025         case 32:
1026         case 33:
1027         case 34:
1028         case 35:
1029         case 36:
1030         case 37:
1031               td->enhFgColorState = value - 30 + 1;
1032               (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer, 
1033                       tpd->topRow + tpd->cursorRow, tpd->cursorColumn,
1034                       enhFgColor, td->enhFgColorState);
1035               return;
1036               break;
1037         case 39:
1038               td->enhFgColorState = 0;
1039               (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer, 
1040                       tpd->topRow + tpd->cursorRow, tpd->cursorColumn,
1041                       enhFgColor, td->enhFgColorState);
1042               return;
1043               break;
1044
1045         case 40:
1046         case 41:
1047         case 42:
1048         case 43:
1049         case 44:
1050         case 45:
1051         case 46:
1052         case 47:
1053               td->enhBgColorState = value - 40 + 1;
1054               (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer, 
1055                       tpd->topRow + tpd->cursorRow, tpd->cursorColumn,
1056                       enhBgColor, td->enhBgColorState);
1057               return;
1058               break;
1059         case 49:
1060               td->enhBgColorState = 0;
1061               (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer, 
1062                       tpd->topRow + tpd->cursorRow, tpd->cursorColumn,
1063                       enhBgColor, td->enhBgColorState);
1064               return;
1065               break;
1066
1067         default: break;
1068             /* fprintf(stderr,"wrong param in SGR esc seq\n") ;*/
1069       }
1070
1071     /* set the enhancement */
1072     (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer, 
1073               tpd->topRow + tpd->cursorRow, tpd->cursorColumn, enhVideo, 
1074               td->enhVideoState);
1075     return;
1076 }
1077
1078 void
1079 _DtTermFontEnhancement(Widget w,int value)
1080 {
1081     DtTermPrimitiveWidget      tw        = (DtTermPrimitiveWidget) w;
1082     DtTermPrimData        tpd        = tw->term.tpd;
1083     DtTermWidget      vtw        = (DtTermWidget) w;
1084     DtTermData        td        = vtw->vt.td;
1085     ParserContext   context   = GetParserContext(w);
1086
1087     (void)_DtTermPrimBufferSetEnhancement(tpd->termBuffer,
1088               tpd->topRow + tpd->cursorRow, tpd->cursorColumn, enhFont, value);
1089 }
1090
1091 /* This are utility functions for the terminal dialog to use to effect the
1092    function key lock
1093 */
1094 void _DtTermSetUserKeyLock(
1095          Widget         w,
1096          Boolean        lock_state)
1097 {
1098   _DtTermWidgetToAppContext(w);
1099
1100   _DtTermAppLock(app);
1101   ((DtTermWidget)w)->vt.td->userKeysLocked = lock_state ;
1102   _DtTermAppUnlock(app);
1103 }
1104
1105 Boolean _DtTermGetUserKeyLock(
1106          Widget         w)
1107 {
1108   Boolean lock_state;
1109   _DtTermWidgetToAppContext(w);
1110
1111   _DtTermAppLock(app);
1112   lock_state = ((DtTermWidget)w)->vt.td->userKeysLocked;
1113   _DtTermAppUnlock(app);
1114   return(lock_state);
1115 }
1116
1117 void _DtTermSetAutoLineFeed(
1118          Widget         w,
1119          Boolean        alf_state)
1120 {
1121       _DtTermWidgetToAppContext(w);
1122
1123       _DtTermAppLock(app);
1124       ((DtTermWidget)w)->vt.td->tpd->autoLineFeed = alf_state ;
1125       _DtTermAppUnlock(app);
1126 }
1127
1128 Boolean _DtTermGetAutoLineFeed(
1129          Widget         w)
1130 {
1131       Boolean alf_state;
1132       _DtTermWidgetToAppContext(w);
1133
1134       _DtTermAppLock(app);
1135       alf_state = ((DtTermWidget)w)->vt.td->tpd->autoLineFeed;
1136       _DtTermAppUnlock(app);
1137       return(alf_state);
1138 }
1139
1140 void _DtTermSetCurrentWorkingDirectory(
1141         Widget          w,
1142         char            *cwd)
1143 {
1144     DtTermWidget      vtw        = (DtTermWidget) w;
1145     _DtTermWidgetToAppContext(w);
1146
1147     _DtTermAppLock(app);
1148     vtw->term.subprocessCWD =
1149             XtRealloc(vtw->term.subprocessCWD, strlen(cwd) + 1);
1150     (void) strcpy(vtw->term.subprocessCWD, cwd);
1151     _DtTermAppUnlock(app);
1152 }
1153
1154 char *_DtTermGetCurrentWorkingDirectory(
1155         Widget          w)
1156 {
1157     DtTermWidget      vtw        = (DtTermWidget) w;
1158     char *cwd;
1159     _DtTermWidgetToAppContext(w);
1160
1161     _DtTermAppLock(app);
1162     cwd = vtw->term.subprocessCWD;
1163     _DtTermAppUnlock(app);
1164     return(cwd);
1165 }