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