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