1 /*LINTLIBRARY*/
2 /*
3 * Mini-Toolbox
4 *
5 * David Harrison
6 * University of California, Berkeley
7 * 1988, 1989
8 *
9 * This file contains routines which implement simple display widgets
10 * which can be used to construct simple dialog boxes.
11 * A mini-toolbox has been written here (overkill but I didn't
12 * want to use any of the standards yet -- they are too unstable).
13 */
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <X11/Xos.h>
18 #include <X11/Xlib.h>
19 #include <X11/Xutil.h>
20 #include "xtb.h"
21
22 extern void abort();
23
24 #define MAXKEYS 10
25
26 #ifdef __STDC__
27 #define FNPTR(fname, rtn, args) rtn (*fname)args
28 #include <stdarg.h>
29 #define VARARGS(func, rtn, args) rtn func args
30 #else
31 #define FNPTR(fname, rtn, args) rtn (*fname)()
32 #include <varargs.h>
33 #define VARARGS(func, rtn, args) /*VARARGS1*/ rtn func(va_alist) va_dcl
34 #endif
35
36 struct h_info {
37 FNPTR(func, xtb_hret, (XEvent *evt, xtb_data info)); /* Function to call */
38 xtb_data info; /* Additional info */
39 };
40
41 static Display *t_disp; /* Display */
42 static int t_scrn; /* Screen */
43
44 static unsigned long norm_pix; /* Foreground color */
45 static unsigned long back_pix; /* Background color */
46
47 static XFontStruct *norm_font; /* Normal font */
48
49 /* extern char *malloc(); */
50 #define STRDUP(str) (strcpy(malloc((unsigned) (strlen(str)+1)), (str)))
51 /* extern char *strcpy(); */
52 /* extern void free(); */
53
54
55
xtb_init(disp,scrn,foreground,background,font)56 void xtb_init(disp, scrn, foreground, background, font)
57 Display *disp; /* Display */
58 int scrn; /* Screen number */
59 unsigned long foreground; /* Foreground color */
60 unsigned long background; /* Background color */
61 XFontStruct *font; /* Normal font */
62 /*
63 * Sets default parameters used by the mini-toolbox.
64 */
65 {
66 t_disp = disp;
67 t_scrn = scrn;
68 norm_pix = foreground;
69 back_pix = background;
70 norm_font = font;
71 }
72
73
74 #define gray_width 32
75 #define gray_height 32
76 static char gray_bits[] = {
77 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
78 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
79 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
80 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
81 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
82 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
83 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
84 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
85 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
86 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
87 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa};
88
make_stipple(disp,able,bits,width,height)89 static Pixmap make_stipple(disp, able, bits, width, height)
90 Display *disp;
91 Drawable able;
92 char *bits;
93 int width, height;
94 {
95 int w, h;
96 Pixmap stipple;
97 int bitmap_pad;
98 GC image_gc;
99 XGCValues image_vals;
100 XImage *stip_image;
101
102 if (!XQueryBestStipple(disp, able, width, height, &w, &h)) {
103 /* Can't query best stipple */
104 return (Pixmap) 0;
105 }
106 if ((w > width) || (h > height)) {
107 /* Given pattern is too small */
108 return (Pixmap) 0;
109 }
110 if (!(stipple = XCreatePixmap(disp, able, w, h, 1))) {
111 /* Can't create pixmap image */
112 return (Pixmap) 0;
113 }
114 bitmap_pad = 8;
115 stip_image = XCreateImage(disp, DefaultVisual(disp, DefaultScreen(disp)),
116 1, XYPixmap, 0, bits, width, height,
117 bitmap_pad, 0);
118 if (!stip_image) return (Pixmap) 0;
119 image_gc = XCreateGC(disp, stipple, (unsigned long) 0, &image_vals);
120 XPutImage(disp, stipple, image_gc, stip_image, 0, 0, 0, 0, w, h);
121 return stipple;
122 }
123
124
gray_map(win)125 static Pixmap gray_map(win)
126 Window win;
127 /*
128 * Returns a gray pixmap suitable for stipple fill.
129 */
130 {
131 static Pixmap map = (Pixmap) 0;
132
133 if (!map) {
134 map = make_stipple(t_disp, win, gray_bits, gray_width, gray_height);
135 }
136 return map;
137 }
138
set_gc(win,fg,bg,font,gray_p)139 static GC set_gc(win, fg, bg, font, gray_p)
140 Window win; /* For creating GC */
141 unsigned long fg; /* Foreground pixel */
142 unsigned long bg; /* Background pixel */
143 Font font; /* Font */
144 int gray_p; /* Gray if set */
145 /*
146 * Sets and returns the fields listed above in a global graphics context.
147 * If graphics context does not exist, it is created.
148 */
149 {
150 static GC t_gc = (GC) 0;
151 XGCValues gcvals;
152 unsigned long gcmask;
153
154 gcvals.foreground = fg;
155 gcvals.background = bg;
156 gcvals.font = font;
157 gcvals.stipple = gray_map(win);
158 gcvals.fill_style = (gray_p ? FillStippled : FillSolid);
159 gcmask = GCForeground | GCBackground | GCFont | GCFillStyle | GCStipple;
160 if (t_gc == (GC) 0) {
161 t_gc = XCreateGC(t_disp, win, gcmask, &gcvals);
162 } else {
163 XChangeGC(t_disp, t_gc, gcmask, &gcvals);
164 }
165 return t_gc;
166 }
167
168
169
170 static XContext h_context = (XContext) 0;
171
xtb_register(win,func,info)172 void xtb_register(win, func, info)
173 Window win;
174 FNPTR( func, xtb_hret, (XEvent *evt, xtb_data info) );
175 xtb_data info;
176 /*
177 * Associates the event handling function `func' with the window
178 * `win'. Additional information `info' will be passed to `func'.
179 * The routine should return one of the return codes given above.
180 */
181 {
182 struct h_info *new_info;
183
184 if (h_context == (XContext) 0) {
185 h_context = XUniqueContext();
186 }
187 new_info = (struct h_info *) malloc(sizeof(struct h_info));
188 new_info->func = func;
189 new_info->info = info;
190 XSaveContext(t_disp, win, h_context, (caddr_t) new_info);
191 }
192
xtb_lookup(win)193 xtb_data xtb_lookup(win)
194 Window win;
195 /*
196 * Returns the associated data with window `win'.
197 */
198 {
199 xtb_data data;
200
201 if (!XFindContext(t_disp, win, h_context, (XPointer*)&data)) {
202 return ((struct h_info *) data)->info;
203 } else {
204 return (xtb_data) 0;
205 }
206 }
207
xtb_dispatch(evt)208 xtb_hret xtb_dispatch(evt)
209 XEvent *evt;
210 /*
211 * Dispatches an event to a handler if its ours. Returns one of
212 * the return codes given above (XTB_NOTDEF, XTB_HANDLED, or XTB_STOP).
213 */
214 {
215 struct h_info *info;
216
217 if (!XFindContext(t_disp, evt->xany.window, h_context, (caddr_t *) &info)) {
218 if (info->func) return (*info->func)(evt, info->info);
219 else return XTB_NOTDEF;
220 } else return XTB_NOTDEF;
221 }
222
xtb_unregister(win,info)223 int xtb_unregister(win, info)
224 Window win;
225 xtb_data *info;
226 /*
227 * Removes `win' from the dialog association table. `info' is
228 * returned to allow the user to delete it (if desired). Returns
229 * a non-zero status if the association was found and properly deleted.
230 */
231 {
232 struct h_info *hi;
233
234 if (!XFindContext(t_disp, win, h_context, (caddr_t *) &hi)) {
235 (void) XDeleteContext(t_disp, win, h_context);
236 *info = hi->info;
237 free((char *) hi);
238 return 1;
239 } else return 0;
240 }
241
242
243
244 #define BT_HPAD 3
245 #define BT_VPAD 2
246 #define BT_LPAD 3
247 #define BT_BRDR 1
248
249 struct b_info {
250 FNPTR( func, xtb_hret, (Window win, int state, xtb_data val) );
251 /* Function to call */
252 char *text; /* Text of button */
253 int flag; /* State of button */
254 int na; /* Non-zero if not active */
255 int line_y, line_w; /* Entry/Exit line */
256 xtb_data val; /* User defined info */
257 };
258
bt_draw(win,ri)259 static void bt_draw(win, ri)
260 Window win;
261 struct b_info *ri;
262 /*
263 * Draws a button window
264 */
265 {
266 if (ri->flag) {
267 XDrawImageString(t_disp, win,
268 set_gc(win, back_pix, norm_pix, norm_font->fid, 0),
269 BT_HPAD, BT_VPAD+norm_font->ascent,
270 ri->text, strlen(ri->text));
271 } else {
272 XDrawImageString(t_disp, win,
273 set_gc(win, norm_pix, back_pix, norm_font->fid, 0),
274 BT_HPAD, BT_VPAD+norm_font->ascent,
275 ri->text, strlen(ri->text));
276 }
277 if (ri->na) {
278 Window root;
279 int x, y;
280 unsigned int w, h, b, d;
281
282 XGetGeometry(t_disp, win, &root, &x, &y, &w, &h, &b, &d);
283 XFillRectangle(t_disp, win,
284 set_gc(win, (ri->flag ? norm_pix : back_pix),
285 back_pix, norm_font->fid, 1),
286 0, 0, w, h);
287 }
288 }
289
bt_line(win,ri,pix)290 static void bt_line(win, ri, pix)
291 Window win;
292 struct b_info *ri;
293 unsigned long pix;
294 /*
295 * Draws a status line beneath the text to indicate the
296 * user has moved into the button.
297 */
298 {
299 XDrawLine(t_disp, win,
300 set_gc(win, pix, back_pix, norm_font->fid, ri->na),
301 BT_HPAD, ri->line_y, BT_HPAD+ri->line_w, ri->line_y);
302 }
303
bt_h(evt,info)304 static xtb_hret bt_h(evt, info)
305 XEvent *evt;
306 xtb_data info;
307 /*
308 * Handles button events.
309 */
310 {
311 Window win = evt->xany.window;
312 struct b_info *ri = (struct b_info *) info;
313 xtb_hret rtn;
314
315 switch (evt->type) {
316 case Expose:
317 bt_draw(win, ri); rtn = XTB_HANDLED;
318 break;
319 case EnterNotify:
320 if (!ri->na) bt_line(win, ri, norm_pix); rtn = XTB_HANDLED;
321 break;
322 case LeaveNotify:
323 if (!ri->na) bt_line(win, ri, back_pix); rtn = XTB_HANDLED;
324 break;
325 case ButtonPress:
326 /* Nothing - just wait for button up */
327 rtn = XTB_HANDLED;
328 break;
329 case ButtonRelease:
330 if (!ri->na) rtn = (*ri->func)(win, ri->flag, ri->val);
331 break;
332 default:
333 rtn = XTB_NOTDEF;
334 }
335 return rtn;
336 }
337
xtb_bt_new(win,text,func,val,frame)338 void xtb_bt_new(win, text, func, val, frame)
339 Window win; /* Parent window */
340 char *text; /* Text in button */
341 FNPTR( func, xtb_hret, (Window, int, xtb_data) ); /* Callback */
342 xtb_data val; /* User data */
343 xtb_frame *frame; /* Size (RETURN) */
344 /*
345 * Makes a new button under `win' with the text `text'. The
346 * window, size, and position of the button are returned in `frame'.
347 * The initial position is always (0, 0). When the
348 * button is pressed, `func' will be called with the button
349 * window, the current state of the button, and `val'.
350 * It is up to `func' to change the state of the button (if desired).
351 * The routine should return XTB_HANDLED normally and XTB_STOP if the
352 * dialog should stop. The window will be automatically mapped.
353 */
354 {
355 XCharStruct bb;
356 struct b_info *info;
357 int dir, ascent, descent;
358
359 XTextExtents(norm_font, text, strlen(text), &dir, &ascent, &descent, &bb);
360 frame->width = bb.width + 2*BT_HPAD;
361 frame->height = norm_font->ascent + norm_font->descent + BT_VPAD + BT_LPAD;
362 frame->x_loc = frame->y_loc = 0;
363 frame->win = XCreateSimpleWindow(t_disp, win,
364 frame->x_loc, frame->y_loc,
365 frame->width, frame->height,
366 BT_BRDR, norm_pix, back_pix);
367 XSelectInput(t_disp, frame->win, ExposureMask|
368 ButtonPressMask|ButtonReleaseMask|
369 EnterWindowMask|LeaveWindowMask);
370 info = (struct b_info *) malloc(sizeof(struct b_info));
371 info->func = func;
372 info->text = STRDUP(text);
373 info->flag = 0;
374 info->na = 0;
375 info->val = val;
376 info->line_y = frame->height - 2;
377 info->line_w = frame->width - 2*BT_HPAD;
378 xtb_register(frame->win, bt_h, (xtb_data) info);
379 XMapWindow(t_disp, frame->win);
380 frame->width += (2*BT_BRDR);
381 frame->height += (2*BT_BRDR);
382 }
383
xtb_bt_get(win,stuff,na)384 int xtb_bt_get(win, stuff, na)
385 Window win;
386 xtb_data *stuff;
387 int *na;
388 /*
389 * Returns the state of button `win'. If provided, the button
390 * specific info is returned in `info' and the active state
391 * of the button is returned in `na'.
392 */
393 {
394 struct b_info *info = (struct b_info *) xtb_lookup(win);
395
396 if (stuff) *stuff = info->val;
397 if (na) *na = info->na;
398 return info->flag;
399 }
400
xtb_bt_set(win,val,stuff,na)401 int xtb_bt_set(win, val, stuff, na)
402 Window win;
403 int val;
404 xtb_data stuff;
405 int na;
406 /*
407 * Changes the value of a button and returns the new state.
408 * The button is drawn. If set, the button specific info
409 * will be set to `info'. This doesn't allow you to set
410 * the state to zero, but that may not be important. If
411 * `na' is non-zero, the button will be deactivated (no
412 * activity will be allowed). The change in button appearance
413 * will be immediate.
414 */
415 {
416 struct b_info *info = (struct b_info *) xtb_lookup(win);
417
418 info->flag = (val != 0);
419 info->na = (na != 0);
420 if (stuff) info->val = stuff;
421 bt_draw(win, info);
422 XFlush(t_disp);
423 return info->flag;
424 }
425
xtb_bt_del(win,info)426 void xtb_bt_del(win, info)
427 Window win;
428 xtb_data *info;
429 /*
430 * Deletes the button `win' and returns the user defined information
431 * in `info' for destruction.
432 */
433 {
434 struct b_info *bi;
435
436 if (xtb_unregister(win, (xtb_data *) &bi)) {
437 *info = bi->val;
438 free((char *) bi->text);
439 free((char *) bi);
440 XDestroyWindow(t_disp, win);
441 }
442 }
443
444
445
446 #define BR_XPAD 2
447 #define BR_YPAD 2
448 #define BR_INTER 2
449
450 struct br_info {
451 Window main_win; /* Main button row */
452 int which_one; /* Which button is on */
453 int btn_cnt; /* How many buttons */
454 FNPTR( func, xtb_hret, (Window win, int prev, int this, xtb_data val) );
455 xtb_data val; /* User data */
456 Window *btns; /* Button windows */
457 };
458
459 /*ARGSUSED*/
br_h(win,val,info)460 static xtb_hret br_h(win, val, info)
461 Window win;
462 int val;
463 xtb_data info;
464 /*
465 * This handles events for button rows. When a button is pressed,
466 * it turns off the button selected in `which_one' and turns itself
467 * on.
468 */
469 {
470 struct br_info *real_info = (struct br_info *) info;
471 int i, prev;
472
473 prev = real_info->which_one;
474 if ((prev >= 0) && (prev < real_info->btn_cnt)) {
475 (void) xtb_bt_set(real_info->btns[prev], 0, (xtb_data) 0, 0);
476 }
477 for (i = 0; i < real_info->btn_cnt; i++) {
478 if (win == real_info->btns[i]) {
479 real_info->which_one = i;
480 break;
481 }
482 }
483 (void) xtb_bt_set(win, 1, (xtb_data) 0, 0);
484 /* Callback */
485 if (real_info->func) {
486 return (*real_info->func)(real_info->main_win,
487 prev, real_info->which_one,
488 real_info->val);
489 } else {
490 return XTB_HANDLED;
491 }
492 }
493
494
xtb_br_new(win,cnt,lbls,init,func,val,frame)495 void xtb_br_new(win, cnt, lbls, init, func, val, frame)
496 Window win; /* Parent window */
497 int cnt; /* Count of buttons */
498 char *lbls[]; /* Button labels */
499 int init; /* Initial button */
500 FNPTR( func, xtb_hret, (Window, int, int, xtb_data) ); /* Callback */
501 xtb_data val; /* User data */
502 xtb_frame *frame; /* Returned size */
503 /*
504 * This routine makes a new row of buttons in the window `win'
505 * and returns a frame containing all of these buttons. These
506 * buttons are designed so that only one of them will be active
507 * at a time. Initially, button `init' will be activated (if
508 * init is less than zero, none will be initially activated).
509 * Whenever a button is pushed, `func' will be called with the
510 * button row window, the index of the previous button (-1 if
511 * none), the index of the current button, and the user data, `val'.
512 * The function is optional (if zero, no function will be called).
513 * The size of the row is returned in `frame'. The window
514 * will be automatically mapped. Initially, the window containing
515 * the buttons will be placed at 0,0 in the parent window.
516 */
517 {
518 struct br_info *info;
519 xtb_frame sub_frame;
520 int i, x, y;
521
522 frame->width = frame->height = 0;
523 frame->x_loc = frame->y_loc = 0;
524 frame->win = XCreateSimpleWindow(t_disp, win, 0, 0, 1, 1,
525 0, back_pix, back_pix);
526 info = (struct br_info *) malloc(sizeof(struct br_info));
527 info->main_win = frame->win;
528 info->btns = (Window *) malloc((unsigned) (sizeof(Window) * cnt));
529 info->btn_cnt = cnt;
530 info->which_one = init;
531 info->func = func;
532 info->val = val;
533 /* the handler is used simply to get information out */
534 xtb_register(frame->win, (xtb_hret (*)()) 0, (xtb_data) info);
535 x = BR_XPAD; y = BR_YPAD;
536 for (i = 0; i < cnt; i++) {
537 xtb_bt_new(frame->win, lbls[i], br_h, (xtb_data) info, &sub_frame);
538 info->btns[i] = sub_frame.win;
539 XMoveWindow(t_disp, info->btns[i], x, y);
540 x += (BR_INTER + sub_frame.width);
541 if (sub_frame.height > frame->height) frame->height = sub_frame.height;
542 if (i == init) (void) xtb_bt_set(info->btns[i], 1, (xtb_data) 0, 0);
543 }
544 frame->width = x - BR_INTER + BR_XPAD;
545 frame->height += (2 * BR_YPAD);
546 XResizeWindow(t_disp, frame->win, frame->width, frame->height);
547 XMapWindow(t_disp, frame->win);
548 }
549
xtb_br_get(win)550 int xtb_br_get(win)
551 Window win;
552 /*
553 * This routine returns the index of the currently selected item of
554 * the button row given by the window `win'. Note: no checking
555 * is done to make sure `win' is a button row.
556 */
557 {
558 struct br_info *info = (struct br_info *) xtb_lookup(win);
559
560 return info->which_one;
561 }
562
xtb_br_del(win)563 void xtb_br_del(win)
564 Window win;
565 /*
566 * Deletes a button row. All resources are reclaimed.
567 */
568 {
569 struct br_info *info;
570 int i;
571
572 if (xtb_unregister(win, (xtb_data *) &info)) {
573 for (i = 0; i < info->btn_cnt; i++) {
574 xtb_bt_del(info->btns[i], (xtb_data *) &info);
575 }
576 free((char *) info->btns);
577 free((char *) info);
578 XDestroyWindow(t_disp, win);
579 }
580 }
581
582
583
584 /* Text widget */
585
586 #define TO_HPAD 1
587 #define TO_VPAD 1
588
589 struct to_info {
590 char *text; /* Text to display */
591 XFontStruct *ft; /* Font to use */
592 };
593
to_draw(win,ri)594 static void to_draw(win, ri)
595 Window win;
596 struct to_info *ri;
597 /*
598 * Draws the text for a widget
599 */
600 {
601 XDrawImageString(t_disp, win,
602 set_gc(win, norm_pix, back_pix, ri->ft->fid, 0),
603 TO_HPAD, TO_VPAD+ri->ft->ascent,
604 ri->text, strlen(ri->text));
605 }
606
to_h(evt,info)607 static xtb_hret to_h(evt, info)
608 XEvent *evt;
609 xtb_data info;
610 /*
611 * Handles text widget events
612 */
613 {
614 Window win = evt->xany.window;
615 struct to_info *ri = (struct to_info *) info;
616
617 switch (evt->type) {
618 case Expose:
619 to_draw(win, ri);
620 return XTB_HANDLED;
621 default:
622 return XTB_NOTDEF;
623 }
624 }
625
xtb_to_new(win,text,ft,frame)626 void xtb_to_new(win, text, ft, frame)
627 Window win; /* Parent window */
628 char *text; /* Text */
629 XFontStruct *ft; /* Font to use */
630 xtb_frame *frame; /* Returned size */
631 /*
632 * Makes a new text widget under `win' with the text `text'.
633 * The size of the widget is returned in `w' and `h'. The
634 * window is created and mapped at 0,0 in `win'. The font
635 * used for the text is given in `ft'.
636 */
637 {
638 struct to_info *info;
639
640 frame->width = XTextWidth(ft, text, strlen(text)) + 2*TO_HPAD;
641 frame->height = ft->ascent + ft->descent + 2*TO_VPAD;
642 frame->x_loc = frame->y_loc = 0;
643 frame->win = XCreateSimpleWindow(t_disp, win, 0, 0,
644 frame->width, frame->height, 0,
645 back_pix, back_pix);
646 XSelectInput(t_disp, frame->win, ExposureMask);
647 info = (struct to_info *) malloc(sizeof(struct to_info));
648 info->text = STRDUP(text);
649 info->ft = ft;
650 xtb_register(frame->win, to_h, (xtb_data) info);
651 XMapWindow(t_disp, frame->win);
652 }
653
xtb_to_del(win)654 void xtb_to_del(win)
655 Window win;
656 /*
657 * Deletes an output only text widget.
658 */
659 {
660 struct to_info *info;
661
662 if (xtb_unregister(win, (xtb_data *) &info)) {
663 free((char *) info->text);
664 free((char *) info);
665 XDestroyWindow(t_disp, win);
666 }
667 }
668
669
670 /*
671 * Input text widget
672 */
673
674 #define TI_HPAD 2
675 #define TI_VPAD 2
676 #define TI_LPAD 3
677 #define TI_BRDR 2
678 #define TI_CRSP 1
679
680 struct ti_info {
681 FNPTR( func, xtb_hret, (Window win, int ch, char *textcopy, xtb_data *val) );
682 /* Function to call */
683 int maxlen; /* Maximum characters */
684 int curidx; /* Current index pos */
685 int curxval; /* Current draw loc */
686 char text[MAXCHBUF]; /* Current text array */
687 int line_y, line_w; /* Entry/Exit line */
688 int focus_flag; /* If on, we have focus */
689 xtb_data val; /* User info */
690 };
691
text_width(font,str,len)692 static int text_width(font, str, len)
693 XFontStruct *font; /* What font */
694 char *str; /* Character array */
695 int len; /* Length of array */
696 /*
697 * Returns the width of a string using XTextExtents.
698 */
699 {
700 XCharStruct bb;
701 int dir, ascent, descent;
702
703 XTextExtents(font, str, len, &dir, &ascent, &descent, &bb);
704 return bb.width;
705 }
706
ti_cursor_on(win,ri)707 static void ti_cursor_on(win, ri)
708 Window win;
709 struct ti_info *ri;
710 /*
711 * Draws the cursor for the window. Uses pixel `pix'.
712 */
713 {
714 XFillRectangle(t_disp, win,
715 set_gc(win, norm_pix, back_pix, norm_font->fid, 0),
716 ri->curxval + TI_HPAD + TI_CRSP, TI_VPAD,
717 (ri->focus_flag ? 2 : 1),
718 norm_font->ascent + norm_font->descent - 1);
719 }
720
ti_cursor_off(win,ri)721 static void ti_cursor_off(win, ri)
722 Window win;
723 struct ti_info *ri;
724 /*
725 * Draws the cursor for the window. Uses pixel `pix'.
726 */
727 {
728 XFillRectangle(t_disp, win,
729 set_gc(win, back_pix, back_pix, norm_font->fid, 0),
730 ri->curxval + TI_HPAD + TI_CRSP, TI_VPAD,
731 (ri->focus_flag ? 2 : 1),
732 norm_font->ascent + norm_font->descent - 1);
733 }
734
ti_draw(win,ri,c_flag)735 static void ti_draw(win, ri, c_flag)
736 Window win;
737 struct ti_info *ri;
738 int c_flag;
739 /*
740 * Draws the indicated text widget. This includes drawing the
741 * text and cursor. If `c_flag' is set, the window will
742 * be cleared first.
743 */
744 {
745 if (c_flag) XClearWindow(t_disp, win);
746 /* Text */
747 XDrawImageString(t_disp, win,
748 set_gc(win, norm_pix, back_pix, norm_font->fid, 0),
749 TI_HPAD, TI_VPAD+norm_font->ascent,
750 ri->text, strlen(ri->text));
751 /* Cursor */
752 ti_cursor_on(win, ri);
753 }
754
ti_line(win,ri,pix)755 static void ti_line(win, ri, pix)
756 Window win;
757 struct ti_info *ri;
758 unsigned long pix;
759 /*
760 * Draws a status line beneath the text in a text widget to indicate
761 * the user has moved into the text field.
762 */
763 {
764 XDrawLine(t_disp, win,
765 set_gc(win, pix, back_pix, norm_font->fid, 0),
766 TI_HPAD, ri->line_y, TI_HPAD+ri->line_w, ri->line_y);
767 }
768
769 /* For debugging */
focus_evt(evt)770 focus_evt(evt)
771 XEvent *evt;
772 {
773 switch (evt->xfocus.mode) {
774 case NotifyNormal:
775 printf("NotifyNormal");
776 break;
777 case NotifyGrab:
778 printf("NotifyGrab");
779 break;
780 case NotifyUngrab:
781 printf("NotifyUngrab");
782 break;
783 }
784 printf(", detail = ");
785 switch (evt->xfocus.detail) {
786 case NotifyAncestor:
787 printf("NotifyAncestor");
788 break;
789 case NotifyVirtual:
790 printf("NotifyVirtual");
791 break;
792 case NotifyInferior:
793 printf("NotifyInferior");
794 break;
795 case NotifyNonlinear:
796 printf("NotifyNonLinear");
797 break;
798 case NotifyNonlinearVirtual:
799 printf("NotifyNonLinearVirtual");
800 break;
801 case NotifyPointer:
802 printf("NotifyPointer");
803 break;
804 case NotifyPointerRoot:
805 printf("NotifyPointerRoot");
806 break;
807 case NotifyDetailNone:
808 printf("NotifyDetailNone");
809 break;
810 }
811 printf("\n");
812 }
813
814
815
ti_h(evt,info)816 static xtb_hret ti_h(evt, info)
817 XEvent *evt;
818 xtb_data info;
819 /*
820 * Handles text input events.
821 */
822 {
823 Window win = evt->xany.window;
824 struct ti_info *ri = (struct ti_info *) info;
825 char keys[MAXKEYS], textcopy[MAXCHBUF];
826 xtb_hret rtn;
827 int nbytes, i;
828
829 switch (evt->type) {
830 case Expose:
831 ti_draw(win, ri, 0); rtn = XTB_HANDLED;
832 break;
833 case KeyPress:
834 nbytes = XLookupString(&evt->xkey, keys, MAXKEYS,
835 (KeySym *) 0, (XComposeStatus *) 0);
836 for (i = 0; i < nbytes; i++) {
837 (void) strcpy(textcopy, ri->text);
838 if ((rtn = (*ri->func)(win, (int) keys[i],
839 textcopy, ri->val)) == XTB_STOP)
840 break;
841 }
842 break;
843 case FocusIn:
844 focus_evt(evt);
845 if (evt->xfocus.detail != NotifyPointer) {
846 ti_cursor_off(win, ri);
847 ri->focus_flag = 1;
848 ti_cursor_on(win, ri);
849 }
850 break;
851 case FocusOut:
852 focus_evt(evt);
853 if (evt->xfocus.detail != NotifyPointer) {
854 ti_cursor_off(win, ri);
855 ri->focus_flag = 0;
856 ti_cursor_on(win, ri);
857 }
858 break;
859 case EnterNotify:
860 ti_line(win, ri, norm_pix); rtn = XTB_HANDLED;
861 break;
862 case LeaveNotify:
863 ti_line(win, ri, back_pix); rtn = XTB_HANDLED;
864 break;
865 case ButtonPress:
866 /* Wait for release */
867 break;
868 case ButtonRelease:
869 /* Set input focus */
870 XSetInputFocus(t_disp, win, RevertToParent, CurrentTime);
871 break;
872 default:
873 rtn = XTB_NOTDEF;
874 break;
875 }
876 return rtn;
877 }
878
xtb_ti_new(win,text,maxchar,func,val,frame)879 void xtb_ti_new(win, text, maxchar, func, val, frame)
880 Window win; /* Parent window */
881 char *text; /* Initial text */
882 int maxchar; /* Maximum characters */
883 FNPTR( func, xtb_hret, (Window, int, char *, xtb_data *) ); /* Callback */
884 xtb_data val; /* User data */
885 xtb_frame *frame; /* Returned size */
886 /*
887 * This routine creates a new editable text widget under `win'
888 * with the initial text `text'. The widget contains only
889 * one line of text which cannot exceed `maxchar' characters.
890 * The size of the widget is returned in `frame'. Each
891 * time a key is pressed in the window, `func' will be called
892 * with the window, the character, a copy of the text, and `val'.
893 * The state of the widget can be changed by the routines below.
894 * May set window to zero if the maximum overall character width
895 * (MAXCHBUF) is exceeded.
896 */
897 {
898 struct ti_info *info;
899
900 if (maxchar >= MAXCHBUF) {
901 frame->win = (Window) 0;
902 return;
903 }
904 frame->width = XTextWidth(norm_font, "8", 1) * maxchar + 2*TI_HPAD;
905 frame->height = norm_font->ascent + norm_font->descent + TI_VPAD + TI_LPAD;
906 frame->x_loc = frame->y_loc = 0;
907 frame->win = XCreateSimpleWindow(t_disp, win, 0, 0,
908 frame->width, frame->height, TI_BRDR,
909 norm_pix, back_pix);
910 XSelectInput(t_disp, frame->win, ExposureMask|KeyPressMask|
911 EnterWindowMask|LeaveWindowMask|
912 FocusChangeMask|ButtonPressMask|
913 ButtonReleaseMask);
914 info = (struct ti_info *) malloc(sizeof(struct ti_info));
915 info->func = func;
916 info->val = val;
917 info->maxlen = maxchar;
918 if (text) (void) strcpy(info->text, text);
919 else info->text[0] = '\0';
920 info->curidx = strlen(info->text);
921 info->curxval = text_width(norm_font, info->text, info->curidx);
922 info->line_y = frame->height - 2;
923 info->line_w = frame->width - 2 * TI_HPAD;
924 info->focus_flag = 0;
925 xtb_register(frame->win, ti_h, (xtb_data) info);
926 XMapWindow(t_disp, frame->win);
927 frame->width += (2 * TI_BRDR);
928 frame->height += (2 * TI_BRDR);
929 }
930
xtb_ti_get(win,text,val)931 void xtb_ti_get(win, text, val)
932 Window win; /* Widget widnow */
933 char text[MAXCHBUF]; /* Filled in text */
934 xtb_data *val; /* User info */
935 /*
936 * This routine returns the information associated with text
937 * widget `win'. The text is filled into the passed buffer
938 * `text' which should be MAXCHBUF characters in size. If
939 * `val' is non-zero, the user supplied info is returned there.
940 */
941 {
942 struct ti_info *info = (struct ti_info *) xtb_lookup(win);
943
944 if (val) *val = info->val;
945 (void) strcpy(text, info->text);
946 }
947
xtb_ti_set(win,text,val)948 int xtb_ti_set(win, text, val)
949 Window win; /* Widget window */
950 char *text; /* Replacement text */
951 xtb_data val; /* User info */
952 /*
953 * This routine sets the text of a text widget. The widget
954 * will be redrawn. Note: for incremental changes, ti_ins and
955 * ti_dch should be used. If `val' is non-zero, it will replace
956 * the user information for the widget. The widget is redrawn.
957 * Will return zero if `text' is too long.
958 */
959 {
960 struct ti_info *info = (struct ti_info *) xtb_lookup(win);
961 int newlen;
962
963 if (text) {
964 if ((newlen = strlen(text)) >= info->maxlen) return 0;
965 } else {
966 newlen = 0;
967 }
968 info->curidx = newlen;
969 if (text) (void) strcpy(info->text, text);
970 else info->text[0] = '\0';
971 info->curxval = text_width(norm_font, info->text, info->curidx);
972 if (val) info->val = val;
973 ti_draw(win, info, 1);
974 return 1;
975 }
976
xtb_ti_ins(win,ch)977 int xtb_ti_ins(win, ch)
978 Window win; /* Widget window */
979 int ch; /* Character */
980 /*
981 * Inserts the character `ch' onto the end of the text for `win'.
982 * Will return zero if there isn't any more room left. Does
983 * all appropriate display updates.
984 */
985 {
986 struct ti_info *info = (struct ti_info *) xtb_lookup(win);
987 char lstr[1];
988
989 if (info->curidx >= info->maxlen-1) return 0;
990 info->text[info->curidx] = ch;
991 info->text[info->curidx+1] = '\0';
992 /* Turn off cursor */
993 ti_cursor_off(win, info);
994 /* Text */
995 lstr[0] = (char) ch;
996 XDrawImageString(t_disp, win,
997 set_gc(win, norm_pix, back_pix, norm_font->fid, 0),
998 info->curxval+TI_HPAD, TI_VPAD+norm_font->ascent,
999 lstr, 1);
1000 info->curidx += 1;
1001 info->curxval += text_width(norm_font, lstr, 1);
1002 ti_cursor_on(win, info);
1003 return 1;
1004 }
1005
xtb_ti_dch(win)1006 int xtb_ti_dch(win)
1007 Window win; /* Widget window */
1008 /*
1009 * Deletes the character at the end of the text for `win'. Will
1010 * return zero if there aren't any characters to delete. Does
1011 * all appropriate display updates.
1012 */
1013 {
1014 struct ti_info *info = (struct ti_info *) xtb_lookup(win);
1015 int chw;
1016
1017 if (info->curidx == 0) return 0;
1018 /* Wipe out cursor */
1019 ti_cursor_off(win, info);
1020 info->curidx -= 1;
1021 chw = text_width(norm_font, &(info->text[info->curidx]), 1);
1022 info->curxval -= chw;
1023 /* Wipe out character */
1024 XClearArea(t_disp, win, info->curxval+TI_HPAD, TI_VPAD,
1025 (unsigned int) chw + 1,
1026 (unsigned int) norm_font->ascent + norm_font->descent,
1027 False);
1028 info->text[info->curidx] = '\0';
1029 ti_cursor_on(win, info);
1030 return 1;
1031 }
1032
xtb_ti_del(win,info)1033 void xtb_ti_del(win, info)
1034 Window win;
1035 xtb_data *info;
1036 /*
1037 * Deletes an input text widget. User defined data is returned in `info'.
1038 */
1039 {
1040 struct ti_info *ti;
1041
1042 if (xtb_unregister(win, (xtb_data *) &ti)) {
1043 *info = ti->val;
1044 free((char *) ti);
1045 XDestroyWindow(t_disp, win);
1046 }
1047 }
1048
1049
1050 /*
1051 * Simple colored output frame - usually used for drawing lines
1052 */
1053
xtb_bk_new(win,width,height,frame)1054 void xtb_bk_new(win, width, height, frame)
1055 Window win; /* Parent window */
1056 unsigned width, height; /* Size */
1057 xtb_frame *frame; /* Returned size */
1058 /*
1059 * This routine creates a new frame that displays a block
1060 * of color whose size is given by `width' and `height'.
1061 * It is usually used to draw lines. No user interaction
1062 * is defined for the frame. The color used is the default
1063 * foreground color set in xtb_init().
1064 */
1065 {
1066 frame->x_loc = frame->y_loc = 0;
1067 frame->width = width;
1068 frame->height = height;
1069 frame->win = XCreateSimpleWindow(t_disp, win,
1070 frame->x_loc, frame->y_loc,
1071 frame->width, frame->height,
1072 0, norm_pix, norm_pix);
1073 XMapWindow(t_disp, frame->win);
1074 }
1075
1076
xtb_bk_del(win)1077 void xtb_bk_del(win)
1078 Window win;
1079 /*
1080 * Deletes a block frame.
1081 */
1082 {
1083 XDestroyWindow(t_disp, win);
1084 }
1085
1086
1087
1088
1089 /*
1090 * Formatting support
1091 */
1092
1093 #define ERROR(msg) printf("%s\n", msg); abort();
1094
xtb_w(w)1095 xtb_fmt *xtb_w(w)
1096 xtb_frame *w;
1097 /*
1098 * Returns formatting structure for a widget.
1099 */
1100 {
1101 xtb_fmt *ret;
1102
1103 ret = (xtb_fmt *) malloc((unsigned) sizeof(xtb_fmt));
1104 ret->wid.type = W_TYPE;
1105 ret->wid.w = w;
1106 return ret;
1107 }
1108
1109 VARARGS(xtb_hort, xtb_fmt *, (xtb_just just, int padding, int interspace, ...))
1110 /*
1111 * Builds a horizontal structure
1112 */
1113 {
1114 va_list ap;
1115 xtb_fmt *ret, *val;
1116 #ifdef __STDC__
1117 va_start(ap, interspace);
1118 #else
1119 xtb_just just;
1120 int padding, interspace;
1121
1122 va_start(ap);
1123 just = va_arg(ap, xtb_just);
1124 padding = va_arg(ap, int);
1125 interspace = va_arg(ap, int);
1126 #endif
1127 ret = (xtb_fmt *) malloc((unsigned) sizeof(xtb_fmt));
1128 ret->align.type = A_TYPE;
1129 ret->align.dir = HORIZONTAL;
1130 ret->align.just = just;
1131 ret->align.padding = padding;
1132 ret->align.interspace = interspace;
1133 /* Build array of incoming xtb_fmt structures */
1134 ret->align.ni = 0;
1135 while ((val = va_arg(ap, xtb_fmt *)) != (xtb_fmt *) 0) {
1136 if (ret->align.ni < MAX_BRANCH) {
1137 ret->align.items[ret->align.ni] = val;
1138 ret->align.ni++;
1139 } else {
1140 ERROR("too many branches\n");
1141 }
1142 }
1143 return ret;
1144 }
1145
1146
1147 VARARGS(xtb_vert, xtb_fmt *, (xtb_just just, int padding, int interspace, ...))
1148 /*
1149 * Builds a vertical structure
1150 */
1151 {
1152 va_list ap;
1153 xtb_fmt *ret, *val;
1154 #ifdef __STDC__
1155 va_start(ap, interspace);
1156 #else
1157 xtb_just just;
1158 int padding, interspace;
1159
1160 va_start(ap);
1161 just = va_arg(ap, xtb_just);
1162 padding = va_arg(ap, int);
1163 interspace = va_arg(ap, int);
1164 #endif
1165 ret = (xtb_fmt *) malloc((unsigned) sizeof(xtb_fmt));
1166 ret->align.type = A_TYPE;
1167 ret->align.dir = VERTICAL;
1168 ret->align.just = just;
1169 ret->align.padding = padding;
1170 ret->align.interspace = interspace;
1171 /* Build array of incoming xtb_fmt structures */
1172 ret->align.ni = 0;
1173 while ((val = va_arg(ap, xtb_fmt *)) != (xtb_fmt *) 0) {
1174 if (ret->align.ni < MAX_BRANCH) {
1175 ret->align.items[ret->align.ni] = val;
1176 ret->align.ni++;
1177 } else {
1178 ERROR("too many branches\n");
1179 }
1180 }
1181 return ret;
1182 }
1183
1184
xtb_fmt_setpos(def,x,y)1185 static void xtb_fmt_setpos(def, x, y)
1186 xtb_fmt *def;
1187 int x, y;
1188 /*
1189 * Sets all position fields of widgets in `def' to x,y.
1190 */
1191 {
1192 int i;
1193
1194 switch (def->type) {
1195 case W_TYPE:
1196 def->wid.w->x_loc = x;
1197 def->wid.w->y_loc = y;
1198 break;
1199 case A_TYPE:
1200 for (i = 0; i < def->align.ni; i++) {
1201 xtb_fmt_setpos(def->align.items[i], x, y);
1202 }
1203 break;
1204 default:
1205 ERROR("bad type");
1206 }
1207 }
1208
1209
xtb_fmt_addpos(def,x,y)1210 static void xtb_fmt_addpos(def, x, y)
1211 xtb_fmt *def;
1212 int x, y;
1213 /*
1214 * Adds the offset specified to all position fields of widgets in `def'.
1215 */
1216 {
1217 int i;
1218
1219 switch (def->type) {
1220 case W_TYPE:
1221 def->wid.w->x_loc += x;
1222 def->wid.w->y_loc += y;
1223 break;
1224 case A_TYPE:
1225 for (i = 0; i < def->align.ni; i++) {
1226 xtb_fmt_addpos(def->align.items[i], x, y);
1227 }
1228 break;
1229 default:
1230 ERROR("bad type");
1231 }
1232 }
1233
xtb_fmt_hort(nd,defs,widths,heights,just,pad,inter,rw,rh)1234 static void xtb_fmt_hort(nd, defs, widths, heights, just, pad, inter, rw, rh)
1235 int nd; /* Number of children */
1236 xtb_fmt *defs[]; /* Definitions themselves */
1237 int widths[]; /* Widths of children */
1238 int heights[]; /* Heights of children */
1239 xtb_just just; /* Justification */
1240 int pad, inter; /* Padding and interspace */
1241 int *rw, *rh; /* Returned size */
1242 /*
1243 * Formats items horizontally subject to the widths and heights
1244 * of the items passed.
1245 */
1246 {
1247 int i;
1248 int max_height = 0;
1249 int tot_width = 0;
1250 int xspot;
1251
1252 /* Find parameters */
1253 for (i = 0; i < nd; i++) {
1254 if (heights[i] > max_height) max_height = heights[i];
1255 tot_width += widths[i];
1256 }
1257 /* Place items -- assumes center justification */
1258 xspot = pad;
1259 for (i = 0; i < nd; i++) {
1260 switch (just) {
1261 case XTB_TOP:
1262 xtb_fmt_addpos(defs[i], xspot, pad);
1263 break;
1264 case XTB_BOTTOM:
1265 xtb_fmt_addpos(defs[i], xspot, max_height - heights[i] + pad);
1266 break;
1267 case XTB_CENTER:
1268 default:
1269 /* Everyone else center */
1270 xtb_fmt_addpos(defs[i], xspot, (max_height - heights[i])/2 + pad);
1271 break;
1272 }
1273 xspot += (widths[i] + inter);
1274 }
1275 /* Figure out resulting size */
1276 *rw = tot_width + (nd-1)*inter + (2 * pad);
1277 *rh = max_height + (2 * pad);
1278 }
1279
1280
xtb_fmt_vert(nd,defs,widths,heights,just,pad,inter,rw,rh)1281 static void xtb_fmt_vert(nd, defs, widths, heights, just, pad, inter, rw, rh)
1282 int nd; /* Number of children */
1283 xtb_fmt *defs[]; /* Definitions themselves */
1284 int widths[]; /* Widths of children */
1285 int heights[]; /* Heights of children */
1286 xtb_just just; /* Justification */
1287 int pad, inter; /* Padding and interspace */
1288 int *rw, *rh; /* Returned size */
1289 /*
1290 * Formats items vertically subject to the widths and heights
1291 * of the items passed.
1292 */
1293 {
1294 int i;
1295 int max_width = 0;
1296 int tot_height = 0;
1297 int yspot;
1298
1299 /* Find parameters */
1300 for (i = 0; i < nd; i++) {
1301 if (widths[i] > max_width) max_width = widths[i];
1302 tot_height += heights[i];
1303 }
1304 /* Place items -- assumes center justification */
1305 yspot = pad;
1306 for (i = 0; i < nd; i++) {
1307 switch (just) {
1308 case XTB_LEFT:
1309 xtb_fmt_addpos(defs[i], pad, yspot);
1310 break;
1311 case XTB_RIGHT:
1312 xtb_fmt_addpos(defs[i], max_width - widths[i] + pad, yspot);
1313 break;
1314 case XTB_CENTER:
1315 default:
1316 /* Everyone else center */
1317 xtb_fmt_addpos(defs[i], (max_width - widths[i])/2 + pad, yspot);
1318 break;
1319 }
1320 yspot += (heights[i] + inter);
1321 }
1322 /* Figure out resulting size */
1323 *rw = max_width + (2 * pad);
1324 *rh = tot_height + (nd-1)*inter + (2 * pad);
1325 }
1326
xtb_fmt_top(def,w,h)1327 static void xtb_fmt_top(def, w, h)
1328 xtb_fmt *def;
1329 unsigned *w, *h;
1330 /*
1331 * Recursive portion of formatter
1332 */
1333 {
1334 unsigned widths[MAX_BRANCH];
1335 unsigned heights[MAX_BRANCH];
1336 int i;
1337
1338 switch (def->type) {
1339 case A_TYPE:
1340 /* Formatting directive */
1341 /* place children and determine sizes */
1342 for (i = 0; i < def->align.ni; i++) {
1343 xtb_fmt_top(def->align.items[i], &(widths[i]), &(heights[i]));
1344 }
1345 /* now format based on direction */
1346 switch (def->align.dir) {
1347 case HORIZONTAL:
1348 xtb_fmt_hort(def->align.ni, def->align.items, widths, heights,
1349 def->align.just, def->align.padding,
1350 def->align.interspace, w, h);
1351 break;
1352 case VERTICAL:
1353 xtb_fmt_vert(def->align.ni, def->align.items, widths, heights,
1354 def->align.just, def->align.padding,
1355 def->align.interspace, w, h);
1356 break;
1357 default:
1358 ERROR("bad direction");
1359 }
1360 break;
1361 case W_TYPE:
1362 /* Simple widget - return size */
1363 *w = def->wid.w->width;
1364 *h = def->wid.w->height;
1365 break;
1366 default:
1367 ERROR("bad type");
1368 }
1369 }
1370
1371 #ifdef DEBUG
xtb_fmt_debug(def)1372 static void xtb_fmt_debug(def)
1373 xtb_fmt *def;
1374 /*
1375 * Dumps formatting structure for debugging purposes.
1376 */
1377 {
1378 int i;
1379
1380 switch (def->type) {
1381 case W_TYPE:
1382 printf("%d %d %d %d\n",
1383 def->wid.w->x_loc, def->wid.w->y_loc,
1384 def->wid.w->width, def->wid.w->height);
1385 break;
1386 case A_TYPE:
1387 for (i = 0; i < def->align.ni; i++) {
1388 xtb_fmt_debug(def->align.items[i]);
1389 }
1390 break;
1391 default:
1392 ERROR("bad type");
1393 }
1394 }
1395 #endif
1396
xtb_fmt_do(def,w,h)1397 xtb_fmt *xtb_fmt_do(def, w, h)
1398 xtb_fmt *def;
1399 unsigned *w, *h;
1400 /*
1401 * Actually does formatting
1402 */
1403 {
1404 /* First zero out all positions */
1405 xtb_fmt_setpos(def, 0, 0);
1406
1407 /* Now call recursive portion */
1408 xtb_fmt_top(def, w, h);
1409
1410 #ifdef DEBUG
1411 xtb_fmt_debug(def);
1412 #endif
1413 return def;
1414 }
1415
xtb_fmt_free(def)1416 void xtb_fmt_free(def)
1417 xtb_fmt *def;
1418 /*
1419 * Frees resources associated with formatting routines
1420 */
1421 {
1422 int i;
1423
1424 if (def->type == A_TYPE) {
1425 for (i = 0; i < def->align.ni; i++) {
1426 xtb_fmt_free(def->align.items[i]);
1427 }
1428 }
1429 free((char *) def);
1430 }
1431
xtb_mv_frames(nf,frames)1432 void xtb_mv_frames(nf, frames)
1433 int nf; /* Number of frames */
1434 xtb_frame frames[]; /* Array of frames */
1435 /*
1436 * Moves frames to the location indicated in the frame
1437 * structure for each item.
1438 */
1439 {
1440 int i;
1441
1442 for (i = 0; i < nf; i++) {
1443 XMoveWindow(t_disp, frames[i].win, frames[i].x_loc, frames[i].y_loc);
1444 }
1445 }
1446
1447