home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d3xx / d386 / xlispstat.lha / XLispStat / src3.lzh / UNIX / X11text.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-30  |  9.7 KB  |  330 lines

  1. /* X11text - text items for X11 dialogs                                */
  2. /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney                  */
  3. /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz    */
  4. /* You may give out copies of this software; for conditions see the    */
  5. /* file COPYING included with this distribution.                       */
  6.  
  7. /***********************************************************************/
  8. /**                                                                   **/
  9. /**                    General Includes and Definitions               **/
  10. /**                                                                   **/
  11. /***********************************************************************/
  12.  
  13. #include <X11/Xlib.h>
  14. #include <X11/Xutil.h>
  15. #include <X11/Xos.h>
  16. #include <X11/keysym.h>
  17.  
  18. #include "dialogs.h"
  19.  
  20. extern Display *StX11Display();
  21. extern Point DialogStringSize();
  22. extern LVAL StX11ItemObject();
  23. extern char *checkstring();
  24.  
  25. typedef struct {
  26.   unsigned long fore, back;
  27. } ColorPair;
  28.  
  29. # define STATIC_TEXT_LEAD 5
  30. # define STATIC_TEXT_PAD 10
  31. # define EDIT_TEXT_LEAD 10
  32. # define EDIT_TEXT_PAD 20
  33.  
  34. /***********************************************************************/
  35. /**                                                                   **/
  36. /**                        Global Variables                           **/
  37. /**                                                                   **/
  38. /***********************************************************************/
  39.  
  40. /* configuration parameters - should be set using the defaults database */
  41. extern XFontStruct *DialogFont;
  42. extern unsigned long DialogBorderColor;
  43. extern ColorPair DialogC;
  44. extern unsigned int text_border_width;
  45.  
  46. extern GC DialogGC, DialogRGC;
  47.  
  48. extern XContext ObjectContext, TextCursorContext;
  49.  
  50. extern Cursor IBeamCursor;
  51.  
  52. /***********************************************************************/
  53. /**                                                                   **/
  54. /**                            Text Items                             **/
  55. /**                                                                   **/
  56. /***********************************************************************/
  57.  
  58. static max_line_size(s)
  59.     char *s;
  60. {
  61.   char *bp;
  62.   int w;
  63.   Point sz;
  64.   
  65.   for (w = 0; *s != '\0'; s++) {
  66.     for (bp = buf; *s != '\0' && *s != '\r' && *s != '\n'; s++, bp++)
  67.       *bp = *s;
  68.     *bp = '\0';
  69.     sz = DialogStringSize(buf);
  70.     w = max(w, sz.h);
  71.   }
  72.   return(w);
  73. }
  74.  
  75. static draw_text(dpy, win, item, erase, move_cursor)
  76.      Display *dpy;
  77.      Window win;
  78.      LVAL item;
  79.      int erase, move_cursor;
  80. {
  81.   char *text, *bp;
  82.   int x, y, len, ascent, font_height, editable, cx, cy;
  83.   Window cursor;
  84.  
  85.   ascent = DialogFont->max_bounds.ascent;
  86.   font_height = ascent + DialogFont->max_bounds.descent;
  87.  
  88.   if (erase) XClearWindow(dpy, win);
  89.  
  90.   text = checkstring(slot_value(item, s_text));
  91.   editable = (slot_value(item, s_editable) != NIL) ? TRUE : FALSE;
  92.  
  93.   x = (editable) ? EDIT_TEXT_LEAD : 0;
  94.   y = (editable) ? EDIT_TEXT_LEAD + ascent : STATIC_TEXT_LEAD + ascent;
  95.   if (editable) {
  96.     len = strlen(text);
  97.     if (move_cursor) {
  98.       cy = EDIT_TEXT_LEAD;
  99.       cx = EDIT_TEXT_LEAD + XTextWidth(DialogFont, text, len);
  100.       if (XFindContext(dpy, win, TextCursorContext, &cursor) != 0)
  101.     xlfail("can't find text cursor context");
  102.       XMoveWindow(dpy, cursor, cx, cy);
  103.     }
  104.     XDrawString(dpy, win, DialogGC, x, y, text, len);
  105.   }
  106.   else {
  107.     for(; *text != '\0'; text++, y += font_height + STATIC_TEXT_LEAD) {
  108.       for (bp = buf;
  109.        *text != '\0' && *text != '\r' && *text != '\n';
  110.        text++, bp++)
  111.     *bp = *text;
  112.       *bp = '\0';
  113.       len = strlen(buf);
  114.       XDrawString(dpy, win, DialogGC, x, y, buf, len);
  115.     }
  116.   }
  117. }
  118.  
  119. #define bufsize 20
  120.  
  121. static do_key(report, dpy, win, item)
  122.      XEvent report;
  123.      Display *dpy;
  124.      Window win;
  125.      LVAL item;
  126. {
  127.   char buffer[bufsize], *text;
  128.   int count, len, erase = FALSE, result = FALSE;
  129.   KeySym keysym;
  130.   /*XComposeStatus compose;*/
  131.   
  132.   text = checkstring(slot_value(item, s_text));
  133.   strcpy(buf, text);
  134.  
  135.   count = XLookupString(&report, buffer, bufsize, &keysym, nil /*&compose*/);
  136.   if (keysym == XK_Return || keysym == XK_KP_Enter || keysym == XK_Linefeed) {
  137.     result = TRUE;
  138. /*    XBell(dpy, 100);*/
  139.   }
  140.   else if ((keysym >= XK_KP_Space && keysym <= XK_KP_9) 
  141.        || (keysym >= XK_space && keysym <= XK_asciitilde)) {
  142.     if (strlen(buf) + count >= STRMAX) XBell(dpy, 100);
  143.     else strncat(buf, buffer, count);
  144.   }
  145.   else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
  146.     ; /* do nothing because it is a modifier key */
  147.   else if (keysym >= XK_F1 && keysym <= XK_F35) {
  148.     if (count == 0) XBell(dpy, 100);
  149.     else if (strlen(buf) + count >= STRMAX) XBell(dpy, 100);
  150.     else strncat(buf, buffer, count);
  151.   }
  152.   else if (keysym == XK_BackSpace || keysym == XK_Delete) {
  153.     if ((len = strlen(buf)) > 0) {
  154.       buf[len - 1] = '\0';
  155.       erase = TRUE;
  156.     }
  157.     else XBell(dpy, 100);
  158.   }
  159.   else XBell(dpy, 100);
  160.  
  161.   set_slot_value(item, s_text, make_string(buf));
  162.   draw_text(dpy, win, item, erase, TRUE);
  163.   return(result);
  164. }
  165.  
  166. static LVAL text_handler(report, modal)
  167.      XEvent report;
  168.      int modal;
  169. {
  170.   Display *dpy = StX11Display();
  171.   Window win, cursor;
  172.   LVAL item, result = NIL;
  173.   int editable;
  174.  
  175.   win = report.xany.window;
  176.   item = StX11ItemObject(dpy, win);
  177.   editable = (slot_value(item, s_editable) != NIL) ? TRUE : FALSE;
  178.   if (item != NIL) {
  179.     switch (report.type) {
  180.     case Expose:
  181.       draw_text(dpy, win, item, FALSE, TRUE);
  182.       break;
  183.     case KeyPress:
  184.       if (editable && do_key(report, dpy, win, item) && modal)
  185.     result = slot_value(slot_value(item, s_dialog), s_default_button);
  186.       break;
  187.     case ButtonPress:
  188.       break;
  189.     case ButtonRelease:
  190.       break;
  191.     case EnterNotify:
  192.       if (editable && report.xcrossing.subwindow == None
  193.       && report.xcrossing.focus) {
  194.     if (XFindContext(dpy, win, TextCursorContext, &cursor) != 0)
  195.       xlfail("can't find text cursor context");
  196.     XSetWindowBackground(dpy, cursor, DialogC.fore);
  197.     XClearWindow(dpy, cursor);
  198.     XSetWindowBorderWidth(dpy, win, text_border_width + 1);
  199.       }
  200.       break;
  201.     case LeaveNotify:
  202.       if (editable && report.xcrossing.subwindow == None
  203.       && report.xcrossing.focus) {
  204.     if (XFindContext(dpy, win, TextCursorContext, &cursor) != 0)
  205.       xlfail("can't find text cursor context");
  206.     XSetWindowBackground(dpy, cursor, DialogC.back);
  207.     XClearWindow(dpy, cursor);
  208.     XSetWindowBorderWidth(dpy, win, text_border_width);
  209.       }
  210.       break;
  211.     default: 
  212.       break;
  213.     }
  214.   }
  215.   return(result);
  216. }
  217.  
  218. InstallTextItem(win, item)
  219.      Window win;
  220.      LVAL item;
  221. {
  222.   Display *dpy = StX11Display();
  223.   Point loc, size;
  224.   Window field, cursor;
  225.   int editable, ascent;
  226.   LVAL s_window_id = xlenter("WINDOW-ID");
  227.     
  228.   loc = ListToPoint(slot_value(item, s_location));
  229.   size = ListToPoint(slot_value(item, s_size));
  230.   editable = (slot_value(item, s_editable) != NIL) ? TRUE : FALSE;
  231.   field = XCreateSimpleWindow(dpy, win, loc.h, loc.v, size.h, size.v,
  232.                   (editable) ? text_border_width : 0,
  233.                                DialogBorderColor, DialogC.back);
  234.   if (editable)
  235.     XSelectInput(dpy, field,
  236.          ExposureMask | EnterWindowMask | LeaveWindowMask | 
  237.          KeyPressMask | ButtonPressMask | ButtonReleaseMask);
  238.   else XSelectInput(dpy, field, ExposureMask);
  239.   if (editable) {
  240.     XDefineCursor(dpy, field, IBeamCursor);
  241.     ascent = DialogFont->max_bounds.ascent;
  242.     cursor = XCreateSimpleWindow(dpy, field, 
  243.                  EDIT_TEXT_LEAD, EDIT_TEXT_LEAD,
  244.                  ascent / 2, ascent,
  245.                  text_border_width, 
  246.                  DialogBorderColor, DialogC.back);
  247.     if (XSaveContext(dpy, field, TextCursorContext, (XContext) cursor) != 0)
  248.       xlfail("can't install cursor for text field");
  249.     XMapWindow(dpy, cursor);
  250.   }
  251.  
  252.   set_slot_value(item, s_window_id, cvfixnum((FIXTYPE) field));
  253.  
  254.   install_dialog_item_handler(dpy, field, text_handler, item);
  255.   if (XSaveContext(dpy, field, ObjectContext, (XContext) item) != 0)
  256.     xlfail("could not install object in window");
  257. }
  258.  
  259. DeleteTextItem(win, item)
  260.      Window win;
  261.      LVAL item;
  262. {
  263.   Display *dpy = StX11Display();
  264.   Window field;
  265.   LVAL s_window_id = xlenter("WINDOW-ID");
  266.  
  267.   field = (Window) getfixnum(slot_value(item, s_window_id));
  268.  
  269.   delete_dialog_item_handler(dpy, field);
  270.   if (XDeleteContext(dpy, field, ObjectContext) != 0)
  271.     xlfail("cound not delete object context");
  272.   if (slot_value(item, s_editable) != nil 
  273.       && XDeleteContext(dpy, field, TextCursorContext) != 0)
  274.     xlfail("cound not delete cursor context");
  275.   set_slot_value(item, s_window_id, NIL);
  276. }
  277.  
  278. DialogTextGetDefaultSize(item, width, height)
  279.      LVAL item;
  280.      int *width, *height;
  281. {
  282.   Point sz, em_sz;
  283.   LVAL text = slot_value(item, s_text);
  284.   LVAL text_length = slot_value(item, xlenter("TEXT-LENGTH"));
  285.   int w = 0;
  286.   char *s;
  287.   
  288.   em_sz = DialogStringSize("M");
  289.   sz.v = em_sz.v + 2 * STATIC_TEXT_LEAD;
  290.   if (stringp(text)) {
  291.     w = max_line_size(getstring(text));
  292.     s = (char *) getstring(text);
  293.     for (sz.v = em_sz.v + 2 * STATIC_TEXT_LEAD; *s != '\0'; s++)
  294.       if (*s == '\n' || *s == '\r') sz.v += em_sz.v + STATIC_TEXT_LEAD;
  295.   }
  296.   if (fixp(text_length)) {
  297.     w = max((int) (getfixnum(text_length) * em_sz.h), w);
  298.   }
  299.   if (slot_value(item, s_editable) != NIL) {
  300.     if (width != nil) *width = w + EDIT_TEXT_PAD;
  301.     if (height != nil) *height = em_sz.v + 2 * EDIT_TEXT_LEAD;
  302.   }
  303.   else {
  304.     if (width != nil) *width = w + STATIC_TEXT_PAD;
  305.     if (height != nil) *height = sz.v;
  306.   }
  307. }
  308.  
  309. LVAL DialogTextItemText(item, set, text)
  310.      LVAL item;
  311.      int set;
  312.      char *text;
  313. {
  314.   Display *dpy = StX11Display();
  315.   LVAL win_id;
  316.   LVAL s_window_id = xlenter("WINDOW-ID");
  317.  
  318.   if (set) {
  319.     set_slot_value(item, s_text, make_string(text));
  320.     win_id = slot_value(item, s_window_id);
  321.     if (fixp(win_id)) 
  322.       draw_text(dpy, (Window) getfixnum(win_id), item, TRUE, TRUE);
  323.   }
  324.   return(slot_value(item, s_text));
  325. }
  326.  
  327. #ifdef TODO
  328. mouse editing support
  329. #endif TODO
  330.