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