|
|
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.