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