fontutils.c revision 0bd37d32
10bd37d32Smrg/* $XTermId: fontutils.c,v 1.387 2013/05/15 00:31:56 tom Exp $ */ 2d522f475Smrg 30bd37d32Smrg/* 40bd37d32Smrg * Copyright 1998-2011,2012 by Thomas E. Dickey 50bd37d32Smrg * 60bd37d32Smrg * All Rights Reserved 70bd37d32Smrg * 80bd37d32Smrg * Permission is hereby granted, free of charge, to any person obtaining a 90bd37d32Smrg * copy of this software and associated documentation files (the 100bd37d32Smrg * "Software"), to deal in the Software without restriction, including 110bd37d32Smrg * without limitation the rights to use, copy, modify, merge, publish, 120bd37d32Smrg * distribute, sublicense, and/or sell copies of the Software, and to 130bd37d32Smrg * permit persons to whom the Software is furnished to do so, subject to 140bd37d32Smrg * the following conditions: 150bd37d32Smrg * 160bd37d32Smrg * The above copyright notice and this permission notice shall be included 170bd37d32Smrg * in all copies or substantial portions of the Software. 180bd37d32Smrg * 190bd37d32Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 200bd37d32Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 210bd37d32Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 220bd37d32Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 230bd37d32Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 240bd37d32Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 250bd37d32Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 260bd37d32Smrg * 270bd37d32Smrg * Except as contained in this notice, the name(s) of the above copyright 280bd37d32Smrg * holders shall not be used in advertising or otherwise to promote the 290bd37d32Smrg * sale, use or other dealings in this Software without prior written 300bd37d32Smrg * authorization. 310bd37d32Smrg */ 32d522f475Smrg 33d522f475Smrg/* 34d522f475Smrg * A portion of this module (for FontNameProperties) was adapted from EMU 1.3; 35d522f475Smrg * it constructs font names with specific properties changed, e.g., for bold 36d522f475Smrg * and double-size characters. 37d522f475Smrg */ 38d522f475Smrg 39d522f475Smrg#define RES_OFFSET(field) XtOffsetOf(SubResourceRec, field) 40d522f475Smrg 41d522f475Smrg#include <fontutils.h> 42d522f475Smrg#include <X11/Xmu/Drawing.h> 4320d2c4d2Smrg#include <X11/Xmu/CharSet.h> 44d522f475Smrg 45d522f475Smrg#include <main.h> 46d522f475Smrg#include <data.h> 47d522f475Smrg#include <menu.h> 48d522f475Smrg#include <xstrings.h> 49d522f475Smrg#include <xterm.h> 50d522f475Smrg 51d522f475Smrg#include <stdio.h> 52d522f475Smrg#include <ctype.h> 53d522f475Smrg 540bd37d32Smrg#define SetFontWidth(screen,dst,src) (dst)->f_width = (src) 550bd37d32Smrg#define SetFontHeight(screen,dst,src) (dst)->f_height = dimRound((screen)->scale_height * (float) (src)) 560bd37d32Smrg 57d522f475Smrg/* from X11/Xlibint.h - not all vendors install this file */ 58d522f475Smrg#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \ 59d522f475Smrg (((cs)->rbearing|(cs)->lbearing| \ 60d522f475Smrg (cs)->ascent|(cs)->descent) == 0)) 61d522f475Smrg 62d522f475Smrg#define CI_GET_CHAR_INFO_1D(fs,col,def,cs) \ 63d522f475Smrg{ \ 64d522f475Smrg cs = def; \ 65d522f475Smrg if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 66d522f475Smrg if (fs->per_char == NULL) { \ 67d522f475Smrg cs = &fs->min_bounds; \ 68d522f475Smrg } else { \ 69d522f475Smrg cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \ 70d522f475Smrg if (CI_NONEXISTCHAR(cs)) cs = def; \ 71d522f475Smrg } \ 72d522f475Smrg } \ 73d522f475Smrg} 74d522f475Smrg 75d522f475Smrg#define CI_GET_CHAR_INFO_2D(fs,row,col,def,cs) \ 76d522f475Smrg{ \ 77d522f475Smrg cs = def; \ 78d522f475Smrg if (row >= fs->min_byte1 && row <= fs->max_byte1 && \ 79d522f475Smrg col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 80d522f475Smrg if (fs->per_char == NULL) { \ 81d522f475Smrg cs = &fs->min_bounds; \ 82d522f475Smrg } else { \ 83d522f475Smrg cs = &fs->per_char[((row - fs->min_byte1) * \ 84d522f475Smrg (fs->max_char_or_byte2 - \ 85d522f475Smrg fs->min_char_or_byte2 + 1)) + \ 86d522f475Smrg (col - fs->min_char_or_byte2)]; \ 87d522f475Smrg if (CI_NONEXISTCHAR(cs)) cs = def; \ 88d522f475Smrg } \ 89d522f475Smrg } \ 90d522f475Smrg} 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 1170bd37d32Smrg#if OPT_RENDERFONT 1180bd37d32Smrgstatic void fillInFaceSize(XtermWidget, int); 1190bd37d32Smrg#endif 1200bd37d32Smrg 121d522f475Smrg#if OPT_SHIFT_FONTS 1220bd37d32Smrgstatic int lookupOneFontSize(XtermWidget, int); 123d522f475Smrg#endif 124d522f475Smrg 125d522f475Smrg#if OPT_WIDE_CHARS 1262eaa94a1Schristosstatic unsigned 127d522f475SmrgcountGlyphs(XFontStruct * fp) 128d522f475Smrg{ 129d522f475Smrg unsigned count = 0; 130d522f475Smrg 131d522f475Smrg if (fp != 0) { 132d522f475Smrg if (fp->min_byte1 == 0 && fp->max_byte1 == 0) { 133d522f475Smrg count = fp->max_char_or_byte2 - fp->min_char_or_byte2; 134d522f475Smrg } else if (fp->min_char_or_byte2 < 256 135d522f475Smrg && fp->max_char_or_byte2 < 256) { 136d522f475Smrg unsigned first = (fp->min_byte1 << 8) + fp->min_char_or_byte2; 137d522f475Smrg unsigned last = (fp->max_byte1 << 8) + fp->max_char_or_byte2; 138d522f475Smrg count = last + 1 - first; 139d522f475Smrg } 140d522f475Smrg } 141d522f475Smrg return count; 142d522f475Smrg} 143d522f475Smrg 144d522f475Smrg/* 145d522f475Smrg * Verify that the wide-bold font is at least a bold font with roughly as many 146d522f475Smrg * glyphs as the wide font. The counts should be the same, but settle for 147d522f475Smrg * filtering out the worst of the font mismatches. 148d522f475Smrg */ 149d522f475Smrgstatic Bool 150d522f475SmrgcompatibleWideCounts(XFontStruct * wfs, XFontStruct * wbfs) 151d522f475Smrg{ 152d522f475Smrg unsigned count_w = countGlyphs(wfs); 153d522f475Smrg unsigned count_wb = countGlyphs(wbfs); 154d522f475Smrg if (count_w <= 256 || 155d522f475Smrg count_wb <= 256 || 156d522f475Smrg ((count_w / 4) * 3) > count_wb) { 157d522f475Smrg TRACE(("...font server lied (count wide %u vs wide-bold %u)\n", 158d522f475Smrg count_w, count_wb)); 159d522f475Smrg return False; 160d522f475Smrg } 161d522f475Smrg return True; 162d522f475Smrg} 163d522f475Smrg#endif /* OPT_WIDE_CHARS */ 164d522f475Smrg 16520d2c4d2Smrg#if OPT_BOX_CHARS 16620d2c4d2Smrgstatic void 16720d2c4d2SmrgsetupPackedFonts(XtermWidget xw) 16820d2c4d2Smrg{ 16920d2c4d2Smrg TScreen *screen = TScreenOf(xw); 17020d2c4d2Smrg Bool value = False; 17120d2c4d2Smrg 17220d2c4d2Smrg#if OPT_RENDERFONT 17320d2c4d2Smrg#define MIXED(name) screen->name[fontnum].map.mixed 1740bd37d32Smrg if (xw->work.render_font == True) { 17520d2c4d2Smrg int fontnum = screen->menu_font_number; 17620d2c4d2Smrg 17720d2c4d2Smrg screen->allow_packing = (Boolean) (MIXED(renderFontNorm) 17820d2c4d2Smrg || MIXED(renderFontBold) 17920d2c4d2Smrg || MIXED(renderFontItal) 18020d2c4d2Smrg#if OPT_RENDERWIDE 18120d2c4d2Smrg || MIXED(renderWideNorm) 18220d2c4d2Smrg || MIXED(renderWideBold) 18320d2c4d2Smrg || MIXED(renderWideItal) 18420d2c4d2Smrg#endif 18520d2c4d2Smrg ); 18620d2c4d2Smrg#undef MIXED 18720d2c4d2Smrg } 18820d2c4d2Smrg#endif /* OPT_RENDERFONT */ 18920d2c4d2Smrg 19020d2c4d2Smrg value = screen->allow_packing; 19120d2c4d2Smrg 19220d2c4d2Smrg SetItemSensitivity(fontMenuEntries[fontMenu_font_packedfont].widget, value); 19320d2c4d2Smrg} 19420d2c4d2Smrg#endif 19520d2c4d2Smrg 196d522f475Smrg/* 197d522f475Smrg * Returns the fields from start to stop in a dash- separated string. This 198d522f475Smrg * function will modify the source, putting '\0's in the appropiate place and 199d522f475Smrg * moving the beginning forward to after the '\0' 200d522f475Smrg * 201d522f475Smrg * This will NOT work for the last field (but we won't need it). 202d522f475Smrg */ 203d522f475Smrgstatic char * 204d522f475Smrgn_fields(char **source, int start, int stop) 205d522f475Smrg{ 206d522f475Smrg int i; 207d522f475Smrg char *str, *str1; 208d522f475Smrg 209d522f475Smrg /* 210d522f475Smrg * find the start-1th dash 211d522f475Smrg */ 212d522f475Smrg for (i = start - 1, str = *source; i; i--, str++) 213d522f475Smrg if ((str = strchr(str, '-')) == 0) 214d522f475Smrg return 0; 215d522f475Smrg 216d522f475Smrg /* 217d522f475Smrg * find the stopth dash 218d522f475Smrg */ 219d522f475Smrg for (i = stop - start + 1, str1 = str; i; i--, str1++) 220d522f475Smrg if ((str1 = strchr(str1, '-')) == 0) 221d522f475Smrg return 0; 222d522f475Smrg 223d522f475Smrg /* 224d522f475Smrg * put a \0 at the end of the fields 225d522f475Smrg */ 226d522f475Smrg *(str1 - 1) = '\0'; 227d522f475Smrg 228d522f475Smrg /* 229d522f475Smrg * move source forward 230d522f475Smrg */ 231d522f475Smrg *source = str1; 232d522f475Smrg 233d522f475Smrg return str; 234d522f475Smrg} 235d522f475Smrg 236956cc18dSsnjstatic Boolean 237956cc18dSsnjcheck_fontname(const char *name) 238956cc18dSsnj{ 239956cc18dSsnj Boolean result = True; 240956cc18dSsnj 241492d43a5Smrg if (IsEmpty(name)) { 242956cc18dSsnj TRACE(("fontname missing\n")); 243956cc18dSsnj result = False; 244956cc18dSsnj } 245956cc18dSsnj return result; 246956cc18dSsnj} 247956cc18dSsnj 248d522f475Smrg/* 249d522f475Smrg * Gets the font properties from a given font structure. We use the FONT name 250d522f475Smrg * to find them out, since that seems easier. 251d522f475Smrg * 252d522f475Smrg * Returns a pointer to a static FontNameProperties structure 253d522f475Smrg * or NULL on error. 254d522f475Smrg */ 255d522f475Smrgstatic FontNameProperties * 2560bd37d32Smrgget_font_name_props(Display * dpy, XFontStruct * fs, char **result) 257d522f475Smrg{ 258d522f475Smrg static FontNameProperties props; 259d522f475Smrg static char *last_name; 260d522f475Smrg 261d522f475Smrg XFontProp *fp; 262d522f475Smrg int i; 263d522f475Smrg Atom fontatom = XInternAtom(dpy, "FONT", False); 26420d2c4d2Smrg char *name = 0; 265d522f475Smrg char *str; 266d522f475Smrg 267d522f475Smrg /* 268d522f475Smrg * first get the full font name 269d522f475Smrg */ 27020d2c4d2Smrg if (fontatom != 0) { 27120d2c4d2Smrg for (i = 0, fp = fs->properties; i < fs->n_properties; i++, fp++) { 27220d2c4d2Smrg if (fp->name == fontatom) { 27320d2c4d2Smrg name = XGetAtomName(dpy, fp->card32); 27420d2c4d2Smrg break; 27520d2c4d2Smrg } 27620d2c4d2Smrg } 27720d2c4d2Smrg } 278d522f475Smrg 279d522f475Smrg if (name == 0) 280d522f475Smrg return 0; 281d522f475Smrg 282d522f475Smrg /* 283d522f475Smrg * XGetAtomName allocates memory - don't leak 284d522f475Smrg */ 285d522f475Smrg if (last_name != 0) 286d522f475Smrg XFree(last_name); 287d522f475Smrg last_name = name; 288d522f475Smrg 289d522f475Smrg if (result != 0) { 290956cc18dSsnj if (!check_fontname(name)) 291d522f475Smrg return 0; 2920bd37d32Smrg if (*result != 0) 2930bd37d32Smrg free(*result); 2940bd37d32Smrg *result = x_strdup(name); 295d522f475Smrg } 296d522f475Smrg 297d522f475Smrg /* 298d522f475Smrg * Now split it up into parts and put them in 299d522f475Smrg * their places. Since we are using parts of 300d522f475Smrg * the original string, we must not free the Atom Name 301d522f475Smrg */ 302d522f475Smrg 303d522f475Smrg /* registry, foundry, family */ 304d522f475Smrg if ((props.beginning = n_fields(&name, 1, 3)) == 0) 305d522f475Smrg return 0; 306d522f475Smrg 307d522f475Smrg /* weight is the next */ 308d522f475Smrg if ((props.weight = n_fields(&name, 1, 1)) == 0) 309d522f475Smrg return 0; 310d522f475Smrg 311d522f475Smrg /* slant */ 312d522f475Smrg if ((props.slant = n_fields(&name, 1, 1)) == 0) 313d522f475Smrg return 0; 314d522f475Smrg 315d522f475Smrg /* width */ 316d522f475Smrg if ((props.wideness = n_fields(&name, 1, 1)) == 0) 317d522f475Smrg return 0; 318d522f475Smrg 319d522f475Smrg /* add style */ 320d522f475Smrg if ((props.add_style = n_fields(&name, 1, 1)) == 0) 321d522f475Smrg return 0; 322d522f475Smrg 323d522f475Smrg /* pixel size */ 324d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 325d522f475Smrg return 0; 326d522f475Smrg if ((props.pixel_size = atoi(str)) == 0) 327d522f475Smrg return 0; 328d522f475Smrg 329d522f475Smrg /* point size */ 330d522f475Smrg if ((props.point_size = n_fields(&name, 1, 1)) == 0) 331d522f475Smrg return 0; 332d522f475Smrg 333d522f475Smrg /* res_x */ 334d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 335d522f475Smrg return 0; 336d522f475Smrg if ((props.res_x = atoi(str)) == 0) 337d522f475Smrg return 0; 338d522f475Smrg 339d522f475Smrg /* res_y */ 340d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 341d522f475Smrg return 0; 342d522f475Smrg if ((props.res_y = atoi(str)) == 0) 343d522f475Smrg return 0; 344d522f475Smrg 345d522f475Smrg /* spacing */ 346d522f475Smrg if ((props.spacing = n_fields(&name, 1, 1)) == 0) 347d522f475Smrg return 0; 348d522f475Smrg 349d522f475Smrg /* average width */ 350d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 351d522f475Smrg return 0; 352d522f475Smrg if ((props.average_width = atoi(str)) == 0) 353d522f475Smrg return 0; 354d522f475Smrg 355d522f475Smrg /* the rest: charset registry and charset encoding */ 356d522f475Smrg props.end = name; 357d522f475Smrg 358d522f475Smrg return &props; 359d522f475Smrg} 360d522f475Smrg 361d522f475Smrg#define ALLOCHUNK(n) ((n | 127) + 1) 362d522f475Smrg 363d522f475Smrgstatic void 364956cc18dSsnjalloca_fontname(char **result, size_t next) 365d522f475Smrg{ 366956cc18dSsnj size_t last = (*result != 0) ? strlen(*result) : 0; 367956cc18dSsnj size_t have = (*result != 0) ? ALLOCHUNK(last) : 0; 368956cc18dSsnj size_t want = last + next + 2; 369d522f475Smrg 370d522f475Smrg if (want >= have) { 371d522f475Smrg want = ALLOCHUNK(want); 372d522f475Smrg if (last != 0) { 373d522f475Smrg *result = TypeRealloc(char, want, *result); 374d522f475Smrg } else { 375d522f475Smrg if ((*result = TypeMallocN(char, want)) != 0) 376d522f475Smrg **result = '\0'; 377d522f475Smrg } 378d522f475Smrg } 379d522f475Smrg} 380d522f475Smrg 381d522f475Smrgstatic void 38220d2c4d2Smrgappend_fontname_str(char **result, const char *value) 383d522f475Smrg{ 384d522f475Smrg if (value == 0) 385d522f475Smrg value = "*"; 386d522f475Smrg alloca_fontname(result, strlen(value)); 387d522f475Smrg if (*result != 0) { 388d522f475Smrg if (**result != '\0') 389d522f475Smrg strcat(*result, "-"); 390d522f475Smrg strcat(*result, value); 391d522f475Smrg } 392d522f475Smrg} 393d522f475Smrg 394d522f475Smrgstatic void 395d522f475Smrgappend_fontname_num(char **result, int value) 396d522f475Smrg{ 397d522f475Smrg if (value < 0) { 398d522f475Smrg append_fontname_str(result, "*"); 399d522f475Smrg } else { 400d522f475Smrg char temp[100]; 401d522f475Smrg sprintf(temp, "%d", value); 402d522f475Smrg append_fontname_str(result, temp); 403d522f475Smrg } 404d522f475Smrg} 405d522f475Smrg 406d522f475Smrg/* 407d522f475Smrg * Take the given font props and try to make a well formed font name specifying 408d522f475Smrg * the same base font and size and everything, but with different weight/width 409d522f475Smrg * according to the parameters. The return value is allocated, should be freed 410d522f475Smrg * by the caller. 411d522f475Smrg */ 412d522f475Smrgstatic char * 413d522f475Smrgderive_font_name(FontNameProperties * props, 41420d2c4d2Smrg const char *use_weight, 415d522f475Smrg int use_average_width, 41620d2c4d2Smrg const char *use_encoding) 417d522f475Smrg{ 418d522f475Smrg char *result = 0; 419d522f475Smrg 420d522f475Smrg append_fontname_str(&result, props->beginning); 421d522f475Smrg append_fontname_str(&result, use_weight); 422d522f475Smrg append_fontname_str(&result, props->slant); 423d522f475Smrg append_fontname_str(&result, 0); 424d522f475Smrg append_fontname_str(&result, 0); 425d522f475Smrg append_fontname_num(&result, props->pixel_size); 426d522f475Smrg append_fontname_str(&result, props->point_size); 427d522f475Smrg append_fontname_num(&result, props->res_x); 428d522f475Smrg append_fontname_num(&result, props->res_y); 429d522f475Smrg append_fontname_str(&result, props->spacing); 430d522f475Smrg append_fontname_num(&result, use_average_width); 431d522f475Smrg append_fontname_str(&result, use_encoding); 432d522f475Smrg 433d522f475Smrg return result; 434d522f475Smrg} 435d522f475Smrg 436d522f475Smrgstatic char * 437d522f475Smrgbold_font_name(FontNameProperties * props, int use_average_width) 438d522f475Smrg{ 439d522f475Smrg return derive_font_name(props, "bold", use_average_width, props->end); 440d522f475Smrg} 441d522f475Smrg 442d522f475Smrg#if OPT_WIDE_CHARS 443d522f475Smrg#define derive_wide_font(props, weight) \ 444d522f475Smrg derive_font_name(props, weight, props->average_width * 2, "ISO10646-1") 445d522f475Smrg 446d522f475Smrgstatic char * 447d522f475Smrgwide_font_name(FontNameProperties * props) 448d522f475Smrg{ 449d522f475Smrg return derive_wide_font(props, "medium"); 450d522f475Smrg} 451d522f475Smrg 452d522f475Smrgstatic char * 453d522f475Smrgwidebold_font_name(FontNameProperties * props) 454d522f475Smrg{ 455d522f475Smrg return derive_wide_font(props, "bold"); 456d522f475Smrg} 457d522f475Smrg#endif /* OPT_WIDE_CHARS */ 458d522f475Smrg 459d522f475Smrg#if OPT_DEC_CHRSET 460d522f475Smrg/* 461d522f475Smrg * Take the given font props and try to make a well formed font name specifying 462d522f475Smrg * the same base font but changed depending on the given attributes and chrset. 463d522f475Smrg * 464d522f475Smrg * For double width fonts, we just double the X-resolution, for double height 465d522f475Smrg * fonts we double the pixel-size and Y-resolution 466d522f475Smrg */ 467d522f475Smrgchar * 468d522f475SmrgxtermSpecialFont(TScreen * screen, unsigned atts, unsigned chrset) 469d522f475Smrg{ 470d522f475Smrg#if OPT_TRACE 471d522f475Smrg static char old_spacing[80]; 472d522f475Smrg static FontNameProperties old_props; 473d522f475Smrg#endif 474d522f475Smrg FontNameProperties *props; 475d522f475Smrg char *result = 0; 47620d2c4d2Smrg const char *weight; 477d522f475Smrg int pixel_size; 478d522f475Smrg int res_x; 479d522f475Smrg int res_y; 480d522f475Smrg 481d522f475Smrg props = get_font_name_props(screen->display, screen->fnts[fNorm].fs, 0); 482d522f475Smrg if (props == 0) 483d522f475Smrg return result; 484d522f475Smrg 485d522f475Smrg pixel_size = props->pixel_size; 486d522f475Smrg res_x = props->res_x; 487d522f475Smrg res_y = props->res_y; 488d522f475Smrg if (atts & BOLD) 489d522f475Smrg weight = "bold"; 490d522f475Smrg else 491d522f475Smrg weight = props->weight; 492d522f475Smrg 493d522f475Smrg if (CSET_DOUBLE(chrset)) 494d522f475Smrg res_x *= 2; 495d522f475Smrg 496d522f475Smrg if (chrset == CSET_DHL_TOP 497d522f475Smrg || chrset == CSET_DHL_BOT) { 498d522f475Smrg res_y *= 2; 499d522f475Smrg pixel_size *= 2; 500d522f475Smrg } 501d522f475Smrg#if OPT_TRACE 502d522f475Smrg if (old_props.res_x != res_x 503d522f475Smrg || old_props.res_x != res_y 504d522f475Smrg || old_props.pixel_size != pixel_size 505d522f475Smrg || strcmp(old_props.spacing, props->spacing)) { 506d522f475Smrg TRACE(("xtermSpecialFont(atts = %#x, chrset = %#x)\n", atts, chrset)); 507d522f475Smrg TRACE(("res_x = %d\n", res_x)); 508d522f475Smrg TRACE(("res_y = %d\n", res_y)); 509d522f475Smrg TRACE(("point_size = %s\n", props->point_size)); 510d522f475Smrg TRACE(("pixel_size = %d\n", pixel_size)); 511d522f475Smrg TRACE(("spacing = %s\n", props->spacing)); 512d522f475Smrg old_props.res_x = res_x; 513d522f475Smrg old_props.res_x = res_y; 514d522f475Smrg old_props.pixel_size = pixel_size; 5150bd37d32Smrg old_props.spacing = old_spacing; 5160bd37d32Smrg sprintf(old_spacing, "%.*s", (int) sizeof(old_spacing) - 2, props->spacing); 517d522f475Smrg } 518d522f475Smrg#endif 519d522f475Smrg 520d522f475Smrg append_fontname_str(&result, props->beginning); 521d522f475Smrg append_fontname_str(&result, weight); 522d522f475Smrg append_fontname_str(&result, props->slant); 523d522f475Smrg append_fontname_str(&result, props->wideness); 524d522f475Smrg append_fontname_str(&result, props->add_style); 525d522f475Smrg append_fontname_num(&result, pixel_size); 526d522f475Smrg append_fontname_str(&result, props->point_size); 527d522f475Smrg append_fontname_num(&result, (atts & NORESOLUTION) ? -1 : res_x); 528d522f475Smrg append_fontname_num(&result, (atts & NORESOLUTION) ? -1 : res_y); 529d522f475Smrg append_fontname_str(&result, props->spacing); 530d522f475Smrg append_fontname_str(&result, 0); 531d522f475Smrg append_fontname_str(&result, props->end); 532d522f475Smrg 533d522f475Smrg return result; 534d522f475Smrg} 535d522f475Smrg#endif /* OPT_DEC_CHRSET */ 536d522f475Smrg 537d522f475Smrg/* 538d522f475Smrg * Case-independent comparison for font-names, including wildcards. 539d522f475Smrg * XLFD allows '?' as a wildcard, but we do not handle that (no one seems 540d522f475Smrg * to use it). 541d522f475Smrg */ 542d522f475Smrgstatic Bool 543492d43a5Smrgsame_font_name(const char *pattern, const char *match) 544d522f475Smrg{ 545956cc18dSsnj Bool result = False; 546956cc18dSsnj 547956cc18dSsnj if (pattern && match) { 548956cc18dSsnj while (*pattern && *match) { 549956cc18dSsnj if (*pattern == *match) { 550956cc18dSsnj pattern++; 551956cc18dSsnj match++; 552956cc18dSsnj } else if (*pattern == '*' || *match == '*') { 553956cc18dSsnj if (same_font_name(pattern + 1, match)) { 554956cc18dSsnj return True; 555956cc18dSsnj } else if (same_font_name(pattern, match + 1)) { 556956cc18dSsnj return True; 557956cc18dSsnj } else { 558956cc18dSsnj return False; 559956cc18dSsnj } 560d522f475Smrg } else { 561956cc18dSsnj int p = x_toupper(*pattern++); 562956cc18dSsnj int m = x_toupper(*match++); 563956cc18dSsnj if (p != m) 564956cc18dSsnj return False; 565d522f475Smrg } 566d522f475Smrg } 567956cc18dSsnj result = (*pattern == *match); /* both should be NUL */ 568d522f475Smrg } 569956cc18dSsnj return result; 570d522f475Smrg} 571d522f475Smrg 572d522f475Smrg/* 573d522f475Smrg * Double-check the fontname that we asked for versus what the font server 574d522f475Smrg * actually gave us. The larger fixed fonts do not always have a matching bold 575d522f475Smrg * font, and the font server may try to scale another font or otherwise 576d522f475Smrg * substitute a mismatched font. 577d522f475Smrg * 578d522f475Smrg * If we cannot get what we requested, we will fallback to the original 579d522f475Smrg * behavior, which simulates bold by overstriking each character at one pixel 580d522f475Smrg * offset. 581d522f475Smrg */ 582d522f475Smrgstatic int 583492d43a5Smrggot_bold_font(Display * dpy, XFontStruct * fs, String requested) 584d522f475Smrg{ 5850bd37d32Smrg char *actual = 0; 586d522f475Smrg int got; 587d522f475Smrg 5880bd37d32Smrg if (get_font_name_props(dpy, fs, &actual) == 0) 589d522f475Smrg got = 0; 590d522f475Smrg else 591d522f475Smrg got = same_font_name(requested, actual); 5920bd37d32Smrg free(actual); 593d522f475Smrg return got; 594d522f475Smrg} 595d522f475Smrg 596d522f475Smrg/* 597d522f475Smrg * If the font server tries to adjust another font, it may not adjust it 598d522f475Smrg * properly. Check that the bounding boxes are compatible. Otherwise we'll 599d522f475Smrg * leave trash on the display when we mix normal and bold fonts. 600d522f475Smrg */ 601d522f475Smrgstatic int 602d522f475Smrgsame_font_size(XtermWidget xw, XFontStruct * nfs, XFontStruct * bfs) 603d522f475Smrg{ 604956cc18dSsnj TScreen *screen = TScreenOf(xw); 605d522f475Smrg TRACE(("same_font_size height %d/%d, min %d/%d max %d/%d\n", 606d522f475Smrg nfs->ascent + nfs->descent, 607d522f475Smrg bfs->ascent + bfs->descent, 608d522f475Smrg nfs->min_bounds.width, bfs->min_bounds.width, 609d522f475Smrg nfs->max_bounds.width, bfs->max_bounds.width)); 610956cc18dSsnj return screen->free_bold_box 611d522f475Smrg || ((nfs->ascent + nfs->descent) == (bfs->ascent + bfs->descent) 612d522f475Smrg && (nfs->min_bounds.width == bfs->min_bounds.width 613d522f475Smrg || nfs->min_bounds.width == bfs->min_bounds.width + 1) 614d522f475Smrg && (nfs->max_bounds.width == bfs->max_bounds.width 615d522f475Smrg || nfs->max_bounds.width == bfs->max_bounds.width + 1)); 616d522f475Smrg} 617d522f475Smrg 618d522f475Smrg/* 619d522f475Smrg * Check if the font looks like it has fixed width 620d522f475Smrg */ 621d522f475Smrgstatic int 622d522f475Smrgis_fixed_font(XFontStruct * fs) 623d522f475Smrg{ 624d522f475Smrg if (fs) 625d522f475Smrg return (fs->min_bounds.width == fs->max_bounds.width); 626d522f475Smrg return 1; 627d522f475Smrg} 628d522f475Smrg 629d522f475Smrg/* 630d522f475Smrg * Check if the font looks like a double width font (i.e. contains 631d522f475Smrg * characters of width X and 2X 632d522f475Smrg */ 633d522f475Smrg#if OPT_WIDE_CHARS 634d522f475Smrgstatic int 635d522f475Smrgis_double_width_font(XFontStruct * fs) 636d522f475Smrg{ 637d522f475Smrg return ((2 * fs->min_bounds.width) == fs->max_bounds.width); 638d522f475Smrg} 639d522f475Smrg#else 640d522f475Smrg#define is_double_width_font(fs) 0 641d522f475Smrg#endif 642d522f475Smrg 643d522f475Smrg#if OPT_WIDE_CHARS && OPT_RENDERFONT && defined(HAVE_TYPE_FCCHAR32) 644d522f475Smrg#define HALF_WIDTH_TEST_STRING "1234567890" 645d522f475Smrg 646d522f475Smrg/* '1234567890' in Chinese characters in UTF-8 */ 647d522f475Smrg#define FULL_WIDTH_TEST_STRING "\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89" \ 648d522f475Smrg "\xe5\x9b\x9b\xe4\xba\x94" \ 649d522f475Smrg "\xef\xa7\x91\xe4\xb8\x83\xe5\x85\xab" \ 650d522f475Smrg "\xe4\xb9\x9d\xef\xa6\xb2" 651d522f475Smrg 652d522f475Smrg/* '1234567890' in Korean script in UTF-8 */ 653d522f475Smrg#define FULL_WIDTH_TEST_STRING2 "\xec\x9d\xbc\xec\x9d\xb4\xec\x82\xbc" \ 654d522f475Smrg "\xec\x82\xac\xec\x98\xa4" \ 655d522f475Smrg "\xec\x9c\xa1\xec\xb9\xa0\xed\x8c\x94" \ 656d522f475Smrg "\xea\xb5\xac\xec\x98\x81" 657d522f475Smrg 658d522f475Smrg#define HALF_WIDTH_CHAR1 0x0031 /* '1' */ 659d522f475Smrg#define HALF_WIDTH_CHAR2 0x0057 /* 'W' */ 660d522f475Smrg#define FULL_WIDTH_CHAR1 0x4E00 /* CJK Ideograph 'number one' */ 661d522f475Smrg#define FULL_WIDTH_CHAR2 0xAC00 /* Korean script syllable 'Ka' */ 662d522f475Smrg 663d522f475Smrgstatic Bool 664d522f475Smrgis_double_width_font_xft(Display * dpy, XftFont * font) 665d522f475Smrg{ 666d522f475Smrg XGlyphInfo gi1, gi2; 667d522f475Smrg FcChar32 c1 = HALF_WIDTH_CHAR1, c2 = HALF_WIDTH_CHAR2; 6680bd37d32Smrg String fwstr = FULL_WIDTH_TEST_STRING; 6690bd37d32Smrg String hwstr = HALF_WIDTH_TEST_STRING; 670d522f475Smrg 671d522f475Smrg /* Some Korean fonts don't have Chinese characters at all. */ 672d522f475Smrg if (!XftCharExists(dpy, font, FULL_WIDTH_CHAR1)) { 673d522f475Smrg if (!XftCharExists(dpy, font, FULL_WIDTH_CHAR2)) 674d522f475Smrg return False; /* Not a CJK font */ 675d522f475Smrg else /* a Korean font without CJK Ideographs */ 676d522f475Smrg fwstr = FULL_WIDTH_TEST_STRING2; 677d522f475Smrg } 678d522f475Smrg 679d522f475Smrg XftTextExtents32(dpy, font, &c1, 1, &gi1); 680d522f475Smrg XftTextExtents32(dpy, font, &c2, 1, &gi2); 681d522f475Smrg if (gi1.xOff != gi2.xOff) /* Not a fixed-width font */ 682d522f475Smrg return False; 683d522f475Smrg 6840bd37d32Smrg XftTextExtentsUtf8(dpy, 6850bd37d32Smrg font, 6860bd37d32Smrg (_Xconst FcChar8 *) hwstr, 6870bd37d32Smrg (int) strlen(hwstr), 6880bd37d32Smrg &gi1); 6890bd37d32Smrg XftTextExtentsUtf8(dpy, 6900bd37d32Smrg font, 6910bd37d32Smrg (_Xconst FcChar8 *) fwstr, 6920bd37d32Smrg (int) strlen(fwstr), 6930bd37d32Smrg &gi2); 694d522f475Smrg 695d522f475Smrg /* 696d522f475Smrg * fontconfig and Xft prior to 2.2(?) set the width of half-width 697d522f475Smrg * characters identical to that of full-width character in CJK double-width 698d522f475Smrg * (bi-width / monospace) font even though the former is half as wide as 699d522f475Smrg * the latter. This was fixed sometime before the release of fontconfig 700d522f475Smrg * 2.2 in early 2003. See 701d522f475Smrg * http://bugzilla.mozilla.org/show_bug.cgi?id=196312 702d522f475Smrg * In the meantime, we have to check both possibilities. 703d522f475Smrg */ 704d522f475Smrg return ((2 * gi1.xOff == gi2.xOff) || (gi1.xOff == gi2.xOff)); 705d522f475Smrg} 706d522f475Smrg#else 707d522f475Smrg#define is_double_width_font_xft(dpy, xftfont) 0 708d522f475Smrg#endif 709d522f475Smrg 710d522f475Smrg#define EmptyFont(fs) (fs != 0 \ 711d522f475Smrg && ((fs)->ascent + (fs)->descent == 0 \ 712d522f475Smrg || (fs)->max_bounds.width == 0)) 713d522f475Smrg 714d522f475Smrg#define FontSize(fs) (((fs)->ascent + (fs)->descent) \ 715d522f475Smrg * (fs)->max_bounds.width) 716d522f475Smrg 717d522f475Smrgconst VTFontNames * 71820d2c4d2SmrgxtermFontName(const char *normal) 719d522f475Smrg{ 720d522f475Smrg static VTFontNames data; 72120d2c4d2Smrg if (data.f_n) 722492d43a5Smrg free((void *) data.f_n); 723d522f475Smrg memset(&data, 0, sizeof(data)); 72420d2c4d2Smrg data.f_n = x_strdup(normal); 725d522f475Smrg return &data; 726d522f475Smrg} 727d522f475Smrg 728d522f475Smrgstatic void 729d522f475Smrgcache_menu_font_name(TScreen * screen, int fontnum, int which, const char *name) 730d522f475Smrg{ 731d522f475Smrg if (name != 0) { 732492d43a5Smrg char *last = (char *) screen->menu_font_names[fontnum][which]; 733d522f475Smrg if (last != 0) { 734d522f475Smrg if (strcmp(last, name)) { 735d522f475Smrg free(last); 736d522f475Smrg TRACE(("caching menu fontname %d.%d %s\n", fontnum, which, name)); 737d522f475Smrg screen->menu_font_names[fontnum][which] = x_strdup(name); 738d522f475Smrg } 739d522f475Smrg } else { 740d522f475Smrg TRACE(("caching menu fontname %d.%d %s\n", fontnum, which, name)); 741d522f475Smrg screen->menu_font_names[fontnum][which] = x_strdup(name); 742d522f475Smrg } 743d522f475Smrg } 744d522f475Smrg} 745d522f475Smrg 746d522f475Smrg/* 747d522f475Smrg * Open the given font and verify that it is non-empty. Return a null on 748d522f475Smrg * failure. 749d522f475Smrg */ 750d522f475SmrgBool 751956cc18dSsnjxtermOpenFont(XtermWidget xw, 752956cc18dSsnj const char *name, 753956cc18dSsnj XTermFonts * result, 754956cc18dSsnj fontWarningTypes warn, 755956cc18dSsnj Bool force) 756d522f475Smrg{ 757d522f475Smrg Bool code = False; 758d522f475Smrg TScreen *screen = TScreenOf(xw); 759d522f475Smrg 760492d43a5Smrg if (!IsEmpty(name)) { 761956cc18dSsnj if ((result->fs = XLoadQueryFont(screen->display, name)) != 0) { 762956cc18dSsnj code = True; 763956cc18dSsnj if (EmptyFont(result->fs)) { 76420d2c4d2Smrg (void) xtermCloseFont(xw, result); 765956cc18dSsnj code = False; 766956cc18dSsnj } else { 767956cc18dSsnj result->fn = x_strdup(name); 768956cc18dSsnj } 76920d2c4d2Smrg } else if (XmuCompareISOLatin1(name, DEFFONT) != 0) { 770956cc18dSsnj if (warn <= xw->misc.fontWarnings 771956cc18dSsnj#if OPT_RENDERFONT 772956cc18dSsnj && !UsingRenderFont(xw) 773956cc18dSsnj#endif 774956cc18dSsnj ) { 775956cc18dSsnj TRACE(("OOPS: cannot load font %s\n", name)); 7760bd37d32Smrg xtermWarning("cannot load font '%s'\n", name); 77720d2c4d2Smrg#if OPT_RENDERFONT 77820d2c4d2Smrg /* 77920d2c4d2Smrg * Do a sanity check in case someone's mixed up xterm with 78020d2c4d2Smrg * one of those programs that read their resource data from 78120d2c4d2Smrg * xterm's namespace. 78220d2c4d2Smrg */ 78320d2c4d2Smrg if (strchr(name, ':') != 0 || strchr(name, '=') != 0) { 7840bd37d32Smrg xtermWarning("Use the \"-fa\" option for the Xft fonts\n"); 78520d2c4d2Smrg } 78620d2c4d2Smrg#endif 787956cc18dSsnj } else { 788492d43a5Smrg TRACE(("xtermOpenFont: cannot load font '%s'\n", name)); 789956cc18dSsnj } 790956cc18dSsnj if (force) { 791956cc18dSsnj code = xtermOpenFont(xw, DEFFONT, result, fwAlways, True); 792956cc18dSsnj } 793d522f475Smrg } 794d522f475Smrg } 795d522f475Smrg return code; 796d522f475Smrg} 797d522f475Smrg 798d522f475Smrg/* 799956cc18dSsnj * Close the font and free the font info. 800d522f475Smrg */ 801d522f475SmrgXTermFonts * 802d522f475SmrgxtermCloseFont(XtermWidget xw, XTermFonts * fnt) 803d522f475Smrg{ 804d522f475Smrg if (fnt != 0 && fnt->fs != 0) { 805d522f475Smrg TScreen *screen = TScreenOf(xw); 806d522f475Smrg 807d522f475Smrg clrCgsFonts(xw, WhichVWin(screen), fnt); 808d522f475Smrg XFreeFont(screen->display, fnt->fs); 809d522f475Smrg xtermFreeFontInfo(fnt); 810d522f475Smrg } 811d522f475Smrg return 0; 812d522f475Smrg} 813d522f475Smrg 814d522f475Smrg/* 815d522f475Smrg * Close the listed fonts, noting that some may use copies of the pointer. 816d522f475Smrg */ 817d522f475Smrgvoid 818d522f475SmrgxtermCloseFonts(XtermWidget xw, XTermFonts * fnts) 819d522f475Smrg{ 820d522f475Smrg int j, k; 821d522f475Smrg 822d522f475Smrg for (j = 0; j < fMAX; ++j) { 823d522f475Smrg /* 824d522f475Smrg * Need to save the pointer since xtermCloseFont zeroes it 825d522f475Smrg */ 826d522f475Smrg XFontStruct *thisFont = fnts[j].fs; 827d522f475Smrg if (thisFont != 0) { 828d522f475Smrg xtermCloseFont(xw, &fnts[j]); 829d522f475Smrg for (k = j + 1; k < fMAX; ++k) { 830d522f475Smrg if (thisFont == fnts[k].fs) 831d522f475Smrg xtermFreeFontInfo(&fnts[k]); 832d522f475Smrg } 833d522f475Smrg } 834d522f475Smrg } 835d522f475Smrg} 836d522f475Smrg 837d522f475Smrg/* 838d522f475Smrg * Make a copy of the source, assuming the XFontStruct's to be unique, but 839d522f475Smrg * ensuring that the names are reallocated to simplify freeing. 840d522f475Smrg */ 841d522f475Smrgvoid 842d522f475SmrgxtermCopyFontInfo(XTermFonts * target, XTermFonts * source) 843d522f475Smrg{ 844d522f475Smrg xtermFreeFontInfo(target); 845d522f475Smrg target->chrset = source->chrset; 846d522f475Smrg target->flags = source->flags; 847d522f475Smrg target->fn = x_strdup(source->fn); 848d522f475Smrg target->fs = source->fs; 849d522f475Smrg} 850d522f475Smrg 851d522f475Smrgvoid 852d522f475SmrgxtermFreeFontInfo(XTermFonts * target) 853d522f475Smrg{ 854d522f475Smrg target->chrset = 0; 855d522f475Smrg target->flags = 0; 856d522f475Smrg if (target->fn != 0) { 857d522f475Smrg free(target->fn); 858d522f475Smrg target->fn = 0; 859d522f475Smrg } 860d522f475Smrg target->fs = 0; 861d522f475Smrg} 862d522f475Smrg 863d522f475Smrgint 864d522f475SmrgxtermLoadFont(XtermWidget xw, 865d522f475Smrg const VTFontNames * fonts, 866d522f475Smrg Bool doresize, 867d522f475Smrg int fontnum) 868d522f475Smrg{ 869956cc18dSsnj TScreen *screen = TScreenOf(xw); 870d522f475Smrg VTwin *win = WhichVWin(screen); 871d522f475Smrg 872d522f475Smrg VTFontNames myfonts; 873d522f475Smrg FontNameProperties *fp; 874d522f475Smrg XTermFonts fnts[fMAX]; 875d522f475Smrg Pixel new_normal; 876d522f475Smrg Pixel new_revers; 877d522f475Smrg char *tmpname = NULL; 8780bd37d32Smrg char *normal = NULL; 879956cc18dSsnj Boolean proportional = False; 880956cc18dSsnj fontWarningTypes warn[fMAX]; 881956cc18dSsnj int j; 882d522f475Smrg 883d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 884d522f475Smrg memset(fnts, 0, sizeof(fnts)); 885d522f475Smrg 886d522f475Smrg if (fonts != 0) 887d522f475Smrg myfonts = *fonts; 888956cc18dSsnj if (!check_fontname(myfonts.f_n)) 889d522f475Smrg return 0; 890d522f475Smrg 891956cc18dSsnj /* 892956cc18dSsnj * Check the font names against the resource values, to see which were 893956cc18dSsnj * derived in a previous call. If so, we'll only warn about those if 894956cc18dSsnj * the warning level is set to "always". 895956cc18dSsnj */ 896956cc18dSsnj for (j = 0; j < fMAX; ++j) { 897956cc18dSsnj warn[j] = fwAlways; 898956cc18dSsnj } 899956cc18dSsnj#define CmpResource(field, index) \ 900956cc18dSsnj if (same_font_name(screen->menu_font_names[fontnum][index], myfonts.field)) \ 901956cc18dSsnj warn[index] = fwResource 902956cc18dSsnj 903956cc18dSsnj CmpResource(f_n, fNorm); 904956cc18dSsnj if (fontnum == fontMenu_default) { 905956cc18dSsnj CmpResource(f_b, fBold); 906956cc18dSsnj#if OPT_WIDE_CHARS 907956cc18dSsnj CmpResource(f_b, fWide); 908956cc18dSsnj CmpResource(f_b, fWBold); 909956cc18dSsnj#endif 910956cc18dSsnj } 911956cc18dSsnj 912d522f475Smrg if (fontnum == fontMenu_fontescape 913d522f475Smrg && myfonts.f_n != screen->MenuFontName(fontnum)) { 914d522f475Smrg if ((tmpname = x_strdup(myfonts.f_n)) == 0) 915d522f475Smrg return 0; 916d522f475Smrg } 917d522f475Smrg 918d522f475Smrg TRACE(("Begin Cgs - xtermLoadFont(%s)\n", myfonts.f_n)); 919d522f475Smrg releaseWindowGCs(xw, win); 920d522f475Smrg 921956cc18dSsnj#define DbgResource(name, field, index) \ 922956cc18dSsnj TRACE(("xtermLoadFont #%d "name" %s%s\n", \ 923956cc18dSsnj fontnum, \ 924956cc18dSsnj (warn[index] == fwResource) ? "*" : " ", \ 925492d43a5Smrg NonNull(myfonts.field))) 926956cc18dSsnj DbgResource("normal", f_n, fNorm); 927956cc18dSsnj DbgResource("bold ", f_b, fBold); 928d522f475Smrg#if OPT_WIDE_CHARS 929956cc18dSsnj DbgResource("wide ", f_w, fWide); 930956cc18dSsnj DbgResource("w/bold", f_wb, fWBold); 931d522f475Smrg#endif 932d522f475Smrg 933e39b573cSmrg /* 934e39b573cSmrg * If we are opening the default font, and it happens to be missing, force 935e39b573cSmrg * that to the compiled-in default font, e.g., "fixed". If we cannot open 936e39b573cSmrg * the font, disable it from the menu. 937e39b573cSmrg */ 938e39b573cSmrg if (!xtermOpenFont(xw, 939e39b573cSmrg myfonts.f_n, 940e39b573cSmrg &fnts[fNorm], 941e39b573cSmrg warn[fNorm], 942e39b573cSmrg (fontnum == fontMenu_default))) { 943e39b573cSmrg SetItemSensitivity(fontMenuEntries[fontnum].widget, False); 944d522f475Smrg goto bad; 945e39b573cSmrg } 946d522f475Smrg 9470bd37d32Smrg normal = x_strdup(myfonts.f_n); 948956cc18dSsnj if (!check_fontname(myfonts.f_b)) { 949956cc18dSsnj warn[fBold] = fwAlways; 9500bd37d32Smrg fp = get_font_name_props(screen->display, fnts[fNorm].fs, &normal); 951d522f475Smrg if (fp != 0) { 952d522f475Smrg myfonts.f_b = bold_font_name(fp, fp->average_width); 953956cc18dSsnj if (!xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], fwAlways, False)) { 954d522f475Smrg myfonts.f_b = bold_font_name(fp, -1); 955956cc18dSsnj xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], fwAlways, False); 956d522f475Smrg } 957492d43a5Smrg TRACE(("...derived bold '%s'\n", NonNull(myfonts.f_b))); 958d522f475Smrg } 959d522f475Smrg if (fp == 0 || fnts[fBold].fs == 0) { 960d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 961d522f475Smrg TRACE(("...cannot load a matching bold font\n")); 962d522f475Smrg } else if (same_font_size(xw, fnts[fNorm].fs, fnts[fBold].fs) 963d522f475Smrg && got_bold_font(screen->display, fnts[fBold].fs, myfonts.f_b)) { 964d522f475Smrg TRACE(("...got a matching bold font\n")); 965d522f475Smrg cache_menu_font_name(screen, fontnum, fBold, myfonts.f_b); 966d522f475Smrg } else { 967d522f475Smrg xtermCloseFont(xw, &fnts[fBold]); 968d522f475Smrg fnts[fBold] = fnts[fNorm]; 969d522f475Smrg TRACE(("...did not get a matching bold font\n")); 970d522f475Smrg } 971956cc18dSsnj } else if (!xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], warn[fBold], False)) { 972d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 973956cc18dSsnj warn[fBold] = fwAlways; 974492d43a5Smrg TRACE(("...cannot load bold font '%s'\n", NonNull(myfonts.f_b))); 975d522f475Smrg } else { 976d522f475Smrg cache_menu_font_name(screen, fontnum, fBold, myfonts.f_b); 977d522f475Smrg } 978d522f475Smrg 979d522f475Smrg /* 980d522f475Smrg * If there is no widefont specified, fake it by doubling AVERAGE_WIDTH 981d522f475Smrg * of normal fonts XLFD, and asking for it. This plucks out 18x18ja 982d522f475Smrg * and 12x13ja as the corresponding fonts for 9x18 and 6x13. 983d522f475Smrg */ 984d522f475Smrg if_OPT_WIDE_CHARS(screen, { 9850bd37d32Smrg Boolean derived; 9860bd37d32Smrg char *bold = NULL; 987d522f475Smrg 988956cc18dSsnj if (check_fontname(myfonts.f_w)) { 989d522f475Smrg cache_menu_font_name(screen, fontnum, fWide, myfonts.f_w); 990e39b573cSmrg } else if (screen->utf8_fonts && !is_double_width_font(fnts[fNorm].fs)) { 9910bd37d32Smrg fp = get_font_name_props(screen->display, fnts[fNorm].fs, &normal); 992d522f475Smrg if (fp != 0) { 993d522f475Smrg myfonts.f_w = wide_font_name(fp); 994956cc18dSsnj warn[fWide] = fwAlways; 995d522f475Smrg TRACE(("...derived wide %s\n", NonNull(myfonts.f_w))); 996d522f475Smrg cache_menu_font_name(screen, fontnum, fWide, myfonts.f_w); 997d522f475Smrg } 998d522f475Smrg } 999d522f475Smrg 1000956cc18dSsnj if (check_fontname(myfonts.f_w)) { 1001956cc18dSsnj (void) xtermOpenFont(xw, myfonts.f_w, &fnts[fWide], warn[fWide], False); 1002d522f475Smrg } else { 1003d522f475Smrg xtermCopyFontInfo(&fnts[fWide], &fnts[fNorm]); 1004956cc18dSsnj warn[fWide] = fwAlways; 1005d522f475Smrg } 1006d522f475Smrg 1007d522f475Smrg derived = False; 1008956cc18dSsnj if (!check_fontname(myfonts.f_wb)) { 10090bd37d32Smrg fp = get_font_name_props(screen->display, fnts[fBold].fs, &bold); 1010d522f475Smrg if (fp != 0) { 1011d522f475Smrg myfonts.f_wb = widebold_font_name(fp); 1012956cc18dSsnj warn[fWBold] = fwAlways; 1013d522f475Smrg derived = True; 1014d522f475Smrg } 1015d522f475Smrg } 1016d522f475Smrg 1017956cc18dSsnj if (check_fontname(myfonts.f_wb)) { 1018d522f475Smrg 1019e39b573cSmrg xtermOpenFont(xw, 1020e39b573cSmrg myfonts.f_wb, 1021e39b573cSmrg &fnts[fWBold], 1022e39b573cSmrg (screen->utf8_fonts 1023e39b573cSmrg ? warn[fWBold] 10240bd37d32Smrg : (fontWarningTypes) (xw->misc.fontWarnings + 1)), 1025e39b573cSmrg False); 1026d522f475Smrg 1027d522f475Smrg if (derived 1028d522f475Smrg && !compatibleWideCounts(fnts[fWide].fs, fnts[fWBold].fs)) { 1029d522f475Smrg xtermCloseFont(xw, &fnts[fWBold]); 1030d522f475Smrg } 1031d522f475Smrg if (fnts[fWBold].fs == 0) { 1032e39b573cSmrg if (IsEmpty(myfonts.f_w)) { 1033e39b573cSmrg myfonts.f_wb = myfonts.f_b; 1034e39b573cSmrg warn[fWBold] = fwAlways; 1035e39b573cSmrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fBold]); 1036e39b573cSmrg TRACE(("...cannot load wide-bold, use bold %s\n", 1037e39b573cSmrg NonNull(myfonts.f_b))); 1038e39b573cSmrg } else { 1039e39b573cSmrg myfonts.f_wb = myfonts.f_w; 1040e39b573cSmrg warn[fWBold] = fwAlways; 1041e39b573cSmrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1042e39b573cSmrg TRACE(("...cannot load wide-bold, use wide %s\n", 1043e39b573cSmrg NonNull(myfonts.f_w))); 1044e39b573cSmrg } 1045d522f475Smrg } else { 1046d522f475Smrg TRACE(("...%s wide/bold %s\n", 1047d522f475Smrg derived ? "derived" : "given", 1048d522f475Smrg NonNull(myfonts.f_wb))); 1049d522f475Smrg cache_menu_font_name(screen, fontnum, fWBold, myfonts.f_wb); 1050d522f475Smrg } 1051d522f475Smrg } else if (is_double_width_font(fnts[fBold].fs)) { 1052d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fBold]); 1053956cc18dSsnj warn[fWBold] = fwAlways; 1054d522f475Smrg TRACE(("...bold font is double-width, use it %s\n", NonNull(myfonts.f_b))); 1055d522f475Smrg } else { 1056d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1057956cc18dSsnj warn[fWBold] = fwAlways; 1058d522f475Smrg TRACE(("...cannot load wide bold font, use wide %s\n", NonNull(myfonts.f_w))); 1059d522f475Smrg } 1060d522f475Smrg 10610bd37d32Smrg free(bold); 10620bd37d32Smrg 1063d522f475Smrg if (EmptyFont(fnts[fWBold].fs)) 1064d522f475Smrg goto bad; /* can't use a 0-sized font */ 1065d522f475Smrg }); 1066d522f475Smrg 1067d522f475Smrg /* 1068d522f475Smrg * Most of the time this call to load the font will succeed, even if 1069d522f475Smrg * there is no wide font : the X server doubles the width of the 1070d522f475Smrg * normal font, or similar. 1071d522f475Smrg * 1072d522f475Smrg * But if it did fail for some reason, then nevermind. 1073d522f475Smrg */ 1074d522f475Smrg if (EmptyFont(fnts[fBold].fs)) 1075d522f475Smrg goto bad; /* can't use a 0-sized font */ 1076d522f475Smrg 1077d522f475Smrg if (!same_font_size(xw, fnts[fNorm].fs, fnts[fBold].fs) 1078d522f475Smrg && (is_fixed_font(fnts[fNorm].fs) && is_fixed_font(fnts[fBold].fs))) { 1079d522f475Smrg TRACE(("...ignoring mismatched normal/bold fonts\n")); 1080d522f475Smrg xtermCloseFont(xw, &fnts[fBold]); 1081d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 1082d522f475Smrg } 1083d522f475Smrg 1084d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1085d522f475Smrg if (fnts[fWide].fs != 0 1086d522f475Smrg && fnts[fWBold].fs != 0 1087d522f475Smrg && !same_font_size(xw, fnts[fWide].fs, fnts[fWBold].fs) 1088d522f475Smrg && (is_fixed_font(fnts[fWide].fs) && is_fixed_font(fnts[fWBold].fs))) { 1089d522f475Smrg TRACE(("...ignoring mismatched normal/bold wide fonts\n")); 1090d522f475Smrg xtermCloseFont(xw, &fnts[fWBold]); 1091d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1092d522f475Smrg } 1093d522f475Smrg }); 1094d522f475Smrg 1095d522f475Smrg /* 1096d522f475Smrg * Normal/bold fonts should be the same width. Also, the min/max 1097d522f475Smrg * values should be the same. 1098d522f475Smrg */ 1099d522f475Smrg if (!is_fixed_font(fnts[fNorm].fs) 1100d522f475Smrg || !is_fixed_font(fnts[fBold].fs) 1101d522f475Smrg || fnts[fNorm].fs->max_bounds.width != fnts[fBold].fs->max_bounds.width) { 1102d522f475Smrg TRACE(("Proportional font! normal %d/%d, bold %d/%d\n", 1103d522f475Smrg fnts[fNorm].fs->min_bounds.width, 1104d522f475Smrg fnts[fNorm].fs->max_bounds.width, 1105d522f475Smrg fnts[fBold].fs->min_bounds.width, 1106d522f475Smrg fnts[fBold].fs->max_bounds.width)); 1107d522f475Smrg proportional = True; 1108d522f475Smrg } 1109d522f475Smrg 1110d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1111d522f475Smrg if (fnts[fWide].fs != 0 1112d522f475Smrg && fnts[fWBold].fs != 0 1113d522f475Smrg && (!is_fixed_font(fnts[fWide].fs) 1114d522f475Smrg || !is_fixed_font(fnts[fWBold].fs) 1115d522f475Smrg || fnts[fWide].fs->max_bounds.width != fnts[fWBold].fs->max_bounds.width)) { 1116d522f475Smrg TRACE(("Proportional font! wide %d/%d, wide bold %d/%d\n", 1117d522f475Smrg fnts[fWide].fs->min_bounds.width, 1118d522f475Smrg fnts[fWide].fs->max_bounds.width, 1119d522f475Smrg fnts[fWBold].fs->min_bounds.width, 1120d522f475Smrg fnts[fWBold].fs->max_bounds.width)); 1121d522f475Smrg proportional = True; 1122d522f475Smrg } 1123d522f475Smrg }); 1124d522f475Smrg 1125d522f475Smrg /* TODO : enforce that the width of the wide font is 2* the width 1126d522f475Smrg of the narrow font */ 1127d522f475Smrg 1128d522f475Smrg /* 1129d522f475Smrg * If we're switching fonts, free the old ones. Otherwise we'll leak 1130d522f475Smrg * the memory that is associated with the old fonts. The 1131d522f475Smrg * XLoadQueryFont call allocates a new XFontStruct. 1132d522f475Smrg */ 1133d522f475Smrg xtermCloseFonts(xw, screen->fnts); 1134d522f475Smrg 1135d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fNorm]), &fnts[fNorm]); 1136d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fBold]), &fnts[fBold]); 1137d522f475Smrg#if OPT_WIDE_CHARS 1138d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fWide]), &fnts[fWide]); 1139d522f475Smrg if (fnts[fWBold].fs == NULL) 1140d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1141d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fWBold]), &fnts[fWBold]); 1142d522f475Smrg#endif 1143d522f475Smrg 1144d522f475Smrg new_normal = getXtermForeground(xw, xw->flags, xw->cur_foreground); 1145d522f475Smrg new_revers = getXtermBackground(xw, xw->flags, xw->cur_background); 1146d522f475Smrg 1147d522f475Smrg setCgsFore(xw, win, gcNorm, new_normal); 1148d522f475Smrg setCgsBack(xw, win, gcNorm, new_revers); 1149d522f475Smrg setCgsFont(xw, win, gcNorm, &(screen->fnts[fNorm])); 1150d522f475Smrg 1151d522f475Smrg copyCgs(xw, win, gcBold, gcNorm); 1152d522f475Smrg setCgsFont(xw, win, gcBold, &(screen->fnts[fBold])); 1153d522f475Smrg 1154d522f475Smrg setCgsFore(xw, win, gcNormReverse, new_revers); 1155d522f475Smrg setCgsBack(xw, win, gcNormReverse, new_normal); 1156d522f475Smrg setCgsFont(xw, win, gcNormReverse, &(screen->fnts[fNorm])); 1157d522f475Smrg 1158d522f475Smrg copyCgs(xw, win, gcBoldReverse, gcNormReverse); 1159d522f475Smrg setCgsFont(xw, win, gcBoldReverse, &(screen->fnts[fBold])); 1160d522f475Smrg 1161d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1162d522f475Smrg if (screen->fnts[fWide].fs != 0 1163d522f475Smrg && screen->fnts[fWBold].fs != 0) { 1164d522f475Smrg setCgsFore(xw, win, gcWide, new_normal); 1165d522f475Smrg setCgsBack(xw, win, gcWide, new_revers); 1166d522f475Smrg setCgsFont(xw, win, gcWide, &(screen->fnts[fWide])); 1167d522f475Smrg 1168d522f475Smrg copyCgs(xw, win, gcWBold, gcWide); 1169d522f475Smrg setCgsFont(xw, win, gcWBold, &(screen->fnts[fWBold])); 1170d522f475Smrg 1171d522f475Smrg setCgsFore(xw, win, gcWideReverse, new_revers); 1172d522f475Smrg setCgsBack(xw, win, gcWideReverse, new_normal); 1173d522f475Smrg setCgsFont(xw, win, gcWideReverse, &(screen->fnts[fWide])); 1174d522f475Smrg 1175d522f475Smrg copyCgs(xw, win, gcWBoldReverse, gcWideReverse); 1176d522f475Smrg setCgsFont(xw, win, gcWBoldReverse, &(screen->fnts[fWBold])); 1177d522f475Smrg } 1178d522f475Smrg }); 1179d522f475Smrg 118020d2c4d2Smrg#if OPT_BOX_CHARS 118120d2c4d2Smrg screen->allow_packing = proportional; 118220d2c4d2Smrg setupPackedFonts(xw); 118320d2c4d2Smrg#endif 118420d2c4d2Smrg screen->fnt_prop = (Boolean) (proportional && !(screen->force_packed)); 1185d522f475Smrg screen->fnt_boxes = True; 1186d522f475Smrg 1187d522f475Smrg#if OPT_BOX_CHARS 1188d522f475Smrg /* 1189d522f475Smrg * Xterm uses character positions 1-31 of a font for the line-drawing 1190d522f475Smrg * characters. Check that they are all present. The null character 1191d522f475Smrg * (0) is special, and is not used. 1192d522f475Smrg */ 1193d522f475Smrg#if OPT_RENDERFONT 1194d522f475Smrg if (UsingRenderFont(xw)) { 1195d522f475Smrg /* 1196d522f475Smrg * FIXME: we shouldn't even be here if we're using Xft. 1197d522f475Smrg */ 1198d522f475Smrg screen->fnt_boxes = False; 1199d522f475Smrg TRACE(("assume Xft missing line-drawing chars\n")); 1200d522f475Smrg } else 1201d522f475Smrg#endif 1202d522f475Smrg { 1203d522f475Smrg unsigned ch; 1204d522f475Smrg 1205d522f475Smrg for (ch = 1; ch < 32; ch++) { 1206d522f475Smrg unsigned n = ch; 1207d522f475Smrg#if OPT_WIDE_CHARS 1208d522f475Smrg if (screen->utf8_mode || screen->unicode_font) { 1209d522f475Smrg n = dec2ucs(ch); 1210d522f475Smrg if (n == UCS_REPL) 1211d522f475Smrg continue; 1212d522f475Smrg } 1213d522f475Smrg#endif 1214956cc18dSsnj if (IsXtermMissingChar(screen, n, &fnts[fNorm])) { 1215d522f475Smrg TRACE(("missing normal char #%d\n", n)); 1216d522f475Smrg screen->fnt_boxes = False; 1217d522f475Smrg break; 1218d522f475Smrg } 1219956cc18dSsnj if (IsXtermMissingChar(screen, n, &fnts[fBold])) { 1220d522f475Smrg TRACE(("missing bold char #%d\n", n)); 1221d522f475Smrg screen->fnt_boxes = False; 1222d522f475Smrg break; 1223d522f475Smrg } 1224d522f475Smrg } 1225d522f475Smrg } 1226d522f475Smrg TRACE(("Will %suse internal line-drawing characters\n", 1227d522f475Smrg screen->fnt_boxes ? "not " : "")); 1228d522f475Smrg#endif 1229d522f475Smrg 1230d522f475Smrg if (screen->always_bold_mode) { 1231d522f475Smrg screen->enbolden = screen->bold_mode; 1232d522f475Smrg } else { 1233d522f475Smrg screen->enbolden = screen->bold_mode 1234d522f475Smrg && ((fnts[fNorm].fs == fnts[fBold].fs) 1235d522f475Smrg || same_font_name(normal, myfonts.f_b)); 1236d522f475Smrg } 1237d522f475Smrg TRACE(("Will %suse 1-pixel offset/overstrike to simulate bold\n", 1238d522f475Smrg screen->enbolden ? "" : "not ")); 1239d522f475Smrg 1240d522f475Smrg set_menu_font(False); 1241d522f475Smrg screen->menu_font_number = fontnum; 1242d522f475Smrg set_menu_font(True); 1243d522f475Smrg if (tmpname) { /* if setting escape or sel */ 1244d522f475Smrg if (screen->MenuFontName(fontnum)) 124520d2c4d2Smrg free((void *) screen->MenuFontName(fontnum)); 1246d522f475Smrg screen->MenuFontName(fontnum) = tmpname; 1247d522f475Smrg if (fontnum == fontMenu_fontescape) { 1248d522f475Smrg SetItemSensitivity(fontMenuEntries[fontMenu_fontescape].widget, 1249d522f475Smrg True); 1250d522f475Smrg } 1251d522f475Smrg#if OPT_SHIFT_FONTS 1252d522f475Smrg screen->menu_font_sizes[fontnum] = FontSize(fnts[fNorm].fs); 1253d522f475Smrg#endif 1254d522f475Smrg } 12550bd37d32Smrg if (normal) 12560bd37d32Smrg free(normal); 1257d522f475Smrg set_cursor_gcs(xw); 1258d522f475Smrg xtermUpdateFontInfo(xw, doresize); 1259d522f475Smrg TRACE(("Success Cgs - xtermLoadFont\n")); 1260d522f475Smrg return 1; 1261d522f475Smrg 1262d522f475Smrg bad: 12630bd37d32Smrg if (normal) 12640bd37d32Smrg free(normal); 1265d522f475Smrg if (tmpname) 1266d522f475Smrg free(tmpname); 12670bd37d32Smrg 12680bd37d32Smrg#if OPT_RENDERFONT 12690bd37d32Smrg if (x_strcasecmp(myfonts.f_n, DEFFONT)) { 12700bd37d32Smrg int code; 12710bd37d32Smrg 12720bd37d32Smrg myfonts.f_n = DEFFONT; 12730bd37d32Smrg TRACE(("...recovering for TrueType fonts\n")); 12740bd37d32Smrg code = xtermLoadFont(xw, &myfonts, doresize, fontnum); 12750bd37d32Smrg if (code) { 12760bd37d32Smrg SetItemSensitivity(fontMenuEntries[fontnum].widget, 12770bd37d32Smrg UsingRenderFont(xw)); 12780bd37d32Smrg TRACE(("...recovered size %dx%d\n", 12790bd37d32Smrg FontHeight(screen), 12800bd37d32Smrg FontWidth(screen))); 12810bd37d32Smrg } 12820bd37d32Smrg return code; 12830bd37d32Smrg } 12840bd37d32Smrg#endif 12850bd37d32Smrg 1286d522f475Smrg releaseWindowGCs(xw, win); 1287d522f475Smrg 1288d522f475Smrg xtermCloseFonts(xw, fnts); 1289d522f475Smrg TRACE(("Fail Cgs - xtermLoadFont\n")); 1290d522f475Smrg return 0; 1291d522f475Smrg} 1292d522f475Smrg 1293d522f475Smrg#if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS 1294d522f475Smrg/* 1295d522f475Smrg * Collect font-names that we can modify with the load-vt-fonts() action. 1296d522f475Smrg */ 1297d522f475Smrg#define MERGE_SUBFONT(src,dst,name) \ 1298492d43a5Smrg if (IsEmpty(dst.name)) { \ 1299d522f475Smrg TRACE(("MERGE_SUBFONT " #dst "." #name " merge %s\n", NonNull(src.name))); \ 1300d522f475Smrg dst.name = src.name; \ 1301d522f475Smrg } else { \ 1302d522f475Smrg TRACE(("MERGE_SUBFONT " #dst "." #name " found %s\n", NonNull(dst.name))); \ 1303d522f475Smrg } 1304d522f475Smrg 1305e39b573cSmrg#define INFER_SUBFONT(src,dst,name) \ 1306e39b573cSmrg if (IsEmpty(dst.name)) { \ 1307e39b573cSmrg TRACE(("INFER_SUBFONT " #dst "." #name " will infer\n")); \ 1308e39b573cSmrg dst.name = x_strdup(""); \ 1309e39b573cSmrg } else { \ 1310e39b573cSmrg TRACE(("INFER_SUBFONT " #dst "." #name " found %s\n", NonNull(dst.name))); \ 1311e39b573cSmrg } 1312e39b573cSmrg 1313d522f475Smrg#define COPY_MENU_FONTS(src,dst) \ 1314d522f475Smrg TRACE(("COPY_MENU_FONTS " #src " to " #dst "\n")); \ 1315d522f475Smrg for (n = fontMenu_default; n <= fontMenu_lastBuiltin; ++n) { \ 1316d522f475Smrg for (m = 0; m < fMAX; ++m) { \ 1317492d43a5Smrg dst.menu_font_names[n][m] = x_strdup(src.menu_font_names[n][m]); \ 1318d522f475Smrg } \ 1319e39b573cSmrg TRACE((".. " #dst ".menu_fonts_names[%d] = %s\n", n, dst.menu_font_names[n][fNorm])); \ 1320e39b573cSmrg } 1321e39b573cSmrg 1322e39b573cSmrgvoid 1323e39b573cSmrgxtermSaveVTFonts(XtermWidget xw) 1324e39b573cSmrg{ 1325e39b573cSmrg TScreen *screen = TScreenOf(xw); 1326e39b573cSmrg Cardinal n, m; 1327e39b573cSmrg 1328e39b573cSmrg if (!screen->savedVTFonts) { 1329e39b573cSmrg 1330e39b573cSmrg screen->savedVTFonts = True; 1331e39b573cSmrg TRACE(("xtermSaveVTFonts saving original\n")); 1332e39b573cSmrg screen->cacheVTFonts.default_font = xw->misc.default_font; 1333e39b573cSmrg COPY_MENU_FONTS(xw->screen, screen->cacheVTFonts); 1334e39b573cSmrg } 1335e39b573cSmrg} 1336e39b573cSmrg 1337e39b573cSmrg#define SAME_STRING(x,y) ((x) == (y) || ((x) && (y) && !strcmp(x, y))) 1338e39b573cSmrg#define SAME_MEMBER(n) SAME_STRING(a->n, b->n) 1339e39b573cSmrg 1340e39b573cSmrgstatic Boolean 1341e39b573cSmrgsameSubResources(SubResourceRec * a, SubResourceRec * b) 1342e39b573cSmrg{ 1343e39b573cSmrg Boolean result = True; 1344e39b573cSmrg int n; 1345e39b573cSmrg 1346e39b573cSmrg if (!SAME_MEMBER(default_font.f_n) 1347e39b573cSmrg || !SAME_MEMBER(default_font.f_b) 13480bd37d32Smrg#if OPT_WIDE_CHARS 1349e39b573cSmrg || !SAME_MEMBER(default_font.f_w) 13500bd37d32Smrg || !SAME_MEMBER(default_font.f_wb) 13510bd37d32Smrg#endif 13520bd37d32Smrg ) { 1353e39b573cSmrg TRACE(("sameSubResources: default_font differs\n")); 1354e39b573cSmrg result = False; 1355e39b573cSmrg } else { 1356e39b573cSmrg for (n = 0; n < NMENUFONTS; ++n) { 1357e39b573cSmrg if (!SAME_MEMBER(menu_font_names[n][fNorm])) { 1358e39b573cSmrg TRACE(("sameSubResources: menu_font_names[%d] differs\n", n)); 1359e39b573cSmrg result = False; 1360e39b573cSmrg break; 1361e39b573cSmrg } 1362d522f475Smrg } 1363e39b573cSmrg } 1364e39b573cSmrg 1365e39b573cSmrg return result; 1366e39b573cSmrg} 1367d522f475Smrg 1368d522f475Smrg/* 1369d522f475Smrg * Load the "VT" font names from the given subresource name/class. These 1370d522f475Smrg * correspond to the VT100 resources. 1371d522f475Smrg */ 1372d522f475Smrgstatic Bool 137320d2c4d2SmrgxtermLoadVTFonts(XtermWidget xw, String myName, String myClass) 1374d522f475Smrg{ 1375e39b573cSmrg SubResourceRec subresourceRec; 1376e39b573cSmrg SubResourceRec referenceRec; 1377d522f475Smrg 1378d522f475Smrg /* 1379d522f475Smrg * These are duplicates of the VT100 font resources, but with a special 1380d522f475Smrg * application/classname passed in to distinguish them. 1381d522f475Smrg */ 1382d522f475Smrg static XtResource font_resources[] = 1383d522f475Smrg { 1384d522f475Smrg Sres(XtNfont, XtCFont, default_font.f_n, DEFFONT), 1385d522f475Smrg Sres(XtNboldFont, XtCBoldFont, default_font.f_b, DEFBOLDFONT), 1386d522f475Smrg#if OPT_WIDE_CHARS 1387d522f475Smrg Sres(XtNwideFont, XtCWideFont, default_font.f_w, DEFWIDEFONT), 1388d522f475Smrg Sres(XtNwideBoldFont, XtCWideBoldFont, default_font.f_wb, DEFWIDEBOLDFONT), 1389d522f475Smrg#endif 1390d522f475Smrg Sres(XtNfont1, XtCFont1, MenuFontName(fontMenu_font1), NULL), 1391d522f475Smrg Sres(XtNfont2, XtCFont2, MenuFontName(fontMenu_font2), NULL), 1392d522f475Smrg Sres(XtNfont3, XtCFont3, MenuFontName(fontMenu_font3), NULL), 1393d522f475Smrg Sres(XtNfont4, XtCFont4, MenuFontName(fontMenu_font4), NULL), 1394d522f475Smrg Sres(XtNfont5, XtCFont5, MenuFontName(fontMenu_font5), NULL), 1395d522f475Smrg Sres(XtNfont6, XtCFont6, MenuFontName(fontMenu_font6), NULL), 1396d522f475Smrg }; 1397d522f475Smrg Cardinal n, m; 1398d522f475Smrg Bool status = True; 1399956cc18dSsnj TScreen *screen = TScreenOf(xw); 1400d522f475Smrg 1401e39b573cSmrg TRACE(("called xtermLoadVTFonts(name=%s, class=%s)\n", 1402e39b573cSmrg NonNull(myName), NonNull(myClass))); 1403d522f475Smrg 1404e39b573cSmrg xtermSaveVTFonts(xw); 1405d522f475Smrg 1406492d43a5Smrg if (IsEmpty(myName)) { 1407d522f475Smrg TRACE(("xtermLoadVTFonts restoring original\n")); 1408e39b573cSmrg xw->misc.default_font = screen->cacheVTFonts.default_font; 1409e39b573cSmrg COPY_MENU_FONTS(screen->cacheVTFonts, xw->screen); 1410e39b573cSmrg for (n = 0; n < XtNumber(screen->cacheVTFonts.menu_font_names); ++n) { 1411e39b573cSmrg screen->MenuFontName(n) = screen->cacheVTFonts.MenuFontName(n); 1412e39b573cSmrg } 1413d522f475Smrg } else { 1414d522f475Smrg TRACE(("xtermLoadVTFonts(%s, %s)\n", myName, myClass)); 1415d522f475Smrg 1416e39b573cSmrg memset(&referenceRec, 0, sizeof(referenceRec)); 1417d522f475Smrg memset(&subresourceRec, 0, sizeof(subresourceRec)); 1418956cc18dSsnj XtGetSubresources((Widget) xw, (XtPointer) &subresourceRec, 1419d522f475Smrg myName, myClass, 1420d522f475Smrg font_resources, 1421d522f475Smrg (Cardinal) XtNumber(font_resources), 1422d522f475Smrg NULL, (Cardinal) 0); 1423d522f475Smrg 1424e39b573cSmrg /* 1425e39b573cSmrg * XtGetSubresources returns no status, so we compare the returned 1426e39b573cSmrg * data against a zero'd struct to see if any data is returned. 1427e39b573cSmrg */ 1428e39b573cSmrg if (memcmp(&referenceRec, &subresourceRec, sizeof(referenceRec)) 1429e39b573cSmrg && !sameSubResources(&(screen->cacheVTFonts), &subresourceRec)) { 1430e39b573cSmrg 1431e39b573cSmrg screen->mergedVTFonts = True; 1432d522f475Smrg 1433d522f475Smrg /* 1434d522f475Smrg * If a particular resource value was not found, use the original. 1435d522f475Smrg */ 1436956cc18dSsnj MERGE_SUBFONT(xw->misc, subresourceRec, default_font.f_n); 1437e39b573cSmrg INFER_SUBFONT(xw->misc, subresourceRec, default_font.f_b); 1438d522f475Smrg#if OPT_WIDE_CHARS 1439e39b573cSmrg INFER_SUBFONT(xw->misc, subresourceRec, default_font.f_w); 1440e39b573cSmrg INFER_SUBFONT(xw->misc, subresourceRec, default_font.f_wb); 1441d522f475Smrg#endif 1442d522f475Smrg for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; ++n) 1443956cc18dSsnj MERGE_SUBFONT(xw->screen, subresourceRec, MenuFontName(n)); 1444d522f475Smrg 1445d522f475Smrg /* 1446d522f475Smrg * Finally, copy the subresource data to the widget. 1447d522f475Smrg */ 1448956cc18dSsnj xw->misc.default_font = subresourceRec.default_font; 1449956cc18dSsnj COPY_MENU_FONTS(subresourceRec, xw->screen); 1450492d43a5Smrg screen->MenuFontName(fontMenu_default) = x_strdup(xw->misc.default_font.f_n); 1451492d43a5Smrg screen->menu_font_names[0][fBold] = x_strdup(xw->misc.default_font.f_b); 1452d522f475Smrg#if OPT_WIDE_CHARS 1453492d43a5Smrg screen->menu_font_names[0][fWide] = x_strdup(xw->misc.default_font.f_w); 1454492d43a5Smrg screen->menu_font_names[0][fWBold] = x_strdup(xw->misc.default_font.f_wb); 1455d522f475Smrg#endif 1456d522f475Smrg } else { 1457d522f475Smrg TRACE(("...no resources found\n")); 1458d522f475Smrg status = False; 1459d522f475Smrg } 1460d522f475Smrg } 1461d522f475Smrg return status; 1462d522f475Smrg} 1463d522f475Smrg 1464d522f475Smrg#if OPT_WIDE_CHARS 1465d522f475Smrgstatic Bool 146620d2c4d2SmrgisWideFont(XFontStruct * fp, const char *tag, Bool nullOk) 1467d522f475Smrg{ 1468d522f475Smrg Bool result = False; 1469d522f475Smrg 1470d522f475Smrg (void) tag; 1471d522f475Smrg if (okFont(fp)) { 1472d522f475Smrg unsigned count = countGlyphs(fp); 1473d522f475Smrg TRACE(("isWideFont(%s) found %d cells\n", tag, count)); 1474d522f475Smrg result = (count > 256) ? True : False; 1475d522f475Smrg } else { 1476d522f475Smrg result = nullOk; 1477d522f475Smrg } 1478d522f475Smrg return result; 1479d522f475Smrg} 1480d522f475Smrg 1481d522f475Smrg/* 1482d522f475Smrg * If the current fonts are not wide, load the UTF8 fonts. 1483d522f475Smrg * 1484d522f475Smrg * Called during initialization (for wide-character mode), the fonts have not 1485d522f475Smrg * been setup, so we pass nullOk=True to isWideFont(). 1486d522f475Smrg * 1487d522f475Smrg * Called after initialization, e.g., in response to the UTF-8 menu entry 1488d522f475Smrg * (starting from narrow character mode), it checks if the fonts are not wide. 1489d522f475Smrg */ 1490d522f475SmrgBool 1491d522f475SmrgxtermLoadWideFonts(XtermWidget xw, Bool nullOk) 1492d522f475Smrg{ 1493956cc18dSsnj TScreen *screen = TScreenOf(xw); 1494d522f475Smrg Bool result; 1495d522f475Smrg 1496d522f475Smrg if (EmptyFont(screen->fnts[fWide].fs)) { 1497d522f475Smrg result = (isWideFont(screen->fnts[fNorm].fs, "normal", nullOk) 1498d522f475Smrg && isWideFont(screen->fnts[fBold].fs, "bold", nullOk)); 1499d522f475Smrg } else { 1500d522f475Smrg result = (isWideFont(screen->fnts[fWide].fs, "wide", nullOk) 1501d522f475Smrg && isWideFont(screen->fnts[fWBold].fs, "wide-bold", nullOk)); 1502d522f475Smrg if (result && !screen->utf8_latin1) { 1503d522f475Smrg result = (isWideFont(screen->fnts[fNorm].fs, "normal", nullOk) 1504d522f475Smrg && isWideFont(screen->fnts[fBold].fs, "bold", nullOk)); 1505d522f475Smrg } 1506d522f475Smrg } 1507d522f475Smrg if (!result) { 1508d522f475Smrg TRACE(("current fonts are not all wide%s\n", nullOk ? " nullOk" : "")); 1509e39b573cSmrg result = xtermLoadVTFonts(xw, XtNutf8Fonts, XtCUtf8Fonts); 1510d522f475Smrg } 1511d522f475Smrg TRACE(("xtermLoadWideFonts:%d\n", result)); 1512d522f475Smrg return result; 1513d522f475Smrg} 1514d522f475Smrg#endif /* OPT_WIDE_CHARS */ 1515d522f475Smrg 1516d522f475Smrg/* 1517d522f475Smrg * Restore the default fonts, i.e., if we had switched to wide-fonts. 1518d522f475Smrg */ 1519d522f475SmrgBool 1520956cc18dSsnjxtermLoadDefaultFonts(XtermWidget xw) 1521d522f475Smrg{ 1522d522f475Smrg Bool result; 1523956cc18dSsnj result = xtermLoadVTFonts(xw, NULL, NULL); 1524d522f475Smrg TRACE(("xtermLoadDefaultFonts:%d\n", result)); 1525d522f475Smrg return result; 1526d522f475Smrg} 1527d522f475Smrg#endif /* OPT_LOAD_VTFONTS || OPT_WIDE_CHARS */ 1528d522f475Smrg 1529d522f475Smrg#if OPT_LOAD_VTFONTS 1530d522f475Smrgvoid 1531d522f475SmrgHandleLoadVTFonts(Widget w, 1532d522f475Smrg XEvent * event GCC_UNUSED, 1533d522f475Smrg String * params GCC_UNUSED, 1534d522f475Smrg Cardinal *param_count GCC_UNUSED) 1535d522f475Smrg{ 1536d522f475Smrg static char empty[] = ""; /* appease strict compilers */ 1537d522f475Smrg 1538956cc18dSsnj XtermWidget xw; 1539956cc18dSsnj 1540956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 1541956cc18dSsnj TScreen *screen = TScreenOf(xw); 1542492d43a5Smrg char name_buf[80]; 1543492d43a5Smrg char class_buf[80]; 1544492d43a5Smrg String name = (String) ((*param_count > 0) ? params[0] : empty); 15450bd37d32Smrg char *myName = (char *) MyStackAlloc(strlen(name) + 1, name_buf); 1546492d43a5Smrg String convert = (String) ((*param_count > 1) ? params[1] : myName); 15470bd37d32Smrg char *myClass = (char *) MyStackAlloc(strlen(convert) + 1, class_buf); 1548d522f475Smrg int n; 1549d522f475Smrg 1550d522f475Smrg TRACE(("HandleLoadVTFonts(%d)\n", *param_count)); 1551492d43a5Smrg strcpy(myName, name); 1552d522f475Smrg strcpy(myClass, convert); 15532eaa94a1Schristos if (*param_count == 1) 15542eaa94a1Schristos myClass[0] = x_toupper(myClass[0]); 1555d522f475Smrg 1556d522f475Smrg if (xtermLoadVTFonts(xw, myName, myClass)) { 1557d522f475Smrg /* 1558d522f475Smrg * When switching fonts, try to preserve the font-menu selection, since 1559d522f475Smrg * it is less surprising to do that (if the font-switching can be 1560d522f475Smrg * undone) than to switch to "Default". 1561d522f475Smrg */ 1562956cc18dSsnj int font_number = screen->menu_font_number; 1563d522f475Smrg if (font_number > fontMenu_lastBuiltin) 1564d522f475Smrg font_number = fontMenu_lastBuiltin; 1565d522f475Smrg for (n = 0; n < NMENUFONTS; ++n) 1566956cc18dSsnj screen->menu_font_sizes[n] = 0; 1567d522f475Smrg SetVTFont(xw, font_number, True, 1568d522f475Smrg ((font_number == fontMenu_default) 1569d522f475Smrg ? &(xw->misc.default_font) 1570d522f475Smrg : NULL)); 1571d522f475Smrg } 1572d522f475Smrg 1573492d43a5Smrg MyStackFree(myName, name_buf); 1574492d43a5Smrg MyStackFree(myClass, class_buf); 1575d522f475Smrg } 1576d522f475Smrg} 1577d522f475Smrg#endif /* OPT_LOAD_VTFONTS */ 1578d522f475Smrg 1579d522f475Smrg/* 1580d522f475Smrg * Set the limits for the box that outlines the cursor. 1581d522f475Smrg */ 1582d522f475Smrgvoid 1583d522f475SmrgxtermSetCursorBox(TScreen * screen) 1584d522f475Smrg{ 1585d522f475Smrg static XPoint VTbox[NBOX]; 1586d522f475Smrg XPoint *vp; 15872eaa94a1Schristos int fw = FontWidth(screen) - 1; 15882eaa94a1Schristos int fh = FontHeight(screen) - 1; 15890bd37d32Smrg int ww = isCursorBar(screen) ? 1 : fw; 15900bd37d32Smrg int hh = isCursorUnderline(screen) ? 1 : fh; 1591d522f475Smrg 1592d522f475Smrg vp = &VTbox[1]; 15930bd37d32Smrg (vp++)->x = (short) ww; 15942eaa94a1Schristos (vp++)->y = (short) hh; 15950bd37d32Smrg (vp++)->x = (short) -ww; 15962eaa94a1Schristos vp->y = (short) -hh; 15972eaa94a1Schristos 1598d522f475Smrg screen->box = VTbox; 1599d522f475Smrg} 1600d522f475Smrg 1601d522f475Smrg#define CACHE_XFT(dst,src) if (src != 0) {\ 1602956cc18dSsnj checkXft(xw, &(dst[fontnum]), src);\ 16030bd37d32Smrg TRACE(("Xft metrics %s[%d] = %d (%d,%d)%s advance %d, actual %d%s\n",\ 1604d522f475Smrg #dst,\ 1605d522f475Smrg fontnum,\ 1606d522f475Smrg src->height,\ 1607d522f475Smrg src->ascent,\ 1608d522f475Smrg src->descent,\ 16090bd37d32Smrg ((src->ascent + src->descent) > src->height ? "*" : ""),\ 1610956cc18dSsnj src->max_advance_width,\ 1611956cc18dSsnj dst[fontnum].map.min_width,\ 1612956cc18dSsnj dst[fontnum].map.mixed ? " mixed" : ""));\ 1613d522f475Smrg } 1614d522f475Smrg 1615d522f475Smrg#if OPT_RENDERFONT 1616956cc18dSsnj 161720d2c4d2Smrg#if OPT_TRACE > 1 161820d2c4d2Smrgstatic FcChar32 161920d2c4d2SmrgxtermXftFirstChar(XftFont * xft) 162020d2c4d2Smrg{ 162120d2c4d2Smrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 162220d2c4d2Smrg FcChar32 next; 162320d2c4d2Smrg FcChar32 first; 162420d2c4d2Smrg int i; 162520d2c4d2Smrg 162620d2c4d2Smrg first = FcCharSetFirstPage(xft->charset, map, &next); 162720d2c4d2Smrg for (i = 0; i < FC_CHARSET_MAP_SIZE; i++) 162820d2c4d2Smrg if (map[i]) { 162920d2c4d2Smrg FcChar32 bits = map[i]; 163020d2c4d2Smrg first += i * 32; 163120d2c4d2Smrg while (!(bits & 0x1)) { 163220d2c4d2Smrg bits >>= 1; 163320d2c4d2Smrg first++; 163420d2c4d2Smrg } 163520d2c4d2Smrg break; 163620d2c4d2Smrg } 163720d2c4d2Smrg return first; 163820d2c4d2Smrg} 163920d2c4d2Smrg 164020d2c4d2Smrgstatic FcChar32 164120d2c4d2SmrgxtermXftLastChar(XftFont * xft) 164220d2c4d2Smrg{ 164320d2c4d2Smrg FcChar32 this, last, next; 164420d2c4d2Smrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 164520d2c4d2Smrg int i; 164620d2c4d2Smrg last = FcCharSetFirstPage(xft->charset, map, &next); 164720d2c4d2Smrg while ((this = FcCharSetNextPage(xft->charset, map, &next)) != FC_CHARSET_DONE) 164820d2c4d2Smrg last = this; 164920d2c4d2Smrg last &= ~0xff; 165020d2c4d2Smrg for (i = FC_CHARSET_MAP_SIZE - 1; i >= 0; i--) 165120d2c4d2Smrg if (map[i]) { 165220d2c4d2Smrg FcChar32 bits = map[i]; 165320d2c4d2Smrg last += i * 32 + 31; 165420d2c4d2Smrg while (!(bits & 0x80000000)) { 165520d2c4d2Smrg last--; 165620d2c4d2Smrg bits <<= 1; 165720d2c4d2Smrg } 165820d2c4d2Smrg break; 165920d2c4d2Smrg } 166020d2c4d2Smrg return (long) last; 166120d2c4d2Smrg} 166220d2c4d2Smrg 166320d2c4d2Smrgstatic void 166420d2c4d2SmrgdumpXft(XtermWidget xw, XTermXftFonts * data) 166520d2c4d2Smrg{ 166620d2c4d2Smrg XftFont *xft = data->font; 166720d2c4d2Smrg TScreen *screen = TScreenOf(xw); 166820d2c4d2Smrg VTwin *win = WhichVWin(screen); 166920d2c4d2Smrg 167020d2c4d2Smrg FcChar32 c; 167120d2c4d2Smrg FcChar32 first = xtermXftFirstChar(xft); 167220d2c4d2Smrg FcChar32 last = xtermXftLastChar(xft); 167320d2c4d2Smrg unsigned count = 0; 167420d2c4d2Smrg unsigned outside = 0; 167520d2c4d2Smrg 167620d2c4d2Smrg TRACE(("dumpXft {{\n")); 167720d2c4d2Smrg TRACE((" data range %#6x..%#6x\n", first, last)); 167820d2c4d2Smrg for (c = first; c <= last; ++c) { 167920d2c4d2Smrg if (FcCharSetHasChar(xft->charset, c)) { 168020d2c4d2Smrg int width = my_wcwidth((int) c); 168120d2c4d2Smrg XGlyphInfo extents; 168220d2c4d2Smrg 168320d2c4d2Smrg XftTextExtents32(XtDisplay(xw), xft, &c, 1, &extents); 168420d2c4d2Smrg TRACE(("%#6x %2d %.1f\n", c, width, 168520d2c4d2Smrg ((double) extents.width) / win->f_width)); 168620d2c4d2Smrg if (extents.width > win->f_width) 168720d2c4d2Smrg ++outside; 168820d2c4d2Smrg ++count; 168920d2c4d2Smrg } 169020d2c4d2Smrg } 169120d2c4d2Smrg TRACE(("}} %u total, %u outside\n", count, outside)); 169220d2c4d2Smrg} 169320d2c4d2Smrg#define DUMP_XFT(xw, data) dumpXft(xw, data) 169420d2c4d2Smrg#else 169520d2c4d2Smrg#define DUMP_XFT(xw, data) /* nothing */ 169620d2c4d2Smrg#endif 169720d2c4d2Smrg 1698956cc18dSsnjstatic void 1699956cc18dSsnjcheckXft(XtermWidget xw, XTermXftFonts * data, XftFont * xft) 1700956cc18dSsnj{ 1701956cc18dSsnj FcChar32 c; 1702956cc18dSsnj Dimension width = 0; 1703956cc18dSsnj 1704956cc18dSsnj data->font = xft; 1705956cc18dSsnj data->map.min_width = 0; 1706956cc18dSsnj data->map.max_width = (Dimension) xft->max_advance_width; 1707956cc18dSsnj 170820d2c4d2Smrg /* 170920d2c4d2Smrg * For each ASCII or ISO-8859-1 printable code, ask what its width is. 171020d2c4d2Smrg * Given the maximum width for those, we have a reasonable estimate of 171120d2c4d2Smrg * the single-column width. 171220d2c4d2Smrg * 171320d2c4d2Smrg * Ignore control characters - their extent information is misleading. 171420d2c4d2Smrg */ 1715956cc18dSsnj for (c = 32; c < 256; ++c) { 171620d2c4d2Smrg if (c >= 127 && c <= 159) 171720d2c4d2Smrg continue; 1718956cc18dSsnj if (FcCharSetHasChar(xft->charset, c)) { 1719956cc18dSsnj XGlyphInfo extents; 1720956cc18dSsnj 1721956cc18dSsnj XftTextExtents32(XtDisplay(xw), xft, &c, 1, &extents); 172220d2c4d2Smrg if (width < extents.width && extents.width <= data->map.max_width) { 1723956cc18dSsnj width = extents.width; 172420d2c4d2Smrg } 1725956cc18dSsnj } 1726956cc18dSsnj } 1727956cc18dSsnj data->map.min_width = width; 1728956cc18dSsnj data->map.mixed = (data->map.max_width >= (data->map.min_width + 1)); 1729956cc18dSsnj} 1730956cc18dSsnj 1731d522f475Smrgstatic XftFont * 1732956cc18dSsnjxtermOpenXft(XtermWidget xw, const char *name, XftPattern * pat, const char *tag) 1733d522f475Smrg{ 1734956cc18dSsnj TScreen *screen = TScreenOf(xw); 1735956cc18dSsnj Display *dpy = screen->display; 1736d522f475Smrg XftPattern *match; 1737d522f475Smrg XftResult status; 1738d522f475Smrg XftFont *result = 0; 1739d522f475Smrg 1740d522f475Smrg if (pat != 0) { 1741d522f475Smrg match = XftFontMatch(dpy, DefaultScreen(dpy), pat, &status); 1742d522f475Smrg if (match != 0) { 1743d522f475Smrg result = XftFontOpenPattern(dpy, match); 1744d522f475Smrg if (result != 0) { 1745d522f475Smrg TRACE(("...matched %s font\n", tag)); 1746d522f475Smrg } else { 1747d522f475Smrg TRACE(("...could did not open %s font\n", tag)); 1748d522f475Smrg XftPatternDestroy(match); 1749956cc18dSsnj if (xw->misc.fontWarnings >= fwAlways) { 1750956cc18dSsnj TRACE(("OOPS cannot open %s font \"%s\"\n", tag, name)); 17510bd37d32Smrg xtermWarning("cannot open %s font \"%s\"\n", tag, name); 1752956cc18dSsnj } 1753d522f475Smrg } 1754d522f475Smrg } else { 1755d522f475Smrg TRACE(("...did not match %s font\n", tag)); 1756956cc18dSsnj if (xw->misc.fontWarnings >= fwResource) { 1757956cc18dSsnj TRACE(("OOPS: cannot match %s font \"%s\"\n", tag, name)); 17580bd37d32Smrg xtermWarning("cannot match %s font \"%s\"\n", tag, name); 1759956cc18dSsnj } 1760d522f475Smrg } 1761d522f475Smrg } 1762d522f475Smrg return result; 1763d522f475Smrg} 1764d522f475Smrg#endif 1765d522f475Smrg 1766d522f475Smrg#if OPT_RENDERFONT 1767d522f475Smrg#if OPT_SHIFT_FONTS 1768d522f475Smrg/* 1769d522f475Smrg * Don't make a dependency on the math library for a single function. 1770d522f475Smrg * (Newton Raphson). 1771d522f475Smrg */ 1772d522f475Smrgstatic double 17730bd37d32SmrgdimSquareRoot(double value) 1774d522f475Smrg{ 1775d522f475Smrg double result = 0.0; 1776d522f475Smrg if (value > 0.0) { 1777d522f475Smrg int n; 1778d522f475Smrg double older = value; 1779d522f475Smrg for (n = 0; n < 10; ++n) { 1780d522f475Smrg double delta = (older * older - value) / (2.0 * older); 1781d522f475Smrg double newer = older - delta; 1782d522f475Smrg older = newer; 1783d522f475Smrg result = newer; 1784d522f475Smrg if (delta > -0.001 && delta < 0.001) 1785d522f475Smrg break; 1786d522f475Smrg } 1787d522f475Smrg } 1788d522f475Smrg return result; 1789d522f475Smrg} 1790d522f475Smrg#endif 1791d522f475Smrg 1792d522f475Smrg/* 1793d522f475Smrg * Given the Xft font metrics, determine the actual font size. This is used 1794d522f475Smrg * for each font to ensure that normal, bold and italic fonts follow the same 1795d522f475Smrg * rule. 1796d522f475Smrg */ 1797d522f475Smrgstatic void 1798d522f475SmrgsetRenderFontsize(TScreen * screen, VTwin * win, XftFont * font, const char *tag) 1799d522f475Smrg{ 1800d522f475Smrg if (font != 0) { 1801d522f475Smrg int width, height, ascent, descent; 1802d522f475Smrg 1803d522f475Smrg (void) screen; 1804d522f475Smrg 1805d522f475Smrg width = font->max_advance_width; 1806d522f475Smrg height = font->height; 1807d522f475Smrg ascent = font->ascent; 1808d522f475Smrg descent = font->descent; 1809d522f475Smrg if (height < ascent + descent) { 1810d522f475Smrg TRACE(("...increase height from %d\n", height)); 1811d522f475Smrg height = ascent + descent; 1812d522f475Smrg } 1813d522f475Smrg if (is_double_width_font_xft(screen->display, font)) { 1814d522f475Smrg TRACE(("...reduced width from %d\n", width)); 1815d522f475Smrg width >>= 1; 1816d522f475Smrg } 1817d522f475Smrg if (tag == 0) { 18180bd37d32Smrg SetFontWidth(screen, win, width); 18190bd37d32Smrg SetFontHeight(screen, win, height); 1820d522f475Smrg win->f_ascent = ascent; 1821d522f475Smrg win->f_descent = descent; 1822d522f475Smrg TRACE(("setRenderFontsize result %dx%d (%d+%d)\n", 1823d522f475Smrg width, height, ascent, descent)); 1824d522f475Smrg } else if (win->f_width < width || 1825d522f475Smrg win->f_height < height || 1826d522f475Smrg win->f_ascent < ascent || 1827d522f475Smrg win->f_descent < descent) { 1828d522f475Smrg TRACE(("setRenderFontsize %s changed %dx%d (%d+%d) to %dx%d (%d+%d)\n", 1829d522f475Smrg tag, 1830d522f475Smrg win->f_width, win->f_height, win->f_ascent, win->f_descent, 1831d522f475Smrg width, height, ascent, descent)); 1832d522f475Smrg 18330bd37d32Smrg SetFontWidth(screen, win, width); 18340bd37d32Smrg SetFontHeight(screen, win, height); 1835d522f475Smrg win->f_ascent = ascent; 1836d522f475Smrg win->f_descent = descent; 1837d522f475Smrg } else { 1838d522f475Smrg TRACE(("setRenderFontsize %s unchanged\n", tag)); 1839d522f475Smrg } 1840d522f475Smrg } 1841d522f475Smrg} 1842d522f475Smrg#endif 1843d522f475Smrg 184420d2c4d2Smrgstatic void 184520d2c4d2SmrgcheckFontInfo(int value, const char *tag) 184620d2c4d2Smrg{ 184720d2c4d2Smrg if (value == 0) { 18480bd37d32Smrg xtermWarning("Selected font has no non-zero %s for ISO-8859-1 encoding\n", tag); 184920d2c4d2Smrg exit(1); 185020d2c4d2Smrg } 185120d2c4d2Smrg} 185220d2c4d2Smrg 185320d2c4d2Smrg#if OPT_RENDERFONT 185420d2c4d2Smrgvoid 185520d2c4d2SmrgxtermCloseXft(TScreen * screen, XTermXftFonts * pub) 185620d2c4d2Smrg{ 185720d2c4d2Smrg if (pub->font != 0) { 185820d2c4d2Smrg XftFontClose(screen->display, pub->font); 185920d2c4d2Smrg pub->font = 0; 186020d2c4d2Smrg } 186120d2c4d2Smrg} 186220d2c4d2Smrg 186320d2c4d2Smrg/* 186420d2c4d2Smrg * Get the faceName/faceDoublesize resource setting. Strip off "xft:", which 18650bd37d32Smrg * is not recognized by XftNameParse(). 186620d2c4d2Smrg */ 1867492d43a5SmrgString 186820d2c4d2SmrggetFaceName(XtermWidget xw, Bool wideName GCC_UNUSED) 186920d2c4d2Smrg{ 187020d2c4d2Smrg#if OPT_RENDERWIDE 1871492d43a5Smrg String result = (wideName 1872492d43a5Smrg ? xw->misc.face_wide_name 1873492d43a5Smrg : xw->misc.face_name); 187420d2c4d2Smrg#else 1875492d43a5Smrg String result = xw->misc.face_name; 187620d2c4d2Smrg#endif 187720d2c4d2Smrg if (!IsEmpty(result) && !strncmp(result, "xft:", (size_t) 4)) 187820d2c4d2Smrg result += 4; 187920d2c4d2Smrg return x_nonempty(result); 188020d2c4d2Smrg} 188120d2c4d2Smrg 188220d2c4d2Smrg/* 188320d2c4d2Smrg * If we change the faceName, we'll have to re-acquire all of the fonts that 188420d2c4d2Smrg * are derived from it. 188520d2c4d2Smrg */ 188620d2c4d2Smrgvoid 188720d2c4d2SmrgsetFaceName(XtermWidget xw, const char *value) 188820d2c4d2Smrg{ 188920d2c4d2Smrg TScreen *screen = TScreenOf(xw); 189020d2c4d2Smrg int n; 18910bd37d32Smrg Boolean changed = (Boolean) ((xw->misc.face_name == 0) 18920bd37d32Smrg || strcmp(xw->misc.face_name, value)); 189320d2c4d2Smrg 18940bd37d32Smrg if (changed) { 18950bd37d32Smrg xw->misc.face_name = x_strdup(value); 18960bd37d32Smrg for (n = 0; n < NMENUFONTS; ++n) { 18970bd37d32Smrg xw->misc.face_size[n] = -1.0; 18980bd37d32Smrg xtermCloseXft(screen, &(screen->renderFontNorm[n])); 18990bd37d32Smrg xtermCloseXft(screen, &(screen->renderFontBold[n])); 19000bd37d32Smrg xtermCloseXft(screen, &(screen->renderFontBold[n])); 190120d2c4d2Smrg#if OPT_RENDERWIDE 19020bd37d32Smrg xtermCloseXft(screen, &(screen->renderWideNorm[n])); 19030bd37d32Smrg xtermCloseXft(screen, &(screen->renderWideBold[n])); 19040bd37d32Smrg xtermCloseXft(screen, &(screen->renderWideItal[n])); 190520d2c4d2Smrg#endif 19060bd37d32Smrg } 190720d2c4d2Smrg } 190820d2c4d2Smrg} 190920d2c4d2Smrg#endif 191020d2c4d2Smrg 1911d522f475Smrg/* 1912d522f475Smrg * Compute useful values for the font/window sizes 1913d522f475Smrg */ 1914d522f475Smrgvoid 1915d522f475SmrgxtermComputeFontInfo(XtermWidget xw, 1916d522f475Smrg VTwin * win, 1917d522f475Smrg XFontStruct * font, 1918d522f475Smrg int sbwidth) 1919d522f475Smrg{ 1920956cc18dSsnj TScreen *screen = TScreenOf(xw); 1921d522f475Smrg 1922d522f475Smrg int i, j, width, height; 1923492d43a5Smrg#if OPT_RENDERFONT 1924492d43a5Smrg int fontnum = screen->menu_font_number; 1925492d43a5Smrg#endif 1926d522f475Smrg 1927d522f475Smrg#if OPT_RENDERFONT 1928d522f475Smrg /* 1929d522f475Smrg * xterm contains a lot of references to fonts, assuming they are fixed 1930d522f475Smrg * size. This chunk of code overrides the actual font-selection (see 1931d522f475Smrg * drawXtermText()), if the user has selected render-font. All of the 1932d522f475Smrg * font-loading for fixed-fonts still goes on whether or not this chunk 1933d522f475Smrg * overrides it. 1934d522f475Smrg */ 1935492d43a5Smrg if (UsingRenderFont(xw) && fontnum >= 0) { 1936492d43a5Smrg String face_name = getFaceName(xw, False); 1937956cc18dSsnj XftFont *norm = screen->renderFontNorm[fontnum].font; 1938956cc18dSsnj XftFont *bold = screen->renderFontBold[fontnum].font; 1939956cc18dSsnj XftFont *ital = screen->renderFontItal[fontnum].font; 1940d522f475Smrg#if OPT_RENDERWIDE 1941956cc18dSsnj XftFont *wnorm = screen->renderWideNorm[fontnum].font; 1942956cc18dSsnj XftFont *wbold = screen->renderWideBold[fontnum].font; 1943956cc18dSsnj XftFont *wital = screen->renderWideItal[fontnum].font; 1944d522f475Smrg#endif 1945d522f475Smrg 194620d2c4d2Smrg if (norm == 0 && face_name) { 1947d522f475Smrg XftPattern *pat; 19480bd37d32Smrg double face_size; 1949d522f475Smrg 19500bd37d32Smrg TRACE(("xtermComputeFontInfo font %d: norm(face %s, size %.1f)\n", 1951492d43a5Smrg fontnum, face_name, 1952d522f475Smrg xw->misc.face_size[fontnum])); 1953d522f475Smrg 19540bd37d32Smrg fillInFaceSize(xw, fontnum); 19550bd37d32Smrg face_size = xw->misc.face_size[fontnum]; 1956d522f475Smrg 1957d522f475Smrg /* 1958d522f475Smrg * By observation (there is no documentation), XftPatternBuild is 1959d522f475Smrg * cumulative. Build the bold- and italic-patterns on top of the 1960d522f475Smrg * normal pattern. 1961d522f475Smrg */ 1962d522f475Smrg#define NormXftPattern \ 1963d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 1964d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 1965d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 1966d522f475Smrg 1967d522f475Smrg#define BoldXftPattern(norm) \ 1968d522f475Smrg XFT_WEIGHT, XftTypeInteger, XFT_WEIGHT_BOLD, \ 1969d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 1970d522f475Smrg 1971d522f475Smrg#define ItalXftPattern(norm) \ 1972d522f475Smrg XFT_SLANT, XftTypeInteger, XFT_SLANT_ITALIC, \ 1973d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 1974d522f475Smrg 197520d2c4d2Smrg if ((pat = XftNameParse(face_name)) != 0) { 197620d2c4d2Smrg#define OPEN_XFT(tag) xtermOpenXft(xw, face_name, pat, tag) 1977d522f475Smrg XftPatternBuild(pat, 1978d522f475Smrg NormXftPattern, 1979d522f475Smrg (void *) 0); 1980956cc18dSsnj norm = OPEN_XFT("normal"); 1981d522f475Smrg 1982d522f475Smrg if (norm != 0) { 1983d522f475Smrg XftPatternBuild(pat, 1984d522f475Smrg BoldXftPattern(norm), 1985d522f475Smrg (void *) 0); 1986956cc18dSsnj bold = OPEN_XFT("bold"); 1987d522f475Smrg 1988d522f475Smrg#if OPT_ISO_COLORS 1989d522f475Smrg if (screen->italicULMode 199020d2c4d2Smrg && (pat = XftNameParse(face_name)) != 0) { 1991d522f475Smrg XftPatternBuild(pat, 1992d522f475Smrg NormXftPattern, 1993d522f475Smrg ItalXftPattern(norm), 1994d522f475Smrg (void *) 0); 1995956cc18dSsnj ital = OPEN_XFT("italic"); 1996d522f475Smrg } 1997d522f475Smrg#endif /* OPT_ISO_COLORS */ 1998956cc18dSsnj#undef OPEN_XFT 1999d522f475Smrg 2000d522f475Smrg /* 2001d522f475Smrg * FIXME: just assume that the corresponding font has no 2002d522f475Smrg * graphics characters. 2003d522f475Smrg */ 2004d522f475Smrg if (screen->fnt_boxes) { 2005d522f475Smrg screen->fnt_boxes = False; 2006d522f475Smrg TRACE(("Xft opened - will %suse internal line-drawing characters\n", 2007d522f475Smrg screen->fnt_boxes ? "not " : "")); 2008d522f475Smrg } 2009d522f475Smrg } 2010d522f475Smrg 2011d522f475Smrg XftPatternDestroy(pat); 2012d522f475Smrg } 2013d522f475Smrg 2014d522f475Smrg CACHE_XFT(screen->renderFontNorm, norm); 2015d522f475Smrg CACHE_XFT(screen->renderFontBold, bold); 2016d522f475Smrg CACHE_XFT(screen->renderFontItal, ital); 2017d522f475Smrg 2018d522f475Smrg /* 2019d522f475Smrg * See xtermXftDrawString(). 2020d522f475Smrg */ 2021d522f475Smrg#if OPT_RENDERWIDE 2022d522f475Smrg if (norm != 0 && screen->wide_chars) { 2023d522f475Smrg int char_width = norm->max_advance_width * 2; 2024956cc18dSsnj#ifdef FC_ASPECT 2025956cc18dSsnj double aspect = ((xw->misc.face_wide_name 2026956cc18dSsnj || screen->renderFontNorm[fontnum].map.mixed) 2027956cc18dSsnj ? 1.0 2028956cc18dSsnj : 2.0); 2029956cc18dSsnj#endif 2030d522f475Smrg 203120d2c4d2Smrg face_name = getFaceName(xw, True); 2032d522f475Smrg TRACE(("xtermComputeFontInfo wide(face %s, char_width %d)\n", 203320d2c4d2Smrg NonNull(face_name), 2034d522f475Smrg char_width)); 2035d522f475Smrg 2036d522f475Smrg#define WideXftPattern \ 2037d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 2038d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 2039d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 2040d522f475Smrg 204120d2c4d2Smrg if (face_name && (pat = XftNameParse(face_name)) != 0) { 2042956cc18dSsnj#define OPEN_XFT(tag) xtermOpenXft(xw, face_name, pat, tag) 2043d522f475Smrg XftPatternBuild(pat, 2044d522f475Smrg WideXftPattern, 2045d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, char_width, 2046956cc18dSsnj#ifdef FC_ASPECT 2047956cc18dSsnj FC_ASPECT, XftTypeDouble, aspect, 2048956cc18dSsnj#endif 2049d522f475Smrg (void *) 0); 2050956cc18dSsnj wnorm = OPEN_XFT("wide"); 2051d522f475Smrg 2052d522f475Smrg if (wnorm != 0) { 2053d522f475Smrg XftPatternBuild(pat, 2054d522f475Smrg WideXftPattern, 2055d522f475Smrg BoldXftPattern(wnorm), 2056d522f475Smrg (void *) 0); 2057956cc18dSsnj wbold = OPEN_XFT("wide-bold"); 2058d522f475Smrg 2059d522f475Smrg#if OPT_ISO_COLORS 2060d522f475Smrg if (screen->italicULMode 2061d522f475Smrg && (pat = XftNameParse(face_name)) != 0) { 2062d522f475Smrg XftPatternBuild(pat, 2063d522f475Smrg WideXftPattern, 2064d522f475Smrg ItalXftPattern(wnorm), 2065d522f475Smrg (void *) 0); 2066956cc18dSsnj wital = OPEN_XFT("wide-italic"); 2067d522f475Smrg } 2068d522f475Smrg#endif 2069956cc18dSsnj#undef OPEN_XFT 2070d522f475Smrg } 2071d522f475Smrg XftPatternDestroy(pat); 2072d522f475Smrg } 2073d522f475Smrg 2074d522f475Smrg CACHE_XFT(screen->renderWideNorm, wnorm); 2075d522f475Smrg CACHE_XFT(screen->renderWideBold, wbold); 2076d522f475Smrg CACHE_XFT(screen->renderWideItal, wital); 2077d522f475Smrg } 2078d522f475Smrg#endif /* OPT_RENDERWIDE */ 2079d522f475Smrg } 2080d522f475Smrg if (norm == 0) { 20812eaa94a1Schristos TRACE(("...no TrueType font found for number %d, disable menu entry\n", fontnum)); 20820bd37d32Smrg xw->work.render_font = False; 2083d522f475Smrg update_font_renderfont(); 2084d522f475Smrg /* now we will fall through into the bitmap fonts */ 2085d522f475Smrg } else { 2086d522f475Smrg setRenderFontsize(screen, win, norm, NULL); 2087d522f475Smrg setRenderFontsize(screen, win, bold, "bold"); 2088d522f475Smrg setRenderFontsize(screen, win, ital, "ital"); 208920d2c4d2Smrg#if OPT_BOX_CHARS 209020d2c4d2Smrg setupPackedFonts(xw); 209120d2c4d2Smrg 209220d2c4d2Smrg if (screen->force_packed) { 209320d2c4d2Smrg XTermXftFonts *use = &(screen->renderFontNorm[fontnum]); 20940bd37d32Smrg SetFontHeight(screen, win, use->font->ascent + use->font->descent); 20950bd37d32Smrg SetFontWidth(screen, win, use->map.min_width); 209620d2c4d2Smrg TRACE(("...packed TrueType font %dx%d vs %d\n", 209720d2c4d2Smrg win->f_height, 209820d2c4d2Smrg win->f_width, 209920d2c4d2Smrg use->map.max_width)); 210020d2c4d2Smrg } 210120d2c4d2Smrg#endif 210220d2c4d2Smrg DUMP_XFT(xw, &(screen->renderFontNorm[fontnum])); 2103d522f475Smrg } 2104d522f475Smrg } 2105d522f475Smrg /* 2106d522f475Smrg * Are we handling a bitmap font? 2107d522f475Smrg */ 2108492d43a5Smrg else 2109d522f475Smrg#endif /* OPT_RENDERFONT */ 2110d522f475Smrg { 211120d2c4d2Smrg if (is_double_width_font(font) && !(screen->fnt_prop)) { 21120bd37d32Smrg SetFontWidth(screen, win, font->min_bounds.width); 2113d522f475Smrg } else { 21140bd37d32Smrg SetFontWidth(screen, win, font->max_bounds.width); 2115d522f475Smrg } 21160bd37d32Smrg SetFontHeight(screen, win, font->ascent + font->descent); 2117d522f475Smrg win->f_ascent = font->ascent; 2118d522f475Smrg win->f_descent = font->descent; 2119d522f475Smrg } 2120d522f475Smrg i = 2 * screen->border + sbwidth; 2121d522f475Smrg j = 2 * screen->border; 2122d522f475Smrg width = MaxCols(screen) * win->f_width + i; 2123d522f475Smrg height = MaxRows(screen) * win->f_height + j; 2124956cc18dSsnj win->fullwidth = (Dimension) width; 2125956cc18dSsnj win->fullheight = (Dimension) height; 2126d522f475Smrg win->width = width - i; 2127d522f475Smrg win->height = height - j; 2128d522f475Smrg 2129d522f475Smrg TRACE(("xtermComputeFontInfo window %dx%d (full %dx%d), fontsize %dx%d (asc %d, dsc %d)\n", 2130d522f475Smrg win->height, 2131d522f475Smrg win->width, 2132d522f475Smrg win->fullheight, 2133d522f475Smrg win->fullwidth, 2134d522f475Smrg win->f_height, 2135d522f475Smrg win->f_width, 2136d522f475Smrg win->f_ascent, 2137d522f475Smrg win->f_descent)); 213820d2c4d2Smrg 213920d2c4d2Smrg checkFontInfo(win->f_height, "height"); 214020d2c4d2Smrg checkFontInfo(win->f_width, "width"); 2141d522f475Smrg} 2142d522f475Smrg 2143d522f475Smrg/* save this information as a side-effect for double-sized characters */ 2144d522f475Smrgvoid 2145d522f475SmrgxtermSaveFontInfo(TScreen * screen, XFontStruct * font) 2146d522f475Smrg{ 2147956cc18dSsnj screen->fnt_wide = (Dimension) (font->max_bounds.width); 2148956cc18dSsnj screen->fnt_high = (Dimension) (font->ascent + font->descent); 2149d522f475Smrg TRACE(("xtermSaveFontInfo %dx%d\n", screen->fnt_high, screen->fnt_wide)); 2150d522f475Smrg} 2151d522f475Smrg 2152d522f475Smrg/* 2153d522f475Smrg * After loading a new font, update the structures that use its size. 2154d522f475Smrg */ 2155d522f475Smrgvoid 2156d522f475SmrgxtermUpdateFontInfo(XtermWidget xw, Bool doresize) 2157d522f475Smrg{ 2158956cc18dSsnj TScreen *screen = TScreenOf(xw); 2159d522f475Smrg 2160d522f475Smrg int scrollbar_width; 2161d522f475Smrg VTwin *win = &(screen->fullVwin); 2162d522f475Smrg 2163d522f475Smrg scrollbar_width = (xw->misc.scrollbar 2164d522f475Smrg ? (screen->scrollWidget->core.width + 2165d522f475Smrg BorderWidth(screen->scrollWidget)) 2166d522f475Smrg : 0); 2167d522f475Smrg xtermComputeFontInfo(xw, win, screen->fnts[fNorm].fs, scrollbar_width); 2168d522f475Smrg xtermSaveFontInfo(screen, screen->fnts[fNorm].fs); 2169d522f475Smrg 2170d522f475Smrg if (doresize) { 2171d522f475Smrg if (VWindow(screen)) { 2172d522f475Smrg xtermClear(xw); 2173d522f475Smrg } 2174d522f475Smrg TRACE(("xtermUpdateFontInfo {{\n")); 2175d522f475Smrg DoResizeScreen(xw); /* set to the new natural size */ 2176d522f475Smrg ResizeScrollBar(xw); 2177d522f475Smrg Redraw(); 2178d522f475Smrg TRACE(("... }} xtermUpdateFontInfo\n")); 2179d522f475Smrg#ifdef SCROLLBAR_RIGHT 2180d522f475Smrg updateRightScrollbar(xw); 2181d522f475Smrg#endif 2182d522f475Smrg } 2183d522f475Smrg xtermSetCursorBox(screen); 2184d522f475Smrg} 2185d522f475Smrg 2186d522f475Smrg#if OPT_BOX_CHARS 2187d522f475Smrg 2188d522f475Smrg/* 2189d522f475Smrg * Returns true if the given character is missing from the specified font. 2190d522f475Smrg */ 2191d522f475SmrgBool 2192956cc18dSsnjxtermMissingChar(unsigned ch, XTermFonts * font) 2193d522f475Smrg{ 2194956cc18dSsnj Bool result = False; 2195956cc18dSsnj XFontStruct *fs = font->fs; 2196956cc18dSsnj static XCharStruct dft, *tmp = &dft, *pc = 0; 2197d522f475Smrg 2198956cc18dSsnj if (fs->max_byte1 == 0) { 2199d522f475Smrg#if OPT_WIDE_CHARS 2200956cc18dSsnj if (ch > 255) { 2201956cc18dSsnj TRACE(("xtermMissingChar %#04x (row)\n", ch)); 2202956cc18dSsnj return True; 2203d522f475Smrg } 2204956cc18dSsnj#endif 2205956cc18dSsnj CI_GET_CHAR_INFO_1D(fs, E2A(ch), tmp, pc); 2206956cc18dSsnj } 2207d522f475Smrg#if OPT_WIDE_CHARS 2208956cc18dSsnj else { 2209956cc18dSsnj CI_GET_CHAR_INFO_2D(fs, HI_BYTE(ch), LO_BYTE(ch), tmp, pc); 2210956cc18dSsnj } 2211d522f475Smrg#else 2212d522f475Smrg 2213956cc18dSsnj if (!pc) 2214956cc18dSsnj return False; /* Urgh! */ 2215d522f475Smrg#endif 2216d522f475Smrg 2217956cc18dSsnj if (CI_NONEXISTCHAR(pc)) { 2218956cc18dSsnj TRACE(("xtermMissingChar %#04x (!exists)\n", ch)); 2219956cc18dSsnj result = True; 2220d522f475Smrg } 2221956cc18dSsnj if (ch < 256) { 2222956cc18dSsnj font->known_missing[ch] = (Char) (result ? 2 : 1); 2223d522f475Smrg } 2224956cc18dSsnj return result; 2225d522f475Smrg} 2226d522f475Smrg 2227d522f475Smrg/* 2228d522f475Smrg * The grid is arbitrary, enough resolution that nothing's lost in 2229d522f475Smrg * initialization. 2230d522f475Smrg */ 2231d522f475Smrg#define BOX_HIGH 60 2232d522f475Smrg#define BOX_WIDE 60 2233d522f475Smrg 2234d522f475Smrg#define MID_HIGH (BOX_HIGH/2) 2235d522f475Smrg#define MID_WIDE (BOX_WIDE/2) 2236d522f475Smrg 2237d522f475Smrg#define CHR_WIDE ((9*BOX_WIDE)/10) 2238d522f475Smrg#define CHR_HIGH ((9*BOX_HIGH)/10) 2239d522f475Smrg 2240d522f475Smrg/* 2241d522f475Smrg * ...since we'll scale the values anyway. 2242d522f475Smrg */ 2243e39b573cSmrg#define SCALED_X(n) ((int)(n) * (((int) font_width) - 1)) / (BOX_WIDE-1) 2244e39b573cSmrg#define SCALED_Y(n) ((int)(n) * (((int) font_height) - 1)) / (BOX_HIGH-1) 2245e39b573cSmrg#define SCALE_X(n) n = SCALED_X(n) 2246e39b573cSmrg#define SCALE_Y(n) n = SCALED_Y(n) 2247d522f475Smrg 2248d522f475Smrg#define SEG(x0,y0,x1,y1) x0,y0, x1,y1 2249d522f475Smrg 2250d522f475Smrg/* 2251d522f475Smrg * Draw the given graphic character, if it is simple enough (i.e., a 2252d522f475Smrg * line-drawing character). 2253d522f475Smrg */ 2254d522f475Smrgvoid 2255d522f475SmrgxtermDrawBoxChar(XtermWidget xw, 2256d522f475Smrg unsigned ch, 2257d522f475Smrg unsigned flags, 2258d522f475Smrg GC gc, 2259d522f475Smrg int x, 2260d522f475Smrg int y, 2261d522f475Smrg int cells) 2262d522f475Smrg{ 2263956cc18dSsnj TScreen *screen = TScreenOf(xw); 2264d522f475Smrg /* *INDENT-OFF* */ 2265d522f475Smrg static const short glyph_ht[] = { 2266d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,5*MID_HIGH/6), /* H */ 2267d522f475Smrg SEG(6*BOX_WIDE/10, 0, 6*BOX_WIDE/10,5*MID_HIGH/6), 2268d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*BOX_WIDE/10,5*MID_HIGH/12), 2269d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 2270d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 2271d522f475Smrg -1 2272d522f475Smrg }, glyph_ff[] = { 2273d522f475Smrg SEG(1*BOX_WIDE/10, 0, 6*BOX_WIDE/10, 0), /* F */ 2274d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*CHR_WIDE/12,5*MID_HIGH/12), 2275d522f475Smrg SEG(1*BOX_WIDE/10, 0, 0*BOX_WIDE/3, 5*MID_HIGH/6), 2276d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 2277d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 2278d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 2279d522f475Smrg -1 2280d522f475Smrg }, glyph_lf[] = { 2281d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,9*MID_HIGH/12), /* L */ 2282d522f475Smrg SEG(1*BOX_WIDE/10,9*MID_HIGH/12,6*BOX_WIDE/10,9*MID_HIGH/12), 2283d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 2284d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 2285d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 2286d522f475Smrg -1 2287d522f475Smrg }, glyph_nl[] = { 2288d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/6, 1*BOX_WIDE/10, 0), /* N */ 2289d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/6, 5*MID_HIGH/6), 2290d522f475Smrg SEG(5*BOX_WIDE/6, 5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 2291d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), /* L */ 2292d522f475Smrg SEG(1*BOX_WIDE/3, CHR_HIGH, CHR_WIDE, CHR_HIGH), 2293d522f475Smrg -1 2294d522f475Smrg }, glyph_vt[] = { 2295d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/12,5*MID_HIGH/6), /* V */ 2296d522f475Smrg SEG(5*BOX_WIDE/12,5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 2297d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 2298d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 2299d522f475Smrg -1 2300d522f475Smrg }, plus_or_minus[] = 2301d522f475Smrg { 2302d522f475Smrg SEG( 0, 5*BOX_HIGH/6, CHR_WIDE, 5*BOX_HIGH/6), 2303d522f475Smrg SEG( MID_WIDE, 2*BOX_HIGH/6, MID_WIDE, 4*BOX_HIGH/6), 2304d522f475Smrg SEG( 0, 3*BOX_HIGH/6, CHR_WIDE, 3*BOX_HIGH/6), 2305d522f475Smrg -1 2306d522f475Smrg }, lower_right_corner[] = 2307d522f475Smrg { 2308d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 2309d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, 0), 2310d522f475Smrg -1 2311d522f475Smrg }, upper_right_corner[] = 2312d522f475Smrg { 2313d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 2314d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2315d522f475Smrg -1 2316d522f475Smrg }, upper_left_corner[] = 2317d522f475Smrg { 2318d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 2319d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2320d522f475Smrg -1 2321d522f475Smrg }, lower_left_corner[] = 2322d522f475Smrg { 2323d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 2324d522f475Smrg SEG( MID_WIDE, MID_WIDE, BOX_WIDE, MID_HIGH), 2325d522f475Smrg -1 2326d522f475Smrg }, cross[] = 2327d522f475Smrg { 2328d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2329d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2330d522f475Smrg -1 2331d522f475Smrg }, scan_line_1[] = 2332d522f475Smrg { 2333d522f475Smrg SEG( 0, 0, BOX_WIDE, 0), 2334d522f475Smrg -1 2335d522f475Smrg }, scan_line_3[] = 2336d522f475Smrg { 2337d522f475Smrg SEG( 0, BOX_HIGH/4, BOX_WIDE, BOX_HIGH/4), 2338d522f475Smrg -1 2339d522f475Smrg }, scan_line_7[] = 2340d522f475Smrg { 2341d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2342d522f475Smrg -1 2343d522f475Smrg }, scan_line_9[] = 2344d522f475Smrg { 2345d522f475Smrg SEG( 0, 3*BOX_HIGH/4, BOX_WIDE, 3*BOX_HIGH/4), 2346d522f475Smrg -1 2347d522f475Smrg }, horizontal_line[] = 2348d522f475Smrg { 2349d522f475Smrg SEG( 0, BOX_HIGH, BOX_WIDE, BOX_HIGH), 2350d522f475Smrg -1 2351d522f475Smrg }, left_tee[] = 2352d522f475Smrg { 2353d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2354d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 2355d522f475Smrg -1 2356d522f475Smrg }, right_tee[] = 2357d522f475Smrg { 2358d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2359d522f475Smrg SEG( MID_WIDE, MID_HIGH, 0, MID_HIGH), 2360d522f475Smrg -1 2361d522f475Smrg }, bottom_tee[] = 2362d522f475Smrg { 2363d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2364d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 2365d522f475Smrg -1 2366d522f475Smrg }, top_tee[] = 2367d522f475Smrg { 2368d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2369d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2370d522f475Smrg -1 2371d522f475Smrg }, vertical_line[] = 2372d522f475Smrg { 2373d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2374d522f475Smrg -1 2375d522f475Smrg }, less_than_or_equal[] = 2376d522f475Smrg { 2377d522f475Smrg SEG( CHR_WIDE, BOX_HIGH/3, 0, MID_HIGH), 2378d522f475Smrg SEG( CHR_WIDE, 2*BOX_HIGH/3, 0, MID_HIGH), 2379d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 2380d522f475Smrg -1 2381d522f475Smrg }, greater_than_or_equal[] = 2382d522f475Smrg { 2383d522f475Smrg SEG( 0, BOX_HIGH/3, CHR_WIDE, MID_HIGH), 2384d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, MID_HIGH), 2385d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 2386d522f475Smrg -1 2387d522f475Smrg }, greek_pi[] = 2388d522f475Smrg { 2389d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 2390d522f475Smrg SEG(5*CHR_WIDE/6, MID_HIGH, 5*CHR_WIDE/6, CHR_HIGH), 2391d522f475Smrg SEG(2*CHR_WIDE/6, MID_HIGH, 2*CHR_WIDE/6, CHR_HIGH), 2392d522f475Smrg -1 2393d522f475Smrg }, not_equal_to[] = 2394d522f475Smrg { 2395d522f475Smrg SEG(2*BOX_WIDE/3, 1*BOX_HIGH/3, 1*BOX_WIDE/3, CHR_HIGH), 2396d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, 2*BOX_HIGH/3), 2397d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 2398d522f475Smrg -1 2399d522f475Smrg }; 2400d522f475Smrg /* *INDENT-ON* */ 2401d522f475Smrg 2402d522f475Smrg static const short *lines[] = 2403d522f475Smrg { 2404d522f475Smrg 0, /* 00 (unused) */ 2405d522f475Smrg 0, /* 01 diamond */ 2406d522f475Smrg 0, /* 02 box */ 2407d522f475Smrg glyph_ht, /* 03 HT */ 2408d522f475Smrg glyph_ff, /* 04 FF */ 2409d522f475Smrg 0, /* 05 CR */ 2410d522f475Smrg glyph_lf, /* 06 LF */ 2411d522f475Smrg 0, /* 07 degrees (small circle) */ 2412d522f475Smrg plus_or_minus, /* 08 */ 2413d522f475Smrg glyph_nl, /* 09 */ 2414d522f475Smrg glyph_vt, /* 0A */ 2415d522f475Smrg lower_right_corner, /* 0B */ 2416d522f475Smrg upper_right_corner, /* 0C */ 2417d522f475Smrg upper_left_corner, /* 0D */ 2418d522f475Smrg lower_left_corner, /* 0E */ 2419d522f475Smrg cross, /* 0F */ 2420d522f475Smrg scan_line_1, /* 10 */ 2421d522f475Smrg scan_line_3, /* 11 */ 2422d522f475Smrg scan_line_7, /* 12 */ 2423d522f475Smrg scan_line_9, /* 13 */ 2424d522f475Smrg horizontal_line, /* 14 */ 2425d522f475Smrg left_tee, /* 15 */ 2426d522f475Smrg right_tee, /* 16 */ 2427d522f475Smrg bottom_tee, /* 17 */ 2428d522f475Smrg top_tee, /* 18 */ 2429d522f475Smrg vertical_line, /* 19 */ 2430d522f475Smrg less_than_or_equal, /* 1A */ 2431d522f475Smrg greater_than_or_equal, /* 1B */ 2432d522f475Smrg greek_pi, /* 1C */ 2433d522f475Smrg not_equal_to, /* 1D */ 2434d522f475Smrg 0, /* 1E LB */ 2435d522f475Smrg 0, /* 1F bullet */ 2436d522f475Smrg }; 2437d522f475Smrg 2438d522f475Smrg GC gc2; 2439d522f475Smrg CgsEnum cgsId = (ch == 2) ? gcDots : gcLine; 2440d522f475Smrg VTwin *cgsWin = WhichVWin(screen); 2441d522f475Smrg const short *p; 2442956cc18dSsnj unsigned font_width = (unsigned) (((flags & DOUBLEWFONT) ? 2 : 1) * screen->fnt_wide); 2443956cc18dSsnj unsigned font_height = (unsigned) (((flags & DOUBLEHFONT) ? 2 : 1) * screen->fnt_high); 2444d522f475Smrg 2445d522f475Smrg if (cells > 1) 2446956cc18dSsnj font_width *= (unsigned) cells; 2447d522f475Smrg 2448d522f475Smrg#if OPT_WIDE_CHARS 2449d522f475Smrg /* 2450d522f475Smrg * Try to show line-drawing characters if we happen to be in UTF-8 2451d522f475Smrg * mode, but have gotten an old-style font. 2452d522f475Smrg */ 2453d522f475Smrg if (screen->utf8_mode 2454d522f475Smrg#if OPT_RENDERFONT 2455d522f475Smrg && !UsingRenderFont(xw) 2456d522f475Smrg#endif 2457d522f475Smrg && (ch > 127) 2458d522f475Smrg && (ch != UCS_REPL)) { 2459d522f475Smrg unsigned n; 2460d522f475Smrg for (n = 1; n < 32; n++) { 2461d522f475Smrg if (dec2ucs(n) == ch 246220d2c4d2Smrg && !((flags & BOLD) 246320d2c4d2Smrg ? IsXtermMissingChar(screen, n, &screen->fnts[fBold]) 246420d2c4d2Smrg : IsXtermMissingChar(screen, n, &screen->fnts[fNorm]))) { 2465d522f475Smrg TRACE(("...use xterm-style linedrawing\n")); 2466d522f475Smrg ch = n; 2467d522f475Smrg break; 2468d522f475Smrg } 2469d522f475Smrg } 2470d522f475Smrg } 2471d522f475Smrg#endif 2472d522f475Smrg 2473d522f475Smrg TRACE(("DRAW_BOX(%d) cell %dx%d at %d,%d%s\n", 2474d522f475Smrg ch, font_height, font_width, y, x, 2475d522f475Smrg (ch >= (sizeof(lines) / sizeof(lines[0])) 2476d522f475Smrg ? "-BAD" 2477d522f475Smrg : ""))); 2478d522f475Smrg 2479d522f475Smrg if (cgsId == gcDots) { 2480d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2481d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2482d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2483d522f475Smrg } else { 2484d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2485d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2486d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2487d522f475Smrg } 2488d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2489d522f475Smrg 2490d522f475Smrg if (!(flags & NOBACKGROUND)) { 24910bd37d32Smrg XFillRectangle(screen->display, VDrawable(screen), gc2, x, y, 2492d522f475Smrg font_width, 2493d522f475Smrg font_height); 2494d522f475Smrg } 2495d522f475Smrg 2496d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2497d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2498d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2499d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2500d522f475Smrg 2501d522f475Smrg XSetLineAttributes(screen->display, gc2, 2502d522f475Smrg (flags & BOLD) 2503d522f475Smrg ? ((font_height > 12) 2504d522f475Smrg ? font_height / 12 2505d522f475Smrg : 1) 2506d522f475Smrg : ((font_height > 16) 2507d522f475Smrg ? font_height / 16 2508d522f475Smrg : 1), 2509d522f475Smrg LineSolid, 2510d522f475Smrg CapProjecting, 2511d522f475Smrg JoinMiter); 2512d522f475Smrg 2513d522f475Smrg if (ch == 1) { /* diamond */ 2514d522f475Smrg XPoint points[5]; 2515d522f475Smrg int npoints = 5, n; 2516d522f475Smrg 2517d522f475Smrg points[0].x = MID_WIDE; 2518d522f475Smrg points[0].y = BOX_HIGH / 4; 2519d522f475Smrg 2520d522f475Smrg points[1].x = 8 * BOX_WIDE / 8; 2521d522f475Smrg points[1].y = MID_HIGH; 2522d522f475Smrg 2523d522f475Smrg points[2].x = points[0].x; 2524d522f475Smrg points[2].y = 3 * BOX_HIGH / 4; 2525d522f475Smrg 2526d522f475Smrg points[3].x = 0 * BOX_WIDE / 8; 2527d522f475Smrg points[3].y = points[1].y; 2528d522f475Smrg 2529d522f475Smrg points[4].x = points[0].x; 2530d522f475Smrg points[4].y = points[0].y; 2531d522f475Smrg 2532d522f475Smrg for (n = 0; n < npoints; ++n) { 2533e39b573cSmrg points[n].x = (short) SCALED_X(points[n].x); 2534e39b573cSmrg points[n].y = (short) SCALED_Y(points[n].y); 2535e39b573cSmrg points[n].x = (short) (points[n].x + x); 2536e39b573cSmrg points[n].y = (short) (points[n].y + y); 2537d522f475Smrg } 2538d522f475Smrg 2539d522f475Smrg XFillPolygon(screen->display, 25400bd37d32Smrg VDrawable(screen), gc2, 2541d522f475Smrg points, npoints, 2542d522f475Smrg Convex, CoordModeOrigin); 2543d522f475Smrg } else if (ch == 7) { /* degrees */ 2544d522f475Smrg unsigned width = (BOX_WIDE / 3); 2545956cc18dSsnj int x_coord = MID_WIDE - (int) (width / 2); 2546956cc18dSsnj int y_coord = MID_HIGH - (int) width; 2547d522f475Smrg 2548d522f475Smrg SCALE_X(x_coord); 2549d522f475Smrg SCALE_Y(y_coord); 2550e39b573cSmrg width = (unsigned) SCALED_X(width); 2551d522f475Smrg 2552d522f475Smrg XDrawArc(screen->display, 25530bd37d32Smrg VDrawable(screen), gc2, 2554d522f475Smrg x + x_coord, y + y_coord, width, width, 2555d522f475Smrg 0, 2556d522f475Smrg 360 * 64); 2557d522f475Smrg } else if (ch == 0x1f) { /* bullet */ 2558d522f475Smrg unsigned width = 7 * BOX_WIDE / 10; 2559956cc18dSsnj int x_coord = MID_WIDE - (int) (width / 3); 2560956cc18dSsnj int y_coord = MID_HIGH - (int) (width / 3); 2561d522f475Smrg 2562d522f475Smrg SCALE_X(x_coord); 2563d522f475Smrg SCALE_Y(y_coord); 2564e39b573cSmrg width = (unsigned) SCALED_X(width); 2565d522f475Smrg 2566d522f475Smrg XDrawArc(screen->display, 25670bd37d32Smrg VDrawable(screen), gc2, 2568d522f475Smrg x + x_coord, y + y_coord, width, width, 2569d522f475Smrg 0, 2570d522f475Smrg 360 * 64); 2571d522f475Smrg } else if (ch < (sizeof(lines) / sizeof(lines[0])) 2572d522f475Smrg && (p = lines[ch]) != 0) { 2573956cc18dSsnj int coord[4]; 2574d522f475Smrg int n = 0; 2575d522f475Smrg while (*p >= 0) { 2576d522f475Smrg coord[n++] = *p++; 2577d522f475Smrg if (n == 4) { 2578d522f475Smrg SCALE_X(coord[0]); 2579d522f475Smrg SCALE_Y(coord[1]); 2580d522f475Smrg SCALE_X(coord[2]); 2581d522f475Smrg SCALE_Y(coord[3]); 2582d522f475Smrg XDrawLine(screen->display, 25830bd37d32Smrg VDrawable(screen), gc2, 2584d522f475Smrg x + coord[0], y + coord[1], 2585d522f475Smrg x + coord[2], y + coord[3]); 2586d522f475Smrg n = 0; 2587d522f475Smrg } 2588d522f475Smrg } 2589d522f475Smrg } else if (screen->force_all_chars) { 2590d522f475Smrg /* bounding rectangle, for debugging */ 25910bd37d32Smrg XDrawRectangle(screen->display, VDrawable(screen), gc2, x, y, 2592d522f475Smrg font_width - 1, 2593d522f475Smrg font_height - 1); 2594d522f475Smrg } 2595d522f475Smrg} 2596d522f475Smrg 2597d522f475Smrg#if OPT_RENDERFONT 2598d522f475Smrg 2599d522f475Smrg/* 2600d522f475Smrg * Check if the given character has a glyph known to Xft. 2601d522f475Smrg * 2602d522f475Smrg * see xc/lib/Xft/xftglyphs.c 2603d522f475Smrg */ 2604d522f475SmrgBool 2605d522f475SmrgxtermXftMissing(XtermWidget xw, XftFont * font, unsigned wc) 2606d522f475Smrg{ 2607d522f475Smrg Bool result = False; 2608d522f475Smrg 2609d522f475Smrg if (font != 0) { 2610956cc18dSsnj TScreen *screen = TScreenOf(xw); 2611956cc18dSsnj if (!XftGlyphExists(screen->display, font, wc)) { 2612d522f475Smrg#if OPT_WIDE_CHARS 2613d522f475Smrg TRACE(("xtermXftMissing %d (dec=%#x, ucs=%#x)\n", 2614d522f475Smrg wc, ucs2dec(wc), dec2ucs(wc))); 2615d522f475Smrg#else 2616d522f475Smrg TRACE(("xtermXftMissing %d\n", wc)); 2617d522f475Smrg#endif 2618d522f475Smrg result = True; 2619d522f475Smrg } 2620d522f475Smrg } 2621d522f475Smrg return result; 2622d522f475Smrg} 2623d522f475Smrg#endif /* OPT_RENDERFONT && OPT_WIDE_CHARS */ 2624d522f475Smrg 2625d522f475Smrg#endif /* OPT_BOX_CHARS */ 2626d522f475Smrg 2627d522f475Smrg#if OPT_WIDE_CHARS 2628d522f475Smrg#define MY_UCS(ucs,dec) case ucs: result = dec; break 2629d522f475Smrgunsigned 2630d522f475Smrgucs2dec(unsigned ch) 2631d522f475Smrg{ 2632d522f475Smrg unsigned result = ch; 2633d522f475Smrg if ((ch > 127) 2634d522f475Smrg && (ch != UCS_REPL)) { 2635d522f475Smrg switch (ch) { 2636d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 2637d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 2638d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 2639d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 2640d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 2641d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 2642d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 2643d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 2644d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 2645d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 2646d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 2647d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 2648d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 2649d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 2650d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 2651d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 2652d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 2653d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 2654d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 2655d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 2656d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 2657d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 2658d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 2659d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 2660d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 2661d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 2662d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 2663d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 2664d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 2665d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 2666d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 2667d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 2668d522f475Smrg } 2669d522f475Smrg } 2670d522f475Smrg return result; 2671d522f475Smrg} 2672d522f475Smrg 2673d522f475Smrg#undef MY_UCS 2674d522f475Smrg#define MY_UCS(ucs,dec) case dec: result = ucs; break 2675d522f475Smrg 2676d522f475Smrgunsigned 2677d522f475Smrgdec2ucs(unsigned ch) 2678d522f475Smrg{ 2679d522f475Smrg unsigned result = ch; 2680d522f475Smrg if (xtermIsDecGraphic(ch)) { 2681d522f475Smrg switch (ch) { 2682d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 2683d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 2684d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 2685d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 2686d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 2687d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 2688d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 2689d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 2690d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 2691d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 2692d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 2693d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 2694d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 2695d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 2696d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 2697d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 2698d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 2699d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 2700d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 2701d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 2702d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 2703d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 2704d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 2705d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 2706d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 2707d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 2708d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 2709d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 2710d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 2711d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 2712d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 2713d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 2714d522f475Smrg } 2715d522f475Smrg } 2716d522f475Smrg return result; 2717d522f475Smrg} 2718d522f475Smrg 2719d522f475Smrg#endif /* OPT_WIDE_CHARS */ 2720d522f475Smrg 2721d522f475Smrg#if OPT_SHIFT_FONTS 27220bd37d32Smrgstatic int 2723d522f475SmrglookupOneFontSize(XtermWidget xw, int fontnum) 2724d522f475Smrg{ 2725d522f475Smrg TScreen *screen = TScreenOf(xw); 2726d522f475Smrg 2727d522f475Smrg if (screen->menu_font_sizes[fontnum] == 0) { 2728d522f475Smrg XTermFonts fnt; 2729d522f475Smrg 2730d522f475Smrg memset(&fnt, 0, sizeof(fnt)); 2731d522f475Smrg screen->menu_font_sizes[fontnum] = -1; 27320bd37d32Smrg if (xtermOpenFont(xw, 27330bd37d32Smrg screen->MenuFontName(fontnum), 27340bd37d32Smrg &fnt, 27350bd37d32Smrg ((fontnum <= fontMenu_lastBuiltin) 27360bd37d32Smrg ? fwAlways 27370bd37d32Smrg : fwResource), 27380bd37d32Smrg True)) { 273920d2c4d2Smrg if (fontnum <= fontMenu_lastBuiltin 27400bd37d32Smrg || strcmp(fnt.fn, DEFFONT)) { 274120d2c4d2Smrg screen->menu_font_sizes[fontnum] = FontSize(fnt.fs); 27420bd37d32Smrg if (screen->menu_font_sizes[fontnum] <= 0) 27430bd37d32Smrg screen->menu_font_sizes[fontnum] = -1; 27440bd37d32Smrg } 2745d522f475Smrg xtermCloseFont(xw, &fnt); 2746d522f475Smrg } 2747d522f475Smrg } 27480bd37d32Smrg return (screen->menu_font_sizes[fontnum] > 0); 2749d522f475Smrg} 2750d522f475Smrg 2751d522f475Smrg/* 2752d522f475Smrg * Cache the font-sizes so subsequent larger/smaller font actions will go fast. 2753d522f475Smrg */ 2754d522f475Smrgstatic void 2755d522f475SmrglookupFontSizes(XtermWidget xw) 2756d522f475Smrg{ 2757d522f475Smrg int n; 2758d522f475Smrg 2759d522f475Smrg for (n = 0; n < NMENUFONTS; n++) { 27600bd37d32Smrg (void) lookupOneFontSize(xw, n); 2761d522f475Smrg } 2762d522f475Smrg} 2763d522f475Smrg 27642eaa94a1Schristos#if OPT_RENDERFONT 27650bd37d32Smrgstatic void 27660bd37d32SmrgfillInFaceSize(XtermWidget xw, int fontnum) 27670bd37d32Smrg{ 27680bd37d32Smrg TScreen *screen = TScreenOf(xw); 27690bd37d32Smrg float value; 27700bd37d32Smrg double face_size = xw->misc.face_size[fontnum]; 27710bd37d32Smrg 27720bd37d32Smrg if (face_size <= 0.0) { 27730bd37d32Smrg#if OPT_SHIFT_FONTS 27740bd37d32Smrg /* 27750bd37d32Smrg * If the user is switching font-sizes, make it follow by 27760bd37d32Smrg * default the same ratios to the default as the fixed fonts 27770bd37d32Smrg * would, for easy comparison. There will be some differences 27780bd37d32Smrg * since the fixed fonts have a variety of height/width ratios, 27790bd37d32Smrg * but this is simpler than adding another resource value - and 27800bd37d32Smrg * as noted above, the data for the fixed fonts are available. 27810bd37d32Smrg */ 27820bd37d32Smrg (void) lookupOneFontSize(xw, 0); 27830bd37d32Smrg if (fontnum == fontMenu_default) { 27840bd37d32Smrg sscanf(DEFFACESIZE, "%f", &value); 27850bd37d32Smrg face_size = value; 27860bd37d32Smrg } else if (lookupOneFontSize(xw, fontnum) 27870bd37d32Smrg && (screen->menu_font_sizes[0] 27880bd37d32Smrg != screen->menu_font_sizes[fontnum])) { 27890bd37d32Smrg double ratio; 27900bd37d32Smrg long num = screen->menu_font_sizes[fontnum]; 27910bd37d32Smrg long den = screen->menu_font_sizes[0]; 27920bd37d32Smrg 27930bd37d32Smrg if (den <= 0) 27940bd37d32Smrg den = 1; 27950bd37d32Smrg ratio = dimSquareRoot((double) num / (double) den); 27960bd37d32Smrg 27970bd37d32Smrg face_size = (ratio * xw->misc.face_size[0]); 27980bd37d32Smrg TRACE(("scaled[%d] using %3ld/%ld = %.2f -> %f\n", 27990bd37d32Smrg fontnum, num, den, ratio, face_size)); 28000bd37d32Smrg } else 28010bd37d32Smrg#endif 28020bd37d32Smrg { 28030bd37d32Smrg#define LikeBitmap(s) (((s) / 78.0) * xw->misc.face_size[fontMenu_default]) 28040bd37d32Smrg switch (fontnum) { 28050bd37d32Smrg case fontMenu_font1: 28060bd37d32Smrg face_size = LikeBitmap(2.0); 28070bd37d32Smrg break; 28080bd37d32Smrg case fontMenu_font2: 28090bd37d32Smrg face_size = LikeBitmap(35.0); 28100bd37d32Smrg break; 28110bd37d32Smrg case fontMenu_font3: 28120bd37d32Smrg face_size = LikeBitmap(60.0); 28130bd37d32Smrg break; 28140bd37d32Smrg default: 28150bd37d32Smrg sscanf(DEFFACESIZE, "%f", &value); 28160bd37d32Smrg face_size = value; 28170bd37d32Smrg break; 28180bd37d32Smrg case fontMenu_font4: 28190bd37d32Smrg face_size = LikeBitmap(90.0); 28200bd37d32Smrg break; 28210bd37d32Smrg case fontMenu_font5: 28220bd37d32Smrg face_size = LikeBitmap(135.0); 28230bd37d32Smrg break; 28240bd37d32Smrg case fontMenu_font6: 28250bd37d32Smrg face_size = LikeBitmap(200.0); 28260bd37d32Smrg break; 28270bd37d32Smrg } 28280bd37d32Smrg TRACE(("builtin[%d] -> %f\n", fontnum, face_size)); 28290bd37d32Smrg } 28300bd37d32Smrg xw->misc.face_size[fontnum] = (float) face_size; 28310bd37d32Smrg } 28320bd37d32Smrg} 28330bd37d32Smrg 28340bd37d32Smrg/* no selection or escape */ 28350bd37d32Smrg#define NMENU_RENDERFONTS (fontMenu_lastBuiltin + 1) 28360bd37d32Smrg 28370bd37d32Smrg/* 28380bd37d32Smrg * Workaround for breakage in font-packages - check if all of the bitmap font 28390bd37d32Smrg * sizes are the same, and if we're using TrueType fonts. 28400bd37d32Smrg */ 28412eaa94a1Schristosstatic Boolean 28422eaa94a1SchristosuseFaceSizes(XtermWidget xw) 28432eaa94a1Schristos{ 28442eaa94a1Schristos Boolean result = False; 28452eaa94a1Schristos int n; 28462eaa94a1Schristos 28470bd37d32Smrg TRACE(("useFaceSizes {{\n")); 28482eaa94a1Schristos if (UsingRenderFont(xw)) { 28490bd37d32Smrg Boolean nonzero = True; 28500bd37d32Smrg 28512eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 28522eaa94a1Schristos if (xw->misc.face_size[n] <= 0.0) { 28530bd37d32Smrg nonzero = False; 28542eaa94a1Schristos break; 28552eaa94a1Schristos } 28562eaa94a1Schristos } 28570bd37d32Smrg if (!nonzero) { 2858956cc18dSsnj Boolean broken_fonts = True; 2859956cc18dSsnj TScreen *screen = TScreenOf(xw); 28600bd37d32Smrg long first; 2861956cc18dSsnj 2862956cc18dSsnj lookupFontSizes(xw); 28630bd37d32Smrg first = screen->menu_font_sizes[0]; 2864956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 2865956cc18dSsnj if (screen->menu_font_sizes[n] > 0 2866956cc18dSsnj && screen->menu_font_sizes[n] != first) { 2867956cc18dSsnj broken_fonts = False; 2868956cc18dSsnj break; 2869956cc18dSsnj } 2870956cc18dSsnj } 2871956cc18dSsnj 2872956cc18dSsnj if (broken_fonts) { 2873956cc18dSsnj 2874956cc18dSsnj TRACE(("bitmap fonts are broken - set faceSize resources\n")); 2875956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 28760bd37d32Smrg fillInFaceSize(xw, n); 2877956cc18dSsnj } 2878956cc18dSsnj 2879956cc18dSsnj } 2880956cc18dSsnj } 28810bd37d32Smrg result = True; 28822eaa94a1Schristos } 28830bd37d32Smrg TRACE(("...}}useFaceSizes %d\n", result)); 28842eaa94a1Schristos return result; 28852eaa94a1Schristos} 28860bd37d32Smrg#endif /* OPT_RENDERFONT */ 28872eaa94a1Schristos 2888d522f475Smrg/* 2889d522f475Smrg * Find the index of a larger/smaller font (according to the sign of 'relative' 2890d522f475Smrg * and its magnitude), starting from the 'old' index. 2891d522f475Smrg */ 2892d522f475Smrgint 2893d522f475SmrglookupRelativeFontSize(XtermWidget xw, int old, int relative) 2894d522f475Smrg{ 2895d522f475Smrg TScreen *screen = TScreenOf(xw); 2896d522f475Smrg int n, m = -1; 2897d522f475Smrg 28982eaa94a1Schristos TRACE(("lookupRelativeFontSize(old=%d, relative=%d)\n", old, relative)); 2899d522f475Smrg if (!IsIcon(screen)) { 29002eaa94a1Schristos#if OPT_RENDERFONT 29012eaa94a1Schristos if (useFaceSizes(xw)) { 29022eaa94a1Schristos TRACE(("...using FaceSize\n")); 29032eaa94a1Schristos if (relative != 0) { 29042eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 29050bd37d32Smrg fillInFaceSize(xw, n); 29062eaa94a1Schristos if (xw->misc.face_size[n] > 0 && 29072eaa94a1Schristos xw->misc.face_size[n] != xw->misc.face_size[old]) { 29082eaa94a1Schristos int cmp_0 = ((xw->misc.face_size[n] > 29092eaa94a1Schristos xw->misc.face_size[old]) 29102eaa94a1Schristos ? relative 29112eaa94a1Schristos : -relative); 29122eaa94a1Schristos int cmp_m = ((m < 0) 29132eaa94a1Schristos ? 1 29142eaa94a1Schristos : ((xw->misc.face_size[n] < 29152eaa94a1Schristos xw->misc.face_size[m]) 29162eaa94a1Schristos ? relative 29172eaa94a1Schristos : -relative)); 29182eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 29192eaa94a1Schristos m = n; 29202eaa94a1Schristos } 2921d522f475Smrg } 2922d522f475Smrg } 2923d522f475Smrg } 29242eaa94a1Schristos } else 29252eaa94a1Schristos#endif 29262eaa94a1Schristos { 29272eaa94a1Schristos TRACE(("...using bitmap areas\n")); 29282eaa94a1Schristos lookupFontSizes(xw); 29292eaa94a1Schristos if (relative != 0) { 29302eaa94a1Schristos for (n = 0; n < NMENUFONTS; ++n) { 29312eaa94a1Schristos if (screen->menu_font_sizes[n] > 0 && 29322eaa94a1Schristos screen->menu_font_sizes[n] != 29332eaa94a1Schristos screen->menu_font_sizes[old]) { 29342eaa94a1Schristos int cmp_0 = ((screen->menu_font_sizes[n] > 29352eaa94a1Schristos screen->menu_font_sizes[old]) 29362eaa94a1Schristos ? relative 29372eaa94a1Schristos : -relative); 29382eaa94a1Schristos int cmp_m = ((m < 0) 29392eaa94a1Schristos ? 1 29402eaa94a1Schristos : ((screen->menu_font_sizes[n] < 29412eaa94a1Schristos screen->menu_font_sizes[m]) 29422eaa94a1Schristos ? relative 29432eaa94a1Schristos : -relative)); 29442eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 29452eaa94a1Schristos m = n; 29462eaa94a1Schristos } 29472eaa94a1Schristos } 29482eaa94a1Schristos } 2949d522f475Smrg } 2950d522f475Smrg } 29512eaa94a1Schristos TRACE(("...new index %d\n", m)); 29522eaa94a1Schristos if (m >= 0) { 29532eaa94a1Schristos if (relative > 1) 29542eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative - 1); 29552eaa94a1Schristos else if (relative < -1) 29562eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative + 1); 29572eaa94a1Schristos } 2958d522f475Smrg } 2959d522f475Smrg return m; 2960d522f475Smrg} 2961d522f475Smrg 2962d522f475Smrg/* ARGSUSED */ 2963d522f475Smrgvoid 2964d522f475SmrgHandleLargerFont(Widget w GCC_UNUSED, 2965d522f475Smrg XEvent * event GCC_UNUSED, 2966d522f475Smrg String * params GCC_UNUSED, 2967d522f475Smrg Cardinal *param_count GCC_UNUSED) 2968d522f475Smrg{ 2969956cc18dSsnj XtermWidget xw; 2970d522f475Smrg 297120d2c4d2Smrg TRACE(("Handle larger-vt-font for %p\n", (void *) w)); 2972956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 2973d522f475Smrg if (xw->misc.shift_fonts) { 2974956cc18dSsnj TScreen *screen = TScreenOf(xw); 2975d522f475Smrg int m; 2976d522f475Smrg 2977d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, 1); 2978d522f475Smrg if (m >= 0) { 2979d522f475Smrg SetVTFont(xw, m, True, NULL); 2980d522f475Smrg } else { 298120d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 2982d522f475Smrg } 2983d522f475Smrg } 2984d522f475Smrg } 2985d522f475Smrg} 2986d522f475Smrg 2987d522f475Smrg/* ARGSUSED */ 2988d522f475Smrgvoid 2989d522f475SmrgHandleSmallerFont(Widget w GCC_UNUSED, 2990d522f475Smrg XEvent * event GCC_UNUSED, 2991d522f475Smrg String * params GCC_UNUSED, 2992d522f475Smrg Cardinal *param_count GCC_UNUSED) 2993d522f475Smrg{ 2994956cc18dSsnj XtermWidget xw; 2995d522f475Smrg 299620d2c4d2Smrg TRACE(("Handle smaller-vt-font for %p\n", (void *) w)); 2997956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 2998d522f475Smrg if (xw->misc.shift_fonts) { 2999956cc18dSsnj TScreen *screen = TScreenOf(xw); 3000d522f475Smrg int m; 3001d522f475Smrg 3002d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, -1); 3003d522f475Smrg if (m >= 0) { 3004d522f475Smrg SetVTFont(xw, m, True, NULL); 3005d522f475Smrg } else { 300620d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3007d522f475Smrg } 3008d522f475Smrg } 3009d522f475Smrg } 3010d522f475Smrg} 3011d522f475Smrg#endif 3012d522f475Smrg 3013d522f475Smrgint 3014d522f475SmrgxtermGetFont(const char *param) 3015d522f475Smrg{ 3016d522f475Smrg int fontnum; 3017d522f475Smrg 3018d522f475Smrg switch (param[0]) { 3019d522f475Smrg case 'd': 3020d522f475Smrg case 'D': 3021d522f475Smrg case '0': 3022d522f475Smrg fontnum = fontMenu_default; 3023d522f475Smrg break; 3024d522f475Smrg case '1': 3025d522f475Smrg fontnum = fontMenu_font1; 3026d522f475Smrg break; 3027d522f475Smrg case '2': 3028d522f475Smrg fontnum = fontMenu_font2; 3029d522f475Smrg break; 3030d522f475Smrg case '3': 3031d522f475Smrg fontnum = fontMenu_font3; 3032d522f475Smrg break; 3033d522f475Smrg case '4': 3034d522f475Smrg fontnum = fontMenu_font4; 3035d522f475Smrg break; 3036d522f475Smrg case '5': 3037d522f475Smrg fontnum = fontMenu_font5; 3038d522f475Smrg break; 3039d522f475Smrg case '6': 3040d522f475Smrg fontnum = fontMenu_font6; 3041d522f475Smrg break; 3042d522f475Smrg case 'e': 3043d522f475Smrg case 'E': 3044d522f475Smrg fontnum = fontMenu_fontescape; 3045d522f475Smrg break; 3046d522f475Smrg case 's': 3047d522f475Smrg case 'S': 3048d522f475Smrg fontnum = fontMenu_fontsel; 3049d522f475Smrg break; 3050d522f475Smrg default: 3051d522f475Smrg fontnum = -1; 3052d522f475Smrg break; 3053d522f475Smrg } 3054d522f475Smrg return fontnum; 3055d522f475Smrg} 3056d522f475Smrg 3057d522f475Smrg/* ARGSUSED */ 3058d522f475Smrgvoid 3059d522f475SmrgHandleSetFont(Widget w GCC_UNUSED, 3060d522f475Smrg XEvent * event GCC_UNUSED, 3061d522f475Smrg String * params, 3062d522f475Smrg Cardinal *param_count) 3063d522f475Smrg{ 3064956cc18dSsnj XtermWidget xw; 3065956cc18dSsnj 3066956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 3067d522f475Smrg int fontnum; 3068d522f475Smrg VTFontNames fonts; 3069d522f475Smrg 3070d522f475Smrg memset(&fonts, 0, sizeof(fonts)); 3071d522f475Smrg 3072d522f475Smrg if (*param_count == 0) { 3073d522f475Smrg fontnum = fontMenu_default; 3074d522f475Smrg } else { 3075d522f475Smrg Cardinal maxparams = 1; /* total number of params allowed */ 3076d522f475Smrg int result = xtermGetFont(params[0]); 3077d522f475Smrg 3078d522f475Smrg switch (result) { 3079d522f475Smrg case fontMenu_default: /* FALLTHRU */ 3080d522f475Smrg case fontMenu_font1: /* FALLTHRU */ 3081d522f475Smrg case fontMenu_font2: /* FALLTHRU */ 3082d522f475Smrg case fontMenu_font3: /* FALLTHRU */ 3083d522f475Smrg case fontMenu_font4: /* FALLTHRU */ 3084d522f475Smrg case fontMenu_font5: /* FALLTHRU */ 3085d522f475Smrg case fontMenu_font6: /* FALLTHRU */ 3086d522f475Smrg break; 3087d522f475Smrg case fontMenu_fontescape: 3088d522f475Smrg#if OPT_WIDE_CHARS 3089d522f475Smrg maxparams = 5; 3090d522f475Smrg#else 3091d522f475Smrg maxparams = 3; 3092d522f475Smrg#endif 3093d522f475Smrg break; 3094d522f475Smrg case fontMenu_fontsel: 3095d522f475Smrg maxparams = 2; 3096d522f475Smrg break; 3097d522f475Smrg default: 309820d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3099d522f475Smrg return; 3100d522f475Smrg } 3101d522f475Smrg fontnum = result; 3102d522f475Smrg 3103d522f475Smrg if (*param_count > maxparams) { /* see if extra args given */ 310420d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3105d522f475Smrg return; 3106d522f475Smrg } 3107d522f475Smrg switch (*param_count) { /* assign 'em */ 3108d522f475Smrg#if OPT_WIDE_CHARS 3109d522f475Smrg case 5: 3110d522f475Smrg fonts.f_wb = params[4]; 3111d522f475Smrg /* FALLTHRU */ 3112d522f475Smrg case 4: 3113d522f475Smrg fonts.f_w = params[3]; 3114d522f475Smrg /* FALLTHRU */ 3115d522f475Smrg#endif 3116d522f475Smrg case 3: 3117d522f475Smrg fonts.f_b = params[2]; 3118d522f475Smrg /* FALLTHRU */ 3119d522f475Smrg case 2: 3120d522f475Smrg fonts.f_n = params[1]; 3121d522f475Smrg break; 3122d522f475Smrg } 3123d522f475Smrg } 3124d522f475Smrg 3125956cc18dSsnj SetVTFont(xw, fontnum, True, &fonts); 3126d522f475Smrg } 3127d522f475Smrg} 3128d522f475Smrg 3129d522f475Smrgvoid 3130d522f475SmrgSetVTFont(XtermWidget xw, 3131d522f475Smrg int which, 3132d522f475Smrg Bool doresize, 3133d522f475Smrg const VTFontNames * fonts) 3134d522f475Smrg{ 3135956cc18dSsnj TScreen *screen = TScreenOf(xw); 3136d522f475Smrg 3137d522f475Smrg TRACE(("SetVTFont(which=%d, f_n=%s, f_b=%s)\n", which, 3138d522f475Smrg (fonts && fonts->f_n) ? fonts->f_n : "<null>", 3139d522f475Smrg (fonts && fonts->f_b) ? fonts->f_b : "<null>")); 3140d522f475Smrg 3141d522f475Smrg if (IsIcon(screen)) { 314220d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3143d522f475Smrg } else if (which >= 0 && which < NMENUFONTS) { 3144d522f475Smrg VTFontNames myfonts; 3145d522f475Smrg 3146d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 3147d522f475Smrg if (fonts != 0) 3148d522f475Smrg myfonts = *fonts; 3149d522f475Smrg 3150d522f475Smrg if (which == fontMenu_fontsel) { /* go get the selection */ 3151d522f475Smrg FindFontSelection(xw, myfonts.f_n, False); 3152d522f475Smrg } else { 3153d522f475Smrg int oldFont = screen->menu_font_number; 3154d522f475Smrg 3155d522f475Smrg#define USE_CACHED(field, name) \ 3156d522f475Smrg if (myfonts.field == 0) { \ 3157492d43a5Smrg myfonts.field = x_strdup(screen->menu_font_names[which][name]); \ 3158d522f475Smrg TRACE(("set myfonts." #field " from menu_font_names[%d][" #name "] %s\n", \ 3159d522f475Smrg which, NonNull(myfonts.field))); \ 3160d522f475Smrg } else { \ 3161d522f475Smrg TRACE(("set myfonts." #field " reused\n")); \ 3162d522f475Smrg } 316320d2c4d2Smrg#define SAVE_FNAME(field, name) \ 316420d2c4d2Smrg if (myfonts.field != 0) { \ 316520d2c4d2Smrg if (screen->menu_font_names[which][name] == 0 \ 316620d2c4d2Smrg || strcmp(screen->menu_font_names[which][name], myfonts.field)) { \ 316720d2c4d2Smrg TRACE(("updating menu_font_names[%d][" #name "] to %s\n", \ 316820d2c4d2Smrg which, myfonts.field)); \ 316920d2c4d2Smrg screen->menu_font_names[which][name] = x_strdup(myfonts.field); \ 317020d2c4d2Smrg } \ 317120d2c4d2Smrg } 317220d2c4d2Smrg 3173d522f475Smrg USE_CACHED(f_n, fNorm); 3174d522f475Smrg USE_CACHED(f_b, fBold); 3175d522f475Smrg#if OPT_WIDE_CHARS 3176d522f475Smrg USE_CACHED(f_w, fWide); 3177d522f475Smrg USE_CACHED(f_wb, fWBold); 3178d522f475Smrg#endif 3179d522f475Smrg if (xtermLoadFont(xw, 3180d522f475Smrg &myfonts, 3181d522f475Smrg doresize, which)) { 318220d2c4d2Smrg /* 318320d2c4d2Smrg * If successful, save the data so that a subsequent query via 318420d2c4d2Smrg * OSC-50 will return the expected values. 318520d2c4d2Smrg */ 318620d2c4d2Smrg SAVE_FNAME(f_n, fNorm); 318720d2c4d2Smrg SAVE_FNAME(f_b, fBold); 318820d2c4d2Smrg#if OPT_WIDE_CHARS 318920d2c4d2Smrg SAVE_FNAME(f_w, fWide); 319020d2c4d2Smrg SAVE_FNAME(f_wb, fWBold); 319120d2c4d2Smrg#endif 3192d522f475Smrg } else { 3193d522f475Smrg xtermLoadFont(xw, 3194d522f475Smrg xtermFontName(screen->MenuFontName(oldFont)), 3195d522f475Smrg doresize, oldFont); 319620d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3197d522f475Smrg } 3198d522f475Smrg } 319920d2c4d2Smrg } else { 320020d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3201d522f475Smrg } 3202d522f475Smrg return; 3203d522f475Smrg} 3204