linedata.c revision 190d7dce
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 */ 44LineData * 45getLineData(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 */ 70void 71copyLineData(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 167void 168initLineData(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 230CellData * 231newCellData(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 241void 242saveCellData(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 286void 287restoreCellData(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