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