testxmc.c revision 956cc18d
1956cc18dSsnj/* $XTermId: testxmc.c,v 1.45 2009/09/10 09:05:20 tom Exp $ */
2d522f475Smrg
3d522f475Smrg/************************************************************
4d522f475Smrg
54e40088cSchristosCopyright 1997-2006,2009 by Thomas E. Dickey
6d522f475Smrg
7d522f475Smrg                        All Rights Reserved
8d522f475Smrg
9d522f475SmrgPermission is hereby granted, free of charge, to any person obtaining a
10d522f475Smrgcopy of this software and associated documentation files (the
11d522f475Smrg"Software"), to deal in the Software without restriction, including
12d522f475Smrgwithout limitation the rights to use, copy, modify, merge, publish,
13d522f475Smrgdistribute, sublicense, and/or sell copies of the Software, and to
14d522f475Smrgpermit persons to whom the Software is furnished to do so, subject to
15d522f475Smrgthe following conditions:
16d522f475Smrg
17d522f475SmrgThe above copyright notice and this permission notice shall be included
18d522f475Smrgin all copies or substantial portions of the Software.
19d522f475Smrg
20d522f475SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21d522f475SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22d522f475SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23d522f475SmrgIN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
24d522f475SmrgCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25d522f475SmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26d522f475SmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27d522f475Smrg
28d522f475SmrgExcept as contained in this notice, the name(s) of the above copyright
29d522f475Smrgholders shall not be used in advertising or otherwise to promote the
30d522f475Smrgsale, use or other dealings in this Software without prior written
31d522f475Smrgauthorization.
32d522f475Smrg
33d522f475Smrg********************************************************/
34d522f475Smrg
35d522f475Smrg/*
36d522f475Smrg * This module provides test support for curses applications that must work
37d522f475Smrg * with terminals that have the xmc (magic cookie) glitch.  The xmc_glitch
38d522f475Smrg * resource denotes the number of spaces that are emitted when switching to or
39d522f475Smrg * from standout (reverse) mode.  Some terminals implement this by storing the
40d522f475Smrg * attribute controls in the character cell that is skipped.  So if the cell is
41d522f475Smrg * overwritten by text, then the attribute change in the cell is cancelled,
42d522f475Smrg * causing attributes to the left of the change to propagate.
43d522f475Smrg *
44d522f475Smrg * We implement the glitch by writing a character that won't be mistaken for
45d522f475Smrg * other normal characters (and mapping normal writes to that character to a
46d522f475Smrg * different one).
47d522f475Smrg *
48d522f475Smrg * Since xmc isn't normally part of xterm, we document it here rather than in
49d522f475Smrg * the man-page.  This module is driven by resources rather than by the
50d522f475Smrg * termcap/terminfo description to make it a little more flexible for testing
51d522f475Smrg * purposes.
52d522f475Smrg *
53d522f475Smrg * Resources:
54d522f475Smrg *
55d522f475Smrg * xmcGlitch (class XmcGlitch)
56d522f475Smrg *	When true, enables this extension.  The default is `0', which disables
57d522f475Smrg *	the module.  (termcap sg, terminfo xmc).
58d522f475Smrg *
59d522f475Smrg * xmcAttributes (class XmcAttributes)
60d522f475Smrg *	The attributes for which we'll generate a glitch, as a bitmask.
61d522f475Smrg *
62d522f475Smrg *		INVERSE		1
63d522f475Smrg *		UNDERLINE	2
64d522f475Smrg *		BOLD		4
65d522f475Smrg *		BLINK		8
66d522f475Smrg *
67d522f475Smrg *	The default is `1' (INVERSE).  Some terminals emit glitches for
68d522f475Smrg *	underline.  Just for completeness, we recognize all of the video
69d522f475Smrg *	attributes.
70d522f475Smrg *
71d522f475Smrg * xmcInline (class XmcInline)
72d522f475Smrg *	When true, limits the extent of an SGR change to the current line.
73d522f475Smrg *	The default is `false'.  (No termcap or terminfo equivalent, though
74d522f475Smrg *	there are comments in some entries relating to this issue).
75d522f475Smrg *
76d522f475Smrg * xmcMoveSGR (class XmcMoveSGR)
77d522f475Smrg *	When false, a cursor movement will leave a glitch when SGR's are
78d522f475Smrg *	active.  The default is `true'.  (termcap ms, terminfo msgr).
79d522f475Smrg *
80d522f475Smrg * TODO:
81d522f475Smrg *	When xmc is active, the terminfo max_attributes (ma) capability is
82d522f475Smrg *	assumed to be 1.
83d522f475Smrg *
84d522f475Smrg *	The xmcAttributes resource should also apply to alternate character
85d522f475Smrg *	sets and to color.
86d522f475Smrg */
87d522f475Smrg
88d522f475Smrg#include <xterm.h>
89d522f475Smrg#include <data.h>
90d522f475Smrg
914e40088cSchristos#define MARK_ON(a)  (my_attrs & a) != 0 && (xw->flags & (whichone = CharOf(a))) == 0
924e40088cSchristos#define MARK_OFF(a) (my_attrs & a) != 0 && (xw->flags & (whichone = CharOf(a))) != 0
93d522f475Smrg
94d522f475Smrgvoid
95d522f475SmrgMark_XMC(XtermWidget xw, int param)
96d522f475Smrg{
97d522f475Smrg    static IChar *glitch;
98d522f475Smrg
99d522f475Smrg    TScreen *screen = &(xw->screen);
100d522f475Smrg    Bool found = False;
1014e40088cSchristos    Char my_attrs = CharOf(screen->xmc_attributes & XMC_FLAGS);
102d522f475Smrg    Char whichone = 0;
103d522f475Smrg
104d522f475Smrg    if (glitch == 0) {
105d522f475Smrg	unsigned len = screen->xmc_glitch;
106d522f475Smrg	glitch = TypeMallocN(IChar, len);
107d522f475Smrg	while (len--)
108d522f475Smrg	    glitch[len] = XMC_GLITCH;
109d522f475Smrg    }
110d522f475Smrg    switch (param) {
111d522f475Smrg    case -1:			/* DEFAULT */
112d522f475Smrg    case 0:			/* FALLTHRU */
113d522f475Smrg	found = MARK_OFF((xw->flags & XMC_FLAGS));
114d522f475Smrg	break;
115d522f475Smrg    case 1:
116d522f475Smrg	found = MARK_ON(BOLD);
117d522f475Smrg	break;
118d522f475Smrg    case 4:
119d522f475Smrg	found = MARK_ON(UNDERLINE);
120d522f475Smrg	break;
121d522f475Smrg    case 5:
122d522f475Smrg	found = MARK_ON(BLINK);
123d522f475Smrg	break;
124d522f475Smrg    case 7:
125d522f475Smrg	found = MARK_ON(INVERSE);
126d522f475Smrg	break;
127d522f475Smrg    case 22:
128d522f475Smrg	found = MARK_OFF(BOLD);
129d522f475Smrg	break;
130d522f475Smrg    case 24:
131d522f475Smrg	found = MARK_OFF(UNDERLINE);
132d522f475Smrg	break;
133d522f475Smrg    case 25:
134d522f475Smrg	found = MARK_OFF(BLINK);
135d522f475Smrg	break;
136d522f475Smrg    case 27:
137d522f475Smrg	found = MARK_OFF(INVERSE);
138d522f475Smrg	break;
139d522f475Smrg    }
140d522f475Smrg
141d522f475Smrg    /*
142d522f475Smrg     * Write a glitch with the attributes temporarily set to the new(er)
143d522f475Smrg     * ones.
144d522f475Smrg     */
145d522f475Smrg    if (found) {
146d522f475Smrg	unsigned save = xw->flags;
147d522f475Smrg	xw->flags ^= whichone;
148d522f475Smrg	TRACE(("XMC Writing glitch (%d/%d) after SGR %d\n", my_attrs,
149d522f475Smrg	       whichone, param));
150d522f475Smrg	dotext(xw, '?', glitch, screen->xmc_glitch);
151d522f475Smrg	xw->flags = save;
152d522f475Smrg    }
153d522f475Smrg}
154d522f475Smrg
155d522f475Smrg/*
156d522f475Smrg * Force a glitch on cursor movement when we're in standout mode and not at the
157d522f475Smrg * end of a line.
158d522f475Smrg */
159d522f475Smrgvoid
160d522f475SmrgJump_XMC(XtermWidget xw)
161d522f475Smrg{
162d522f475Smrg    TScreen *screen = &(xw->screen);
163d522f475Smrg    if (!screen->move_sgr_ok
164956cc18dSsnj	&& screen->cur_col <= LineMaxCol(screen,
165956cc18dSsnj					 getLineData(screen, screen->cur_row))) {
166d522f475Smrg	Mark_XMC(xw, -1);
167d522f475Smrg    }
168d522f475Smrg}
169d522f475Smrg
170d522f475Smrg/*
171d522f475Smrg * After writing text to the screen, resolve mismatch between the current
172d522f475Smrg * location and any attributes that would have been set by preceding locations.
173d522f475Smrg */
174d522f475Smrgvoid
175d522f475SmrgResolve_XMC(XtermWidget xw)
176d522f475Smrg{
177d522f475Smrg    TScreen *screen = &(xw->screen);
178956cc18dSsnj    LineData *ld;
179d522f475Smrg    Bool changed = False;
180d522f475Smrg    Char start;
1814e40088cSchristos    Char my_attrs = CharOf(screen->xmc_attributes & XMC_FLAGS);
182d522f475Smrg    int row = screen->cur_row;
183d522f475Smrg    int col = screen->cur_col;
184d522f475Smrg
185d522f475Smrg    /* Find the preceding cell.
186d522f475Smrg     */
187956cc18dSsnj    ld = getLineData(screen, row);
188956cc18dSsnj    if (ld->charData[col] != XMC_GLITCH) {
189d522f475Smrg	if (col != 0) {
190d522f475Smrg	    col--;
191d522f475Smrg	} else if (!screen->xmc_inline && row != 0) {
192956cc18dSsnj	    ld = getLineData(screen, --row);
193956cc18dSsnj	    col = LineMaxCol(screen, ld);
194d522f475Smrg	}
195d522f475Smrg    }
196956cc18dSsnj    start = (ld->attribs[col] & my_attrs);
197d522f475Smrg
198d522f475Smrg    /* Now propagate the starting state until we reach a cell which holds
199d522f475Smrg     * a glitch.
200d522f475Smrg     */
201d522f475Smrg    for (;;) {
202956cc18dSsnj	if (col < LineMaxCol(screen, ld)) {
203d522f475Smrg	    col++;
204d522f475Smrg	} else if (!screen->xmc_inline && row < screen->max_row) {
205d522f475Smrg	    col = 0;
206956cc18dSsnj	    ld = getLineData(screen, ++row);
207d522f475Smrg	} else
208d522f475Smrg	    break;
209956cc18dSsnj	if (ld->charData[col] == XMC_GLITCH)
210d522f475Smrg	    break;
211956cc18dSsnj	if ((ld->attribs[col] & my_attrs) != start) {
212956cc18dSsnj	    ld->attribs[col] =
213956cc18dSsnj		CharOf(start | (ld->attribs[col] & ~my_attrs));
214d522f475Smrg	    changed = True;
215d522f475Smrg	}
216d522f475Smrg    }
217d522f475Smrg
218d522f475Smrg    TRACE(("XMC %s (%s:%d/%d) from %d,%d to %d,%d\n",
219d522f475Smrg	   changed ? "Ripple" : "Nochange",
220d522f475Smrg	   BtoS(xw->flags & my_attrs),
221d522f475Smrg	   my_attrs, start,
222d522f475Smrg	   screen->cur_row, screen->cur_col,
223d522f475Smrg	   row, col));
224d522f475Smrg
225d522f475Smrg    if (changed) {
226d522f475Smrg	ScrnUpdate(xw, screen->cur_row, 0, row + 1 - screen->cur_row,
227d522f475Smrg		   MaxCols(screen), True);
228d522f475Smrg    }
229d522f475Smrg}
230