doublechr.c revision d522f475
1/* $XTermId: doublechr.c,v 1.60 2008/01/27 15:07:16 tom Exp $ */ 2 3/************************************************************ 4 5Copyright 1997-2007,2008 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#include <xterm.h> 36#include <data.h> 37#include <fontutils.h> 38 39#include <assert.h> 40 41#define WhichCgsId(flag) (((flag) & BOLD) ? gcCBold : gcCNorm) 42 43/* 44 * The first column is all that matters for double-size characters (since the 45 * controls apply to a whole line). However, it's easier to maintain the 46 * information for special fonts by writing to all cells. 47 */ 48#define curChrSet SCRN_BUF_CSETS(screen, screen->cur_row)[0] 49 50#if OPT_DEC_CHRSET 51 52static void 53repaint_line(XtermWidget xw, unsigned newChrSet) 54{ 55 register TScreen *screen = &xw->screen; 56 int curcol = screen->cur_col; 57 int currow = screen->cur_row; 58 unsigned len = MaxCols(screen); 59 int width = len; 60 unsigned oldChrSet = SCRN_BUF_CSETS(screen, currow)[0]; 61 62 assert(width > 0); 63 64 /* 65 * Ignore repetition. 66 */ 67 if (oldChrSet == newChrSet) 68 return; 69 70 TRACE(("repaint_line(%2d,%2d) (%s -> %s)\n", currow, screen->cur_col, 71 visibleChrsetName(oldChrSet), 72 visibleChrsetName(newChrSet))); 73 HideCursor(); 74 75 /* If switching from single-width, keep the cursor in the visible part 76 * of the line. 77 */ 78 if (CSET_DOUBLE(newChrSet)) { 79 width /= 2; 80 if (curcol > width) 81 curcol = width; 82 } 83 84 /* 85 * ScrnRefresh won't paint blanks for us if we're switching between a 86 * single-size and double-size font. So we paint our own. 87 */ 88 ClearCurBackground(xw, 89 CursorY(screen, currow), 90 CurCursorX(screen, currow, 0), 91 (unsigned) FontHeight(screen), 92 len * CurFontWidth(screen, currow)); 93 94 /* FIXME: do VT220 softchars allow double-sizes? */ 95 memset(SCRN_BUF_CSETS(screen, currow), (Char) newChrSet, len); 96 97 set_cur_col(screen, 0); 98 ScrnUpdate(xw, currow, 0, 1, (int) len, True); 99 set_cur_col(screen, curcol); 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#if OPT_DEC_CHRSET 140static void 141discard_font(XtermWidget xw, int n) 142{ 143 TScreen *screen = &xw->screen; 144 XTermFonts *data = &(screen->double_fonts[n]); 145 146 TRACE(("discard_font chrset=%d %s\n", data->chrset, 147 (data->fn != 0) ? data->fn : "<no-name>")); 148 149 data->chrset = 0; 150 data->flags = 0; 151 if (data->fn != 0) { 152 free(data->fn); 153 data->fn = 0; 154 } 155 (void) xtermCloseFont(xw, data); 156 157 screen->fonts_used -= 1; 158 while (n < screen->fonts_used) { 159 screen->double_fonts[n] = screen->double_fonts[n + 1]; 160 ++n; 161 } 162} 163 164/* push back existing fonts and create a new entry */ 165static XTermFonts * 166pushback_font(XtermWidget xw, XTermFonts * source) 167{ 168 TScreen *screen = &xw->screen; 169 XTermFonts *data = screen->double_fonts; 170 int n; 171 172 if (screen->fonts_used >= screen->cache_doublesize) { 173 TRACE(("pushback_font: discard oldest\n")); 174 discard_font(xw, screen->fonts_used - 1); 175 } else { 176 screen->fonts_used += 1; 177 } 178 179 for (n = screen->fonts_used; n > 0; n--) 180 data[n] = data[n - 1]; 181 data[0] = *source; 182 183 TRACE(("pushback_font -> (NEW:%d)\n", screen->fonts_used)); 184 185 return data; 186} 187 188int 189xterm_Double_index(XtermWidget xw, unsigned chrset, unsigned flags) 190{ 191 int n; 192 int result = -1; 193 TScreen *screen = &xw->screen; 194 XTermFonts *data = screen->double_fonts; 195 196 flags &= BOLD; 197 TRACE(("xterm_Double_index chrset=%#x, flags=%#x\n", chrset, flags)); 198 199 for (n = 0; n < screen->fonts_used; n++) { 200 if (data[n].chrset == chrset 201 && data[n].flags == flags) { 202 if (n != 0) { 203 XTermFonts save; 204 TRACE(("...xterm_Double_index -> %d (OLD:%d)\n", n, screen->fonts_used)); 205 save = data[n]; 206 while (n > 0) { 207 data[n] = data[n - 1]; 208 n--; 209 } 210 data[n] = save; 211 } 212 result = n; 213 break; 214 } 215 } 216 217 return result; 218} 219 220/* 221 * Lookup/cache a GC for the double-size character display. We save up to 222 * NUM_CHRSET values. 223 */ 224GC 225xterm_DoubleGC(XtermWidget xw, 226 unsigned chrset, 227 unsigned flags, 228 GC old_gc, 229 int *inxp) 230{ 231 TScreen *screen = &(xw->screen); 232 VTwin *cgsWin = WhichVWin(screen); 233 int n; 234 char *name; 235 XTermFonts *data = 0; 236 GC result = 0; 237 238 if ((name = xtermSpecialFont(screen, flags, chrset)) != 0) { 239 CgsEnum cgsId = WhichCgsId(flags); 240 Boolean found = False; 241 242 if ((n = xterm_Double_index(xw, chrset, flags)) >= 0) { 243 data = &(screen->double_fonts[n]); 244 if (data->fn != 0) { 245 if (!strcmp(data->fn, name) 246 && data->fs != 0) { 247 found = True; 248 free(name); 249 } else { 250 discard_font(xw, n); 251 } 252 } 253 } 254 255 if (!found) { 256 XTermFonts temp; 257 258 TRACE(("xterm_DoubleGC %s %d: %s\n", 259 flags & BOLD ? "BOLD" : "NORM", n, name)); 260 261 memset(&temp, 0, sizeof(temp)); 262 temp.fn = name; 263 temp.chrset = chrset; 264 temp.flags = (flags & BOLD); 265 266 if (!xtermOpenFont(xw, name, &temp)) { 267 /* Retry with * in resolutions */ 268 char *nname = xtermSpecialFont(screen, flags | NORESOLUTION, chrset); 269 270 if (nname != 0) { 271 found = xtermOpenFont(xw, nname, &temp); 272 free(nname); 273 } 274 } else { 275 found = True; 276 } 277 free(name); 278 279 if (found) { 280 n = 0; 281 data = pushback_font(xw, &temp); 282 } 283 284 TRACE(("-> %s\n", found ? "OK" : "FAIL")); 285 } 286 287 if (found) { 288 setCgsCSet(xw, cgsWin, cgsId, chrset); 289 setCgsFont(xw, cgsWin, cgsId, data); 290 setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, old_gc)); 291 setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, old_gc)); 292 result = getCgsGC(xw, cgsWin, cgsId); 293 *inxp = n; 294 } else if (flags & BOLD) { 295 flags &= ~BOLD; 296 result = xterm_DoubleGC(xw, chrset, flags, old_gc, inxp); 297 } 298 } 299 300 return result; 301} 302#endif 303