Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / lib / DtTerm / Term / TermBuffer.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 /*                                                                      *
24  * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company               *
25  * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
26  * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.                *
27  * (c) Copyright 1993, 1994, 1996 Novell, Inc.                          *
28  * (c) Copyright 1996 Digital Equipment Corporation.                    *
29  * (c) Copyright 1996 FUJITSU LIMITED.                                  *
30  * (c) Copyright 1996 Hitachi.                                          *
31  */
32
33 #define USE_MEMCPY      /* use memcpy for line movement... */
34
35 #include <Xm/Xm.h>
36 #include "TermPrim.h"
37 #include "TermHeader.h"       /* for MIN/MAX */
38 #include "TermBufferP.h"
39 #include "TermEnhance.h"
40
41 /*
42 ** clear "count" enhancements starting at startCol
43 */
44 static void
45 clearEnhancements
46 (
47     TermBuffer tb,
48     short      row,
49     short      startCol,
50     short      count
51 );
52
53 static void
54 insertEnhancements
55 (
56     TermBuffer tb,
57     short      row,
58     short      col,
59     short      insertCount
60 );
61
62 static void
63 deleteEnhancement
64 (
65     TermBuffer tb, 
66     short      row,
67     short      col
68 );
69
70 static void
71 _DtTermClearEnhancements
72 (
73     TermBuffer tb,
74     short      row,
75     short      col,
76     short      count
77 );
78
79 static int
80 _DtTermSetEnhancement
81 (
82     TermBuffer      tb,
83     short           row,
84     short           col,
85     unsigned char   id,
86     enhValue        value
87 );
88
89 static Boolean
90 _DtTermGetEnhancement
91 (
92     const TermBuffer      tb,
93     const short           row,
94     const short           col,
95     enhValue            **enhancements,
96     short                *count,
97     const countSpec       countWhich
98 );
99
100 static termChar *
101 _DtTermGetCharacterPointer
102 (
103     TermBuffer  tb,
104     short       row,
105     short       col
106 );
107
108 static void
109 _DtTermInsertEnhancements
110 (
111     const TermBuffer  tb, 
112     const short       row,
113     const short       col,
114     short             insertCount,
115     const Boolean     insertFlag
116 );
117
118 static Boolean
119 _DtTermBufferCreateEnhancement
120 (
121     TermBuffer  tb,
122     short       row,
123     short       col
124 );
125
126 static void
127 _DtTermBufferResize
128 (
129     TermBuffer  newTb,
130     short      *newRows,
131     short      *newCols
132 );
133
134 static void
135 _DtTermDeleteEnhancement
136 (
137     TermBuffer  tb, 
138     short       row,
139     short       col,
140     short       width
141 );
142
143 static short
144 _DtTermInsert
145 (
146     TermBuffer  tb,
147     short       row,
148     short       col,
149     termChar   *newChars,
150     short       numChars,
151     Boolean     insertFlag,   /* if TRUE, insert, else overwrite        */
152     termChar  **returnChars,  /* pointer to overflow buffer             */
153     short      *returnCount   /* count of characters in overflow buffer */
154 );
155
156 static Boolean
157 _DtTermSetLineLength
158 (
159     TermBuffer      tb,
160     short           row,
161     short           newLength
162 );
163
164 static short
165 _DtTermGetLineLength
166 (
167     TermBuffer      tb,
168     short           row
169 );
170
171 static Boolean
172 _DtTermClearLine
173 (
174     TermBuffer  tb,
175     short       row,
176     short       newLength
177 );
178
179 #if (defined(TEST) || defined(__CODECENTER__) || defined(VALIDATE_ENH))
180 static void
181 validateEnhancements
182 (
183     TermBuffer  tb,
184     short       row
185 );    
186 #    define VALIDATE_ENHANCEMENTS(tb, row) validateEnhancements((tb), (row))
187 #else    
188 #    define VALIDATE_ENHANCEMENTS(tb, row)
189 #endif /* TEST || __CODECENTER__ || VALIDATE_ENH */
190
191 /*
192 ** A blank enhancement structure, it will come in handy.
193 */
194 static DtTermEnhPart blankEnh = {0, 0, 0, 0, 0};
195
196 /* 
197 ** Create and initialize the Dt-specific parts of the term buffer.
198 */
199 TermBuffer
200 _DtTermBufferCreateBuffer
201 (
202     const Widget  w,
203     const short   rows,
204     const short   cols,
205     const short   sizeOfBuffer,
206     const short   sizeOfLine,
207     const short   sizeOfEnh
208 )
209 {
210     int             i;
211     TermBuffer      newTB;
212     DtLine    *lines;
213
214     newTB = _DtTermPrimBufferCreateBuffer(w, rows, cols, 
215                                     sizeOfBuffer, sizeOfLine, sizeOfEnh);
216     
217     
218     if (newTB)
219     {
220         VALUE_LIST(newTB) = (enhValues) malloc(NUM_ENHANCEMENT_FIELDS *
221                                                sizeof(enhValue));
222
223         if (!VALUE_LIST(newTB))
224         {
225             _DtTermPrimBufferFreeBuffer(newTB);
226             return((TermBuffer) NULL);
227         }
228
229         NUM_ENH_FIELDS(newTB) = NUM_ENHANCEMENT_FIELDS;
230         for (lines = DT_LINES(newTB);
231              lines < DT_LINES(newTB) + ROWS(newTB);
232              lines++)
233         {
234             DT_ENH(*lines) = (DtEnh) NULL;
235         }        
236         DT_ENH_STATE(newTB)    = blankEnh;
237         DT_ENH_DIRTY(newTB)    = 0;
238         ENH_PROC(newTB)        = _DtTermEnhProc;
239         BUFFER_CREATE(newTB)   = _DtTermBufferCreateBuffer;
240         BUFFER_FREE(newTB)     = _DtTermBufferFreeBuffer;
241         BUFFER_RESIZE(newTB)   = _DtTermBufferResize;
242         CLEAR_ENH(newTB)       = _DtTermClearEnhancements;
243         INSERT_ENH(newTB)      = _DtTermInsertEnhancements;
244         DELETE_ENH(newTB)      = _DtTermDeleteEnhancement;
245         SET_ENH(newTB)         = _DtTermSetEnhancement;
246         GET_ENH(newTB)         = _DtTermGetEnhancement;
247         SET_LINE_LENGTH(newTB) = _DtTermSetLineLength;
248         CLEAR_LINE(newTB)      = _DtTermClearLine;
249     }
250     return(newTB);
251 }                    
252
253 /* 
254 ** Resize buffer, this is a helper function, if malloc fails, then the
255 ** appropriate dimensions are forced to the current maximums
256 */
257 static void
258 _DtTermBufferResize
259 (
260     TermBuffer  tb,
261     short      *newRows,
262     short      *newCols
263 )
264 {
265     short   i;
266     DtEnh   enh;
267     DtLine *lines;
268     
269     /*
270     ** make any necessary width adjustments first...
271     **
272     ** NOTE:
273     **    We do not take any action if the new column width is less
274     **    than the current column width.  It is the responsibility of
275     **    the rendering code to make sure that two column characters
276     **    are handled properly if the second column falls past the last
277     **    column in the window.
278     */
279     if (*newCols > MAX_COLS(tb)) 
280     {
281         termChar *newLineBuffer;
282
283         /*
284         ** now extend the line buffers and enhancements for all lines,
285         ** (even lines that are not being used at the moment
286         ** (ROWS < MAX_ROWS))...
287         */
288         lines = DT_LINES(tb);
289         for (i = 0; i < MAX_ROWS(tb); i++)
290         {
291             /*
292             ** only copy the enhancement information when it exists
293             */
294             if (DT_ENH(lines[i]))
295             {
296                 enh = (DtEnh) malloc(*newCols * sizeof(DtTermEnhPart));
297
298                 if (enh)
299                 {
300                     /*
301                     ** copy the enhancment info for all characters on
302                     ** the line, zero out the rest
303                     */
304                     (void) memcpy(enh, DT_ENH(lines[i]),
305                                   WIDTH(lines[i]) * sizeof(DtTermEnhPart));
306                     (void) memset(&enh[WIDTH(lines[i])], 0,
307                                   (*newCols - WIDTH(lines[i])) *
308                                   sizeof(DtTermEnhPart));
309                     free(DT_ENH(lines[i]));
310                     DT_ENH(lines[i]) = enh;
311                 }
312                 else
313                 {
314                     /*
315                     ** the malloc failed, revert back to MAX_COLS
316                     */
317                     *newCols = MAX_COLS(tb);
318                     *newRows = MIN(*newRows, MAX_ROWS(tb));
319                     break;
320                 }
321             }
322             newLineBuffer = (termChar *) malloc((unsigned) 
323                                         *newCols * BYTES_PER_CHAR(tb));
324             
325             if (newLineBuffer == NULL)
326             {
327                 /*
328                 ** line buffer malloc failed, we can only increase the
329                 ** width to the current maximum...
330                 */
331                 *newCols = MAX_COLS(tb);
332                 *newRows = MIN(*newRows, MAX_ROWS(tb));
333                 break;
334             }
335             memcpy(newLineBuffer, BUFFER(lines[i]), LENGTH(lines[i]) *
336                    BYTES_PER_CHAR(tb));
337             free(BUFFER(lines[i]));
338             BUFFER(lines[i])  = newLineBuffer;
339             WRAPPED(lines[i]) = False;
340         }
341         MAX_COLS(tb) = *newCols;
342     }
343     COLS(tb) = *newCols;
344
345     /*
346     ** now adjust the length of the buffer as necessary...
347     */
348     if (*newRows > MAX_ROWS(tb)) 
349     {
350         /*
351         ** the number of rows is increasing
352         */
353         lines = (DtLine *) malloc((unsigned) *newRows * sizeof(DtLine));
354         if (lines != NULL)
355         {
356             /*
357             ** the malloc succeeded, copy the old information, and then
358             ** free it...
359             */
360             memcpy(lines, DT_LINES(tb), sizeof(DtLine) * MAX_ROWS(tb));
361             free(DT_LINES(tb));
362             LINES(tb) = (TermLine *)lines;
363             
364             /*
365             ** now initialize the new lines...
366             **
367             ** NOTE:
368             **     If we are unable to malloc any part of a line, adjust
369             **     "newRows" and break.
370             */
371             for (i = MAX_ROWS(tb); i < *newRows; i++)
372             {
373                 lines[i] = (DtLine) malloc(SIZE_OF_LINE(tb));
374                 if (lines[i])
375                 {
376                     DT_ENH(lines[i])    = NULL;
377                     BUFFER(lines[i]) = (termChar *) malloc((unsigned) COLS(tb) *
378                                                            BYTES_PER_CHAR(tb));
379                     if (BUFFER(lines[i]))
380                     {
381                         LENGTH(lines[i])  = 0;
382                         WIDTH(lines[i])   = 0;
383                         WRAPPED(lines[i]) = False;
384                     }
385                     else 
386                     {
387                         /*
388                         ** the line buffer malloc failed...
389                         */
390                         *newRows = i;
391                         break;
392                     }
393                 }
394                 else
395                 {
396                     /*
397                     ** we couldn't malloc this line...
398                     */
399                     *newRows = i;
400                     break;
401                 }
402             }
403             MAX_ROWS(tb) = *newRows;
404         }
405         else
406         {
407             /*
408             ** the malloc for the row buffer failed, revert back to MAX_ROWS
409             */
410             *newRows = MAX_ROWS(tb);
411         }
412     }
413     ROWS(tb) = *newRows;
414 }    
415
416 /*
417 ** Free the buffer.
418 **
419 ** NOTE: This is a helper function, and should only be called by
420 **       TermPrimBufferFreeBuffer.
421 */
422 void
423 _DtTermBufferFreeBuffer
424 (
425     const TermBuffer tb
426 )
427 {
428     DtLine     *lines;
429
430     /*
431     ** Free the Dt-specific buffer info...
432     */
433     for (lines = DT_LINES(tb); lines < DT_LINES(tb) + ROWS(tb); lines++)
434     {
435         if (DT_ENH(*lines))
436         {
437             (void) free(DT_ENH(*lines));
438         }
439     }
440     if (VALUE_LIST(tb))
441     {
442         (void) free(VALUE_LIST(tb));
443     }
444 }
445
446 /*
447 ** clear all the enhancements from startCol through stopCol
448 */
449 static void
450 clearEnhancements
451 (
452     TermBuffer tb,
453     short      row,
454     short      col,
455     short      count
456 )
457 {
458     DtEnh  enh;
459     int    i;
460     
461
462     enh  = DT_ENH(DT_LINE_OF_TBUF(tb, row));
463     
464     if (enh)
465     {
466         enh += col;
467         for(i = 0; i < count; i++)
468         {
469             /*
470             ** Clear all of the enhancement information.
471             */
472             *enh = blankEnh;
473             enh++;
474         }
475     }
476 }
477
478 /*
479 ** Clear "count" enhancement blocks, starting at the specified row and column.
480 */
481 static void
482 _DtTermClearEnhancements
483 (
484     TermBuffer  tb,
485     short       row,
486     short       col,
487     short       count
488 )
489 {
490     clearEnhancements(tb, row, col, count);
491 }
492
493 /* 
494 ** Insert the desired number of enhancements at the specified
495 ** position...
496 **
497 ** NOTE:
498 **   We depend on the calling function to insure that insertCount
499 **   has been properly clipped to insure that we don't go out of
500 **   bounds.
501 **   Results are undefined if this function is called when the specified
502 **   column is at the end of the line.
503 */
504 static void
505 _DtTermInsertEnhancements
506 (
507     const TermBuffer  tb, 
508     const short       row,
509     const short       col,
510     short             insertCount,
511     const Boolean     insertFlag
512 )
513 {
514
515     DtTermEnhPart   fillEnh;
516     DtEnh           enh;
517     DtLine          line;
518     int             i;    
519     int             copyCount;
520     
521     line = DT_LINE_OF_TBUF(tb, row);
522     enh  = DT_ENH(line);
523
524     /* 
525     ** There's nothing to do if we're past the end of the line or
526     ** the dirty bit is clear and there are no ehancements on
527     ** this line...
528     */
529     if ((col < WIDTH(line)) && ((DT_ENH_DIRTY(tb)) || (enh != NULL)))
530     {
531         if ((enh == NULL))
532         {
533             /* 
534             ** there are currently no enhancements on this line, 
535             ** allocate an enhancement buffer, and reset 'enh'...
536             */
537             _DtTermBufferCreateEnhancement(tb, row, col);
538             enh = DT_ENH(line);
539         }
540
541         /* 
542         ** get a copy of the current enhancement (we'll insert 'copyCount'
543         ** copies of it into the enhancement buffer)
544         */
545         fillEnh = DT_ENH_STATE(tb);
546
547         if (insertFlag)
548         {
549             /* 
550             ** we're in insert mode, move any existing enhancements...
551             */
552             copyCount = MIN((WIDTH(line) - col),
553                     (COLS(tb) - col - insertCount));
554             copyCount = MAX(0, copyCount);
555             memmove(enh + col + insertCount, enh + col, 
556                     copyCount * sizeof(DtTermEnhPart));
557         }
558
559 #ifdef    NOCODE
560         /* 
561         ** insert insertCount copies of fillEnh into the enhancement buffer
562         ** starting at line->enh[col + 1]...
563         */
564         enh += col + 1;
565         for (i = 0; i < insertCount; i++)
566         {
567             *enh = fillEnh;
568             enh++;
569         }
570 #else  /* NOCODE */
571         /* 
572         ** insert insertCount copies of fillEnh into the enhancement buffer
573         ** starting at line->enh[col + 1]...
574         */
575         enh += col;
576         for (i = 0; i < insertCount; i++)
577         {
578             *enh = fillEnh;
579             enh++;
580         }
581 #endif /* NOCODE */
582
583     }
584 }
585
586 void
587 _DtTermBufferDelete
588 (
589     TermBuffer  tb,
590     short      *row,
591     short      *col,
592     short      *count        /* number of columns to delete     */
593 )
594 {
595     _DtTermPrimBufferDelete(tb, row, col, count, NULL, NULL);
596 }
597
598 /* 
599 ** delete the desired enhancements starting the specified position...
600 */
601 static void
602 _DtTermDeleteEnhancement
603 (
604     TermBuffer  tb, 
605     short       row,
606     short       col,
607     short       width
608 )
609 {
610     DtEnh           enh;
611     DtTermEnhPart   fillEnh;
612     DtLine          line;
613     int             copyCount;
614     
615     line = DT_LINE_OF_TBUF(tb, row);
616     enh  = DT_ENH(line);
617
618     if ((enh == NULL) || (WIDTH(line) <= col))
619     {
620         /* 
621         ** no enhancements, or at (or past) the end of the line, return
622         */
623         return;
624     }
625
626     /* 
627     ** get a copy of the current enhancement
628     */
629     fillEnh = enh[col];
630
631     /* 
632     ** move all of the enhancement blocks between col + width and and the
633     ** end of the line to col
634     */
635     copyCount = WIDTH(line) - (col + width);
636     memmove(enh + col , enh + col + width,
637             copyCount * sizeof(DtTermEnhPart));
638
639 }
640
641
642 /*
643 ** Create an enhancement block at the specified row and column.
644 **
645 ** NOTE:  For the time being, we simply allocate an entire row's worth
646 **        of enhancement blocks if it doesn't exist already.  We may
647 **        get smarter later on.
648 */
649 /*ARGSUSED*/
650 static Boolean
651 _DtTermBufferCreateEnhancement
652 (
653     TermBuffer  tb,
654     short       row,
655     short       col
656 )
657 {
658     DtLine  line;
659     DtEnh  *enh;
660     
661     if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
662     {
663         return(False);
664     }
665                         
666     line = DT_LINE_OF_TBUF(tb, row);
667     enh  = &(DT_ENH(line));
668
669     /*
670     ** If this row already has enhancement blocks allocated, return.
671     */
672     if (*enh == NULL)
673     {
674         /*
675         ** Otherwise, allocate and initialize a row of enhancement blocks.
676         */
677         *enh = (DtEnh) malloc(MAX_COLS(tb) * sizeof(DtTermEnhPart));
678         if (*enh == NULL)
679         {
680             return(False);
681         }
682
683         /*
684         ** Clear all the enhancements...
685         */
686         (void) memset(*enh, 0, MAX_COLS(tb) * sizeof(DtTermEnhPart));
687     }
688     return(True);
689 }
690
691 /*
692 ** Free the enhancement block at the specified row and column.
693 **
694 ** NOTE: We may get smarter later on.
695 */
696 Boolean
697 _DtTermBufferFreeEnhancement
698 (
699     TermBuffer  tb,
700     short       row,
701     short       col
702 )
703 {
704     return(True);
705 }
706
707 /*
708 ** Set the desired enhancement.
709 **
710 **  This function does the right thing (as far as I can tell regarding
711 **  propagating enhancements).
712 **
713 ** Return:
714 **     -1   : the enhancement was not set
715 **     >= 0 : the number of characters (as opposed to character positions)
716 **            that the enhancement affects
717 */
718 static int
719 _DtTermSetEnhancement
720 (
721     TermBuffer      tb,
722     short           row,
723     short           col,
724     unsigned char   id,
725     enhValue        value
726 )
727 {
728     int     i;
729     DtEnh   enhState;
730     
731     enhState = (DtEnh) &(DT_ENH_STATE(tb));
732     
733     /*
734     ** Set the value.
735     */
736     switch (id)
737     {
738       case enhVideo:
739         enhState->video   = (value &= VIDEO_MASK);
740         break;
741       case enhField:
742         enhState->field   = (value &= FIELD_MASK);
743         break;
744       case enhFgColor:
745         enhState->fgColor = (value &= COLOR_MASK);
746         break;
747       case enhBgColor:
748         enhState->bgColor = (value &= COLOR_MASK);
749         break;
750       case enhFont:
751         enhState->font    = (value &= FONT_MASK);
752         break;
753       default:
754         return(-1);
755     }
756     
757     /* 
758     ** We've set the value, now decide if this anything but the blank
759     ** enhancement.
760     */
761     DT_ENH_DIRTY(tb) = ((enhState->video   != blankEnh.video  ) ||
762                         (enhState->field   != blankEnh.field  ) ||
763                         (enhState->fgColor != blankEnh.fgColor) ||
764                         (enhState->bgColor != blankEnh.bgColor) ||
765                         (enhState->font    != blankEnh.font   ));
766     /* 
767     ** return the correct count (which in this case will always be 0)
768     */
769     return(0);
770 }
771
772 /*
773 ** Get the enhancements for the desired row and column.
774 **
775 **  enhValues:
776 **      a pointer to an array of the current enhancement values
777 **
778 **  count:
779 **      the number of columns for which the enhancements are
780 **      valid, or the number of columns until the enhancements
781 **      were modified by an escape sequence (see 'countWhich' below)
782 **
783 **  countWhich:
784 **      if 'countWhich' is countAll then count until any enhancement value
785 **      changes
786 **      if 'countAll' is countNew then count until a new enhancement value
787 **      starts (regardless of whether it is the same or not).
788 **
789 ** Return:
790 **     True if row and col are valid
791 */
792 static Boolean
793 _DtTermGetEnhancement
794 (
795     const TermBuffer      tb,
796     const short           row,
797     const short           col,
798           enhValue      **values,
799           short          *count,
800     const countSpec       countWhich
801 )
802 {
803     /*
804     ** store the current enhancement values here
805     */
806     int    i;
807     DtLine line;
808     DtEnh  enh;
809
810     /*
811     ** First we do some simple bounds checking
812     */
813     VALIDATE_ENHANCEMENTS(tb, row);
814     if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
815     {
816         return(False);
817     }
818     line = DT_LINE_OF_TBUF(tb, row);
819
820     /*
821     ** point to the correct enhancement chunk.
822     */
823     if (DT_ENH(line) == NULL || (WIDTH(line) <= col))
824     {
825         /*
826         ** There are either no enhancements allocated for this line, 
827         ** or we're past the end of the line, in either case return
828         ** a blank enhancement.
829         */
830         enh = &blankEnh;
831     }
832     else
833     {
834         /*
835         ** We're in the line get the current enhancement values
836         */
837         enh = &(DT_ENH(line)[col]);
838     }
839
840     /*
841     ** Shove the enhancement values into their correct locations...
842     */
843     *values                    = (VALUE_LIST(tb));
844     (*values)[(int)enhVideo  ] = (enh->video   & VIDEO_MASK);
845     (*values)[(int)enhField  ] = (enh->field   & FIELD_MASK);
846     (*values)[(int)enhFgColor] = (enh->fgColor & COLOR_MASK);
847     (*values)[(int)enhBgColor] = (enh->bgColor & COLOR_MASK);
848     (*values)[(int)enhFont   ] = (enh->font    & FONT_MASK );
849
850     /*
851     ** Now count how many characters are affected by the enhancements.
852     */
853     if (DT_ENH(line) == NULL)
854     {
855         /*
856         ** There no enhancements allocated for this line, the default
857         ** enhancement is active for the remainder of the line.
858         ** NOTE: Make sure count >= 0.
859         */
860         *count = MAX(0, WIDTH(line) - col);
861     }
862     else if (WIDTH(line) <= col)
863     {
864         /*
865         ** We're past the end of the line, count will always == 0;
866         */
867         *count = 0;
868     }
869     else
870     {
871         /*
872         ** We're in the line, determine the number of characters that
873         ** these enhancements apply to.
874         */
875         switch (countWhich)
876         {
877           case countNew:
878             /*
879             **  For Vt220 emulation, countNew is the same as countAll...
880             **  JRM 08/30/93
881             */
882           case countAll:
883             /*
884             ** count until an enhancement value changes
885             */
886             for (i = 0; i < (WIDTH(line) - col); i++)
887             {
888                 if (((*values)[(int)enhVideo  ] != (enh->video   & VIDEO_MASK))||
889                     ((*values)[(int)enhField  ] != (enh->field   & FIELD_MASK))||
890                     ((*values)[(int)enhFgColor] != (enh->fgColor & COLOR_MASK))||
891                     ((*values)[(int)enhBgColor] != (enh->bgColor & COLOR_MASK))||
892                     ((*values)[(int)enhFont   ] != (enh->font    & FONT_MASK ))  )
893                 {
894                     /*
895                     ** the enhancements differ; break out
896                     */
897                     break;
898                 }
899                 enh++;
900             }
901             break;
902           default:
903             VALIDATE_ENHANCEMENTS(tb, row);
904             return(False);
905         }
906         *count = i;
907     }
908     VALIDATE_ENHANCEMENTS(tb, row);
909     return(True);
910 }
911
912 /*
913 ** This is a vt-specific helper function for setting the line length.
914 ** By the time the function is called, termBufferSetLineLength()
915 ** as already validated the newLength, the row, and insured that the
916 ** new length is > the current length
917 **
918 ** This function propagates the correct enhancement to the new end of line.
919 */
920 static Boolean
921 _DtTermSetLineLength
922 (
923     TermBuffer      tb,
924     short           row,
925     short           newLength
926 )
927 {
928     return(True);
929 }
930
931 /*
932 ** _DtTermPrimBufferClearLine will reset the line width, this is
933 ** our chance to clear any enhancements that may exist on this line...
934 */
935 static Boolean
936 _DtTermClearLine
937 (
938     TermBuffer  tb,
939     short       row,
940     short       newWidth
941 )
942 {
943     DtLine  line;
944     DtEnh   enh;
945     
946     line = DT_LINE_OF_TBUF(tb, row);
947     enh  = DT_ENH(line);
948     
949     if (enh != NULL)
950     {
951         /*
952         ** We have enhancements, clear all those between the current
953         ** and the new length...
954         */
955         
956         (void) memset(&enh[newWidth], 0,
957                       (WIDTH(line) - newWidth) * sizeof(DtTermEnhPart));
958     }
959     return(True);
960 }
961
962 /*
963 ** Erase characters on the specified row (and clear the enhancements) with
964 ** the appropriate semantics.  For VT class emulators, there are several
965 ** ways to erase characters:
966 **      - from the active position to the end of line
967 **      - erase the specified number of characters starting at the current
968 **        cursor position
969 **      - from the start of the line to the active position
970 **      - erase the entire line
971 **      - from the active position to the end of the buffer
972 **      - erase the specified number of lines starting at the current
973 **        cursor position
974 **      - from the start of the buffer to the active position
975 **      - erase the entire buffer
976 */
977 void
978 _DtTermBufferErase
979 (
980     TermBuffer  tb,
981     short       row,
982     short       col,
983     short       count,
984     DtEraseMode eraseSwitch
985 )
986 {
987     short  startCol;
988     short  lastCol;
989     
990     switch(eraseSwitch)
991     {
992       case eraseFromCol0:
993         /*
994         ** erase from col 0 to the current cursor position
995         */
996         startCol = 0;
997         lastCol  = MIN(col, WIDTH(DT_LINE_OF_TBUF(tb, row)) - 1);
998         break;
999         
1000       case eraseCharCount:
1001         /*
1002         ** erase "count" characters from the current cursor position
1003         */
1004         startCol = col;
1005         lastCol  = MIN(col + count - 1, WIDTH(DT_LINE_OF_TBUF(tb, row)) - 1);
1006         break;
1007
1008       case eraseLineCount:
1009       case eraseToEOL:
1010       case eraseLine:
1011       case eraseBuffer:
1012       case eraseFromRow0Col0:
1013       case eraseToEOB:
1014         /*
1015         ** These cases should have been handled by _DtTermFuncErase()
1016         */
1017         return;
1018     }
1019
1020     _DtTermPrimBufferErase(tb, row, startCol, lastCol);
1021     /*
1022     ** now clear the corresponding enhancements...
1023     */
1024     clearEnhancements(tb, row, startCol, lastCol - startCol + 1);
1025 }
1026
1027 #if (defined(TEST) || defined(__CODECENTER__) || defined(VALIDATE_ENH))
1028 static void
1029 _DtTermValidateEnhancements
1030 (
1031     TermBuffer  tb,
1032     short       row
1033 )
1034 {
1035     DtTermEnhPart  refEnh;
1036     DtEnh        thisEnh;
1037     DtLine    thisLine;
1038     short          col;
1039     Boolean validatePassed;
1040
1041     validatePassed = True;
1042
1043     thisLine = DT_LINE_OF_TBUF(tb, row);
1044     if (DT_ENH(thisLine))
1045     {
1046         /* 
1047         ** Initialize the reference enhancement
1048         */
1049         refEnh = blankEnh;
1050         refEnh.videoStart = 0;
1051         refEnh.fieldStart = 0;
1052         refEnh.colorStart = 0;
1053         refEnh.fontStart  = 0;
1054
1055         for(col = 0, thisEnh = DT_ENH(thisLine); 
1056             col < WIDTH(thisLine) + 
1057                   (DANGLE(thisLine) >= 0 ? 1 : 0);
1058             col++, thisEnh++)
1059         {
1060             if (thisEnh->videoStart)
1061             {
1062                 refEnh.video = thisEnh->video;
1063             }
1064             else if (refEnh.video != thisEnh->video)
1065             {
1066                 fprintf(stderr, "Video enhancements don't match:");
1067                 fprintf(stderr, "    row : %3.3d, col : %3.3d\n", row, col);
1068                 fprintf(stderr, "    refEnh.video : %d\n", (int)(refEnh.video  & VIDEO_MASK));
1069                 fprintf(stderr, "    thisEnh->video: %d\n", (int)(thisEnh->video & VIDEO_MASK));
1070                 validatePassed = False;
1071             }    
1072
1073             if (thisEnh->fieldStart)
1074             {
1075                 refEnh.field = thisEnh->field;
1076             }
1077             else if (refEnh.field != thisEnh->field)
1078             {
1079                 fprintf(stderr, "Field enhancements don't match:");
1080                 fprintf(stderr, "    row : %3.3d, col : %3.3d\n", row, col);
1081                 fprintf(stderr, "    refEnh.field : %d\n", (int)(refEnh.field  & FIELD_MASK));
1082                 fprintf(stderr, "    thisEnh->field: %d\n", (int)(thisEnh->field & FIELD_MASK));
1083                 validatePassed = False;
1084             }    
1085             if (thisEnh->colorStart)
1086             {
1087                 refEnh.color = thisEnh->color;
1088             }
1089             else if (refEnh.color != thisEnh->color)
1090             {
1091                 fprintf(stderr, "Color enhancements don't match:");
1092                 fprintf(stderr, "    row : %3.3d, col : %3.3d\n", row, col);
1093                 fprintf(stderr, "    refEnh.color : %d\n", (int)(refEnh.color  & COLOR_MASK));
1094                 fprintf(stderr, "    thisEnh->color: %d\n", (int)(thisEnh->color & COLOR_MASK));
1095                 validatePassed = False;
1096             }    
1097             if (thisEnh->font <= 2)
1098             {
1099                 if (thisEnh->fontStart)
1100                 {
1101                     refEnh.font = thisEnh->font;
1102                 }
1103                 else if (refEnh.font != thisEnh->font)
1104                 {
1105                     fprintf(stderr, "Font enhancements don't match:");
1106                     fprintf(stderr, "    row : %3.3d, col : %3.3d\n", row, col);
1107                     fprintf(stderr, "    refEnh.font : %d\n", (int)(refEnh.font  & FONT_MASK));
1108                     fprintf(stderr, "    thisEnh->font: %d\n", (int)(thisEnh->font & FONT_MASK));
1109                     validatePassed = False;
1110                 }    
1111             }
1112             else
1113             {
1114                 fprintf(stderr, "Font enhancement out of range:");
1115                 fprintf(stderr, "    row : %3.3d, col : %3.3d\n", row, col);
1116                 fprintf(stderr, "    thisEnh->font: %d\n", (int)(thisEnh->font & FONT_MASK));
1117                 validatePassed = False;
1118             }
1119         }
1120     }
1121     if (validatePassed == False)
1122     {
1123         fprintf(stderr, "validateEnhancement failed\n");
1124     }
1125 }
1126 #endif /* TEST || __CODECENTER__ || DEBUG || VALIDATE_ENH */
1127
1128 #if (defined(TEST) || defined(__CODECENTER__) || defined(DEBUG))
1129 #ifdef NOCODE
1130 static void
1131 _printLine
1132 (
1133     TermBuffer tb,
1134     short row
1135 )
1136 {
1137     DtLine line;
1138     termChar   *pChar;
1139     short       j;
1140
1141     printf("Line: %d\n", row);
1142
1143     line = tb->lines[row];
1144     printf("    length: %3d\n", line->length);
1145     if (line->length > 0)
1146     {
1147         printf("    buffer: <");
1148         pChar = line->buffer;
1149         for (j = 0; j < line->length; j++)
1150         {
1151             printf("%X", *pChar++);
1152         }
1153         printf(">\n");
1154     }
1155 }
1156
1157 static int
1158 _DtTermPrintEnhancement
1159 (
1160     TermBuffer tb,
1161     short row,
1162     short col
1163 )
1164 {
1165     enhValue        enhancements[NUM_ENHANCEMENT_FIELDS];
1166     short           enhCount;
1167
1168
1169     _DtTermPrimBufferGetEnhancement(tb, row, col, enhancements, &enhCount, countNew);
1170     printf("    col  : %d\n", col);
1171     printf("    Count: %d\n", enhCount);
1172     printf("        Video: '_");
1173     printf("%s", IS_BOLD(enhancements[enhVideo])        != 0 ? "B":"b");
1174     printf("_");
1175     printf("%s", IS_SECURE(enhancements[enhVideo])      != 0 ? "S":"s");
1176     printf("_");
1177     printf("%s", IS_HALF_BRIGHT(enhancements[enhVideo]) != 0 ? "H":"h");
1178     printf("_");
1179     printf("%s", IS_UNDERLINE(enhancements[enhVideo])   != 0 ? "U":"u");
1180     printf("_");
1181     printf("%s", IS_INVERSE(enhancements[enhVideo])     != 0 ? "I":"i");
1182     printf("_");
1183     printf("%s", IS_BLINK(enhancements[enhVideo])       != 0 ? "B":"b");
1184     printf("_'\n");
1185
1186     /*
1187     ** Field type
1188     */
1189     printf("        Field: ");
1190     switch (enhancements[enhField])
1191     {
1192       case FIELD_PROTECT:
1193         printf("PROTECT");
1194         break;
1195       case FIELD_UNPROTECT:
1196         printf("UNPROTECT");
1197         break;
1198       case FIELD_TRANSMIT:
1199         printf("TRANSMIT");
1200         break;
1201       case FIELD_END:
1202         printf("END");
1203         break;
1204     }
1205     printf("\n");
1206
1207     /*
1208     ** Color id
1209     */
1210     printf("        Color: %1d\n", enhancements[enhFont]);
1211
1212     /*
1213     ** Font id
1214     */
1215     printf("        Font : ");
1216     switch (enhancements[enhFont])
1217     {
1218       case FONT_NORMAL:
1219         printf("NORMAL");
1220         break;
1221       case FONT_LINEDRAW:
1222         printf("LINEDRAW");
1223         break;
1224     }
1225     printf("\n");
1226     return(enhCount);
1227 }
1228 #endif /* NOCODE */
1229
1230 static void
1231 printEnh
1232 (
1233     DtEnh enh
1234 )
1235 {
1236     printf(" video  : %d\n", enh->video);
1237     printf(" field  : %d\n", enh->field);
1238     printf(" fgColor: %d\n", enh->fgColor);
1239     printf(" bgColor: %d\n", enh->bgColor);
1240     printf(" font   : %d\n", enh->font);
1241 }
1242
1243 /*
1244 ** Print the contents of the TermBuffer.
1245 */
1246 static void
1247 _DtTermPrintBuffer
1248 (
1249     DtTermBuffer tb
1250 )
1251 {
1252     short i;
1253     short j;
1254     short k;
1255
1256     if (tb == NULL) {
1257         printf("TermBuffer has been freed.\n");
1258         return;
1259     }
1260
1261     printf("TermBuffer dimensions:\n");
1262     printf("    rows: %d\n", ROWS(tb));
1263     printf("    cols: %d\n", COLS(tb));
1264     printf("    enhDirty: %d\n", DT_ENH_DIRTY(tb));
1265     printf("    enhState:\n");
1266     printEnh(&(DT_ENH_STATE(tb)));
1267 #ifdef NOCODE
1268     for (i = 0; i < ROWS(tb); i++)
1269     {
1270         _printLine(tb, i);
1271         j = 0;
1272         do
1273         {
1274             k = _termBufferPrintEnhancement(tb, i, j);
1275             if (k == 0)
1276             {
1277                 break;
1278             }
1279             j += k;
1280         } while (j < COLS(tb));
1281     }
1282 #endif /* NOCODE */
1283 }
1284 #endif /* (defined(TEST) || defined(__CODECENTER__)) */
1285
1286 #ifdef TEST
1287 /*
1288 ** Some simple tests of the termBuffer.
1289 */
1290 /* the following is to allow for a single main function in the code... */
1291 #define       termBufMain     main
1292 termBufMain()
1293 {
1294     TermBuffer  myTB;
1295
1296     printf("Sizeof DtTermEnhPart : %d\n", sizeof(struct _DtTermEnhPart));
1297     printf("Sizeof termBufferRec : %d\n", sizeof(struct _TermBufferRec));
1298
1299     myTB = _DtTermPrimBufferCreateBuffer(12, 80);
1300     _termBufferPrintBuffer(myTB);
1301
1302     printf("[0,0] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 0, enhVideo, BLINK));
1303     _termBufferPrintEnhancement(myTB, 0, 0);
1304     printf("[0,1] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 1, enhVideo, INVERSE));
1305     _termBufferPrintEnhancement(myTB, 0, 0);
1306     _termBufferPrintEnhancement(myTB, 0, 1);
1307     printf("[0,9] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 9, enhVideo, UNDERLINE));
1308     _termBufferPrintEnhancement(myTB, 0, 0);
1309     _termBufferPrintEnhancement(myTB, 0, 1);
1310     _termBufferPrintEnhancement(myTB, 0, 9);
1311     printf("[0,6] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 6, enhVideo, HALF_BRIGHT));
1312     _termBufferPrintEnhancement(myTB, 0, 0);
1313     _termBufferPrintEnhancement(myTB, 0, 1);
1314     _termBufferPrintEnhancement(myTB, 0, 6);
1315     _termBufferPrintEnhancement(myTB, 0, 9);
1316     _termBufferPrintBuffer(myTB);
1317
1318     _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
1319     _DtTermPrimBufferSetEnhancement(myTB, 10, 20, enhColor, 3);
1320     _termBufferPrintBuffer(myTB);
1321
1322     _DtTermPrimBufferResizeBuffer(&myTB,  6, 40);
1323     _termBufferPrintBuffer(myTB);
1324
1325     _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
1326     _DtTermPrimBufferResizeBuffer(&myTB, 12, 80);
1327     _termBufferPrintBuffer(myTB);
1328
1329     _DtTermPrimBufferFreeBuffer(myTB);
1330 }
1331 #endif /* TEST */
1332
1333
1334
1335
1336
1337
1338
1339
1340