xtb.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:37k
源码类别:

通讯编程

开发平台:

Visual C++

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