home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume10 / xt-examples / part05 / LabelGadge.c next >
C/C++ Source or Header  |  1990-11-04  |  13KB  |  423 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 <string.h>        /* Needed for string manipulation */
  25. #include <X11/IntrinsicP.h>    /* Intrinsics header file */
  26. #include <X11/StringDefs.h>    /* Resource string definitions */
  27. #include "LabelGadgP.h"        /* LabelGadget private header file */
  28.  
  29. #define Offset(field) XtOffsetOf(LabelGadgetRec, label.field)
  30.  
  31. static XtResource resources[] = {
  32.     {XtNlabel, XtCLabel, XtRString, sizeof(String),
  33.     Offset(label), XtRString, (XtPointer) NULL},
  34.     {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  35.     Offset(font), XtRString, (XtPointer) XtDefaultFont},
  36.     {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  37.     Offset(foreground), XtRString,
  38.     (XtPointer) XtDefaultForeground},
  39.     {XtNjustify, XtCJustify, XtRJustify, sizeof(Justify),
  40.     Offset(justify), XtRImmediate, (XtPointer) Left},
  41.     {XtNspace, XtCSpace, XtRDimension, sizeof(Dimension),
  42.     Offset(space), XtRImmediate, (XtPointer) 2},
  43.     {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
  44.          XtOffsetOf(LabelGadgetRec, rectObj.border_width),
  45.      XtRImmediate, (XtPointer) 0},
  46.     {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
  47.     Offset(background), XtRString,
  48.     (XtPointer) XtDefaultBackground},
  49.     {XtNborderColor, XtCBorderColor, XtRPixel, sizeof(Pixel),
  50.     Offset(border), XtRString, (XtPointer) XtDefaultForeground},
  51. };
  52. #undef Offset
  53.  
  54. /* Forward declarations */
  55.  
  56. static void ClassInitialize(), Initialize(),
  57.     Redisplay(), Destroy(), Resize();
  58. static Boolean SetValues();
  59. static XtGeometryResult QueryGeometry();
  60.  
  61. /* Class record declaration */
  62.  
  63. LabelGadgetClassRec labelGadgetClassRec = {
  64.     /* RectObj class part */
  65.   {
  66.     /* superclass         */    (WidgetClass) &rectObjClassRec,
  67.     /* class_name         */    "LabelGadget",
  68.     /* widget_size         */    sizeof(LabelGadgetRec),
  69.     /* class_initialize      */ ClassInitialize,
  70.     /* class_part_initialize */    NULL,
  71.     /* class_inited          */    FALSE,
  72.     /* initialize         */    Initialize,
  73.     /* initialize_hook       */    NULL,        
  74.     /* rect1             */    NULL,
  75.     /* rect2             */    NULL,
  76.     /* rect3             */    0,
  77.     /* resources         */    resources,
  78.     /* num_resources         */    XtNumber(resources),
  79.     /* xrm_class         */    NULLQUARK,
  80.     /* rect4             */    0,
  81.     /* rect5             */    0,
  82.     /* rect6             */    0,
  83.     /* rect7             */    0,
  84.     /* destroy             */    Destroy,
  85.     /* resize             */    Resize,
  86.     /* expose             */    Redisplay,
  87.     /* set_values         */    SetValues,
  88.     /* set_values_hook       */    NULL,            
  89.     /* set_values_almost     */    XtInheritSetValuesAlmost,  
  90.     /* get_values_hook       */    NULL,            
  91.     /* rect9             */    NULL,
  92.     /* version             */    XtVersion,
  93.     /* callback offsets      */ NULL,
  94.     /* rect10             */ NULL,
  95.     /* query_geometry         */    QueryGeometry,
  96.     /* rect11             */ NULL,
  97.     /* extension             */ NULL
  98.   },
  99.     /* LabelGadget class part    */
  100.   {
  101.     /* extension             */ NULL
  102.   }
  103. };
  104.  
  105. /* Class record pointer */
  106.  
  107. WidgetClass labelGadgetClass = (WidgetClass) &labelGadgetClassRec;
  108.  
  109. static void ClassInitialize()
  110. {
  111.     extern void CvtStringToJustify();    /* Defined in Label.c */
  112.  
  113.     /* Register a converter for string to justification */
  114.  
  115.     XtSetTypeConverter(XtRString, XtRJustify, CvtStringToJustify,
  116.             (XtConvertArgList) NULL, 0,
  117.         XtCacheAll, (XtDestructor) NULL);
  118. }
  119.  
  120. static void SetTextWidthAndHeight(lw)
  121.     LabelGadget lw;
  122. {
  123.     register XFontStruct *fs = lw->label.font;
  124.  
  125.     /* Compute the text dimensions based on the string and the font */
  126.  
  127.     lw->label.label_len = strlen(lw->label.label);
  128.     lw->label.label_width =
  129.         XTextWidth(fs, lw->label.label, lw->label.label_len);
  130.     lw->label.label_height =
  131.         fs->max_bounds.ascent + fs->max_bounds.descent;
  132. }
  133.  
  134. static GC GetNormalGC(lw)
  135.     LabelGadget lw;
  136. {
  137.     XGCValues    values;
  138.  
  139.     /* Allocate a graphics context with the foreground and font */
  140.  
  141.     values.foreground = lw->label.foreground;
  142.     values.font = lw->label.font->fid;
  143.     return XtGetGC((Widget) lw, GCForeground | GCFont, &values);
  144. }
  145.  
  146. static GC GetBackgroundGC(lw)
  147.     LabelGadget lw;
  148. {
  149.     XGCValues    values;
  150.  
  151.     /* Allocate a graphics context with the background */
  152.  
  153.     values.foreground = lw->label.background;
  154.     return XtGetGC((Widget) lw, GCForeground, &values);
  155. }
  156.  
  157. static GC GetBorderGC(lw)
  158.     LabelGadget lw;
  159. {
  160.     XGCValues    values;
  161.  
  162.     if (lw->rectObj.border_width == 0) return NULL;
  163.  
  164.     /* Allocate a graphics context with the border values */
  165.  
  166.     values.foreground = lw->label.border;
  167.     values.line_width = lw->rectObj.border_width;
  168.     return XtGetGC((Widget) lw, GCForeground | GCLineWidth, &values);
  169. }
  170.  
  171. static void Initialize(request, new, args, num_args)
  172.     Widget request, new;
  173.     ArgList args;
  174.     Cardinal *num_args;
  175. {
  176.     LabelGadget lw = (LabelGadget) new;
  177.  
  178.     /* If no label is specified, use the name */
  179.     if (lw->label.label == NULL) lw->label.label = XtName(lw);
  180.  
  181.     /* Copy the label */
  182.     lw->label.label = XtNewString(lw->label.label);
  183.  
  184.     /* Compute the text dimensions and get graphics contexts. */
  185.     SetTextWidthAndHeight(lw);
  186.     lw->label.gc = lw->label.current_gc = GetNormalGC(lw);
  187.     lw->label.background_gc =
  188.         lw->label.current_bg_gc = GetBackgroundGC(lw);
  189.     lw->label.border_gc = GetBorderGC(lw);
  190.  
  191.     /* If no size specified, compute one */
  192.     lw->label.size_computed =
  193.         (lw->rectObj.width == 0) && (lw->rectObj.height == 0);
  194.  
  195.     if (lw->rectObj.width == 0) {
  196.     lw->rectObj.width = lw->label.label_width +
  197.         2 * lw->label.space;
  198.     }
  199.     if (lw->rectObj.height == 0) {
  200.     lw->rectObj.height = lw->label.label_height +
  201.         2 * lw->label.space;
  202.     }
  203.  
  204.     lw->label.old_border = lw->rectObj.border_width;
  205.  
  206.     lw->label.desired_width = lw->rectObj.width;
  207.     lw->label.desired_height = lw->rectObj.height;
  208. }
  209.  
  210. static Boolean SetValues(old, request, new, args, num_args)
  211.     Widget  old, request, new;
  212.     ArgList args;
  213.     Cardinal *num_args;
  214. {
  215.     LabelGadget oldlw = (LabelGadget) old;
  216.     LabelGadget newlw = (LabelGadget) new;
  217.     Boolean redisplay = FALSE;
  218.  
  219. #define NE(field) (oldlw->field != newlw->field)
  220.  
  221.     /* If the label has been reset to NULL, change to the name */
  222.  
  223.     if (newlw->label.label == NULL) {
  224.     newlw->label.label = XtName(newlw);
  225.     }
  226.  
  227.     /* Decide whether to compute the size */
  228.  
  229.     if (newlw->rectObj.width == 0 && newlw->rectObj.height == 0) {
  230.     newlw->label.size_computed = TRUE;
  231.     } else if (NE(rectObj.width) || NE(rectObj.height)) {
  232.     newlw->label.size_computed = FALSE;
  233.     if (NE(rectObj.width)) {
  234.         newlw->label.desired_width = newlw->rectObj.width;
  235.     }
  236.     if (NE(rectObj.height)) {
  237.         newlw->label.desired_height = newlw->rectObj.height;
  238.     }
  239.     } /* else leave the same */
  240.  
  241.     /* If label, or font has changed, recopy and compute size */
  242.  
  243.     if (NE(label.label) || NE(label.font)) {
  244.     if (NE(label.label)) {
  245.         XtFree((char *) oldlw->label.label);
  246.         newlw->label.label = XtNewString(newlw->label.label);
  247.     }
  248.     SetTextWidthAndHeight(newlw);
  249.     redisplay = TRUE;
  250.     }
  251.  
  252.     /* Compute the size if necessary */
  253.  
  254.     if (newlw->label.size_computed || newlw->rectObj.width == 0) {
  255.     newlw->label.desired_width = newlw->rectObj.width =
  256.         newlw->label.label_width + 2 * newlw->label.space;
  257.     }
  258.     if (newlw->label.size_computed || newlw->rectObj.height == 0) {
  259.     newlw->label.desired_height = newlw->rectObj.height =
  260.         newlw->label.label_height + 2 * newlw->label.space;
  261.     }
  262.     
  263.     /* If foreground or font has changed, update GC */
  264.  
  265.     if (NE(label.foreground) || NE(label.font->fid)) {
  266.     XtReleaseGC(newlw, oldlw->label.gc);
  267.     newlw->label.gc = GetNormalGC(newlw);
  268.  
  269.     if (newlw->label.current_gc == oldlw->label.gc) {
  270.         newlw->label.current_gc = newlw->label.gc;
  271.         redisplay = TRUE;
  272.     }
  273.     }
  274.  
  275.     /* If background has changed, update background GC */
  276.  
  277.     if (NE(label.background)) {
  278.     XtReleaseGC(newlw, oldlw->label.background_gc);
  279.     newlw->label.background_gc = GetBackgroundGC(newlw);
  280.  
  281.     if (newlw->label.current_bg_gc == oldlw->label.background_gc) {
  282.         newlw->label.current_bg_gc = newlw->label.background_gc;
  283.         redisplay = TRUE;
  284.     }
  285.     }
  286.  
  287.     /* If border has changed, update border GC */
  288.  
  289.     if (NE(label.border) || NE(rectObj.border_width)) {
  290.     if (oldlw->label.border_gc != NULL) {
  291.         XtReleaseGC(newlw, oldlw->label.border_gc);
  292.     }
  293.     newlw->label.border_gc = GetBorderGC(newlw);
  294.     redisplay = TRUE;
  295.     }
  296.  
  297.     return redisplay || NE(label.space) || NE(label.justify);
  298. #undef NE
  299. }
  300.  
  301. static void Destroy(w)
  302.     Widget w;
  303. {
  304.     LabelGadget lw = (LabelGadget) w;
  305.  
  306.     XtFree((char *) lw->label.label);
  307.  
  308.     XtReleaseGC(w, lw->label.gc);
  309.     XtReleaseGC(w, lw->label.background_gc);
  310.     if (lw->label.border_gc != NULL) {
  311.     XtReleaseGC(w, lw->label.border_gc);
  312.     }
  313. }
  314.  
  315. static void Redisplay(w, event, region)
  316.     Widget w;
  317.     XEvent *event;
  318.     Region region;
  319. {
  320.     LabelGadget lw = (LabelGadget) w;
  321.     int offset, x;
  322.     XRectangle rect;
  323.     Region r1, r2;
  324.  
  325.     /* Draw the background */
  326.     XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
  327.             lw->label.current_bg_gc,
  328.         lw->rectObj.x + lw->rectObj.border_width,
  329.         lw->rectObj.y + lw->rectObj.border_width,
  330.         lw->rectObj.width, lw->rectObj.height);
  331.  
  332.     /* Draw the border */
  333.     if (lw->rectObj.border_width != 0) {
  334.     offset = lw->rectObj.border_width / 2;
  335.     XDrawRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
  336.         lw->label.border_gc,
  337.         lw->rectObj.x + offset, lw->rectObj.y + offset,
  338.         lw->rectObj.width + lw->rectObj.border_width,
  339.         lw->rectObj.height + lw->rectObj.border_width);
  340.     }
  341.  
  342.     switch (lw->label.justify) {
  343.     case Left:
  344.         x = lw->label.space;    
  345.         break;
  346.     case Right:
  347.         x = (int) lw->rectObj.width - (int) lw->label.space -
  348.             (int) lw->label.label_width;
  349.         break;
  350.     case Center:
  351.         x = ((int) lw->rectObj.width -
  352.             (int) lw->label.label_width) / 2;
  353.         break;
  354.     }
  355.  
  356.     /* Temporarily change the clip mask in the gc */
  357.     rect.x = lw->rectObj.x + lw->rectObj.border_width;
  358.     rect.y = lw->rectObj.y + lw->rectObj.border_width;
  359.     rect.width = lw->rectObj.width;
  360.     rect.height = lw->rectObj.height;
  361.  
  362.     r1 = XCreateRegion();
  363.     r2 = XCreateRegion();
  364.     if (region != NULL) {
  365.     XUnionRectWithRegion(&rect, r1, r2);    /* r2 = rectangle */
  366.     XIntersectRegion(region, r2, r1);    /* r1 = intersection */
  367.     } else XUnionRectWithRegion(&rect, r2, r1); /* r1 = rectangle */
  368.  
  369.     XSetRegion(XtDisplayOfObject(w), lw->label.current_gc, r1);
  370.     XDestroyRegion(r1);
  371.     XDestroyRegion(r2);
  372.  
  373.     XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w),
  374.         lw->label.current_gc,
  375.         lw->rectObj.x + lw->rectObj.border_width + x,
  376.         lw->rectObj.y + lw->rectObj.border_width + 
  377.         lw->label.space + lw->label.font->max_bounds.ascent,
  378.         lw->label.label, lw->label.label_len);
  379.  
  380.     /* Restore the GC */
  381.     XSetClipMask(XtDisplayOfObject(w), lw->label.current_gc, None);
  382. }
  383.  
  384. static void Resize(w)
  385.     Widget w;
  386. {
  387.     LabelGadget lw = (LabelGadget) w;
  388.  
  389.     /* If border width changed, update border GC */
  390.  
  391.     if (lw->label.old_border != lw->rectObj.border_width) {
  392.     if (lw->label.border_gc != NULL) {
  393.         XtReleaseGC(w, lw->label.border_gc);
  394.     }
  395.     lw->label.border_gc = GetBorderGC(lw);
  396.     lw->label.old_border = lw->rectObj.border_width;
  397.     }
  398. }   
  399.  
  400. static XtGeometryResult QueryGeometry(w, proposed, desired)
  401.     Widget w;
  402.     XtWidgetGeometry *proposed, *desired;
  403. {
  404.     LabelGadget lw = (LabelGadget) w;
  405. #define Set(bit) (proposed->request_mode & bit)
  406.  
  407.     desired->width = lw->label.desired_width;
  408.     desired->height = lw->label.desired_height;
  409.     desired->request_mode = CWWidth | CWHeight;
  410.  
  411.     if (Set(CWWidth) && proposed->width == desired->width &&
  412.         Set(CWHeight) && proposed->height == desired->height) {
  413.     return XtGeometryYes;
  414.     }
  415.  
  416.     if (desired->width == lw->rectObj.width &&
  417.         desired->height == lw->rectObj.height) {
  418.     return XtGeometryNo;
  419.     }
  420.     return XtGeometryAlmost;
  421. #undef Set
  422. }
  423.