Home | History | Annotate | Line # | Download | only in dist
      1 /* $XTermId: linedata.c,v 1.107 2024/12/01 20:27:00 tom Exp $ */
      2 
      3 /*
      4  * Copyright 2009-2023,2024 by Thomas E. Dickey
      5  *
      6  *                         All Rights Reserved
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the
     10  * "Software"), to deal in the Software without restriction, including
     11  * without limitation the rights to use, copy, modify, merge, publish,
     12  * distribute, sublicense, and/or sell copies of the Software, and to
     13  * permit persons to whom the Software is furnished to do so, subject to
     14  * the following conditions:
     15  *
     16  * The above copyright notice and this permission notice shall be included
     17  * in all copies or substantial portions of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     22  * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
     23  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26  *
     27  * Except as contained in this notice, the name(s) of the above copyright
     28  * holders shall not be used in advertising or otherwise to promote the
     29  * sale, use or other dealings in this Software without prior written
     30  * authorization.
     31  */
     32 
     33 #include <xterm.h>
     34 #include <data.h>
     35 
     36 #include <assert.h>
     37 
     38 /*
     39  * Given a row-number, find the corresponding data for the line in the VT100
     40  * widget.  Row numbers can be positive or negative.
     41  *
     42  * If the data comes from the scrollback, defer that to getScrollback().
     43  */
     44 LineData *
     45 getLineData(TScreen *screen, int row)
     46 {
     47     LineData *result = NULL;
     48     ScrnBuf buffer;
     49     int max_row = LastRowNumber(screen);
     50 
     51     if (row >= 0) {
     52 	buffer = screen->visbuf;
     53     } else {
     54 	buffer = NULL;
     55 	result = getScrollback(screen, row);
     56     }
     57     if (row >= 0 && row <= max_row) {
     58 	result = (LineData *) scrnHeadAddr(screen, buffer, (unsigned) row);
     59     }
     60 
     61     return result;
     62 }
     63 
     64 /*
     65  * Copy line's data, e.g., from one screen buffer to another, given the preset
     66  * pointers for the destination.
     67  *
     68  * TODO: optionally prune unused combining character data from the result.
     69  */
     70 void
     71 copyLineData(LineData *dst, CLineData *src)
     72 {
     73     if (dst == NULL || src == NULL || dst == src)
     74 	return;
     75 
     76     dst->bufHead = src->bufHead;
     77 
     78 #if OPT_WIDE_CHARS
     79     dst->combSize = src->combSize;
     80 #endif
     81 
     82     /*
     83      * Usually we're copying the same-sized line; a memcpy is faster than
     84      * several loops.
     85      */
     86     if (dst->lineSize == src->lineSize) {
     87 	size_t size = (sizeof(dst->attribs[0])
     88 #if OPT_ISO_COLORS
     89 		       + sizeof(dst->color[0])
     90 #endif
     91 		       + sizeof(dst->charData[0])
     92 #if OPT_WIDE_CHARS
     93 		       + sizeof(dst->combData[0][0]) * dst->combSize
     94 #endif
     95 #if OPT_DEC_RECTOPS
     96 		       + sizeof(dst->charSeen[0])
     97 		       + sizeof(dst->charSets[0])
     98 #endif
     99 	);
    100 
    101 	memcpy(dst->attribs, src->attribs, size * dst->lineSize);
    102     } else {
    103 	Dimension col;
    104 	Dimension limit = ((dst->lineSize < src->lineSize)
    105 			   ? dst->lineSize
    106 			   : src->lineSize);
    107 #if OPT_WIDE_CHARS
    108 	Char comb;
    109 #endif
    110 
    111 	for (col = 0; col < limit; ++col) {
    112 	    dst->attribs[col] = src->attribs[col];
    113 #if OPT_ISO_COLORS
    114 	    dst->color[col] = src->color[col];
    115 #endif
    116 	    dst->charData[col] = src->charData[col];
    117 #if OPT_DEC_RECTOPS
    118 	    dst->charSeen[col] = src->charSeen[col];
    119 	    dst->charSets[col] = src->charSets[col];
    120 #endif
    121 #if OPT_WIDE_CHARS
    122 	    for (comb = 0; comb < dst->combSize; ++comb) {
    123 		dst->combData[comb][col] = src->combData[comb][col];
    124 	    }
    125 #endif
    126 	}
    127 	for (col = limit; col < dst->lineSize; ++col) {
    128 	    dst->attribs[col] = 0;
    129 #if OPT_ISO_COLORS
    130 	    dst->color[col] = initCColor;
    131 #endif
    132 	    dst->charData[col] = 0;
    133 #if OPT_DEC_RECTOPS
    134 	    dst->charSeen[col] = 0;
    135 	    dst->charSets[col] = 0;
    136 #endif
    137 #if OPT_WIDE_CHARS
    138 	    for (comb = 0; comb < dst->combSize; ++comb) {
    139 		dst->combData[comb][col] = 0;
    140 	    }
    141 #endif
    142 	}
    143     }
    144 }
    145 
    146 #if OPT_WIDE_CHARS
    147 #define initLineExtra(screen) \
    148     screen->lineExtra = ((size_t) (screen->max_combining) * sizeof(IChar *)); \
    149     screen->cellExtra = ((size_t) (screen->max_combining) * sizeof(IChar))
    150 #else
    151 #define initLineExtra(screen) \
    152     screen->lineExtra = 0; \
    153     screen->cellExtra = 0
    154 #endif
    155 
    156 /*
    157  * CellData size depends on the "combiningChars" resource.
    158  */
    159 #define CellDataSize(screen) (SizeOfCellData + screen->cellExtra)
    160 
    161 #define CellDataAddr(screen, data, cell) \
    162 	( (CellData *)(void *) ((char *)data + (cell * CellDataSize(screen))) )
    163 #define ConstCellDataAddr(screen, data, cell) \
    164 	( (const CellData *)(const void *) ( \
    165 	      (const char *)data + (cell * CellDataSize(screen))) )
    166 
    167 void
    168 initLineData(XtermWidget xw)
    169 {
    170     TScreen *screen = TScreenOf(xw);
    171 
    172     initLineExtra(screen);
    173 
    174 #if OPT_WIDE_CHARS
    175     TRACE(("initLineData %lu (%d combining chars)\n",
    176 	   (unsigned long) screen->lineExtra, screen->max_combining));
    177 #else
    178     TRACE(("initLineData\n"));
    179 #endif
    180 
    181     /*
    182      * Per-line size/offsets.
    183      */
    184     TRACE(("** sizeof(LineData)  %lu\n", (unsigned long) sizeof(LineData)));
    185     TRACE(("   offset(lineSize)  %lu\n", (unsigned long) offsetof(LineData, lineSize)));
    186     TRACE(("   offset(bufHead)   %lu\n", (unsigned long) offsetof(LineData, bufHead)));
    187 #if OPT_WIDE_CHARS
    188     TRACE(("   offset(combSize)  %lu\n", (unsigned long) offsetof(LineData, combSize)));
    189 #endif
    190 #if OPT_DEC_RECTOPS
    191     TRACE(("   offset(*charSeen) %lu\n", (unsigned long) offsetof(LineData, charSeen)));
    192     TRACE(("   offset(*charSets) %lu\n", (unsigned long) offsetof(LineData, charSets)));
    193 #endif
    194     TRACE(("   offset(*attribs)  %lu\n", (unsigned long) offsetof(LineData, attribs)));
    195 #if OPT_ISO_COLORS
    196     TRACE(("   offset(*color)    %lu\n", (unsigned long) offsetof(LineData, color)));
    197 #endif
    198     TRACE(("   offset(*charData) %lu\n", (unsigned long) offsetof(LineData, charData)));
    199     TRACE(("   offset(*combData) %lu\n", (unsigned long) offsetof(LineData, combData)));
    200 
    201     /*
    202      * Per-cell size/offsets.
    203      */
    204     TRACE(("** sizeof(CellData)  %lu\n", (unsigned long) CellDataSize(screen)));
    205     TRACE(("   offset(attribs)   %lu\n", (unsigned long) offsetof(CellData, attribs)));
    206 #if OPT_WIDE_CHARS
    207     TRACE(("   offset(combSize)  %lu\n", (unsigned long) offsetof(CellData, combSize)));
    208 #endif
    209 #if OPT_DEC_RECTOPS
    210     TRACE(("   offset(charSeen)  %lu\n", (unsigned long) offsetof(CellData, charSeen)));
    211     TRACE(("   offset(charSets)  %lu\n", (unsigned long) offsetof(CellData, charSets)));
    212 #endif
    213 #if OPT_ISO_COLORS
    214     TRACE(("   offset(color)     %lu\n", (unsigned long) offsetof(CellData, color)));
    215 #endif
    216     TRACE(("   offset(charData)  %lu\n", (unsigned long) offsetof(CellData, charData)));
    217     TRACE(("   offset(combData)  %lu\n", (unsigned long) offsetof(CellData, combData)));
    218 
    219     /*
    220      * Data-type sizes.
    221      */
    222 #if OPT_ISO_COLORS
    223     TRACE(("** sizeof(CellColor) %lu\n", (unsigned long) sizeof(CellColor)));
    224 #endif
    225     TRACE(("** sizeof(IAttr)     %lu\n", (unsigned long) sizeof(IAttr)));
    226     TRACE(("** sizeof(IChar)     %lu\n", (unsigned long) sizeof(IChar)));
    227     TRACE(("** sizeof(RowData)   %lu\n", (unsigned long) sizeof(RowData)));
    228 }
    229 
    230 CellData *
    231 newCellData(XtermWidget xw, Cardinal count)
    232 {
    233     CellData *result;
    234     TScreen *screen = TScreenOf(xw);
    235 
    236     initLineExtra(screen);
    237     result = (CellData *) calloc((size_t) count, (size_t) CellDataSize(screen));
    238     return result;
    239 }
    240 
    241 void
    242 saveCellData(TScreen *screen,
    243 	     CellData *data,
    244 	     Cardinal cell,
    245 	     CLineData *ld,
    246 	     XTermRect *limits,
    247 	     int column)
    248 {
    249     CellData *item = CellDataAddr(screen, data, cell);
    250 
    251     (void) limits;
    252     if (column < MaxCols(screen)) {
    253 	item->attribs = ld->attribs[column];
    254 	if_OPT_ISO_COLORS(screen, {
    255 	    item->color = ld->color[column];
    256 	});
    257 	if_OPT_DEC_RECTOPS({
    258 	    item->charSeen = ld->charSeen[column];
    259 	    item->charData = ld->charData[column];
    260 	});
    261 	if_OPT_WIDE_CHARS(screen, {
    262 	    size_t off;
    263 	    Bool blank = (((item->charData == HIDDEN_CHAR)
    264 			   && (limits == NULL
    265 			       || (column + 1) == limits->left))
    266 			  || (item->charData != HIDDEN_CHAR
    267 			      && WideCells(item->charData) > 1
    268 			      && (limits == NULL
    269 				  || (column + 1) >= limits->right)));
    270 	    if (blank) {
    271 		if_OPT_DEC_RECTOPS(item->charSeen = ' ');
    272 		item->charData = (CharData) ' ';
    273 	    }
    274 	    item->combSize = blank ? 0 : ld->combSize;
    275 	    if_OPT_DEC_RECTOPS(item->charSets = (blank
    276 						 ? 0
    277 						 : ld->charSets[column]));
    278 	    for_each_combData(off, item) {
    279 		item->combData[off] = ld->combData[off][column];
    280 	    }
    281 	});
    282 	TRACE2(("SAVED::%s\n", visibleIChars(&(item->charData), 1)));
    283     }
    284 }
    285 
    286 void
    287 restoreCellData(TScreen *screen,
    288 		const CellData *data,
    289 		Cardinal cell,
    290 		LineData *ld,
    291 		XTermRect *limits,
    292 		int column)
    293 {
    294     const CellData *item = ConstCellDataAddr(screen, data, cell);
    295 
    296     (void) limits;
    297     if (column < MaxCols(screen)) {
    298 	ld->attribs[column] = item->attribs;
    299 	TRACE2(("BEFORE:%2d:%s\n", column + 1, visibleIChars(ld->charData, ld->lineSize)));
    300 	if_OPT_ISO_COLORS(screen, {
    301 	    ld->color[column] = item->color;
    302 	});
    303 	if_OPT_DEC_RECTOPS({
    304 	    ld->charSeen[column] = item->charSeen;
    305 	    ld->charSets[column] = item->charSets;
    306 	});
    307 	ld->charData[column] = item->charData;
    308 	if_OPT_WIDE_CHARS(screen, {
    309 	    size_t off;
    310 	    ld->combSize = item->combSize;
    311 	    if_OPT_DEC_RECTOPS(ld->charSets[column] = item->charSets);
    312 	    for_each_combData(off, ld) {
    313 		ld->combData[off][column] = item->combData[off];
    314 	    }
    315 	});
    316 	TRACE2(("AFTER::%2d:%s\n", column + 1, visibleIChars(ld->charData, ld->lineSize)));
    317     }
    318 }
    319