fontutils.c revision 2eaa94a1
12eaa94a1Schristos/* $XTermId: fontutils.c,v 1.278 2008/12/30 17:32:06 tom Exp $ */ 2d522f475Smrg 3d522f475Smrg/************************************************************ 4d522f475Smrg 5d522f475SmrgCopyright 1998-2007,2008 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> 45d522f475Smrg 46d522f475Smrg#include <main.h> 47d522f475Smrg#include <data.h> 48d522f475Smrg#include <menu.h> 49d522f475Smrg#include <xstrings.h> 50d522f475Smrg#include <xterm.h> 51d522f475Smrg 52d522f475Smrg#include <stdio.h> 53d522f475Smrg#include <ctype.h> 54d522f475Smrg 55d522f475Smrg/* from X11/Xlibint.h - not all vendors install this file */ 56d522f475Smrg#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \ 57d522f475Smrg (((cs)->rbearing|(cs)->lbearing| \ 58d522f475Smrg (cs)->ascent|(cs)->descent) == 0)) 59d522f475Smrg 60d522f475Smrg#define CI_GET_CHAR_INFO_1D(fs,col,def,cs) \ 61d522f475Smrg{ \ 62d522f475Smrg cs = def; \ 63d522f475Smrg if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 64d522f475Smrg if (fs->per_char == NULL) { \ 65d522f475Smrg cs = &fs->min_bounds; \ 66d522f475Smrg } else { \ 67d522f475Smrg cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \ 68d522f475Smrg if (CI_NONEXISTCHAR(cs)) cs = def; \ 69d522f475Smrg } \ 70d522f475Smrg } \ 71d522f475Smrg} 72d522f475Smrg 73d522f475Smrg#define CI_GET_CHAR_INFO_2D(fs,row,col,def,cs) \ 74d522f475Smrg{ \ 75d522f475Smrg cs = def; \ 76d522f475Smrg if (row >= fs->min_byte1 && row <= fs->max_byte1 && \ 77d522f475Smrg col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 78d522f475Smrg if (fs->per_char == NULL) { \ 79d522f475Smrg cs = &fs->min_bounds; \ 80d522f475Smrg } else { \ 81d522f475Smrg cs = &fs->per_char[((row - fs->min_byte1) * \ 82d522f475Smrg (fs->max_char_or_byte2 - \ 83d522f475Smrg fs->min_char_or_byte2 + 1)) + \ 84d522f475Smrg (col - fs->min_char_or_byte2)]; \ 85d522f475Smrg if (CI_NONEXISTCHAR(cs)) cs = def; \ 86d522f475Smrg } \ 87d522f475Smrg } \ 88d522f475Smrg} 89d522f475Smrg 90d522f475Smrg#define MAX_FONTNAME 200 91d522f475Smrg 92d522f475Smrg/* 93d522f475Smrg * A structure to hold the relevant properties from a font 94d522f475Smrg * we need to make a well formed font name for it. 95d522f475Smrg */ 96d522f475Smrgtypedef struct { 97d522f475Smrg /* registry, foundry, family */ 98d522f475Smrg char *beginning; 99d522f475Smrg /* weight */ 100d522f475Smrg char *weight; 101d522f475Smrg /* slant */ 102d522f475Smrg char *slant; 103d522f475Smrg /* wideness */ 104d522f475Smrg char *wideness; 105d522f475Smrg /* add style */ 106d522f475Smrg char *add_style; 107d522f475Smrg int pixel_size; 108d522f475Smrg char *point_size; 109d522f475Smrg int res_x; 110d522f475Smrg int res_y; 111d522f475Smrg char *spacing; 112d522f475Smrg int average_width; 113d522f475Smrg /* charset registry, charset encoding */ 114d522f475Smrg char *end; 115d522f475Smrg} FontNameProperties; 116d522f475Smrg 117d522f475Smrg#if OPT_SHIFT_FONTS 118d522f475Smrgstatic void lookupOneFontSize(XtermWidget, int); 119d522f475Smrg#endif 120d522f475Smrg 121d522f475Smrg#if OPT_WIDE_CHARS 1222eaa94a1Schristosstatic unsigned 123d522f475SmrgcountGlyphs(XFontStruct * fp) 124d522f475Smrg{ 125d522f475Smrg unsigned count = 0; 126d522f475Smrg 127d522f475Smrg if (fp != 0) { 128d522f475Smrg if (fp->min_byte1 == 0 && fp->max_byte1 == 0) { 129d522f475Smrg count = fp->max_char_or_byte2 - fp->min_char_or_byte2; 130d522f475Smrg } else if (fp->min_char_or_byte2 < 256 131d522f475Smrg && fp->max_char_or_byte2 < 256) { 132d522f475Smrg unsigned first = (fp->min_byte1 << 8) + fp->min_char_or_byte2; 133d522f475Smrg unsigned last = (fp->max_byte1 << 8) + fp->max_char_or_byte2; 134d522f475Smrg count = last + 1 - first; 135d522f475Smrg } 136d522f475Smrg } 137d522f475Smrg return count; 138d522f475Smrg} 139d522f475Smrg 140d522f475Smrg/* 141d522f475Smrg * Verify that the wide-bold font is at least a bold font with roughly as many 142d522f475Smrg * glyphs as the wide font. The counts should be the same, but settle for 143d522f475Smrg * filtering out the worst of the font mismatches. 144d522f475Smrg */ 145d522f475Smrgstatic Bool 146d522f475SmrgcompatibleWideCounts(XFontStruct * wfs, XFontStruct * wbfs) 147d522f475Smrg{ 148d522f475Smrg unsigned count_w = countGlyphs(wfs); 149d522f475Smrg unsigned count_wb = countGlyphs(wbfs); 150d522f475Smrg if (count_w <= 256 || 151d522f475Smrg count_wb <= 256 || 152d522f475Smrg ((count_w / 4) * 3) > count_wb) { 153d522f475Smrg TRACE(("...font server lied (count wide %u vs wide-bold %u)\n", 154d522f475Smrg count_w, count_wb)); 155d522f475Smrg return False; 156d522f475Smrg } 157d522f475Smrg return True; 158d522f475Smrg} 159d522f475Smrg#endif /* OPT_WIDE_CHARS */ 160d522f475Smrg 161d522f475Smrg/* 162d522f475Smrg * Returns the fields from start to stop in a dash- separated string. This 163d522f475Smrg * function will modify the source, putting '\0's in the appropiate place and 164d522f475Smrg * moving the beginning forward to after the '\0' 165d522f475Smrg * 166d522f475Smrg * This will NOT work for the last field (but we won't need it). 167d522f475Smrg */ 168d522f475Smrgstatic char * 169d522f475Smrgn_fields(char **source, int start, int stop) 170d522f475Smrg{ 171d522f475Smrg int i; 172d522f475Smrg char *str, *str1; 173d522f475Smrg 174d522f475Smrg /* 175d522f475Smrg * find the start-1th dash 176d522f475Smrg */ 177d522f475Smrg for (i = start - 1, str = *source; i; i--, str++) 178d522f475Smrg if ((str = strchr(str, '-')) == 0) 179d522f475Smrg return 0; 180d522f475Smrg 181d522f475Smrg /* 182d522f475Smrg * find the stopth dash 183d522f475Smrg */ 184d522f475Smrg for (i = stop - start + 1, str1 = str; i; i--, str1++) 185d522f475Smrg if ((str1 = strchr(str1, '-')) == 0) 186d522f475Smrg return 0; 187d522f475Smrg 188d522f475Smrg /* 189d522f475Smrg * put a \0 at the end of the fields 190d522f475Smrg */ 191d522f475Smrg *(str1 - 1) = '\0'; 192d522f475Smrg 193d522f475Smrg /* 194d522f475Smrg * move source forward 195d522f475Smrg */ 196d522f475Smrg *source = str1; 197d522f475Smrg 198d522f475Smrg return str; 199d522f475Smrg} 200d522f475Smrg 201d522f475Smrg/* 202d522f475Smrg * Gets the font properties from a given font structure. We use the FONT name 203d522f475Smrg * to find them out, since that seems easier. 204d522f475Smrg * 205d522f475Smrg * Returns a pointer to a static FontNameProperties structure 206d522f475Smrg * or NULL on error. 207d522f475Smrg */ 208d522f475Smrgstatic FontNameProperties * 209d522f475Smrgget_font_name_props(Display * dpy, XFontStruct * fs, char *result) 210d522f475Smrg{ 211d522f475Smrg static FontNameProperties props; 212d522f475Smrg static char *last_name; 213d522f475Smrg 214d522f475Smrg XFontProp *fp; 215d522f475Smrg int i; 216d522f475Smrg Atom fontatom = XInternAtom(dpy, "FONT", False); 217d522f475Smrg char *name; 218d522f475Smrg char *str; 219d522f475Smrg 220d522f475Smrg /* 221d522f475Smrg * first get the full font name 222d522f475Smrg */ 223d522f475Smrg for (name = 0, i = 0, fp = fs->properties; 224d522f475Smrg i < fs->n_properties; 225d522f475Smrg i++, fp++) 226d522f475Smrg if (fp->name == fontatom) 227d522f475Smrg name = XGetAtomName(dpy, fp->card32); 228d522f475Smrg 229d522f475Smrg if (name == 0) 230d522f475Smrg return 0; 231d522f475Smrg 232d522f475Smrg /* 233d522f475Smrg * XGetAtomName allocates memory - don't leak 234d522f475Smrg */ 235d522f475Smrg if (last_name != 0) 236d522f475Smrg XFree(last_name); 237d522f475Smrg last_name = name; 238d522f475Smrg 239d522f475Smrg if (result != 0) { 240d522f475Smrg if (strlen(name) < MAX_FONTNAME - 1) { 241d522f475Smrg strcpy(result, name); 242d522f475Smrg } else { 243d522f475Smrg TRACE(("fontname too large: %s\n", name)); 244d522f475Smrg return 0; 245d522f475Smrg } 246d522f475Smrg } 247d522f475Smrg 248d522f475Smrg /* 249d522f475Smrg * Now split it up into parts and put them in 250d522f475Smrg * their places. Since we are using parts of 251d522f475Smrg * the original string, we must not free the Atom Name 252d522f475Smrg */ 253d522f475Smrg 254d522f475Smrg /* registry, foundry, family */ 255d522f475Smrg if ((props.beginning = n_fields(&name, 1, 3)) == 0) 256d522f475Smrg return 0; 257d522f475Smrg 258d522f475Smrg /* weight is the next */ 259d522f475Smrg if ((props.weight = n_fields(&name, 1, 1)) == 0) 260d522f475Smrg return 0; 261d522f475Smrg 262d522f475Smrg /* slant */ 263d522f475Smrg if ((props.slant = n_fields(&name, 1, 1)) == 0) 264d522f475Smrg return 0; 265d522f475Smrg 266d522f475Smrg /* width */ 267d522f475Smrg if ((props.wideness = n_fields(&name, 1, 1)) == 0) 268d522f475Smrg return 0; 269d522f475Smrg 270d522f475Smrg /* add style */ 271d522f475Smrg if ((props.add_style = n_fields(&name, 1, 1)) == 0) 272d522f475Smrg return 0; 273d522f475Smrg 274d522f475Smrg /* pixel size */ 275d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 276d522f475Smrg return 0; 277d522f475Smrg if ((props.pixel_size = atoi(str)) == 0) 278d522f475Smrg return 0; 279d522f475Smrg 280d522f475Smrg /* point size */ 281d522f475Smrg if ((props.point_size = n_fields(&name, 1, 1)) == 0) 282d522f475Smrg return 0; 283d522f475Smrg 284d522f475Smrg /* res_x */ 285d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 286d522f475Smrg return 0; 287d522f475Smrg if ((props.res_x = atoi(str)) == 0) 288d522f475Smrg return 0; 289d522f475Smrg 290d522f475Smrg /* res_y */ 291d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 292d522f475Smrg return 0; 293d522f475Smrg if ((props.res_y = atoi(str)) == 0) 294d522f475Smrg return 0; 295d522f475Smrg 296d522f475Smrg /* spacing */ 297d522f475Smrg if ((props.spacing = n_fields(&name, 1, 1)) == 0) 298d522f475Smrg return 0; 299d522f475Smrg 300d522f475Smrg /* average width */ 301d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 302d522f475Smrg return 0; 303d522f475Smrg if ((props.average_width = atoi(str)) == 0) 304d522f475Smrg return 0; 305d522f475Smrg 306d522f475Smrg /* the rest: charset registry and charset encoding */ 307d522f475Smrg props.end = name; 308d522f475Smrg 309d522f475Smrg return &props; 310d522f475Smrg} 311d522f475Smrg 312d522f475Smrg#define ALLOCHUNK(n) ((n | 127) + 1) 313d522f475Smrg 314d522f475Smrgstatic void 315d522f475Smrgalloca_fontname(char **result, unsigned next) 316d522f475Smrg{ 317d522f475Smrg unsigned last = (*result != 0) ? strlen(*result) : 0; 318d522f475Smrg unsigned have = (*result != 0) ? ALLOCHUNK(last) : 0; 319d522f475Smrg unsigned want = last + next + 2; 320d522f475Smrg 321d522f475Smrg if (want >= have) { 322d522f475Smrg want = ALLOCHUNK(want); 323d522f475Smrg if (last != 0) { 324d522f475Smrg *result = TypeRealloc(char, want, *result); 325d522f475Smrg } else { 326d522f475Smrg if ((*result = TypeMallocN(char, want)) != 0) 327d522f475Smrg **result = '\0'; 328d522f475Smrg } 329d522f475Smrg } 330d522f475Smrg} 331d522f475Smrg 332d522f475Smrgstatic void 333d522f475Smrgappend_fontname_str(char **result, char *value) 334d522f475Smrg{ 335d522f475Smrg if (value == 0) 336d522f475Smrg value = "*"; 337d522f475Smrg alloca_fontname(result, strlen(value)); 338d522f475Smrg if (*result != 0) { 339d522f475Smrg if (**result != '\0') 340d522f475Smrg strcat(*result, "-"); 341d522f475Smrg strcat(*result, value); 342d522f475Smrg } 343d522f475Smrg} 344d522f475Smrg 345d522f475Smrgstatic void 346d522f475Smrgappend_fontname_num(char **result, int value) 347d522f475Smrg{ 348d522f475Smrg if (value < 0) { 349d522f475Smrg append_fontname_str(result, "*"); 350d522f475Smrg } else { 351d522f475Smrg char temp[100]; 352d522f475Smrg sprintf(temp, "%d", value); 353d522f475Smrg append_fontname_str(result, temp); 354d522f475Smrg } 355d522f475Smrg} 356d522f475Smrg 357d522f475Smrg/* 358d522f475Smrg * Take the given font props and try to make a well formed font name specifying 359d522f475Smrg * the same base font and size and everything, but with different weight/width 360d522f475Smrg * according to the parameters. The return value is allocated, should be freed 361d522f475Smrg * by the caller. 362d522f475Smrg */ 363d522f475Smrgstatic char * 364d522f475Smrgderive_font_name(FontNameProperties * props, 365d522f475Smrg char *use_weight, 366d522f475Smrg int use_average_width, 367d522f475Smrg char *use_encoding) 368d522f475Smrg{ 369d522f475Smrg char *result = 0; 370d522f475Smrg 371d522f475Smrg append_fontname_str(&result, props->beginning); 372d522f475Smrg append_fontname_str(&result, use_weight); 373d522f475Smrg append_fontname_str(&result, props->slant); 374d522f475Smrg append_fontname_str(&result, 0); 375d522f475Smrg append_fontname_str(&result, 0); 376d522f475Smrg append_fontname_num(&result, props->pixel_size); 377d522f475Smrg append_fontname_str(&result, props->point_size); 378d522f475Smrg append_fontname_num(&result, props->res_x); 379d522f475Smrg append_fontname_num(&result, props->res_y); 380d522f475Smrg append_fontname_str(&result, props->spacing); 381d522f475Smrg append_fontname_num(&result, use_average_width); 382d522f475Smrg append_fontname_str(&result, use_encoding); 383d522f475Smrg 384d522f475Smrg return result; 385d522f475Smrg} 386d522f475Smrg 387d522f475Smrgstatic char * 388d522f475Smrgbold_font_name(FontNameProperties * props, int use_average_width) 389d522f475Smrg{ 390d522f475Smrg return derive_font_name(props, "bold", use_average_width, props->end); 391d522f475Smrg} 392d522f475Smrg 393d522f475Smrg#if OPT_WIDE_CHARS 394d522f475Smrg#define derive_wide_font(props, weight) \ 395d522f475Smrg derive_font_name(props, weight, props->average_width * 2, "ISO10646-1") 396d522f475Smrg 397d522f475Smrgstatic char * 398d522f475Smrgwide_font_name(FontNameProperties * props) 399d522f475Smrg{ 400d522f475Smrg return derive_wide_font(props, "medium"); 401d522f475Smrg} 402d522f475Smrg 403d522f475Smrgstatic char * 404d522f475Smrgwidebold_font_name(FontNameProperties * props) 405d522f475Smrg{ 406d522f475Smrg return derive_wide_font(props, "bold"); 407d522f475Smrg} 408d522f475Smrg#endif /* OPT_WIDE_CHARS */ 409d522f475Smrg 410d522f475Smrg#if OPT_DEC_CHRSET 411d522f475Smrg/* 412d522f475Smrg * Take the given font props and try to make a well formed font name specifying 413d522f475Smrg * the same base font but changed depending on the given attributes and chrset. 414d522f475Smrg * 415d522f475Smrg * For double width fonts, we just double the X-resolution, for double height 416d522f475Smrg * fonts we double the pixel-size and Y-resolution 417d522f475Smrg */ 418d522f475Smrgchar * 419d522f475SmrgxtermSpecialFont(TScreen * screen, unsigned atts, unsigned chrset) 420d522f475Smrg{ 421d522f475Smrg#if OPT_TRACE 422d522f475Smrg static char old_spacing[80]; 423d522f475Smrg static FontNameProperties old_props; 424d522f475Smrg#endif 425d522f475Smrg FontNameProperties *props; 426d522f475Smrg char *result = 0; 427d522f475Smrg char *weight; 428d522f475Smrg int pixel_size; 429d522f475Smrg int res_x; 430d522f475Smrg int res_y; 431d522f475Smrg 432d522f475Smrg props = get_font_name_props(screen->display, screen->fnts[fNorm].fs, 0); 433d522f475Smrg if (props == 0) 434d522f475Smrg return result; 435d522f475Smrg 436d522f475Smrg pixel_size = props->pixel_size; 437d522f475Smrg res_x = props->res_x; 438d522f475Smrg res_y = props->res_y; 439d522f475Smrg if (atts & BOLD) 440d522f475Smrg weight = "bold"; 441d522f475Smrg else 442d522f475Smrg weight = props->weight; 443d522f475Smrg 444d522f475Smrg if (CSET_DOUBLE(chrset)) 445d522f475Smrg res_x *= 2; 446d522f475Smrg 447d522f475Smrg if (chrset == CSET_DHL_TOP 448d522f475Smrg || chrset == CSET_DHL_BOT) { 449d522f475Smrg res_y *= 2; 450d522f475Smrg pixel_size *= 2; 451d522f475Smrg } 452d522f475Smrg#if OPT_TRACE 453d522f475Smrg if (old_props.res_x != res_x 454d522f475Smrg || old_props.res_x != res_y 455d522f475Smrg || old_props.pixel_size != pixel_size 456d522f475Smrg || strcmp(old_props.spacing, props->spacing)) { 457d522f475Smrg TRACE(("xtermSpecialFont(atts = %#x, chrset = %#x)\n", atts, chrset)); 458d522f475Smrg TRACE(("res_x = %d\n", res_x)); 459d522f475Smrg TRACE(("res_y = %d\n", res_y)); 460d522f475Smrg TRACE(("point_size = %s\n", props->point_size)); 461d522f475Smrg TRACE(("pixel_size = %d\n", pixel_size)); 462d522f475Smrg TRACE(("spacing = %s\n", props->spacing)); 463d522f475Smrg old_props.res_x = res_x; 464d522f475Smrg old_props.res_x = res_y; 465d522f475Smrg old_props.pixel_size = pixel_size; 466d522f475Smrg old_props.spacing = strcpy(old_spacing, props->spacing); 467d522f475Smrg } 468d522f475Smrg#endif 469d522f475Smrg 470d522f475Smrg append_fontname_str(&result, props->beginning); 471d522f475Smrg append_fontname_str(&result, weight); 472d522f475Smrg append_fontname_str(&result, props->slant); 473d522f475Smrg append_fontname_str(&result, props->wideness); 474d522f475Smrg append_fontname_str(&result, props->add_style); 475d522f475Smrg append_fontname_num(&result, pixel_size); 476d522f475Smrg append_fontname_str(&result, props->point_size); 477d522f475Smrg append_fontname_num(&result, (atts & NORESOLUTION) ? -1 : res_x); 478d522f475Smrg append_fontname_num(&result, (atts & NORESOLUTION) ? -1 : res_y); 479d522f475Smrg append_fontname_str(&result, props->spacing); 480d522f475Smrg append_fontname_str(&result, 0); 481d522f475Smrg append_fontname_str(&result, props->end); 482d522f475Smrg 483d522f475Smrg return result; 484d522f475Smrg} 485d522f475Smrg#endif /* OPT_DEC_CHRSET */ 486d522f475Smrg 487d522f475Smrg/* 488d522f475Smrg * Case-independent comparison for font-names, including wildcards. 489d522f475Smrg * XLFD allows '?' as a wildcard, but we do not handle that (no one seems 490d522f475Smrg * to use it). 491d522f475Smrg */ 492d522f475Smrgstatic Bool 493d522f475Smrgsame_font_name(char *pattern, char *match) 494d522f475Smrg{ 495d522f475Smrg while (*pattern && *match) { 496d522f475Smrg if (*pattern == *match) { 497d522f475Smrg pattern++; 498d522f475Smrg match++; 499d522f475Smrg } else if (*pattern == '*' || *match == '*') { 500d522f475Smrg if (same_font_name(pattern + 1, match)) { 501d522f475Smrg return True; 502d522f475Smrg } else if (same_font_name(pattern, match + 1)) { 503d522f475Smrg return True; 504d522f475Smrg } else { 505d522f475Smrg return False; 506d522f475Smrg } 507d522f475Smrg } else { 5082eaa94a1Schristos int p = x_toupper(*pattern++); 5092eaa94a1Schristos int m = x_toupper(*match++); 510d522f475Smrg if (p != m) 511d522f475Smrg return False; 512d522f475Smrg } 513d522f475Smrg } 514d522f475Smrg return (*pattern == *match); /* both should be NUL */ 515d522f475Smrg} 516d522f475Smrg 517d522f475Smrg/* 518d522f475Smrg * Double-check the fontname that we asked for versus what the font server 519d522f475Smrg * actually gave us. The larger fixed fonts do not always have a matching bold 520d522f475Smrg * font, and the font server may try to scale another font or otherwise 521d522f475Smrg * substitute a mismatched font. 522d522f475Smrg * 523d522f475Smrg * If we cannot get what we requested, we will fallback to the original 524d522f475Smrg * behavior, which simulates bold by overstriking each character at one pixel 525d522f475Smrg * offset. 526d522f475Smrg */ 527d522f475Smrgstatic int 528d522f475Smrggot_bold_font(Display * dpy, XFontStruct * fs, char *requested) 529d522f475Smrg{ 530d522f475Smrg char actual[MAX_FONTNAME]; 531d522f475Smrg int got; 532d522f475Smrg 533d522f475Smrg if (get_font_name_props(dpy, fs, actual) == 0) 534d522f475Smrg got = 0; 535d522f475Smrg else 536d522f475Smrg got = same_font_name(requested, actual); 537d522f475Smrg return got; 538d522f475Smrg} 539d522f475Smrg 540d522f475Smrg/* 541d522f475Smrg * If the font server tries to adjust another font, it may not adjust it 542d522f475Smrg * properly. Check that the bounding boxes are compatible. Otherwise we'll 543d522f475Smrg * leave trash on the display when we mix normal and bold fonts. 544d522f475Smrg */ 545d522f475Smrgstatic int 546d522f475Smrgsame_font_size(XtermWidget xw, XFontStruct * nfs, XFontStruct * bfs) 547d522f475Smrg{ 548d522f475Smrg TRACE(("same_font_size height %d/%d, min %d/%d max %d/%d\n", 549d522f475Smrg nfs->ascent + nfs->descent, 550d522f475Smrg bfs->ascent + bfs->descent, 551d522f475Smrg nfs->min_bounds.width, bfs->min_bounds.width, 552d522f475Smrg nfs->max_bounds.width, bfs->max_bounds.width)); 553d522f475Smrg return xw->screen.free_bold_box 554d522f475Smrg || ((nfs->ascent + nfs->descent) == (bfs->ascent + bfs->descent) 555d522f475Smrg && (nfs->min_bounds.width == bfs->min_bounds.width 556d522f475Smrg || nfs->min_bounds.width == bfs->min_bounds.width + 1) 557d522f475Smrg && (nfs->max_bounds.width == bfs->max_bounds.width 558d522f475Smrg || nfs->max_bounds.width == bfs->max_bounds.width + 1)); 559d522f475Smrg} 560d522f475Smrg 561d522f475Smrg/* 562d522f475Smrg * Check if the font looks like it has fixed width 563d522f475Smrg */ 564d522f475Smrgstatic int 565d522f475Smrgis_fixed_font(XFontStruct * fs) 566d522f475Smrg{ 567d522f475Smrg if (fs) 568d522f475Smrg return (fs->min_bounds.width == fs->max_bounds.width); 569d522f475Smrg return 1; 570d522f475Smrg} 571d522f475Smrg 572d522f475Smrg/* 573d522f475Smrg * Check if the font looks like a double width font (i.e. contains 574d522f475Smrg * characters of width X and 2X 575d522f475Smrg */ 576d522f475Smrg#if OPT_WIDE_CHARS 577d522f475Smrgstatic int 578d522f475Smrgis_double_width_font(XFontStruct * fs) 579d522f475Smrg{ 580d522f475Smrg return ((2 * fs->min_bounds.width) == fs->max_bounds.width); 581d522f475Smrg} 582d522f475Smrg#else 583d522f475Smrg#define is_double_width_font(fs) 0 584d522f475Smrg#endif 585d522f475Smrg 586d522f475Smrg#if OPT_WIDE_CHARS && OPT_RENDERFONT && defined(HAVE_TYPE_FCCHAR32) 587d522f475Smrg#define HALF_WIDTH_TEST_STRING "1234567890" 588d522f475Smrg 589d522f475Smrg/* '1234567890' in Chinese characters in UTF-8 */ 590d522f475Smrg#define FULL_WIDTH_TEST_STRING "\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89" \ 591d522f475Smrg "\xe5\x9b\x9b\xe4\xba\x94" \ 592d522f475Smrg "\xef\xa7\x91\xe4\xb8\x83\xe5\x85\xab" \ 593d522f475Smrg "\xe4\xb9\x9d\xef\xa6\xb2" 594d522f475Smrg 595d522f475Smrg/* '1234567890' in Korean script in UTF-8 */ 596d522f475Smrg#define FULL_WIDTH_TEST_STRING2 "\xec\x9d\xbc\xec\x9d\xb4\xec\x82\xbc" \ 597d522f475Smrg "\xec\x82\xac\xec\x98\xa4" \ 598d522f475Smrg "\xec\x9c\xa1\xec\xb9\xa0\xed\x8c\x94" \ 599d522f475Smrg "\xea\xb5\xac\xec\x98\x81" 600d522f475Smrg 601d522f475Smrg#define HALF_WIDTH_CHAR1 0x0031 /* '1' */ 602d522f475Smrg#define HALF_WIDTH_CHAR2 0x0057 /* 'W' */ 603d522f475Smrg#define FULL_WIDTH_CHAR1 0x4E00 /* CJK Ideograph 'number one' */ 604d522f475Smrg#define FULL_WIDTH_CHAR2 0xAC00 /* Korean script syllable 'Ka' */ 605d522f475Smrg 606d522f475Smrgstatic Bool 607d522f475Smrgis_double_width_font_xft(Display * dpy, XftFont * font) 608d522f475Smrg{ 609d522f475Smrg XGlyphInfo gi1, gi2; 610d522f475Smrg FcChar32 c1 = HALF_WIDTH_CHAR1, c2 = HALF_WIDTH_CHAR2; 611d522f475Smrg char *fwstr = FULL_WIDTH_TEST_STRING; 612d522f475Smrg char *hwstr = HALF_WIDTH_TEST_STRING; 613d522f475Smrg 614d522f475Smrg /* Some Korean fonts don't have Chinese characters at all. */ 615d522f475Smrg if (!XftCharExists(dpy, font, FULL_WIDTH_CHAR1)) { 616d522f475Smrg if (!XftCharExists(dpy, font, FULL_WIDTH_CHAR2)) 617d522f475Smrg return False; /* Not a CJK font */ 618d522f475Smrg else /* a Korean font without CJK Ideographs */ 619d522f475Smrg fwstr = FULL_WIDTH_TEST_STRING2; 620d522f475Smrg } 621d522f475Smrg 622d522f475Smrg XftTextExtents32(dpy, font, &c1, 1, &gi1); 623d522f475Smrg XftTextExtents32(dpy, font, &c2, 1, &gi2); 624d522f475Smrg if (gi1.xOff != gi2.xOff) /* Not a fixed-width font */ 625d522f475Smrg return False; 626d522f475Smrg 627d522f475Smrg XftTextExtentsUtf8(dpy, font, (FcChar8 *) hwstr, (int) strlen(hwstr), &gi1); 628d522f475Smrg XftTextExtentsUtf8(dpy, font, (FcChar8 *) fwstr, (int) strlen(fwstr), &gi2); 629d522f475Smrg 630d522f475Smrg /* 631d522f475Smrg * fontconfig and Xft prior to 2.2(?) set the width of half-width 632d522f475Smrg * characters identical to that of full-width character in CJK double-width 633d522f475Smrg * (bi-width / monospace) font even though the former is half as wide as 634d522f475Smrg * the latter. This was fixed sometime before the release of fontconfig 635d522f475Smrg * 2.2 in early 2003. See 636d522f475Smrg * http://bugzilla.mozilla.org/show_bug.cgi?id=196312 637d522f475Smrg * In the meantime, we have to check both possibilities. 638d522f475Smrg */ 639d522f475Smrg return ((2 * gi1.xOff == gi2.xOff) || (gi1.xOff == gi2.xOff)); 640d522f475Smrg} 641d522f475Smrg#else 642d522f475Smrg#define is_double_width_font_xft(dpy, xftfont) 0 643d522f475Smrg#endif 644d522f475Smrg 645d522f475Smrg#define EmptyFont(fs) (fs != 0 \ 646d522f475Smrg && ((fs)->ascent + (fs)->descent == 0 \ 647d522f475Smrg || (fs)->max_bounds.width == 0)) 648d522f475Smrg 649d522f475Smrg#define FontSize(fs) (((fs)->ascent + (fs)->descent) \ 650d522f475Smrg * (fs)->max_bounds.width) 651d522f475Smrg 652d522f475Smrgconst VTFontNames * 653d522f475SmrgxtermFontName(char *normal) 654d522f475Smrg{ 655d522f475Smrg static VTFontNames data; 656d522f475Smrg memset(&data, 0, sizeof(data)); 657d522f475Smrg data.f_n = normal; 658d522f475Smrg return &data; 659d522f475Smrg} 660d522f475Smrg 661d522f475Smrgstatic void 662d522f475Smrgcache_menu_font_name(TScreen * screen, int fontnum, int which, const char *name) 663d522f475Smrg{ 664d522f475Smrg if (name != 0) { 665d522f475Smrg char *last = screen->menu_font_names[fontnum][which]; 666d522f475Smrg if (last != 0) { 667d522f475Smrg if (strcmp(last, name)) { 668d522f475Smrg free(last); 669d522f475Smrg TRACE(("caching menu fontname %d.%d %s\n", fontnum, which, name)); 670d522f475Smrg screen->menu_font_names[fontnum][which] = x_strdup(name); 671d522f475Smrg } 672d522f475Smrg } else { 673d522f475Smrg TRACE(("caching menu fontname %d.%d %s\n", fontnum, which, name)); 674d522f475Smrg screen->menu_font_names[fontnum][which] = x_strdup(name); 675d522f475Smrg } 676d522f475Smrg } 677d522f475Smrg} 678d522f475Smrg 679d522f475Smrg/* 680d522f475Smrg * Open the given font and verify that it is non-empty. Return a null on 681d522f475Smrg * failure. 682d522f475Smrg */ 683d522f475SmrgBool 684d522f475SmrgxtermOpenFont(XtermWidget xw, char *name, XTermFonts * result) 685d522f475Smrg{ 686d522f475Smrg Bool code = False; 687d522f475Smrg TScreen *screen = TScreenOf(xw); 688d522f475Smrg 689d522f475Smrg if (name != 0 690d522f475Smrg && (result->fs = XLoadQueryFont(screen->display, name)) != 0) { 691d522f475Smrg code = True; 692d522f475Smrg if (EmptyFont(result->fs)) { 693d522f475Smrg result = xtermCloseFont(xw, result); 694d522f475Smrg code = False; 695d522f475Smrg } else { 696d522f475Smrg result->fn = x_strdup(name); 697d522f475Smrg } 698d522f475Smrg } 699d522f475Smrg return code; 700d522f475Smrg} 701d522f475Smrg 702d522f475Smrg/* 703d522f475Smrg * Close the font and Free the font info 704d522f475Smrg */ 705d522f475SmrgXTermFonts * 706d522f475SmrgxtermCloseFont(XtermWidget xw, XTermFonts * fnt) 707d522f475Smrg{ 708d522f475Smrg if (fnt != 0 && fnt->fs != 0) { 709d522f475Smrg TScreen *screen = TScreenOf(xw); 710d522f475Smrg 711d522f475Smrg clrCgsFonts(xw, WhichVWin(screen), fnt); 712d522f475Smrg XFreeFont(screen->display, fnt->fs); 713d522f475Smrg xtermFreeFontInfo(fnt); 714d522f475Smrg } 715d522f475Smrg return 0; 716d522f475Smrg} 717d522f475Smrg 718d522f475Smrg/* 719d522f475Smrg * Close the listed fonts, noting that some may use copies of the pointer. 720d522f475Smrg */ 721d522f475Smrgvoid 722d522f475SmrgxtermCloseFonts(XtermWidget xw, XTermFonts * fnts) 723d522f475Smrg{ 724d522f475Smrg int j, k; 725d522f475Smrg 726d522f475Smrg for (j = 0; j < fMAX; ++j) { 727d522f475Smrg /* 728d522f475Smrg * Need to save the pointer since xtermCloseFont zeroes it 729d522f475Smrg */ 730d522f475Smrg XFontStruct *thisFont = fnts[j].fs; 731d522f475Smrg if (thisFont != 0) { 732d522f475Smrg xtermCloseFont(xw, &fnts[j]); 733d522f475Smrg for (k = j + 1; k < fMAX; ++k) { 734d522f475Smrg if (thisFont == fnts[k].fs) 735d522f475Smrg xtermFreeFontInfo(&fnts[k]); 736d522f475Smrg } 737d522f475Smrg } 738d522f475Smrg } 739d522f475Smrg} 740d522f475Smrg 741d522f475Smrg/* 742d522f475Smrg * Make a copy of the source, assuming the XFontStruct's to be unique, but 743d522f475Smrg * ensuring that the names are reallocated to simplify freeing. 744d522f475Smrg */ 745d522f475Smrgvoid 746d522f475SmrgxtermCopyFontInfo(XTermFonts * target, XTermFonts * source) 747d522f475Smrg{ 748d522f475Smrg xtermFreeFontInfo(target); 749d522f475Smrg target->chrset = source->chrset; 750d522f475Smrg target->flags = source->flags; 751d522f475Smrg target->fn = x_strdup(source->fn); 752d522f475Smrg target->fs = source->fs; 753d522f475Smrg} 754d522f475Smrg 755d522f475Smrgvoid 756d522f475SmrgxtermFreeFontInfo(XTermFonts * target) 757d522f475Smrg{ 758d522f475Smrg target->chrset = 0; 759d522f475Smrg target->flags = 0; 760d522f475Smrg if (target->fn != 0) { 761d522f475Smrg free(target->fn); 762d522f475Smrg target->fn = 0; 763d522f475Smrg } 764d522f475Smrg target->fs = 0; 765d522f475Smrg} 766d522f475Smrg 767d522f475Smrgint 768d522f475SmrgxtermLoadFont(XtermWidget xw, 769d522f475Smrg const VTFontNames * fonts, 770d522f475Smrg Bool doresize, 771d522f475Smrg int fontnum) 772d522f475Smrg{ 773d522f475Smrg TScreen *screen = &(xw->screen); 774d522f475Smrg VTwin *win = WhichVWin(screen); 775d522f475Smrg 776d522f475Smrg VTFontNames myfonts; 777d522f475Smrg FontNameProperties *fp; 778d522f475Smrg XTermFonts fnts[fMAX]; 779d522f475Smrg Pixel new_normal; 780d522f475Smrg Pixel new_revers; 781d522f475Smrg char *tmpname = NULL; 782d522f475Smrg char normal[MAX_FONTNAME]; 783d522f475Smrg Bool proportional = False; 784d522f475Smrg 785d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 786d522f475Smrg memset(fnts, 0, sizeof(fnts)); 787d522f475Smrg 788d522f475Smrg if (fonts != 0) 789d522f475Smrg myfonts = *fonts; 790d522f475Smrg if (myfonts.f_n == 0) 791d522f475Smrg return 0; 792d522f475Smrg 793d522f475Smrg if (fontnum == fontMenu_fontescape 794d522f475Smrg && myfonts.f_n != screen->MenuFontName(fontnum)) { 795d522f475Smrg if ((tmpname = x_strdup(myfonts.f_n)) == 0) 796d522f475Smrg return 0; 797d522f475Smrg } 798d522f475Smrg 799d522f475Smrg TRACE(("Begin Cgs - xtermLoadFont(%s)\n", myfonts.f_n)); 800d522f475Smrg releaseWindowGCs(xw, win); 801d522f475Smrg 802d522f475Smrg TRACE(("xtermLoadFont #%d normal %s\n", fontnum, NonNull(myfonts.f_n))); 803d522f475Smrg TRACE(("xtermLoadFont #%d bold %s\n", fontnum, NonNull(myfonts.f_b))); 804d522f475Smrg#if OPT_WIDE_CHARS 805d522f475Smrg TRACE(("xtermLoadFont #%d wide %s\n", fontnum, NonNull(myfonts.f_w))); 806d522f475Smrg TRACE(("xtermLoadFont #%d w/bold %s\n", fontnum, NonNull(myfonts.f_wb))); 807d522f475Smrg#endif 808d522f475Smrg 809d522f475Smrg if (!xtermOpenFont(xw, myfonts.f_n, &fnts[fNorm])) 810d522f475Smrg goto bad; 811d522f475Smrg 812d522f475Smrg strcpy(normal, myfonts.f_n); 813d522f475Smrg if (myfonts.f_b == 0) { 814d522f475Smrg fp = get_font_name_props(screen->display, fnts[fNorm].fs, normal); 815d522f475Smrg if (fp != 0) { 816d522f475Smrg myfonts.f_b = bold_font_name(fp, fp->average_width); 817d522f475Smrg if (!xtermOpenFont(xw, myfonts.f_b, &fnts[fBold])) { 818d522f475Smrg myfonts.f_b = bold_font_name(fp, -1); 819d522f475Smrg (void) xtermOpenFont(xw, myfonts.f_b, &fnts[fBold]); 820d522f475Smrg } 821d522f475Smrg TRACE(("...derived bold %s\n", NonNull(myfonts.f_b))); 822d522f475Smrg } 823d522f475Smrg if (fp == 0 || fnts[fBold].fs == 0) { 824d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 825d522f475Smrg TRACE(("...cannot load a matching bold font\n")); 826d522f475Smrg } else if (same_font_size(xw, fnts[fNorm].fs, fnts[fBold].fs) 827d522f475Smrg && got_bold_font(screen->display, fnts[fBold].fs, myfonts.f_b)) { 828d522f475Smrg TRACE(("...got a matching bold font\n")); 829d522f475Smrg cache_menu_font_name(screen, fontnum, fBold, myfonts.f_b); 830d522f475Smrg } else { 831d522f475Smrg xtermCloseFont(xw, &fnts[fBold]); 832d522f475Smrg fnts[fBold] = fnts[fNorm]; 833d522f475Smrg TRACE(("...did not get a matching bold font\n")); 834d522f475Smrg } 835d522f475Smrg } else if (!xtermOpenFont(xw, myfonts.f_b, &fnts[fBold])) { 836d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 837d522f475Smrg TRACE(("...cannot load bold font %s\n", NonNull(myfonts.f_b))); 838d522f475Smrg } else { 839d522f475Smrg cache_menu_font_name(screen, fontnum, fBold, myfonts.f_b); 840d522f475Smrg } 841d522f475Smrg 842d522f475Smrg /* 843d522f475Smrg * If there is no widefont specified, fake it by doubling AVERAGE_WIDTH 844d522f475Smrg * of normal fonts XLFD, and asking for it. This plucks out 18x18ja 845d522f475Smrg * and 12x13ja as the corresponding fonts for 9x18 and 6x13. 846d522f475Smrg */ 847d522f475Smrg if_OPT_WIDE_CHARS(screen, { 848d522f475Smrg Bool derived; 849d522f475Smrg char bold[MAX_FONTNAME]; 850d522f475Smrg 851d522f475Smrg if (myfonts.f_w != 0) { 852d522f475Smrg cache_menu_font_name(screen, fontnum, fWide, myfonts.f_w); 853d522f475Smrg } else if (!is_double_width_font(fnts[fNorm].fs)) { 854d522f475Smrg fp = get_font_name_props(screen->display, fnts[fNorm].fs, normal); 855d522f475Smrg if (fp != 0) { 856d522f475Smrg myfonts.f_w = wide_font_name(fp); 857d522f475Smrg TRACE(("...derived wide %s\n", NonNull(myfonts.f_w))); 858d522f475Smrg cache_menu_font_name(screen, fontnum, fWide, myfonts.f_w); 859d522f475Smrg } 860d522f475Smrg } 861d522f475Smrg 862d522f475Smrg if (myfonts.f_w) { 863d522f475Smrg (void) xtermOpenFont(xw, myfonts.f_w, &fnts[fWide]); 864d522f475Smrg } else { 865d522f475Smrg xtermCopyFontInfo(&fnts[fWide], &fnts[fNorm]); 866d522f475Smrg } 867d522f475Smrg 868d522f475Smrg derived = False; 869d522f475Smrg if (myfonts.f_wb == 0) { 870d522f475Smrg fp = get_font_name_props(screen->display, fnts[fBold].fs, bold); 871d522f475Smrg if (fp != 0) { 872d522f475Smrg myfonts.f_wb = widebold_font_name(fp); 873d522f475Smrg derived = True; 874d522f475Smrg } 875d522f475Smrg } 876d522f475Smrg 877d522f475Smrg if (myfonts.f_wb) { 878d522f475Smrg 879d522f475Smrg (void) xtermOpenFont(xw, myfonts.f_wb, &fnts[fWBold]); 880d522f475Smrg 881d522f475Smrg if (derived 882d522f475Smrg && !compatibleWideCounts(fnts[fWide].fs, fnts[fWBold].fs)) { 883d522f475Smrg xtermCloseFont(xw, &fnts[fWBold]); 884d522f475Smrg } 885d522f475Smrg if (fnts[fWBold].fs == 0) { 886d522f475Smrg myfonts.f_wb = myfonts.f_w; 887d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 888d522f475Smrg TRACE(("...cannot load wide-bold, use wide %s\n", NonNull(myfonts.f_w))); 889d522f475Smrg } else { 890d522f475Smrg TRACE(("...%s wide/bold %s\n", 891d522f475Smrg derived ? "derived" : "given", 892d522f475Smrg NonNull(myfonts.f_wb))); 893d522f475Smrg cache_menu_font_name(screen, fontnum, fWBold, myfonts.f_wb); 894d522f475Smrg } 895d522f475Smrg } else if (is_double_width_font(fnts[fBold].fs)) { 896d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fBold]); 897d522f475Smrg TRACE(("...bold font is double-width, use it %s\n", NonNull(myfonts.f_b))); 898d522f475Smrg } else { 899d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 900d522f475Smrg TRACE(("...cannot load wide bold font, use wide %s\n", NonNull(myfonts.f_w))); 901d522f475Smrg } 902d522f475Smrg 903d522f475Smrg if (EmptyFont(fnts[fWBold].fs)) 904d522f475Smrg goto bad; /* can't use a 0-sized font */ 905d522f475Smrg }); 906d522f475Smrg 907d522f475Smrg /* 908d522f475Smrg * Most of the time this call to load the font will succeed, even if 909d522f475Smrg * there is no wide font : the X server doubles the width of the 910d522f475Smrg * normal font, or similar. 911d522f475Smrg * 912d522f475Smrg * But if it did fail for some reason, then nevermind. 913d522f475Smrg */ 914d522f475Smrg if (EmptyFont(fnts[fBold].fs)) 915d522f475Smrg goto bad; /* can't use a 0-sized font */ 916d522f475Smrg 917d522f475Smrg if (!same_font_size(xw, fnts[fNorm].fs, fnts[fBold].fs) 918d522f475Smrg && (is_fixed_font(fnts[fNorm].fs) && is_fixed_font(fnts[fBold].fs))) { 919d522f475Smrg TRACE(("...ignoring mismatched normal/bold fonts\n")); 920d522f475Smrg xtermCloseFont(xw, &fnts[fBold]); 921d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 922d522f475Smrg } 923d522f475Smrg 924d522f475Smrg if_OPT_WIDE_CHARS(screen, { 925d522f475Smrg if (fnts[fWide].fs != 0 926d522f475Smrg && fnts[fWBold].fs != 0 927d522f475Smrg && !same_font_size(xw, fnts[fWide].fs, fnts[fWBold].fs) 928d522f475Smrg && (is_fixed_font(fnts[fWide].fs) && is_fixed_font(fnts[fWBold].fs))) { 929d522f475Smrg TRACE(("...ignoring mismatched normal/bold wide fonts\n")); 930d522f475Smrg xtermCloseFont(xw, &fnts[fWBold]); 931d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 932d522f475Smrg } 933d522f475Smrg }); 934d522f475Smrg 935d522f475Smrg /* 936d522f475Smrg * Normal/bold fonts should be the same width. Also, the min/max 937d522f475Smrg * values should be the same. 938d522f475Smrg */ 939d522f475Smrg if (!is_fixed_font(fnts[fNorm].fs) 940d522f475Smrg || !is_fixed_font(fnts[fBold].fs) 941d522f475Smrg || fnts[fNorm].fs->max_bounds.width != fnts[fBold].fs->max_bounds.width) { 942d522f475Smrg TRACE(("Proportional font! normal %d/%d, bold %d/%d\n", 943d522f475Smrg fnts[fNorm].fs->min_bounds.width, 944d522f475Smrg fnts[fNorm].fs->max_bounds.width, 945d522f475Smrg fnts[fBold].fs->min_bounds.width, 946d522f475Smrg fnts[fBold].fs->max_bounds.width)); 947d522f475Smrg proportional = True; 948d522f475Smrg } 949d522f475Smrg 950d522f475Smrg if_OPT_WIDE_CHARS(screen, { 951d522f475Smrg if (fnts[fWide].fs != 0 952d522f475Smrg && fnts[fWBold].fs != 0 953d522f475Smrg && (!is_fixed_font(fnts[fWide].fs) 954d522f475Smrg || !is_fixed_font(fnts[fWBold].fs) 955d522f475Smrg || fnts[fWide].fs->max_bounds.width != fnts[fWBold].fs->max_bounds.width)) { 956d522f475Smrg TRACE(("Proportional font! wide %d/%d, wide bold %d/%d\n", 957d522f475Smrg fnts[fWide].fs->min_bounds.width, 958d522f475Smrg fnts[fWide].fs->max_bounds.width, 959d522f475Smrg fnts[fWBold].fs->min_bounds.width, 960d522f475Smrg fnts[fWBold].fs->max_bounds.width)); 961d522f475Smrg proportional = True; 962d522f475Smrg } 963d522f475Smrg }); 964d522f475Smrg 965d522f475Smrg /* TODO : enforce that the width of the wide font is 2* the width 966d522f475Smrg of the narrow font */ 967d522f475Smrg 968d522f475Smrg /* 969d522f475Smrg * If we're switching fonts, free the old ones. Otherwise we'll leak 970d522f475Smrg * the memory that is associated with the old fonts. The 971d522f475Smrg * XLoadQueryFont call allocates a new XFontStruct. 972d522f475Smrg */ 973d522f475Smrg xtermCloseFonts(xw, screen->fnts); 974d522f475Smrg 975d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fNorm]), &fnts[fNorm]); 976d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fBold]), &fnts[fBold]); 977d522f475Smrg#if OPT_WIDE_CHARS 978d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fWide]), &fnts[fWide]); 979d522f475Smrg if (fnts[fWBold].fs == NULL) 980d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 981d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fWBold]), &fnts[fWBold]); 982d522f475Smrg#endif 983d522f475Smrg 984d522f475Smrg new_normal = getXtermForeground(xw, xw->flags, xw->cur_foreground); 985d522f475Smrg new_revers = getXtermBackground(xw, xw->flags, xw->cur_background); 986d522f475Smrg 987d522f475Smrg setCgsFore(xw, win, gcNorm, new_normal); 988d522f475Smrg setCgsBack(xw, win, gcNorm, new_revers); 989d522f475Smrg setCgsFont(xw, win, gcNorm, &(screen->fnts[fNorm])); 990d522f475Smrg 991d522f475Smrg copyCgs(xw, win, gcBold, gcNorm); 992d522f475Smrg setCgsFont(xw, win, gcBold, &(screen->fnts[fBold])); 993d522f475Smrg 994d522f475Smrg setCgsFore(xw, win, gcNormReverse, new_revers); 995d522f475Smrg setCgsBack(xw, win, gcNormReverse, new_normal); 996d522f475Smrg setCgsFont(xw, win, gcNormReverse, &(screen->fnts[fNorm])); 997d522f475Smrg 998d522f475Smrg copyCgs(xw, win, gcBoldReverse, gcNormReverse); 999d522f475Smrg setCgsFont(xw, win, gcBoldReverse, &(screen->fnts[fBold])); 1000d522f475Smrg 1001d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1002d522f475Smrg if (screen->fnts[fWide].fs != 0 1003d522f475Smrg && screen->fnts[fWBold].fs != 0) { 1004d522f475Smrg setCgsFore(xw, win, gcWide, new_normal); 1005d522f475Smrg setCgsBack(xw, win, gcWide, new_revers); 1006d522f475Smrg setCgsFont(xw, win, gcWide, &(screen->fnts[fWide])); 1007d522f475Smrg 1008d522f475Smrg copyCgs(xw, win, gcWBold, gcWide); 1009d522f475Smrg setCgsFont(xw, win, gcWBold, &(screen->fnts[fWBold])); 1010d522f475Smrg 1011d522f475Smrg setCgsFore(xw, win, gcWideReverse, new_revers); 1012d522f475Smrg setCgsBack(xw, win, gcWideReverse, new_normal); 1013d522f475Smrg setCgsFont(xw, win, gcWideReverse, &(screen->fnts[fWide])); 1014d522f475Smrg 1015d522f475Smrg copyCgs(xw, win, gcWBoldReverse, gcWideReverse); 1016d522f475Smrg setCgsFont(xw, win, gcWBoldReverse, &(screen->fnts[fWBold])); 1017d522f475Smrg } 1018d522f475Smrg }); 1019d522f475Smrg 1020d522f475Smrg screen->fnt_prop = proportional; 1021d522f475Smrg screen->fnt_boxes = True; 1022d522f475Smrg 1023d522f475Smrg#if OPT_BOX_CHARS 1024d522f475Smrg /* 1025d522f475Smrg * Xterm uses character positions 1-31 of a font for the line-drawing 1026d522f475Smrg * characters. Check that they are all present. The null character 1027d522f475Smrg * (0) is special, and is not used. 1028d522f475Smrg */ 1029d522f475Smrg#if OPT_RENDERFONT 1030d522f475Smrg if (UsingRenderFont(xw)) { 1031d522f475Smrg /* 1032d522f475Smrg * FIXME: we shouldn't even be here if we're using Xft. 1033d522f475Smrg */ 1034d522f475Smrg screen->fnt_boxes = False; 1035d522f475Smrg TRACE(("assume Xft missing line-drawing chars\n")); 1036d522f475Smrg } else 1037d522f475Smrg#endif 1038d522f475Smrg { 1039d522f475Smrg unsigned ch; 1040d522f475Smrg 1041d522f475Smrg for (ch = 1; ch < 32; ch++) { 1042d522f475Smrg unsigned n = ch; 1043d522f475Smrg#if OPT_WIDE_CHARS 1044d522f475Smrg if (screen->utf8_mode || screen->unicode_font) { 1045d522f475Smrg n = dec2ucs(ch); 1046d522f475Smrg if (n == UCS_REPL) 1047d522f475Smrg continue; 1048d522f475Smrg } 1049d522f475Smrg#endif 1050d522f475Smrg if (xtermMissingChar(xw, n, fnts[fNorm].fs)) { 1051d522f475Smrg TRACE(("missing normal char #%d\n", n)); 1052d522f475Smrg screen->fnt_boxes = False; 1053d522f475Smrg break; 1054d522f475Smrg } 1055d522f475Smrg if (xtermMissingChar(xw, n, fnts[fBold].fs)) { 1056d522f475Smrg TRACE(("missing bold char #%d\n", n)); 1057d522f475Smrg screen->fnt_boxes = False; 1058d522f475Smrg break; 1059d522f475Smrg } 1060d522f475Smrg } 1061d522f475Smrg } 1062d522f475Smrg TRACE(("Will %suse internal line-drawing characters\n", 1063d522f475Smrg screen->fnt_boxes ? "not " : "")); 1064d522f475Smrg#endif 1065d522f475Smrg 1066d522f475Smrg if (screen->always_bold_mode) { 1067d522f475Smrg screen->enbolden = screen->bold_mode; 1068d522f475Smrg } else { 1069d522f475Smrg screen->enbolden = screen->bold_mode 1070d522f475Smrg && ((fnts[fNorm].fs == fnts[fBold].fs) 1071d522f475Smrg || same_font_name(normal, myfonts.f_b)); 1072d522f475Smrg } 1073d522f475Smrg TRACE(("Will %suse 1-pixel offset/overstrike to simulate bold\n", 1074d522f475Smrg screen->enbolden ? "" : "not ")); 1075d522f475Smrg 1076d522f475Smrg set_menu_font(False); 1077d522f475Smrg screen->menu_font_number = fontnum; 1078d522f475Smrg set_menu_font(True); 1079d522f475Smrg if (tmpname) { /* if setting escape or sel */ 1080d522f475Smrg if (screen->MenuFontName(fontnum)) 1081d522f475Smrg free(screen->MenuFontName(fontnum)); 1082d522f475Smrg screen->MenuFontName(fontnum) = tmpname; 1083d522f475Smrg if (fontnum == fontMenu_fontescape) { 1084d522f475Smrg SetItemSensitivity(fontMenuEntries[fontMenu_fontescape].widget, 1085d522f475Smrg True); 1086d522f475Smrg } 1087d522f475Smrg#if OPT_SHIFT_FONTS 1088d522f475Smrg screen->menu_font_sizes[fontnum] = FontSize(fnts[fNorm].fs); 1089d522f475Smrg#endif 1090d522f475Smrg } 1091d522f475Smrg set_cursor_gcs(xw); 1092d522f475Smrg xtermUpdateFontInfo(xw, doresize); 1093d522f475Smrg TRACE(("Success Cgs - xtermLoadFont\n")); 1094d522f475Smrg return 1; 1095d522f475Smrg 1096d522f475Smrg bad: 1097d522f475Smrg if (tmpname) 1098d522f475Smrg free(tmpname); 1099d522f475Smrg releaseWindowGCs(xw, win); 1100d522f475Smrg 1101d522f475Smrg xtermCloseFonts(xw, fnts); 1102d522f475Smrg TRACE(("Fail Cgs - xtermLoadFont\n")); 1103d522f475Smrg return 0; 1104d522f475Smrg} 1105d522f475Smrg 1106d522f475Smrg#if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS 1107d522f475Smrg/* 1108d522f475Smrg * Collect font-names that we can modify with the load-vt-fonts() action. 1109d522f475Smrg */ 1110d522f475Smrgtypedef struct { 1111d522f475Smrg VTFontNames default_font; 1112d522f475Smrg char *menu_font_names[fontMenu_lastBuiltin + 1][fMAX]; 1113d522f475Smrg} SubResourceRec; 1114d522f475Smrg 1115d522f475Smrg#define MERGE_SUBFONT(src,dst,name) \ 1116d522f475Smrg if (dst.name == 0) { \ 1117d522f475Smrg TRACE(("MERGE_SUBFONT " #dst "." #name " merge %s\n", NonNull(src.name))); \ 1118d522f475Smrg dst.name = src.name; \ 1119d522f475Smrg } else { \ 1120d522f475Smrg TRACE(("MERGE_SUBFONT " #dst "." #name " found %s\n", NonNull(dst.name))); \ 1121d522f475Smrg } 1122d522f475Smrg 1123d522f475Smrg#define COPY_MENU_FONTS(src,dst) \ 1124d522f475Smrg TRACE(("COPY_MENU_FONTS " #src " to " #dst "\n")); \ 1125d522f475Smrg for (n = fontMenu_default; n <= fontMenu_lastBuiltin; ++n) { \ 1126d522f475Smrg for (m = 0; m < fMAX; ++m) { \ 1127d522f475Smrg dst.menu_font_names[n][m] = src.menu_font_names[n][m]; \ 1128d522f475Smrg } \ 1129d522f475Smrg } 1130d522f475Smrg 1131d522f475Smrg/* 1132d522f475Smrg * Load the "VT" font names from the given subresource name/class. These 1133d522f475Smrg * correspond to the VT100 resources. 1134d522f475Smrg */ 1135d522f475Smrgstatic Bool 1136d522f475SmrgxtermLoadVTFonts(XtermWidget w, char *myName, char *myClass) 1137d522f475Smrg{ 1138d522f475Smrg static Bool initialized = False; 1139d522f475Smrg static SubResourceRec original, referenceRec, subresourceRec; 1140d522f475Smrg 1141d522f475Smrg /* 1142d522f475Smrg * These are duplicates of the VT100 font resources, but with a special 1143d522f475Smrg * application/classname passed in to distinguish them. 1144d522f475Smrg */ 1145d522f475Smrg static XtResource font_resources[] = 1146d522f475Smrg { 1147d522f475Smrg Sres(XtNfont, XtCFont, default_font.f_n, DEFFONT), 1148d522f475Smrg Sres(XtNboldFont, XtCBoldFont, default_font.f_b, DEFBOLDFONT), 1149d522f475Smrg#if OPT_WIDE_CHARS 1150d522f475Smrg Sres(XtNwideFont, XtCWideFont, default_font.f_w, DEFWIDEFONT), 1151d522f475Smrg Sres(XtNwideBoldFont, XtCWideBoldFont, default_font.f_wb, DEFWIDEBOLDFONT), 1152d522f475Smrg#endif 1153d522f475Smrg Sres(XtNfont1, XtCFont1, MenuFontName(fontMenu_font1), NULL), 1154d522f475Smrg Sres(XtNfont2, XtCFont2, MenuFontName(fontMenu_font2), NULL), 1155d522f475Smrg Sres(XtNfont3, XtCFont3, MenuFontName(fontMenu_font3), NULL), 1156d522f475Smrg Sres(XtNfont4, XtCFont4, MenuFontName(fontMenu_font4), NULL), 1157d522f475Smrg Sres(XtNfont5, XtCFont5, MenuFontName(fontMenu_font5), NULL), 1158d522f475Smrg Sres(XtNfont6, XtCFont6, MenuFontName(fontMenu_font6), NULL), 1159d522f475Smrg }; 1160d522f475Smrg Cardinal n, m; 1161d522f475Smrg Bool status = True; 1162d522f475Smrg 1163d522f475Smrg if (!initialized) { 1164d522f475Smrg 1165d522f475Smrg initialized = True; 1166d522f475Smrg TRACE(("xtermLoadVTFonts saving original\n")); 1167d522f475Smrg original.default_font = w->misc.default_font; 1168d522f475Smrg COPY_MENU_FONTS(w->screen, original); 1169d522f475Smrg } 1170d522f475Smrg 1171d522f475Smrg if (myName == 0 || *myName == 0) { 1172d522f475Smrg TRACE(("xtermLoadVTFonts restoring original\n")); 1173d522f475Smrg w->misc.default_font = original.default_font; 1174d522f475Smrg COPY_MENU_FONTS(original, w->screen); 1175d522f475Smrg for (n = 0; n < XtNumber(original.menu_font_names); ++n) 1176d522f475Smrg w->screen.MenuFontName(n) = original.MenuFontName(n); 1177d522f475Smrg } else { 1178d522f475Smrg TRACE(("xtermLoadVTFonts(%s, %s)\n", myName, myClass)); 1179d522f475Smrg 1180d522f475Smrg memset(&subresourceRec, 0, sizeof(subresourceRec)); 1181d522f475Smrg XtGetSubresources((Widget) w, (XtPointer) &subresourceRec, 1182d522f475Smrg myName, myClass, 1183d522f475Smrg font_resources, 1184d522f475Smrg (Cardinal) XtNumber(font_resources), 1185d522f475Smrg NULL, (Cardinal) 0); 1186d522f475Smrg 1187d522f475Smrg if (memcmp(&referenceRec, &subresourceRec, sizeof(referenceRec))) { 1188d522f475Smrg 1189d522f475Smrg /* 1190d522f475Smrg * If a particular resource value was not found, use the original. 1191d522f475Smrg */ 1192d522f475Smrg MERGE_SUBFONT(w->misc, subresourceRec, default_font.f_n); 1193d522f475Smrg MERGE_SUBFONT(w->misc, subresourceRec, default_font.f_b); 1194d522f475Smrg#if OPT_WIDE_CHARS 1195d522f475Smrg MERGE_SUBFONT(w->misc, subresourceRec, default_font.f_w); 1196d522f475Smrg MERGE_SUBFONT(w->misc, subresourceRec, default_font.f_wb); 1197d522f475Smrg#endif 1198d522f475Smrg for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; ++n) 1199d522f475Smrg MERGE_SUBFONT(w->screen, subresourceRec, MenuFontName(n)); 1200d522f475Smrg 1201d522f475Smrg /* 1202d522f475Smrg * Finally, copy the subresource data to the widget. 1203d522f475Smrg */ 1204d522f475Smrg w->misc.default_font = subresourceRec.default_font; 1205d522f475Smrg COPY_MENU_FONTS(subresourceRec, w->screen); 1206d522f475Smrg w->screen.MenuFontName(fontMenu_default) = w->misc.default_font.f_n; 1207d522f475Smrg w->screen.menu_font_names[0][fBold] = w->misc.default_font.f_b; 1208d522f475Smrg#if OPT_WIDE_CHARS 1209d522f475Smrg w->screen.menu_font_names[0][fWide] = w->misc.default_font.f_w; 1210d522f475Smrg w->screen.menu_font_names[0][fWBold] = w->misc.default_font.f_wb; 1211d522f475Smrg#endif 1212d522f475Smrg } else { 1213d522f475Smrg TRACE(("...no resources found\n")); 1214d522f475Smrg status = False; 1215d522f475Smrg } 1216d522f475Smrg } 1217d522f475Smrg return status; 1218d522f475Smrg} 1219d522f475Smrg 1220d522f475Smrg#if OPT_WIDE_CHARS 1221d522f475Smrgstatic Bool 1222d522f475SmrgisWideFont(XFontStruct * fp, char *tag, Bool nullOk) 1223d522f475Smrg{ 1224d522f475Smrg Bool result = False; 1225d522f475Smrg 1226d522f475Smrg (void) tag; 1227d522f475Smrg if (okFont(fp)) { 1228d522f475Smrg unsigned count = countGlyphs(fp); 1229d522f475Smrg TRACE(("isWideFont(%s) found %d cells\n", tag, count)); 1230d522f475Smrg result = (count > 256) ? True : False; 1231d522f475Smrg } else { 1232d522f475Smrg result = nullOk; 1233d522f475Smrg } 1234d522f475Smrg return result; 1235d522f475Smrg} 1236d522f475Smrg 1237d522f475Smrg/* 1238d522f475Smrg * If the current fonts are not wide, load the UTF8 fonts. 1239d522f475Smrg * 1240d522f475Smrg * Called during initialization (for wide-character mode), the fonts have not 1241d522f475Smrg * been setup, so we pass nullOk=True to isWideFont(). 1242d522f475Smrg * 1243d522f475Smrg * Called after initialization, e.g., in response to the UTF-8 menu entry 1244d522f475Smrg * (starting from narrow character mode), it checks if the fonts are not wide. 1245d522f475Smrg */ 1246d522f475SmrgBool 1247d522f475SmrgxtermLoadWideFonts(XtermWidget xw, Bool nullOk) 1248d522f475Smrg{ 1249d522f475Smrg TScreen *screen = &(xw->screen); 1250d522f475Smrg Bool result; 1251d522f475Smrg 1252d522f475Smrg if (EmptyFont(screen->fnts[fWide].fs)) { 1253d522f475Smrg result = (isWideFont(screen->fnts[fNorm].fs, "normal", nullOk) 1254d522f475Smrg && isWideFont(screen->fnts[fBold].fs, "bold", nullOk)); 1255d522f475Smrg } else { 1256d522f475Smrg result = (isWideFont(screen->fnts[fWide].fs, "wide", nullOk) 1257d522f475Smrg && isWideFont(screen->fnts[fWBold].fs, "wide-bold", nullOk)); 1258d522f475Smrg if (result && !screen->utf8_latin1) { 1259d522f475Smrg result = (isWideFont(screen->fnts[fNorm].fs, "normal", nullOk) 1260d522f475Smrg && isWideFont(screen->fnts[fBold].fs, "bold", nullOk)); 1261d522f475Smrg } 1262d522f475Smrg } 1263d522f475Smrg if (!result) { 1264d522f475Smrg TRACE(("current fonts are not all wide%s\n", nullOk ? " nullOk" : "")); 1265d522f475Smrg result = xtermLoadVTFonts(xw, "utf8Fonts", "Utf8Fonts"); 1266d522f475Smrg } 1267d522f475Smrg TRACE(("xtermLoadWideFonts:%d\n", result)); 1268d522f475Smrg return result; 1269d522f475Smrg} 1270d522f475Smrg#endif /* OPT_WIDE_CHARS */ 1271d522f475Smrg 1272d522f475Smrg/* 1273d522f475Smrg * Restore the default fonts, i.e., if we had switched to wide-fonts. 1274d522f475Smrg */ 1275d522f475SmrgBool 1276d522f475SmrgxtermLoadDefaultFonts(XtermWidget w) 1277d522f475Smrg{ 1278d522f475Smrg Bool result; 1279d522f475Smrg result = xtermLoadVTFonts(w, NULL, NULL); 1280d522f475Smrg TRACE(("xtermLoadDefaultFonts:%d\n", result)); 1281d522f475Smrg return result; 1282d522f475Smrg} 1283d522f475Smrg#endif /* OPT_LOAD_VTFONTS || OPT_WIDE_CHARS */ 1284d522f475Smrg 1285d522f475Smrg#if OPT_LOAD_VTFONTS 1286d522f475Smrgvoid 1287d522f475SmrgHandleLoadVTFonts(Widget w, 1288d522f475Smrg XEvent * event GCC_UNUSED, 1289d522f475Smrg String * params GCC_UNUSED, 1290d522f475Smrg Cardinal *param_count GCC_UNUSED) 1291d522f475Smrg{ 1292d522f475Smrg static char empty[] = ""; /* appease strict compilers */ 1293d522f475Smrg 1294d522f475Smrg if (IsXtermWidget(w)) { 1295d522f475Smrg XtermWidget xw = (XtermWidget) w; 1296d522f475Smrg char buf[80]; 1297d522f475Smrg char *myName = (*param_count > 0) ? params[0] : empty; 1298d522f475Smrg char *convert = (*param_count > 1) ? params[1] : myName; 1299d522f475Smrg char *myClass = (char *) MyStackAlloc(strlen(convert), buf); 1300d522f475Smrg int n; 1301d522f475Smrg 1302d522f475Smrg TRACE(("HandleLoadVTFonts(%d)\n", *param_count)); 1303d522f475Smrg strcpy(myClass, convert); 13042eaa94a1Schristos if (*param_count == 1) 13052eaa94a1Schristos myClass[0] = x_toupper(myClass[0]); 1306d522f475Smrg 1307d522f475Smrg if (xtermLoadVTFonts(xw, myName, myClass)) { 1308d522f475Smrg /* 1309d522f475Smrg * When switching fonts, try to preserve the font-menu selection, since 1310d522f475Smrg * it is less surprising to do that (if the font-switching can be 1311d522f475Smrg * undone) than to switch to "Default". 1312d522f475Smrg */ 1313d522f475Smrg int font_number = xw->screen.menu_font_number; 1314d522f475Smrg if (font_number > fontMenu_lastBuiltin) 1315d522f475Smrg font_number = fontMenu_lastBuiltin; 1316d522f475Smrg for (n = 0; n < NMENUFONTS; ++n) 1317d522f475Smrg xw->screen.menu_font_sizes[n] = 0; 1318d522f475Smrg SetVTFont(xw, font_number, True, 1319d522f475Smrg ((font_number == fontMenu_default) 1320d522f475Smrg ? &(xw->misc.default_font) 1321d522f475Smrg : NULL)); 1322d522f475Smrg } 1323d522f475Smrg 1324d522f475Smrg MyStackFree(myClass, buf); 1325d522f475Smrg } 1326d522f475Smrg} 1327d522f475Smrg#endif /* OPT_LOAD_VTFONTS */ 1328d522f475Smrg 1329d522f475Smrg/* 1330d522f475Smrg * Set the limits for the box that outlines the cursor. 1331d522f475Smrg */ 1332d522f475Smrgvoid 1333d522f475SmrgxtermSetCursorBox(TScreen * screen) 1334d522f475Smrg{ 1335d522f475Smrg static XPoint VTbox[NBOX]; 1336d522f475Smrg XPoint *vp; 13372eaa94a1Schristos int fw = FontWidth(screen) - 1; 13382eaa94a1Schristos int fh = FontHeight(screen) - 1; 13392eaa94a1Schristos int hh = screen->cursor_underline ? 1 : fh; 1340d522f475Smrg 1341d522f475Smrg vp = &VTbox[1]; 13422eaa94a1Schristos (vp++)->x = (short) fw; 13432eaa94a1Schristos (vp++)->y = (short) hh; 13442eaa94a1Schristos (vp++)->x = (short) -fw; 13452eaa94a1Schristos vp->y = (short) -hh; 13462eaa94a1Schristos 1347d522f475Smrg screen->box = VTbox; 1348d522f475Smrg} 1349d522f475Smrg 1350d522f475Smrg#define CACHE_XFT(dst,src) if (src != 0) {\ 1351d522f475Smrg dst[fontnum] = src;\ 1352d522f475Smrg TRACE(("%s[%d] = %d (%d,%d) by %d\n",\ 1353d522f475Smrg #dst,\ 1354d522f475Smrg fontnum,\ 1355d522f475Smrg src->height,\ 1356d522f475Smrg src->ascent,\ 1357d522f475Smrg src->descent,\ 1358d522f475Smrg src->max_advance_width));\ 1359d522f475Smrg } 1360d522f475Smrg 1361d522f475Smrg#if OPT_RENDERFONT 1362d522f475Smrgstatic XftFont * 1363d522f475SmrgxtermOpenXft(Display * dpy, XftPattern * pat, const char *tag GCC_UNUSED) 1364d522f475Smrg{ 1365d522f475Smrg XftPattern *match; 1366d522f475Smrg XftResult status; 1367d522f475Smrg XftFont *result = 0; 1368d522f475Smrg 1369d522f475Smrg if (pat != 0) { 1370d522f475Smrg match = XftFontMatch(dpy, DefaultScreen(dpy), pat, &status); 1371d522f475Smrg if (match != 0) { 1372d522f475Smrg result = XftFontOpenPattern(dpy, match); 1373d522f475Smrg if (result != 0) { 1374d522f475Smrg TRACE(("...matched %s font\n", tag)); 1375d522f475Smrg } else { 1376d522f475Smrg TRACE(("...could did not open %s font\n", tag)); 1377d522f475Smrg XftPatternDestroy(match); 1378d522f475Smrg } 1379d522f475Smrg } else { 1380d522f475Smrg TRACE(("...did not match %s font\n", tag)); 1381d522f475Smrg } 1382d522f475Smrg } 1383d522f475Smrg return result; 1384d522f475Smrg} 1385d522f475Smrg#endif 1386d522f475Smrg 1387d522f475Smrg#if OPT_RENDERFONT 1388d522f475Smrg#if OPT_SHIFT_FONTS 1389d522f475Smrg/* 1390d522f475Smrg * Don't make a dependency on the math library for a single function. 1391d522f475Smrg * (Newton Raphson). 1392d522f475Smrg */ 1393d522f475Smrgstatic double 1394d522f475SmrgmySquareRoot(double value) 1395d522f475Smrg{ 1396d522f475Smrg double result = 0.0; 1397d522f475Smrg if (value > 0.0) { 1398d522f475Smrg int n; 1399d522f475Smrg double older = value; 1400d522f475Smrg for (n = 0; n < 10; ++n) { 1401d522f475Smrg double delta = (older * older - value) / (2.0 * older); 1402d522f475Smrg double newer = older - delta; 1403d522f475Smrg older = newer; 1404d522f475Smrg result = newer; 1405d522f475Smrg if (delta > -0.001 && delta < 0.001) 1406d522f475Smrg break; 1407d522f475Smrg } 1408d522f475Smrg } 1409d522f475Smrg return result; 1410d522f475Smrg} 1411d522f475Smrg#endif 1412d522f475Smrg 1413d522f475Smrg/* 1414d522f475Smrg * Given the Xft font metrics, determine the actual font size. This is used 1415d522f475Smrg * for each font to ensure that normal, bold and italic fonts follow the same 1416d522f475Smrg * rule. 1417d522f475Smrg */ 1418d522f475Smrgstatic void 1419d522f475SmrgsetRenderFontsize(TScreen * screen, VTwin * win, XftFont * font, const char *tag) 1420d522f475Smrg{ 1421d522f475Smrg if (font != 0) { 1422d522f475Smrg int width, height, ascent, descent; 1423d522f475Smrg 1424d522f475Smrg (void) screen; 1425d522f475Smrg 1426d522f475Smrg width = font->max_advance_width; 1427d522f475Smrg height = font->height; 1428d522f475Smrg ascent = font->ascent; 1429d522f475Smrg descent = font->descent; 1430d522f475Smrg if (height < ascent + descent) { 1431d522f475Smrg TRACE(("...increase height from %d\n", height)); 1432d522f475Smrg height = ascent + descent; 1433d522f475Smrg } 1434d522f475Smrg if (is_double_width_font_xft(screen->display, font)) { 1435d522f475Smrg TRACE(("...reduced width from %d\n", width)); 1436d522f475Smrg width >>= 1; 1437d522f475Smrg } 1438d522f475Smrg if (tag == 0) { 1439d522f475Smrg win->f_width = width; 1440d522f475Smrg win->f_height = height; 1441d522f475Smrg win->f_ascent = ascent; 1442d522f475Smrg win->f_descent = descent; 1443d522f475Smrg TRACE(("setRenderFontsize result %dx%d (%d+%d)\n", 1444d522f475Smrg width, height, ascent, descent)); 1445d522f475Smrg } else if (win->f_width < width || 1446d522f475Smrg win->f_height < height || 1447d522f475Smrg win->f_ascent < ascent || 1448d522f475Smrg win->f_descent < descent) { 1449d522f475Smrg TRACE(("setRenderFontsize %s changed %dx%d (%d+%d) to %dx%d (%d+%d)\n", 1450d522f475Smrg tag, 1451d522f475Smrg win->f_width, win->f_height, win->f_ascent, win->f_descent, 1452d522f475Smrg width, height, ascent, descent)); 1453d522f475Smrg 1454d522f475Smrg win->f_width = width; 1455d522f475Smrg win->f_height = height; 1456d522f475Smrg win->f_ascent = ascent; 1457d522f475Smrg win->f_descent = descent; 1458d522f475Smrg } else { 1459d522f475Smrg TRACE(("setRenderFontsize %s unchanged\n", tag)); 1460d522f475Smrg } 1461d522f475Smrg } 1462d522f475Smrg} 1463d522f475Smrg#endif 1464d522f475Smrg 1465d522f475Smrg/* 1466d522f475Smrg * Compute useful values for the font/window sizes 1467d522f475Smrg */ 1468d522f475Smrgvoid 1469d522f475SmrgxtermComputeFontInfo(XtermWidget xw, 1470d522f475Smrg VTwin * win, 1471d522f475Smrg XFontStruct * font, 1472d522f475Smrg int sbwidth) 1473d522f475Smrg{ 1474d522f475Smrg TScreen *screen = &(xw->screen); 1475d522f475Smrg 1476d522f475Smrg int i, j, width, height; 1477d522f475Smrg 1478d522f475Smrg#if OPT_RENDERFONT 1479d522f475Smrg /* 1480d522f475Smrg * xterm contains a lot of references to fonts, assuming they are fixed 1481d522f475Smrg * size. This chunk of code overrides the actual font-selection (see 1482d522f475Smrg * drawXtermText()), if the user has selected render-font. All of the 1483d522f475Smrg * font-loading for fixed-fonts still goes on whether or not this chunk 1484d522f475Smrg * overrides it. 1485d522f475Smrg */ 1486d522f475Smrg if (xw->misc.render_font && !IsIconWin(screen, win)) { 1487d522f475Smrg Display *dpy = screen->display; 1488d522f475Smrg int fontnum = screen->menu_font_number; 1489d522f475Smrg XftFont *norm = screen->renderFontNorm[fontnum]; 1490d522f475Smrg XftFont *bold = screen->renderFontBold[fontnum]; 1491d522f475Smrg XftFont *ital = screen->renderFontItal[fontnum]; 1492d522f475Smrg#if OPT_RENDERWIDE 1493d522f475Smrg XftFont *wnorm = screen->renderWideNorm[fontnum]; 1494d522f475Smrg XftFont *wbold = screen->renderWideBold[fontnum]; 1495d522f475Smrg XftFont *wital = screen->renderWideItal[fontnum]; 1496d522f475Smrg#endif 1497d522f475Smrg 1498d522f475Smrg if (norm == 0 && xw->misc.face_name) { 1499d522f475Smrg XftPattern *pat; 1500d522f475Smrg double face_size = xw->misc.face_size[fontnum]; 1501d522f475Smrg 1502d522f475Smrg TRACE(("xtermComputeFontInfo norm(face %s, size %f)\n", 1503d522f475Smrg xw->misc.face_name, 1504d522f475Smrg xw->misc.face_size[fontnum])); 1505d522f475Smrg 1506d522f475Smrg if (face_size <= 0.0) { 1507d522f475Smrg#if OPT_SHIFT_FONTS 1508d522f475Smrg /* 1509d522f475Smrg * If the user is switching font-sizes, make it follow by 1510d522f475Smrg * default the same ratios to the default as the fixed fonts 1511d522f475Smrg * would, for easy comparison. There will be some differences 1512d522f475Smrg * since the fixed fonts have a variety of height/width ratios, 1513d522f475Smrg * but this is simpler than adding another resource value - and 1514d522f475Smrg * as noted above, the data for the fixed fonts are available. 1515d522f475Smrg */ 1516d522f475Smrg lookupOneFontSize(xw, 0); 1517d522f475Smrg lookupOneFontSize(xw, fontnum); 1518d522f475Smrg if (fontnum == fontMenu_default) { 1519d522f475Smrg face_size = 14.0; 1520d522f475Smrg } else { 1521d522f475Smrg double ratio; 1522d522f475Smrg int num = screen->menu_font_sizes[fontnum]; 1523d522f475Smrg int den = screen->menu_font_sizes[0]; 1524d522f475Smrg 1525d522f475Smrg if (den <= 0) 1526d522f475Smrg den = 1; 1527d522f475Smrg ratio = mySquareRoot((1.0 * num) / den); 1528d522f475Smrg 1529d522f475Smrg face_size = (ratio * xw->misc.face_size[0]); 1530d522f475Smrg TRACE(("scaled using %3d/%d = %.2f -> %f\n", 1531d522f475Smrg num, den, ratio, face_size)); 1532d522f475Smrg } 1533d522f475Smrg#else 1534d522f475Smrg switch (fontnum) { 1535d522f475Smrg case fontMenu_font1: 1536d522f475Smrg face_size = 8.0; 1537d522f475Smrg break; 1538d522f475Smrg case fontMenu_font2: 1539d522f475Smrg face_size = 10.0; 1540d522f475Smrg break; 1541d522f475Smrg case fontMenu_font3: 1542d522f475Smrg face_size = 12.0; 1543d522f475Smrg break; 1544d522f475Smrg default: 1545d522f475Smrg face_size = 14.0; 1546d522f475Smrg break; 1547d522f475Smrg case fontMenu_font4: 1548d522f475Smrg face_size = 16.0; 1549d522f475Smrg break; 1550d522f475Smrg case fontMenu_font5: 1551d522f475Smrg face_size = 18.0; 1552d522f475Smrg break; 1553d522f475Smrg case fontMenu_font6: 1554d522f475Smrg face_size = 20.0; 1555d522f475Smrg break; 1556d522f475Smrg } 1557d522f475Smrg#endif 1558d522f475Smrg xw->misc.face_size[fontnum] = face_size; 1559d522f475Smrg } 1560d522f475Smrg 1561d522f475Smrg /* 1562d522f475Smrg * By observation (there is no documentation), XftPatternBuild is 1563d522f475Smrg * cumulative. Build the bold- and italic-patterns on top of the 1564d522f475Smrg * normal pattern. 1565d522f475Smrg */ 1566d522f475Smrg#define NormXftPattern \ 1567d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 1568d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 1569d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 1570d522f475Smrg 1571d522f475Smrg#define BoldXftPattern(norm) \ 1572d522f475Smrg XFT_WEIGHT, XftTypeInteger, XFT_WEIGHT_BOLD, \ 1573d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 1574d522f475Smrg 1575d522f475Smrg#define ItalXftPattern(norm) \ 1576d522f475Smrg XFT_SLANT, XftTypeInteger, XFT_SLANT_ITALIC, \ 1577d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 1578d522f475Smrg 1579d522f475Smrg if ((pat = XftNameParse(xw->misc.face_name)) != 0) { 1580d522f475Smrg XftPatternBuild(pat, 1581d522f475Smrg NormXftPattern, 1582d522f475Smrg (void *) 0); 1583d522f475Smrg norm = xtermOpenXft(dpy, pat, "normal"); 1584d522f475Smrg 1585d522f475Smrg if (norm != 0) { 1586d522f475Smrg XftPatternBuild(pat, 1587d522f475Smrg BoldXftPattern(norm), 1588d522f475Smrg (void *) 0); 1589d522f475Smrg bold = xtermOpenXft(dpy, pat, "bold"); 1590d522f475Smrg 1591d522f475Smrg#if OPT_ISO_COLORS 1592d522f475Smrg if (screen->italicULMode 1593d522f475Smrg && (pat = XftNameParse(xw->misc.face_name)) != 0) { 1594d522f475Smrg XftPatternBuild(pat, 1595d522f475Smrg NormXftPattern, 1596d522f475Smrg ItalXftPattern(norm), 1597d522f475Smrg (void *) 0); 1598d522f475Smrg ital = xtermOpenXft(dpy, pat, "italic"); 1599d522f475Smrg } 1600d522f475Smrg#endif /* OPT_ISO_COLORS */ 1601d522f475Smrg 1602d522f475Smrg /* 1603d522f475Smrg * FIXME: just assume that the corresponding font has no 1604d522f475Smrg * graphics characters. 1605d522f475Smrg */ 1606d522f475Smrg if (screen->fnt_boxes) { 1607d522f475Smrg screen->fnt_boxes = False; 1608d522f475Smrg TRACE(("Xft opened - will %suse internal line-drawing characters\n", 1609d522f475Smrg screen->fnt_boxes ? "not " : "")); 1610d522f475Smrg } 1611d522f475Smrg } 1612d522f475Smrg 1613d522f475Smrg XftPatternDestroy(pat); 1614d522f475Smrg } 1615d522f475Smrg 1616d522f475Smrg CACHE_XFT(screen->renderFontNorm, norm); 1617d522f475Smrg CACHE_XFT(screen->renderFontBold, bold); 1618d522f475Smrg CACHE_XFT(screen->renderFontItal, ital); 1619d522f475Smrg 1620d522f475Smrg /* 1621d522f475Smrg * See xtermXftDrawString(). 1622d522f475Smrg */ 1623d522f475Smrg#if OPT_RENDERWIDE 1624d522f475Smrg if (norm != 0 && screen->wide_chars) { 1625d522f475Smrg char *face_name = (xw->misc.face_wide_name 1626d522f475Smrg ? xw->misc.face_wide_name 1627d522f475Smrg : xw->misc.face_name); 1628d522f475Smrg int char_width = norm->max_advance_width * 2; 1629d522f475Smrg 1630d522f475Smrg TRACE(("xtermComputeFontInfo wide(face %s, char_width %d)\n", 1631d522f475Smrg face_name, 1632d522f475Smrg char_width)); 1633d522f475Smrg 1634d522f475Smrg#define WideXftPattern \ 1635d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 1636d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 1637d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 1638d522f475Smrg 1639d522f475Smrg if ((pat = XftNameParse(face_name)) != 0) { 1640d522f475Smrg XftPatternBuild(pat, 1641d522f475Smrg WideXftPattern, 1642d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, char_width, 1643d522f475Smrg (void *) 0); 1644d522f475Smrg wnorm = xtermOpenXft(dpy, pat, "wide"); 1645d522f475Smrg 1646d522f475Smrg if (wnorm != 0) { 1647d522f475Smrg XftPatternBuild(pat, 1648d522f475Smrg WideXftPattern, 1649d522f475Smrg BoldXftPattern(wnorm), 1650d522f475Smrg (void *) 0); 1651d522f475Smrg wbold = xtermOpenXft(dpy, pat, "wide-bold"); 1652d522f475Smrg 1653d522f475Smrg#if OPT_ISO_COLORS 1654d522f475Smrg if (screen->italicULMode 1655d522f475Smrg && (pat = XftNameParse(face_name)) != 0) { 1656d522f475Smrg XftPatternBuild(pat, 1657d522f475Smrg WideXftPattern, 1658d522f475Smrg ItalXftPattern(wnorm), 1659d522f475Smrg (void *) 0); 1660d522f475Smrg wital = xtermOpenXft(dpy, pat, "wide-italic"); 1661d522f475Smrg } 1662d522f475Smrg#endif 1663d522f475Smrg } 1664d522f475Smrg XftPatternDestroy(pat); 1665d522f475Smrg } 1666d522f475Smrg 1667d522f475Smrg CACHE_XFT(screen->renderWideNorm, wnorm); 1668d522f475Smrg CACHE_XFT(screen->renderWideBold, wbold); 1669d522f475Smrg CACHE_XFT(screen->renderWideItal, wital); 1670d522f475Smrg } 1671d522f475Smrg#endif /* OPT_RENDERWIDE */ 1672d522f475Smrg } 1673d522f475Smrg if (norm == 0) { 16742eaa94a1Schristos TRACE(("...no TrueType font found for number %d, disable menu entry\n", fontnum)); 1675d522f475Smrg xw->misc.render_font = False; 1676d522f475Smrg update_font_renderfont(); 1677d522f475Smrg /* now we will fall through into the bitmap fonts */ 1678d522f475Smrg } else { 1679d522f475Smrg setRenderFontsize(screen, win, norm, NULL); 1680d522f475Smrg setRenderFontsize(screen, win, bold, "bold"); 1681d522f475Smrg setRenderFontsize(screen, win, ital, "ital"); 1682d522f475Smrg } 1683d522f475Smrg } 1684d522f475Smrg /* 1685d522f475Smrg * Are we handling a bitmap font? 1686d522f475Smrg */ 1687d522f475Smrg if (!xw->misc.render_font || IsIconWin(screen, win)) 1688d522f475Smrg#endif /* OPT_RENDERFONT */ 1689d522f475Smrg { 1690d522f475Smrg if (is_double_width_font(font)) { 1691d522f475Smrg win->f_width = (font->min_bounds.width); 1692d522f475Smrg } else { 1693d522f475Smrg win->f_width = (font->max_bounds.width); 1694d522f475Smrg } 1695d522f475Smrg win->f_height = (font->ascent + font->descent); 1696d522f475Smrg win->f_ascent = font->ascent; 1697d522f475Smrg win->f_descent = font->descent; 1698d522f475Smrg } 1699d522f475Smrg i = 2 * screen->border + sbwidth; 1700d522f475Smrg j = 2 * screen->border; 1701d522f475Smrg width = MaxCols(screen) * win->f_width + i; 1702d522f475Smrg height = MaxRows(screen) * win->f_height + j; 1703d522f475Smrg win->fullwidth = width; 1704d522f475Smrg win->fullheight = height; 1705d522f475Smrg win->width = width - i; 1706d522f475Smrg win->height = height - j; 1707d522f475Smrg 1708d522f475Smrg TRACE(("xtermComputeFontInfo window %dx%d (full %dx%d), fontsize %dx%d (asc %d, dsc %d)\n", 1709d522f475Smrg win->height, 1710d522f475Smrg win->width, 1711d522f475Smrg win->fullheight, 1712d522f475Smrg win->fullwidth, 1713d522f475Smrg win->f_height, 1714d522f475Smrg win->f_width, 1715d522f475Smrg win->f_ascent, 1716d522f475Smrg win->f_descent)); 1717d522f475Smrg} 1718d522f475Smrg 1719d522f475Smrg/* save this information as a side-effect for double-sized characters */ 1720d522f475Smrgvoid 1721d522f475SmrgxtermSaveFontInfo(TScreen * screen, XFontStruct * font) 1722d522f475Smrg{ 1723d522f475Smrg screen->fnt_wide = (font->max_bounds.width); 1724d522f475Smrg screen->fnt_high = (font->ascent + font->descent); 1725d522f475Smrg TRACE(("xtermSaveFontInfo %dx%d\n", screen->fnt_high, screen->fnt_wide)); 1726d522f475Smrg} 1727d522f475Smrg 1728d522f475Smrg/* 1729d522f475Smrg * After loading a new font, update the structures that use its size. 1730d522f475Smrg */ 1731d522f475Smrgvoid 1732d522f475SmrgxtermUpdateFontInfo(XtermWidget xw, Bool doresize) 1733d522f475Smrg{ 1734d522f475Smrg TScreen *screen = &(xw->screen); 1735d522f475Smrg 1736d522f475Smrg int scrollbar_width; 1737d522f475Smrg VTwin *win = &(screen->fullVwin); 1738d522f475Smrg 1739d522f475Smrg scrollbar_width = (xw->misc.scrollbar 1740d522f475Smrg ? (screen->scrollWidget->core.width + 1741d522f475Smrg BorderWidth(screen->scrollWidget)) 1742d522f475Smrg : 0); 1743d522f475Smrg xtermComputeFontInfo(xw, win, screen->fnts[fNorm].fs, scrollbar_width); 1744d522f475Smrg xtermSaveFontInfo(screen, screen->fnts[fNorm].fs); 1745d522f475Smrg 1746d522f475Smrg if (doresize) { 1747d522f475Smrg if (VWindow(screen)) { 1748d522f475Smrg xtermClear(xw); 1749d522f475Smrg } 1750d522f475Smrg TRACE(("xtermUpdateFontInfo {{\n")); 1751d522f475Smrg DoResizeScreen(xw); /* set to the new natural size */ 1752d522f475Smrg ResizeScrollBar(xw); 1753d522f475Smrg Redraw(); 1754d522f475Smrg TRACE(("... }} xtermUpdateFontInfo\n")); 1755d522f475Smrg#ifdef SCROLLBAR_RIGHT 1756d522f475Smrg updateRightScrollbar(xw); 1757d522f475Smrg#endif 1758d522f475Smrg } 1759d522f475Smrg xtermSetCursorBox(screen); 1760d522f475Smrg} 1761d522f475Smrg 1762d522f475Smrg#if OPT_BOX_CHARS 1763d522f475Smrg 1764d522f475Smrg/* 1765d522f475Smrg * Returns true if the given character is missing from the specified font. 1766d522f475Smrg */ 1767d522f475SmrgBool 1768d522f475SmrgxtermMissingChar(XtermWidget xw, unsigned ch, XFontStruct * font) 1769d522f475Smrg{ 1770d522f475Smrg if (font != 0 1771d522f475Smrg && font->per_char != 0 1772d522f475Smrg && !font->all_chars_exist) { 1773d522f475Smrg static XCharStruct dft, *tmp = &dft, *pc = 0; 1774d522f475Smrg 1775d522f475Smrg if (font->max_byte1 == 0) { 1776d522f475Smrg#if OPT_WIDE_CHARS 1777d522f475Smrg if (ch > 255) { 1778d522f475Smrg TRACE(("xtermMissingChar %#04x (row)\n", ch)); 1779d522f475Smrg return True; 1780d522f475Smrg } 1781d522f475Smrg#endif 1782d522f475Smrg CI_GET_CHAR_INFO_1D(font, E2A(ch), tmp, pc); 1783d522f475Smrg } 1784d522f475Smrg#if OPT_WIDE_CHARS 1785d522f475Smrg else { 1786d522f475Smrg CI_GET_CHAR_INFO_2D(font, HI_BYTE(ch), LO_BYTE(ch), tmp, pc); 1787d522f475Smrg } 1788d522f475Smrg#else 1789d522f475Smrg 1790d522f475Smrg if (!pc) 1791d522f475Smrg return False; /* Urgh! */ 1792d522f475Smrg#endif 1793d522f475Smrg 1794d522f475Smrg if (CI_NONEXISTCHAR(pc)) { 1795d522f475Smrg TRACE(("xtermMissingChar %#04x (!exists)\n", ch)); 1796d522f475Smrg return True; 1797d522f475Smrg } 1798d522f475Smrg } 1799d522f475Smrg if (xtermIsDecGraphic(ch) 1800d522f475Smrg && xw->screen.force_box_chars) { 1801d522f475Smrg TRACE(("xtermMissingChar %#04x (forced off)\n", ch)); 1802d522f475Smrg return True; 1803d522f475Smrg } 1804d522f475Smrg return False; 1805d522f475Smrg} 1806d522f475Smrg 1807d522f475Smrg/* 1808d522f475Smrg * The grid is arbitrary, enough resolution that nothing's lost in 1809d522f475Smrg * initialization. 1810d522f475Smrg */ 1811d522f475Smrg#define BOX_HIGH 60 1812d522f475Smrg#define BOX_WIDE 60 1813d522f475Smrg 1814d522f475Smrg#define MID_HIGH (BOX_HIGH/2) 1815d522f475Smrg#define MID_WIDE (BOX_WIDE/2) 1816d522f475Smrg 1817d522f475Smrg#define CHR_WIDE ((9*BOX_WIDE)/10) 1818d522f475Smrg#define CHR_HIGH ((9*BOX_HIGH)/10) 1819d522f475Smrg 1820d522f475Smrg/* 1821d522f475Smrg * ...since we'll scale the values anyway. 1822d522f475Smrg */ 1823d522f475Smrg#define SCALE_X(n) n = (n * (font_width-1)) / (BOX_WIDE-1) 1824d522f475Smrg#define SCALE_Y(n) n = (n * (font_height-1)) / (BOX_HIGH-1) 1825d522f475Smrg 1826d522f475Smrg#define SEG(x0,y0,x1,y1) x0,y0, x1,y1 1827d522f475Smrg 1828d522f475Smrg/* 1829d522f475Smrg * Draw the given graphic character, if it is simple enough (i.e., a 1830d522f475Smrg * line-drawing character). 1831d522f475Smrg */ 1832d522f475Smrgvoid 1833d522f475SmrgxtermDrawBoxChar(XtermWidget xw, 1834d522f475Smrg unsigned ch, 1835d522f475Smrg unsigned flags, 1836d522f475Smrg GC gc, 1837d522f475Smrg int x, 1838d522f475Smrg int y, 1839d522f475Smrg int cells) 1840d522f475Smrg{ 1841d522f475Smrg TScreen *screen = &(xw->screen); 1842d522f475Smrg /* *INDENT-OFF* */ 1843d522f475Smrg static const short glyph_ht[] = { 1844d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,5*MID_HIGH/6), /* H */ 1845d522f475Smrg SEG(6*BOX_WIDE/10, 0, 6*BOX_WIDE/10,5*MID_HIGH/6), 1846d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*BOX_WIDE/10,5*MID_HIGH/12), 1847d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 1848d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 1849d522f475Smrg -1 1850d522f475Smrg }, glyph_ff[] = { 1851d522f475Smrg SEG(1*BOX_WIDE/10, 0, 6*BOX_WIDE/10, 0), /* F */ 1852d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*CHR_WIDE/12,5*MID_HIGH/12), 1853d522f475Smrg SEG(1*BOX_WIDE/10, 0, 0*BOX_WIDE/3, 5*MID_HIGH/6), 1854d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 1855d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 1856d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 1857d522f475Smrg -1 1858d522f475Smrg }, glyph_lf[] = { 1859d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,9*MID_HIGH/12), /* L */ 1860d522f475Smrg SEG(1*BOX_WIDE/10,9*MID_HIGH/12,6*BOX_WIDE/10,9*MID_HIGH/12), 1861d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 1862d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 1863d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 1864d522f475Smrg -1 1865d522f475Smrg }, glyph_nl[] = { 1866d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/6, 1*BOX_WIDE/10, 0), /* N */ 1867d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/6, 5*MID_HIGH/6), 1868d522f475Smrg SEG(5*BOX_WIDE/6, 5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 1869d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), /* L */ 1870d522f475Smrg SEG(1*BOX_WIDE/3, CHR_HIGH, CHR_WIDE, CHR_HIGH), 1871d522f475Smrg -1 1872d522f475Smrg }, glyph_vt[] = { 1873d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/12,5*MID_HIGH/6), /* V */ 1874d522f475Smrg SEG(5*BOX_WIDE/12,5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 1875d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 1876d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 1877d522f475Smrg -1 1878d522f475Smrg }, plus_or_minus[] = 1879d522f475Smrg { 1880d522f475Smrg SEG( 0, 5*BOX_HIGH/6, CHR_WIDE, 5*BOX_HIGH/6), 1881d522f475Smrg SEG( MID_WIDE, 2*BOX_HIGH/6, MID_WIDE, 4*BOX_HIGH/6), 1882d522f475Smrg SEG( 0, 3*BOX_HIGH/6, CHR_WIDE, 3*BOX_HIGH/6), 1883d522f475Smrg -1 1884d522f475Smrg }, lower_right_corner[] = 1885d522f475Smrg { 1886d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 1887d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, 0), 1888d522f475Smrg -1 1889d522f475Smrg }, upper_right_corner[] = 1890d522f475Smrg { 1891d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 1892d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 1893d522f475Smrg -1 1894d522f475Smrg }, upper_left_corner[] = 1895d522f475Smrg { 1896d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 1897d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 1898d522f475Smrg -1 1899d522f475Smrg }, lower_left_corner[] = 1900d522f475Smrg { 1901d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 1902d522f475Smrg SEG( MID_WIDE, MID_WIDE, BOX_WIDE, MID_HIGH), 1903d522f475Smrg -1 1904d522f475Smrg }, cross[] = 1905d522f475Smrg { 1906d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 1907d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 1908d522f475Smrg -1 1909d522f475Smrg }, scan_line_1[] = 1910d522f475Smrg { 1911d522f475Smrg SEG( 0, 0, BOX_WIDE, 0), 1912d522f475Smrg -1 1913d522f475Smrg }, scan_line_3[] = 1914d522f475Smrg { 1915d522f475Smrg SEG( 0, BOX_HIGH/4, BOX_WIDE, BOX_HIGH/4), 1916d522f475Smrg -1 1917d522f475Smrg }, scan_line_7[] = 1918d522f475Smrg { 1919d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 1920d522f475Smrg -1 1921d522f475Smrg }, scan_line_9[] = 1922d522f475Smrg { 1923d522f475Smrg SEG( 0, 3*BOX_HIGH/4, BOX_WIDE, 3*BOX_HIGH/4), 1924d522f475Smrg -1 1925d522f475Smrg }, horizontal_line[] = 1926d522f475Smrg { 1927d522f475Smrg SEG( 0, BOX_HIGH, BOX_WIDE, BOX_HIGH), 1928d522f475Smrg -1 1929d522f475Smrg }, left_tee[] = 1930d522f475Smrg { 1931d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 1932d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 1933d522f475Smrg -1 1934d522f475Smrg }, right_tee[] = 1935d522f475Smrg { 1936d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 1937d522f475Smrg SEG( MID_WIDE, MID_HIGH, 0, MID_HIGH), 1938d522f475Smrg -1 1939d522f475Smrg }, bottom_tee[] = 1940d522f475Smrg { 1941d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 1942d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 1943d522f475Smrg -1 1944d522f475Smrg }, top_tee[] = 1945d522f475Smrg { 1946d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 1947d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 1948d522f475Smrg -1 1949d522f475Smrg }, vertical_line[] = 1950d522f475Smrg { 1951d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 1952d522f475Smrg -1 1953d522f475Smrg }, less_than_or_equal[] = 1954d522f475Smrg { 1955d522f475Smrg SEG( CHR_WIDE, BOX_HIGH/3, 0, MID_HIGH), 1956d522f475Smrg SEG( CHR_WIDE, 2*BOX_HIGH/3, 0, MID_HIGH), 1957d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 1958d522f475Smrg -1 1959d522f475Smrg }, greater_than_or_equal[] = 1960d522f475Smrg { 1961d522f475Smrg SEG( 0, BOX_HIGH/3, CHR_WIDE, MID_HIGH), 1962d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, MID_HIGH), 1963d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 1964d522f475Smrg -1 1965d522f475Smrg }, greek_pi[] = 1966d522f475Smrg { 1967d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 1968d522f475Smrg SEG(5*CHR_WIDE/6, MID_HIGH, 5*CHR_WIDE/6, CHR_HIGH), 1969d522f475Smrg SEG(2*CHR_WIDE/6, MID_HIGH, 2*CHR_WIDE/6, CHR_HIGH), 1970d522f475Smrg -1 1971d522f475Smrg }, not_equal_to[] = 1972d522f475Smrg { 1973d522f475Smrg SEG(2*BOX_WIDE/3, 1*BOX_HIGH/3, 1*BOX_WIDE/3, CHR_HIGH), 1974d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, 2*BOX_HIGH/3), 1975d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 1976d522f475Smrg -1 1977d522f475Smrg }; 1978d522f475Smrg /* *INDENT-ON* */ 1979d522f475Smrg 1980d522f475Smrg static const short *lines[] = 1981d522f475Smrg { 1982d522f475Smrg 0, /* 00 (unused) */ 1983d522f475Smrg 0, /* 01 diamond */ 1984d522f475Smrg 0, /* 02 box */ 1985d522f475Smrg glyph_ht, /* 03 HT */ 1986d522f475Smrg glyph_ff, /* 04 FF */ 1987d522f475Smrg 0, /* 05 CR */ 1988d522f475Smrg glyph_lf, /* 06 LF */ 1989d522f475Smrg 0, /* 07 degrees (small circle) */ 1990d522f475Smrg plus_or_minus, /* 08 */ 1991d522f475Smrg glyph_nl, /* 09 */ 1992d522f475Smrg glyph_vt, /* 0A */ 1993d522f475Smrg lower_right_corner, /* 0B */ 1994d522f475Smrg upper_right_corner, /* 0C */ 1995d522f475Smrg upper_left_corner, /* 0D */ 1996d522f475Smrg lower_left_corner, /* 0E */ 1997d522f475Smrg cross, /* 0F */ 1998d522f475Smrg scan_line_1, /* 10 */ 1999d522f475Smrg scan_line_3, /* 11 */ 2000d522f475Smrg scan_line_7, /* 12 */ 2001d522f475Smrg scan_line_9, /* 13 */ 2002d522f475Smrg horizontal_line, /* 14 */ 2003d522f475Smrg left_tee, /* 15 */ 2004d522f475Smrg right_tee, /* 16 */ 2005d522f475Smrg bottom_tee, /* 17 */ 2006d522f475Smrg top_tee, /* 18 */ 2007d522f475Smrg vertical_line, /* 19 */ 2008d522f475Smrg less_than_or_equal, /* 1A */ 2009d522f475Smrg greater_than_or_equal, /* 1B */ 2010d522f475Smrg greek_pi, /* 1C */ 2011d522f475Smrg not_equal_to, /* 1D */ 2012d522f475Smrg 0, /* 1E LB */ 2013d522f475Smrg 0, /* 1F bullet */ 2014d522f475Smrg }; 2015d522f475Smrg 2016d522f475Smrg GC gc2; 2017d522f475Smrg CgsEnum cgsId = (ch == 2) ? gcDots : gcLine; 2018d522f475Smrg VTwin *cgsWin = WhichVWin(screen); 2019d522f475Smrg const short *p; 2020d522f475Smrg unsigned font_width = ((flags & DOUBLEWFONT) ? 2 : 1) * screen->fnt_wide; 2021d522f475Smrg unsigned font_height = ((flags & DOUBLEHFONT) ? 2 : 1) * screen->fnt_high; 2022d522f475Smrg 2023d522f475Smrg if (cells > 1) 2024d522f475Smrg font_width *= cells; 2025d522f475Smrg 2026d522f475Smrg#if OPT_WIDE_CHARS 2027d522f475Smrg /* 2028d522f475Smrg * Try to show line-drawing characters if we happen to be in UTF-8 2029d522f475Smrg * mode, but have gotten an old-style font. 2030d522f475Smrg */ 2031d522f475Smrg if (screen->utf8_mode 2032d522f475Smrg#if OPT_RENDERFONT 2033d522f475Smrg && !UsingRenderFont(xw) 2034d522f475Smrg#endif 2035d522f475Smrg && (ch > 127) 2036d522f475Smrg && (ch != UCS_REPL)) { 2037d522f475Smrg unsigned n; 2038d522f475Smrg for (n = 1; n < 32; n++) { 2039d522f475Smrg if (dec2ucs(n) == ch 2040d522f475Smrg && !xtermMissingChar(xw, n, 2041d522f475Smrg ((flags & BOLD) 2042d522f475Smrg ? screen->fnts[fBold].fs 2043d522f475Smrg : screen->fnts[fNorm].fs))) { 2044d522f475Smrg TRACE(("...use xterm-style linedrawing\n")); 2045d522f475Smrg ch = n; 2046d522f475Smrg break; 2047d522f475Smrg } 2048d522f475Smrg } 2049d522f475Smrg } 2050d522f475Smrg#endif 2051d522f475Smrg 2052d522f475Smrg TRACE(("DRAW_BOX(%d) cell %dx%d at %d,%d%s\n", 2053d522f475Smrg ch, font_height, font_width, y, x, 2054d522f475Smrg (ch >= (sizeof(lines) / sizeof(lines[0])) 2055d522f475Smrg ? "-BAD" 2056d522f475Smrg : ""))); 2057d522f475Smrg 2058d522f475Smrg if (cgsId == gcDots) { 2059d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2060d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2061d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2062d522f475Smrg } else { 2063d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2064d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2065d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2066d522f475Smrg } 2067d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2068d522f475Smrg 2069d522f475Smrg if (!(flags & NOBACKGROUND)) { 2070d522f475Smrg XFillRectangle(screen->display, VWindow(screen), gc2, x, y, 2071d522f475Smrg font_width, 2072d522f475Smrg font_height); 2073d522f475Smrg } 2074d522f475Smrg 2075d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2076d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2077d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2078d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2079d522f475Smrg 2080d522f475Smrg XSetLineAttributes(screen->display, gc2, 2081d522f475Smrg (flags & BOLD) 2082d522f475Smrg ? ((font_height > 12) 2083d522f475Smrg ? font_height / 12 2084d522f475Smrg : 1) 2085d522f475Smrg : ((font_height > 16) 2086d522f475Smrg ? font_height / 16 2087d522f475Smrg : 1), 2088d522f475Smrg LineSolid, 2089d522f475Smrg CapProjecting, 2090d522f475Smrg JoinMiter); 2091d522f475Smrg 2092d522f475Smrg if (ch == 1) { /* diamond */ 2093d522f475Smrg XPoint points[5]; 2094d522f475Smrg int npoints = 5, n; 2095d522f475Smrg 2096d522f475Smrg points[0].x = MID_WIDE; 2097d522f475Smrg points[0].y = BOX_HIGH / 4; 2098d522f475Smrg 2099d522f475Smrg points[1].x = 8 * BOX_WIDE / 8; 2100d522f475Smrg points[1].y = MID_HIGH; 2101d522f475Smrg 2102d522f475Smrg points[2].x = points[0].x; 2103d522f475Smrg points[2].y = 3 * BOX_HIGH / 4; 2104d522f475Smrg 2105d522f475Smrg points[3].x = 0 * BOX_WIDE / 8; 2106d522f475Smrg points[3].y = points[1].y; 2107d522f475Smrg 2108d522f475Smrg points[4].x = points[0].x; 2109d522f475Smrg points[4].y = points[0].y; 2110d522f475Smrg 2111d522f475Smrg for (n = 0; n < npoints; ++n) { 2112d522f475Smrg SCALE_X(points[n].x); 2113d522f475Smrg SCALE_Y(points[n].y); 2114d522f475Smrg points[n].x += x; 2115d522f475Smrg points[n].y += y; 2116d522f475Smrg } 2117d522f475Smrg 2118d522f475Smrg XFillPolygon(screen->display, 2119d522f475Smrg VWindow(screen), gc2, 2120d522f475Smrg points, npoints, 2121d522f475Smrg Convex, CoordModeOrigin); 2122d522f475Smrg } else if (ch == 7) { /* degrees */ 2123d522f475Smrg unsigned width = (BOX_WIDE / 3); 2124d522f475Smrg int x_coord = MID_WIDE - (width / 2); 2125d522f475Smrg int y_coord = MID_HIGH - width; 2126d522f475Smrg 2127d522f475Smrg SCALE_X(x_coord); 2128d522f475Smrg SCALE_Y(y_coord); 2129d522f475Smrg SCALE_X(width); 2130d522f475Smrg 2131d522f475Smrg XDrawArc(screen->display, 2132d522f475Smrg VWindow(screen), gc2, 2133d522f475Smrg x + x_coord, y + y_coord, width, width, 2134d522f475Smrg 0, 2135d522f475Smrg 360 * 64); 2136d522f475Smrg } else if (ch == 0x1f) { /* bullet */ 2137d522f475Smrg unsigned width = 7 * BOX_WIDE / 10; 2138d522f475Smrg int x_coord = MID_WIDE - (width / 3); 2139d522f475Smrg int y_coord = MID_HIGH - (width / 3); 2140d522f475Smrg 2141d522f475Smrg SCALE_X(x_coord); 2142d522f475Smrg SCALE_Y(y_coord); 2143d522f475Smrg SCALE_X(width); 2144d522f475Smrg 2145d522f475Smrg XDrawArc(screen->display, 2146d522f475Smrg VWindow(screen), gc2, 2147d522f475Smrg x + x_coord, y + y_coord, width, width, 2148d522f475Smrg 0, 2149d522f475Smrg 360 * 64); 2150d522f475Smrg } else if (ch < (sizeof(lines) / sizeof(lines[0])) 2151d522f475Smrg && (p = lines[ch]) != 0) { 21522eaa94a1Schristos unsigned coord[4]; 2153d522f475Smrg int n = 0; 2154d522f475Smrg while (*p >= 0) { 2155d522f475Smrg coord[n++] = *p++; 2156d522f475Smrg if (n == 4) { 2157d522f475Smrg SCALE_X(coord[0]); 2158d522f475Smrg SCALE_Y(coord[1]); 2159d522f475Smrg SCALE_X(coord[2]); 2160d522f475Smrg SCALE_Y(coord[3]); 2161d522f475Smrg XDrawLine(screen->display, 2162d522f475Smrg VWindow(screen), gc2, 2163d522f475Smrg x + coord[0], y + coord[1], 2164d522f475Smrg x + coord[2], y + coord[3]); 2165d522f475Smrg n = 0; 2166d522f475Smrg } 2167d522f475Smrg } 2168d522f475Smrg } else if (screen->force_all_chars) { 2169d522f475Smrg /* bounding rectangle, for debugging */ 2170d522f475Smrg XDrawRectangle(screen->display, VWindow(screen), gc2, x, y, 2171d522f475Smrg font_width - 1, 2172d522f475Smrg font_height - 1); 2173d522f475Smrg } 2174d522f475Smrg} 2175d522f475Smrg 2176d522f475Smrg#if OPT_RENDERFONT 2177d522f475Smrg 2178d522f475Smrg/* 2179d522f475Smrg * Check if the given character has a glyph known to Xft. 2180d522f475Smrg * 2181d522f475Smrg * see xc/lib/Xft/xftglyphs.c 2182d522f475Smrg */ 2183d522f475SmrgBool 2184d522f475SmrgxtermXftMissing(XtermWidget xw, XftFont * font, unsigned wc) 2185d522f475Smrg{ 2186d522f475Smrg Bool result = False; 2187d522f475Smrg 2188d522f475Smrg if (font != 0) { 2189d522f475Smrg if (!XftGlyphExists(xw->screen.display, font, wc)) { 2190d522f475Smrg#if OPT_WIDE_CHARS 2191d522f475Smrg TRACE(("xtermXftMissing %d (dec=%#x, ucs=%#x)\n", 2192d522f475Smrg wc, ucs2dec(wc), dec2ucs(wc))); 2193d522f475Smrg#else 2194d522f475Smrg TRACE(("xtermXftMissing %d\n", wc)); 2195d522f475Smrg#endif 2196d522f475Smrg result = True; 2197d522f475Smrg } 2198d522f475Smrg } 2199d522f475Smrg return result; 2200d522f475Smrg} 2201d522f475Smrg#endif /* OPT_RENDERFONT && OPT_WIDE_CHARS */ 2202d522f475Smrg 2203d522f475Smrg#endif /* OPT_BOX_CHARS */ 2204d522f475Smrg 2205d522f475Smrg#if OPT_WIDE_CHARS 2206d522f475Smrg#define MY_UCS(ucs,dec) case ucs: result = dec; break 2207d522f475Smrgunsigned 2208d522f475Smrgucs2dec(unsigned ch) 2209d522f475Smrg{ 2210d522f475Smrg unsigned result = ch; 2211d522f475Smrg if ((ch > 127) 2212d522f475Smrg && (ch != UCS_REPL)) { 2213d522f475Smrg switch (ch) { 2214d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 2215d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 2216d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 2217d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 2218d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 2219d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 2220d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 2221d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 2222d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 2223d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 2224d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 2225d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 2226d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 2227d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 2228d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 2229d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 2230d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 2231d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 2232d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 2233d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 2234d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 2235d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 2236d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 2237d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 2238d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 2239d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 2240d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 2241d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 2242d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 2243d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 2244d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 2245d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 2246d522f475Smrg } 2247d522f475Smrg } 2248d522f475Smrg return result; 2249d522f475Smrg} 2250d522f475Smrg 2251d522f475Smrg#undef MY_UCS 2252d522f475Smrg#define MY_UCS(ucs,dec) case dec: result = ucs; break 2253d522f475Smrg 2254d522f475Smrgunsigned 2255d522f475Smrgdec2ucs(unsigned ch) 2256d522f475Smrg{ 2257d522f475Smrg unsigned result = ch; 2258d522f475Smrg if (xtermIsDecGraphic(ch)) { 2259d522f475Smrg switch (ch) { 2260d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 2261d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 2262d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 2263d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 2264d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 2265d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 2266d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 2267d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 2268d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 2269d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 2270d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 2271d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 2272d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 2273d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 2274d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 2275d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 2276d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 2277d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 2278d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 2279d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 2280d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 2281d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 2282d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 2283d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 2284d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 2285d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 2286d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 2287d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 2288d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 2289d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 2290d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 2291d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 2292d522f475Smrg } 2293d522f475Smrg } 2294d522f475Smrg return result; 2295d522f475Smrg} 2296d522f475Smrg 2297d522f475Smrg#endif /* OPT_WIDE_CHARS */ 2298d522f475Smrg 2299d522f475Smrg#if OPT_SHIFT_FONTS 2300d522f475Smrgstatic void 2301d522f475SmrglookupOneFontSize(XtermWidget xw, int fontnum) 2302d522f475Smrg{ 2303d522f475Smrg TScreen *screen = TScreenOf(xw); 2304d522f475Smrg 2305d522f475Smrg if (screen->menu_font_sizes[fontnum] == 0) { 2306d522f475Smrg XTermFonts fnt; 2307d522f475Smrg 2308d522f475Smrg memset(&fnt, 0, sizeof(fnt)); 2309d522f475Smrg screen->menu_font_sizes[fontnum] = -1; 2310d522f475Smrg if (xtermOpenFont(xw, screen->MenuFontName(fontnum), &fnt)) { 2311d522f475Smrg screen->menu_font_sizes[fontnum] = FontSize(fnt.fs); 2312d522f475Smrg TRACE(("menu_font_sizes[%d] = %ld\n", fontnum, 2313d522f475Smrg screen->menu_font_sizes[fontnum])); 2314d522f475Smrg xtermCloseFont(xw, &fnt); 2315d522f475Smrg } 2316d522f475Smrg } 2317d522f475Smrg} 2318d522f475Smrg 2319d522f475Smrg/* 2320d522f475Smrg * Cache the font-sizes so subsequent larger/smaller font actions will go fast. 2321d522f475Smrg */ 2322d522f475Smrgstatic void 2323d522f475SmrglookupFontSizes(XtermWidget xw) 2324d522f475Smrg{ 2325d522f475Smrg int n; 2326d522f475Smrg 2327d522f475Smrg for (n = 0; n < NMENUFONTS; n++) { 2328d522f475Smrg lookupOneFontSize(xw, n); 2329d522f475Smrg } 2330d522f475Smrg} 2331d522f475Smrg 23322eaa94a1Schristos#if OPT_RENDERFONT 23332eaa94a1Schristos#define NMENU_RENDERFONTS (NMENUFONTS - 2) /* no selection or escape */ 23342eaa94a1Schristosstatic Boolean 23352eaa94a1SchristosuseFaceSizes(XtermWidget xw) 23362eaa94a1Schristos{ 23372eaa94a1Schristos Boolean result = False; 23382eaa94a1Schristos int n; 23392eaa94a1Schristos 23402eaa94a1Schristos if (UsingRenderFont(xw)) { 23412eaa94a1Schristos result = True; 23422eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 23432eaa94a1Schristos if (xw->misc.face_size[n] <= 0.0) { 23442eaa94a1Schristos result = False; 23452eaa94a1Schristos break; 23462eaa94a1Schristos } 23472eaa94a1Schristos } 23482eaa94a1Schristos } 23492eaa94a1Schristos return result; 23502eaa94a1Schristos} 23512eaa94a1Schristos#endif 23522eaa94a1Schristos 2353d522f475Smrg/* 2354d522f475Smrg * Find the index of a larger/smaller font (according to the sign of 'relative' 2355d522f475Smrg * and its magnitude), starting from the 'old' index. 2356d522f475Smrg */ 2357d522f475Smrgint 2358d522f475SmrglookupRelativeFontSize(XtermWidget xw, int old, int relative) 2359d522f475Smrg{ 2360d522f475Smrg TScreen *screen = TScreenOf(xw); 2361d522f475Smrg int n, m = -1; 2362d522f475Smrg 23632eaa94a1Schristos TRACE(("lookupRelativeFontSize(old=%d, relative=%d)\n", old, relative)); 2364d522f475Smrg if (!IsIcon(screen)) { 23652eaa94a1Schristos#if OPT_RENDERFONT 23662eaa94a1Schristos if (useFaceSizes(xw)) { 23672eaa94a1Schristos TRACE(("...using FaceSize\n")); 23682eaa94a1Schristos if (relative != 0) { 23692eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 23702eaa94a1Schristos if (xw->misc.face_size[n] > 0 && 23712eaa94a1Schristos xw->misc.face_size[n] != xw->misc.face_size[old]) { 23722eaa94a1Schristos int cmp_0 = ((xw->misc.face_size[n] > 23732eaa94a1Schristos xw->misc.face_size[old]) 23742eaa94a1Schristos ? relative 23752eaa94a1Schristos : -relative); 23762eaa94a1Schristos int cmp_m = ((m < 0) 23772eaa94a1Schristos ? 1 23782eaa94a1Schristos : ((xw->misc.face_size[n] < 23792eaa94a1Schristos xw->misc.face_size[m]) 23802eaa94a1Schristos ? relative 23812eaa94a1Schristos : -relative)); 23822eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 23832eaa94a1Schristos m = n; 23842eaa94a1Schristos } 2385d522f475Smrg } 2386d522f475Smrg } 2387d522f475Smrg } 23882eaa94a1Schristos } else 23892eaa94a1Schristos#endif 23902eaa94a1Schristos { 23912eaa94a1Schristos TRACE(("...using bitmap areas\n")); 23922eaa94a1Schristos lookupFontSizes(xw); 23932eaa94a1Schristos if (relative != 0) { 23942eaa94a1Schristos for (n = 0; n < NMENUFONTS; ++n) { 23952eaa94a1Schristos if (screen->menu_font_sizes[n] > 0 && 23962eaa94a1Schristos screen->menu_font_sizes[n] != 23972eaa94a1Schristos screen->menu_font_sizes[old]) { 23982eaa94a1Schristos int cmp_0 = ((screen->menu_font_sizes[n] > 23992eaa94a1Schristos screen->menu_font_sizes[old]) 24002eaa94a1Schristos ? relative 24012eaa94a1Schristos : -relative); 24022eaa94a1Schristos int cmp_m = ((m < 0) 24032eaa94a1Schristos ? 1 24042eaa94a1Schristos : ((screen->menu_font_sizes[n] < 24052eaa94a1Schristos screen->menu_font_sizes[m]) 24062eaa94a1Schristos ? relative 24072eaa94a1Schristos : -relative)); 24082eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 24092eaa94a1Schristos m = n; 24102eaa94a1Schristos } 24112eaa94a1Schristos } 24122eaa94a1Schristos } 2413d522f475Smrg } 2414d522f475Smrg } 24152eaa94a1Schristos TRACE(("...new index %d\n", m)); 24162eaa94a1Schristos if (m >= 0) { 24172eaa94a1Schristos if (relative > 1) 24182eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative - 1); 24192eaa94a1Schristos else if (relative < -1) 24202eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative + 1); 24212eaa94a1Schristos } 2422d522f475Smrg } 2423d522f475Smrg return m; 2424d522f475Smrg} 2425d522f475Smrg 2426d522f475Smrg/* ARGSUSED */ 2427d522f475Smrgvoid 2428d522f475SmrgHandleLargerFont(Widget w GCC_UNUSED, 2429d522f475Smrg XEvent * event GCC_UNUSED, 2430d522f475Smrg String * params GCC_UNUSED, 2431d522f475Smrg Cardinal *param_count GCC_UNUSED) 2432d522f475Smrg{ 2433d522f475Smrg if (IsXtermWidget(w)) { 2434d522f475Smrg XtermWidget xw = (XtermWidget) w; 2435d522f475Smrg 2436d522f475Smrg if (xw->misc.shift_fonts) { 2437d522f475Smrg TScreen *screen = &xw->screen; 2438d522f475Smrg int m; 2439d522f475Smrg 2440d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, 1); 2441d522f475Smrg if (m >= 0) { 2442d522f475Smrg SetVTFont(xw, m, True, NULL); 2443d522f475Smrg } else { 2444d522f475Smrg Bell(XkbBI_MinorError, 0); 2445d522f475Smrg } 2446d522f475Smrg } 2447d522f475Smrg } 2448d522f475Smrg} 2449d522f475Smrg 2450d522f475Smrg/* ARGSUSED */ 2451d522f475Smrgvoid 2452d522f475SmrgHandleSmallerFont(Widget w GCC_UNUSED, 2453d522f475Smrg XEvent * event GCC_UNUSED, 2454d522f475Smrg String * params GCC_UNUSED, 2455d522f475Smrg Cardinal *param_count GCC_UNUSED) 2456d522f475Smrg{ 2457d522f475Smrg if (IsXtermWidget(w)) { 2458d522f475Smrg XtermWidget xw = (XtermWidget) w; 2459d522f475Smrg 2460d522f475Smrg if (xw->misc.shift_fonts) { 2461d522f475Smrg TScreen *screen = &xw->screen; 2462d522f475Smrg int m; 2463d522f475Smrg 2464d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, -1); 2465d522f475Smrg if (m >= 0) { 2466d522f475Smrg SetVTFont(xw, m, True, NULL); 2467d522f475Smrg } else { 2468d522f475Smrg Bell(XkbBI_MinorError, 0); 2469d522f475Smrg } 2470d522f475Smrg } 2471d522f475Smrg } 2472d522f475Smrg} 2473d522f475Smrg#endif 2474d522f475Smrg 2475d522f475Smrgint 2476d522f475SmrgxtermGetFont(const char *param) 2477d522f475Smrg{ 2478d522f475Smrg int fontnum; 2479d522f475Smrg 2480d522f475Smrg switch (param[0]) { 2481d522f475Smrg case 'd': 2482d522f475Smrg case 'D': 2483d522f475Smrg case '0': 2484d522f475Smrg fontnum = fontMenu_default; 2485d522f475Smrg break; 2486d522f475Smrg case '1': 2487d522f475Smrg fontnum = fontMenu_font1; 2488d522f475Smrg break; 2489d522f475Smrg case '2': 2490d522f475Smrg fontnum = fontMenu_font2; 2491d522f475Smrg break; 2492d522f475Smrg case '3': 2493d522f475Smrg fontnum = fontMenu_font3; 2494d522f475Smrg break; 2495d522f475Smrg case '4': 2496d522f475Smrg fontnum = fontMenu_font4; 2497d522f475Smrg break; 2498d522f475Smrg case '5': 2499d522f475Smrg fontnum = fontMenu_font5; 2500d522f475Smrg break; 2501d522f475Smrg case '6': 2502d522f475Smrg fontnum = fontMenu_font6; 2503d522f475Smrg break; 2504d522f475Smrg case 'e': 2505d522f475Smrg case 'E': 2506d522f475Smrg fontnum = fontMenu_fontescape; 2507d522f475Smrg break; 2508d522f475Smrg case 's': 2509d522f475Smrg case 'S': 2510d522f475Smrg fontnum = fontMenu_fontsel; 2511d522f475Smrg break; 2512d522f475Smrg default: 2513d522f475Smrg fontnum = -1; 2514d522f475Smrg break; 2515d522f475Smrg } 2516d522f475Smrg return fontnum; 2517d522f475Smrg} 2518d522f475Smrg 2519d522f475Smrg/* ARGSUSED */ 2520d522f475Smrgvoid 2521d522f475SmrgHandleSetFont(Widget w GCC_UNUSED, 2522d522f475Smrg XEvent * event GCC_UNUSED, 2523d522f475Smrg String * params, 2524d522f475Smrg Cardinal *param_count) 2525d522f475Smrg{ 2526d522f475Smrg if (IsXtermWidget(w)) { 2527d522f475Smrg int fontnum; 2528d522f475Smrg VTFontNames fonts; 2529d522f475Smrg 2530d522f475Smrg memset(&fonts, 0, sizeof(fonts)); 2531d522f475Smrg 2532d522f475Smrg if (*param_count == 0) { 2533d522f475Smrg fontnum = fontMenu_default; 2534d522f475Smrg } else { 2535d522f475Smrg Cardinal maxparams = 1; /* total number of params allowed */ 2536d522f475Smrg int result = xtermGetFont(params[0]); 2537d522f475Smrg 2538d522f475Smrg switch (result) { 2539d522f475Smrg case fontMenu_default: /* FALLTHRU */ 2540d522f475Smrg case fontMenu_font1: /* FALLTHRU */ 2541d522f475Smrg case fontMenu_font2: /* FALLTHRU */ 2542d522f475Smrg case fontMenu_font3: /* FALLTHRU */ 2543d522f475Smrg case fontMenu_font4: /* FALLTHRU */ 2544d522f475Smrg case fontMenu_font5: /* FALLTHRU */ 2545d522f475Smrg case fontMenu_font6: /* FALLTHRU */ 2546d522f475Smrg break; 2547d522f475Smrg case fontMenu_fontescape: 2548d522f475Smrg#if OPT_WIDE_CHARS 2549d522f475Smrg maxparams = 5; 2550d522f475Smrg#else 2551d522f475Smrg maxparams = 3; 2552d522f475Smrg#endif 2553d522f475Smrg break; 2554d522f475Smrg case fontMenu_fontsel: 2555d522f475Smrg maxparams = 2; 2556d522f475Smrg break; 2557d522f475Smrg default: 2558d522f475Smrg Bell(XkbBI_MinorError, 0); 2559d522f475Smrg return; 2560d522f475Smrg } 2561d522f475Smrg fontnum = result; 2562d522f475Smrg 2563d522f475Smrg if (*param_count > maxparams) { /* see if extra args given */ 2564d522f475Smrg Bell(XkbBI_MinorError, 0); 2565d522f475Smrg return; 2566d522f475Smrg } 2567d522f475Smrg switch (*param_count) { /* assign 'em */ 2568d522f475Smrg#if OPT_WIDE_CHARS 2569d522f475Smrg case 5: 2570d522f475Smrg fonts.f_wb = params[4]; 2571d522f475Smrg /* FALLTHRU */ 2572d522f475Smrg case 4: 2573d522f475Smrg fonts.f_w = params[3]; 2574d522f475Smrg /* FALLTHRU */ 2575d522f475Smrg#endif 2576d522f475Smrg case 3: 2577d522f475Smrg fonts.f_b = params[2]; 2578d522f475Smrg /* FALLTHRU */ 2579d522f475Smrg case 2: 2580d522f475Smrg fonts.f_n = params[1]; 2581d522f475Smrg break; 2582d522f475Smrg } 2583d522f475Smrg } 2584d522f475Smrg 2585d522f475Smrg SetVTFont((XtermWidget) w, fontnum, True, &fonts); 2586d522f475Smrg } 2587d522f475Smrg} 2588d522f475Smrg 2589d522f475Smrgvoid 2590d522f475SmrgSetVTFont(XtermWidget xw, 2591d522f475Smrg int which, 2592d522f475Smrg Bool doresize, 2593d522f475Smrg const VTFontNames * fonts) 2594d522f475Smrg{ 2595d522f475Smrg TScreen *screen = &xw->screen; 2596d522f475Smrg 2597d522f475Smrg TRACE(("SetVTFont(which=%d, f_n=%s, f_b=%s)\n", which, 2598d522f475Smrg (fonts && fonts->f_n) ? fonts->f_n : "<null>", 2599d522f475Smrg (fonts && fonts->f_b) ? fonts->f_b : "<null>")); 2600d522f475Smrg 2601d522f475Smrg if (IsIcon(screen)) { 2602d522f475Smrg Bell(XkbBI_MinorError, 0); 2603d522f475Smrg } else if (which >= 0 && which < NMENUFONTS) { 2604d522f475Smrg VTFontNames myfonts; 2605d522f475Smrg 2606d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 2607d522f475Smrg if (fonts != 0) 2608d522f475Smrg myfonts = *fonts; 2609d522f475Smrg 2610d522f475Smrg if (which == fontMenu_fontsel) { /* go get the selection */ 2611d522f475Smrg FindFontSelection(xw, myfonts.f_n, False); 2612d522f475Smrg return; 2613d522f475Smrg } else { 2614d522f475Smrg int oldFont = screen->menu_font_number; 2615d522f475Smrg 2616d522f475Smrg#define USE_CACHED(field, name) \ 2617d522f475Smrg if (myfonts.field == 0) { \ 2618d522f475Smrg myfonts.field = screen->menu_font_names[which][name]; \ 2619d522f475Smrg TRACE(("set myfonts." #field " from menu_font_names[%d][" #name "] %s\n", \ 2620d522f475Smrg which, NonNull(myfonts.field))); \ 2621d522f475Smrg } else { \ 2622d522f475Smrg TRACE(("set myfonts." #field " reused\n")); \ 2623d522f475Smrg } 2624d522f475Smrg USE_CACHED(f_n, fNorm); 2625d522f475Smrg USE_CACHED(f_b, fBold); 2626d522f475Smrg#if OPT_WIDE_CHARS 2627d522f475Smrg USE_CACHED(f_w, fWide); 2628d522f475Smrg USE_CACHED(f_wb, fWBold); 2629d522f475Smrg#endif 2630d522f475Smrg if (xtermLoadFont(xw, 2631d522f475Smrg &myfonts, 2632d522f475Smrg doresize, which)) { 2633d522f475Smrg return; 2634d522f475Smrg } else { 2635d522f475Smrg xtermLoadFont(xw, 2636d522f475Smrg xtermFontName(screen->MenuFontName(oldFont)), 2637d522f475Smrg doresize, oldFont); 2638d522f475Smrg } 2639d522f475Smrg } 2640d522f475Smrg } 2641d522f475Smrg 2642d522f475Smrg Bell(XkbBI_MinorError, 0); 2643d522f475Smrg return; 2644d522f475Smrg} 2645