home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / XfeWidgets / Xfe / Label.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  33.1 KB  |  1,178 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*-----------------------------------------*/
  19. /*                                                                        */
  20. /* Name:        <Xfe/Label.c>                                            */
  21. /* Description:    XfeLabel widget source.                                    */
  22. /* Author:        Ramiro Estrugo <ramiro@netscape.com>                    */
  23. /*                                                                        */
  24. /*----------------------------------------------------------------------*/
  25.  
  26.  
  27. #include <Xfe/LabelP.h>
  28.  
  29. /*----------------------------------------------------------------------*/
  30. /*                                                                        */
  31. /* Warnings and messages                                                */
  32. /*                                                                        */
  33. /*----------------------------------------------------------------------*/
  34. #define MESSAGE1 "Widget is not a XfeLabel."
  35. #define MESSAGE2 "If XmNtruncateLabel is true, XmNtruncateProc cannot be NULL."
  36.  
  37.  
  38. #define INSENSITIVE_OFFSET 1
  39.  
  40. /*----------------------------------------------------------------------*/
  41. /*                                                                        */
  42. /* Core class methods                                                    */
  43. /*                                                                        */
  44. /*----------------------------------------------------------------------*/
  45. static void        ClassPartInit    (WidgetClass);
  46. static void     Initialize        (Widget,Widget,ArgList,Cardinal *);
  47. static void     Destroy            (Widget);
  48. static Boolean    SetValues        (Widget,Widget,Widget,ArgList,Cardinal *);
  49. static void        GetValuesHook    (Widget,ArgList,Cardinal *);
  50.  
  51. /*----------------------------------------------------------------------*/
  52. /*                                                                        */
  53. /* XfePrimitive class methods                                            */
  54. /*                                                                        */
  55. /*----------------------------------------------------------------------*/
  56. static void    PreferredGeometry        (Widget,Dimension *,Dimension *);
  57. static void    PrepareComponents        (Widget,int);
  58. static void    LayoutComponents        (Widget);
  59. static void    DrawComponents            (Widget,XEvent *,Region,XRectangle *);
  60.  
  61. /*----------------------------------------------------------------------*/
  62. /*                                                                        */
  63. /* XfeLabel class methods                                                */
  64. /*                                                                        */
  65. /*----------------------------------------------------------------------*/
  66. static void    LayoutString            (Widget);
  67. static void    DrawString                (Widget,XEvent *,Region,XRectangle *);
  68. static void    DrawSelection            (Widget,XEvent *,Region,XRectangle *);
  69. static GC    GetLabelGC                (Widget);
  70. static GC    GetSelectionGC            (Widget);
  71.  
  72. /*----------------------------------------------------------------------*/
  73. /*                                                                        */
  74. /* Misc XfeLabel functions                                                */
  75. /*                                                                        */
  76. /*----------------------------------------------------------------------*/
  77. static XmString    CreateTruncatedString        (Widget);
  78. static void        InvokeSelectionChangedCallback        (Widget,XEvent *);
  79.  
  80. /*----------------------------------------------------------------------*/
  81. /*                                                                        */
  82. /* XfeLabel Resources                                                    */
  83. /*                                                                        */
  84. /*----------------------------------------------------------------------*/
  85. static XtResource resources[] = 
  86. {
  87.     /* Callback resources */         
  88.     { 
  89.         XmNselectionChangedCallback,
  90.         XmCCallback,
  91.         XmRCallback,
  92.         sizeof(XtCallbackList),
  93.         XtOffsetOf(XfeLabelRec , xfe_label . selection_changed_callback),
  94.         XmRImmediate, 
  95.         (XtPointer) NULL
  96.     },
  97.  
  98.     /* Label resources */
  99.     { 
  100.         XmNlabelAlignment,
  101.         XmCLabelAlignment,
  102.         XmRAlignment,
  103.         sizeof(unsigned char),
  104.         XtOffsetOf(XfeLabelRec , xfe_label . label_alignment),
  105.         XmRImmediate, 
  106.         (XtPointer) XmALIGNMENT_CENTER
  107.     },
  108.     { 
  109.         XmNlabelDirection,
  110.         XmCLabelDirection,
  111.         XmRStringDirection,
  112.         sizeof(unsigned char),
  113.         XtOffsetOf(XfeLabelRec , xfe_label . label_direction),
  114.         XmRImmediate, 
  115.         (XtPointer) XmSTRING_DIRECTION_L_TO_R
  116.     },
  117.     { 
  118.         XmNfontList,
  119.         XmCFontList,
  120.         XmRFontList,
  121.         sizeof(XmFontList),
  122.         XtOffsetOf(XfeLabelRec , xfe_label . font_list),
  123.         XmRImmediate, 
  124.         (XtPointer) NULL
  125.     },
  126.     { 
  127.         XmNlabelString,
  128.         XmCLabelString,
  129.         XmRXmString,
  130.         sizeof(XmString),
  131.         XtOffsetOf(XfeLabelRec , xfe_label . label_string),
  132.         XmRImmediate, 
  133.         (XtPointer) NULL
  134.     },
  135.  
  136.     /* Truncation resources */
  137.     { 
  138.         XmNtruncateLabel,
  139.         XmCTruncateLabel,
  140.         XmRBoolean,
  141.         sizeof(Boolean),
  142.         XtOffsetOf(XfeLabelRec , xfe_label  . truncate_label),
  143.         XmRImmediate, 
  144.         (XtPointer) False
  145.     },
  146.     { 
  147.         XmNtruncateProc,
  148.         XmCTruncateProc,
  149.         XmRProc,
  150.         sizeof(XtPointer),
  151.         XtOffsetOf(XfeLabelRec , xfe_label  . truncate_proc),
  152.         XmRImmediate, 
  153.         (XtPointer) NULL
  154.     },
  155.  
  156.     /* Selection resources */
  157.     { 
  158.         XmNselected,
  159.         XmCSelected,
  160.         XmRBoolean,
  161.         sizeof(Boolean),
  162.         XtOffsetOf(XfeLabelRec , xfe_label  . selected),
  163.         XmRImmediate, 
  164.         (XtPointer) False
  165.     },
  166.     { 
  167.         XmNselectionColor,
  168.         XmCSelectionColor,
  169.         XmRPixel,
  170.         sizeof(Pixel),
  171.         XtOffsetOf(XfeLabelRec , xfe_label  . selection_color),
  172.         XmRCallProc, 
  173.         (XtPointer) _XfeCallProcSelectPixel
  174.     },
  175.     { 
  176.         XmNselectionModifiers,
  177.         XmCSelectionModifiers,
  178.         XmRModifiers,
  179.         sizeof(Modifiers),
  180.         XtOffsetOf(XfeLabelRec , xfe_label  . selection_modifiers),
  181.         XmRImmediate, 
  182.         (XtPointer) None
  183.     },
  184.  
  185.     /* Force buffer type to XmBUFFER_NONE */
  186.     { 
  187.         XmNbufferType,
  188.         XmCBufferType,
  189.         XmRBufferType,
  190.         sizeof(unsigned char),
  191.         XtOffsetOf(XfeLabelRec , xfe_primitive . buffer_type),
  192.         XmRImmediate, 
  193.         (XtPointer) XmBUFFER_SHARED
  194.     },
  195.  
  196.     { 
  197.         XmNtraversalOn,
  198.         XmCTraversalOn,
  199.         XmRBoolean,
  200.         sizeof(Boolean),
  201.         XtOffsetOf(XfeLabelRec , primitive . traversal_on),
  202.         XmRImmediate, 
  203.         (XtPointer) False
  204.     },
  205.     { 
  206.         XmNhighlightThickness,
  207.         XmCHighlightThickness,
  208.         XmRHorizontalDimension,
  209.         sizeof(Dimension),
  210.         XtOffsetOf(XfeLabelRec , primitive . highlight_thickness),
  211.         XmRImmediate, 
  212.         (XtPointer) 0
  213.     },
  214. };
  215.  
  216. /*----------------------------------------------------------------------*/
  217. /*                                                                        */
  218. /* XfeButton actions                                                    */
  219. /*                                                                        */
  220. /*----------------------------------------------------------------------*/
  221. static XtActionsRec actions[] = 
  222. {
  223.     { "Select",                _XfeLabelSelect            },
  224. };
  225.  
  226. /*----------------------------------------------------------------------*/
  227. /*                                                                        */
  228. /* XfeLabel widget class record initialization                            */
  229. /*                                                                        */
  230. /*----------------------------------------------------------------------*/
  231. _XFE_WIDGET_CLASS_RECORD(label,Label) =
  232. {
  233.     {
  234.         /* Core Part */
  235.         (WidgetClass) &xfePrimitiveClassRec,    /* superclass             */
  236.         "XfeLabel",                                /* class_name             */
  237.         sizeof(XfeLabelRec),                    /* widget_size            */
  238.         NULL,                                    /* class_initialize       */
  239.         ClassPartInit,                            /* class_part_initialize*/
  240.         FALSE,                                  /* class_inited           */
  241.         Initialize,                             /* initialize             */
  242.         NULL,                                   /* initialize_hook        */
  243.         XtInheritRealize,                       /* realize                */
  244.         actions,                                /* actions                */
  245.         XtNumber(actions),                        /* num_actions            */
  246.         resources,                              /* resources              */
  247.         XtNumber(resources),                    /* num_resources          */
  248.         NULLQUARK,                              /* xrm_class              */
  249.         TRUE,                                   /* compress_motion        */
  250.         XtExposeCompressMaximal,                /* compress_exposure      */
  251.         TRUE,                                   /* compress_enterleave    */
  252.         FALSE,                                  /* visible_interest       */
  253.         Destroy,                                /* destroy                */
  254.         XtInheritResize,                        /* resize                 */
  255.         XtInheritExpose,                        /* expose                 */
  256.         SetValues,                              /* set_values             */
  257.         NULL,                                   /* set_values_hook        */
  258.         XtInheritSetValuesAlmost,                /* set_values_almost      */
  259.         GetValuesHook,                            /* get_values_hook        */
  260.         NULL,                                   /* accept_focus           */
  261.         XtVersion,                              /* version                */
  262.         NULL,                                   /* callback_private       */
  263.         _XfeLabelDefaultTranslations,            /* tm_table               */
  264.         XtInheritQueryGeometry,                    /* query_geometry         */
  265.         XtInheritDisplayAccelerator,            /* display accel          */
  266.         NULL,                                   /* extension              */
  267.     },
  268.  
  269.     /* XmPrimitive Part */
  270.     {
  271.         XmInheritBorderHighlight,                /* border_highlight        */
  272.         XmInheritBorderUnhighlight,                /* border_unhighlight     */
  273.         XtInheritTranslations,                  /* translations           */
  274.         NULL,                                    /* arm_and_activate       */
  275.         NULL,                                    /* syn resources          */
  276.         0,                                        /* num syn_resources      */
  277.         NULL,                                    /* extension              */
  278.     },
  279.  
  280.     /* XfePrimitive Part */
  281.     {
  282.         XfeInheritBitGravity,                    /* bit_gravity            */
  283.         PreferredGeometry,                        /* preferred_geometry    */
  284.         XfeInheritMinimumGeometry,                /* minimum_geometry        */
  285.         XfeInheritUpdateRect,                    /* update_rect            */
  286.         PrepareComponents,                        /* prepare_components    */
  287.         LayoutComponents,                        /* layout_components    */
  288.         XfeInheritDrawBackground,                /* draw_background        */
  289.         XfeInheritDrawShadow,                    /* draw_shadow            */
  290.         DrawComponents,                            /* draw_components        */
  291.         NULL,                                    /* extension            */
  292.     },
  293.  
  294.     /* XfeLabel Part */
  295.     {
  296.         LayoutString,                            /* layout_string        */
  297.         DrawString,                                /* draw_string            */
  298.         DrawSelection,                            /* draw_selection        */
  299.         GetLabelGC,                                /* get_label_gc            */
  300.         GetSelectionGC,                            /* get_selection_gc        */
  301.         NULL,                                    /* extension            */
  302.     },
  303. };
  304.  
  305. /*----------------------------------------------------------------------*/
  306. /*                                                                        */
  307. /* xfeLabelWidgetClass declaration.                                        */
  308. /*                                                                        */
  309. /*----------------------------------------------------------------------*/
  310. _XFE_WIDGET_CLASS(label,Label);
  311.  
  312. /*----------------------------------------------------------------------*/
  313. /*                                                                        */
  314. /* Core class methods                                                    */
  315. /*                                                                        */
  316. /*----------------------------------------------------------------------*/
  317. static void
  318. ClassPartInit(WidgetClass wc)
  319. {
  320.     XfeLabelWidgetClass cc = (XfeLabelWidgetClass) wc;
  321.     XfeLabelWidgetClass sc = (XfeLabelWidgetClass) wc->core_class.superclass;
  322.  
  323.     /* Resolve inheritance of all XfeLabel class methods */
  324.     _XfeResolve(cc,sc,xfe_label_class,layout_string,
  325.                 XfeInheritLayoutString);
  326.  
  327.     _XfeResolve(cc,sc,xfe_label_class,draw_string,
  328.                 XfeInheritDrawString);
  329.  
  330.     _XfeResolve(cc,sc,xfe_label_class,draw_selection,
  331.                 XfeInheritDrawSelection);
  332.  
  333.     _XfeResolve(cc,sc,xfe_label_class,get_label_gc,
  334.                 XfeInheritGetLabelGC);
  335.  
  336.     _XfeResolve(cc,sc,xfe_label_class,get_selection_gc,
  337.                 XfeInheritGetSelectionGC);
  338. }
  339. /*----------------------------------------------------------------------*/
  340. static void
  341. Initialize(Widget rw,Widget nw,ArgList args,Cardinal *nargs)
  342. {
  343.     XfeLabelPart * lp = _XfeLabelPart(nw);
  344.  
  345.     /* Make sure rep types are ok */
  346.     XfeRepTypeCheck(nw,XmRAlignment,&lp->label_alignment,
  347.                     XmALIGNMENT_CENTER);
  348.  
  349.     XfeRepTypeCheck(nw,XmRStringDirection,&lp->label_direction,
  350.            XmSTRING_DIRECTION_L_TO_R);
  351.  
  352.     /* Make sure the label is set up properly */
  353.     lp->label_string = XfeXmStringCopy(nw,lp->label_string,XtName(nw));
  354.     
  355.     /* Make sure the font list is set up properly */
  356.     lp->font_list = XfeXmFontListCopy(nw,lp->font_list,XmLABEL_FONTLIST);
  357.  
  358.     /* Allocate the label GCs */
  359.     lp->label_GC = XfeAllocateStringGc(nw,lp->font_list,
  360.                                        _XfeForeground(nw),None,True);
  361.     
  362.     /* Allocate the label insensitive GCs */
  363.     lp->insensitive_top_GC = XfeAllocateStringGc(nw,lp->font_list,
  364.                                                  _XfeTopShadowColor(nw),
  365.                                                  None,True);
  366.     
  367.     lp->insensitive_bottom_GC = XfeAllocateStringGc(nw,lp->font_list,
  368.                                                     _XfeBottomShadowColor(nw),
  369.                                                     None,True);
  370.  
  371.     /* Allocate the selection GCs */
  372.     lp->selection_GC = XfeAllocateColorGc(nw,lp->selection_color,None,True);
  373.  
  374.     /* Initialize private members */
  375.     lp->misc_offset = 0;
  376.     
  377.     /* Finish of initialization */
  378.     _XfePrimitiveChainInitialize(rw,nw,xfeLabelWidgetClass);
  379. }
  380. /*----------------------------------------------------------------------*/
  381. static void
  382. Destroy(Widget w)
  383. {
  384.     XfeLabelPart * lp = _XfeLabelPart(w);
  385.  
  386.     /* Release GCs */
  387.     XtReleaseGC(w,lp->label_GC);
  388.     XtReleaseGC(w,lp->insensitive_top_GC);
  389.     XtReleaseGC(w,lp->insensitive_bottom_GC);
  390.     XtReleaseGC(w,lp->selection_GC);
  391.  
  392.     /* Free the label string */
  393.     XmStringFree(lp->label_string);
  394.  
  395.     /* Free the font list */
  396.     XmFontListFree(lp->font_list);
  397. }
  398. /*----------------------------------------------------------------------*/
  399. static Boolean
  400. SetValues(Widget ow,Widget rw,Widget nw,ArgList args,Cardinal *nargs)
  401. {
  402.     XfeLabelPart *    np = _XfeLabelPart(nw);
  403.     XfeLabelPart *    op = _XfeLabelPart(ow);
  404.     Boolean            label_gc_flag = False;
  405.     Boolean            selection_gc_flag = False;
  406.     Boolean            insensitive_top_gc_flag = False;
  407.     Boolean            insensitive_bottom_gc_flag = False;
  408.  
  409.     /* font_list */
  410.     if (np->font_list != op->font_list)
  411.     {
  412.         /* Make sure the new font is ok */
  413.         np->font_list = XfeXmFontListCopy(nw,np->font_list,XmLABEL_FONTLIST);
  414.       
  415.         /* Free the old fontlist */
  416.         if (op->font_list)
  417.         {
  418.             XmFontListFree(op->font_list);
  419.         }
  420.     
  421.         label_gc_flag = True;   
  422.         insensitive_bottom_gc_flag = True;
  423.         insensitive_top_gc_flag = True;
  424.     
  425.         _XfeConfigFlags(nw) |= XfeConfigGLE;
  426.     
  427.         _XfePrepareFlags(nw) |= _XFE_PREPARE_LABEL_STRING;
  428.     }
  429.  
  430.     /* label_string */
  431.     if (np->label_string != op->label_string)
  432.     {
  433.         /* Free the old string if needed */
  434.         if (op->label_string)
  435.         {
  436.             XmStringFree(op->label_string);
  437.         }
  438.     
  439.         /* Make sure the new string is ok */
  440.         np->label_string = XfeXmStringCopy(nw,np->label_string,XtName(nw));
  441.  
  442.         _XfeConfigFlags(nw) |= XfeConfigGLE;
  443.  
  444.         _XfePrepareFlags(nw) |= _XFE_PREPARE_LABEL_STRING;
  445.     }
  446.  
  447.     /* foreground */
  448.     if (_XfeForeground(nw) != _XfeForeground(ow))
  449.     {
  450.         label_gc_flag = True;   
  451.  
  452.         _XfeConfigFlags(nw) |= XfeConfigExpose;
  453.     }
  454.  
  455.     /* top_shadow_color */
  456.     if (_XfeTopShadowColor(nw) != _XfeTopShadowColor(ow))
  457.     {
  458.         insensitive_top_gc_flag = True;
  459.  
  460.         if (!_XfeIsSensitive(nw))
  461.         {
  462.             _XfeConfigFlags(nw) |= XfeConfigExpose;
  463.         }
  464.     }
  465.  
  466.     /* bottom_shadow_color */
  467.     if (_XfeBottomShadowColor(nw) != _XfeBottomShadowColor(ow))
  468.     {
  469.         insensitive_bottom_gc_flag = True;
  470.  
  471.         if (!_XfeIsSensitive(nw))
  472.         {
  473.             _XfeConfigFlags(nw) |= XfeConfigExpose;
  474.         }
  475.  
  476.     }
  477.  
  478.     /* label_alignment */
  479.     if (np->label_alignment != op->label_alignment)
  480.     {
  481.         /* Make sure the new label alignment is ok */
  482.         XfeRepTypeCheck(nw,XmRAlignment,&np->label_alignment,
  483.                         XmALIGNMENT_CENTER);
  484.  
  485.         _XfeConfigFlags(nw) |= XfeConfigLE;   
  486.     }
  487.  
  488.     /* label_direction */
  489.     if (np->label_direction != op->label_direction)
  490.     {
  491.         /* Make sure the new label direction is ok */
  492.         XfeRepTypeCheck(nw,XmRStringDirection,&np->label_direction,
  493.                         XmSTRING_DIRECTION_L_TO_R);
  494.  
  495.         _XfeConfigFlags(nw) |= XfeConfigExpose;   
  496.     }
  497.  
  498.     /* selected */
  499.     if (np->selected != op->selected)
  500.     {
  501.         _XfeConfigFlags(nw) |= XfeConfigExpose;
  502.     }
  503.  
  504.     /* selection_color */
  505.     if (np->selection_color != op->selection_color)
  506.     {
  507.         selection_gc_flag = True;   
  508.  
  509.         _XfeConfigFlags(nw) |= XfeConfigExpose;
  510.     }
  511.  
  512.     /* Update the label GC */
  513.     if (label_gc_flag)
  514.     {
  515.         /* Release the old label GC */
  516.         XtReleaseGC(nw,np->label_GC);
  517.     
  518.         /* Allocate the new label GC */
  519.         np->label_GC = XfeAllocateStringGc(nw,np->font_list,
  520.                                            _XfeForeground(nw),None,True);
  521.     }
  522.  
  523.     /* Update the selection GC */
  524.     if (selection_gc_flag)
  525.     {
  526.         /* Release the old selection GC */
  527.         XtReleaseGC(nw,np->selection_GC);
  528.     
  529.         /* Allocate the new selection GC */
  530.         np->selection_GC = XfeAllocateColorGc(nw,np->selection_color,
  531.                                               None,True);
  532.     }
  533.  
  534.     /* Update the insens top GC */
  535.     if (insensitive_top_gc_flag)
  536.     {
  537.         /* Release the old label GC */
  538.         XtReleaseGC(nw,np->insensitive_top_GC);
  539.     
  540.         /* Allocate the new label GC */
  541.         np->insensitive_top_GC = 
  542.             XfeAllocateStringGc(nw,np->font_list,
  543.                                 _XfeTopShadowColor(nw),
  544.                                 None,True);
  545.     }
  546.  
  547.  
  548.     /* Update the insens bottom GC */
  549.     if (insensitive_bottom_gc_flag)
  550.     {
  551.         /* Release the old label GC */
  552.         XtReleaseGC(nw,np->insensitive_bottom_GC);
  553.     
  554.         /* Allocate the new label GC */
  555.         np->insensitive_bottom_GC = 
  556.             XfeAllocateStringGc(nw,np->font_list,
  557.                                 _XfeBottomShadowColor(nw),
  558.                                 None,True);
  559.     }
  560.  
  561.  
  562.  
  563.     return _XfePrimitiveChainSetValues(ow,rw,nw,xfeLabelWidgetClass);
  564. }
  565. /*----------------------------------------------------------------------*/
  566. static void
  567. GetValuesHook(Widget w,ArgList args,Cardinal* nargs)
  568. {
  569.     XfeLabelPart *    lp = _XfeLabelPart(w);
  570.     Cardinal        i;
  571.     
  572.     for (i = 0; i < *nargs; i++)
  573.     {
  574.         /* label_string */
  575.         if (strcmp(args[i].name,XmNlabelString) == 0)
  576.         {
  577.             *((XtArgVal *) args[i].value) = 
  578.                 (XtArgVal) XmStringCopy(lp->label_string);
  579.         }
  580.         /* font_list */
  581.         else if (strcmp(args[i].name,XmNfontList) == 0)
  582.         {
  583.             *((XtArgVal *) args[i].value) = 
  584.                 (XtArgVal) XmFontListCopy(lp->font_list);
  585.         }      
  586.     }
  587. }
  588. /*----------------------------------------------------------------------*/
  589.  
  590. /*----------------------------------------------------------------------*/
  591. /*                                                                        */
  592. /* XfePrimitive methods                                                    */
  593. /*                                                                        */
  594. /*----------------------------------------------------------------------*/
  595. static void
  596. PreferredGeometry(Widget w,Dimension *width,Dimension *height)
  597. {
  598.     XfeLabelPart * lp = _XfeLabelPart(w);
  599.  
  600.     *width  = _XfeOffsetLeft(w) + _XfeOffsetRight(w)  + lp->label_rect.width;
  601.     *height = _XfeOffsetTop(w)  + _XfeOffsetBottom(w) + lp->label_rect.height;
  602. }
  603. /*----------------------------------------------------------------------*/
  604. static void
  605. PrepareComponents(Widget w,int flags)
  606. {
  607.     if (flags & _XFE_PREPARE_LABEL_STRING)
  608.     {
  609.         XfeLabelPart *    lp = _XfeLabelPart(w);
  610.     
  611.         /* Obtain the labels's dimensions */
  612.         XmStringExtent(lp->font_list,
  613.                        lp->label_string,
  614.                        &lp->label_rect.width,
  615.                        &lp->label_rect.height);
  616.     }
  617. }
  618. /*----------------------------------------------------------------------*/
  619. static void
  620. LayoutComponents(Widget w)
  621. /*----------------------------------------------------------------------*/
  622. {
  623.     /* Invoke layout_string method */
  624.     _XfeLabelLayoutString(w);
  625. }
  626. /*----------------------------------------------------------------------*/
  627. static void
  628. DrawComponents(Widget w,XEvent *event,Region region,XRectangle * clip_rect)
  629. {
  630.     /* Invoke draw_selection method */
  631.     _XfeLabelDrawSelection(w,event,region,clip_rect);
  632.  
  633.     /* Invoke draw_string method */
  634.     _XfeLabelDrawString(w,event,region,clip_rect);
  635. }
  636. /*----------------------------------------------------------------------*/
  637. static GC
  638. GetLabelGC(Widget w)
  639. {
  640.     XfeLabelPart *    lp = _XfeLabelPart(w);
  641.  
  642.     return lp->label_GC;
  643. }
  644. /*----------------------------------------------------------------------*/
  645. static GC
  646. GetSelectionGC(Widget w)
  647. {
  648.     XfeLabelPart *    lp = _XfeLabelPart(w);
  649.  
  650.     return lp->selection_GC;
  651. }
  652. /*----------------------------------------------------------------------*/
  653.  
  654.  
  655. /*----------------------------------------------------------------------*/
  656. /*                                                                        */
  657. /* XfeLabel methods                                                        */
  658. /*                                                                        */
  659. /*----------------------------------------------------------------------*/
  660. static void
  661. LayoutString(Widget w)
  662. /*----------------------------------------------------------------------*/
  663. {
  664.     XfeLabelPart *    lp = _XfeLabelPart(w);
  665.  
  666.     /* Layout the label according to the alignment */
  667.     switch(lp->label_alignment)
  668.     {
  669.     case XmALIGNMENT_BEGINNING:
  670.  
  671.         lp->label_rect.x = _XfeRectX(w);
  672.  
  673.         break;
  674.         
  675.     case XmALIGNMENT_CENTER:
  676.  
  677.         lp->label_rect.x = (_XfeWidth(w) - lp->label_rect.width) / 2;
  678.  
  679.         break;
  680.         
  681.     case XmALIGNMENT_END:
  682.  
  683.         lp->label_rect.x = 
  684.             XfeWidth(w) - 
  685.             lp->label_rect.width - 
  686.             _XfeOffsetRight(w);
  687.         
  688.         break;
  689.     }
  690.  
  691.     /* the label is always centered vertically */
  692.     lp->label_rect.y = (_XfeHeight(w) - lp->label_rect.height) / 2;
  693. }
  694. /*----------------------------------------------------------------------*/
  695. static void
  696. DrawString(Widget w,XEvent * event,Region region,XRectangle * clip_rect)
  697. {
  698.     XfeLabelPart *    lp = _XfeLabelPart(w);
  699.     XRectangle        rect;
  700.     XmString        string = NULL;
  701.     Boolean            need_to_free_string = False;
  702.  
  703.     /* Make sure the label has something before drawing */
  704.     if (!lp->label_rect.width || !lp->label_rect.height || !lp->label_string)
  705.     {
  706.         return;
  707.     }
  708.  
  709.     /* The height and y coordinate are the same regardless of truncation */
  710.     rect.height        = lp->label_rect.height;
  711.     rect.y            = lp->label_rect.y;
  712.  
  713.     /* Determine whether we need to truncate the string */
  714.     if (lp->truncate_label && (lp->label_rect.width > _XfeRectWidth(w)))
  715.     {
  716.         string = CreateTruncatedString(w);
  717.  
  718.         rect.width    = _XfeRectWidth(w);
  719.         rect.x        = _XfeRectX(w);
  720.  
  721.         need_to_free_string = True;        
  722.     }
  723.     else
  724.     {
  725.         string = lp->label_string;
  726.  
  727.         rect.width    = lp->label_rect.width;
  728.         rect.x        = lp->label_rect.x;
  729.  
  730.         need_to_free_string = False;
  731.     }
  732.  
  733.     assert( string != NULL );
  734.  
  735.     /* Determine which gc to use to render the label */
  736.     if (_XfeIsSensitive(w))
  737.     {
  738.         /* Draw the string once */
  739.         XmStringDraw(XtDisplay(w),
  740.                      _XfePrimitiveDrawable(w),
  741.                      lp->font_list,
  742.                      string,
  743.                      _XfeLabelGetLabelGC(w),
  744.                      rect.x + lp->misc_offset,
  745.                      rect.y + lp->misc_offset,
  746.                      rect.width,
  747.                      lp->label_alignment,
  748.                      lp->label_direction,
  749.                      &_XfeWidgetRect(w));
  750.     }
  751.     else
  752.     {
  753.         /* Draw the string twice to achieve that cool insensitve look */
  754.         XmStringDraw(XtDisplay(w),
  755.                      _XfePrimitiveDrawable(w),
  756.                      lp->font_list,
  757.                      string,
  758.                      lp->insensitive_top_GC,
  759.                      rect.x + INSENSITIVE_OFFSET + lp->misc_offset,
  760.                      rect.y + INSENSITIVE_OFFSET + lp->misc_offset,
  761.                      rect.width,
  762.                      lp->label_alignment,
  763.                      lp->label_direction,
  764.                      &_XfeWidgetRect(w));
  765.  
  766.         XmStringDraw(XtDisplay(w),
  767.                      _XfePrimitiveDrawable(w),
  768.                      lp->font_list,
  769.                      string,
  770.                      lp->insensitive_bottom_GC,
  771.                      rect.x + lp->misc_offset,
  772.                      rect.y + lp->misc_offset,
  773.                      rect.width,
  774.                      lp->label_alignment,
  775.                      lp->label_direction,
  776.                      &_XfeWidgetRect(w));
  777.     }
  778.  
  779.     /* Free the string if needed */
  780.     if (need_to_free_string)
  781.     {
  782.         XmStringFree(string);
  783.     }
  784. }
  785. /*----------------------------------------------------------------------*/
  786. static void
  787. DrawSelection(Widget w,XEvent * event,Region region,XRectangle * clip_rect)
  788. {
  789.     XfeLabelPart *    lp = _XfeLabelPart(w);
  790.     Dimension        dx;
  791.     Dimension        dy;
  792.  
  793.     /* Make sure the widget is selected */
  794.     if (!lp->selected)
  795.     {
  796.         return;
  797.     }
  798.  
  799.     /* Make sure the label has something before drawing */
  800.     if (!lp->label_rect.width || !lp->label_rect.height || !lp->label_string)
  801.     {
  802.         return;
  803.     }
  804.  
  805.     /* Compute the extra offset for the selection */
  806.     dx = XfeMin(_XfeMarginLeft(w),_XfeMarginRight(w));
  807.     dx = XfeMin(dx,1);
  808.  
  809.     dy = XfeMin(_XfeMarginTop(w),_XfeMarginBottom(w));
  810.     dy = XfeMin(dy,1);
  811.  
  812.     XFillRectangle(XtDisplay(w),
  813.                    _XfePrimitiveDrawable(w),
  814.                    _XfeLabelGetSelectionGC(w),
  815.                    lp->label_rect.x - dx,
  816.                    lp->label_rect.y - dy,
  817.                    lp->label_rect.width + 2 * dx,
  818.                    lp->label_rect.height + 2 * dy);
  819. }
  820. /*----------------------------------------------------------------------*/
  821.  
  822. /*----------------------------------------------------------------------*/
  823. /*                                                                        */
  824. /* XfeLabel Method invocation functions                                    */
  825. /*                                                                        */
  826. /*----------------------------------------------------------------------*/
  827. /* extern */ void
  828. _XfeLabelLayoutString(Widget w)
  829. {
  830.     XfeLabelWidgetClass    lc = (XfeLabelWidgetClass) XtClass(w);
  831.  
  832.     if (lc->xfe_label_class.layout_string)
  833.     {
  834.         (*lc->xfe_label_class.layout_string)(w);
  835.     }
  836. }
  837. /*----------------------------------------------------------------------*/
  838. /* extern */ void
  839. _XfeLabelDrawString(Widget            w,
  840.                    XEvent *            event,
  841.                    Region            region,
  842.                    XRectangle *        clip_rect)
  843. {
  844.     XfeLabelWidgetClass    lc = (XfeLabelWidgetClass) XtClass(w);
  845.  
  846.     if (lc->xfe_label_class.draw_string)
  847.     {
  848.         (*lc->xfe_label_class.draw_string)(w,event,region,clip_rect);
  849.     }
  850. }
  851. /*----------------------------------------------------------------------*/
  852. /* extern */ void
  853. _XfeLabelDrawSelection(Widget            w,
  854.                        XEvent *            event,
  855.                        Region            region,
  856.                        XRectangle *        clip_rect)
  857. {
  858.     XfeLabelWidgetClass    lc = (XfeLabelWidgetClass) XtClass(w);
  859.  
  860.     if (lc->xfe_label_class.draw_selection)
  861.     {
  862.         (*lc->xfe_label_class.draw_selection)(w,event,region,clip_rect);
  863.     }
  864. }
  865. /*----------------------------------------------------------------------*/
  866. /* extern */ GC
  867. _XfeLabelGetLabelGC(Widget     w)
  868. {
  869.     XfeLabelWidgetClass    lc = (XfeLabelWidgetClass) XtClass(w);
  870.  
  871.     assert( lc->xfe_label_class.get_label_gc != NULL );
  872.  
  873.     return (*lc->xfe_label_class.get_label_gc)(w);
  874. }
  875. /*----------------------------------------------------------------------*/
  876. /* extern */ GC
  877. _XfeLabelGetSelectionGC(Widget     w)
  878. {
  879.     XfeLabelWidgetClass    lc = (XfeLabelWidgetClass) XtClass(w);
  880.  
  881.     assert( lc->xfe_label_class.get_selection_gc != NULL );
  882.  
  883.     return (*lc->xfe_label_class.get_selection_gc)(w);
  884. }
  885. /*----------------------------------------------------------------------*/
  886.  
  887. /*----------------------------------------------------------------------*/
  888. /*                                                                        */
  889. /* Misc XfeLabel functions                                                */
  890. /*                                                                        */
  891. /*----------------------------------------------------------------------*/
  892. static XmString
  893. CreateTruncatedString(Widget w)
  894. {
  895.     XfeLabelPart *    lp = _XfeLabelPart(w);
  896.     XmString        result = NULL;
  897.  
  898.     /* Make sure the truncate proc is good */
  899.     if (lp->truncate_proc)
  900.     {
  901.         String        psz_tmp;
  902.  
  903.         /* Access the label as a psz String */
  904.         XmStringGetLtoR(lp->label_string,XmFONTLIST_DEFAULT_TAG,&psz_tmp);
  905.  
  906.         if (psz_tmp)
  907.         {
  908.             Dimension max_width = _XfeRectWidth(w) - lp->misc_offset;
  909.  
  910.             if (!_XfeIsSensitive(w))
  911.             {
  912.                 max_width -= 1;
  913.             }
  914.             
  915.             /* Create a truncated string */
  916.             result = (*lp->truncate_proc)(psz_tmp,
  917.                                           XmFONTLIST_DEFAULT_TAG,
  918.                                           lp->font_list,
  919.                                           max_width);
  920.  
  921.             /* Free the psz String */
  922.             XtFree(psz_tmp);
  923.         }
  924.     }
  925.     else
  926.     {
  927.         _XfeWarning(w,MESSAGE2);
  928.     }
  929.  
  930.     return result;
  931. }
  932. /*----------------------------------------------------------------------*/
  933. static void
  934. InvokeSelectionChangedCallback(Widget w,XEvent * event)
  935. {
  936.     XfeLabelPart *    lp = _XfeLabelPart(w);
  937.  
  938.     /* Invoke the callbacks only if needed */
  939.     if (lp->selection_changed_callback)
  940.     {
  941.         XfeLabelSelectionChangedCallbackStruct cbs;
  942.     
  943.         cbs.event        = event;
  944.         cbs.reason        = XmCR_SELECTION_CHANGED;
  945.         cbs.selected    = lp->selected;
  946.  
  947.         /* Flush the display */
  948.         XFlush(XtDisplay(w));
  949.         
  950.         /* Invoke the Callback List */
  951.         XtCallCallbackList(w,lp->selection_changed_callback,&cbs);
  952.     }
  953. }
  954. /*----------------------------------------------------------------------*/
  955.  
  956. /*----------------------------------------------------------------------*/
  957. /*                                                                        */
  958. /* XfeLabel action procedures                                            */
  959. /*                                                                        */
  960. /*----------------------------------------------------------------------*/
  961. /* extern */  void
  962. _XfeLabelSelect(Widget w,XEvent * event,char ** params,Cardinal * nparams)
  963. {
  964.     XfeLabelPart *    lp = _XfeLabelPart(w);
  965.  
  966.     /* Make sure we are not pretending to be insensitive */
  967.     if (!_XfeIsSensitive(w))
  968.     {
  969.         return;
  970.     }
  971.  
  972.     /* Look for modifiers that matches the selection modifiers */
  973.     if (_XfeLabelAcceptSelectionEvent(w,event,True))
  974.     {
  975.         _XfeLabelSetSelected(w,event,!lp->selected,True);
  976.     }
  977. }
  978. /*----------------------------------------------------------------------*/
  979.  
  980. /*----------------------------------------------------------------------*/
  981. /*                                                                        */
  982. /* XfeLabel private functions                                            */
  983. /*                                                                        */
  984. /*----------------------------------------------------------------------*/
  985. /* extern */  Boolean
  986. _XfeLabelAcceptSelectionEvent(Widget w,XEvent * event,Boolean inside_label)
  987. {
  988.     XfeLabelPart *    lp = _XfeLabelPart(w);
  989.     Boolean            result = False;
  990.  
  991.     /* Look for modifiers that matches the selection modifiers */
  992.     if ((XfeEventGetModifiers(event) & lp->selection_modifiers) || 
  993.         (lp->selection_modifiers == AnyModifier))
  994.     {
  995.         /* Make sure the event's x,y occured inside the label if needed */
  996.         if (inside_label)
  997.         {
  998.             int    x;
  999.             int    y;
  1000.  
  1001.             /* Determine if the pointer is in the label */
  1002.             result = (XfeEventGetXY(event,&x,&y) && 
  1003.                       XfePointInRect(&lp->label_rect,x,y));
  1004.         }
  1005.         else
  1006.         {
  1007.             result = True;
  1008.         }
  1009.     }
  1010.  
  1011.     return result;
  1012. }
  1013. /*----------------------------------------------------------------------*/
  1014. /* extern */  void
  1015. _XfeLabelSetSelected(Widget        w,
  1016.                      XEvent *    event,
  1017.                      Boolean    selected,
  1018.                      Boolean    invoke_callbacks)
  1019. {
  1020.     XfeLabelPart *    lp = _XfeLabelPart(w);
  1021.  
  1022.     assert( XfeIsLabel(w) );
  1023.  
  1024.     /* Make sure the selection has changed */
  1025.     if (lp->selected == selected)
  1026.     {
  1027.         return;
  1028.     }
  1029.  
  1030.     /* Assign the new selection */
  1031.     lp->selected = selected;
  1032.  
  1033.     /* Make sure the widget is alive and kicking before drawing */
  1034.     if (_XfeIsRealized(w) && _XfeIsManaged(w))
  1035.     {
  1036.         /* Erase the old stuff */
  1037.         _XfePrimitiveClearBackground(w);
  1038.         
  1039.         /* Redraw the buffer */
  1040.         _XfePrimitiveDrawEverything(w,NULL,NULL);
  1041.         
  1042.         /* Draw the buffer onto the window */
  1043.         XfeExpose(w,NULL,NULL);
  1044.     }
  1045.  
  1046.     /* Invoke the selection callbacks if needed */
  1047.     if (invoke_callbacks)
  1048.     {
  1049.         InvokeSelectionChangedCallback(w,event);
  1050.     }
  1051. }
  1052. /*----------------------------------------------------------------------*/
  1053.  
  1054.  
  1055. /*----------------------------------------------------------------------*/
  1056. /*                                                                        */
  1057. /* XfeLabel Public Methods                                                */
  1058. /*                                                                        */
  1059. /*----------------------------------------------------------------------*/
  1060. /* extern */ Widget
  1061. XfeCreateLabel(Widget pw,char * name,ArgList av,Cardinal ac)
  1062. {
  1063.     return XtCreateWidget(name,xfeLabelWidgetClass,pw,av,ac);
  1064. }
  1065. /*----------------------------------------------------------------------*/
  1066. /* extern */ void
  1067. XfeLabelSetString(Widget w,XmString xm_label)
  1068. {
  1069.     XfeLabelPart *    lp = _XfeLabelPart(w);
  1070.  
  1071.     assert( _XfeIsAlive(w) );
  1072.  
  1073.     /* Make sure the label is different */
  1074.     if (XmStringByteCompare(xm_label,lp->label_string))
  1075.     {
  1076.         return;
  1077.     }
  1078.  
  1079.     /* Free the old string */
  1080.     XmStringFree(lp->label_string);
  1081.  
  1082.     /* Make a copy of the given string or set it to "" if null */
  1083.     if (xm_label)
  1084.     {
  1085.         lp->label_string = XfeXmStringCopy(w,xm_label,XtName(w));
  1086.     }
  1087.     else
  1088.     {
  1089.         lp->label_string = XmStringCreate("",XmFONTLIST_DEFAULT_TAG);
  1090.     }
  1091.  
  1092.  
  1093.     /* Prepare the label */
  1094.     _XfePrimitivePrepareComponents(w,_XFE_PREPARE_LABEL_STRING);
  1095.  
  1096.     /* Relayout the widget */
  1097.     _XfePrimitiveLayoutComponents(w);
  1098.  
  1099.     /* Make sure the widget is realized before drawing anything */
  1100.     if (!XtIsRealized(w))
  1101.     {
  1102.         return;
  1103.     }
  1104.  
  1105.     /* Erase the old stuff */
  1106.     _XfePrimitiveClearBackground(w);
  1107.  
  1108.     /* Redraw the buffer */
  1109.     _XfePrimitiveDrawEverything(w,NULL,NULL);
  1110.  
  1111.     /* Draw the buffer onto the window */
  1112.     XfeExpose(w,NULL,NULL);
  1113. }
  1114. /*----------------------------------------------------------------------*/
  1115. /* extern */ void
  1116. XfeLabelSetStringPSZ(Widget w,String psz_label)
  1117. {
  1118.     XfeLabelPart *        lp = _XfeLabelPart(w);
  1119.     XmString            xm_new_label;
  1120.  
  1121.     assert( _XfeIsAlive(w) );
  1122.  
  1123.     /* Set the new string */
  1124.     if (psz_label)
  1125.     {
  1126.         xm_new_label = XmStringCreate(psz_label,XmFONTLIST_DEFAULT_TAG);
  1127.     }
  1128.     else
  1129.     {
  1130.         xm_new_label = XmStringCreate("",XmFONTLIST_DEFAULT_TAG);
  1131.     }
  1132.  
  1133.     /* Make sure the label is different */
  1134.     if (XmStringByteCompare(xm_new_label,lp->label_string))
  1135.     {
  1136.         XmStringFree(xm_new_label);
  1137.  
  1138.         return;
  1139.     }
  1140.  
  1141.     /* Free the old string */
  1142.     XmStringFree(lp->label_string);
  1143.  
  1144.     lp->label_string = xm_new_label;
  1145.  
  1146.     /* Prepare the label */
  1147.     _XfePrimitivePrepareComponents(w,_XFE_PREPARE_LABEL_STRING);
  1148.  
  1149.     /* Relayout the widget */
  1150.     _XfePrimitiveLayoutComponents(w);
  1151.  
  1152.     /* Make sure the widget is realized before drawing anything */
  1153.     if (!XtIsRealized(w))
  1154.     {
  1155.         return;
  1156.     }
  1157.  
  1158.     /* Erase the old stuff */
  1159.     _XfePrimitiveClearBackground(w);
  1160.  
  1161.     /* Redraw the buffer */
  1162.     _XfePrimitiveDrawEverything(w,NULL,NULL);
  1163.  
  1164.     /* Draw the buffer onto the window */
  1165.     XfeExpose(w,NULL,NULL);
  1166. }
  1167. /*----------------------------------------------------------------------*/
  1168. /* extern */  void
  1169. XfeLabelSetSelected(Widget w,Boolean selected)
  1170. {
  1171.     XfeLabelPart *    lp = _XfeLabelPart(w);
  1172.  
  1173.     assert( XfeIsLabel(w) );
  1174.  
  1175.     _XfeLabelSetSelected(w,NULL,selected,False);
  1176. }
  1177. /*----------------------------------------------------------------------*/
  1178.