2    Copyright (C) 1996 Scott W. Sadler
 
  10       03-Mar-96 1.0; Scott W. Sadler (ssadler@cisco.com)
 
  18 #include <Xm/RowColumn.h>
 
  19 #include <Xm/SeparatoG.h>
 
  20 #include <Xm/PushBG.h>
 
  21 #include <X11/Shell.h>
 
  22 #include <X11/cursorfont.h>
 
  23 #include "XsMotifWindow.h"
 
  24 #include "XsResizeOutline.h"
 
  25 #include "XsMoveOutline.h"
 
  26 #include "xs_motif_icon.xbm"
 
  30 const int BorderSize_   = 6;
 
  31 const int ButtonSize_   = 23;
 
  32 const int IconSize_     = 70;
 
  35    ----------------------------------------------------------------------------
 
  41 _XsMotifBase::_XsMotifBase (const char *name, XsMotifWindow *win) :
 
  55 _XsMotifBase::~_XsMotifBase ( )
 
  58       XtReleaseGC (_base, _topShadowGC);
 
  61       XtReleaseGC (_base, _bottomShadowGC);
 
  66 void _XsMotifBase::show ( )
 
  70 // Install event handler
 
  72    XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
 
  74 // Call the base-class
 
  76    XsComponent::show ( );
 
  81 const char* _XsMotifBase::className ( ) const
 
  83    return ("_XsMotifBase");
 
  86 // _componentDestroyed ( )
 
  88 void _XsMotifBase::_componentDestroyed ( )
 
  94       XtReleaseGC (_base, _topShadowGC);
 
  97       XtReleaseGC (_base, _bottomShadowGC);
 
 102 // Call the base-class
 
 104    XsComponent::_componentDestroyed ( );
 
 109 void _XsMotifBase::_drawShadows (Position x, Position y, Dimension width,
 
 110    Dimension height, Dimension thick, Boolean reverse)
 
 116    XSegment segs[nsegs];
 
 120 // Work out the graphics contexts
 
 122    topShadowGC = (reverse == False) ? _topShadowGC : _bottomShadowGC;
 
 123    bottomShadowGC = (reverse == False) ? _bottomShadowGC : _topShadowGC;
 
 125    for (int loop = 0; loop < thick; loop++)
 
 134       segs[0].x1 = x + loop;
 
 135       segs[0].y1 = y + loop;
 
 136       segs[0].x2 = x + width - loop - 2; 
 
 137       segs[0].y2 = y + loop;
 
 139 // Down the left side
 
 141       segs[1].x1 = x + loop;
 
 142       segs[1].y1 = y + loop + 1;
 
 143       segs[1].x2 = x + loop;
 
 144       segs[1].y2 = y + height - loop - 2;
 
 146       XDrawSegments (XtDisplay (_base), XtWindow (_base), topShadowGC, segs, nsegs);
 
 149    BOTTOM SHADOW DRAWING
 
 154       segs[0].x1 = x + loop;
 
 155       segs[0].y1 = y + height - loop - 1;
 
 156       segs[0].x2 = x + width - loop - 1;
 
 157       segs[0].y2 = y + height - loop - 1;
 
 159 // Down the right side
 
 161       segs[1].x1 = x + width - loop - 1;
 
 162       segs[1].y1 = y + loop;
 
 163       segs[1].x2 = x + width - loop - 1;
 
 164       segs[1].y2 = y + height - loop - 1;
 
 166       XDrawSegments (XtDisplay (_base), XtWindow (_base), bottomShadowGC, segs, nsegs);
 
 172 void _XsMotifBase::_drawLine (Position x1, Position y1, Position x2, Position y2, GC &gc)
 
 175    XDrawLine (XtDisplay (_base), XtWindow (_base), gc, x1, y1, x2, y2);
 
 180 void _XsMotifBase::_map ( )
 
 183 // Create the graphics contexts
 
 185    unsigned long valuemask;
 
 190    XtVaGetValues (_win->base ( ), XmNtopShadowColor, &topShadow, XmNbottomShadowColor, 
 
 191       &bottomShadow, NULL);
 
 193 // Create the graphics contexts
 
 195    valuemask = GCForeground | GCLineWidth | GCGraphicsExposures;
 
 196    values.line_width = 0;
 
 197    values.graphics_exposures = False;
 
 199    values.foreground = topShadow;
 
 200    _topShadowGC = XtGetGC (_base, valuemask, &values);
 
 202    values.foreground = bottomShadow;
 
 203    _bottomShadowGC = XtGetGC (_base, valuemask, &values);
 
 208 void _XsMotifBase::_mapEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
 
 210    if (event->type == MapNotify)
 
 212       _XsMotifBase *obj = (_XsMotifBase*)clientData;
 
 215 // Remove the event handler
 
 217       XtRemoveEventHandler (obj->_base, StructureNotifyMask, False, obj->_mapEventHandler, clientData);
 
 222    ----------------------------------------------------------------------------
 
 226 Cursor _XsMotifComponent::_cursors[_XsMotifComponent::NumCursors];
 
 228 int _XsMotifComponent::_mutex = 0;
 
 230 XtResource _XsMotifComponent::_resourceList[] = {
 
 236       XtOffset (_XsMotifComponent*, _borderSize),
 
 238       (XtPointer)BorderSize_
 
 245       XtOffset (_XsMotifComponent*, _buttonSize),
 
 247       (XtPointer)ButtonSize_
 
 253 _XsMotifComponent::_XsMotifComponent (const char *name, XsMotifWindow *win,
 
 254    Widget parent) : _XsMotifBase (name, win)
 
 257 // Create cursors (if necessary)
 
 262       Display *dpy = XtDisplay (win->base ( ));
 
 264       _cursors[TopCursor] = XCreateFontCursor (dpy, XC_top_side);
 
 265       _cursors[BottomCursor] = XCreateFontCursor (dpy, XC_bottom_side);
 
 266       _cursors[LeftCursor] = XCreateFontCursor (dpy, XC_left_side);
 
 267       _cursors[RightCursor] = XCreateFontCursor (dpy, XC_right_side);
 
 268       _cursors[TopLeftCursor] = XCreateFontCursor (dpy, XC_top_left_corner);
 
 269       _cursors[TopRightCursor] = XCreateFontCursor (dpy, XC_top_right_corner);
 
 270       _cursors[BottomLeftCursor] = XCreateFontCursor (dpy, XC_bottom_left_corner);
 
 271       _cursors[BottomRightCursor] = XCreateFontCursor (dpy, XC_bottom_right_corner);
 
 276 // Create the component
 
 278    _base = XtVaCreateWidget (name, widgetClass, (parent != 0) ? parent : _win->base ( ), NULL);
 
 280 // Install destroy handler
 
 282    _installDestroyHandler ( );
 
 286    _getResources (_resourceList, XtNumber (_resourceList));
 
 288 // Compute the corner size
 
 290    _cornerSize = _buttonSize + _borderSize;
 
 292 // Install event handlers
 
 294    XtAddEventHandler (_base, ExposureMask, False, _exposeEventHandler, (XtPointer)this);
 
 295    XtAddEventHandler (_base, ButtonPressMask | ButtonReleaseMask | Button1MotionMask | Button2MotionMask, False, _inputEventHandler, (XtPointer)this);
 
 300 _XsMotifComponent::~_XsMotifComponent ( )
 
 307 const char* _XsMotifComponent::className ( ) const
 
 309    return ("_XsMotifComponent");
 
 314 void _XsMotifComponent::_input (XEvent*)
 
 319 // _exposeEventHandler
 
 321 void _XsMotifComponent::_exposeEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
 
 323    _XsMotifComponent *obj = (_XsMotifComponent*)clientData;
 
 325    if (event->xexpose.count == 0)
 
 326       obj->_expose (event);
 
 329 // _inputEventHandler
 
 331 void _XsMotifComponent::_inputEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
 
 333    _XsMotifComponent *obj = (_XsMotifComponent*)clientData;
 
 338    ----------------------------------------------------------------------------
 
 344 _XsMotifCorner::_XsMotifCorner (const char *name, XsMotifWindow *win, Corner corner)
 
 345    : _XsMotifComponent (name, win)
 
 352 // Configure component
 
 354    XtVaSetValues (_base, XmNwidth, _cornerSize, XmNheight, _cornerSize,
 
 355       XmNborderWidth, (Dimension)0, NULL);
 
 360 _XsMotifCorner::~_XsMotifCorner ( )
 
 367 const char *_XsMotifCorner::className ( ) const
 
 369    return ("_XsMotifCorner");
 
 374 void _XsMotifCorner::_expose (XEvent*)
 
 378    if (_topShadowGC == 0) // JACS
 
 381 // Get the size of the corner
 
 383    XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
 
 387    _drawShadows (0, 0, w, h, 1);
 
 389 // Draw the extra lines and relief
 
 395          _drawLine (1, 1, w - 2, 1, _topShadowGC);
 
 396          _drawLine (1, 1, 1, h - 2, _topShadowGC);
 
 400          _drawLine (_borderSize - 1, _borderSize - 1, _borderSize +
 
 401             _buttonSize - 2, _borderSize - 1, _bottomShadowGC);
 
 403          _drawLine (_borderSize - 1, _borderSize - 1, _borderSize - 1,
 
 404             _borderSize + _buttonSize - 2, _bottomShadowGC);
 
 410          _drawLine (1, 1, w - 2, 1, _topShadowGC);
 
 411          _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
 
 415          _drawLine (0, _borderSize - 1, _buttonSize - 1, _borderSize - 1,
 
 418          _drawLine (w - _borderSize, _borderSize - 1, w - _borderSize,
 
 419             _borderSize + _buttonSize - 2, _topShadowGC);            
 
 425          _drawLine (1, 1, 1, h - 2, _topShadowGC);
 
 426          _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
 
 430          _drawLine (_borderSize - 1, h - _borderSize, _borderSize +
 
 431             _buttonSize - 2, h - _borderSize, _topShadowGC);
 
 433          _drawLine (_borderSize - 1, 1, _borderSize - 1,
 
 434             _buttonSize - 1, _bottomShadowGC);
 
 440          _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
 
 441          _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
 
 445          _drawLine (1, h - _borderSize, _buttonSize, h - _borderSize,
 
 448          _drawLine (w - _borderSize, 1, w - _borderSize,
 
 449             _buttonSize - 1, _topShadowGC);
 
 460 void _XsMotifCorner::_input (XEvent *event)
 
 466          if (event->xbutton.button == 2)
 
 468             XsMoveOutline move (_win->base ( ));
 
 472             if (move.go ( ) != False)
 
 475 // Relocate the window      
 
 477                _win->setPosition (move.x ( ), move.y ( ));
 
 480          else if (event->xbutton.button == 3)
 
 487          switch (event->xbutton.button)
 
 492                _win->raise ( );     // Raise the window
 
 501 // Figure kind of resize we are doing
 
 505          if (_corner == TopLeft)
 
 506             dir = XsResizeOutline::Up | XsResizeOutline::Left;
 
 507          else if (_corner == TopRight)
 
 508             dir = XsResizeOutline::Up | XsResizeOutline::Right;
 
 509          else if (_corner == BottomLeft)
 
 510             dir = XsResizeOutline::Down | XsResizeOutline::Left;
 
 511          else if (_corner == BottomRight)
 
 512             dir = XsResizeOutline::Down | XsResizeOutline::Right;
 
 516          XsResizeOutline resize (_win->base ( ), dir);
 
 517          resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
 
 521          if (resize.go ( ) != False)
 
 524 // Relocate the window      
 
 526             _win->setPosition (resize.x ( ), resize.y ( ));
 
 527             _win->setSize (resize.width ( ), resize.height ( ));
 
 536 void _XsMotifCorner::_map ( )
 
 539 // Call the base-class
 
 541    _XsMotifComponent::_map ( );
 
 543 // Install the cursor
 
 545    if (_corner == TopLeft)
 
 546       XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[TopLeftCursor]);
 
 547    else if (_corner == TopRight)
 
 548       XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[TopRightCursor]);
 
 549    else if (_corner == BottomLeft)
 
 550       XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[BottomLeftCursor]);
 
 551    else if (_corner == BottomRight)
 
 552       XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[BottomRightCursor]);
 
 558    ----------------------------------------------------------------------------
 
 564 _XsMotifSide::_XsMotifSide (const char *name, XsMotifWindow *win, Side side) :
 
 565    _XsMotifComponent (name, win)
 
 571    _lastW = _lastH = -1;
 
 573 // Configure component
 
 580          XtVaSetValues (_base, XmNheight, _borderSize, XmNborderWidth,
 
 587          XtVaSetValues (_base, XmNwidth, _borderSize, XmNborderWidth,
 
 595 // Install event handler
 
 597    XtAddEventHandler (_base, StructureNotifyMask, False, _configureEventHandler, (XtPointer)this);
 
 602 _XsMotifSide::~_XsMotifSide ( )
 
 609 const char *_XsMotifSide::className ( ) const
 
 611    return ("_XsMotifSide");
 
 616 void _XsMotifSide::_expose (XEvent *event)
 
 618    if (_topShadowGC == 0) // JACS
 
 621 // Clear out the window first
 
 624       XClearWindow (XtDisplay (_base), XtWindow (_base));
 
 628 // Get the size of the side
 
 630    XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
 
 634    _drawShadows (0, 0, w, h, 1);
 
 636 // Draw the extra lines
 
 642          _drawLine (1, 1, w - 2, 1, _topShadowGC);
 
 647          _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
 
 652          _drawLine (1, 1, 1, h - 2, _topShadowGC);
 
 657          _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
 
 667 void _XsMotifSide::_input (XEvent *event)
 
 673          if (event->xbutton.button == 2)
 
 675             XsMoveOutline move (_win->base ( ));
 
 679             if (move.go ( ) != False)
 
 682 // Relocate the window      
 
 684                _win->setPosition (move.x ( ), move.y ( ));
 
 687          else if (event->xbutton.button == 3)
 
 694          switch (event->xbutton.button)
 
 699                _win->raise ( );     // Raise the window
 
 708 // Figure kind of resize we are doing
 
 713             dir = XsResizeOutline::Up;
 
 714          else if (_side == Bottom)
 
 715             dir = XsResizeOutline::Down;
 
 716          else if (_side == Left)
 
 717             dir = XsResizeOutline::Left;
 
 718          else if (_side == Right)
 
 719             dir = XsResizeOutline::Right;
 
 723          XsResizeOutline resize (_win->base ( ), dir);
 
 724          resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
 
 728          if (resize.go ( ) != False)
 
 731 // Relocate the window      
 
 733             _win->setPosition (resize.x ( ), resize.y ( ));
 
 734             _win->setSize (resize.width ( ), resize.height ( ));
 
 743 void _XsMotifSide::_map ( )
 
 746 // Call the base-class
 
 748    _XsMotifComponent::_map ( );
 
 750 // Install the cursor
 
 753       XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[TopCursor]);
 
 754    else if (_side == Bottom)
 
 755       XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[BottomCursor]);
 
 756    else if (_side == Left)
 
 757       XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[LeftCursor]);
 
 758    else if (_side == Right)
 
 759       XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[RightCursor]);
 
 766 void _XsMotifSide::_configure (XEvent *event)
 
 768    XConfigureEvent *ce = (XConfigureEvent*)event;
 
 771    Check if window has been resized.  If so, generate an expose event
 
 772    to redraw its contents.
 
 775    if ((_lastW != ce->width) || (_lastH != ce->height))
 
 777       if ((_base != 0) && XtIsManaged (_base))
 
 778          XClearArea (XtDisplay (_base), XtWindow (_base), 0, 0, 0, 0, True);
 
 785 // _configureEventHandler
 
 787 void _XsMotifSide::_configureEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
 
 789    if (event->type == ConfigureNotify)
 
 791       _XsMotifSide *obj = (_XsMotifSide*)clientData;
 
 792       obj->_configure (event);
 
 797    ----------------------------------------------------------------------------
 
 803 _XsMotifButton::_XsMotifButton (const char *name, XsMotifWindow *win, Button button) :
 
 804    _XsMotifComponent (name, win)
 
 812 // Configure the component
 
 814    XtVaSetValues (_base, XmNheight, _buttonSize, XmNwidth, _buttonSize,
 
 815       XmNborderWidth, (Dimension)0, NULL);
 
 820 _XsMotifButton::~_XsMotifButton ( )
 
 827 void _XsMotifButton::redraw ( )
 
 830 // Make sure component is viewable
 
 832    if (!XtIsRealized (_base))
 
 835 // Check if window is viewable
 
 837    XWindowAttributes attrs;
 
 838    XGetWindowAttributes (XtDisplay (_base), XtWindow (_base), &attrs);
 
 840    if (attrs.map_state == IsViewable)
 
 841       _expose (0);      // Just pretend we got an expose event
 
 846 const char *_XsMotifButton::className ( ) const
 
 848    return ("_XsMotifButton");
 
 853 void _XsMotifButton::_expose (XEvent *event)
 
 855    if (_topShadowGC == 0) // JACS
 
 860 // Get the size of the button
 
 862    XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
 
 866    _drawShadows (0, 0, w, h, 1, _pressed);
 
 868 // Draw the extra line
 
 870    _drawLine (1, h - 2, w - 2, h - 2, (_pressed) ? _topShadowGC : _bottomShadowGC);
 
 872 // Check if we need to draw the decal
 
 874    if ((_button != Maximize) && (event == 0))
 
 877 // Compute the decal size
 
 880    Boolean  reverse = False;
 
 886          dw = _buttonSize - 6;
 
 897          dw = _buttonSize - 6;
 
 900          if (_win->maximized ( ))
 
 911    _drawShadows ((w / 2) - (dw / 2), (h / 2) - (dh / 2), dw, dh, 1, reverse);
 
 916 void _XsMotifButton::_input (XEvent *event)
 
 918    static Time lastTime = (Time)0;
 
 924          if (event->xbutton.button == 1)
 
 931 // Get double-click time
 
 933                int multiClick = XtGetMultiClickTime (XtDisplay (_base));
 
 935 // Check for double-click
 
 937                if ((event->xbutton.time - lastTime) <= multiClick)
 
 943                   lastTime = event->xbutton.time;                  
 
 945 // Redraw the button (pushed-in)
 
 951                _win->popupMenu (False);
 
 953 // The menu will consume the ButtonRelease, so fake one
 
 959             else if ((_button == Minimize) || (_button == Maximize))
 
 964          else if (event->xbutton.button == 2)            
 
 966             XsMoveOutline move (_win->base ( ));
 
 970             if (move.go ( ) != False)
 
 973 // Relocate the window      
 
 975                _win->setPosition (move.x ( ), move.y ( ));
 
 978          else if (event->xbutton.button == 3)
 
 985          if (event->xbutton.button == 1)
 
 989 // Check if pointer is really in the window
 
 991             XButtonEvent *b = &event->xbutton;
 
 992             Dimension width, height;
 
 993             Boolean  inWindow = False;
 
 995             XtVaGetValues (_base, XmNwidth, &width, XmNheight, &height, NULL);
 
 996             if ((b->x >= 0) && (b->y >= 0) && (b->x < width) && (b->y < height))
 
 999             if (_button == Minimize)
 
1003                   if (_win->minimized ( ))
 
1011             else if (_button == Maximize)
 
1015                   if (_win->maximized ( ))
 
1031 void _XsMotifButton::_map ( )
 
1034 // Call the base-class
 
1036    _XsMotifComponent::_map ( );
 
1040    XRaiseWindow (XtDisplay (_base), XtWindow (_base));
 
1044    ----------------------------------------------------------------------------
 
1048 XtResource _XsMotifTitle::_resourceList[] = {
 
1054       XtOffset (_XsMotifTitle*, _titleString),
 
1062       sizeof (XFontStruct*),
 
1063       XtOffset (_XsMotifTitle*, _titleFont),
 
1065       "-*-helvetica-bold-o-normal-*-14-*-*-*-*-*-iso8859-1"
 
1071 _XsMotifTitle::_XsMotifTitle (const char *name, XsMotifWindow *win) :
 
1072    _XsMotifComponent (name, win)
 
1081    _lastW = _lastH = -1;
 
1085    _getResources (_resourceList, XtNumber (_resourceList));
 
1087 // Copy title string to local memory
 
1089    if (_titleString != 0)
 
1091       char *tmp = new char[strlen (_titleString) + 1];
 
1092       strcpy (tmp, _titleString);
 
1096 // Configure the title
 
1098    XtVaSetValues (_base,  XmNheight, _buttonSize, XmNborderWidth,
 
1099       (Dimension)0, NULL);
 
1101 // Install event handler
 
1103    XtAddEventHandler (_base, StructureNotifyMask, False, _configureEventHandler, (XtPointer)this);
 
1108 _XsMotifTitle::~_XsMotifTitle ( )
 
1111       XtReleaseGC (_base, _fontGC);
 
1113    delete [] _titleString;
 
1118 void _XsMotifTitle::setTitle (const char *title)
 
1120    assert (title != 0);
 
1122    delete [] _titleString;
 
1124    _titleString = new char[strlen (title) + 1];
 
1125    strcpy (_titleString, title);
 
1130 const char *_XsMotifTitle::className ( ) const
 
1132    return ("_XsMotifTitle");
 
1135 // _componentDestroyed
 
1137 void _XsMotifTitle::_componentDestroyed ( )
 
1143       XtReleaseGC (_base, _fontGC);
 
1149    _XsMotifComponent::_componentDestroyed ( );
 
1154 void _XsMotifTitle::_redraw ( )
 
1156    _expose (0);      // Just pretend we got an expose event
 
1161 void _XsMotifTitle::_expose (XEvent *event)
 
1163    if (_topShadowGC == 0) // JACS
 
1166 // Clear out the window first
 
1169       XClearWindow (XtDisplay (_base), XtWindow (_base));
 
1173 // Get the size of the button
 
1175    XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
 
1179    _drawShadows (0, 0, w, h, 1, _pressed);
 
1181 // Draw the extra line
 
1183    _drawLine (1, h - 2, w - 2, h - 2, (_pressed) ? _topShadowGC : _bottomShadowGC);
 
1185 // If this is an artificial event, no need continuing
 
1190 // Draw the text string
 
1192    const int LeftOffset = 5;
 
1193    const int TopOffset = 2;
 
1195 // Figure out the title
 
1197    const char *title = (_titleString != 0) ? _titleString : _win->name ( );
 
1199    if ((title != 0) && (title[0] != '\0'))
 
1201       int len = strlen (title);
 
1203       XDrawString (XtDisplay (_base), XtWindow (_base), _fontGC,
 
1204          LeftOffset, TopOffset + _titleFont->ascent, title, len);
 
1210 void _XsMotifTitle::_input (XEvent *event)
 
1212    switch (event->type)
 
1216          switch (event->xbutton.button)
 
1226                XsMoveOutline move (_win->base ( ));
 
1230                if (move.go ( ) != False)
 
1233 // Relocate the window      
 
1235                   _win->setPosition (move.x ( ), move.y ( ));
 
1241                _win->popupMenu ( );
 
1249          switch (event->xbutton.button)
 
1265          XsMoveOutline move (_win->base ( ));
 
1269          if (move.go ( ) != False)
 
1272 // Relocate the window      
 
1274             _win->setPosition (move.x ( ), move.y ( ));
 
1276 // Redraw the title bar
 
1288 void _XsMotifTitle::_map ( )
 
1291 // Call the base-class
 
1293    _XsMotifComponent::_map ( );
 
1297    XRaiseWindow (XtDisplay (_base), XtWindow (_base));
 
1299    unsigned long valuemask;
 
1306    XtVaGetValues (_win->base ( ), XmNforeground, &foreground, XmNbackground, &background, NULL);
 
1308 // Create the font graphics context
 
1310    valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
 
1312    values.foreground = foreground;
 
1313    values.background = background;
 
1314    values.font = _titleFont->fid;
 
1315    values.graphics_exposures = False;
 
1317    _fontGC = XtGetGC (_base, valuemask, &values);
 
1322 void _XsMotifTitle::_configure (XEvent *event)
 
1324    XConfigureEvent *ce = (XConfigureEvent*)event;
 
1327    Check if window has been resized.  If so, generate an expose event
 
1328    to redraw its contents.
 
1331    if ((_lastW != ce->width) || (_lastH != ce->height))
 
1333       if ((_base != 0) && XtIsManaged (_base))
 
1334          XClearArea (XtDisplay (_base), XtWindow (_base), 0, 0, 0, 0, True);
 
1337       _lastH = ce->height;
 
1341 // _configureEventHandler
 
1343 void _XsMotifTitle::_configureEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
 
1345    if (event->type == ConfigureNotify)
 
1347       _XsMotifTitle *obj = (_XsMotifTitle*)clientData;
 
1348       obj->_configure (event);
 
1353    ----------------------------------------------------------------------------
 
1357 XtResource _XsMotifIcon::_resourceList[] = {
 
1363       XtOffset (_XsMotifIcon*, _iconSize),
 
1365       (XtPointer)IconSize_
 
1372       XtOffset (_XsMotifIcon*, _iconName),
 
1380       sizeof (XFontStruct*),
 
1381       XtOffset (_XsMotifIcon*, _iconFont),
 
1383       "-*-helvetica-bold-r-normal-*-12-*-*-*-*-*-iso8859-1"
 
1390       XtOffset (_XsMotifIcon*, _iconX),
 
1399       XtOffset (_XsMotifIcon*, _iconY),
 
1407 _XsMotifIcon::_XsMotifIcon (const char *name, XsMotifWindow *win, Widget parent) :
 
1408    _XsMotifComponent (name, win, parent)
 
1418    _freePixmap = False;
 
1420    _width = _height = 0;
 
1425    _getResources (_resourceList, XtNumber (_resourceList));
 
1427 // Copy icon name to local memory
 
1431       char *tmp = new char[strlen (_iconName) + 1];
 
1432       strcpy (tmp, _iconName);
 
1436 // Configure the icon
 
1438    XtVaSetValues (_base, XmNwidth, _iconSize, XmNheight, _iconSize, NULL);
 
1443 _XsMotifIcon::~_XsMotifIcon ( )
 
1446       XtReleaseGC (_base, _fontGC);
 
1449       XtReleaseGC (_base, _pixmapGC);
 
1452       XFreePixmap (XtDisplay (_base), _pixmap);
 
1454    delete [] _iconName;
 
1459 void _XsMotifIcon::show ( )
 
1463    Configure the icon position.  Either use the position specified
 
1464    in the resource, or place the icon at the top-left corner of the
 
1468    if (_placed == False)
 
1474          XtVaGetValues (_win->base ( ), XmNx, &x, NULL);
 
1483          XtVaGetValues (_win->base ( ), XmNy, &y, NULL);
 
1490       XtVaSetValues (_base, XmNx, x, XmNy, y, NULL);
 
1495 // Call the base class
 
1497    _XsMotifComponent::show ( );
 
1502 void _XsMotifIcon::setIconName (const char *iconName)
 
1504    assert (iconName != 0);
 
1506    delete [] _iconName;
 
1508    _iconName = new char[strlen (iconName) + 1];
 
1509    strcpy (_iconName, iconName);
 
1514 void _XsMotifIcon::setPixmap (Pixmap pixmap)
 
1516    assert (pixmap != 0);
 
1518 // Free the existing pixmap (if necessary)
 
1522       XFreePixmap (XtDisplay (_base), _pixmap);
 
1523       _freePixmap = False;
 
1526 // Save the new pixmap
 
1530 // Get the pixmap width and height
 
1534    unsigned int   uw, uh, ub, ud;
 
1536    XGetGeometry (XtDisplay (_base), _pixmap, &dummy, &xd, &yd, &uw, &uh, &ub, &ud);
 
1544 const char *_XsMotifIcon::className ( ) const
 
1546    return ("_XsMotifIcon");
 
1549 // _componentDestroyed
 
1551 void _XsMotifIcon::_componentDestroyed ( )
 
1557       XtReleaseGC (_base, _fontGC);
 
1560       XtReleaseGC (_base, _pixmapGC);
 
1563       XFreePixmap (XtDisplay (_base), _pixmap);
 
1569 // Call the base-class
 
1571    _XsMotifComponent::_componentDestroyed ( );
 
1576 void _XsMotifIcon::_input (XEvent *event)
 
1578    static Time lastTime = (Time)0;
 
1580    switch (event->type)
 
1584          switch (event->xbutton.button)
 
1591                XsMoveOutline move (_base);
 
1595                if (move.go ( ) != False)
 
1598 // Relocate the window      
 
1600                   _win->setPosition (move.x ( ), move.y ( ));
 
1606                _win->popupMenu ( );
 
1614          switch (event->xbutton.button)
 
1619 // Get double-click time
 
1621                int multiClick = XtGetMultiClickTime (XtDisplay (_base));
 
1623 // Check for double-click
 
1625                if ((event->xbutton.time - lastTime) <= multiClick)
 
1629                   lastTime = event->xbutton.time;
 
1639          XsMoveOutline  move (_base);
 
1643          if (move.go ( ) != False)
 
1646 // Relocate the icon
 
1648             _win->setPosition (move.x ( ), move.y ( ));
 
1657 void _XsMotifIcon::_expose (XEvent *)
 
1659    if (_topShadowGC == 0) // JACS
 
1662    Dimension   iconHeight;
 
1663    Dimension   iconWidth;
 
1665 // Compute icon size
 
1667    XtVaGetValues (_base, XmNwidth, &iconWidth, XmNheight, &iconHeight, NULL);
 
1671    _drawShadows (0, 0, iconWidth, iconHeight, 2);
 
1673 // Figure out the icon string
 
1675    const char *iconName = (_iconName != 0) ? _iconName : (_win->title ( ) != 0) ?
 
1676       _win->title ( ) : _win->name ( );
 
1678    const int fontX = 3;
 
1679    const int fontY = 3;
 
1681    if ((iconName != 0) && (iconName[0] != '\0'))
 
1684       int   len = strlen (iconName);
 
1686 // Compute the text size
 
1688       textWidth = XTextWidth (_iconFont, iconName, len);
 
1690 // Center the text in the bottom of the icon (or left-justify it)
 
1694       if (textWidth <= (iconWidth - (fontX * 2)))
 
1695          x = (iconWidth - (int)textWidth) / 2;
 
1699       y = (int)iconHeight - _iconFont->descent - fontY;
 
1703       XDrawString (XtDisplay (_base), XtWindow (_base), _fontGC,
 
1704          x, y, iconName, len);
 
1707 // Compute label size
 
1709    int labelHeight = _iconFont->descent + _iconFont->ascent + (fontY * 2);
 
1711    if (labelHeight >= (iconHeight - 6))
 
1714 // Draw the separator
 
1716    int sepY = (iconHeight) - labelHeight;
 
1718    _drawLine (1, sepY, iconWidth - 2, sepY, _bottomShadowGC);
 
1719    _drawLine (1, sepY + 1, iconWidth - 2, sepY + 1, _topShadowGC);
 
1721 // Draw the pixmap frame
 
1723    const int frameX = 4;
 
1724    const int frameY = 4;
 
1726    if ((frameX + 6) >= sepY)
 
1729    int   frameWidth = iconWidth - (frameX * 2);
 
1730    int   frameHeight = sepY - frameY - 2;
 
1732    _drawShadows (frameX, frameY, frameWidth, frameHeight, 1, True);
 
1737    _drawShadows (frameX + 1, frameY + 1, frameWidth, frameHeight, 1);
 
1746       if ((frameWidth > 0) && (frameHeight > 0))
 
1751 // Center the pixmap or top-left orient it
 
1753          if (frameWidth > _width)
 
1755             origX = (frameWidth - _width) / 2;
 
1756             origX += frameX + 2;
 
1765          if (frameHeight > _height)
 
1767             origY = (frameHeight - _height) / 2;
 
1768             origY += frameY + 2;
 
1774             drawH = frameHeight;
 
1777          XCopyArea (XtDisplay (_base), _pixmap, XtWindow (_base), _pixmapGC,
 
1778             0, 0, drawW, drawH, origX, origY);
 
1785 void _XsMotifIcon::_map ( )
 
1787    unsigned long valuemask;
 
1793 // Call the base-class
 
1795    _XsMotifComponent::_map ( );
 
1797 // Get the icon pixels
 
1799    XtVaGetValues (_win->base ( ), XmNdepth, &depth, XmNbackground, &bg,
 
1800       XmNforeground, &fg, NULL);
 
1802 // Create the default icon pixmap
 
1806       _pixmap = XCreatePixmapFromBitmapData (XtDisplay (_base), XtWindow (_base),
 
1807          xs_motif_icon_bits, xs_motif_icon_width, xs_motif_icon_height,
 
1812       setPixmap (_pixmap);
 
1816 // Create the icon pixmap graphics context
 
1818       valuemask = GCGraphicsExposures | GCForeground | GCBackground;
 
1820       values.graphics_exposures = False;
 
1821       values.foreground = fg;
 
1822       values.background = bg;
 
1824       _pixmapGC = XtGetGC (_base, valuemask, &values);
 
1827 // Create the font graphics context
 
1829    valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
 
1831    values.foreground = fg;
 
1832    values.background = bg;
 
1833    values.font = _iconFont->fid;
 
1834    values.graphics_exposures = False;
 
1836    _fontGC = XtGetGC (_base, valuemask, &values);
 
1840    ----------------------------------------------------------------------------
 
1844 // Static definitions
 
1846 int _XsMotifMenu::_count = 0;
 
1847 Cursor _XsMotifMenu::_cursor = None;
 
1848 Pixmap _XsMotifMenu::_stipple = None;
 
1849 Display *_XsMotifMenu::_dpy = 0;
 
1853 XtResource _XsMotifMenu::_resourceList[] = {
 
1859       XtOffset (_XsMotifMenu*, _saveUnder),
 
1868       XtOffset (_XsMotifMenu*, _strings[Restore]),
 
1877       XtOffset (_XsMotifMenu*, _strings[Move]),
 
1886       XtOffset (_XsMotifMenu*, _strings[Size]),
 
1895       XtOffset (_XsMotifMenu*, _strings[Minimize]),
 
1904       XtOffset (_XsMotifMenu*, _strings[Maximize]),
 
1913       XtOffset (_XsMotifMenu*, _strings[Raise]),
 
1922       XtOffset (_XsMotifMenu*, _strings[Lower]),
 
1931       XtOffset (_XsMotifMenu*, _strings[Close]),
 
1939       sizeof (XFontStruct*),
 
1940       XtOffset (_XsMotifMenu*, _menuFont),
 
1942       "-*-helvetica-bold-o-normal-*-14-*-*-*-*-*-iso8859-1"
 
1948 _XsMotifMenu::_XsMotifMenu (const char *name, XsMotifWindow *win) :
 
1949    _XsMotifBase (name, win)
 
1952 // Create the cursor (if necessary)
 
1957 // Create the menu cursor
 
1959       _cursor = XCreateFontCursor (XtDisplay (win->base ( )), XC_arrow);
 
1961 // Create a stippled pixmap
 
1963       Widget   parent = _win->base ( );
 
1968       XtVaGetValues (parent, XmNforeground, &foreground, XmNbackground,
 
1969          &background, XmNdepth, &depth, NULL);
 
1971       const int pixmapWidth = 2;
 
1972       const int pixmapHeight = 2;
 
1973       static unsigned char pixmapBits[] = { 0x02, 0x01 };
 
1975       _dpy = XtDisplay (parent);
 
1976       _stipple = XCreatePixmapFromBitmapData (_dpy, DefaultRootWindow (_dpy),
 
1977          (char*)pixmapBits, pixmapWidth, pixmapHeight, foreground, background,
 
1987 // Create the component (why doesn't overrideShell work?)
 
1989    _base = XtVaCreatePopupShell (_name, topLevelShellWidgetClass,
 
1990       XtParent (_win->base ( )), XmNoverrideRedirect, True,
 
1991       XmNborderWidth, 1, NULL);
 
1993 // Install destroy handler
 
1995    _installDestroyHandler ( );
 
1997 // Install event handler ('cause we never call _XsMotifBase::show)
 
1999    XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
 
2003    _getResources (_resourceList, XtNumber (_resourceList));
 
2005 // Get the background color
 
2009    XtVaGetValues (_win->base ( ), XmNbackground, &bg, NULL);
 
2011 // Compute the size of the (largest) menu item
 
2013    int   textHeight = _menuFont->ascent + _menuFont->descent;
 
2017    for (int loop = 0; loop < Num; loop++)
 
2019       tmp = XTextWidth (_menuFont, _strings[loop], strlen (_strings[loop]));
 
2021       if (tmp > textWidth)
 
2025 // Put a border around the buttons
 
2027    textWidth += (2 * HorizTextOffset);
 
2028    textHeight += (2 * VertTextOffset);
 
2031    The menu height is the menu-shadow (1 pixel on top and bottom) + the
 
2035    int   menuHeight = (2 * ShadowThickness) +   // Top and bottom shadow
 
2036                       (textHeight * Num);       // The menu items
 
2039    The menu width is the menu-shadow (1 pixel on the left and right) +
 
2040    the largest menu text (calculated above)
 
2043    int   menuWidth = (2 * ShadowThickness) +    // Left and right shadow   
 
2044                      textWidth;                 // Largest text item
 
2046 // Configure the popup
 
2048    XtVaSetValues (_base, XmNsaveUnder, _saveUnder, XmNwidth, menuWidth,
 
2049       XmNheight, menuHeight, NULL);
 
2054 _XsMotifMenu::~_XsMotifMenu ( )
 
2057       XtReleaseGC (_base, _fontGC);
 
2060       XtReleaseGC (_base, _grayGC);
 
2063       XtReleaseGC (_base, _backgroundGC);
 
2065 // Free the pixmap (if necessary)
 
2068       XFreePixmap (_dpy, _stipple);
 
2073 void _XsMotifMenu::popup (Boolean atPointer)
 
2075    assert (_base != 0);
 
2079 // Compute the location of the menu.
 
2088 // Menu at pointer location
 
2090       XQueryPointer (XtDisplay (_base), XtWindow (XtParent (_base)),
 
2091          &win, &win, &rootX, &rootY, &winX, &winY, &mask);
 
2093       x = (Position)rootX;
 
2094       y = (Position)rootY;
 
2099 // Menu at top-left corner of client area
 
2101       XtTranslateCoords (_win->clientArea ( ), 0, 0, &x, &y);
 
2106    XtVaSetValues (_base, XmNx, x, XmNy, y, NULL);
 
2108 // Initialize the item
 
2114    XtPopup (_base, XtGrabNone);
 
2118    if (_grabPointer ( ) == FALSE)
 
2125 // Pop the menu down
 
2129 // Ungrab the pointer
 
2133    if (_curItem != NoItem)
 
2137    Post a work-proc to process this item.  This will allow everything
 
2138    to get caught up before we process the menu item
 
2141       XtAppContext appContext = XtWidgetToApplicationContext (_base);
 
2142       XtAppAddWorkProc (appContext, _workProc, (XtPointer)this);
 
2148 const char *_XsMotifMenu::className ( ) const
 
2150    return ("_XsMotifMenu");
 
2153 // _componentDestroyed
 
2155 void _XsMotifMenu::_componentDestroyed ( )
 
2161       XtReleaseGC (_base, _fontGC);
 
2164       XtReleaseGC (_base, _grayGC);
 
2167       XtReleaseGC (_base, _backgroundGC);
 
2173 // Call the base-class
 
2175    _XsMotifBase::_componentDestroyed ( );
 
2180 void _XsMotifMenu::_processEvents ( )
 
2182    assert (_base != 0);
 
2184    XtAppContext appContext = XtWidgetToApplicationContext (_base);
 
2186    Display *dpy = XtDisplay (_base);
 
2191       XtAppNextEvent (appContext, &event);
 
2193 // Process this event
 
2211 // Process only the last motion event
 
2213             while (XPending (dpy) > 0)
 
2215                XPeekEvent (dpy, &next);
 
2216                if (next.type != MotionNotify)
 
2218                XtAppNextEvent (appContext, &event);
 
2221 // Track the mouse and toggle the menu items
 
2223             Item item = _trackPointer ((XMotionEvent*)&event);
 
2225 // Unselect the current item (if the item is different)
 
2227             if (item != _curItem)
 
2229                _toggleItem (_curItem, False);
 
2231 // Select the new item
 
2233                _toggleItem ((_curItem = item), True);
 
2240             XtDispatchEvent (&event);
 
2249 void _XsMotifMenu::_processItem (Item item)
 
2263          Widget base = (_win->minimized ( )) ? _win->icon ( ) : _win->base ( );
 
2265 // Warp the pointer to the center of the window
 
2267          Dimension width, height;
 
2268          XtVaGetValues (base, XmNwidth, &width, XmNheight, &height, NULL);
 
2270          XWarpPointer (XtDisplay (_base), None, XtWindow (base), 0, 0, 0, 0,
 
2271             (width / 2), (height / 2));
 
2275          XsMoveOutline move (base);
 
2279          if (move.go (True) != False)
 
2282 // Relocate the window      
 
2284             _win->setPosition (move.x ( ), move.y ( ));
 
2290          Widget base = (_win->minimized ( )) ? _win->icon ( ) : _win->base ( );
 
2292 // Warp the pointer to the center of the window
 
2294          Dimension width, height;
 
2295          XtVaGetValues (base, XmNwidth, &width, XmNheight, &height, NULL);
 
2297          XWarpPointer (XtDisplay (_base), None, XtWindow (base), 0, 0, 0, 0,
 
2298             (width / 2), (height / 2));
 
2300 // Resize the window
 
2302          XsResizeOutline resize (_win->base ( ), XsResizeOutline::Undetermined);
 
2303          resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
 
2307          if (resize.go (True) != False)
 
2310 // Relocate the window      
 
2312             _win->setPosition (resize.x ( ), resize.y ( ));
 
2313             _win->setSize (resize.width ( ), resize.height ( ));
 
2349 void _XsMotifMenu::_redrawMenu ( )
 
2353 // Get the size of the menu
 
2355    XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
 
2357 // Draw a shadow around the menu
 
2359    _drawShadows (0, 0, w, h, ShadowThickness);
 
2361 // Cycle and draw all of the elements
 
2363    for (int loop = 0; loop < Num; loop++)
 
2364       _redrawItem ((Item)loop);
 
2369 void _XsMotifMenu::_redrawItem (Item item)
 
2374    int   x = ShadowThickness + HorizTextOffset;
 
2378    Compute the y-position of the element.  This will be the size of the
 
2379    top-shadow + the items before it + the offset of the item itself
 
2382    y = ShadowThickness +                           // Top shadow
 
2383        (item * ((VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent))) +
 
2384        (VertTextOffset + _menuFont->ascent);       // The item iteself
 
2386 // Figure out the graphics-context
 
2390    if (_win->minimized ( ))
 
2391       gc = ((item == Size) || (item == Minimize)) ? _grayGC : _fontGC;
 
2392    else if (_win->maximized ( ))
 
2393       gc = (item == Maximize) ? _grayGC : _fontGC;
 
2395       gc = (item == Restore) ? _grayGC : _fontGC;      
 
2399    XDrawString (XtDisplay (_base), XtWindow (_base), gc, x, y,
 
2400       _strings[item], strlen (_strings[item]));
 
2405 void _XsMotifMenu::_toggleItem (Item item, Boolean active)
 
2411    Either draw the background of the specified item in the active color
 
2412    or the standard background color
 
2415    GC gc = (active) ? _topShadowGC : _backgroundGC;
 
2417 // Get the width of the menu
 
2419    Dimension menuWidth;
 
2420    XtVaGetValues (_base, XmNwidth, &menuWidth, NULL);
 
2422 // Compute the location and size of the rectangle
 
2425    unsigned int width, height;
 
2427    x = ShadowThickness;
 
2428    height = ((VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent));
 
2429    y = ShadowThickness + (item * height);
 
2430    width = menuWidth - (2 * ShadowThickness);
 
2432 // Draw the filled rectangle
 
2434    XFillRectangle (XtDisplay (_base), XtWindow (_base), gc, x, y, width, height);
 
2443 _XsMotifMenu::Item _XsMotifMenu::_trackPointer (XMotionEvent *event)
 
2445    assert (_base != 0);
 
2447    Dimension   menuWidth;
 
2448    Dimension   menuHeight;
 
2451 // Get the menu size and position
 
2453    XtVaGetValues (_base, XmNwidth, &menuWidth, XmNheight, &menuHeight,
 
2454       XmNx, &x, XmNy, &y, NULL);
 
2456 // Make sure the pointer is in the menu
 
2458    if ((event->x_root < x) || (event->x_root > (x + menuWidth)))
 
2461    if ((event->y_root < y) || (event->y_root > (y + menuHeight)))
 
2464 // Make sure the pointer is on the confines of the shadow
 
2466    if ((event->x < ShadowThickness) || (event->x > (menuWidth - (2 * ShadowThickness))))
 
2469    if ((event->y < ShadowThickness) || (event->y > (menuHeight - (2 * ShadowThickness))))
 
2473    Now we are just concerned with the y-position.  Subtract off the
 
2474    shadow thickness to normalize the location
 
2477    int   yPos = event->y - ShadowThickness;
 
2479 // Compute which item the mouse is in
 
2481    int itemHeight = (VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent);
 
2483    Item item = (Item)(yPos / itemHeight);
 
2485 // Validate that the item is not grayed-out
 
2487    if (_win->minimized ( ))
 
2489       if ((item == Size) || (item == Minimize))
 
2492    else if (_win->maximized ( ))
 
2494       if (item == Maximize)
 
2497    else if (item == Restore)
 
2505 Boolean _XsMotifMenu::_grabPointer ( )
 
2508 // Sync everything up before being grabby
 
2510    XSync (XtDisplay (_base), False);
 
2514    if (XGrabPointer (XtDisplay (_base), XtWindow (_base), False,
 
2515       (unsigned int)(ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
 
2516       EnterWindowMask | LeaveWindowMask), GrabModeAsync,
 
2517       GrabModeAsync, None, _cursor, CurrentTime) != GrabSuccess)
 
2519       XBell (XtDisplay (_base), 100);
 
2528 void _XsMotifMenu::_ungrabPointer ( )
 
2531 // Ungrab the pointer
 
2533    XUngrabPointer (XtDisplay (_base), CurrentTime);
 
2535 // Sync everything back up
 
2537    XSync (XtDisplay (_base), False);
 
2542 void _XsMotifMenu::_map ( )
 
2545 // Call the base-class
 
2547    _XsMotifBase::_map ( );
 
2549    unsigned long valuemask;
 
2556    XtVaGetValues (XtParent (_base), XmNforeground, &foreground, NULL);
 
2557    XtVaGetValues (_base, XmNbackground, &background, NULL);
 
2559 // Create the font graphics context
 
2561    valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
 
2563    values.foreground = foreground;
 
2564    values.background = background;
 
2565    values.font = _menuFont->fid;
 
2566    values.graphics_exposures = False;
 
2568    _fontGC = XtGetGC (_base, valuemask, &values);
 
2570 // Create the insensitive font graphics context
 
2572    valuemask |= (GCFillStyle | GCTile);
 
2574    values.fill_style = FillTiled;
 
2575    values.tile = _stipple;
 
2577    _grayGC = XtGetGC (_base, valuemask, &values);
 
2579 // Create the background contexts
 
2581    valuemask = GCForeground | GCLineWidth | GCGraphicsExposures;
 
2582    values.line_width = 0;
 
2583    values.graphics_exposures = False;
 
2584    values.foreground = background;
 
2586    _backgroundGC = XtGetGC (_base, valuemask, &values);
 
2591 Boolean _XsMotifMenu::_workProc (XtPointer clientData)
 
2593    _XsMotifMenu *obj = (_XsMotifMenu*)clientData;
 
2594    if (obj->_curItem != NoItem)
 
2595       obj->_processItem (obj->_curItem);
 
2601    ----------------------------------------------------------------------------
 
2605 // Static definitions
 
2607 XtResource XsMotifWindow::_resourceList[] = {
 
2613       XtOffset (XsMotifWindow*, _showBorder),
 
2622       XtOffset (XsMotifWindow*, _showResize),
 
2631       XtOffset (XsMotifWindow*, _showTitle),
 
2640       XtOffset (XsMotifWindow*, _showMenu),
 
2649       XtOffset (XsMotifWindow*, _showMinimize),
 
2658       XtOffset (XsMotifWindow*, _showMaximize),
 
2667       XtOffset (XsMotifWindow*, _lowerOnIconify),
 
2676       XtOffset (XsMotifWindow*, _minW),
 
2678       (XtPointer)((BorderSize_ + ButtonSize_) * 3)
 
2685       XtOffset (XsMotifWindow*, _maxW),
 
2694       XtOffset (XsMotifWindow*, _minH),
 
2696       (XtPointer)((BorderSize_ + ButtonSize_) * 3)
 
2703       XtOffset (XsMotifWindow*, _maxH),
 
2711 XsMotifWindow::XsMotifWindow (const char *name) : XsMDIWindow (name)
 
2717    for (loop = 0; loop < _XsMotifSide::Max; loop++)
 
2723    for (loop = 0; loop < _XsMotifButton::Max; loop++)
 
2736 XsMotifWindow::~XsMotifWindow ( )
 
2740    for (loop = 0; loop < _XsMotifSide::Max; loop++)
 
2742       delete _corners[loop];
 
2743       delete _sides[loop];
 
2746    for (loop = 0; loop < _XsMotifButton::Max; loop++)
 
2747       delete _buttons[loop];
 
2756 void XsMotifWindow::raise ( )
 
2758    Widget w = (_minimized == True) ? _icon->base ( ) : _base;
 
2760    XRaiseWindow (XtDisplay (w), XtWindow (w));
 
2765 void XsMotifWindow::lower ( )
 
2767    Widget w = (_minimized == True) ? _icon->base ( ) : _base;
 
2769    XLowerWindow (XtDisplay (w), XtWindow (w));
 
2774 void XsMotifWindow::minimize ( )
 
2776    assert (_base != 0);
 
2778 // Check if we are already minimized
 
2780    if (_minimized == True)
 
2783 // Minimize the window
 
2789 // Lower (if necessary)
 
2791    if (_lowerOnIconify)
 
2799 void XsMotifWindow::maximize ( )
 
2801    assert (_base != 0);
 
2803 // Check if we are already in this state
 
2805    if (_maximized == True)
 
2808 // Restore (if necessary)
 
2813 // Save current dimensions
 
2815    XtVaGetValues (_base, XmNx, &_savedX, XmNy, &_savedY, XmNwidth,
 
2816       &_savedWidth, XmNheight, &_savedHeight, NULL);
 
2819    Constrain the new window size.  The size of the maximized window
 
2820    is equal to the size of the current clip-window of the canvas.
 
2823    const Dimension offset = 5;      // Border around max'd window
 
2825    Widget clipWindow = XtParent (XtParent (_base));
 
2826    assert (clipWindow != 0);
 
2827    Dimension   clipW, clipH;   
 
2831    XtVaGetValues (clipWindow, XmNheight, &clipH, XmNwidth, &clipW, NULL);
 
2835    if (clipW > (offset * 2))
 
2836       clipW -= (offset * 2);
 
2838    if (clipH > (offset * 2))
 
2839       clipH -= (offset * 2);
 
2841 // Compute the new window position (map clip-window to work-area)
 
2843    XTranslateCoordinates (XtDisplay (_base), XtWindow (clipWindow),
 
2844       XtWindow (XtParent (_base)), (int)offset, (int)offset,
 
2845       &newX, &newY, &child);
 
2847 // Set new maximum dimensions
 
2849    setPosition ((Position)newX, (Position)newY);
 
2850    setSize (clipW, clipH);
 
2854 // Redraw the maximize button
 
2856    _buttons[_XsMotifButton::Maximize]->redraw ( );
 
2861 void XsMotifWindow::restore ( )
 
2863    assert (_base != 0);
 
2865 // Check if we are already restored
 
2867    if ((_maximized == False) && (_minimized == False))
 
2870 // Either un-minimize or un-maximize
 
2875 // Restore the window
 
2880 // If maximized, restore again
 
2892 // Restore saved dimensions
 
2894       setPosition (_savedX, _savedY);
 
2895       setSize (_savedWidth, _savedHeight);
 
2901 void XsMotifWindow::close ( )
 
2905    Don't delete the window (because its not ours to delete).
 
2917 void XsMotifWindow::setTitle (const char *title)
 
2920       _title->setTitle (title);
 
2925 void XsMotifWindow::setIconName (const char *iconName)
 
2928       _icon->setIconName (iconName);
 
2933 void XsMotifWindow::setPixmap (Pixmap pixmap)
 
2936       _icon->setPixmap (pixmap);
 
2941 void XsMotifWindow::popupMenu (Boolean b)
 
2949 void XsMotifWindow::setPosition (Position x, Position y)
 
2953       Widget w = (_minimized == True) ? _icon->base ( ) : _base;
 
2955       XtVaSetValues (w, XmNx, x, XmNy, y, NULL);
 
2958       XsMDIWindow::setPosition (x, y);    // Cache the points
 
2963 void XsMotifWindow::setSize (Dimension w, Dimension h)
 
2966 // Set the window size
 
2972       else if ((_maxW != (Dimension)-1) && (w > _maxW))
 
2977       else if ((_maxH != (Dimension)-1) && (h > _maxH))
 
2980       if (_minimized == False)
 
2981          XtVaSetValues (_base, XmNwidth, w, XmNheight, h, NULL);
 
2983 // If window was maximized, change the window state back to normal
 
2985       if (_maximized == True)
 
2989 // Redraw the maximize button
 
2991          _buttons[_XsMotifButton::Maximize]->redraw ( );
 
2995       XsMDIWindow::setSize (w, h);     // Cache the points
 
3000 const char* XsMotifWindow::className ( ) const
 
3002    return ("XsMotifWindow");
 
3007 void XsMotifWindow::_createWindow (Widget parent)
 
3009    assert (parent != 0);
 
3011 // Create the window frame
 
3013    _base = XtVaCreateWidget (_name, xmFormWidgetClass, parent,
 
3014       XmNborderWidth, (Dimension)1, NULL);
 
3016 // Install destroy handler
 
3018    _installDestroyHandler ( );
 
3022    _getResources (_resourceList, XtNumber (_resourceList));
 
3025    Fix configuration inter-dependencies.  Here are the rules:
 
3027    1) If there is no border, then there are no resize handles
 
3028    2) If there is no title, then there are no buttons (would look stupid)
 
3031    if (_showBorder == False)
 
3032       _showResize = False;
 
3034    if (_showTitle == False)
 
3037       _showMinimize = False;
 
3038       _showMaximize = False;
 
3050       _corners[_XsMotifCorner::TopLeft] = new _XsMotifCorner ("topLeft", this, _XsMotifCorner::TopLeft);
 
3052       XtVaSetValues (_corners[_XsMotifCorner::TopLeft]->base ( ), XmNtopAttachment,
 
3053          XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment,
 
3054          XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
 
3058       _corners[_XsMotifCorner::TopRight] = new _XsMotifCorner ("topRight", this, _XsMotifCorner::TopRight);
 
3060       XtVaSetValues (_corners[_XsMotifCorner::TopRight]->base ( ), XmNtopAttachment,
 
3061          XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment,
 
3062          XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
 
3066       _corners[_XsMotifCorner::BottomLeft] = new _XsMotifCorner ("bottomLeft", this, _XsMotifCorner::BottomLeft);
 
3068       XtVaSetValues (_corners[_XsMotifCorner::BottomLeft]->base ( ), XmNtopAttachment,
 
3069          XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
 
3070          XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
 
3074       _corners[_XsMotifCorner::BottomRight] = new _XsMotifCorner ("bottomRight", this, _XsMotifCorner::BottomRight);
 
3076       XtVaSetValues (_corners[_XsMotifCorner::BottomRight]->base ( ), XmNtopAttachment,
 
3077          XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
 
3078          XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
 
3090       _sides[_XsMotifSide::Top] = new _XsMotifSide ("top", this, _XsMotifSide::Top);
 
3092       XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ),  XmNtopAttachment,
 
3093          XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, NULL);
 
3097          XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ), XmNleftAttachment,
 
3098             XmATTACH_WIDGET, XmNleftWidget, _corners[_XsMotifCorner::TopLeft]->base ( ),
 
3099             XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
 
3100             _corners[_XsMotifCorner::TopRight]->base ( ), NULL);
 
3104          XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ), XmNleftAttachment,
 
3105             XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
 
3110       _sides[_XsMotifSide::Bottom] = new _XsMotifSide ("bottom", this, _XsMotifSide::Bottom);
 
3112       XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNtopAttachment,
 
3113          XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, NULL);
 
3117          XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNleftAttachment,
 
3118             XmATTACH_WIDGET, XmNleftWidget, _corners[_XsMotifCorner::BottomLeft]->base ( ),
 
3119             XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
 
3120             _corners[_XsMotifCorner::BottomRight]->base ( ), NULL);
 
3124          XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNleftAttachment,
 
3125             XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
 
3130       _sides[_XsMotifSide::Left] = new _XsMotifSide ("left", this, _XsMotifSide::Left);
 
3132       XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNleftAttachment,
 
3133          XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
 
3137          XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNtopAttachment,
 
3138             XmATTACH_WIDGET, XmNtopWidget, _corners[_XsMotifCorner::TopLeft]->base ( ),
 
3139             XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget,
 
3140             _corners[_XsMotifCorner::BottomLeft]->base ( ), NULL);
 
3144          XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNtopAttachment,
 
3145             XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL);
 
3150       _sides[_XsMotifSide::Right] = new _XsMotifSide ("right", this, _XsMotifSide::Right);
 
3152       XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNleftAttachment,
 
3153          XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
 
3157          XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNtopAttachment,
 
3158             XmATTACH_WIDGET, XmNtopWidget, _corners[_XsMotifCorner::TopRight]->base ( ),
 
3159             XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget,
 
3160             _corners[_XsMotifCorner::BottomRight]->base ( ), NULL);
 
3164          XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNtopAttachment,
 
3165             XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL);
 
3173       _buttons[_XsMotifButton::Menu] = new _XsMotifButton ("menu", this, _XsMotifButton::Menu);
 
3175       XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNbottomAttachment,
 
3176          XmATTACH_NONE, XmNrightAttachment, XmATTACH_NONE, NULL);
 
3180          XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNleftAttachment,
 
3181             XmATTACH_WIDGET, XmNleftWidget, _sides[_XsMotifSide::Left]->base ( ),
 
3182             XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
 
3187          XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNleftAttachment,
 
3188             XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, NULL);
 
3196       _buttons[_XsMotifButton::Maximize] = new _XsMotifButton ("maximize", this, _XsMotifButton::Maximize);
 
3198       XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNbottomAttachment,
 
3199          XmATTACH_NONE, XmNleftAttachment, XmATTACH_NONE, NULL);
 
3203          XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNtopAttachment,
 
3204             XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
 
3205             XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, _sides[_XsMotifSide::Right]->base ( ),
 
3210          XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNtopAttachment,
 
3211             XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
 
3219       _buttons[_XsMotifButton::Minimize] = new _XsMotifButton ("minimize", this, _XsMotifButton::Minimize);
 
3221       XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
 
3222          XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_NONE,
 
3227          XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ), XmNtopAttachment,
 
3228             XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
 
3229             XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
 
3230             _sides[_XsMotifSide::Right]->base ( ), NULL);
 
3234          XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
 
3235             XmNtopAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM,
 
3241          XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
 
3242             XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
 
3243             _buttons[_XsMotifButton::Maximize]->base ( ), NULL);
 
3253       _title = new _XsMotifTitle ("title", this);
 
3255       XtVaSetValues (_title->base ( ), XmNbottomAttachment, XmATTACH_NONE,
 
3260          XtVaSetValues (_title->base ( ), XmNtopAttachment, XmATTACH_WIDGET,
 
3261             XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
 
3262             XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget,
 
3263             _sides[_XsMotifSide::Left]->base ( ), XmNrightAttachment,
 
3264             XmATTACH_WIDGET, XmNrightWidget, _sides[_XsMotifSide::Right]->base ( ),
 
3269          XtVaSetValues (_title->base ( ), XmNtopAttachment, XmATTACH_FORM,
 
3270             XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM,
 
3276          XtVaSetValues (_title->base ( ), XmNleftAttachment, XmATTACH_WIDGET,
 
3277             XmNleftWidget, _buttons[_XsMotifButton::Menu]->base ( ), NULL);
 
3280       Widget ba = (_buttons[_XsMotifButton::Minimize] != 0) ?
 
3281          _buttons[_XsMotifButton::Minimize]->base ( ) :
 
3282          (_buttons[_XsMotifButton::Maximize] != 0) ?
 
3283          _buttons[_XsMotifButton::Maximize]->base ( ) : 0;
 
3287          XtVaSetValues (_title->base ( ), XmNrightAttachment, XmATTACH_WIDGET,
 
3288             XmNrightWidget, ba, NULL);
 
3296    _icon = new _XsMotifIcon ("icon", this, parent);
 
3302    _menu = new _XsMotifMenu ("menu", this);
 
3308    _clientArea = XtVaCreateWidget ("clientArea", xmFormWidgetClass, _base, NULL);
 
3312       XtVaSetValues (_clientArea, XmNleftAttachment, XmATTACH_WIDGET,
 
3313          XmNleftWidget, _sides[_XsMotifSide::Left]->base ( ), XmNrightAttachment,
 
3314          XmATTACH_WIDGET, XmNrightWidget, _sides[_XsMotifSide::Right]->base ( ),
 
3315          XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget,
 
3316          _sides[_XsMotifSide::Bottom]->base ( ), NULL);
 
3320       XtVaSetValues (_clientArea, XmNleftAttachment, XmATTACH_FORM,
 
3321          XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM,
 
3325    Widget topW = (_showTitle) ? _title->base ( ) :
 
3326                  (_showBorder) ? _sides[_XsMotifSide::Top]->base ( ) : 0;
 
3330       XtVaSetValues (_clientArea, XmNtopAttachment, XmATTACH_WIDGET,
 
3331          XmNtopWidget, topW, NULL);
 
3334       XtVaSetValues (_clientArea, XmNtopAttachment, XmATTACH_FORM, NULL);
 
3336 // Call the class function to create the contents of the window
 
3338    _buildClientArea (_clientArea);
 
3340 // Add an event handler to be called when this window is mapped
 
3342    XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
 
3348    for (loop = 0; loop < _XsMotifSide::Max; loop++)
 
3350       if (_corners[loop] != 0)
 
3351          _corners[loop]->show ( );
 
3352       if (_sides[loop] != 0)
 
3353          _sides[loop]->show ( );
 
3356    for (loop = 0; loop < _XsMotifButton::Max; loop++)
 
3358       if (_buttons[loop] != 0)
 
3359          _buttons[loop]->show ( );
 
3368 void XsMotifWindow::_mapEvent ( )
 
3371 // Raise the client-area
 
3373    XRaiseWindow (XtDisplay (_clientArea), XtWindow (_clientArea));
 
3378 void XsMotifWindow::_mapEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
 
3380    if (event->type == MapNotify)
 
3382       XsMotifWindow *obj = (XsMotifWindow*)clientData;
 
3384       XtRemoveEventHandler (obj->_base, StructureNotifyMask, False, obj->_mapEventHandler, clientData);