|
|
1.1 ! root 1: /* Copyright 1987, Massachusetts Institute of Technology */ ! 2: ! 3: /* ! 4: * xfd: program to display a font for perusal by the user. ! 5: * ! 6: * Written by Mark Lillibridge ! 7: * ! 8: */ ! 9: ! 10: #include <X11/Xlib.h> ! 11: #include <X11/Xutil.h> ! 12: #include <X11/Xatom.h> ! 13: #include <stdio.h> ! 14: ! 15: #define BUFFERSIZE 10 ! 16: #define VERBOSE_LINES 4 /* Number of lines in verbose display */ ! 17: ! 18: ! 19: /* Global variables */ ! 20: ! 21: int space_per_line; /* How much space to reserve per line */ ! 22: int line_offset; /* Where to start writting (base line) */ ! 23: int number_of_lines=1; /* number of lines in bottom area display */ ! 24: int verbose = 0; /* verbose mode? */ ! 25: int box_x = 0; /* The size of one box in grid */ ! 26: int box_y = 0; ! 27: int x_offset = 0; /* Point in box to display character from */ ! 28: int y_offset = 0; ! 29: int x_boxes = 0; /* Current size of window in # of boxes */ ! 30: int y_boxes = 0; ! 31: int bottom = 0; /* Size of grid in pixels */ ! 32: int right = 0; ! 33: int first_char = 0; /* Character # of first character displayed on ! 34: the grid */ ! 35: GC body_gc, real_gc; /* Graphics contexts */ ! 36: XFontStruct *real_font; /* The font we are to display */ ! 37: ! 38: /* Gray pattern for use as background */ ! 39: #include "X11/bitmaps/light_gray" ! 40: ! 41: /* Include routines to handle parsing defaults */ ! 42: #define TITLE_DEFAULT "xfd" /* Our name... */ ! 43: #define DEFX_DEFAULT 300 /* Default window pop-up location */ ! 44: #define DEFY_DEFAULT 300 ! 45: #define RESIZE_X_INC 1 /* We will specify a resize inc later ... */ ! 46: #define RESIZE_Y_INC 1 ! 47: #define MIN_X_SIZE 1 /* Ditto for minimum window size */ ! 48: #define MIN_Y_SIZE 1 ! 49: ! 50: #include "wsimple.h" ! 51: ! 52: /* ! 53: * usage: routine to show usage then exit. ! 54: */ ! 55: usage() ! 56: { ! 57: fprintf(stderr, "%s: usage: %s %s [-v[erbose]] [-gray] [-start <char number>] fontname\n", program_name, ! 58: program_name, X_USAGE); ! 59: exit(1); ! 60: } ! 61: ! 62: ! 63: /* ! 64: * The main program: ! 65: */ ! 66: main(argc, argv) ! 67: ! 68: int argc; ! 69: char **argv; ! 70: { ! 71: register int i; ! 72: GC gc; ! 73: XGCValues gc_init; ! 74: XEvent event; ! 75: char *fontname = BODY_FONT_DEFAULT; /* Display default body font */ ! 76: int gray = 0; /* use gray background ? */ ! 77: char buffer[BUFFERSIZE]; /* buffer for XLookupString */ ! 78: ! 79: INIT_NAME; ! 80: ! 81: /* Handle command line arguments, open the display */ ! 82: Get_X_Options(&argc, argv); ! 83: for (i = 1; i < argc; i++) { ! 84: if (!strcmp("-", argv[i])) ! 85: continue; ! 86: if (!strcmp("-gray", argv[i])) { ! 87: gray = 1; ! 88: continue; ! 89: } ! 90: if (!strcmp("-start", argv[i])) { ! 91: if (++i >= argc) usage(); ! 92: first_char = atoi(argv[i]); ! 93: continue; ! 94: } ! 95: if (!strcmp("-verbose", argv[i]) || !strcmp("-v", argv[i])) { ! 96: verbose = 1; ! 97: number_of_lines = VERBOSE_LINES; ! 98: continue; ! 99: } ! 100: if (argv[i][0] == '-') ! 101: usage(); ! 102: fontname = argv[i]; ! 103: } ! 104: ! 105: /* Load in the font to display */ ! 106: real_font = Open_Font(fontname); ! 107: ! 108: /* Resolve the X options */ ! 109: Resolve_X_Options(); ! 110: ! 111: line_offset = 2 + body_font->ascent; ! 112: space_per_line = body_font->descent + line_offset + 2; ! 113: ! 114: /* Get minimun perfered size */ ! 115: Calc_Default_Size(); ! 116: ! 117: /* Create the window */ ! 118: Create_Default_Window(); ! 119: if (gray) ! 120: SetBackgroundToBitmap(XCreateBitmapFromData(dpy, ! 121: wind, ! 122: light_gray_bits, ! 123: light_gray_width, ! 124: light_gray_height), ! 125: light_gray_width, light_gray_height); ! 126: ! 127: /* Setup graphics contexts */ ! 128: body_gc = Get_Default_GC(); /* This one has body font */ ! 129: real_gc = Get_Default_GC(); /* This one has font to display */ ! 130: ! 131: gc_init.font = real_font->fid; ! 132: XChangeGC(dpy, real_gc, GCFont, &gc_init); ! 133: ! 134: /* Start main loop by selecting events then mapping window */ ! 135: XSelectInput(dpy, wind, ButtonPressMask|ExposureMask|KeyPressMask); ! 136: XMapWindow(dpy, wind); ! 137: ! 138: /* Main event loop */ ! 139: for (;;) { ! 140: XNextEvent(dpy, &event); ! 141: if (event.type == ButtonPress) { ! 142: if (event.xbutton.button == 1) ! 143: Go_Back(); ! 144: else if (event.xbutton.button == 2) ! 145: Identify_character(event.xbutton.x, event.xbutton.y); ! 146: else if (event.xbutton.button == 3) ! 147: Go_Forward(); ! 148: } else if (event.type == KeyPress) { ! 149: i = XLookupString(&event, buffer, BUFFERSIZE, ! 150: NULL, NULL); ! 151: if (i==1 && (buffer[0]=='q' || buffer[0]=='Q' || ! 152: buffer[0]==' ' || buffer[0]=='\03')) ! 153: exit(0); ! 154: if (i==1 && buffer[0]=='<') { ! 155: minimum_bounds(); ! 156: continue; ! 157: } ! 158: if (i==1 && buffer[0]=='>') { ! 159: maximum_bounds(); ! 160: continue; ! 161: } ! 162: if (i && buffer[0]) ! 163: Beep(); ! 164: } ! 165: else if (event.type== GraphicsExpose || event.type == Expose) { ! 166: /* Only redisplay if this is the last exposure in a series */ ! 167: if (!event.xexpose.count) ! 168: Display_Contents(); ! 169: } ! 170: } ! 171: } ! 172: ! 173: /* ! 174: * Calc_Default_Size: This routine calculates the size of a box in the grid ! 175: * and where to write a character from so that every character will fit ! 176: * in a box. The size of an ideal window (16 boxes by 16 boxes with room ! 177: * for the bottom text) is then calculated. ! 178: */ ! 179: Calc_Default_Size() ! 180: { ! 181: XCharStruct min_bounds; ! 182: XCharStruct max_bounds; ! 183: ! 184: min_bounds = real_font->min_bounds; ! 185: max_bounds = real_font->max_bounds; ! 186: ! 187: /* ! 188: * Calculate size of box which will hold 1 character as well ! 189: * as were to draw it from in the box. ! 190: */ ! 191: x_offset = y_offset = 0; ! 192: if (min_bounds.lbearing<0) ! 193: x_offset = -min_bounds.lbearing; ! 194: if (max_bounds.ascent>0) ! 195: y_offset = max_bounds.ascent; ! 196: if (real_font->ascent > y_offset) ! 197: y_offset = real_font->ascent; ! 198: ! 199: box_x = x_offset; ! 200: box_y = y_offset; ! 201: ! 202: if (max_bounds.rbearing + x_offset > box_x) ! 203: box_x = max_bounds.rbearing + x_offset; ! 204: if (x_offset + max_bounds.width > box_x) ! 205: box_x = x_offset + max_bounds.width; ! 206: ! 207: if (max_bounds.descent + y_offset > box_y) ! 208: box_y = max_bounds.descent + y_offset; ! 209: if (real_font->descent + y_offset > box_y) ! 210: box_y = real_font->descent + y_offset; ! 211: ! 212: /* Leave room for grid lines & a little space */ ! 213: x_offset += 2; y_offset += 2; ! 214: box_x += 3; box_y += 3; ! 215: ! 216: if (!geometry) { /* if user didn't override, use ideal size */ ! 217: size_hints.width = box_x*16+1; ! 218: size_hints.height = box_y*16 + space_per_line *number_of_lines; ! 219: } ! 220: ! 221: size_hints.width_inc = box_x; ! 222: size_hints.height_inc = box_y; ! 223: ! 224: size_hints.min_width = box_x+1; ! 225: size_hints.min_height = box_y + space_per_line*number_of_lines; ! 226: } ! 227: ! 228: char s[4] = { 0, 0, 0, 0 }; ! 229: ! 230: /* ! 231: * Display_Contents: Routine to (re)display the contents of the window. ! 232: */ ! 233: Display_Contents() ! 234: { ! 235: int i, x, y; ! 236: XWindowAttributes wind_info; ! 237: ! 238: /* Get the size of the window */ ! 239: if (!XGetWindowAttributes(dpy, wind, &wind_info)) ! 240: Fatal_Error("Can't get window atrributes!"); ! 241: size_hints.width = wind_info.width; ! 242: size_hints.height = wind_info.height; ! 243: ! 244: /* Erase previous contents if any */ ! 245: XClearWindow(dpy, wind); ! 246: ! 247: /* Calculate the size of the grid */ ! 248: x_boxes = (size_hints.width-1) / box_x; ! 249: y_boxes = (size_hints.height - space_per_line * number_of_lines) ! 250: / box_y; ! 251: right = x_boxes * box_x; ! 252: bottom = y_boxes * box_y; ! 253: ! 254: /* Draw the grid */ ! 255: for (i = 0; i<=x_boxes; i++) ! 256: XDrawLine(dpy, wind, body_gc, i*box_x, 0, i*box_x, bottom); ! 257: for (i = 0; i<=y_boxes; i++) ! 258: XDrawLine(dpy, wind, body_gc, 0, i*box_y, right, i*box_y); ! 259: ! 260: /* Draw one character in every box */ ! 261: for (y=0; y<y_boxes; y++) { ! 262: for (x=0; x<x_boxes; x++) { ! 263: s[0] = (first_char + x + y*x_boxes) / 256; ! 264: s[1] = (first_char + x + y*x_boxes) % 256; ! 265: XDrawImageString16(dpy, wind, real_gc, x*box_x+x_offset, ! 266: y*box_y+y_offset, (XChar2b *) s, 1); ! 267: } ! 268: } ! 269: } ! 270: ! 271: char short_format[] = " %d. 0x%x"; ! 272: char line1_alt[] = " %s bounds:"; ! 273: char line1_format[] = " character # = %d. (0x%x):"; ! 274: char line2_format[] = " left bearing = %d, right bearing = %d"; ! 275: char line3_format[] = " ascent = %d, descent = %d"; ! 276: char line4_format[] = " width = %d"; ! 277: char buf[80*2]; ! 278: ! 279: /* ! 280: * Identify_character: Routine to print the number of the character that was ! 281: * clicked on by the mouse on the bottom line or beep if no character was ! 282: * clicked on. ! 283: */ ! 284: Identify_character(x, y) ! 285: int x,y; ! 286: { ! 287: int xbox, ybox; ! 288: int char_number; ! 289: XCharStruct char_info; ! 290: int index, byte1, byte2; ! 291: char *msg; ! 292: ! 293: /* If not in grid, beep */ ! 294: if (x>=right | y>=bottom) { ! 295: Beep(); ! 296: return; ! 297: } ! 298: ! 299: /* Find out which box clicked in */ ! 300: xbox = x / box_x; ! 301: ybox = y / box_y; ! 302: ! 303: /* Convert that to the character number */ ! 304: char_number = first_char + xbox + ybox * x_boxes; ! 305: ! 306: char_info = real_font->max_bounds; ! 307: index = char_number; ! 308: if (real_font->per_char) { ! 309: if (!real_font->min_byte1 && !real_font->max_byte1) { ! 310: if (char_number < real_font->min_char_or_byte2 || ! 311: char_number > real_font->max_char_or_byte2) ! 312: index = real_font->default_char; ! 313: index -= real_font->min_char_or_byte2; ! 314: } else { ! 315: byte2 = index & 0xff; ! 316: byte1 = (index>>8) & 0xff; ! 317: if (byte1 < real_font->min_byte1 || ! 318: byte1 > real_font->max_byte1 || ! 319: byte2 < real_font->min_char_or_byte2 || ! 320: byte2 > real_font->max_char_or_byte2) { ! 321: byte2 = real_font->default_char & 0xff; ! 322: byte1 = (real_font->default_char>>8)&0xff; ! 323: } ! 324: byte1 -= real_font->min_byte1; ! 325: byte2 -= real_font->min_char_or_byte2; ! 326: index = byte1 * (real_font->max_char_or_byte2 - ! 327: real_font->min_char_or_byte2 + 1) + ! 328: byte2; ! 329: } ! 330: char_info = real_font->per_char[index]; ! 331: } ! 332: ! 333: if (!verbose) { ! 334: sprintf(buf, short_format, char_number, char_number); ! 335: put_line(buf, 0); ! 336: } else { ! 337: sprintf(buf, line1_format, char_number, char_number); ! 338: put_line(buf, 0); ! 339: ! 340: display_char_info(char_info); ! 341: } ! 342: } ! 343: ! 344: /* ! 345: * maximum_bounds: display info for maximum bounds ! 346: */ ! 347: maximum_bounds() ! 348: { ! 349: sprintf(buf, line1_alt, "maximum"); ! 350: put_line(buf, 0); ! 351: ! 352: display_char_info(real_font->max_bounds); ! 353: } ! 354: ! 355: ! 356: /* ! 357: * minimum_bounds: display info for minimum bounds ! 358: */ ! 359: minimum_bounds() ! 360: { ! 361: sprintf(buf, line1_alt, "minimum"); ! 362: put_line(buf, 0); ! 363: ! 364: display_char_info(real_font->min_bounds); ! 365: } ! 366: ! 367: /* ! 368: * display_char_info: routine to display char info on bottom 3 lines ! 369: */ ! 370: display_char_info(char_info) ! 371: XCharStruct char_info; ! 372: { ! 373: sprintf(buf, line2_format, char_info.lbearing, ! 374: char_info.rbearing); ! 375: put_line(buf, 1); ! 376: ! 377: sprintf(buf, line3_format, char_info.ascent, ! 378: char_info.descent); ! 379: put_line(buf, 2); ! 380: ! 381: sprintf(buf, line4_format, char_info.width); ! 382: put_line(buf, 3); ! 383: } ! 384: ! 385: /* ! 386: * Put_line: print a line in bottom area at a given line # ! 387: */ ! 388: put_line(line, n) ! 389: char *line; ! 390: int n; ! 391: { ! 392: strcat(line," "); ! 393: XDrawImageString(dpy, wind, body_gc, 5, bottom + line_offset + ! 394: space_per_line*n, line, 80); ! 395: } ! 396: ! 397: ! 398: /* ! 399: * Go_Back: Routine to page back a gridful of characters. ! 400: */ ! 401: Go_Back() ! 402: { ! 403: /* If try and page back past first 0th character, beep */ ! 404: if (first_char == 0) { ! 405: Beep(); ! 406: return; ! 407: } ! 408: ! 409: first_char -= x_boxes*y_boxes; ! 410: if (first_char<0) ! 411: first_char = 0; ! 412: ! 413: Display_Contents(); ! 414: } ! 415: ! 416: /* ! 417: * Go_Forward: Routine to page forward a gridful of characters. ! 418: */ ! 419: Go_Forward() ! 420: { ! 421: first_char += x_boxes*y_boxes; ! 422: ! 423: Display_Contents(); ! 424: } ! 425: ! 426: ! 427: /* ! 428: * SetBackgroundToBitmap: Set the window's background to a caller supplied ! 429: * bitmap. ! 430: */ ! 431: SetBackgroundToBitmap(bitmap, width, height) ! 432: Pixmap bitmap; ! 433: int width, height; ! 434: { ! 435: Pixmap pix; ! 436: GC gc; ! 437: XGCValues gc_init; ! 438: ! 439: gc_init.foreground = foreground; ! 440: gc_init.background = background; ! 441: gc = XCreateGC(dpy, RootWindow(dpy, screen),GCForeground|GCBackground, ! 442: &gc_init); ! 443: ! 444: pix = Bitmap_To_Pixmap(dpy, wind, gc, bitmap, width, height); ! 445: ! 446: XSetWindowBackgroundPixmap(dpy, wind, pix); ! 447: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.