fontutils.c revision 9a64e1c5
19a64e1c5Smrg/* $XTermId: fontutils.c,v 1.439 2014/06/17 20:38:27 tom Exp $ */ 2d522f475Smrg 30bd37d32Smrg/* 49a64e1c5Smrg * Copyright 1998-2013,2014 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 549a64e1c5Smrg#define ALLOC_STRING(name) \ 559a64e1c5Smrg if (name != 0) \ 569a64e1c5Smrg name = x_strdup(name) 579a64e1c5Smrg#define FREE_STRING(name) \ 589a64e1c5Smrg free_string(name) 599a64e1c5Smrg 600bd37d32Smrg#define SetFontWidth(screen,dst,src) (dst)->f_width = (src) 610bd37d32Smrg#define SetFontHeight(screen,dst,src) (dst)->f_height = dimRound((screen)->scale_height * (float) (src)) 620bd37d32Smrg 63d522f475Smrg/* from X11/Xlibint.h - not all vendors install this file */ 64d522f475Smrg#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \ 65d522f475Smrg (((cs)->rbearing|(cs)->lbearing| \ 66d522f475Smrg (cs)->ascent|(cs)->descent) == 0)) 67d522f475Smrg 68fa3f02f3Smrg#define CI_GET_CHAR_INFO_1D(fs,col,cs) \ 69d522f475Smrg{ \ 70fa3f02f3Smrg cs = 0; \ 71d522f475Smrg if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 72d522f475Smrg if (fs->per_char == NULL) { \ 73d522f475Smrg cs = &fs->min_bounds; \ 74d522f475Smrg } else { \ 75d522f475Smrg cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \ 76d522f475Smrg } \ 77fa3f02f3Smrg if (CI_NONEXISTCHAR(cs)) cs = 0; \ 78d522f475Smrg } \ 79d522f475Smrg} 80d522f475Smrg 81fa3f02f3Smrg#define CI_GET_CHAR_INFO_2D(fs,row,col,cs) \ 82d522f475Smrg{ \ 83fa3f02f3Smrg cs = 0; \ 84d522f475Smrg if (row >= fs->min_byte1 && row <= fs->max_byte1 && \ 85d522f475Smrg col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \ 86d522f475Smrg if (fs->per_char == NULL) { \ 87d522f475Smrg cs = &fs->min_bounds; \ 88d522f475Smrg } else { \ 89d522f475Smrg cs = &fs->per_char[((row - fs->min_byte1) * \ 90d522f475Smrg (fs->max_char_or_byte2 - \ 91d522f475Smrg fs->min_char_or_byte2 + 1)) + \ 92d522f475Smrg (col - fs->min_char_or_byte2)]; \ 93d522f475Smrg } \ 94fa3f02f3Smrg if (CI_NONEXISTCHAR(cs)) cs = 0; \ 95d522f475Smrg } \ 96d522f475Smrg} 97d522f475Smrg 989a64e1c5Smrg#define FREE_FNAME(field) \ 999a64e1c5Smrg if (fonts == 0 || myfonts.field != fonts->field) { \ 1009a64e1c5Smrg FREE_STRING(myfonts.field); \ 1019a64e1c5Smrg myfonts.field = 0; \ 1029a64e1c5Smrg } 1039a64e1c5Smrg 104d522f475Smrg/* 105d522f475Smrg * A structure to hold the relevant properties from a font 106d522f475Smrg * we need to make a well formed font name for it. 107d522f475Smrg */ 108d522f475Smrgtypedef struct { 109d522f475Smrg /* registry, foundry, family */ 1109a64e1c5Smrg const char *beginning; 111d522f475Smrg /* weight */ 1129a64e1c5Smrg const char *weight; 113d522f475Smrg /* slant */ 1149a64e1c5Smrg const char *slant; 115d522f475Smrg /* wideness */ 1169a64e1c5Smrg const char *wideness; 117d522f475Smrg /* add style */ 1189a64e1c5Smrg const char *add_style; 119d522f475Smrg int pixel_size; 1209a64e1c5Smrg const char *point_size; 121d522f475Smrg int res_x; 122d522f475Smrg int res_y; 1239a64e1c5Smrg const char *spacing; 124d522f475Smrg int average_width; 125d522f475Smrg /* charset registry, charset encoding */ 126d522f475Smrg char *end; 127d522f475Smrg} FontNameProperties; 128d522f475Smrg 1299a64e1c5Smrgstatic void 1309a64e1c5Smrgfree_string(String value) 1319a64e1c5Smrg{ 1329a64e1c5Smrg free((void *) value); 1339a64e1c5Smrg} 1349a64e1c5Smrg 1350bd37d32Smrg#if OPT_RENDERFONT 1360bd37d32Smrgstatic void fillInFaceSize(XtermWidget, int); 1370bd37d32Smrg#endif 1380bd37d32Smrg 139d522f475Smrg#if OPT_SHIFT_FONTS 1400bd37d32Smrgstatic int lookupOneFontSize(XtermWidget, int); 141d522f475Smrg#endif 142d522f475Smrg 143fa3f02f3Smrg#if OPT_REPORT_FONTS || OPT_WIDE_CHARS 1442eaa94a1Schristosstatic unsigned 1459a64e1c5SmrgcountGlyphs(XFontStruct *fp) 146d522f475Smrg{ 147d522f475Smrg unsigned count = 0; 148d522f475Smrg 149d522f475Smrg if (fp != 0) { 150d522f475Smrg if (fp->min_byte1 == 0 && fp->max_byte1 == 0) { 151fa3f02f3Smrg count = fp->max_char_or_byte2 - fp->min_char_or_byte2 + 1; 152d522f475Smrg } else if (fp->min_char_or_byte2 < 256 153d522f475Smrg && fp->max_char_or_byte2 < 256) { 154d522f475Smrg unsigned first = (fp->min_byte1 << 8) + fp->min_char_or_byte2; 155d522f475Smrg unsigned last = (fp->max_byte1 << 8) + fp->max_char_or_byte2; 156d522f475Smrg count = last + 1 - first; 157d522f475Smrg } 158d522f475Smrg } 159d522f475Smrg return count; 160d522f475Smrg} 161fa3f02f3Smrg#endif 162d522f475Smrg 163fa3f02f3Smrg#if OPT_WIDE_CHARS 164d522f475Smrg/* 165d522f475Smrg * Verify that the wide-bold font is at least a bold font with roughly as many 166d522f475Smrg * glyphs as the wide font. The counts should be the same, but settle for 167d522f475Smrg * filtering out the worst of the font mismatches. 168d522f475Smrg */ 169d522f475Smrgstatic Bool 1709a64e1c5SmrgcompatibleWideCounts(XFontStruct *wfs, XFontStruct *wbfs) 171d522f475Smrg{ 172d522f475Smrg unsigned count_w = countGlyphs(wfs); 173d522f475Smrg unsigned count_wb = countGlyphs(wbfs); 174d522f475Smrg if (count_w <= 256 || 175d522f475Smrg count_wb <= 256 || 176d522f475Smrg ((count_w / 4) * 3) > count_wb) { 177d522f475Smrg TRACE(("...font server lied (count wide %u vs wide-bold %u)\n", 178d522f475Smrg count_w, count_wb)); 179d522f475Smrg return False; 180d522f475Smrg } 181d522f475Smrg return True; 182d522f475Smrg} 183d522f475Smrg#endif /* OPT_WIDE_CHARS */ 184d522f475Smrg 18520d2c4d2Smrg#if OPT_BOX_CHARS 18620d2c4d2Smrgstatic void 18720d2c4d2SmrgsetupPackedFonts(XtermWidget xw) 18820d2c4d2Smrg{ 18920d2c4d2Smrg TScreen *screen = TScreenOf(xw); 19020d2c4d2Smrg Bool value = False; 19120d2c4d2Smrg 19220d2c4d2Smrg#if OPT_RENDERFONT 19320d2c4d2Smrg#define MIXED(name) screen->name[fontnum].map.mixed 1940bd37d32Smrg if (xw->work.render_font == True) { 19520d2c4d2Smrg int fontnum = screen->menu_font_number; 19620d2c4d2Smrg 19720d2c4d2Smrg screen->allow_packing = (Boolean) (MIXED(renderFontNorm) 19820d2c4d2Smrg || MIXED(renderFontBold) 19920d2c4d2Smrg || MIXED(renderFontItal) 20020d2c4d2Smrg#if OPT_RENDERWIDE 20120d2c4d2Smrg || MIXED(renderWideNorm) 20220d2c4d2Smrg || MIXED(renderWideBold) 20320d2c4d2Smrg || MIXED(renderWideItal) 20420d2c4d2Smrg#endif 20520d2c4d2Smrg ); 20620d2c4d2Smrg#undef MIXED 20720d2c4d2Smrg } 20820d2c4d2Smrg#endif /* OPT_RENDERFONT */ 20920d2c4d2Smrg 21020d2c4d2Smrg value = screen->allow_packing; 21120d2c4d2Smrg 21220d2c4d2Smrg SetItemSensitivity(fontMenuEntries[fontMenu_font_packedfont].widget, value); 21320d2c4d2Smrg} 21420d2c4d2Smrg#endif 21520d2c4d2Smrg 216d522f475Smrg/* 217d522f475Smrg * Returns the fields from start to stop in a dash- separated string. This 2189a64e1c5Smrg * function will modify the source, putting '\0's in the appropriate place and 219d522f475Smrg * moving the beginning forward to after the '\0' 220d522f475Smrg * 221d522f475Smrg * This will NOT work for the last field (but we won't need it). 222d522f475Smrg */ 223d522f475Smrgstatic char * 224d522f475Smrgn_fields(char **source, int start, int stop) 225d522f475Smrg{ 226d522f475Smrg int i; 227d522f475Smrg char *str, *str1; 228d522f475Smrg 229d522f475Smrg /* 230d522f475Smrg * find the start-1th dash 231d522f475Smrg */ 2329a64e1c5Smrg for (i = start - 1, str = *source; i; i--, str++) { 233d522f475Smrg if ((str = strchr(str, '-')) == 0) 234d522f475Smrg return 0; 2359a64e1c5Smrg } 236d522f475Smrg 237d522f475Smrg /* 238d522f475Smrg * find the stopth dash 239d522f475Smrg */ 2409a64e1c5Smrg for (i = stop - start + 1, str1 = str; i; i--, str1++) { 241d522f475Smrg if ((str1 = strchr(str1, '-')) == 0) 242d522f475Smrg return 0; 2439a64e1c5Smrg } 244d522f475Smrg 245d522f475Smrg /* 246d522f475Smrg * put a \0 at the end of the fields 247d522f475Smrg */ 248d522f475Smrg *(str1 - 1) = '\0'; 249d522f475Smrg 250d522f475Smrg /* 251d522f475Smrg * move source forward 252d522f475Smrg */ 253d522f475Smrg *source = str1; 254d522f475Smrg 255d522f475Smrg return str; 256d522f475Smrg} 257d522f475Smrg 258956cc18dSsnjstatic Boolean 259956cc18dSsnjcheck_fontname(const char *name) 260956cc18dSsnj{ 261956cc18dSsnj Boolean result = True; 262956cc18dSsnj 263492d43a5Smrg if (IsEmpty(name)) { 264956cc18dSsnj TRACE(("fontname missing\n")); 265956cc18dSsnj result = False; 266956cc18dSsnj } 267956cc18dSsnj return result; 268956cc18dSsnj} 269956cc18dSsnj 270d522f475Smrg/* 271d522f475Smrg * Gets the font properties from a given font structure. We use the FONT name 272d522f475Smrg * to find them out, since that seems easier. 273d522f475Smrg * 274d522f475Smrg * Returns a pointer to a static FontNameProperties structure 275d522f475Smrg * or NULL on error. 276d522f475Smrg */ 277d522f475Smrgstatic FontNameProperties * 2789a64e1c5Smrgget_font_name_props(Display *dpy, XFontStruct *fs, char **result) 279d522f475Smrg{ 280d522f475Smrg static FontNameProperties props; 281d522f475Smrg static char *last_name; 282d522f475Smrg 283d522f475Smrg XFontProp *fp; 284d522f475Smrg int i; 285d522f475Smrg Atom fontatom = XInternAtom(dpy, "FONT", False); 28620d2c4d2Smrg char *name = 0; 287d522f475Smrg char *str; 288d522f475Smrg 289d522f475Smrg /* 290d522f475Smrg * first get the full font name 291d522f475Smrg */ 29220d2c4d2Smrg if (fontatom != 0) { 29320d2c4d2Smrg for (i = 0, fp = fs->properties; i < fs->n_properties; i++, fp++) { 29420d2c4d2Smrg if (fp->name == fontatom) { 29520d2c4d2Smrg name = XGetAtomName(dpy, fp->card32); 29620d2c4d2Smrg break; 29720d2c4d2Smrg } 29820d2c4d2Smrg } 29920d2c4d2Smrg } 300d522f475Smrg 301d522f475Smrg if (name == 0) 302d522f475Smrg return 0; 303d522f475Smrg 304d522f475Smrg /* 305d522f475Smrg * XGetAtomName allocates memory - don't leak 306d522f475Smrg */ 307d522f475Smrg if (last_name != 0) 308d522f475Smrg XFree(last_name); 309d522f475Smrg last_name = name; 310d522f475Smrg 311d522f475Smrg if (result != 0) { 312956cc18dSsnj if (!check_fontname(name)) 313d522f475Smrg return 0; 3140bd37d32Smrg if (*result != 0) 3150bd37d32Smrg free(*result); 3160bd37d32Smrg *result = x_strdup(name); 317d522f475Smrg } 318d522f475Smrg 319d522f475Smrg /* 320d522f475Smrg * Now split it up into parts and put them in 321d522f475Smrg * their places. Since we are using parts of 322d522f475Smrg * the original string, we must not free the Atom Name 323d522f475Smrg */ 324d522f475Smrg 325d522f475Smrg /* registry, foundry, family */ 326d522f475Smrg if ((props.beginning = n_fields(&name, 1, 3)) == 0) 327d522f475Smrg return 0; 328d522f475Smrg 329d522f475Smrg /* weight is the next */ 330d522f475Smrg if ((props.weight = n_fields(&name, 1, 1)) == 0) 331d522f475Smrg return 0; 332d522f475Smrg 333d522f475Smrg /* slant */ 334d522f475Smrg if ((props.slant = n_fields(&name, 1, 1)) == 0) 335d522f475Smrg return 0; 336d522f475Smrg 337d522f475Smrg /* width */ 338d522f475Smrg if ((props.wideness = n_fields(&name, 1, 1)) == 0) 339d522f475Smrg return 0; 340d522f475Smrg 341d522f475Smrg /* add style */ 342d522f475Smrg if ((props.add_style = n_fields(&name, 1, 1)) == 0) 343d522f475Smrg return 0; 344d522f475Smrg 345d522f475Smrg /* pixel size */ 346d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 347d522f475Smrg return 0; 348d522f475Smrg if ((props.pixel_size = atoi(str)) == 0) 349d522f475Smrg return 0; 350d522f475Smrg 351d522f475Smrg /* point size */ 352d522f475Smrg if ((props.point_size = n_fields(&name, 1, 1)) == 0) 353d522f475Smrg return 0; 354d522f475Smrg 355d522f475Smrg /* res_x */ 356d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 357d522f475Smrg return 0; 358d522f475Smrg if ((props.res_x = atoi(str)) == 0) 359d522f475Smrg return 0; 360d522f475Smrg 361d522f475Smrg /* res_y */ 362d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 363d522f475Smrg return 0; 364d522f475Smrg if ((props.res_y = atoi(str)) == 0) 365d522f475Smrg return 0; 366d522f475Smrg 367d522f475Smrg /* spacing */ 368d522f475Smrg if ((props.spacing = n_fields(&name, 1, 1)) == 0) 369d522f475Smrg return 0; 370d522f475Smrg 371d522f475Smrg /* average width */ 372d522f475Smrg if ((str = n_fields(&name, 1, 1)) == 0) 373d522f475Smrg return 0; 374d522f475Smrg if ((props.average_width = atoi(str)) == 0) 375d522f475Smrg return 0; 376d522f475Smrg 377d522f475Smrg /* the rest: charset registry and charset encoding */ 378d522f475Smrg props.end = name; 379d522f475Smrg 380d522f475Smrg return &props; 381d522f475Smrg} 382d522f475Smrg 383d522f475Smrg#define ALLOCHUNK(n) ((n | 127) + 1) 384d522f475Smrg 385d522f475Smrgstatic void 386956cc18dSsnjalloca_fontname(char **result, size_t next) 387d522f475Smrg{ 388956cc18dSsnj size_t last = (*result != 0) ? strlen(*result) : 0; 389956cc18dSsnj size_t have = (*result != 0) ? ALLOCHUNK(last) : 0; 390956cc18dSsnj size_t want = last + next + 2; 391d522f475Smrg 392d522f475Smrg if (want >= have) { 393d522f475Smrg want = ALLOCHUNK(want); 394d522f475Smrg if (last != 0) { 3959a64e1c5Smrg char *save = *result; 396d522f475Smrg *result = TypeRealloc(char, want, *result); 3979a64e1c5Smrg if (*result == 0) 3989a64e1c5Smrg free(save); 399d522f475Smrg } else { 400d522f475Smrg if ((*result = TypeMallocN(char, want)) != 0) 401d522f475Smrg **result = '\0'; 402d522f475Smrg } 403d522f475Smrg } 404d522f475Smrg} 405d522f475Smrg 406d522f475Smrgstatic void 40720d2c4d2Smrgappend_fontname_str(char **result, const char *value) 408d522f475Smrg{ 409d522f475Smrg if (value == 0) 410d522f475Smrg value = "*"; 411d522f475Smrg alloca_fontname(result, strlen(value)); 412d522f475Smrg if (*result != 0) { 413d522f475Smrg if (**result != '\0') 414d522f475Smrg strcat(*result, "-"); 415d522f475Smrg strcat(*result, value); 416d522f475Smrg } 417d522f475Smrg} 418d522f475Smrg 419d522f475Smrgstatic void 420d522f475Smrgappend_fontname_num(char **result, int value) 421d522f475Smrg{ 422d522f475Smrg if (value < 0) { 423d522f475Smrg append_fontname_str(result, "*"); 424d522f475Smrg } else { 425d522f475Smrg char temp[100]; 426d522f475Smrg sprintf(temp, "%d", value); 427d522f475Smrg append_fontname_str(result, temp); 428d522f475Smrg } 429d522f475Smrg} 430d522f475Smrg 431d522f475Smrg/* 432d522f475Smrg * Take the given font props and try to make a well formed font name specifying 433d522f475Smrg * the same base font and size and everything, but with different weight/width 434d522f475Smrg * according to the parameters. The return value is allocated, should be freed 435d522f475Smrg * by the caller. 436d522f475Smrg */ 437d522f475Smrgstatic char * 4389a64e1c5Smrgderive_font_name(FontNameProperties *props, 43920d2c4d2Smrg const char *use_weight, 440d522f475Smrg int use_average_width, 44120d2c4d2Smrg const char *use_encoding) 442d522f475Smrg{ 443d522f475Smrg char *result = 0; 444d522f475Smrg 445d522f475Smrg append_fontname_str(&result, props->beginning); 446d522f475Smrg append_fontname_str(&result, use_weight); 447d522f475Smrg append_fontname_str(&result, props->slant); 448d522f475Smrg append_fontname_str(&result, 0); 449d522f475Smrg append_fontname_str(&result, 0); 450d522f475Smrg append_fontname_num(&result, props->pixel_size); 451d522f475Smrg append_fontname_str(&result, props->point_size); 452d522f475Smrg append_fontname_num(&result, props->res_x); 453d522f475Smrg append_fontname_num(&result, props->res_y); 454d522f475Smrg append_fontname_str(&result, props->spacing); 455d522f475Smrg append_fontname_num(&result, use_average_width); 456d522f475Smrg append_fontname_str(&result, use_encoding); 457d522f475Smrg 458d522f475Smrg return result; 459d522f475Smrg} 460d522f475Smrg 461d522f475Smrgstatic char * 4629a64e1c5Smrgbold_font_name(FontNameProperties *props, int use_average_width) 463d522f475Smrg{ 464d522f475Smrg return derive_font_name(props, "bold", use_average_width, props->end); 465d522f475Smrg} 466d522f475Smrg 4679a64e1c5Smrg#if OPT_WIDE_ATTRS 4689a64e1c5Smrgstatic char * 4699a64e1c5Smrgitalic_font_name(FontNameProperties *props, int use_average_width) 4709a64e1c5Smrg{ 4719a64e1c5Smrg FontNameProperties myprops = *props; 4729a64e1c5Smrg myprops.slant = "o"; 4739a64e1c5Smrg return derive_font_name(&myprops, props->weight, use_average_width, props->end); 4749a64e1c5Smrg} 4759a64e1c5Smrg#endif 4769a64e1c5Smrg 477d522f475Smrg#if OPT_WIDE_CHARS 478d522f475Smrg#define derive_wide_font(props, weight) \ 479d522f475Smrg derive_font_name(props, weight, props->average_width * 2, "ISO10646-1") 480d522f475Smrg 481d522f475Smrgstatic char * 4829a64e1c5Smrgwide_font_name(FontNameProperties *props) 483d522f475Smrg{ 484d522f475Smrg return derive_wide_font(props, "medium"); 485d522f475Smrg} 486d522f475Smrg 487d522f475Smrgstatic char * 4889a64e1c5Smrgwidebold_font_name(FontNameProperties *props) 489d522f475Smrg{ 490d522f475Smrg return derive_wide_font(props, "bold"); 491d522f475Smrg} 492d522f475Smrg#endif /* OPT_WIDE_CHARS */ 493d522f475Smrg 494d522f475Smrg#if OPT_DEC_CHRSET 495d522f475Smrg/* 496d522f475Smrg * Take the given font props and try to make a well formed font name specifying 497d522f475Smrg * the same base font but changed depending on the given attributes and chrset. 498d522f475Smrg * 499d522f475Smrg * For double width fonts, we just double the X-resolution, for double height 500d522f475Smrg * fonts we double the pixel-size and Y-resolution 501d522f475Smrg */ 502d522f475Smrgchar * 5039a64e1c5SmrgxtermSpecialFont(TScreen *screen, unsigned attr_flags, unsigned draw_flags, unsigned chrset) 504d522f475Smrg{ 505d522f475Smrg#if OPT_TRACE 506d522f475Smrg static char old_spacing[80]; 507d522f475Smrg static FontNameProperties old_props; 508d522f475Smrg#endif 509d522f475Smrg FontNameProperties *props; 510d522f475Smrg char *result = 0; 51120d2c4d2Smrg const char *weight; 512d522f475Smrg int pixel_size; 513d522f475Smrg int res_x; 514d522f475Smrg int res_y; 515d522f475Smrg 516d522f475Smrg props = get_font_name_props(screen->display, screen->fnts[fNorm].fs, 0); 517d522f475Smrg if (props == 0) 518d522f475Smrg return result; 519d522f475Smrg 520d522f475Smrg pixel_size = props->pixel_size; 521d522f475Smrg res_x = props->res_x; 522d522f475Smrg res_y = props->res_y; 5239a64e1c5Smrg if (attr_flags & BOLD) 524d522f475Smrg weight = "bold"; 525d522f475Smrg else 526d522f475Smrg weight = props->weight; 527d522f475Smrg 528d522f475Smrg if (CSET_DOUBLE(chrset)) 529d522f475Smrg res_x *= 2; 530d522f475Smrg 531d522f475Smrg if (chrset == CSET_DHL_TOP 532d522f475Smrg || chrset == CSET_DHL_BOT) { 533d522f475Smrg res_y *= 2; 534d522f475Smrg pixel_size *= 2; 535d522f475Smrg } 536d522f475Smrg#if OPT_TRACE 537d522f475Smrg if (old_props.res_x != res_x 538d522f475Smrg || old_props.res_x != res_y 539d522f475Smrg || old_props.pixel_size != pixel_size 540d522f475Smrg || strcmp(old_props.spacing, props->spacing)) { 5419a64e1c5Smrg TRACE(("xtermSpecialFont(atts = %#x, draw = %#x, chrset = %#x)\n", 5429a64e1c5Smrg attr_flags, draw_flags, chrset)); 543d522f475Smrg TRACE(("res_x = %d\n", res_x)); 544d522f475Smrg TRACE(("res_y = %d\n", res_y)); 545d522f475Smrg TRACE(("point_size = %s\n", props->point_size)); 546d522f475Smrg TRACE(("pixel_size = %d\n", pixel_size)); 547d522f475Smrg TRACE(("spacing = %s\n", props->spacing)); 548d522f475Smrg old_props.res_x = res_x; 549d522f475Smrg old_props.res_x = res_y; 550d522f475Smrg old_props.pixel_size = pixel_size; 5510bd37d32Smrg old_props.spacing = old_spacing; 5520bd37d32Smrg sprintf(old_spacing, "%.*s", (int) sizeof(old_spacing) - 2, props->spacing); 553d522f475Smrg } 554d522f475Smrg#endif 555d522f475Smrg 556d522f475Smrg append_fontname_str(&result, props->beginning); 557d522f475Smrg append_fontname_str(&result, weight); 558d522f475Smrg append_fontname_str(&result, props->slant); 559d522f475Smrg append_fontname_str(&result, props->wideness); 560d522f475Smrg append_fontname_str(&result, props->add_style); 561d522f475Smrg append_fontname_num(&result, pixel_size); 562d522f475Smrg append_fontname_str(&result, props->point_size); 5639a64e1c5Smrg append_fontname_num(&result, (draw_flags & NORESOLUTION) ? -1 : res_x); 5649a64e1c5Smrg append_fontname_num(&result, (draw_flags & NORESOLUTION) ? -1 : res_y); 565d522f475Smrg append_fontname_str(&result, props->spacing); 566d522f475Smrg append_fontname_str(&result, 0); 567d522f475Smrg append_fontname_str(&result, props->end); 568d522f475Smrg 569d522f475Smrg return result; 570d522f475Smrg} 571d522f475Smrg#endif /* OPT_DEC_CHRSET */ 572d522f475Smrg 573d522f475Smrg/* 574d522f475Smrg * Case-independent comparison for font-names, including wildcards. 575d522f475Smrg * XLFD allows '?' as a wildcard, but we do not handle that (no one seems 576d522f475Smrg * to use it). 577d522f475Smrg */ 578d522f475Smrgstatic Bool 579492d43a5Smrgsame_font_name(const char *pattern, const char *match) 580d522f475Smrg{ 581956cc18dSsnj Bool result = False; 582956cc18dSsnj 583956cc18dSsnj if (pattern && match) { 584956cc18dSsnj while (*pattern && *match) { 585956cc18dSsnj if (*pattern == *match) { 586956cc18dSsnj pattern++; 587956cc18dSsnj match++; 588956cc18dSsnj } else if (*pattern == '*' || *match == '*') { 589956cc18dSsnj if (same_font_name(pattern + 1, match)) { 590956cc18dSsnj return True; 591956cc18dSsnj } else if (same_font_name(pattern, match + 1)) { 592956cc18dSsnj return True; 593956cc18dSsnj } else { 594956cc18dSsnj return False; 595956cc18dSsnj } 596d522f475Smrg } else { 597956cc18dSsnj int p = x_toupper(*pattern++); 598956cc18dSsnj int m = x_toupper(*match++); 599956cc18dSsnj if (p != m) 600956cc18dSsnj return False; 601d522f475Smrg } 602d522f475Smrg } 603956cc18dSsnj result = (*pattern == *match); /* both should be NUL */ 604d522f475Smrg } 605956cc18dSsnj return result; 606d522f475Smrg} 607d522f475Smrg 608d522f475Smrg/* 609d522f475Smrg * Double-check the fontname that we asked for versus what the font server 610d522f475Smrg * actually gave us. The larger fixed fonts do not always have a matching bold 611d522f475Smrg * font, and the font server may try to scale another font or otherwise 612d522f475Smrg * substitute a mismatched font. 613d522f475Smrg * 614d522f475Smrg * If we cannot get what we requested, we will fallback to the original 615d522f475Smrg * behavior, which simulates bold by overstriking each character at one pixel 616d522f475Smrg * offset. 617d522f475Smrg */ 618d522f475Smrgstatic int 6199a64e1c5Smrggot_bold_font(Display *dpy, XFontStruct *fs, String requested) 620d522f475Smrg{ 6210bd37d32Smrg char *actual = 0; 622d522f475Smrg int got; 623d522f475Smrg 6240bd37d32Smrg if (get_font_name_props(dpy, fs, &actual) == 0) 625d522f475Smrg got = 0; 626d522f475Smrg else 627d522f475Smrg got = same_font_name(requested, actual); 6280bd37d32Smrg free(actual); 629d522f475Smrg return got; 630d522f475Smrg} 631d522f475Smrg 6329a64e1c5Smrg/* 6339a64e1c5Smrg * Check normal/bold (or wide/wide-bold) font pairs to see if we will be able 6349a64e1c5Smrg * to check for missing glyphs in a comparable manner. 6359a64e1c5Smrg */ 6369a64e1c5Smrgstatic int 6379a64e1c5Smrgcomparable_metrics(XFontStruct *normal, XFontStruct *bold) 6389a64e1c5Smrg{ 6399a64e1c5Smrg#define DATA "comparable_metrics: " 6409a64e1c5Smrg int result = 0; 6419a64e1c5Smrg 6429a64e1c5Smrg if (normal->all_chars_exist) { 6439a64e1c5Smrg if (bold->all_chars_exist) { 6449a64e1c5Smrg result = 1; 6459a64e1c5Smrg } else { 6469a64e1c5Smrg TRACE((DATA "all chars exist in normal font, but not in bold\n")); 6479a64e1c5Smrg } 6489a64e1c5Smrg } else if (normal->per_char != 0) { 6499a64e1c5Smrg if (bold->per_char != 0) { 6509a64e1c5Smrg result = 1; 6519a64e1c5Smrg } else { 6529a64e1c5Smrg TRACE((DATA "normal font has per-char metrics, but not bold\n")); 6539a64e1c5Smrg } 6549a64e1c5Smrg } else { 6559a64e1c5Smrg TRACE((DATA "normal font is not very good!\n")); 6569a64e1c5Smrg result = 1; /* give in (we're not going in reverse) */ 6579a64e1c5Smrg } 6589a64e1c5Smrg return result; 6599a64e1c5Smrg#undef DATA 6609a64e1c5Smrg} 6619a64e1c5Smrg 662d522f475Smrg/* 663d522f475Smrg * If the font server tries to adjust another font, it may not adjust it 664d522f475Smrg * properly. Check that the bounding boxes are compatible. Otherwise we'll 665d522f475Smrg * leave trash on the display when we mix normal and bold fonts. 666d522f475Smrg */ 667d522f475Smrgstatic int 6689a64e1c5Smrgsame_font_size(XtermWidget xw, XFontStruct *nfs, XFontStruct *bfs) 669d522f475Smrg{ 670956cc18dSsnj TScreen *screen = TScreenOf(xw); 671d522f475Smrg TRACE(("same_font_size height %d/%d, min %d/%d max %d/%d\n", 672d522f475Smrg nfs->ascent + nfs->descent, 673d522f475Smrg bfs->ascent + bfs->descent, 674d522f475Smrg nfs->min_bounds.width, bfs->min_bounds.width, 675d522f475Smrg nfs->max_bounds.width, bfs->max_bounds.width)); 676956cc18dSsnj return screen->free_bold_box 677d522f475Smrg || ((nfs->ascent + nfs->descent) == (bfs->ascent + bfs->descent) 678d522f475Smrg && (nfs->min_bounds.width == bfs->min_bounds.width 679d522f475Smrg || nfs->min_bounds.width == bfs->min_bounds.width + 1) 680d522f475Smrg && (nfs->max_bounds.width == bfs->max_bounds.width 681d522f475Smrg || nfs->max_bounds.width == bfs->max_bounds.width + 1)); 682d522f475Smrg} 683d522f475Smrg 684d522f475Smrg/* 685d522f475Smrg * Check if the font looks like it has fixed width 686d522f475Smrg */ 687d522f475Smrgstatic int 6889a64e1c5Smrgis_fixed_font(XFontStruct *fs) 689d522f475Smrg{ 690d522f475Smrg if (fs) 691d522f475Smrg return (fs->min_bounds.width == fs->max_bounds.width); 692d522f475Smrg return 1; 693d522f475Smrg} 694d522f475Smrg 695d522f475Smrg/* 696d522f475Smrg * Check if the font looks like a double width font (i.e. contains 697d522f475Smrg * characters of width X and 2X 698d522f475Smrg */ 699d522f475Smrg#if OPT_WIDE_CHARS 700d522f475Smrgstatic int 7019a64e1c5Smrgis_double_width_font(XFontStruct *fs) 702d522f475Smrg{ 703d522f475Smrg return ((2 * fs->min_bounds.width) == fs->max_bounds.width); 704d522f475Smrg} 705d522f475Smrg#else 706d522f475Smrg#define is_double_width_font(fs) 0 707d522f475Smrg#endif 708d522f475Smrg 709d522f475Smrg#if OPT_WIDE_CHARS && OPT_RENDERFONT && defined(HAVE_TYPE_FCCHAR32) 710d522f475Smrg#define HALF_WIDTH_TEST_STRING "1234567890" 711d522f475Smrg 712d522f475Smrg/* '1234567890' in Chinese characters in UTF-8 */ 713d522f475Smrg#define FULL_WIDTH_TEST_STRING "\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89" \ 714d522f475Smrg "\xe5\x9b\x9b\xe4\xba\x94" \ 715d522f475Smrg "\xef\xa7\x91\xe4\xb8\x83\xe5\x85\xab" \ 716d522f475Smrg "\xe4\xb9\x9d\xef\xa6\xb2" 717d522f475Smrg 718d522f475Smrg/* '1234567890' in Korean script in UTF-8 */ 719d522f475Smrg#define FULL_WIDTH_TEST_STRING2 "\xec\x9d\xbc\xec\x9d\xb4\xec\x82\xbc" \ 720d522f475Smrg "\xec\x82\xac\xec\x98\xa4" \ 721d522f475Smrg "\xec\x9c\xa1\xec\xb9\xa0\xed\x8c\x94" \ 722d522f475Smrg "\xea\xb5\xac\xec\x98\x81" 723d522f475Smrg 724d522f475Smrg#define HALF_WIDTH_CHAR1 0x0031 /* '1' */ 725d522f475Smrg#define HALF_WIDTH_CHAR2 0x0057 /* 'W' */ 726d522f475Smrg#define FULL_WIDTH_CHAR1 0x4E00 /* CJK Ideograph 'number one' */ 727d522f475Smrg#define FULL_WIDTH_CHAR2 0xAC00 /* Korean script syllable 'Ka' */ 728d522f475Smrg 729d522f475Smrgstatic Bool 7309a64e1c5Smrgis_double_width_font_xft(Display *dpy, XftFont *font) 731d522f475Smrg{ 732d522f475Smrg XGlyphInfo gi1, gi2; 733d522f475Smrg FcChar32 c1 = HALF_WIDTH_CHAR1, c2 = HALF_WIDTH_CHAR2; 7340bd37d32Smrg String fwstr = FULL_WIDTH_TEST_STRING; 7350bd37d32Smrg String hwstr = HALF_WIDTH_TEST_STRING; 736d522f475Smrg 737d522f475Smrg /* Some Korean fonts don't have Chinese characters at all. */ 738d522f475Smrg if (!XftCharExists(dpy, font, FULL_WIDTH_CHAR1)) { 739d522f475Smrg if (!XftCharExists(dpy, font, FULL_WIDTH_CHAR2)) 740d522f475Smrg return False; /* Not a CJK font */ 741d522f475Smrg else /* a Korean font without CJK Ideographs */ 742d522f475Smrg fwstr = FULL_WIDTH_TEST_STRING2; 743d522f475Smrg } 744d522f475Smrg 745d522f475Smrg XftTextExtents32(dpy, font, &c1, 1, &gi1); 746d522f475Smrg XftTextExtents32(dpy, font, &c2, 1, &gi2); 747d522f475Smrg if (gi1.xOff != gi2.xOff) /* Not a fixed-width font */ 748d522f475Smrg return False; 749d522f475Smrg 7500bd37d32Smrg XftTextExtentsUtf8(dpy, 7510bd37d32Smrg font, 7520bd37d32Smrg (_Xconst FcChar8 *) hwstr, 7530bd37d32Smrg (int) strlen(hwstr), 7540bd37d32Smrg &gi1); 7550bd37d32Smrg XftTextExtentsUtf8(dpy, 7560bd37d32Smrg font, 7570bd37d32Smrg (_Xconst FcChar8 *) fwstr, 7580bd37d32Smrg (int) strlen(fwstr), 7590bd37d32Smrg &gi2); 760d522f475Smrg 761d522f475Smrg /* 762d522f475Smrg * fontconfig and Xft prior to 2.2(?) set the width of half-width 763d522f475Smrg * characters identical to that of full-width character in CJK double-width 764d522f475Smrg * (bi-width / monospace) font even though the former is half as wide as 765d522f475Smrg * the latter. This was fixed sometime before the release of fontconfig 766d522f475Smrg * 2.2 in early 2003. See 767d522f475Smrg * http://bugzilla.mozilla.org/show_bug.cgi?id=196312 768d522f475Smrg * In the meantime, we have to check both possibilities. 769d522f475Smrg */ 770d522f475Smrg return ((2 * gi1.xOff == gi2.xOff) || (gi1.xOff == gi2.xOff)); 771d522f475Smrg} 772d522f475Smrg#else 773d522f475Smrg#define is_double_width_font_xft(dpy, xftfont) 0 774d522f475Smrg#endif 775d522f475Smrg 776d522f475Smrg#define EmptyFont(fs) (fs != 0 \ 777d522f475Smrg && ((fs)->ascent + (fs)->descent == 0 \ 778d522f475Smrg || (fs)->max_bounds.width == 0)) 779d522f475Smrg 780d522f475Smrg#define FontSize(fs) (((fs)->ascent + (fs)->descent) \ 781d522f475Smrg * (fs)->max_bounds.width) 782d522f475Smrg 783d522f475Smrgconst VTFontNames * 78420d2c4d2SmrgxtermFontName(const char *normal) 785d522f475Smrg{ 786d522f475Smrg static VTFontNames data; 7879a64e1c5Smrg FREE_STRING(data.f_n); 788d522f475Smrg memset(&data, 0, sizeof(data)); 78920d2c4d2Smrg data.f_n = x_strdup(normal); 790d522f475Smrg return &data; 791d522f475Smrg} 792d522f475Smrg 793d522f475Smrgstatic void 794fa3f02f3Smrgcache_menu_font_name(TScreen *screen, int fontnum, int which, const char *name) 795d522f475Smrg{ 796d522f475Smrg if (name != 0) { 7979a64e1c5Smrg String last = screen->menu_font_names[fontnum][which]; 798d522f475Smrg if (last != 0) { 799d522f475Smrg if (strcmp(last, name)) { 8009a64e1c5Smrg FREE_STRING(last); 801d522f475Smrg TRACE(("caching menu fontname %d.%d %s\n", fontnum, which, name)); 802d522f475Smrg screen->menu_font_names[fontnum][which] = x_strdup(name); 803d522f475Smrg } 804d522f475Smrg } else { 805d522f475Smrg TRACE(("caching menu fontname %d.%d %s\n", fontnum, which, name)); 806d522f475Smrg screen->menu_font_names[fontnum][which] = x_strdup(name); 807d522f475Smrg } 808d522f475Smrg } 809d522f475Smrg} 810d522f475Smrg 811d522f475Smrg/* 812d522f475Smrg * Open the given font and verify that it is non-empty. Return a null on 813d522f475Smrg * failure. 814d522f475Smrg */ 815d522f475SmrgBool 816956cc18dSsnjxtermOpenFont(XtermWidget xw, 817956cc18dSsnj const char *name, 818956cc18dSsnj XTermFonts * result, 819956cc18dSsnj fontWarningTypes warn, 820956cc18dSsnj Bool force) 821d522f475Smrg{ 822d522f475Smrg Bool code = False; 823d522f475Smrg TScreen *screen = TScreenOf(xw); 824d522f475Smrg 825492d43a5Smrg if (!IsEmpty(name)) { 826956cc18dSsnj if ((result->fs = XLoadQueryFont(screen->display, name)) != 0) { 827956cc18dSsnj code = True; 828956cc18dSsnj if (EmptyFont(result->fs)) { 82920d2c4d2Smrg (void) xtermCloseFont(xw, result); 830956cc18dSsnj code = False; 831956cc18dSsnj } else { 832956cc18dSsnj result->fn = x_strdup(name); 833956cc18dSsnj } 83420d2c4d2Smrg } else if (XmuCompareISOLatin1(name, DEFFONT) != 0) { 835956cc18dSsnj if (warn <= xw->misc.fontWarnings 836956cc18dSsnj#if OPT_RENDERFONT 837956cc18dSsnj && !UsingRenderFont(xw) 838956cc18dSsnj#endif 839956cc18dSsnj ) { 840956cc18dSsnj TRACE(("OOPS: cannot load font %s\n", name)); 8410bd37d32Smrg xtermWarning("cannot load font '%s'\n", name); 84220d2c4d2Smrg#if OPT_RENDERFONT 84320d2c4d2Smrg /* 84420d2c4d2Smrg * Do a sanity check in case someone's mixed up xterm with 84520d2c4d2Smrg * one of those programs that read their resource data from 84620d2c4d2Smrg * xterm's namespace. 84720d2c4d2Smrg */ 84820d2c4d2Smrg if (strchr(name, ':') != 0 || strchr(name, '=') != 0) { 8490bd37d32Smrg xtermWarning("Use the \"-fa\" option for the Xft fonts\n"); 85020d2c4d2Smrg } 85120d2c4d2Smrg#endif 852956cc18dSsnj } else { 853492d43a5Smrg TRACE(("xtermOpenFont: cannot load font '%s'\n", name)); 854956cc18dSsnj } 855956cc18dSsnj if (force) { 856956cc18dSsnj code = xtermOpenFont(xw, DEFFONT, result, fwAlways, True); 857956cc18dSsnj } 858d522f475Smrg } 859d522f475Smrg } 860d522f475Smrg return code; 861d522f475Smrg} 862d522f475Smrg 863d522f475Smrg/* 864956cc18dSsnj * Close the font and free the font info. 865d522f475Smrg */ 866d522f475SmrgXTermFonts * 867d522f475SmrgxtermCloseFont(XtermWidget xw, XTermFonts * fnt) 868d522f475Smrg{ 869d522f475Smrg if (fnt != 0 && fnt->fs != 0) { 870d522f475Smrg TScreen *screen = TScreenOf(xw); 871d522f475Smrg 872d522f475Smrg clrCgsFonts(xw, WhichVWin(screen), fnt); 873d522f475Smrg XFreeFont(screen->display, fnt->fs); 874d522f475Smrg xtermFreeFontInfo(fnt); 875d522f475Smrg } 876d522f475Smrg return 0; 877d522f475Smrg} 878d522f475Smrg 879d522f475Smrg/* 880d522f475Smrg * Close the listed fonts, noting that some may use copies of the pointer. 881d522f475Smrg */ 882d522f475Smrgvoid 883d522f475SmrgxtermCloseFonts(XtermWidget xw, XTermFonts * fnts) 884d522f475Smrg{ 885d522f475Smrg int j, k; 886d522f475Smrg 887d522f475Smrg for (j = 0; j < fMAX; ++j) { 888d522f475Smrg /* 889d522f475Smrg * Need to save the pointer since xtermCloseFont zeroes it 890d522f475Smrg */ 891d522f475Smrg XFontStruct *thisFont = fnts[j].fs; 892d522f475Smrg if (thisFont != 0) { 893d522f475Smrg xtermCloseFont(xw, &fnts[j]); 894d522f475Smrg for (k = j + 1; k < fMAX; ++k) { 895d522f475Smrg if (thisFont == fnts[k].fs) 896d522f475Smrg xtermFreeFontInfo(&fnts[k]); 897d522f475Smrg } 898d522f475Smrg } 899d522f475Smrg } 900d522f475Smrg} 901d522f475Smrg 902d522f475Smrg/* 903d522f475Smrg * Make a copy of the source, assuming the XFontStruct's to be unique, but 904d522f475Smrg * ensuring that the names are reallocated to simplify freeing. 905d522f475Smrg */ 906d522f475Smrgvoid 907d522f475SmrgxtermCopyFontInfo(XTermFonts * target, XTermFonts * source) 908d522f475Smrg{ 909d522f475Smrg xtermFreeFontInfo(target); 910d522f475Smrg target->chrset = source->chrset; 911d522f475Smrg target->flags = source->flags; 912d522f475Smrg target->fn = x_strdup(source->fn); 913d522f475Smrg target->fs = source->fs; 914d522f475Smrg} 915d522f475Smrg 916d522f475Smrgvoid 917d522f475SmrgxtermFreeFontInfo(XTermFonts * target) 918d522f475Smrg{ 919d522f475Smrg target->chrset = 0; 920d522f475Smrg target->flags = 0; 921d522f475Smrg if (target->fn != 0) { 922d522f475Smrg free(target->fn); 923d522f475Smrg target->fn = 0; 924d522f475Smrg } 925d522f475Smrg target->fs = 0; 926d522f475Smrg} 927d522f475Smrg 928fa3f02f3Smrg#if OPT_REPORT_FONTS 929fa3f02f3Smrgstatic void 930fa3f02f3SmrgreportXCharStruct(const char *tag, XCharStruct * cs) 931fa3f02f3Smrg{ 932fa3f02f3Smrg printf("\t\t%s:\n", tag); 933fa3f02f3Smrg printf("\t\t\tlbearing: %d\n", cs->lbearing); 934fa3f02f3Smrg printf("\t\t\trbearing: %d\n", cs->rbearing); 935fa3f02f3Smrg printf("\t\t\twidth: %d\n", cs->width); 936fa3f02f3Smrg printf("\t\t\tascent: %d\n", cs->ascent); 937fa3f02f3Smrg printf("\t\t\tdescent: %d\n", cs->descent); 938fa3f02f3Smrg} 939fa3f02f3Smrg 940fa3f02f3Smrgstatic void 941fa3f02f3SmrgreportOneVTFont(const char *tag, 942fa3f02f3Smrg XTermFonts * fnt) 943fa3f02f3Smrg{ 944fa3f02f3Smrg if (!IsEmpty(fnt->fn)) { 945fa3f02f3Smrg XFontStruct *fs = fnt->fs; 946fa3f02f3Smrg unsigned first_char = 0; 947fa3f02f3Smrg unsigned last_char = 0; 948fa3f02f3Smrg unsigned ch; 949fa3f02f3Smrg 950fa3f02f3Smrg if (fs->max_byte1 == 0) { 951fa3f02f3Smrg first_char = fs->min_char_or_byte2; 952fa3f02f3Smrg last_char = fs->max_char_or_byte2; 953fa3f02f3Smrg } else { 954fa3f02f3Smrg first_char = (fs->min_byte1 * 256) + fs->min_char_or_byte2; 955fa3f02f3Smrg last_char = (fs->max_byte1 * 256) + fs->max_char_or_byte2; 956fa3f02f3Smrg } 957fa3f02f3Smrg 958fa3f02f3Smrg printf("\t%s: %s\n", tag, NonNull(fnt->fn)); 959fa3f02f3Smrg printf("\t\tall chars: %s\n", fs->all_chars_exist ? "yes" : "no"); 960fa3f02f3Smrg printf("\t\tdefault char: %d\n", fs->default_char); 961fa3f02f3Smrg printf("\t\tdirection: %d\n", fs->direction); 962fa3f02f3Smrg printf("\t\tascent: %d\n", fs->ascent); 963fa3f02f3Smrg printf("\t\tdescent: %d\n", fs->descent); 964fa3f02f3Smrg printf("\t\tfirst char: %u\n", first_char); 965fa3f02f3Smrg printf("\t\tlast char: %u\n", last_char); 966fa3f02f3Smrg printf("\t\tmaximum-chars: %u\n", countGlyphs(fs)); 9679a64e1c5Smrg if (FontLacksMetrics(fnt)) { 9689a64e1c5Smrg printf("\t\tmissing-chars: ?\n"); 9699a64e1c5Smrg printf("\t\tpresent-chars: ?\n"); 9709a64e1c5Smrg } else { 9719a64e1c5Smrg unsigned missing = 0; 9729a64e1c5Smrg for (ch = first_char; ch <= last_char; ++ch) { 9739a64e1c5Smrg if (xtermMissingChar(ch, fnt)) { 9749a64e1c5Smrg ++missing; 9759a64e1c5Smrg } 9769a64e1c5Smrg } 9779a64e1c5Smrg printf("\t\tmissing-chars: %u\n", missing); 9789a64e1c5Smrg printf("\t\tpresent-chars: %u\n", countGlyphs(fs) - missing); 9799a64e1c5Smrg } 980fa3f02f3Smrg printf("\t\tmin_byte1: %d\n", fs->min_byte1); 981fa3f02f3Smrg printf("\t\tmax_byte1: %d\n", fs->max_byte1); 982fa3f02f3Smrg printf("\t\tproperties: %d\n", fs->n_properties); 983fa3f02f3Smrg reportXCharStruct("min_bounds", &(fs->min_bounds)); 984fa3f02f3Smrg reportXCharStruct("max_bounds", &(fs->max_bounds)); 985fa3f02f3Smrg /* TODO: report fs->properties and fs->per_char */ 986fa3f02f3Smrg } 987fa3f02f3Smrg} 988fa3f02f3Smrg 989fa3f02f3Smrgstatic void 990fa3f02f3SmrgreportVTFontInfo(XtermWidget xw, int fontnum) 991fa3f02f3Smrg{ 992fa3f02f3Smrg if (resource.reportFonts) { 993fa3f02f3Smrg TScreen *screen = TScreenOf(xw); 994fa3f02f3Smrg 995fa3f02f3Smrg if (fontnum) { 996fa3f02f3Smrg printf("Loaded VTFonts(font%d)\n", fontnum); 997fa3f02f3Smrg } else { 998fa3f02f3Smrg printf("Loaded VTFonts(default)\n"); 999fa3f02f3Smrg } 1000fa3f02f3Smrg reportOneVTFont("fNorm", &screen->fnts[fNorm]); 1001fa3f02f3Smrg reportOneVTFont("fBold", &screen->fnts[fBold]); 1002fa3f02f3Smrg#if OPT_WIDE_CHARS 1003fa3f02f3Smrg reportOneVTFont("fWide", &screen->fnts[fWide]); 1004fa3f02f3Smrg reportOneVTFont("fWBold", &screen->fnts[fWBold]); 1005fa3f02f3Smrg#endif 1006fa3f02f3Smrg } 1007fa3f02f3Smrg} 1008fa3f02f3Smrg#endif 1009fa3f02f3Smrg 10109a64e1c5Smrgvoid 10119a64e1c5SmrgxtermUpdateFontGCs(XtermWidget xw, XTermFonts * fnts) 10129a64e1c5Smrg{ 10139a64e1c5Smrg TScreen *screen = TScreenOf(xw); 10149a64e1c5Smrg VTwin *win = WhichVWin(screen); 10159a64e1c5Smrg Pixel new_normal = getXtermForeground(xw, xw->flags, xw->cur_foreground); 10169a64e1c5Smrg Pixel new_revers = getXtermBackground(xw, xw->flags, xw->cur_background); 10179a64e1c5Smrg 10189a64e1c5Smrg setCgsFore(xw, win, gcNorm, new_normal); 10199a64e1c5Smrg setCgsBack(xw, win, gcNorm, new_revers); 10209a64e1c5Smrg setCgsFont(xw, win, gcNorm, &(fnts[fNorm])); 10219a64e1c5Smrg 10229a64e1c5Smrg copyCgs(xw, win, gcBold, gcNorm); 10239a64e1c5Smrg setCgsFont(xw, win, gcBold, &(fnts[fBold])); 10249a64e1c5Smrg 10259a64e1c5Smrg setCgsFore(xw, win, gcNormReverse, new_revers); 10269a64e1c5Smrg setCgsBack(xw, win, gcNormReverse, new_normal); 10279a64e1c5Smrg setCgsFont(xw, win, gcNormReverse, &(fnts[fNorm])); 10289a64e1c5Smrg 10299a64e1c5Smrg copyCgs(xw, win, gcBoldReverse, gcNormReverse); 10309a64e1c5Smrg setCgsFont(xw, win, gcBoldReverse, &(fnts[fBold])); 10319a64e1c5Smrg 10329a64e1c5Smrg if_OPT_WIDE_CHARS(screen, { 10339a64e1c5Smrg if (fnts[fWide].fs != 0 10349a64e1c5Smrg && fnts[fWBold].fs != 0) { 10359a64e1c5Smrg setCgsFore(xw, win, gcWide, new_normal); 10369a64e1c5Smrg setCgsBack(xw, win, gcWide, new_revers); 10379a64e1c5Smrg setCgsFont(xw, win, gcWide, &(fnts[fWide])); 10389a64e1c5Smrg 10399a64e1c5Smrg copyCgs(xw, win, gcWBold, gcWide); 10409a64e1c5Smrg setCgsFont(xw, win, gcWBold, &(fnts[fWBold])); 10419a64e1c5Smrg 10429a64e1c5Smrg setCgsFore(xw, win, gcWideReverse, new_revers); 10439a64e1c5Smrg setCgsBack(xw, win, gcWideReverse, new_normal); 10449a64e1c5Smrg setCgsFont(xw, win, gcWideReverse, &(fnts[fWide])); 10459a64e1c5Smrg 10469a64e1c5Smrg copyCgs(xw, win, gcWBoldReverse, gcWideReverse); 10479a64e1c5Smrg setCgsFont(xw, win, gcWBoldReverse, &(fnts[fWBold])); 10489a64e1c5Smrg } 10499a64e1c5Smrg }); 10509a64e1c5Smrg} 10519a64e1c5Smrg 10529a64e1c5Smrg#if OPT_TRACE 10539a64e1c5Smrgstatic void 10549a64e1c5Smrgshow_font_misses(const char *name, XTermFonts * fp) 10559a64e1c5Smrg{ 10569a64e1c5Smrg if (fp->fs != 0) { 10579a64e1c5Smrg if (FontLacksMetrics(fp)) { 10589a64e1c5Smrg TRACE(("%s font lacks metrics\n", name)); 10599a64e1c5Smrg } else if (FontIsIncomplete(fp)) { 10609a64e1c5Smrg TRACE(("%s font is incomplete\n", name)); 10619a64e1c5Smrg } else { 10629a64e1c5Smrg TRACE(("%s font is complete\n", name)); 10639a64e1c5Smrg } 10649a64e1c5Smrg } else { 10659a64e1c5Smrg TRACE(("%s font is missing\n", name)); 10669a64e1c5Smrg } 10679a64e1c5Smrg} 10689a64e1c5Smrg#endif 10699a64e1c5Smrg 1070d522f475Smrgint 1071d522f475SmrgxtermLoadFont(XtermWidget xw, 1072d522f475Smrg const VTFontNames * fonts, 1073d522f475Smrg Bool doresize, 1074d522f475Smrg int fontnum) 1075d522f475Smrg{ 1076956cc18dSsnj TScreen *screen = TScreenOf(xw); 1077d522f475Smrg VTwin *win = WhichVWin(screen); 1078d522f475Smrg 1079d522f475Smrg VTFontNames myfonts; 1080d522f475Smrg FontNameProperties *fp; 1081d522f475Smrg XTermFonts fnts[fMAX]; 1082d522f475Smrg char *tmpname = NULL; 10830bd37d32Smrg char *normal = NULL; 1084956cc18dSsnj Boolean proportional = False; 1085956cc18dSsnj fontWarningTypes warn[fMAX]; 1086956cc18dSsnj int j; 1087d522f475Smrg 1088d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 1089d522f475Smrg memset(fnts, 0, sizeof(fnts)); 1090d522f475Smrg 1091d522f475Smrg if (fonts != 0) 1092d522f475Smrg myfonts = *fonts; 1093956cc18dSsnj if (!check_fontname(myfonts.f_n)) 1094d522f475Smrg return 0; 1095d522f475Smrg 1096956cc18dSsnj /* 1097956cc18dSsnj * Check the font names against the resource values, to see which were 1098956cc18dSsnj * derived in a previous call. If so, we'll only warn about those if 1099956cc18dSsnj * the warning level is set to "always". 1100956cc18dSsnj */ 1101956cc18dSsnj for (j = 0; j < fMAX; ++j) { 1102956cc18dSsnj warn[j] = fwAlways; 1103956cc18dSsnj } 1104956cc18dSsnj#define CmpResource(field, index) \ 1105956cc18dSsnj if (same_font_name(screen->menu_font_names[fontnum][index], myfonts.field)) \ 1106956cc18dSsnj warn[index] = fwResource 1107956cc18dSsnj 1108956cc18dSsnj CmpResource(f_n, fNorm); 1109956cc18dSsnj if (fontnum == fontMenu_default) { 1110956cc18dSsnj CmpResource(f_b, fBold); 1111956cc18dSsnj#if OPT_WIDE_CHARS 1112956cc18dSsnj CmpResource(f_b, fWide); 1113956cc18dSsnj CmpResource(f_b, fWBold); 1114956cc18dSsnj#endif 1115956cc18dSsnj } 1116956cc18dSsnj 1117d522f475Smrg if (fontnum == fontMenu_fontescape 1118d522f475Smrg && myfonts.f_n != screen->MenuFontName(fontnum)) { 1119d522f475Smrg if ((tmpname = x_strdup(myfonts.f_n)) == 0) 1120d522f475Smrg return 0; 1121d522f475Smrg } 1122d522f475Smrg 1123d522f475Smrg TRACE(("Begin Cgs - xtermLoadFont(%s)\n", myfonts.f_n)); 1124d522f475Smrg releaseWindowGCs(xw, win); 1125d522f475Smrg 1126956cc18dSsnj#define DbgResource(name, field, index) \ 1127956cc18dSsnj TRACE(("xtermLoadFont #%d "name" %s%s\n", \ 1128956cc18dSsnj fontnum, \ 1129956cc18dSsnj (warn[index] == fwResource) ? "*" : " ", \ 1130492d43a5Smrg NonNull(myfonts.field))) 1131956cc18dSsnj DbgResource("normal", f_n, fNorm); 1132956cc18dSsnj DbgResource("bold ", f_b, fBold); 1133d522f475Smrg#if OPT_WIDE_CHARS 1134956cc18dSsnj DbgResource("wide ", f_w, fWide); 1135956cc18dSsnj DbgResource("w/bold", f_wb, fWBold); 1136d522f475Smrg#endif 1137d522f475Smrg 1138e39b573cSmrg /* 1139e39b573cSmrg * If we are opening the default font, and it happens to be missing, force 1140e39b573cSmrg * that to the compiled-in default font, e.g., "fixed". If we cannot open 1141e39b573cSmrg * the font, disable it from the menu. 1142e39b573cSmrg */ 1143e39b573cSmrg if (!xtermOpenFont(xw, 1144e39b573cSmrg myfonts.f_n, 1145e39b573cSmrg &fnts[fNorm], 1146e39b573cSmrg warn[fNorm], 1147e39b573cSmrg (fontnum == fontMenu_default))) { 1148e39b573cSmrg SetItemSensitivity(fontMenuEntries[fontnum].widget, False); 1149d522f475Smrg goto bad; 1150e39b573cSmrg } 1151d522f475Smrg 11520bd37d32Smrg normal = x_strdup(myfonts.f_n); 1153956cc18dSsnj if (!check_fontname(myfonts.f_b)) { 1154956cc18dSsnj warn[fBold] = fwAlways; 11550bd37d32Smrg fp = get_font_name_props(screen->display, fnts[fNorm].fs, &normal); 1156d522f475Smrg if (fp != 0) { 11579a64e1c5Smrg FREE_FNAME(f_b); 1158d522f475Smrg myfonts.f_b = bold_font_name(fp, fp->average_width); 1159956cc18dSsnj if (!xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], fwAlways, False)) { 11609a64e1c5Smrg FREE_FNAME(f_b); 1161d522f475Smrg myfonts.f_b = bold_font_name(fp, -1); 1162956cc18dSsnj xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], fwAlways, False); 1163d522f475Smrg } 1164492d43a5Smrg TRACE(("...derived bold '%s'\n", NonNull(myfonts.f_b))); 1165d522f475Smrg } 1166d522f475Smrg if (fp == 0 || fnts[fBold].fs == 0) { 1167d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 1168d522f475Smrg TRACE(("...cannot load a matching bold font\n")); 11699a64e1c5Smrg } else if (comparable_metrics(fnts[fNorm].fs, fnts[fBold].fs) 11709a64e1c5Smrg && same_font_size(xw, fnts[fNorm].fs, fnts[fBold].fs) 1171d522f475Smrg && got_bold_font(screen->display, fnts[fBold].fs, myfonts.f_b)) { 1172d522f475Smrg TRACE(("...got a matching bold font\n")); 1173d522f475Smrg cache_menu_font_name(screen, fontnum, fBold, myfonts.f_b); 1174d522f475Smrg } else { 1175d522f475Smrg xtermCloseFont(xw, &fnts[fBold]); 1176d522f475Smrg fnts[fBold] = fnts[fNorm]; 1177d522f475Smrg TRACE(("...did not get a matching bold font\n")); 1178d522f475Smrg } 1179956cc18dSsnj } else if (!xtermOpenFont(xw, myfonts.f_b, &fnts[fBold], warn[fBold], False)) { 1180d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 1181956cc18dSsnj warn[fBold] = fwAlways; 1182492d43a5Smrg TRACE(("...cannot load bold font '%s'\n", NonNull(myfonts.f_b))); 1183d522f475Smrg } else { 1184d522f475Smrg cache_menu_font_name(screen, fontnum, fBold, myfonts.f_b); 1185d522f475Smrg } 1186d522f475Smrg 1187d522f475Smrg /* 1188d522f475Smrg * If there is no widefont specified, fake it by doubling AVERAGE_WIDTH 1189d522f475Smrg * of normal fonts XLFD, and asking for it. This plucks out 18x18ja 1190d522f475Smrg * and 12x13ja as the corresponding fonts for 9x18 and 6x13. 1191d522f475Smrg */ 1192d522f475Smrg if_OPT_WIDE_CHARS(screen, { 11930bd37d32Smrg Boolean derived; 11940bd37d32Smrg char *bold = NULL; 1195d522f475Smrg 1196956cc18dSsnj if (check_fontname(myfonts.f_w)) { 1197d522f475Smrg cache_menu_font_name(screen, fontnum, fWide, myfonts.f_w); 1198e39b573cSmrg } else if (screen->utf8_fonts && !is_double_width_font(fnts[fNorm].fs)) { 11999a64e1c5Smrg FREE_FNAME(f_w); 12000bd37d32Smrg fp = get_font_name_props(screen->display, fnts[fNorm].fs, &normal); 1201d522f475Smrg if (fp != 0) { 1202d522f475Smrg myfonts.f_w = wide_font_name(fp); 1203956cc18dSsnj warn[fWide] = fwAlways; 1204d522f475Smrg TRACE(("...derived wide %s\n", NonNull(myfonts.f_w))); 1205d522f475Smrg cache_menu_font_name(screen, fontnum, fWide, myfonts.f_w); 1206d522f475Smrg } 1207d522f475Smrg } 1208d522f475Smrg 1209956cc18dSsnj if (check_fontname(myfonts.f_w)) { 1210956cc18dSsnj (void) xtermOpenFont(xw, myfonts.f_w, &fnts[fWide], warn[fWide], False); 1211d522f475Smrg } else { 1212d522f475Smrg xtermCopyFontInfo(&fnts[fWide], &fnts[fNorm]); 1213956cc18dSsnj warn[fWide] = fwAlways; 1214d522f475Smrg } 1215d522f475Smrg 1216d522f475Smrg derived = False; 1217956cc18dSsnj if (!check_fontname(myfonts.f_wb)) { 12180bd37d32Smrg fp = get_font_name_props(screen->display, fnts[fBold].fs, &bold); 1219d522f475Smrg if (fp != 0) { 1220d522f475Smrg myfonts.f_wb = widebold_font_name(fp); 1221956cc18dSsnj warn[fWBold] = fwAlways; 1222d522f475Smrg derived = True; 1223d522f475Smrg } 1224d522f475Smrg } 1225d522f475Smrg 1226956cc18dSsnj if (check_fontname(myfonts.f_wb)) { 1227d522f475Smrg 1228e39b573cSmrg xtermOpenFont(xw, 1229e39b573cSmrg myfonts.f_wb, 1230e39b573cSmrg &fnts[fWBold], 1231e39b573cSmrg (screen->utf8_fonts 1232e39b573cSmrg ? warn[fWBold] 12330bd37d32Smrg : (fontWarningTypes) (xw->misc.fontWarnings + 1)), 1234e39b573cSmrg False); 1235d522f475Smrg 1236d522f475Smrg if (derived 1237d522f475Smrg && !compatibleWideCounts(fnts[fWide].fs, fnts[fWBold].fs)) { 1238d522f475Smrg xtermCloseFont(xw, &fnts[fWBold]); 1239d522f475Smrg } 1240d522f475Smrg if (fnts[fWBold].fs == 0) { 12419a64e1c5Smrg FREE_FNAME(f_wb); 1242e39b573cSmrg if (IsEmpty(myfonts.f_w)) { 12439a64e1c5Smrg myfonts.f_wb = x_strdup(myfonts.f_b); 1244e39b573cSmrg warn[fWBold] = fwAlways; 1245e39b573cSmrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fBold]); 1246e39b573cSmrg TRACE(("...cannot load wide-bold, use bold %s\n", 1247e39b573cSmrg NonNull(myfonts.f_b))); 1248e39b573cSmrg } else { 12499a64e1c5Smrg myfonts.f_wb = x_strdup(myfonts.f_w); 1250e39b573cSmrg warn[fWBold] = fwAlways; 1251e39b573cSmrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1252e39b573cSmrg TRACE(("...cannot load wide-bold, use wide %s\n", 1253e39b573cSmrg NonNull(myfonts.f_w))); 1254e39b573cSmrg } 1255d522f475Smrg } else { 1256d522f475Smrg TRACE(("...%s wide/bold %s\n", 1257d522f475Smrg derived ? "derived" : "given", 1258d522f475Smrg NonNull(myfonts.f_wb))); 1259d522f475Smrg cache_menu_font_name(screen, fontnum, fWBold, myfonts.f_wb); 1260d522f475Smrg } 1261d522f475Smrg } else if (is_double_width_font(fnts[fBold].fs)) { 1262d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fBold]); 1263956cc18dSsnj warn[fWBold] = fwAlways; 1264d522f475Smrg TRACE(("...bold font is double-width, use it %s\n", NonNull(myfonts.f_b))); 1265d522f475Smrg } else { 1266d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1267956cc18dSsnj warn[fWBold] = fwAlways; 1268d522f475Smrg TRACE(("...cannot load wide bold font, use wide %s\n", NonNull(myfonts.f_w))); 1269d522f475Smrg } 1270d522f475Smrg 12710bd37d32Smrg free(bold); 12720bd37d32Smrg 1273d522f475Smrg if (EmptyFont(fnts[fWBold].fs)) 1274d522f475Smrg goto bad; /* can't use a 0-sized font */ 1275d522f475Smrg }); 1276d522f475Smrg 1277d522f475Smrg /* 1278d522f475Smrg * Most of the time this call to load the font will succeed, even if 1279d522f475Smrg * there is no wide font : the X server doubles the width of the 1280d522f475Smrg * normal font, or similar. 1281d522f475Smrg * 1282d522f475Smrg * But if it did fail for some reason, then nevermind. 1283d522f475Smrg */ 1284d522f475Smrg if (EmptyFont(fnts[fBold].fs)) 1285d522f475Smrg goto bad; /* can't use a 0-sized font */ 1286d522f475Smrg 1287d522f475Smrg if (!same_font_size(xw, fnts[fNorm].fs, fnts[fBold].fs) 1288d522f475Smrg && (is_fixed_font(fnts[fNorm].fs) && is_fixed_font(fnts[fBold].fs))) { 1289d522f475Smrg TRACE(("...ignoring mismatched normal/bold fonts\n")); 1290d522f475Smrg xtermCloseFont(xw, &fnts[fBold]); 1291d522f475Smrg xtermCopyFontInfo(&fnts[fBold], &fnts[fNorm]); 1292d522f475Smrg } 1293d522f475Smrg 1294d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1295d522f475Smrg if (fnts[fWide].fs != 0 1296d522f475Smrg && fnts[fWBold].fs != 0 12979a64e1c5Smrg && (!comparable_metrics(fnts[fWide].fs, fnts[fWBold].fs) 12989a64e1c5Smrg || (!same_font_size(xw, fnts[fWide].fs, fnts[fWBold].fs) 12999a64e1c5Smrg && is_fixed_font(fnts[fWide].fs) 13009a64e1c5Smrg && is_fixed_font(fnts[fWBold].fs)))) { 1301d522f475Smrg TRACE(("...ignoring mismatched normal/bold wide fonts\n")); 1302d522f475Smrg xtermCloseFont(xw, &fnts[fWBold]); 1303d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1304d522f475Smrg } 1305d522f475Smrg }); 1306d522f475Smrg 1307d522f475Smrg /* 1308d522f475Smrg * Normal/bold fonts should be the same width. Also, the min/max 1309d522f475Smrg * values should be the same. 1310d522f475Smrg */ 1311d522f475Smrg if (!is_fixed_font(fnts[fNorm].fs) 1312d522f475Smrg || !is_fixed_font(fnts[fBold].fs) 1313d522f475Smrg || fnts[fNorm].fs->max_bounds.width != fnts[fBold].fs->max_bounds.width) { 1314d522f475Smrg TRACE(("Proportional font! normal %d/%d, bold %d/%d\n", 1315d522f475Smrg fnts[fNorm].fs->min_bounds.width, 1316d522f475Smrg fnts[fNorm].fs->max_bounds.width, 1317d522f475Smrg fnts[fBold].fs->min_bounds.width, 1318d522f475Smrg fnts[fBold].fs->max_bounds.width)); 1319d522f475Smrg proportional = True; 1320d522f475Smrg } 1321d522f475Smrg 1322d522f475Smrg if_OPT_WIDE_CHARS(screen, { 1323d522f475Smrg if (fnts[fWide].fs != 0 1324d522f475Smrg && fnts[fWBold].fs != 0 1325d522f475Smrg && (!is_fixed_font(fnts[fWide].fs) 1326d522f475Smrg || !is_fixed_font(fnts[fWBold].fs) 1327d522f475Smrg || fnts[fWide].fs->max_bounds.width != fnts[fWBold].fs->max_bounds.width)) { 1328d522f475Smrg TRACE(("Proportional font! wide %d/%d, wide bold %d/%d\n", 1329d522f475Smrg fnts[fWide].fs->min_bounds.width, 1330d522f475Smrg fnts[fWide].fs->max_bounds.width, 1331d522f475Smrg fnts[fWBold].fs->min_bounds.width, 1332d522f475Smrg fnts[fWBold].fs->max_bounds.width)); 1333d522f475Smrg proportional = True; 1334d522f475Smrg } 1335d522f475Smrg }); 1336d522f475Smrg 1337d522f475Smrg /* TODO : enforce that the width of the wide font is 2* the width 1338d522f475Smrg of the narrow font */ 1339d522f475Smrg 1340d522f475Smrg /* 1341d522f475Smrg * If we're switching fonts, free the old ones. Otherwise we'll leak 1342d522f475Smrg * the memory that is associated with the old fonts. The 1343d522f475Smrg * XLoadQueryFont call allocates a new XFontStruct. 1344d522f475Smrg */ 1345d522f475Smrg xtermCloseFonts(xw, screen->fnts); 13469a64e1c5Smrg#if OPT_WIDE_ATTRS 13479a64e1c5Smrg xtermCloseFonts(xw, screen->ifnts); 13489a64e1c5Smrg screen->ifnts_ok = False; 13499a64e1c5Smrg#endif 1350d522f475Smrg 1351d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fNorm]), &fnts[fNorm]); 1352d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fBold]), &fnts[fBold]); 1353d522f475Smrg#if OPT_WIDE_CHARS 1354d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fWide]), &fnts[fWide]); 1355d522f475Smrg if (fnts[fWBold].fs == NULL) 1356d522f475Smrg xtermCopyFontInfo(&fnts[fWBold], &fnts[fWide]); 1357d522f475Smrg xtermCopyFontInfo(&(screen->fnts[fWBold]), &fnts[fWBold]); 1358d522f475Smrg#endif 1359d522f475Smrg 13609a64e1c5Smrg xtermUpdateFontGCs(xw, screen->fnts); 1361d522f475Smrg 136220d2c4d2Smrg#if OPT_BOX_CHARS 136320d2c4d2Smrg screen->allow_packing = proportional; 136420d2c4d2Smrg setupPackedFonts(xw); 136520d2c4d2Smrg#endif 136620d2c4d2Smrg screen->fnt_prop = (Boolean) (proportional && !(screen->force_packed)); 1367d522f475Smrg screen->fnt_boxes = True; 1368d522f475Smrg 1369d522f475Smrg#if OPT_BOX_CHARS 1370d522f475Smrg /* 13719a64e1c5Smrg * xterm uses character positions 1-31 of a font for the line-drawing 1372d522f475Smrg * characters. Check that they are all present. The null character 1373d522f475Smrg * (0) is special, and is not used. 1374d522f475Smrg */ 1375d522f475Smrg#if OPT_RENDERFONT 1376d522f475Smrg if (UsingRenderFont(xw)) { 1377d522f475Smrg /* 1378d522f475Smrg * FIXME: we shouldn't even be here if we're using Xft. 1379d522f475Smrg */ 1380d522f475Smrg screen->fnt_boxes = False; 1381d522f475Smrg TRACE(("assume Xft missing line-drawing chars\n")); 1382d522f475Smrg } else 1383d522f475Smrg#endif 1384d522f475Smrg { 1385d522f475Smrg unsigned ch; 1386d522f475Smrg 13879a64e1c5Smrg#if OPT_TRACE 13889a64e1c5Smrg#define TRACE_MISS(index) show_font_misses(#index, &fnts[index]) 13899a64e1c5Smrg TRACE_MISS(fNorm); 13909a64e1c5Smrg TRACE_MISS(fBold); 13919a64e1c5Smrg#if OPT_WIDE_CHARS 13929a64e1c5Smrg TRACE_MISS(fWide); 13939a64e1c5Smrg TRACE_MISS(fWBold); 13949a64e1c5Smrg#endif 13959a64e1c5Smrg#endif 1396fa3f02f3Smrg 1397d522f475Smrg for (ch = 1; ch < 32; ch++) { 1398d522f475Smrg unsigned n = ch; 1399d522f475Smrg#if OPT_WIDE_CHARS 1400d522f475Smrg if (screen->utf8_mode || screen->unicode_font) { 1401d522f475Smrg n = dec2ucs(ch); 1402d522f475Smrg if (n == UCS_REPL) 1403d522f475Smrg continue; 1404d522f475Smrg } 1405d522f475Smrg#endif 1406956cc18dSsnj if (IsXtermMissingChar(screen, n, &fnts[fNorm])) { 1407d522f475Smrg TRACE(("missing normal char #%d\n", n)); 1408d522f475Smrg screen->fnt_boxes = False; 1409d522f475Smrg break; 1410d522f475Smrg } 1411956cc18dSsnj if (IsXtermMissingChar(screen, n, &fnts[fBold])) { 1412d522f475Smrg TRACE(("missing bold char #%d\n", n)); 1413d522f475Smrg screen->fnt_boxes = False; 1414d522f475Smrg break; 1415d522f475Smrg } 1416d522f475Smrg } 1417d522f475Smrg } 1418d522f475Smrg TRACE(("Will %suse internal line-drawing characters\n", 1419d522f475Smrg screen->fnt_boxes ? "not " : "")); 1420d522f475Smrg#endif 1421d522f475Smrg 1422d522f475Smrg if (screen->always_bold_mode) { 1423d522f475Smrg screen->enbolden = screen->bold_mode; 1424d522f475Smrg } else { 1425d522f475Smrg screen->enbolden = screen->bold_mode 1426d522f475Smrg && ((fnts[fNorm].fs == fnts[fBold].fs) 1427d522f475Smrg || same_font_name(normal, myfonts.f_b)); 1428d522f475Smrg } 1429d522f475Smrg TRACE(("Will %suse 1-pixel offset/overstrike to simulate bold\n", 1430d522f475Smrg screen->enbolden ? "" : "not ")); 1431d522f475Smrg 1432d522f475Smrg set_menu_font(False); 1433d522f475Smrg screen->menu_font_number = fontnum; 1434d522f475Smrg set_menu_font(True); 1435d522f475Smrg if (tmpname) { /* if setting escape or sel */ 1436d522f475Smrg if (screen->MenuFontName(fontnum)) 14379a64e1c5Smrg FREE_STRING(screen->MenuFontName(fontnum)); 1438d522f475Smrg screen->MenuFontName(fontnum) = tmpname; 1439d522f475Smrg if (fontnum == fontMenu_fontescape) { 1440d522f475Smrg SetItemSensitivity(fontMenuEntries[fontMenu_fontescape].widget, 1441d522f475Smrg True); 1442d522f475Smrg } 1443d522f475Smrg#if OPT_SHIFT_FONTS 1444d522f475Smrg screen->menu_font_sizes[fontnum] = FontSize(fnts[fNorm].fs); 1445d522f475Smrg#endif 1446d522f475Smrg } 14470bd37d32Smrg if (normal) 14480bd37d32Smrg free(normal); 1449d522f475Smrg set_cursor_gcs(xw); 1450d522f475Smrg xtermUpdateFontInfo(xw, doresize); 1451d522f475Smrg TRACE(("Success Cgs - xtermLoadFont\n")); 1452fa3f02f3Smrg#if OPT_REPORT_FONTS 1453fa3f02f3Smrg reportVTFontInfo(xw, fontnum); 14549a64e1c5Smrg#endif 14559a64e1c5Smrg FREE_FNAME(f_n); 14569a64e1c5Smrg FREE_FNAME(f_b); 14579a64e1c5Smrg#if OPT_WIDE_CHARS 14589a64e1c5Smrg FREE_FNAME(f_w); 14599a64e1c5Smrg FREE_FNAME(f_wb); 14609a64e1c5Smrg#endif 14619a64e1c5Smrg if (fnts[fNorm].fn == fnts[fBold].fn) { 14629a64e1c5Smrg free(fnts[fNorm].fn); 14639a64e1c5Smrg } else { 14649a64e1c5Smrg free(fnts[fNorm].fn); 14659a64e1c5Smrg free(fnts[fBold].fn); 14669a64e1c5Smrg } 14679a64e1c5Smrg#if OPT_WIDE_CHARS 14689a64e1c5Smrg free(fnts[fWide].fn); 14699a64e1c5Smrg free(fnts[fWBold].fn); 1470fa3f02f3Smrg#endif 1471d522f475Smrg return 1; 1472d522f475Smrg 1473d522f475Smrg bad: 14740bd37d32Smrg if (normal) 14750bd37d32Smrg free(normal); 1476d522f475Smrg if (tmpname) 1477d522f475Smrg free(tmpname); 14780bd37d32Smrg 14790bd37d32Smrg#if OPT_RENDERFONT 14809a64e1c5Smrg if (fontnum == fontMenu_fontsel) { 14819a64e1c5Smrg int old_fontnum = screen->menu_font_number; 14829a64e1c5Smrg#if OPT_TOOLBAR 14839a64e1c5Smrg SetItemSensitivity(fontMenuEntries[fontnum].widget, True); 14849a64e1c5Smrg#endif 14859a64e1c5Smrg Bell(xw, XkbBI_MinorError, 0); 14869a64e1c5Smrg myfonts.f_n = screen->MenuFontName(old_fontnum); 14879a64e1c5Smrg return xtermLoadFont(xw, &myfonts, doresize, old_fontnum); 14889a64e1c5Smrg } else if (x_strcasecmp(myfonts.f_n, DEFFONT)) { 14890bd37d32Smrg int code; 14900bd37d32Smrg 14910bd37d32Smrg myfonts.f_n = DEFFONT; 14920bd37d32Smrg TRACE(("...recovering for TrueType fonts\n")); 14930bd37d32Smrg code = xtermLoadFont(xw, &myfonts, doresize, fontnum); 14940bd37d32Smrg if (code) { 14950bd37d32Smrg SetItemSensitivity(fontMenuEntries[fontnum].widget, 14960bd37d32Smrg UsingRenderFont(xw)); 14970bd37d32Smrg TRACE(("...recovered size %dx%d\n", 14980bd37d32Smrg FontHeight(screen), 14990bd37d32Smrg FontWidth(screen))); 15000bd37d32Smrg } 15010bd37d32Smrg return code; 15020bd37d32Smrg } 15030bd37d32Smrg#endif 15040bd37d32Smrg 1505d522f475Smrg releaseWindowGCs(xw, win); 1506d522f475Smrg 1507d522f475Smrg xtermCloseFonts(xw, fnts); 1508d522f475Smrg TRACE(("Fail Cgs - xtermLoadFont\n")); 1509d522f475Smrg return 0; 1510d522f475Smrg} 1511d522f475Smrg 15129a64e1c5Smrg#if OPT_WIDE_ATTRS 15139a64e1c5Smrg/* 15149a64e1c5Smrg * (Attempt to) load matching italics for the current normal/bold/etc fonts. 15159a64e1c5Smrg * If the attempt fails for a given style, use the non-italic font. 15169a64e1c5Smrg */ 15179a64e1c5Smrgvoid 15189a64e1c5SmrgxtermLoadItalics(XtermWidget xw) 15199a64e1c5Smrg{ 15209a64e1c5Smrg TScreen *screen = TScreenOf(xw); 15219a64e1c5Smrg FontNameProperties *fp; 15229a64e1c5Smrg char *name; 15239a64e1c5Smrg int n; 15249a64e1c5Smrg 15259a64e1c5Smrg if (!screen->ifnts_ok) { 15269a64e1c5Smrg screen->ifnts_ok = True; 15279a64e1c5Smrg for (n = 0; n < fMAX; ++n) { 15289a64e1c5Smrg /* 15299a64e1c5Smrg * FIXME - need to handle font-leaks 15309a64e1c5Smrg */ 15319a64e1c5Smrg screen->ifnts[n].fs = 0; 15329a64e1c5Smrg if (screen->fnts[n].fs != 0 && 15339a64e1c5Smrg (fp = get_font_name_props(screen->display, 15349a64e1c5Smrg screen->fnts[n].fs, 15359a64e1c5Smrg 0)) != 0) { 15369a64e1c5Smrg if ((name = italic_font_name(fp, fp->average_width)) != 0) { 15379a64e1c5Smrg TRACE(("xtermLoadItalics #%d %s\n", n, name)); 15389a64e1c5Smrg (void) xtermOpenFont(xw, 15399a64e1c5Smrg name, 15409a64e1c5Smrg &(screen->ifnts[n]), 15419a64e1c5Smrg fwResource, 15429a64e1c5Smrg False); 15439a64e1c5Smrg#if OPT_TRACE 15449a64e1c5Smrg { 15459a64e1c5Smrg XFontStruct *fs = 15469a64e1c5Smrg screen->ifnts[n].fs; 15479a64e1c5Smrg if (fs != 0) { 15489a64e1c5Smrg TRACE(("...actual size %dx%d (ascent %d, descent %d)\n", 15499a64e1c5Smrg fs->ascent + 15509a64e1c5Smrg fs->descent, 15519a64e1c5Smrg fs->max_bounds.width, 15529a64e1c5Smrg fs->ascent, 15539a64e1c5Smrg fs->descent)); 15549a64e1c5Smrg } 15559a64e1c5Smrg } 15569a64e1c5Smrg#endif 15579a64e1c5Smrg free(name); 15589a64e1c5Smrg } 15599a64e1c5Smrg } 15609a64e1c5Smrg } 15619a64e1c5Smrg } 15629a64e1c5Smrg} 15639a64e1c5Smrg#endif 15649a64e1c5Smrg 1565d522f475Smrg#if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS 1566d522f475Smrg/* 1567d522f475Smrg * Collect font-names that we can modify with the load-vt-fonts() action. 1568d522f475Smrg */ 1569d522f475Smrg#define MERGE_SUBFONT(src,dst,name) \ 1570492d43a5Smrg if (IsEmpty(dst.name)) { \ 1571d522f475Smrg TRACE(("MERGE_SUBFONT " #dst "." #name " merge %s\n", NonNull(src.name))); \ 15729a64e1c5Smrg dst.name = x_strdup(src.name); \ 1573d522f475Smrg } else { \ 1574d522f475Smrg TRACE(("MERGE_SUBFONT " #dst "." #name " found %s\n", NonNull(dst.name))); \ 1575d522f475Smrg } 1576d522f475Smrg 1577e39b573cSmrg#define INFER_SUBFONT(src,dst,name) \ 1578e39b573cSmrg if (IsEmpty(dst.name)) { \ 1579e39b573cSmrg TRACE(("INFER_SUBFONT " #dst "." #name " will infer\n")); \ 1580e39b573cSmrg dst.name = x_strdup(""); \ 1581e39b573cSmrg } else { \ 1582e39b573cSmrg TRACE(("INFER_SUBFONT " #dst "." #name " found %s\n", NonNull(dst.name))); \ 1583e39b573cSmrg } 1584e39b573cSmrg 15859a64e1c5Smrg#define FREE_MENU_FONTS(dst) \ 15869a64e1c5Smrg TRACE(("FREE_MENU_FONTS " #dst "\n")); \ 15879a64e1c5Smrg for (n = fontMenu_default; n <= fontMenu_lastBuiltin; ++n) { \ 15889a64e1c5Smrg for (m = 0; m < fMAX; ++m) { \ 15899a64e1c5Smrg FREE_STRING(dst.menu_font_names[n][m]); \ 15909a64e1c5Smrg dst.menu_font_names[n][m] = 0; \ 15919a64e1c5Smrg } \ 15929a64e1c5Smrg } 15939a64e1c5Smrg 1594d522f475Smrg#define COPY_MENU_FONTS(src,dst) \ 1595d522f475Smrg TRACE(("COPY_MENU_FONTS " #src " to " #dst "\n")); \ 1596d522f475Smrg for (n = fontMenu_default; n <= fontMenu_lastBuiltin; ++n) { \ 1597d522f475Smrg for (m = 0; m < fMAX; ++m) { \ 15989a64e1c5Smrg FREE_STRING(dst.menu_font_names[n][m]); \ 1599492d43a5Smrg dst.menu_font_names[n][m] = x_strdup(src.menu_font_names[n][m]); \ 1600d522f475Smrg } \ 1601e39b573cSmrg TRACE((".. " #dst ".menu_fonts_names[%d] = %s\n", n, dst.menu_font_names[n][fNorm])); \ 1602e39b573cSmrg } 1603e39b573cSmrg 16049a64e1c5Smrg#define COPY_DEFAULT_FONTS(target, source) \ 16059a64e1c5Smrg xtermCopyVTFontNames(&target.default_font, &source.default_font) 16069a64e1c5Smrg 16079a64e1c5Smrgstatic void 16089a64e1c5SmrgxtermCopyVTFontNames(VTFontNames * target, VTFontNames * source) 16099a64e1c5Smrg{ 16109a64e1c5Smrg target->f_n = x_strdup(source->f_n); 16119a64e1c5Smrg target->f_b = x_strdup(source->f_b); 16129a64e1c5Smrg#if OPT_WIDE_CHARS 16139a64e1c5Smrg target->f_w = x_strdup(source->f_w); 16149a64e1c5Smrg target->f_wb = x_strdup(source->f_wb); 16159a64e1c5Smrg#endif 16169a64e1c5Smrg} 16179a64e1c5Smrg 1618e39b573cSmrgvoid 1619e39b573cSmrgxtermSaveVTFonts(XtermWidget xw) 1620e39b573cSmrg{ 1621e39b573cSmrg TScreen *screen = TScreenOf(xw); 1622e39b573cSmrg Cardinal n, m; 1623e39b573cSmrg 1624e39b573cSmrg if (!screen->savedVTFonts) { 1625e39b573cSmrg 1626e39b573cSmrg screen->savedVTFonts = True; 1627e39b573cSmrg TRACE(("xtermSaveVTFonts saving original\n")); 16289a64e1c5Smrg COPY_DEFAULT_FONTS(screen->cacheVTFonts, xw->misc); 1629e39b573cSmrg COPY_MENU_FONTS(xw->screen, screen->cacheVTFonts); 1630e39b573cSmrg } 1631e39b573cSmrg} 1632e39b573cSmrg 1633e39b573cSmrg#define SAME_STRING(x,y) ((x) == (y) || ((x) && (y) && !strcmp(x, y))) 1634e39b573cSmrg#define SAME_MEMBER(n) SAME_STRING(a->n, b->n) 1635e39b573cSmrg 1636e39b573cSmrgstatic Boolean 1637e39b573cSmrgsameSubResources(SubResourceRec * a, SubResourceRec * b) 1638e39b573cSmrg{ 1639e39b573cSmrg Boolean result = True; 1640e39b573cSmrg int n; 1641e39b573cSmrg 1642e39b573cSmrg if (!SAME_MEMBER(default_font.f_n) 1643e39b573cSmrg || !SAME_MEMBER(default_font.f_b) 16440bd37d32Smrg#if OPT_WIDE_CHARS 1645e39b573cSmrg || !SAME_MEMBER(default_font.f_w) 16460bd37d32Smrg || !SAME_MEMBER(default_font.f_wb) 16470bd37d32Smrg#endif 16480bd37d32Smrg ) { 1649e39b573cSmrg TRACE(("sameSubResources: default_font differs\n")); 1650e39b573cSmrg result = False; 1651e39b573cSmrg } else { 1652e39b573cSmrg for (n = 0; n < NMENUFONTS; ++n) { 1653e39b573cSmrg if (!SAME_MEMBER(menu_font_names[n][fNorm])) { 1654e39b573cSmrg TRACE(("sameSubResources: menu_font_names[%d] differs\n", n)); 1655e39b573cSmrg result = False; 1656e39b573cSmrg break; 1657e39b573cSmrg } 1658d522f475Smrg } 1659e39b573cSmrg } 1660e39b573cSmrg 1661e39b573cSmrg return result; 1662e39b573cSmrg} 1663d522f475Smrg 1664d522f475Smrg/* 1665d522f475Smrg * Load the "VT" font names from the given subresource name/class. These 1666d522f475Smrg * correspond to the VT100 resources. 1667d522f475Smrg */ 1668d522f475Smrgstatic Bool 166920d2c4d2SmrgxtermLoadVTFonts(XtermWidget xw, String myName, String myClass) 1670d522f475Smrg{ 1671e39b573cSmrg SubResourceRec subresourceRec; 1672e39b573cSmrg SubResourceRec referenceRec; 1673d522f475Smrg 1674d522f475Smrg /* 1675d522f475Smrg * These are duplicates of the VT100 font resources, but with a special 1676d522f475Smrg * application/classname passed in to distinguish them. 1677d522f475Smrg */ 1678d522f475Smrg static XtResource font_resources[] = 1679d522f475Smrg { 1680d522f475Smrg Sres(XtNfont, XtCFont, default_font.f_n, DEFFONT), 1681d522f475Smrg Sres(XtNboldFont, XtCBoldFont, default_font.f_b, DEFBOLDFONT), 1682d522f475Smrg#if OPT_WIDE_CHARS 1683d522f475Smrg Sres(XtNwideFont, XtCWideFont, default_font.f_w, DEFWIDEFONT), 1684d522f475Smrg Sres(XtNwideBoldFont, XtCWideBoldFont, default_font.f_wb, DEFWIDEBOLDFONT), 1685d522f475Smrg#endif 1686d522f475Smrg Sres(XtNfont1, XtCFont1, MenuFontName(fontMenu_font1), NULL), 1687d522f475Smrg Sres(XtNfont2, XtCFont2, MenuFontName(fontMenu_font2), NULL), 1688d522f475Smrg Sres(XtNfont3, XtCFont3, MenuFontName(fontMenu_font3), NULL), 1689d522f475Smrg Sres(XtNfont4, XtCFont4, MenuFontName(fontMenu_font4), NULL), 1690d522f475Smrg Sres(XtNfont5, XtCFont5, MenuFontName(fontMenu_font5), NULL), 1691d522f475Smrg Sres(XtNfont6, XtCFont6, MenuFontName(fontMenu_font6), NULL), 1692d522f475Smrg }; 1693d522f475Smrg Cardinal n, m; 1694d522f475Smrg Bool status = True; 1695956cc18dSsnj TScreen *screen = TScreenOf(xw); 1696d522f475Smrg 1697e39b573cSmrg TRACE(("called xtermLoadVTFonts(name=%s, class=%s)\n", 1698e39b573cSmrg NonNull(myName), NonNull(myClass))); 1699d522f475Smrg 1700e39b573cSmrg xtermSaveVTFonts(xw); 1701d522f475Smrg 1702492d43a5Smrg if (IsEmpty(myName)) { 1703d522f475Smrg TRACE(("xtermLoadVTFonts restoring original\n")); 17049a64e1c5Smrg COPY_DEFAULT_FONTS(xw->misc, screen->cacheVTFonts); 17059a64e1c5Smrg FREE_MENU_FONTS(xw->screen); 1706e39b573cSmrg COPY_MENU_FONTS(screen->cacheVTFonts, xw->screen); 1707d522f475Smrg } else { 1708d522f475Smrg TRACE(("xtermLoadVTFonts(%s, %s)\n", myName, myClass)); 1709d522f475Smrg 1710e39b573cSmrg memset(&referenceRec, 0, sizeof(referenceRec)); 1711d522f475Smrg memset(&subresourceRec, 0, sizeof(subresourceRec)); 1712956cc18dSsnj XtGetSubresources((Widget) xw, (XtPointer) &subresourceRec, 1713d522f475Smrg myName, myClass, 1714d522f475Smrg font_resources, 1715d522f475Smrg (Cardinal) XtNumber(font_resources), 1716d522f475Smrg NULL, (Cardinal) 0); 1717d522f475Smrg 1718e39b573cSmrg /* 1719e39b573cSmrg * XtGetSubresources returns no status, so we compare the returned 1720e39b573cSmrg * data against a zero'd struct to see if any data is returned. 1721e39b573cSmrg */ 1722e39b573cSmrg if (memcmp(&referenceRec, &subresourceRec, sizeof(referenceRec)) 1723e39b573cSmrg && !sameSubResources(&(screen->cacheVTFonts), &subresourceRec)) { 1724e39b573cSmrg 1725e39b573cSmrg screen->mergedVTFonts = True; 1726d522f475Smrg 17279a64e1c5Smrg /* 17289a64e1c5Smrg * To make it simple, reallocate the strings returned by 17299a64e1c5Smrg * XtGetSubresources. We can free our own strings, but not theirs. 17309a64e1c5Smrg */ 17319a64e1c5Smrg ALLOC_STRING(subresourceRec.default_font.f_n); 17329a64e1c5Smrg ALLOC_STRING(subresourceRec.default_font.f_b); 17339a64e1c5Smrg#if OPT_WIDE_CHARS 17349a64e1c5Smrg ALLOC_STRING(subresourceRec.default_font.f_w); 17359a64e1c5Smrg ALLOC_STRING(subresourceRec.default_font.f_wb); 17369a64e1c5Smrg#endif 17379a64e1c5Smrg for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; ++n) { 17389a64e1c5Smrg ALLOC_STRING(subresourceRec.MenuFontName(n)); 17399a64e1c5Smrg } 17409a64e1c5Smrg 1741d522f475Smrg /* 1742d522f475Smrg * If a particular resource value was not found, use the original. 1743d522f475Smrg */ 1744956cc18dSsnj MERGE_SUBFONT(xw->misc, subresourceRec, default_font.f_n); 1745e39b573cSmrg INFER_SUBFONT(xw->misc, subresourceRec, default_font.f_b); 1746d522f475Smrg#if OPT_WIDE_CHARS 1747e39b573cSmrg INFER_SUBFONT(xw->misc, subresourceRec, default_font.f_w); 1748e39b573cSmrg INFER_SUBFONT(xw->misc, subresourceRec, default_font.f_wb); 1749d522f475Smrg#endif 17509a64e1c5Smrg for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; ++n) { 1751956cc18dSsnj MERGE_SUBFONT(xw->screen, subresourceRec, MenuFontName(n)); 17529a64e1c5Smrg } 1753d522f475Smrg 1754d522f475Smrg /* 1755d522f475Smrg * Finally, copy the subresource data to the widget. 1756d522f475Smrg */ 17579a64e1c5Smrg COPY_DEFAULT_FONTS(xw->misc, subresourceRec); 17589a64e1c5Smrg FREE_MENU_FONTS(xw->screen); 1759956cc18dSsnj COPY_MENU_FONTS(subresourceRec, xw->screen); 17609a64e1c5Smrg 17619a64e1c5Smrg FREE_STRING(screen->MenuFontName(fontMenu_default)); 17629a64e1c5Smrg FREE_STRING(screen->menu_font_names[0][fBold]); 1763492d43a5Smrg screen->MenuFontName(fontMenu_default) = x_strdup(xw->misc.default_font.f_n); 1764492d43a5Smrg screen->menu_font_names[0][fBold] = x_strdup(xw->misc.default_font.f_b); 1765d522f475Smrg#if OPT_WIDE_CHARS 17669a64e1c5Smrg FREE_STRING(screen->menu_font_names[0][fWide]); 17679a64e1c5Smrg FREE_STRING(screen->menu_font_names[0][fWBold]); 1768492d43a5Smrg screen->menu_font_names[0][fWide] = x_strdup(xw->misc.default_font.f_w); 1769492d43a5Smrg screen->menu_font_names[0][fWBold] = x_strdup(xw->misc.default_font.f_wb); 1770d522f475Smrg#endif 17719a64e1c5Smrg /* 17729a64e1c5Smrg * And remove our copies of strings. 17739a64e1c5Smrg */ 17749a64e1c5Smrg FREE_STRING(subresourceRec.default_font.f_n); 17759a64e1c5Smrg FREE_STRING(subresourceRec.default_font.f_b); 17769a64e1c5Smrg#if OPT_WIDE_CHARS 17779a64e1c5Smrg FREE_STRING(subresourceRec.default_font.f_w); 17789a64e1c5Smrg FREE_STRING(subresourceRec.default_font.f_wb); 17799a64e1c5Smrg#endif 17809a64e1c5Smrg for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; ++n) { 17819a64e1c5Smrg FREE_STRING(subresourceRec.MenuFontName(n)); 17829a64e1c5Smrg } 1783d522f475Smrg } else { 1784d522f475Smrg TRACE(("...no resources found\n")); 1785d522f475Smrg status = False; 1786d522f475Smrg } 1787d522f475Smrg } 1788d522f475Smrg return status; 1789d522f475Smrg} 1790d522f475Smrg 1791d522f475Smrg#if OPT_WIDE_CHARS 1792d522f475Smrgstatic Bool 17939a64e1c5SmrgisWideFont(XFontStruct *fp, const char *tag, Bool nullOk) 1794d522f475Smrg{ 1795d522f475Smrg Bool result = False; 1796d522f475Smrg 1797d522f475Smrg (void) tag; 1798d522f475Smrg if (okFont(fp)) { 1799d522f475Smrg unsigned count = countGlyphs(fp); 1800d522f475Smrg TRACE(("isWideFont(%s) found %d cells\n", tag, count)); 1801d522f475Smrg result = (count > 256) ? True : False; 1802d522f475Smrg } else { 1803d522f475Smrg result = nullOk; 1804d522f475Smrg } 1805d522f475Smrg return result; 1806d522f475Smrg} 1807d522f475Smrg 1808d522f475Smrg/* 1809d522f475Smrg * If the current fonts are not wide, load the UTF8 fonts. 1810d522f475Smrg * 1811d522f475Smrg * Called during initialization (for wide-character mode), the fonts have not 1812d522f475Smrg * been setup, so we pass nullOk=True to isWideFont(). 1813d522f475Smrg * 1814d522f475Smrg * Called after initialization, e.g., in response to the UTF-8 menu entry 1815d522f475Smrg * (starting from narrow character mode), it checks if the fonts are not wide. 1816d522f475Smrg */ 1817d522f475SmrgBool 1818d522f475SmrgxtermLoadWideFonts(XtermWidget xw, Bool nullOk) 1819d522f475Smrg{ 1820956cc18dSsnj TScreen *screen = TScreenOf(xw); 1821d522f475Smrg Bool result; 1822d522f475Smrg 1823d522f475Smrg if (EmptyFont(screen->fnts[fWide].fs)) { 1824d522f475Smrg result = (isWideFont(screen->fnts[fNorm].fs, "normal", nullOk) 1825d522f475Smrg && isWideFont(screen->fnts[fBold].fs, "bold", nullOk)); 1826d522f475Smrg } else { 1827d522f475Smrg result = (isWideFont(screen->fnts[fWide].fs, "wide", nullOk) 1828d522f475Smrg && isWideFont(screen->fnts[fWBold].fs, "wide-bold", nullOk)); 1829d522f475Smrg if (result && !screen->utf8_latin1) { 1830d522f475Smrg result = (isWideFont(screen->fnts[fNorm].fs, "normal", nullOk) 1831d522f475Smrg && isWideFont(screen->fnts[fBold].fs, "bold", nullOk)); 1832d522f475Smrg } 1833d522f475Smrg } 1834d522f475Smrg if (!result) { 1835d522f475Smrg TRACE(("current fonts are not all wide%s\n", nullOk ? " nullOk" : "")); 1836e39b573cSmrg result = xtermLoadVTFonts(xw, XtNutf8Fonts, XtCUtf8Fonts); 1837d522f475Smrg } 1838d522f475Smrg TRACE(("xtermLoadWideFonts:%d\n", result)); 1839d522f475Smrg return result; 1840d522f475Smrg} 1841d522f475Smrg#endif /* OPT_WIDE_CHARS */ 1842d522f475Smrg 1843d522f475Smrg/* 1844d522f475Smrg * Restore the default fonts, i.e., if we had switched to wide-fonts. 1845d522f475Smrg */ 1846d522f475SmrgBool 1847956cc18dSsnjxtermLoadDefaultFonts(XtermWidget xw) 1848d522f475Smrg{ 1849d522f475Smrg Bool result; 1850956cc18dSsnj result = xtermLoadVTFonts(xw, NULL, NULL); 1851d522f475Smrg TRACE(("xtermLoadDefaultFonts:%d\n", result)); 1852d522f475Smrg return result; 1853d522f475Smrg} 1854d522f475Smrg#endif /* OPT_LOAD_VTFONTS || OPT_WIDE_CHARS */ 1855d522f475Smrg 1856d522f475Smrg#if OPT_LOAD_VTFONTS 1857d522f475Smrgvoid 1858d522f475SmrgHandleLoadVTFonts(Widget w, 18599a64e1c5Smrg XEvent *event GCC_UNUSED, 1860fa3f02f3Smrg String *params GCC_UNUSED, 1861d522f475Smrg Cardinal *param_count GCC_UNUSED) 1862d522f475Smrg{ 1863d522f475Smrg static char empty[] = ""; /* appease strict compilers */ 1864d522f475Smrg 1865956cc18dSsnj XtermWidget xw; 1866956cc18dSsnj 1867956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 1868956cc18dSsnj TScreen *screen = TScreenOf(xw); 1869492d43a5Smrg char name_buf[80]; 1870492d43a5Smrg char class_buf[80]; 1871492d43a5Smrg String name = (String) ((*param_count > 0) ? params[0] : empty); 18720bd37d32Smrg char *myName = (char *) MyStackAlloc(strlen(name) + 1, name_buf); 1873492d43a5Smrg String convert = (String) ((*param_count > 1) ? params[1] : myName); 18740bd37d32Smrg char *myClass = (char *) MyStackAlloc(strlen(convert) + 1, class_buf); 1875d522f475Smrg int n; 1876d522f475Smrg 1877d522f475Smrg TRACE(("HandleLoadVTFonts(%d)\n", *param_count)); 1878492d43a5Smrg strcpy(myName, name); 1879d522f475Smrg strcpy(myClass, convert); 18802eaa94a1Schristos if (*param_count == 1) 18812eaa94a1Schristos myClass[0] = x_toupper(myClass[0]); 1882d522f475Smrg 1883d522f475Smrg if (xtermLoadVTFonts(xw, myName, myClass)) { 1884d522f475Smrg /* 1885d522f475Smrg * When switching fonts, try to preserve the font-menu selection, since 1886d522f475Smrg * it is less surprising to do that (if the font-switching can be 1887d522f475Smrg * undone) than to switch to "Default". 1888d522f475Smrg */ 1889956cc18dSsnj int font_number = screen->menu_font_number; 1890d522f475Smrg if (font_number > fontMenu_lastBuiltin) 1891d522f475Smrg font_number = fontMenu_lastBuiltin; 18929a64e1c5Smrg for (n = 0; n < NMENUFONTS; ++n) { 1893956cc18dSsnj screen->menu_font_sizes[n] = 0; 18949a64e1c5Smrg } 1895d522f475Smrg SetVTFont(xw, font_number, True, 1896d522f475Smrg ((font_number == fontMenu_default) 1897d522f475Smrg ? &(xw->misc.default_font) 1898d522f475Smrg : NULL)); 1899d522f475Smrg } 1900d522f475Smrg 1901492d43a5Smrg MyStackFree(myName, name_buf); 1902492d43a5Smrg MyStackFree(myClass, class_buf); 1903d522f475Smrg } 1904d522f475Smrg} 1905d522f475Smrg#endif /* OPT_LOAD_VTFONTS */ 1906d522f475Smrg 1907d522f475Smrg/* 1908d522f475Smrg * Set the limits for the box that outlines the cursor. 1909d522f475Smrg */ 1910d522f475Smrgvoid 1911fa3f02f3SmrgxtermSetCursorBox(TScreen *screen) 1912d522f475Smrg{ 1913d522f475Smrg static XPoint VTbox[NBOX]; 1914d522f475Smrg XPoint *vp; 19152eaa94a1Schristos int fw = FontWidth(screen) - 1; 19162eaa94a1Schristos int fh = FontHeight(screen) - 1; 19170bd37d32Smrg int ww = isCursorBar(screen) ? 1 : fw; 19180bd37d32Smrg int hh = isCursorUnderline(screen) ? 1 : fh; 1919d522f475Smrg 1920d522f475Smrg vp = &VTbox[1]; 19210bd37d32Smrg (vp++)->x = (short) ww; 19222eaa94a1Schristos (vp++)->y = (short) hh; 19230bd37d32Smrg (vp++)->x = (short) -ww; 19242eaa94a1Schristos vp->y = (short) -hh; 19252eaa94a1Schristos 1926d522f475Smrg screen->box = VTbox; 1927d522f475Smrg} 1928d522f475Smrg 1929d522f475Smrg#define CACHE_XFT(dst,src) if (src != 0) {\ 1930956cc18dSsnj checkXft(xw, &(dst[fontnum]), src);\ 19310bd37d32Smrg TRACE(("Xft metrics %s[%d] = %d (%d,%d)%s advance %d, actual %d%s\n",\ 1932d522f475Smrg #dst,\ 1933d522f475Smrg fontnum,\ 1934d522f475Smrg src->height,\ 1935d522f475Smrg src->ascent,\ 1936d522f475Smrg src->descent,\ 19370bd37d32Smrg ((src->ascent + src->descent) > src->height ? "*" : ""),\ 1938956cc18dSsnj src->max_advance_width,\ 1939956cc18dSsnj dst[fontnum].map.min_width,\ 1940956cc18dSsnj dst[fontnum].map.mixed ? " mixed" : ""));\ 1941d522f475Smrg } 1942d522f475Smrg 1943d522f475Smrg#if OPT_RENDERFONT 1944956cc18dSsnj 194520d2c4d2Smrgstatic FcChar32 19469a64e1c5SmrgxtermXftFirstChar(XftFont *xft) 194720d2c4d2Smrg{ 194820d2c4d2Smrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 194920d2c4d2Smrg FcChar32 next; 195020d2c4d2Smrg FcChar32 first; 195120d2c4d2Smrg int i; 195220d2c4d2Smrg 195320d2c4d2Smrg first = FcCharSetFirstPage(xft->charset, map, &next); 19549a64e1c5Smrg for (i = 0; i < FC_CHARSET_MAP_SIZE; i++) { 195520d2c4d2Smrg if (map[i]) { 195620d2c4d2Smrg FcChar32 bits = map[i]; 1957fa3f02f3Smrg first += (FcChar32) i *32; 195820d2c4d2Smrg while (!(bits & 0x1)) { 195920d2c4d2Smrg bits >>= 1; 196020d2c4d2Smrg first++; 196120d2c4d2Smrg } 196220d2c4d2Smrg break; 196320d2c4d2Smrg } 19649a64e1c5Smrg } 196520d2c4d2Smrg return first; 196620d2c4d2Smrg} 196720d2c4d2Smrg 196820d2c4d2Smrgstatic FcChar32 19699a64e1c5SmrgxtermXftLastChar(XftFont *xft) 197020d2c4d2Smrg{ 197120d2c4d2Smrg FcChar32 this, last, next; 197220d2c4d2Smrg FcChar32 map[FC_CHARSET_MAP_SIZE]; 197320d2c4d2Smrg int i; 197420d2c4d2Smrg last = FcCharSetFirstPage(xft->charset, map, &next); 197520d2c4d2Smrg while ((this = FcCharSetNextPage(xft->charset, map, &next)) != FC_CHARSET_DONE) 197620d2c4d2Smrg last = this; 1977fa3f02f3Smrg last &= (FcChar32) ~ 0xff; 19789a64e1c5Smrg for (i = FC_CHARSET_MAP_SIZE - 1; i >= 0; i--) { 197920d2c4d2Smrg if (map[i]) { 198020d2c4d2Smrg FcChar32 bits = map[i]; 1981fa3f02f3Smrg last += (FcChar32) i *32 + 31; 198220d2c4d2Smrg while (!(bits & 0x80000000)) { 198320d2c4d2Smrg last--; 198420d2c4d2Smrg bits <<= 1; 198520d2c4d2Smrg } 198620d2c4d2Smrg break; 198720d2c4d2Smrg } 19889a64e1c5Smrg } 198920d2c4d2Smrg return (long) last; 199020d2c4d2Smrg} 199120d2c4d2Smrg 1992fa3f02f3Smrg#if OPT_TRACE > 1 199320d2c4d2Smrgstatic void 19949a64e1c5SmrgdumpXft(XtermWidget xw, XTermXftFonts *data) 199520d2c4d2Smrg{ 199620d2c4d2Smrg XftFont *xft = data->font; 199720d2c4d2Smrg TScreen *screen = TScreenOf(xw); 199820d2c4d2Smrg VTwin *win = WhichVWin(screen); 199920d2c4d2Smrg 200020d2c4d2Smrg FcChar32 c; 200120d2c4d2Smrg FcChar32 first = xtermXftFirstChar(xft); 200220d2c4d2Smrg FcChar32 last = xtermXftLastChar(xft); 200320d2c4d2Smrg unsigned count = 0; 200420d2c4d2Smrg unsigned outside = 0; 200520d2c4d2Smrg 200620d2c4d2Smrg TRACE(("dumpXft {{\n")); 200720d2c4d2Smrg TRACE((" data range %#6x..%#6x\n", first, last)); 200820d2c4d2Smrg for (c = first; c <= last; ++c) { 200920d2c4d2Smrg if (FcCharSetHasChar(xft->charset, c)) { 201020d2c4d2Smrg int width = my_wcwidth((int) c); 201120d2c4d2Smrg XGlyphInfo extents; 201220d2c4d2Smrg 201320d2c4d2Smrg XftTextExtents32(XtDisplay(xw), xft, &c, 1, &extents); 201420d2c4d2Smrg TRACE(("%#6x %2d %.1f\n", c, width, 201520d2c4d2Smrg ((double) extents.width) / win->f_width)); 201620d2c4d2Smrg if (extents.width > win->f_width) 201720d2c4d2Smrg ++outside; 201820d2c4d2Smrg ++count; 201920d2c4d2Smrg } 202020d2c4d2Smrg } 202120d2c4d2Smrg TRACE(("}} %u total, %u outside\n", count, outside)); 202220d2c4d2Smrg} 202320d2c4d2Smrg#define DUMP_XFT(xw, data) dumpXft(xw, data) 202420d2c4d2Smrg#else 202520d2c4d2Smrg#define DUMP_XFT(xw, data) /* nothing */ 202620d2c4d2Smrg#endif 202720d2c4d2Smrg 2028956cc18dSsnjstatic void 20299a64e1c5SmrgcheckXft(XtermWidget xw, XTermXftFonts *data, XftFont *xft) 2030956cc18dSsnj{ 2031956cc18dSsnj FcChar32 c; 2032956cc18dSsnj Dimension width = 0; 2033956cc18dSsnj 2034956cc18dSsnj data->font = xft; 2035956cc18dSsnj data->map.min_width = 0; 2036956cc18dSsnj data->map.max_width = (Dimension) xft->max_advance_width; 2037956cc18dSsnj 203820d2c4d2Smrg /* 203920d2c4d2Smrg * For each ASCII or ISO-8859-1 printable code, ask what its width is. 204020d2c4d2Smrg * Given the maximum width for those, we have a reasonable estimate of 204120d2c4d2Smrg * the single-column width. 204220d2c4d2Smrg * 204320d2c4d2Smrg * Ignore control characters - their extent information is misleading. 204420d2c4d2Smrg */ 2045956cc18dSsnj for (c = 32; c < 256; ++c) { 204620d2c4d2Smrg if (c >= 127 && c <= 159) 204720d2c4d2Smrg continue; 2048956cc18dSsnj if (FcCharSetHasChar(xft->charset, c)) { 2049956cc18dSsnj XGlyphInfo extents; 2050956cc18dSsnj 2051956cc18dSsnj XftTextExtents32(XtDisplay(xw), xft, &c, 1, &extents); 205220d2c4d2Smrg if (width < extents.width && extents.width <= data->map.max_width) { 2053956cc18dSsnj width = extents.width; 205420d2c4d2Smrg } 2055956cc18dSsnj } 2056956cc18dSsnj } 2057956cc18dSsnj data->map.min_width = width; 2058956cc18dSsnj data->map.mixed = (data->map.max_width >= (data->map.min_width + 1)); 2059956cc18dSsnj} 2060956cc18dSsnj 2061fa3f02f3Smrgstatic void 2062fa3f02f3SmrgreportXftFonts(XtermWidget xw, 20639a64e1c5Smrg XftFont *fp, 2064fa3f02f3Smrg const char *name, 2065fa3f02f3Smrg const char *tag, 20669a64e1c5Smrg XftPattern *match) 2067fa3f02f3Smrg{ 2068fa3f02f3Smrg if (resource.reportFonts) { 2069fa3f02f3Smrg char buffer[1024]; 2070fa3f02f3Smrg FcChar32 first_char = xtermXftFirstChar(fp); 2071fa3f02f3Smrg FcChar32 last_char = xtermXftLastChar(fp); 2072fa3f02f3Smrg FcChar32 ch; 2073fa3f02f3Smrg unsigned missing = 0; 2074fa3f02f3Smrg 2075fa3f02f3Smrg printf("Loaded XftFonts(%s:%s)\n", name, tag); 2076fa3f02f3Smrg 2077fa3f02f3Smrg for (ch = first_char; ch <= last_char; ++ch) { 2078fa3f02f3Smrg if (xtermXftMissing(xw, fp, ch)) { 2079fa3f02f3Smrg ++missing; 2080fa3f02f3Smrg } 2081fa3f02f3Smrg } 2082fa3f02f3Smrg printf("\t\tfirst char: %u\n", first_char); 2083fa3f02f3Smrg printf("\t\tlast char: %u\n", last_char); 2084fa3f02f3Smrg printf("\t\tmissing-chars: %u\n", missing); 2085fa3f02f3Smrg printf("\t\tpresent-chars: %u\n", (last_char - first_char) + 1 - missing); 2086fa3f02f3Smrg 2087fa3f02f3Smrg if (XftNameUnparse(match, buffer, (int) sizeof(buffer))) { 2088fa3f02f3Smrg char *target; 2089fa3f02f3Smrg char *source = buffer; 2090fa3f02f3Smrg while ((target = strtok(source, ":")) != 0) { 2091fa3f02f3Smrg printf("\t%s\n", target); 2092fa3f02f3Smrg source = 0; 2093fa3f02f3Smrg } 2094fa3f02f3Smrg } 2095fa3f02f3Smrg } 2096fa3f02f3Smrg} 2097fa3f02f3Smrg 2098d522f475Smrgstatic XftFont * 20999a64e1c5SmrgxtermOpenXft(XtermWidget xw, const char *name, XftPattern *pat, const char *tag) 2100d522f475Smrg{ 2101956cc18dSsnj TScreen *screen = TScreenOf(xw); 2102956cc18dSsnj Display *dpy = screen->display; 2103d522f475Smrg XftPattern *match; 2104d522f475Smrg XftResult status; 2105d522f475Smrg XftFont *result = 0; 2106d522f475Smrg 2107d522f475Smrg if (pat != 0) { 2108d522f475Smrg match = XftFontMatch(dpy, DefaultScreen(dpy), pat, &status); 2109d522f475Smrg if (match != 0) { 2110d522f475Smrg result = XftFontOpenPattern(dpy, match); 2111d522f475Smrg if (result != 0) { 2112d522f475Smrg TRACE(("...matched %s font\n", tag)); 2113fa3f02f3Smrg reportXftFonts(xw, result, name, tag, match); 2114d522f475Smrg } else { 2115d522f475Smrg TRACE(("...could did not open %s font\n", tag)); 2116d522f475Smrg XftPatternDestroy(match); 2117956cc18dSsnj if (xw->misc.fontWarnings >= fwAlways) { 2118956cc18dSsnj TRACE(("OOPS cannot open %s font \"%s\"\n", tag, name)); 21190bd37d32Smrg xtermWarning("cannot open %s font \"%s\"\n", tag, name); 2120956cc18dSsnj } 2121d522f475Smrg } 2122d522f475Smrg } else { 2123d522f475Smrg TRACE(("...did not match %s font\n", tag)); 2124956cc18dSsnj if (xw->misc.fontWarnings >= fwResource) { 2125956cc18dSsnj TRACE(("OOPS: cannot match %s font \"%s\"\n", tag, name)); 21260bd37d32Smrg xtermWarning("cannot match %s font \"%s\"\n", tag, name); 2127956cc18dSsnj } 2128d522f475Smrg } 2129d522f475Smrg } 2130d522f475Smrg return result; 2131d522f475Smrg} 2132d522f475Smrg#endif 2133d522f475Smrg 2134d522f475Smrg#if OPT_RENDERFONT 2135d522f475Smrg#if OPT_SHIFT_FONTS 2136d522f475Smrg/* 2137d522f475Smrg * Don't make a dependency on the math library for a single function. 2138d522f475Smrg * (Newton Raphson). 2139d522f475Smrg */ 2140d522f475Smrgstatic double 21410bd37d32SmrgdimSquareRoot(double value) 2142d522f475Smrg{ 2143d522f475Smrg double result = 0.0; 2144d522f475Smrg if (value > 0.0) { 2145d522f475Smrg int n; 2146d522f475Smrg double older = value; 2147d522f475Smrg for (n = 0; n < 10; ++n) { 2148d522f475Smrg double delta = (older * older - value) / (2.0 * older); 2149d522f475Smrg double newer = older - delta; 2150d522f475Smrg older = newer; 2151d522f475Smrg result = newer; 2152d522f475Smrg if (delta > -0.001 && delta < 0.001) 2153d522f475Smrg break; 2154d522f475Smrg } 2155d522f475Smrg } 2156d522f475Smrg return result; 2157d522f475Smrg} 2158d522f475Smrg#endif 2159d522f475Smrg 2160d522f475Smrg/* 2161d522f475Smrg * Given the Xft font metrics, determine the actual font size. This is used 2162d522f475Smrg * for each font to ensure that normal, bold and italic fonts follow the same 2163d522f475Smrg * rule. 2164d522f475Smrg */ 2165d522f475Smrgstatic void 21669a64e1c5SmrgsetRenderFontsize(TScreen *screen, VTwin *win, XftFont *font, const char *tag) 2167d522f475Smrg{ 2168d522f475Smrg if (font != 0) { 2169d522f475Smrg int width, height, ascent, descent; 2170d522f475Smrg 2171d522f475Smrg (void) screen; 2172d522f475Smrg 2173d522f475Smrg width = font->max_advance_width; 2174d522f475Smrg height = font->height; 2175d522f475Smrg ascent = font->ascent; 2176d522f475Smrg descent = font->descent; 2177d522f475Smrg if (height < ascent + descent) { 2178d522f475Smrg TRACE(("...increase height from %d\n", height)); 2179d522f475Smrg height = ascent + descent; 2180d522f475Smrg } 2181d522f475Smrg if (is_double_width_font_xft(screen->display, font)) { 2182d522f475Smrg TRACE(("...reduced width from %d\n", width)); 2183d522f475Smrg width >>= 1; 2184d522f475Smrg } 2185d522f475Smrg if (tag == 0) { 21860bd37d32Smrg SetFontWidth(screen, win, width); 21870bd37d32Smrg SetFontHeight(screen, win, height); 2188d522f475Smrg win->f_ascent = ascent; 2189d522f475Smrg win->f_descent = descent; 2190d522f475Smrg TRACE(("setRenderFontsize result %dx%d (%d+%d)\n", 2191d522f475Smrg width, height, ascent, descent)); 2192d522f475Smrg } else if (win->f_width < width || 2193d522f475Smrg win->f_height < height || 2194d522f475Smrg win->f_ascent < ascent || 2195d522f475Smrg win->f_descent < descent) { 2196d522f475Smrg TRACE(("setRenderFontsize %s changed %dx%d (%d+%d) to %dx%d (%d+%d)\n", 2197d522f475Smrg tag, 2198d522f475Smrg win->f_width, win->f_height, win->f_ascent, win->f_descent, 2199d522f475Smrg width, height, ascent, descent)); 2200d522f475Smrg 22010bd37d32Smrg SetFontWidth(screen, win, width); 22020bd37d32Smrg SetFontHeight(screen, win, height); 2203d522f475Smrg win->f_ascent = ascent; 2204d522f475Smrg win->f_descent = descent; 2205d522f475Smrg } else { 2206d522f475Smrg TRACE(("setRenderFontsize %s unchanged\n", tag)); 2207d522f475Smrg } 2208d522f475Smrg } 2209d522f475Smrg} 2210d522f475Smrg#endif 2211d522f475Smrg 221220d2c4d2Smrgstatic void 221320d2c4d2SmrgcheckFontInfo(int value, const char *tag) 221420d2c4d2Smrg{ 221520d2c4d2Smrg if (value == 0) { 22160bd37d32Smrg xtermWarning("Selected font has no non-zero %s for ISO-8859-1 encoding\n", tag); 221720d2c4d2Smrg exit(1); 221820d2c4d2Smrg } 221920d2c4d2Smrg} 222020d2c4d2Smrg 222120d2c4d2Smrg#if OPT_RENDERFONT 222220d2c4d2Smrgvoid 22239a64e1c5SmrgxtermCloseXft(TScreen *screen, XTermXftFonts *pub) 222420d2c4d2Smrg{ 222520d2c4d2Smrg if (pub->font != 0) { 222620d2c4d2Smrg XftFontClose(screen->display, pub->font); 222720d2c4d2Smrg pub->font = 0; 222820d2c4d2Smrg } 222920d2c4d2Smrg} 223020d2c4d2Smrg 223120d2c4d2Smrg/* 223220d2c4d2Smrg * Get the faceName/faceDoublesize resource setting. Strip off "xft:", which 22330bd37d32Smrg * is not recognized by XftNameParse(). 223420d2c4d2Smrg */ 2235492d43a5SmrgString 223620d2c4d2SmrggetFaceName(XtermWidget xw, Bool wideName GCC_UNUSED) 223720d2c4d2Smrg{ 223820d2c4d2Smrg#if OPT_RENDERWIDE 2239492d43a5Smrg String result = (wideName 2240492d43a5Smrg ? xw->misc.face_wide_name 2241492d43a5Smrg : xw->misc.face_name); 224220d2c4d2Smrg#else 2243492d43a5Smrg String result = xw->misc.face_name; 224420d2c4d2Smrg#endif 224520d2c4d2Smrg if (!IsEmpty(result) && !strncmp(result, "xft:", (size_t) 4)) 224620d2c4d2Smrg result += 4; 224720d2c4d2Smrg return x_nonempty(result); 224820d2c4d2Smrg} 224920d2c4d2Smrg 225020d2c4d2Smrg/* 225120d2c4d2Smrg * If we change the faceName, we'll have to re-acquire all of the fonts that 225220d2c4d2Smrg * are derived from it. 225320d2c4d2Smrg */ 225420d2c4d2Smrgvoid 225520d2c4d2SmrgsetFaceName(XtermWidget xw, const char *value) 225620d2c4d2Smrg{ 225720d2c4d2Smrg TScreen *screen = TScreenOf(xw); 225820d2c4d2Smrg int n; 22590bd37d32Smrg Boolean changed = (Boolean) ((xw->misc.face_name == 0) 22600bd37d32Smrg || strcmp(xw->misc.face_name, value)); 226120d2c4d2Smrg 22620bd37d32Smrg if (changed) { 22630bd37d32Smrg xw->misc.face_name = x_strdup(value); 22640bd37d32Smrg for (n = 0; n < NMENUFONTS; ++n) { 22650bd37d32Smrg xw->misc.face_size[n] = -1.0; 22660bd37d32Smrg xtermCloseXft(screen, &(screen->renderFontNorm[n])); 22670bd37d32Smrg xtermCloseXft(screen, &(screen->renderFontBold[n])); 22680bd37d32Smrg xtermCloseXft(screen, &(screen->renderFontBold[n])); 226920d2c4d2Smrg#if OPT_RENDERWIDE 22700bd37d32Smrg xtermCloseXft(screen, &(screen->renderWideNorm[n])); 22710bd37d32Smrg xtermCloseXft(screen, &(screen->renderWideBold[n])); 22720bd37d32Smrg xtermCloseXft(screen, &(screen->renderWideItal[n])); 227320d2c4d2Smrg#endif 22740bd37d32Smrg } 227520d2c4d2Smrg } 227620d2c4d2Smrg} 227720d2c4d2Smrg#endif 227820d2c4d2Smrg 2279d522f475Smrg/* 2280d522f475Smrg * Compute useful values for the font/window sizes 2281d522f475Smrg */ 2282d522f475Smrgvoid 2283d522f475SmrgxtermComputeFontInfo(XtermWidget xw, 22849a64e1c5Smrg VTwin *win, 22859a64e1c5Smrg XFontStruct *font, 2286d522f475Smrg int sbwidth) 2287d522f475Smrg{ 2288956cc18dSsnj TScreen *screen = TScreenOf(xw); 2289d522f475Smrg 2290d522f475Smrg int i, j, width, height; 2291492d43a5Smrg#if OPT_RENDERFONT 2292492d43a5Smrg int fontnum = screen->menu_font_number; 2293492d43a5Smrg#endif 2294d522f475Smrg 2295d522f475Smrg#if OPT_RENDERFONT 2296d522f475Smrg /* 2297d522f475Smrg * xterm contains a lot of references to fonts, assuming they are fixed 2298d522f475Smrg * size. This chunk of code overrides the actual font-selection (see 2299d522f475Smrg * drawXtermText()), if the user has selected render-font. All of the 2300d522f475Smrg * font-loading for fixed-fonts still goes on whether or not this chunk 2301d522f475Smrg * overrides it. 2302d522f475Smrg */ 2303492d43a5Smrg if (UsingRenderFont(xw) && fontnum >= 0) { 2304492d43a5Smrg String face_name = getFaceName(xw, False); 2305956cc18dSsnj XftFont *norm = screen->renderFontNorm[fontnum].font; 2306956cc18dSsnj XftFont *bold = screen->renderFontBold[fontnum].font; 2307956cc18dSsnj XftFont *ital = screen->renderFontItal[fontnum].font; 2308d522f475Smrg#if OPT_RENDERWIDE 2309956cc18dSsnj XftFont *wnorm = screen->renderWideNorm[fontnum].font; 2310956cc18dSsnj XftFont *wbold = screen->renderWideBold[fontnum].font; 2311956cc18dSsnj XftFont *wital = screen->renderWideItal[fontnum].font; 2312d522f475Smrg#endif 2313d522f475Smrg 231420d2c4d2Smrg if (norm == 0 && face_name) { 2315d522f475Smrg XftPattern *pat; 23160bd37d32Smrg double face_size; 2317d522f475Smrg 23180bd37d32Smrg TRACE(("xtermComputeFontInfo font %d: norm(face %s, size %.1f)\n", 2319492d43a5Smrg fontnum, face_name, 2320d522f475Smrg xw->misc.face_size[fontnum])); 2321d522f475Smrg 23220bd37d32Smrg fillInFaceSize(xw, fontnum); 23230bd37d32Smrg face_size = xw->misc.face_size[fontnum]; 2324d522f475Smrg 2325d522f475Smrg /* 2326d522f475Smrg * By observation (there is no documentation), XftPatternBuild is 2327d522f475Smrg * cumulative. Build the bold- and italic-patterns on top of the 2328d522f475Smrg * normal pattern. 2329d522f475Smrg */ 2330d522f475Smrg#define NormXftPattern \ 2331d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 2332d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 2333d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 2334d522f475Smrg 2335d522f475Smrg#define BoldXftPattern(norm) \ 2336d522f475Smrg XFT_WEIGHT, XftTypeInteger, XFT_WEIGHT_BOLD, \ 2337d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 2338d522f475Smrg 2339d522f475Smrg#define ItalXftPattern(norm) \ 2340d522f475Smrg XFT_SLANT, XftTypeInteger, XFT_SLANT_ITALIC, \ 2341d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, norm->max_advance_width 2342d522f475Smrg 23439a64e1c5Smrg#if OPT_WIDE_ATTRS 23449a64e1c5Smrg#define HAVE_ITALICS 1 23459a64e1c5Smrg#define FIND_ITALICS ((pat = XftNameParse(face_name)) != 0) 23469a64e1c5Smrg#elif OPT_ISO_COLORS 23479a64e1c5Smrg#define HAVE_ITALICS 1 23489a64e1c5Smrg#define FIND_ITALICS (screen->italicULMode && (pat = XftNameParse(face_name)) != 0) 23499a64e1c5Smrg#else 23509a64e1c5Smrg#define HAVE_ITALICS 0 23519a64e1c5Smrg#endif 23529a64e1c5Smrg 235320d2c4d2Smrg if ((pat = XftNameParse(face_name)) != 0) { 235420d2c4d2Smrg#define OPEN_XFT(tag) xtermOpenXft(xw, face_name, pat, tag) 2355d522f475Smrg XftPatternBuild(pat, 2356d522f475Smrg NormXftPattern, 2357d522f475Smrg (void *) 0); 2358956cc18dSsnj norm = OPEN_XFT("normal"); 2359d522f475Smrg 2360d522f475Smrg if (norm != 0) { 2361d522f475Smrg XftPatternBuild(pat, 2362d522f475Smrg BoldXftPattern(norm), 2363d522f475Smrg (void *) 0); 2364956cc18dSsnj bold = OPEN_XFT("bold"); 2365d522f475Smrg 23669a64e1c5Smrg#if HAVE_ITALICS 23679a64e1c5Smrg if (FIND_ITALICS) { 2368d522f475Smrg XftPatternBuild(pat, 2369d522f475Smrg NormXftPattern, 2370d522f475Smrg ItalXftPattern(norm), 2371d522f475Smrg (void *) 0); 2372956cc18dSsnj ital = OPEN_XFT("italic"); 2373d522f475Smrg } 23749a64e1c5Smrg#endif 2375956cc18dSsnj#undef OPEN_XFT 2376d522f475Smrg 2377d522f475Smrg /* 2378d522f475Smrg * FIXME: just assume that the corresponding font has no 2379d522f475Smrg * graphics characters. 2380d522f475Smrg */ 2381d522f475Smrg if (screen->fnt_boxes) { 2382d522f475Smrg screen->fnt_boxes = False; 2383d522f475Smrg TRACE(("Xft opened - will %suse internal line-drawing characters\n", 2384d522f475Smrg screen->fnt_boxes ? "not " : "")); 2385d522f475Smrg } 2386d522f475Smrg } 2387d522f475Smrg 2388d522f475Smrg XftPatternDestroy(pat); 2389d522f475Smrg } 2390d522f475Smrg 2391d522f475Smrg CACHE_XFT(screen->renderFontNorm, norm); 2392d522f475Smrg CACHE_XFT(screen->renderFontBold, bold); 2393d522f475Smrg CACHE_XFT(screen->renderFontItal, ital); 2394d522f475Smrg 2395d522f475Smrg /* 2396d522f475Smrg * See xtermXftDrawString(). 2397d522f475Smrg */ 2398d522f475Smrg#if OPT_RENDERWIDE 2399d522f475Smrg if (norm != 0 && screen->wide_chars) { 2400d522f475Smrg int char_width = norm->max_advance_width * 2; 2401956cc18dSsnj#ifdef FC_ASPECT 2402956cc18dSsnj double aspect = ((xw->misc.face_wide_name 2403956cc18dSsnj || screen->renderFontNorm[fontnum].map.mixed) 2404956cc18dSsnj ? 1.0 2405956cc18dSsnj : 2.0); 2406956cc18dSsnj#endif 2407d522f475Smrg 240820d2c4d2Smrg face_name = getFaceName(xw, True); 2409d522f475Smrg TRACE(("xtermComputeFontInfo wide(face %s, char_width %d)\n", 241020d2c4d2Smrg NonNull(face_name), 2411d522f475Smrg char_width)); 2412d522f475Smrg 2413d522f475Smrg#define WideXftPattern \ 2414d522f475Smrg XFT_FAMILY, XftTypeString, "mono", \ 2415d522f475Smrg XFT_SIZE, XftTypeDouble, face_size, \ 2416d522f475Smrg XFT_SPACING, XftTypeInteger, XFT_MONO 2417d522f475Smrg 241820d2c4d2Smrg if (face_name && (pat = XftNameParse(face_name)) != 0) { 2419956cc18dSsnj#define OPEN_XFT(tag) xtermOpenXft(xw, face_name, pat, tag) 2420d522f475Smrg XftPatternBuild(pat, 2421d522f475Smrg WideXftPattern, 2422d522f475Smrg XFT_CHAR_WIDTH, XftTypeInteger, char_width, 2423956cc18dSsnj#ifdef FC_ASPECT 2424956cc18dSsnj FC_ASPECT, XftTypeDouble, aspect, 2425956cc18dSsnj#endif 2426d522f475Smrg (void *) 0); 2427956cc18dSsnj wnorm = OPEN_XFT("wide"); 2428d522f475Smrg 2429d522f475Smrg if (wnorm != 0) { 2430d522f475Smrg XftPatternBuild(pat, 2431d522f475Smrg WideXftPattern, 2432d522f475Smrg BoldXftPattern(wnorm), 2433d522f475Smrg (void *) 0); 2434956cc18dSsnj wbold = OPEN_XFT("wide-bold"); 2435d522f475Smrg 24369a64e1c5Smrg#if HAVE_ITALICS 24379a64e1c5Smrg if (FIND_ITALICS) { 2438d522f475Smrg XftPatternBuild(pat, 2439d522f475Smrg WideXftPattern, 2440d522f475Smrg ItalXftPattern(wnorm), 2441d522f475Smrg (void *) 0); 2442956cc18dSsnj wital = OPEN_XFT("wide-italic"); 2443d522f475Smrg } 2444d522f475Smrg#endif 2445956cc18dSsnj#undef OPEN_XFT 2446d522f475Smrg } 2447d522f475Smrg XftPatternDestroy(pat); 2448d522f475Smrg } 2449d522f475Smrg 2450d522f475Smrg CACHE_XFT(screen->renderWideNorm, wnorm); 2451d522f475Smrg CACHE_XFT(screen->renderWideBold, wbold); 2452d522f475Smrg CACHE_XFT(screen->renderWideItal, wital); 2453d522f475Smrg } 2454d522f475Smrg#endif /* OPT_RENDERWIDE */ 2455d522f475Smrg } 2456d522f475Smrg if (norm == 0) { 24572eaa94a1Schristos TRACE(("...no TrueType font found for number %d, disable menu entry\n", fontnum)); 24580bd37d32Smrg xw->work.render_font = False; 2459d522f475Smrg update_font_renderfont(); 2460d522f475Smrg /* now we will fall through into the bitmap fonts */ 2461d522f475Smrg } else { 2462d522f475Smrg setRenderFontsize(screen, win, norm, NULL); 2463d522f475Smrg setRenderFontsize(screen, win, bold, "bold"); 2464d522f475Smrg setRenderFontsize(screen, win, ital, "ital"); 246520d2c4d2Smrg#if OPT_BOX_CHARS 246620d2c4d2Smrg setupPackedFonts(xw); 246720d2c4d2Smrg 246820d2c4d2Smrg if (screen->force_packed) { 246920d2c4d2Smrg XTermXftFonts *use = &(screen->renderFontNorm[fontnum]); 24700bd37d32Smrg SetFontHeight(screen, win, use->font->ascent + use->font->descent); 24710bd37d32Smrg SetFontWidth(screen, win, use->map.min_width); 247220d2c4d2Smrg TRACE(("...packed TrueType font %dx%d vs %d\n", 247320d2c4d2Smrg win->f_height, 247420d2c4d2Smrg win->f_width, 247520d2c4d2Smrg use->map.max_width)); 247620d2c4d2Smrg } 247720d2c4d2Smrg#endif 247820d2c4d2Smrg DUMP_XFT(xw, &(screen->renderFontNorm[fontnum])); 2479d522f475Smrg } 2480d522f475Smrg } 2481d522f475Smrg /* 2482d522f475Smrg * Are we handling a bitmap font? 2483d522f475Smrg */ 2484492d43a5Smrg else 2485d522f475Smrg#endif /* OPT_RENDERFONT */ 2486d522f475Smrg { 248720d2c4d2Smrg if (is_double_width_font(font) && !(screen->fnt_prop)) { 24880bd37d32Smrg SetFontWidth(screen, win, font->min_bounds.width); 2489d522f475Smrg } else { 24900bd37d32Smrg SetFontWidth(screen, win, font->max_bounds.width); 2491d522f475Smrg } 24920bd37d32Smrg SetFontHeight(screen, win, font->ascent + font->descent); 2493d522f475Smrg win->f_ascent = font->ascent; 2494d522f475Smrg win->f_descent = font->descent; 2495d522f475Smrg } 2496d522f475Smrg i = 2 * screen->border + sbwidth; 2497d522f475Smrg j = 2 * screen->border; 2498d522f475Smrg width = MaxCols(screen) * win->f_width + i; 2499d522f475Smrg height = MaxRows(screen) * win->f_height + j; 2500956cc18dSsnj win->fullwidth = (Dimension) width; 2501956cc18dSsnj win->fullheight = (Dimension) height; 2502d522f475Smrg win->width = width - i; 2503d522f475Smrg win->height = height - j; 2504d522f475Smrg 2505d522f475Smrg TRACE(("xtermComputeFontInfo window %dx%d (full %dx%d), fontsize %dx%d (asc %d, dsc %d)\n", 2506d522f475Smrg win->height, 2507d522f475Smrg win->width, 2508d522f475Smrg win->fullheight, 2509d522f475Smrg win->fullwidth, 2510d522f475Smrg win->f_height, 2511d522f475Smrg win->f_width, 2512d522f475Smrg win->f_ascent, 2513d522f475Smrg win->f_descent)); 251420d2c4d2Smrg 251520d2c4d2Smrg checkFontInfo(win->f_height, "height"); 251620d2c4d2Smrg checkFontInfo(win->f_width, "width"); 2517d522f475Smrg} 2518d522f475Smrg 2519d522f475Smrg/* save this information as a side-effect for double-sized characters */ 2520d522f475Smrgvoid 25219a64e1c5SmrgxtermSaveFontInfo(TScreen *screen, XFontStruct *font) 2522d522f475Smrg{ 2523956cc18dSsnj screen->fnt_wide = (Dimension) (font->max_bounds.width); 2524956cc18dSsnj screen->fnt_high = (Dimension) (font->ascent + font->descent); 2525d522f475Smrg TRACE(("xtermSaveFontInfo %dx%d\n", screen->fnt_high, screen->fnt_wide)); 2526d522f475Smrg} 2527d522f475Smrg 2528d522f475Smrg/* 2529d522f475Smrg * After loading a new font, update the structures that use its size. 2530d522f475Smrg */ 2531d522f475Smrgvoid 2532d522f475SmrgxtermUpdateFontInfo(XtermWidget xw, Bool doresize) 2533d522f475Smrg{ 2534956cc18dSsnj TScreen *screen = TScreenOf(xw); 2535d522f475Smrg 2536d522f475Smrg int scrollbar_width; 2537d522f475Smrg VTwin *win = &(screen->fullVwin); 2538d522f475Smrg 2539d522f475Smrg scrollbar_width = (xw->misc.scrollbar 2540d522f475Smrg ? (screen->scrollWidget->core.width + 2541d522f475Smrg BorderWidth(screen->scrollWidget)) 2542d522f475Smrg : 0); 2543d522f475Smrg xtermComputeFontInfo(xw, win, screen->fnts[fNorm].fs, scrollbar_width); 2544d522f475Smrg xtermSaveFontInfo(screen, screen->fnts[fNorm].fs); 2545d522f475Smrg 2546d522f475Smrg if (doresize) { 2547d522f475Smrg if (VWindow(screen)) { 2548d522f475Smrg xtermClear(xw); 2549d522f475Smrg } 2550d522f475Smrg TRACE(("xtermUpdateFontInfo {{\n")); 2551d522f475Smrg DoResizeScreen(xw); /* set to the new natural size */ 2552d522f475Smrg ResizeScrollBar(xw); 2553d522f475Smrg Redraw(); 2554d522f475Smrg TRACE(("... }} xtermUpdateFontInfo\n")); 2555d522f475Smrg#ifdef SCROLLBAR_RIGHT 2556d522f475Smrg updateRightScrollbar(xw); 2557d522f475Smrg#endif 2558d522f475Smrg } 2559d522f475Smrg xtermSetCursorBox(screen); 2560d522f475Smrg} 2561d522f475Smrg 2562fa3f02f3Smrg#if OPT_BOX_CHARS || OPT_REPORT_FONTS 2563d522f475Smrg 2564d522f475Smrg/* 2565d522f475Smrg * Returns true if the given character is missing from the specified font. 2566d522f475Smrg */ 2567d522f475SmrgBool 2568956cc18dSsnjxtermMissingChar(unsigned ch, XTermFonts * font) 2569d522f475Smrg{ 2570956cc18dSsnj Bool result = False; 2571956cc18dSsnj XFontStruct *fs = font->fs; 2572fa3f02f3Smrg XCharStruct *pc = 0; 2573d522f475Smrg 2574956cc18dSsnj if (fs->max_byte1 == 0) { 2575d522f475Smrg#if OPT_WIDE_CHARS 2576fa3f02f3Smrg if (ch < 256) 2577956cc18dSsnj#endif 2578fa3f02f3Smrg { 2579fa3f02f3Smrg CI_GET_CHAR_INFO_1D(fs, E2A(ch), pc); 2580fa3f02f3Smrg } 2581956cc18dSsnj } 2582d522f475Smrg#if OPT_WIDE_CHARS 2583956cc18dSsnj else { 2584fa3f02f3Smrg unsigned row = (ch >> 8); 2585fa3f02f3Smrg unsigned col = (ch & 0xff); 2586fa3f02f3Smrg CI_GET_CHAR_INFO_2D(fs, row, col, pc); 2587956cc18dSsnj } 2588d522f475Smrg#endif 2589d522f475Smrg 2590fa3f02f3Smrg if (pc == 0 || CI_NONEXISTCHAR(pc)) { 2591956cc18dSsnj TRACE(("xtermMissingChar %#04x (!exists)\n", ch)); 2592956cc18dSsnj result = True; 2593d522f475Smrg } 2594fa3f02f3Smrg if (ch < KNOWN_MISSING) { 2595956cc18dSsnj font->known_missing[ch] = (Char) (result ? 2 : 1); 2596d522f475Smrg } 2597956cc18dSsnj return result; 2598d522f475Smrg} 2599fa3f02f3Smrg#endif 2600d522f475Smrg 2601fa3f02f3Smrg#if OPT_BOX_CHARS 2602d522f475Smrg/* 2603d522f475Smrg * The grid is arbitrary, enough resolution that nothing's lost in 2604d522f475Smrg * initialization. 2605d522f475Smrg */ 2606d522f475Smrg#define BOX_HIGH 60 2607d522f475Smrg#define BOX_WIDE 60 2608d522f475Smrg 2609d522f475Smrg#define MID_HIGH (BOX_HIGH/2) 2610d522f475Smrg#define MID_WIDE (BOX_WIDE/2) 2611d522f475Smrg 2612d522f475Smrg#define CHR_WIDE ((9*BOX_WIDE)/10) 2613d522f475Smrg#define CHR_HIGH ((9*BOX_HIGH)/10) 2614d522f475Smrg 2615d522f475Smrg/* 2616d522f475Smrg * ...since we'll scale the values anyway. 2617d522f475Smrg */ 2618e39b573cSmrg#define SCALED_X(n) ((int)(n) * (((int) font_width) - 1)) / (BOX_WIDE-1) 2619e39b573cSmrg#define SCALED_Y(n) ((int)(n) * (((int) font_height) - 1)) / (BOX_HIGH-1) 2620e39b573cSmrg#define SCALE_X(n) n = SCALED_X(n) 2621e39b573cSmrg#define SCALE_Y(n) n = SCALED_Y(n) 2622d522f475Smrg 2623d522f475Smrg#define SEG(x0,y0,x1,y1) x0,y0, x1,y1 2624d522f475Smrg 2625d522f475Smrg/* 2626d522f475Smrg * Draw the given graphic character, if it is simple enough (i.e., a 2627d522f475Smrg * line-drawing character). 2628d522f475Smrg */ 2629d522f475Smrgvoid 2630d522f475SmrgxtermDrawBoxChar(XtermWidget xw, 2631d522f475Smrg unsigned ch, 26329a64e1c5Smrg unsigned attr_flags, 26339a64e1c5Smrg unsigned draw_flags, 2634d522f475Smrg GC gc, 2635d522f475Smrg int x, 2636d522f475Smrg int y, 2637d522f475Smrg int cells) 2638d522f475Smrg{ 2639956cc18dSsnj TScreen *screen = TScreenOf(xw); 2640d522f475Smrg /* *INDENT-OFF* */ 2641d522f475Smrg static const short glyph_ht[] = { 2642d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,5*MID_HIGH/6), /* H */ 2643d522f475Smrg SEG(6*BOX_WIDE/10, 0, 6*BOX_WIDE/10,5*MID_HIGH/6), 2644d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*BOX_WIDE/10,5*MID_HIGH/12), 2645d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 2646d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 2647d522f475Smrg -1 2648d522f475Smrg }, glyph_ff[] = { 2649d522f475Smrg SEG(1*BOX_WIDE/10, 0, 6*BOX_WIDE/10, 0), /* F */ 2650d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/12,6*CHR_WIDE/12,5*MID_HIGH/12), 2651d522f475Smrg SEG(1*BOX_WIDE/10, 0, 0*BOX_WIDE/3, 5*MID_HIGH/6), 2652d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 2653d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 2654d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 2655d522f475Smrg -1 2656d522f475Smrg }, glyph_lf[] = { 2657d522f475Smrg SEG(1*BOX_WIDE/10, 0, 1*BOX_WIDE/10,9*MID_HIGH/12), /* L */ 2658d522f475Smrg SEG(1*BOX_WIDE/10,9*MID_HIGH/12,6*BOX_WIDE/10,9*MID_HIGH/12), 2659d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ 2660d522f475Smrg SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), 2661d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), 2662d522f475Smrg -1 2663d522f475Smrg }, glyph_nl[] = { 2664d522f475Smrg SEG(1*BOX_WIDE/10,5*MID_HIGH/6, 1*BOX_WIDE/10, 0), /* N */ 2665d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/6, 5*MID_HIGH/6), 2666d522f475Smrg SEG(5*BOX_WIDE/6, 5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 2667d522f475Smrg SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), /* L */ 2668d522f475Smrg SEG(1*BOX_WIDE/3, CHR_HIGH, CHR_WIDE, CHR_HIGH), 2669d522f475Smrg -1 2670d522f475Smrg }, glyph_vt[] = { 2671d522f475Smrg SEG(1*BOX_WIDE/10, 0, 5*BOX_WIDE/12,5*MID_HIGH/6), /* V */ 2672d522f475Smrg SEG(5*BOX_WIDE/12,5*MID_HIGH/6, 5*BOX_WIDE/6, 0), 2673d522f475Smrg SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ 2674d522f475Smrg SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), 2675d522f475Smrg -1 2676d522f475Smrg }, plus_or_minus[] = 2677d522f475Smrg { 2678d522f475Smrg SEG( 0, 5*BOX_HIGH/6, CHR_WIDE, 5*BOX_HIGH/6), 2679d522f475Smrg SEG( MID_WIDE, 2*BOX_HIGH/6, MID_WIDE, 4*BOX_HIGH/6), 2680d522f475Smrg SEG( 0, 3*BOX_HIGH/6, CHR_WIDE, 3*BOX_HIGH/6), 2681d522f475Smrg -1 2682d522f475Smrg }, lower_right_corner[] = 2683d522f475Smrg { 2684d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 2685d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, 0), 2686d522f475Smrg -1 2687d522f475Smrg }, upper_right_corner[] = 2688d522f475Smrg { 2689d522f475Smrg SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), 2690d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2691d522f475Smrg -1 2692d522f475Smrg }, upper_left_corner[] = 2693d522f475Smrg { 2694d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 2695d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2696d522f475Smrg -1 2697d522f475Smrg }, lower_left_corner[] = 2698d522f475Smrg { 2699d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 2700d522f475Smrg SEG( MID_WIDE, MID_WIDE, BOX_WIDE, MID_HIGH), 2701d522f475Smrg -1 2702d522f475Smrg }, cross[] = 2703d522f475Smrg { 2704d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2705d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2706d522f475Smrg -1 2707d522f475Smrg }, scan_line_1[] = 2708d522f475Smrg { 2709d522f475Smrg SEG( 0, 0, BOX_WIDE, 0), 2710d522f475Smrg -1 2711d522f475Smrg }, scan_line_3[] = 2712d522f475Smrg { 2713d522f475Smrg SEG( 0, BOX_HIGH/4, BOX_WIDE, BOX_HIGH/4), 2714d522f475Smrg -1 2715d522f475Smrg }, scan_line_7[] = 2716d522f475Smrg { 2717d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2718d522f475Smrg -1 2719d522f475Smrg }, scan_line_9[] = 2720d522f475Smrg { 2721d522f475Smrg SEG( 0, 3*BOX_HIGH/4, BOX_WIDE, 3*BOX_HIGH/4), 2722d522f475Smrg -1 2723d522f475Smrg }, horizontal_line[] = 2724d522f475Smrg { 2725d522f475Smrg SEG( 0, BOX_HIGH, BOX_WIDE, BOX_HIGH), 2726d522f475Smrg -1 2727d522f475Smrg }, left_tee[] = 2728d522f475Smrg { 2729d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2730d522f475Smrg SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), 2731d522f475Smrg -1 2732d522f475Smrg }, right_tee[] = 2733d522f475Smrg { 2734d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2735d522f475Smrg SEG( MID_WIDE, MID_HIGH, 0, MID_HIGH), 2736d522f475Smrg -1 2737d522f475Smrg }, bottom_tee[] = 2738d522f475Smrg { 2739d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2740d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), 2741d522f475Smrg -1 2742d522f475Smrg }, top_tee[] = 2743d522f475Smrg { 2744d522f475Smrg SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), 2745d522f475Smrg SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), 2746d522f475Smrg -1 2747d522f475Smrg }, vertical_line[] = 2748d522f475Smrg { 2749d522f475Smrg SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), 2750d522f475Smrg -1 2751d522f475Smrg }, less_than_or_equal[] = 2752d522f475Smrg { 2753d522f475Smrg SEG( CHR_WIDE, BOX_HIGH/3, 0, MID_HIGH), 2754d522f475Smrg SEG( CHR_WIDE, 2*BOX_HIGH/3, 0, MID_HIGH), 2755d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 2756d522f475Smrg -1 2757d522f475Smrg }, greater_than_or_equal[] = 2758d522f475Smrg { 2759d522f475Smrg SEG( 0, BOX_HIGH/3, CHR_WIDE, MID_HIGH), 2760d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, MID_HIGH), 2761d522f475Smrg SEG( 0, 3*BOX_HIGH/4, CHR_WIDE, 3*BOX_HIGH/4), 2762d522f475Smrg -1 2763d522f475Smrg }, greek_pi[] = 2764d522f475Smrg { 2765d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 2766d522f475Smrg SEG(5*CHR_WIDE/6, MID_HIGH, 5*CHR_WIDE/6, CHR_HIGH), 2767d522f475Smrg SEG(2*CHR_WIDE/6, MID_HIGH, 2*CHR_WIDE/6, CHR_HIGH), 2768d522f475Smrg -1 2769d522f475Smrg }, not_equal_to[] = 2770d522f475Smrg { 2771d522f475Smrg SEG(2*BOX_WIDE/3, 1*BOX_HIGH/3, 1*BOX_WIDE/3, CHR_HIGH), 2772d522f475Smrg SEG( 0, 2*BOX_HIGH/3, CHR_WIDE, 2*BOX_HIGH/3), 2773d522f475Smrg SEG( 0, MID_HIGH, CHR_WIDE, MID_HIGH), 2774d522f475Smrg -1 2775d522f475Smrg }; 2776d522f475Smrg /* *INDENT-ON* */ 2777d522f475Smrg 2778d522f475Smrg static const short *lines[] = 2779d522f475Smrg { 2780d522f475Smrg 0, /* 00 (unused) */ 2781d522f475Smrg 0, /* 01 diamond */ 2782d522f475Smrg 0, /* 02 box */ 2783d522f475Smrg glyph_ht, /* 03 HT */ 2784d522f475Smrg glyph_ff, /* 04 FF */ 2785d522f475Smrg 0, /* 05 CR */ 2786d522f475Smrg glyph_lf, /* 06 LF */ 2787d522f475Smrg 0, /* 07 degrees (small circle) */ 2788d522f475Smrg plus_or_minus, /* 08 */ 2789d522f475Smrg glyph_nl, /* 09 */ 2790d522f475Smrg glyph_vt, /* 0A */ 2791d522f475Smrg lower_right_corner, /* 0B */ 2792d522f475Smrg upper_right_corner, /* 0C */ 2793d522f475Smrg upper_left_corner, /* 0D */ 2794d522f475Smrg lower_left_corner, /* 0E */ 2795d522f475Smrg cross, /* 0F */ 2796d522f475Smrg scan_line_1, /* 10 */ 2797d522f475Smrg scan_line_3, /* 11 */ 2798d522f475Smrg scan_line_7, /* 12 */ 2799d522f475Smrg scan_line_9, /* 13 */ 2800d522f475Smrg horizontal_line, /* 14 */ 2801d522f475Smrg left_tee, /* 15 */ 2802d522f475Smrg right_tee, /* 16 */ 2803d522f475Smrg bottom_tee, /* 17 */ 2804d522f475Smrg top_tee, /* 18 */ 2805d522f475Smrg vertical_line, /* 19 */ 2806d522f475Smrg less_than_or_equal, /* 1A */ 2807d522f475Smrg greater_than_or_equal, /* 1B */ 2808d522f475Smrg greek_pi, /* 1C */ 2809d522f475Smrg not_equal_to, /* 1D */ 2810d522f475Smrg 0, /* 1E LB */ 2811d522f475Smrg 0, /* 1F bullet */ 2812d522f475Smrg }; 2813d522f475Smrg 2814d522f475Smrg GC gc2; 2815d522f475Smrg CgsEnum cgsId = (ch == 2) ? gcDots : gcLine; 2816d522f475Smrg VTwin *cgsWin = WhichVWin(screen); 2817d522f475Smrg const short *p; 28189a64e1c5Smrg unsigned font_width = (unsigned) (((draw_flags & DOUBLEWFONT) ? 2 : 1) 28199a64e1c5Smrg * screen->fnt_wide); 28209a64e1c5Smrg unsigned font_height = (unsigned) (((draw_flags & DOUBLEHFONT) ? 2 : 1) 28219a64e1c5Smrg * screen->fnt_high); 2822d522f475Smrg 2823d522f475Smrg if (cells > 1) 2824956cc18dSsnj font_width *= (unsigned) cells; 2825d522f475Smrg 2826d522f475Smrg#if OPT_WIDE_CHARS 2827d522f475Smrg /* 2828d522f475Smrg * Try to show line-drawing characters if we happen to be in UTF-8 2829d522f475Smrg * mode, but have gotten an old-style font. 2830d522f475Smrg */ 2831d522f475Smrg if (screen->utf8_mode 2832d522f475Smrg#if OPT_RENDERFONT 2833d522f475Smrg && !UsingRenderFont(xw) 2834d522f475Smrg#endif 2835d522f475Smrg && (ch > 127) 2836d522f475Smrg && (ch != UCS_REPL)) { 2837d522f475Smrg unsigned n; 2838d522f475Smrg for (n = 1; n < 32; n++) { 2839d522f475Smrg if (dec2ucs(n) == ch 28409a64e1c5Smrg && !((attr_flags & BOLD) 284120d2c4d2Smrg ? IsXtermMissingChar(screen, n, &screen->fnts[fBold]) 284220d2c4d2Smrg : IsXtermMissingChar(screen, n, &screen->fnts[fNorm]))) { 2843d522f475Smrg TRACE(("...use xterm-style linedrawing\n")); 2844d522f475Smrg ch = n; 2845d522f475Smrg break; 2846d522f475Smrg } 2847d522f475Smrg } 2848d522f475Smrg } 2849d522f475Smrg#endif 2850d522f475Smrg 2851d522f475Smrg TRACE(("DRAW_BOX(%d) cell %dx%d at %d,%d%s\n", 2852d522f475Smrg ch, font_height, font_width, y, x, 2853d522f475Smrg (ch >= (sizeof(lines) / sizeof(lines[0])) 2854d522f475Smrg ? "-BAD" 2855d522f475Smrg : ""))); 2856d522f475Smrg 2857d522f475Smrg if (cgsId == gcDots) { 2858d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2859d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2860d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2861d522f475Smrg } else { 2862d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2863d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2864d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2865d522f475Smrg } 2866d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2867d522f475Smrg 28689a64e1c5Smrg if (!(draw_flags & NOBACKGROUND)) { 28690bd37d32Smrg XFillRectangle(screen->display, VDrawable(screen), gc2, x, y, 2870d522f475Smrg font_width, 2871d522f475Smrg font_height); 2872d522f475Smrg } 2873d522f475Smrg 2874d522f475Smrg setCgsFont(xw, cgsWin, cgsId, getCgsFont(xw, cgsWin, gc)); 2875d522f475Smrg setCgsFore(xw, cgsWin, cgsId, getCgsFore(xw, cgsWin, gc)); 2876d522f475Smrg setCgsBack(xw, cgsWin, cgsId, getCgsBack(xw, cgsWin, gc)); 2877d522f475Smrg gc2 = getCgsGC(xw, cgsWin, cgsId); 2878d522f475Smrg 2879d522f475Smrg XSetLineAttributes(screen->display, gc2, 28809a64e1c5Smrg (attr_flags & BOLD) 2881d522f475Smrg ? ((font_height > 12) 2882d522f475Smrg ? font_height / 12 2883d522f475Smrg : 1) 2884d522f475Smrg : ((font_height > 16) 2885d522f475Smrg ? font_height / 16 2886d522f475Smrg : 1), 2887d522f475Smrg LineSolid, 2888d522f475Smrg CapProjecting, 2889d522f475Smrg JoinMiter); 2890d522f475Smrg 2891d522f475Smrg if (ch == 1) { /* diamond */ 2892d522f475Smrg XPoint points[5]; 2893d522f475Smrg int npoints = 5, n; 2894d522f475Smrg 2895d522f475Smrg points[0].x = MID_WIDE; 2896d522f475Smrg points[0].y = BOX_HIGH / 4; 2897d522f475Smrg 2898d522f475Smrg points[1].x = 8 * BOX_WIDE / 8; 2899d522f475Smrg points[1].y = MID_HIGH; 2900d522f475Smrg 2901d522f475Smrg points[2].x = points[0].x; 2902d522f475Smrg points[2].y = 3 * BOX_HIGH / 4; 2903d522f475Smrg 2904d522f475Smrg points[3].x = 0 * BOX_WIDE / 8; 2905d522f475Smrg points[3].y = points[1].y; 2906d522f475Smrg 2907d522f475Smrg points[4].x = points[0].x; 2908d522f475Smrg points[4].y = points[0].y; 2909d522f475Smrg 2910d522f475Smrg for (n = 0; n < npoints; ++n) { 2911e39b573cSmrg points[n].x = (short) SCALED_X(points[n].x); 2912e39b573cSmrg points[n].y = (short) SCALED_Y(points[n].y); 2913e39b573cSmrg points[n].x = (short) (points[n].x + x); 2914e39b573cSmrg points[n].y = (short) (points[n].y + y); 2915d522f475Smrg } 2916d522f475Smrg 2917d522f475Smrg XFillPolygon(screen->display, 29180bd37d32Smrg VDrawable(screen), gc2, 2919d522f475Smrg points, npoints, 2920d522f475Smrg Convex, CoordModeOrigin); 2921d522f475Smrg } else if (ch == 7) { /* degrees */ 2922d522f475Smrg unsigned width = (BOX_WIDE / 3); 2923956cc18dSsnj int x_coord = MID_WIDE - (int) (width / 2); 2924956cc18dSsnj int y_coord = MID_HIGH - (int) width; 2925d522f475Smrg 2926d522f475Smrg SCALE_X(x_coord); 2927d522f475Smrg SCALE_Y(y_coord); 2928e39b573cSmrg width = (unsigned) SCALED_X(width); 2929d522f475Smrg 2930d522f475Smrg XDrawArc(screen->display, 29310bd37d32Smrg VDrawable(screen), gc2, 2932d522f475Smrg x + x_coord, y + y_coord, width, width, 2933d522f475Smrg 0, 2934d522f475Smrg 360 * 64); 2935d522f475Smrg } else if (ch == 0x1f) { /* bullet */ 2936d522f475Smrg unsigned width = 7 * BOX_WIDE / 10; 2937956cc18dSsnj int x_coord = MID_WIDE - (int) (width / 3); 2938956cc18dSsnj int y_coord = MID_HIGH - (int) (width / 3); 2939d522f475Smrg 2940d522f475Smrg SCALE_X(x_coord); 2941d522f475Smrg SCALE_Y(y_coord); 2942e39b573cSmrg width = (unsigned) SCALED_X(width); 2943d522f475Smrg 2944d522f475Smrg XDrawArc(screen->display, 29450bd37d32Smrg VDrawable(screen), gc2, 2946d522f475Smrg x + x_coord, y + y_coord, width, width, 2947d522f475Smrg 0, 2948d522f475Smrg 360 * 64); 2949d522f475Smrg } else if (ch < (sizeof(lines) / sizeof(lines[0])) 2950d522f475Smrg && (p = lines[ch]) != 0) { 2951956cc18dSsnj int coord[4]; 2952d522f475Smrg int n = 0; 2953d522f475Smrg while (*p >= 0) { 2954d522f475Smrg coord[n++] = *p++; 2955d522f475Smrg if (n == 4) { 2956d522f475Smrg SCALE_X(coord[0]); 2957d522f475Smrg SCALE_Y(coord[1]); 2958d522f475Smrg SCALE_X(coord[2]); 2959d522f475Smrg SCALE_Y(coord[3]); 2960d522f475Smrg XDrawLine(screen->display, 29610bd37d32Smrg VDrawable(screen), gc2, 2962d522f475Smrg x + coord[0], y + coord[1], 2963d522f475Smrg x + coord[2], y + coord[3]); 2964d522f475Smrg n = 0; 2965d522f475Smrg } 2966d522f475Smrg } 2967d522f475Smrg } else if (screen->force_all_chars) { 2968d522f475Smrg /* bounding rectangle, for debugging */ 29690bd37d32Smrg XDrawRectangle(screen->display, VDrawable(screen), gc2, x, y, 2970d522f475Smrg font_width - 1, 2971d522f475Smrg font_height - 1); 2972d522f475Smrg } 2973d522f475Smrg} 2974fa3f02f3Smrg#endif /* OPT_BOX_CHARS */ 2975d522f475Smrg 2976d522f475Smrg#if OPT_RENDERFONT 2977d522f475Smrg 2978d522f475Smrg/* 2979d522f475Smrg * Check if the given character has a glyph known to Xft. 2980d522f475Smrg * 2981d522f475Smrg * see xc/lib/Xft/xftglyphs.c 2982d522f475Smrg */ 2983d522f475SmrgBool 29849a64e1c5SmrgxtermXftMissing(XtermWidget xw, XftFont *font, unsigned wc) 2985d522f475Smrg{ 2986d522f475Smrg Bool result = False; 2987d522f475Smrg 2988d522f475Smrg if (font != 0) { 2989956cc18dSsnj TScreen *screen = TScreenOf(xw); 2990956cc18dSsnj if (!XftGlyphExists(screen->display, font, wc)) { 2991d522f475Smrg#if OPT_WIDE_CHARS 2992d522f475Smrg TRACE(("xtermXftMissing %d (dec=%#x, ucs=%#x)\n", 2993d522f475Smrg wc, ucs2dec(wc), dec2ucs(wc))); 2994d522f475Smrg#else 2995d522f475Smrg TRACE(("xtermXftMissing %d\n", wc)); 2996d522f475Smrg#endif 2997d522f475Smrg result = True; 2998d522f475Smrg } 2999d522f475Smrg } 3000d522f475Smrg return result; 3001d522f475Smrg} 3002fa3f02f3Smrg#endif /* OPT_RENDERFONT */ 3003d522f475Smrg 3004d522f475Smrg#if OPT_WIDE_CHARS 3005d522f475Smrg#define MY_UCS(ucs,dec) case ucs: result = dec; break 3006d522f475Smrgunsigned 3007d522f475Smrgucs2dec(unsigned ch) 3008d522f475Smrg{ 3009d522f475Smrg unsigned result = ch; 3010d522f475Smrg if ((ch > 127) 3011d522f475Smrg && (ch != UCS_REPL)) { 3012d522f475Smrg switch (ch) { 3013d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 3014d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 3015d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 3016d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 3017d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 3018d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 3019d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 3020d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 3021d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 3022d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 3023d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 3024d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 3025d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 3026d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 3027d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 3028d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 3029d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 3030d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 3031d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 3032d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 3033d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 3034d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 3035d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 3036d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 3037d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 3038d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 3039d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 3040d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 3041d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 3042d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 3043d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 3044d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 3045d522f475Smrg } 3046d522f475Smrg } 3047d522f475Smrg return result; 3048d522f475Smrg} 3049d522f475Smrg 3050d522f475Smrg#undef MY_UCS 3051d522f475Smrg#define MY_UCS(ucs,dec) case dec: result = ucs; break 3052d522f475Smrg 3053d522f475Smrgunsigned 3054d522f475Smrgdec2ucs(unsigned ch) 3055d522f475Smrg{ 3056d522f475Smrg unsigned result = ch; 3057d522f475Smrg if (xtermIsDecGraphic(ch)) { 3058d522f475Smrg switch (ch) { 3059d522f475Smrg MY_UCS(0x25ae, 0); /* black vertical rectangle */ 3060d522f475Smrg MY_UCS(0x25c6, 1); /* black diamond */ 3061d522f475Smrg MY_UCS(0x2592, 2); /* medium shade */ 3062d522f475Smrg MY_UCS(0x2409, 3); /* symbol for horizontal tabulation */ 3063d522f475Smrg MY_UCS(0x240c, 4); /* symbol for form feed */ 3064d522f475Smrg MY_UCS(0x240d, 5); /* symbol for carriage return */ 3065d522f475Smrg MY_UCS(0x240a, 6); /* symbol for line feed */ 3066d522f475Smrg MY_UCS(0x00b0, 7); /* degree sign */ 3067d522f475Smrg MY_UCS(0x00b1, 8); /* plus-minus sign */ 3068d522f475Smrg MY_UCS(0x2424, 9); /* symbol for newline */ 3069d522f475Smrg MY_UCS(0x240b, 10); /* symbol for vertical tabulation */ 3070d522f475Smrg MY_UCS(0x2518, 11); /* box drawings light up and left */ 3071d522f475Smrg MY_UCS(0x2510, 12); /* box drawings light down and left */ 3072d522f475Smrg MY_UCS(0x250c, 13); /* box drawings light down and right */ 3073d522f475Smrg MY_UCS(0x2514, 14); /* box drawings light up and right */ 3074d522f475Smrg MY_UCS(0x253c, 15); /* box drawings light vertical and horizontal */ 3075d522f475Smrg MY_UCS(0x23ba, 16); /* box drawings scan 1 */ 3076d522f475Smrg MY_UCS(0x23bb, 17); /* box drawings scan 3 */ 3077d522f475Smrg MY_UCS(0x2500, 18); /* box drawings light horizontal */ 3078d522f475Smrg MY_UCS(0x23bc, 19); /* box drawings scan 7 */ 3079d522f475Smrg MY_UCS(0x23bd, 20); /* box drawings scan 9 */ 3080d522f475Smrg MY_UCS(0x251c, 21); /* box drawings light vertical and right */ 3081d522f475Smrg MY_UCS(0x2524, 22); /* box drawings light vertical and left */ 3082d522f475Smrg MY_UCS(0x2534, 23); /* box drawings light up and horizontal */ 3083d522f475Smrg MY_UCS(0x252c, 24); /* box drawings light down and horizontal */ 3084d522f475Smrg MY_UCS(0x2502, 25); /* box drawings light vertical */ 3085d522f475Smrg MY_UCS(0x2264, 26); /* less-than or equal to */ 3086d522f475Smrg MY_UCS(0x2265, 27); /* greater-than or equal to */ 3087d522f475Smrg MY_UCS(0x03c0, 28); /* greek small letter pi */ 3088d522f475Smrg MY_UCS(0x2260, 29); /* not equal to */ 3089d522f475Smrg MY_UCS(0x00a3, 30); /* pound sign */ 3090d522f475Smrg MY_UCS(0x00b7, 31); /* middle dot */ 3091d522f475Smrg } 3092d522f475Smrg } 3093d522f475Smrg return result; 3094d522f475Smrg} 3095d522f475Smrg 3096d522f475Smrg#endif /* OPT_WIDE_CHARS */ 3097d522f475Smrg 3098b6fea0ceSmrg#if OPT_RENDERFONT || OPT_SHIFT_FONTS 30990bd37d32Smrgstatic int 3100d522f475SmrglookupOneFontSize(XtermWidget xw, int fontnum) 3101d522f475Smrg{ 3102d522f475Smrg TScreen *screen = TScreenOf(xw); 3103d522f475Smrg 3104d522f475Smrg if (screen->menu_font_sizes[fontnum] == 0) { 3105d522f475Smrg XTermFonts fnt; 3106d522f475Smrg 3107d522f475Smrg memset(&fnt, 0, sizeof(fnt)); 3108d522f475Smrg screen->menu_font_sizes[fontnum] = -1; 31090bd37d32Smrg if (xtermOpenFont(xw, 31100bd37d32Smrg screen->MenuFontName(fontnum), 31110bd37d32Smrg &fnt, 31120bd37d32Smrg ((fontnum <= fontMenu_lastBuiltin) 31130bd37d32Smrg ? fwAlways 31140bd37d32Smrg : fwResource), 31150bd37d32Smrg True)) { 311620d2c4d2Smrg if (fontnum <= fontMenu_lastBuiltin 31170bd37d32Smrg || strcmp(fnt.fn, DEFFONT)) { 311820d2c4d2Smrg screen->menu_font_sizes[fontnum] = FontSize(fnt.fs); 31190bd37d32Smrg if (screen->menu_font_sizes[fontnum] <= 0) 31200bd37d32Smrg screen->menu_font_sizes[fontnum] = -1; 31210bd37d32Smrg } 3122d522f475Smrg xtermCloseFont(xw, &fnt); 3123d522f475Smrg } 3124d522f475Smrg } 31250bd37d32Smrg return (screen->menu_font_sizes[fontnum] > 0); 3126d522f475Smrg} 3127d522f475Smrg 3128d522f475Smrg/* 3129d522f475Smrg * Cache the font-sizes so subsequent larger/smaller font actions will go fast. 3130d522f475Smrg */ 3131d522f475Smrgstatic void 3132d522f475SmrglookupFontSizes(XtermWidget xw) 3133d522f475Smrg{ 3134d522f475Smrg int n; 3135d522f475Smrg 3136d522f475Smrg for (n = 0; n < NMENUFONTS; n++) { 31370bd37d32Smrg (void) lookupOneFontSize(xw, n); 3138d522f475Smrg } 3139d522f475Smrg} 3140b6fea0ceSmrg#endif /* OPT_RENDERFONT || OPT_SHIFT_FONTS */ 3141d522f475Smrg 31422eaa94a1Schristos#if OPT_RENDERFONT 31439a64e1c5Smrgstatic double 31449a64e1c5SmrgdefaultFaceSize(void) 31459a64e1c5Smrg{ 31469a64e1c5Smrg double result; 31479a64e1c5Smrg float value; 31489a64e1c5Smrg 31499a64e1c5Smrg if (sscanf(DEFFACESIZE, "%f", &value) == 1) 31509a64e1c5Smrg result = value; 31519a64e1c5Smrg else 31529a64e1c5Smrg result = 14.0; 31539a64e1c5Smrg return result; 31549a64e1c5Smrg} 31559a64e1c5Smrg 31560bd37d32Smrgstatic void 31570bd37d32SmrgfillInFaceSize(XtermWidget xw, int fontnum) 31580bd37d32Smrg{ 31590bd37d32Smrg TScreen *screen = TScreenOf(xw); 31600bd37d32Smrg double face_size = xw->misc.face_size[fontnum]; 31610bd37d32Smrg 31620bd37d32Smrg if (face_size <= 0.0) { 31630bd37d32Smrg#if OPT_SHIFT_FONTS 31640bd37d32Smrg /* 31650bd37d32Smrg * If the user is switching font-sizes, make it follow by 31660bd37d32Smrg * default the same ratios to the default as the fixed fonts 31670bd37d32Smrg * would, for easy comparison. There will be some differences 31680bd37d32Smrg * since the fixed fonts have a variety of height/width ratios, 31690bd37d32Smrg * but this is simpler than adding another resource value - and 31700bd37d32Smrg * as noted above, the data for the fixed fonts are available. 31710bd37d32Smrg */ 31720bd37d32Smrg (void) lookupOneFontSize(xw, 0); 31730bd37d32Smrg if (fontnum == fontMenu_default) { 31749a64e1c5Smrg face_size = defaultFaceSize(); 31750bd37d32Smrg } else if (lookupOneFontSize(xw, fontnum) 31760bd37d32Smrg && (screen->menu_font_sizes[0] 31770bd37d32Smrg != screen->menu_font_sizes[fontnum])) { 31780bd37d32Smrg double ratio; 31790bd37d32Smrg long num = screen->menu_font_sizes[fontnum]; 31800bd37d32Smrg long den = screen->menu_font_sizes[0]; 31810bd37d32Smrg 31820bd37d32Smrg if (den <= 0) 31830bd37d32Smrg den = 1; 31840bd37d32Smrg ratio = dimSquareRoot((double) num / (double) den); 31850bd37d32Smrg 31860bd37d32Smrg face_size = (ratio * xw->misc.face_size[0]); 31870bd37d32Smrg TRACE(("scaled[%d] using %3ld/%ld = %.2f -> %f\n", 31880bd37d32Smrg fontnum, num, den, ratio, face_size)); 31890bd37d32Smrg } else 31900bd37d32Smrg#endif 31910bd37d32Smrg { 31920bd37d32Smrg#define LikeBitmap(s) (((s) / 78.0) * xw->misc.face_size[fontMenu_default]) 31930bd37d32Smrg switch (fontnum) { 31940bd37d32Smrg case fontMenu_font1: 31950bd37d32Smrg face_size = LikeBitmap(2.0); 31960bd37d32Smrg break; 31970bd37d32Smrg case fontMenu_font2: 31980bd37d32Smrg face_size = LikeBitmap(35.0); 31990bd37d32Smrg break; 32000bd37d32Smrg case fontMenu_font3: 32010bd37d32Smrg face_size = LikeBitmap(60.0); 32020bd37d32Smrg break; 32030bd37d32Smrg default: 32049a64e1c5Smrg face_size = defaultFaceSize(); 32050bd37d32Smrg break; 32060bd37d32Smrg case fontMenu_font4: 32070bd37d32Smrg face_size = LikeBitmap(90.0); 32080bd37d32Smrg break; 32090bd37d32Smrg case fontMenu_font5: 32100bd37d32Smrg face_size = LikeBitmap(135.0); 32110bd37d32Smrg break; 32120bd37d32Smrg case fontMenu_font6: 32130bd37d32Smrg face_size = LikeBitmap(200.0); 32140bd37d32Smrg break; 32150bd37d32Smrg } 32160bd37d32Smrg TRACE(("builtin[%d] -> %f\n", fontnum, face_size)); 32170bd37d32Smrg } 32180bd37d32Smrg xw->misc.face_size[fontnum] = (float) face_size; 32190bd37d32Smrg } 32200bd37d32Smrg} 32210bd37d32Smrg 32220bd37d32Smrg/* no selection or escape */ 32230bd37d32Smrg#define NMENU_RENDERFONTS (fontMenu_lastBuiltin + 1) 32240bd37d32Smrg 32250bd37d32Smrg/* 32260bd37d32Smrg * Workaround for breakage in font-packages - check if all of the bitmap font 32270bd37d32Smrg * sizes are the same, and if we're using TrueType fonts. 32280bd37d32Smrg */ 32292eaa94a1Schristosstatic Boolean 32302eaa94a1SchristosuseFaceSizes(XtermWidget xw) 32312eaa94a1Schristos{ 32322eaa94a1Schristos Boolean result = False; 32332eaa94a1Schristos int n; 32342eaa94a1Schristos 32350bd37d32Smrg TRACE(("useFaceSizes {{\n")); 32362eaa94a1Schristos if (UsingRenderFont(xw)) { 32370bd37d32Smrg Boolean nonzero = True; 32380bd37d32Smrg 32392eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 32402eaa94a1Schristos if (xw->misc.face_size[n] <= 0.0) { 32410bd37d32Smrg nonzero = False; 32422eaa94a1Schristos break; 32432eaa94a1Schristos } 32442eaa94a1Schristos } 32450bd37d32Smrg if (!nonzero) { 3246956cc18dSsnj Boolean broken_fonts = True; 3247956cc18dSsnj TScreen *screen = TScreenOf(xw); 32480bd37d32Smrg long first; 3249956cc18dSsnj 3250956cc18dSsnj lookupFontSizes(xw); 32510bd37d32Smrg first = screen->menu_font_sizes[0]; 3252956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 3253956cc18dSsnj if (screen->menu_font_sizes[n] > 0 3254956cc18dSsnj && screen->menu_font_sizes[n] != first) { 3255956cc18dSsnj broken_fonts = False; 3256956cc18dSsnj break; 3257956cc18dSsnj } 3258956cc18dSsnj } 3259956cc18dSsnj 3260956cc18dSsnj if (broken_fonts) { 3261956cc18dSsnj 3262956cc18dSsnj TRACE(("bitmap fonts are broken - set faceSize resources\n")); 3263956cc18dSsnj for (n = 0; n < NMENUFONTS; n++) { 32640bd37d32Smrg fillInFaceSize(xw, n); 3265956cc18dSsnj } 3266956cc18dSsnj 3267956cc18dSsnj } 3268956cc18dSsnj } 32690bd37d32Smrg result = True; 32702eaa94a1Schristos } 32710bd37d32Smrg TRACE(("...}}useFaceSizes %d\n", result)); 32722eaa94a1Schristos return result; 32732eaa94a1Schristos} 32740bd37d32Smrg#endif /* OPT_RENDERFONT */ 32752eaa94a1Schristos 3276b6fea0ceSmrg#if OPT_SHIFT_FONTS 3277d522f475Smrg/* 3278d522f475Smrg * Find the index of a larger/smaller font (according to the sign of 'relative' 3279d522f475Smrg * and its magnitude), starting from the 'old' index. 3280d522f475Smrg */ 3281d522f475Smrgint 3282d522f475SmrglookupRelativeFontSize(XtermWidget xw, int old, int relative) 3283d522f475Smrg{ 3284d522f475Smrg TScreen *screen = TScreenOf(xw); 3285d522f475Smrg int n, m = -1; 3286d522f475Smrg 32872eaa94a1Schristos TRACE(("lookupRelativeFontSize(old=%d, relative=%d)\n", old, relative)); 3288d522f475Smrg if (!IsIcon(screen)) { 32892eaa94a1Schristos#if OPT_RENDERFONT 32902eaa94a1Schristos if (useFaceSizes(xw)) { 32912eaa94a1Schristos TRACE(("...using FaceSize\n")); 32922eaa94a1Schristos if (relative != 0) { 32932eaa94a1Schristos for (n = 0; n < NMENU_RENDERFONTS; ++n) { 32940bd37d32Smrg fillInFaceSize(xw, n); 32952eaa94a1Schristos if (xw->misc.face_size[n] > 0 && 32962eaa94a1Schristos xw->misc.face_size[n] != xw->misc.face_size[old]) { 32972eaa94a1Schristos int cmp_0 = ((xw->misc.face_size[n] > 32982eaa94a1Schristos xw->misc.face_size[old]) 32992eaa94a1Schristos ? relative 33002eaa94a1Schristos : -relative); 33012eaa94a1Schristos int cmp_m = ((m < 0) 33022eaa94a1Schristos ? 1 33032eaa94a1Schristos : ((xw->misc.face_size[n] < 33042eaa94a1Schristos xw->misc.face_size[m]) 33052eaa94a1Schristos ? relative 33062eaa94a1Schristos : -relative)); 33072eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 33082eaa94a1Schristos m = n; 33092eaa94a1Schristos } 3310d522f475Smrg } 3311d522f475Smrg } 3312d522f475Smrg } 33132eaa94a1Schristos } else 33142eaa94a1Schristos#endif 33152eaa94a1Schristos { 33162eaa94a1Schristos TRACE(("...using bitmap areas\n")); 33172eaa94a1Schristos lookupFontSizes(xw); 33182eaa94a1Schristos if (relative != 0) { 33192eaa94a1Schristos for (n = 0; n < NMENUFONTS; ++n) { 33202eaa94a1Schristos if (screen->menu_font_sizes[n] > 0 && 33212eaa94a1Schristos screen->menu_font_sizes[n] != 33222eaa94a1Schristos screen->menu_font_sizes[old]) { 33232eaa94a1Schristos int cmp_0 = ((screen->menu_font_sizes[n] > 33242eaa94a1Schristos screen->menu_font_sizes[old]) 33252eaa94a1Schristos ? relative 33262eaa94a1Schristos : -relative); 33272eaa94a1Schristos int cmp_m = ((m < 0) 33282eaa94a1Schristos ? 1 33292eaa94a1Schristos : ((screen->menu_font_sizes[n] < 33302eaa94a1Schristos screen->menu_font_sizes[m]) 33312eaa94a1Schristos ? relative 33322eaa94a1Schristos : -relative)); 33332eaa94a1Schristos if (cmp_0 > 0 && cmp_m > 0) { 33342eaa94a1Schristos m = n; 33352eaa94a1Schristos } 33362eaa94a1Schristos } 33372eaa94a1Schristos } 3338d522f475Smrg } 3339d522f475Smrg } 33402eaa94a1Schristos TRACE(("...new index %d\n", m)); 33412eaa94a1Schristos if (m >= 0) { 33422eaa94a1Schristos if (relative > 1) 33432eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative - 1); 33442eaa94a1Schristos else if (relative < -1) 33452eaa94a1Schristos m = lookupRelativeFontSize(xw, m, relative + 1); 33462eaa94a1Schristos } 3347d522f475Smrg } 3348d522f475Smrg return m; 3349d522f475Smrg} 3350d522f475Smrg 3351d522f475Smrg/* ARGSUSED */ 3352d522f475Smrgvoid 3353d522f475SmrgHandleLargerFont(Widget w GCC_UNUSED, 33549a64e1c5Smrg XEvent *event GCC_UNUSED, 3355fa3f02f3Smrg String *params GCC_UNUSED, 3356d522f475Smrg Cardinal *param_count GCC_UNUSED) 3357d522f475Smrg{ 3358956cc18dSsnj XtermWidget xw; 3359d522f475Smrg 336020d2c4d2Smrg TRACE(("Handle larger-vt-font for %p\n", (void *) w)); 3361956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 3362d522f475Smrg if (xw->misc.shift_fonts) { 3363956cc18dSsnj TScreen *screen = TScreenOf(xw); 3364d522f475Smrg int m; 3365d522f475Smrg 3366d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, 1); 3367d522f475Smrg if (m >= 0) { 3368d522f475Smrg SetVTFont(xw, m, True, NULL); 3369d522f475Smrg } else { 337020d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3371d522f475Smrg } 3372d522f475Smrg } 3373d522f475Smrg } 3374d522f475Smrg} 3375d522f475Smrg 3376d522f475Smrg/* ARGSUSED */ 3377d522f475Smrgvoid 3378d522f475SmrgHandleSmallerFont(Widget w GCC_UNUSED, 33799a64e1c5Smrg XEvent *event GCC_UNUSED, 3380fa3f02f3Smrg String *params GCC_UNUSED, 3381d522f475Smrg Cardinal *param_count GCC_UNUSED) 3382d522f475Smrg{ 3383956cc18dSsnj XtermWidget xw; 3384d522f475Smrg 338520d2c4d2Smrg TRACE(("Handle smaller-vt-font for %p\n", (void *) w)); 3386956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 3387d522f475Smrg if (xw->misc.shift_fonts) { 3388956cc18dSsnj TScreen *screen = TScreenOf(xw); 3389d522f475Smrg int m; 3390d522f475Smrg 3391d522f475Smrg m = lookupRelativeFontSize(xw, screen->menu_font_number, -1); 3392d522f475Smrg if (m >= 0) { 3393d522f475Smrg SetVTFont(xw, m, True, NULL); 3394d522f475Smrg } else { 339520d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3396d522f475Smrg } 3397d522f475Smrg } 3398d522f475Smrg } 3399d522f475Smrg} 3400b6fea0ceSmrg#endif /* OPT_SHIFT_FONTS */ 3401d522f475Smrg 3402d522f475Smrgint 3403d522f475SmrgxtermGetFont(const char *param) 3404d522f475Smrg{ 3405d522f475Smrg int fontnum; 3406d522f475Smrg 3407d522f475Smrg switch (param[0]) { 3408d522f475Smrg case 'd': 3409d522f475Smrg case 'D': 3410d522f475Smrg case '0': 3411d522f475Smrg fontnum = fontMenu_default; 3412d522f475Smrg break; 3413d522f475Smrg case '1': 3414d522f475Smrg fontnum = fontMenu_font1; 3415d522f475Smrg break; 3416d522f475Smrg case '2': 3417d522f475Smrg fontnum = fontMenu_font2; 3418d522f475Smrg break; 3419d522f475Smrg case '3': 3420d522f475Smrg fontnum = fontMenu_font3; 3421d522f475Smrg break; 3422d522f475Smrg case '4': 3423d522f475Smrg fontnum = fontMenu_font4; 3424d522f475Smrg break; 3425d522f475Smrg case '5': 3426d522f475Smrg fontnum = fontMenu_font5; 3427d522f475Smrg break; 3428d522f475Smrg case '6': 3429d522f475Smrg fontnum = fontMenu_font6; 3430d522f475Smrg break; 3431d522f475Smrg case 'e': 3432d522f475Smrg case 'E': 3433d522f475Smrg fontnum = fontMenu_fontescape; 3434d522f475Smrg break; 3435d522f475Smrg case 's': 3436d522f475Smrg case 'S': 3437d522f475Smrg fontnum = fontMenu_fontsel; 3438d522f475Smrg break; 3439d522f475Smrg default: 3440d522f475Smrg fontnum = -1; 3441d522f475Smrg break; 3442d522f475Smrg } 3443d522f475Smrg return fontnum; 3444d522f475Smrg} 3445d522f475Smrg 3446d522f475Smrg/* ARGSUSED */ 3447d522f475Smrgvoid 3448d522f475SmrgHandleSetFont(Widget w GCC_UNUSED, 34499a64e1c5Smrg XEvent *event GCC_UNUSED, 3450fa3f02f3Smrg String *params, 3451d522f475Smrg Cardinal *param_count) 3452d522f475Smrg{ 3453956cc18dSsnj XtermWidget xw; 3454956cc18dSsnj 3455956cc18dSsnj if ((xw = getXtermWidget(w)) != 0) { 3456d522f475Smrg int fontnum; 3457d522f475Smrg VTFontNames fonts; 3458d522f475Smrg 3459d522f475Smrg memset(&fonts, 0, sizeof(fonts)); 3460d522f475Smrg 3461d522f475Smrg if (*param_count == 0) { 3462d522f475Smrg fontnum = fontMenu_default; 3463d522f475Smrg } else { 3464d522f475Smrg Cardinal maxparams = 1; /* total number of params allowed */ 3465d522f475Smrg int result = xtermGetFont(params[0]); 3466d522f475Smrg 3467d522f475Smrg switch (result) { 3468d522f475Smrg case fontMenu_default: /* FALLTHRU */ 3469d522f475Smrg case fontMenu_font1: /* FALLTHRU */ 3470d522f475Smrg case fontMenu_font2: /* FALLTHRU */ 3471d522f475Smrg case fontMenu_font3: /* FALLTHRU */ 3472d522f475Smrg case fontMenu_font4: /* FALLTHRU */ 3473d522f475Smrg case fontMenu_font5: /* FALLTHRU */ 3474d522f475Smrg case fontMenu_font6: /* FALLTHRU */ 3475d522f475Smrg break; 3476d522f475Smrg case fontMenu_fontescape: 3477d522f475Smrg#if OPT_WIDE_CHARS 3478d522f475Smrg maxparams = 5; 3479d522f475Smrg#else 3480d522f475Smrg maxparams = 3; 3481d522f475Smrg#endif 3482d522f475Smrg break; 3483d522f475Smrg case fontMenu_fontsel: 3484d522f475Smrg maxparams = 2; 3485d522f475Smrg break; 3486d522f475Smrg default: 348720d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3488d522f475Smrg return; 3489d522f475Smrg } 3490d522f475Smrg fontnum = result; 3491d522f475Smrg 3492d522f475Smrg if (*param_count > maxparams) { /* see if extra args given */ 349320d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3494d522f475Smrg return; 3495d522f475Smrg } 3496d522f475Smrg switch (*param_count) { /* assign 'em */ 3497d522f475Smrg#if OPT_WIDE_CHARS 3498d522f475Smrg case 5: 3499d522f475Smrg fonts.f_wb = params[4]; 3500d522f475Smrg /* FALLTHRU */ 3501d522f475Smrg case 4: 3502d522f475Smrg fonts.f_w = params[3]; 3503d522f475Smrg /* FALLTHRU */ 3504d522f475Smrg#endif 3505d522f475Smrg case 3: 3506d522f475Smrg fonts.f_b = params[2]; 3507d522f475Smrg /* FALLTHRU */ 3508d522f475Smrg case 2: 3509d522f475Smrg fonts.f_n = params[1]; 3510d522f475Smrg break; 3511d522f475Smrg } 3512d522f475Smrg } 3513d522f475Smrg 3514956cc18dSsnj SetVTFont(xw, fontnum, True, &fonts); 3515d522f475Smrg } 3516d522f475Smrg} 3517d522f475Smrg 3518d522f475Smrgvoid 3519d522f475SmrgSetVTFont(XtermWidget xw, 3520d522f475Smrg int which, 3521d522f475Smrg Bool doresize, 3522d522f475Smrg const VTFontNames * fonts) 3523d522f475Smrg{ 3524956cc18dSsnj TScreen *screen = TScreenOf(xw); 3525d522f475Smrg 3526d522f475Smrg TRACE(("SetVTFont(which=%d, f_n=%s, f_b=%s)\n", which, 3527d522f475Smrg (fonts && fonts->f_n) ? fonts->f_n : "<null>", 3528d522f475Smrg (fonts && fonts->f_b) ? fonts->f_b : "<null>")); 3529d522f475Smrg 3530d522f475Smrg if (IsIcon(screen)) { 353120d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3532d522f475Smrg } else if (which >= 0 && which < NMENUFONTS) { 3533d522f475Smrg VTFontNames myfonts; 3534d522f475Smrg 3535d522f475Smrg memset(&myfonts, 0, sizeof(myfonts)); 3536d522f475Smrg if (fonts != 0) 3537d522f475Smrg myfonts = *fonts; 3538d522f475Smrg 3539d522f475Smrg if (which == fontMenu_fontsel) { /* go get the selection */ 3540d522f475Smrg FindFontSelection(xw, myfonts.f_n, False); 3541d522f475Smrg } else { 3542d522f475Smrg int oldFont = screen->menu_font_number; 3543d522f475Smrg 3544d522f475Smrg#define USE_CACHED(field, name) \ 3545d522f475Smrg if (myfonts.field == 0) { \ 3546492d43a5Smrg myfonts.field = x_strdup(screen->menu_font_names[which][name]); \ 3547d522f475Smrg TRACE(("set myfonts." #field " from menu_font_names[%d][" #name "] %s\n", \ 3548d522f475Smrg which, NonNull(myfonts.field))); \ 3549d522f475Smrg } else { \ 3550d522f475Smrg TRACE(("set myfonts." #field " reused\n")); \ 3551d522f475Smrg } 355220d2c4d2Smrg#define SAVE_FNAME(field, name) \ 355320d2c4d2Smrg if (myfonts.field != 0) { \ 355420d2c4d2Smrg if (screen->menu_font_names[which][name] == 0 \ 355520d2c4d2Smrg || strcmp(screen->menu_font_names[which][name], myfonts.field)) { \ 355620d2c4d2Smrg TRACE(("updating menu_font_names[%d][" #name "] to %s\n", \ 355720d2c4d2Smrg which, myfonts.field)); \ 35589a64e1c5Smrg FREE_STRING(screen->menu_font_names[which][name]); \ 355920d2c4d2Smrg screen->menu_font_names[which][name] = x_strdup(myfonts.field); \ 356020d2c4d2Smrg } \ 356120d2c4d2Smrg } 356220d2c4d2Smrg 3563d522f475Smrg USE_CACHED(f_n, fNorm); 3564d522f475Smrg USE_CACHED(f_b, fBold); 3565d522f475Smrg#if OPT_WIDE_CHARS 3566d522f475Smrg USE_CACHED(f_w, fWide); 3567d522f475Smrg USE_CACHED(f_wb, fWBold); 3568d522f475Smrg#endif 3569d522f475Smrg if (xtermLoadFont(xw, 3570d522f475Smrg &myfonts, 3571d522f475Smrg doresize, which)) { 357220d2c4d2Smrg /* 357320d2c4d2Smrg * If successful, save the data so that a subsequent query via 357420d2c4d2Smrg * OSC-50 will return the expected values. 357520d2c4d2Smrg */ 357620d2c4d2Smrg SAVE_FNAME(f_n, fNorm); 357720d2c4d2Smrg SAVE_FNAME(f_b, fBold); 357820d2c4d2Smrg#if OPT_WIDE_CHARS 357920d2c4d2Smrg SAVE_FNAME(f_w, fWide); 358020d2c4d2Smrg SAVE_FNAME(f_wb, fWBold); 358120d2c4d2Smrg#endif 3582d522f475Smrg } else { 3583d522f475Smrg xtermLoadFont(xw, 3584d522f475Smrg xtermFontName(screen->MenuFontName(oldFont)), 3585d522f475Smrg doresize, oldFont); 358620d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3587d522f475Smrg } 35889a64e1c5Smrg FREE_FNAME(f_n); 35899a64e1c5Smrg FREE_FNAME(f_b); 35909a64e1c5Smrg#if OPT_WIDE_CHARS 35919a64e1c5Smrg FREE_FNAME(f_w); 35929a64e1c5Smrg FREE_FNAME(f_wb); 35939a64e1c5Smrg#endif 3594d522f475Smrg } 359520d2c4d2Smrg } else { 359620d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 3597d522f475Smrg } 3598d522f475Smrg return; 3599d522f475Smrg} 3600