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