|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: fl_set_fonts_x.cxx 8037 2010-12-15 13:54:34Z manolo $" 00003 // 00004 // X11 font utilities for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 1998-2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems on the following page: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 00028 // This function fills in the fltk font table with all the fonts that 00029 // are found on the X server. It tries to place the fonts into families 00030 // and to sort them so the first 4 in a family are normal, bold, italic, 00031 // and bold italic. 00032 00033 // Standard X fonts are matched by a pattern that is always of 00034 // this form, and this pattern is put in the table: 00035 // "-*-family-weight-slant-width1-style-*-registry-encoding" 00036 00037 // Non-standard font names (those not starting with '-') are matched 00038 // by a pattern of the form "prefix*suffix", where the '*' is where 00039 // fltk thinks the point size is, or by the actual font name if no 00040 // point size is found. 00041 00042 // Fltk knows how to pull an "attribute" out of a font name, such as 00043 // bold or italic, by matching known x font field values. All words 00044 // that don't match a known attribute are combined into the "name" 00045 // of the font. Names are compared before attributes for sorting, this 00046 // makes the bold and plain version of a font come out next to each 00047 // other despite the poor X font naming scheme. 00048 00049 // By default fl_set_fonts() only does iso8859-1 encoded fonts. You can 00050 // do all normal X fonts by passing "-*" or every possible font with "*". 00051 00052 // Fl::set_font will take strings other than the ones this stores 00053 // and can identify any font on X that way. You may want to write your 00054 // own system of font management and not use this code. 00055 00056 // turn word N of a X font name into either some attribute bits 00057 // (right now 0, FL_BOLD, or FL_ITALIC), or into -1 indicating that 00058 // the word should be put into the name: 00059 00060 static int attribute(int n, const char *p) { 00061 // don't put blank things into name: 00062 if (!*p || *p=='-' || *p=='*') return 0; 00063 if (n == 3) { // weight 00064 if (!strncmp(p,"normal",6) || 00065 !strncmp(p,"light",5) || 00066 !strncmp(p,"medium",6) || 00067 !strncmp(p,"book",4)) return 0; 00068 if (!strncmp(p,"bold",4) || !strncmp(p,"demi",4)) return FL_BOLD; 00069 } else if (n == 4) { // slant 00070 if (*p == 'r') return 0; 00071 if (*p == 'i' || *p == 'o') return FL_ITALIC; 00072 } else if (n == 5) { // sWidth 00073 if (!strncmp(p,"normal",6)) return 0; 00074 } 00075 return -1; 00076 } 00077 00078 // return non-zero if the registry-encoding should be used: 00079 extern const char* fl_encoding; 00080 static int use_registry(const char *p) { 00081 return *p && *p!='*' && strcmp(p,fl_encoding); 00082 } 00083 00084 // Bug: older versions calculated the value for *ap as a side effect of 00085 // making the name, and then forgot about it. To avoid having to change 00086 // the header files I decided to store this value in the last character 00087 // of the font name array. 00088 #define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 00089 00090 // turn a stored (with *'s) X font name into a pretty name: 00091 const char* Fl::get_font_name(Fl_Font fnum, int* ap) { 00092 Fl_Fontdesc *f = fl_fonts + fnum; 00093 if (!f->fontname[0]) { 00094 int type = 0; 00095 const char* p = f->name; 00096 if (!p) { 00097 if (ap) *ap = 0; 00098 return ""; 00099 } 00100 char *o = f->fontname; 00101 00102 if (*p != '-') { // non-standard font, just replace * with spaces: 00103 if (strstr(p,"bold")) type = FL_BOLD; 00104 if (strstr(p,"ital")) type |= FL_ITALIC; 00105 for (;*p; p++) { 00106 if (*p == '*' || *p == ' ' || *p == '-') { 00107 do p++; while (*p == '*' || *p == ' ' || *p == '-'); 00108 if (!*p) break; 00109 if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = ' '; 00110 } 00111 if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = *p; 00112 } 00113 *o = 0; 00114 00115 } else { // standard dash-separated font: 00116 00117 // get the family: 00118 const char *x = fl_font_word(p,2); if (*x) x++; if (*x=='*') x++; 00119 if (!*x) { 00120 if (ap) *ap = 0; 00121 return p; 00122 } 00123 const char *e = fl_font_word(x,1); 00124 if ((e - x) < (int)(ENDOFBUFFER - 1)) { 00125 // MRS: we want strncpy here, not strlcpy... 00126 strncpy(o,x,e-x); 00127 o += e-x; 00128 } else { 00129 strlcpy(f->fontname, x, ENDOFBUFFER); 00130 o = f->fontname+ENDOFBUFFER-1; 00131 } 00132 00133 // collect all the attribute words: 00134 for (int n = 3; n <= 6; n++) { 00135 // get the next word: 00136 if (*e) e++; x = e; e = fl_font_word(x,1); 00137 int t = attribute(n,x); 00138 if (t < 0) { 00139 if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = ' '; 00140 if ((e - x) < (int)(ENDOFBUFFER - (o - f->fontname) - 1)) { 00141 // MRS: we want strncpy here, not strlcpy... 00142 strncpy(o,x,e-x); 00143 o += e-x; 00144 } else { 00145 strlcpy(o,x, ENDOFBUFFER - (o - f->fontname) - 1); 00146 o = f->fontname+ENDOFBUFFER-1; 00147 } 00148 } else type |= t; 00149 } 00150 00151 // skip over the '*' for the size and get the registry-encoding: 00152 x = fl_font_word(e,2); 00153 if (*x) {x++; *o++ = '('; while (*x) *o++ = *x++; *o++ = ')';} 00154 00155 *o = 0; 00156 if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); 00157 if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); 00158 } 00159 f->fontname[ENDOFBUFFER] = (char)type; 00160 } 00161 if (ap) *ap = f->fontname[ENDOFBUFFER]; 00162 return f->fontname; 00163 } 00164 00165 extern "C" { 00166 // sort raw (non-'*') X font names into perfect order: 00167 00168 static int ultrasort(const void *aa, const void *bb) { 00169 const char *a = *(char **)aa; 00170 const char *b = *(char **)bb; 00171 00172 // sort all non x-fonts at the end: 00173 if (*a != '-') { 00174 if (*b == '-') return 1; 00175 // 2 non-x fonts are matched by "numeric sort" 00176 int ret = 0; 00177 for (;;) { 00178 if (isdigit(*a) && isdigit(*b)) { 00179 int na = strtol(a, (char **)&a, 10); 00180 int nb = strtol(b, (char **)&b, 10); 00181 if (!ret) ret = na-nb; 00182 } else if (*a != *b) { 00183 return (*a-*b); 00184 } else if (!*a) { 00185 return ret; 00186 } else { 00187 a++; b++; 00188 } 00189 } 00190 } else { 00191 if (*b != '-') return -1; 00192 } 00193 00194 // skip the foundry (assume equal): 00195 for (a++; *a && *a++!='-';); 00196 for (b++; *b && *b++!='-';); 00197 00198 // compare the family and all the attribute words: 00199 int atype = 0; 00200 int btype = 0; 00201 for (int n = 2; n <= 6; n++) { 00202 int at = attribute(n,a); 00203 int bt = attribute(n,b); 00204 if (at < 0) { 00205 if (bt >= 0) return 1; 00206 for (;;) {if (*a!=*b) return *a-*b; b++; if (!*a || *a++=='-') break;} 00207 } else { 00208 if (bt < 0) return -1; 00209 a = fl_font_word(a,1); if (*a) a++; 00210 b = fl_font_word(b,1); if (*b) b++; 00211 atype |= at; btype |= bt; 00212 } 00213 } 00214 00215 // remember the pixel size: 00216 int asize = atoi(a); 00217 int bsize = atoi(b); 00218 00219 // compare the registry/encoding: 00220 a = fl_font_word(a,6); if (*a) a++; 00221 b = fl_font_word(b,6); if (*b) b++; 00222 if (use_registry(a)) { 00223 if (!use_registry(b)) return 1; 00224 int r = strcmp(a,b); if (r) return r; 00225 } else { 00226 if (use_registry(b)) return -1; 00227 } 00228 00229 if (atype != btype) return atype-btype; 00230 if (asize != bsize) return asize-bsize; 00231 00232 // something wrong, just do a string compare... 00233 return strcmp(*(char**)aa, *(char**)bb); 00234 } 00235 } 00236 00237 // converts a X font name to a standard starname, returns point size: 00238 static int to_canonical(char *to, const char *from, size_t tolen) { 00239 char* c = fl_find_fontsize((char*)from); 00240 if (!c) return -1; // no point size found... 00241 const char* endptr; 00242 int size = strtol(c,(char**)&endptr,10); 00243 if (from[0] == '-') { 00244 // replace the "foundry" with -*-: 00245 *to++ = '-'; *to++ = '*'; 00246 for (from++; *from && *from != '-'; from++); 00247 // skip to the registry-encoding: 00248 endptr = (char*)fl_font_word(endptr,6); 00249 if (*endptr && !use_registry(endptr+1)) endptr = ""; 00250 } 00251 int n = c-from; 00252 // MRS: we want strncpy here, not strlcpy... 00253 if (n > (int)(tolen - 1)) return -1; 00254 strncpy(to,from,n); 00255 to[n++] = '*'; 00256 strlcpy(to+n,endptr, tolen - n); 00257 return size; 00258 } 00259 00260 static unsigned int fl_free_font = FL_FREE_FONT; 00261 00262 Fl_Font Fl::set_fonts(const char* xstarname) { 00263 if (fl_free_font > (unsigned)FL_FREE_FONT) // already been here 00264 return (Fl_Font)fl_free_font; 00265 fl_open_display(); 00266 int xlistsize; 00267 char buf[20]; 00268 if (!xstarname) { 00269 strcpy(buf,"-*-"); strcpy(buf+3,fl_encoding); 00270 xstarname = buf; 00271 } 00272 char **xlist = XListFonts(fl_display, xstarname, 10000, &xlistsize); 00273 if (!xlist) return (Fl_Font)fl_free_font; 00274 qsort(xlist, xlistsize, sizeof(*xlist), ultrasort); 00275 int used_xlist = 0; 00276 for (int i=0; i<xlistsize;) { 00277 int first_xlist = i; 00278 const char *p = xlist[i++]; 00279 char canon[1024]; 00280 int size = to_canonical(canon, p, sizeof(canon)); 00281 if (size >= 0) { 00282 for (;;) { // find all matching fonts: 00283 if (i >= xlistsize) break; 00284 const char *q = xlist[i]; 00285 char this_canon[1024]; 00286 if (to_canonical(this_canon, q, sizeof(this_canon)) < 0) break; 00287 if (strcmp(canon, this_canon)) break; 00288 i++; 00289 } 00290 /*if (*p=='-' || i > first_xlist+1)*/ p = canon; 00291 } 00292 unsigned int j; 00293 for (j = 0;; j++) { 00294 /*if (j < FL_FREE_FONT) { 00295 // see if it is one of our built-in fonts: 00296 // if so, set the list of x fonts, since we have it anyway 00297 if (fl_fonts[j].name && !strcmp(fl_fonts[j].name, p)) break; 00298 } else */{ 00299 j = fl_free_font++; 00300 if (p == canon) p = strdup(p); else used_xlist = 1; 00301 Fl::set_font((Fl_Font)j, p); 00302 break; 00303 } 00304 } 00305 if (!fl_fonts[j].xlist) { 00306 fl_fonts[j].xlist = xlist+first_xlist; 00307 fl_fonts[j].n = -(i-first_xlist); 00308 used_xlist = 1; 00309 } 00310 } 00311 if (!used_xlist) XFreeFontNames(xlist); 00312 return (Fl_Font)fl_free_font; 00313 } 00314 00315 int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { 00316 Fl_Fontdesc *s = fl_fonts+fnum; 00317 if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 00318 if (!s->xlist) { 00319 fl_open_display(); 00320 s->xlist = XListFonts(fl_display, s->name, 100, &(s->n)); 00321 if (!s->xlist) return 0; 00322 } 00323 int listsize = s->n; if (listsize<0) listsize = -listsize; 00324 static int sizes[128]; 00325 int numsizes = 0; 00326 for (int i = 0; i < listsize; i++) { 00327 char *q = s->xlist[i]; 00328 char *d = fl_find_fontsize(q); 00329 if (!d) continue; 00330 int s = strtol(d,0,10); 00331 if (!numsizes || sizes[numsizes-1] < s) { 00332 sizes[numsizes++] = s; 00333 } else { 00334 // insert-sort the new size into list: 00335 int n; 00336 for (n = numsizes-1; n > 0; n--) if (sizes[n-1] < s) break; 00337 if (sizes[n] != s) { 00338 for (int m = numsizes; m > n; m--) sizes[m] = sizes[m-1]; 00339 sizes[n] = s; 00340 numsizes++; 00341 } 00342 } 00343 } 00344 sizep = sizes; 00345 return numsizes; 00346 } 00347 00348 // 00349 // End of "$Id: fl_set_fonts_x.cxx 8037 2010-12-15 13:54:34Z manolo $". 00350 //