home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / XfeWidgets / Xfe / BmCascade.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  24.5 KB  |  809 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/BmCascade.c>                                        */
  21. /* Description:    XfeBmCascade widget source.                                */
  22. /* Author:        Ramiro Estrugo <ramiro@netscape.com>                    */
  23. /*                                                                        */
  24. /*----------------------------------------------------------------------*/
  25.  
  26.  
  27. #include <Xfe/BmCascadeP.h>
  28. #include <Xfe/BmButtonP.h>
  29. #include <Xfe/Cascade.h>
  30. #include <Xfe/ManagerP.h>
  31.  
  32. #include <Xm/CascadeBGP.h>
  33.  
  34. #include <Xm/MenuShellP.h>
  35. #include <Xm/RowColumnP.h>
  36.  
  37. /*----------------------------------------------------------------------*/
  38. /*                                                                        */
  39. /* Warnings and messages                                                */
  40. /*                                                                        */
  41. /*----------------------------------------------------------------------*/
  42. #define MESSAGE1 "Widget is not a XfeBmCascade."
  43. #define MESSAGE2 "XmNaccentType is a read-only reasource."
  44.  
  45. /*----------------------------------------------------------------------*/
  46. /*                                                                        */
  47. /* Core Class methods                                                    */
  48. /*                                                                        */
  49. /*----------------------------------------------------------------------*/
  50. static void                Initialize        (Widget,Widget,ArgList,Cardinal *);
  51. static void                Destroy            (Widget);
  52. static void                Resize            (Widget);
  53. static void                Redisplay        (Widget,XEvent *,Region);
  54. static Boolean            SetValues        (Widget,Widget,Widget,
  55.                                          ArgList,Cardinal *);
  56.  
  57. static XtGeometryResult    QueryGeometry    (Widget,XtWidgetGeometry *,
  58.                                          XtWidgetGeometry *);
  59.  
  60. /*----------------------------------------------------------------------*/
  61. /*                                                                        */
  62. /* XmPrimitive methods                                                    */
  63. /*                                                                        */
  64. /*----------------------------------------------------------------------*/
  65. static void     BorderHighlight            (Widget);
  66. static void     BorderUnhighlight        (Widget);
  67.  
  68. /*----------------------------------------------------------------------*/
  69. /*                                                                        */
  70. /* XfeBmCascade action procedures                                        */
  71. /*                                                                        */
  72. /*----------------------------------------------------------------------*/
  73. static void     CheckDisarm                (Widget,XEvent *,char **,Cardinal *);
  74. static void     DelayedArm                (Widget,XEvent *,char **,Cardinal *);
  75. static void     DoSelect                (Widget,XEvent *,char **,Cardinal *);
  76. static void     Motion                    (Widget,XEvent *,char **,Cardinal *);
  77.  
  78. /*----------------------------------------------------------------------*/
  79. /*                                                                        */
  80. /* Misc XfeBmCascade functions                                            */
  81. /*                                                                        */
  82. /*----------------------------------------------------------------------*/
  83. static void        DrawPixmap                (Widget,XEvent *,Region);
  84. static Position    GetPointerY                (Widget);
  85.  
  86. static void        AccentUpdate            (Widget,Position);
  87. static void        AccentDraw                (Widget);
  88. static void        AccentErase                (Widget);
  89.  
  90. /*----------------------------------------------------------------------*/
  91. /*                                                                        */
  92. /* XfeBmCascade Resources                                                */
  93. /*                                                                        */
  94. /*----------------------------------------------------------------------*/
  95. static XtResource resources[] = 
  96. {
  97.     /* Pixmap resources */
  98.     { 
  99.         XmNaccentType,
  100.         XmCAccentType,
  101.         XmRAccentType,
  102.         sizeof(unsigned char),
  103.         XtOffsetOf(XfeBmCascadeRec , bm_cascade . accent_type),
  104.         XmRImmediate, 
  105.         (XtPointer) XmACCENT_NONE
  106.     },
  107.     { 
  108.         XmNarmPixmap,
  109.         XmCArmPixmap,
  110.         XmRPixmap,
  111.         sizeof(Pixmap),
  112.         XtOffsetOf(XfeBmCascadeRec , bm_cascade . arm_pixmap),
  113.         XmRImmediate, 
  114.         (XtPointer) XmUNSPECIFIED_PIXMAP
  115.     },
  116.     { 
  117.         XmNarmPixmapMask,
  118.         XmCArmPixmapMask,
  119.         XmRPixmap,
  120.         sizeof(Pixmap),
  121.         XtOffsetOf(XfeBmCascadeRec , bm_cascade . arm_pixmap_mask),
  122.         XmRImmediate, 
  123.         (XtPointer) XmUNSPECIFIED_PIXMAP
  124.     },
  125.     { 
  126.         XmNlabelPixmapMask,
  127.         XmCLabelPixmapMask,
  128.         XmRPixmap,
  129.         sizeof(Pixmap),
  130.         XtOffsetOf(XfeBmCascadeRec , bm_cascade . label_pixmap_mask),
  131.         XmRImmediate, 
  132.         (XtPointer) XmUNSPECIFIED_PIXMAP
  133.     },
  134. };
  135.  
  136. /*----------------------------------------------------------------------*/
  137. /*                                                                        */
  138. /* XmPrimitive extension record initialization                            */
  139. /*                                                                        */
  140. /*----------------------------------------------------------------------*/
  141. static XmPrimitiveClassExtRec xmPrimitiveClassExtRec = 
  142. {
  143.     NULL,                                    /* next_extension            */
  144.     NULLQUARK,                                /* record_type                */
  145.     XmPrimitiveClassExtVersion,                /* version                    */
  146.     sizeof(XmPrimitiveClassExtRec),            /* record_size                */
  147.     XmInheritBaselineProc,                    /* widget_baseline            */
  148.     XmInheritDisplayRectProc,                /* widget_display_rect        */
  149.     XmInheritMarginsProc,                    /* widget_margins            */
  150. };
  151.  
  152.  
  153. /*----------------------------------------------------------------------*/
  154. /*                                                                        */
  155. /* XmCascadeButton extension record initialization                        */
  156. /*                                                                        */
  157. /*----------------------------------------------------------------------*/
  158. static XmBaseClassExtRec xmCascadeButtonClassExtRec = 
  159. {
  160.     NULL,                                   /* Next extension           */
  161.     NULLQUARK,                              /* record type XmQmotif     */
  162.     XmBaseClassExtVersion,                  /* version                  */
  163.     sizeof(XmBaseClassExtRec),              /* size                     */
  164.     XmInheritInitializePrehook,             /* initialize prehook       */
  165.     XmInheritSetValuesPrehook,              /* set_values prehook       */
  166.     XmInheritInitializePosthook,            /* initialize posthook      */
  167.     XmInheritSetValuesPosthook,             /* set_values posthook      */
  168.     XmInheritClass,                         /* secondary class          */
  169.     XmInheritSecObjectCreate,               /* creation proc            */
  170.     XmInheritGetSecResData,                 /* getSecResData            */
  171.     {0},                                    /* fast subclass            */
  172.     XmInheritGetValuesPrehook,              /* get_values prehook       */
  173.     XmInheritGetValuesPosthook,             /* get_values posthook      */
  174.     XmInheritClassPartInitPrehook,          /* classPartInitPrehook     */
  175.     XmInheritClassPartInitPosthook,         /* classPartInitPosthook    */
  176.     NULL,                                   /* ext_resources            */
  177.     NULL,                                   /* compiled_ext_resources   */
  178.     0,                                      /* num_ext_resources        */
  179.     FALSE,                                  /* use_sub_resources        */
  180.     XmInheritWidgetNavigable,               /* widgetNavigable          */
  181.     XmInheritFocusChange,                   /* focusChange              */
  182. };
  183.  
  184. /*----------------------------------------------------------------------*/
  185. /*                                                                        */
  186. /* XfeBmCascade actions                                                    */
  187. /*                                                                        */
  188. /*----------------------------------------------------------------------*/
  189. static XtActionsRec actions[] = 
  190. {
  191.     { "CheckDisarm",            CheckDisarm            },
  192.     { "DelayedArm",                DelayedArm            },
  193.     { "DoSelect",                DoSelect            },
  194.     { "Motion",                    Motion                },
  195. };
  196.  
  197. /*----------------------------------------------------------------------*/
  198. /*                                                                        */
  199. /* XfeBmCascade widget class record initialization                        */
  200. /*                                                                        */
  201. /*----------------------------------------------------------------------*/
  202. _XFE_WIDGET_CLASS_RECORD(bmcascade,BmCascade) =
  203. {
  204.     {
  205.         /* Core Part */
  206.         (WidgetClass) &xmCascadeButtonClassRec,    /* superclass             */
  207.         "XfeBmCascade",                            /* class_name            */
  208.         sizeof(XfeBmCascadeRec),                /* widget_size            */
  209.         NULL,                                    /* class_initialize       */
  210.         NULL,                                    /* class_part_initialize*/
  211.         FALSE,                                  /* class_inited           */
  212.         Initialize,                                /* initialize            */
  213.         NULL,                                   /* initialize_hook        */
  214.         XtInheritRealize,                       /* realize                */
  215.         actions,                                /* actions                */
  216.         XtNumber(actions),                        /* num_actions            */
  217.         resources,                              /* resources              */
  218.         XtNumber(resources),                    /* num_resources          */
  219.         NULLQUARK,                              /* xrm_class              */
  220.         TRUE,                                   /* compress_motion        */
  221.         XtExposeCompressMaximal,                /* compress_exposure      */
  222.         TRUE,                                   /* compress_enterleave    */
  223.         FALSE,                                  /* visible_interest       */
  224.         Destroy,                                /* destroy                */
  225.         Resize,                                    /* resize                 */
  226.         Redisplay,                                /* expose                 */
  227.         SetValues,                              /* set_values             */
  228.         NULL,                                   /* set_values_hook        */
  229.         XtInheritSetValuesAlmost,                /* set_values_almost      */
  230.         NULL,                                    /* get_values_hook        */
  231.         NULL,                                   /* accept_focus           */
  232.         XtVersion,                              /* version                */
  233.         NULL,                                   /* callback_private       */
  234.         XtInheritTranslations,                    /* tm_table               */
  235.         QueryGeometry,                            /* query_geometry         */
  236.         XtInheritDisplayAccelerator,            /* display accel          */
  237.         (XtPointer) &xmCascadeButtonClassExtRec    /* extension              */
  238.     },
  239.  
  240.     /* XmPrimitive Part */
  241.     {
  242.         BorderHighlight,                        /* border_highlight     */
  243.         BorderUnhighlight,                        /* border_unhighlight     */
  244.         XtInheritTranslations,                  /* translations           */
  245.         XmInheritArmAndActivate,                /* arm_and_activate       */
  246.         NULL,                                    /* syn resources          */
  247.         0,                                        /* num syn_resources      */
  248.         (XtPointer) &xmPrimitiveClassExtRec,    /* extension              */
  249.     },
  250.  
  251.     /* XmLabel Part */
  252.     {
  253.         XmInheritWidgetProc,                    /* setOverrideCallback    */
  254.         XmInheritMenuProc,                        /* menu procedures        */
  255.         XtInheritTranslations,                    /* menu traversal xlat    */
  256.         (XtPointer) NULL,                        /* extension            */
  257.     },
  258.  
  259.     /* XmCascadeButton Part */
  260.     {
  261.         (XtPointer) NULL,                        /* extension            */
  262.     },
  263.  
  264.     /* XfeBmCascade Part */
  265.     {
  266.         (XtPointer) NULL,                        /* extension            */
  267.     }
  268. };
  269.  
  270. /*----------------------------------------------------------------------*/
  271. /*                                                                        */
  272. /* xfeBmCascadeWidgetClass declaration.                                    */
  273. /*                                                                        */
  274. /*----------------------------------------------------------------------*/
  275. _XFE_WIDGET_CLASS(bmcascade,BmCascade);
  276.  
  277. /*----------------------------------------------------------------------*/
  278. /*                                                                        */
  279. /* Core Class methods                                                    */
  280. /*                                                                        */
  281. /*----------------------------------------------------------------------*/
  282. static void
  283. Initialize(Widget rw,Widget nw,ArgList args,Cardinal *nargs)
  284. {
  285.     XfeBmCascadePart *        bmc = _XfeBmCascadePart(nw);
  286.     XmLabelPart *            lp = _XfeXmLabelPart(nw);
  287.  
  288.     /* Force the type to be string always */
  289.     lp->label_type = XmSTRING;
  290.  
  291.     bmc->pixmap_GC = XfeAllocateTransparentGc(nw);
  292.  
  293.     _XfePixmapPrepare(nw,
  294.                       &lp->pixmap,
  295.                       &bmc->pixmap_width,
  296.                       &bmc->pixmap_height,
  297.                       XmNlabelPixmap);
  298.  
  299.     XfeOverrideTranslations(nw,_XfeBmButtonExtraTranslations);
  300. }
  301. /*----------------------------------------------------------------------*/
  302. static void
  303. Destroy(Widget w)
  304. {
  305.     XfeBmCascadePart * bmc = _XfeBmCascadePart(w);
  306.  
  307.     XtReleaseGC(w,bmc->pixmap_GC);
  308. }
  309. /*----------------------------------------------------------------------*/
  310. static XtGeometryResult
  311. QueryGeometry(Widget w,XtWidgetGeometry    *req,XtWidgetGeometry *reply)
  312. {
  313.     XfeBmCascadePart *        bmc = _XfeBmCascadePart(w);
  314.     XmLabelPart *            lp = _XfeXmLabelPart(w);
  315.     XtGeometryResult        result;
  316.     XmCascadeButtonWidgetClass cbc = 
  317.         (XmCascadeButtonWidgetClass) xmCascadeButtonWidgetClass;
  318.     
  319.     result = (*cbc->core_class.query_geometry)(w,req,reply);
  320.  
  321.     if (bmc->pixmap_width && bmc->pixmap_height)
  322.     {
  323.         Dimension offset;
  324.         Dimension label_height;
  325.  
  326.         reply->width += (bmc->pixmap_width + XfeBmPixmapGetOffset());
  327.  
  328.         offset = 
  329.             lp->margin_top +
  330.             lp->margin_bottom +
  331.             _XfePrimitiveOffset(w);
  332.  
  333.         label_height = reply->height - offset;
  334.  
  335.         reply->height = 
  336.             XfeMax(label_height,bmc->pixmap_height) +
  337.             offset;
  338.     }
  339.  
  340.     return result;
  341. }
  342. /*----------------------------------------------------------------------*/
  343. static void
  344. Resize(Widget w)
  345. {
  346.     XfeBmCascadePart *            bmc = _XfeBmCascadePart(w);
  347.     XmLabelPart *                lp = _XfeXmLabelPart(w);
  348.     XmCascadeButtonWidgetClass    cbc = 
  349.         (XmCascadeButtonWidgetClass) xmCascadeButtonWidgetClass;
  350.  
  351.     (*cbc->core_class.resize)(w);
  352.  
  353.     /* Layout the pixmap if needed */
  354.     if (bmc->pixmap_width && bmc->pixmap_height)
  355.     {
  356.         /* Move the label outta the way to the right */
  357.         lp->TextRect.x += (bmc->pixmap_width + XfeBmPixmapGetOffset());
  358.     }
  359. }
  360. /*----------------------------------------------------------------------*/
  361. static void
  362. Redisplay(Widget w,XEvent *event,Region region)
  363. {
  364.     XmCascadeButtonWidgetClass        pwc = 
  365.         (XmCascadeButtonWidgetClass) xmCascadeButtonWidgetClass;
  366.  
  367.     if (XfeBmAccentIsEnabled())
  368.     {
  369.         Dimension shadow_thickness = _XfeShadowThickness(w);
  370.  
  371.         /*
  372.          * We change the shadow thickness to 0, so that the real Expose() 
  373.          * method not draw anything the shadow so that the accent lines
  374.          * are not disturbed.
  375.          */
  376.         _XfeShadowThickness(w)        = 0;
  377.         _XfeHighlightThickness(w)    = shadow_thickness;
  378.         
  379.         (*pwc->core_class.expose)(w,event,region);
  380.         
  381.         _XfeShadowThickness(w)        = shadow_thickness;
  382.         _XfeHighlightThickness(w)    = 0;
  383.     }
  384.     else
  385.     {
  386.         (*pwc->core_class.expose)(w,event,region);
  387.     }
  388.     
  389.     DrawPixmap(w,event,region);
  390. }
  391. /*----------------------------------------------------------------------*/
  392. static Boolean
  393. SetValues(Widget ow,Widget rw,Widget nw,ArgList args,Cardinal *nargs)
  394. {
  395.     Boolean                    redisplay = False;
  396.     Boolean                    resize = False;
  397.      XmCascadeButtonPart *    old_cp = _XfeXmCascadeButtonPart(ow);
  398.      XmCascadeButtonPart *    new_cp = _XfeXmCascadeButtonPart(nw);
  399.     XmLabelPart *            old_lp = _XfeXmLabelPart(ow);
  400.     XmLabelPart *            new_lp = _XfeXmLabelPart(nw);
  401.     XfeBmCascadePart *        new_bmc = _XfeBmCascadePart(nw);
  402.     XfeBmCascadePart *        old_bmc = _XfeBmCascadePart(ow);
  403.  
  404.     /* accent_type */
  405.     if (new_bmc->accent_type != old_bmc->accent_type)
  406.     {
  407.         new_bmc->accent_type = old_bmc->accent_type;
  408.  
  409.         _XfeWarning(nw,MESSAGE2);
  410.     }
  411.  
  412.     /* label_pixmap */
  413.     if (new_lp->pixmap != old_lp->pixmap)
  414.     {
  415.         _XfePixmapPrepare(nw,&new_lp->pixmap,
  416.                           &new_bmc->pixmap_width,
  417.                           &new_bmc->pixmap_height,
  418.                           XmNlabelPixmap);
  419.  
  420.         redisplay = True;
  421.         resize = True;
  422.     }
  423.  
  424.     /* arm_pixmap */
  425.     if (new_bmc->arm_pixmap != old_bmc->arm_pixmap)
  426.     {
  427.         Dimension width;
  428.         Dimension height;
  429.  
  430.         assert( _XfePixmapGood(new_lp->pixmap) );
  431.  
  432.         _XfePixmapPrepare(nw,&new_bmc->arm_pixmap,
  433.                           &width,
  434.                           &height,
  435.                           XmNarmPixmap);
  436.  
  437.         assert( width == new_bmc->pixmap_width );
  438.         assert( height == new_bmc->pixmap_height );
  439.  
  440.         redisplay = True;
  441.         resize = True;
  442.     }
  443.  
  444.     if (resize)
  445.     {
  446.         Resize(nw);
  447.     }
  448.  
  449.     return redisplay;
  450. }
  451. /*----------------------------------------------------------------------*/
  452.  
  453. /*----------------------------------------------------------------------*/
  454. /*                                                                        */
  455. /* XmPrimitive methods                                                    */
  456. /*                                                                        */
  457. /*----------------------------------------------------------------------*/
  458. static void
  459. BorderHighlight(Widget w)
  460. {
  461.     XfeBmCascadePart *            bmc = _XfeBmCascadePart(w);
  462.     XmCascadeButtonWidgetClass        cwc = 
  463.         (XmCascadeButtonWidgetClass) xmCascadeButtonWidgetClass;
  464.  
  465.     if (XfeBmAccentIsEnabled())
  466.     {
  467.         _XfeBmProcWithoutDrawing(w,cwc->primitive_class.border_highlight);
  468.     }
  469.     else
  470.     {
  471.         (*cwc->primitive_class.border_highlight)(w);
  472.     }
  473.  
  474.     DrawPixmap(w,NULL,NULL);
  475. }
  476. /*----------------------------------------------------------------------*/
  477. static void
  478. BorderUnhighlight(Widget w)
  479. {
  480.     XfeBmCascadePart *            bmc = _XfeBmCascadePart(w);
  481.     XmCascadeButtonWidgetClass        cwc = 
  482.         (XmCascadeButtonWidgetClass) xmCascadeButtonWidgetClass;
  483.  
  484.     if (XfeBmAccentIsEnabled())
  485.     {
  486.          _XfeBmProcWithoutDrawing(w,cwc->primitive_class.border_unhighlight);
  487.     }
  488.     else
  489.     {
  490.         (*cwc->primitive_class.border_unhighlight)(w);
  491.     }
  492.  
  493.     DrawPixmap(w,NULL,NULL);
  494. }
  495. /*----------------------------------------------------------------------*/
  496.  
  497. /*----------------------------------------------------------------------*/
  498. /*                                                                        */
  499. /* XfeBmCascade action procedures                                        */
  500. /*                                                                        */
  501. /*----------------------------------------------------------------------*/
  502. static void
  503. CheckDisarm(Widget w,XEvent * event,char ** params,Cardinal * nparams)
  504. {
  505.     static XtActionProc        check_disarm_action = NULL;
  506.     XfeBmCascadePart *        bmc = _XfeBmCascadePart(w);
  507.  
  508.     if (!check_disarm_action)
  509.     {
  510.         check_disarm_action = _XfeGetActionProc(xmCascadeButtonWidgetClass,
  511.                                               "CheckDisarm");
  512.     }
  513.  
  514.     if (XfeBmAccentIsEnabled())
  515.     {
  516.         _XfeBmActionWithoutDrawing(w,check_disarm_action,event,params,nparams);
  517.  
  518.         AccentUpdate(w,XfeACCENT_OUTSIDE);
  519.     }
  520.     else
  521.     {
  522.         check_disarm_action(w,event,params,nparams);
  523.     }
  524.  
  525.     /*
  526.      * Redraw the pixmap since fancy motif menus such as those in 
  527.      * irix or cde will fill the whole background and erase the 
  528.      * previous menu.  This should be smarter, and redraw the pixmap
  529.      * only if needed, but the extra waste in time is smaller than
  530.      * the effort needed to implement it.
  531.      */
  532.     DrawPixmap(w,NULL,NULL);
  533. }
  534. /*----------------------------------------------------------------------*/
  535. static void
  536. DelayedArm(Widget w,XEvent * event,char ** params,Cardinal * nparams)
  537. {
  538.     static XtActionProc        delayed_arm_action = NULL;
  539.     XfeBmCascadePart *        bmc = _XfeBmCascadePart(w);
  540.  
  541.     if (!delayed_arm_action)
  542.     {
  543.         delayed_arm_action = _XfeGetActionProc(xmCascadeButtonWidgetClass,
  544.                                               "DelayedArm");
  545.     }
  546.  
  547.     if (XfeBmAccentIsEnabled())
  548.     {
  549.         /*
  550.          * There is a very nasty motif bug that causes the cascading shell
  551.          * to appear much to the right of what it is supposed to be.
  552.          * 
  553.          * The reason for this is very complicated, but fortunately the
  554.          * solution is pretty simple.  By moving the parent row column
  555.          * to (0,0) every time before the cascading shell is posted, the
  556.          * problem is fixed.
  557.          */
  558.         _XfeMoveWidget(XtParent(w),0,0);
  559.  
  560.         _XfeBmActionWithoutDrawing(w,delayed_arm_action,event,params,nparams);
  561.         
  562.         AccentUpdate(w,event->xcrossing.y);
  563.     }
  564.     else
  565.     {
  566.         delayed_arm_action(w,event,params,nparams);
  567.     }
  568.  
  569.  
  570.     /*
  571.      * Redraw the pixmap since fancy motif menus such as those in 
  572.      * irix or cde will fill the whole background and erase the 
  573.      * previous menu.  This should be smarter, and redraw the pixmap
  574.      * only if needed, but the extra waste in time is smaller than
  575.      * the effort needed to implement it.
  576.      */
  577.     DrawPixmap(w,NULL,NULL);
  578. }
  579. /*----------------------------------------------------------------------*/
  580. static void
  581. DoSelect(Widget w,XEvent * event,char ** params,Cardinal * nparams)
  582. {
  583.     static XtActionProc do_select_action = NULL;
  584.  
  585.  
  586.     if (!do_select_action)
  587.     {
  588.         do_select_action = _XfeGetActionProc(xmCascadeButtonWidgetClass,
  589.                                              "DoSelect");
  590.     }
  591.  
  592.     if (XfeBmAccentIsEnabled())
  593.     {
  594.         XmCascadeButtonPart * cp = _XfeXmCascadeButtonPart(w);
  595.  
  596.           _XmMenuPopDown(XtParent(w),event,NULL);
  597.  
  598.         _XfeInvokeCallbacks(w,cp->activate_callback,XmCR_ACTIVATE,event,False);
  599.         
  600.         AccentUpdate(w,XfeACCENT_OUTSIDE);
  601.     }
  602.     else
  603.     {
  604.         do_select_action(w,event,params,nparams);
  605.     }
  606. }
  607. /*----------------------------------------------------------------------*/
  608. static void
  609. Motion(Widget w,XEvent * event,char ** params,Cardinal * nparams)
  610. {
  611.     XfeBmCascadePart *        bmc = _XfeBmCascadePart(w);
  612.  
  613.     if (!XfeBmAccentIsEnabled())
  614.     {
  615.         return;
  616.     }
  617.  
  618.     AccentUpdate(w,event->xmotion.y);
  619. }
  620. /*----------------------------------------------------------------------*/
  621.  
  622. /*----------------------------------------------------------------------*/
  623. /*                                                                        */
  624. /* Misc XfeBmCascade functions                                            */
  625. /*                                                                        */
  626. /*----------------------------------------------------------------------*/
  627. static void
  628. DrawPixmap(Widget w,XEvent *event,Region region)
  629. {
  630.     XfeBmCascadePart *        bmc = _XfeBmCascadePart(w);
  631.     XmLabelPart *            lp = _XfeXmLabelPart(w);
  632.     Pixmap                    pixmap = XmUNSPECIFIED_PIXMAP;
  633.     Pixmap                    mask = XmUNSPECIFIED_PIXMAP;
  634.     Boolean                    armed = CB_IsArmed(w);
  635.  
  636.     if (armed && _XfePixmapGood(bmc->arm_pixmap))
  637.     {
  638.         pixmap = bmc->arm_pixmap;
  639.  
  640.         if (_XfePixmapGood(bmc->arm_pixmap_mask))
  641.         {
  642.             mask = bmc->arm_pixmap_mask;
  643.         }
  644.     }
  645.     else if (_XfePixmapGood(lp->pixmap) && 
  646.              bmc->pixmap_width && bmc->pixmap_height)
  647.     {
  648.         pixmap = lp->pixmap;
  649.  
  650.         if (_XfePixmapGood(bmc->label_pixmap_mask))
  651.         {
  652.             mask = bmc->label_pixmap_mask;
  653.         }
  654.     }
  655.  
  656.     if (_XfePixmapGood(pixmap))
  657.     {
  658.         Position x = _XfePrimitiveOffset(w) + lp->margin_width;
  659.         Position y = (_XfeHeight(w) - bmc->pixmap_height) / 2;
  660.  
  661.         if (_XfePixmapGood(mask))
  662.         {
  663.             XSetClipOrigin(XtDisplay(w),bmc->pixmap_GC,x,y);
  664.             XSetClipMask(XtDisplay(w),bmc->pixmap_GC,mask);
  665.         }
  666.         else
  667.         {
  668.             XSetClipMask(XtDisplay(w),bmc->pixmap_GC,None);
  669.         }
  670.  
  671.         XCopyArea(XtDisplay(w),
  672.                   pixmap,
  673.                   _XfeWindow(w),
  674.                   bmc->pixmap_GC,
  675.                   0,0,
  676.                   bmc->pixmap_width,
  677.                   bmc->pixmap_height,
  678.                   x,
  679.                   y);
  680.     }
  681.  
  682. }
  683. /*----------------------------------------------------------------------*/
  684. static Position
  685. GetPointerY(Widget w)
  686. {
  687.     Window            root;
  688.     Window            child;
  689.     int                rx;
  690.     int                ry;
  691.     int                cx;
  692.     int                cy;
  693.     unsigned int    mask;
  694.  
  695.     if (XQueryPointer(XtDisplay(w),_XfeWindow(w),&root,&child,
  696.                       &rx,&ry,&cx,&cy,&mask))
  697.     {
  698.         cy -= _XfeY(w);
  699.  
  700.         if (cy < 0)
  701.         {
  702.             cy = 0;
  703.         }
  704.         
  705.         if (cy > _XfeHeight(w))
  706.         {
  707.             cy = _XfeHeight(w);
  708.         }
  709.  
  710.         return cy;
  711.     }
  712.  
  713.     return 0;
  714. }
  715. /*----------------------------------------------------------------------*/
  716. static void
  717. AccentUpdate(Widget w,Position y)
  718. {
  719.     unsigned char         new_accent_type = XmACCENT_NONE;
  720.     XfeBmCascadePart *     bmc = _XfeBmCascadePart(w);
  721.     Dimension            one_fourth = _XfeHeight(w) / 4;
  722.  
  723.     /* Determine the new accent */
  724.     if (XfeBmAccentGetFileMode() == XmACCENT_FILE_ANYWHERE)
  725.     {
  726.         if ( (y <= one_fourth) && (y >= 0) )
  727.         {
  728.             new_accent_type = XmACCENT_TOP;
  729.         }
  730.         else if ( (y > (_XfeHeight(w) - one_fourth)) && (y <= _XfeHeight(w)) )
  731.         {
  732.             new_accent_type = XmACCENT_BOTTOM;
  733.         }
  734.         else if ( (y > one_fourth) && (y <= (_XfeHeight(w) - one_fourth)))
  735.         {
  736.             new_accent_type = XmACCENT_ALL;
  737.         }
  738.     }
  739.     else
  740.     {
  741.         if ( (y >= 0) && (y <= _XfeHeight(w)) )
  742.         {
  743.             new_accent_type = XmACCENT_ALL;
  744.         }
  745.     }
  746.  
  747.     /* Make sure the new accent has changed */
  748.     if (new_accent_type == bmc->accent_type)
  749.     {
  750.          return;
  751.     }
  752.  
  753.     AccentErase(w);
  754.  
  755.     bmc->accent_type = new_accent_type;
  756.  
  757.     AccentDraw(w);
  758. }
  759. /*----------------------------------------------------------------------*/
  760. static void
  761. AccentDraw(Widget w)
  762. {
  763.     XfeBmCascadePart *     bmc = _XfeBmCascadePart(w);
  764.  
  765.     if (bmc->accent_type == XmACCENT_NONE)
  766.     {
  767.         return;
  768.     }
  769.  
  770.     XfeMenuItemDrawAccent(w,
  771.                           bmc->accent_type,
  772.                           XfeBmAccentGetOffsetLeft(),
  773.                           XfeBmAccentGetOffsetRight(),
  774.                           XfeBmAccentGetShadowThickness(),
  775.                           XfeBmAccentGetThickness());
  776. }
  777. /*----------------------------------------------------------------------*/
  778. static void
  779. AccentErase(Widget w)
  780. {
  781.     XfeBmCascadePart *     bmc = _XfeBmCascadePart(w);
  782.  
  783.     if (bmc->accent_type == XmACCENT_NONE)
  784.     {
  785.         return;
  786.     }
  787.  
  788.     XfeMenuItemEraseAccent(w,
  789.                            bmc->accent_type,
  790.                            XfeBmAccentGetOffsetLeft(),
  791.                            XfeBmAccentGetOffsetRight(),
  792.                            XfeBmAccentGetShadowThickness(),
  793.                            XfeBmAccentGetThickness());
  794. }
  795. /*----------------------------------------------------------------------*/
  796.  
  797. /*----------------------------------------------------------------------*/
  798. /*                                                                        */
  799. /* XfeBmCascade public functions                                        */
  800. /*                                                                        */
  801. /*----------------------------------------------------------------------*/
  802. /*extern*/ Widget
  803. XfeCreateBmCascade(Widget pw,char * name,Arg * av,Cardinal ac)
  804. {
  805.     return XtCreateWidget(name,xfeBmCascadeWidgetClass,pw,av,ac);
  806. }
  807. /*----------------------------------------------------------------------*/
  808.  
  809.