home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume10 / xt-examples / part04 / Graph.c < prev    next >
C/C++ Source or Header  |  1990-11-04  |  11KB  |  353 lines

  1. /***********************************************************
  2. Copyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
  3.  
  4.                         All Rights Reserved
  5.  
  6. Permission to use, copy, modify, and distribute these examples for any
  7. purpose and without fee is hereby granted, provided that the above
  8. copyright notice appear in all copies and that both that copyright
  9. notice and this permission notice appear in supporting documentation,
  10. and that the name of Digital not be used in advertising or publicity
  11. pertaining to distribution of the software without specific, written
  12. prior permission.
  13.  
  14. DIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  15. SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  16. FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
  17. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  18. OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  19. OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  20. OR PERFORMANCE OF THIS SOFTWARE.
  21.  
  22. ******************************************************************/
  23.  
  24. #include <X11/IntrinsicP.h>    /* Intrinsics header file */
  25. #include <X11/StringDefs.h>    /* Resource string definitions */
  26. #include "GraphP.h"        /* Graph private header file */
  27. #include "GraphDispP.h"        /* Graph display object */
  28.  
  29. #define Offset(field) XtOffsetOf(GraphRec, graph.field)
  30.  
  31. static XtResource resources[] = {
  32.     {XtNnumEntries, XtCNumEntries, XtRInt, sizeof(int),
  33.     Offset(num_entries), XtRImmediate, (XtPointer) 0},
  34.     {XtNlabels, XtCLabels, XtRStringTable, sizeof(String *),
  35.         Offset(labels), XtRImmediate, (XtPointer) NULL},
  36.     {XtNvalues, XtCValues, XtRPointer, sizeof(int *),
  37.     Offset(values), XtRImmediate, (XtPointer) NULL},
  38.     {XtNmaxValue, XtCMaxValue, XtRInt, sizeof(int),
  39.     Offset(max_value), XtRImmediate, (XtPointer) 100},
  40.     {XtNscale, XtCScale, XtRInt, sizeof(int),
  41.         Offset(scale), XtRImmediate, (XtPointer) 1}
  42. };
  43. #undef Offset
  44.  
  45. /* Forward declarations */
  46.  
  47. static void ClassInitialize(), Initialize(),
  48.     Redisplay(), Destroy(), Resize(), Realize(),
  49.     InsertChild();
  50. static Boolean SetValues();
  51.  
  52. static CompositeClassExtensionRec compositeExtension = {
  53.     /* next_extension        */ NULL,
  54.     /* record_type        */ NULLQUARK,
  55.     /* version            */ XtCompositeExtensionVersion,
  56.     /* record_size        */ sizeof(CompositeClassExtensionRec),
  57.     /* accepts_objects        */ TRUE
  58. };
  59.  
  60. GraphClassRec graphClassRec = {
  61.     /* Core class part */
  62.   {
  63.     /* superclass         */    (WidgetClass) &compositeClassRec,
  64.     /* class_name         */    "Graph",
  65.     /* widget_size         */    sizeof(GraphRec),
  66.     /* class_initialize      */ ClassInitialize,
  67.     /* class_part_initialize */    NULL,
  68.     /* class_inited          */    FALSE,
  69.     /* initialize         */    Initialize,
  70.     /* initialize_hook       */    NULL,        
  71.     /* realize             */    Realize,
  72.     /* actions             */    NULL,
  73.     /* num_actions         */    0,
  74.     /* resources         */    resources,
  75.     /* num_resources         */    XtNumber(resources),
  76.     /* xrm_class         */    NULLQUARK,
  77.     /* compress_motion         */    TRUE,
  78.     /* compress_exposure     */    XtExposeCompressMultiple,
  79.     /* compress_enterleave   */    TRUE,
  80.     /* visible_interest         */    FALSE,
  81.     /* destroy             */    Destroy,
  82.     /* resize             */    Resize,
  83.     /* expose             */    Redisplay,
  84.     /* set_values         */    SetValues,
  85.     /* set_values_hook       */    NULL,            
  86.     /* set_values_almost     */    XtInheritSetValuesAlmost,  
  87.     /* get_values_hook       */    NULL,            
  88.     /* accept_focus         */    NULL,
  89.     /* version             */    XtVersion,
  90.     /* callback offsets      */ NULL,
  91.     /* tm_table              */ NULL,
  92.     /* query_geometry         */    NULL,
  93.     /* display_accelerator   */ NULL,
  94.     /* extension             */ NULL
  95.   },
  96.     /* Composite class part */
  97.   {
  98.     /* geometry_manager         */    NULL,
  99.     /* change_managed         */    NULL,
  100.     /* insert_child         */    InsertChild,
  101.     /* delete_child         */    XtInheritDeleteChild,
  102.     /* extension         */    (XtPointer) &compositeExtension,
  103.   },
  104.     /* Graph class part    */
  105.   {
  106.     /* extension             */ NULL
  107.   }
  108. };
  109.  
  110. /* Class record pointer */
  111.  
  112. WidgetClass graphWidgetClass = (WidgetClass) &graphClassRec;
  113.  
  114. static Boolean CvtStringToStringList(dpy, args, num_args,
  115.     from, to, data)
  116.     Display *dpy;
  117.     XrmValuePtr args;
  118.     Cardinal *num_args;
  119.     XrmValuePtr from, to;
  120.     XtPointer *data;
  121. {
  122.     register int i, count = 1;
  123.     register char *ch, *start = from->addr;
  124.     static String *list;
  125.     int len;
  126.  
  127.     if (*num_args != 0) {
  128.     XtAppErrorMsg(XtDisplayToApplicationContext(dpy),
  129.        "cvtStringToStringList", "wrongParameters",
  130.        "XtToolkitError",
  131.        "String to string list conversion needs no extra arguments",
  132.        (String *) NULL, (Cardinal *) NULL);
  133.     }
  134.     if (to->addr != NULL && to->size < sizeof(String *)) {
  135.     to->size = sizeof(String *);
  136.     return FALSE;
  137.     }
  138.     if (start == NULL || *start == '\0') list = NULL;
  139.     else {
  140.     for (ch = start; *ch != '\0'; ch++) {    /* Count strings */
  141.         if (*ch == '\n') count++;
  142.     }
  143.     list = (String *) XtCalloc(count+1, sizeof(String));
  144.  
  145.     for (i = 0; i < count; i++) {
  146.         for (ch = start; *ch != '\n' && *ch != '\0'; ch++) {}
  147.         len = ch - start;
  148.         list[i] = XtMalloc(len + 1);
  149.         (void) strncpy(list[i], start, len);
  150.         list[i][len] = '\0';
  151.         start = ch + 1;
  152.     }
  153.     }
  154.     if (to->addr == NULL) to->addr = (caddr_t) &list;
  155.     else *(String **) to->addr = list;
  156.     to->size = sizeof(String *);
  157.     return TRUE;
  158. }
  159.  
  160. static void StringListDestructor(app, to, converter_data,
  161.     args, num_args)
  162.     XtAppContext app;
  163.     XrmValuePtr to;
  164.     XtPointer converter_data;
  165.     XrmValuePtr args;
  166.     Cardinal *num_args;
  167. {
  168.     String *list = (String *) to->addr;
  169.     register String *entry;
  170.  
  171.     if (list == NULL) return;
  172.  
  173.     for (entry = list; entry != NULL; entry++) {
  174.     XtFree((XtPointer) entry);
  175.     }
  176.  
  177.     XtFree((XtPointer) list);
  178. }
  179.  
  180. static void ClassInitialize()
  181. {
  182.     /* Register a converter for string to string list */
  183.  
  184.     XtSetTypeConverter(XtRString, XtRStringTable,
  185.         CvtStringToStringList, (XtConvertArgList) NULL, 0,
  186.         XtCacheAll | XtCacheRefCount, StringListDestructor);
  187. }
  188.  
  189. static void Initialize(request, new, args, num_args)
  190.     Widget request, new;
  191.     ArgList args;
  192.     Cardinal *num_args;
  193. {
  194.     register GraphWidget gw = (GraphWidget) new;
  195.     int *values;
  196.     register int i;
  197.     String label;
  198.  
  199.     /* Copy the values */
  200.     values = (int *) XtCalloc(gw->graph.num_entries, sizeof(int));
  201.     for (i = 0; i < gw->graph.num_entries; i++) {
  202.     values[i] = gw->graph.values[i];
  203.     }
  204.     gw->graph.values = values;
  205.  
  206.     /* If labels is not NULL, make sure there are enough of them now
  207.        to avoid an error some random other place. */
  208.     if (gw->graph.labels != NULL) {
  209.     for (i = 0; i < gw->graph.num_entries; i++) {
  210.         label = gw->graph.labels[i];
  211.     }
  212.     }
  213. }
  214.  
  215. static Boolean SetValues(old, req, new, args, num_args)
  216.     Widget old, req, new;
  217.     ArgList args;
  218.     Cardinal *num_args;
  219. {
  220.     register GraphWidget oldgraph = (GraphWidget) old;
  221.     register GraphWidget newgraph = (GraphWidget) new;
  222.     int *values;
  223.     String label;
  224.     register int i;
  225.  
  226. #define NE(field) (newgraph->graph.field != oldgraph->graph.field)
  227. #define EQ(field) (newgraph->graph.field == oldgraph->graph.field)
  228.  
  229.     if (NE(values)) {
  230.     values = (int *) XtCalloc(newgraph->graph.num_entries,
  231.         sizeof(int));
  232.     XtFree(oldgraph->graph.values);
  233.     for (i = 0; i < newgraph->graph.num_entries; i++) {
  234.         values[i] = newgraph->graph.values[i];
  235.     }
  236.     newgraph->graph.values = values;
  237.     return TRUE;
  238.     }
  239.  
  240.     /* If num_entries changed but not the labels or values,
  241.        something's wrong */
  242.     if (NE(num_entries) && (EQ(labels) || EQ(values))) {
  243.     XtAppErrorMsg(XtWidgetToApplicationContext(new),
  244.         "countError", "numEntries", "WidgetError",
  245.         "Number of graph entries changed but not labels or values",
  246.         (String *) NULL, (Cardinal *) NULL);
  247.     }
  248.  
  249.     if (NE(labels) && newgraph->graph.labels != NULL) {
  250.     for (i = 0; i < newgraph->graph.num_entries; i++) {
  251.         label = newgraph->graph.labels[i];
  252.     }
  253.     }
  254.  
  255.     return NE(num_entries) || NE(labels) || NE(max_value);
  256. #undef NE
  257. }
  258.  
  259. static void Destroy(w)
  260.     Widget w;
  261. {
  262.     GraphWidget gw = (GraphWidget) w;
  263.  
  264.     XtFree((char *) gw->graph.values);
  265. }
  266.  
  267. static void InsertChild(w)
  268.     Widget w;
  269. {
  270.     String params[2];
  271.     Cardinal num_params;
  272.     CompositeWidget parent = (CompositeWidget) XtParent(w);
  273.     GraphDisplayObjectClass childClass;
  274.  
  275.     if (!XtIsSubclass(w, graphDisplayObjectClass)) {
  276.     params[0] = XtClass(w)->core_class.class_name;
  277.     params[1] = XtClass(parent)->core_class.class_name;
  278.     num_params = 2;
  279.     XtAppErrorMsg(XtWidgetToApplicationContext(w),
  280.         "childError", "class", "WidgetError",
  281.         "Children of class %s cannot be added to %n widgets",
  282.         params, &num_params);
  283.     }
  284.  
  285.     if (parent->composite.num_children != 0) {
  286.     params[0] = XtClass(parent)->core_class.class_name;
  287.     num_params = 1;
  288.     XtAppErrorMsg(XtWidgetToApplicationContext(w),
  289.         "childError", "number", "WidgetError",
  290.         "%s widgets can only take one child",
  291.         params, &num_params);
  292.     }
  293.  
  294.     (*((CompositeWidgetClass)(graphWidgetClass->
  295.         core_class.superclass))->composite_class.insert_child) (w);
  296.  
  297.     /* Give the child a chance to compute our dimensions */
  298.  
  299.     childClass = (GraphDisplayObjectClass) XtClass(w);
  300.     if (childClass->graphDisplay_class.compute_size != NULL) {
  301.     (*childClass->graphDisplay_class.compute_size) (parent);
  302.     }
  303. }
  304.  
  305. static void Realize(w, valueMask, attributes)
  306.     Widget w;
  307.     XtValueMask *valueMask;
  308.     XSetWindowAttributes *attributes;
  309. {
  310.     GraphWidget gw = (GraphWidget) w;
  311.     String params[2];
  312.     Cardinal num_params;
  313.  
  314.     if (gw->composite.num_children != 1) {
  315.     params[0] = XtClass(w)->core_class.class_name;
  316.     num_params = 1;
  317.     XtAppErrorMsg(XtWidgetToApplicationContext(w),
  318.         "childError", "number", "WidgetError",
  319.         "%s widgets must have exactly one child",
  320.         params, &num_params);
  321.     }
  322.  
  323.     (*graphWidgetClass->core_class.superclass->core_class.realize)
  324.         (w, valueMask, attributes);
  325. }
  326.  
  327. static void Redisplay(w, event, region)
  328.     Widget w;
  329.     XEvent *event;
  330.     Region region;
  331. {
  332.     GraphWidget gw = (GraphWidget) w;
  333.     GraphDisplayObject d =
  334.         (GraphDisplayObject) gw->composite.children[0];
  335.     GraphDisplayObjectClass childClass;
  336.  
  337.     childClass = (GraphDisplayObjectClass) XtClass((Widget) d);
  338.     if (childClass->graphDisplay_class.expose != NULL) {
  339.     (*childClass->graphDisplay_class.expose) (w, event, region);
  340.     }
  341. }
  342. static void Resize(w)
  343.     Widget w;
  344. {
  345.     /* If widget is realized, clear and redisplay */
  346.  
  347.     if (XtIsRealized(w)) {
  348.     XClearWindow(XtDisplay(w), XtWindow(w));
  349.     (*(XtClass(w)->core_class.expose))(w,
  350.         (XEvent *) NULL, (Region) NULL);
  351.     }
  352. }   
  353.