fontutils.c revision 94644356
194644356Smrg/* $XTermId: fontutils.c,v 1.448 2015/03/02 13:19:36 tom Exp $ */ 2d522f475Smrg 30bd37d32Smrg/* 494644356Smrg * Copyright 1998-2014,2015 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 62fa3f02f3Smrg#define CI_GET_CHAR_INFO_1D(fs,col,cs) \ 63d522f475Smrg{ \ 64fa3f02f3Smrg cs = 0; \ 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 } \ 71fa3f02f3Smrg if (CI_NONEXISTCHAR(cs)) cs = 0; \ 72d522f475Smrg } \ 73d522f475Smrg} 74d522f475Smrg 75fa3f02f3Smrg#define CI_GET_CHAR_INFO_2D(fs,row,col,cs) \ 76d522f475Smrg{ \ 77fa3f02f3Smrg cs = 0; \ 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 } \ 88fa3f02f3Smrg if (CI_NONEXISTCHAR(cs)) cs = 0; \ 89d522f475Smrg } \ 90d522f475Smrg} 91d522f475Smrg 929a64e1c5Smrg#define FREE_FNAME(field) \ 939a64e1c5Smrg if (fonts == 0 || myfonts.field != fonts->field) { \ 949a64e1c5Smrg FREE_STRING(myfonts.field); \ 959a64e1c5Smrg myfonts.field = 0; \ 969a64e1c5Smrg } 979a64e1c5Smrg 98d522f475Smrg/* 99d522f475Smrg * A structure to hold the relevant properties from a font 100d522f475Smrg * we need to make a well formed font name for it. 101d522f475Smrg */ 102d522f475Smrgtypedef struct { 103d522f475Smrg /* registry, foundry, family */ 1049a64e1c5Smrg const char *beginning; 105d522f475Smrg /* weight */ 1069a64e1c5Smrg const char *weight; 107d522f475Smrg /* slant */ 1089a64e1c5Smrg const char *slant; 109d522f475Smrg /* wideness */ 1109a64e1c5Smrg const char *wideness; 111d522f475Smrg /* add style */ 1129a64e1c5Smrg const char *add_style; 113d522f475Smrg int pixel_size; 1149a64e1c5Smrg const char *point_size; 115d522f475Smrg int res_x; 116d522f475Smrg int res_y; 1179a64e1c5Smrg const char *spacing; 118d522f475Smrg int average_width; 119d522f475Smrg /* charset registry, charset encoding */ 120d522f475Smrg char *end; 121d522f475Smrg} FontNameProperties; 122d522f475Smrg 1230bd37d32Smrg#if OPT_RENDERFONT 1240bd37d32Smrgstatic void fillInFaceSize(XtermWidget, int); 1250bd37d32Smrg#endif 1260bd37d32Smrg 127d522f475Smrg#if OPT_SHIFT_FONTS 1280bd37d32Smrgstatic int lookupOneFontSize(XtermWidget, int); 129d522f475Smrg#endif 130d522f475Smrg 131fa3f02f3Smrg#if OPT_REPORT_FONTS || OPT_WIDE_CHARS 1322eaa94a1Schristosstatic unsigned 1339a64e1c5SmrgcountGlyphs(XFontStruct *fp) 134d522f475Smrg{ 135d522f475Smrg unsigned count = 0; 136d522f475Smrg 137d522f475Smrg if (fp != 0) { 138d522f475Smrg if (fp->min_byte1 == 0 && fp->max_byte1 == 0) { 139fa3f02f3Smrg count = fp->max_char_or_byte2 - fp->min_char_or_byte2 + 1; 140d522f475Smrg } else if (fp->min_char_or_byte2 < 256 141d522f475Smrg && fp->max_char_or_byte2 < 256) { 142d522f475Smrg unsigned first = (fp->min_byte1 << 8) + fp->min_char_or_byte2; 143d522f475Smrg unsigned last = (fp->max_byte1 << 8) + fp->max_char_or_byte2; 144d522f475Smrg count = last + 1 - first; 145d522f475Smrg } 146d522f475Smrg } 147d522f475Smrg return count; 148d522f475Smrg} 149fa3f02f3Smrg#endif 150d522f475Smrg 151fa3f02f3Smrg#if OPT_WIDE_CHARS 152d522f475Smrg/* 153d522f475Smrg * Verify that the wide-bold font is at least a bold font with roughly as many 154d522f475Smrg * glyphs as the wide font. The counts should be the same, but settle for 155d522f475Smrg * filtering out the worst of the font mismatches. 156d522f475Smrg */ 157d522f475Smrgstatic Bool 1589a64e1c5SmrgcompatibleWideCounts(XFontStruct *wfs, XFontStruct *wbfs) 159d522f475Smrg{ 160d522f475Smrg unsigned count_w = countGlyphs(wfs); 161d522f475Smrg unsigned count_wb = countGlyphs(wbfs); 162d522f475Smrg if (count_w <= 256 || 163d522f475Smrg count_wb <= 256 || 164d522f475Smrg ((count_w / 4) * 3) > count_wb) { 165d522f475Smrg TRACE(("...font server lied (count wide %u vs wide-bold %u)\n", 166d522f475Smrg count_w, count_wb)); 167d522f475Smrg return False; 168d522f475Smrg } 169d522f475Smrg return True; 170d522f475Smrg} 171d522f475Smrg#endif /* OPT_WIDE_CHARS */ 172d522f475Smrg 17320d2c4d2Smrg#if OPT_BOX_CHARS 17420d2c4d2Smrgstatic void 17520d2c4d2SmrgsetupPackedFonts(XtermWidget xw) 17620d2c4d2Smrg{ 17720d2c4d2Smrg TScreen *screen = TScreenOf(xw); 17820d2c4d2Smrg Bool value = False; 17920d2c4d2Smrg 18020d2c4d2Smrg#if OPT_RENDERFONT 18120d2c4d2Smrg#define MIXED(name) screen->name[fontnum].map.mixed 1820bd37d32Smrg if (xw->work.render_font == True) { 18320d2c4d2Smrg int fontnum = screen->menu_font_number; 18420d2c4d2Smrg 18520d2c4d2Smrg screen->allow_packing = (Boolean) (MIXED(renderFontNorm) 18620d2c4d2Smrg || MIXED(renderFontBold) 18720d2c4d2Smrg || MIXED(renderFontItal) 18820d2c4d2Smrg#if OPT_RENDERWIDE 18920d2c4d2Smrg || MIXED(renderWideNorm) 19020d2c4d2Smrg || MIXED(renderWideBold) 19120d2c4d2Smrg || MIXED(renderWideItal) 19220d2c4d2Smrg#endif 19320d2c4d2Smrg ); 19420d2c4d2Smrg#undef MIXED 19520d2c4d2Smrg } 19620d2c4d2Smrg#endif /* OPT_RENDERFONT */ 19720d2c4d2Smrg 19820d2c4d2Smrg value = screen->allow_packing; 19920d2c4d2Smrg 20020d2c4d2Smrg SetItemSensitivity(fontMenuEntries[fontMenu_font_packedfont].widget, value); 20120d2c4d2Smrg} 20220d2c4d2Smrg#endif 20320d2c4d2Smrg 204d522f475Smrg/* 205d522f475Smrg * Returns the fields from start to stop in a dash- separated string. This 2069a64e1c5Smrg * function will modify the source, putting '\0's in the appropriate place and 207d522f475Smrg * moving the beginning forward to after the '\0' 208d522f475Smrg * 209d522f475Smrg * This will NOT work for the last field (but we won't need it). 210d522f475Smrg */ 211d522f475Smrgstatic char * 212d522f475Smrgn_fields(char **source, int start, int stop) 213d522f475Smrg{ 214d522f475Smrg int i; 215d522f475Smrg char *str, *str1; 216d522f475Smrg 217d522f475Smrg /* 218d522f475Smrg * find the start-1th dash 219d522f475Smrg */ 2209a64e1c5Smrg for (i = start - 1, str = *source; i; i--, str++) { 221d522f475Smrg if ((str = strchr(str, '-')) == 0) 222d522f475Smrg return 0; 2239a64e1c5Smrg } 224d522f475Smrg 225d522f475Smrg /* 226d522f475Smrg * find the stopth dash 227d522f475Smrg */ 2289a64e1c5Smrg for (i = stop - start + 1, str1 = str; i; i--, str1++) { 229d522f475Smrg if ((str1 = strchr(str1, '-')) == 0) 230d522f475Smrg return 0; 2319a64e1c5Smrg } 232d522f475Smrg 233d522f475Smrg /* 234d522f475Smrg * put a \0 at the end of the fields 235d522f475Smrg */ 236d522f475Smrg *(str1 - 1) = '\0'; 237d522f475Smrg 238d522f475Smrg /* 239d522f475Smrg * move source forward 240d522f475Smrg */ 241d522f475Smrg *source = str1; 242d522f475Smrg 243d522f475Smrg return str; 244d522f475Smrg} 245d522f475Smrg 246956cc18dSsnjstatic Boolean 247956cc18dSsnjcheck_fontname(const char *name) 248956cc18dSsnj{ 249956cc18dSsnj Boolean result = True; 250956cc18dSsnj 251492d43a5Smrg if (IsEmpty(name)) { 252956cc18dSsnj TRACE(("fontname missing\n")); 253956cc18dSsnj result = False; 254956cc18dSsnj } 255956cc18dSsnj return result; 256956cc18dSsnj} 257956cc18dSsnj 258d522f475Smrg/* 259d522f475Smrg * Gets the font properties from a given font structure. We use the FONT name 260d522f475Smrg * to find them out, since that seems easier. 261d522f475Smrg * 262d522f475Smrg * Returns a pointer to a static FontNameProperties structure 263d522f475Smrg * or NULL on error. 264d522f475Smrg */ 265d522f475Smrgstatic FontNameProperties * 2669a64e1c5Smrgget_font_name_props(Display *dpy, XFontStruct *fs, char **result) 267d522f475Smrg{ 268d522f475Smrg static FontNameProperties props; 269d522f475Smrg static char *last_name; 270d522f475Smrg 271d522f475Smrg XFontProp *fp; 272d522f475Smrg int i; 273d522f475Smrg Atom fontatom = XInternAtom(dpy, "FONT", False); 27420d2c4d2Smrg char *name = 0; 275d522f475Smrg char *str; 276d522f475Smrg 277d522f475Smrg /* 278d522f475Smrg * first get the full font name 279d522f475Smrg */ 28020d2c4d2Smrg if (fontatom != 0) { 28120d2c4d2Smrg for (i = 0, fp = fs->properties; i < fs->n_properties; i++, fp++) { 28220d2c4d2Smrg if (fp->name == fontatom) { 28320d2c4d2Smrg name = XGetAtomName(dpy, fp->card32); 28420d2c4d2Smrg break; 28520d2c4d2Smrg } 28620d2c4d2Smrg } 28720d2c4d2Smrg } 288d522f475Smrg 289d522f475Smrg if (name == 0) 290d522f475Smrg return 0; 291d522f475Smrg 292d522f475Smrg /* 293d522f475Smrg * XGetAtomName allocates memory - don't leak 294d522f475Smrg */ 295d522f475Smrg if (last_name != 0) 296d522f475Smrg XFree(last_name); 297d522f475Smrg last_name = name; 298d522f475Smrg 299d522f475Smrg if (result != 0) { 300956cc18dSsnj if (!check_fontname(name)) 301d522f475Smrg return 0; 3020bd37d32Smrg if (*result != 0) 3030bd37d32Smrg free(*result); 3040bd37d32Smrg *result = x_strdup(name); 305d522f475Smrg } 306d522f475Smrg 307d522f475Smrg /* 308d522f475Smrg * Now split it up into parts and put them in 309d522f475Smrg * their places. Since we are using parts of 310d522f475Smrg * the original string, we must not free the Atom Name 311d522f475Smrg */ 312d522f475Smrg 313d522f475Smrg /* registry, foundry, family */ 314d522f475Smrg if ((props.beginning = n_fields(&name, 1, 3)) == 0) 315d522f475Smrg return 0; 316d522f475Smrg 317d522f475Smrg /* weight is the next */ 318d522f475Smrg if ((props.weight = n_fields(&name, 1, 1)) == 0) 319d522f475Smrg return 0; 320d522f475Smrg 321d522f475Smrg /* slant */ 322d522f475Smrg if ((props.slant = n_fields(&name, 1, 1)) == 0) 323d522f475Smrg return 0; 324d522f475Smrg 325d522f475Smrg /* width */ 326d522f475Smrg if ((props.wideness = n_fields(&name, 1, 1)) == 0) 327d522f475Smrg return 0; 328d522f475Smrg 329d522f475Smrg /* add style */ 330d522f475Smrg if ((props.add_style = n_fields(&name, 1, 1)) == 0) 331d522f475Smrg return 0; 332d522f475Smrg 333d522f475Smrg /* pixel size */ 334d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 335d522f475Smrg return 0; 336d522f475Smrg if ((props.pixel_size = atoi(str)) == 0) 337d522f475Smrg return 0; 338d522f475Smrg 339d522f475Smrg /* point size */ 340d522f475Smrg if ((props.point_size = n_fields(&name, 1, 1)) == 0) 341d522f475Smrg return 0; 342d522f475Smrg 343d522f475Smrg /* res_x */ 344d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 345d522f475Smrg return 0; 346d522f475Smrg if ((props.res_x = atoi(str)) == 0) 347d522f475Smrg return 0; 348d522f475Smrg 349d522f475Smrg /* res_y */ 350d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 351d522f475Smrg return 0; 352d522f475Smrg if ((props.res_y = atoi(str)) == 0) 353d522f475Smrg return 0; 354d522f475Smrg 355d522f475Smrg /* spacing */ 356d522f475Smrg if ((props.spacing = n_fields(&name, 1, 1)) == 0) 357d522f475Smrg return 0; 358d522f475Smrg 359d522f475Smrg /* average width */ 360d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 361d522f475Smrg return 0; 362d522f475Smrg if ((props.average_width = atoi(str)) == 0) 363d522f475Smrg return 0; 364d522f475Smrg 365d522f475Smrg /* the rest: charset registry and charset encoding */ 366d522f475Smrg props.end = name; 367d522f475Smrg 368d522f475Smrg return &props; 369d522f475Smrg} 370d522f475Smrg 371d522f475Smrg#define ALLOCHUNK(n) ((n | 127) + 1) 372d522f475Smrg 373d522f475Smrgstatic void 374956cc18dSsnjalloca_fontname(char **result, size_t next) 375d522f475Smrg{ 376956cc18dSsnj size_t last = (*result != 0) ? strlen(*result) : 0; 377956cc18dSsnj size_t have = (*result != 0) ? ALLOCHUNK(last) : 0; 378956cc18dSsnj size_t want = last + next + 2; 379d522f475Smrg 380d522f475Smrg if (want >= have) { 381d522f475Smrg want = ALLOCHUNK(want); 382d522f475Smrg if (last != 0) { 3839a64e1c5Smrg char *save = *result; 384d522f475Smrg *result = TypeRealloc(char, want, *result); 3859a64e1c5Smrg if (*result == 0) 3869a64e1c5Smrg free(save); 387d522f475Smrg } else { 388d522f475Smrg if ((*result = TypeMallocN(char, want)) != 0) 389d522f475Smrg **result = '\0'; 390d522f475Smrg } 391d522f475Smrg } 392d522f475Smrg} 393d522f475Smrg 394d522f475Smrgstatic void 39520d2c4d2Smrgappend_fontname_str(char **result, const char *value) 396d522f475Smrg{ 397d522f475Smrg if (value == 0) 398d522f475Smrg value = "*"; 399d522f475Smrg alloca_fontname(result, strlen(value)); 400d522f475Smrg if (*result != 0) { 401d522f475Smrg if (**result != '\0') 402d522f475Smrg strcat(*result, "-"); 403d522f475Smrg strcat(*result, value); 404d522f475Smrg } 405d522f475Smrg} 406d522f475Smrg 407d522f475Smrgstatic void 408d522f475Smrgappend_fontname_num(char **result, int value) 409d522f475Smrg{ 410d522f475Smrg if (value < 0) { 411d522f475Smrg append_fontname_str(result, "*"); 412d522f475Smrg } else { 413d522f475Smrg char temp[100]; 414d522f475Smrg sprintf(temp, "%d", value); 415d522f475Smrg append_fontname_str(result, temp); 416d522f475Smrg } 417d522f475Smrg} 418d522f475Smrg 419d522f475Smrg/* 420d522f475Smrg * Take the given font props and try to make a well formed font name specifying 421d522f475Smrg * the same base font and size and everything, but with different weight/width 422d522f475Smrg * according to the parameters. The return value is allocated, should be freed 423d522f475Smrg * by the caller. 424d522f475Smrg */ 425d522f475Smrgstatic char * 4269a64e1c5Smrgderive_font_name(FontNameProperties *props, 42720d2c4d2Smrg const char *use_weight, 428d522f475Smrg int use_average_width, 42920d2c4d2Smrg const char *use_encoding) 430d522f475Smrg{ 431d522f475Smrg char *result = 0; 432d522f475Smrg 433d522f475Smrg append_fontname_str(&result, props->beginning); 434d522f475Smrg append_fontname_str(&result, use_weight); 435d522f475Smrg append_fontname_str(&result, props->slant); 436d522f475Smrg append_fontname_str(&result, 0); 437d522f475Smrg append_fontname_str(&result, 0); 438d522f475Smrg append_fontname_num(&result, props->pixel_size); 439d522f475Smrg append_fontname_str(&result, props->point_size); 440d522f475Smrg append_fontname_num(&result, props->res_x); 441d522f475Smrg append_fontname_num(&result, props->res_y); 442d522f475Smrg append_fontname_str(&result, props->spacing); 443d522f475Smrg append_fontname_num(&result, use_average_width); 444d522f475Smrg append_fontname_str(&result, use_encoding); 445d522f475Smrg 446d522f475Smrg return result; 447d522f475Smrg} 448d522f475Smrg 449d522f475Smrgstatic char * 4509a64e1c5Smrgbold_font_name(FontNameProperties *props, int use_average_width) 451d522f475Smrg{ 452d522f475Smrg return derive_font_name(props, "bold", use_average_width, props->end); 453d522f475Smrg} 454d522f475Smrg 4559a64e1c5Smrg#if OPT_WIDE_ATTRS 4569a64e1c5Smrgstatic char * 4579a64e1c5Smrgitalic_font_name(FontNameProperties *props, int use_average_width) 4589a64e1c5Smrg{ 4599a64e1c5Smrg FontNameProperties myprops = *props; 4609a64e1c5Smrg myprops.slant = "o"; 4619a64e1c5Smrg return derive_font_name(&myprops, props->weight, use_average_width, props->end); 4629a64e1c5Smrg} 4639a64e1c5Smrg#endif 4649a64e1c5Smrg 465d522f475Smrg#if OPT_WIDE_CHARS 466d522f475Smrg#define derive_wide_font(props, weight) \ 467d522f475Smrg derive_font_name(props, weight, props->average_width * 2, "ISO10646-1") 468d522f475Smrg 469d522f475Smrgstatic char * 4709a64e1c5Smrgwide_font_name(FontNameProperties *props) 471d522f475Smrg{ 472d522f475Smrg return derive_wide_font(props, "medium"); 473d522f475Smrg} 474d522f475Smrg 475d522f475Smrgstatic char * 4769a64e1c5Smrgwidebold_font_name(FontNameProperties *props) 477d522f475Smrg{ 478d522f475Smrg return derive_wide_font(props, "bold"); 479d522f475Smrg} 480d522f475Smrg#endif /* OPT_WIDE_CHARS */ 481d522f475Smrg 482d522f475Smrg#if OPT_DEC_CHRSET 483d522f475Smrg/* 484d522f475Smrg * Take the given font props and try to make a well formed font name specifying 485d522f475Smrg * the same base font but changed depending on the given attributes and chrset. 486d522f475Smrg * 487d522f475Smrg * For double width fonts, we just double the X-resolution, for double height 488d522f475Smrg * fonts we double the pixel-size and Y-resolution 489d522f475Smrg */ 490d522f475Smrgchar * 4919a64e1c5SmrgxtermSpecialFont(TScreen *screen, unsigned attr_flags, unsigned draw_flags, unsigned chrset) 492d522f475Smrg{ 493d522f475Smrg#if OPT_TRACE 494d522f475Smrg static char old_spacing[80]; 495d522f475Smrg static FontNameProperties old_props; 496d522f475Smrg#endif 497d522f475Smrg FontNameProperties *props; 498d522f475Smrg char *result = 0; 49920d2c4d2Smrg const char *weight; 500d522f475Smrg int pixel_size; 501d522f475Smrg int res_x; 502d522f475Smrg int res_y; 503d522f475Smrg 504d522f475Smrg props = get_font_name_props(screen->display, screen->fnts[fNorm].fs, 0); 505d522f475Smrg if (props == 0) 506d522f475Smrg return result; 507d522f475Smrg 508d522f475Smrg pixel_size = props->pixel_size; 509d522f475Smrg res_x = props->res_x; 510d522f475Smrg res_y = props->res_y; 5119a64e1c5Smrg if (attr_flags & BOLD) 512d522f475Smrg weight = "bold"; 513d522f475Smrg else 514d522f475Smrg weight = props->weight; 515d522f475Smrg 516d522f475Smrg if (CSET_DOUBLE(chrset)) 517d522f475Smrg res_x *= 2; 518d522f475Smrg 519d522f475Smrg if (chrset == CSET_DHL_TOP 520d522f475Smrg || chrset == CSET_DHL_BOT) { 521d522f475Smrg res_y *= 2; 522d522f475Smrg pixel_size *= 2; 523d522f475Smrg } 524d522f475Smrg#if OPT_TRACE 525d522f475Smrg if (old_props.res_x != res_x 526d522f475Smrg || old_props.res_x != res_y 527d522f475Smrg || old_props.pixel_size != pixel_size 528d522f475Smrg || strcmp(old_props.spacing, props->spacing)) { 5299a64e1c5Smrg TRACE(("xtermSpecialFont(atts = %#x, draw = %#x, chrset = %#x)\n", 5309a64e1c5Smrg attr_flags, draw_flags, chrset)); 531d522f475Smrg TRACE(("res_x = %d\n", res_x)); 532d522f475Smrg TRACE(("res_y = %d\n", res_y)); 533d522f475Smrg TRACE(("point_size = %s\n", props->point_size)); 534d522f475Smrg TRACE(("pixel_size = %d\n", pixel_size)); 535d522f475Smrg TRACE(("spacing = %s\n", props->spacing)); 536d522f475Smrg old_props.res_x = res_x; 537d522f475Smrg old_props.res_x = res_y; 538d522f475Smrg old_props.pixel_size = pixel_size; 5390bd37d32Smrg old_props.spacing = old_spacing; 5400bd37d32Smrg sprintf(old_spacing, "%.*s", (int) sizeof(old_spacing) - 2, props->spacing); 541d522f475Smrg } 542d522f475Smrg#endif 543d522f475Smrg 544d522f475Smrg append_fontname_str(&result, props->beginning); 545d522f475Smrg append_fontname_str(&result, weight); 546d522f475Smrg append_fontname_str(&result, props->slant); 547d522f475Smrg append_fontname_str(&result, props->wideness); 548d522f475Smrg append_fontname_str(&result, props->add_style); 549d522f475Smrg append_fontname_num(&result, pixel_size); 550d522f475Smrg append_fontname_str(&result, props->point_size); 5519a64e1c5Smrg append_fontname_num(&result, (draw_flags & NORESOLUTION) ? -1 : res_x); 5529a64e1c5Smrg append_fontname_num(&result, (draw_flags & NORESOLUTION) ? -1 : res_y); 553d522f475Smrg append_fontname_str(&result, props->spacing); 554d522f475Smrg append_fontname_str(&result, 0); 555d522f475Smrg append_fontname_str(&result, props->end); 556d522f475Smrg 557d522f475Smrg return result; 558d522f475Smrg} 559d522f475Smrg#endif /* OPT_DEC_CHRSET */ 560d522f475Smrg 561d522f475Smrg/* 562d522f475Smrg * Case-independent comparison for font-names, including wildcards. 563d522f475Smrg * XLFD allows '?' as a wildcard, but we do not handle that (no one seems 564d522f475Smrg * to use it). 565d522f475Smrg */ 566d522f475Smrgstatic Bool 567492d43a5Smrgsame_font_name(const char *pattern, const char *match) 568d522f475Smrg{ 569956cc18dSsnj Bool result = False; 570956cc18dSsnj 571956cc18dSsnj if (pattern && match) { 572956cc18dSsnj while (*pattern && *match) { 573956cc18dSsnj if (*pattern == *match) { 574956cc18dSsnj pattern++; 575956cc18dSsnj match++; 576956cc18dSsnj } else if (*pattern == '*' || *match == '*') { 577956cc18dSsnj if (same_font_name(pattern + 1, match)) { 578956cc18dSsnj return True; 579956cc18dSsnj } else if (same_font_name(pattern, match + 1)) { 580956cc18dSsnj return True; 581956cc18dSsnj } else { 582956cc18dSsnj return False; 583956cc18dSsnj } 584d522f475Smrg } else { 585956cc18dSsnj int p = x_toupper(*pattern++); 586956cc18dSsnj int m = x_toupper(*match++); 587956cc18dSsnj if (p != m) 588956cc18dSsnj return False; 589d522f475Smrg } 590d522f475Smrg } 591956cc18dSsnj result = (*pattern == *match); /* both should be NUL */ 592d522f475Smrg } 593956cc18dSsnj return result; 594d522f475Smrg} 595d522f475Smrg 596d522f475Smrg/* 597d522f475Smrg * Double-check the fontname that we asked for versus what the font server 598d522f475Smrg * actually gave us. The larger fixed fonts do not always have a matching bold 599d522f475Smrg * font, and the font server may try to scale another font or otherwise 600d522f475Smrg * substitute a mismatched font. 601d522f475Smrg * 602d522f475Smrg * If we cannot get what we requested, we will fallback to the original 603d522f475Smrg * behavior, which simulates bold by overstriking each character at one pixel 604d522f475Smrg * offset. 605d522f475Smrg */ 606d522f475Smrgstatic int 6079a64e1c5Smrggot_bold_font(Display *dpy, XFontStruct *fs, String requested) 608d522f475Smrg{ 6090bd37d32Smrg char *actual = 0; 610d522f475Smrg int got; 611d522f475Smrg 6120bd37d32Smrg if (get_font_name_props(dpy, fs, &actual) == 0) 613d522f475Smrg got = 0; 614d522f475Smrg else 615d522f475Smrg got = same_font_name(requested, actual); 6160bd37d32Smrg free(actual); 617d522f475Smrg return got; 618d522f475Smrg} 619d522f475Smrg 6209a64e1c5Smrg/* 6219a64e1c5Smrg * Check normal/bold (or wide/wide-bold) font pairs to see if we will be able 6229a64e1c5Smrg * to check for missing glyphs in a comparable manner. 6239a64e1c5Smrg */ 6249a64e1c5Smrgstatic int 6259a64e1c5Smrgcomparable_metrics(XFontStruct *normal, XFontStruct *bold) 6269a64e1c5Smrg{ 6279a64e1c5Smrg#define DATA "comparable_metrics: " 6289a64e1c5Smrg int result = 0; 6299a64e1c5Smrg 6309a64e1c5Smrg if (normal->all_chars_exist) { 6319a64e1c5Smrg if (bold->all_chars_exist) { 6329a64e1c5Smrg result = 1; 6339a64e1c5Smrg } else { 6349a64e1c5Smrg TRACE((DATA "all chars exist in normal font, but not in bold\n")); 6359a64e1c5Smrg } 6369a64e1c5Smrg } else if (normal->per_char != 0) { 6379a64e1c5Smrg if (bold->per_char != 0) { 6389a64e1c5Smrg result = 1; 6399a64e1c5Smrg } else { 6409a64e1c5Smrg TRACE((DATA "normal font has per-char metrics, but not bold\n")); 6419a64e1c5Smrg } 6429a64e1c5Smrg } else { 6439a64e1c5Smrg TRACE((DATA "normal font is not very good!\n")); 6449a64e1c5Smrg result = 1; /* give in (we're not going in reverse) */ 6459a64e1c5Smrg } 6469a64e1c5Smrg return result; 6479a64e1c5Smrg#undef DATA 6489a64e1c5Smrg} 6499a64e1c5Smrg 650d522f475Smrg/* 651d522f475Smrg * If the font server tries to adjust another font, it may not adjust it 652d522f475Smrg * properly. Check that the bounding boxes are compatible. Otherwise we'll 653d522f475Smrg * leave trash on the display when we mix normal and bold fonts. 654d522f475Smrg */ 655d522f475Smrgstatic int 6569a64e1c5Smrgsame_font_size(XtermWidget xw, XFontStruct *nfs, XFontStruct *bfs) 657d522f475Smrg{ 658956cc18dSsnj TScreen *screen = TScreenOf(xw); 659d522f475Smrg TRACE(("same_font_size height %d/%d, min %d/%d max %d/%d\n", 660d522f475Smrg nfs->ascent + nfs->descent, 661d522f475Smrg bfs->ascent + bfs->descent, 662d522f475Smrg nfs->min_bounds.width, bfs->min_bounds.width, 663d522f475Smrg nfs->max_bounds.width, bfs->max_bounds.width)); 664956cc18dSsnj return screen->free_bold_box 665d522f475Smrg || ((nfs->ascent + nfs->descent) == (bfs->ascent + bfs->descent) 666d522f475Smrg && (nfs->min_bounds.width == bfs->min_bounds.width 667d522f475Smrg || nfs->min_bounds.width == bfs->min_bounds.width + 1) 668d522f475Smrg && (nfs->max_bounds.width == bfs->max_bounds.width 669d522f475Smrg || nfs->max_bounds.width == bfs->max_bounds.width + 1)); 670d522f475Smrg} 671d522f475Smrg 672d522f475Smrg/* 673d522f475Smrg * Check if the font looks like it has fixed width 674d522f475Smrg */ 675d522f475Smrgstatic int 6769a64e1c5Smrgis_fixed_font(XFontStruct *fs) 677d522f475Smrg{ 678d522f475Smrg if (fs) 679d522f475Smrg return (fs->min_bounds.width == fs->max_bounds.width); 680d522f475Smrg return 1; 681d522f475Smrg} 682d522f475Smrg 683d522f475Smrg/* 684d522f475Smrg * Check if the font looks like a double width font (i.e. contains 685d522f475Smrg * characters of width X and 2X 686d522f475Smrg */ 687d522f475Smrg#if OPT_WIDE_CHARS 688d522f475Smrgstatic int 6899a64e1c5Smrgis_double_width_font(XFontStruct *fs) 690d522f475Smrg{ 691d522f475Smrg return ((2 * fs->min_bounds.width) == fs->max_bounds.width); 692d522f475Smrg} 693d522f475Smrg#else 694d522f475Smrg#define is_double_width_font(fs) 0 695d522f475Smrg#endif 696d522f475Smrg 697d522f475Smrg#if OPT_WIDE_CHARS && OPT_RENDERFONT && defined(HAVE_TYPE_FCCHAR32) 698d522f475Smrg#define HALF_WIDTH_TEST_STRING "1234567890" 699d522f475Smrg 700d522f475Smrg/* '1234567890' in Chinese characters in UTF-8 */ 701d522f475Smrg#define FULL_WIDTH_TEST_STRING "\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89" \ 702d522f475Smrg "\xe5\x9b\x9b\xe4\xba\x94" \ 703d522f475Smrg "\xef\xa7\x91\xe4\xb8\x83\xe5\x85\xab" \ 704d522f475Smrg "\xe4\xb9\x9d\xef\xa6\xb2" 705d522f475Smrg 706d522f475Smrg/* '1234567890' in Korean script in UTF-8 */ 707d522f475Smrg#define FULL_WIDTH_TEST_STRING2 "\xec\x9d\xbc\xec\x9d\xb4\xec\x82\xbc" \ 708d522f475Smrg "\xec\x82\xac\xec\x98\xa4" \ 709d522f475Smrg "\xec\x9c\xa1\xec\xb9\xa0\xed\x8c\x94" \ 710d522f475Smrg "\xea\xb5\xac\xec\x98\x81" 711d522f475Smrg 712d522f475Smrg#define HALF_WIDTH_CHAR1 0x0031 /* '1' */ 713d522f475Smrg#define HALF_WIDTH_CHAR2 0x0057 /* 'W' */ 714d522f475Smrg#define FULL_WIDTH_CHAR1 0x4E00 /* CJK Ideograph 'number one' */ 715d522f475Smrg#define FULL_WIDTH_CHAR2 0xAC00 /* Korean script syllable 'Ka' */ 716d522f475Smrg 717d522f475Smrgstatic Bool 7189a64e1c5Smrgis_double_width_font_xft(Display *dpy, XftFont *font) 719d522f475Smrg{ 720d522f475Smrg XGlyphInfo gi1, gi2; 721d522f475Smrg FcChar32 c1 = HALF_WIDTH_CHAR1, c2 = HALF_WIDTH_CHAR2; 7220bd37d32Smrg String fwstr = FULL_WIDTH_TEST_STRING; 7230bd37d32Smrg String hwstr = HALF_WIDTH_TEST_STRING; 724d522f475Smrg 725d522f475Smrg /* Some Korean fonts don't have Chinese characters at all. */ 726d522f475Smrg if (!XftCharExists(dpy, font, FULL_WIDTH_CHAR1)) { 727d522f475Smrg if (!XftCharExists(dpy, font, FULL_WIDTH_CHAR2)) 728d522f475Smrg return False; /* Not a CJK font */ 729d522f475Smrg else /* a Korean font without CJK Ideographs */ 730d522f475Smrg fwstr = FULL_WIDTH_TEST_STRING2; 731d522f475Smrg } 732d522f475Smrg 733d522f475Smrg XftTextExtents32(dpy, font, &c1, 1, &gi1); 734d522f475Smrg XftTextExtents32(dpy, font, &c2, 1, &gi2); 735d522f475Smrg if (gi1.xOff != gi2.xOff) /* Not a fixed-width font */ 736d522f475Smrg return False; 737d522f475Smrg 7380bd37d32Smrg XftTextExtentsUtf8(dpy, 7390bd37d32Smrg font, 7400bd37d32Smrg (_Xconst FcChar8 *) hwstr, 7410bd37d32Smrg (int) strlen(hwstr), 7420bd37d32Smrg &gi1); 7430bd37d32Smrg XftTextExtentsUtf8(dpy, 7440bd37d32Smrg font, 7450bd37d32Smrg (_Xconst FcChar8 *) fwstr, 7460bd37d32Smrg (int) strlen(fwstr), 7470bd37d32Smrg &gi2); 748d522f475Smrg 749d522f475Smrg /* 750d522f475Smrg * fontconfig and Xft prior to 2.2(?) set the width of half-width 751d522f475Smrg * characters identical to that of full-width character in CJK double-width 752d522f475Smrg * (bi-width / monospace) font even though the former is half as wide as 753d522f475Smrg * the latter. This was fixed sometime before the release of fontconfig 754d522f475Smrg * 2.2 in early 2003. See 755d522f475Smrg * http://bugzilla.mozilla.org/show_bug.cgi?id=196312 756d522f475Smrg * In the meantime, we have to check both possibilities. 757d522f475Smrg */ 758d522f475Smrg return ((2 * gi1.xOff == gi2.xOff) || (gi1.xOff == gi2.xOff)); 759d522f475Smrg} 760d522f475Smrg#else 761d522f475Smrg#define is_double_width_font_xft(dpy, xftfont) 0 762d522f475Smrg#endif 763d522f475Smrg 764d522f475Smrg#define EmptyFont(fs) (fs != 0 \ 765d522f475Smrg && ((fs)->ascent + (fs)->descent == 0 \ 766d522f475Smrg || (fs)->max_bounds.width == 0)) 767d522f475Smrg 768d522f475Smrg#define FontSize(fs) (((fs)->ascent + (fs)->descent) \ 769d522f475Smrg * (fs)->max_bounds.width) 770d522f475Smrg 771d522f475Smrgconst VTFontNames * 77220d2c4d2SmrgxtermFontName(const char *normal) 773d522f475Smrg{ 774d522f475Smrg static VTFontNames data; 7759a64e1c5Smrg FREE_STRING(data.f_n); 776d522f475Smrg memset(&data, 0, sizeof(data)); 77720d2c4d2Smrg data.f_n = x_strdup(normal); 778d522f475Smrg return &data; 779d522f475Smrg} 780d522f475Smrg 781d522f475Smrgstatic void 782fa3f02f3Smrgcache_menu_font_name(TScreen *screen, int fontnum, int which, const char *name) 783d522f475Smrg{ 784d522f475Smrg if (name != 0) { 7859a64e1c5Smrg String last = screen->menu_font_names[fontnum][which]; 786d522f475Smrg if (last != 0) { 787d522f475Smrg if (strcmp(last, name)) { 7889a64e1c5Smrg FREE_STRING(last); 789d522f475Smrg TRACE(("caching menu fontname %d.%d %s\n", fontnum, which, name)); 790d522f475Smrg screen->menu_font_names[fontnum][which] = x_strdup(name); 791d522f475Smrg } 792d522f475Smrg } else { 793d522f475Smrg TRACE(("caching menu fontname %d.%d %s\n", fontnum, which, name)); 794d522f475Smrg screen->menu_font_names[fontnum][which] = x_strdup(name); 795d522f475Smrg } 796d522f475Smrg } 797d522f475Smrg} 798d522f475Smrg 799d522f475Smrg/* 800d522f475Smrg * Open the given font and verify that it is non-empty. Return a null on 801d522f475Smrg * failure. 802d522f475Smrg */ 803d522f475SmrgBool 804956cc18dSsnjxtermOpenFont(XtermWidget xw, 805956cc18dSsnj const char *name, 806956cc18dSsnj XTermFonts * result, 807956cc18dSsnj fontWarningTypes warn, 808956cc18dSsnj Bool force) 809d522f475Smrg{ 810d522f475Smrg Bool code = False; 811d522f475Smrg TScreen *screen = TScreenOf(xw); 812d522f475Smrg 813492d43a5Smrg if (!IsEmpty(name)) { 814956cc18dSsnj if ((result->fs = XLoadQueryFont(screen->display, name)) != 0) { 815956cc18dSsnj code = True; 816956cc18dSsnj if (EmptyFont(result->fs)) { 81720d2c4d2Smrg (void) xtermCloseFont(xw, result); 818956cc18dSsnj code = False; 819956cc18dSsnj } else { 820956cc18dSsnj result->fn = x_strdup(name); 821956cc18dSsnj } 82220d2c4d2Smrg } else if (XmuCompareISOLatin1(name, DEFFONT) != 0) { 823956cc18dSsnj if (warn <= xw->misc.fontWarnings 824956cc18dSsnj#if OPT_RENDERFONT 825956cc18dSsnj && !UsingRenderFont(xw) 826956cc18dSsnj#endif 827956cc18dSsnj ) { 828956cc18dSsnj TRACE(("OOPS: cannot load font %s\n", name)); 8290bd37d32Smrg xtermWarning("cannot load font '%s'\n", name); 83020d2c4d2Smrg#if OPT_RENDERFONT 83120d2c4d2Smrg /* 83220d2c4d2Smrg * Do a sanity check in case someone's mixed up xterm with 83320d2c4d2Smrg * one of those programs that read their resource data from 83420d2c4d2Smrg * xterm's namespace. 83520d2c4d2Smrg */ 83620d2c4d2Smrg if (strchr(name, ':') != 0 || strchr(name, '=') != 0) { 8370bd37d32Smrg xtermWarning("Use the \"-fa\" option for the Xft fonts\n"); 83820d2c4d2Smrg } 83920d2c4d2Smrg#endif 840956cc18dSsnj } else { 841492d43a5Smrg TRACE(("xtermOpenFont: cannot load font '%s'\n", name)); 842956cc18dSsnj } 843956cc18dSsnj if (force) { 844956cc18dSsnj code = xtermOpenFont(xw, DEFFONT, result, fwAlways, True); 845956cc18dSsnj } 846d522f475Smrg } 847d522f475Smrg } 848d522f475Smrg return code; 849d522f475Smrg} 850d522f475Smrg 851d522f475Smrg/* 852956cc18dSsnj * Close the font and free the font info. 853d522f475Smrg */ 854d522f475SmrgXTermFonts * 855d522f475SmrgxtermCloseFont(XtermWidget xw, XTermFonts * fnt) 856d522f475Smrg{ 857d522f475Smrg if (fnt != 0 && fnt->fs != 0) { 858d522f475Smrg TScreen *screen = TScreenOf(xw); 859d522f475Smrg 860d522f475Smrg clrCgsFonts(xw, WhichVWin(screen), fnt); 861d522f475Smrg XFreeFont(screen->display, fnt->fs); 862d522f475Smrg xtermFreeFontInfo(fnt); 863d522f475Smrg } 864d522f475Smrg return 0; 865d522f475Smrg} 866d522f475Smrg 867d522f475Smrg/* 868d522f475Smrg * Close the listed fonts, noting that some may use copies of the pointer. 869d522f475Smrg */ 870d522f475Smrgvoid 871d522f475SmrgxtermCloseFonts(XtermWidget xw, XTermFonts * fnts) 872d522f475Smrg{ 873d522f475Smrg int j, k; 874d522f475Smrg 875d522f475Smrg for (j = 0; j < fMAX; ++j) { 876d522f475Smrg /* 877d522f475Smrg * Need to save the pointer since xtermCloseFont zeroes it 878d522f475Smrg */ 879d522f475Smrg XFontStruct *thisFont = fnts[j].fs; 880d522f475Smrg if (thisFont != 0) { 881d522f475Smrg xtermCloseFont(xw, &fnts[j]); 882d522f475Smrg for (k = j + 1; k < fMAX; ++k) { 883d522f475Smrg if (thisFont == fnts[k].fs) 884d522f475Smrg xtermFreeFontInfo(&fnts[k]); 885d522f475Smrg } 886d522f475Smrg } 887d522f475Smrg } 888d522f475Smrg} 889d522f475Smrg 890d522f475Smrg/* 891d522f475Smrg * Make a copy of the source, assuming the XFontStruct's to be unique, but 892d522f475Smrg * ensuring that the names are reallocated to simplify freeing. 893d522f475Smrg */ 894d522f475Smrgvoid 895d522f475SmrgxtermCopyFontInfo(XTermFonts * target, XTermFonts * source) 896d522f475Smrg{ 897d522f475Smrg xtermFreeFontInfo(target); 898d522f475Smrg target->chrset = source->chrset; 899d522f475Smrg target->flags = source->flags; 900d522f475Smrg target->fn = x_strdup(source->fn); 901d522f475Smrg target->fs = source->fs; 902d522f475Smrg} 903d522f475Smrg 904d522f475Smrgvoid 905d522f475SmrgxtermFreeFontInfo(XTermFonts * target) 906d522f475Smrg{ 907d522f475Smrg target->chrset = 0; 908d522f475Smrg target->flags = 0; 909d522f475Smrg if (target->fn != 0) { 910d522f475Smrg free(target->fn); 911d522f475Smrg target->fn = 0; 912d522f475Smrg } 913d522f475Smrg target->fs = 0; 914d522f475Smrg} 915d522f475Smrg 916fa3f02f3Smrg#if OPT_REPORT_FONTS 917fa3f02f3Smrgstatic void 918fa3f02f3SmrgreportXCharStruct(const char *tag, XCharStruct * cs) 919fa3f02f3Smrg{ 920fa3f02f3Smrg printf("\t\t%s:\n", tag); 921fa3f02f3Smrg printf("\t\t\tlbearing: %d\n", cs->lbearing); 922fa3f02f3Smrg printf("\t\t\trbearing: %d\n", cs->rbearing); 923fa3f02f3Smrg printf("\t\t\twidth: %d\n", cs->width); 924fa3f02f3Smrg printf("\t\t\tascent: %d\n", cs->ascent); 925fa3f02f3Smrg printf("\t\t\tdescent: %d\n", cs->descent); 926fa3f02f3Smrg} 927fa3f02f3Smrg 928fa3f02f3Smrgstatic void 929fa3f02f3SmrgreportOneVTFont(const char *tag, 930fa3f02f3Smrg XTermFonts * fnt) 931fa3f02f3Smrg{ 932fa3f02f3Smrg if (!IsEmpty(fnt->fn)) { 933fa3f02f3Smrg XFontStruct *fs = fnt->fs; 934fa3f02f3Smrg unsigned first_char = 0; 935fa3f02f3Smrg unsigned last_char = 0; 936fa3f02f3Smrg unsigned ch; 937fa3f02f3Smrg 938fa3f02f3Smrg if (fs->max_byte1 == 0) { 939fa3f02f3Smrg first_char = fs->min_char_or_byte2; 940fa3f02f3Smrg last_char = fs->max_char_or_byte2; 941fa3f02f3Smrg } else { 942fa3f02f3Smrg first_char = (fs->min_byte1 * 256) + fs->min_char_or_byte2; 943fa3f02f3Smrg last_char = (fs->max_byte1 * 256) + fs->max_char_or_byte2; 944fa3f02f3Smrg } 945fa3f02f3Smrg 946fa3f02f3Smrg printf("\t%s: %s\n", tag, NonNull(fnt->fn)); 947fa3f02f3Smrg printf("\t\tall chars: %s\n", fs->all_chars_exist ? "yes" : "no"); 948fa3f02f3Smrg printf("\t\tdefault char: %d\n", fs->default_char); 949fa3f02f3Smrg printf("\t\tdirection: %d\n", fs->direction); 950fa3f02f3Smrg printf("\t\tascent: %d\n", fs->ascent); 951fa3f02f3Smrg printf("\t\tdescent: %d\n", fs->descent); 952fa3f02f3Smrg printf("\t\tfirst char: %u\n", first_char); 953fa3f02f3Smrg printf("\t\tlast char: %u\n", last_char); 954fa3f02f3Smrg printf("\t\tmaximum-chars: %u\n", countGlyphs(fs)); 9559a64e1c5Smrg if (FontLacksMetrics(fnt)) { 9569a64e1c5Smrg printf("\t\tmissing-chars: ?\n"); 9579a64e1c5Smrg printf("\t\tpresent-chars: ?\n"); 9589a64e1c5Smrg } else { 9599a64e1c5Smrg unsigned missing = 0; 9609a64e1c5Smrg for (ch = first_char; ch <= last_char; ++ch) { 9619a64e1c5Smrg if (xtermMissingChar(ch, fnt)) { 9629a64e1c5Smrg ++missing; 9639a64e1c5Smrg } 9649a64e1c5Smrg } 9659a64e1c5Smrg printf("\t\tmissing-chars: %u\n", missing); 9669a64e1c5Smrg printf("\t\tpresent-chars: %u\n", countGlyphs(fs) - missing); 9679a64e1c5Smrg } 968fa3f02f3Smrg printf("\t\tmin_byte1: %d\n", fs->min_byte1); 969fa3f02f3Smrg printf("\t\tmax_byte1: %d\n", fs->max_byte1); 970fa3f02f3Smrg printf("\t\tproperties: %d\n", fs->n_properties); 971fa3f02f3Smrg reportXCharStruct("min_bounds", &(fs->min_bounds)); 972fa3f02f3Smrg reportXCharStruct("max_bounds", &(fs->max_bounds)); 973fa3f02f3Smrg /* TODO: report fs->properties and fs->per_char */ 974fa3f02f3Smrg } 975fa3f02f3Smrg} 976fa3f02f3Smrg 977fa3f02f3Smrgstatic void 978fa3f02f3SmrgreportVTFontInfo(XtermWidget xw, int fontnum) 979fa3f02f3Smrg{ 980fa3f02f3Smrg if (resource.reportFonts) { 981fa3f02f3Smrg TScreen *screen = TScreenOf(xw); 982fa3f02f3Smrg 983fa3f02f3Smrg if (fontnum) { 984fa3f02f3Smrg printf("Loaded VTFonts(font%d)\n", fontnum); 985fa3f02f3Smrg } else { 986fa3f02f3Smrg printf("Loaded VTFonts(default)\n"); 987fa3f02f3Smrg } 988fa3f02f3Smrg reportOneVTFont("fNorm", &screen->fnts[fNorm]); 989fa3f02f3Smrg reportOneVTFont("fBold", &screen->fnts[fBold]); 990fa3f02f3Smrg#if OPT_WIDE_CHARS 991fa3f02f3Smrg reportOneVTFont("fWide", &screen->fnts[fWide]); 992fa3f02f3Smrg reportOneVTFont("fWBold", &screen->fnts[fWBold]); 993fa3f02f3Smrg#endif 994fa3f02f3Smrg } 995fa3f02f3Smrg} 996fa3f02f3Smrg#endif 997fa3f02f3Smrg 9989a64e1c5Smrgvoid 9999a64e1c5SmrgxtermUpdateFontGCs(XtermWidget xw, XTermFonts * fnts) 10009a64e1c5Smrg{ 10019a64e1c5Smrg TScreen *screen = TScreenOf(xw); 10029a64e1c5Smrg VTwin *win = WhichVWin(screen); 10039a64e1c5Smrg Pixel new_normal = getXtermForeground(xw, xw->flags, xw->cur_foreground); 10049a64e1c5Smrg Pixel new_revers = getXtermBackground(xw, xw->flags, xw->cur_background); 10059a64e1c5Smrg 10069a64e1c5Smrg setCgsFore(xw, win, gcNorm, new_normal); 10079a64e1c5Smrg setCgsBack(xw, win, gcNorm, new_revers); 10089a64e1c5Smrg setCgsFont(xw, win, gcNorm, &(fnts[fNorm])); 10099a64e1c5Smrg 10109a64e1c5Smrg copyCgs(xw, win, gcBold, gcNorm); 10119a64e1c5Smrg setCgsFont(xw, win, gcBold, &(fnts[fBold])); 10129a64e1c5Smrg 10139a64e1c5Smrg setCgsFore(xw, win, gcNormReverse, new_revers); 10149a64e1c5Smrg setCgsBack(xw, win, gcNormReverse, new_normal); 10159a64e1c5Smrg setCgsFont(xw, win, gcNormReverse, &(fnts[fNorm])); 10169a64e1c5Smrg 10179a64e1c5Smrg copyCgs(xw, win, gcBoldReverse, gcNormReverse); 10189a64e1c5Smrg setCgsFont(xw, win, gcBoldReverse, &(fnts[fBold])); 10199a64e1c5Smrg 10209a64e1c5Smrg if_OPT_WIDE_CHARS(screen, { 10219a64e1c5Smrg if (fnts[fWide].fs != 0 10229a64e1c5Smrg && fnts[fWBold].fs != 0) { 10239a64e1c5Smrg setCgsFore(xw, win, gcWide, new_normal); 10249a64e1c5Smrg setCgsBack(xw, win, gcWide, new_revers); 10259a64e1c5Smrg setCgsFont(xw, win, gcWide, &(fnts[fWide])); 10269a64e1c5Smrg 10279a64e1c5Smrg copyCgs(xw, win, gcWBold, gcWide); 10289a64e1c5Smrg setCgsFont(xw, win, gcWBold, &(fnts[fWBold])); 10299a64e1c5Smrg 10309a64e1c5Smrg setCgsFore(xw, win, gcWideReverse, new_revers); 10319a64e1c5Smrg setCgsBack(xw, win, gcWideReverse, new_normal); 10329a64e1c5Smrg setCgsFont(xw, win, gcWideReverse, &(fnts[fWide])); 10339a64e1c5Smrg 10349a64e1c5Smrg copyCgs(xw, win, gcWBoldReverse, gcWideReverse); 10359a64e1c5Smrg setCgsFont(xw, win, gcWBoldReverse, &(fnts[fWBold])); 10369a64e1c5Smrg } 10379a64e1c5Smrg }); 10389a64e1c5Smrg} 10399a64e1c5Smrg 10409a64e1c5Smrg#if OPT_TRACE 10419a64e1c5Smrgstatic void 10429a64e1c5Smrgshow_font_misses(const char *name, XTermFonts * fp) 10439a64e1c5Smrg{ 10449a64e1c5Smrg if (fp->fs != 0) { 10459a64e1c5Smrg if (FontLacksMetrics(fp)) { 10469a64e1c5Smrg TRACE(("%s font lacks metrics\n", name)); 10479a64e1c5Smrg } else if (FontIsIncomplete(fp)) { 10489a64e1c5Smrg TRACE(("%s font is incomplete\n", name)); 10499a64e1c5Smrg } else { 10509a64e1c5Smrg TRACE(("%s font is complete\n", name)); 10519a64e1c5Smrg } 10529a64e1c5Smrg } else { 10539a64e1c5Smrg TRACE(("%s font is missing\n", name)); 10549a64e1c5Smrg } 10559a64e1c5Smrg} 10569a64e1c5Smrg#endif 10579a64e1c5Smrg 1058d522f475Smrgint 1059d522f475SmrgxtermLoadFont(XtermWidget xw, 1060d522f475Smrg const VTFontNames * fonts, 1061d522f475Smrg Bool doresize, 1062d522f475Smrg int fontnum) 1063d522f475Smrg{ 1064956cc18dSsnj TScreen *screen = TScreenOf(xw); 1065d522f475Smrg VTwin *win = WhichVWin(screen); 1066d522f475Smrg 1067d522f475Smrg VTFontNames myfonts; 1068d522f475Smrg FontNameProperties *fp; 1069d522f475Smrg XTermFonts fnts[fMAX]; 1070d522f475Smrg char *tmpname = NULL; 10710bd37d32Smrg char *normal = NULL; 1072956cc18dSsnj Boolean proportional = False; 1073956cc18dSsnj fontWarningTypes warn[fMAX]; 1074956cc18dSsnj int j; 1075d522f475Smrg 1076d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 1077d522f475Smrg memset(fnts, 0, sizeof(fnts)); 1078d522f475Smrg 1079d522f475Smrg if (fonts != 0) 1080d522f475Smrg myfonts = *fonts; 1081956cc18dSsnj if (!check_fontname(myfonts.f_n)) 1082d522f475Smrg return 0; 1083d522f475Smrg 1084956cc18dSsnj /* 1085956cc18dSsnj * Check the font names against the resource values, to see which were 1086956cc18dSsnj * derived in a previous call. If so, we'll only warn about those if 1087956cc18dSsnj * the warning level is set to "always". 1088956cc18dSsnj */ 1089956cc18dSsnj for (j = 0; j < fMAX; ++j) { 1090956cc18dSsnj warn[j] = fwAlways; 1091956cc18dSsnj } 1092956cc18dSsnj#define CmpResource(field, index) \ 1093956cc18dSsnj if (same_font_name(screen->menu_font_names[fontnum][index], myfonts.field)) \ 1094956cc18dSsnj warn[index] = fwResource 1095956cc18dSsnj 1096956cc18dSsnj CmpResource(f_n, fNorm); 1097956cc18dSsnj if (fontnum == fontMenu_default) { 1098956cc18dSsnj CmpResource(f_b, fBold); 1099956cc18dSsnj#if OPT_WIDE_CHARS 1100956cc18dSsnj CmpResource(f_b, fWide); 1101956cc18dSsnj CmpResource(f_b, fWBold); 1102956cc18dSsnj#endif 1103956cc18dSsnj } 1104956cc18dSsnj 1105d522f475Smrg if (fontnum == fontMenu_fontescape 1106d522f475Smrg && myfonts.f_n != screen->MenuFontName(fontnum)) { 1107d522f475Smrg if ((tmpname = x_strdup(myfonts.f_n)) == 0) 1108d522f475Smrg return 0; 1109d522f475Smrg } 1110d522f475Smrg 1111d522f475Smrg TRACE(("Begin Cgs - xtermLoadFont(%s)\n", myfonts.f_n)); 1112d522f475Smrg releaseWindowGCs(xw, win); 1113d522f475Smrg 1114956cc18dSsnj#define DbgResource(name, field, index) \ 1115956cc18dSsnj TRACE(("xtermLoadFont #%d "name" %s%s\n", \ 1116956cc18dSsnj fontnum, \ 1117956cc18dSsnj (warn[index] == fwResource) ? "*" : " ", \ 1118492d43a5Smrg NonNull(myfonts.field))) 1119956cc18dSsnj DbgResource("normal", f_n, fNorm); 1120956cc18dSsnj DbgResource("bold ", f_b, fBold); 1121d522f475Smrg#if OPT_WIDE_CHARS 1122956cc18dSsnj DbgResource("wide ", f_w, fWide); 1123956cc18dSsnj DbgResource("w/bold", f_wb, fWBold); 1124d522f475Smrg#endif 1125d522f475Smrg 1126e39b573cSmrg /* 1127e39b573cSmrg * If we are opening the default font, and it happens to be missing, force 1128e39b573cSmrg * that to the compiled-in default font, e.g., "fixed". If we cannot open 1129e39b573cSmrg * the font, disable it from the menu. 1130e39b573cSmrg */ 1131e39b573cSmrg if (!xtermOpenFont(xw, 1132e39b573cSmrg myfonts.f_n, 1133e39b573cSmrg &fnts[fNorm], 1134e39b573cSmrg warn[fNorm], 1135e39b573cSmrg (fontnum == fontMenu_default))) { 113694644356Smrg if (fontnum != fontMenu_fontsel) { 113794644356Smrg SetItemSensitivity(fontMenuEntries[fontnum].widget, False); 113894644356Smrg } 1139d522f475Smrg goto bad; 1140e39b573cSmrg } 1141d522f475Smrg 11420bd37d32Smrg normal = x_strdup(myfonts.f_n); 1143956cc18dSsnj if (!check_fontname(myfonts.f_b)) { 1144956cc18dSsnj warn[fBold] = fwAlways; 11450bd37d32Smrg fp = get_font_name_props(screen->display, fnts[fNorm].fs, &normal); 1146d522f475Smrg if (fp != 0) { 11479a64e1c5Smrg FREE_FNAME(f_b); 1148d522f475Smrg myfonts.f_b = bold_font_name(fp, fp->average_width); 1149956cc18dSsnj if (!xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], fwAlways, False)) { 11509a64e1c5Smrg FREE_FNAME(f_b); 1151d522f475Smrg myfonts.f_b = bold_font_name(fp, -1); 1152956cc18dSsnj xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], fwAlways, False); 1153d522f475Smrg } 1154492d43a5Smrg TRACE(("...derived bold '%s'\n", NonNull(myfonts.f_b))); 1155d522f475Smrg } 1156d522f475Smrg if (fp == 0 || fnts[fBold].fs == 0) { 1157d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 1158d522f475Smrg TRACE(("...cannot load a matching bold font\n")); 11599a64e1c5Smrg } else if (comparable_metrics(fnts[fNorm].fs, fnts[fBold].fs) 11609a64e1c5Smrg && same_font_size(xw, fnts[fNorm].fs, fnts[fBold].fs) 1161d522f475Smrg && got_bold_font(screen->display, fnts[fBold].fs, myfonts.f_b)) { 1162d522f475Smrg TRACE(("...got a matching bold font\n")); 1163d522f475Smrg cache_menu_font_name(screen, fontnum, fBold, myfonts.f_b); 1164d522f475Smrg } else { 1165d522f475Smrg xtermCloseFont(xw, &fnts[fBold]); 1166d522f475Smrg fnts[fBold] = fnts[fNorm]; 1167d522f475Smrg TRACE(("...did not get a matching bold font\n")); 1168d522f475Smrg } 1169956cc18dSsnj } else if (!xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], warn[fBold], False)) { 1170d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 1171956cc18dSsnj warn[fBold] = fwAlways; 1172492d43a5Smrg TRACE(("...cannot load bold font '%s'\n", NonNull(myfonts.f_b))); 1173d522f475Smrg } else { 1174d522f475Smrg cache_menu_font_name(screen, fontnum, fBold, myfonts.f_b); 1175d522f475Smrg } 1176d522f475Smrg 1177d522f475Smrg /* 1178d522f475Smrg * If there is no widefont specified, fake it by doubling AVERAGE_WIDTH 1179d522f475Smrg * of normal fonts XLFD, and asking for it. This plucks out 18x18ja 1180d522f475Smrg * and 12x13ja as the corresponding fonts for 9x18 and 6x13. 1181d522f475Smrg */ 1182d522f475Smrg if_OPT_WIDE_CHARS(screen, { 11830bd37d32Smrg Boolean derived; 11840bd37d32Smrg char *bold = NULL; 1185d522f475Smrg 1186956cc18dSsnj if (check_fontname(myfonts.f_w)) { 1187d522f475Smrg cache_menu_font_name(screen, fontnum, fWide, myfonts.f_w); 1188e39b573cSmrg } else if (screen->utf8_fonts && !is_double_width_font(fnts[fNorm].fs)) { 11899a64e1c5Smrg FREE_FNAME(f_w); 11900bd37d32Smrg fp = get_font_name_props(screen->display, fnts[fNorm].fs, &normal); 1191d522f475Smrg if (fp != 0) { 1192d522f475Smrg myfonts.f_w = wide_font_name(fp); 1193956cc18dSsnj warn[fWide] = fwAlways; 1194d522f475Smrg TRACE(("...derived wide %s\n", NonNull(myfonts.f_w))); 1195d522f475Smrg cache_menu_font_name(screen, fontnum, fWide, myfonts.f_w); 1196d522f475Smrg } 1197d522f475Smrg } 1198d522f475Smrg 1199956cc18dSsnj if (check_fontname(myfonts.f_w)) { 1200956cc18dSsnj (void) xtermOpenFont(xw, myfonts.f_w, &fnts[fWide], warn[fWide], False); 1201d522f475Smrg } else { 1202d522f475Smrg xtermCopyFontInfo(&fnts[fWide], &fnts[fNorm]); 1203956cc18dSsnj warn[fWide] = fwAlways; 1204d522f475Smrg } 1205d522f475Smrg 1206d522f475Smrg derived = False; 1207956cc18dSsnj if (!check_fontname(myfonts.f_wb)) { 12080bd37d32Smrg fp = get_font_name_props(screen->display, fnts[fBold].fs, &bold); 1209d522f475Smrg if (fp != 0) { 1210d522f475Smrg myfonts.f_wb = widebold_font_name(fp); 1211956cc18dSsnj warn[fWBold] = fwAlways; 1212d522f475Smrg derived = True; 1213d522f475Smrg } 1214d522f475Smrg } 1215d522f475Smrg 1216956cc18dSsnj if (check_fontname(myfonts.f_wb)) { 1217d522f475Smrg 1218e39b573cSmrg xtermOpenFont(xw, 1219e39b573cSmrg myfonts.f_wb, 1220e39b573cSmrg &fnts[fWBold], 1221e39b573cSmrg (screen->utf8_fonts 1222e39b573cSmrg ? warn[fWBold] 12230bd37d32Smrg : (fontWarningTypes) (xw->misc.fontWarnings + 1)), 1224e39b573cSmrg False); 1225d522f475Smrg 1226d522f475Smrg if (derived 1227d522f475Smrg && !compatibleWideCounts(fnts[fWide].fs, fnts[fWBold].fs)) { 1228d522f475Smrg xtermCloseFont(xw, &fnts[fWBold]); 1229d522f475Smrg } 1230d522f475Smrg if (fnts[fWBold].fs == 0) { 12319a64e1c5Smrg FREE_FNAME(f_wb); 1232e39b573cSmrg if (IsEmpty(myfonts.f_w)) { 12339a64e1c5Smrg myfonts.f_wb = x_strdup(myfonts.f_b); 1234e39b573cSmrg warn[fWBold] = fwAlways; 1235e39b573cSmrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fBold]); 1236e39b573cSmrg TRACE(("...cannot load wide-bold, use bold %s\n", 1237e39b573cSmrg NonNull(myfonts.f_b))); 1238e39b573cSmrg } else { 12399a64e1c5Smrg myfonts.f_wb = x_strdup(myfonts.f_w); 1240e39b573cSmrg warn[fWBold] = fwAlways; 1241e39b573cSmrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1242e39b573cSmrg TRACE(("...cannot load wide-bold, use wide %s\n", 1243e39b573cSmrg NonNull(myfonts.f_w))); 1244e39b573cSmrg } 1245d522f475Smrg } else { 1246d522f475Smrg TRACE(("...%s wide/bold %s\n", 1247d522f475Smrg derived ? "derived" : "given", 1248d522f475Smrg NonNull(myfonts.f_wb))); 1249d522f475Smrg cache_menu_font_name(screen, fontnum, fWBold, myfonts.f_wb); 1250d522f475Smrg } 1251d522f475Smrg } else if (is_double_width_font(fnts[fBold].fs)) { 1252d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fBold]); 1253956cc18dSsnj warn[fWBold] = fwAlways; 1254d522f475Smrg TRACE(("...bold font is double-width, use it %s\n", NonNull(myfonts.f_b))); 1255d522f475Smrg } else { 1256d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1257956cc18dSsnj warn[fWBold] = fwAlways; 1258d522f475Smrg TRACE(("...cannot load wide bold font, use wide %s\n", NonNull(myfonts.f_w))); 1259d522f475Smrg } 1260d522f475Smrg 12610bd37d32Smrg free(bold); 12620bd37d32Smrg 1263d522f475Smrg if (EmptyFont(fnts[fWBold].fs)) 1264d522f475Smrg goto bad; /* can't use a 0-sized font */ 1265d522f475Smrg }); 1266d522f475Smrg 1267d522f475Smrg /* 1268d522f475Smrg * Most of the time this call to load the font will succeed, even if 1269d522f475Smrg * there is no wide font : the X server doubles the width of the 1270d522f475Smrg * normal font, or similar. 1271d522f475Smrg * 1272d522f475Smrg * But if it did fail for some reason, then nevermind. 1273d522f475Smrg */ 1274d522f475Smrg if (EmptyFont(fnts[fBold].fs)) 1275d522f475Smrg goto bad; /* can't use a 0-sized font */ 1276d522f475Smrg 1277d522f475Smrg if (!same_font_size(xw, fnts[fNorm].fs, fnts[fBold].fs) 1278d522f475Smrg && (is_fixed_font(fnts[fNorm].fs) && is_fixed_font(fnts[fBold].fs))) { 1279d522f475Smrg TRACE(("...ignoring mismatched normal/bold fonts\n")); 1280d522f475Smrg xtermCloseFont(xw, &fnts[fBold]); 1281d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 1282d522f475Smrg } 1283d522f475Smrg 1284d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1285d522f475Smrg if (fnts[fWide].fs != 0 1286d522f475Smrg && fnts[fWBold].fs != 0 12879a64e1c5Smrg && (!comparable_metrics(fnts[fWide].fs, fnts[fWBold].fs) 12889a64e1c5Smrg || (!same_font_size(xw, fnts[fWide].fs, fnts[fWBold].fs) 12899a64e1c5Smrg && is_fixed_font(fnts[fWide].fs) 12909a64e1c5Smrg && is_fixed_font(fnts[fWBold].fs)))) { 1291d522f475Smrg TRACE(("...ignoring mismatched normal/bold wide fonts\n")); 1292d522f475Smrg xtermCloseFont(xw, &fnts[fWBold]); 1293d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1294d522f475Smrg } 1295d522f475Smrg }); 1296d522f475Smrg 1297d522f475Smrg /* 1298d522f475Smrg * Normal/bold fonts should be the same width. Also, the min/max 1299d522f475Smrg * values should be the same. 1300d522f475Smrg */ 1301d522f475Smrg if (!is_fixed_font(fnts[fNorm].fs) 1302d522f475Smrg || !is_fixed_font(fnts[fBold].fs) 1303d522f475Smrg || fnts[fNorm].fs->max_bounds.width != fnts[fBold].fs->max_bounds.width) { 1304d522f475Smrg TRACE(("Proportional font! normal %d/%d, bold %d/%d\n", 1305d522f475Smrg fnts[fNorm].fs->min_bounds.width, 1306d522f475Smrg fnts[fNorm].fs->max_bounds.width, 1307d522f475Smrg fnts[fBold].fs->min_bounds.width, 1308d522f475Smrg fnts[fBold].fs->max_bounds.width)); 1309d522f475Smrg proportional = True; 1310d522f475Smrg } 1311d522f475Smrg 1312d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1313d522f475Smrg if (fnts[fWide].fs != 0 1314d522f475Smrg && fnts[fWBold].fs != 0 1315d522f475Smrg && (!is_fixed_font(fnts[fWide].fs) 1316d522f475Smrg || !is_fixed_font(fnts[fWBold].fs) 1317d522f475Smrg || fnts[fWide].fs->max_bounds.width != fnts[fWBold].fs->max_bounds.width)) { 1318d522f475Smrg TRACE(("Proportional font! wide %d/%d, wide bold %d/%d\n", 1319d522f475Smrg fnts[fWide].fs->min_bounds.width, 1320d522f475Smrg fnts[fWide].fs->max_bounds.width, 1321d522f475Smrg fnts[fWBold].fs->min_bounds.width, 1322d522f475Smrg fnts[fWBold].fs->max_bounds.width)); 1323d522f475Smrg proportional = True; 1324d522f475Smrg } 1325d522f475Smrg }); 1326d522f475Smrg 1327d522f475Smrg /* TODO : enforce that the width of the wide font is 2* the width 1328d522f475Smrg of the narrow font */ 1329d522f475Smrg 1330d522f475Smrg /* 1331d522f475Smrg * If we're switching fonts, free the old ones. Otherwise we'll leak 1332d522f475Smrg * the memory that is associated with the old fonts. The 1333d522f475Smrg * XLoadQueryFont call allocates a new XFontStruct. 1334d522f475Smrg */ 1335d522f475Smrg xtermCloseFonts(xw, screen->fnts); 13369a64e1c5Smrg#if OPT_WIDE_ATTRS 13379a64e1c5Smrg xtermCloseFonts(xw, screen->ifnts); 13389a64e1c5Smrg screen->ifnts_ok = False; 13399a64e1c5Smrg#endif 1340d522f475Smrg 1341d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fNorm]), &fnts[fNorm]); 1342d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fBold]), &fnts[fBold]); 1343d522f475Smrg#if OPT_WIDE_CHARS 1344d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fWide]), &fnts[fWide]); 1345d522f475Smrg if (fnts[fWBold].fs == NULL) 1346d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1347d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fWBold]), &fnts[fWBold]); 1348d522f475Smrg#endif 1349d522f475Smrg 13509a64e1c5Smrg xtermUpdateFontGCs(xw, screen->fnts); 1351d522f475Smrg 135220d2c4d2Smrg#if OPT_BOX_CHARS 135320d2c4d2Smrg screen->allow_packing = proportional; 135420d2c4d2Smrg setupPackedFonts(xw); 135520d2c4d2Smrg#endif 135620d2c4d2Smrg screen->fnt_prop = (Boolean) (proportional && !(screen->force_packed)); 1357d522f475Smrg screen->fnt_boxes = True; 1358d522f475Smrg 1359d522f475Smrg#if OPT_BOX_CHARS 1360d522f475Smrg /* 13619a64e1c5Smrg * xterm uses character positions 1-31 of a font for the line-drawing 1362d522f475Smrg * characters. Check that they are all present. The null character 1363d522f475Smrg * (0) is special, and is not used. 1364d522f475Smrg */ 1365d522f475Smrg#if OPT_RENDERFONT 1366d522f475Smrg if (UsingRenderFont(xw)) { 1367d522f475Smrg /* 1368d522f475Smrg * FIXME: we shouldn't even be here if we're using Xft. 1369d522f475Smrg */ 1370d522f475Smrg screen->fnt_boxes = False; 1371d522f475Smrg TRACE(("assume Xft missing line-drawing chars\n")); 1372d522f475Smrg } else 1373d522f475Smrg#endif 1374d522f475Smrg { 1375d522f475Smrg unsigned ch; 1376d522f475Smrg 13779a64e1c5Smrg#if OPT_TRACE 13789a64e1c5Smrg#define TRACE_MISS(index) show_font_misses(#index, &fnts[index]) 13799a64e1c5Smrg TRACE_MISS(fNorm); 13809a64e1c5Smrg TRACE_MISS(fBold); 13819a64e1c5Smrg#if OPT_WIDE_CHARS 13829a64e1c5Smrg TRACE_MISS(fWide); 13839a64e1c5Smrg TRACE_MISS(fWBold); 13849a64e1c5Smrg#endif 13859a64e1c5Smrg#endif 1386fa3f02f3Smrg 1387d522f475Smrg for (ch = 1; ch < 32; ch++) { 1388d522f475Smrg unsigned n = ch; 1389d522f475Smrg#if OPT_WIDE_CHARS 1390d522f475Smrg if (screen->utf8_mode || screen->unicode_font) { 1391d522f475Smrg n = dec2ucs(ch); 1392d522f475Smrg if (n == UCS_REPL) 1393d522f475Smrg continue; 1394d522f475Smrg } 1395d522f475Smrg#endif 1396956cc18dSsnj if (IsXtermMissingChar(screen, n, &fnts[fNorm])) { 1397d522f475Smrg TRACE(("missing normal char #%d\n", n)); 1398d522f475Smrg screen->fnt_boxes = False; 1399d522f475Smrg break; 1400d522f475Smrg } 1401956cc18dSsnj if (IsXtermMissingChar(screen, n, &fnts[fBold])) { 1402d522f475Smrg TRACE(("missing bold char #%d\n", n)); 1403d522f475Smrg screen->fnt_boxes = False; 1404d522f475Smrg break; 1405d522f475Smrg } 1406d522f475Smrg } 1407d522f475Smrg } 1408d522f475Smrg TRACE(("Will %suse internal line-drawing characters\n", 1409d522f475Smrg screen->fnt_boxes ? "not " : "")); 1410d522f475Smrg#endif 1411d522f475Smrg 1412d522f475Smrg if (screen->always_bold_mode) { 1413d522f475Smrg screen->enbolden = screen->bold_mode; 1414d522f475Smrg } else { 1415d522f475Smrg screen->enbolden = screen->bold_mode 1416d522f475Smrg && ((fnts[fNorm].fs == fnts[fBold].fs) 1417d522f475Smrg || same_font_name(normal, myfonts.f_b)); 1418d522f475Smrg } 1419d522f475Smrg TRACE(("Will %suse 1-pixel offset/overstrike to simulate bold\n", 1420d522f475Smrg screen->enbolden ? "" : "not ")); 1421d522f475Smrg 1422d522f475Smrg set_menu_font(False); 1423d522f475Smrg screen->menu_font_number = fontnum; 1424d522f475Smrg set_menu_font(True); 1425d522f475Smrg if (tmpname) { /* if setting escape or sel */ 1426d522f475Smrg if (screen->MenuFontName(fontnum)) 14279a64e1c5Smrg FREE_STRING(screen->MenuFontName(fontnum)); 1428d522f475Smrg screen->MenuFontName(fontnum) = tmpname; 1429d522f475Smrg if (fontnum == fontMenu_fontescape) { 143094644356Smrg update_font_escape(); 1431d522f475Smrg } 1432d522f475Smrg#if OPT_SHIFT_FONTS 1433d522f475Smrg screen->menu_font_sizes[fontnum] = FontSize(fnts[fNorm].fs); 1434d522f475Smrg#endif 1435d522f475Smrg } 14360bd37d32Smrg if (normal) 14370bd37d32Smrg free(normal); 1438d522f475Smrg set_cursor_gcs(xw); 1439d522f475Smrg xtermUpdateFontInfo(xw, doresize); 1440d522f475Smrg TRACE(("Success Cgs - xtermLoadFont\n")); 1441fa3f02f3Smrg#if OPT_REPORT_FONTS 1442fa3f02f3Smrg reportVTFontInfo(xw, fontnum); 14439a64e1c5Smrg#endif 14449a64e1c5Smrg FREE_FNAME(f_n); 14459a64e1c5Smrg FREE_FNAME(f_b); 14469a64e1c5Smrg#if OPT_WIDE_CHARS 14479a64e1c5Smrg FREE_FNAME(f_w); 14489a64e1c5Smrg FREE_FNAME(f_wb); 14499a64e1c5Smrg#endif 14509a64e1c5Smrg if (fnts[fNorm].fn == fnts[fBold].fn) { 14519a64e1c5Smrg free(fnts[fNorm].fn); 14529a64e1c5Smrg } else { 14539a64e1c5Smrg free(fnts[fNorm].fn); 14549a64e1c5Smrg free(fnts[fBold].fn); 14559a64e1c5Smrg } 14569a64e1c5Smrg#if OPT_WIDE_CHARS 14579a64e1c5Smrg free(fnts[fWide].fn); 14589a64e1c5Smrg free(fnts[fWBold].fn); 1459fa3f02f3Smrg#endif 1460d522f475Smrg return 1; 1461d522f475Smrg 1462d522f475Smrg bad: 14630bd37d32Smrg if (normal) 14640bd37d32Smrg free(normal); 1465d522f475Smrg if (tmpname) 1466d522f475Smrg free(tmpname); 14670bd37d32Smrg 14680bd37d32Smrg#if OPT_RENDERFONT 146994644356Smrg if ((fontnum == fontMenu_fontsel) && (fontnum != screen->menu_font_number)) { 14709a64e1c5Smrg int old_fontnum = screen->menu_font_number; 14719a64e1c5Smrg#if OPT_TOOLBAR 14729a64e1c5Smrg SetItemSensitivity(fontMenuEntries[fontnum].widget, True); 14739a64e1c5Smrg#endif 14749a64e1c5Smrg Bell(xw, XkbBI_MinorError, 0); 14759a64e1c5Smrg myfonts.f_n = screen->MenuFontName(old_fontnum); 14769a64e1c5Smrg return xtermLoadFont(xw, &myfonts, doresize, old_fontnum); 14779a64e1c5Smrg } else if (x_strcasecmp(myfonts.f_n, DEFFONT)) { 14780bd37d32Smrg int code; 14790bd37d32Smrg 14800bd37d32Smrg myfonts.f_n = DEFFONT; 14810bd37d32Smrg TRACE(("...recovering for TrueType fonts\n")); 14820bd37d32Smrg code = xtermLoadFont(xw, &myfonts, doresize, fontnum); 14830bd37d32Smrg if (code) { 148494644356Smrg if (fontnum != fontMenu_fontsel) { 148594644356Smrg SetItemSensitivity(fontMenuEntries[fontnum].widget, 148694644356Smrg UsingRenderFont(xw)); 148794644356Smrg } 14880bd37d32Smrg TRACE(("...recovered size %dx%d\n", 14890bd37d32Smrg FontHeight(screen), 14900bd37d32Smrg FontWidth(screen))); 14910bd37d32Smrg } 14920bd37d32Smrg return code; 14930bd37d32Smrg } 14940bd37d32Smrg#endif 14950bd37d32Smrg 1496d522f475Smrg releaseWindowGCs(xw, win); 1497d522f475Smrg 1498d522f475Smrg xtermCloseFonts(xw, fnts); 1499d522f475Smrg TRACE(("Fail Cgs - xtermLoadFont\n")); 1500d522f475Smrg return 0; 1501d522f475Smrg} 1502d522f475Smrg 15039a64e1c5Smrg#if OPT_WIDE_ATTRS 15049a64e1c5Smrg/* 15059a64e1c5Smrg * (Attempt to) load matching italics for the current normal/bold/etc fonts. 15069a64e1c5Smrg * If the attempt fails for a given style, use the non-italic font. 15079a64e1c5Smrg */ 15089a64e1c5Smrgvoid 15099a64e1c5SmrgxtermLoadItalics(XtermWidget xw) 15109a64e1c5Smrg{ 15119a64e1c5Smrg TScreen *screen = TScreenOf(xw); 15129a64e1c5Smrg FontNameProperties *fp; 15139a64e1c5Smrg char *name; 15149a64e1c5Smrg int n; 15159a64e1c5Smrg 15169a64e1c5Smrg if (!screen->ifnts_ok) { 15179a64e1c5Smrg screen->ifnts_ok = True; 15189a64e1c5Smrg for (n = 0; n < fMAX; ++n) { 15199a64e1c5Smrg /* 15209a64e1c5Smrg * FIXME - need to handle font-leaks 15219a64e1c5Smrg */ 15229a64e1c5Smrg screen->ifnts[n].fs = 0; 15239a64e1c5Smrg if (screen->fnts[n].fs != 0 && 15249a64e1c5Smrg (fp = get_font_name_props(screen->display, 15259a64e1c5Smrg screen->fnts[n].fs, 15269a64e1c5Smrg 0)) != 0) { 15279a64e1c5Smrg if ((name = italic_font_name(fp, fp->average_width)) != 0) { 15289a64e1c5Smrg TRACE(("xtermLoadItalics #%d %s\n", n, name)); 15299a64e1c5Smrg (void) xtermOpenFont(xw, 15309a64e1c5Smrg name, 15319a64e1c5Smrg &(screen->ifnts[n]), 15329a64e1c5Smrg fwResource, 15339a64e1c5Smrg False); 15349a64e1c5Smrg#if OPT_TRACE 15359a64e1c5Smrg { 15369a64e1c5Smrg XFontStruct *fs = 15379a64e1c5Smrg screen->ifnts[n].fs; 15389a64e1c5Smrg if (fs != 0) { 15399a64e1c5Smrg TRACE(("...actual size %dx%d (ascent %d, descent %d)\n", 15409a64e1c5Smrg fs->ascent + 15419a64e1c5Smrg fs->descent, 15429a64e1c5Smrg fs->max_bounds.width, 15439a64e1c5Smrg fs->ascent, 15449a64e1c5Smrg fs->descent)); 15459a64e1c5Smrg } 15469a64e1c5Smrg } 15479a64e1c5Smrg#endif 15489a64e1c5Smrg free(name); 15499a64e1c5Smrg } 15509a64e1c5Smrg } 15519a64e1c5Smrg } 15529a64e1c5Smrg } 15539a64e1c5Smrg} 15549a64e1c5Smrg#endif 15559a64e1c5Smrg 1556d522f475Smrg#if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS 1557d522f475Smrg/* 1558d522f475Smrg * Collect font-names that we can modify with the load-vt-fonts() action. 1559d522f475Smrg */ 1560d522f475Smrg#define MERGE_SUBFONT(src,dst,name) \ 1561492d43a5Smrg if (IsEmpty(dst.name)) { \ 1562d522f475Smrg TRACE(("MERGE_SUBFONT " #dst "." #name " merge %s\n", NonNull(src.name))); \ 15639a64e1c5Smrg dst.name = x_strdup(src.name); \ 1564d522f475Smrg } else { \ 1565d522f475Smrg TRACE(("MERGE_SUBFONT " #dst "." #name " found %s\n", NonNull(dst.name))); \ 1566d522f475Smrg } 1567d522f475Smrg 1568e39b573cSmrg#define INFER_SUBFONT(src,dst,name) \ 1569e39b573cSmrg if (IsEmpty(dst.name)) { \ 1570e39b573cSmrg TRACE(("INFER_SUBFONT " #dst "." #name " will infer\n")); \ 1571e39b573cSmrg dst.name = x_strdup(""); \ 1572e39b573cSmrg } else { \ 1573e39b573cSmrg TRACE(("INFER_SUBFONT " #dst "." #name " found %s\n", NonNull(dst.name))); \ 1574e39b573cSmrg } 1575e39b573cSmrg 15769a64e1c5Smrg#define FREE_MENU_FONTS(dst) \ 15779a64e1c5Smrg TRACE(("FREE_MENU_FONTS " #dst "\n")); \ 15789a64e1c5Smrg for (n = fontMenu_default; n <= fontMenu_lastBuiltin; ++n) { \ 15799a64e1c5Smrg for (m = 0; m < fMAX; ++m) { \ 15809a64e1c5Smrg FREE_STRING(dst.menu_font_names[n][m]); \ 15819a64e1c5Smrg dst.menu_font_names[n][m] = 0; \ 15829a64e1c5Smrg } \ 15839a64e1c5Smrg } 15849a64e1c5Smrg 1585d522f475Smrg#define COPY_MENU_FONTS(src,dst) \ 1586d522f475Smrg TRACE(("COPY_MENU_FONTS " #src " to " #dst "\n")); \ 1587d522f475Smrg for (n = fontMenu_default; n <= fontMenu_lastBuiltin; ++n) { \ 1588d522f475Smrg for (m = 0; m < fMAX; ++m) { \ 15899a64e1c5Smrg FREE_STRING(dst.menu_font_names[n][m]); \ 1590492d43a5Smrg dst.menu_font_names[n][m] = x_strdup(src.menu_font_names[n][m]); \ 1591d522f475Smrg } \ 159294644356Smrg TRACE((".. " #dst ".menu_fonts_names[%d] = %s\n", n, NonNull(dst.menu_font_names[n][fNorm]))); \ 1593e39b573cSmrg } 1594e39b573cSmrg 15959a64e1c5Smrg#define COPY_DEFAULT_FONTS(target, source) \ 15969a64e1c5Smrg xtermCopyVTFontNames(&target.default_font, &source.default_font) 15979a64e1c5Smrg 15989a64e1c5Smrgstatic void 15999a64e1c5SmrgxtermCopyVTFontNames(VTFontNames * target, VTFontNames * source) 16009a64e1c5Smrg{ 16019a64e1c5Smrg target->f_n = x_strdup(source->f_n); 16029a64e1c5Smrg target->f_b = x_strdup(source->f_b); 16039a64e1c5Smrg#if OPT_WIDE_CHARS 16049a64e1c5Smrg target->f_w = x_strdup(source->f_w); 16059a64e1c5Smrg target->f_wb = x_strdup(source->f_wb); 16069a64e1c5Smrg#endif 16079a64e1c5Smrg} 16089a64e1c5Smrg 1609e39b573cSmrgvoid 1610e39b573cSmrgxtermSaveVTFonts(XtermWidget xw) 1611e39b573cSmrg{ 1612e39b573cSmrg TScreen *screen = TScreenOf(xw); 1613e39b573cSmrg Cardinal n, m; 1614e39b573cSmrg 1615e39b573cSmrg if (!screen->savedVTFonts) { 1616e39b573cSmrg 1617e39b573cSmrg screen->savedVTFonts = True; 1618e39b573cSmrg TRACE(("xtermSaveVTFonts saving original\n")); 16199a64e1c5Smrg COPY_DEFAULT_FONTS(screen->cacheVTFonts, xw->misc); 1620e39b573cSmrg COPY_MENU_FONTS(xw->screen, screen->cacheVTFonts); 1621e39b573cSmrg } 1622e39b573cSmrg} 1623e39b573cSmrg 1624e39b573cSmrg#define SAME_STRING(x,y) ((x) == (y) || ((x) && (y) && !strcmp(x, y))) 1625e39b573cSmrg#define SAME_MEMBER(n) SAME_STRING(a->n, b->n) 1626e39b573cSmrg 1627e39b573cSmrgstatic Boolean 1628e39b573cSmrgsameSubResources(SubResourceRec * a, SubResourceRec * b) 1629e39b573cSmrg{ 1630e39b573cSmrg Boolean result = True; 1631e39b573cSmrg int n; 1632e39b573cSmrg 1633e39b573cSmrg if (!SAME_MEMBER(default_font.f_n) 1634e39b573cSmrg || !SAME_MEMBER(default_font.f_b) 16350bd37d32Smrg#if OPT_WIDE_CHARS 1636e39b573cSmrg || !SAME_MEMBER(default_font.f_w) 16370bd37d32Smrg || !SAME_MEMBER(default_font.f_wb) 16380bd37d32Smrg#endif 16390bd37d32Smrg ) { 1640e39b573cSmrg TRACE(("sameSubResources: default_font differs\n")); 1641e39b573cSmrg result = False; 1642e39b573cSmrg } else { 1643e39b573cSmrg for (n = 0; n < NMENUFONTS; ++n) { 1644e39b573cSmrg if (!SAME_MEMBER(menu_font_names[n][fNorm])) { 1645e39b573cSmrg TRACE(("sameSubResources: menu_font_names[%d] differs\n", n)); 1646e39b573cSmrg result = False; 1647e39b573cSmrg break; 1648e39b573cSmrg } 1649d522f475Smrg } 1650e39b573cSmrg } 1651e39b573cSmrg 1652e39b573cSmrg return result; 1653e39b573cSmrg} 1654d522f475Smrg 1655d522f475Smrg/* 1656d522f475Smrg * Load the "VT" font names from the given subresource name/class. These 1657d522f475Smrg * correspond to the VT100 resources. 1658d522f475Smrg */ 1659d522f475Smrgstatic Bool 166020d2c4d2SmrgxtermLoadVTFonts(XtermWidget xw, String myName, String myClass) 1661d522f475Smrg{ 1662e39b573cSmrg SubResourceRec subresourceRec; 1663e39b573cSmrg SubResourceRec referenceRec; 1664d522f475Smrg 1665d522f475Smrg /* 1666d522f475Smrg * These are duplicates of the VT100 font resources, but with a special 1667d522f475Smrg * application/classname passed in to distinguish them. 1668d522f475Smrg */ 1669d522f475Smrg static XtResource font_resources[] = 1670d522f475Smrg { 1671d522f475Smrg Sres(XtNfont, XtCFont, default_font.f_n, DEFFONT), 1672d522f475Smrg Sres(XtNboldFont, XtCBoldFont, default_font.f_b, DEFBOLDFONT), 1673d522f475Smrg#if OPT_WIDE_CHARS 1674d522f475Smrg Sres(XtNwideFont, XtCWideFont, default_font.f_w, DEFWIDEFONT), 1675d522f475Smrg Sres(XtNwideBoldFont, XtCWideBoldFont, default_font.f_wb, DEFWIDEBOLDFONT), 1676d522f475Smrg#endif 1677d522f475Smrg Sres(XtNfont1, XtCFont1, MenuFontName(fontMenu_font1), NULL), 1678d522f475Smrg Sres(XtNfont2, XtCFont2, MenuFontName(fontMenu_font2), NULL), 1679d522f475Smrg Sres(XtNfont3, XtCFont3, MenuFontName(fontMenu_font3), NULL), 1680d522f475Smrg Sres(XtNfont4, XtCFont4, MenuFontName(fontMenu_font4), NULL), 1681d522f475Smrg Sres(XtNfont5, XtCFont5, MenuFontName(fontMenu_font5), NULL), 1682d522f475Smrg Sres(XtNfont6, XtCFont6, MenuFontName(fontMenu_font6), NULL), 1683d522f475Smrg }; 1684d522f475Smrg Cardinal n, m; 1685d522f475Smrg Bool status = True; 1686956cc18dSsnj TScreen *screen = TScreenOf(xw); 1687d522f475Smrg 1688e39b573cSmrg TRACE(("called xtermLoadVTFonts(name=%s, class=%s)\n", 1689e39b573cSmrg NonNull(myName), NonNull(myClass))); 1690d522f475Smrg 1691e39b573cSmrg xtermSaveVTFonts(xw); 1692d522f475Smrg 1693492d43a5Smrg if (IsEmpty(myName)) { 1694d522f475Smrg TRACE(("xtermLoadVTFonts restoring original\n")); 16959a64e1c5Smrg COPY_DEFAULT_FONTS(xw->misc, screen->cacheVTFonts); 16969a64e1c5Smrg FREE_MENU_FONTS(xw->screen); 1697e39b573cSmrg COPY_MENU_FONTS(screen->cacheVTFonts, xw->screen); 1698d522f475Smrg } else { 1699d522f475Smrg TRACE(("xtermLoadVTFonts(%s, %s)\n", myName, myClass)); 1700d522f475Smrg 1701e39b573cSmrg memset(&referenceRec, 0, sizeof(referenceRec)); 1702d522f475Smrg memset(&subresourceRec, 0, sizeof(subresourceRec)); 1703956cc18dSsnj XtGetSubresources((Widget) xw, (XtPointer) &subresourceRec, 1704d522f475Smrg myName, myClass, 1705d522f475Smrg font_resources, 1706d522f475Smrg (Cardinal) XtNumber(font_resources), 1707d522f475Smrg NULL, (Cardinal) 0); 1708d522f475Smrg 1709e39b573cSmrg /* 1710e39b573cSmrg * XtGetSubresources returns no status, so we compare the returned 1711e39b573cSmrg * data against a zero'd struct to see if any data is returned. 1712e39b573cSmrg */ 1713e39b573cSmrg if (memcmp(&referenceRec, &subresourceRec, sizeof(referenceRec)) 1714e39b573cSmrg && !sameSubResources(&(screen->cacheVTFonts), &subresourceRec)) { 1715e39b573cSmrg 1716e39b573cSmrg screen->mergedVTFonts = True; 1717d522f475Smrg 17189a64e1c5Smrg /* 17199a64e1c5Smrg * To make it simple, reallocate the strings returned by 17209a64e1c5Smrg * XtGetSubresources. We can free our own strings, but not theirs. 17219a64e1c5Smrg */ 17229a64e1c5Smrg ALLOC_STRING(subresourceRec.default_font.f_n); 17239a64e1c5Smrg ALLOC_STRING(subresourceRec.default_font.f_b); 17249a64e1c5Smrg#if OPT_WIDE_CHARS 17259a64e1c5Smrg ALLOC_STRING(subresourceRec.default_font.f_w); 17269a64e1c5Smrg ALLOC_STRING(subresourceRec.default_font.f_wb); 17279a64e1c5Smrg#endif 17289a64e1c5Smrg for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; ++n) { 17299a64e1c5Smrg ALLOC_STRING(subresourceRec.MenuFontName(n)); 17309a64e1c5Smrg } 17319a64e1c5Smrg 1732d522f475Smrg /* 1733d522f475Smrg * If a particular resource value was not found, use the original. 1734d522f475Smrg */ 1735956cc18dSsnj MERGE_SUBFONT(xw->misc, subresourceRec, default_font.f_n); 1736e39b573cSmrg INFER_SUBFONT(xw->misc, subresourceRec, default_font.f_b); 1737d522f475Smrg#if OPT_WIDE_CHARS 1738e39b573cSmrg INFER_SUBFONT(xw->misc, subresourceRec, default_font.f_w); 1739e39b573cSmrg INFER_SUBFONT(xw->misc, subresourceRec, default_font.f_wb); 1740d522f475Smrg#endif 17419a64e1c5Smrg for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; ++n) { 1742956cc18dSsnj MERGE_SUBFONT(xw->screen, subresourceRec, MenuFontName(n)); 17439a64e1c5Smrg } 1744d522f475Smrg 1745d522f475Smrg /* 1746d522f475Smrg * Finally, copy the subresource data to the widget. 1747d522f475Smrg */ 17489a64e1c5Smrg COPY_DEFAULT_FONTS(xw->misc, subresourceRec); 17499a64e1c5Smrg FREE_MENU_FONTS(xw->screen); 1750956cc18dSsnj COPY_MENU_FONTS(subresourceRec, xw->screen); 17519a64e1c5Smrg 17529a64e1c5Smrg FREE_STRING(screen->MenuFontName(fontMenu_default)); 17539a64e1c5Smrg FREE_STRING(screen->menu_font_names[0][fBold]); 1754492d43a5Smrg screen->MenuFontName(fontMenu_default) = x_strdup(xw->misc.default_font.f_n); 1755492d43a5Smrg screen->menu_font_names[0][fBold] = x_strdup(xw->misc.default_font.f_b); 1756d522f475Smrg#if OPT_WIDE_CHARS 17579a64e1c5Smrg FREE_STRING(screen->menu_font_names[0][fWide]); 17589a64e1c5Smrg FREE_STRING(screen->menu_font_names[0][fWBold]); 1759492d43a5Smrg screen->menu_font_names[0][fWide] = x_strdup(xw->misc.default_font.f_w); 1760492d43a5Smrg screen->menu_font_names[0][fWBold] = x_strdup(xw->misc.default_font.f_wb); 1761d522f475Smrg#endif 17629a64e1c5Smrg /* 17639a64e1c5Smrg * And remove our copies of strings. 17649a64e1c5Smrg */ 17659a64e1c5Smrg FREE_STRING(subresourceRec.default_font.f_n); 17669a64e1c5Smrg FREE_STRING(subresourceRec.default_font.f_b); 17679a64e1c5Smrg#if OPT_WIDE_CHARS 17689a64e1c5Smrg FREE_STRING(subresourceRec.default_font.f_w); 17699a64e1c5Smrg FREE_STRING(subresourceRec.default_font.f_wb); 17709a64e1c5Smrg#endif 17719a64e1c5Smrg for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; ++n) { 17729a64e1c5Smrg FREE_STRING(subresourceRec.MenuFontName(n)); 17739a64e1c5Smrg } 1774d522f475Smrg } else { 1775d522f475Smrg TRACE(("...no resources found\n")); 1776d522f475Smrg status = False; 1777d522f475Smrg } 1778d522f475Smrg } 1779d522f475Smrg return status; 1780d522f475Smrg} 1781d522f475Smrg 1782d522f475Smrg#if OPT_WIDE_CHARS 1783d522f475Smrgstatic Bool 17849a64e1c5SmrgisWideFont(XFontStruct *fp, const char *tag, Bool nullOk) 1785d522f475Smrg{ 1786d522f475Smrg Bool result = False; 1787d522f475Smrg 1788d522f475Smrg (void) tag; 1789d522f475Smrg if (okFont(fp)) { 1790d522f475Smrg unsigned count = countGlyphs(fp); 1791d522f475Smrg TRACE(("isWideFont(%s) found %d cells\n", tag, count)); 1792d522f475Smrg result = (count > 256) ? True : False; 1793d522f475Smrg } else { 1794d522f475Smrg result = nullOk; 1795d522f475Smrg } 1796d522f475Smrg return result; 1797d522f475Smrg} 1798d522f475Smrg 1799d522f475Smrg/* 1800d522f475Smrg * If the current fonts are not wide, load the UTF8 fonts. 1801d522f475Smrg * 1802d522f475Smrg * Called during initialization (for wide-character mode), the fonts have not 1803d522f475Smrg * been setup, so we pass nullOk=True to isWideFont(). 1804d522f475Smrg * 1805d522f475Smrg * Called after initialization, e.g., in response to the UTF-8 menu entry 1806d522f475Smrg * (starting from narrow character mode), it checks if the fonts are not wide. 1807d522f475Smrg */ 1808d522f475SmrgBool 1809d522f475SmrgxtermLoadWideFonts(XtermWidget xw, Bool nullOk) 1810d522f475Smrg{ 1811956cc18dSsnj TScreen *screen = TScreenOf(xw); 1812d522f475Smrg Bool result; 1813d522f475Smrg 1814d522f475Smrg if (EmptyFont(screen->fnts[fWide].fs)) { 1815d522f475Smrg result = (isWideFont(screen->fnts[fNorm].fs, "normal", nullOk) 1816d522f475Smrg && isWideFont(screen->fnts[fBold].fs, "bold", nullOk)); 1817d522f475Smrg } else { 1818d522f475Smrg result = (isWideFont(screen->fnts[fWide].fs, "wide", nullOk) 1819d522f475Smrg && isWideFont(screen->fnts[fWBold].fs, "wide-bold", nullOk)); 1820d522f475Smrg if (result && !screen->utf8_latin1) { 1821d522f475Smrg result = (isWideFont(screen->fnts[fNorm].fs, "normal", nullOk) 1822d522f475Smrg && isWideFont(screen->fnts[fBold].fs, "bold", nullOk)); 1823d522f475Smrg } 1824d522f475Smrg } 1825d522f475Smrg if (!result) { 1826d522f475Smrg TRACE(("current fonts are not all wide%s\n", nullOk ? " nullOk" : "")); 1827e39b573cSmrg result = xtermLoadVTFonts(xw, XtNutf8Fonts, XtCUtf8Fonts); 1828d522f475Smrg } 1829d522f475Smrg TRACE(("xtermLoadWideFonts:%d\n", result)); 1830d522f475Smrg return result; 1831d522f475Smrg} 1832d522f475Smrg#endif /* OPT_WIDE_CHARS */ 1833d522f475Smrg 1834d522f475Smrg/* 1835d522f475Smrg * Restore the default fonts, i.e., if we had switched to wide-fonts. 1836d522f475Smrg */ 1837d522f475SmrgBool 1838956cc18dSsnjxtermLoadDefaultFonts(XtermWidget xw) 1839d522f475Smrg{ 1840d522f475Smrg Bool result; 1841956cc18dSsnj result = xtermLoadVTFonts(xw, NULL, NULL); 1842d522f475Smrg TRACE(("xtermLoadDefaultFonts:%d\n", result)); 1843d522f475Smrg return result; 1844d522f475Smrg} 1845d522f475Smrg#endif /* OPT_LOAD_VTFONTS || OPT_WIDE_CHARS */ 1846d522f475Smrg 1847d522f475Smrg#if OPT_LOAD_VTFONTS 1848d522f475Smrgvoid 1849d522f475SmrgHandleLoadVTFonts(Widget w, 18509a64e1c5Smrg XEvent *event GCC_UNUSED, 1851fa3f02f3Smrg String *params GCC_UNUSED, 1852d522f475Smrg Cardinal *param_count GCC_UNUSED) 1853d522f475Smrg{ 1854d522f475Smrg static char empty[] = ""; /* appease strict compilers */ 1855d522f475Smrg 1856956cc18dSsnj XtermWidget xw; 1857956cc18dSsnj 1858956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 1859956cc18dSsnj TScreen *screen = TScreenOf(xw); 1860492d43a5Smrg char name_buf[80]; 1861492d43a5Smrg char class_buf[80]; 1862492d43a5Smrg String name = (String) ((*param_count > 0) ? params[0] : empty); 186394644356Smrg char *myName = MyStackAlloc(strlen(name) + 1, name_buf); 1864d522f475Smrg 1865d522f475Smrg TRACE(("HandleLoadVTFonts(%d)\n", *param_count)); 186694644356Smrg if (myName != 0) { 186794644356Smrg String convert = (String) ((*param_count > 1) ? params[1] : myName); 186894644356Smrg char *myClass = MyStackAlloc(strlen(convert) + 1, class_buf); 186994644356Smrg int n; 187094644356Smrg 187194644356Smrg strcpy(myName, name); 187294644356Smrg if (myClass != 0) { 187394644356Smrg strcpy(myClass, convert); 187494644356Smrg if (*param_count == 1) 187594644356Smrg myClass[0] = x_toupper(myClass[0]); 187694644356Smrg 187794644356Smrg if (xtermLoadVTFonts(xw, myName, myClass)) { 187894644356Smrg /* 187994644356Smrg * When switching fonts, try to preserve the font-menu 188094644356Smrg * selection, since it is less surprising to do that (if 188194644356Smrg * the font-switching can be undone) than to switch to 188294644356Smrg * "Default". 188394644356Smrg */ 188494644356Smrg int font_number = screen->menu_font_number; 188594644356Smrg if (font_number > fontMenu_lastBuiltin) 188694644356Smrg font_number = fontMenu_lastBuiltin; 188794644356Smrg for (n = 0; n < NMENUFONTS; ++n) { 188894644356Smrg screen->menu_font_sizes[n] = 0; 188994644356Smrg } 189094644356Smrg SetVTFont(xw, font_number, True, 189194644356Smrg ((font_number == fontMenu_default) 189294644356Smrg ? &(xw->misc.default_font) 189394644356Smrg : NULL)); 189494644356Smrg } 189594644356Smrg MyStackFree(myClass, class_buf); 18969a64e1c5Smrg } 189794644356Smrg MyStackFree(myName, name_buf); 1898d522f475Smrg } 1899d522f475Smrg } 1900d522f475Smrg} 1901d522f475Smrg#endif /* OPT_LOAD_VTFONTS */ 1902d522f475Smrg 1903d522f475Smrg/* 1904d522f475Smrg * Set the limits for the box that outlines the cursor. 1905d522f475Smrg */ 1906d522f475Smrgvoid 1907fa3f02f3SmrgxtermSetCursorBox(TScreen *screen) 1908d522f475Smrg{ 1909d522f475Smrg static XPoint VTbox[NBOX]; 1910d522f475Smrg XPoint *vp; 19112eaa94a1Schristos int fw = FontWidth(screen) - 1; 19122eaa94a1Schristos int fh = FontHeight(screen) - 1; 19130bd37d32Smrg int ww = isCursorBar(screen) ? 1 : fw; 19140bd37d32Smrg int hh = isCursorUnderline(screen) ? 1 : fh; 1915d522f475Smrg 1916d522f475Smrg vp = &VTbox[1]; 19170bd37d32Smrg (vp++)->x = (short) ww; 19182eaa94a1Schristos (vp++)->y = (short) hh; 19190bd37d32Smrg (vp++)->x = (short) -ww; 19202eaa94a1Schristos vp->y = (short) -hh; 19212eaa94a1Schristos 1922d522f475Smrg screen->box = VTbox; 1923d522f475Smrg} 1924d522f475Smrg 1925d522f475Smrg#define CACHE_XFT(dst,src) if (src != 0) {\ 1926956cc18dSsnj checkXft(xw, &(dst[fontnum]), src);\ 19270bd37d32Smrg TRACE(("Xft metrics %s[%d] = %d (%d,%d)%s advance %d, actual %d%s\n",\ 1928d522f475Smrg #dst,\ 1929d522f475Smrg fontnum,\ 1930d522f475Smrg src->height,\ 1931d522f475Smrg src->ascent,\ 1932d522f475Smrg src->descent,\ 19330bd37d32Smrg ((src->ascent + src->descent) > src->height ? "*" : ""),\ 1934956cc18dSsnj src->max_advance_width,\ 1935956cc18dSsnj dst[fontnum].map.min_width,\ 1936956cc18dSsnj dst[fontnum].map.mixed ? " mixed" : ""));\ 1937d522f475Smrg } 1938d522f475Smrg 1939d522f475Smrg#if OPT_RENDERFONT 1940956cc18dSsnj 194120d2c4d2Smrgstatic FcChar32 19429a64e1c5SmrgxtermXftFirstChar(XftFont *xft) 194320d2c4d2Smrg{ 194420d2c4d2Smrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 194520d2c4d2Smrg FcChar32 next; 194620d2c4d2Smrg FcChar32 first; 194720d2c4d2Smrg int i; 194820d2c4d2Smrg 194920d2c4d2Smrg first = FcCharSetFirstPage(xft->charset, map, &next); 19509a64e1c5Smrg for (i = 0; i < FC_CHARSET_MAP_SIZE; i++) { 195120d2c4d2Smrg if (map[i]) { 195220d2c4d2Smrg FcChar32 bits = map[i]; 1953fa3f02f3Smrg first += (FcChar32) i *32; 195420d2c4d2Smrg while (!(bits & 0x1)) { 195520d2c4d2Smrg bits >>= 1; 195620d2c4d2Smrg first++; 195720d2c4d2Smrg } 195820d2c4d2Smrg break; 195920d2c4d2Smrg } 19609a64e1c5Smrg } 196120d2c4d2Smrg return first; 196220d2c4d2Smrg} 196320d2c4d2Smrg 196420d2c4d2Smrgstatic FcChar32 19659a64e1c5SmrgxtermXftLastChar(XftFont *xft) 196620d2c4d2Smrg{ 196720d2c4d2Smrg FcChar32 this, last, next; 196820d2c4d2Smrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 196920d2c4d2Smrg int i; 197020d2c4d2Smrg last = FcCharSetFirstPage(xft->charset, map, &next); 197120d2c4d2Smrg while ((this = FcCharSetNextPage(xft->charset, map, &next)) != FC_CHARSET_DONE) 197220d2c4d2Smrg last = this; 1973fa3f02f3Smrg last &= (FcChar32) ~ 0xff; 19749a64e1c5Smrg for (i = FC_CHARSET_MAP_SIZE - 1; i >= 0; i--) { 197520d2c4d2Smrg if (map[i]) { 197620d2c4d2Smrg FcChar32 bits = map[i]; 1977fa3f02f3Smrg last += (FcChar32) i *32 + 31; 197820d2c4d2Smrg while (!(bits & 0x80000000)) { 197920d2c4d2Smrg last--; 198020d2c4d2Smrg bits <<= 1; 198120d2c4d2Smrg } 198220d2c4d2Smrg break; 198320d2c4d2Smrg } 19849a64e1c5Smrg } 198520d2c4d2Smrg return (long) last; 198620d2c4d2Smrg} 198720d2c4d2Smrg 1988fa3f02f3Smrg#if OPT_TRACE > 1 198920d2c4d2Smrgstatic void 19909a64e1c5SmrgdumpXft(XtermWidget xw, XTermXftFonts *data) 199120d2c4d2Smrg{ 199220d2c4d2Smrg XftFont *xft = data->font; 199320d2c4d2Smrg TScreen *screen = TScreenOf(xw); 199420d2c4d2Smrg VTwin *win = WhichVWin(screen); 199520d2c4d2Smrg 199620d2c4d2Smrg FcChar32 c; 199720d2c4d2Smrg FcChar32 first = xtermXftFirstChar(xft); 199820d2c4d2Smrg FcChar32 last = xtermXftLastChar(xft); 199920d2c4d2Smrg unsigned count = 0; 200020d2c4d2Smrg unsigned outside = 0; 200120d2c4d2Smrg 200220d2c4d2Smrg TRACE(("dumpXft {{\n")); 200320d2c4d2Smrg TRACE((" data range %#6x..%#6x\n", first, last)); 200420d2c4d2Smrg for (c = first; c <= last; ++c) { 200520d2c4d2Smrg if (FcCharSetHasChar(xft->charset, c)) { 200620d2c4d2Smrg int width = my_wcwidth((int) c); 200720d2c4d2Smrg XGlyphInfo extents; 200820d2c4d2Smrg 200920d2c4d2Smrg XftTextExtents32(XtDisplay(xw), xft, &c, 1, &extents); 201020d2c4d2Smrg TRACE(("%#6x %2d %.1f\n", c, width, 201120d2c4d2Smrg ((double) extents.width) / win->f_width)); 201220d2c4d2Smrg if (extents.width > win->f_width) 201320d2c4d2Smrg ++outside; 201420d2c4d2Smrg ++count; 201520d2c4d2Smrg } 201620d2c4d2Smrg } 201720d2c4d2Smrg TRACE(("}} %u total, %u outside\n", count, outside)); 201820d2c4d2Smrg} 201920d2c4d2Smrg#define DUMP_XFT(xw, data) dumpXft(xw, data) 202020d2c4d2Smrg#else 202120d2c4d2Smrg#define DUMP_XFT(xw, data) /* nothing */ 202220d2c4d2Smrg#endif 202320d2c4d2Smrg 2024956cc18dSsnjstatic void 20259a64e1c5SmrgcheckXft(XtermWidget xw, XTermXftFonts *data, XftFont *xft) 2026956cc18dSsnj{ 2027956cc18dSsnj FcChar32 c; 2028956cc18dSsnj Dimension width = 0; 2029956cc18dSsnj 2030956cc18dSsnj data->font = xft; 2031956cc18dSsnj data->map.min_width = 0; 2032956cc18dSsnj data->map.max_width = (Dimension) xft->max_advance_width; 2033956cc18dSsnj 203420d2c4d2Smrg /* 203520d2c4d2Smrg * For each ASCII or ISO-8859-1 printable code, ask what its width is. 203620d2c4d2Smrg * Given the maximum width for those, we have a reasonable estimate of 203720d2c4d2Smrg * the single-column width. 203820d2c4d2Smrg * 203920d2c4d2Smrg * Ignore control characters - their extent information is misleading. 204020d2c4d2Smrg */ 2041956cc18dSsnj for (c = 32; c < 256; ++c) { 204220d2c4d2Smrg if (c >= 127 && c <= 159) 204320d2c4d2Smrg continue; 2044956cc18dSsnj if (FcCharSetHasChar(xft->charset, c)) { 2045956cc18dSsnj XGlyphInfo extents; 2046956cc18dSsnj 2047956cc18dSsnj XftTextExtents32(XtDisplay(xw), xft, &c, 1, &extents); 204820d2c4d2Smrg if (width < extents.width && extents.width <= data->map.max_width) { 2049956cc18dSsnj width = extents.width; 205020d2c4d2Smrg } 2051956cc18dSsnj } 2052956cc18dSsnj } 2053956cc18dSsnj data->map.min_width = width; 2054956cc18dSsnj data->map.mixed = (data->map.max_width >= (data->map.min_width + 1)); 2055956cc18dSsnj} 2056956cc18dSsnj 2057fa3f02f3Smrgstatic void 2058fa3f02f3SmrgreportXftFonts(XtermWidget xw, 20599a64e1c5Smrg XftFont *fp, 2060fa3f02f3Smrg const char *name, 2061fa3f02f3Smrg const char *tag, 20629a64e1c5Smrg XftPattern *match) 2063fa3f02f3Smrg{ 2064fa3f02f3Smrg if (resource.reportFonts) { 2065fa3f02f3Smrg char buffer[1024]; 2066fa3f02f3Smrg FcChar32 first_char = xtermXftFirstChar(fp); 2067fa3f02f3Smrg FcChar32 last_char = xtermXftLastChar(fp); 2068fa3f02f3Smrg FcChar32 ch; 2069fa3f02f3Smrg unsigned missing = 0; 2070fa3f02f3Smrg 207194644356Smrg printf("Loaded XftFonts(%s[%s])\n", name, tag); 2072fa3f02f3Smrg 2073fa3f02f3Smrg for (ch = first_char; ch <= last_char; ++ch) { 2074fa3f02f3Smrg if (xtermXftMissing(xw, fp, ch)) { 2075fa3f02f3Smrg ++missing; 2076fa3f02f3Smrg } 2077fa3f02f3Smrg } 2078fa3f02f3Smrg printf("\t\tfirst char: %u\n", first_char); 2079fa3f02f3Smrg printf("\t\tlast char: %u\n", last_char); 2080fa3f02f3Smrg printf("\t\tmissing-chars: %u\n", missing); 2081fa3f02f3Smrg printf("\t\tpresent-chars: %u\n", (last_char - first_char) + 1 - missing); 2082fa3f02f3Smrg 2083fa3f02f3Smrg if (XftNameUnparse(match, buffer, (int) sizeof(buffer))) { 2084fa3f02f3Smrg char *target; 2085fa3f02f3Smrg char *source = buffer; 2086fa3f02f3Smrg while ((target = strtok(source, ":")) != 0) { 2087fa3f02f3Smrg printf("\t%s\n", target); 2088fa3f02f3Smrg source = 0; 2089fa3f02f3Smrg } 2090fa3f02f3Smrg } 2091fa3f02f3Smrg } 2092fa3f02f3Smrg} 2093fa3f02f3Smrg 2094d522f475Smrgstatic XftFont * 20959a64e1c5SmrgxtermOpenXft(XtermWidget xw, const char *name, XftPattern *pat, const char *tag) 2096d522f475Smrg{ 2097956cc18dSsnj TScreen *screen = TScreenOf(xw); 2098956cc18dSsnj Display *dpy = screen->display; 2099d522f475Smrg XftPattern *match; 2100d522f475Smrg XftResult status; 2101d522f475Smrg XftFont *result = 0; 2102d522f475Smrg 2103d522f475Smrg if (pat != 0) { 2104d522f475Smrg match = XftFontMatch(dpy, DefaultScreen(dpy), pat, &status); 2105d522f475Smrg if (match != 0) { 2106d522f475Smrg result = XftFontOpenPattern(dpy, match); 2107d522f475Smrg if (result != 0) { 2108d522f475Smrg TRACE(("...matched %s font\n", tag)); 2109fa3f02f3Smrg reportXftFonts(xw, result, name, tag, match); 2110d522f475Smrg } else { 2111d522f475Smrg TRACE(("...could did not open %s font\n", tag)); 2112d522f475Smrg XftPatternDestroy(match); 2113956cc18dSsnj if (xw->misc.fontWarnings >= fwAlways) { 2114956cc18dSsnj TRACE(("OOPS cannot open %s font \"%s\"\n", tag, name)); 21150bd37d32Smrg xtermWarning("cannot open %s font \"%s\"\n", tag, name); 2116956cc18dSsnj } 2117d522f475Smrg } 2118d522f475Smrg } else { 2119d522f475Smrg TRACE(("...did not match %s font\n", tag)); 2120956cc18dSsnj if (xw->misc.fontWarnings >= fwResource) { 2121956cc18dSsnj TRACE(("OOPS: cannot match %s font \"%s\"\n", tag, name)); 21220bd37d32Smrg xtermWarning("cannot match %s font \"%s\"\n", tag, name); 2123956cc18dSsnj } 2124d522f475Smrg } 2125d522f475Smrg } 2126d522f475Smrg return result; 2127d522f475Smrg} 2128d522f475Smrg#endif 2129d522f475Smrg 2130d522f475Smrg#if OPT_RENDERFONT 2131d522f475Smrg#if OPT_SHIFT_FONTS 2132d522f475Smrg/* 2133d522f475Smrg * Don't make a dependency on the math library for a single function. 2134d522f475Smrg * (Newton Raphson). 2135d522f475Smrg */ 2136d522f475Smrgstatic double 21370bd37d32SmrgdimSquareRoot(double value) 2138d522f475Smrg{ 2139d522f475Smrg double result = 0.0; 2140d522f475Smrg if (value > 0.0) { 2141d522f475Smrg int n; 2142d522f475Smrg double older = value; 2143d522f475Smrg for (n = 0; n < 10; ++n) { 2144d522f475Smrg double delta = (older * older - value) / (2.0 * older); 2145d522f475Smrg double newer = older - delta; 2146d522f475Smrg older = newer; 2147d522f475Smrg result = newer; 2148d522f475Smrg if (delta > -0.001 && delta < 0.001) 2149d522f475Smrg break; 2150d522f475Smrg } 2151d522f475Smrg } 2152d522f475Smrg return result; 2153d522f475Smrg} 2154d522f475Smrg#endif 2155d522f475Smrg 2156d522f475Smrg/* 2157d522f475Smrg * Given the Xft font metrics, determine the actual font size. This is used 2158d522f475Smrg * for each font to ensure that normal, bold and italic fonts follow the same 2159d522f475Smrg * rule. 2160d522f475Smrg */ 2161d522f475Smrgstatic void 21629a64e1c5SmrgsetRenderFontsize(TScreen *screen, VTwin *win, XftFont *font, const char *tag) 2163d522f475Smrg{ 2164d522f475Smrg if (font != 0) { 2165d522f475Smrg int width, height, ascent, descent; 2166d522f475Smrg 2167d522f475Smrg (void) screen; 2168d522f475Smrg 2169d522f475Smrg width = font->max_advance_width; 2170d522f475Smrg height = font->height; 2171d522f475Smrg ascent = font->ascent; 2172d522f475Smrg descent = font->descent; 2173d522f475Smrg if (height < ascent + descent) { 2174d522f475Smrg TRACE(("...increase height from %d\n", height)); 2175d522f475Smrg height = ascent + descent; 2176d522f475Smrg } 2177d522f475Smrg if (is_double_width_font_xft(screen->display, font)) { 2178d522f475Smrg TRACE(("...reduced width from %d\n", width)); 2179d522f475Smrg width >>= 1; 2180d522f475Smrg } 2181d522f475Smrg if (tag == 0) { 21820bd37d32Smrg SetFontWidth(screen, win, width); 21830bd37d32Smrg SetFontHeight(screen, win, height); 2184d522f475Smrg win->f_ascent = ascent; 2185d522f475Smrg win->f_descent = descent; 2186d522f475Smrg TRACE(("setRenderFontsize result %dx%d (%d+%d)\n", 2187d522f475Smrg width, height, ascent, descent)); 2188d522f475Smrg } else if (win->f_width < width || 2189d522f475Smrg win->f_height < height || 2190d522f475Smrg win->f_ascent < ascent || 2191d522f475Smrg win->f_descent < descent) { 2192d522f475Smrg TRACE(("setRenderFontsize %s changed %dx%d (%d+%d) to %dx%d (%d+%d)\n", 2193d522f475Smrg tag, 2194d522f475Smrg win->f_width, win->f_height, win->f_ascent, win->f_descent, 2195d522f475Smrg width, height, ascent, descent)); 2196d522f475Smrg 21970bd37d32Smrg SetFontWidth(screen, win, width); 21980bd37d32Smrg SetFontHeight(screen, win, height); 2199d522f475Smrg win->f_ascent = ascent; 2200d522f475Smrg win->f_descent = descent; 2201d522f475Smrg } else { 2202d522f475Smrg TRACE(("setRenderFontsize %s unchanged\n", tag)); 2203d522f475Smrg } 2204d522f475Smrg } 2205d522f475Smrg} 2206d522f475Smrg#endif 2207d522f475Smrg 220820d2c4d2Smrgstatic void 220920d2c4d2SmrgcheckFontInfo(int value, const char *tag) 221020d2c4d2Smrg{ 221120d2c4d2Smrg if (value == 0) { 22120bd37d32Smrg xtermWarning("Selected font has no non-zero %s for ISO-8859-1 encoding\n", tag); 221320d2c4d2Smrg exit(1); 221420d2c4d2Smrg } 221520d2c4d2Smrg} 221620d2c4d2Smrg 221720d2c4d2Smrg#if OPT_RENDERFONT 221820d2c4d2Smrgvoid 22199a64e1c5SmrgxtermCloseXft(TScreen *screen, XTermXftFonts *pub) 222020d2c4d2Smrg{ 222120d2c4d2Smrg if (pub->font != 0) { 222220d2c4d2Smrg XftFontClose(screen->display, pub->font); 222320d2c4d2Smrg pub->font = 0; 222420d2c4d2Smrg } 222520d2c4d2Smrg} 222620d2c4d2Smrg 222720d2c4d2Smrg/* 222820d2c4d2Smrg * Get the faceName/faceDoublesize resource setting. Strip off "xft:", which 22290bd37d32Smrg * is not recognized by XftNameParse(). 223020d2c4d2Smrg */ 2231492d43a5SmrgString 223220d2c4d2SmrggetFaceName(XtermWidget xw, Bool wideName GCC_UNUSED) 223320d2c4d2Smrg{ 223420d2c4d2Smrg#if OPT_RENDERWIDE 2235492d43a5Smrg String result = (wideName 2236492d43a5Smrg ? xw->misc.face_wide_name 2237492d43a5Smrg : xw->misc.face_name); 223820d2c4d2Smrg#else 2239492d43a5Smrg String result = xw->misc.face_name; 224020d2c4d2Smrg#endif 224120d2c4d2Smrg if (!IsEmpty(result) && !strncmp(result, "xft:", (size_t) 4)) 224220d2c4d2Smrg result += 4; 224320d2c4d2Smrg return x_nonempty(result); 224420d2c4d2Smrg} 224520d2c4d2Smrg 224620d2c4d2Smrg/* 224720d2c4d2Smrg * If we change the faceName, we'll have to re-acquire all of the fonts that 224820d2c4d2Smrg * are derived from it. 224920d2c4d2Smrg */ 225020d2c4d2Smrgvoid 225120d2c4d2SmrgsetFaceName(XtermWidget xw, const char *value) 225220d2c4d2Smrg{ 225320d2c4d2Smrg TScreen *screen = TScreenOf(xw); 225420d2c4d2Smrg int n; 22550bd37d32Smrg Boolean changed = (Boolean) ((xw->misc.face_name == 0) 22560bd37d32Smrg || strcmp(xw->misc.face_name, value)); 225720d2c4d2Smrg 22580bd37d32Smrg if (changed) { 22590bd37d32Smrg xw->misc.face_name = x_strdup(value); 22600bd37d32Smrg for (n = 0; n < NMENUFONTS; ++n) { 22610bd37d32Smrg xw->misc.face_size[n] = -1.0; 22620bd37d32Smrg xtermCloseXft(screen, &(screen->renderFontNorm[n])); 22630bd37d32Smrg xtermCloseXft(screen, &(screen->renderFontBold[n])); 22640bd37d32Smrg xtermCloseXft(screen, &(screen->renderFontBold[n])); 226520d2c4d2Smrg#if OPT_RENDERWIDE 22660bd37d32Smrg xtermCloseXft(screen, &(screen->renderWideNorm[n])); 22670bd37d32Smrg xtermCloseXft(screen, &(screen->renderWideBold[n])); 22680bd37d32Smrg xtermCloseXft(screen, &(screen->renderWideItal[n])); 226920d2c4d2Smrg#endif 22700bd37d32Smrg } 227120d2c4d2Smrg } 227220d2c4d2Smrg} 227320d2c4d2Smrg#endif 227420d2c4d2Smrg 2275d522f475Smrg/* 2276d522f475Smrg * Compute useful values for the font/window sizes 2277d522f475Smrg */ 2278d522f475Smrgvoid 2279d522f475SmrgxtermComputeFontInfo(XtermWidget xw, 22809a64e1c5Smrg VTwin *win, 22819a64e1c5Smrg XFontStruct *font, 2282d522f475Smrg int sbwidth) 2283d522f475Smrg{ 2284956cc18dSsnj TScreen *screen = TScreenOf(xw); 2285d522f475Smrg 2286d522f475Smrg int i, j, width, height; 2287492d43a5Smrg#if OPT_RENDERFONT 2288492d43a5Smrg int fontnum = screen->menu_font_number; 2289492d43a5Smrg#endif 2290d522f475Smrg 2291d522f475Smrg#if OPT_RENDERFONT 2292d522f475Smrg /* 2293d522f475Smrg * xterm contains a lot of references to fonts, assuming they are fixed 2294d522f475Smrg * size. This chunk of code overrides the actual font-selection (see 2295d522f475Smrg * drawXtermText()), if the user has selected render-font. All of the 2296d522f475Smrg * font-loading for fixed-fonts still goes on whether or not this chunk 2297d522f475Smrg * overrides it. 2298d522f475Smrg */ 2299492d43a5Smrg if (UsingRenderFont(xw) && fontnum >= 0) { 2300492d43a5Smrg String face_name = getFaceName(xw, False); 2301956cc18dSsnj XftFont *norm = screen->renderFontNorm[fontnum].font; 2302956cc18dSsnj XftFont *bold = screen->renderFontBold[fontnum].font; 2303956cc18dSsnj XftFont *ital = screen->renderFontItal[fontnum].font; 2304d522f475Smrg#if OPT_RENDERWIDE 2305956cc18dSsnj XftFont *wnorm = screen->renderWideNorm[fontnum].font; 2306956cc18dSsnj XftFont *wbold = screen->renderWideBold[fontnum].font; 2307956cc18dSsnj XftFont *wital = screen->renderWideItal[fontnum].font; 2308d522f475Smrg#endif 2309d522f475Smrg 231020d2c4d2Smrg if (norm == 0 && face_name) { 2311d522f475Smrg XftPattern *pat; 23120bd37d32Smrg double face_size; 2313d522f475Smrg 23140bd37d32Smrg TRACE(("xtermComputeFontInfo font %d: norm(face %s, size %.1f)\n", 2315492d43a5Smrg fontnum, face_name, 2316d522f475Smrg xw->misc.face_size[fontnum])); 2317d522f475Smrg 23180bd37d32Smrg fillInFaceSize(xw, fontnum); 23190bd37d32Smrg face_size = xw->misc.face_size[fontnum]; 2320d522f475Smrg 2321d522f475Smrg /* 2322d522f475Smrg * By observation (there is no documentation), XftPatternBuild is 2323d522f475Smrg * cumulative. Build the bold- and italic-patterns on top of the 2324d522f475Smrg * normal pattern. 2325d522f475Smrg */ 2326d522f475Smrg#define NormXftPattern \ 2327d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 2328d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 2329d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 2330d522f475Smrg 2331d522f475Smrg#define BoldXftPattern(norm) \ 2332d522f475Smrg XFT_WEIGHT, XftTypeInteger, XFT_WEIGHT_BOLD, \ 2333d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 2334d522f475Smrg 2335d522f475Smrg#define ItalXftPattern(norm) \ 2336d522f475Smrg XFT_SLANT, XftTypeInteger, XFT_SLANT_ITALIC, \ 2337d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 2338d522f475Smrg 23399a64e1c5Smrg#if OPT_WIDE_ATTRS 23409a64e1c5Smrg#define HAVE_ITALICS 1 23419a64e1c5Smrg#define FIND_ITALICS ((pat = XftNameParse(face_name)) != 0) 23429a64e1c5Smrg#elif OPT_ISO_COLORS 23439a64e1c5Smrg#define HAVE_ITALICS 1 23449a64e1c5Smrg#define FIND_ITALICS (screen->italicULMode && (pat = XftNameParse(face_name)) != 0) 23459a64e1c5Smrg#else 23469a64e1c5Smrg#define HAVE_ITALICS 0 23479a64e1c5Smrg#endif 23489a64e1c5Smrg 234920d2c4d2Smrg if ((pat = XftNameParse(face_name)) != 0) { 235020d2c4d2Smrg#define OPEN_XFT(tag) xtermOpenXft(xw, face_name, pat, tag) 2351d522f475Smrg XftPatternBuild(pat, 2352d522f475Smrg NormXftPattern, 2353d522f475Smrg (void *) 0); 2354956cc18dSsnj norm = OPEN_XFT("normal"); 2355d522f475Smrg 2356d522f475Smrg if (norm != 0) { 2357d522f475Smrg XftPatternBuild(pat, 2358d522f475Smrg BoldXftPattern(norm), 2359d522f475Smrg (void *) 0); 2360956cc18dSsnj bold = OPEN_XFT("bold"); 2361d522f475Smrg 23629a64e1c5Smrg#if HAVE_ITALICS 23639a64e1c5Smrg if (FIND_ITALICS) { 2364d522f475Smrg XftPatternBuild(pat, 2365d522f475Smrg NormXftPattern, 2366d522f475Smrg ItalXftPattern(norm), 2367d522f475Smrg (void *) 0); 2368956cc18dSsnj ital = OPEN_XFT("italic"); 2369d522f475Smrg } 23709a64e1c5Smrg#endif 2371956cc18dSsnj#undef OPEN_XFT 2372d522f475Smrg 2373d522f475Smrg /* 2374d522f475Smrg * FIXME: just assume that the corresponding font has no 2375d522f475Smrg * graphics characters. 2376d522f475Smrg */ 2377d522f475Smrg if (screen->fnt_boxes) { 2378d522f475Smrg screen->fnt_boxes = False; 2379d522f475Smrg TRACE(("Xft opened - will %suse internal line-drawing characters\n", 2380d522f475Smrg screen->fnt_boxes ? "not " : "")); 2381d522f475Smrg } 2382d522f475Smrg } 2383d522f475Smrg 2384d522f475Smrg XftPatternDestroy(pat); 2385d522f475Smrg } 2386d522f475Smrg 2387d522f475Smrg CACHE_XFT(screen->renderFontNorm, norm); 2388d522f475Smrg CACHE_XFT(screen->renderFontBold, bold); 2389d522f475Smrg CACHE_XFT(screen->renderFontItal, ital); 2390d522f475Smrg 2391d522f475Smrg /* 2392d522f475Smrg * See xtermXftDrawString(). 2393d522f475Smrg */ 2394d522f475Smrg#if OPT_RENDERWIDE 2395d522f475Smrg if (norm != 0 && screen->wide_chars) { 2396d522f475Smrg int char_width = norm->max_advance_width * 2; 2397956cc18dSsnj#ifdef FC_ASPECT 2398956cc18dSsnj double aspect = ((xw->misc.face_wide_name 2399956cc18dSsnj || screen->renderFontNorm[fontnum].map.mixed) 2400956cc18dSsnj ? 1.0 2401956cc18dSsnj : 2.0); 2402956cc18dSsnj#endif 2403d522f475Smrg 240420d2c4d2Smrg face_name = getFaceName(xw, True); 2405d522f475Smrg TRACE(("xtermComputeFontInfo wide(face %s, char_width %d)\n", 240620d2c4d2Smrg NonNull(face_name), 2407d522f475Smrg char_width)); 2408d522f475Smrg 2409d522f475Smrg#define WideXftPattern \ 2410d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 2411d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 2412d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 2413d522f475Smrg 241420d2c4d2Smrg if (face_name && (pat = XftNameParse(face_name)) != 0) { 2415956cc18dSsnj#define OPEN_XFT(tag) xtermOpenXft(xw, face_name, pat, tag) 2416d522f475Smrg XftPatternBuild(pat, 2417d522f475Smrg WideXftPattern, 2418d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, char_width, 2419956cc18dSsnj#ifdef FC_ASPECT 2420956cc18dSsnj FC_ASPECT, XftTypeDouble, aspect, 2421956cc18dSsnj#endif 2422d522f475Smrg (void *) 0); 2423956cc18dSsnj wnorm = OPEN_XFT("wide"); 2424d522f475Smrg 2425d522f475Smrg if (wnorm != 0) { 2426d522f475Smrg XftPatternBuild(pat, 2427d522f475Smrg WideXftPattern, 2428d522f475Smrg BoldXftPattern(wnorm), 2429d522f475Smrg (void *) 0); 2430956cc18dSsnj wbold = OPEN_XFT("wide-bold"); 2431d522f475Smrg 24329a64e1c5Smrg#if HAVE_ITALICS 24339a64e1c5Smrg if (FIND_ITALICS) { 2434d522f475Smrg XftPatternBuild(pat, 2435d522f475Smrg WideXftPattern, 2436d522f475Smrg ItalXftPattern(wnorm), 2437d522f475Smrg (void *) 0); 2438956cc18dSsnj wital = OPEN_XFT("wide-italic"); 2439d522f475Smrg } 2440d522f475Smrg#endif 2441956cc18dSsnj#undef OPEN_XFT 2442d522f475Smrg } 2443d522f475Smrg XftPatternDestroy(pat); 2444d522f475Smrg } 2445d522f475Smrg 2446d522f475Smrg CACHE_XFT(screen->renderWideNorm, wnorm); 2447d522f475Smrg CACHE_XFT(screen->renderWideBold, wbold); 2448d522f475Smrg CACHE_XFT(screen->renderWideItal, wital); 2449d522f475Smrg } 2450d522f475Smrg#endif /* OPT_RENDERWIDE */ 2451d522f475Smrg } 2452d522f475Smrg if (norm == 0) { 24532eaa94a1Schristos TRACE(("...no TrueType font found for number %d, disable menu entry\n", fontnum)); 24540bd37d32Smrg xw->work.render_font = False; 2455d522f475Smrg update_font_renderfont(); 2456d522f475Smrg /* now we will fall through into the bitmap fonts */ 2457d522f475Smrg } else { 2458d522f475Smrg setRenderFontsize(screen, win, norm, NULL); 2459d522f475Smrg setRenderFontsize(screen, win, bold, "bold"); 2460d522f475Smrg setRenderFontsize(screen, win, ital, "ital"); 246120d2c4d2Smrg#if OPT_BOX_CHARS 246220d2c4d2Smrg setupPackedFonts(xw); 246320d2c4d2Smrg 246420d2c4d2Smrg if (screen->force_packed) { 246520d2c4d2Smrg XTermXftFonts *use = &(screen->renderFontNorm[fontnum]); 24660bd37d32Smrg SetFontHeight(screen, win, use->font->ascent + use->font->descent); 24670bd37d32Smrg SetFontWidth(screen, win, use->map.min_width); 246820d2c4d2Smrg TRACE(("...packed TrueType font %dx%d vs %d\n", 246920d2c4d2Smrg win->f_height, 247020d2c4d2Smrg win->f_width, 247120d2c4d2Smrg use->map.max_width)); 247220d2c4d2Smrg } 247320d2c4d2Smrg#endif 247420d2c4d2Smrg DUMP_XFT(xw, &(screen->renderFontNorm[fontnum])); 2475d522f475Smrg } 2476d522f475Smrg } 2477d522f475Smrg /* 2478d522f475Smrg * Are we handling a bitmap font? 2479d522f475Smrg */ 2480492d43a5Smrg else 2481d522f475Smrg#endif /* OPT_RENDERFONT */ 2482d522f475Smrg { 248320d2c4d2Smrg if (is_double_width_font(font) && !(screen->fnt_prop)) { 24840bd37d32Smrg SetFontWidth(screen, win, font->min_bounds.width); 2485d522f475Smrg } else { 24860bd37d32Smrg SetFontWidth(screen, win, font->max_bounds.width); 2487d522f475Smrg } 24880bd37d32Smrg SetFontHeight(screen, win, font->ascent + font->descent); 2489d522f475Smrg win->f_ascent = font->ascent; 2490d522f475Smrg win->f_descent = font->descent; 2491d522f475Smrg } 2492d522f475Smrg i = 2 * screen->border + sbwidth; 2493d522f475Smrg j = 2 * screen->border; 2494d522f475Smrg width = MaxCols(screen) * win->f_width + i; 2495d522f475Smrg height = MaxRows(screen) * win->f_height + j; 2496956cc18dSsnj win->fullwidth = (Dimension) width; 2497956cc18dSsnj win->fullheight = (Dimension) height; 2498d522f475Smrg win->width = width - i; 2499d522f475Smrg win->height = height - j; 2500d522f475Smrg 2501d522f475Smrg TRACE(("xtermComputeFontInfo window %dx%d (full %dx%d), fontsize %dx%d (asc %d, dsc %d)\n", 2502d522f475Smrg win->height, 2503d522f475Smrg win->width, 2504d522f475Smrg win->fullheight, 2505d522f475Smrg win->fullwidth, 2506d522f475Smrg win->f_height, 2507d522f475Smrg win->f_width, 2508d522f475Smrg win->f_ascent, 2509d522f475Smrg win->f_descent)); 251020d2c4d2Smrg 251120d2c4d2Smrg checkFontInfo(win->f_height, "height"); 251220d2c4d2Smrg checkFontInfo(win->f_width, "width"); 2513d522f475Smrg} 2514d522f475Smrg 2515d522f475Smrg/* save this information as a side-effect for double-sized characters */ 2516d522f475Smrgvoid 25179a64e1c5SmrgxtermSaveFontInfo(TScreen *screen, XFontStruct *font) 2518d522f475Smrg{ 2519956cc18dSsnj screen->fnt_wide = (Dimension) (font->max_bounds.width); 2520956cc18dSsnj screen->fnt_high = (Dimension) (font->ascent + font->descent); 2521d522f475Smrg TRACE(("xtermSaveFontInfo %dx%d\n", screen->fnt_high, screen->fnt_wide)); 2522d522f475Smrg} 2523d522f475Smrg 2524d522f475Smrg/* 2525d522f475Smrg * After loading a new font, update the structures that use its size. 2526d522f475Smrg */ 2527d522f475Smrgvoid 2528d522f475SmrgxtermUpdateFontInfo(XtermWidget xw, Bool doresize) 2529d522f475Smrg{ 2530956cc18dSsnj TScreen *screen = TScreenOf(xw); 2531d522f475Smrg 2532d522f475Smrg int scrollbar_width; 2533d522f475Smrg VTwin *win = &(screen->fullVwin); 2534d522f475Smrg 2535d522f475Smrg scrollbar_width = (xw->misc.scrollbar 2536d522f475Smrg ? (screen->scrollWidget->core.width + 2537d522f475Smrg BorderWidth(screen->scrollWidget)) 2538d522f475Smrg : 0); 2539d522f475Smrg xtermComputeFontInfo(xw, win, screen->fnts[fNorm].fs, scrollbar_width); 2540d522f475Smrg xtermSaveFontInfo(screen, screen->fnts[fNorm].fs); 2541d522f475Smrg 2542d522f475Smrg if (doresize) { 2543d522f475Smrg if (VWindow(screen)) { 2544d522f475Smrg xtermClear(xw); 2545d522f475Smrg } 2546d522f475Smrg TRACE(("xtermUpdateFontInfo {{\n")); 2547d522f475Smrg DoResizeScreen(xw); /* set to the new natural size */ 2548d522f475Smrg ResizeScrollBar(xw); 2549d522f475Smrg Redraw(); 2550d522f475Smrg TRACE(("... }} xtermUpdateFontInfo\n")); 2551d522f475Smrg#ifdef SCROLLBAR_RIGHT 2552d522f475Smrg updateRightScrollbar(xw); 2553d522f475Smrg#endif 2554d522f475Smrg } 2555d522f475Smrg xtermSetCursorBox(screen); 2556d522f475Smrg} 2557d522f475Smrg 2558fa3f02f3Smrg#if OPT_BOX_CHARS || OPT_REPORT_FONTS 2559d522f475Smrg 2560d522f475Smrg/* 2561d522f475Smrg * Returns true if the given character is missing from the specified font. 2562d522f475Smrg */ 2563d522f475SmrgBool 2564956cc18dSsnjxtermMissingChar(unsigned ch, XTermFonts * font) 2565d522f475Smrg{ 2566956cc18dSsnj Bool result = False; 2567956cc18dSsnj XFontStruct *fs = font->fs; 2568fa3f02f3Smrg XCharStruct *pc = 0; 2569d522f475Smrg 2570956cc18dSsnj if (fs->max_byte1 == 0) { 2571d522f475Smrg#if OPT_WIDE_CHARS 2572fa3f02f3Smrg if (ch < 256) 2573956cc18dSsnj#endif 2574fa3f02f3Smrg { 2575fa3f02f3Smrg CI_GET_CHAR_INFO_1D(fs, E2A(ch), pc); 2576fa3f02f3Smrg } 2577956cc18dSsnj } 2578d522f475Smrg#if OPT_WIDE_CHARS 2579956cc18dSsnj else { 2580fa3f02f3Smrg unsigned row = (ch >> 8); 2581fa3f02f3Smrg unsigned col = (ch & 0xff); 2582fa3f02f3Smrg CI_GET_CHAR_INFO_2D(fs, row, col, pc); 2583956cc18dSsnj } 2584d522f475Smrg#endif 2585d522f475Smrg 2586fa3f02f3Smrg if (pc == 0 || CI_NONEXISTCHAR(pc)) { 2587956cc18dSsnj TRACE(("xtermMissingChar %#04x (!exists)\n", ch)); 2588956cc18dSsnj result = True; 2589d522f475Smrg } 2590fa3f02f3Smrg if (ch < KNOWN_MISSING) { 2591956cc18dSsnj font->known_missing[ch] = (Char) (result ? 2 : 1); 2592d522f475Smrg } 2593956cc18dSsnj return result; 2594d522f475Smrg} 2595fa3f02f3Smrg#endif 2596d522f475Smrg 2597fa3f02f3Smrg#if OPT_BOX_CHARS 2598d522f475Smrg/* 2599d522f475Smrg * The grid is arbitrary, enough resolution that nothing's lost in 2600d522f475Smrg * initialization. 2601d522f475Smrg */ 2602d522f475Smrg#define BOX_HIGH 60 2603d522f475Smrg#define BOX_WIDE 60 2604d522f475Smrg 2605d522f475Smrg#define MID_HIGH (BOX_HIGH/2) 2606d522f475Smrg#define MID_WIDE (BOX_WIDE/2) 2607d522f475Smrg 2608d522f475Smrg#define CHR_WIDE ((9*BOX_WIDE)/10) 2609d522f475Smrg#define CHR_HIGH ((9*BOX_HIGH)/10) 2610d522f475Smrg 2611d522f475Smrg/* 2612d522f475Smrg * ...since we'll scale the values anyway. 2613d522f475Smrg */ 2614e39b573cSmrg#define SCALED_X(n) ((int)(n) * (((int) font_width) - 1)) / (BOX_WIDE-1) 2615e39b573cSmrg#define SCALED_Y(n) ((int)(n) * (((int) font_height) - 1)) / (BOX_HIGH-1) 2616e39b573cSmrg#define SCALE_X(n) n = SCALED_X(n) 2617e39b573cSmrg#define SCALE_Y(n) n = SCALED_Y(n) 2618d522f475Smrg 2619d522f475Smrg#define SEG(x0,y0,x1,y1) x0,y0, x1,y1 2620d522f475Smrg 2621d522f475Smrg/* 2622d522f475Smrg * Draw the given graphic character, if it is simple enough (i.e., a 2623d522f475Smrg * line-drawing character). 2624d522f475Smrg */ 2625d522f475Smrgvoid 2626d522f475SmrgxtermDrawBoxChar(XtermWidget xw, 2627d522f475Smrg unsigned ch, 26289a64e1c5Smrg unsigned attr_flags, 26299a64e1c5Smrg unsigned draw_flags, 2630d522f475Smrg GC gc, 2631d522f475Smrg int x, 2632d522f475Smrg int y, 2633d522f475Smrg int cells) 2634d522f475Smrg{ 2635956cc18dSsnj TScreen *screen = TScreenOf(xw); 2636d522f475Smrg /* *INDENT-OFF* */ 2637d522f475Smrg static const short glyph_ht[] = { 2638d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,5*MID_HIGH/6), /* H */ 2639d522f475Smrg SEG(6*BOX_WIDE/10, 0, 6*BOX_WIDE/10,5*MID_HIGH/6), 2640d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*BOX_WIDE/10,5*MID_HIGH/12), 2641d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 2642d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 2643d522f475Smrg -1 2644d522f475Smrg }, glyph_ff[] = { 2645d522f475Smrg SEG(1*BOX_WIDE/10, 0, 6*BOX_WIDE/10, 0), /* F */ 2646d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*CHR_WIDE/12,5*MID_HIGH/12), 2647d522f475Smrg SEG(1*BOX_WIDE/10, 0, 0*BOX_WIDE/3, 5*MID_HIGH/6), 2648d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 2649d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 2650d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 2651d522f475Smrg -1 2652d522f475Smrg }, glyph_lf[] = { 2653d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,9*MID_HIGH/12), /* L */ 2654d522f475Smrg SEG(1*BOX_WIDE/10,9*MID_HIGH/12,6*BOX_WIDE/10,9*MID_HIGH/12), 2655d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 2656d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 2657d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 2658d522f475Smrg -1 2659d522f475Smrg }, glyph_nl[] = { 2660d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/6, 1*BOX_WIDE/10, 0), /* N */ 2661d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/6, 5*MID_HIGH/6), 2662d522f475Smrg SEG(5*BOX_WIDE/6, 5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 2663d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), /* L */ 2664d522f475Smrg SEG(1*BOX_WIDE/3, CHR_HIGH, CHR_WIDE, CHR_HIGH), 2665d522f475Smrg -1 2666d522f475Smrg }, glyph_vt[] = { 2667d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/12,5*MID_HIGH/6), /* V */ 2668d522f475Smrg SEG(5*BOX_WIDE/12,5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 2669d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 2670d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 2671d522f475Smrg -1 2672d522f475Smrg }, plus_or_minus[] = 2673d522f475Smrg { 2674d522f475Smrg SEG( 0, 5*BOX_HIGH/6, CHR_WIDE, 5*BOX_HIGH/6), 2675d522f475Smrg SEG( MID_WIDE, 2*BOX_HIGH/6, MID_WIDE, 4*BOX_HIGH/6), 2676d522f475Smrg SEG( 0, 3*BOX_HIGH/6, CHR_WIDE, 3*BOX_HIGH/6), 2677d522f475Smrg -1 2678d522f475Smrg }, lower_right_corner[] = 2679d522f475Smrg { 2680d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 2681d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, 0), 2682d522f475Smrg -1 2683d522f475Smrg }, upper_right_corner[] = 2684d522f475Smrg { 2685d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 2686d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2687d522f475Smrg -1 2688d522f475Smrg }, upper_left_corner[] = 2689d522f475Smrg { 2690d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 2691d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2692d522f475Smrg -1 2693d522f475Smrg }, lower_left_corner[] = 2694d522f475Smrg { 2695d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 2696d522f475Smrg SEG( MID_WIDE, MID_WIDE, BOX_WIDE, MID_HIGH), 2697d522f475Smrg -1 2698d522f475Smrg }, cross[] = 2699d522f475Smrg { 2700d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2701d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2702d522f475Smrg -1 2703d522f475Smrg }, scan_line_1[] = 2704d522f475Smrg { 2705d522f475Smrg SEG( 0, 0, BOX_WIDE, 0), 2706d522f475Smrg -1 2707d522f475Smrg }, scan_line_3[] = 2708d522f475Smrg { 2709d522f475Smrg SEG( 0, BOX_HIGH/4, BOX_WIDE, BOX_HIGH/4), 2710d522f475Smrg -1 2711d522f475Smrg }, scan_line_7[] = 2712d522f475Smrg { 2713d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2714d522f475Smrg -1 2715d522f475Smrg }, scan_line_9[] = 2716d522f475Smrg { 2717d522f475Smrg SEG( 0, 3*BOX_HIGH/4, BOX_WIDE, 3*BOX_HIGH/4), 2718d522f475Smrg -1 2719d522f475Smrg }, horizontal_line[] = 2720d522f475Smrg { 2721d522f475Smrg SEG( 0, BOX_HIGH, BOX_WIDE, BOX_HIGH), 2722d522f475Smrg -1 2723d522f475Smrg }, left_tee[] = 2724d522f475Smrg { 2725d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2726d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 2727d522f475Smrg -1 2728d522f475Smrg }, right_tee[] = 2729d522f475Smrg { 2730d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2731d522f475Smrg SEG( MID_WIDE, MID_HIGH, 0, MID_HIGH), 2732d522f475Smrg -1 2733d522f475Smrg }, bottom_tee[] = 2734d522f475Smrg { 2735d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2736d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 2737d522f475Smrg -1 2738d522f475Smrg }, top_tee[] = 2739d522f475Smrg { 2740d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2741d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2742d522f475Smrg -1 2743d522f475Smrg }, vertical_line[] = 2744d522f475Smrg { 2745d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2746d522f475Smrg -1 2747d522f475Smrg }, less_than_or_equal[] = 2748d522f475Smrg { 2749d522f475Smrg SEG( CHR_WIDE, BOX_HIGH/3, 0, MID_HIGH), 2750d522f475Smrg SEG( CHR_WIDE, 2*BOX_HIGH/3, 0, MID_HIGH), 2751d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 2752d522f475Smrg -1 2753d522f475Smrg }, greater_than_or_equal[] = 2754d522f475Smrg { 2755d522f475Smrg SEG( 0, BOX_HIGH/3, CHR_WIDE, MID_HIGH), 2756d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, MID_HIGH), 2757d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 2758d522f475Smrg -1 2759d522f475Smrg }, greek_pi[] = 2760d522f475Smrg { 2761d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 2762d522f475Smrg SEG(5*CHR_WIDE/6, MID_HIGH, 5*CHR_WIDE/6, CHR_HIGH), 2763d522f475Smrg SEG(2*CHR_WIDE/6, MID_HIGH, 2*CHR_WIDE/6, CHR_HIGH), 2764d522f475Smrg -1 2765d522f475Smrg }, not_equal_to[] = 2766d522f475Smrg { 2767d522f475Smrg SEG(2*BOX_WIDE/3, 1*BOX_HIGH/3, 1*BOX_WIDE/3, CHR_HIGH), 2768d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, 2*BOX_HIGH/3), 2769d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 2770d522f475Smrg -1 2771d522f475Smrg }; 2772d522f475Smrg /* *INDENT-ON* */ 2773d522f475Smrg 2774d522f475Smrg static const short *lines[] = 2775d522f475Smrg { 2776d522f475Smrg 0, /* 00 (unused) */ 2777d522f475Smrg 0, /* 01 diamond */ 2778d522f475Smrg 0, /* 02 box */ 2779d522f475Smrg glyph_ht, /* 03 HT */ 2780d522f475Smrg glyph_ff, /* 04 FF */ 2781d522f475Smrg 0, /* 05 CR */ 2782d522f475Smrg glyph_lf, /* 06 LF */ 2783d522f475Smrg 0, /* 07 degrees (small circle) */ 2784d522f475Smrg plus_or_minus, /* 08 */ 2785d522f475Smrg glyph_nl, /* 09 */ 2786d522f475Smrg glyph_vt, /* 0A */ 2787d522f475Smrg lower_right_corner, /* 0B */ 2788d522f475Smrg upper_right_corner, /* 0C */ 2789d522f475Smrg upper_left_corner, /* 0D */ 2790d522f475Smrg lower_left_corner, /* 0E */ 2791d522f475Smrg cross, /* 0F */ 2792d522f475Smrg scan_line_1, /* 10 */ 2793d522f475Smrg scan_line_3, /* 11 */ 2794d522f475Smrg scan_line_7, /* 12 */ 2795d522f475Smrg scan_line_9, /* 13 */ 2796d522f475Smrg horizontal_line, /* 14 */ 2797d522f475Smrg left_tee, /* 15 */ 2798d522f475Smrg right_tee, /* 16 */ 2799d522f475Smrg bottom_tee, /* 17 */ 2800d522f475Smrg top_tee, /* 18 */ 2801d522f475Smrg vertical_line, /* 19 */ 2802d522f475Smrg less_than_or_equal, /* 1A */ 2803d522f475Smrg greater_than_or_equal, /* 1B */ 2804d522f475Smrg greek_pi, /* 1C */ 2805d522f475Smrg not_equal_to, /* 1D */ 2806d522f475Smrg 0, /* 1E LB */ 2807d522f475Smrg 0, /* 1F bullet */ 2808d522f475Smrg }; 2809d522f475Smrg 2810d522f475Smrg GC gc2; 2811d522f475Smrg CgsEnum cgsId = (ch == 2) ? gcDots : gcLine; 2812d522f475Smrg VTwin *cgsWin = WhichVWin(screen); 2813d522f475Smrg const short *p; 28149a64e1c5Smrg unsigned font_width = (unsigned) (((draw_flags & DOUBLEWFONT) ? 2 : 1) 28159a64e1c5Smrg * screen->fnt_wide); 28169a64e1c5Smrg unsigned font_height = (unsigned) (((draw_flags & DOUBLEHFONT) ? 2 : 1) 28179a64e1c5Smrg * screen->fnt_high); 2818d522f475Smrg 2819d522f475Smrg if (cells > 1) 2820956cc18dSsnj font_width *= (unsigned) cells; 2821d522f475Smrg 2822d522f475Smrg#if OPT_WIDE_CHARS 2823d522f475Smrg /* 2824d522f475Smrg * Try to show line-drawing characters if we happen to be in UTF-8 2825d522f475Smrg * mode, but have gotten an old-style font. 2826d522f475Smrg */ 2827d522f475Smrg if (screen->utf8_mode 2828d522f475Smrg#if OPT_RENDERFONT 2829d522f475Smrg && !UsingRenderFont(xw) 2830d522f475Smrg#endif 2831d522f475Smrg && (ch > 127) 2832d522f475Smrg && (ch != UCS_REPL)) { 2833d522f475Smrg unsigned n; 2834d522f475Smrg for (n = 1; n < 32; n++) { 2835d522f475Smrg if (dec2ucs(n) == ch 28369a64e1c5Smrg && !((attr_flags & BOLD) 283720d2c4d2Smrg ? IsXtermMissingChar(screen, n, &screen->fnts[fBold]) 283820d2c4d2Smrg : IsXtermMissingChar(screen, n, &screen->fnts[fNorm]))) { 2839d522f475Smrg TRACE(("...use xterm-style linedrawing\n")); 2840d522f475Smrg ch = n; 2841d522f475Smrg break; 2842d522f475Smrg } 2843d522f475Smrg } 2844d522f475Smrg } 2845d522f475Smrg#endif 2846d522f475Smrg 2847d522f475Smrg TRACE(("DRAW_BOX(%d) cell %dx%d at %d,%d%s\n", 2848d522f475Smrg ch, font_height, font_width, y, x, 2849d522f475Smrg (ch >= (sizeof(lines) / sizeof(lines[0])) 2850d522f475Smrg ? "-BAD" 2851d522f475Smrg : ""))); 2852d522f475Smrg 2853d522f475Smrg if (cgsId == gcDots) { 2854d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2855d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2856d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2857d522f475Smrg } else { 2858d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2859d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2860d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2861d522f475Smrg } 2862d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2863d522f475Smrg 28649a64e1c5Smrg if (!(draw_flags & NOBACKGROUND)) { 28650bd37d32Smrg XFillRectangle(screen->display, VDrawable(screen), gc2, x, y, 2866d522f475Smrg font_width, 2867d522f475Smrg font_height); 2868d522f475Smrg } 2869d522f475Smrg 2870d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2871d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2872d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2873d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2874d522f475Smrg 2875d522f475Smrg XSetLineAttributes(screen->display, gc2, 28769a64e1c5Smrg (attr_flags & BOLD) 2877d522f475Smrg ? ((font_height > 12) 2878d522f475Smrg ? font_height / 12 2879d522f475Smrg : 1) 2880d522f475Smrg : ((font_height > 16) 2881d522f475Smrg ? font_height / 16 2882d522f475Smrg : 1), 2883d522f475Smrg LineSolid, 2884d522f475Smrg CapProjecting, 2885d522f475Smrg JoinMiter); 2886d522f475Smrg 2887d522f475Smrg if (ch == 1) { /* diamond */ 2888d522f475Smrg XPoint points[5]; 2889d522f475Smrg int npoints = 5, n; 2890d522f475Smrg 2891d522f475Smrg points[0].x = MID_WIDE; 2892d522f475Smrg points[0].y = BOX_HIGH / 4; 2893d522f475Smrg 2894d522f475Smrg points[1].x = 8 * BOX_WIDE / 8; 2895d522f475Smrg points[1].y = MID_HIGH; 2896d522f475Smrg 2897d522f475Smrg points[2].x = points[0].x; 2898d522f475Smrg points[2].y = 3 * BOX_HIGH / 4; 2899d522f475Smrg 2900d522f475Smrg points[3].x = 0 * BOX_WIDE / 8; 2901d522f475Smrg points[3].y = points[1].y; 2902d522f475Smrg 2903d522f475Smrg points[4].x = points[0].x; 2904d522f475Smrg points[4].y = points[0].y; 2905d522f475Smrg 2906d522f475Smrg for (n = 0; n < npoints; ++n) { 2907e39b573cSmrg points[n].x = (short) SCALED_X(points[n].x); 2908e39b573cSmrg points[n].y = (short) SCALED_Y(points[n].y); 2909e39b573cSmrg points[n].x = (short) (points[n].x + x); 2910e39b573cSmrg points[n].y = (short) (points[n].y + y); 2911d522f475Smrg } 2912d522f475Smrg 2913d522f475Smrg XFillPolygon(screen->display, 29140bd37d32Smrg VDrawable(screen), gc2, 2915d522f475Smrg points, npoints, 2916d522f475Smrg Convex, CoordModeOrigin); 2917d522f475Smrg } else if (ch == 7) { /* degrees */ 2918d522f475Smrg unsigned width = (BOX_WIDE / 3); 2919956cc18dSsnj int x_coord = MID_WIDE - (int) (width / 2); 2920956cc18dSsnj int y_coord = MID_HIGH - (int) width; 2921d522f475Smrg 2922d522f475Smrg SCALE_X(x_coord); 2923d522f475Smrg SCALE_Y(y_coord); 2924e39b573cSmrg width = (unsigned) SCALED_X(width); 2925d522f475Smrg 2926d522f475Smrg XDrawArc(screen->display, 29270bd37d32Smrg VDrawable(screen), gc2, 2928d522f475Smrg x + x_coord, y + y_coord, width, width, 2929d522f475Smrg 0, 2930d522f475Smrg 360 * 64); 2931d522f475Smrg } else if (ch == 0x1f) { /* bullet */ 2932d522f475Smrg unsigned width = 7 * BOX_WIDE / 10; 2933956cc18dSsnj int x_coord = MID_WIDE - (int) (width / 3); 2934956cc18dSsnj int y_coord = MID_HIGH - (int) (width / 3); 2935d522f475Smrg 2936d522f475Smrg SCALE_X(x_coord); 2937d522f475Smrg SCALE_Y(y_coord); 2938e39b573cSmrg width = (unsigned) SCALED_X(width); 2939d522f475Smrg 2940d522f475Smrg XDrawArc(screen->display, 29410bd37d32Smrg VDrawable(screen), gc2, 2942d522f475Smrg x + x_coord, y + y_coord, width, width, 2943d522f475Smrg 0, 2944d522f475Smrg 360 * 64); 2945d522f475Smrg } else if (ch < (sizeof(lines) / sizeof(lines[0])) 2946d522f475Smrg && (p = lines[ch]) != 0) { 2947956cc18dSsnj int coord[4]; 2948d522f475Smrg int n = 0; 2949d522f475Smrg while (*p >= 0) { 2950d522f475Smrg coord[n++] = *p++; 2951d522f475Smrg if (n == 4) { 2952d522f475Smrg SCALE_X(coord[0]); 2953d522f475Smrg SCALE_Y(coord[1]); 2954d522f475Smrg SCALE_X(coord[2]); 2955d522f475Smrg SCALE_Y(coord[3]); 2956d522f475Smrg XDrawLine(screen->display, 29570bd37d32Smrg VDrawable(screen), gc2, 2958d522f475Smrg x + coord[0], y + coord[1], 2959d522f475Smrg x + coord[2], y + coord[3]); 2960d522f475Smrg n = 0; 2961d522f475Smrg } 2962d522f475Smrg } 2963d522f475Smrg } else if (screen->force_all_chars) { 2964d522f475Smrg /* bounding rectangle, for debugging */ 29650bd37d32Smrg XDrawRectangle(screen->display, VDrawable(screen), gc2, x, y, 2966d522f475Smrg font_width - 1, 2967d522f475Smrg font_height - 1); 2968d522f475Smrg } 2969d522f475Smrg} 2970fa3f02f3Smrg#endif /* OPT_BOX_CHARS */ 2971d522f475Smrg 2972d522f475Smrg#if OPT_RENDERFONT 2973d522f475Smrg 2974d522f475Smrg/* 2975d522f475Smrg * Check if the given character has a glyph known to Xft. 2976d522f475Smrg * 2977d522f475Smrg * see xc/lib/Xft/xftglyphs.c 2978d522f475Smrg */ 2979d522f475SmrgBool 29809a64e1c5SmrgxtermXftMissing(XtermWidget xw, XftFont *font, unsigned wc) 2981d522f475Smrg{ 2982d522f475Smrg Bool result = False; 2983d522f475Smrg 2984d522f475Smrg if (font != 0) { 2985956cc18dSsnj TScreen *screen = TScreenOf(xw); 2986956cc18dSsnj if (!XftGlyphExists(screen->display, font, wc)) { 2987d522f475Smrg#if OPT_WIDE_CHARS 2988d522f475Smrg TRACE(("xtermXftMissing %d (dec=%#x, ucs=%#x)\n", 2989d522f475Smrg wc, ucs2dec(wc), dec2ucs(wc))); 2990d522f475Smrg#else 2991d522f475Smrg TRACE(("xtermXftMissing %d\n", wc)); 2992d522f475Smrg#endif 2993d522f475Smrg result = True; 2994d522f475Smrg } 2995d522f475Smrg } 2996d522f475Smrg return result; 2997d522f475Smrg} 2998fa3f02f3Smrg#endif /* OPT_RENDERFONT */ 2999d522f475Smrg 3000d522f475Smrg#if OPT_WIDE_CHARS 3001d522f475Smrg#define MY_UCS(ucs,dec) case ucs: result = dec; break 3002d522f475Smrgunsigned 3003d522f475Smrgucs2dec(unsigned ch) 3004d522f475Smrg{ 3005d522f475Smrg unsigned result = ch; 3006d522f475Smrg if ((ch > 127) 3007d522f475Smrg && (ch != UCS_REPL)) { 3008d522f475Smrg switch (ch) { 3009d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 3010d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 3011d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 3012d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 3013d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 3014d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 3015d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 3016d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 3017d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 3018d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 3019d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 3020d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 3021d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 3022d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 3023d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 3024d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 3025d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 3026d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 3027d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 3028d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 3029d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 3030d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 3031d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 3032d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 3033d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 3034d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 3035d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 3036d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 3037d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 3038d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 3039d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 3040d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 3041d522f475Smrg } 3042d522f475Smrg } 3043d522f475Smrg return result; 3044d522f475Smrg} 3045d522f475Smrg 3046d522f475Smrg#undef MY_UCS 3047d522f475Smrg#define MY_UCS(ucs,dec) case dec: result = ucs; break 3048d522f475Smrg 3049d522f475Smrgunsigned 3050d522f475Smrgdec2ucs(unsigned ch) 3051d522f475Smrg{ 3052d522f475Smrg unsigned result = ch; 3053d522f475Smrg if (xtermIsDecGraphic(ch)) { 3054d522f475Smrg switch (ch) { 3055d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 3056d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 3057d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 3058d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 3059d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 3060d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 3061d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 3062d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 3063d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 3064d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 3065d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 3066d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 3067d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 3068d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 3069d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 3070d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 3071d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 3072d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 3073d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 3074d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 3075d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 3076d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 3077d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 3078d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 3079d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 3080d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 3081d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 3082d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 3083d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 3084d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 3085d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 3086d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 3087d522f475Smrg } 3088d522f475Smrg } 3089d522f475Smrg return result; 3090d522f475Smrg} 3091d522f475Smrg 3092d522f475Smrg#endif /* OPT_WIDE_CHARS */ 3093d522f475Smrg 3094b6fea0ceSmrg#if OPT_RENDERFONT || OPT_SHIFT_FONTS 30950bd37d32Smrgstatic int 3096d522f475SmrglookupOneFontSize(XtermWidget xw, int fontnum) 3097d522f475Smrg{ 3098d522f475Smrg TScreen *screen = TScreenOf(xw); 3099d522f475Smrg 3100d522f475Smrg if (screen->menu_font_sizes[fontnum] == 0) { 3101d522f475Smrg XTermFonts fnt; 3102d522f475Smrg 3103d522f475Smrg memset(&fnt, 0, sizeof(fnt)); 3104d522f475Smrg screen->menu_font_sizes[fontnum] = -1; 31050bd37d32Smrg if (xtermOpenFont(xw, 31060bd37d32Smrg screen->MenuFontName(fontnum), 31070bd37d32Smrg &fnt, 31080bd37d32Smrg ((fontnum <= fontMenu_lastBuiltin) 31090bd37d32Smrg ? fwAlways 31100bd37d32Smrg : fwResource), 31110bd37d32Smrg True)) { 311220d2c4d2Smrg if (fontnum <= fontMenu_lastBuiltin 31130bd37d32Smrg || strcmp(fnt.fn, DEFFONT)) { 311420d2c4d2Smrg screen->menu_font_sizes[fontnum] = FontSize(fnt.fs); 31150bd37d32Smrg if (screen->menu_font_sizes[fontnum] <= 0) 31160bd37d32Smrg screen->menu_font_sizes[fontnum] = -1; 31170bd37d32Smrg } 3118d522f475Smrg xtermCloseFont(xw, &fnt); 3119d522f475Smrg } 3120d522f475Smrg } 31210bd37d32Smrg return (screen->menu_font_sizes[fontnum] > 0); 3122d522f475Smrg} 3123d522f475Smrg 3124d522f475Smrg/* 3125d522f475Smrg * Cache the font-sizes so subsequent larger/smaller font actions will go fast. 3126d522f475Smrg */ 3127d522f475Smrgstatic void 3128d522f475SmrglookupFontSizes(XtermWidget xw) 3129d522f475Smrg{ 3130d522f475Smrg int n; 3131d522f475Smrg 3132d522f475Smrg for (n = 0; n < NMENUFONTS; n++) { 31330bd37d32Smrg (void) lookupOneFontSize(xw, n); 3134d522f475Smrg } 3135d522f475Smrg} 3136b6fea0ceSmrg#endif /* OPT_RENDERFONT || OPT_SHIFT_FONTS */ 3137d522f475Smrg 31382eaa94a1Schristos#if OPT_RENDERFONT 31399a64e1c5Smrgstatic double 31409a64e1c5SmrgdefaultFaceSize(void) 31419a64e1c5Smrg{ 31429a64e1c5Smrg double result; 31439a64e1c5Smrg float value; 31449a64e1c5Smrg 31459a64e1c5Smrg if (sscanf(DEFFACESIZE, "%f", &value) == 1) 31469a64e1c5Smrg result = value; 31479a64e1c5Smrg else 31489a64e1c5Smrg result = 14.0; 31499a64e1c5Smrg return result; 31509a64e1c5Smrg} 31519a64e1c5Smrg 31520bd37d32Smrgstatic void 31530bd37d32SmrgfillInFaceSize(XtermWidget xw, int fontnum) 31540bd37d32Smrg{ 31550bd37d32Smrg TScreen *screen = TScreenOf(xw); 31560bd37d32Smrg double face_size = xw->misc.face_size[fontnum]; 31570bd37d32Smrg 31580bd37d32Smrg if (face_size <= 0.0) { 31590bd37d32Smrg#if OPT_SHIFT_FONTS 31600bd37d32Smrg /* 31610bd37d32Smrg * If the user is switching font-sizes, make it follow by 31620bd37d32Smrg * default the same ratios to the default as the fixed fonts 31630bd37d32Smrg * would, for easy comparison. There will be some differences 31640bd37d32Smrg * since the fixed fonts have a variety of height/width ratios, 31650bd37d32Smrg * but this is simpler than adding another resource value - and 31660bd37d32Smrg * as noted above, the data for the fixed fonts are available. 31670bd37d32Smrg */ 31680bd37d32Smrg (void) lookupOneFontSize(xw, 0); 31690bd37d32Smrg if (fontnum == fontMenu_default) { 31709a64e1c5Smrg face_size = defaultFaceSize(); 31710bd37d32Smrg } else if (lookupOneFontSize(xw, fontnum) 31720bd37d32Smrg && (screen->menu_font_sizes[0] 31730bd37d32Smrg != screen->menu_font_sizes[fontnum])) { 31740bd37d32Smrg double ratio; 31750bd37d32Smrg long num = screen->menu_font_sizes[fontnum]; 31760bd37d32Smrg long den = screen->menu_font_sizes[0]; 31770bd37d32Smrg 31780bd37d32Smrg if (den <= 0) 31790bd37d32Smrg den = 1; 31800bd37d32Smrg ratio = dimSquareRoot((double) num / (double) den); 31810bd37d32Smrg 31820bd37d32Smrg face_size = (ratio * xw->misc.face_size[0]); 31830bd37d32Smrg TRACE(("scaled[%d] using %3ld/%ld = %.2f -> %f\n", 31840bd37d32Smrg fontnum, num, den, ratio, face_size)); 31850bd37d32Smrg } else 31860bd37d32Smrg#endif 31870bd37d32Smrg { 31880bd37d32Smrg#define LikeBitmap(s) (((s) / 78.0) * xw->misc.face_size[fontMenu_default]) 31890bd37d32Smrg switch (fontnum) { 31900bd37d32Smrg case fontMenu_font1: 31910bd37d32Smrg face_size = LikeBitmap(2.0); 31920bd37d32Smrg break; 31930bd37d32Smrg case fontMenu_font2: 31940bd37d32Smrg face_size = LikeBitmap(35.0); 31950bd37d32Smrg break; 31960bd37d32Smrg case fontMenu_font3: 31970bd37d32Smrg face_size = LikeBitmap(60.0); 31980bd37d32Smrg break; 31990bd37d32Smrg default: 32009a64e1c5Smrg face_size = defaultFaceSize(); 32010bd37d32Smrg break; 32020bd37d32Smrg case fontMenu_font4: 32030bd37d32Smrg face_size = LikeBitmap(90.0); 32040bd37d32Smrg break; 32050bd37d32Smrg case fontMenu_font5: 32060bd37d32Smrg face_size = LikeBitmap(135.0); 32070bd37d32Smrg break; 32080bd37d32Smrg case fontMenu_font6: 32090bd37d32Smrg face_size = LikeBitmap(200.0); 32100bd37d32Smrg break; 32110bd37d32Smrg } 32120bd37d32Smrg TRACE(("builtin[%d] -> %f\n", fontnum, face_size)); 32130bd37d32Smrg } 32140bd37d32Smrg xw->misc.face_size[fontnum] = (float) face_size; 32150bd37d32Smrg } 32160bd37d32Smrg} 32170bd37d32Smrg 32180bd37d32Smrg/* no selection or escape */ 32190bd37d32Smrg#define NMENU_RENDERFONTS (fontMenu_lastBuiltin + 1) 32200bd37d32Smrg 32210bd37d32Smrg/* 32220bd37d32Smrg * Workaround for breakage in font-packages - check if all of the bitmap font 32230bd37d32Smrg * sizes are the same, and if we're using TrueType fonts. 32240bd37d32Smrg */ 32252eaa94a1Schristosstatic Boolean 32262eaa94a1SchristosuseFaceSizes(XtermWidget xw) 32272eaa94a1Schristos{ 32282eaa94a1Schristos Boolean result = False; 32292eaa94a1Schristos int n; 32302eaa94a1Schristos 32310bd37d32Smrg TRACE(("useFaceSizes {{\n")); 32322eaa94a1Schristos if (UsingRenderFont(xw)) { 32330bd37d32Smrg Boolean nonzero = True; 32340bd37d32Smrg 32352eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 32362eaa94a1Schristos if (xw->misc.face_size[n] <= 0.0) { 32370bd37d32Smrg nonzero = False; 32382eaa94a1Schristos break; 32392eaa94a1Schristos } 32402eaa94a1Schristos } 32410bd37d32Smrg if (!nonzero) { 3242956cc18dSsnj Boolean broken_fonts = True; 3243956cc18dSsnj TScreen *screen = TScreenOf(xw); 32440bd37d32Smrg long first; 3245956cc18dSsnj 3246956cc18dSsnj lookupFontSizes(xw); 32470bd37d32Smrg first = screen->menu_font_sizes[0]; 3248956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 3249956cc18dSsnj if (screen->menu_font_sizes[n] > 0 3250956cc18dSsnj && screen->menu_font_sizes[n] != first) { 3251956cc18dSsnj broken_fonts = False; 3252956cc18dSsnj break; 3253956cc18dSsnj } 3254956cc18dSsnj } 3255956cc18dSsnj 3256956cc18dSsnj if (broken_fonts) { 3257956cc18dSsnj 3258956cc18dSsnj TRACE(("bitmap fonts are broken - set faceSize resources\n")); 3259956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 32600bd37d32Smrg fillInFaceSize(xw, n); 3261956cc18dSsnj } 3262956cc18dSsnj 3263956cc18dSsnj } 3264956cc18dSsnj } 32650bd37d32Smrg result = True; 32662eaa94a1Schristos } 32670bd37d32Smrg TRACE(("...}}useFaceSizes %d\n", result)); 32682eaa94a1Schristos return result; 32692eaa94a1Schristos} 32700bd37d32Smrg#endif /* OPT_RENDERFONT */ 32712eaa94a1Schristos 3272b6fea0ceSmrg#if OPT_SHIFT_FONTS 3273d522f475Smrg/* 3274d522f475Smrg * Find the index of a larger/smaller font (according to the sign of 'relative' 3275d522f475Smrg * and its magnitude), starting from the 'old' index. 3276d522f475Smrg */ 3277d522f475Smrgint 3278d522f475SmrglookupRelativeFontSize(XtermWidget xw, int old, int relative) 3279d522f475Smrg{ 3280d522f475Smrg TScreen *screen = TScreenOf(xw); 3281d522f475Smrg int n, m = -1; 3282d522f475Smrg 32832eaa94a1Schristos TRACE(("lookupRelativeFontSize(old=%d, relative=%d)\n", old, relative)); 3284d522f475Smrg if (!IsIcon(screen)) { 32852eaa94a1Schristos#if OPT_RENDERFONT 32862eaa94a1Schristos if (useFaceSizes(xw)) { 32872eaa94a1Schristos TRACE(("...using FaceSize\n")); 32882eaa94a1Schristos if (relative != 0) { 32892eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 32900bd37d32Smrg fillInFaceSize(xw, n); 32912eaa94a1Schristos if (xw->misc.face_size[n] > 0 && 32922eaa94a1Schristos xw->misc.face_size[n] != xw->misc.face_size[old]) { 32932eaa94a1Schristos int cmp_0 = ((xw->misc.face_size[n] > 32942eaa94a1Schristos xw->misc.face_size[old]) 32952eaa94a1Schristos ? relative 32962eaa94a1Schristos : -relative); 32972eaa94a1Schristos int cmp_m = ((m < 0) 32982eaa94a1Schristos ? 1 32992eaa94a1Schristos : ((xw->misc.face_size[n] < 33002eaa94a1Schristos xw->misc.face_size[m]) 33012eaa94a1Schristos ? relative 33022eaa94a1Schristos : -relative)); 33032eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 33042eaa94a1Schristos m = n; 33052eaa94a1Schristos } 3306d522f475Smrg } 3307d522f475Smrg } 3308d522f475Smrg } 33092eaa94a1Schristos } else 33102eaa94a1Schristos#endif 33112eaa94a1Schristos { 33122eaa94a1Schristos TRACE(("...using bitmap areas\n")); 33132eaa94a1Schristos lookupFontSizes(xw); 33142eaa94a1Schristos if (relative != 0) { 33152eaa94a1Schristos for (n = 0; n < NMENUFONTS; ++n) { 33162eaa94a1Schristos if (screen->menu_font_sizes[n] > 0 && 33172eaa94a1Schristos screen->menu_font_sizes[n] != 33182eaa94a1Schristos screen->menu_font_sizes[old]) { 33192eaa94a1Schristos int cmp_0 = ((screen->menu_font_sizes[n] > 33202eaa94a1Schristos screen->menu_font_sizes[old]) 33212eaa94a1Schristos ? relative 33222eaa94a1Schristos : -relative); 33232eaa94a1Schristos int cmp_m = ((m < 0) 33242eaa94a1Schristos ? 1 33252eaa94a1Schristos : ((screen->menu_font_sizes[n] < 33262eaa94a1Schristos screen->menu_font_sizes[m]) 33272eaa94a1Schristos ? relative 33282eaa94a1Schristos : -relative)); 33292eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 33302eaa94a1Schristos m = n; 33312eaa94a1Schristos } 33322eaa94a1Schristos } 33332eaa94a1Schristos } 3334d522f475Smrg } 3335d522f475Smrg } 33362eaa94a1Schristos TRACE(("...new index %d\n", m)); 33372eaa94a1Schristos if (m >= 0) { 33382eaa94a1Schristos if (relative > 1) 33392eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative - 1); 33402eaa94a1Schristos else if (relative < -1) 33412eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative + 1); 33422eaa94a1Schristos } 3343d522f475Smrg } 3344d522f475Smrg return m; 3345d522f475Smrg} 3346d522f475Smrg 3347d522f475Smrg/* ARGSUSED */ 3348d522f475Smrgvoid 3349d522f475SmrgHandleLargerFont(Widget w GCC_UNUSED, 33509a64e1c5Smrg XEvent *event GCC_UNUSED, 3351fa3f02f3Smrg String *params GCC_UNUSED, 3352d522f475Smrg Cardinal *param_count GCC_UNUSED) 3353d522f475Smrg{ 3354956cc18dSsnj XtermWidget xw; 3355d522f475Smrg 335620d2c4d2Smrg TRACE(("Handle larger-vt-font for %p\n", (void *) w)); 3357956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 3358d522f475Smrg if (xw->misc.shift_fonts) { 3359956cc18dSsnj TScreen *screen = TScreenOf(xw); 3360d522f475Smrg int m; 3361d522f475Smrg 3362d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, 1); 3363d522f475Smrg if (m >= 0) { 3364d522f475Smrg SetVTFont(xw, m, True, NULL); 3365d522f475Smrg } else { 336620d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3367d522f475Smrg } 3368d522f475Smrg } 3369d522f475Smrg } 3370d522f475Smrg} 3371d522f475Smrg 3372d522f475Smrg/* ARGSUSED */ 3373d522f475Smrgvoid 3374d522f475SmrgHandleSmallerFont(Widget w GCC_UNUSED, 33759a64e1c5Smrg XEvent *event GCC_UNUSED, 3376fa3f02f3Smrg String *params GCC_UNUSED, 3377d522f475Smrg Cardinal *param_count GCC_UNUSED) 3378d522f475Smrg{ 3379956cc18dSsnj XtermWidget xw; 3380d522f475Smrg 338120d2c4d2Smrg TRACE(("Handle smaller-vt-font for %p\n", (void *) w)); 3382956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 3383d522f475Smrg if (xw->misc.shift_fonts) { 3384956cc18dSsnj TScreen *screen = TScreenOf(xw); 3385d522f475Smrg int m; 3386d522f475Smrg 3387d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, -1); 3388d522f475Smrg if (m >= 0) { 3389d522f475Smrg SetVTFont(xw, m, True, NULL); 3390d522f475Smrg } else { 339120d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3392d522f475Smrg } 3393d522f475Smrg } 3394d522f475Smrg } 3395d522f475Smrg} 3396b6fea0ceSmrg#endif /* OPT_SHIFT_FONTS */ 3397d522f475Smrg 3398d522f475Smrgint 3399d522f475SmrgxtermGetFont(const char *param) 3400d522f475Smrg{ 3401d522f475Smrg int fontnum; 3402d522f475Smrg 3403d522f475Smrg switch (param[0]) { 3404d522f475Smrg case 'd': 3405d522f475Smrg case 'D': 3406d522f475Smrg case '0': 3407d522f475Smrg fontnum = fontMenu_default; 3408d522f475Smrg break; 3409d522f475Smrg case '1': 3410d522f475Smrg fontnum = fontMenu_font1; 3411d522f475Smrg break; 3412d522f475Smrg case '2': 3413d522f475Smrg fontnum = fontMenu_font2; 3414d522f475Smrg break; 3415d522f475Smrg case '3': 3416d522f475Smrg fontnum = fontMenu_font3; 3417d522f475Smrg break; 3418d522f475Smrg case '4': 3419d522f475Smrg fontnum = fontMenu_font4; 3420d522f475Smrg break; 3421d522f475Smrg case '5': 3422d522f475Smrg fontnum = fontMenu_font5; 3423d522f475Smrg break; 3424d522f475Smrg case '6': 3425d522f475Smrg fontnum = fontMenu_font6; 3426d522f475Smrg break; 3427d522f475Smrg case 'e': 3428d522f475Smrg case 'E': 3429d522f475Smrg fontnum = fontMenu_fontescape; 3430d522f475Smrg break; 3431d522f475Smrg case 's': 3432d522f475Smrg case 'S': 3433d522f475Smrg fontnum = fontMenu_fontsel; 3434d522f475Smrg break; 3435d522f475Smrg default: 3436d522f475Smrg fontnum = -1; 3437d522f475Smrg break; 3438d522f475Smrg } 3439d522f475Smrg return fontnum; 3440d522f475Smrg} 3441d522f475Smrg 3442d522f475Smrg/* ARGSUSED */ 3443d522f475Smrgvoid 3444d522f475SmrgHandleSetFont(Widget w GCC_UNUSED, 34459a64e1c5Smrg XEvent *event GCC_UNUSED, 3446fa3f02f3Smrg String *params, 3447d522f475Smrg Cardinal *param_count) 3448d522f475Smrg{ 3449956cc18dSsnj XtermWidget xw; 3450956cc18dSsnj 3451956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 3452d522f475Smrg int fontnum; 3453d522f475Smrg VTFontNames fonts; 3454d522f475Smrg 3455d522f475Smrg memset(&fonts, 0, sizeof(fonts)); 3456d522f475Smrg 3457d522f475Smrg if (*param_count == 0) { 3458d522f475Smrg fontnum = fontMenu_default; 3459d522f475Smrg } else { 3460d522f475Smrg Cardinal maxparams = 1; /* total number of params allowed */ 3461d522f475Smrg int result = xtermGetFont(params[0]); 3462d522f475Smrg 3463d522f475Smrg switch (result) { 3464d522f475Smrg case fontMenu_default: /* FALLTHRU */ 3465d522f475Smrg case fontMenu_font1: /* FALLTHRU */ 3466d522f475Smrg case fontMenu_font2: /* FALLTHRU */ 3467d522f475Smrg case fontMenu_font3: /* FALLTHRU */ 3468d522f475Smrg case fontMenu_font4: /* FALLTHRU */ 3469d522f475Smrg case fontMenu_font5: /* FALLTHRU */ 3470d522f475Smrg case fontMenu_font6: /* FALLTHRU */ 3471d522f475Smrg break; 3472d522f475Smrg case fontMenu_fontescape: 3473d522f475Smrg#if OPT_WIDE_CHARS 3474d522f475Smrg maxparams = 5; 3475d522f475Smrg#else 3476d522f475Smrg maxparams = 3; 3477d522f475Smrg#endif 3478d522f475Smrg break; 3479d522f475Smrg case fontMenu_fontsel: 3480d522f475Smrg maxparams = 2; 3481d522f475Smrg break; 3482d522f475Smrg default: 348320d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3484d522f475Smrg return; 3485d522f475Smrg } 3486d522f475Smrg fontnum = result; 3487d522f475Smrg 3488d522f475Smrg if (*param_count > maxparams) { /* see if extra args given */ 348920d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3490d522f475Smrg return; 3491d522f475Smrg } 3492d522f475Smrg switch (*param_count) { /* assign 'em */ 3493d522f475Smrg#if OPT_WIDE_CHARS 3494d522f475Smrg case 5: 3495d522f475Smrg fonts.f_wb = params[4]; 3496d522f475Smrg /* FALLTHRU */ 3497d522f475Smrg case 4: 3498d522f475Smrg fonts.f_w = params[3]; 3499d522f475Smrg /* FALLTHRU */ 3500d522f475Smrg#endif 3501d522f475Smrg case 3: 3502d522f475Smrg fonts.f_b = params[2]; 3503d522f475Smrg /* FALLTHRU */ 3504d522f475Smrg case 2: 3505d522f475Smrg fonts.f_n = params[1]; 3506d522f475Smrg break; 3507d522f475Smrg } 3508d522f475Smrg } 3509d522f475Smrg 3510956cc18dSsnj SetVTFont(xw, fontnum, True, &fonts); 3511d522f475Smrg } 3512d522f475Smrg} 3513d522f475Smrg 3514d522f475Smrgvoid 3515d522f475SmrgSetVTFont(XtermWidget xw, 3516d522f475Smrg int which, 3517d522f475Smrg Bool doresize, 3518d522f475Smrg const VTFontNames * fonts) 3519d522f475Smrg{ 3520956cc18dSsnj TScreen *screen = TScreenOf(xw); 3521d522f475Smrg 3522d522f475Smrg TRACE(("SetVTFont(which=%d, f_n=%s, f_b=%s)\n", which, 3523d522f475Smrg (fonts && fonts->f_n) ? fonts->f_n : "<null>", 3524d522f475Smrg (fonts && fonts->f_b) ? fonts->f_b : "<null>")); 3525d522f475Smrg 3526d522f475Smrg if (IsIcon(screen)) { 352720d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3528d522f475Smrg } else if (which >= 0 && which < NMENUFONTS) { 3529d522f475Smrg VTFontNames myfonts; 3530d522f475Smrg 3531d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 3532d522f475Smrg if (fonts != 0) 3533d522f475Smrg myfonts = *fonts; 3534d522f475Smrg 3535d522f475Smrg if (which == fontMenu_fontsel) { /* go get the selection */ 3536d522f475Smrg FindFontSelection(xw, myfonts.f_n, False); 3537d522f475Smrg } else { 3538d522f475Smrg int oldFont = screen->menu_font_number; 3539d522f475Smrg 3540d522f475Smrg#define USE_CACHED(field, name) \ 3541d522f475Smrg if (myfonts.field == 0) { \ 3542492d43a5Smrg myfonts.field = x_strdup(screen->menu_font_names[which][name]); \ 3543d522f475Smrg TRACE(("set myfonts." #field " from menu_font_names[%d][" #name "] %s\n", \ 3544d522f475Smrg which, NonNull(myfonts.field))); \ 3545d522f475Smrg } else { \ 3546d522f475Smrg TRACE(("set myfonts." #field " reused\n")); \ 3547d522f475Smrg } 354820d2c4d2Smrg#define SAVE_FNAME(field, name) \ 354920d2c4d2Smrg if (myfonts.field != 0) { \ 355020d2c4d2Smrg if (screen->menu_font_names[which][name] == 0 \ 355120d2c4d2Smrg || strcmp(screen->menu_font_names[which][name], myfonts.field)) { \ 355220d2c4d2Smrg TRACE(("updating menu_font_names[%d][" #name "] to %s\n", \ 355320d2c4d2Smrg which, myfonts.field)); \ 35549a64e1c5Smrg FREE_STRING(screen->menu_font_names[which][name]); \ 355520d2c4d2Smrg screen->menu_font_names[which][name] = x_strdup(myfonts.field); \ 355620d2c4d2Smrg } \ 355720d2c4d2Smrg } 355820d2c4d2Smrg 3559d522f475Smrg USE_CACHED(f_n, fNorm); 3560d522f475Smrg USE_CACHED(f_b, fBold); 3561d522f475Smrg#if OPT_WIDE_CHARS 3562d522f475Smrg USE_CACHED(f_w, fWide); 3563d522f475Smrg USE_CACHED(f_wb, fWBold); 3564d522f475Smrg#endif 3565d522f475Smrg if (xtermLoadFont(xw, 3566d522f475Smrg &myfonts, 3567d522f475Smrg doresize, which)) { 356820d2c4d2Smrg /* 356920d2c4d2Smrg * If successful, save the data so that a subsequent query via 357020d2c4d2Smrg * OSC-50 will return the expected values. 357120d2c4d2Smrg */ 357220d2c4d2Smrg SAVE_FNAME(f_n, fNorm); 357320d2c4d2Smrg SAVE_FNAME(f_b, fBold); 357420d2c4d2Smrg#if OPT_WIDE_CHARS 357520d2c4d2Smrg SAVE_FNAME(f_w, fWide); 357620d2c4d2Smrg SAVE_FNAME(f_wb, fWBold); 357720d2c4d2Smrg#endif 3578d522f475Smrg } else { 357994644356Smrg (void) xtermLoadFont(xw, 358094644356Smrg xtermFontName(screen->MenuFontName(oldFont)), 358194644356Smrg doresize, oldFont); 358220d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3583d522f475Smrg } 35849a64e1c5Smrg FREE_FNAME(f_n); 35859a64e1c5Smrg FREE_FNAME(f_b); 35869a64e1c5Smrg#if OPT_WIDE_CHARS 35879a64e1c5Smrg FREE_FNAME(f_w); 35889a64e1c5Smrg FREE_FNAME(f_wb); 35899a64e1c5Smrg#endif 3590d522f475Smrg } 359120d2c4d2Smrg } else { 359220d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3593d522f475Smrg } 3594d522f475Smrg return; 3595d522f475Smrg} 3596