1190d7dceSmrg/* $XTermId: linedata.c,v 1.107 2024/12/01 20:27:00 tom Exp $ */ 2956cc18dSsnj 33367019cSmrg/* 4190d7dceSmrg * Copyright 2009-2023,2024 by Thomas E. Dickey 53367019cSmrg * 63367019cSmrg * All Rights Reserved 73367019cSmrg * 83367019cSmrg * Permission is hereby granted, free of charge, to any person obtaining a 93367019cSmrg * copy of this software and associated documentation files (the 103367019cSmrg * "Software"), to deal in the Software without restriction, including 113367019cSmrg * without limitation the rights to use, copy, modify, merge, publish, 123367019cSmrg * distribute, sublicense, and/or sell copies of the Software, and to 133367019cSmrg * permit persons to whom the Software is furnished to do so, subject to 143367019cSmrg * the following conditions: 153367019cSmrg * 163367019cSmrg * The above copyright notice and this permission notice shall be included 173367019cSmrg * in all copies or substantial portions of the Software. 183367019cSmrg * 193367019cSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 203367019cSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 213367019cSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 223367019cSmrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 233367019cSmrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 243367019cSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 253367019cSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 263367019cSmrg * 273367019cSmrg * Except as contained in this notice, the name(s) of the above copyright 283367019cSmrg * holders shall not be used in advertising or otherwise to promote the 293367019cSmrg * sale, use or other dealings in this Software without prior written 303367019cSmrg * authorization. 313367019cSmrg */ 32956cc18dSsnj 33956cc18dSsnj#include <xterm.h> 34d4fba8b9Smrg#include <data.h> 35956cc18dSsnj 36956cc18dSsnj#include <assert.h> 37956cc18dSsnj 38956cc18dSsnj/* 39956cc18dSsnj * Given a row-number, find the corresponding data for the line in the VT100 40956cc18dSsnj * widget. Row numbers can be positive or negative. 41956cc18dSsnj * 42956cc18dSsnj * If the data comes from the scrollback, defer that to getScrollback(). 43956cc18dSsnj */ 44956cc18dSsnjLineData * 4594644356SmrggetLineData(TScreen *screen, int row) 46956cc18dSsnj{ 47190d7dceSmrg LineData *result = NULL; 48956cc18dSsnj ScrnBuf buffer; 4950027b5bSmrg int max_row = LastRowNumber(screen); 50956cc18dSsnj 51956cc18dSsnj if (row >= 0) { 52956cc18dSsnj buffer = screen->visbuf; 53956cc18dSsnj } else { 54190d7dceSmrg buffer = NULL; 55956cc18dSsnj result = getScrollback(screen, row); 56956cc18dSsnj } 5720d2c4d2Smrg if (row >= 0 && row <= max_row) { 58956cc18dSsnj result = (LineData *) scrnHeadAddr(screen, buffer, (unsigned) row); 59956cc18dSsnj } 60956cc18dSsnj 61956cc18dSsnj return result; 62956cc18dSsnj} 63956cc18dSsnj 64956cc18dSsnj/* 65956cc18dSsnj * Copy line's data, e.g., from one screen buffer to another, given the preset 66956cc18dSsnj * pointers for the destination. 67956cc18dSsnj * 68956cc18dSsnj * TODO: optionally prune unused combining character data from the result. 69956cc18dSsnj */ 70956cc18dSsnjvoid 7194644356SmrgcopyLineData(LineData *dst, CLineData *src) 72956cc18dSsnj{ 73d1603babSmrg if (dst == NULL || src == NULL || dst == src) 74d4fba8b9Smrg return; 75d4fba8b9Smrg 76956cc18dSsnj dst->bufHead = src->bufHead; 77956cc18dSsnj 78956cc18dSsnj#if OPT_WIDE_CHARS 79956cc18dSsnj dst->combSize = src->combSize; 80956cc18dSsnj#endif 81956cc18dSsnj 82956cc18dSsnj /* 83956cc18dSsnj * Usually we're copying the same-sized line; a memcpy is faster than 84956cc18dSsnj * several loops. 85956cc18dSsnj */ 86956cc18dSsnj if (dst->lineSize == src->lineSize) { 87956cc18dSsnj size_t size = (sizeof(dst->attribs[0]) 88956cc18dSsnj#if OPT_ISO_COLORS 89956cc18dSsnj + sizeof(dst->color[0]) 90956cc18dSsnj#endif 91956cc18dSsnj + sizeof(dst->charData[0]) 92956cc18dSsnj#if OPT_WIDE_CHARS 93956cc18dSsnj + sizeof(dst->combData[0][0]) * dst->combSize 94980988aeSmrg#endif 95980988aeSmrg#if OPT_DEC_RECTOPS 96980988aeSmrg + sizeof(dst->charSeen[0]) 97980988aeSmrg + sizeof(dst->charSets[0]) 98956cc18dSsnj#endif 99956cc18dSsnj ); 100956cc18dSsnj 101956cc18dSsnj memcpy(dst->attribs, src->attribs, size * dst->lineSize); 102956cc18dSsnj } else { 103956cc18dSsnj Dimension col; 104956cc18dSsnj Dimension limit = ((dst->lineSize < src->lineSize) 105956cc18dSsnj ? dst->lineSize 106956cc18dSsnj : src->lineSize); 107956cc18dSsnj#if OPT_WIDE_CHARS 108956cc18dSsnj Char comb; 109956cc18dSsnj#endif 110956cc18dSsnj 111956cc18dSsnj for (col = 0; col < limit; ++col) { 112956cc18dSsnj dst->attribs[col] = src->attribs[col]; 113956cc18dSsnj#if OPT_ISO_COLORS 114956cc18dSsnj dst->color[col] = src->color[col]; 115956cc18dSsnj#endif 116956cc18dSsnj dst->charData[col] = src->charData[col]; 117980988aeSmrg#if OPT_DEC_RECTOPS 118980988aeSmrg dst->charSeen[col] = src->charSeen[col]; 119980988aeSmrg dst->charSets[col] = src->charSets[col]; 120980988aeSmrg#endif 121956cc18dSsnj#if OPT_WIDE_CHARS 122956cc18dSsnj for (comb = 0; comb < dst->combSize; ++comb) { 123956cc18dSsnj dst->combData[comb][col] = src->combData[comb][col]; 124956cc18dSsnj } 125956cc18dSsnj#endif 126956cc18dSsnj } 127956cc18dSsnj for (col = limit; col < dst->lineSize; ++col) { 128956cc18dSsnj dst->attribs[col] = 0; 129956cc18dSsnj#if OPT_ISO_COLORS 130d4fba8b9Smrg dst->color[col] = initCColor; 131956cc18dSsnj#endif 132956cc18dSsnj dst->charData[col] = 0; 133980988aeSmrg#if OPT_DEC_RECTOPS 134980988aeSmrg dst->charSeen[col] = 0; 135980988aeSmrg dst->charSets[col] = 0; 136980988aeSmrg#endif 137956cc18dSsnj#if OPT_WIDE_CHARS 138956cc18dSsnj for (comb = 0; comb < dst->combSize; ++comb) { 139956cc18dSsnj dst->combData[comb][col] = 0; 140956cc18dSsnj } 141956cc18dSsnj#endif 142956cc18dSsnj } 143956cc18dSsnj } 144956cc18dSsnj} 145956cc18dSsnj 146956cc18dSsnj#if OPT_WIDE_CHARS 147956cc18dSsnj#define initLineExtra(screen) \ 148d4fba8b9Smrg screen->lineExtra = ((size_t) (screen->max_combining) * sizeof(IChar *)); \ 149d4fba8b9Smrg screen->cellExtra = ((size_t) (screen->max_combining) * sizeof(IChar)) 150956cc18dSsnj#else 151956cc18dSsnj#define initLineExtra(screen) \ 152d4fba8b9Smrg screen->lineExtra = 0; \ 153d4fba8b9Smrg screen->cellExtra = 0 154956cc18dSsnj#endif 155956cc18dSsnj 156d4fba8b9Smrg/* 157d4fba8b9Smrg * CellData size depends on the "combiningChars" resource. 158d4fba8b9Smrg */ 159d4fba8b9Smrg#define CellDataSize(screen) (SizeOfCellData + screen->cellExtra) 160d4fba8b9Smrg 161d4fba8b9Smrg#define CellDataAddr(screen, data, cell) \ 162d4fba8b9Smrg ( (CellData *)(void *) ((char *)data + (cell * CellDataSize(screen))) ) 163d4fba8b9Smrg#define ConstCellDataAddr(screen, data, cell) \ 164d4fba8b9Smrg ( (const CellData *)(const void *) ( \ 165d4fba8b9Smrg (const char *)data + (cell * CellDataSize(screen))) ) 166d4fba8b9Smrg 167956cc18dSsnjvoid 168956cc18dSsnjinitLineData(XtermWidget xw) 169956cc18dSsnj{ 17020d2c4d2Smrg TScreen *screen = TScreenOf(xw); 171956cc18dSsnj 172956cc18dSsnj initLineExtra(screen); 173956cc18dSsnj 174d4fba8b9Smrg#if OPT_WIDE_CHARS 175d4fba8b9Smrg TRACE(("initLineData %lu (%d combining chars)\n", 176d4fba8b9Smrg (unsigned long) screen->lineExtra, screen->max_combining)); 177d4fba8b9Smrg#else 178d4fba8b9Smrg TRACE(("initLineData\n")); 179956cc18dSsnj#endif 180d4fba8b9Smrg 181d4fba8b9Smrg /* 182d4fba8b9Smrg * Per-line size/offsets. 183d4fba8b9Smrg */ 184d4fba8b9Smrg TRACE(("** sizeof(LineData) %lu\n", (unsigned long) sizeof(LineData))); 185d4fba8b9Smrg TRACE((" offset(lineSize) %lu\n", (unsigned long) offsetof(LineData, lineSize))); 186d4fba8b9Smrg TRACE((" offset(bufHead) %lu\n", (unsigned long) offsetof(LineData, bufHead))); 187956cc18dSsnj#if OPT_WIDE_CHARS 188d4fba8b9Smrg TRACE((" offset(combSize) %lu\n", (unsigned long) offsetof(LineData, combSize))); 189980988aeSmrg#endif 190980988aeSmrg#if OPT_DEC_RECTOPS 191980988aeSmrg TRACE((" offset(*charSeen) %lu\n", (unsigned long) offsetof(LineData, charSeen))); 192980988aeSmrg TRACE((" offset(*charSets) %lu\n", (unsigned long) offsetof(LineData, charSets))); 193956cc18dSsnj#endif 194d4fba8b9Smrg TRACE((" offset(*attribs) %lu\n", (unsigned long) offsetof(LineData, attribs))); 195956cc18dSsnj#if OPT_ISO_COLORS 196d4fba8b9Smrg TRACE((" offset(*color) %lu\n", (unsigned long) offsetof(LineData, color))); 197956cc18dSsnj#endif 198d4fba8b9Smrg TRACE((" offset(*charData) %lu\n", (unsigned long) offsetof(LineData, charData))); 199d4fba8b9Smrg TRACE((" offset(*combData) %lu\n", (unsigned long) offsetof(LineData, combData))); 200956cc18dSsnj 201d4fba8b9Smrg /* 202d4fba8b9Smrg * Per-cell size/offsets. 203d4fba8b9Smrg */ 204d4fba8b9Smrg TRACE(("** sizeof(CellData) %lu\n", (unsigned long) CellDataSize(screen))); 205d4fba8b9Smrg TRACE((" offset(attribs) %lu\n", (unsigned long) offsetof(CellData, attribs))); 206d4fba8b9Smrg#if OPT_WIDE_CHARS 207d4fba8b9Smrg TRACE((" offset(combSize) %lu\n", (unsigned long) offsetof(CellData, combSize))); 208d4fba8b9Smrg#endif 209980988aeSmrg#if OPT_DEC_RECTOPS 210980988aeSmrg TRACE((" offset(charSeen) %lu\n", (unsigned long) offsetof(CellData, charSeen))); 211980988aeSmrg TRACE((" offset(charSets) %lu\n", (unsigned long) offsetof(CellData, charSets))); 212980988aeSmrg#endif 213d4fba8b9Smrg#if OPT_ISO_COLORS 214d4fba8b9Smrg TRACE((" offset(color) %lu\n", (unsigned long) offsetof(CellData, color))); 215d4fba8b9Smrg#endif 216d4fba8b9Smrg TRACE((" offset(charData) %lu\n", (unsigned long) offsetof(CellData, charData))); 217d4fba8b9Smrg TRACE((" offset(combData) %lu\n", (unsigned long) offsetof(CellData, combData))); 218956cc18dSsnj 219d4fba8b9Smrg /* 220d4fba8b9Smrg * Data-type sizes. 221d4fba8b9Smrg */ 222d4fba8b9Smrg#if OPT_ISO_COLORS 223d4fba8b9Smrg TRACE(("** sizeof(CellColor) %lu\n", (unsigned long) sizeof(CellColor))); 224d4fba8b9Smrg#endif 225d4fba8b9Smrg TRACE(("** sizeof(IAttr) %lu\n", (unsigned long) sizeof(IAttr))); 226d4fba8b9Smrg TRACE(("** sizeof(IChar) %lu\n", (unsigned long) sizeof(IChar))); 227d4fba8b9Smrg TRACE(("** sizeof(RowData) %lu\n", (unsigned long) sizeof(RowData))); 228d4fba8b9Smrg} 229956cc18dSsnj 230956cc18dSsnjCellData * 231956cc18dSsnjnewCellData(XtermWidget xw, Cardinal count) 232956cc18dSsnj{ 233956cc18dSsnj CellData *result; 23420d2c4d2Smrg TScreen *screen = TScreenOf(xw); 235956cc18dSsnj 236956cc18dSsnj initLineExtra(screen); 237956cc18dSsnj result = (CellData *) calloc((size_t) count, (size_t) CellDataSize(screen)); 238956cc18dSsnj return result; 239956cc18dSsnj} 240956cc18dSsnj 241956cc18dSsnjvoid 24294644356SmrgsaveCellData(TScreen *screen, 24394644356Smrg CellData *data, 244956cc18dSsnj Cardinal cell, 24594644356Smrg CLineData *ld, 246d4fba8b9Smrg XTermRect *limits, 247956cc18dSsnj int column) 248956cc18dSsnj{ 249956cc18dSsnj CellData *item = CellDataAddr(screen, data, cell); 250956cc18dSsnj 251d4fba8b9Smrg (void) limits; 252956cc18dSsnj if (column < MaxCols(screen)) { 253956cc18dSsnj item->attribs = ld->attribs[column]; 254d4fba8b9Smrg if_OPT_ISO_COLORS(screen, { 255d4fba8b9Smrg item->color = ld->color[column]; 256d4fba8b9Smrg }); 257980988aeSmrg if_OPT_DEC_RECTOPS({ 258980988aeSmrg item->charSeen = ld->charSeen[column]; 259980988aeSmrg item->charData = ld->charData[column]; 260980988aeSmrg }); 261956cc18dSsnj if_OPT_WIDE_CHARS(screen, { 262956cc18dSsnj size_t off; 263d4fba8b9Smrg Bool blank = (((item->charData == HIDDEN_CHAR) 264d4fba8b9Smrg && (limits == NULL 265d4fba8b9Smrg || (column + 1) == limits->left)) 266d4fba8b9Smrg || (item->charData != HIDDEN_CHAR 267d4fba8b9Smrg && WideCells(item->charData) > 1 268d4fba8b9Smrg && (limits == NULL 269d4fba8b9Smrg || (column + 1) >= limits->right))); 270d4fba8b9Smrg if (blank) { 271980988aeSmrg if_OPT_DEC_RECTOPS(item->charSeen = ' '); 2728f44fb3bSmrg item->charData = (CharData) ' '; 273d4fba8b9Smrg } 274d4fba8b9Smrg item->combSize = blank ? 0 : ld->combSize; 275980988aeSmrg if_OPT_DEC_RECTOPS(item->charSets = (blank 276980988aeSmrg ? 0 277980988aeSmrg : ld->charSets[column])); 278d4fba8b9Smrg for_each_combData(off, item) { 279956cc18dSsnj item->combData[off] = ld->combData[off][column]; 280956cc18dSsnj } 281d4fba8b9Smrg }); 282d4fba8b9Smrg TRACE2(("SAVED::%s\n", visibleIChars(&(item->charData), 1))); 283956cc18dSsnj } 284956cc18dSsnj} 285956cc18dSsnj 286956cc18dSsnjvoid 28794644356SmrgrestoreCellData(TScreen *screen, 28894644356Smrg const CellData *data, 289956cc18dSsnj Cardinal cell, 29094644356Smrg LineData *ld, 291d4fba8b9Smrg XTermRect *limits, 292956cc18dSsnj int column) 293956cc18dSsnj{ 29494644356Smrg const CellData *item = ConstCellDataAddr(screen, data, cell); 295956cc18dSsnj 296d4fba8b9Smrg (void) limits; 297956cc18dSsnj if (column < MaxCols(screen)) { 298956cc18dSsnj ld->attribs[column] = item->attribs; 299d4fba8b9Smrg TRACE2(("BEFORE:%2d:%s\n", column + 1, visibleIChars(ld->charData, ld->lineSize))); 300d4fba8b9Smrg if_OPT_ISO_COLORS(screen, { 301d4fba8b9Smrg ld->color[column] = item->color; 302d4fba8b9Smrg }); 303980988aeSmrg if_OPT_DEC_RECTOPS({ 304980988aeSmrg ld->charSeen[column] = item->charSeen; 305980988aeSmrg ld->charSets[column] = item->charSets; 306980988aeSmrg }); 307956cc18dSsnj ld->charData[column] = item->charData; 308956cc18dSsnj if_OPT_WIDE_CHARS(screen, { 309956cc18dSsnj size_t off; 310956cc18dSsnj ld->combSize = item->combSize; 311980988aeSmrg if_OPT_DEC_RECTOPS(ld->charSets[column] = item->charSets); 312956cc18dSsnj for_each_combData(off, ld) { 313956cc18dSsnj ld->combData[off][column] = item->combData[off]; 314956cc18dSsnj } 315d4fba8b9Smrg }); 316d4fba8b9Smrg TRACE2(("AFTER::%2d:%s\n", column + 1, visibleIChars(ld->charData, ld->lineSize))); 317956cc18dSsnj } 318956cc18dSsnj} 319