fontutils.c revision 20d2c4d2
120d2c4d2Smrg/* $XTermId: fontutils.c,v 1.344 2010/06/15 08:18:58 tom Exp $ */ 2d522f475Smrg 3d522f475Smrg/************************************************************ 4d522f475Smrg 520d2c4d2SmrgCopyright 1998-2009,2010 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 * A portion of this module (for FontNameProperties) was adapted from EMU 1.3; 37d522f475Smrg * it constructs font names with specific properties changed, e.g., for bold 38d522f475Smrg * and double-size characters. 39d522f475Smrg */ 40d522f475Smrg 41d522f475Smrg#define RES_OFFSET(field) XtOffsetOf(SubResourceRec, field) 42d522f475Smrg 43d522f475Smrg#include <fontutils.h> 44d522f475Smrg#include <X11/Xmu/Drawing.h> 4520d2c4d2Smrg#include <X11/Xmu/CharSet.h> 46d522f475Smrg 47d522f475Smrg#include <main.h> 48d522f475Smrg#include <data.h> 49d522f475Smrg#include <menu.h> 50d522f475Smrg#include <xstrings.h> 51d522f475Smrg#include <xterm.h> 52d522f475Smrg 53d522f475Smrg#include <stdio.h> 54d522f475Smrg#include <ctype.h> 55d522f475Smrg 56d522f475Smrg/* from X11/Xlibint.h - not all vendors install this file */ 57d522f475Smrg#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \ 58d522f475Smrg (((cs)->rbearing|(cs)->lbearing| \ 59d522f475Smrg (cs)->ascent|(cs)->descent) == 0)) 60d522f475Smrg 61d522f475Smrg#define CI_GET_CHAR_INFO_1D(fs,col,def,cs) \ 62d522f475Smrg{ \ 63d522f475Smrg cs = def; \ 64d522f475Smrg if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 65d522f475Smrg if (fs->per_char == NULL) { \ 66d522f475Smrg cs = &fs->min_bounds; \ 67d522f475Smrg } else { \ 68d522f475Smrg cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \ 69d522f475Smrg if (CI_NONEXISTCHAR(cs)) cs = def; \ 70d522f475Smrg } \ 71d522f475Smrg } \ 72d522f475Smrg} 73d522f475Smrg 74d522f475Smrg#define CI_GET_CHAR_INFO_2D(fs,row,col,def,cs) \ 75d522f475Smrg{ \ 76d522f475Smrg cs = def; \ 77d522f475Smrg if (row >= fs->min_byte1 && row <= fs->max_byte1 && \ 78d522f475Smrg col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 79d522f475Smrg if (fs->per_char == NULL) { \ 80d522f475Smrg cs = &fs->min_bounds; \ 81d522f475Smrg } else { \ 82d522f475Smrg cs = &fs->per_char[((row - fs->min_byte1) * \ 83d522f475Smrg (fs->max_char_or_byte2 - \ 84d522f475Smrg fs->min_char_or_byte2 + 1)) + \ 85d522f475Smrg (col - fs->min_char_or_byte2)]; \ 86d522f475Smrg if (CI_NONEXISTCHAR(cs)) cs = def; \ 87d522f475Smrg } \ 88d522f475Smrg } \ 89d522f475Smrg} 90d522f475Smrg 91d522f475Smrg#define MAX_FONTNAME 200 92d522f475Smrg 93d522f475Smrg/* 94d522f475Smrg * A structure to hold the relevant properties from a font 95d522f475Smrg * we need to make a well formed font name for it. 96d522f475Smrg */ 97d522f475Smrgtypedef struct { 98d522f475Smrg /* registry, foundry, family */ 99d522f475Smrg char *beginning; 100d522f475Smrg /* weight */ 101d522f475Smrg char *weight; 102d522f475Smrg /* slant */ 103d522f475Smrg char *slant; 104d522f475Smrg /* wideness */ 105d522f475Smrg char *wideness; 106d522f475Smrg /* add style */ 107d522f475Smrg char *add_style; 108d522f475Smrg int pixel_size; 109d522f475Smrg char *point_size; 110d522f475Smrg int res_x; 111d522f475Smrg int res_y; 112d522f475Smrg char *spacing; 113d522f475Smrg int average_width; 114d522f475Smrg /* charset registry, charset encoding */ 115d522f475Smrg char *end; 116d522f475Smrg} FontNameProperties; 117d522f475Smrg 118d522f475Smrg#if OPT_SHIFT_FONTS 119d522f475Smrgstatic void lookupOneFontSize(XtermWidget, int); 120d522f475Smrg#endif 121d522f475Smrg 122d522f475Smrg#if OPT_WIDE_CHARS 1232eaa94a1Schristosstatic unsigned 124d522f475SmrgcountGlyphs(XFontStruct * fp) 125d522f475Smrg{ 126d522f475Smrg unsigned count = 0; 127d522f475Smrg 128d522f475Smrg if (fp != 0) { 129d522f475Smrg if (fp->min_byte1 == 0 && fp->max_byte1 == 0) { 130d522f475Smrg count = fp->max_char_or_byte2 - fp->min_char_or_byte2; 131d522f475Smrg } else if (fp->min_char_or_byte2 < 256 132d522f475Smrg && fp->max_char_or_byte2 < 256) { 133d522f475Smrg unsigned first = (fp->min_byte1 << 8) + fp->min_char_or_byte2; 134d522f475Smrg unsigned last = (fp->max_byte1 << 8) + fp->max_char_or_byte2; 135d522f475Smrg count = last + 1 - first; 136d522f475Smrg } 137d522f475Smrg } 138d522f475Smrg return count; 139d522f475Smrg} 140d522f475Smrg 141d522f475Smrg/* 142d522f475Smrg * Verify that the wide-bold font is at least a bold font with roughly as many 143d522f475Smrg * glyphs as the wide font. The counts should be the same, but settle for 144d522f475Smrg * filtering out the worst of the font mismatches. 145d522f475Smrg */ 146d522f475Smrgstatic Bool 147d522f475SmrgcompatibleWideCounts(XFontStruct * wfs, XFontStruct * wbfs) 148d522f475Smrg{ 149d522f475Smrg unsigned count_w = countGlyphs(wfs); 150d522f475Smrg unsigned count_wb = countGlyphs(wbfs); 151d522f475Smrg if (count_w <= 256 || 152d522f475Smrg count_wb <= 256 || 153d522f475Smrg ((count_w / 4) * 3) > count_wb) { 154d522f475Smrg TRACE(("...font server lied (count wide %u vs wide-bold %u)\n", 155d522f475Smrg count_w, count_wb)); 156d522f475Smrg return False; 157d522f475Smrg } 158d522f475Smrg return True; 159d522f475Smrg} 160d522f475Smrg#endif /* OPT_WIDE_CHARS */ 161d522f475Smrg 16220d2c4d2Smrg#if OPT_BOX_CHARS 16320d2c4d2Smrgstatic void 16420d2c4d2SmrgsetupPackedFonts(XtermWidget xw) 16520d2c4d2Smrg{ 16620d2c4d2Smrg TScreen *screen = TScreenOf(xw); 16720d2c4d2Smrg Bool value = False; 16820d2c4d2Smrg 16920d2c4d2Smrg#if OPT_RENDERFONT 17020d2c4d2Smrg#define MIXED(name) screen->name[fontnum].map.mixed 17120d2c4d2Smrg if (xw->misc.render_font == True) { 17220d2c4d2Smrg int fontnum = screen->menu_font_number; 17320d2c4d2Smrg 17420d2c4d2Smrg screen->allow_packing = (Boolean) (MIXED(renderFontNorm) 17520d2c4d2Smrg || MIXED(renderFontBold) 17620d2c4d2Smrg || MIXED(renderFontItal) 17720d2c4d2Smrg#if OPT_RENDERWIDE 17820d2c4d2Smrg || MIXED(renderWideNorm) 17920d2c4d2Smrg || MIXED(renderWideBold) 18020d2c4d2Smrg || MIXED(renderWideItal) 18120d2c4d2Smrg#endif 18220d2c4d2Smrg ); 18320d2c4d2Smrg#undef MIXED 18420d2c4d2Smrg } 18520d2c4d2Smrg#endif /* OPT_RENDERFONT */ 18620d2c4d2Smrg 18720d2c4d2Smrg value = screen->allow_packing; 18820d2c4d2Smrg 18920d2c4d2Smrg SetItemSensitivity(fontMenuEntries[fontMenu_font_packedfont].widget, value); 19020d2c4d2Smrg} 19120d2c4d2Smrg#endif 19220d2c4d2Smrg 193d522f475Smrg/* 194d522f475Smrg * Returns the fields from start to stop in a dash- separated string. This 195d522f475Smrg * function will modify the source, putting '\0's in the appropiate place and 196d522f475Smrg * moving the beginning forward to after the '\0' 197d522f475Smrg * 198d522f475Smrg * This will NOT work for the last field (but we won't need it). 199d522f475Smrg */ 200d522f475Smrgstatic char * 201d522f475Smrgn_fields(char **source, int start, int stop) 202d522f475Smrg{ 203d522f475Smrg int i; 204d522f475Smrg char *str, *str1; 205d522f475Smrg 206d522f475Smrg /* 207d522f475Smrg * find the start-1th dash 208d522f475Smrg */ 209d522f475Smrg for (i = start - 1, str = *source; i; i--, str++) 210d522f475Smrg if ((str = strchr(str, '-')) == 0) 211d522f475Smrg return 0; 212d522f475Smrg 213d522f475Smrg /* 214d522f475Smrg * find the stopth dash 215d522f475Smrg */ 216d522f475Smrg for (i = stop - start + 1, str1 = str; i; i--, str1++) 217d522f475Smrg if ((str1 = strchr(str1, '-')) == 0) 218d522f475Smrg return 0; 219d522f475Smrg 220d522f475Smrg /* 221d522f475Smrg * put a \0 at the end of the fields 222d522f475Smrg */ 223d522f475Smrg *(str1 - 1) = '\0'; 224d522f475Smrg 225d522f475Smrg /* 226d522f475Smrg * move source forward 227d522f475Smrg */ 228d522f475Smrg *source = str1; 229d522f475Smrg 230d522f475Smrg return str; 231d522f475Smrg} 232d522f475Smrg 233956cc18dSsnjstatic Boolean 234956cc18dSsnjcheck_fontname(const char *name) 235956cc18dSsnj{ 236956cc18dSsnj Boolean result = True; 237956cc18dSsnj 238956cc18dSsnj if (name == 0) { 239956cc18dSsnj TRACE(("fontname missing\n")); 240956cc18dSsnj result = False; 241956cc18dSsnj } else if (strlen(name) >= MAX_FONTNAME - 1) { 242956cc18dSsnj TRACE(("fontname too large: %s\n", name)); 243956cc18dSsnj result = False; 244956cc18dSsnj } 245956cc18dSsnj return result; 246956cc18dSsnj} 247956cc18dSsnj 248d522f475Smrg/* 249d522f475Smrg * Gets the font properties from a given font structure. We use the FONT name 250d522f475Smrg * to find them out, since that seems easier. 251d522f475Smrg * 252d522f475Smrg * Returns a pointer to a static FontNameProperties structure 253d522f475Smrg * or NULL on error. 254d522f475Smrg */ 255d522f475Smrgstatic FontNameProperties * 256d522f475Smrgget_font_name_props(Display * dpy, XFontStruct * fs, char *result) 257d522f475Smrg{ 258d522f475Smrg static FontNameProperties props; 259d522f475Smrg static char *last_name; 260d522f475Smrg 261d522f475Smrg XFontProp *fp; 262d522f475Smrg int i; 263d522f475Smrg Atom fontatom = XInternAtom(dpy, "FONT", False); 26420d2c4d2Smrg char *name = 0; 265d522f475Smrg char *str; 266d522f475Smrg 267d522f475Smrg /* 268d522f475Smrg * first get the full font name 269d522f475Smrg */ 27020d2c4d2Smrg if (fontatom != 0) { 27120d2c4d2Smrg for (i = 0, fp = fs->properties; i < fs->n_properties; i++, fp++) { 27220d2c4d2Smrg if (fp->name == fontatom) { 27320d2c4d2Smrg name = XGetAtomName(dpy, fp->card32); 27420d2c4d2Smrg break; 27520d2c4d2Smrg } 27620d2c4d2Smrg } 27720d2c4d2Smrg } 278d522f475Smrg 279d522f475Smrg if (name == 0) 280d522f475Smrg return 0; 281d522f475Smrg 282d522f475Smrg /* 283d522f475Smrg * XGetAtomName allocates memory - don't leak 284d522f475Smrg */ 285d522f475Smrg if (last_name != 0) 286d522f475Smrg XFree(last_name); 287d522f475Smrg last_name = name; 288d522f475Smrg 289d522f475Smrg if (result != 0) { 290956cc18dSsnj if (!check_fontname(name)) 291d522f475Smrg return 0; 292956cc18dSsnj strcpy(result, name); 293d522f475Smrg } 294d522f475Smrg 295d522f475Smrg /* 296d522f475Smrg * Now split it up into parts and put them in 297d522f475Smrg * their places. Since we are using parts of 298d522f475Smrg * the original string, we must not free the Atom Name 299d522f475Smrg */ 300d522f475Smrg 301d522f475Smrg /* registry, foundry, family */ 302d522f475Smrg if ((props.beginning = n_fields(&name, 1, 3)) == 0) 303d522f475Smrg return 0; 304d522f475Smrg 305d522f475Smrg /* weight is the next */ 306d522f475Smrg if ((props.weight = n_fields(&name, 1, 1)) == 0) 307d522f475Smrg return 0; 308d522f475Smrg 309d522f475Smrg /* slant */ 310d522f475Smrg if ((props.slant = n_fields(&name, 1, 1)) == 0) 311d522f475Smrg return 0; 312d522f475Smrg 313d522f475Smrg /* width */ 314d522f475Smrg if ((props.wideness = n_fields(&name, 1, 1)) == 0) 315d522f475Smrg return 0; 316d522f475Smrg 317d522f475Smrg /* add style */ 318d522f475Smrg if ((props.add_style = n_fields(&name, 1, 1)) == 0) 319d522f475Smrg return 0; 320d522f475Smrg 321d522f475Smrg /* pixel size */ 322d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 323d522f475Smrg return 0; 324d522f475Smrg if ((props.pixel_size = atoi(str)) == 0) 325d522f475Smrg return 0; 326d522f475Smrg 327d522f475Smrg /* point size */ 328d522f475Smrg if ((props.point_size = n_fields(&name, 1, 1)) == 0) 329d522f475Smrg return 0; 330d522f475Smrg 331d522f475Smrg /* res_x */ 332d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 333d522f475Smrg return 0; 334d522f475Smrg if ((props.res_x = atoi(str)) == 0) 335d522f475Smrg return 0; 336d522f475Smrg 337d522f475Smrg /* res_y */ 338d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 339d522f475Smrg return 0; 340d522f475Smrg if ((props.res_y = atoi(str)) == 0) 341d522f475Smrg return 0; 342d522f475Smrg 343d522f475Smrg /* spacing */ 344d522f475Smrg if ((props.spacing = n_fields(&name, 1, 1)) == 0) 345d522f475Smrg return 0; 346d522f475Smrg 347d522f475Smrg /* average width */ 348d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 349d522f475Smrg return 0; 350d522f475Smrg if ((props.average_width = atoi(str)) == 0) 351d522f475Smrg return 0; 352d522f475Smrg 353d522f475Smrg /* the rest: charset registry and charset encoding */ 354d522f475Smrg props.end = name; 355d522f475Smrg 356d522f475Smrg return &props; 357d522f475Smrg} 358d522f475Smrg 359d522f475Smrg#define ALLOCHUNK(n) ((n | 127) + 1) 360d522f475Smrg 361d522f475Smrgstatic void 362956cc18dSsnjalloca_fontname(char **result, size_t next) 363d522f475Smrg{ 364956cc18dSsnj size_t last = (*result != 0) ? strlen(*result) : 0; 365956cc18dSsnj size_t have = (*result != 0) ? ALLOCHUNK(last) : 0; 366956cc18dSsnj size_t want = last + next + 2; 367d522f475Smrg 368d522f475Smrg if (want >= have) { 369d522f475Smrg want = ALLOCHUNK(want); 370d522f475Smrg if (last != 0) { 371d522f475Smrg *result = TypeRealloc(char, want, *result); 372d522f475Smrg } else { 373d522f475Smrg if ((*result = TypeMallocN(char, want)) != 0) 374d522f475Smrg **result = '\0'; 375d522f475Smrg } 376d522f475Smrg } 377d522f475Smrg} 378d522f475Smrg 379d522f475Smrgstatic void 38020d2c4d2Smrgappend_fontname_str(char **result, const char *value) 381d522f475Smrg{ 382d522f475Smrg if (value == 0) 383d522f475Smrg value = "*"; 384d522f475Smrg alloca_fontname(result, strlen(value)); 385d522f475Smrg if (*result != 0) { 386d522f475Smrg if (**result != '\0') 387d522f475Smrg strcat(*result, "-"); 388d522f475Smrg strcat(*result, value); 389d522f475Smrg } 390d522f475Smrg} 391d522f475Smrg 392d522f475Smrgstatic void 393d522f475Smrgappend_fontname_num(char **result, int value) 394d522f475Smrg{ 395d522f475Smrg if (value < 0) { 396d522f475Smrg append_fontname_str(result, "*"); 397d522f475Smrg } else { 398d522f475Smrg char temp[100]; 399d522f475Smrg sprintf(temp, "%d", value); 400d522f475Smrg append_fontname_str(result, temp); 401d522f475Smrg } 402d522f475Smrg} 403d522f475Smrg 404d522f475Smrg/* 405d522f475Smrg * Take the given font props and try to make a well formed font name specifying 406d522f475Smrg * the same base font and size and everything, but with different weight/width 407d522f475Smrg * according to the parameters. The return value is allocated, should be freed 408d522f475Smrg * by the caller. 409d522f475Smrg */ 410d522f475Smrgstatic char * 411d522f475Smrgderive_font_name(FontNameProperties * props, 41220d2c4d2Smrg const char *use_weight, 413d522f475Smrg int use_average_width, 41420d2c4d2Smrg const char *use_encoding) 415d522f475Smrg{ 416d522f475Smrg char *result = 0; 417d522f475Smrg 418d522f475Smrg append_fontname_str(&result, props->beginning); 419d522f475Smrg append_fontname_str(&result, use_weight); 420d522f475Smrg append_fontname_str(&result, props->slant); 421d522f475Smrg append_fontname_str(&result, 0); 422d522f475Smrg append_fontname_str(&result, 0); 423d522f475Smrg append_fontname_num(&result, props->pixel_size); 424d522f475Smrg append_fontname_str(&result, props->point_size); 425d522f475Smrg append_fontname_num(&result, props->res_x); 426d522f475Smrg append_fontname_num(&result, props->res_y); 427d522f475Smrg append_fontname_str(&result, props->spacing); 428d522f475Smrg append_fontname_num(&result, use_average_width); 429d522f475Smrg append_fontname_str(&result, use_encoding); 430d522f475Smrg 431d522f475Smrg return result; 432d522f475Smrg} 433d522f475Smrg 434d522f475Smrgstatic char * 435d522f475Smrgbold_font_name(FontNameProperties * props, int use_average_width) 436d522f475Smrg{ 437d522f475Smrg return derive_font_name(props, "bold", use_average_width, props->end); 438d522f475Smrg} 439d522f475Smrg 440d522f475Smrg#if OPT_WIDE_CHARS 441d522f475Smrg#define derive_wide_font(props, weight) \ 442d522f475Smrg derive_font_name(props, weight, props->average_width * 2, "ISO10646-1") 443d522f475Smrg 444d522f475Smrgstatic char * 445d522f475Smrgwide_font_name(FontNameProperties * props) 446d522f475Smrg{ 447d522f475Smrg return derive_wide_font(props, "medium"); 448d522f475Smrg} 449d522f475Smrg 450d522f475Smrgstatic char * 451d522f475Smrgwidebold_font_name(FontNameProperties * props) 452d522f475Smrg{ 453d522f475Smrg return derive_wide_font(props, "bold"); 454d522f475Smrg} 455d522f475Smrg#endif /* OPT_WIDE_CHARS */ 456d522f475Smrg 457d522f475Smrg#if OPT_DEC_CHRSET 458d522f475Smrg/* 459d522f475Smrg * Take the given font props and try to make a well formed font name specifying 460d522f475Smrg * the same base font but changed depending on the given attributes and chrset. 461d522f475Smrg * 462d522f475Smrg * For double width fonts, we just double the X-resolution, for double height 463d522f475Smrg * fonts we double the pixel-size and Y-resolution 464d522f475Smrg */ 465d522f475Smrgchar * 466d522f475SmrgxtermSpecialFont(TScreen * screen, unsigned atts, unsigned chrset) 467d522f475Smrg{ 468d522f475Smrg#if OPT_TRACE 469d522f475Smrg static char old_spacing[80]; 470d522f475Smrg static FontNameProperties old_props; 471d522f475Smrg#endif 472d522f475Smrg FontNameProperties *props; 473d522f475Smrg char *result = 0; 47420d2c4d2Smrg const char *weight; 475d522f475Smrg int pixel_size; 476d522f475Smrg int res_x; 477d522f475Smrg int res_y; 478d522f475Smrg 479d522f475Smrg props = get_font_name_props(screen->display, screen->fnts[fNorm].fs, 0); 480d522f475Smrg if (props == 0) 481d522f475Smrg return result; 482d522f475Smrg 483d522f475Smrg pixel_size = props->pixel_size; 484d522f475Smrg res_x = props->res_x; 485d522f475Smrg res_y = props->res_y; 486d522f475Smrg if (atts & BOLD) 487d522f475Smrg weight = "bold"; 488d522f475Smrg else 489d522f475Smrg weight = props->weight; 490d522f475Smrg 491d522f475Smrg if (CSET_DOUBLE(chrset)) 492d522f475Smrg res_x *= 2; 493d522f475Smrg 494d522f475Smrg if (chrset == CSET_DHL_TOP 495d522f475Smrg || chrset == CSET_DHL_BOT) { 496d522f475Smrg res_y *= 2; 497d522f475Smrg pixel_size *= 2; 498d522f475Smrg } 499d522f475Smrg#if OPT_TRACE 500d522f475Smrg if (old_props.res_x != res_x 501d522f475Smrg || old_props.res_x != res_y 502d522f475Smrg || old_props.pixel_size != pixel_size 503d522f475Smrg || strcmp(old_props.spacing, props->spacing)) { 504d522f475Smrg TRACE(("xtermSpecialFont(atts = %#x, chrset = %#x)\n", atts, chrset)); 505d522f475Smrg TRACE(("res_x = %d\n", res_x)); 506d522f475Smrg TRACE(("res_y = %d\n", res_y)); 507d522f475Smrg TRACE(("point_size = %s\n", props->point_size)); 508d522f475Smrg TRACE(("pixel_size = %d\n", pixel_size)); 509d522f475Smrg TRACE(("spacing = %s\n", props->spacing)); 510d522f475Smrg old_props.res_x = res_x; 511d522f475Smrg old_props.res_x = res_y; 512d522f475Smrg old_props.pixel_size = pixel_size; 513d522f475Smrg old_props.spacing = strcpy(old_spacing, props->spacing); 514d522f475Smrg } 515d522f475Smrg#endif 516d522f475Smrg 517d522f475Smrg append_fontname_str(&result, props->beginning); 518d522f475Smrg append_fontname_str(&result, weight); 519d522f475Smrg append_fontname_str(&result, props->slant); 520d522f475Smrg append_fontname_str(&result, props->wideness); 521d522f475Smrg append_fontname_str(&result, props->add_style); 522d522f475Smrg append_fontname_num(&result, pixel_size); 523d522f475Smrg append_fontname_str(&result, props->point_size); 524d522f475Smrg append_fontname_num(&result, (atts & NORESOLUTION) ? -1 : res_x); 525d522f475Smrg append_fontname_num(&result, (atts & NORESOLUTION) ? -1 : res_y); 526d522f475Smrg append_fontname_str(&result, props->spacing); 527d522f475Smrg append_fontname_str(&result, 0); 528d522f475Smrg append_fontname_str(&result, props->end); 529d522f475Smrg 530d522f475Smrg return result; 531d522f475Smrg} 532d522f475Smrg#endif /* OPT_DEC_CHRSET */ 533d522f475Smrg 534d522f475Smrg/* 535d522f475Smrg * Case-independent comparison for font-names, including wildcards. 536d522f475Smrg * XLFD allows '?' as a wildcard, but we do not handle that (no one seems 537d522f475Smrg * to use it). 538d522f475Smrg */ 539d522f475Smrgstatic Bool 540d522f475Smrgsame_font_name(char *pattern, char *match) 541d522f475Smrg{ 542956cc18dSsnj Bool result = False; 543956cc18dSsnj 544956cc18dSsnj if (pattern && match) { 545956cc18dSsnj while (*pattern && *match) { 546956cc18dSsnj if (*pattern == *match) { 547956cc18dSsnj pattern++; 548956cc18dSsnj match++; 549956cc18dSsnj } else if (*pattern == '*' || *match == '*') { 550956cc18dSsnj if (same_font_name(pattern + 1, match)) { 551956cc18dSsnj return True; 552956cc18dSsnj } else if (same_font_name(pattern, match + 1)) { 553956cc18dSsnj return True; 554956cc18dSsnj } else { 555956cc18dSsnj return False; 556956cc18dSsnj } 557d522f475Smrg } else { 558956cc18dSsnj int p = x_toupper(*pattern++); 559956cc18dSsnj int m = x_toupper(*match++); 560956cc18dSsnj if (p != m) 561956cc18dSsnj return False; 562d522f475Smrg } 563d522f475Smrg } 564956cc18dSsnj result = (*pattern == *match); /* both should be NUL */ 565d522f475Smrg } 566956cc18dSsnj return result; 567d522f475Smrg} 568d522f475Smrg 569d522f475Smrg/* 570d522f475Smrg * Double-check the fontname that we asked for versus what the font server 571d522f475Smrg * actually gave us. The larger fixed fonts do not always have a matching bold 572d522f475Smrg * font, and the font server may try to scale another font or otherwise 573d522f475Smrg * substitute a mismatched font. 574d522f475Smrg * 575d522f475Smrg * If we cannot get what we requested, we will fallback to the original 576d522f475Smrg * behavior, which simulates bold by overstriking each character at one pixel 577d522f475Smrg * offset. 578d522f475Smrg */ 579d522f475Smrgstatic int 580d522f475Smrggot_bold_font(Display * dpy, XFontStruct * fs, char *requested) 581d522f475Smrg{ 582d522f475Smrg char actual[MAX_FONTNAME]; 583d522f475Smrg int got; 584d522f475Smrg 585d522f475Smrg if (get_font_name_props(dpy, fs, actual) == 0) 586d522f475Smrg got = 0; 587d522f475Smrg else 588d522f475Smrg got = same_font_name(requested, actual); 589d522f475Smrg return got; 590d522f475Smrg} 591d522f475Smrg 592d522f475Smrg/* 593d522f475Smrg * If the font server tries to adjust another font, it may not adjust it 594d522f475Smrg * properly. Check that the bounding boxes are compatible. Otherwise we'll 595d522f475Smrg * leave trash on the display when we mix normal and bold fonts. 596d522f475Smrg */ 597d522f475Smrgstatic int 598d522f475Smrgsame_font_size(XtermWidget xw, XFontStruct * nfs, XFontStruct * bfs) 599d522f475Smrg{ 600956cc18dSsnj TScreen *screen = TScreenOf(xw); 601d522f475Smrg TRACE(("same_font_size height %d/%d, min %d/%d max %d/%d\n", 602d522f475Smrg nfs->ascent + nfs->descent, 603d522f475Smrg bfs->ascent + bfs->descent, 604d522f475Smrg nfs->min_bounds.width, bfs->min_bounds.width, 605d522f475Smrg nfs->max_bounds.width, bfs->max_bounds.width)); 606956cc18dSsnj return screen->free_bold_box 607d522f475Smrg || ((nfs->ascent + nfs->descent) == (bfs->ascent + bfs->descent) 608d522f475Smrg && (nfs->min_bounds.width == bfs->min_bounds.width 609d522f475Smrg || nfs->min_bounds.width == bfs->min_bounds.width + 1) 610d522f475Smrg && (nfs->max_bounds.width == bfs->max_bounds.width 611d522f475Smrg || nfs->max_bounds.width == bfs->max_bounds.width + 1)); 612d522f475Smrg} 613d522f475Smrg 614d522f475Smrg/* 615d522f475Smrg * Check if the font looks like it has fixed width 616d522f475Smrg */ 617d522f475Smrgstatic int 618d522f475Smrgis_fixed_font(XFontStruct * fs) 619d522f475Smrg{ 620d522f475Smrg if (fs) 621d522f475Smrg return (fs->min_bounds.width == fs->max_bounds.width); 622d522f475Smrg return 1; 623d522f475Smrg} 624d522f475Smrg 625d522f475Smrg/* 626d522f475Smrg * Check if the font looks like a double width font (i.e. contains 627d522f475Smrg * characters of width X and 2X 628d522f475Smrg */ 629d522f475Smrg#if OPT_WIDE_CHARS 630d522f475Smrgstatic int 631d522f475Smrgis_double_width_font(XFontStruct * fs) 632d522f475Smrg{ 633d522f475Smrg return ((2 * fs->min_bounds.width) == fs->max_bounds.width); 634d522f475Smrg} 635d522f475Smrg#else 636d522f475Smrg#define is_double_width_font(fs) 0 637d522f475Smrg#endif 638d522f475Smrg 639d522f475Smrg#if OPT_WIDE_CHARS && OPT_RENDERFONT && defined(HAVE_TYPE_FCCHAR32) 640d522f475Smrg#define HALF_WIDTH_TEST_STRING "1234567890" 641d522f475Smrg 642d522f475Smrg/* '1234567890' in Chinese characters in UTF-8 */ 643d522f475Smrg#define FULL_WIDTH_TEST_STRING "\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89" \ 644d522f475Smrg "\xe5\x9b\x9b\xe4\xba\x94" \ 645d522f475Smrg "\xef\xa7\x91\xe4\xb8\x83\xe5\x85\xab" \ 646d522f475Smrg "\xe4\xb9\x9d\xef\xa6\xb2" 647d522f475Smrg 648d522f475Smrg/* '1234567890' in Korean script in UTF-8 */ 649d522f475Smrg#define FULL_WIDTH_TEST_STRING2 "\xec\x9d\xbc\xec\x9d\xb4\xec\x82\xbc" \ 650d522f475Smrg "\xec\x82\xac\xec\x98\xa4" \ 651d522f475Smrg "\xec\x9c\xa1\xec\xb9\xa0\xed\x8c\x94" \ 652d522f475Smrg "\xea\xb5\xac\xec\x98\x81" 653d522f475Smrg 654d522f475Smrg#define HALF_WIDTH_CHAR1 0x0031 /* '1' */ 655d522f475Smrg#define HALF_WIDTH_CHAR2 0x0057 /* 'W' */ 656d522f475Smrg#define FULL_WIDTH_CHAR1 0x4E00 /* CJK Ideograph 'number one' */ 657d522f475Smrg#define FULL_WIDTH_CHAR2 0xAC00 /* Korean script syllable 'Ka' */ 658d522f475Smrg 659d522f475Smrgstatic Bool 660d522f475Smrgis_double_width_font_xft(Display * dpy, XftFont * font) 661d522f475Smrg{ 662d522f475Smrg XGlyphInfo gi1, gi2; 663d522f475Smrg FcChar32 c1 = HALF_WIDTH_CHAR1, c2 = HALF_WIDTH_CHAR2; 664d522f475Smrg char *fwstr = FULL_WIDTH_TEST_STRING; 665d522f475Smrg char *hwstr = HALF_WIDTH_TEST_STRING; 666d522f475Smrg 667d522f475Smrg /* Some Korean fonts don't have Chinese characters at all. */ 668d522f475Smrg if (!XftCharExists(dpy, font, FULL_WIDTH_CHAR1)) { 669d522f475Smrg if (!XftCharExists(dpy, font, FULL_WIDTH_CHAR2)) 670d522f475Smrg return False; /* Not a CJK font */ 671d522f475Smrg else /* a Korean font without CJK Ideographs */ 672d522f475Smrg fwstr = FULL_WIDTH_TEST_STRING2; 673d522f475Smrg } 674d522f475Smrg 675d522f475Smrg XftTextExtents32(dpy, font, &c1, 1, &gi1); 676d522f475Smrg XftTextExtents32(dpy, font, &c2, 1, &gi2); 677d522f475Smrg if (gi1.xOff != gi2.xOff) /* Not a fixed-width font */ 678d522f475Smrg return False; 679d522f475Smrg 680d522f475Smrg XftTextExtentsUtf8(dpy, font, (FcChar8 *) hwstr, (int) strlen(hwstr), &gi1); 681d522f475Smrg XftTextExtentsUtf8(dpy, font, (FcChar8 *) fwstr, (int) strlen(fwstr), &gi2); 682d522f475Smrg 683d522f475Smrg /* 684d522f475Smrg * fontconfig and Xft prior to 2.2(?) set the width of half-width 685d522f475Smrg * characters identical to that of full-width character in CJK double-width 686d522f475Smrg * (bi-width / monospace) font even though the former is half as wide as 687d522f475Smrg * the latter. This was fixed sometime before the release of fontconfig 688d522f475Smrg * 2.2 in early 2003. See 689d522f475Smrg * http://bugzilla.mozilla.org/show_bug.cgi?id=196312 690d522f475Smrg * In the meantime, we have to check both possibilities. 691d522f475Smrg */ 692d522f475Smrg return ((2 * gi1.xOff == gi2.xOff) || (gi1.xOff == gi2.xOff)); 693d522f475Smrg} 694d522f475Smrg#else 695d522f475Smrg#define is_double_width_font_xft(dpy, xftfont) 0 696d522f475Smrg#endif 697d522f475Smrg 698d522f475Smrg#define EmptyFont(fs) (fs != 0 \ 699d522f475Smrg && ((fs)->ascent + (fs)->descent == 0 \ 700d522f475Smrg || (fs)->max_bounds.width == 0)) 701d522f475Smrg 702d522f475Smrg#define FontSize(fs) (((fs)->ascent + (fs)->descent) \ 703d522f475Smrg * (fs)->max_bounds.width) 704d522f475Smrg 705d522f475Smrgconst VTFontNames * 70620d2c4d2SmrgxtermFontName(const char *normal) 707d522f475Smrg{ 708d522f475Smrg static VTFontNames data; 70920d2c4d2Smrg if (data.f_n) 71020d2c4d2Smrg free(data.f_n); 711d522f475Smrg memset(&data, 0, sizeof(data)); 71220d2c4d2Smrg data.f_n = x_strdup(normal); 713d522f475Smrg return &data; 714d522f475Smrg} 715d522f475Smrg 716d522f475Smrgstatic void 717d522f475Smrgcache_menu_font_name(TScreen * screen, int fontnum, int which, const char *name) 718d522f475Smrg{ 719d522f475Smrg if (name != 0) { 720d522f475Smrg char *last = screen->menu_font_names[fontnum][which]; 721d522f475Smrg if (last != 0) { 722d522f475Smrg if (strcmp(last, name)) { 723d522f475Smrg free(last); 724d522f475Smrg TRACE(("caching menu fontname %d.%d %s\n", fontnum, which, name)); 725d522f475Smrg screen->menu_font_names[fontnum][which] = x_strdup(name); 726d522f475Smrg } 727d522f475Smrg } else { 728d522f475Smrg TRACE(("caching menu fontname %d.%d %s\n", fontnum, which, name)); 729d522f475Smrg screen->menu_font_names[fontnum][which] = x_strdup(name); 730d522f475Smrg } 731d522f475Smrg } 732d522f475Smrg} 733d522f475Smrg 734d522f475Smrg/* 735d522f475Smrg * Open the given font and verify that it is non-empty. Return a null on 736d522f475Smrg * failure. 737d522f475Smrg */ 738d522f475SmrgBool 739956cc18dSsnjxtermOpenFont(XtermWidget xw, 740956cc18dSsnj const char *name, 741956cc18dSsnj XTermFonts * result, 742956cc18dSsnj fontWarningTypes warn, 743956cc18dSsnj Bool force) 744d522f475Smrg{ 745d522f475Smrg Bool code = False; 746d522f475Smrg TScreen *screen = TScreenOf(xw); 747d522f475Smrg 748956cc18dSsnj if (name != 0) { 749956cc18dSsnj if ((result->fs = XLoadQueryFont(screen->display, name)) != 0) { 750956cc18dSsnj code = True; 751956cc18dSsnj if (EmptyFont(result->fs)) { 75220d2c4d2Smrg (void) xtermCloseFont(xw, result); 753956cc18dSsnj code = False; 754956cc18dSsnj } else { 755956cc18dSsnj result->fn = x_strdup(name); 756956cc18dSsnj } 75720d2c4d2Smrg } else if (XmuCompareISOLatin1(name, DEFFONT) != 0) { 758956cc18dSsnj if (warn <= xw->misc.fontWarnings 759956cc18dSsnj#if OPT_RENDERFONT 760956cc18dSsnj && !UsingRenderFont(xw) 761956cc18dSsnj#endif 762956cc18dSsnj ) { 763956cc18dSsnj TRACE(("OOPS: cannot load font %s\n", name)); 764956cc18dSsnj fprintf(stderr, "%s: cannot load font %s\n", ProgramName, name); 76520d2c4d2Smrg#if OPT_RENDERFONT 76620d2c4d2Smrg /* 76720d2c4d2Smrg * Do a sanity check in case someone's mixed up xterm with 76820d2c4d2Smrg * one of those programs that read their resource data from 76920d2c4d2Smrg * xterm's namespace. 77020d2c4d2Smrg */ 77120d2c4d2Smrg if (strchr(name, ':') != 0 || strchr(name, '=') != 0) { 77220d2c4d2Smrg fprintf(stderr, 77320d2c4d2Smrg "Use the \"-fa\" option for the Xft fonts\n"); 77420d2c4d2Smrg } 77520d2c4d2Smrg#endif 776956cc18dSsnj } else { 777956cc18dSsnj TRACE(("xtermOpenFont: cannot load font %s\n", name)); 778956cc18dSsnj } 779956cc18dSsnj if (force) { 780956cc18dSsnj code = xtermOpenFont(xw, DEFFONT, result, fwAlways, True); 781956cc18dSsnj } 782d522f475Smrg } 783d522f475Smrg } 784d522f475Smrg return code; 785d522f475Smrg} 786d522f475Smrg 787d522f475Smrg/* 788956cc18dSsnj * Close the font and free the font info. 789d522f475Smrg */ 790d522f475SmrgXTermFonts * 791d522f475SmrgxtermCloseFont(XtermWidget xw, XTermFonts * fnt) 792d522f475Smrg{ 793d522f475Smrg if (fnt != 0 && fnt->fs != 0) { 794d522f475Smrg TScreen *screen = TScreenOf(xw); 795d522f475Smrg 796d522f475Smrg clrCgsFonts(xw, WhichVWin(screen), fnt); 797d522f475Smrg XFreeFont(screen->display, fnt->fs); 798d522f475Smrg xtermFreeFontInfo(fnt); 799d522f475Smrg } 800d522f475Smrg return 0; 801d522f475Smrg} 802d522f475Smrg 803d522f475Smrg/* 804d522f475Smrg * Close the listed fonts, noting that some may use copies of the pointer. 805d522f475Smrg */ 806d522f475Smrgvoid 807d522f475SmrgxtermCloseFonts(XtermWidget xw, XTermFonts * fnts) 808d522f475Smrg{ 809d522f475Smrg int j, k; 810d522f475Smrg 811d522f475Smrg for (j = 0; j < fMAX; ++j) { 812d522f475Smrg /* 813d522f475Smrg * Need to save the pointer since xtermCloseFont zeroes it 814d522f475Smrg */ 815d522f475Smrg XFontStruct *thisFont = fnts[j].fs; 816d522f475Smrg if (thisFont != 0) { 817d522f475Smrg xtermCloseFont(xw, &fnts[j]); 818d522f475Smrg for (k = j + 1; k < fMAX; ++k) { 819d522f475Smrg if (thisFont == fnts[k].fs) 820d522f475Smrg xtermFreeFontInfo(&fnts[k]); 821d522f475Smrg } 822d522f475Smrg } 823d522f475Smrg } 824d522f475Smrg} 825d522f475Smrg 826d522f475Smrg/* 827d522f475Smrg * Make a copy of the source, assuming the XFontStruct's to be unique, but 828d522f475Smrg * ensuring that the names are reallocated to simplify freeing. 829d522f475Smrg */ 830d522f475Smrgvoid 831d522f475SmrgxtermCopyFontInfo(XTermFonts * target, XTermFonts * source) 832d522f475Smrg{ 833d522f475Smrg xtermFreeFontInfo(target); 834d522f475Smrg target->chrset = source->chrset; 835d522f475Smrg target->flags = source->flags; 836d522f475Smrg target->fn = x_strdup(source->fn); 837d522f475Smrg target->fs = source->fs; 838d522f475Smrg} 839d522f475Smrg 840d522f475Smrgvoid 841d522f475SmrgxtermFreeFontInfo(XTermFonts * target) 842d522f475Smrg{ 843d522f475Smrg target->chrset = 0; 844d522f475Smrg target->flags = 0; 845d522f475Smrg if (target->fn != 0) { 846d522f475Smrg free(target->fn); 847d522f475Smrg target->fn = 0; 848d522f475Smrg } 849d522f475Smrg target->fs = 0; 850d522f475Smrg} 851d522f475Smrg 852d522f475Smrgint 853d522f475SmrgxtermLoadFont(XtermWidget xw, 854d522f475Smrg const VTFontNames * fonts, 855d522f475Smrg Bool doresize, 856d522f475Smrg int fontnum) 857d522f475Smrg{ 858956cc18dSsnj TScreen *screen = TScreenOf(xw); 859d522f475Smrg VTwin *win = WhichVWin(screen); 860d522f475Smrg 861d522f475Smrg VTFontNames myfonts; 862d522f475Smrg FontNameProperties *fp; 863d522f475Smrg XTermFonts fnts[fMAX]; 864d522f475Smrg Pixel new_normal; 865d522f475Smrg Pixel new_revers; 866d522f475Smrg char *tmpname = NULL; 867d522f475Smrg char normal[MAX_FONTNAME]; 868956cc18dSsnj Boolean proportional = False; 869956cc18dSsnj fontWarningTypes warn[fMAX]; 870956cc18dSsnj int j; 871d522f475Smrg 872d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 873d522f475Smrg memset(fnts, 0, sizeof(fnts)); 874d522f475Smrg 875d522f475Smrg if (fonts != 0) 876d522f475Smrg myfonts = *fonts; 877956cc18dSsnj if (!check_fontname(myfonts.f_n)) 878d522f475Smrg return 0; 879d522f475Smrg 880956cc18dSsnj /* 881956cc18dSsnj * Check the font names against the resource values, to see which were 882956cc18dSsnj * derived in a previous call. If so, we'll only warn about those if 883956cc18dSsnj * the warning level is set to "always". 884956cc18dSsnj */ 885956cc18dSsnj for (j = 0; j < fMAX; ++j) { 886956cc18dSsnj warn[j] = fwAlways; 887956cc18dSsnj } 888956cc18dSsnj#define CmpResource(field, index) \ 889956cc18dSsnj if (same_font_name(screen->menu_font_names[fontnum][index], myfonts.field)) \ 890956cc18dSsnj warn[index] = fwResource 891956cc18dSsnj 892956cc18dSsnj CmpResource(f_n, fNorm); 893956cc18dSsnj if (fontnum == fontMenu_default) { 894956cc18dSsnj CmpResource(f_b, fBold); 895956cc18dSsnj#if OPT_WIDE_CHARS 896956cc18dSsnj CmpResource(f_b, fWide); 897956cc18dSsnj CmpResource(f_b, fWBold); 898956cc18dSsnj#endif 899956cc18dSsnj } 900956cc18dSsnj 901d522f475Smrg if (fontnum == fontMenu_fontescape 902d522f475Smrg && myfonts.f_n != screen->MenuFontName(fontnum)) { 903d522f475Smrg if ((tmpname = x_strdup(myfonts.f_n)) == 0) 904d522f475Smrg return 0; 905d522f475Smrg } 906d522f475Smrg 907d522f475Smrg TRACE(("Begin Cgs - xtermLoadFont(%s)\n", myfonts.f_n)); 908d522f475Smrg releaseWindowGCs(xw, win); 909d522f475Smrg 910956cc18dSsnj#define DbgResource(name, field, index) \ 911956cc18dSsnj TRACE(("xtermLoadFont #%d "name" %s%s\n", \ 912956cc18dSsnj fontnum, \ 913956cc18dSsnj (warn[index] == fwResource) ? "*" : " ", \ 914956cc18dSsnj NonNull(myfonts.field))); 915956cc18dSsnj DbgResource("normal", f_n, fNorm); 916956cc18dSsnj DbgResource("bold ", f_b, fBold); 917d522f475Smrg#if OPT_WIDE_CHARS 918956cc18dSsnj DbgResource("wide ", f_w, fWide); 919956cc18dSsnj DbgResource("w/bold", f_wb, fWBold); 920d522f475Smrg#endif 921d522f475Smrg 922956cc18dSsnj if (!xtermOpenFont(xw, myfonts.f_n, &fnts[fNorm], warn[fNorm], True)) 923d522f475Smrg goto bad; 924d522f475Smrg 925d522f475Smrg strcpy(normal, myfonts.f_n); 926956cc18dSsnj if (!check_fontname(myfonts.f_b)) { 927956cc18dSsnj warn[fBold] = fwAlways; 928d522f475Smrg fp = get_font_name_props(screen->display, fnts[fNorm].fs, normal); 929d522f475Smrg if (fp != 0) { 930d522f475Smrg myfonts.f_b = bold_font_name(fp, fp->average_width); 931956cc18dSsnj if (!xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], fwAlways, False)) { 932d522f475Smrg myfonts.f_b = bold_font_name(fp, -1); 933956cc18dSsnj xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], fwAlways, False); 934d522f475Smrg } 935d522f475Smrg TRACE(("...derived bold %s\n", NonNull(myfonts.f_b))); 936d522f475Smrg } 937d522f475Smrg if (fp == 0 || fnts[fBold].fs == 0) { 938d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 939d522f475Smrg TRACE(("...cannot load a matching bold font\n")); 940d522f475Smrg } else if (same_font_size(xw, fnts[fNorm].fs, fnts[fBold].fs) 941d522f475Smrg && got_bold_font(screen->display, fnts[fBold].fs, myfonts.f_b)) { 942d522f475Smrg TRACE(("...got a matching bold font\n")); 943d522f475Smrg cache_menu_font_name(screen, fontnum, fBold, myfonts.f_b); 944d522f475Smrg } else { 945d522f475Smrg xtermCloseFont(xw, &fnts[fBold]); 946d522f475Smrg fnts[fBold] = fnts[fNorm]; 947d522f475Smrg TRACE(("...did not get a matching bold font\n")); 948d522f475Smrg } 949956cc18dSsnj } else if (!xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], warn[fBold], False)) { 950d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 951956cc18dSsnj warn[fBold] = fwAlways; 952d522f475Smrg TRACE(("...cannot load bold font %s\n", NonNull(myfonts.f_b))); 953d522f475Smrg } else { 954d522f475Smrg cache_menu_font_name(screen, fontnum, fBold, myfonts.f_b); 955d522f475Smrg } 956d522f475Smrg 957d522f475Smrg /* 958d522f475Smrg * If there is no widefont specified, fake it by doubling AVERAGE_WIDTH 959d522f475Smrg * of normal fonts XLFD, and asking for it. This plucks out 18x18ja 960d522f475Smrg * and 12x13ja as the corresponding fonts for 9x18 and 6x13. 961d522f475Smrg */ 962d522f475Smrg if_OPT_WIDE_CHARS(screen, { 963d522f475Smrg Bool derived; 964d522f475Smrg char bold[MAX_FONTNAME]; 965d522f475Smrg 966956cc18dSsnj if (check_fontname(myfonts.f_w)) { 967d522f475Smrg cache_menu_font_name(screen, fontnum, fWide, myfonts.f_w); 968d522f475Smrg } else if (!is_double_width_font(fnts[fNorm].fs)) { 969d522f475Smrg fp = get_font_name_props(screen->display, fnts[fNorm].fs, normal); 970d522f475Smrg if (fp != 0) { 971d522f475Smrg myfonts.f_w = wide_font_name(fp); 972956cc18dSsnj warn[fWide] = fwAlways; 973d522f475Smrg TRACE(("...derived wide %s\n", NonNull(myfonts.f_w))); 974d522f475Smrg cache_menu_font_name(screen, fontnum, fWide, myfonts.f_w); 975d522f475Smrg } 976d522f475Smrg } 977d522f475Smrg 978956cc18dSsnj if (check_fontname(myfonts.f_w)) { 979956cc18dSsnj (void) xtermOpenFont(xw, myfonts.f_w, &fnts[fWide], warn[fWide], False); 980d522f475Smrg } else { 981d522f475Smrg xtermCopyFontInfo(&fnts[fWide], &fnts[fNorm]); 982956cc18dSsnj warn[fWide] = fwAlways; 983d522f475Smrg } 984d522f475Smrg 985d522f475Smrg derived = False; 986956cc18dSsnj if (!check_fontname(myfonts.f_wb)) { 987d522f475Smrg fp = get_font_name_props(screen->display, fnts[fBold].fs, bold); 988d522f475Smrg if (fp != 0) { 989d522f475Smrg myfonts.f_wb = widebold_font_name(fp); 990956cc18dSsnj warn[fWBold] = fwAlways; 991d522f475Smrg derived = True; 992d522f475Smrg } 993d522f475Smrg } 994d522f475Smrg 995956cc18dSsnj if (check_fontname(myfonts.f_wb)) { 996d522f475Smrg 997956cc18dSsnj xtermOpenFont(xw, myfonts.f_wb, &fnts[fWBold], warn[fWBold], False); 998d522f475Smrg 999d522f475Smrg if (derived 1000d522f475Smrg && !compatibleWideCounts(fnts[fWide].fs, fnts[fWBold].fs)) { 1001d522f475Smrg xtermCloseFont(xw, &fnts[fWBold]); 1002d522f475Smrg } 1003d522f475Smrg if (fnts[fWBold].fs == 0) { 1004d522f475Smrg myfonts.f_wb = myfonts.f_w; 1005956cc18dSsnj warn[fWBold] = fwAlways; 1006d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1007d522f475Smrg TRACE(("...cannot load wide-bold, use wide %s\n", NonNull(myfonts.f_w))); 1008d522f475Smrg } else { 1009d522f475Smrg TRACE(("...%s wide/bold %s\n", 1010d522f475Smrg derived ? "derived" : "given", 1011d522f475Smrg NonNull(myfonts.f_wb))); 1012d522f475Smrg cache_menu_font_name(screen, fontnum, fWBold, myfonts.f_wb); 1013d522f475Smrg } 1014d522f475Smrg } else if (is_double_width_font(fnts[fBold].fs)) { 1015d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fBold]); 1016956cc18dSsnj warn[fWBold] = fwAlways; 1017d522f475Smrg TRACE(("...bold font is double-width, use it %s\n", NonNull(myfonts.f_b))); 1018d522f475Smrg } else { 1019d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1020956cc18dSsnj warn[fWBold] = fwAlways; 1021d522f475Smrg TRACE(("...cannot load wide bold font, use wide %s\n", NonNull(myfonts.f_w))); 1022d522f475Smrg } 1023d522f475Smrg 1024d522f475Smrg if (EmptyFont(fnts[fWBold].fs)) 1025d522f475Smrg goto bad; /* can't use a 0-sized font */ 1026d522f475Smrg }); 1027d522f475Smrg 1028d522f475Smrg /* 1029d522f475Smrg * Most of the time this call to load the font will succeed, even if 1030d522f475Smrg * there is no wide font : the X server doubles the width of the 1031d522f475Smrg * normal font, or similar. 1032d522f475Smrg * 1033d522f475Smrg * But if it did fail for some reason, then nevermind. 1034d522f475Smrg */ 1035d522f475Smrg if (EmptyFont(fnts[fBold].fs)) 1036d522f475Smrg goto bad; /* can't use a 0-sized font */ 1037d522f475Smrg 1038d522f475Smrg if (!same_font_size(xw, fnts[fNorm].fs, fnts[fBold].fs) 1039d522f475Smrg && (is_fixed_font(fnts[fNorm].fs) && is_fixed_font(fnts[fBold].fs))) { 1040d522f475Smrg TRACE(("...ignoring mismatched normal/bold fonts\n")); 1041d522f475Smrg xtermCloseFont(xw, &fnts[fBold]); 1042d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 1043d522f475Smrg } 1044d522f475Smrg 1045d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1046d522f475Smrg if (fnts[fWide].fs != 0 1047d522f475Smrg && fnts[fWBold].fs != 0 1048d522f475Smrg && !same_font_size(xw, fnts[fWide].fs, fnts[fWBold].fs) 1049d522f475Smrg && (is_fixed_font(fnts[fWide].fs) && is_fixed_font(fnts[fWBold].fs))) { 1050d522f475Smrg TRACE(("...ignoring mismatched normal/bold wide fonts\n")); 1051d522f475Smrg xtermCloseFont(xw, &fnts[fWBold]); 1052d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1053d522f475Smrg } 1054d522f475Smrg }); 1055d522f475Smrg 1056d522f475Smrg /* 1057d522f475Smrg * Normal/bold fonts should be the same width. Also, the min/max 1058d522f475Smrg * values should be the same. 1059d522f475Smrg */ 1060d522f475Smrg if (!is_fixed_font(fnts[fNorm].fs) 1061d522f475Smrg || !is_fixed_font(fnts[fBold].fs) 1062d522f475Smrg || fnts[fNorm].fs->max_bounds.width != fnts[fBold].fs->max_bounds.width) { 1063d522f475Smrg TRACE(("Proportional font! normal %d/%d, bold %d/%d\n", 1064d522f475Smrg fnts[fNorm].fs->min_bounds.width, 1065d522f475Smrg fnts[fNorm].fs->max_bounds.width, 1066d522f475Smrg fnts[fBold].fs->min_bounds.width, 1067d522f475Smrg fnts[fBold].fs->max_bounds.width)); 1068d522f475Smrg proportional = True; 1069d522f475Smrg } 1070d522f475Smrg 1071d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1072d522f475Smrg if (fnts[fWide].fs != 0 1073d522f475Smrg && fnts[fWBold].fs != 0 1074d522f475Smrg && (!is_fixed_font(fnts[fWide].fs) 1075d522f475Smrg || !is_fixed_font(fnts[fWBold].fs) 1076d522f475Smrg || fnts[fWide].fs->max_bounds.width != fnts[fWBold].fs->max_bounds.width)) { 1077d522f475Smrg TRACE(("Proportional font! wide %d/%d, wide bold %d/%d\n", 1078d522f475Smrg fnts[fWide].fs->min_bounds.width, 1079d522f475Smrg fnts[fWide].fs->max_bounds.width, 1080d522f475Smrg fnts[fWBold].fs->min_bounds.width, 1081d522f475Smrg fnts[fWBold].fs->max_bounds.width)); 1082d522f475Smrg proportional = True; 1083d522f475Smrg } 1084d522f475Smrg }); 1085d522f475Smrg 1086d522f475Smrg /* TODO : enforce that the width of the wide font is 2* the width 1087d522f475Smrg of the narrow font */ 1088d522f475Smrg 1089d522f475Smrg /* 1090d522f475Smrg * If we're switching fonts, free the old ones. Otherwise we'll leak 1091d522f475Smrg * the memory that is associated with the old fonts. The 1092d522f475Smrg * XLoadQueryFont call allocates a new XFontStruct. 1093d522f475Smrg */ 1094d522f475Smrg xtermCloseFonts(xw, screen->fnts); 1095d522f475Smrg 1096d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fNorm]), &fnts[fNorm]); 1097d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fBold]), &fnts[fBold]); 1098d522f475Smrg#if OPT_WIDE_CHARS 1099d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fWide]), &fnts[fWide]); 1100d522f475Smrg if (fnts[fWBold].fs == NULL) 1101d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1102d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fWBold]), &fnts[fWBold]); 1103d522f475Smrg#endif 1104d522f475Smrg 1105d522f475Smrg new_normal = getXtermForeground(xw, xw->flags, xw->cur_foreground); 1106d522f475Smrg new_revers = getXtermBackground(xw, xw->flags, xw->cur_background); 1107d522f475Smrg 1108d522f475Smrg setCgsFore(xw, win, gcNorm, new_normal); 1109d522f475Smrg setCgsBack(xw, win, gcNorm, new_revers); 1110d522f475Smrg setCgsFont(xw, win, gcNorm, &(screen->fnts[fNorm])); 1111d522f475Smrg 1112d522f475Smrg copyCgs(xw, win, gcBold, gcNorm); 1113d522f475Smrg setCgsFont(xw, win, gcBold, &(screen->fnts[fBold])); 1114d522f475Smrg 1115d522f475Smrg setCgsFore(xw, win, gcNormReverse, new_revers); 1116d522f475Smrg setCgsBack(xw, win, gcNormReverse, new_normal); 1117d522f475Smrg setCgsFont(xw, win, gcNormReverse, &(screen->fnts[fNorm])); 1118d522f475Smrg 1119d522f475Smrg copyCgs(xw, win, gcBoldReverse, gcNormReverse); 1120d522f475Smrg setCgsFont(xw, win, gcBoldReverse, &(screen->fnts[fBold])); 1121d522f475Smrg 1122d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1123d522f475Smrg if (screen->fnts[fWide].fs != 0 1124d522f475Smrg && screen->fnts[fWBold].fs != 0) { 1125d522f475Smrg setCgsFore(xw, win, gcWide, new_normal); 1126d522f475Smrg setCgsBack(xw, win, gcWide, new_revers); 1127d522f475Smrg setCgsFont(xw, win, gcWide, &(screen->fnts[fWide])); 1128d522f475Smrg 1129d522f475Smrg copyCgs(xw, win, gcWBold, gcWide); 1130d522f475Smrg setCgsFont(xw, win, gcWBold, &(screen->fnts[fWBold])); 1131d522f475Smrg 1132d522f475Smrg setCgsFore(xw, win, gcWideReverse, new_revers); 1133d522f475Smrg setCgsBack(xw, win, gcWideReverse, new_normal); 1134d522f475Smrg setCgsFont(xw, win, gcWideReverse, &(screen->fnts[fWide])); 1135d522f475Smrg 1136d522f475Smrg copyCgs(xw, win, gcWBoldReverse, gcWideReverse); 1137d522f475Smrg setCgsFont(xw, win, gcWBoldReverse, &(screen->fnts[fWBold])); 1138d522f475Smrg } 1139d522f475Smrg }); 1140d522f475Smrg 114120d2c4d2Smrg#if OPT_BOX_CHARS 114220d2c4d2Smrg screen->allow_packing = proportional; 114320d2c4d2Smrg setupPackedFonts(xw); 114420d2c4d2Smrg#endif 114520d2c4d2Smrg screen->fnt_prop = (Boolean) (proportional && !(screen->force_packed)); 1146d522f475Smrg screen->fnt_boxes = True; 1147d522f475Smrg 1148d522f475Smrg#if OPT_BOX_CHARS 1149d522f475Smrg /* 1150d522f475Smrg * Xterm uses character positions 1-31 of a font for the line-drawing 1151d522f475Smrg * characters. Check that they are all present. The null character 1152d522f475Smrg * (0) is special, and is not used. 1153d522f475Smrg */ 1154d522f475Smrg#if OPT_RENDERFONT 1155d522f475Smrg if (UsingRenderFont(xw)) { 1156d522f475Smrg /* 1157d522f475Smrg * FIXME: we shouldn't even be here if we're using Xft. 1158d522f475Smrg */ 1159d522f475Smrg screen->fnt_boxes = False; 1160d522f475Smrg TRACE(("assume Xft missing line-drawing chars\n")); 1161d522f475Smrg } else 1162d522f475Smrg#endif 1163d522f475Smrg { 1164d522f475Smrg unsigned ch; 1165d522f475Smrg 1166d522f475Smrg for (ch = 1; ch < 32; ch++) { 1167d522f475Smrg unsigned n = ch; 1168d522f475Smrg#if OPT_WIDE_CHARS 1169d522f475Smrg if (screen->utf8_mode || screen->unicode_font) { 1170d522f475Smrg n = dec2ucs(ch); 1171d522f475Smrg if (n == UCS_REPL) 1172d522f475Smrg continue; 1173d522f475Smrg } 1174d522f475Smrg#endif 1175956cc18dSsnj if (IsXtermMissingChar(screen, n, &fnts[fNorm])) { 1176d522f475Smrg TRACE(("missing normal char #%d\n", n)); 1177d522f475Smrg screen->fnt_boxes = False; 1178d522f475Smrg break; 1179d522f475Smrg } 1180956cc18dSsnj if (IsXtermMissingChar(screen, n, &fnts[fBold])) { 1181d522f475Smrg TRACE(("missing bold char #%d\n", n)); 1182d522f475Smrg screen->fnt_boxes = False; 1183d522f475Smrg break; 1184d522f475Smrg } 1185d522f475Smrg } 1186d522f475Smrg } 1187d522f475Smrg TRACE(("Will %suse internal line-drawing characters\n", 1188d522f475Smrg screen->fnt_boxes ? "not " : "")); 1189d522f475Smrg#endif 1190d522f475Smrg 1191d522f475Smrg if (screen->always_bold_mode) { 1192d522f475Smrg screen->enbolden = screen->bold_mode; 1193d522f475Smrg } else { 1194d522f475Smrg screen->enbolden = screen->bold_mode 1195d522f475Smrg && ((fnts[fNorm].fs == fnts[fBold].fs) 1196d522f475Smrg || same_font_name(normal, myfonts.f_b)); 1197d522f475Smrg } 1198d522f475Smrg TRACE(("Will %suse 1-pixel offset/overstrike to simulate bold\n", 1199d522f475Smrg screen->enbolden ? "" : "not ")); 1200d522f475Smrg 1201d522f475Smrg set_menu_font(False); 1202d522f475Smrg screen->menu_font_number = fontnum; 1203d522f475Smrg set_menu_font(True); 1204d522f475Smrg if (tmpname) { /* if setting escape or sel */ 1205d522f475Smrg if (screen->MenuFontName(fontnum)) 120620d2c4d2Smrg free((void *) screen->MenuFontName(fontnum)); 1207d522f475Smrg screen->MenuFontName(fontnum) = tmpname; 1208d522f475Smrg if (fontnum == fontMenu_fontescape) { 1209d522f475Smrg SetItemSensitivity(fontMenuEntries[fontMenu_fontescape].widget, 1210d522f475Smrg True); 1211d522f475Smrg } 1212d522f475Smrg#if OPT_SHIFT_FONTS 1213d522f475Smrg screen->menu_font_sizes[fontnum] = FontSize(fnts[fNorm].fs); 1214d522f475Smrg#endif 1215d522f475Smrg } 1216d522f475Smrg set_cursor_gcs(xw); 1217d522f475Smrg xtermUpdateFontInfo(xw, doresize); 1218d522f475Smrg TRACE(("Success Cgs - xtermLoadFont\n")); 1219d522f475Smrg return 1; 1220d522f475Smrg 1221d522f475Smrg bad: 1222d522f475Smrg if (tmpname) 1223d522f475Smrg free(tmpname); 1224d522f475Smrg releaseWindowGCs(xw, win); 1225d522f475Smrg 1226d522f475Smrg xtermCloseFonts(xw, fnts); 1227d522f475Smrg TRACE(("Fail Cgs - xtermLoadFont\n")); 1228d522f475Smrg return 0; 1229d522f475Smrg} 1230d522f475Smrg 1231d522f475Smrg#if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS 1232d522f475Smrg/* 1233d522f475Smrg * Collect font-names that we can modify with the load-vt-fonts() action. 1234d522f475Smrg */ 1235d522f475Smrgtypedef struct { 1236d522f475Smrg VTFontNames default_font; 1237d522f475Smrg char *menu_font_names[fontMenu_lastBuiltin + 1][fMAX]; 1238d522f475Smrg} SubResourceRec; 1239d522f475Smrg 1240d522f475Smrg#define MERGE_SUBFONT(src,dst,name) \ 1241d522f475Smrg if (dst.name == 0) { \ 1242d522f475Smrg TRACE(("MERGE_SUBFONT " #dst "." #name " merge %s\n", NonNull(src.name))); \ 1243d522f475Smrg dst.name = src.name; \ 1244d522f475Smrg } else { \ 1245d522f475Smrg TRACE(("MERGE_SUBFONT " #dst "." #name " found %s\n", NonNull(dst.name))); \ 1246d522f475Smrg } 1247d522f475Smrg 1248d522f475Smrg#define COPY_MENU_FONTS(src,dst) \ 1249d522f475Smrg TRACE(("COPY_MENU_FONTS " #src " to " #dst "\n")); \ 1250d522f475Smrg for (n = fontMenu_default; n <= fontMenu_lastBuiltin; ++n) { \ 1251d522f475Smrg for (m = 0; m < fMAX; ++m) { \ 1252d522f475Smrg dst.menu_font_names[n][m] = src.menu_font_names[n][m]; \ 1253d522f475Smrg } \ 1254d522f475Smrg } 1255d522f475Smrg 1256d522f475Smrg/* 1257d522f475Smrg * Load the "VT" font names from the given subresource name/class. These 1258d522f475Smrg * correspond to the VT100 resources. 1259d522f475Smrg */ 1260d522f475Smrgstatic Bool 126120d2c4d2SmrgxtermLoadVTFonts(XtermWidget xw, String myName, String myClass) 1262d522f475Smrg{ 1263d522f475Smrg static Bool initialized = False; 1264d522f475Smrg static SubResourceRec original, referenceRec, subresourceRec; 1265d522f475Smrg 1266d522f475Smrg /* 1267d522f475Smrg * These are duplicates of the VT100 font resources, but with a special 1268d522f475Smrg * application/classname passed in to distinguish them. 1269d522f475Smrg */ 1270d522f475Smrg static XtResource font_resources[] = 1271d522f475Smrg { 1272d522f475Smrg Sres(XtNfont, XtCFont, default_font.f_n, DEFFONT), 1273d522f475Smrg Sres(XtNboldFont, XtCBoldFont, default_font.f_b, DEFBOLDFONT), 1274d522f475Smrg#if OPT_WIDE_CHARS 1275d522f475Smrg Sres(XtNwideFont, XtCWideFont, default_font.f_w, DEFWIDEFONT), 1276d522f475Smrg Sres(XtNwideBoldFont, XtCWideBoldFont, default_font.f_wb, DEFWIDEBOLDFONT), 1277d522f475Smrg#endif 1278d522f475Smrg Sres(XtNfont1, XtCFont1, MenuFontName(fontMenu_font1), NULL), 1279d522f475Smrg Sres(XtNfont2, XtCFont2, MenuFontName(fontMenu_font2), NULL), 1280d522f475Smrg Sres(XtNfont3, XtCFont3, MenuFontName(fontMenu_font3), NULL), 1281d522f475Smrg Sres(XtNfont4, XtCFont4, MenuFontName(fontMenu_font4), NULL), 1282d522f475Smrg Sres(XtNfont5, XtCFont5, MenuFontName(fontMenu_font5), NULL), 1283d522f475Smrg Sres(XtNfont6, XtCFont6, MenuFontName(fontMenu_font6), NULL), 1284d522f475Smrg }; 1285d522f475Smrg Cardinal n, m; 1286d522f475Smrg Bool status = True; 1287956cc18dSsnj TScreen *screen = TScreenOf(xw); 1288d522f475Smrg 1289d522f475Smrg if (!initialized) { 1290d522f475Smrg 1291d522f475Smrg initialized = True; 1292d522f475Smrg TRACE(("xtermLoadVTFonts saving original\n")); 1293956cc18dSsnj original.default_font = xw->misc.default_font; 1294956cc18dSsnj COPY_MENU_FONTS(xw->screen, original); 1295d522f475Smrg } 1296d522f475Smrg 1297d522f475Smrg if (myName == 0 || *myName == 0) { 1298d522f475Smrg TRACE(("xtermLoadVTFonts restoring original\n")); 1299956cc18dSsnj xw->misc.default_font = original.default_font; 1300956cc18dSsnj COPY_MENU_FONTS(original, xw->screen); 1301d522f475Smrg for (n = 0; n < XtNumber(original.menu_font_names); ++n) 1302956cc18dSsnj screen->MenuFontName(n) = original.MenuFontName(n); 1303d522f475Smrg } else { 1304d522f475Smrg TRACE(("xtermLoadVTFonts(%s, %s)\n", myName, myClass)); 1305d522f475Smrg 1306d522f475Smrg memset(&subresourceRec, 0, sizeof(subresourceRec)); 1307956cc18dSsnj XtGetSubresources((Widget) xw, (XtPointer) &subresourceRec, 1308d522f475Smrg myName, myClass, 1309d522f475Smrg font_resources, 1310d522f475Smrg (Cardinal) XtNumber(font_resources), 1311d522f475Smrg NULL, (Cardinal) 0); 1312d522f475Smrg 1313d522f475Smrg if (memcmp(&referenceRec, &subresourceRec, sizeof(referenceRec))) { 1314d522f475Smrg 1315d522f475Smrg /* 1316d522f475Smrg * If a particular resource value was not found, use the original. 1317d522f475Smrg */ 1318956cc18dSsnj MERGE_SUBFONT(xw->misc, subresourceRec, default_font.f_n); 1319956cc18dSsnj MERGE_SUBFONT(xw->misc, subresourceRec, default_font.f_b); 1320d522f475Smrg#if OPT_WIDE_CHARS 1321956cc18dSsnj MERGE_SUBFONT(xw->misc, subresourceRec, default_font.f_w); 1322956cc18dSsnj MERGE_SUBFONT(xw->misc, subresourceRec, default_font.f_wb); 1323d522f475Smrg#endif 1324d522f475Smrg for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; ++n) 1325956cc18dSsnj MERGE_SUBFONT(xw->screen, subresourceRec, MenuFontName(n)); 1326d522f475Smrg 1327d522f475Smrg /* 1328d522f475Smrg * Finally, copy the subresource data to the widget. 1329d522f475Smrg */ 1330956cc18dSsnj xw->misc.default_font = subresourceRec.default_font; 1331956cc18dSsnj COPY_MENU_FONTS(subresourceRec, xw->screen); 1332956cc18dSsnj screen->MenuFontName(fontMenu_default) = xw->misc.default_font.f_n; 1333956cc18dSsnj screen->menu_font_names[0][fBold] = xw->misc.default_font.f_b; 1334d522f475Smrg#if OPT_WIDE_CHARS 1335956cc18dSsnj screen->menu_font_names[0][fWide] = xw->misc.default_font.f_w; 1336956cc18dSsnj screen->menu_font_names[0][fWBold] = xw->misc.default_font.f_wb; 1337d522f475Smrg#endif 1338d522f475Smrg } else { 1339d522f475Smrg TRACE(("...no resources found\n")); 1340d522f475Smrg status = False; 1341d522f475Smrg } 1342d522f475Smrg } 1343d522f475Smrg return status; 1344d522f475Smrg} 1345d522f475Smrg 1346d522f475Smrg#if OPT_WIDE_CHARS 1347d522f475Smrgstatic Bool 134820d2c4d2SmrgisWideFont(XFontStruct * fp, const char *tag, Bool nullOk) 1349d522f475Smrg{ 1350d522f475Smrg Bool result = False; 1351d522f475Smrg 1352d522f475Smrg (void) tag; 1353d522f475Smrg if (okFont(fp)) { 1354d522f475Smrg unsigned count = countGlyphs(fp); 1355d522f475Smrg TRACE(("isWideFont(%s) found %d cells\n", tag, count)); 1356d522f475Smrg result = (count > 256) ? True : False; 1357d522f475Smrg } else { 1358d522f475Smrg result = nullOk; 1359d522f475Smrg } 1360d522f475Smrg return result; 1361d522f475Smrg} 1362d522f475Smrg 1363d522f475Smrg/* 1364d522f475Smrg * If the current fonts are not wide, load the UTF8 fonts. 1365d522f475Smrg * 1366d522f475Smrg * Called during initialization (for wide-character mode), the fonts have not 1367d522f475Smrg * been setup, so we pass nullOk=True to isWideFont(). 1368d522f475Smrg * 1369d522f475Smrg * Called after initialization, e.g., in response to the UTF-8 menu entry 1370d522f475Smrg * (starting from narrow character mode), it checks if the fonts are not wide. 1371d522f475Smrg */ 1372d522f475SmrgBool 1373d522f475SmrgxtermLoadWideFonts(XtermWidget xw, Bool nullOk) 1374d522f475Smrg{ 1375956cc18dSsnj TScreen *screen = TScreenOf(xw); 1376d522f475Smrg Bool result; 1377d522f475Smrg 1378d522f475Smrg if (EmptyFont(screen->fnts[fWide].fs)) { 1379d522f475Smrg result = (isWideFont(screen->fnts[fNorm].fs, "normal", nullOk) 1380d522f475Smrg && isWideFont(screen->fnts[fBold].fs, "bold", nullOk)); 1381d522f475Smrg } else { 1382d522f475Smrg result = (isWideFont(screen->fnts[fWide].fs, "wide", nullOk) 1383d522f475Smrg && isWideFont(screen->fnts[fWBold].fs, "wide-bold", nullOk)); 1384d522f475Smrg if (result && !screen->utf8_latin1) { 1385d522f475Smrg result = (isWideFont(screen->fnts[fNorm].fs, "normal", nullOk) 1386d522f475Smrg && isWideFont(screen->fnts[fBold].fs, "bold", nullOk)); 1387d522f475Smrg } 1388d522f475Smrg } 1389d522f475Smrg if (!result) { 1390d522f475Smrg TRACE(("current fonts are not all wide%s\n", nullOk ? " nullOk" : "")); 1391d522f475Smrg result = xtermLoadVTFonts(xw, "utf8Fonts", "Utf8Fonts"); 1392d522f475Smrg } 1393d522f475Smrg TRACE(("xtermLoadWideFonts:%d\n", result)); 1394d522f475Smrg return result; 1395d522f475Smrg} 1396d522f475Smrg#endif /* OPT_WIDE_CHARS */ 1397d522f475Smrg 1398d522f475Smrg/* 1399d522f475Smrg * Restore the default fonts, i.e., if we had switched to wide-fonts. 1400d522f475Smrg */ 1401d522f475SmrgBool 1402956cc18dSsnjxtermLoadDefaultFonts(XtermWidget xw) 1403d522f475Smrg{ 1404d522f475Smrg Bool result; 1405956cc18dSsnj result = xtermLoadVTFonts(xw, NULL, NULL); 1406d522f475Smrg TRACE(("xtermLoadDefaultFonts:%d\n", result)); 1407d522f475Smrg return result; 1408d522f475Smrg} 1409d522f475Smrg#endif /* OPT_LOAD_VTFONTS || OPT_WIDE_CHARS */ 1410d522f475Smrg 1411d522f475Smrg#if OPT_LOAD_VTFONTS 1412d522f475Smrgvoid 1413d522f475SmrgHandleLoadVTFonts(Widget w, 1414d522f475Smrg XEvent * event GCC_UNUSED, 1415d522f475Smrg String * params GCC_UNUSED, 1416d522f475Smrg Cardinal *param_count GCC_UNUSED) 1417d522f475Smrg{ 1418d522f475Smrg static char empty[] = ""; /* appease strict compilers */ 1419d522f475Smrg 1420956cc18dSsnj XtermWidget xw; 1421956cc18dSsnj 1422956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 1423956cc18dSsnj TScreen *screen = TScreenOf(xw); 1424d522f475Smrg char buf[80]; 142520d2c4d2Smrg char *myName = (char *) ((*param_count > 0) ? params[0] : empty); 142620d2c4d2Smrg char *convert = (char *) ((*param_count > 1) ? params[1] : myName); 1427d522f475Smrg char *myClass = (char *) MyStackAlloc(strlen(convert), buf); 1428d522f475Smrg int n; 1429d522f475Smrg 1430d522f475Smrg TRACE(("HandleLoadVTFonts(%d)\n", *param_count)); 1431d522f475Smrg strcpy(myClass, convert); 14322eaa94a1Schristos if (*param_count == 1) 14332eaa94a1Schristos myClass[0] = x_toupper(myClass[0]); 1434d522f475Smrg 1435d522f475Smrg if (xtermLoadVTFonts(xw, myName, myClass)) { 1436d522f475Smrg /* 1437d522f475Smrg * When switching fonts, try to preserve the font-menu selection, since 1438d522f475Smrg * it is less surprising to do that (if the font-switching can be 1439d522f475Smrg * undone) than to switch to "Default". 1440d522f475Smrg */ 1441956cc18dSsnj int font_number = screen->menu_font_number; 1442d522f475Smrg if (font_number > fontMenu_lastBuiltin) 1443d522f475Smrg font_number = fontMenu_lastBuiltin; 1444d522f475Smrg for (n = 0; n < NMENUFONTS; ++n) 1445956cc18dSsnj screen->menu_font_sizes[n] = 0; 1446d522f475Smrg SetVTFont(xw, font_number, True, 1447d522f475Smrg ((font_number == fontMenu_default) 1448d522f475Smrg ? &(xw->misc.default_font) 1449d522f475Smrg : NULL)); 1450d522f475Smrg } 1451d522f475Smrg 1452d522f475Smrg MyStackFree(myClass, buf); 1453d522f475Smrg } 1454d522f475Smrg} 1455d522f475Smrg#endif /* OPT_LOAD_VTFONTS */ 1456d522f475Smrg 1457d522f475Smrg/* 1458d522f475Smrg * Set the limits for the box that outlines the cursor. 1459d522f475Smrg */ 1460d522f475Smrgvoid 1461d522f475SmrgxtermSetCursorBox(TScreen * screen) 1462d522f475Smrg{ 1463d522f475Smrg static XPoint VTbox[NBOX]; 1464d522f475Smrg XPoint *vp; 14652eaa94a1Schristos int fw = FontWidth(screen) - 1; 14662eaa94a1Schristos int fh = FontHeight(screen) - 1; 14672eaa94a1Schristos int hh = screen->cursor_underline ? 1 : fh; 1468d522f475Smrg 1469d522f475Smrg vp = &VTbox[1]; 14702eaa94a1Schristos (vp++)->x = (short) fw; 14712eaa94a1Schristos (vp++)->y = (short) hh; 14722eaa94a1Schristos (vp++)->x = (short) -fw; 14732eaa94a1Schristos vp->y = (short) -hh; 14742eaa94a1Schristos 1475d522f475Smrg screen->box = VTbox; 1476d522f475Smrg} 1477d522f475Smrg 1478d522f475Smrg#define CACHE_XFT(dst,src) if (src != 0) {\ 1479956cc18dSsnj checkXft(xw, &(dst[fontnum]), src);\ 1480956cc18dSsnj TRACE(("Xft metrics %s[%d] = %d (%d,%d) advance %d, actual %d%s\n",\ 1481d522f475Smrg #dst,\ 1482d522f475Smrg fontnum,\ 1483d522f475Smrg src->height,\ 1484d522f475Smrg src->ascent,\ 1485d522f475Smrg src->descent,\ 1486956cc18dSsnj src->max_advance_width,\ 1487956cc18dSsnj dst[fontnum].map.min_width,\ 1488956cc18dSsnj dst[fontnum].map.mixed ? " mixed" : ""));\ 1489d522f475Smrg } 1490d522f475Smrg 1491d522f475Smrg#if OPT_RENDERFONT 1492956cc18dSsnj 149320d2c4d2Smrg#if OPT_TRACE > 1 149420d2c4d2Smrgstatic FcChar32 149520d2c4d2SmrgxtermXftFirstChar(XftFont * xft) 149620d2c4d2Smrg{ 149720d2c4d2Smrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 149820d2c4d2Smrg FcChar32 next; 149920d2c4d2Smrg FcChar32 first; 150020d2c4d2Smrg int i; 150120d2c4d2Smrg 150220d2c4d2Smrg first = FcCharSetFirstPage(xft->charset, map, &next); 150320d2c4d2Smrg for (i = 0; i < FC_CHARSET_MAP_SIZE; i++) 150420d2c4d2Smrg if (map[i]) { 150520d2c4d2Smrg FcChar32 bits = map[i]; 150620d2c4d2Smrg first += i * 32; 150720d2c4d2Smrg while (!(bits & 0x1)) { 150820d2c4d2Smrg bits >>= 1; 150920d2c4d2Smrg first++; 151020d2c4d2Smrg } 151120d2c4d2Smrg break; 151220d2c4d2Smrg } 151320d2c4d2Smrg return first; 151420d2c4d2Smrg} 151520d2c4d2Smrg 151620d2c4d2Smrgstatic FcChar32 151720d2c4d2SmrgxtermXftLastChar(XftFont * xft) 151820d2c4d2Smrg{ 151920d2c4d2Smrg FcChar32 this, last, next; 152020d2c4d2Smrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 152120d2c4d2Smrg int i; 152220d2c4d2Smrg last = FcCharSetFirstPage(xft->charset, map, &next); 152320d2c4d2Smrg while ((this = FcCharSetNextPage(xft->charset, map, &next)) != FC_CHARSET_DONE) 152420d2c4d2Smrg last = this; 152520d2c4d2Smrg last &= ~0xff; 152620d2c4d2Smrg for (i = FC_CHARSET_MAP_SIZE - 1; i >= 0; i--) 152720d2c4d2Smrg if (map[i]) { 152820d2c4d2Smrg FcChar32 bits = map[i]; 152920d2c4d2Smrg last += i * 32 + 31; 153020d2c4d2Smrg while (!(bits & 0x80000000)) { 153120d2c4d2Smrg last--; 153220d2c4d2Smrg bits <<= 1; 153320d2c4d2Smrg } 153420d2c4d2Smrg break; 153520d2c4d2Smrg } 153620d2c4d2Smrg return (long) last; 153720d2c4d2Smrg} 153820d2c4d2Smrg 153920d2c4d2Smrgstatic void 154020d2c4d2SmrgdumpXft(XtermWidget xw, XTermXftFonts * data) 154120d2c4d2Smrg{ 154220d2c4d2Smrg XftFont *xft = data->font; 154320d2c4d2Smrg TScreen *screen = TScreenOf(xw); 154420d2c4d2Smrg VTwin *win = WhichVWin(screen); 154520d2c4d2Smrg 154620d2c4d2Smrg FcChar32 c; 154720d2c4d2Smrg FcChar32 first = xtermXftFirstChar(xft); 154820d2c4d2Smrg FcChar32 last = xtermXftLastChar(xft); 154920d2c4d2Smrg unsigned count = 0; 155020d2c4d2Smrg unsigned outside = 0; 155120d2c4d2Smrg 155220d2c4d2Smrg TRACE(("dumpXft {{\n")); 155320d2c4d2Smrg TRACE((" data range %#6x..%#6x\n", first, last)); 155420d2c4d2Smrg for (c = first; c <= last; ++c) { 155520d2c4d2Smrg if (FcCharSetHasChar(xft->charset, c)) { 155620d2c4d2Smrg int width = my_wcwidth((int) c); 155720d2c4d2Smrg XGlyphInfo extents; 155820d2c4d2Smrg 155920d2c4d2Smrg XftTextExtents32(XtDisplay(xw), xft, &c, 1, &extents); 156020d2c4d2Smrg TRACE(("%#6x %2d %.1f\n", c, width, 156120d2c4d2Smrg ((double) extents.width) / win->f_width)); 156220d2c4d2Smrg if (extents.width > win->f_width) 156320d2c4d2Smrg ++outside; 156420d2c4d2Smrg ++count; 156520d2c4d2Smrg } 156620d2c4d2Smrg } 156720d2c4d2Smrg TRACE(("}} %u total, %u outside\n", count, outside)); 156820d2c4d2Smrg} 156920d2c4d2Smrg#define DUMP_XFT(xw, data) dumpXft(xw, data) 157020d2c4d2Smrg#else 157120d2c4d2Smrg#define DUMP_XFT(xw, data) /* nothing */ 157220d2c4d2Smrg#endif 157320d2c4d2Smrg 1574956cc18dSsnjstatic void 1575956cc18dSsnjcheckXft(XtermWidget xw, XTermXftFonts * data, XftFont * xft) 1576956cc18dSsnj{ 1577956cc18dSsnj FcChar32 c; 1578956cc18dSsnj Dimension width = 0; 1579956cc18dSsnj 1580956cc18dSsnj data->font = xft; 1581956cc18dSsnj data->map.min_width = 0; 1582956cc18dSsnj data->map.max_width = (Dimension) xft->max_advance_width; 1583956cc18dSsnj 158420d2c4d2Smrg /* 158520d2c4d2Smrg * For each ASCII or ISO-8859-1 printable code, ask what its width is. 158620d2c4d2Smrg * Given the maximum width for those, we have a reasonable estimate of 158720d2c4d2Smrg * the single-column width. 158820d2c4d2Smrg * 158920d2c4d2Smrg * Ignore control characters - their extent information is misleading. 159020d2c4d2Smrg */ 1591956cc18dSsnj for (c = 32; c < 256; ++c) { 159220d2c4d2Smrg if (c >= 127 && c <= 159) 159320d2c4d2Smrg continue; 1594956cc18dSsnj if (FcCharSetHasChar(xft->charset, c)) { 1595956cc18dSsnj XGlyphInfo extents; 1596956cc18dSsnj 1597956cc18dSsnj XftTextExtents32(XtDisplay(xw), xft, &c, 1, &extents); 159820d2c4d2Smrg if (width < extents.width && extents.width <= data->map.max_width) { 1599956cc18dSsnj width = extents.width; 160020d2c4d2Smrg } 1601956cc18dSsnj } 1602956cc18dSsnj } 1603956cc18dSsnj data->map.min_width = width; 1604956cc18dSsnj data->map.mixed = (data->map.max_width >= (data->map.min_width + 1)); 1605956cc18dSsnj} 1606956cc18dSsnj 1607d522f475Smrgstatic XftFont * 1608956cc18dSsnjxtermOpenXft(XtermWidget xw, const char *name, XftPattern * pat, const char *tag) 1609d522f475Smrg{ 1610956cc18dSsnj TScreen *screen = TScreenOf(xw); 1611956cc18dSsnj Display *dpy = screen->display; 1612d522f475Smrg XftPattern *match; 1613d522f475Smrg XftResult status; 1614d522f475Smrg XftFont *result = 0; 1615d522f475Smrg 1616d522f475Smrg if (pat != 0) { 1617d522f475Smrg match = XftFontMatch(dpy, DefaultScreen(dpy), pat, &status); 1618d522f475Smrg if (match != 0) { 1619d522f475Smrg result = XftFontOpenPattern(dpy, match); 1620d522f475Smrg if (result != 0) { 1621d522f475Smrg TRACE(("...matched %s font\n", tag)); 1622d522f475Smrg } else { 1623d522f475Smrg TRACE(("...could did not open %s font\n", tag)); 1624d522f475Smrg XftPatternDestroy(match); 1625956cc18dSsnj if (xw->misc.fontWarnings >= fwAlways) { 1626956cc18dSsnj TRACE(("OOPS cannot open %s font \"%s\"\n", tag, name)); 1627956cc18dSsnj fprintf(stderr, "%s: cannot open %s font \"%s\"\n", 1628956cc18dSsnj ProgramName, tag, name); 1629956cc18dSsnj } 1630d522f475Smrg } 1631d522f475Smrg } else { 1632d522f475Smrg TRACE(("...did not match %s font\n", tag)); 1633956cc18dSsnj if (xw->misc.fontWarnings >= fwResource) { 1634956cc18dSsnj TRACE(("OOPS: cannot match %s font \"%s\"\n", tag, name)); 1635956cc18dSsnj fprintf(stderr, "%s: cannot match %s font \"%s\"\n", 1636956cc18dSsnj ProgramName, tag, name); 1637956cc18dSsnj } 1638d522f475Smrg } 1639d522f475Smrg } 1640d522f475Smrg return result; 1641d522f475Smrg} 1642d522f475Smrg#endif 1643d522f475Smrg 1644d522f475Smrg#if OPT_RENDERFONT 1645d522f475Smrg#if OPT_SHIFT_FONTS 1646d522f475Smrg/* 1647d522f475Smrg * Don't make a dependency on the math library for a single function. 1648d522f475Smrg * (Newton Raphson). 1649d522f475Smrg */ 1650d522f475Smrgstatic double 1651d522f475SmrgmySquareRoot(double value) 1652d522f475Smrg{ 1653d522f475Smrg double result = 0.0; 1654d522f475Smrg if (value > 0.0) { 1655d522f475Smrg int n; 1656d522f475Smrg double older = value; 1657d522f475Smrg for (n = 0; n < 10; ++n) { 1658d522f475Smrg double delta = (older * older - value) / (2.0 * older); 1659d522f475Smrg double newer = older - delta; 1660d522f475Smrg older = newer; 1661d522f475Smrg result = newer; 1662d522f475Smrg if (delta > -0.001 && delta < 0.001) 1663d522f475Smrg break; 1664d522f475Smrg } 1665d522f475Smrg } 1666d522f475Smrg return result; 1667d522f475Smrg} 1668d522f475Smrg#endif 1669d522f475Smrg 1670d522f475Smrg/* 1671d522f475Smrg * Given the Xft font metrics, determine the actual font size. This is used 1672d522f475Smrg * for each font to ensure that normal, bold and italic fonts follow the same 1673d522f475Smrg * rule. 1674d522f475Smrg */ 1675d522f475Smrgstatic void 1676d522f475SmrgsetRenderFontsize(TScreen * screen, VTwin * win, XftFont * font, const char *tag) 1677d522f475Smrg{ 1678d522f475Smrg if (font != 0) { 1679d522f475Smrg int width, height, ascent, descent; 1680d522f475Smrg 1681d522f475Smrg (void) screen; 1682d522f475Smrg 1683d522f475Smrg width = font->max_advance_width; 1684d522f475Smrg height = font->height; 1685d522f475Smrg ascent = font->ascent; 1686d522f475Smrg descent = font->descent; 1687d522f475Smrg if (height < ascent + descent) { 1688d522f475Smrg TRACE(("...increase height from %d\n", height)); 1689d522f475Smrg height = ascent + descent; 1690d522f475Smrg } 1691d522f475Smrg if (is_double_width_font_xft(screen->display, font)) { 1692d522f475Smrg TRACE(("...reduced width from %d\n", width)); 1693d522f475Smrg width >>= 1; 1694d522f475Smrg } 1695d522f475Smrg if (tag == 0) { 1696d522f475Smrg win->f_width = width; 1697d522f475Smrg win->f_height = height; 1698d522f475Smrg win->f_ascent = ascent; 1699d522f475Smrg win->f_descent = descent; 1700d522f475Smrg TRACE(("setRenderFontsize result %dx%d (%d+%d)\n", 1701d522f475Smrg width, height, ascent, descent)); 1702d522f475Smrg } else if (win->f_width < width || 1703d522f475Smrg win->f_height < height || 1704d522f475Smrg win->f_ascent < ascent || 1705d522f475Smrg win->f_descent < descent) { 1706d522f475Smrg TRACE(("setRenderFontsize %s changed %dx%d (%d+%d) to %dx%d (%d+%d)\n", 1707d522f475Smrg tag, 1708d522f475Smrg win->f_width, win->f_height, win->f_ascent, win->f_descent, 1709d522f475Smrg width, height, ascent, descent)); 1710d522f475Smrg 1711d522f475Smrg win->f_width = width; 1712d522f475Smrg win->f_height = height; 1713d522f475Smrg win->f_ascent = ascent; 1714d522f475Smrg win->f_descent = descent; 1715d522f475Smrg } else { 1716d522f475Smrg TRACE(("setRenderFontsize %s unchanged\n", tag)); 1717d522f475Smrg } 1718d522f475Smrg } 1719d522f475Smrg} 1720d522f475Smrg#endif 1721d522f475Smrg 172220d2c4d2Smrgstatic void 172320d2c4d2SmrgcheckFontInfo(int value, const char *tag) 172420d2c4d2Smrg{ 172520d2c4d2Smrg if (value == 0) { 172620d2c4d2Smrg fprintf(stderr, 172720d2c4d2Smrg "Selected font has no non-zero %s for ISO-8859-1 encoding\n", tag); 172820d2c4d2Smrg exit(1); 172920d2c4d2Smrg } 173020d2c4d2Smrg} 173120d2c4d2Smrg 173220d2c4d2Smrg#if OPT_RENDERFONT 173320d2c4d2Smrgvoid 173420d2c4d2SmrgxtermCloseXft(TScreen * screen, XTermXftFonts * pub) 173520d2c4d2Smrg{ 173620d2c4d2Smrg if (pub->font != 0) { 173720d2c4d2Smrg XftFontClose(screen->display, pub->font); 173820d2c4d2Smrg pub->font = 0; 173920d2c4d2Smrg } 174020d2c4d2Smrg} 174120d2c4d2Smrg 174220d2c4d2Smrg/* 174320d2c4d2Smrg * Get the faceName/faceDoublesize resource setting. Strip off "xft:", which 174420d2c4d2Smrg * is not recognized by XftParseName(). 174520d2c4d2Smrg */ 174620d2c4d2Smrgchar * 174720d2c4d2SmrggetFaceName(XtermWidget xw, Bool wideName GCC_UNUSED) 174820d2c4d2Smrg{ 174920d2c4d2Smrg#if OPT_RENDERWIDE 175020d2c4d2Smrg char *result = (wideName 175120d2c4d2Smrg ? xw->misc.face_wide_name 175220d2c4d2Smrg : xw->misc.face_name); 175320d2c4d2Smrg#else 175420d2c4d2Smrg char *result = xw->misc.face_name; 175520d2c4d2Smrg#endif 175620d2c4d2Smrg if (!IsEmpty(result) && !strncmp(result, "xft:", (size_t) 4)) 175720d2c4d2Smrg result += 4; 175820d2c4d2Smrg return x_nonempty(result); 175920d2c4d2Smrg} 176020d2c4d2Smrg 176120d2c4d2Smrg/* 176220d2c4d2Smrg * If we change the faceName, we'll have to re-acquire all of the fonts that 176320d2c4d2Smrg * are derived from it. 176420d2c4d2Smrg */ 176520d2c4d2Smrgvoid 176620d2c4d2SmrgsetFaceName(XtermWidget xw, const char *value) 176720d2c4d2Smrg{ 176820d2c4d2Smrg TScreen *screen = TScreenOf(xw); 176920d2c4d2Smrg int n; 177020d2c4d2Smrg 177120d2c4d2Smrg xw->misc.face_name = x_strdup(value); 177220d2c4d2Smrg for (n = 0; n < NMENUFONTS; ++n) { 177320d2c4d2Smrg xw->misc.face_size[n] = -1.0; 177420d2c4d2Smrg xtermCloseXft(screen, &(screen->renderFontNorm[n])); 177520d2c4d2Smrg xtermCloseXft(screen, &(screen->renderFontBold[n])); 177620d2c4d2Smrg xtermCloseXft(screen, &(screen->renderFontBold[n])); 177720d2c4d2Smrg#if OPT_RENDERWIDE 177820d2c4d2Smrg xtermCloseXft(screen, &(screen->renderWideNorm[n])); 177920d2c4d2Smrg xtermCloseXft(screen, &(screen->renderWideBold[n])); 178020d2c4d2Smrg xtermCloseXft(screen, &(screen->renderWideItal[n])); 178120d2c4d2Smrg#endif 178220d2c4d2Smrg } 178320d2c4d2Smrg} 178420d2c4d2Smrg#endif 178520d2c4d2Smrg 1786d522f475Smrg/* 1787d522f475Smrg * Compute useful values for the font/window sizes 1788d522f475Smrg */ 1789d522f475Smrgvoid 1790d522f475SmrgxtermComputeFontInfo(XtermWidget xw, 1791d522f475Smrg VTwin * win, 1792d522f475Smrg XFontStruct * font, 1793d522f475Smrg int sbwidth) 1794d522f475Smrg{ 1795956cc18dSsnj TScreen *screen = TScreenOf(xw); 1796d522f475Smrg 1797d522f475Smrg int i, j, width, height; 1798d522f475Smrg 1799d522f475Smrg#if OPT_RENDERFONT 1800d522f475Smrg /* 1801d522f475Smrg * xterm contains a lot of references to fonts, assuming they are fixed 1802d522f475Smrg * size. This chunk of code overrides the actual font-selection (see 1803d522f475Smrg * drawXtermText()), if the user has selected render-font. All of the 1804d522f475Smrg * font-loading for fixed-fonts still goes on whether or not this chunk 1805d522f475Smrg * overrides it. 1806d522f475Smrg */ 180720d2c4d2Smrg if (UsingRenderFont(xw)) { 180820d2c4d2Smrg char *face_name = getFaceName(xw, False); 1809d522f475Smrg int fontnum = screen->menu_font_number; 1810956cc18dSsnj XftFont *norm = screen->renderFontNorm[fontnum].font; 1811956cc18dSsnj XftFont *bold = screen->renderFontBold[fontnum].font; 1812956cc18dSsnj XftFont *ital = screen->renderFontItal[fontnum].font; 1813d522f475Smrg#if OPT_RENDERWIDE 1814956cc18dSsnj XftFont *wnorm = screen->renderWideNorm[fontnum].font; 1815956cc18dSsnj XftFont *wbold = screen->renderWideBold[fontnum].font; 1816956cc18dSsnj XftFont *wital = screen->renderWideItal[fontnum].font; 1817d522f475Smrg#endif 1818d522f475Smrg 181920d2c4d2Smrg if (norm == 0 && face_name) { 1820d522f475Smrg XftPattern *pat; 1821d522f475Smrg double face_size = xw->misc.face_size[fontnum]; 1822d522f475Smrg 1823d522f475Smrg TRACE(("xtermComputeFontInfo norm(face %s, size %f)\n", 182420d2c4d2Smrg face_name, 1825d522f475Smrg xw->misc.face_size[fontnum])); 1826d522f475Smrg 1827d522f475Smrg if (face_size <= 0.0) { 1828d522f475Smrg#if OPT_SHIFT_FONTS 1829d522f475Smrg /* 1830d522f475Smrg * If the user is switching font-sizes, make it follow by 1831d522f475Smrg * default the same ratios to the default as the fixed fonts 1832d522f475Smrg * would, for easy comparison. There will be some differences 1833d522f475Smrg * since the fixed fonts have a variety of height/width ratios, 1834d522f475Smrg * but this is simpler than adding another resource value - and 1835d522f475Smrg * as noted above, the data for the fixed fonts are available. 1836d522f475Smrg */ 1837d522f475Smrg lookupOneFontSize(xw, 0); 1838d522f475Smrg lookupOneFontSize(xw, fontnum); 1839d522f475Smrg if (fontnum == fontMenu_default) { 1840d522f475Smrg face_size = 14.0; 1841d522f475Smrg } else { 1842d522f475Smrg double ratio; 184320d2c4d2Smrg long num = screen->menu_font_sizes[fontnum]; 184420d2c4d2Smrg long den = screen->menu_font_sizes[0]; 1845d522f475Smrg 1846d522f475Smrg if (den <= 0) 1847d522f475Smrg den = 1; 184820d2c4d2Smrg ratio = mySquareRoot((double) num / (double) den); 1849d522f475Smrg 1850d522f475Smrg face_size = (ratio * xw->misc.face_size[0]); 185120d2c4d2Smrg TRACE(("scaled using %3ld/%ld = %.2f -> %f\n", 1852d522f475Smrg num, den, ratio, face_size)); 1853d522f475Smrg } 1854d522f475Smrg#else 1855d522f475Smrg switch (fontnum) { 1856d522f475Smrg case fontMenu_font1: 1857d522f475Smrg face_size = 8.0; 1858d522f475Smrg break; 1859d522f475Smrg case fontMenu_font2: 1860d522f475Smrg face_size = 10.0; 1861d522f475Smrg break; 1862d522f475Smrg case fontMenu_font3: 1863d522f475Smrg face_size = 12.0; 1864d522f475Smrg break; 1865d522f475Smrg default: 1866d522f475Smrg face_size = 14.0; 1867d522f475Smrg break; 1868d522f475Smrg case fontMenu_font4: 1869d522f475Smrg face_size = 16.0; 1870d522f475Smrg break; 1871d522f475Smrg case fontMenu_font5: 1872d522f475Smrg face_size = 18.0; 1873d522f475Smrg break; 1874d522f475Smrg case fontMenu_font6: 1875d522f475Smrg face_size = 20.0; 1876d522f475Smrg break; 1877d522f475Smrg } 1878d522f475Smrg#endif 1879956cc18dSsnj xw->misc.face_size[fontnum] = (float) face_size; 1880d522f475Smrg } 1881d522f475Smrg 1882d522f475Smrg /* 1883d522f475Smrg * By observation (there is no documentation), XftPatternBuild is 1884d522f475Smrg * cumulative. Build the bold- and italic-patterns on top of the 1885d522f475Smrg * normal pattern. 1886d522f475Smrg */ 1887d522f475Smrg#define NormXftPattern \ 1888d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 1889d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 1890d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 1891d522f475Smrg 1892d522f475Smrg#define BoldXftPattern(norm) \ 1893d522f475Smrg XFT_WEIGHT, XftTypeInteger, XFT_WEIGHT_BOLD, \ 1894d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 1895d522f475Smrg 1896d522f475Smrg#define ItalXftPattern(norm) \ 1897d522f475Smrg XFT_SLANT, XftTypeInteger, XFT_SLANT_ITALIC, \ 1898d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 1899d522f475Smrg 190020d2c4d2Smrg if ((pat = XftNameParse(face_name)) != 0) { 190120d2c4d2Smrg#define OPEN_XFT(tag) xtermOpenXft(xw, face_name, pat, tag) 1902d522f475Smrg XftPatternBuild(pat, 1903d522f475Smrg NormXftPattern, 1904d522f475Smrg (void *) 0); 1905956cc18dSsnj norm = OPEN_XFT("normal"); 1906d522f475Smrg 1907d522f475Smrg if (norm != 0) { 1908d522f475Smrg XftPatternBuild(pat, 1909d522f475Smrg BoldXftPattern(norm), 1910d522f475Smrg (void *) 0); 1911956cc18dSsnj bold = OPEN_XFT("bold"); 1912d522f475Smrg 1913d522f475Smrg#if OPT_ISO_COLORS 1914d522f475Smrg if (screen->italicULMode 191520d2c4d2Smrg && (pat = XftNameParse(face_name)) != 0) { 1916d522f475Smrg XftPatternBuild(pat, 1917d522f475Smrg NormXftPattern, 1918d522f475Smrg ItalXftPattern(norm), 1919d522f475Smrg (void *) 0); 1920956cc18dSsnj ital = OPEN_XFT("italic"); 1921d522f475Smrg } 1922d522f475Smrg#endif /* OPT_ISO_COLORS */ 1923956cc18dSsnj#undef OPEN_XFT 1924d522f475Smrg 1925d522f475Smrg /* 1926d522f475Smrg * FIXME: just assume that the corresponding font has no 1927d522f475Smrg * graphics characters. 1928d522f475Smrg */ 1929d522f475Smrg if (screen->fnt_boxes) { 1930d522f475Smrg screen->fnt_boxes = False; 1931d522f475Smrg TRACE(("Xft opened - will %suse internal line-drawing characters\n", 1932d522f475Smrg screen->fnt_boxes ? "not " : "")); 1933d522f475Smrg } 1934d522f475Smrg } 1935d522f475Smrg 1936d522f475Smrg XftPatternDestroy(pat); 1937d522f475Smrg } 1938d522f475Smrg 1939d522f475Smrg CACHE_XFT(screen->renderFontNorm, norm); 1940d522f475Smrg CACHE_XFT(screen->renderFontBold, bold); 1941d522f475Smrg CACHE_XFT(screen->renderFontItal, ital); 1942d522f475Smrg 1943d522f475Smrg /* 1944d522f475Smrg * See xtermXftDrawString(). 1945d522f475Smrg */ 1946d522f475Smrg#if OPT_RENDERWIDE 1947d522f475Smrg if (norm != 0 && screen->wide_chars) { 1948d522f475Smrg int char_width = norm->max_advance_width * 2; 1949956cc18dSsnj#ifdef FC_ASPECT 1950956cc18dSsnj double aspect = ((xw->misc.face_wide_name 1951956cc18dSsnj || screen->renderFontNorm[fontnum].map.mixed) 1952956cc18dSsnj ? 1.0 1953956cc18dSsnj : 2.0); 1954956cc18dSsnj#endif 1955d522f475Smrg 195620d2c4d2Smrg face_name = getFaceName(xw, True); 1957d522f475Smrg TRACE(("xtermComputeFontInfo wide(face %s, char_width %d)\n", 195820d2c4d2Smrg NonNull(face_name), 1959d522f475Smrg char_width)); 1960d522f475Smrg 1961d522f475Smrg#define WideXftPattern \ 1962d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 1963d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 1964d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 1965d522f475Smrg 196620d2c4d2Smrg if (face_name && (pat = XftNameParse(face_name)) != 0) { 1967956cc18dSsnj#define OPEN_XFT(tag) xtermOpenXft(xw, face_name, pat, tag) 1968d522f475Smrg XftPatternBuild(pat, 1969d522f475Smrg WideXftPattern, 1970d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, char_width, 1971956cc18dSsnj#ifdef FC_ASPECT 1972956cc18dSsnj FC_ASPECT, XftTypeDouble, aspect, 1973956cc18dSsnj#endif 1974d522f475Smrg (void *) 0); 1975956cc18dSsnj wnorm = OPEN_XFT("wide"); 1976d522f475Smrg 1977d522f475Smrg if (wnorm != 0) { 1978d522f475Smrg XftPatternBuild(pat, 1979d522f475Smrg WideXftPattern, 1980d522f475Smrg BoldXftPattern(wnorm), 1981d522f475Smrg (void *) 0); 1982956cc18dSsnj wbold = OPEN_XFT("wide-bold"); 1983d522f475Smrg 1984d522f475Smrg#if OPT_ISO_COLORS 1985d522f475Smrg if (screen->italicULMode 1986d522f475Smrg && (pat = XftNameParse(face_name)) != 0) { 1987d522f475Smrg XftPatternBuild(pat, 1988d522f475Smrg WideXftPattern, 1989d522f475Smrg ItalXftPattern(wnorm), 1990d522f475Smrg (void *) 0); 1991956cc18dSsnj wital = OPEN_XFT("wide-italic"); 1992d522f475Smrg } 1993d522f475Smrg#endif 1994956cc18dSsnj#undef OPEN_XFT 1995d522f475Smrg } 1996d522f475Smrg XftPatternDestroy(pat); 1997d522f475Smrg } 1998d522f475Smrg 1999d522f475Smrg CACHE_XFT(screen->renderWideNorm, wnorm); 2000d522f475Smrg CACHE_XFT(screen->renderWideBold, wbold); 2001d522f475Smrg CACHE_XFT(screen->renderWideItal, wital); 2002d522f475Smrg } 2003d522f475Smrg#endif /* OPT_RENDERWIDE */ 2004d522f475Smrg } 2005d522f475Smrg if (norm == 0) { 20062eaa94a1Schristos TRACE(("...no TrueType font found for number %d, disable menu entry\n", fontnum)); 2007d522f475Smrg xw->misc.render_font = False; 2008d522f475Smrg update_font_renderfont(); 2009d522f475Smrg /* now we will fall through into the bitmap fonts */ 2010d522f475Smrg } else { 2011d522f475Smrg setRenderFontsize(screen, win, norm, NULL); 2012d522f475Smrg setRenderFontsize(screen, win, bold, "bold"); 2013d522f475Smrg setRenderFontsize(screen, win, ital, "ital"); 201420d2c4d2Smrg#if OPT_BOX_CHARS 201520d2c4d2Smrg setupPackedFonts(xw); 201620d2c4d2Smrg 201720d2c4d2Smrg if (screen->force_packed) { 201820d2c4d2Smrg XTermXftFonts *use = &(screen->renderFontNorm[fontnum]); 201920d2c4d2Smrg win->f_height = use->font->ascent + use->font->descent; 202020d2c4d2Smrg win->f_width = use->map.min_width; 202120d2c4d2Smrg TRACE(("...packed TrueType font %dx%d vs %d\n", 202220d2c4d2Smrg win->f_height, 202320d2c4d2Smrg win->f_width, 202420d2c4d2Smrg use->map.max_width)); 202520d2c4d2Smrg } 202620d2c4d2Smrg#endif 202720d2c4d2Smrg DUMP_XFT(xw, &(screen->renderFontNorm[fontnum])); 2028d522f475Smrg } 2029d522f475Smrg } 2030d522f475Smrg /* 2031d522f475Smrg * Are we handling a bitmap font? 2032d522f475Smrg */ 203320d2c4d2Smrg if (!UsingRenderFont(xw)) 2034d522f475Smrg#endif /* OPT_RENDERFONT */ 2035d522f475Smrg { 203620d2c4d2Smrg if (is_double_width_font(font) && !(screen->fnt_prop)) { 2037d522f475Smrg win->f_width = (font->min_bounds.width); 2038d522f475Smrg } else { 2039d522f475Smrg win->f_width = (font->max_bounds.width); 2040d522f475Smrg } 2041d522f475Smrg win->f_height = (font->ascent + font->descent); 2042d522f475Smrg win->f_ascent = font->ascent; 2043d522f475Smrg win->f_descent = font->descent; 2044d522f475Smrg } 2045d522f475Smrg i = 2 * screen->border + sbwidth; 2046d522f475Smrg j = 2 * screen->border; 2047d522f475Smrg width = MaxCols(screen) * win->f_width + i; 2048d522f475Smrg height = MaxRows(screen) * win->f_height + j; 2049956cc18dSsnj win->fullwidth = (Dimension) width; 2050956cc18dSsnj win->fullheight = (Dimension) height; 2051d522f475Smrg win->width = width - i; 2052d522f475Smrg win->height = height - j; 2053d522f475Smrg 2054d522f475Smrg TRACE(("xtermComputeFontInfo window %dx%d (full %dx%d), fontsize %dx%d (asc %d, dsc %d)\n", 2055d522f475Smrg win->height, 2056d522f475Smrg win->width, 2057d522f475Smrg win->fullheight, 2058d522f475Smrg win->fullwidth, 2059d522f475Smrg win->f_height, 2060d522f475Smrg win->f_width, 2061d522f475Smrg win->f_ascent, 2062d522f475Smrg win->f_descent)); 206320d2c4d2Smrg 206420d2c4d2Smrg checkFontInfo(win->f_height, "height"); 206520d2c4d2Smrg checkFontInfo(win->f_width, "width"); 2066d522f475Smrg} 2067d522f475Smrg 2068d522f475Smrg/* save this information as a side-effect for double-sized characters */ 2069d522f475Smrgvoid 2070d522f475SmrgxtermSaveFontInfo(TScreen * screen, XFontStruct * font) 2071d522f475Smrg{ 2072956cc18dSsnj screen->fnt_wide = (Dimension) (font->max_bounds.width); 2073956cc18dSsnj screen->fnt_high = (Dimension) (font->ascent + font->descent); 2074d522f475Smrg TRACE(("xtermSaveFontInfo %dx%d\n", screen->fnt_high, screen->fnt_wide)); 2075d522f475Smrg} 2076d522f475Smrg 2077d522f475Smrg/* 2078d522f475Smrg * After loading a new font, update the structures that use its size. 2079d522f475Smrg */ 2080d522f475Smrgvoid 2081d522f475SmrgxtermUpdateFontInfo(XtermWidget xw, Bool doresize) 2082d522f475Smrg{ 2083956cc18dSsnj TScreen *screen = TScreenOf(xw); 2084d522f475Smrg 2085d522f475Smrg int scrollbar_width; 2086d522f475Smrg VTwin *win = &(screen->fullVwin); 2087d522f475Smrg 2088d522f475Smrg scrollbar_width = (xw->misc.scrollbar 2089d522f475Smrg ? (screen->scrollWidget->core.width + 2090d522f475Smrg BorderWidth(screen->scrollWidget)) 2091d522f475Smrg : 0); 2092d522f475Smrg xtermComputeFontInfo(xw, win, screen->fnts[fNorm].fs, scrollbar_width); 2093d522f475Smrg xtermSaveFontInfo(screen, screen->fnts[fNorm].fs); 2094d522f475Smrg 2095d522f475Smrg if (doresize) { 2096d522f475Smrg if (VWindow(screen)) { 2097d522f475Smrg xtermClear(xw); 2098d522f475Smrg } 2099d522f475Smrg TRACE(("xtermUpdateFontInfo {{\n")); 2100d522f475Smrg DoResizeScreen(xw); /* set to the new natural size */ 2101d522f475Smrg ResizeScrollBar(xw); 2102d522f475Smrg Redraw(); 2103d522f475Smrg TRACE(("... }} xtermUpdateFontInfo\n")); 2104d522f475Smrg#ifdef SCROLLBAR_RIGHT 2105d522f475Smrg updateRightScrollbar(xw); 2106d522f475Smrg#endif 2107d522f475Smrg } 2108d522f475Smrg xtermSetCursorBox(screen); 2109d522f475Smrg} 2110d522f475Smrg 2111d522f475Smrg#if OPT_BOX_CHARS 2112d522f475Smrg 2113d522f475Smrg/* 2114d522f475Smrg * Returns true if the given character is missing from the specified font. 2115d522f475Smrg */ 2116d522f475SmrgBool 2117956cc18dSsnjxtermMissingChar(unsigned ch, XTermFonts * font) 2118d522f475Smrg{ 2119956cc18dSsnj Bool result = False; 2120956cc18dSsnj XFontStruct *fs = font->fs; 2121956cc18dSsnj static XCharStruct dft, *tmp = &dft, *pc = 0; 2122d522f475Smrg 2123956cc18dSsnj if (fs->max_byte1 == 0) { 2124d522f475Smrg#if OPT_WIDE_CHARS 2125956cc18dSsnj if (ch > 255) { 2126956cc18dSsnj TRACE(("xtermMissingChar %#04x (row)\n", ch)); 2127956cc18dSsnj return True; 2128d522f475Smrg } 2129956cc18dSsnj#endif 2130956cc18dSsnj CI_GET_CHAR_INFO_1D(fs, E2A(ch), tmp, pc); 2131956cc18dSsnj } 2132d522f475Smrg#if OPT_WIDE_CHARS 2133956cc18dSsnj else { 2134956cc18dSsnj CI_GET_CHAR_INFO_2D(fs, HI_BYTE(ch), LO_BYTE(ch), tmp, pc); 2135956cc18dSsnj } 2136d522f475Smrg#else 2137d522f475Smrg 2138956cc18dSsnj if (!pc) 2139956cc18dSsnj return False; /* Urgh! */ 2140d522f475Smrg#endif 2141d522f475Smrg 2142956cc18dSsnj if (CI_NONEXISTCHAR(pc)) { 2143956cc18dSsnj TRACE(("xtermMissingChar %#04x (!exists)\n", ch)); 2144956cc18dSsnj result = True; 2145d522f475Smrg } 2146956cc18dSsnj if (ch < 256) { 2147956cc18dSsnj font->known_missing[ch] = (Char) (result ? 2 : 1); 2148d522f475Smrg } 2149956cc18dSsnj return result; 2150d522f475Smrg} 2151d522f475Smrg 2152d522f475Smrg/* 2153d522f475Smrg * The grid is arbitrary, enough resolution that nothing's lost in 2154d522f475Smrg * initialization. 2155d522f475Smrg */ 2156d522f475Smrg#define BOX_HIGH 60 2157d522f475Smrg#define BOX_WIDE 60 2158d522f475Smrg 2159d522f475Smrg#define MID_HIGH (BOX_HIGH/2) 2160d522f475Smrg#define MID_WIDE (BOX_WIDE/2) 2161d522f475Smrg 2162d522f475Smrg#define CHR_WIDE ((9*BOX_WIDE)/10) 2163d522f475Smrg#define CHR_HIGH ((9*BOX_HIGH)/10) 2164d522f475Smrg 2165d522f475Smrg/* 2166d522f475Smrg * ...since we'll scale the values anyway. 2167d522f475Smrg */ 2168956cc18dSsnj#define SCALE_X(n) n = (n * (((int) font_width) - 1)) / (BOX_WIDE-1) 2169956cc18dSsnj#define SCALE_Y(n) n = (n * (((int) font_height) - 1)) / (BOX_HIGH-1) 2170d522f475Smrg 2171d522f475Smrg#define SEG(x0,y0,x1,y1) x0,y0, x1,y1 2172d522f475Smrg 2173d522f475Smrg/* 2174d522f475Smrg * Draw the given graphic character, if it is simple enough (i.e., a 2175d522f475Smrg * line-drawing character). 2176d522f475Smrg */ 2177d522f475Smrgvoid 2178d522f475SmrgxtermDrawBoxChar(XtermWidget xw, 2179d522f475Smrg unsigned ch, 2180d522f475Smrg unsigned flags, 2181d522f475Smrg GC gc, 2182d522f475Smrg int x, 2183d522f475Smrg int y, 2184d522f475Smrg int cells) 2185d522f475Smrg{ 2186956cc18dSsnj TScreen *screen = TScreenOf(xw); 2187d522f475Smrg /* *INDENT-OFF* */ 2188d522f475Smrg static const short glyph_ht[] = { 2189d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,5*MID_HIGH/6), /* H */ 2190d522f475Smrg SEG(6*BOX_WIDE/10, 0, 6*BOX_WIDE/10,5*MID_HIGH/6), 2191d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*BOX_WIDE/10,5*MID_HIGH/12), 2192d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 2193d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 2194d522f475Smrg -1 2195d522f475Smrg }, glyph_ff[] = { 2196d522f475Smrg SEG(1*BOX_WIDE/10, 0, 6*BOX_WIDE/10, 0), /* F */ 2197d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*CHR_WIDE/12,5*MID_HIGH/12), 2198d522f475Smrg SEG(1*BOX_WIDE/10, 0, 0*BOX_WIDE/3, 5*MID_HIGH/6), 2199d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 2200d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 2201d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 2202d522f475Smrg -1 2203d522f475Smrg }, glyph_lf[] = { 2204d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,9*MID_HIGH/12), /* L */ 2205d522f475Smrg SEG(1*BOX_WIDE/10,9*MID_HIGH/12,6*BOX_WIDE/10,9*MID_HIGH/12), 2206d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 2207d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 2208d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 2209d522f475Smrg -1 2210d522f475Smrg }, glyph_nl[] = { 2211d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/6, 1*BOX_WIDE/10, 0), /* N */ 2212d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/6, 5*MID_HIGH/6), 2213d522f475Smrg SEG(5*BOX_WIDE/6, 5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 2214d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), /* L */ 2215d522f475Smrg SEG(1*BOX_WIDE/3, CHR_HIGH, CHR_WIDE, CHR_HIGH), 2216d522f475Smrg -1 2217d522f475Smrg }, glyph_vt[] = { 2218d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/12,5*MID_HIGH/6), /* V */ 2219d522f475Smrg SEG(5*BOX_WIDE/12,5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 2220d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 2221d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 2222d522f475Smrg -1 2223d522f475Smrg }, plus_or_minus[] = 2224d522f475Smrg { 2225d522f475Smrg SEG( 0, 5*BOX_HIGH/6, CHR_WIDE, 5*BOX_HIGH/6), 2226d522f475Smrg SEG( MID_WIDE, 2*BOX_HIGH/6, MID_WIDE, 4*BOX_HIGH/6), 2227d522f475Smrg SEG( 0, 3*BOX_HIGH/6, CHR_WIDE, 3*BOX_HIGH/6), 2228d522f475Smrg -1 2229d522f475Smrg }, lower_right_corner[] = 2230d522f475Smrg { 2231d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 2232d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, 0), 2233d522f475Smrg -1 2234d522f475Smrg }, upper_right_corner[] = 2235d522f475Smrg { 2236d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 2237d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2238d522f475Smrg -1 2239d522f475Smrg }, upper_left_corner[] = 2240d522f475Smrg { 2241d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 2242d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2243d522f475Smrg -1 2244d522f475Smrg }, lower_left_corner[] = 2245d522f475Smrg { 2246d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 2247d522f475Smrg SEG( MID_WIDE, MID_WIDE, BOX_WIDE, MID_HIGH), 2248d522f475Smrg -1 2249d522f475Smrg }, cross[] = 2250d522f475Smrg { 2251d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2252d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2253d522f475Smrg -1 2254d522f475Smrg }, scan_line_1[] = 2255d522f475Smrg { 2256d522f475Smrg SEG( 0, 0, BOX_WIDE, 0), 2257d522f475Smrg -1 2258d522f475Smrg }, scan_line_3[] = 2259d522f475Smrg { 2260d522f475Smrg SEG( 0, BOX_HIGH/4, BOX_WIDE, BOX_HIGH/4), 2261d522f475Smrg -1 2262d522f475Smrg }, scan_line_7[] = 2263d522f475Smrg { 2264d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2265d522f475Smrg -1 2266d522f475Smrg }, scan_line_9[] = 2267d522f475Smrg { 2268d522f475Smrg SEG( 0, 3*BOX_HIGH/4, BOX_WIDE, 3*BOX_HIGH/4), 2269d522f475Smrg -1 2270d522f475Smrg }, horizontal_line[] = 2271d522f475Smrg { 2272d522f475Smrg SEG( 0, BOX_HIGH, BOX_WIDE, BOX_HIGH), 2273d522f475Smrg -1 2274d522f475Smrg }, left_tee[] = 2275d522f475Smrg { 2276d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2277d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 2278d522f475Smrg -1 2279d522f475Smrg }, right_tee[] = 2280d522f475Smrg { 2281d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2282d522f475Smrg SEG( MID_WIDE, MID_HIGH, 0, MID_HIGH), 2283d522f475Smrg -1 2284d522f475Smrg }, bottom_tee[] = 2285d522f475Smrg { 2286d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2287d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 2288d522f475Smrg -1 2289d522f475Smrg }, top_tee[] = 2290d522f475Smrg { 2291d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2292d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2293d522f475Smrg -1 2294d522f475Smrg }, vertical_line[] = 2295d522f475Smrg { 2296d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2297d522f475Smrg -1 2298d522f475Smrg }, less_than_or_equal[] = 2299d522f475Smrg { 2300d522f475Smrg SEG( CHR_WIDE, BOX_HIGH/3, 0, MID_HIGH), 2301d522f475Smrg SEG( CHR_WIDE, 2*BOX_HIGH/3, 0, MID_HIGH), 2302d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 2303d522f475Smrg -1 2304d522f475Smrg }, greater_than_or_equal[] = 2305d522f475Smrg { 2306d522f475Smrg SEG( 0, BOX_HIGH/3, CHR_WIDE, MID_HIGH), 2307d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, MID_HIGH), 2308d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 2309d522f475Smrg -1 2310d522f475Smrg }, greek_pi[] = 2311d522f475Smrg { 2312d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 2313d522f475Smrg SEG(5*CHR_WIDE/6, MID_HIGH, 5*CHR_WIDE/6, CHR_HIGH), 2314d522f475Smrg SEG(2*CHR_WIDE/6, MID_HIGH, 2*CHR_WIDE/6, CHR_HIGH), 2315d522f475Smrg -1 2316d522f475Smrg }, not_equal_to[] = 2317d522f475Smrg { 2318d522f475Smrg SEG(2*BOX_WIDE/3, 1*BOX_HIGH/3, 1*BOX_WIDE/3, CHR_HIGH), 2319d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, 2*BOX_HIGH/3), 2320d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 2321d522f475Smrg -1 2322d522f475Smrg }; 2323d522f475Smrg /* *INDENT-ON* */ 2324d522f475Smrg 2325d522f475Smrg static const short *lines[] = 2326d522f475Smrg { 2327d522f475Smrg 0, /* 00 (unused) */ 2328d522f475Smrg 0, /* 01 diamond */ 2329d522f475Smrg 0, /* 02 box */ 2330d522f475Smrg glyph_ht, /* 03 HT */ 2331d522f475Smrg glyph_ff, /* 04 FF */ 2332d522f475Smrg 0, /* 05 CR */ 2333d522f475Smrg glyph_lf, /* 06 LF */ 2334d522f475Smrg 0, /* 07 degrees (small circle) */ 2335d522f475Smrg plus_or_minus, /* 08 */ 2336d522f475Smrg glyph_nl, /* 09 */ 2337d522f475Smrg glyph_vt, /* 0A */ 2338d522f475Smrg lower_right_corner, /* 0B */ 2339d522f475Smrg upper_right_corner, /* 0C */ 2340d522f475Smrg upper_left_corner, /* 0D */ 2341d522f475Smrg lower_left_corner, /* 0E */ 2342d522f475Smrg cross, /* 0F */ 2343d522f475Smrg scan_line_1, /* 10 */ 2344d522f475Smrg scan_line_3, /* 11 */ 2345d522f475Smrg scan_line_7, /* 12 */ 2346d522f475Smrg scan_line_9, /* 13 */ 2347d522f475Smrg horizontal_line, /* 14 */ 2348d522f475Smrg left_tee, /* 15 */ 2349d522f475Smrg right_tee, /* 16 */ 2350d522f475Smrg bottom_tee, /* 17 */ 2351d522f475Smrg top_tee, /* 18 */ 2352d522f475Smrg vertical_line, /* 19 */ 2353d522f475Smrg less_than_or_equal, /* 1A */ 2354d522f475Smrg greater_than_or_equal, /* 1B */ 2355d522f475Smrg greek_pi, /* 1C */ 2356d522f475Smrg not_equal_to, /* 1D */ 2357d522f475Smrg 0, /* 1E LB */ 2358d522f475Smrg 0, /* 1F bullet */ 2359d522f475Smrg }; 2360d522f475Smrg 2361d522f475Smrg GC gc2; 2362d522f475Smrg CgsEnum cgsId = (ch == 2) ? gcDots : gcLine; 2363d522f475Smrg VTwin *cgsWin = WhichVWin(screen); 2364d522f475Smrg const short *p; 2365956cc18dSsnj unsigned font_width = (unsigned) (((flags & DOUBLEWFONT) ? 2 : 1) * screen->fnt_wide); 2366956cc18dSsnj unsigned font_height = (unsigned) (((flags & DOUBLEHFONT) ? 2 : 1) * screen->fnt_high); 2367d522f475Smrg 2368d522f475Smrg if (cells > 1) 2369956cc18dSsnj font_width *= (unsigned) cells; 2370d522f475Smrg 2371d522f475Smrg#if OPT_WIDE_CHARS 2372d522f475Smrg /* 2373d522f475Smrg * Try to show line-drawing characters if we happen to be in UTF-8 2374d522f475Smrg * mode, but have gotten an old-style font. 2375d522f475Smrg */ 2376d522f475Smrg if (screen->utf8_mode 2377d522f475Smrg#if OPT_RENDERFONT 2378d522f475Smrg && !UsingRenderFont(xw) 2379d522f475Smrg#endif 2380d522f475Smrg && (ch > 127) 2381d522f475Smrg && (ch != UCS_REPL)) { 2382d522f475Smrg unsigned n; 2383d522f475Smrg for (n = 1; n < 32; n++) { 2384d522f475Smrg if (dec2ucs(n) == ch 238520d2c4d2Smrg && !((flags & BOLD) 238620d2c4d2Smrg ? IsXtermMissingChar(screen, n, &screen->fnts[fBold]) 238720d2c4d2Smrg : IsXtermMissingChar(screen, n, &screen->fnts[fNorm]))) { 2388d522f475Smrg TRACE(("...use xterm-style linedrawing\n")); 2389d522f475Smrg ch = n; 2390d522f475Smrg break; 2391d522f475Smrg } 2392d522f475Smrg } 2393d522f475Smrg } 2394d522f475Smrg#endif 2395d522f475Smrg 2396d522f475Smrg TRACE(("DRAW_BOX(%d) cell %dx%d at %d,%d%s\n", 2397d522f475Smrg ch, font_height, font_width, y, x, 2398d522f475Smrg (ch >= (sizeof(lines) / sizeof(lines[0])) 2399d522f475Smrg ? "-BAD" 2400d522f475Smrg : ""))); 2401d522f475Smrg 2402d522f475Smrg if (cgsId == gcDots) { 2403d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2404d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2405d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2406d522f475Smrg } else { 2407d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2408d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2409d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2410d522f475Smrg } 2411d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2412d522f475Smrg 2413d522f475Smrg if (!(flags & NOBACKGROUND)) { 2414d522f475Smrg XFillRectangle(screen->display, VWindow(screen), gc2, x, y, 2415d522f475Smrg font_width, 2416d522f475Smrg font_height); 2417d522f475Smrg } 2418d522f475Smrg 2419d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2420d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2421d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2422d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2423d522f475Smrg 2424d522f475Smrg XSetLineAttributes(screen->display, gc2, 2425d522f475Smrg (flags & BOLD) 2426d522f475Smrg ? ((font_height > 12) 2427d522f475Smrg ? font_height / 12 2428d522f475Smrg : 1) 2429d522f475Smrg : ((font_height > 16) 2430d522f475Smrg ? font_height / 16 2431d522f475Smrg : 1), 2432d522f475Smrg LineSolid, 2433d522f475Smrg CapProjecting, 2434d522f475Smrg JoinMiter); 2435d522f475Smrg 2436d522f475Smrg if (ch == 1) { /* diamond */ 2437d522f475Smrg XPoint points[5]; 2438d522f475Smrg int npoints = 5, n; 2439d522f475Smrg 2440d522f475Smrg points[0].x = MID_WIDE; 2441d522f475Smrg points[0].y = BOX_HIGH / 4; 2442d522f475Smrg 2443d522f475Smrg points[1].x = 8 * BOX_WIDE / 8; 2444d522f475Smrg points[1].y = MID_HIGH; 2445d522f475Smrg 2446d522f475Smrg points[2].x = points[0].x; 2447d522f475Smrg points[2].y = 3 * BOX_HIGH / 4; 2448d522f475Smrg 2449d522f475Smrg points[3].x = 0 * BOX_WIDE / 8; 2450d522f475Smrg points[3].y = points[1].y; 2451d522f475Smrg 2452d522f475Smrg points[4].x = points[0].x; 2453d522f475Smrg points[4].y = points[0].y; 2454d522f475Smrg 2455d522f475Smrg for (n = 0; n < npoints; ++n) { 2456d522f475Smrg SCALE_X(points[n].x); 2457d522f475Smrg SCALE_Y(points[n].y); 2458d522f475Smrg points[n].x += x; 2459d522f475Smrg points[n].y += y; 2460d522f475Smrg } 2461d522f475Smrg 2462d522f475Smrg XFillPolygon(screen->display, 2463d522f475Smrg VWindow(screen), gc2, 2464d522f475Smrg points, npoints, 2465d522f475Smrg Convex, CoordModeOrigin); 2466d522f475Smrg } else if (ch == 7) { /* degrees */ 2467d522f475Smrg unsigned width = (BOX_WIDE / 3); 2468956cc18dSsnj int x_coord = MID_WIDE - (int) (width / 2); 2469956cc18dSsnj int y_coord = MID_HIGH - (int) width; 2470d522f475Smrg 2471d522f475Smrg SCALE_X(x_coord); 2472d522f475Smrg SCALE_Y(y_coord); 2473d522f475Smrg SCALE_X(width); 2474d522f475Smrg 2475d522f475Smrg XDrawArc(screen->display, 2476d522f475Smrg VWindow(screen), gc2, 2477d522f475Smrg x + x_coord, y + y_coord, width, width, 2478d522f475Smrg 0, 2479d522f475Smrg 360 * 64); 2480d522f475Smrg } else if (ch == 0x1f) { /* bullet */ 2481d522f475Smrg unsigned width = 7 * BOX_WIDE / 10; 2482956cc18dSsnj int x_coord = MID_WIDE - (int) (width / 3); 2483956cc18dSsnj int y_coord = MID_HIGH - (int) (width / 3); 2484d522f475Smrg 2485d522f475Smrg SCALE_X(x_coord); 2486d522f475Smrg SCALE_Y(y_coord); 2487d522f475Smrg SCALE_X(width); 2488d522f475Smrg 2489d522f475Smrg XDrawArc(screen->display, 2490d522f475Smrg VWindow(screen), gc2, 2491d522f475Smrg x + x_coord, y + y_coord, width, width, 2492d522f475Smrg 0, 2493d522f475Smrg 360 * 64); 2494d522f475Smrg } else if (ch < (sizeof(lines) / sizeof(lines[0])) 2495d522f475Smrg && (p = lines[ch]) != 0) { 2496956cc18dSsnj int coord[4]; 2497d522f475Smrg int n = 0; 2498d522f475Smrg while (*p >= 0) { 2499d522f475Smrg coord[n++] = *p++; 2500d522f475Smrg if (n == 4) { 2501d522f475Smrg SCALE_X(coord[0]); 2502d522f475Smrg SCALE_Y(coord[1]); 2503d522f475Smrg SCALE_X(coord[2]); 2504d522f475Smrg SCALE_Y(coord[3]); 2505d522f475Smrg XDrawLine(screen->display, 2506d522f475Smrg VWindow(screen), gc2, 2507d522f475Smrg x + coord[0], y + coord[1], 2508d522f475Smrg x + coord[2], y + coord[3]); 2509d522f475Smrg n = 0; 2510d522f475Smrg } 2511d522f475Smrg } 2512d522f475Smrg } else if (screen->force_all_chars) { 2513d522f475Smrg /* bounding rectangle, for debugging */ 2514d522f475Smrg XDrawRectangle(screen->display, VWindow(screen), gc2, x, y, 2515d522f475Smrg font_width - 1, 2516d522f475Smrg font_height - 1); 2517d522f475Smrg } 2518d522f475Smrg} 2519d522f475Smrg 2520d522f475Smrg#if OPT_RENDERFONT 2521d522f475Smrg 2522d522f475Smrg/* 2523d522f475Smrg * Check if the given character has a glyph known to Xft. 2524d522f475Smrg * 2525d522f475Smrg * see xc/lib/Xft/xftglyphs.c 2526d522f475Smrg */ 2527d522f475SmrgBool 2528d522f475SmrgxtermXftMissing(XtermWidget xw, XftFont * font, unsigned wc) 2529d522f475Smrg{ 2530d522f475Smrg Bool result = False; 2531d522f475Smrg 2532d522f475Smrg if (font != 0) { 2533956cc18dSsnj TScreen *screen = TScreenOf(xw); 2534956cc18dSsnj if (!XftGlyphExists(screen->display, font, wc)) { 2535d522f475Smrg#if OPT_WIDE_CHARS 2536d522f475Smrg TRACE(("xtermXftMissing %d (dec=%#x, ucs=%#x)\n", 2537d522f475Smrg wc, ucs2dec(wc), dec2ucs(wc))); 2538d522f475Smrg#else 2539d522f475Smrg TRACE(("xtermXftMissing %d\n", wc)); 2540d522f475Smrg#endif 2541d522f475Smrg result = True; 2542d522f475Smrg } 2543d522f475Smrg } 2544d522f475Smrg return result; 2545d522f475Smrg} 2546d522f475Smrg#endif /* OPT_RENDERFONT && OPT_WIDE_CHARS */ 2547d522f475Smrg 2548d522f475Smrg#endif /* OPT_BOX_CHARS */ 2549d522f475Smrg 2550d522f475Smrg#if OPT_WIDE_CHARS 2551d522f475Smrg#define MY_UCS(ucs,dec) case ucs: result = dec; break 2552d522f475Smrgunsigned 2553d522f475Smrgucs2dec(unsigned ch) 2554d522f475Smrg{ 2555d522f475Smrg unsigned result = ch; 2556d522f475Smrg if ((ch > 127) 2557d522f475Smrg && (ch != UCS_REPL)) { 2558d522f475Smrg switch (ch) { 2559d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 2560d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 2561d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 2562d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 2563d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 2564d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 2565d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 2566d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 2567d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 2568d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 2569d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 2570d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 2571d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 2572d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 2573d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 2574d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 2575d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 2576d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 2577d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 2578d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 2579d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 2580d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 2581d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 2582d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 2583d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 2584d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 2585d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 2586d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 2587d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 2588d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 2589d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 2590d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 2591d522f475Smrg } 2592d522f475Smrg } 2593d522f475Smrg return result; 2594d522f475Smrg} 2595d522f475Smrg 2596d522f475Smrg#undef MY_UCS 2597d522f475Smrg#define MY_UCS(ucs,dec) case dec: result = ucs; break 2598d522f475Smrg 2599d522f475Smrgunsigned 2600d522f475Smrgdec2ucs(unsigned ch) 2601d522f475Smrg{ 2602d522f475Smrg unsigned result = ch; 2603d522f475Smrg if (xtermIsDecGraphic(ch)) { 2604d522f475Smrg switch (ch) { 2605d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 2606d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 2607d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 2608d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 2609d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 2610d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 2611d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 2612d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 2613d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 2614d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 2615d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 2616d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 2617d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 2618d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 2619d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 2620d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 2621d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 2622d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 2623d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 2624d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 2625d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 2626d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 2627d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 2628d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 2629d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 2630d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 2631d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 2632d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 2633d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 2634d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 2635d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 2636d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 2637d522f475Smrg } 2638d522f475Smrg } 2639d522f475Smrg return result; 2640d522f475Smrg} 2641d522f475Smrg 2642d522f475Smrg#endif /* OPT_WIDE_CHARS */ 2643d522f475Smrg 2644d522f475Smrg#if OPT_SHIFT_FONTS 2645d522f475Smrgstatic void 2646d522f475SmrglookupOneFontSize(XtermWidget xw, int fontnum) 2647d522f475Smrg{ 2648d522f475Smrg TScreen *screen = TScreenOf(xw); 2649d522f475Smrg 2650d522f475Smrg if (screen->menu_font_sizes[fontnum] == 0) { 2651d522f475Smrg XTermFonts fnt; 2652d522f475Smrg 2653d522f475Smrg memset(&fnt, 0, sizeof(fnt)); 2654d522f475Smrg screen->menu_font_sizes[fontnum] = -1; 2655956cc18dSsnj if (xtermOpenFont(xw, screen->MenuFontName(fontnum), &fnt, fwAlways, True)) { 265620d2c4d2Smrg if (fontnum <= fontMenu_lastBuiltin 265720d2c4d2Smrg || strcmp(fnt.fn, DEFFONT)) 265820d2c4d2Smrg screen->menu_font_sizes[fontnum] = FontSize(fnt.fs); 2659d522f475Smrg xtermCloseFont(xw, &fnt); 2660d522f475Smrg } 2661d522f475Smrg } 2662d522f475Smrg} 2663d522f475Smrg 2664d522f475Smrg/* 2665d522f475Smrg * Cache the font-sizes so subsequent larger/smaller font actions will go fast. 2666d522f475Smrg */ 2667d522f475Smrgstatic void 2668d522f475SmrglookupFontSizes(XtermWidget xw) 2669d522f475Smrg{ 2670d522f475Smrg int n; 2671d522f475Smrg 2672d522f475Smrg for (n = 0; n < NMENUFONTS; n++) { 2673d522f475Smrg lookupOneFontSize(xw, n); 2674d522f475Smrg } 2675d522f475Smrg} 2676d522f475Smrg 26772eaa94a1Schristos#if OPT_RENDERFONT 26782eaa94a1Schristos#define NMENU_RENDERFONTS (NMENUFONTS - 2) /* no selection or escape */ 26792eaa94a1Schristosstatic Boolean 26802eaa94a1SchristosuseFaceSizes(XtermWidget xw) 26812eaa94a1Schristos{ 26822eaa94a1Schristos Boolean result = False; 26832eaa94a1Schristos int n; 26842eaa94a1Schristos 26852eaa94a1Schristos if (UsingRenderFont(xw)) { 26862eaa94a1Schristos result = True; 26872eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 26882eaa94a1Schristos if (xw->misc.face_size[n] <= 0.0) { 26892eaa94a1Schristos result = False; 26902eaa94a1Schristos break; 26912eaa94a1Schristos } 26922eaa94a1Schristos } 2693956cc18dSsnj if (!result) { 2694956cc18dSsnj Boolean broken_fonts = True; 2695956cc18dSsnj TScreen *screen = TScreenOf(xw); 269620d2c4d2Smrg long first = screen->menu_font_sizes[0]; 2697956cc18dSsnj 2698956cc18dSsnj lookupFontSizes(xw); 2699956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 2700956cc18dSsnj if (screen->menu_font_sizes[n] > 0 2701956cc18dSsnj && screen->menu_font_sizes[n] != first) { 2702956cc18dSsnj broken_fonts = False; 2703956cc18dSsnj break; 2704956cc18dSsnj } 2705956cc18dSsnj } 2706956cc18dSsnj 2707956cc18dSsnj /* 2708956cc18dSsnj * Workaround for breakage in font-packages - check if all of the 2709956cc18dSsnj * bitmap font sizes are the same, and if we're using TrueType 2710956cc18dSsnj * fonts. 2711956cc18dSsnj */ 2712956cc18dSsnj if (broken_fonts) { 2713956cc18dSsnj float lo_value = (float) 9.0e9; 2714956cc18dSsnj float hi_value = (float) 0.0; 2715956cc18dSsnj float value; 2716956cc18dSsnj 2717956cc18dSsnj TRACE(("bitmap fonts are broken - set faceSize resources\n")); 2718956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 2719956cc18dSsnj value = xw->misc.face_size[n]; 2720956cc18dSsnj if (value > 0.0) { 2721956cc18dSsnj if (lo_value > value) 2722956cc18dSsnj lo_value = value; 2723956cc18dSsnj if (hi_value < value) 2724956cc18dSsnj hi_value = value; 2725956cc18dSsnj } 2726956cc18dSsnj } 2727956cc18dSsnj 2728956cc18dSsnj if (hi_value <= 0.0) 2729956cc18dSsnj sscanf(DEFFACESIZE, "%f", &value); 2730956cc18dSsnj else 2731956cc18dSsnj value = (float) ((hi_value + lo_value) / 2.0); 2732956cc18dSsnj if (value <= 0) 2733956cc18dSsnj value = (float) 14.0; 2734956cc18dSsnj 2735956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 2736956cc18dSsnj TRACE(("setting faceSize%d %.1f\n", n, value)); 2737956cc18dSsnj xw->misc.face_size[n] = value; 2738956cc18dSsnj value = (float) (value * 1.1); 2739956cc18dSsnj } 2740956cc18dSsnj result = True; 2741956cc18dSsnj } 2742956cc18dSsnj } 27432eaa94a1Schristos } 27442eaa94a1Schristos return result; 27452eaa94a1Schristos} 27462eaa94a1Schristos#endif 27472eaa94a1Schristos 2748d522f475Smrg/* 2749d522f475Smrg * Find the index of a larger/smaller font (according to the sign of 'relative' 2750d522f475Smrg * and its magnitude), starting from the 'old' index. 2751d522f475Smrg */ 2752d522f475Smrgint 2753d522f475SmrglookupRelativeFontSize(XtermWidget xw, int old, int relative) 2754d522f475Smrg{ 2755d522f475Smrg TScreen *screen = TScreenOf(xw); 2756d522f475Smrg int n, m = -1; 2757d522f475Smrg 27582eaa94a1Schristos TRACE(("lookupRelativeFontSize(old=%d, relative=%d)\n", old, relative)); 2759d522f475Smrg if (!IsIcon(screen)) { 27602eaa94a1Schristos#if OPT_RENDERFONT 27612eaa94a1Schristos if (useFaceSizes(xw)) { 27622eaa94a1Schristos TRACE(("...using FaceSize\n")); 27632eaa94a1Schristos if (relative != 0) { 27642eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 27652eaa94a1Schristos if (xw->misc.face_size[n] > 0 && 27662eaa94a1Schristos xw->misc.face_size[n] != xw->misc.face_size[old]) { 27672eaa94a1Schristos int cmp_0 = ((xw->misc.face_size[n] > 27682eaa94a1Schristos xw->misc.face_size[old]) 27692eaa94a1Schristos ? relative 27702eaa94a1Schristos : -relative); 27712eaa94a1Schristos int cmp_m = ((m < 0) 27722eaa94a1Schristos ? 1 27732eaa94a1Schristos : ((xw->misc.face_size[n] < 27742eaa94a1Schristos xw->misc.face_size[m]) 27752eaa94a1Schristos ? relative 27762eaa94a1Schristos : -relative)); 27772eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 27782eaa94a1Schristos m = n; 27792eaa94a1Schristos } 2780d522f475Smrg } 2781d522f475Smrg } 2782d522f475Smrg } 27832eaa94a1Schristos } else 27842eaa94a1Schristos#endif 27852eaa94a1Schristos { 27862eaa94a1Schristos TRACE(("...using bitmap areas\n")); 27872eaa94a1Schristos lookupFontSizes(xw); 27882eaa94a1Schristos if (relative != 0) { 27892eaa94a1Schristos for (n = 0; n < NMENUFONTS; ++n) { 27902eaa94a1Schristos if (screen->menu_font_sizes[n] > 0 && 27912eaa94a1Schristos screen->menu_font_sizes[n] != 27922eaa94a1Schristos screen->menu_font_sizes[old]) { 27932eaa94a1Schristos int cmp_0 = ((screen->menu_font_sizes[n] > 27942eaa94a1Schristos screen->menu_font_sizes[old]) 27952eaa94a1Schristos ? relative 27962eaa94a1Schristos : -relative); 27972eaa94a1Schristos int cmp_m = ((m < 0) 27982eaa94a1Schristos ? 1 27992eaa94a1Schristos : ((screen->menu_font_sizes[n] < 28002eaa94a1Schristos screen->menu_font_sizes[m]) 28012eaa94a1Schristos ? relative 28022eaa94a1Schristos : -relative)); 28032eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 28042eaa94a1Schristos m = n; 28052eaa94a1Schristos } 28062eaa94a1Schristos } 28072eaa94a1Schristos } 2808d522f475Smrg } 2809d522f475Smrg } 28102eaa94a1Schristos TRACE(("...new index %d\n", m)); 28112eaa94a1Schristos if (m >= 0) { 28122eaa94a1Schristos if (relative > 1) 28132eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative - 1); 28142eaa94a1Schristos else if (relative < -1) 28152eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative + 1); 28162eaa94a1Schristos } 2817d522f475Smrg } 2818d522f475Smrg return m; 2819d522f475Smrg} 2820d522f475Smrg 2821d522f475Smrg/* ARGSUSED */ 2822d522f475Smrgvoid 2823d522f475SmrgHandleLargerFont(Widget w GCC_UNUSED, 2824d522f475Smrg XEvent * event GCC_UNUSED, 2825d522f475Smrg String * params GCC_UNUSED, 2826d522f475Smrg Cardinal *param_count GCC_UNUSED) 2827d522f475Smrg{ 2828956cc18dSsnj XtermWidget xw; 2829d522f475Smrg 283020d2c4d2Smrg TRACE(("Handle larger-vt-font for %p\n", (void *) w)); 2831956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 2832d522f475Smrg if (xw->misc.shift_fonts) { 2833956cc18dSsnj TScreen *screen = TScreenOf(xw); 2834d522f475Smrg int m; 2835d522f475Smrg 2836d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, 1); 2837d522f475Smrg if (m >= 0) { 2838d522f475Smrg SetVTFont(xw, m, True, NULL); 2839d522f475Smrg } else { 284020d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 2841d522f475Smrg } 2842d522f475Smrg } 2843d522f475Smrg } 2844d522f475Smrg} 2845d522f475Smrg 2846d522f475Smrg/* ARGSUSED */ 2847d522f475Smrgvoid 2848d522f475SmrgHandleSmallerFont(Widget w GCC_UNUSED, 2849d522f475Smrg XEvent * event GCC_UNUSED, 2850d522f475Smrg String * params GCC_UNUSED, 2851d522f475Smrg Cardinal *param_count GCC_UNUSED) 2852d522f475Smrg{ 2853956cc18dSsnj XtermWidget xw; 2854d522f475Smrg 285520d2c4d2Smrg TRACE(("Handle smaller-vt-font for %p\n", (void *) w)); 2856956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 2857d522f475Smrg if (xw->misc.shift_fonts) { 2858956cc18dSsnj TScreen *screen = TScreenOf(xw); 2859d522f475Smrg int m; 2860d522f475Smrg 2861d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, -1); 2862d522f475Smrg if (m >= 0) { 2863d522f475Smrg SetVTFont(xw, m, True, NULL); 2864d522f475Smrg } else { 286520d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 2866d522f475Smrg } 2867d522f475Smrg } 2868d522f475Smrg } 2869d522f475Smrg} 2870d522f475Smrg#endif 2871d522f475Smrg 2872d522f475Smrgint 2873d522f475SmrgxtermGetFont(const char *param) 2874d522f475Smrg{ 2875d522f475Smrg int fontnum; 2876d522f475Smrg 2877d522f475Smrg switch (param[0]) { 2878d522f475Smrg case 'd': 2879d522f475Smrg case 'D': 2880d522f475Smrg case '0': 2881d522f475Smrg fontnum = fontMenu_default; 2882d522f475Smrg break; 2883d522f475Smrg case '1': 2884d522f475Smrg fontnum = fontMenu_font1; 2885d522f475Smrg break; 2886d522f475Smrg case '2': 2887d522f475Smrg fontnum = fontMenu_font2; 2888d522f475Smrg break; 2889d522f475Smrg case '3': 2890d522f475Smrg fontnum = fontMenu_font3; 2891d522f475Smrg break; 2892d522f475Smrg case '4': 2893d522f475Smrg fontnum = fontMenu_font4; 2894d522f475Smrg break; 2895d522f475Smrg case '5': 2896d522f475Smrg fontnum = fontMenu_font5; 2897d522f475Smrg break; 2898d522f475Smrg case '6': 2899d522f475Smrg fontnum = fontMenu_font6; 2900d522f475Smrg break; 2901d522f475Smrg case 'e': 2902d522f475Smrg case 'E': 2903d522f475Smrg fontnum = fontMenu_fontescape; 2904d522f475Smrg break; 2905d522f475Smrg case 's': 2906d522f475Smrg case 'S': 2907d522f475Smrg fontnum = fontMenu_fontsel; 2908d522f475Smrg break; 2909d522f475Smrg default: 2910d522f475Smrg fontnum = -1; 2911d522f475Smrg break; 2912d522f475Smrg } 2913d522f475Smrg return fontnum; 2914d522f475Smrg} 2915d522f475Smrg 2916d522f475Smrg/* ARGSUSED */ 2917d522f475Smrgvoid 2918d522f475SmrgHandleSetFont(Widget w GCC_UNUSED, 2919d522f475Smrg XEvent * event GCC_UNUSED, 2920d522f475Smrg String * params, 2921d522f475Smrg Cardinal *param_count) 2922d522f475Smrg{ 2923956cc18dSsnj XtermWidget xw; 2924956cc18dSsnj 2925956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 2926d522f475Smrg int fontnum; 2927d522f475Smrg VTFontNames fonts; 2928d522f475Smrg 2929d522f475Smrg memset(&fonts, 0, sizeof(fonts)); 2930d522f475Smrg 2931d522f475Smrg if (*param_count == 0) { 2932d522f475Smrg fontnum = fontMenu_default; 2933d522f475Smrg } else { 2934d522f475Smrg Cardinal maxparams = 1; /* total number of params allowed */ 2935d522f475Smrg int result = xtermGetFont(params[0]); 2936d522f475Smrg 2937d522f475Smrg switch (result) { 2938d522f475Smrg case fontMenu_default: /* FALLTHRU */ 2939d522f475Smrg case fontMenu_font1: /* FALLTHRU */ 2940d522f475Smrg case fontMenu_font2: /* FALLTHRU */ 2941d522f475Smrg case fontMenu_font3: /* FALLTHRU */ 2942d522f475Smrg case fontMenu_font4: /* FALLTHRU */ 2943d522f475Smrg case fontMenu_font5: /* FALLTHRU */ 2944d522f475Smrg case fontMenu_font6: /* FALLTHRU */ 2945d522f475Smrg break; 2946d522f475Smrg case fontMenu_fontescape: 2947d522f475Smrg#if OPT_WIDE_CHARS 2948d522f475Smrg maxparams = 5; 2949d522f475Smrg#else 2950d522f475Smrg maxparams = 3; 2951d522f475Smrg#endif 2952d522f475Smrg break; 2953d522f475Smrg case fontMenu_fontsel: 2954d522f475Smrg maxparams = 2; 2955d522f475Smrg break; 2956d522f475Smrg default: 295720d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 2958d522f475Smrg return; 2959d522f475Smrg } 2960d522f475Smrg fontnum = result; 2961d522f475Smrg 2962d522f475Smrg if (*param_count > maxparams) { /* see if extra args given */ 296320d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 2964d522f475Smrg return; 2965d522f475Smrg } 2966d522f475Smrg switch (*param_count) { /* assign 'em */ 2967d522f475Smrg#if OPT_WIDE_CHARS 2968d522f475Smrg case 5: 2969d522f475Smrg fonts.f_wb = params[4]; 2970d522f475Smrg /* FALLTHRU */ 2971d522f475Smrg case 4: 2972d522f475Smrg fonts.f_w = params[3]; 2973d522f475Smrg /* FALLTHRU */ 2974d522f475Smrg#endif 2975d522f475Smrg case 3: 2976d522f475Smrg fonts.f_b = params[2]; 2977d522f475Smrg /* FALLTHRU */ 2978d522f475Smrg case 2: 2979d522f475Smrg fonts.f_n = params[1]; 2980d522f475Smrg break; 2981d522f475Smrg } 2982d522f475Smrg } 2983d522f475Smrg 2984956cc18dSsnj SetVTFont(xw, fontnum, True, &fonts); 2985d522f475Smrg } 2986d522f475Smrg} 2987d522f475Smrg 2988d522f475Smrgvoid 2989d522f475SmrgSetVTFont(XtermWidget xw, 2990d522f475Smrg int which, 2991d522f475Smrg Bool doresize, 2992d522f475Smrg const VTFontNames * fonts) 2993d522f475Smrg{ 2994956cc18dSsnj TScreen *screen = TScreenOf(xw); 2995d522f475Smrg 2996d522f475Smrg TRACE(("SetVTFont(which=%d, f_n=%s, f_b=%s)\n", which, 2997d522f475Smrg (fonts && fonts->f_n) ? fonts->f_n : "<null>", 2998d522f475Smrg (fonts && fonts->f_b) ? fonts->f_b : "<null>")); 2999d522f475Smrg 3000d522f475Smrg if (IsIcon(screen)) { 300120d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3002d522f475Smrg } else if (which >= 0 && which < NMENUFONTS) { 3003d522f475Smrg VTFontNames myfonts; 3004d522f475Smrg 3005d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 3006d522f475Smrg if (fonts != 0) 3007d522f475Smrg myfonts = *fonts; 3008d522f475Smrg 3009d522f475Smrg if (which == fontMenu_fontsel) { /* go get the selection */ 3010d522f475Smrg FindFontSelection(xw, myfonts.f_n, False); 3011d522f475Smrg } else { 3012d522f475Smrg int oldFont = screen->menu_font_number; 3013d522f475Smrg 3014d522f475Smrg#define USE_CACHED(field, name) \ 3015d522f475Smrg if (myfonts.field == 0) { \ 3016d522f475Smrg myfonts.field = screen->menu_font_names[which][name]; \ 3017d522f475Smrg TRACE(("set myfonts." #field " from menu_font_names[%d][" #name "] %s\n", \ 3018d522f475Smrg which, NonNull(myfonts.field))); \ 3019d522f475Smrg } else { \ 3020d522f475Smrg TRACE(("set myfonts." #field " reused\n")); \ 3021d522f475Smrg } 302220d2c4d2Smrg#define SAVE_FNAME(field, name) \ 302320d2c4d2Smrg if (myfonts.field != 0) { \ 302420d2c4d2Smrg if (screen->menu_font_names[which][name] == 0 \ 302520d2c4d2Smrg || strcmp(screen->menu_font_names[which][name], myfonts.field)) { \ 302620d2c4d2Smrg TRACE(("updating menu_font_names[%d][" #name "] to %s\n", \ 302720d2c4d2Smrg which, myfonts.field)); \ 302820d2c4d2Smrg screen->menu_font_names[which][name] = x_strdup(myfonts.field); \ 302920d2c4d2Smrg } \ 303020d2c4d2Smrg } 303120d2c4d2Smrg 3032d522f475Smrg USE_CACHED(f_n, fNorm); 3033d522f475Smrg USE_CACHED(f_b, fBold); 3034d522f475Smrg#if OPT_WIDE_CHARS 3035d522f475Smrg USE_CACHED(f_w, fWide); 3036d522f475Smrg USE_CACHED(f_wb, fWBold); 3037d522f475Smrg#endif 3038d522f475Smrg if (xtermLoadFont(xw, 3039d522f475Smrg &myfonts, 3040d522f475Smrg doresize, which)) { 304120d2c4d2Smrg /* 304220d2c4d2Smrg * If successful, save the data so that a subsequent query via 304320d2c4d2Smrg * OSC-50 will return the expected values. 304420d2c4d2Smrg */ 304520d2c4d2Smrg SAVE_FNAME(f_n, fNorm); 304620d2c4d2Smrg SAVE_FNAME(f_b, fBold); 304720d2c4d2Smrg#if OPT_WIDE_CHARS 304820d2c4d2Smrg SAVE_FNAME(f_w, fWide); 304920d2c4d2Smrg SAVE_FNAME(f_wb, fWBold); 305020d2c4d2Smrg#endif 3051d522f475Smrg } else { 3052d522f475Smrg xtermLoadFont(xw, 3053d522f475Smrg xtermFontName(screen->MenuFontName(oldFont)), 3054d522f475Smrg doresize, oldFont); 305520d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3056d522f475Smrg } 3057d522f475Smrg } 305820d2c4d2Smrg } else { 305920d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3060d522f475Smrg } 3061d522f475Smrg return; 3062d522f475Smrg} 3063