linedata.c revision 3367019c
1/* $XTermId: linedata.c,v 1.82 2013/02/08 00:11:16 tom Exp $ */
2
3/*
4 * Copyright 2009-2012,2013 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
35#include <assert.h>
36
37/*
38 * Given a row-number, find the corresponding data for the line in the VT100
39 * widget.  Row numbers can be positive or negative.
40 *
41 * If the data comes from the scrollback, defer that to getScrollback().
42 */
43LineData *
44getLineData(TScreen * screen, int row)
45{
46    LineData *result = 0;
47    ScrnBuf buffer;
48    int max_row = screen->max_row;
49
50    if (row >= 0) {
51	buffer = screen->visbuf;
52    } else {
53#if OPT_FIFO_LINES
54	buffer = 0;
55	result = getScrollback(screen, row);
56#else
57	buffer = screen->saveBuf_index;
58	row += screen->savelines;
59	max_row += screen->savelines;
60#endif
61    }
62    if (row >= 0 && row <= max_row) {
63	result = (LineData *) scrnHeadAddr(screen, buffer, (unsigned) row);
64	if (result != 0) {
65#if 1				/* FIXME - these should be done in setupLineData, etc. */
66	    result->lineSize = (Dimension) MaxCols(screen);
67#if OPT_WIDE_CHARS
68	    if (screen->wide_chars) {
69		result->combSize = (Char) screen->max_combining;
70	    } else {
71		result->combSize = 0;
72	    }
73#endif
74#endif /* FIXME */
75	}
76    }
77
78    return result;
79}
80
81/*
82 * Copy line's data, e.g., from one screen buffer to another, given the preset
83 * pointers for the destination.
84 *
85 * TODO: optionally prune unused combining character data from the result.
86 */
87void
88copyLineData(LineData * dst, LineData * src)
89{
90    dst->bufHead = src->bufHead;
91
92#if OPT_WIDE_CHARS
93    dst->combSize = src->combSize;
94#endif
95
96    /*
97     * Usually we're copying the same-sized line; a memcpy is faster than
98     * several loops.
99     */
100    if (dst->lineSize == src->lineSize) {
101	size_t size = (sizeof(dst->attribs[0])
102#if OPT_ISO_COLORS
103		       + sizeof(dst->color[0])
104#endif
105		       + sizeof(dst->charData[0])
106#if OPT_WIDE_CHARS
107		       + sizeof(dst->combData[0][0]) * dst->combSize
108#endif
109	);
110
111	memcpy(dst->attribs, src->attribs, size * dst->lineSize);
112    } else {
113	Dimension col;
114	Dimension limit = ((dst->lineSize < src->lineSize)
115			   ? dst->lineSize
116			   : src->lineSize);
117#if OPT_WIDE_CHARS
118	Char comb;
119#endif
120
121	for (col = 0; col < limit; ++col) {
122	    dst->attribs[col] = src->attribs[col];
123#if OPT_ISO_COLORS
124	    dst->color[col] = src->color[col];
125#endif
126	    dst->charData[col] = src->charData[col];
127#if OPT_WIDE_CHARS
128	    for (comb = 0; comb < dst->combSize; ++comb) {
129		dst->combData[comb][col] = src->combData[comb][col];
130	    }
131#endif
132	}
133	for (col = limit; col < dst->lineSize; ++col) {
134	    dst->attribs[col] = 0;
135#if OPT_ISO_COLORS
136	    dst->color[col] = 0;
137#endif
138	    dst->charData[col] = 0;
139#if OPT_WIDE_CHARS
140	    for (comb = 0; comb < dst->combSize; ++comb) {
141		dst->combData[comb][col] = 0;
142	    }
143#endif
144	}
145    }
146}
147
148#if OPT_WIDE_CHARS
149#define initLineExtra(screen) \
150    screen->lineExtra = ((size_t) (screen->max_combining) * sizeof(IChar *))
151#else
152#define initLineExtra(screen) \
153    screen->lineExtra = 0
154#endif
155
156void
157initLineData(XtermWidget xw)
158{
159    TScreen *screen = TScreenOf(xw);
160
161    initLineExtra(screen);
162
163    TRACE(("initLineData %lu\n", (unsigned long) screen->lineExtra));
164    TRACE(("...sizeof(LineData)  %lu\n", (unsigned long) sizeof(LineData)));
165#if OPT_ISO_COLORS
166    TRACE(("...sizeof(CellColor) %lu\n", (unsigned long) sizeof(CellColor)));
167#endif
168    TRACE(("...sizeof(RowData)   %lu\n", (unsigned long) sizeof(RowData)));
169    TRACE(("...offset(lineSize)  %lu\n", (unsigned long) offsetof(LineData, lineSize)));
170    TRACE(("...offset(bufHead)   %lu\n", (unsigned long) offsetof(LineData, bufHead)));
171#if OPT_WIDE_CHARS
172    TRACE(("...offset(combSize)  %lu\n", (unsigned long) offsetof(LineData, combSize)));
173#endif
174    TRACE(("...offset(attribs)   %lu\n", (unsigned long) offsetof(LineData, attribs)));
175#if OPT_ISO_COLORS
176    TRACE(("...offset(color)     %lu\n", (unsigned long) offsetof(LineData, color)));
177#endif
178    TRACE(("...offset(charData)  %lu\n", (unsigned long) offsetof(LineData, charData)));
179    TRACE(("...offset(combData)  %lu\n", (unsigned long) offsetof(LineData, combData)));
180}
181
182/*
183 * CellData size depends on the "combiningChars" resource.
184 * FIXME - revise this to reduce arithmetic...
185 */
186#define CellDataSize(screen) (SizeOfCellData + screen->lineExtra)
187
188#define CellDataAddr(screen, data, cell) \
189	(CellData *)(void *) ((char *)data + (cell * CellDataSize(screen)))
190
191CellData *
192newCellData(XtermWidget xw, Cardinal count)
193{
194    CellData *result;
195    TScreen *screen = TScreenOf(xw);
196
197    initLineExtra(screen);
198    result = (CellData *) calloc((size_t) count, (size_t) CellDataSize(screen));
199    return result;
200}
201
202void
203saveCellData(TScreen * screen,
204	     CellData * data,
205	     Cardinal cell,
206	     LineData * ld,
207	     int column)
208{
209    CellData *item = CellDataAddr(screen, data, cell);
210
211    if (column < MaxCols(screen)) {
212	item->attribs = ld->attribs[column];
213#if OPT_ISO_COLORS
214	item->color = ld->color[column];
215#endif
216	item->charData = ld->charData[column];
217	if_OPT_WIDE_CHARS(screen, {
218	    size_t off;
219	    item->combSize = ld->combSize;
220	    for_each_combData(off, ld) {
221		item->combData[off] = ld->combData[off][column];
222	    }
223	})
224    }
225}
226
227void
228restoreCellData(TScreen * screen,
229		CellData * data,
230		Cardinal cell,
231		LineData * ld,
232		int column)
233{
234    CellData *item = CellDataAddr(screen, data, cell);
235
236    if (column < MaxCols(screen)) {
237	ld->attribs[column] = item->attribs;
238#if OPT_ISO_COLORS
239	ld->color[column] = item->color;
240#endif
241	ld->charData[column] = item->charData;
242	if_OPT_WIDE_CHARS(screen, {
243	    size_t off;
244	    ld->combSize = item->combSize;
245	    for_each_combData(off, ld) {
246		ld->combData[off][column] = item->combData[off];
247	    }
248	})
249    }
250}
251