doublechr.c revision 894e0ac8
1/* $XTermId: doublechr.c,v 1.85 2014/05/08 01:08:39 tom Exp $ */ 2 3/* 4 * Copyright 1997-2013,2014 by Thomas E. Dickey 5 * 6 * All Rights Reserved 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sublicense, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * Except as contained in this notice, the name(s) of the above copyright 28 * holders shall not be used in advertising or otherwise to promote the 29 * sale, use or other dealings in this Software without prior written 30 * authorization. 31 */ 32 33#include <xterm.h> 34#include <data.h> 35#include <fontutils.h> 36 37#include <assert.h> 38 39#define WhichCgsId(flag) (((flag) & BOLD) ? gcCBold : gcCNorm) 40 41/* 42 * The first column is all that matters for double-size characters (since the 43 * controls apply to a whole line). However, it's easier to maintain the 44 * information for special fonts by writing to all cells. 45 */ 46#if OPT_DEC_CHRSET 47 48static void 49repaint_line(XtermWidget xw, unsigned newChrSet) 50{ 51 TScreen *screen = TScreenOf(xw); 52 LineData *ld; 53 int curcol = screen->cur_col; 54 int currow = screen->cur_row; 55 int width = MaxCols(screen); 56 unsigned len = (unsigned) width; 57 58 assert(width > 0); 59 60 /* 61 * Ignore repetition. 62 */ 63 if (!IsLeftRightMode(xw) 64 && (ld = getLineData(screen, currow)) != 0) { 65 unsigned oldChrSet = GetLineDblCS(ld); 66 67 if (oldChrSet != newChrSet) { 68 TRACE(("repaint_line(%2d,%2d) (%s -> %s)\n", currow, screen->cur_col, 69 visibleDblChrset(oldChrSet), 70 visibleDblChrset(newChrSet))); 71 HideCursor(); 72 73 /* If switching from single-width, keep the cursor in the visible part 74 * of the line. 75 */ 76 if (CSET_DOUBLE(newChrSet)) { 77 width /= 2; 78 if (curcol > width) 79 curcol = width; 80 } 81 82 /* 83 * ScrnRefresh won't paint blanks for us if we're switching between a 84 * single-size and double-size font. So we paint our own. 85 */ 86 ClearCurBackground(xw, 87 currow, 88 0, 89 1, 90 len, 91 (unsigned) LineFontWidth(screen, ld)); 92 93 SetLineDblCS(ld, newChrSet); 94 95 set_cur_col(screen, 0); 96 ScrnUpdate(xw, currow, 0, 1, (int) len, True); 97 set_cur_col(screen, curcol); 98 } 99 } 100} 101#endif 102 103/* 104 * Set the line to double-height characters. The 'top' flag denotes whether 105 * we'll be using it for the top (true) or bottom (false) of the line. 106 */ 107void 108xterm_DECDHL(XtermWidget xw GCC_UNUSED, Bool top) 109{ 110#if OPT_DEC_CHRSET 111 repaint_line(xw, (unsigned) (top ? CSET_DHL_TOP : CSET_DHL_BOT)); 112#else 113 (void) top; 114#endif 115} 116 117/* 118 * Set the line to single-width characters (the normal state). 119 */ 120void 121xterm_DECSWL(XtermWidget xw GCC_UNUSED) 122{ 123#if OPT_DEC_CHRSET 124 repaint_line(xw, CSET_SWL); 125#endif 126} 127 128/* 129 * Set the line to double-width characters 130 */ 131void 132xterm_DECDWL(XtermWidget xw GCC_UNUSED) 133{ 134#if OPT_DEC_CHRSET 135 repaint_line(xw, CSET_DWL); 136#endif 137} 138 139/* 140 * Reset all lines on the screen to single-width/single-height. 141 */ 142void 143xterm_ResetDouble(XtermWidget xw) 144{ 145#if OPT_DEC_CHRSET 146 TScreen *screen = TScreenOf(xw); 147 Boolean changed = False; 148 LineData *ld; 149 unsigned code; 150 int row; 151 152 for (row = 0; row < screen->max_row; ++row) { 153 if ((ld = getLineData(screen, ROW2INX(screen, row))) != 0) { 154 code = GetLineDblCS(ld); 155 if (code != CSET_SWL) { 156 SetLineDblCS(ld, CSET_SWL); 157 changed = True; 158 } 159 } 160 } 161 if (changed) { 162 xtermRepaint(xw); 163 } 164#else 165 (void) xw; 166#endif 167} 168 169#if OPT_DEC_CHRSET 170static void 171discard_font(XtermWidget xw, int n) 172{ 173 TScreen *screen = TScreenOf(xw); 174 XTermFonts *data = &(screen->double_fonts[n]); 175 176 TRACE(("discard_font chrset=%d %s\n", data->chrset, 177 (data->fn != 0) ? data->fn : "<no-name>")); 178 179 data->chrset = 0; 180 data->flags = 0; 181 if (data->fn != 0) { 182 free(data->fn); 183 data->fn = 0; 184 } 185 (void) xtermCloseFont(xw, data); 186 187 screen->fonts_used -= 1; 188 while (n < screen->fonts_used) { 189 screen->double_fonts[n] = screen->double_fonts[n + 1]; 190 ++n; 191 } 192} 193 194/* push back existing fonts and create a new entry */ 195static XTermFonts * 196pushback_font(XtermWidget xw, XTermFonts * source) 197{ 198 TScreen *screen = TScreenOf(xw); 199 XTermFonts *data = screen->double_fonts; 200 int n; 201 202 if (screen->fonts_used >= screen->cache_doublesize) { 203 TRACE(("pushback_font: discard oldest\n")); 204 discard_font(xw, screen->fonts_used - 1); 205 } else { 206 screen->fonts_used += 1; 207 } 208 209 for (n = screen->fonts_used; n > 0; n--) 210 data[n] = data[n - 1]; 211 data[0] = *source; 212 213 TRACE(("pushback_font -> (NEW:%d)\n", screen->fonts_used)); 214 215 return data; 216} 217 218int 219xterm_Double_index(XtermWidget xw, unsigned chrset, unsigned flags) 220{ 221 int n; 222 int result = -1; 223 TScreen *screen = TScreenOf(xw); 224 XTermFonts *data = screen->double_fonts; 225 226 flags &= BOLD; 227 TRACE(("xterm_Double_index chrset=%#x, flags=%#x\n", chrset, flags)); 228 229 for (n = 0; n < screen->fonts_used; n++) { 230 if (data[n].chrset == chrset 231 && data[n].flags == flags) { 232 if (n != 0) { 233 XTermFonts save; 234 TRACE(("...xterm_Double_index -> %d (OLD:%d)\n", n, screen->fonts_used)); 235 save = data[n]; 236 while (n > 0) { 237 data[n] = data[n - 1]; 238 n--; 239 } 240 data[n] = save; 241 } 242 result = n; 243 break; 244 } 245 } 246 247 return result; 248} 249 250/* 251 * Lookup/cache a GC for the double-size character display. We save up to 252 * NUM_CHRSET values. 253 */ 254GC 255xterm_DoubleGC(XtermWidget xw, 256 unsigned chrset, 257 unsigned attr_flags, 258 unsigned draw_flags, 259 GC old_gc, 260 int *inxp) 261{ 262 TScreen *screen = TScreenOf(xw); 263 VTwin *cgsWin = WhichVWin(screen); 264 int n; 265 char *name; 266 XTermFonts *data = 0; 267 GC result = 0; 268 269 if ((name = xtermSpecialFont(screen, attr_flags, draw_flags, chrset)) != 0) { 270 CgsEnum cgsId = WhichCgsId(attr_flags); 271 Boolean found = False; 272 273 if ((n = xterm_Double_index(xw, chrset, attr_flags)) >= 0) { 274 data = &(screen->double_fonts[n]); 275 if (data->fn != 0) { 276 if (!strcmp(data->fn, name) 277 && data->fs != 0) { 278 found = True; 279 free(name); 280 } else { 281 discard_font(xw, n); 282 } 283 } 284 } 285 286 if (!found) { 287 XTermFonts temp; 288 289 TRACE(("xterm_DoubleGC %s %d: %s\n", 290 attr_flags & BOLD ? "BOLD" : "NORM", n, name)); 291 292 memset(&temp, 0, sizeof(temp)); 293 temp.fn = name; 294 temp.chrset = chrset; 295 temp.flags = (attr_flags & BOLD); 296 297 if (!xtermOpenFont(xw, name, &temp, fwAlways, False)) { 298 /* Retry with * in resolutions */ 299 char *nname = xtermSpecialFont(screen, 300 attr_flags, 301 draw_flags | NORESOLUTION, 302 chrset); 303 304 if (nname != 0) { 305 found = (Boolean) xtermOpenFont(xw, nname, &temp, 306 fwAlways, False); 307 free(nname); 308 } 309 } else { 310 found = True; 311 } 312 free(name); 313 314 if (found) { 315 n = 0; 316 data = pushback_font(xw, &temp); 317 } 318 319 TRACE(("-> %s\n", found ? "OK" : "FAIL")); 320 } 321 322 if (found) { 323 setCgsCSet(xw, cgsWin, cgsId, chrset); 324 setCgsFont(xw, cgsWin, cgsId, data); 325 setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, old_gc)); 326 setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, old_gc)); 327 result = getCgsGC(xw, cgsWin, cgsId); 328 *inxp = n; 329 } else if (attr_flags & BOLD) { 330 UIntClr(attr_flags, BOLD); 331 result = xterm_DoubleGC(xw, chrset, 332 attr_flags, 333 draw_flags, 334 old_gc, inxp); 335 } 336 } 337 338 return result; 339} 340#endif 341