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