linedata.c revision 50027b5b
1/* $XTermId: linedata.c,v 1.101 2021/12/27 23:43:28 tom Exp $ */ 2 3/* 4 * Copyright 2009-2019,2021 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 = 0; 48 ScrnBuf buffer; 49 int max_row = LastRowNumber(screen); 50 51 if (row >= 0) { 52 buffer = screen->visbuf; 53 } else { 54 buffer = 0; 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) 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 ); 96 97 memcpy(dst->attribs, src->attribs, size * dst->lineSize); 98 } else { 99 Dimension col; 100 Dimension limit = ((dst->lineSize < src->lineSize) 101 ? dst->lineSize 102 : src->lineSize); 103#if OPT_WIDE_CHARS 104 Char comb; 105#endif 106 107 for (col = 0; col < limit; ++col) { 108 dst->attribs[col] = src->attribs[col]; 109#if OPT_ISO_COLORS 110 dst->color[col] = src->color[col]; 111#endif 112 dst->charData[col] = src->charData[col]; 113#if OPT_WIDE_CHARS 114 for (comb = 0; comb < dst->combSize; ++comb) { 115 dst->combData[comb][col] = src->combData[comb][col]; 116 } 117#endif 118 } 119 for (col = limit; col < dst->lineSize; ++col) { 120 dst->attribs[col] = 0; 121#if OPT_ISO_COLORS 122 dst->color[col] = initCColor; 123#endif 124 dst->charData[col] = 0; 125#if OPT_WIDE_CHARS 126 for (comb = 0; comb < dst->combSize; ++comb) { 127 dst->combData[comb][col] = 0; 128 } 129#endif 130 } 131 } 132} 133 134#if OPT_WIDE_CHARS 135#define initLineExtra(screen) \ 136 screen->lineExtra = ((size_t) (screen->max_combining) * sizeof(IChar *)); \ 137 screen->cellExtra = ((size_t) (screen->max_combining) * sizeof(IChar)) 138#else 139#define initLineExtra(screen) \ 140 screen->lineExtra = 0; \ 141 screen->cellExtra = 0 142#endif 143 144/* 145 * CellData size depends on the "combiningChars" resource. 146 */ 147#define CellDataSize(screen) (SizeOfCellData + screen->cellExtra) 148 149#define CellDataAddr(screen, data, cell) \ 150 ( (CellData *)(void *) ((char *)data + (cell * CellDataSize(screen))) ) 151#define ConstCellDataAddr(screen, data, cell) \ 152 ( (const CellData *)(const void *) ( \ 153 (const char *)data + (cell * CellDataSize(screen))) ) 154 155void 156initLineData(XtermWidget xw) 157{ 158 TScreen *screen = TScreenOf(xw); 159 160 initLineExtra(screen); 161 162#if OPT_WIDE_CHARS 163 TRACE(("initLineData %lu (%d combining chars)\n", 164 (unsigned long) screen->lineExtra, screen->max_combining)); 165#else 166 TRACE(("initLineData\n")); 167#endif 168 169 /* 170 * Per-line size/offsets. 171 */ 172 TRACE(("** sizeof(LineData) %lu\n", (unsigned long) sizeof(LineData))); 173 TRACE((" offset(lineSize) %lu\n", (unsigned long) offsetof(LineData, lineSize))); 174 TRACE((" offset(bufHead) %lu\n", (unsigned long) offsetof(LineData, bufHead))); 175#if OPT_WIDE_CHARS 176 TRACE((" offset(combSize) %lu\n", (unsigned long) offsetof(LineData, combSize))); 177#endif 178 TRACE((" offset(*attribs) %lu\n", (unsigned long) offsetof(LineData, attribs))); 179#if OPT_ISO_COLORS 180 TRACE((" offset(*color) %lu\n", (unsigned long) offsetof(LineData, color))); 181#endif 182 TRACE((" offset(*charData) %lu\n", (unsigned long) offsetof(LineData, charData))); 183 TRACE((" offset(*combData) %lu\n", (unsigned long) offsetof(LineData, combData))); 184 185 /* 186 * Per-cell size/offsets. 187 */ 188 TRACE(("** sizeof(CellData) %lu\n", (unsigned long) CellDataSize(screen))); 189 TRACE((" offset(attribs) %lu\n", (unsigned long) offsetof(CellData, attribs))); 190#if OPT_WIDE_CHARS 191 TRACE((" offset(combSize) %lu\n", (unsigned long) offsetof(CellData, combSize))); 192#endif 193#if OPT_ISO_COLORS 194 TRACE((" offset(color) %lu\n", (unsigned long) offsetof(CellData, color))); 195#endif 196 TRACE((" offset(charData) %lu\n", (unsigned long) offsetof(CellData, charData))); 197 TRACE((" offset(combData) %lu\n", (unsigned long) offsetof(CellData, combData))); 198 199 /* 200 * Data-type sizes. 201 */ 202#if OPT_ISO_COLORS 203 TRACE(("** sizeof(CellColor) %lu\n", (unsigned long) sizeof(CellColor))); 204#endif 205 TRACE(("** sizeof(IAttr) %lu\n", (unsigned long) sizeof(IAttr))); 206 TRACE(("** sizeof(IChar) %lu\n", (unsigned long) sizeof(IChar))); 207 TRACE(("** sizeof(RowData) %lu\n", (unsigned long) sizeof(RowData))); 208} 209 210CellData * 211newCellData(XtermWidget xw, Cardinal count) 212{ 213 CellData *result; 214 TScreen *screen = TScreenOf(xw); 215 216 initLineExtra(screen); 217 result = (CellData *) calloc((size_t) count, (size_t) CellDataSize(screen)); 218 return result; 219} 220 221void 222saveCellData(TScreen *screen, 223 CellData *data, 224 Cardinal cell, 225 CLineData *ld, 226 XTermRect *limits, 227 int column) 228{ 229 CellData *item = CellDataAddr(screen, data, cell); 230 231 (void) limits; 232 if (column < MaxCols(screen)) { 233 item->attribs = ld->attribs[column]; 234 if_OPT_ISO_COLORS(screen, { 235 item->color = ld->color[column]; 236 }); 237 item->charData = ld->charData[column]; 238 if_OPT_WIDE_CHARS(screen, { 239 size_t off; 240 Bool blank = (((item->charData == HIDDEN_CHAR) 241 && (limits == NULL 242 || (column + 1) == limits->left)) 243 || (item->charData != HIDDEN_CHAR 244 && WideCells(item->charData) > 1 245 && (limits == NULL 246 || (column + 1) >= limits->right))); 247 if (blank) { 248 item->charData = (CharData) ' '; 249 } 250 item->combSize = blank ? 0 : ld->combSize; 251 for_each_combData(off, item) { 252 item->combData[off] = ld->combData[off][column]; 253 } 254 }); 255 TRACE2(("SAVED::%s\n", visibleIChars(&(item->charData), 1))); 256 } 257} 258 259void 260restoreCellData(TScreen *screen, 261 const CellData *data, 262 Cardinal cell, 263 LineData *ld, 264 XTermRect *limits, 265 int column) 266{ 267 const CellData *item = ConstCellDataAddr(screen, data, cell); 268 269 (void) limits; 270 if (column < MaxCols(screen)) { 271 ld->attribs[column] = item->attribs; 272 TRACE2(("BEFORE:%2d:%s\n", column + 1, visibleIChars(ld->charData, ld->lineSize))); 273 if_OPT_ISO_COLORS(screen, { 274 ld->color[column] = item->color; 275 }); 276 ld->charData[column] = item->charData; 277 if_OPT_WIDE_CHARS(screen, { 278 size_t off; 279 ld->combSize = item->combSize; 280 for_each_combData(off, ld) { 281 ld->combData[off][column] = item->combData[off]; 282 } 283 }); 284 TRACE2(("AFTER::%2d:%s\n", column + 1, visibleIChars(ld->charData, ld->lineSize))); 285 } 286} 287