linedata.c revision 94644356
194644356Smrg/* $XTermId: linedata.c,v 1.85 2014/11/13 01:17:59 tom Exp $ */
2956cc18dSsnj
33367019cSmrg/*
494644356Smrg * Copyright 2009-2013,2014 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>
34956cc18dSsnj
35956cc18dSsnj#include <assert.h>
36956cc18dSsnj
37956cc18dSsnj/*
38956cc18dSsnj * Given a row-number, find the corresponding data for the line in the VT100
39956cc18dSsnj * widget.  Row numbers can be positive or negative.
40956cc18dSsnj *
41956cc18dSsnj * If the data comes from the scrollback, defer that to getScrollback().
42956cc18dSsnj */
43956cc18dSsnjLineData *
4494644356SmrggetLineData(TScreen *screen, int row)
45956cc18dSsnj{
46956cc18dSsnj    LineData *result = 0;
47956cc18dSsnj    ScrnBuf buffer;
4820d2c4d2Smrg    int max_row = screen->max_row;
49956cc18dSsnj
50956cc18dSsnj    if (row >= 0) {
51956cc18dSsnj	buffer = screen->visbuf;
52956cc18dSsnj    } else {
53956cc18dSsnj#if OPT_FIFO_LINES
54956cc18dSsnj	buffer = 0;
55956cc18dSsnj	result = getScrollback(screen, row);
56956cc18dSsnj#else
57956cc18dSsnj	buffer = screen->saveBuf_index;
58956cc18dSsnj	row += screen->savelines;
5920d2c4d2Smrg	max_row += screen->savelines;
60956cc18dSsnj#endif
61956cc18dSsnj    }
6220d2c4d2Smrg    if (row >= 0 && row <= max_row) {
63956cc18dSsnj	result = (LineData *) scrnHeadAddr(screen, buffer, (unsigned) row);
64956cc18dSsnj	if (result != 0) {
65956cc18dSsnj#if 1				/* FIXME - these should be done in setupLineData, etc. */
66956cc18dSsnj	    result->lineSize = (Dimension) MaxCols(screen);
67956cc18dSsnj#if OPT_WIDE_CHARS
68956cc18dSsnj	    if (screen->wide_chars) {
69956cc18dSsnj		result->combSize = (Char) screen->max_combining;
70956cc18dSsnj	    } else {
71956cc18dSsnj		result->combSize = 0;
72956cc18dSsnj	    }
73956cc18dSsnj#endif
74956cc18dSsnj#endif /* FIXME */
75956cc18dSsnj	}
76956cc18dSsnj    }
77956cc18dSsnj
78956cc18dSsnj    return result;
79956cc18dSsnj}
80956cc18dSsnj
81956cc18dSsnj/*
82956cc18dSsnj * Copy line's data, e.g., from one screen buffer to another, given the preset
83956cc18dSsnj * pointers for the destination.
84956cc18dSsnj *
85956cc18dSsnj * TODO: optionally prune unused combining character data from the result.
86956cc18dSsnj */
87956cc18dSsnjvoid
8894644356SmrgcopyLineData(LineData *dst, CLineData *src)
89956cc18dSsnj{
90956cc18dSsnj    dst->bufHead = src->bufHead;
91956cc18dSsnj
92956cc18dSsnj#if OPT_WIDE_CHARS
93956cc18dSsnj    dst->combSize = src->combSize;
94956cc18dSsnj#endif
95956cc18dSsnj
96956cc18dSsnj    /*
97956cc18dSsnj     * Usually we're copying the same-sized line; a memcpy is faster than
98956cc18dSsnj     * several loops.
99956cc18dSsnj     */
100956cc18dSsnj    if (dst->lineSize == src->lineSize) {
101956cc18dSsnj	size_t size = (sizeof(dst->attribs[0])
102956cc18dSsnj#if OPT_ISO_COLORS
103956cc18dSsnj		       + sizeof(dst->color[0])
104956cc18dSsnj#endif
105956cc18dSsnj		       + sizeof(dst->charData[0])
106956cc18dSsnj#if OPT_WIDE_CHARS
107956cc18dSsnj		       + sizeof(dst->combData[0][0]) * dst->combSize
108956cc18dSsnj#endif
109956cc18dSsnj	);
110956cc18dSsnj
111956cc18dSsnj	memcpy(dst->attribs, src->attribs, size * dst->lineSize);
112956cc18dSsnj    } else {
113956cc18dSsnj	Dimension col;
114956cc18dSsnj	Dimension limit = ((dst->lineSize < src->lineSize)
115956cc18dSsnj			   ? dst->lineSize
116956cc18dSsnj			   : src->lineSize);
117956cc18dSsnj#if OPT_WIDE_CHARS
118956cc18dSsnj	Char comb;
119956cc18dSsnj#endif
120956cc18dSsnj
121956cc18dSsnj	for (col = 0; col < limit; ++col) {
122956cc18dSsnj	    dst->attribs[col] = src->attribs[col];
123956cc18dSsnj#if OPT_ISO_COLORS
124956cc18dSsnj	    dst->color[col] = src->color[col];
125956cc18dSsnj#endif
126956cc18dSsnj	    dst->charData[col] = src->charData[col];
127956cc18dSsnj#if OPT_WIDE_CHARS
128956cc18dSsnj	    for (comb = 0; comb < dst->combSize; ++comb) {
129956cc18dSsnj		dst->combData[comb][col] = src->combData[comb][col];
130956cc18dSsnj	    }
131956cc18dSsnj#endif
132956cc18dSsnj	}
133956cc18dSsnj	for (col = limit; col < dst->lineSize; ++col) {
134956cc18dSsnj	    dst->attribs[col] = 0;
135956cc18dSsnj#if OPT_ISO_COLORS
136956cc18dSsnj	    dst->color[col] = 0;
137956cc18dSsnj#endif
138956cc18dSsnj	    dst->charData[col] = 0;
139956cc18dSsnj#if OPT_WIDE_CHARS
140956cc18dSsnj	    for (comb = 0; comb < dst->combSize; ++comb) {
141956cc18dSsnj		dst->combData[comb][col] = 0;
142956cc18dSsnj	    }
143956cc18dSsnj#endif
144956cc18dSsnj	}
145956cc18dSsnj    }
146956cc18dSsnj}
147956cc18dSsnj
148956cc18dSsnj#if OPT_WIDE_CHARS
149956cc18dSsnj#define initLineExtra(screen) \
150956cc18dSsnj    screen->lineExtra = ((size_t) (screen->max_combining) * sizeof(IChar *))
151956cc18dSsnj#else
152956cc18dSsnj#define initLineExtra(screen) \
153956cc18dSsnj    screen->lineExtra = 0
154956cc18dSsnj#endif
155956cc18dSsnj
156956cc18dSsnjvoid
157956cc18dSsnjinitLineData(XtermWidget xw)
158956cc18dSsnj{
15920d2c4d2Smrg    TScreen *screen = TScreenOf(xw);
160956cc18dSsnj
161956cc18dSsnj    initLineExtra(screen);
162956cc18dSsnj
16320d2c4d2Smrg    TRACE(("initLineData %lu\n", (unsigned long) screen->lineExtra));
16420d2c4d2Smrg    TRACE(("...sizeof(LineData)  %lu\n", (unsigned long) sizeof(LineData)));
165956cc18dSsnj#if OPT_ISO_COLORS
16620d2c4d2Smrg    TRACE(("...sizeof(CellColor) %lu\n", (unsigned long) sizeof(CellColor)));
167956cc18dSsnj#endif
16820d2c4d2Smrg    TRACE(("...sizeof(RowData)   %lu\n", (unsigned long) sizeof(RowData)));
16920d2c4d2Smrg    TRACE(("...offset(lineSize)  %lu\n", (unsigned long) offsetof(LineData, lineSize)));
17020d2c4d2Smrg    TRACE(("...offset(bufHead)   %lu\n", (unsigned long) offsetof(LineData, bufHead)));
171956cc18dSsnj#if OPT_WIDE_CHARS
17220d2c4d2Smrg    TRACE(("...offset(combSize)  %lu\n", (unsigned long) offsetof(LineData, combSize)));
173956cc18dSsnj#endif
17420d2c4d2Smrg    TRACE(("...offset(attribs)   %lu\n", (unsigned long) offsetof(LineData, attribs)));
175956cc18dSsnj#if OPT_ISO_COLORS
17620d2c4d2Smrg    TRACE(("...offset(color)     %lu\n", (unsigned long) offsetof(LineData, color)));
177956cc18dSsnj#endif
17820d2c4d2Smrg    TRACE(("...offset(charData)  %lu\n", (unsigned long) offsetof(LineData, charData)));
17920d2c4d2Smrg    TRACE(("...offset(combData)  %lu\n", (unsigned long) offsetof(LineData, combData)));
180956cc18dSsnj}
181956cc18dSsnj
182956cc18dSsnj/*
183956cc18dSsnj * CellData size depends on the "combiningChars" resource.
184956cc18dSsnj * FIXME - revise this to reduce arithmetic...
185956cc18dSsnj */
186956cc18dSsnj#define CellDataSize(screen) (SizeOfCellData + screen->lineExtra)
187956cc18dSsnj
188956cc18dSsnj#define CellDataAddr(screen, data, cell) \
18994644356Smrg	( (CellData *)(void *) ((char *)data + (cell * CellDataSize(screen))) )
19094644356Smrg#define ConstCellDataAddr(screen, data, cell) \
19194644356Smrg	( (const CellData *)(const void *) ( \
19294644356Smrg	      (const char *)data + (cell * CellDataSize(screen))) )
193956cc18dSsnj
194956cc18dSsnjCellData *
195956cc18dSsnjnewCellData(XtermWidget xw, Cardinal count)
196956cc18dSsnj{
197956cc18dSsnj    CellData *result;
19820d2c4d2Smrg    TScreen *screen = TScreenOf(xw);
199956cc18dSsnj
200956cc18dSsnj    initLineExtra(screen);
201956cc18dSsnj    result = (CellData *) calloc((size_t) count, (size_t) CellDataSize(screen));
202956cc18dSsnj    return result;
203956cc18dSsnj}
204956cc18dSsnj
205956cc18dSsnjvoid
20694644356SmrgsaveCellData(TScreen *screen,
20794644356Smrg	     CellData *data,
208956cc18dSsnj	     Cardinal cell,
20994644356Smrg	     CLineData *ld,
210956cc18dSsnj	     int column)
211956cc18dSsnj{
212956cc18dSsnj    CellData *item = CellDataAddr(screen, data, cell);
213956cc18dSsnj
214956cc18dSsnj    if (column < MaxCols(screen)) {
215956cc18dSsnj	item->attribs = ld->attribs[column];
216956cc18dSsnj#if OPT_ISO_COLORS
217956cc18dSsnj	item->color = ld->color[column];
218956cc18dSsnj#endif
219956cc18dSsnj	item->charData = ld->charData[column];
220956cc18dSsnj	if_OPT_WIDE_CHARS(screen, {
221956cc18dSsnj	    size_t off;
222956cc18dSsnj	    item->combSize = ld->combSize;
223956cc18dSsnj	    for_each_combData(off, ld) {
224956cc18dSsnj		item->combData[off] = ld->combData[off][column];
225956cc18dSsnj	    }
226956cc18dSsnj	})
227956cc18dSsnj    }
228956cc18dSsnj}
229956cc18dSsnj
230956cc18dSsnjvoid
23194644356SmrgrestoreCellData(TScreen *screen,
23294644356Smrg		const CellData *data,
233956cc18dSsnj		Cardinal cell,
23494644356Smrg		LineData *ld,
235956cc18dSsnj		int column)
236956cc18dSsnj{
23794644356Smrg    const CellData *item = ConstCellDataAddr(screen, data, cell);
238956cc18dSsnj
239956cc18dSsnj    if (column < MaxCols(screen)) {
240956cc18dSsnj	ld->attribs[column] = item->attribs;
241956cc18dSsnj#if OPT_ISO_COLORS
242956cc18dSsnj	ld->color[column] = item->color;
243956cc18dSsnj#endif
244956cc18dSsnj	ld->charData[column] = item->charData;
245956cc18dSsnj	if_OPT_WIDE_CHARS(screen, {
246956cc18dSsnj	    size_t off;
247956cc18dSsnj	    ld->combSize = item->combSize;
248956cc18dSsnj	    for_each_combData(off, ld) {
249956cc18dSsnj		ld->combData[off][column] = item->combData[off];
250956cc18dSsnj	    }
251956cc18dSsnj	})
252956cc18dSsnj    }
253956cc18dSsnj}
254