fontutils.c revision 492d43a5
1492d43a5Smrg/* $XTermId: fontutils.c,v 1.353 2010/10/23 00:27:22 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 238492d43a5Smrg if (IsEmpty(name)) { 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 540492d43a5Smrgsame_font_name(const char *pattern, const 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 580492d43a5Smrggot_bold_font(Display * dpy, XFontStruct * fs, String 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) 710492d43a5Smrg free((void *) 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) { 720492d43a5Smrg char *last = (char *) 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 748492d43a5Smrg if (!IsEmpty(name)) { 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)); 764492d43a5Smrg 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 { 777492d43a5Smrg 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) ? "*" : " ", \ 914492d43a5Smrg 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 } 935492d43a5Smrg 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; 952492d43a5Smrg 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; 1237492d43a5Smrg String menu_font_names[fontMenu_lastBuiltin + 1][fMAX]; 1238d522f475Smrg} SubResourceRec; 1239d522f475Smrg 1240d522f475Smrg#define MERGE_SUBFONT(src,dst,name) \ 1241492d43a5Smrg if (IsEmpty(dst.name)) { \ 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) { \ 1252492d43a5Smrg dst.menu_font_names[n][m] = x_strdup(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 1297492d43a5Smrg if (IsEmpty(myName)) { 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); 1332492d43a5Smrg screen->MenuFontName(fontMenu_default) = x_strdup(xw->misc.default_font.f_n); 1333492d43a5Smrg screen->menu_font_names[0][fBold] = x_strdup(xw->misc.default_font.f_b); 1334d522f475Smrg#if OPT_WIDE_CHARS 1335492d43a5Smrg screen->menu_font_names[0][fWide] = x_strdup(xw->misc.default_font.f_w); 1336492d43a5Smrg screen->menu_font_names[0][fWBold] = x_strdup(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); 1424492d43a5Smrg char name_buf[80]; 1425492d43a5Smrg char class_buf[80]; 1426492d43a5Smrg String name = (String) ((*param_count > 0) ? params[0] : empty); 1427492d43a5Smrg char *myName = (char *) MyStackAlloc(strlen(name), name_buf); 1428492d43a5Smrg String convert = (String) ((*param_count > 1) ? params[1] : myName); 1429492d43a5Smrg char *myClass = (char *) MyStackAlloc(strlen(convert), class_buf); 1430d522f475Smrg int n; 1431d522f475Smrg 1432d522f475Smrg TRACE(("HandleLoadVTFonts(%d)\n", *param_count)); 1433492d43a5Smrg strcpy(myName, name); 1434d522f475Smrg strcpy(myClass, convert); 14352eaa94a1Schristos if (*param_count == 1) 14362eaa94a1Schristos myClass[0] = x_toupper(myClass[0]); 1437d522f475Smrg 1438d522f475Smrg if (xtermLoadVTFonts(xw, myName, myClass)) { 1439d522f475Smrg /* 1440d522f475Smrg * When switching fonts, try to preserve the font-menu selection, since 1441d522f475Smrg * it is less surprising to do that (if the font-switching can be 1442d522f475Smrg * undone) than to switch to "Default". 1443d522f475Smrg */ 1444956cc18dSsnj int font_number = screen->menu_font_number; 1445d522f475Smrg if (font_number > fontMenu_lastBuiltin) 1446d522f475Smrg font_number = fontMenu_lastBuiltin; 1447d522f475Smrg for (n = 0; n < NMENUFONTS; ++n) 1448956cc18dSsnj screen->menu_font_sizes[n] = 0; 1449d522f475Smrg SetVTFont(xw, font_number, True, 1450d522f475Smrg ((font_number == fontMenu_default) 1451d522f475Smrg ? &(xw->misc.default_font) 1452d522f475Smrg : NULL)); 1453d522f475Smrg } 1454d522f475Smrg 1455492d43a5Smrg MyStackFree(myName, name_buf); 1456492d43a5Smrg MyStackFree(myClass, class_buf); 1457d522f475Smrg } 1458d522f475Smrg} 1459d522f475Smrg#endif /* OPT_LOAD_VTFONTS */ 1460d522f475Smrg 1461d522f475Smrg/* 1462d522f475Smrg * Set the limits for the box that outlines the cursor. 1463d522f475Smrg */ 1464d522f475Smrgvoid 1465d522f475SmrgxtermSetCursorBox(TScreen * screen) 1466d522f475Smrg{ 1467d522f475Smrg static XPoint VTbox[NBOX]; 1468d522f475Smrg XPoint *vp; 14692eaa94a1Schristos int fw = FontWidth(screen) - 1; 14702eaa94a1Schristos int fh = FontHeight(screen) - 1; 14712eaa94a1Schristos int hh = screen->cursor_underline ? 1 : fh; 1472d522f475Smrg 1473d522f475Smrg vp = &VTbox[1]; 14742eaa94a1Schristos (vp++)->x = (short) fw; 14752eaa94a1Schristos (vp++)->y = (short) hh; 14762eaa94a1Schristos (vp++)->x = (short) -fw; 14772eaa94a1Schristos vp->y = (short) -hh; 14782eaa94a1Schristos 1479d522f475Smrg screen->box = VTbox; 1480d522f475Smrg} 1481d522f475Smrg 1482d522f475Smrg#define CACHE_XFT(dst,src) if (src != 0) {\ 1483956cc18dSsnj checkXft(xw, &(dst[fontnum]), src);\ 1484956cc18dSsnj TRACE(("Xft metrics %s[%d] = %d (%d,%d) advance %d, actual %d%s\n",\ 1485d522f475Smrg #dst,\ 1486d522f475Smrg fontnum,\ 1487d522f475Smrg src->height,\ 1488d522f475Smrg src->ascent,\ 1489d522f475Smrg src->descent,\ 1490956cc18dSsnj src->max_advance_width,\ 1491956cc18dSsnj dst[fontnum].map.min_width,\ 1492956cc18dSsnj dst[fontnum].map.mixed ? " mixed" : ""));\ 1493d522f475Smrg } 1494d522f475Smrg 1495d522f475Smrg#if OPT_RENDERFONT 1496956cc18dSsnj 149720d2c4d2Smrg#if OPT_TRACE > 1 149820d2c4d2Smrgstatic FcChar32 149920d2c4d2SmrgxtermXftFirstChar(XftFont * xft) 150020d2c4d2Smrg{ 150120d2c4d2Smrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 150220d2c4d2Smrg FcChar32 next; 150320d2c4d2Smrg FcChar32 first; 150420d2c4d2Smrg int i; 150520d2c4d2Smrg 150620d2c4d2Smrg first = FcCharSetFirstPage(xft->charset, map, &next); 150720d2c4d2Smrg for (i = 0; i < FC_CHARSET_MAP_SIZE; i++) 150820d2c4d2Smrg if (map[i]) { 150920d2c4d2Smrg FcChar32 bits = map[i]; 151020d2c4d2Smrg first += i * 32; 151120d2c4d2Smrg while (!(bits & 0x1)) { 151220d2c4d2Smrg bits >>= 1; 151320d2c4d2Smrg first++; 151420d2c4d2Smrg } 151520d2c4d2Smrg break; 151620d2c4d2Smrg } 151720d2c4d2Smrg return first; 151820d2c4d2Smrg} 151920d2c4d2Smrg 152020d2c4d2Smrgstatic FcChar32 152120d2c4d2SmrgxtermXftLastChar(XftFont * xft) 152220d2c4d2Smrg{ 152320d2c4d2Smrg FcChar32 this, last, next; 152420d2c4d2Smrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 152520d2c4d2Smrg int i; 152620d2c4d2Smrg last = FcCharSetFirstPage(xft->charset, map, &next); 152720d2c4d2Smrg while ((this = FcCharSetNextPage(xft->charset, map, &next)) != FC_CHARSET_DONE) 152820d2c4d2Smrg last = this; 152920d2c4d2Smrg last &= ~0xff; 153020d2c4d2Smrg for (i = FC_CHARSET_MAP_SIZE - 1; i >= 0; i--) 153120d2c4d2Smrg if (map[i]) { 153220d2c4d2Smrg FcChar32 bits = map[i]; 153320d2c4d2Smrg last += i * 32 + 31; 153420d2c4d2Smrg while (!(bits & 0x80000000)) { 153520d2c4d2Smrg last--; 153620d2c4d2Smrg bits <<= 1; 153720d2c4d2Smrg } 153820d2c4d2Smrg break; 153920d2c4d2Smrg } 154020d2c4d2Smrg return (long) last; 154120d2c4d2Smrg} 154220d2c4d2Smrg 154320d2c4d2Smrgstatic void 154420d2c4d2SmrgdumpXft(XtermWidget xw, XTermXftFonts * data) 154520d2c4d2Smrg{ 154620d2c4d2Smrg XftFont *xft = data->font; 154720d2c4d2Smrg TScreen *screen = TScreenOf(xw); 154820d2c4d2Smrg VTwin *win = WhichVWin(screen); 154920d2c4d2Smrg 155020d2c4d2Smrg FcChar32 c; 155120d2c4d2Smrg FcChar32 first = xtermXftFirstChar(xft); 155220d2c4d2Smrg FcChar32 last = xtermXftLastChar(xft); 155320d2c4d2Smrg unsigned count = 0; 155420d2c4d2Smrg unsigned outside = 0; 155520d2c4d2Smrg 155620d2c4d2Smrg TRACE(("dumpXft {{\n")); 155720d2c4d2Smrg TRACE((" data range %#6x..%#6x\n", first, last)); 155820d2c4d2Smrg for (c = first; c <= last; ++c) { 155920d2c4d2Smrg if (FcCharSetHasChar(xft->charset, c)) { 156020d2c4d2Smrg int width = my_wcwidth((int) c); 156120d2c4d2Smrg XGlyphInfo extents; 156220d2c4d2Smrg 156320d2c4d2Smrg XftTextExtents32(XtDisplay(xw), xft, &c, 1, &extents); 156420d2c4d2Smrg TRACE(("%#6x %2d %.1f\n", c, width, 156520d2c4d2Smrg ((double) extents.width) / win->f_width)); 156620d2c4d2Smrg if (extents.width > win->f_width) 156720d2c4d2Smrg ++outside; 156820d2c4d2Smrg ++count; 156920d2c4d2Smrg } 157020d2c4d2Smrg } 157120d2c4d2Smrg TRACE(("}} %u total, %u outside\n", count, outside)); 157220d2c4d2Smrg} 157320d2c4d2Smrg#define DUMP_XFT(xw, data) dumpXft(xw, data) 157420d2c4d2Smrg#else 157520d2c4d2Smrg#define DUMP_XFT(xw, data) /* nothing */ 157620d2c4d2Smrg#endif 157720d2c4d2Smrg 1578956cc18dSsnjstatic void 1579956cc18dSsnjcheckXft(XtermWidget xw, XTermXftFonts * data, XftFont * xft) 1580956cc18dSsnj{ 1581956cc18dSsnj FcChar32 c; 1582956cc18dSsnj Dimension width = 0; 1583956cc18dSsnj 1584956cc18dSsnj data->font = xft; 1585956cc18dSsnj data->map.min_width = 0; 1586956cc18dSsnj data->map.max_width = (Dimension) xft->max_advance_width; 1587956cc18dSsnj 158820d2c4d2Smrg /* 158920d2c4d2Smrg * For each ASCII or ISO-8859-1 printable code, ask what its width is. 159020d2c4d2Smrg * Given the maximum width for those, we have a reasonable estimate of 159120d2c4d2Smrg * the single-column width. 159220d2c4d2Smrg * 159320d2c4d2Smrg * Ignore control characters - their extent information is misleading. 159420d2c4d2Smrg */ 1595956cc18dSsnj for (c = 32; c < 256; ++c) { 159620d2c4d2Smrg if (c >= 127 && c <= 159) 159720d2c4d2Smrg continue; 1598956cc18dSsnj if (FcCharSetHasChar(xft->charset, c)) { 1599956cc18dSsnj XGlyphInfo extents; 1600956cc18dSsnj 1601956cc18dSsnj XftTextExtents32(XtDisplay(xw), xft, &c, 1, &extents); 160220d2c4d2Smrg if (width < extents.width && extents.width <= data->map.max_width) { 1603956cc18dSsnj width = extents.width; 160420d2c4d2Smrg } 1605956cc18dSsnj } 1606956cc18dSsnj } 1607956cc18dSsnj data->map.min_width = width; 1608956cc18dSsnj data->map.mixed = (data->map.max_width >= (data->map.min_width + 1)); 1609956cc18dSsnj} 1610956cc18dSsnj 1611d522f475Smrgstatic XftFont * 1612956cc18dSsnjxtermOpenXft(XtermWidget xw, const char *name, XftPattern * pat, const char *tag) 1613d522f475Smrg{ 1614956cc18dSsnj TScreen *screen = TScreenOf(xw); 1615956cc18dSsnj Display *dpy = screen->display; 1616d522f475Smrg XftPattern *match; 1617d522f475Smrg XftResult status; 1618d522f475Smrg XftFont *result = 0; 1619d522f475Smrg 1620d522f475Smrg if (pat != 0) { 1621d522f475Smrg match = XftFontMatch(dpy, DefaultScreen(dpy), pat, &status); 1622d522f475Smrg if (match != 0) { 1623d522f475Smrg result = XftFontOpenPattern(dpy, match); 1624d522f475Smrg if (result != 0) { 1625d522f475Smrg TRACE(("...matched %s font\n", tag)); 1626d522f475Smrg } else { 1627d522f475Smrg TRACE(("...could did not open %s font\n", tag)); 1628d522f475Smrg XftPatternDestroy(match); 1629956cc18dSsnj if (xw->misc.fontWarnings >= fwAlways) { 1630956cc18dSsnj TRACE(("OOPS cannot open %s font \"%s\"\n", tag, name)); 1631956cc18dSsnj fprintf(stderr, "%s: cannot open %s font \"%s\"\n", 1632956cc18dSsnj ProgramName, tag, name); 1633956cc18dSsnj } 1634d522f475Smrg } 1635d522f475Smrg } else { 1636d522f475Smrg TRACE(("...did not match %s font\n", tag)); 1637956cc18dSsnj if (xw->misc.fontWarnings >= fwResource) { 1638956cc18dSsnj TRACE(("OOPS: cannot match %s font \"%s\"\n", tag, name)); 1639956cc18dSsnj fprintf(stderr, "%s: cannot match %s font \"%s\"\n", 1640956cc18dSsnj ProgramName, tag, name); 1641956cc18dSsnj } 1642d522f475Smrg } 1643d522f475Smrg } 1644d522f475Smrg return result; 1645d522f475Smrg} 1646d522f475Smrg#endif 1647d522f475Smrg 1648d522f475Smrg#if OPT_RENDERFONT 1649d522f475Smrg#if OPT_SHIFT_FONTS 1650d522f475Smrg/* 1651d522f475Smrg * Don't make a dependency on the math library for a single function. 1652d522f475Smrg * (Newton Raphson). 1653d522f475Smrg */ 1654d522f475Smrgstatic double 1655d522f475SmrgmySquareRoot(double value) 1656d522f475Smrg{ 1657d522f475Smrg double result = 0.0; 1658d522f475Smrg if (value > 0.0) { 1659d522f475Smrg int n; 1660d522f475Smrg double older = value; 1661d522f475Smrg for (n = 0; n < 10; ++n) { 1662d522f475Smrg double delta = (older * older - value) / (2.0 * older); 1663d522f475Smrg double newer = older - delta; 1664d522f475Smrg older = newer; 1665d522f475Smrg result = newer; 1666d522f475Smrg if (delta > -0.001 && delta < 0.001) 1667d522f475Smrg break; 1668d522f475Smrg } 1669d522f475Smrg } 1670d522f475Smrg return result; 1671d522f475Smrg} 1672d522f475Smrg#endif 1673d522f475Smrg 1674d522f475Smrg/* 1675d522f475Smrg * Given the Xft font metrics, determine the actual font size. This is used 1676d522f475Smrg * for each font to ensure that normal, bold and italic fonts follow the same 1677d522f475Smrg * rule. 1678d522f475Smrg */ 1679d522f475Smrgstatic void 1680d522f475SmrgsetRenderFontsize(TScreen * screen, VTwin * win, XftFont * font, const char *tag) 1681d522f475Smrg{ 1682d522f475Smrg if (font != 0) { 1683d522f475Smrg int width, height, ascent, descent; 1684d522f475Smrg 1685d522f475Smrg (void) screen; 1686d522f475Smrg 1687d522f475Smrg width = font->max_advance_width; 1688d522f475Smrg height = font->height; 1689d522f475Smrg ascent = font->ascent; 1690d522f475Smrg descent = font->descent; 1691d522f475Smrg if (height < ascent + descent) { 1692d522f475Smrg TRACE(("...increase height from %d\n", height)); 1693d522f475Smrg height = ascent + descent; 1694d522f475Smrg } 1695d522f475Smrg if (is_double_width_font_xft(screen->display, font)) { 1696d522f475Smrg TRACE(("...reduced width from %d\n", width)); 1697d522f475Smrg width >>= 1; 1698d522f475Smrg } 1699d522f475Smrg if (tag == 0) { 1700d522f475Smrg win->f_width = width; 1701d522f475Smrg win->f_height = height; 1702d522f475Smrg win->f_ascent = ascent; 1703d522f475Smrg win->f_descent = descent; 1704d522f475Smrg TRACE(("setRenderFontsize result %dx%d (%d+%d)\n", 1705d522f475Smrg width, height, ascent, descent)); 1706d522f475Smrg } else if (win->f_width < width || 1707d522f475Smrg win->f_height < height || 1708d522f475Smrg win->f_ascent < ascent || 1709d522f475Smrg win->f_descent < descent) { 1710d522f475Smrg TRACE(("setRenderFontsize %s changed %dx%d (%d+%d) to %dx%d (%d+%d)\n", 1711d522f475Smrg tag, 1712d522f475Smrg win->f_width, win->f_height, win->f_ascent, win->f_descent, 1713d522f475Smrg width, height, ascent, descent)); 1714d522f475Smrg 1715d522f475Smrg win->f_width = width; 1716d522f475Smrg win->f_height = height; 1717d522f475Smrg win->f_ascent = ascent; 1718d522f475Smrg win->f_descent = descent; 1719d522f475Smrg } else { 1720d522f475Smrg TRACE(("setRenderFontsize %s unchanged\n", tag)); 1721d522f475Smrg } 1722d522f475Smrg } 1723d522f475Smrg} 1724d522f475Smrg#endif 1725d522f475Smrg 172620d2c4d2Smrgstatic void 172720d2c4d2SmrgcheckFontInfo(int value, const char *tag) 172820d2c4d2Smrg{ 172920d2c4d2Smrg if (value == 0) { 173020d2c4d2Smrg fprintf(stderr, 173120d2c4d2Smrg "Selected font has no non-zero %s for ISO-8859-1 encoding\n", tag); 173220d2c4d2Smrg exit(1); 173320d2c4d2Smrg } 173420d2c4d2Smrg} 173520d2c4d2Smrg 173620d2c4d2Smrg#if OPT_RENDERFONT 173720d2c4d2Smrgvoid 173820d2c4d2SmrgxtermCloseXft(TScreen * screen, XTermXftFonts * pub) 173920d2c4d2Smrg{ 174020d2c4d2Smrg if (pub->font != 0) { 174120d2c4d2Smrg XftFontClose(screen->display, pub->font); 174220d2c4d2Smrg pub->font = 0; 174320d2c4d2Smrg } 174420d2c4d2Smrg} 174520d2c4d2Smrg 174620d2c4d2Smrg/* 174720d2c4d2Smrg * Get the faceName/faceDoublesize resource setting. Strip off "xft:", which 174820d2c4d2Smrg * is not recognized by XftParseName(). 174920d2c4d2Smrg */ 1750492d43a5SmrgString 175120d2c4d2SmrggetFaceName(XtermWidget xw, Bool wideName GCC_UNUSED) 175220d2c4d2Smrg{ 175320d2c4d2Smrg#if OPT_RENDERWIDE 1754492d43a5Smrg String result = (wideName 1755492d43a5Smrg ? xw->misc.face_wide_name 1756492d43a5Smrg : xw->misc.face_name); 175720d2c4d2Smrg#else 1758492d43a5Smrg String result = xw->misc.face_name; 175920d2c4d2Smrg#endif 176020d2c4d2Smrg if (!IsEmpty(result) && !strncmp(result, "xft:", (size_t) 4)) 176120d2c4d2Smrg result += 4; 176220d2c4d2Smrg return x_nonempty(result); 176320d2c4d2Smrg} 176420d2c4d2Smrg 176520d2c4d2Smrg/* 176620d2c4d2Smrg * If we change the faceName, we'll have to re-acquire all of the fonts that 176720d2c4d2Smrg * are derived from it. 176820d2c4d2Smrg */ 176920d2c4d2Smrgvoid 177020d2c4d2SmrgsetFaceName(XtermWidget xw, const char *value) 177120d2c4d2Smrg{ 177220d2c4d2Smrg TScreen *screen = TScreenOf(xw); 177320d2c4d2Smrg int n; 177420d2c4d2Smrg 177520d2c4d2Smrg xw->misc.face_name = x_strdup(value); 177620d2c4d2Smrg for (n = 0; n < NMENUFONTS; ++n) { 177720d2c4d2Smrg xw->misc.face_size[n] = -1.0; 177820d2c4d2Smrg xtermCloseXft(screen, &(screen->renderFontNorm[n])); 177920d2c4d2Smrg xtermCloseXft(screen, &(screen->renderFontBold[n])); 178020d2c4d2Smrg xtermCloseXft(screen, &(screen->renderFontBold[n])); 178120d2c4d2Smrg#if OPT_RENDERWIDE 178220d2c4d2Smrg xtermCloseXft(screen, &(screen->renderWideNorm[n])); 178320d2c4d2Smrg xtermCloseXft(screen, &(screen->renderWideBold[n])); 178420d2c4d2Smrg xtermCloseXft(screen, &(screen->renderWideItal[n])); 178520d2c4d2Smrg#endif 178620d2c4d2Smrg } 178720d2c4d2Smrg} 178820d2c4d2Smrg#endif 178920d2c4d2Smrg 1790d522f475Smrg/* 1791d522f475Smrg * Compute useful values for the font/window sizes 1792d522f475Smrg */ 1793d522f475Smrgvoid 1794d522f475SmrgxtermComputeFontInfo(XtermWidget xw, 1795d522f475Smrg VTwin * win, 1796d522f475Smrg XFontStruct * font, 1797d522f475Smrg int sbwidth) 1798d522f475Smrg{ 1799956cc18dSsnj TScreen *screen = TScreenOf(xw); 1800d522f475Smrg 1801d522f475Smrg int i, j, width, height; 1802492d43a5Smrg#if OPT_RENDERFONT 1803492d43a5Smrg int fontnum = screen->menu_font_number; 1804492d43a5Smrg#endif 1805d522f475Smrg 1806d522f475Smrg#if OPT_RENDERFONT 1807d522f475Smrg /* 1808d522f475Smrg * xterm contains a lot of references to fonts, assuming they are fixed 1809d522f475Smrg * size. This chunk of code overrides the actual font-selection (see 1810d522f475Smrg * drawXtermText()), if the user has selected render-font. All of the 1811d522f475Smrg * font-loading for fixed-fonts still goes on whether or not this chunk 1812d522f475Smrg * overrides it. 1813d522f475Smrg */ 1814492d43a5Smrg if (UsingRenderFont(xw) && fontnum >= 0) { 1815492d43a5Smrg String face_name = getFaceName(xw, False); 1816956cc18dSsnj XftFont *norm = screen->renderFontNorm[fontnum].font; 1817956cc18dSsnj XftFont *bold = screen->renderFontBold[fontnum].font; 1818956cc18dSsnj XftFont *ital = screen->renderFontItal[fontnum].font; 1819d522f475Smrg#if OPT_RENDERWIDE 1820956cc18dSsnj XftFont *wnorm = screen->renderWideNorm[fontnum].font; 1821956cc18dSsnj XftFont *wbold = screen->renderWideBold[fontnum].font; 1822956cc18dSsnj XftFont *wital = screen->renderWideItal[fontnum].font; 1823d522f475Smrg#endif 1824d522f475Smrg 182520d2c4d2Smrg if (norm == 0 && face_name) { 1826d522f475Smrg XftPattern *pat; 1827d522f475Smrg double face_size = xw->misc.face_size[fontnum]; 1828d522f475Smrg 1829492d43a5Smrg TRACE(("xtermComputeFontInfo font %d: norm(face %s, size %f)\n", 1830492d43a5Smrg fontnum, face_name, 1831d522f475Smrg xw->misc.face_size[fontnum])); 1832d522f475Smrg 1833d522f475Smrg if (face_size <= 0.0) { 1834d522f475Smrg#if OPT_SHIFT_FONTS 1835d522f475Smrg /* 1836d522f475Smrg * If the user is switching font-sizes, make it follow by 1837d522f475Smrg * default the same ratios to the default as the fixed fonts 1838d522f475Smrg * would, for easy comparison. There will be some differences 1839d522f475Smrg * since the fixed fonts have a variety of height/width ratios, 1840d522f475Smrg * but this is simpler than adding another resource value - and 1841d522f475Smrg * as noted above, the data for the fixed fonts are available. 1842d522f475Smrg */ 1843d522f475Smrg lookupOneFontSize(xw, 0); 1844d522f475Smrg lookupOneFontSize(xw, fontnum); 1845d522f475Smrg if (fontnum == fontMenu_default) { 1846d522f475Smrg face_size = 14.0; 1847d522f475Smrg } else { 1848d522f475Smrg double ratio; 184920d2c4d2Smrg long num = screen->menu_font_sizes[fontnum]; 185020d2c4d2Smrg long den = screen->menu_font_sizes[0]; 1851d522f475Smrg 1852d522f475Smrg if (den <= 0) 1853d522f475Smrg den = 1; 185420d2c4d2Smrg ratio = mySquareRoot((double) num / (double) den); 1855d522f475Smrg 1856d522f475Smrg face_size = (ratio * xw->misc.face_size[0]); 185720d2c4d2Smrg TRACE(("scaled using %3ld/%ld = %.2f -> %f\n", 1858d522f475Smrg num, den, ratio, face_size)); 1859d522f475Smrg } 1860d522f475Smrg#else 1861d522f475Smrg switch (fontnum) { 1862d522f475Smrg case fontMenu_font1: 1863d522f475Smrg face_size = 8.0; 1864d522f475Smrg break; 1865d522f475Smrg case fontMenu_font2: 1866d522f475Smrg face_size = 10.0; 1867d522f475Smrg break; 1868d522f475Smrg case fontMenu_font3: 1869d522f475Smrg face_size = 12.0; 1870d522f475Smrg break; 1871d522f475Smrg default: 1872d522f475Smrg face_size = 14.0; 1873d522f475Smrg break; 1874d522f475Smrg case fontMenu_font4: 1875d522f475Smrg face_size = 16.0; 1876d522f475Smrg break; 1877d522f475Smrg case fontMenu_font5: 1878d522f475Smrg face_size = 18.0; 1879d522f475Smrg break; 1880d522f475Smrg case fontMenu_font6: 1881d522f475Smrg face_size = 20.0; 1882d522f475Smrg break; 1883d522f475Smrg } 1884d522f475Smrg#endif 1885956cc18dSsnj xw->misc.face_size[fontnum] = (float) face_size; 1886d522f475Smrg } 1887d522f475Smrg 1888d522f475Smrg /* 1889d522f475Smrg * By observation (there is no documentation), XftPatternBuild is 1890d522f475Smrg * cumulative. Build the bold- and italic-patterns on top of the 1891d522f475Smrg * normal pattern. 1892d522f475Smrg */ 1893d522f475Smrg#define NormXftPattern \ 1894d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 1895d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 1896d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 1897d522f475Smrg 1898d522f475Smrg#define BoldXftPattern(norm) \ 1899d522f475Smrg XFT_WEIGHT, XftTypeInteger, XFT_WEIGHT_BOLD, \ 1900d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 1901d522f475Smrg 1902d522f475Smrg#define ItalXftPattern(norm) \ 1903d522f475Smrg XFT_SLANT, XftTypeInteger, XFT_SLANT_ITALIC, \ 1904d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 1905d522f475Smrg 190620d2c4d2Smrg if ((pat = XftNameParse(face_name)) != 0) { 190720d2c4d2Smrg#define OPEN_XFT(tag) xtermOpenXft(xw, face_name, pat, tag) 1908d522f475Smrg XftPatternBuild(pat, 1909d522f475Smrg NormXftPattern, 1910d522f475Smrg (void *) 0); 1911956cc18dSsnj norm = OPEN_XFT("normal"); 1912d522f475Smrg 1913d522f475Smrg if (norm != 0) { 1914d522f475Smrg XftPatternBuild(pat, 1915d522f475Smrg BoldXftPattern(norm), 1916d522f475Smrg (void *) 0); 1917956cc18dSsnj bold = OPEN_XFT("bold"); 1918d522f475Smrg 1919d522f475Smrg#if OPT_ISO_COLORS 1920d522f475Smrg if (screen->italicULMode 192120d2c4d2Smrg && (pat = XftNameParse(face_name)) != 0) { 1922d522f475Smrg XftPatternBuild(pat, 1923d522f475Smrg NormXftPattern, 1924d522f475Smrg ItalXftPattern(norm), 1925d522f475Smrg (void *) 0); 1926956cc18dSsnj ital = OPEN_XFT("italic"); 1927d522f475Smrg } 1928d522f475Smrg#endif /* OPT_ISO_COLORS */ 1929956cc18dSsnj#undef OPEN_XFT 1930d522f475Smrg 1931d522f475Smrg /* 1932d522f475Smrg * FIXME: just assume that the corresponding font has no 1933d522f475Smrg * graphics characters. 1934d522f475Smrg */ 1935d522f475Smrg if (screen->fnt_boxes) { 1936d522f475Smrg screen->fnt_boxes = False; 1937d522f475Smrg TRACE(("Xft opened - will %suse internal line-drawing characters\n", 1938d522f475Smrg screen->fnt_boxes ? "not " : "")); 1939d522f475Smrg } 1940d522f475Smrg } 1941d522f475Smrg 1942d522f475Smrg XftPatternDestroy(pat); 1943d522f475Smrg } 1944d522f475Smrg 1945d522f475Smrg CACHE_XFT(screen->renderFontNorm, norm); 1946d522f475Smrg CACHE_XFT(screen->renderFontBold, bold); 1947d522f475Smrg CACHE_XFT(screen->renderFontItal, ital); 1948d522f475Smrg 1949d522f475Smrg /* 1950d522f475Smrg * See xtermXftDrawString(). 1951d522f475Smrg */ 1952d522f475Smrg#if OPT_RENDERWIDE 1953d522f475Smrg if (norm != 0 && screen->wide_chars) { 1954d522f475Smrg int char_width = norm->max_advance_width * 2; 1955956cc18dSsnj#ifdef FC_ASPECT 1956956cc18dSsnj double aspect = ((xw->misc.face_wide_name 1957956cc18dSsnj || screen->renderFontNorm[fontnum].map.mixed) 1958956cc18dSsnj ? 1.0 1959956cc18dSsnj : 2.0); 1960956cc18dSsnj#endif 1961d522f475Smrg 196220d2c4d2Smrg face_name = getFaceName(xw, True); 1963d522f475Smrg TRACE(("xtermComputeFontInfo wide(face %s, char_width %d)\n", 196420d2c4d2Smrg NonNull(face_name), 1965d522f475Smrg char_width)); 1966d522f475Smrg 1967d522f475Smrg#define WideXftPattern \ 1968d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 1969d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 1970d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 1971d522f475Smrg 197220d2c4d2Smrg if (face_name && (pat = XftNameParse(face_name)) != 0) { 1973956cc18dSsnj#define OPEN_XFT(tag) xtermOpenXft(xw, face_name, pat, tag) 1974d522f475Smrg XftPatternBuild(pat, 1975d522f475Smrg WideXftPattern, 1976d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, char_width, 1977956cc18dSsnj#ifdef FC_ASPECT 1978956cc18dSsnj FC_ASPECT, XftTypeDouble, aspect, 1979956cc18dSsnj#endif 1980d522f475Smrg (void *) 0); 1981956cc18dSsnj wnorm = OPEN_XFT("wide"); 1982d522f475Smrg 1983d522f475Smrg if (wnorm != 0) { 1984d522f475Smrg XftPatternBuild(pat, 1985d522f475Smrg WideXftPattern, 1986d522f475Smrg BoldXftPattern(wnorm), 1987d522f475Smrg (void *) 0); 1988956cc18dSsnj wbold = OPEN_XFT("wide-bold"); 1989d522f475Smrg 1990d522f475Smrg#if OPT_ISO_COLORS 1991d522f475Smrg if (screen->italicULMode 1992d522f475Smrg && (pat = XftNameParse(face_name)) != 0) { 1993d522f475Smrg XftPatternBuild(pat, 1994d522f475Smrg WideXftPattern, 1995d522f475Smrg ItalXftPattern(wnorm), 1996d522f475Smrg (void *) 0); 1997956cc18dSsnj wital = OPEN_XFT("wide-italic"); 1998d522f475Smrg } 1999d522f475Smrg#endif 2000956cc18dSsnj#undef OPEN_XFT 2001d522f475Smrg } 2002d522f475Smrg XftPatternDestroy(pat); 2003d522f475Smrg } 2004d522f475Smrg 2005d522f475Smrg CACHE_XFT(screen->renderWideNorm, wnorm); 2006d522f475Smrg CACHE_XFT(screen->renderWideBold, wbold); 2007d522f475Smrg CACHE_XFT(screen->renderWideItal, wital); 2008d522f475Smrg } 2009d522f475Smrg#endif /* OPT_RENDERWIDE */ 2010d522f475Smrg } 2011d522f475Smrg if (norm == 0) { 20122eaa94a1Schristos TRACE(("...no TrueType font found for number %d, disable menu entry\n", fontnum)); 2013d522f475Smrg xw->misc.render_font = False; 2014d522f475Smrg update_font_renderfont(); 2015d522f475Smrg /* now we will fall through into the bitmap fonts */ 2016d522f475Smrg } else { 2017d522f475Smrg setRenderFontsize(screen, win, norm, NULL); 2018d522f475Smrg setRenderFontsize(screen, win, bold, "bold"); 2019d522f475Smrg setRenderFontsize(screen, win, ital, "ital"); 202020d2c4d2Smrg#if OPT_BOX_CHARS 202120d2c4d2Smrg setupPackedFonts(xw); 202220d2c4d2Smrg 202320d2c4d2Smrg if (screen->force_packed) { 202420d2c4d2Smrg XTermXftFonts *use = &(screen->renderFontNorm[fontnum]); 202520d2c4d2Smrg win->f_height = use->font->ascent + use->font->descent; 202620d2c4d2Smrg win->f_width = use->map.min_width; 202720d2c4d2Smrg TRACE(("...packed TrueType font %dx%d vs %d\n", 202820d2c4d2Smrg win->f_height, 202920d2c4d2Smrg win->f_width, 203020d2c4d2Smrg use->map.max_width)); 203120d2c4d2Smrg } 203220d2c4d2Smrg#endif 203320d2c4d2Smrg DUMP_XFT(xw, &(screen->renderFontNorm[fontnum])); 2034d522f475Smrg } 2035d522f475Smrg } 2036d522f475Smrg /* 2037d522f475Smrg * Are we handling a bitmap font? 2038d522f475Smrg */ 2039492d43a5Smrg else 2040d522f475Smrg#endif /* OPT_RENDERFONT */ 2041d522f475Smrg { 204220d2c4d2Smrg if (is_double_width_font(font) && !(screen->fnt_prop)) { 2043d522f475Smrg win->f_width = (font->min_bounds.width); 2044d522f475Smrg } else { 2045d522f475Smrg win->f_width = (font->max_bounds.width); 2046d522f475Smrg } 2047d522f475Smrg win->f_height = (font->ascent + font->descent); 2048d522f475Smrg win->f_ascent = font->ascent; 2049d522f475Smrg win->f_descent = font->descent; 2050d522f475Smrg } 2051d522f475Smrg i = 2 * screen->border + sbwidth; 2052d522f475Smrg j = 2 * screen->border; 2053d522f475Smrg width = MaxCols(screen) * win->f_width + i; 2054d522f475Smrg height = MaxRows(screen) * win->f_height + j; 2055956cc18dSsnj win->fullwidth = (Dimension) width; 2056956cc18dSsnj win->fullheight = (Dimension) height; 2057d522f475Smrg win->width = width - i; 2058d522f475Smrg win->height = height - j; 2059d522f475Smrg 2060d522f475Smrg TRACE(("xtermComputeFontInfo window %dx%d (full %dx%d), fontsize %dx%d (asc %d, dsc %d)\n", 2061d522f475Smrg win->height, 2062d522f475Smrg win->width, 2063d522f475Smrg win->fullheight, 2064d522f475Smrg win->fullwidth, 2065d522f475Smrg win->f_height, 2066d522f475Smrg win->f_width, 2067d522f475Smrg win->f_ascent, 2068d522f475Smrg win->f_descent)); 206920d2c4d2Smrg 207020d2c4d2Smrg checkFontInfo(win->f_height, "height"); 207120d2c4d2Smrg checkFontInfo(win->f_width, "width"); 2072d522f475Smrg} 2073d522f475Smrg 2074d522f475Smrg/* save this information as a side-effect for double-sized characters */ 2075d522f475Smrgvoid 2076d522f475SmrgxtermSaveFontInfo(TScreen * screen, XFontStruct * font) 2077d522f475Smrg{ 2078956cc18dSsnj screen->fnt_wide = (Dimension) (font->max_bounds.width); 2079956cc18dSsnj screen->fnt_high = (Dimension) (font->ascent + font->descent); 2080d522f475Smrg TRACE(("xtermSaveFontInfo %dx%d\n", screen->fnt_high, screen->fnt_wide)); 2081d522f475Smrg} 2082d522f475Smrg 2083d522f475Smrg/* 2084d522f475Smrg * After loading a new font, update the structures that use its size. 2085d522f475Smrg */ 2086d522f475Smrgvoid 2087d522f475SmrgxtermUpdateFontInfo(XtermWidget xw, Bool doresize) 2088d522f475Smrg{ 2089956cc18dSsnj TScreen *screen = TScreenOf(xw); 2090d522f475Smrg 2091d522f475Smrg int scrollbar_width; 2092d522f475Smrg VTwin *win = &(screen->fullVwin); 2093d522f475Smrg 2094d522f475Smrg scrollbar_width = (xw->misc.scrollbar 2095d522f475Smrg ? (screen->scrollWidget->core.width + 2096d522f475Smrg BorderWidth(screen->scrollWidget)) 2097d522f475Smrg : 0); 2098d522f475Smrg xtermComputeFontInfo(xw, win, screen->fnts[fNorm].fs, scrollbar_width); 2099d522f475Smrg xtermSaveFontInfo(screen, screen->fnts[fNorm].fs); 2100d522f475Smrg 2101d522f475Smrg if (doresize) { 2102d522f475Smrg if (VWindow(screen)) { 2103d522f475Smrg xtermClear(xw); 2104d522f475Smrg } 2105d522f475Smrg TRACE(("xtermUpdateFontInfo {{\n")); 2106d522f475Smrg DoResizeScreen(xw); /* set to the new natural size */ 2107d522f475Smrg ResizeScrollBar(xw); 2108d522f475Smrg Redraw(); 2109d522f475Smrg TRACE(("... }} xtermUpdateFontInfo\n")); 2110d522f475Smrg#ifdef SCROLLBAR_RIGHT 2111d522f475Smrg updateRightScrollbar(xw); 2112d522f475Smrg#endif 2113d522f475Smrg } 2114d522f475Smrg xtermSetCursorBox(screen); 2115d522f475Smrg} 2116d522f475Smrg 2117d522f475Smrg#if OPT_BOX_CHARS 2118d522f475Smrg 2119d522f475Smrg/* 2120d522f475Smrg * Returns true if the given character is missing from the specified font. 2121d522f475Smrg */ 2122d522f475SmrgBool 2123956cc18dSsnjxtermMissingChar(unsigned ch, XTermFonts * font) 2124d522f475Smrg{ 2125956cc18dSsnj Bool result = False; 2126956cc18dSsnj XFontStruct *fs = font->fs; 2127956cc18dSsnj static XCharStruct dft, *tmp = &dft, *pc = 0; 2128d522f475Smrg 2129956cc18dSsnj if (fs->max_byte1 == 0) { 2130d522f475Smrg#if OPT_WIDE_CHARS 2131956cc18dSsnj if (ch > 255) { 2132956cc18dSsnj TRACE(("xtermMissingChar %#04x (row)\n", ch)); 2133956cc18dSsnj return True; 2134d522f475Smrg } 2135956cc18dSsnj#endif 2136956cc18dSsnj CI_GET_CHAR_INFO_1D(fs, E2A(ch), tmp, pc); 2137956cc18dSsnj } 2138d522f475Smrg#if OPT_WIDE_CHARS 2139956cc18dSsnj else { 2140956cc18dSsnj CI_GET_CHAR_INFO_2D(fs, HI_BYTE(ch), LO_BYTE(ch), tmp, pc); 2141956cc18dSsnj } 2142d522f475Smrg#else 2143d522f475Smrg 2144956cc18dSsnj if (!pc) 2145956cc18dSsnj return False; /* Urgh! */ 2146d522f475Smrg#endif 2147d522f475Smrg 2148956cc18dSsnj if (CI_NONEXISTCHAR(pc)) { 2149956cc18dSsnj TRACE(("xtermMissingChar %#04x (!exists)\n", ch)); 2150956cc18dSsnj result = True; 2151d522f475Smrg } 2152956cc18dSsnj if (ch < 256) { 2153956cc18dSsnj font->known_missing[ch] = (Char) (result ? 2 : 1); 2154d522f475Smrg } 2155956cc18dSsnj return result; 2156d522f475Smrg} 2157d522f475Smrg 2158d522f475Smrg/* 2159d522f475Smrg * The grid is arbitrary, enough resolution that nothing's lost in 2160d522f475Smrg * initialization. 2161d522f475Smrg */ 2162d522f475Smrg#define BOX_HIGH 60 2163d522f475Smrg#define BOX_WIDE 60 2164d522f475Smrg 2165d522f475Smrg#define MID_HIGH (BOX_HIGH/2) 2166d522f475Smrg#define MID_WIDE (BOX_WIDE/2) 2167d522f475Smrg 2168d522f475Smrg#define CHR_WIDE ((9*BOX_WIDE)/10) 2169d522f475Smrg#define CHR_HIGH ((9*BOX_HIGH)/10) 2170d522f475Smrg 2171d522f475Smrg/* 2172d522f475Smrg * ...since we'll scale the values anyway. 2173d522f475Smrg */ 2174956cc18dSsnj#define SCALE_X(n) n = (n * (((int) font_width) - 1)) / (BOX_WIDE-1) 2175956cc18dSsnj#define SCALE_Y(n) n = (n * (((int) font_height) - 1)) / (BOX_HIGH-1) 2176d522f475Smrg 2177d522f475Smrg#define SEG(x0,y0,x1,y1) x0,y0, x1,y1 2178d522f475Smrg 2179d522f475Smrg/* 2180d522f475Smrg * Draw the given graphic character, if it is simple enough (i.e., a 2181d522f475Smrg * line-drawing character). 2182d522f475Smrg */ 2183d522f475Smrgvoid 2184d522f475SmrgxtermDrawBoxChar(XtermWidget xw, 2185d522f475Smrg unsigned ch, 2186d522f475Smrg unsigned flags, 2187d522f475Smrg GC gc, 2188d522f475Smrg int x, 2189d522f475Smrg int y, 2190d522f475Smrg int cells) 2191d522f475Smrg{ 2192956cc18dSsnj TScreen *screen = TScreenOf(xw); 2193d522f475Smrg /* *INDENT-OFF* */ 2194d522f475Smrg static const short glyph_ht[] = { 2195d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,5*MID_HIGH/6), /* H */ 2196d522f475Smrg SEG(6*BOX_WIDE/10, 0, 6*BOX_WIDE/10,5*MID_HIGH/6), 2197d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*BOX_WIDE/10,5*MID_HIGH/12), 2198d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 2199d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 2200d522f475Smrg -1 2201d522f475Smrg }, glyph_ff[] = { 2202d522f475Smrg SEG(1*BOX_WIDE/10, 0, 6*BOX_WIDE/10, 0), /* F */ 2203d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*CHR_WIDE/12,5*MID_HIGH/12), 2204d522f475Smrg SEG(1*BOX_WIDE/10, 0, 0*BOX_WIDE/3, 5*MID_HIGH/6), 2205d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 2206d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 2207d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 2208d522f475Smrg -1 2209d522f475Smrg }, glyph_lf[] = { 2210d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,9*MID_HIGH/12), /* L */ 2211d522f475Smrg SEG(1*BOX_WIDE/10,9*MID_HIGH/12,6*BOX_WIDE/10,9*MID_HIGH/12), 2212d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 2213d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 2214d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 2215d522f475Smrg -1 2216d522f475Smrg }, glyph_nl[] = { 2217d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/6, 1*BOX_WIDE/10, 0), /* N */ 2218d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/6, 5*MID_HIGH/6), 2219d522f475Smrg SEG(5*BOX_WIDE/6, 5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 2220d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), /* L */ 2221d522f475Smrg SEG(1*BOX_WIDE/3, CHR_HIGH, CHR_WIDE, CHR_HIGH), 2222d522f475Smrg -1 2223d522f475Smrg }, glyph_vt[] = { 2224d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/12,5*MID_HIGH/6), /* V */ 2225d522f475Smrg SEG(5*BOX_WIDE/12,5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 2226d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 2227d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 2228d522f475Smrg -1 2229d522f475Smrg }, plus_or_minus[] = 2230d522f475Smrg { 2231d522f475Smrg SEG( 0, 5*BOX_HIGH/6, CHR_WIDE, 5*BOX_HIGH/6), 2232d522f475Smrg SEG( MID_WIDE, 2*BOX_HIGH/6, MID_WIDE, 4*BOX_HIGH/6), 2233d522f475Smrg SEG( 0, 3*BOX_HIGH/6, CHR_WIDE, 3*BOX_HIGH/6), 2234d522f475Smrg -1 2235d522f475Smrg }, lower_right_corner[] = 2236d522f475Smrg { 2237d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 2238d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, 0), 2239d522f475Smrg -1 2240d522f475Smrg }, upper_right_corner[] = 2241d522f475Smrg { 2242d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 2243d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2244d522f475Smrg -1 2245d522f475Smrg }, upper_left_corner[] = 2246d522f475Smrg { 2247d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 2248d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2249d522f475Smrg -1 2250d522f475Smrg }, lower_left_corner[] = 2251d522f475Smrg { 2252d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 2253d522f475Smrg SEG( MID_WIDE, MID_WIDE, BOX_WIDE, MID_HIGH), 2254d522f475Smrg -1 2255d522f475Smrg }, cross[] = 2256d522f475Smrg { 2257d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2258d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2259d522f475Smrg -1 2260d522f475Smrg }, scan_line_1[] = 2261d522f475Smrg { 2262d522f475Smrg SEG( 0, 0, BOX_WIDE, 0), 2263d522f475Smrg -1 2264d522f475Smrg }, scan_line_3[] = 2265d522f475Smrg { 2266d522f475Smrg SEG( 0, BOX_HIGH/4, BOX_WIDE, BOX_HIGH/4), 2267d522f475Smrg -1 2268d522f475Smrg }, scan_line_7[] = 2269d522f475Smrg { 2270d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2271d522f475Smrg -1 2272d522f475Smrg }, scan_line_9[] = 2273d522f475Smrg { 2274d522f475Smrg SEG( 0, 3*BOX_HIGH/4, BOX_WIDE, 3*BOX_HIGH/4), 2275d522f475Smrg -1 2276d522f475Smrg }, horizontal_line[] = 2277d522f475Smrg { 2278d522f475Smrg SEG( 0, BOX_HIGH, BOX_WIDE, BOX_HIGH), 2279d522f475Smrg -1 2280d522f475Smrg }, left_tee[] = 2281d522f475Smrg { 2282d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2283d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 2284d522f475Smrg -1 2285d522f475Smrg }, right_tee[] = 2286d522f475Smrg { 2287d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2288d522f475Smrg SEG( MID_WIDE, MID_HIGH, 0, MID_HIGH), 2289d522f475Smrg -1 2290d522f475Smrg }, bottom_tee[] = 2291d522f475Smrg { 2292d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2293d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 2294d522f475Smrg -1 2295d522f475Smrg }, top_tee[] = 2296d522f475Smrg { 2297d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2298d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2299d522f475Smrg -1 2300d522f475Smrg }, vertical_line[] = 2301d522f475Smrg { 2302d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2303d522f475Smrg -1 2304d522f475Smrg }, less_than_or_equal[] = 2305d522f475Smrg { 2306d522f475Smrg SEG( CHR_WIDE, BOX_HIGH/3, 0, MID_HIGH), 2307d522f475Smrg SEG( CHR_WIDE, 2*BOX_HIGH/3, 0, MID_HIGH), 2308d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 2309d522f475Smrg -1 2310d522f475Smrg }, greater_than_or_equal[] = 2311d522f475Smrg { 2312d522f475Smrg SEG( 0, BOX_HIGH/3, CHR_WIDE, MID_HIGH), 2313d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, MID_HIGH), 2314d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 2315d522f475Smrg -1 2316d522f475Smrg }, greek_pi[] = 2317d522f475Smrg { 2318d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 2319d522f475Smrg SEG(5*CHR_WIDE/6, MID_HIGH, 5*CHR_WIDE/6, CHR_HIGH), 2320d522f475Smrg SEG(2*CHR_WIDE/6, MID_HIGH, 2*CHR_WIDE/6, CHR_HIGH), 2321d522f475Smrg -1 2322d522f475Smrg }, not_equal_to[] = 2323d522f475Smrg { 2324d522f475Smrg SEG(2*BOX_WIDE/3, 1*BOX_HIGH/3, 1*BOX_WIDE/3, CHR_HIGH), 2325d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, 2*BOX_HIGH/3), 2326d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 2327d522f475Smrg -1 2328d522f475Smrg }; 2329d522f475Smrg /* *INDENT-ON* */ 2330d522f475Smrg 2331d522f475Smrg static const short *lines[] = 2332d522f475Smrg { 2333d522f475Smrg 0, /* 00 (unused) */ 2334d522f475Smrg 0, /* 01 diamond */ 2335d522f475Smrg 0, /* 02 box */ 2336d522f475Smrg glyph_ht, /* 03 HT */ 2337d522f475Smrg glyph_ff, /* 04 FF */ 2338d522f475Smrg 0, /* 05 CR */ 2339d522f475Smrg glyph_lf, /* 06 LF */ 2340d522f475Smrg 0, /* 07 degrees (small circle) */ 2341d522f475Smrg plus_or_minus, /* 08 */ 2342d522f475Smrg glyph_nl, /* 09 */ 2343d522f475Smrg glyph_vt, /* 0A */ 2344d522f475Smrg lower_right_corner, /* 0B */ 2345d522f475Smrg upper_right_corner, /* 0C */ 2346d522f475Smrg upper_left_corner, /* 0D */ 2347d522f475Smrg lower_left_corner, /* 0E */ 2348d522f475Smrg cross, /* 0F */ 2349d522f475Smrg scan_line_1, /* 10 */ 2350d522f475Smrg scan_line_3, /* 11 */ 2351d522f475Smrg scan_line_7, /* 12 */ 2352d522f475Smrg scan_line_9, /* 13 */ 2353d522f475Smrg horizontal_line, /* 14 */ 2354d522f475Smrg left_tee, /* 15 */ 2355d522f475Smrg right_tee, /* 16 */ 2356d522f475Smrg bottom_tee, /* 17 */ 2357d522f475Smrg top_tee, /* 18 */ 2358d522f475Smrg vertical_line, /* 19 */ 2359d522f475Smrg less_than_or_equal, /* 1A */ 2360d522f475Smrg greater_than_or_equal, /* 1B */ 2361d522f475Smrg greek_pi, /* 1C */ 2362d522f475Smrg not_equal_to, /* 1D */ 2363d522f475Smrg 0, /* 1E LB */ 2364d522f475Smrg 0, /* 1F bullet */ 2365d522f475Smrg }; 2366d522f475Smrg 2367d522f475Smrg GC gc2; 2368d522f475Smrg CgsEnum cgsId = (ch == 2) ? gcDots : gcLine; 2369d522f475Smrg VTwin *cgsWin = WhichVWin(screen); 2370d522f475Smrg const short *p; 2371956cc18dSsnj unsigned font_width = (unsigned) (((flags & DOUBLEWFONT) ? 2 : 1) * screen->fnt_wide); 2372956cc18dSsnj unsigned font_height = (unsigned) (((flags & DOUBLEHFONT) ? 2 : 1) * screen->fnt_high); 2373d522f475Smrg 2374d522f475Smrg if (cells > 1) 2375956cc18dSsnj font_width *= (unsigned) cells; 2376d522f475Smrg 2377d522f475Smrg#if OPT_WIDE_CHARS 2378d522f475Smrg /* 2379d522f475Smrg * Try to show line-drawing characters if we happen to be in UTF-8 2380d522f475Smrg * mode, but have gotten an old-style font. 2381d522f475Smrg */ 2382d522f475Smrg if (screen->utf8_mode 2383d522f475Smrg#if OPT_RENDERFONT 2384d522f475Smrg && !UsingRenderFont(xw) 2385d522f475Smrg#endif 2386d522f475Smrg && (ch > 127) 2387d522f475Smrg && (ch != UCS_REPL)) { 2388d522f475Smrg unsigned n; 2389d522f475Smrg for (n = 1; n < 32; n++) { 2390d522f475Smrg if (dec2ucs(n) == ch 239120d2c4d2Smrg && !((flags & BOLD) 239220d2c4d2Smrg ? IsXtermMissingChar(screen, n, &screen->fnts[fBold]) 239320d2c4d2Smrg : IsXtermMissingChar(screen, n, &screen->fnts[fNorm]))) { 2394d522f475Smrg TRACE(("...use xterm-style linedrawing\n")); 2395d522f475Smrg ch = n; 2396d522f475Smrg break; 2397d522f475Smrg } 2398d522f475Smrg } 2399d522f475Smrg } 2400d522f475Smrg#endif 2401d522f475Smrg 2402d522f475Smrg TRACE(("DRAW_BOX(%d) cell %dx%d at %d,%d%s\n", 2403d522f475Smrg ch, font_height, font_width, y, x, 2404d522f475Smrg (ch >= (sizeof(lines) / sizeof(lines[0])) 2405d522f475Smrg ? "-BAD" 2406d522f475Smrg : ""))); 2407d522f475Smrg 2408d522f475Smrg if (cgsId == gcDots) { 2409d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2410d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2411d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2412d522f475Smrg } else { 2413d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2414d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2415d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2416d522f475Smrg } 2417d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2418d522f475Smrg 2419d522f475Smrg if (!(flags & NOBACKGROUND)) { 2420d522f475Smrg XFillRectangle(screen->display, VWindow(screen), gc2, x, y, 2421d522f475Smrg font_width, 2422d522f475Smrg font_height); 2423d522f475Smrg } 2424d522f475Smrg 2425d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2426d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2427d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2428d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2429d522f475Smrg 2430d522f475Smrg XSetLineAttributes(screen->display, gc2, 2431d522f475Smrg (flags & BOLD) 2432d522f475Smrg ? ((font_height > 12) 2433d522f475Smrg ? font_height / 12 2434d522f475Smrg : 1) 2435d522f475Smrg : ((font_height > 16) 2436d522f475Smrg ? font_height / 16 2437d522f475Smrg : 1), 2438d522f475Smrg LineSolid, 2439d522f475Smrg CapProjecting, 2440d522f475Smrg JoinMiter); 2441d522f475Smrg 2442d522f475Smrg if (ch == 1) { /* diamond */ 2443d522f475Smrg XPoint points[5]; 2444d522f475Smrg int npoints = 5, n; 2445d522f475Smrg 2446d522f475Smrg points[0].x = MID_WIDE; 2447d522f475Smrg points[0].y = BOX_HIGH / 4; 2448d522f475Smrg 2449d522f475Smrg points[1].x = 8 * BOX_WIDE / 8; 2450d522f475Smrg points[1].y = MID_HIGH; 2451d522f475Smrg 2452d522f475Smrg points[2].x = points[0].x; 2453d522f475Smrg points[2].y = 3 * BOX_HIGH / 4; 2454d522f475Smrg 2455d522f475Smrg points[3].x = 0 * BOX_WIDE / 8; 2456d522f475Smrg points[3].y = points[1].y; 2457d522f475Smrg 2458d522f475Smrg points[4].x = points[0].x; 2459d522f475Smrg points[4].y = points[0].y; 2460d522f475Smrg 2461d522f475Smrg for (n = 0; n < npoints; ++n) { 2462d522f475Smrg SCALE_X(points[n].x); 2463d522f475Smrg SCALE_Y(points[n].y); 2464d522f475Smrg points[n].x += x; 2465d522f475Smrg points[n].y += y; 2466d522f475Smrg } 2467d522f475Smrg 2468d522f475Smrg XFillPolygon(screen->display, 2469d522f475Smrg VWindow(screen), gc2, 2470d522f475Smrg points, npoints, 2471d522f475Smrg Convex, CoordModeOrigin); 2472d522f475Smrg } else if (ch == 7) { /* degrees */ 2473d522f475Smrg unsigned width = (BOX_WIDE / 3); 2474956cc18dSsnj int x_coord = MID_WIDE - (int) (width / 2); 2475956cc18dSsnj int y_coord = MID_HIGH - (int) width; 2476d522f475Smrg 2477d522f475Smrg SCALE_X(x_coord); 2478d522f475Smrg SCALE_Y(y_coord); 2479d522f475Smrg SCALE_X(width); 2480d522f475Smrg 2481d522f475Smrg XDrawArc(screen->display, 2482d522f475Smrg VWindow(screen), gc2, 2483d522f475Smrg x + x_coord, y + y_coord, width, width, 2484d522f475Smrg 0, 2485d522f475Smrg 360 * 64); 2486d522f475Smrg } else if (ch == 0x1f) { /* bullet */ 2487d522f475Smrg unsigned width = 7 * BOX_WIDE / 10; 2488956cc18dSsnj int x_coord = MID_WIDE - (int) (width / 3); 2489956cc18dSsnj int y_coord = MID_HIGH - (int) (width / 3); 2490d522f475Smrg 2491d522f475Smrg SCALE_X(x_coord); 2492d522f475Smrg SCALE_Y(y_coord); 2493d522f475Smrg SCALE_X(width); 2494d522f475Smrg 2495d522f475Smrg XDrawArc(screen->display, 2496d522f475Smrg VWindow(screen), gc2, 2497d522f475Smrg x + x_coord, y + y_coord, width, width, 2498d522f475Smrg 0, 2499d522f475Smrg 360 * 64); 2500d522f475Smrg } else if (ch < (sizeof(lines) / sizeof(lines[0])) 2501d522f475Smrg && (p = lines[ch]) != 0) { 2502956cc18dSsnj int coord[4]; 2503d522f475Smrg int n = 0; 2504d522f475Smrg while (*p >= 0) { 2505d522f475Smrg coord[n++] = *p++; 2506d522f475Smrg if (n == 4) { 2507d522f475Smrg SCALE_X(coord[0]); 2508d522f475Smrg SCALE_Y(coord[1]); 2509d522f475Smrg SCALE_X(coord[2]); 2510d522f475Smrg SCALE_Y(coord[3]); 2511d522f475Smrg XDrawLine(screen->display, 2512d522f475Smrg VWindow(screen), gc2, 2513d522f475Smrg x + coord[0], y + coord[1], 2514d522f475Smrg x + coord[2], y + coord[3]); 2515d522f475Smrg n = 0; 2516d522f475Smrg } 2517d522f475Smrg } 2518d522f475Smrg } else if (screen->force_all_chars) { 2519d522f475Smrg /* bounding rectangle, for debugging */ 2520d522f475Smrg XDrawRectangle(screen->display, VWindow(screen), gc2, x, y, 2521d522f475Smrg font_width - 1, 2522d522f475Smrg font_height - 1); 2523d522f475Smrg } 2524d522f475Smrg} 2525d522f475Smrg 2526d522f475Smrg#if OPT_RENDERFONT 2527d522f475Smrg 2528d522f475Smrg/* 2529d522f475Smrg * Check if the given character has a glyph known to Xft. 2530d522f475Smrg * 2531d522f475Smrg * see xc/lib/Xft/xftglyphs.c 2532d522f475Smrg */ 2533d522f475SmrgBool 2534d522f475SmrgxtermXftMissing(XtermWidget xw, XftFont * font, unsigned wc) 2535d522f475Smrg{ 2536d522f475Smrg Bool result = False; 2537d522f475Smrg 2538d522f475Smrg if (font != 0) { 2539956cc18dSsnj TScreen *screen = TScreenOf(xw); 2540956cc18dSsnj if (!XftGlyphExists(screen->display, font, wc)) { 2541d522f475Smrg#if OPT_WIDE_CHARS 2542d522f475Smrg TRACE(("xtermXftMissing %d (dec=%#x, ucs=%#x)\n", 2543d522f475Smrg wc, ucs2dec(wc), dec2ucs(wc))); 2544d522f475Smrg#else 2545d522f475Smrg TRACE(("xtermXftMissing %d\n", wc)); 2546d522f475Smrg#endif 2547d522f475Smrg result = True; 2548d522f475Smrg } 2549d522f475Smrg } 2550d522f475Smrg return result; 2551d522f475Smrg} 2552d522f475Smrg#endif /* OPT_RENDERFONT && OPT_WIDE_CHARS */ 2553d522f475Smrg 2554d522f475Smrg#endif /* OPT_BOX_CHARS */ 2555d522f475Smrg 2556d522f475Smrg#if OPT_WIDE_CHARS 2557d522f475Smrg#define MY_UCS(ucs,dec) case ucs: result = dec; break 2558d522f475Smrgunsigned 2559d522f475Smrgucs2dec(unsigned ch) 2560d522f475Smrg{ 2561d522f475Smrg unsigned result = ch; 2562d522f475Smrg if ((ch > 127) 2563d522f475Smrg && (ch != UCS_REPL)) { 2564d522f475Smrg switch (ch) { 2565d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 2566d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 2567d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 2568d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 2569d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 2570d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 2571d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 2572d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 2573d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 2574d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 2575d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 2576d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 2577d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 2578d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 2579d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 2580d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 2581d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 2582d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 2583d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 2584d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 2585d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 2586d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 2587d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 2588d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 2589d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 2590d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 2591d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 2592d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 2593d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 2594d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 2595d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 2596d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 2597d522f475Smrg } 2598d522f475Smrg } 2599d522f475Smrg return result; 2600d522f475Smrg} 2601d522f475Smrg 2602d522f475Smrg#undef MY_UCS 2603d522f475Smrg#define MY_UCS(ucs,dec) case dec: result = ucs; break 2604d522f475Smrg 2605d522f475Smrgunsigned 2606d522f475Smrgdec2ucs(unsigned ch) 2607d522f475Smrg{ 2608d522f475Smrg unsigned result = ch; 2609d522f475Smrg if (xtermIsDecGraphic(ch)) { 2610d522f475Smrg switch (ch) { 2611d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 2612d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 2613d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 2614d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 2615d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 2616d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 2617d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 2618d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 2619d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 2620d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 2621d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 2622d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 2623d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 2624d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 2625d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 2626d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 2627d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 2628d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 2629d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 2630d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 2631d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 2632d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 2633d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 2634d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 2635d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 2636d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 2637d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 2638d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 2639d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 2640d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 2641d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 2642d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 2643d522f475Smrg } 2644d522f475Smrg } 2645d522f475Smrg return result; 2646d522f475Smrg} 2647d522f475Smrg 2648d522f475Smrg#endif /* OPT_WIDE_CHARS */ 2649d522f475Smrg 2650d522f475Smrg#if OPT_SHIFT_FONTS 2651d522f475Smrgstatic void 2652d522f475SmrglookupOneFontSize(XtermWidget xw, int fontnum) 2653d522f475Smrg{ 2654d522f475Smrg TScreen *screen = TScreenOf(xw); 2655d522f475Smrg 2656d522f475Smrg if (screen->menu_font_sizes[fontnum] == 0) { 2657d522f475Smrg XTermFonts fnt; 2658d522f475Smrg 2659d522f475Smrg memset(&fnt, 0, sizeof(fnt)); 2660d522f475Smrg screen->menu_font_sizes[fontnum] = -1; 2661956cc18dSsnj if (xtermOpenFont(xw, screen->MenuFontName(fontnum), &fnt, fwAlways, True)) { 266220d2c4d2Smrg if (fontnum <= fontMenu_lastBuiltin 266320d2c4d2Smrg || strcmp(fnt.fn, DEFFONT)) 266420d2c4d2Smrg screen->menu_font_sizes[fontnum] = FontSize(fnt.fs); 2665d522f475Smrg xtermCloseFont(xw, &fnt); 2666d522f475Smrg } 2667d522f475Smrg } 2668d522f475Smrg} 2669d522f475Smrg 2670d522f475Smrg/* 2671d522f475Smrg * Cache the font-sizes so subsequent larger/smaller font actions will go fast. 2672d522f475Smrg */ 2673d522f475Smrgstatic void 2674d522f475SmrglookupFontSizes(XtermWidget xw) 2675d522f475Smrg{ 2676d522f475Smrg int n; 2677d522f475Smrg 2678d522f475Smrg for (n = 0; n < NMENUFONTS; n++) { 2679d522f475Smrg lookupOneFontSize(xw, n); 2680d522f475Smrg } 2681d522f475Smrg} 2682d522f475Smrg 26832eaa94a1Schristos#if OPT_RENDERFONT 26842eaa94a1Schristos#define NMENU_RENDERFONTS (NMENUFONTS - 2) /* no selection or escape */ 26852eaa94a1Schristosstatic Boolean 26862eaa94a1SchristosuseFaceSizes(XtermWidget xw) 26872eaa94a1Schristos{ 26882eaa94a1Schristos Boolean result = False; 26892eaa94a1Schristos int n; 26902eaa94a1Schristos 26912eaa94a1Schristos if (UsingRenderFont(xw)) { 26922eaa94a1Schristos result = True; 26932eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 26942eaa94a1Schristos if (xw->misc.face_size[n] <= 0.0) { 26952eaa94a1Schristos result = False; 26962eaa94a1Schristos break; 26972eaa94a1Schristos } 26982eaa94a1Schristos } 2699956cc18dSsnj if (!result) { 2700956cc18dSsnj Boolean broken_fonts = True; 2701956cc18dSsnj TScreen *screen = TScreenOf(xw); 270220d2c4d2Smrg long first = screen->menu_font_sizes[0]; 2703956cc18dSsnj 2704956cc18dSsnj lookupFontSizes(xw); 2705956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 2706956cc18dSsnj if (screen->menu_font_sizes[n] > 0 2707956cc18dSsnj && screen->menu_font_sizes[n] != first) { 2708956cc18dSsnj broken_fonts = False; 2709956cc18dSsnj break; 2710956cc18dSsnj } 2711956cc18dSsnj } 2712956cc18dSsnj 2713956cc18dSsnj /* 2714956cc18dSsnj * Workaround for breakage in font-packages - check if all of the 2715956cc18dSsnj * bitmap font sizes are the same, and if we're using TrueType 2716956cc18dSsnj * fonts. 2717956cc18dSsnj */ 2718956cc18dSsnj if (broken_fonts) { 2719956cc18dSsnj float lo_value = (float) 9.0e9; 2720956cc18dSsnj float hi_value = (float) 0.0; 2721956cc18dSsnj float value; 2722956cc18dSsnj 2723956cc18dSsnj TRACE(("bitmap fonts are broken - set faceSize resources\n")); 2724956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 2725956cc18dSsnj value = xw->misc.face_size[n]; 2726956cc18dSsnj if (value > 0.0) { 2727956cc18dSsnj if (lo_value > value) 2728956cc18dSsnj lo_value = value; 2729956cc18dSsnj if (hi_value < value) 2730956cc18dSsnj hi_value = value; 2731956cc18dSsnj } 2732956cc18dSsnj } 2733956cc18dSsnj 2734956cc18dSsnj if (hi_value <= 0.0) 2735956cc18dSsnj sscanf(DEFFACESIZE, "%f", &value); 2736956cc18dSsnj else 2737956cc18dSsnj value = (float) ((hi_value + lo_value) / 2.0); 2738956cc18dSsnj if (value <= 0) 2739956cc18dSsnj value = (float) 14.0; 2740956cc18dSsnj 2741956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 2742956cc18dSsnj TRACE(("setting faceSize%d %.1f\n", n, value)); 2743956cc18dSsnj xw->misc.face_size[n] = value; 2744956cc18dSsnj value = (float) (value * 1.1); 2745956cc18dSsnj } 2746956cc18dSsnj result = True; 2747956cc18dSsnj } 2748956cc18dSsnj } 27492eaa94a1Schristos } 27502eaa94a1Schristos return result; 27512eaa94a1Schristos} 27522eaa94a1Schristos#endif 27532eaa94a1Schristos 2754d522f475Smrg/* 2755d522f475Smrg * Find the index of a larger/smaller font (according to the sign of 'relative' 2756d522f475Smrg * and its magnitude), starting from the 'old' index. 2757d522f475Smrg */ 2758d522f475Smrgint 2759d522f475SmrglookupRelativeFontSize(XtermWidget xw, int old, int relative) 2760d522f475Smrg{ 2761d522f475Smrg TScreen *screen = TScreenOf(xw); 2762d522f475Smrg int n, m = -1; 2763d522f475Smrg 27642eaa94a1Schristos TRACE(("lookupRelativeFontSize(old=%d, relative=%d)\n", old, relative)); 2765d522f475Smrg if (!IsIcon(screen)) { 27662eaa94a1Schristos#if OPT_RENDERFONT 27672eaa94a1Schristos if (useFaceSizes(xw)) { 27682eaa94a1Schristos TRACE(("...using FaceSize\n")); 27692eaa94a1Schristos if (relative != 0) { 27702eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 27712eaa94a1Schristos if (xw->misc.face_size[n] > 0 && 27722eaa94a1Schristos xw->misc.face_size[n] != xw->misc.face_size[old]) { 27732eaa94a1Schristos int cmp_0 = ((xw->misc.face_size[n] > 27742eaa94a1Schristos xw->misc.face_size[old]) 27752eaa94a1Schristos ? relative 27762eaa94a1Schristos : -relative); 27772eaa94a1Schristos int cmp_m = ((m < 0) 27782eaa94a1Schristos ? 1 27792eaa94a1Schristos : ((xw->misc.face_size[n] < 27802eaa94a1Schristos xw->misc.face_size[m]) 27812eaa94a1Schristos ? relative 27822eaa94a1Schristos : -relative)); 27832eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 27842eaa94a1Schristos m = n; 27852eaa94a1Schristos } 2786d522f475Smrg } 2787d522f475Smrg } 2788d522f475Smrg } 27892eaa94a1Schristos } else 27902eaa94a1Schristos#endif 27912eaa94a1Schristos { 27922eaa94a1Schristos TRACE(("...using bitmap areas\n")); 27932eaa94a1Schristos lookupFontSizes(xw); 27942eaa94a1Schristos if (relative != 0) { 27952eaa94a1Schristos for (n = 0; n < NMENUFONTS; ++n) { 27962eaa94a1Schristos if (screen->menu_font_sizes[n] > 0 && 27972eaa94a1Schristos screen->menu_font_sizes[n] != 27982eaa94a1Schristos screen->menu_font_sizes[old]) { 27992eaa94a1Schristos int cmp_0 = ((screen->menu_font_sizes[n] > 28002eaa94a1Schristos screen->menu_font_sizes[old]) 28012eaa94a1Schristos ? relative 28022eaa94a1Schristos : -relative); 28032eaa94a1Schristos int cmp_m = ((m < 0) 28042eaa94a1Schristos ? 1 28052eaa94a1Schristos : ((screen->menu_font_sizes[n] < 28062eaa94a1Schristos screen->menu_font_sizes[m]) 28072eaa94a1Schristos ? relative 28082eaa94a1Schristos : -relative)); 28092eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 28102eaa94a1Schristos m = n; 28112eaa94a1Schristos } 28122eaa94a1Schristos } 28132eaa94a1Schristos } 2814d522f475Smrg } 2815d522f475Smrg } 28162eaa94a1Schristos TRACE(("...new index %d\n", m)); 28172eaa94a1Schristos if (m >= 0) { 28182eaa94a1Schristos if (relative > 1) 28192eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative - 1); 28202eaa94a1Schristos else if (relative < -1) 28212eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative + 1); 28222eaa94a1Schristos } 2823d522f475Smrg } 2824d522f475Smrg return m; 2825d522f475Smrg} 2826d522f475Smrg 2827d522f475Smrg/* ARGSUSED */ 2828d522f475Smrgvoid 2829d522f475SmrgHandleLargerFont(Widget w GCC_UNUSED, 2830d522f475Smrg XEvent * event GCC_UNUSED, 2831d522f475Smrg String * params GCC_UNUSED, 2832d522f475Smrg Cardinal *param_count GCC_UNUSED) 2833d522f475Smrg{ 2834956cc18dSsnj XtermWidget xw; 2835d522f475Smrg 283620d2c4d2Smrg TRACE(("Handle larger-vt-font for %p\n", (void *) w)); 2837956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 2838d522f475Smrg if (xw->misc.shift_fonts) { 2839956cc18dSsnj TScreen *screen = TScreenOf(xw); 2840d522f475Smrg int m; 2841d522f475Smrg 2842d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, 1); 2843d522f475Smrg if (m >= 0) { 2844d522f475Smrg SetVTFont(xw, m, True, NULL); 2845d522f475Smrg } else { 284620d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 2847d522f475Smrg } 2848d522f475Smrg } 2849d522f475Smrg } 2850d522f475Smrg} 2851d522f475Smrg 2852d522f475Smrg/* ARGSUSED */ 2853d522f475Smrgvoid 2854d522f475SmrgHandleSmallerFont(Widget w GCC_UNUSED, 2855d522f475Smrg XEvent * event GCC_UNUSED, 2856d522f475Smrg String * params GCC_UNUSED, 2857d522f475Smrg Cardinal *param_count GCC_UNUSED) 2858d522f475Smrg{ 2859956cc18dSsnj XtermWidget xw; 2860d522f475Smrg 286120d2c4d2Smrg TRACE(("Handle smaller-vt-font for %p\n", (void *) w)); 2862956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 2863d522f475Smrg if (xw->misc.shift_fonts) { 2864956cc18dSsnj TScreen *screen = TScreenOf(xw); 2865d522f475Smrg int m; 2866d522f475Smrg 2867d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, -1); 2868d522f475Smrg if (m >= 0) { 2869d522f475Smrg SetVTFont(xw, m, True, NULL); 2870d522f475Smrg } else { 287120d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 2872d522f475Smrg } 2873d522f475Smrg } 2874d522f475Smrg } 2875d522f475Smrg} 2876d522f475Smrg#endif 2877d522f475Smrg 2878d522f475Smrgint 2879d522f475SmrgxtermGetFont(const char *param) 2880d522f475Smrg{ 2881d522f475Smrg int fontnum; 2882d522f475Smrg 2883d522f475Smrg switch (param[0]) { 2884d522f475Smrg case 'd': 2885d522f475Smrg case 'D': 2886d522f475Smrg case '0': 2887d522f475Smrg fontnum = fontMenu_default; 2888d522f475Smrg break; 2889d522f475Smrg case '1': 2890d522f475Smrg fontnum = fontMenu_font1; 2891d522f475Smrg break; 2892d522f475Smrg case '2': 2893d522f475Smrg fontnum = fontMenu_font2; 2894d522f475Smrg break; 2895d522f475Smrg case '3': 2896d522f475Smrg fontnum = fontMenu_font3; 2897d522f475Smrg break; 2898d522f475Smrg case '4': 2899d522f475Smrg fontnum = fontMenu_font4; 2900d522f475Smrg break; 2901d522f475Smrg case '5': 2902d522f475Smrg fontnum = fontMenu_font5; 2903d522f475Smrg break; 2904d522f475Smrg case '6': 2905d522f475Smrg fontnum = fontMenu_font6; 2906d522f475Smrg break; 2907d522f475Smrg case 'e': 2908d522f475Smrg case 'E': 2909d522f475Smrg fontnum = fontMenu_fontescape; 2910d522f475Smrg break; 2911d522f475Smrg case 's': 2912d522f475Smrg case 'S': 2913d522f475Smrg fontnum = fontMenu_fontsel; 2914d522f475Smrg break; 2915d522f475Smrg default: 2916d522f475Smrg fontnum = -1; 2917d522f475Smrg break; 2918d522f475Smrg } 2919d522f475Smrg return fontnum; 2920d522f475Smrg} 2921d522f475Smrg 2922d522f475Smrg/* ARGSUSED */ 2923d522f475Smrgvoid 2924d522f475SmrgHandleSetFont(Widget w GCC_UNUSED, 2925d522f475Smrg XEvent * event GCC_UNUSED, 2926d522f475Smrg String * params, 2927d522f475Smrg Cardinal *param_count) 2928d522f475Smrg{ 2929956cc18dSsnj XtermWidget xw; 2930956cc18dSsnj 2931956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 2932d522f475Smrg int fontnum; 2933d522f475Smrg VTFontNames fonts; 2934d522f475Smrg 2935d522f475Smrg memset(&fonts, 0, sizeof(fonts)); 2936d522f475Smrg 2937d522f475Smrg if (*param_count == 0) { 2938d522f475Smrg fontnum = fontMenu_default; 2939d522f475Smrg } else { 2940d522f475Smrg Cardinal maxparams = 1; /* total number of params allowed */ 2941d522f475Smrg int result = xtermGetFont(params[0]); 2942d522f475Smrg 2943d522f475Smrg switch (result) { 2944d522f475Smrg case fontMenu_default: /* FALLTHRU */ 2945d522f475Smrg case fontMenu_font1: /* FALLTHRU */ 2946d522f475Smrg case fontMenu_font2: /* FALLTHRU */ 2947d522f475Smrg case fontMenu_font3: /* FALLTHRU */ 2948d522f475Smrg case fontMenu_font4: /* FALLTHRU */ 2949d522f475Smrg case fontMenu_font5: /* FALLTHRU */ 2950d522f475Smrg case fontMenu_font6: /* FALLTHRU */ 2951d522f475Smrg break; 2952d522f475Smrg case fontMenu_fontescape: 2953d522f475Smrg#if OPT_WIDE_CHARS 2954d522f475Smrg maxparams = 5; 2955d522f475Smrg#else 2956d522f475Smrg maxparams = 3; 2957d522f475Smrg#endif 2958d522f475Smrg break; 2959d522f475Smrg case fontMenu_fontsel: 2960d522f475Smrg maxparams = 2; 2961d522f475Smrg break; 2962d522f475Smrg default: 296320d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 2964d522f475Smrg return; 2965d522f475Smrg } 2966d522f475Smrg fontnum = result; 2967d522f475Smrg 2968d522f475Smrg if (*param_count > maxparams) { /* see if extra args given */ 296920d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 2970d522f475Smrg return; 2971d522f475Smrg } 2972d522f475Smrg switch (*param_count) { /* assign 'em */ 2973d522f475Smrg#if OPT_WIDE_CHARS 2974d522f475Smrg case 5: 2975d522f475Smrg fonts.f_wb = params[4]; 2976d522f475Smrg /* FALLTHRU */ 2977d522f475Smrg case 4: 2978d522f475Smrg fonts.f_w = params[3]; 2979d522f475Smrg /* FALLTHRU */ 2980d522f475Smrg#endif 2981d522f475Smrg case 3: 2982d522f475Smrg fonts.f_b = params[2]; 2983d522f475Smrg /* FALLTHRU */ 2984d522f475Smrg case 2: 2985d522f475Smrg fonts.f_n = params[1]; 2986d522f475Smrg break; 2987d522f475Smrg } 2988d522f475Smrg } 2989d522f475Smrg 2990956cc18dSsnj SetVTFont(xw, fontnum, True, &fonts); 2991d522f475Smrg } 2992d522f475Smrg} 2993d522f475Smrg 2994d522f475Smrgvoid 2995d522f475SmrgSetVTFont(XtermWidget xw, 2996d522f475Smrg int which, 2997d522f475Smrg Bool doresize, 2998d522f475Smrg const VTFontNames * fonts) 2999d522f475Smrg{ 3000956cc18dSsnj TScreen *screen = TScreenOf(xw); 3001d522f475Smrg 3002d522f475Smrg TRACE(("SetVTFont(which=%d, f_n=%s, f_b=%s)\n", which, 3003d522f475Smrg (fonts && fonts->f_n) ? fonts->f_n : "<null>", 3004d522f475Smrg (fonts && fonts->f_b) ? fonts->f_b : "<null>")); 3005d522f475Smrg 3006d522f475Smrg if (IsIcon(screen)) { 300720d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3008d522f475Smrg } else if (which >= 0 && which < NMENUFONTS) { 3009d522f475Smrg VTFontNames myfonts; 3010d522f475Smrg 3011d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 3012d522f475Smrg if (fonts != 0) 3013d522f475Smrg myfonts = *fonts; 3014d522f475Smrg 3015d522f475Smrg if (which == fontMenu_fontsel) { /* go get the selection */ 3016d522f475Smrg FindFontSelection(xw, myfonts.f_n, False); 3017d522f475Smrg } else { 3018d522f475Smrg int oldFont = screen->menu_font_number; 3019d522f475Smrg 3020d522f475Smrg#define USE_CACHED(field, name) \ 3021d522f475Smrg if (myfonts.field == 0) { \ 3022492d43a5Smrg myfonts.field = x_strdup(screen->menu_font_names[which][name]); \ 3023d522f475Smrg TRACE(("set myfonts." #field " from menu_font_names[%d][" #name "] %s\n", \ 3024d522f475Smrg which, NonNull(myfonts.field))); \ 3025d522f475Smrg } else { \ 3026d522f475Smrg TRACE(("set myfonts." #field " reused\n")); \ 3027d522f475Smrg } 302820d2c4d2Smrg#define SAVE_FNAME(field, name) \ 302920d2c4d2Smrg if (myfonts.field != 0) { \ 303020d2c4d2Smrg if (screen->menu_font_names[which][name] == 0 \ 303120d2c4d2Smrg || strcmp(screen->menu_font_names[which][name], myfonts.field)) { \ 303220d2c4d2Smrg TRACE(("updating menu_font_names[%d][" #name "] to %s\n", \ 303320d2c4d2Smrg which, myfonts.field)); \ 303420d2c4d2Smrg screen->menu_font_names[which][name] = x_strdup(myfonts.field); \ 303520d2c4d2Smrg } \ 303620d2c4d2Smrg } 303720d2c4d2Smrg 3038d522f475Smrg USE_CACHED(f_n, fNorm); 3039d522f475Smrg USE_CACHED(f_b, fBold); 3040d522f475Smrg#if OPT_WIDE_CHARS 3041d522f475Smrg USE_CACHED(f_w, fWide); 3042d522f475Smrg USE_CACHED(f_wb, fWBold); 3043d522f475Smrg#endif 3044d522f475Smrg if (xtermLoadFont(xw, 3045d522f475Smrg &myfonts, 3046d522f475Smrg doresize, which)) { 304720d2c4d2Smrg /* 304820d2c4d2Smrg * If successful, save the data so that a subsequent query via 304920d2c4d2Smrg * OSC-50 will return the expected values. 305020d2c4d2Smrg */ 305120d2c4d2Smrg SAVE_FNAME(f_n, fNorm); 305220d2c4d2Smrg SAVE_FNAME(f_b, fBold); 305320d2c4d2Smrg#if OPT_WIDE_CHARS 305420d2c4d2Smrg SAVE_FNAME(f_w, fWide); 305520d2c4d2Smrg SAVE_FNAME(f_wb, fWBold); 305620d2c4d2Smrg#endif 3057d522f475Smrg } else { 3058d522f475Smrg xtermLoadFont(xw, 3059d522f475Smrg xtermFontName(screen->MenuFontName(oldFont)), 3060d522f475Smrg doresize, oldFont); 306120d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3062d522f475Smrg } 3063d522f475Smrg } 306420d2c4d2Smrg } else { 306520d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3066d522f475Smrg } 3067d522f475Smrg return; 3068d522f475Smrg} 3069