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