linedata.c revision 3367019c
13367019cSmrg/* $XTermId: linedata.c,v 1.82 2013/02/08 00:11:16 tom Exp $ */
2956cc18dSsnj
33367019cSmrg/*
43367019cSmrg * Copyright 2009-2012,2013 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 *
44956cc18dSsnjgetLineData(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
88956cc18dSsnjcopyLineData(LineData * dst, LineData * 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) \
189c219fbebSmrg	(CellData *)(void *) ((char *)data + (cell * CellDataSize(screen)))
190956cc18dSsnj
191956cc18dSsnjCellData *
192956cc18dSsnjnewCellData(XtermWidget xw, Cardinal count)
193956cc18dSsnj{
194956cc18dSsnj    CellData *result;
19520d2c4d2Smrg    TScreen *screen = TScreenOf(xw);
196956cc18dSsnj
197956cc18dSsnj    initLineExtra(screen);
198956cc18dSsnj    result = (CellData *) calloc((size_t) count, (size_t) CellDataSize(screen));
199956cc18dSsnj    return result;
200956cc18dSsnj}
201956cc18dSsnj
202956cc18dSsnjvoid
203956cc18dSsnjsaveCellData(TScreen * screen,
204956cc18dSsnj	     CellData * data,
205956cc18dSsnj	     Cardinal cell,
206956cc18dSsnj	     LineData * ld,
207956cc18dSsnj	     int column)
208956cc18dSsnj{
209956cc18dSsnj    CellData *item = CellDataAddr(screen, data, cell);
210956cc18dSsnj
211956cc18dSsnj    if (column < MaxCols(screen)) {
212956cc18dSsnj	item->attribs = ld->attribs[column];
213956cc18dSsnj#if OPT_ISO_COLORS
214956cc18dSsnj	item->color = ld->color[column];
215956cc18dSsnj#endif
216956cc18dSsnj	item->charData = ld->charData[column];
217956cc18dSsnj	if_OPT_WIDE_CHARS(screen, {
218956cc18dSsnj	    size_t off;
219956cc18dSsnj	    item->combSize = ld->combSize;
220956cc18dSsnj	    for_each_combData(off, ld) {
221956cc18dSsnj		item->combData[off] = ld->combData[off][column];
222956cc18dSsnj	    }
223956cc18dSsnj	})
224956cc18dSsnj    }
225956cc18dSsnj}
226956cc18dSsnj
227956cc18dSsnjvoid
228956cc18dSsnjrestoreCellData(TScreen * screen,
229956cc18dSsnj		CellData * data,
230956cc18dSsnj		Cardinal cell,
231956cc18dSsnj		LineData * ld,
232956cc18dSsnj		int column)
233956cc18dSsnj{
234956cc18dSsnj    CellData *item = CellDataAddr(screen, data, cell);
235956cc18dSsnj
236956cc18dSsnj    if (column < MaxCols(screen)) {
237956cc18dSsnj	ld->attribs[column] = item->attribs;
238956cc18dSsnj#if OPT_ISO_COLORS
239956cc18dSsnj	ld->color[column] = item->color;
240956cc18dSsnj#endif
241956cc18dSsnj	ld->charData[column] = item->charData;
242956cc18dSsnj	if_OPT_WIDE_CHARS(screen, {
243956cc18dSsnj	    size_t off;
244956cc18dSsnj	    ld->combSize = item->combSize;
245956cc18dSsnj	    for_each_combData(off, ld) {
246956cc18dSsnj		ld->combData[off][column] = item->combData[off];
247956cc18dSsnj	    }
248956cc18dSsnj	})
249956cc18dSsnj    }
250956cc18dSsnj}
251