fslsfonts.c revision 4f9ac78a
1/* 2 3Copyright 1990, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25 * Copyright 1990 Network Computing Devices; 26 * Portions Copyright 1987 by Digital Equipment Corporation 27 * 28 * Permission to use, copy, modify, distribute, and sell this software and 29 * its documentation for any purpose is hereby granted without fee, provided 30 * that the above copyright notice appear in all copies and that both that 31 * copyright notice and this permission notice appear in supporting 32 * documentation, and that the names of Network Computing Devices, or Digital 33 * not be used in advertising or publicity pertaining to distribution 34 * of the software without specific, written prior permission. 35 * 36 * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH 37 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 38 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, 39 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 40 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 41 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 42 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 43 * THIS SOFTWARE. 44 */ 45 46#include <X11/fonts/FSlib.h> 47#include <stdio.h> 48#include <X11/Xos.h> 49#include <stdlib.h> 50 51#ifndef N_START 52#define N_START 1000 /* Maximum # of fonts to start with */ 53#endif 54 55static int max_output_line_width = 79; 56static int output_line_padding = 3; 57static int columns = 0; 58 59#define L_SHORT 0 60#define L_MEDIUM 1 61#define L_LONG 2 62#define L_VERYLONG 3 63 64static Bool sort_output = True; 65static int long_list = L_SHORT; 66static int nnames = N_START; 67static int font_cnt; 68static int min_max; 69typedef struct { 70 char *name; 71 FSXFontInfoHeader *info; 72 FSPropInfo *pi; 73 FSPropOffset *po; 74 unsigned char *pd; 75} FontList; 76static FontList *font_list; 77 78static FSServer *svr; 79 80static char *program_name; 81 82static void usage ( void ); 83static void get_list ( char *pattern ); 84static int compare ( const void *f1, const void *f2 ); 85static void show_fonts ( void ); 86static void print_font_header ( void ); 87static void show_font_header ( FontList *list ); 88static void copy_number ( char **pp1, char **pp2, int n1, int n2 ); 89static void show_font_props ( FontList *list ); 90 91static void 92usage(void) 93{ 94 fprintf(stderr, "usage: %s [-options] [-fn pattern]\n", program_name); 95 fprintf(stderr, "where options include:\n"); 96 97 fprintf(stderr, 98 " -l[l[l]] give long info about each font\n"); 99 fprintf(stderr, 100 " -m give character min and max bounds\n"); 101 102 fprintf(stderr, 103 " -C force columns\n"); 104 fprintf(stderr, 105 " -1 force single column\n"); 106 fprintf(stderr, 107 " -u keep output unsorted\n"); 108 fprintf(stderr, 109 " -w width maximum width for multiple columns\n"); 110 fprintf(stderr, 111 " -n columns number of columns if multi column\n"); 112 fprintf(stderr, 113 " -server servername font server to contact\n"); 114 fprintf(stderr, 115 "\n"); 116 exit(1); 117} 118 119int 120main(int argc, char *argv[]) 121{ 122 int argcnt = 0, 123 i; 124 char *servername = NULL; 125 126 program_name = argv[0]; 127 128 for (i = 1; i < argc; i++) { 129 if (strncmp(argv[i], "-s", 2) == 0) { 130 if (++i >= argc) 131 usage(); 132 servername = argv[i]; 133 } 134 } 135 136 if ((svr = FSOpenServer(servername)) == NULL) { 137 if (FSServerName(servername) == NULL) { 138 fprintf(stderr, "%s: no font server defined\n", program_name); 139 exit(0); 140 } 141 fprintf(stderr, "%s: unable to open server \"%s\"\n", 142 program_name, FSServerName(servername)); 143 exit(0); 144 } 145 /* Handle command line arguments, open display */ 146 for (argv++, argc--; argc; argv++, argc--) { 147 if (argv[0][0] == '-') { 148 if (argcnt > 0) 149 usage(); 150 for (i = 1; argv[0][i]; i++) 151 switch (argv[0][i]) { 152 case 'l': 153 long_list++; 154 break; 155 case 'm': 156 min_max++; 157 break; 158 case 'C': 159 columns = 0; 160 break; 161 case '1': 162 columns = 1; 163 break; 164 case 'f': 165 if (--argc <= 0) 166 usage(); 167 argcnt++; 168 argv++; 169 get_list(argv[0]); 170 goto next; 171 case 'w': 172 if (--argc <= 0) 173 usage(); 174 argv++; 175 max_output_line_width = atoi(argv[0]); 176 goto next; 177 case 'n': 178 if (--argc <= 0) 179 usage(); 180 argv++; 181 columns = atoi(argv[0]); 182 goto next; 183 case 'u': 184 sort_output = False; 185 break; 186 case 's': /* eat -s */ 187 if (--argc <= 0) 188 usage(); 189 argv++; 190 goto next; 191 default: 192 usage(); 193 break; 194 } 195 if (i == 1) 196 usage(); 197 } else { 198 argcnt++; 199 get_list(argv[0]); 200 } 201next: ; 202 } 203 if (argcnt == 0) 204 get_list("*"); 205 FSCloseServer(svr); 206 show_fonts(); 207 exit(0); 208} 209 210static void 211get_list(char *pattern) 212{ 213 int available = nnames + 1, 214 i; 215 char **fonts; 216 FSXFontInfoHeader **info; 217 FSPropInfo **props; 218 FSPropOffset **offsets; 219 unsigned char **pdata; 220 221 /* Get list of fonts matching pattern */ 222 for (;;) { 223 224 if (long_list >= L_MEDIUM) 225 fonts = FSListFontsWithXInfo(svr, 226 pattern, nnames, &available, &info, &props, &offsets, &pdata); 227 else 228 fonts = FSListFonts(svr, pattern, nnames, &available); 229 if (fonts == NULL || available < nnames) 230 break; 231 232 if (long_list >= L_MEDIUM) { 233 for (i = 0; i < available; i++) { 234 FSFree((char *) fonts[i]); 235 FSFree((char *) info[i]); 236 FSFree((char *) props[i]); 237 FSFree((char *) offsets[i]); 238 FSFree((char *) pdata[i]); 239 } 240 FSFree((char *) fonts); 241 FSFree((char *) info); 242 FSFree((char *) props); 243 FSFree((char *) offsets); 244 FSFree((char *) pdata); 245 } else { 246 FSFreeFontNames(fonts); 247 } 248 nnames = available * 2; 249 } 250 251 if (fonts == NULL) { 252 fprintf(stderr, "%s: pattern \"%s\" unmatched\n", 253 program_name, pattern); 254 return; 255 } 256 if (font_list) 257 font_list = (FontList *) realloc(font_list, 258 (font_cnt + available) * sizeof(FontList)); 259 else 260 font_list = (FontList *) malloc((unsigned) 261 (font_cnt + available) * sizeof(FontList)); 262 for (i = 0; i < available; i++) { 263 font_list[font_cnt].name = fonts[i]; 264 265 if (long_list >= L_MEDIUM) { 266 font_list[font_cnt].info = info[i]; 267 font_list[font_cnt].pi = props[i]; 268 font_list[font_cnt].po = offsets[i]; 269 font_list[font_cnt].pd = pdata[i]; 270 } else 271 font_list[font_cnt].info = NULL; 272 font_cnt++; 273 } 274} 275 276static int 277compare(const void *f1, const void *f2) 278{ 279 char *p1 = ((FontList *)f1)->name, 280 *p2 = ((FontList *)f2)->name; 281 282 while (*p1 && *p2 && *p1 == *p2) 283 p1++, p2++; 284 return (*p1 - *p2); 285} 286 287static void 288show_fonts(void) 289{ 290 int i; 291 292 if (font_cnt == 0) 293 return; 294 295 /* first sort the output */ 296 if (sort_output) 297 qsort(font_list, font_cnt, sizeof(FontList), compare); 298 299 if (long_list > L_MEDIUM) { 300 print_font_header(); 301 for (i = 0; i < font_cnt; i++) { 302 show_font_header(&font_list[i]); 303 show_font_props(&font_list[i]); 304 } 305 return; 306 } 307 if (long_list == L_MEDIUM) { 308 print_font_header(); 309 310 for (i = 0; i < font_cnt; i++) { 311 show_font_header(&font_list[i]); 312 } 313 314 return; 315 } 316 if ((columns == 0 && isatty(1)) || columns > 1) { 317 int width, 318 max_width = 0, 319 lines_per_column, 320 j, 321 index; 322 323 for (i = 0; i < font_cnt; i++) { 324 width = strlen(font_list[i].name); 325 if (width > max_width) 326 max_width = width; 327 } 328 if (max_width == 0) { 329 fprintf(stderr, "all %d fontnames listed are zero length", 330 font_cnt); 331 exit(-1); 332 } 333 if (columns == 0) { 334 if ((max_width * 2) + output_line_padding > 335 max_output_line_width) { 336 columns = 1; 337 } else { 338 max_width += output_line_padding; 339 columns = ((max_output_line_width + 340 output_line_padding) / max_width); 341 } 342 } else { 343 max_width += output_line_padding; 344 } 345 if (columns <= 1) 346 goto single_column; 347 348 if (font_cnt < columns) 349 columns = font_cnt; 350 lines_per_column = (font_cnt + columns - 1) / columns; 351 352 for (i = 0; i < lines_per_column; i++) { 353 for (j = 0; j < columns; j++) { 354 index = j * lines_per_column + i; 355 if (index >= font_cnt) 356 break; 357 if (j + 1 == columns) 358 printf("%s", font_list[index].name); 359 else 360 printf("%-*s", 361 max_width, 362 font_list[index].name); 363 } 364 printf("\n"); 365 } 366 return; 367 } 368single_column: 369 for (i = 0; i < font_cnt; i++) 370 printf("%s\n", font_list[i].name); 371} 372 373static void 374print_font_header(void) 375{ 376 printf("DIR "); 377 printf("MIN "); 378 printf("MAX "); 379 printf("EXIST "); 380 printf("DFLT "); 381 printf("ASC "); 382 printf("DESC "); 383 printf("NAME"); 384 printf("\n"); 385} 386 387static void 388show_font_header(FontList *list) 389{ 390 char *string; 391 FSXFontInfoHeader *pfh; 392 393 pfh = list->info; 394 if (!pfh) { 395 fprintf(stderr, 396 "%s: no font information for font \"%s\".\n", 397 program_name, list->name ? list->name : ""); 398 return; 399 } 400 if (pfh->draw_direction == LeftToRightDrawDirection) 401 string = "-->"; 402 else 403 string = "<--"; 404 printf("%-4s", string); 405 if (pfh->char_range.min_char.high == 0 406 && pfh->char_range.max_char.high == 0) { 407 printf(" %3d ", pfh->char_range.min_char.low); 408 printf(" %3d ", pfh->char_range.max_char.low); 409 } else { 410 printf("*%3d ", pfh->char_range.min_char.high); 411 printf("*%3d ", pfh->char_range.max_char.high); 412 } 413 printf("%5s ", (pfh->flags & FontInfoAllCharsExist) ? "all" : "some"); 414 printf("%4d ", (pfh->default_char.high << 8) + pfh->default_char.low); 415 printf("%3d ", pfh->font_ascent); 416 printf("%4d ", pfh->font_descent); 417 printf("%s\n", list->name); 418 if (min_max) { 419 char min[BUFSIZ], 420 max[BUFSIZ]; 421 char *pmax = max, 422 *pmin = min; 423 424 strcpy(pmin, " min(l,r,w,a,d) = ("); 425 strcpy(pmax, " max(l,r,w,a,d) = ("); 426 pmin += strlen(pmin); 427 pmax += strlen(pmax); 428 429 copy_number(&pmin, &pmax, 430 pfh->min_bounds.left, 431 pfh->max_bounds.left); 432 *pmin++ = *pmax++ = ','; 433 copy_number(&pmin, &pmax, 434 pfh->min_bounds.right, 435 pfh->max_bounds.right); 436 *pmin++ = *pmax++ = ','; 437 copy_number(&pmin, &pmax, 438 pfh->min_bounds.width, 439 pfh->max_bounds.width); 440 *pmin++ = *pmax++ = ','; 441 copy_number(&pmin, &pmax, 442 pfh->min_bounds.ascent, 443 pfh->max_bounds.ascent); 444 *pmin++ = *pmax++ = ','; 445 copy_number(&pmin, &pmax, 446 pfh->min_bounds.descent, 447 pfh->max_bounds.descent); 448 *pmin++ = *pmax++ = ')'; 449 *pmin = *pmax = '\0'; 450 printf("%s\n", min); 451 printf("%s\n", max); 452 } 453} 454 455#ifndef max 456#define max(a, b) ((a) > (b) ? (a) : (b)) 457#endif 458 459static void 460copy_number(char **pp1, char **pp2, int n1, int n2) 461{ 462 char *p1 = *pp1; 463 char *p2 = *pp2; 464 int w; 465 466 sprintf(p1, "%d", n1); 467 sprintf(p2, "%d", n2); 468 w = max(strlen(p1), strlen(p2)); 469 sprintf(p1, "%*d", w, n1); 470 sprintf(p2, "%*d", w, n2); 471 p1 += strlen(p1); 472 p2 += strlen(p2); 473 *pp1 = p1; 474 *pp2 = p2; 475} 476 477static void 478show_font_props(FontList *list) 479{ 480 int i; 481 char buf[1000]; 482 FSPropInfo *pi = list->pi; 483 FSPropOffset *po = list->po; 484 unsigned char *pd = list->pd; 485 int num_props; 486 487 num_props = pi->num_offsets; 488 for (i = 0; i < num_props; i++, po++) { 489 strncpy(buf, (char *) (pd + po->name.position), po->name.length); 490 buf[po->name.length] = '\0'; 491 printf("%s\t", buf); 492 switch (po->type) { 493 case PropTypeString: 494 strncpy(buf, (char *)pd + po->value.position, po->value.length); 495 buf[po->value.length] = '\0'; 496 printf("%s\n", buf); 497 break; 498 case PropTypeUnsigned: 499 printf("%lu\n", (unsigned long) po->value.position); 500 break; 501 case PropTypeSigned: 502 printf("%lu\n", (long) po->value.position); 503 break; 504 default: 505 fprintf(stderr, "bogus property\n"); 506 break; 507 } 508 509 } 510} 511