linedata.c revision d4fba8b9
1/* $XTermId: linedata.c,v 1.97 2019/06/30 19:10:53 tom Exp $ */ 2 3/* 4 * Copyright 2009-2018,2019 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 = screen->max_row; 50 51 if (row >= 0) { 52 buffer = screen->visbuf; 53 } else { 54#if OPT_FIFO_LINES 55 buffer = 0; 56 result = getScrollback(screen, row); 57#else 58 buffer = screen->saveBuf_index; 59 row += screen->savelines; 60 max_row += screen->savelines; 61#endif 62 } 63 if (row >= 0 && row <= max_row) { 64 result = (LineData *) scrnHeadAddr(screen, buffer, (unsigned) row); 65 } 66 67 return result; 68} 69 70/* 71 * Copy line's data, e.g., from one screen buffer to another, given the preset 72 * pointers for the destination. 73 * 74 * TODO: optionally prune unused combining character data from the result. 75 */ 76void 77copyLineData(LineData *dst, CLineData *src) 78{ 79 if (dst == NULL || src == NULL) 80 return; 81 82 dst->bufHead = src->bufHead; 83 84#if OPT_WIDE_CHARS 85 dst->combSize = src->combSize; 86#endif 87 88 /* 89 * Usually we're copying the same-sized line; a memcpy is faster than 90 * several loops. 91 */ 92 if (dst->lineSize == src->lineSize) { 93 size_t size = (sizeof(dst->attribs[0]) 94#if OPT_ISO_COLORS 95 + sizeof(dst->color[0]) 96#endif 97 + sizeof(dst->charData[0]) 98#if OPT_WIDE_CHARS 99 + sizeof(dst->combData[0][0]) * dst->combSize 100#endif 101 ); 102 103 memcpy(dst->attribs, src->attribs, size * dst->lineSize); 104 } else { 105 Dimension col; 106 Dimension limit = ((dst->lineSize < src->lineSize) 107 ? dst->lineSize 108 : src->lineSize); 109#if OPT_WIDE_CHARS 110 Char comb; 111#endif 112 113 for (col = 0; col < limit; ++col) { 114 dst->attribs[col] = src->attribs[col]; 115#if OPT_ISO_COLORS 116 dst->color[col] = src->color[col]; 117#endif 118 dst->charData[col] = src->charData[col]; 119#if OPT_WIDE_CHARS 120 for (comb = 0; comb < dst->combSize; ++comb) { 121 dst->combData[comb][col] = src->combData[comb][col]; 122 } 123#endif 124 } 125 for (col = limit; col < dst->lineSize; ++col) { 126 dst->attribs[col] = 0; 127#if OPT_ISO_COLORS 128 dst->color[col] = initCColor; 129#endif 130 dst->charData[col] = 0; 131#if OPT_WIDE_CHARS 132 for (comb = 0; comb < dst->combSize; ++comb) { 133 dst->combData[comb][col] = 0; 134 } 135#endif 136 } 137 } 138} 139 140#if OPT_WIDE_CHARS 141#define initLineExtra(screen) \ 142 screen->lineExtra = ((size_t) (screen->max_combining) * sizeof(IChar *)); \ 143 screen->cellExtra = ((size_t) (screen->max_combining) * sizeof(IChar)) 144#else 145#define initLineExtra(screen) \ 146 screen->lineExtra = 0; \ 147 screen->cellExtra = 0 148#endif 149 150/* 151 * CellData size depends on the "combiningChars" resource. 152 */ 153#define CellDataSize(screen) (SizeOfCellData + screen->cellExtra) 154 155#define CellDataAddr(screen, data, cell) \ 156 ( (CellData *)(void *) ((char *)data + (cell * CellDataSize(screen))) ) 157#define ConstCellDataAddr(screen, data, cell) \ 158 ( (const CellData *)(const void *) ( \ 159 (const char *)data + (cell * CellDataSize(screen))) ) 160 161void 162initLineData(XtermWidget xw) 163{ 164 TScreen *screen = TScreenOf(xw); 165 166 initLineExtra(screen); 167 168#if OPT_WIDE_CHARS 169 TRACE(("initLineData %lu (%d combining chars)\n", 170 (unsigned long) screen->lineExtra, screen->max_combining)); 171#else 172 TRACE(("initLineData\n")); 173#endif 174 175 /* 176 * Per-line size/offsets. 177 */ 178 TRACE(("** sizeof(LineData) %lu\n", (unsigned long) sizeof(LineData))); 179 TRACE((" offset(lineSize) %lu\n", (unsigned long) offsetof(LineData, lineSize))); 180 TRACE((" offset(bufHead) %lu\n", (unsigned long) offsetof(LineData, bufHead))); 181#if OPT_WIDE_CHARS 182 TRACE((" offset(combSize) %lu\n", (unsigned long) offsetof(LineData, combSize))); 183#endif 184 TRACE((" offset(*attribs) %lu\n", (unsigned long) offsetof(LineData, attribs))); 185#if OPT_ISO_COLORS 186 TRACE((" offset(*color) %lu\n", (unsigned long) offsetof(LineData, color))); 187#endif 188 TRACE((" offset(*charData) %lu\n", (unsigned long) offsetof(LineData, charData))); 189 TRACE((" offset(*combData) %lu\n", (unsigned long) offsetof(LineData, combData))); 190 191 /* 192 * Per-cell size/offsets. 193 */ 194 TRACE(("** sizeof(CellData) %lu\n", (unsigned long) CellDataSize(screen))); 195 TRACE((" offset(attribs) %lu\n", (unsigned long) offsetof(CellData, attribs))); 196#if OPT_WIDE_CHARS 197 TRACE((" offset(combSize) %lu\n", (unsigned long) offsetof(CellData, combSize))); 198#endif 199#if OPT_ISO_COLORS 200 TRACE((" offset(color) %lu\n", (unsigned long) offsetof(CellData, color))); 201#endif 202 TRACE((" offset(charData) %lu\n", (unsigned long) offsetof(CellData, charData))); 203 TRACE((" offset(combData) %lu\n", (unsigned long) offsetof(CellData, combData))); 204 205 /* 206 * Data-type sizes. 207 */ 208#if OPT_ISO_COLORS 209 TRACE(("** sizeof(CellColor) %lu\n", (unsigned long) sizeof(CellColor))); 210#endif 211 TRACE(("** sizeof(IAttr) %lu\n", (unsigned long) sizeof(IAttr))); 212 TRACE(("** sizeof(IChar) %lu\n", (unsigned long) sizeof(IChar))); 213 TRACE(("** sizeof(RowData) %lu\n", (unsigned long) sizeof(RowData))); 214} 215 216CellData * 217newCellData(XtermWidget xw, Cardinal count) 218{ 219 CellData *result; 220 TScreen *screen = TScreenOf(xw); 221 222 initLineExtra(screen); 223 result = (CellData *) calloc((size_t) count, (size_t) CellDataSize(screen)); 224 return result; 225} 226 227void 228saveCellData(TScreen *screen, 229 CellData *data, 230 Cardinal cell, 231 CLineData *ld, 232 XTermRect *limits, 233 int column) 234{ 235 CellData *item = CellDataAddr(screen, data, cell); 236 237 (void) limits; 238 if (column < MaxCols(screen)) { 239 item->attribs = ld->attribs[column]; 240 if_OPT_ISO_COLORS(screen, { 241 item->color = ld->color[column]; 242 }); 243 item->charData = ld->charData[column]; 244 if_OPT_WIDE_CHARS(screen, { 245 size_t off; 246 Bool blank = (((item->charData == HIDDEN_CHAR) 247 && (limits == NULL 248 || (column + 1) == limits->left)) 249 || (item->charData != HIDDEN_CHAR 250 && WideCells(item->charData) > 1 251 && (limits == NULL 252 || (column + 1) >= limits->right))); 253 if (blank) { 254 item->charData = (Char) ' '; 255 } 256 item->combSize = blank ? 0 : ld->combSize; 257 for_each_combData(off, item) { 258 item->combData[off] = ld->combData[off][column]; 259 } 260 }); 261 TRACE2(("SAVED::%s\n", visibleIChars(&(item->charData), 1))); 262 } 263} 264 265void 266restoreCellData(TScreen *screen, 267 const CellData *data, 268 Cardinal cell, 269 LineData *ld, 270 XTermRect *limits, 271 int column) 272{ 273 const CellData *item = ConstCellDataAddr(screen, data, cell); 274 275 (void) limits; 276 if (column < MaxCols(screen)) { 277 ld->attribs[column] = item->attribs; 278 TRACE2(("BEFORE:%2d:%s\n", column + 1, visibleIChars(ld->charData, ld->lineSize))); 279 if_OPT_ISO_COLORS(screen, { 280 ld->color[column] = item->color; 281 }); 282 ld->charData[column] = item->charData; 283 if_OPT_WIDE_CHARS(screen, { 284 size_t off; 285 ld->combSize = item->combSize; 286 for_each_combData(off, ld) { 287 ld->combData[off][column] = item->combData[off]; 288 } 289 }); 290 TRACE2(("AFTER::%2d:%s\n", column + 1, visibleIChars(ld->charData, ld->lineSize))); 291 } 292} 293