home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / fontutils-0.6-base.tgz / fontutils-0.6-base.tar / fsf / fontutils / widgets / Item.c < prev    next >
C/C++ Source or Header  |  1992-03-27  |  13KB  |  370 lines

  1. /* Item.c: implementation of an Item widget, for simple user
  2.    interaction.
  3.  
  4. Copyright (C) 1992 Free Software Foundation, Inc.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "config.h"
  21.  
  22. #include "xt-common.h"
  23. #include <X11/IntrinsicP.h>
  24. #include <X11/Xaw/Label.h>
  25. #include <X11/Xaw/LabelP.h>
  26. #include <X11/Xaw/AsciiText.h>
  27.  
  28.  
  29. #include "ItemP.h"
  30.  
  31.  
  32. /* These routines perform the actions.  The actions are specified in the
  33.    app-defaults file; they take place in the AsciiText widget we create,
  34.    rather than the Item widget itself.  */
  35. static action_proc_type accept_value;
  36.  
  37. /* The mapping of action names to procedures.  */
  38. static XtActionsRec item_actions[]
  39.   = { { "AcceptValue", accept_value },
  40.     };
  41.  
  42.  
  43. /* This structure defines the default values of the resources specific
  44.    to the Item widget.  */
  45. #define OFFSET(field) XtOffset (ItemWidget, item.field)
  46. static XtResource item_resources[]
  47.   = { { XtNcallback, XtCCallback, XtRCallback, sizeof (XtCallbackList),
  48.           OFFSET (accept_callback), XtRCallback, NULL },
  49.       STRING_RESOURCE (label, Label, NULL),
  50.       STRING_RESOURCE (value, Value, ""),
  51.       IMMEDIATE_RESOURCE (length, Length, Dimension, 1),
  52.     };
  53.  
  54. /* Routines in the class record.  */
  55. static void item_initialize (Widget, Widget, ArgList, Cardinal *);
  56. static void item_realize (Widget, XtValueMask *, XSetWindowAttributes *);
  57. static Boolean item_set_values (Widget, Widget, Widget, ArgList, Cardinal *);
  58. static void item_expose (Widget, XEvent *, Region);
  59. static void item_destroy (Widget);
  60.  
  61. /* We can inherit most things in the instantiation of the class record.  */
  62. ItemClassRec itemClassRec
  63.   = { /* Core class fields.  */
  64.       { /* superclass          */ (WidgetClass) &simpleClassRec,
  65.         /* class_name          */ "Item",
  66.         /* widget_size          */ sizeof (ItemRec),
  67.         /* class_initialize       */ NULL,
  68.         /* class_part_initialize*/ NULL,
  69.         /* class_inited           */ FALSE,
  70.         /* initialize          */ item_initialize,
  71.         /* initialize_hook    */ NULL,
  72.         /* realize        */ item_realize,
  73.         /* actions        */ item_actions,
  74.         /* num_actions          */ XtNumber (item_actions),
  75.         /* resources          */ item_resources,
  76.         /* num_resources    */ XtNumber (item_resources),
  77.         /* xrm_class          */ NULLQUARK,
  78.         /* compress_motion    */ TRUE,
  79.         /* compress_exposure      */ TRUE,
  80.         /* compress_enterleave    */ TRUE,
  81.         /* visible_interest    */ FALSE,
  82.         /* destroy        */ item_destroy,
  83.         /* resize        */ XtInheritResize,
  84.         /* expose        */ item_expose,
  85.         /* set_values          */ item_set_values,
  86.         /* set_values_hook    */ NULL,
  87.         /* set_values_almost    */ XtInheritSetValuesAlmost,
  88.         /* get_values_hook    */ NULL,
  89.         /* accept_focus         */ NULL,
  90.         /* version        */ XtVersion,
  91.         /* callback_private       */ NULL,
  92.         /* tm_table        */ NULL,
  93.         /* query_geometry    */ XtInheritQueryGeometry,
  94.         /* display_accelerator    */ XtInheritDisplayAccelerator,
  95.         /* extension        */ NULL
  96.       },
  97.  
  98.       /* Simple class fields.  */
  99.       { /* change_sensitive */ XtInheritChangeSensitive },
  100.  
  101.       /* Item class fields.  */
  102.       { 0 }
  103.     };
  104.  
  105. WidgetClass itemWidgetClass = (WidgetClass) &itemClassRec;
  106.  
  107.  
  108.  
  109. /* Class routines.  */
  110.  
  111. /* This routine is called at widget creation time by the toolkit, after
  112.    our superclasses have been initialized.  REQUEST is the widget that
  113.    was originally requested by the user; NEW is the widget that has been
  114.    created in response to the requests by our superclasses.  We do not
  115.    use the parameters ARGS and N_ARGS.
  116.    
  117.    We create two children, a Label and an AsciiText widget.  Because we
  118.    are not a subclass of Composite, we must realize and otherwise
  119.    operate on those widgets ourselves.
  120.    
  121.    Since it is the AsciiText widget that handles the events, we must
  122.    replace its event bindings with our own, where they conflict.  The
  123.    Intrinsics have already converted the string representation of the
  124.    translation table in the class record into the compiled form. 
  125.    (Incidentally, perhaps accelerators would be a better way to do this.
  126.    I'm not sure.)   */
  127.  
  128. static void
  129. item_initialize (Widget request, Widget new, ArgList args, Cardinal *n_args)
  130. {
  131.   Widget label_widget, value_widget;
  132.   XFontStruct *value_font;
  133.   unsigned value_width;
  134.   ItemWidget iw = (ItemWidget) new;
  135.   Arg label_args[]
  136.     = { { XtNlabel,    (XtArgVal) (iw->item.label ? : iw->core.name) },
  137.       };
  138.  
  139.   string temp = xmalloc (iw->item.length + 1);
  140.   Arg text_args[]
  141.     = { { XtNstring,        (XtArgVal) temp },
  142.         { XtNlength,        iw->item.length },
  143.       };
  144.   
  145.   /* Create the widget to handle the label.  */
  146.   iw->item.label_widget = label_widget
  147.     = XtCreateWidget ("item label", labelWidgetClass, new, XTARG (label_args));
  148.   label_widget->core.x = 0;
  149.   label_widget->core.y = 0;
  150.  
  151.   if (strlen (iw->item.value) > iw->item.length)
  152.     {
  153.       string error_params[]
  154.         = { itoa (iw->item.length), iw->item.value };
  155.       *n_args = XtNumber (error_params);
  156.       XtErrorMsg ("invalidParameter", "itemInitialize", "ItemError",
  157.                   "Length resource of %s too short for value `%s'",
  158.                   error_params, n_args);
  159.     }
  160.                     
  161.   /* Save the string in our own storage.  */
  162.   strcpy (temp, iw->item.value);
  163.   iw->item.value = temp;
  164.   
  165.   /* Create the widget to handle the editing.  */
  166.   iw->item.value_widget = value_widget
  167.     = XtCreateWidget ("item value", asciiTextWidgetClass, new,
  168.                       XTARG (text_args));
  169.  
  170.   /* Since the default width for Text objects is a constant number
  171.      (100), we compute the longest width we expect here, based on the
  172.      Text's font and our own length resource. */
  173.   XtVaGetValues (value_widget, XtNfont, (XtArgVal) &value_font, NULL, NULL);
  174.   value_width = iw->item.length * (value_font->max_bounds.rbearing
  175.                                    - value_font->min_bounds.lbearing);
  176.   XtVaSetValues (value_widget, XtNwidth, value_width, NULL, NULL);
  177.  
  178.   /* Put the value widget next to the label widget.  */
  179.   value_widget->core.x = label_widget->core.width;
  180.   value_widget->core.y = 0;
  181.  
  182.   /* Key events should go to the AsciiText widget.  */
  183.   XtSetKeyboardFocus ((Widget) iw, value_widget);
  184.   
  185.   /* If our own width and/or height are zero, set them appropriately.  */
  186.   if (iw->core.width == 0)
  187.     iw->core.width = label_widget->core.width + value_widget->core.width; 
  188.  
  189.   if (iw->core.height == 0)
  190.     iw->core.height
  191.       = MAX (label_widget->core.height, value_widget->core.height);
  192.  
  193.   /* Set up normal and inverse GC's for highlighting.  */
  194.   {
  195.     XGCValues values;
  196.     
  197.     iw->item.normal_GC = ((LabelWidget) label_widget)->label.normal_GC;
  198.     
  199.     values.foreground = iw->core.background_pixel;
  200.     values.background = ((LabelWidget) label_widget)->label.foreground;
  201.     iw->item.highlight_GC = XtGetGC ((Widget) iw, GCForeground | GCBackground,
  202.                                      &values);
  203.   }
  204. }
  205.  
  206.  
  207. /* Because we have children, and are not a subclass of Composite, we
  208.    must realize the children ourselves.  (See p.41 of the Xt manual.) */
  209.  
  210. static void
  211. item_realize (Widget w, XtValueMask *value_mask, XSetWindowAttributes *attrs)
  212. {
  213.   ItemWidget iw = (ItemWidget) w;
  214.   
  215.   /* Create our own window in the same way as Core's realize procedure.  */
  216.   XtCreateWindow (w, CopyFromParent, CopyFromParent, *value_mask, attrs);
  217.   
  218.   /* Create the windows for our children.  */
  219.   XtRealizeWidget (iw->item.label_widget);
  220.   XtRealizeWidget (iw->item.value_widget);
  221.  
  222.   /* Map those windows.  */
  223.   XtMapWidget (iw->item.label_widget);
  224.   XtMapWidget (iw->item.value_widget);
  225. }
  226.  
  227.  
  228. /* This routine is called when one of the resources in the widget
  229.    changes; for example, in response to an XtSetValues call.  The
  230.    toolkit has already modified our resources.  OLD is the widget before
  231.    any resources were changed; REQUEST is the widget before any class
  232.    `set_values' procedures have been called; NEW is the widget as
  233.    updated by the superclasses.  We don't handle cases where the new
  234.    values should cause resizes.  */
  235.  
  236. static Boolean
  237. item_set_values (Widget old, Widget request, Widget new, ArgList args,
  238.                  Cardinal *n_args) 
  239. {
  240.   Boolean redisplay = False;
  241.   ItemWidget old_iw = (ItemWidget) old;
  242.   ItemWidget iw = (ItemWidget) new;
  243.   Arg label_args[] = { { XtNlabel, (XtArgVal) iw->item.label } };
  244.   boolean needs_length = false;
  245.   
  246.   /* It is safe to assume that the `label_widget' field is initialized,
  247.      since `item_initialize' must have been called before us, and the
  248.      application is not supposed to have direct access to the Label widget.  */
  249.   if (old_iw->item.label != iw->item.label)
  250.     {
  251.       XtSetValues (iw->item.label_widget, XTARG (label_args));
  252.       redisplay = True;
  253.     }
  254.  
  255.   if (old_iw->item.length != iw->item.length)
  256.     { /* They changed the length.  Make sure it's long enough.  */
  257.       if (strlen (iw->item.value) > iw->item.length)
  258.         {
  259.           string error_params[]
  260.             = { itoa (iw->item.length), iw->item.value };
  261.           *n_args = XtNumber (error_params);
  262.           XtErrorMsg ("invalidParameter", "itemSetValues", "ItemError",
  263.                       "Length resource of %s too short for value `%s'",
  264.                       error_params, n_args);
  265.         }
  266.       needs_length = true;
  267.     }
  268.  
  269.   if (needs_length || old_iw->item.value != iw->item.value)
  270.     { /* The string to edit has changed.  */
  271.       string temp = xmalloc (iw->item.length + 1);
  272.       Arg text_args[] = { { XtNstring,        (XtArgVal) temp },
  273.                           { XtNlength,        iw->item.length },
  274.                         };
  275.  
  276.       strcpy (temp, iw->item.value);
  277.       free (old_iw->item.value);
  278.       iw->item.value = temp;
  279.  
  280.       XtSetValues (iw->item.value_widget, XTARG (text_args));
  281.       redisplay = true;
  282.     }
  283.     
  284.   return redisplay;
  285. }
  286.  
  287.  
  288. /* This routine is called whenever part of the widget needs to be
  289.    redisplayed.  We simply pass on our arguments to our child widgets,
  290.    since we don't have any information ourselves.  */
  291.  
  292. static void
  293. item_expose (Widget w, XEvent *event, Region region)
  294. {
  295.   ItemWidget iw = (ItemWidget) w;
  296.   Widget lw = iw->item.label_widget;
  297.   Widget tw = iw->item.value_widget;
  298.   
  299.   labelWidgetClass->core_class.expose (lw, event, region);
  300.   asciiTextWidgetClass->core_class.expose (tw, event, region);
  301. }
  302.  
  303.  
  304. /* This routine is called when the widget is destroyed.  We are not a
  305.    subclass of Composite, so we must destroy our children ourselves.  */
  306.  
  307. static void
  308. item_destroy (Widget w)
  309. {
  310.   ItemWidget iw = (ItemWidget) w;
  311.   
  312.   XtDestroyWidget (iw->item.label_widget);
  313.   XtDestroyWidget (iw->item.value_widget);  
  314.   free (iw->item.value);
  315. }
  316.  
  317.  
  318.  
  319. /* This convenience procedure saves clients the trouble of constructing
  320.    an ArgList to get the value string from the Item widget.  Since we
  321.    use the string in place, we don't have to get the current value from
  322.    our Text widget.  */
  323.  
  324. string
  325. ItemGetValueString (Widget w)
  326. {
  327.   ItemWidget iw = (ItemWidget) w;
  328.   return iw->item.value;
  329. }
  330.  
  331.  
  332. /* A similar routine, for the label string.  */
  333. string
  334. ItemGetLabelString (Widget w)
  335. {
  336.   ItemWidget iw = (ItemWidget) w;
  337.   return iw->item.label;
  338. }
  339.  
  340.  
  341. /* This can't be duplicated with a resource request, but it's pretty
  342.    similar: a client might need to get the value widget itself.  */
  343.  
  344. Widget
  345. ItemGetValueWidget (Widget w)
  346. {
  347.   ItemWidget iw = (ItemWidget) w;
  348.   return iw->item.value_widget;
  349. }
  350.  
  351.  
  352.  
  353. /* Call the routines on the callback list.  W is the AsciiText widget we
  354.    created, rather than an Item widget, because the events actually
  355.    take place in the former.  (Because we didn't use accelerators.)  */
  356.  
  357. static void
  358. accept_value (Widget w, XEvent *event, String *s, Cardinal *c)
  359. {
  360.   ItemWidget iw = (ItemWidget) XtParent (w);
  361.   Display *display = XtDisplay (iw);
  362.   LabelWidget lw = (LabelWidget) iw->item.label_widget;
  363.   
  364.   lw->label.normal_GC = iw->item.highlight_GC;
  365.   XClearArea (display, XtWindow (iw), 0, 0,
  366.               iw->core.width, iw->core.height, True);
  367.   XtCallCallbacks ((Widget) iw, XtNcallback, iw->item.value);
  368.   lw->label.normal_GC = iw->item.normal_GC;
  369. }
  370.