1 /*
2    Copyright (C) 1996 Scott W. Sadler
3    All rights reserved.
4 */
5 
6 /*
7    XsMotifWindow.C
8 
9    History
10       03-Mar-96 1.0; Scott W. Sadler (ssadler@cisco.com)
11                      Created
12 */
13 
14 // Includes
15 
16 #include <assert.h>
17 #include <Xm/Form.h>
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"
27 
28 // Constants
29 
30 const int BorderSize_   = 6;
31 const int ButtonSize_   = 23;
32 const int IconSize_     = 70;
33 
34 /*
35    ----------------------------------------------------------------------------
36    _XsMotifBase
37 */
38 
39 // Constructor
40 
_XsMotifBase(const char * name,XsMotifWindow * win)41 _XsMotifBase::_XsMotifBase (const char *name, XsMotifWindow *win) :
42    XsComponent (name)
43 {
44    assert (win != 0);
45 
46 // Initialize
47 
48    _win = win;
49    _topShadowGC = 0;
50    _bottomShadowGC = 0;
51 }
52 
53 // Destructor
54 
~_XsMotifBase()55 _XsMotifBase::~_XsMotifBase ( )
56 {
57    if (_topShadowGC)
58       XtReleaseGC (_base, _topShadowGC);
59 
60    if (_bottomShadowGC)
61       XtReleaseGC (_base, _bottomShadowGC);
62 }
63 
64 // show
65 
show()66 void _XsMotifBase::show ( )
67 {
68    assert (_base != 0);
69 
70 // Install event handler
71 
72    XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
73 
74 // Call the base-class
75 
76    XsComponent::show ( );
77 }
78 
79 // className
80 
className()81 const char* _XsMotifBase::className ( ) const
82 {
83    return ("_XsMotifBase");
84 }
85 
86 // _componentDestroyed ( )
87 
_componentDestroyed()88 void _XsMotifBase::_componentDestroyed ( )
89 {
90 
91 // Clean up the GCs
92 
93    if (_topShadowGC)
94       XtReleaseGC (_base, _topShadowGC);
95 
96    if (_bottomShadowGC)
97       XtReleaseGC (_base, _bottomShadowGC);
98 
99    _topShadowGC = 0;
100    _bottomShadowGC = 0;
101 
102 // Call the base-class
103 
104    XsComponent::_componentDestroyed ( );
105 }
106 
107 // _drawShadows
108 
_drawShadows(Position x,Position y,Dimension width,Dimension height,Dimension thick,Boolean reverse)109 void _XsMotifBase::_drawShadows (Position x, Position y, Dimension width,
110    Dimension height, Dimension thick, Boolean reverse)
111 {
112    assert (_base != 0);
113    assert (thick > 0);
114 
115    const int nsegs = 2;
116    XSegment segs[nsegs];
117    GC    topShadowGC;
118    GC    bottomShadowGC;
119 
120 // Work out the graphics contexts
121 
122    topShadowGC = (reverse == False) ? _topShadowGC : _bottomShadowGC;
123    bottomShadowGC = (reverse == False) ? _bottomShadowGC : _topShadowGC;
124 
125    for (int loop = 0; loop < thick; loop++)
126    {
127 
128 /*
129    TOP SHADOW DRAWING
130 */
131 
132 // Across the top
133 
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;
138 
139 // Down the left side
140 
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;
145 
146       XDrawSegments (XtDisplay (_base), XtWindow (_base), topShadowGC, segs, nsegs);
147 
148 /*
149    BOTTOM SHADOW DRAWING
150 */
151 
152 // Across the bottom
153 
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;
158 
159 // Down the right side
160 
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;
165 
166       XDrawSegments (XtDisplay (_base), XtWindow (_base), bottomShadowGC, segs, nsegs);
167    }
168 }
169 
170 // _drawLine
171 
_drawLine(Position x1,Position y1,Position x2,Position y2,GC & gc)172 void _XsMotifBase::_drawLine (Position x1, Position y1, Position x2, Position y2, GC &gc)
173 {
174    assert (_base != 0);
175    XDrawLine (XtDisplay (_base), XtWindow (_base), gc, x1, y1, x2, y2);
176 }
177 
178 // _map
179 
_map()180 void _XsMotifBase::_map ( )
181 {
182 
183 // Create the graphics contexts
184 
185    unsigned long valuemask;
186    XGCValues   values;
187    Pixel topShadow;
188    Pixel bottomShadow;
189 
190    XtVaGetValues (_win->base ( ), XmNtopShadowColor, &topShadow, XmNbottomShadowColor,
191       &bottomShadow, NULL);
192 
193 // Create the graphics contexts
194 
195    valuemask = GCForeground | GCLineWidth | GCGraphicsExposures;
196    values.line_width = 0;
197    values.graphics_exposures = False;
198 
199    values.foreground = topShadow;
200    _topShadowGC = XtGetGC (_base, valuemask, &values);
201 
202    values.foreground = bottomShadow;
203    _bottomShadowGC = XtGetGC (_base, valuemask, &values);
204 }
205 
206 // _mapEventHandler
207 
_mapEventHandler(Widget,XtPointer clientData,XEvent * event,Boolean *)208 void _XsMotifBase::_mapEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
209 {
210    if (event->type == MapNotify)
211    {
212       _XsMotifBase *obj = (_XsMotifBase*)clientData;
213       obj->_map ( );
214 
215 // Remove the event handler
216 
217       XtRemoveEventHandler (obj->_base, StructureNotifyMask, False, obj->_mapEventHandler, clientData);
218    }
219 }
220 
221 /*
222    ----------------------------------------------------------------------------
223    _XsMotifComponent
224 */
225 
226 Cursor _XsMotifComponent::_cursors[_XsMotifComponent::NumCursors];
227 
228 int _XsMotifComponent::_mutex = 0;
229 
230 XtResource _XsMotifComponent::_resourceList[] = {
231    {
232       "borderSize",
233       "BorderSize",
234       XmRDimension,
235       sizeof (Dimension),
236       XtOffset (_XsMotifComponent*, _borderSize),
237       XmRImmediate,
238       (XtPointer)BorderSize_
239    },
240    {
241       "buttonSize",
242       "ButtonSize",
243       XmRDimension,
244       sizeof (Dimension),
245       XtOffset (_XsMotifComponent*, _buttonSize),
246       XmRImmediate,
247       (XtPointer)ButtonSize_
248    }
249 };
250 
251 // Constructor
252 
_XsMotifComponent(const char * name,XsMotifWindow * win,Widget parent)253 _XsMotifComponent::_XsMotifComponent (const char *name, XsMotifWindow *win,
254    Widget parent) : _XsMotifBase (name, win)
255 {
256 
257 // Create cursors (if necessary)
258 
259    if (_mutex == 0)
260    {
261 
262       Display *dpy = XtDisplay (win->base ( ));
263 
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);
272 
273       _mutex = 1;
274    }
275 
276 // Create the component
277 
278    _base = XtVaCreateWidget (name, widgetClass, (parent != 0) ? parent : _win->base ( ), NULL);
279 
280 // Install destroy handler
281 
282    _installDestroyHandler ( );
283 
284 // Get resources
285 
286    _getResources (_resourceList, XtNumber (_resourceList));
287 
288 // Compute the corner size
289 
290    _cornerSize = _buttonSize + _borderSize;
291 
292 // Install event handlers
293 
294    XtAddEventHandler (_base, ExposureMask, False, _exposeEventHandler, (XtPointer)this);
295    XtAddEventHandler (_base, ButtonPressMask | ButtonReleaseMask | Button1MotionMask | Button2MotionMask, False, _inputEventHandler, (XtPointer)this);
296 }
297 
298 // Destructor
299 
~_XsMotifComponent()300 _XsMotifComponent::~_XsMotifComponent ( )
301 {
302    // Empty
303 }
304 
305 // className
306 
className()307 const char* _XsMotifComponent::className ( ) const
308 {
309    return ("_XsMotifComponent");
310 }
311 
312 // _input
313 
_input(XEvent *)314 void _XsMotifComponent::_input (XEvent*)
315 {
316    // Empty
317 }
318 
319 // _exposeEventHandler
320 
_exposeEventHandler(Widget,XtPointer clientData,XEvent * event,Boolean *)321 void _XsMotifComponent::_exposeEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
322 {
323    _XsMotifComponent *obj = (_XsMotifComponent*)clientData;
324 
325    if (event->xexpose.count == 0)
326       obj->_expose (event);
327 }
328 
329 // _inputEventHandler
330 
_inputEventHandler(Widget,XtPointer clientData,XEvent * event,Boolean *)331 void _XsMotifComponent::_inputEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
332 {
333    _XsMotifComponent *obj = (_XsMotifComponent*)clientData;
334    obj->_input (event);
335 }
336 
337 /*
338    ----------------------------------------------------------------------------
339    _XsMotifCorner
340 */
341 
342 // Constructor
343 
_XsMotifCorner(const char * name,XsMotifWindow * win,Corner corner)344 _XsMotifCorner::_XsMotifCorner (const char *name, XsMotifWindow *win, Corner corner)
345    : _XsMotifComponent (name, win)
346 {
347 
348 // Initialize
349 
350    _corner = corner;
351 
352 // Configure component
353 
354    XtVaSetValues (_base, XmNwidth, _cornerSize, XmNheight, _cornerSize,
355       XmNborderWidth, (Dimension)0, NULL);
356 }
357 
358 // Destructor
359 
~_XsMotifCorner()360 _XsMotifCorner::~_XsMotifCorner ( )
361 {
362    // Empty
363 }
364 
365 // className
366 
className()367 const char *_XsMotifCorner::className ( ) const
368 {
369    return ("_XsMotifCorner");
370 }
371 
372 // _expose
373 
_expose(XEvent *)374 void _XsMotifCorner::_expose (XEvent*)
375 {
376    Dimension   w, h;
377 
378    if (_topShadowGC == 0) // JACS
379      return;
380 
381 // Get the size of the corner
382 
383    XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
384 
385 // Draw the shadow
386 
387    _drawShadows (0, 0, w, h, 1);
388 
389 // Draw the extra lines and relief
390 
391    switch (_corner)
392    {
393       case TopLeft:
394       {
395          _drawLine (1, 1, w - 2, 1, _topShadowGC);
396          _drawLine (1, 1, 1, h - 2, _topShadowGC);
397 
398 // Relief
399 
400          _drawLine (_borderSize - 1, _borderSize - 1, _borderSize +
401             _buttonSize - 2, _borderSize - 1, _bottomShadowGC);
402 
403          _drawLine (_borderSize - 1, _borderSize - 1, _borderSize - 1,
404             _borderSize + _buttonSize - 2, _bottomShadowGC);
405 
406          break;
407       }
408       case TopRight:
409       {
410          _drawLine (1, 1, w - 2, 1, _topShadowGC);
411          _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
412 
413 // Relief
414 
415          _drawLine (0, _borderSize - 1, _buttonSize - 1, _borderSize - 1,
416             _bottomShadowGC);
417 
418          _drawLine (w - _borderSize, _borderSize - 1, w - _borderSize,
419             _borderSize + _buttonSize - 2, _topShadowGC);
420 
421          break;
422       }
423       case BottomLeft:
424       {
425          _drawLine (1, 1, 1, h - 2, _topShadowGC);
426          _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
427 
428 // Relief
429 
430          _drawLine (_borderSize - 1, h - _borderSize, _borderSize +
431             _buttonSize - 2, h - _borderSize, _topShadowGC);
432 
433          _drawLine (_borderSize - 1, 1, _borderSize - 1,
434             _buttonSize - 1, _bottomShadowGC);
435 
436          break;
437       }
438       case BottomRight:
439       {
440          _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
441          _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
442 
443 // Relief
444 
445          _drawLine (1, h - _borderSize, _buttonSize, h - _borderSize,
446             _topShadowGC);
447 
448          _drawLine (w - _borderSize, 1, w - _borderSize,
449             _buttonSize - 1, _topShadowGC);
450 
451          break;
452       }
453       default:
454          assert (0);
455    }
456 }
457 
458 // _input
459 
_input(XEvent * event)460 void _XsMotifCorner::_input (XEvent *event)
461 {
462    switch (event->type)
463    {
464       case ButtonPress:
465       {
466          if (event->xbutton.button == 2)
467          {
468             XsMoveOutline move (_win->base ( ));
469 
470 // Start the move
471 
472             if (move.go ( ) != False)
473             {
474 
475 // Relocate the window
476 
477                _win->setPosition (move.x ( ), move.y ( ));
478             }
479          }
480          else if (event->xbutton.button == 3)
481             _win->popupMenu ( );
482 
483          break;
484       }
485       case ButtonRelease:
486       {
487          switch (event->xbutton.button)
488          {
489             case 1:
490             case 2:
491             {
492                _win->raise ( );     // Raise the window
493                break;
494             }
495          }
496          break;
497       }
498       case MotionNotify:
499       {
500 
501 // Figure kind of resize we are doing
502 
503          int   dir;
504 
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;
513          else
514             assert (0);
515 
516          XsResizeOutline resize (_win->base ( ), dir);
517          resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
518 
519 // Start the resize
520 
521          if (resize.go ( ) != False)
522          {
523 
524 // Relocate the window
525 
526             _win->setPosition (resize.x ( ), resize.y ( ));
527             _win->setSize (resize.width ( ), resize.height ( ));
528          }
529          break;
530       }
531    }
532 }
533 
534 // _map
535 
_map()536 void _XsMotifCorner::_map ( )
537 {
538 
539 // Call the base-class
540 
541    _XsMotifComponent::_map ( );
542 
543 // Install the cursor
544 
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]);
553    else
554       assert (0);
555 }
556 
557 /*
558    ----------------------------------------------------------------------------
559    _XsMotifSide
560 */
561 
562 // Constructor
563 
_XsMotifSide(const char * name,XsMotifWindow * win,Side side)564 _XsMotifSide::_XsMotifSide (const char *name, XsMotifWindow *win, Side side) :
565    _XsMotifComponent (name, win)
566 {
567 
568 // Initialize
569 
570    _side = side;
571    _lastW = _lastH = -1;
572 
573 // Configure component
574 
575    switch (_side)
576    {
577       case Top:
578       case Bottom:
579       {
580          XtVaSetValues (_base, XmNheight, _borderSize, XmNborderWidth,
581             (Dimension)0, NULL);
582          break;
583       }
584       case Left:
585       case Right:
586       {
587          XtVaSetValues (_base, XmNwidth, _borderSize, XmNborderWidth,
588             (Dimension)0, NULL);
589          break;
590       }
591       default:
592          assert (0);
593    }
594 
595 // Install event handler
596 
597    XtAddEventHandler (_base, StructureNotifyMask, False, _configureEventHandler, (XtPointer)this);
598 }
599 
600 // Destructor
601 
~_XsMotifSide()602 _XsMotifSide::~_XsMotifSide ( )
603 {
604    // Empty
605 }
606 
607 // className
608 
className()609 const char *_XsMotifSide::className ( ) const
610 {
611    return ("_XsMotifSide");
612 }
613 
614 // _expose
615 
_expose(XEvent * event)616 void _XsMotifSide::_expose (XEvent *event)
617 {
618    if (_topShadowGC == 0) // JACS
619      return;
620 
621 // Clear out the window first
622 
623    if (event != 0)
624       XClearWindow (XtDisplay (_base), XtWindow (_base));
625 
626    Dimension   w, h;
627 
628 // Get the size of the side
629 
630    XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
631 
632 // Draw the shadow
633 
634    _drawShadows (0, 0, w, h, 1);
635 
636 // Draw the extra lines
637 
638    switch (_side)
639    {
640       case Top:
641       {
642          _drawLine (1, 1, w - 2, 1, _topShadowGC);
643          break;
644       }
645       case Bottom:
646       {
647          _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
648          break;
649       }
650       case Left:
651       {
652          _drawLine (1, 1, 1, h - 2, _topShadowGC);
653          break;
654       }
655       case Right:
656       {
657          _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
658          break;
659       }
660       default:
661          assert (0);
662    }
663 }
664 
665 // _input
666 
_input(XEvent * event)667 void _XsMotifSide::_input (XEvent *event)
668 {
669    switch (event->type)
670    {
671       case ButtonPress:
672       {
673          if (event->xbutton.button == 2)
674          {
675             XsMoveOutline move (_win->base ( ));
676 
677 // Start the move
678 
679             if (move.go ( ) != False)
680             {
681 
682 // Relocate the window
683 
684                _win->setPosition (move.x ( ), move.y ( ));
685             }
686          }
687          else if (event->xbutton.button == 3)
688             _win->popupMenu ( );
689 
690          break;
691       }
692       case ButtonRelease:
693       {
694          switch (event->xbutton.button)
695          {
696             case 1:
697             case 2:
698             {
699                _win->raise ( );     // Raise the window
700                break;
701             }
702          }
703          break;
704       }
705       case MotionNotify:
706       {
707 
708 // Figure kind of resize we are doing
709 
710          int   dir;
711 
712          if (_side == Top)
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;
720          else
721             assert (0);
722 
723          XsResizeOutline resize (_win->base ( ), dir);
724          resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
725 
726 // Start the resize
727 
728          if (resize.go ( ) != False)
729          {
730 
731 // Relocate the window
732 
733             _win->setPosition (resize.x ( ), resize.y ( ));
734             _win->setSize (resize.width ( ), resize.height ( ));
735          }
736          break;
737       }
738    }
739 }
740 
741 // _map
742 
_map()743 void _XsMotifSide::_map ( )
744 {
745 
746 // Call the base-class
747 
748    _XsMotifComponent::_map ( );
749 
750 // Install the cursor
751 
752    if (_side == Top)
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]);
760    else
761       assert (0);
762 }
763 
764 // _configure
765 
_configure(XEvent * event)766 void _XsMotifSide::_configure (XEvent *event)
767 {
768    XConfigureEvent *ce = (XConfigureEvent*)event;
769 
770 /*
771    Check if window has been resized.  If so, generate an expose event
772    to redraw its contents.
773 */
774 
775    if ((_lastW != ce->width) || (_lastH != ce->height))
776    {
777       if ((_base != 0) && XtIsManaged (_base))
778          XClearArea (XtDisplay (_base), XtWindow (_base), 0, 0, 0, 0, True);
779 
780       _lastW = ce->width;
781       _lastH = ce->height;
782    }
783 }
784 
785 // _configureEventHandler
786 
_configureEventHandler(Widget,XtPointer clientData,XEvent * event,Boolean *)787 void _XsMotifSide::_configureEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
788 {
789    if (event->type == ConfigureNotify)
790    {
791       _XsMotifSide *obj = (_XsMotifSide*)clientData;
792       obj->_configure (event);
793    }
794 }
795 
796 /*
797    ----------------------------------------------------------------------------
798    _XsMotifButton
799 */
800 
801 // Constructor
802 
_XsMotifButton(const char * name,XsMotifWindow * win,Button button)803 _XsMotifButton::_XsMotifButton (const char *name, XsMotifWindow *win, Button button) :
804    _XsMotifComponent (name, win)
805 {
806 
807 // Initialize
808 
809    _pressed = False;
810    _button = button;
811 
812 // Configure the component
813 
814    XtVaSetValues (_base, XmNheight, _buttonSize, XmNwidth, _buttonSize,
815       XmNborderWidth, (Dimension)0, NULL);
816 }
817 
818 // Destructor
819 
~_XsMotifButton()820 _XsMotifButton::~_XsMotifButton ( )
821 {
822    // Empty
823 }
824 
825 // redraw
826 
redraw()827 void _XsMotifButton::redraw ( )
828 {
829 
830 // Make sure component is viewable
831 
832    if (!XtIsRealized (_base))
833       return;
834 
835 // Check if window is viewable
836 
837    XWindowAttributes attrs;
838    XGetWindowAttributes (XtDisplay (_base), XtWindow (_base), &attrs);
839 
840    if (attrs.map_state == IsViewable)
841       _expose (0);      // Just pretend we got an expose event
842 }
843 
844 // className
845 
className()846 const char *_XsMotifButton::className ( ) const
847 {
848    return ("_XsMotifButton");
849 }
850 
851 // _expose
852 
_expose(XEvent * event)853 void _XsMotifButton::_expose (XEvent *event)
854 {
855    if (_topShadowGC == 0) // JACS
856      return;
857 
858    Dimension   w, h;
859 
860 // Get the size of the button
861 
862    XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
863 
864 // Draw the shadow
865 
866    _drawShadows (0, 0, w, h, 1, _pressed);
867 
868 // Draw the extra line
869 
870    _drawLine (1, h - 2, w - 2, h - 2, (_pressed) ? _topShadowGC : _bottomShadowGC);
871 
872 // Check if we need to draw the decal
873 
874    if ((_button != Maximize) && (event == 0))
875       return;
876 
877 // Compute the decal size
878 
879    Dimension dw, dh;
880    Boolean  reverse = False;
881 
882    switch (_button)
883    {
884       case Menu:
885       {
886          dw = _buttonSize - 6;
887 	 dh = 4;
888          break;
889       }
890       case Minimize:
891       {
892          dw = dh = 4;
893          break;
894       }
895       case Maximize:
896       {
897          dw = _buttonSize - 6;
898          dh = dw - 1;
899 
900          if (_win->maximized ( ))
901             reverse = True;
902 
903          break;
904       }
905       default:
906          assert (0);
907    }
908 
909 // Draw the decal
910 
911    _drawShadows ((w / 2) - (dw / 2), (h / 2) - (dh / 2), dw, dh, 1, reverse);
912 }
913 
914 // _input
915 
_input(XEvent * event)916 void _XsMotifButton::_input (XEvent *event)
917 {
918    static Time lastTime = (Time)0;
919 
920    switch (event->type)
921    {
922       case ButtonPress:
923       {
924          if (event->xbutton.button == 1)
925          {
926             _pressed = True;
927 
928             if (_button == Menu)
929             {
930 
931 // Get double-click time
932 
933                int multiClick = XtGetMultiClickTime (XtDisplay (_base));
934 
935 // Check for double-click
936 
937                if ((event->xbutton.time - lastTime) <= multiClick)
938                {
939                   _win->close ( );
940                   return;
941                }
942                else
943                   lastTime = event->xbutton.time;
944 
945 // Redraw the button (pushed-in)
946 
947                redraw ( );
948 
949 // Popup the menu
950 
951                _win->popupMenu (False);
952 
953 // The menu will consume the ButtonRelease, so fake one
954 
955                _pressed = False;
956                redraw ( );
957 
958             }
959             else if ((_button == Minimize) || (_button == Maximize))
960             {
961                redraw ( );
962             }
963          }
964          else if (event->xbutton.button == 2)
965          {
966             XsMoveOutline move (_win->base ( ));
967 
968 // Start the move
969 
970             if (move.go ( ) != False)
971             {
972 
973 // Relocate the window
974 
975                _win->setPosition (move.x ( ), move.y ( ));
976             }
977          }
978          else if (event->xbutton.button == 3)
979             _win->popupMenu ( );
980 
981          break;
982       }
983       case ButtonRelease:
984       {
985          if (event->xbutton.button == 1)
986          {
987             _pressed = False;
988 
989 // Check if pointer is really in the window
990 
991             XButtonEvent *b = &event->xbutton;
992             Dimension width, height;
993             Boolean  inWindow = False;
994 
995             XtVaGetValues (_base, XmNwidth, &width, XmNheight, &height, NULL);
996             if ((b->x >= 0) && (b->y >= 0) && (b->x < width) && (b->y < height))
997                inWindow = True;
998 
999             if (_button == Minimize)
1000             {
1001                if (inWindow)
1002                {
1003                   if (_win->minimized ( ))
1004                      _win->restore ( );
1005                   else
1006                      _win->minimize ( );
1007                }
1008                else
1009                   redraw ( );
1010             }
1011             else if (_button == Maximize)
1012             {
1013                if (inWindow)
1014                {
1015                   if (_win->maximized ( ))
1016                      _win->restore ( );
1017                   else
1018                      _win->maximize ( );
1019                }
1020                else
1021                   redraw ( );
1022             }
1023          }
1024          break;
1025       }
1026    }
1027 }
1028 
1029 // _map
1030 
_map()1031 void _XsMotifButton::_map ( )
1032 {
1033 
1034 // Call the base-class
1035 
1036    _XsMotifComponent::_map ( );
1037 
1038 // Raise ourself
1039 
1040    XRaiseWindow (XtDisplay (_base), XtWindow (_base));
1041 }
1042 
1043 /*
1044    ----------------------------------------------------------------------------
1045    _XsMotifTitle
1046 */
1047 
1048 XtResource _XsMotifTitle::_resourceList[] = {
1049    {
1050       "title",
1051       "Title",
1052       XmRString,
1053       sizeof (String),
1054       XtOffset (_XsMotifTitle*, _titleString),
1055       XmRImmediate,
1056       NULL
1057    },
1058    {
1059       "titleFont",
1060       "TitleFont",
1061       XmRFontStruct,
1062       sizeof (XFontStruct*),
1063       XtOffset (_XsMotifTitle*, _titleFont),
1064       XmRString,
1065       "-*-helvetica-bold-o-normal-*-14-*-*-*-*-*-iso8859-1"
1066    }
1067 };
1068 
1069 // Constructor
1070 
_XsMotifTitle(const char * name,XsMotifWindow * win)1071 _XsMotifTitle::_XsMotifTitle (const char *name, XsMotifWindow *win) :
1072    _XsMotifComponent (name, win)
1073 {
1074 
1075 // Initialize
1076 
1077    _pressed = False;
1078    _titleString = 0;
1079    _titleFont = 0;
1080    _fontGC = 0;
1081    _lastW = _lastH = -1;
1082 
1083 // Get resources
1084 
1085    _getResources (_resourceList, XtNumber (_resourceList));
1086 
1087 // Copy title string to local memory
1088 
1089    if (_titleString != 0)
1090    {
1091       char *tmp = new char[strlen (_titleString) + 1];
1092       strcpy (tmp, _titleString);
1093       _titleString = tmp;
1094    }
1095 
1096 // Configure the title
1097 
1098    XtVaSetValues (_base,  XmNheight, _buttonSize, XmNborderWidth,
1099       (Dimension)0, NULL);
1100 
1101 // Install event handler
1102 
1103    XtAddEventHandler (_base, StructureNotifyMask, False, _configureEventHandler, (XtPointer)this);
1104 }
1105 
1106 // Destructor
1107 
~_XsMotifTitle()1108 _XsMotifTitle::~_XsMotifTitle ( )
1109 {
1110    if (_fontGC)
1111       XtReleaseGC (_base, _fontGC);
1112 
1113    delete [] _titleString;
1114 }
1115 
1116 // setTitle
1117 
setTitle(const char * title)1118 void _XsMotifTitle::setTitle (const char *title)
1119 {
1120    assert (title != 0);
1121 
1122    delete [] _titleString;
1123 
1124    _titleString = new char[strlen (title) + 1];
1125    strcpy (_titleString, title);
1126 }
1127 
1128 // className
1129 
className()1130 const char *_XsMotifTitle::className ( ) const
1131 {
1132    return ("_XsMotifTitle");
1133 }
1134 
1135 // _componentDestroyed
1136 
_componentDestroyed()1137 void _XsMotifTitle::_componentDestroyed ( )
1138 {
1139 
1140 // Clean up the GCs
1141 
1142    if (_fontGC)
1143       XtReleaseGC (_base, _fontGC);
1144 
1145    _fontGC = 0;
1146 
1147 // Call base-class
1148 
1149    _XsMotifComponent::_componentDestroyed ( );
1150 }
1151 
1152 // _redraw
1153 
_redraw()1154 void _XsMotifTitle::_redraw ( )
1155 {
1156    _expose (0);      // Just pretend we got an expose event
1157 }
1158 
1159 // _expose
1160 
_expose(XEvent * event)1161 void _XsMotifTitle::_expose (XEvent *event)
1162 {
1163    if (_topShadowGC == 0) // JACS
1164      return;
1165 
1166 // Clear out the window first
1167 
1168    if (event != 0)
1169       XClearWindow (XtDisplay (_base), XtWindow (_base));
1170 
1171    Dimension   w, h;
1172 
1173 // Get the size of the button
1174 
1175    XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
1176 
1177 // Draw the shadow
1178 
1179    _drawShadows (0, 0, w, h, 1, _pressed);
1180 
1181 // Draw the extra line
1182 
1183    _drawLine (1, h - 2, w - 2, h - 2, (_pressed) ? _topShadowGC : _bottomShadowGC);
1184 
1185 // If this is an artificial event, no need continuing
1186 
1187    if (event == 0)
1188       return;
1189 
1190 // Draw the text string
1191 
1192    const int LeftOffset = 5;
1193    const int TopOffset = 2;
1194 
1195 // Figure out the title
1196 
1197    const char *title = (_titleString != 0) ? _titleString : _win->name ( );
1198 
1199    if ((title != 0) && (title[0] != '\0'))
1200    {
1201       int len = strlen (title);
1202 
1203       XDrawString (XtDisplay (_base), XtWindow (_base), _fontGC,
1204          LeftOffset, TopOffset + _titleFont->ascent, title, len);
1205    }
1206 }
1207 
1208 // _input
1209 
_input(XEvent * event)1210 void _XsMotifTitle::_input (XEvent *event)
1211 {
1212    switch (event->type)
1213    {
1214       case ButtonPress:
1215       {
1216          switch (event->xbutton.button)
1217          {
1218             case 1:
1219             {
1220                _pressed = True;
1221                _redraw ( );
1222                break;
1223             }
1224             case 2:
1225             {
1226                XsMoveOutline move (_win->base ( ));
1227 
1228 // Start the move
1229 
1230                if (move.go ( ) != False)
1231                {
1232 
1233 // Relocate the window
1234 
1235                   _win->setPosition (move.x ( ), move.y ( ));
1236                }
1237                break;
1238             }
1239             case 3:
1240             {
1241                _win->popupMenu ( );
1242                break;
1243             }
1244          }
1245          break;
1246       }
1247       case ButtonRelease:
1248       {
1249          switch (event->xbutton.button)
1250          {
1251             case 1:
1252             case 2:
1253             {
1254                _pressed = False;
1255                _redraw ( );
1256 
1257                _win->raise ( );
1258                break;
1259             }
1260          }
1261          break;
1262       }
1263       case MotionNotify:
1264       {
1265          XsMoveOutline move (_win->base ( ));
1266 
1267 // Start the move
1268 
1269          if (move.go ( ) != False)
1270          {
1271 
1272 // Relocate the window
1273 
1274             _win->setPosition (move.x ( ), move.y ( ));
1275 
1276 // Redraw the title bar
1277 
1278             _pressed = False;
1279             _redraw ( );
1280          }
1281          break;
1282       }
1283    }
1284 }
1285 
1286 // _map
1287 
_map()1288 void _XsMotifTitle::_map ( )
1289 {
1290 
1291 // Call the base-class
1292 
1293    _XsMotifComponent::_map ( );
1294 
1295 // Raise ourself
1296 
1297    XRaiseWindow (XtDisplay (_base), XtWindow (_base));
1298 
1299    unsigned long valuemask;
1300    XGCValues   values;
1301    Pixel foreground;
1302    Pixel background;
1303 
1304 // Get the pixels
1305 
1306    XtVaGetValues (_win->base ( ), XmNforeground, &foreground, XmNbackground, &background, NULL);
1307 
1308 // Create the font graphics context
1309 
1310    valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
1311 
1312    values.foreground = foreground;
1313    values.background = background;
1314    values.font = _titleFont->fid;
1315    values.graphics_exposures = False;
1316 
1317    _fontGC = XtGetGC (_base, valuemask, &values);
1318 }
1319 
1320 // _configure
1321 
_configure(XEvent * event)1322 void _XsMotifTitle::_configure (XEvent *event)
1323 {
1324    XConfigureEvent *ce = (XConfigureEvent*)event;
1325 
1326 /*
1327    Check if window has been resized.  If so, generate an expose event
1328    to redraw its contents.
1329 */
1330 
1331    if ((_lastW != ce->width) || (_lastH != ce->height))
1332    {
1333       if ((_base != 0) && XtIsManaged (_base))
1334          XClearArea (XtDisplay (_base), XtWindow (_base), 0, 0, 0, 0, True);
1335 
1336       _lastW = ce->width;
1337       _lastH = ce->height;
1338    }
1339 }
1340 
1341 // _configureEventHandler
1342 
_configureEventHandler(Widget,XtPointer clientData,XEvent * event,Boolean *)1343 void _XsMotifTitle::_configureEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
1344 {
1345    if (event->type == ConfigureNotify)
1346    {
1347       _XsMotifTitle *obj = (_XsMotifTitle*)clientData;
1348       obj->_configure (event);
1349    }
1350 }
1351 
1352 /*
1353    ----------------------------------------------------------------------------
1354    _XsMotifIcon
1355 */
1356 
1357 XtResource _XsMotifIcon::_resourceList[] = {
1358    {
1359       "iconSize",
1360       "IconSize",
1361       XmRDimension,
1362       sizeof (Dimension),
1363       XtOffset (_XsMotifIcon*, _iconSize),
1364       XmRImmediate,
1365       (XtPointer)IconSize_
1366    },
1367    {
1368       "iconName",
1369       "IconName",
1370       XmRString,
1371       sizeof (String),
1372       XtOffset (_XsMotifIcon*, _iconName),
1373       XmRImmediate,
1374       NULL
1375    },
1376    {
1377       "iconFont",
1378       "IconFont",
1379       XmRFontStruct,
1380       sizeof (XFontStruct*),
1381       XtOffset (_XsMotifIcon*, _iconFont),
1382       XmRString,
1383       "-*-helvetica-bold-r-normal-*-12-*-*-*-*-*-iso8859-1"
1384    },
1385    {
1386       XmNiconX,
1387       XmCIconX,
1388       XmRPosition,
1389       sizeof (Position),
1390       XtOffset (_XsMotifIcon*, _iconX),
1391       XmRImmediate,
1392       (XtPointer)-1
1393    },
1394    {
1395       XmNiconY,
1396       XmCIconY,
1397       XmRPosition,
1398       sizeof (Position),
1399       XtOffset (_XsMotifIcon*, _iconY),
1400       XmRImmediate,
1401       (XtPointer)-1
1402    }
1403 };
1404 
1405 // Constructor
1406 
_XsMotifIcon(const char * name,XsMotifWindow * win,Widget parent)1407 _XsMotifIcon::_XsMotifIcon (const char *name, XsMotifWindow *win, Widget parent) :
1408    _XsMotifComponent (name, win, parent)
1409 {
1410 
1411 // Initialize
1412 
1413    _pixmapGC = 0;
1414    _fontGC = 0;
1415 
1416    _iconName = 0;
1417    _pixmap = 0;
1418    _freePixmap = False;
1419 
1420    _width = _height = 0;
1421    _placed = 0;
1422 
1423 // Get resources
1424 
1425    _getResources (_resourceList, XtNumber (_resourceList));
1426 
1427 // Copy icon name to local memory
1428 
1429    if (_iconName != 0)
1430    {
1431       char *tmp = new char[strlen (_iconName) + 1];
1432       strcpy (tmp, _iconName);
1433       _iconName = tmp;
1434    }
1435 
1436 // Configure the icon
1437 
1438    XtVaSetValues (_base, XmNwidth, _iconSize, XmNheight, _iconSize, NULL);
1439 }
1440 
1441 // Destructor
1442 
~_XsMotifIcon()1443 _XsMotifIcon::~_XsMotifIcon ( )
1444 {
1445    if (_fontGC)
1446       XtReleaseGC (_base, _fontGC);
1447 
1448    if (_pixmapGC)
1449       XtReleaseGC (_base, _pixmapGC);
1450 
1451    if (_freePixmap)
1452       XFreePixmap (XtDisplay (_base), _pixmap);
1453 
1454    delete [] _iconName;
1455 }
1456 
1457 // show
1458 
show()1459 void _XsMotifIcon::show ( )
1460 {
1461 
1462 /*
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
1465    window.
1466 */
1467 
1468    if (_placed == False)
1469    {
1470       Position x, y;
1471 
1472       if (_iconX == -1)
1473       {
1474          XtVaGetValues (_win->base ( ), XmNx, &x, NULL);
1475          if (x < 0)  x = 0;
1476          _iconX = x;
1477       }
1478       else
1479          x = _iconX;
1480 
1481       if (_iconY == -1)
1482       {
1483          XtVaGetValues (_win->base ( ), XmNy, &y, NULL);
1484          if (y < 0)  y = 0;
1485          _iconY = y;
1486       }
1487       else
1488          y = _iconY;
1489 
1490       XtVaSetValues (_base, XmNx, x, XmNy, y, NULL);
1491 
1492       _placed = True;
1493    }
1494 
1495 // Call the base class
1496 
1497    _XsMotifComponent::show ( );
1498 }
1499 
1500 // setIconName
1501 
setIconName(const char * iconName)1502 void _XsMotifIcon::setIconName (const char *iconName)
1503 {
1504    assert (iconName != 0);
1505 
1506    delete [] _iconName;
1507 
1508    _iconName = new char[strlen (iconName) + 1];
1509    strcpy (_iconName, iconName);
1510 }
1511 
1512 // setPixmap
1513 
setPixmap(Pixmap pixmap)1514 void _XsMotifIcon::setPixmap (Pixmap pixmap)
1515 {
1516    assert (pixmap != 0);
1517 
1518 // Free the existing pixmap (if necessary)
1519 
1520    if (_freePixmap)
1521    {
1522       XFreePixmap (XtDisplay (_base), _pixmap);
1523       _freePixmap = False;
1524    }
1525 
1526 // Save the new pixmap
1527 
1528    _pixmap = pixmap;
1529 
1530 // Get the pixmap width and height
1531 
1532    Window   dummy;
1533    int      xd, yd;
1534    unsigned int   uw, uh, ub, ud;
1535 
1536    XGetGeometry (XtDisplay (_base), _pixmap, &dummy, &xd, &yd, &uw, &uh, &ub, &ud);
1537 
1538    _width = uw;
1539    _height = uh;
1540 }
1541 
1542 // className
1543 
className()1544 const char *_XsMotifIcon::className ( ) const
1545 {
1546    return ("_XsMotifIcon");
1547 }
1548 
1549 // _componentDestroyed
1550 
_componentDestroyed()1551 void _XsMotifIcon::_componentDestroyed ( )
1552 {
1553 
1554 // Clear up the GCs
1555 
1556    if (_fontGC)
1557       XtReleaseGC (_base, _fontGC);
1558 
1559    if (_pixmapGC)
1560       XtReleaseGC (_base, _pixmapGC);
1561 
1562    if (_freePixmap)
1563       XFreePixmap (XtDisplay (_base), _pixmap);
1564 
1565    _fontGC = 0;
1566    _pixmapGC = 0;
1567    _freePixmap = 0;
1568 
1569 // Call the base-class
1570 
1571    _XsMotifComponent::_componentDestroyed ( );
1572 }
1573 
1574 // _input
1575 
_input(XEvent * event)1576 void _XsMotifIcon::_input (XEvent *event)
1577 {
1578    static Time lastTime = (Time)0;
1579 
1580    switch (event->type)
1581    {
1582       case ButtonPress:
1583       {
1584          switch (event->xbutton.button)
1585          {
1586             case 1:
1587                break;
1588 
1589             case 2:
1590             {
1591                XsMoveOutline move (_base);
1592 
1593 // Start the move
1594 
1595                if (move.go ( ) != False)
1596                {
1597 
1598 // Relocate the window
1599 
1600                   _win->setPosition (move.x ( ), move.y ( ));
1601                }
1602                break;
1603             }
1604             case 3:
1605             {
1606                _win->popupMenu ( );
1607                break;
1608             }
1609          }
1610          break;
1611       }
1612       case ButtonRelease:
1613       {
1614          switch (event->xbutton.button)
1615          {
1616             case 1:
1617             {
1618 
1619 // Get double-click time
1620 
1621                int multiClick = XtGetMultiClickTime (XtDisplay (_base));
1622 
1623 // Check for double-click
1624 
1625                if ((event->xbutton.time - lastTime) <= multiClick)
1626                   _win->restore ( );
1627                else
1628                {
1629                   lastTime = event->xbutton.time;
1630                   _win->raise ( );
1631                }
1632                break;
1633             }
1634          }
1635          break;
1636       }
1637       case MotionNotify:
1638       {
1639          XsMoveOutline  move (_base);
1640 
1641 // Start the move
1642 
1643          if (move.go ( ) != False)
1644          {
1645 
1646 // Relocate the icon
1647 
1648             _win->setPosition (move.x ( ), move.y ( ));
1649          }
1650          break;
1651       }
1652    }
1653 }
1654 
1655 // _expose
1656 
_expose(XEvent *)1657 void _XsMotifIcon::_expose (XEvent *)
1658 {
1659    if (_topShadowGC == 0) // JACS
1660      return;
1661 
1662    Dimension   iconHeight;
1663    Dimension   iconWidth;
1664 
1665 // Compute icon size
1666 
1667    XtVaGetValues (_base, XmNwidth, &iconWidth, XmNheight, &iconHeight, NULL);
1668 
1669 // Draw the shadow
1670 
1671    _drawShadows (0, 0, iconWidth, iconHeight, 2);
1672 
1673 // Figure out the icon string
1674 
1675    const char *iconName = (_iconName != 0) ? _iconName : (_win->title ( ) != 0) ?
1676       _win->title ( ) : _win->name ( );
1677 
1678    const int fontX = 3;
1679    const int fontY = 3;
1680 
1681    if ((iconName != 0) && (iconName[0] != '\0'))
1682    {
1683       int   textWidth;
1684       int   len = strlen (iconName);
1685 
1686 // Compute the text size
1687 
1688       textWidth = XTextWidth (_iconFont, iconName, len);
1689 
1690 // Center the text in the bottom of the icon (or left-justify it)
1691 
1692       int   x, y;
1693 
1694       if (textWidth <= (iconWidth - (fontX * 2)))
1695          x = (iconWidth - (int)textWidth) / 2;
1696       else
1697          x = fontX;
1698 
1699       y = (int)iconHeight - _iconFont->descent - fontY;
1700 
1701 // Draw the string
1702 
1703       XDrawString (XtDisplay (_base), XtWindow (_base), _fontGC,
1704          x, y, iconName, len);
1705    }
1706 
1707 // Compute label size
1708 
1709    int labelHeight = _iconFont->descent + _iconFont->ascent + (fontY * 2);
1710 
1711    if (labelHeight >= (iconHeight - 6))
1712       return;
1713 
1714 // Draw the separator
1715 
1716    int sepY = (iconHeight) - labelHeight;
1717 
1718    _drawLine (1, sepY, iconWidth - 2, sepY, _bottomShadowGC);
1719    _drawLine (1, sepY + 1, iconWidth - 2, sepY + 1, _topShadowGC);
1720 
1721 // Draw the pixmap frame
1722 
1723    const int frameX = 4;
1724    const int frameY = 4;
1725 
1726    if ((frameX + 6) >= sepY)
1727       return;
1728 
1729    int   frameWidth = iconWidth - (frameX * 2);
1730    int   frameHeight = sepY - frameY - 2;
1731 
1732    _drawShadows (frameX, frameY, frameWidth, frameHeight, 1, True);
1733 
1734    frameWidth -= 2;
1735    frameHeight -= 2;
1736 
1737    _drawShadows (frameX + 1, frameY + 1, frameWidth, frameHeight, 1);
1738 
1739    frameWidth -= 2;
1740    frameHeight -= 2;
1741 
1742 // Blit the pixmap
1743 
1744    if (_pixmap != 0)
1745    {
1746       if ((frameWidth > 0) && (frameHeight > 0))
1747       {
1748          int   origX, origY;
1749          int   drawW, drawH;
1750 
1751 // Center the pixmap or top-left orient it
1752 
1753          if (frameWidth > _width)
1754          {
1755             origX = (frameWidth - _width) / 2;
1756             origX += frameX + 2;
1757             drawW = _width;
1758          }
1759          else
1760          {
1761             origX = frameX + 2;
1762             drawW = frameWidth;
1763          }
1764 
1765          if (frameHeight > _height)
1766          {
1767             origY = (frameHeight - _height) / 2;
1768             origY += frameY + 2;
1769             drawH = _height;
1770          }
1771          else
1772          {
1773             origY = frameY + 2;
1774             drawH = frameHeight;
1775          }
1776 
1777          XCopyArea (XtDisplay (_base), _pixmap, XtWindow (_base), _pixmapGC,
1778             0, 0, drawW, drawH, origX, origY);
1779       }
1780    }
1781 }
1782 
1783 // _map
1784 
_map()1785 void _XsMotifIcon::_map ( )
1786 {
1787    unsigned long valuemask;
1788    XGCValues   values;
1789    Pixel fg;
1790    Pixel bg;
1791    int   depth;
1792 
1793 // Call the base-class
1794 
1795    _XsMotifComponent::_map ( );
1796 
1797 // Get the icon pixels
1798 
1799    XtVaGetValues (_win->base ( ), XmNdepth, &depth, XmNbackground, &bg,
1800       XmNforeground, &fg, NULL);
1801 
1802 // Create the default icon pixmap
1803 
1804    if (_pixmap == 0)
1805    {
1806       _pixmap = XCreatePixmapFromBitmapData (XtDisplay (_base), XtWindow (_base),
1807          xs_motif_icon_bits, xs_motif_icon_width, xs_motif_icon_height,
1808          fg, bg, depth);
1809 
1810 // Set this pixmap
1811 
1812       setPixmap (_pixmap);
1813 
1814       _freePixmap = True;
1815 
1816 // Create the icon pixmap graphics context
1817 
1818       valuemask = GCGraphicsExposures | GCForeground | GCBackground;
1819 
1820       values.graphics_exposures = False;
1821       values.foreground = fg;
1822       values.background = bg;
1823 
1824       _pixmapGC = XtGetGC (_base, valuemask, &values);
1825    }
1826 
1827 // Create the font graphics context
1828 
1829    valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
1830 
1831    values.foreground = fg;
1832    values.background = bg;
1833    values.font = _iconFont->fid;
1834    values.graphics_exposures = False;
1835 
1836    _fontGC = XtGetGC (_base, valuemask, &values);
1837 }
1838 
1839 /*
1840    ----------------------------------------------------------------------------
1841    _XsMotifMenu
1842 */
1843 
1844 // Static definitions
1845 
1846 int _XsMotifMenu::_count = 0;
1847 Cursor _XsMotifMenu::_cursor = None;
1848 Pixmap _XsMotifMenu::_stipple = None;
1849 Display *_XsMotifMenu::_dpy = 0;
1850 
1851 // Resources
1852 
1853 XtResource _XsMotifMenu::_resourceList[] = {
1854    {
1855       "saveUnder",
1856       "SaveUnder",
1857       XmRBoolean,
1858       sizeof (Boolean),
1859       XtOffset (_XsMotifMenu*, _saveUnder),
1860       XmRImmediate,
1861       (XtPointer)True
1862    },
1863    {
1864       "restoreString",
1865       "RestoreString",
1866       XmRString,
1867       sizeof (String),
1868       XtOffset (_XsMotifMenu*, _strings[Restore]),
1869       XmRString,
1870       "Restore"
1871    },
1872    {
1873       "moveString",
1874       "MoveString",
1875       XmRString,
1876       sizeof (String),
1877       XtOffset (_XsMotifMenu*, _strings[Move]),
1878       XmRString,
1879       "Move"
1880    },
1881    {
1882       "sizeString",
1883       "SizeString",
1884       XmRString,
1885       sizeof (String),
1886       XtOffset (_XsMotifMenu*, _strings[Size]),
1887       XmRString,
1888       "Size"
1889    },
1890    {
1891       "minimizeString",
1892       "MinimizeString",
1893       XmRString,
1894       sizeof (String),
1895       XtOffset (_XsMotifMenu*, _strings[Minimize]),
1896       XmRString,
1897       "Minimize"
1898    },
1899    {
1900       "maximizeString",
1901       "MaximizeString",
1902       XmRString,
1903       sizeof (String),
1904       XtOffset (_XsMotifMenu*, _strings[Maximize]),
1905       XmRString,
1906       "Maximize"
1907    },
1908    {
1909       "raiseString",
1910       "RaiseString",
1911       XmRString,
1912       sizeof (String),
1913       XtOffset (_XsMotifMenu*, _strings[Raise]),
1914       XmRString,
1915       "Raise"
1916    },
1917    {
1918       "lowerString",
1919       "LowerString",
1920       XmRString,
1921       sizeof (String),
1922       XtOffset (_XsMotifMenu*, _strings[Lower]),
1923       XmRString,
1924       "Lower"
1925    },
1926    {
1927       "closeString",
1928       "CloseString",
1929       XmRString,
1930       sizeof (String),
1931       XtOffset (_XsMotifMenu*, _strings[Close]),
1932       XmRString,
1933       "Close"
1934    },
1935    {
1936       "menuFont",
1937       "menuFont",
1938       XmRFontStruct,
1939       sizeof (XFontStruct*),
1940       XtOffset (_XsMotifMenu*, _menuFont),
1941       XmRString,
1942       "-*-helvetica-bold-o-normal-*-14-*-*-*-*-*-iso8859-1"
1943    }
1944 };
1945 
1946 // Constructor
1947 
_XsMotifMenu(const char * name,XsMotifWindow * win)1948 _XsMotifMenu::_XsMotifMenu (const char *name, XsMotifWindow *win) :
1949    _XsMotifBase (name, win)
1950 {
1951 
1952 // Create the cursor (if necessary)
1953 
1954    if (_count++ == 0)
1955    {
1956 
1957 // Create the menu cursor
1958 
1959       _cursor = XCreateFontCursor (XtDisplay (win->base ( )), XC_arrow);
1960 
1961 // Create a stippled pixmap
1962 
1963       Widget   parent = _win->base ( );
1964       Pixel    foreground;
1965       Pixel    background;
1966       int      depth;
1967 
1968       XtVaGetValues (parent, XmNforeground, &foreground, XmNbackground,
1969          &background, XmNdepth, &depth, NULL);
1970 
1971       const int pixmapWidth = 2;
1972       const int pixmapHeight = 2;
1973       static unsigned char pixmapBits[] = { 0x02, 0x01 };
1974 
1975       _dpy = XtDisplay (parent);
1976       _stipple = XCreatePixmapFromBitmapData (_dpy, DefaultRootWindow (_dpy),
1977          (char*)pixmapBits, pixmapWidth, pixmapHeight, foreground, background,
1978          depth);
1979    }
1980 
1981 // Initialize
1982 
1983    _fontGC = 0;
1984    _grayGC = 0;
1985    _backgroundGC = 0;
1986 
1987 // Create the component (why doesn't overrideShell work?)
1988 
1989    _base = XtVaCreatePopupShell (_name, topLevelShellWidgetClass,
1990       XtParent (_win->base ( )), XmNoverrideRedirect, True,
1991       XmNborderWidth, 1, NULL);
1992 
1993 // Install destroy handler
1994 
1995    _installDestroyHandler ( );
1996 
1997 // Install event handler ('cause we never call _XsMotifBase::show)
1998 
1999    XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
2000 
2001 // Get resources
2002 
2003    _getResources (_resourceList, XtNumber (_resourceList));
2004 
2005 // Get the background color
2006 
2007    Pixel bg;
2008 
2009    XtVaGetValues (_win->base ( ), XmNbackground, &bg, NULL);
2010 
2011 // Compute the size of the (largest) menu item
2012 
2013    int   textHeight = _menuFont->ascent + _menuFont->descent;
2014    int   textWidth = 0;
2015    int   tmp;
2016 
2017    for (int loop = 0; loop < Num; loop++)
2018    {
2019       tmp = XTextWidth (_menuFont, _strings[loop], strlen (_strings[loop]));
2020 
2021       if (tmp > textWidth)
2022          textWidth = tmp;
2023    }
2024 
2025 // Put a border around the buttons
2026 
2027    textWidth += (2 * HorizTextOffset);
2028    textHeight += (2 * VertTextOffset);
2029 
2030 /*
2031    The menu height is the menu-shadow (1 pixel on top and bottom) + the
2032    items themselves.
2033 */
2034 
2035    int   menuHeight = (2 * ShadowThickness) +   // Top and bottom shadow
2036                       (textHeight * Num);       // The menu items
2037 
2038 /*
2039    The menu width is the menu-shadow (1 pixel on the left and right) +
2040    the largest menu text (calculated above)
2041 */
2042 
2043    int   menuWidth = (2 * ShadowThickness) +    // Left and right shadow
2044                      textWidth;                 // Largest text item
2045 
2046 // Configure the popup
2047 
2048    XtVaSetValues (_base, XmNsaveUnder, _saveUnder, XmNwidth, menuWidth,
2049       XmNheight, menuHeight, NULL);
2050 }
2051 
2052 // Destructor
2053 
~_XsMotifMenu()2054 _XsMotifMenu::~_XsMotifMenu ( )
2055 {
2056    if (_fontGC)
2057       XtReleaseGC (_base, _fontGC);
2058 
2059    if (_grayGC)
2060       XtReleaseGC (_base, _grayGC);
2061 
2062    if (_backgroundGC)
2063       XtReleaseGC (_base, _backgroundGC);
2064 
2065 // Free the pixmap (if necessary)
2066 
2067    if (--_count == 0)
2068       XFreePixmap (_dpy, _stipple);
2069 }
2070 
2071 // popup
2072 
popup(Boolean atPointer)2073 void _XsMotifMenu::popup (Boolean atPointer)
2074 {
2075    assert (_base != 0);
2076 
2077    Position x, y;
2078 
2079 // Compute the location of the menu.
2080 
2081    if (atPointer)
2082    {
2083       unsigned int mask;
2084       Window   win;
2085       int      winX, winY;
2086       int      rootX, rootY;
2087 
2088 // Menu at pointer location
2089 
2090       XQueryPointer (XtDisplay (_base), XtWindow (XtParent (_base)),
2091          &win, &win, &rootX, &rootY, &winX, &winY, &mask);
2092 
2093       x = (Position)rootX;
2094       y = (Position)rootY;
2095    }
2096    else
2097    {
2098 
2099 // Menu at top-left corner of client area
2100 
2101       XtTranslateCoords (_win->clientArea ( ), 0, 0, &x, &y);
2102    }
2103 
2104 // Move the menu
2105 
2106    XtVaSetValues (_base, XmNx, x, XmNy, y, NULL);
2107 
2108 // Initialize the item
2109 
2110    _curItem = NoItem;
2111 
2112 // Pop it up
2113 
2114    XtPopup (_base, XtGrabNone);
2115 
2116 // Grab the pointer
2117 
2118    if (_grabPointer ( ) == FALSE)
2119       return;
2120 
2121 // Update the menu
2122 
2123    _processEvents ( );
2124 
2125 // Pop the menu down
2126 
2127    XtPopdown (_base);
2128 
2129 // Ungrab the pointer
2130 
2131    _ungrabPointer ( );
2132 
2133    if (_curItem != NoItem)
2134    {
2135 
2136 /*
2137    Post a work-proc to process this item.  This will allow everything
2138    to get caught up before we process the menu item
2139 */
2140 
2141       XtAppContext appContext = XtWidgetToApplicationContext (_base);
2142       XtAppAddWorkProc (appContext, _workProc, (XtPointer)this);
2143    }
2144 }
2145 
2146 // className
2147 
className()2148 const char *_XsMotifMenu::className ( ) const
2149 {
2150    return ("_XsMotifMenu");
2151 }
2152 
2153 // _componentDestroyed
2154 
_componentDestroyed()2155 void _XsMotifMenu::_componentDestroyed ( )
2156 {
2157 
2158 // Clean up the GCs
2159 
2160    if (_fontGC)
2161       XtReleaseGC (_base, _fontGC);
2162 
2163    if (_grayGC)
2164       XtReleaseGC (_base, _grayGC);
2165 
2166    if (_backgroundGC)
2167       XtReleaseGC (_base, _backgroundGC);
2168 
2169    _fontGC = 0;
2170    _grayGC = 0;
2171    _backgroundGC = 0;
2172 
2173 // Call the base-class
2174 
2175    _XsMotifBase::_componentDestroyed ( );
2176 }
2177 
2178 // _processEvents
2179 
_processEvents()2180 void _XsMotifMenu::_processEvents ( )
2181 {
2182    assert (_base != 0);
2183 
2184    XtAppContext appContext = XtWidgetToApplicationContext (_base);
2185    XEvent event;
2186    Display *dpy = XtDisplay (_base);
2187    int   done = 0;
2188 
2189    while (!done)
2190    {
2191       XtAppNextEvent (appContext, &event);
2192 
2193 // Process this event
2194 
2195       switch (event.type)
2196       {
2197          case ButtonRelease:
2198          {
2199             done = 1;
2200             break;
2201          }
2202          case Expose:
2203          {
2204             _redrawMenu ( );
2205             break;
2206          }
2207          case MotionNotify:
2208          {
2209             XEvent next;
2210 
2211 // Process only the last motion event
2212 
2213             while (XPending (dpy) > 0)
2214             {
2215                XPeekEvent (dpy, &next);
2216                if (next.type != MotionNotify)
2217                   break;
2218                XtAppNextEvent (appContext, &event);
2219             }
2220 
2221 // Track the mouse and toggle the menu items
2222 
2223             Item item = _trackPointer ((XMotionEvent*)&event);
2224 
2225 // Unselect the current item (if the item is different)
2226 
2227             if (item != _curItem)
2228             {
2229                _toggleItem (_curItem, False);
2230 
2231 // Select the new item
2232 
2233                _toggleItem ((_curItem = item), True);
2234             }
2235 
2236             break;
2237          }
2238          default:
2239          {
2240             XtDispatchEvent (&event);
2241             break;
2242          }
2243       }
2244    }
2245 }
2246 
2247 // _processItem
2248 
_processItem(Item item)2249 void _XsMotifMenu::_processItem (Item item)
2250 {
2251    if (item == NoItem)
2252       return;
2253 
2254    switch (item)
2255    {
2256       case Restore:
2257       {
2258          _win->restore ( );
2259          break;
2260       }
2261       case Move:
2262       {
2263          Widget base = (_win->minimized ( )) ? _win->icon ( ) : _win->base ( );
2264 
2265 // Warp the pointer to the center of the window
2266 
2267          Dimension width, height;
2268          XtVaGetValues (base, XmNwidth, &width, XmNheight, &height, NULL);
2269 
2270          XWarpPointer (XtDisplay (_base), None, XtWindow (base), 0, 0, 0, 0,
2271             (width / 2), (height / 2));
2272 
2273 // Move the window
2274 
2275          XsMoveOutline move (base);
2276 
2277 // Start the move
2278 
2279          if (move.go (True) != False)
2280          {
2281 
2282 // Relocate the window
2283 
2284             _win->setPosition (move.x ( ), move.y ( ));
2285          }
2286          break;
2287       }
2288       case Size:
2289       {
2290          Widget base = (_win->minimized ( )) ? _win->icon ( ) : _win->base ( );
2291 
2292 // Warp the pointer to the center of the window
2293 
2294          Dimension width, height;
2295          XtVaGetValues (base, XmNwidth, &width, XmNheight, &height, NULL);
2296 
2297          XWarpPointer (XtDisplay (_base), None, XtWindow (base), 0, 0, 0, 0,
2298             (width / 2), (height / 2));
2299 
2300 // Resize the window
2301 
2302          XsResizeOutline resize (_win->base ( ), XsResizeOutline::Undetermined);
2303          resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
2304 
2305 // Start the resize
2306 
2307          if (resize.go (True) != False)
2308          {
2309 
2310 // Relocate the window
2311 
2312             _win->setPosition (resize.x ( ), resize.y ( ));
2313             _win->setSize (resize.width ( ), resize.height ( ));
2314          }
2315          break;
2316       }
2317       case Minimize:
2318       {
2319          _win->minimize ( );
2320          break;
2321       }
2322       case Maximize:
2323       {
2324          _win->maximize ( );
2325          break;
2326       }
2327       case Raise:
2328       {
2329          _win->raise ( );
2330          break;
2331       }
2332       case Lower:
2333       {
2334          _win->lower ( );
2335          break;
2336       }
2337       case Close:
2338       {
2339          _win->close ( );
2340          break;
2341       }
2342       default:
2343          assert (0);
2344    }
2345 }
2346 
2347 // _redrawMenu
2348 
_redrawMenu()2349 void _XsMotifMenu::_redrawMenu ( )
2350 {
2351    Dimension   w, h;
2352 
2353 // Get the size of the menu
2354 
2355    XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
2356 
2357 // Draw a shadow around the menu
2358 
2359    _drawShadows (0, 0, w, h, ShadowThickness);
2360 
2361 // Cycle and draw all of the elements
2362 
2363    for (int loop = 0; loop < Num; loop++)
2364       _redrawItem ((Item)loop);
2365 }
2366 
2367 // _redrawItem
2368 
_redrawItem(Item item)2369 void _XsMotifMenu::_redrawItem (Item item)
2370 {
2371    if (item == NoItem)
2372       return;
2373 
2374    int   x = ShadowThickness + HorizTextOffset;
2375    int   y;
2376 
2377 /*
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
2380 */
2381 
2382    y = ShadowThickness +                           // Top shadow
2383        (item * ((VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent))) +
2384        (VertTextOffset + _menuFont->ascent);       // The item iteself
2385 
2386 // Figure out the graphics-context
2387 
2388    GC gc;
2389 
2390    if (_win->minimized ( ))
2391       gc = ((item == Size) || (item == Minimize)) ? _grayGC : _fontGC;
2392    else if (_win->maximized ( ))
2393       gc = (item == Maximize) ? _grayGC : _fontGC;
2394    else
2395       gc = (item == Restore) ? _grayGC : _fontGC;
2396 
2397 // Draw the string
2398 
2399    XDrawString (XtDisplay (_base), XtWindow (_base), gc, x, y,
2400       _strings[item], strlen (_strings[item]));
2401 }
2402 
2403 // _toggleItem
2404 
_toggleItem(Item item,Boolean active)2405 void _XsMotifMenu::_toggleItem (Item item, Boolean active)
2406 {
2407    if (item == NoItem)
2408       return;
2409 
2410 /*
2411    Either draw the background of the specified item in the active color
2412    or the standard background color
2413 */
2414 
2415    GC gc = (active) ? _topShadowGC : _backgroundGC;
2416 
2417 // Get the width of the menu
2418 
2419    Dimension menuWidth;
2420    XtVaGetValues (_base, XmNwidth, &menuWidth, NULL);
2421 
2422 // Compute the location and size of the rectangle
2423 
2424    int   x, y;
2425    unsigned int width, height;
2426 
2427    x = ShadowThickness;
2428    height = ((VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent));
2429    y = ShadowThickness + (item * height);
2430    width = menuWidth - (2 * ShadowThickness);
2431 
2432 // Draw the filled rectangle
2433 
2434    XFillRectangle (XtDisplay (_base), XtWindow (_base), gc, x, y, width, height);
2435 
2436 // Redraw the text
2437 
2438    _redrawItem (item);
2439 }
2440 
2441 // _trackPointer
2442 
_trackPointer(XMotionEvent * event)2443 _XsMotifMenu::Item _XsMotifMenu::_trackPointer (XMotionEvent *event)
2444 {
2445    assert (_base != 0);
2446 
2447    Dimension   menuWidth;
2448    Dimension   menuHeight;
2449    Position    x, y;
2450 
2451 // Get the menu size and position
2452 
2453    XtVaGetValues (_base, XmNwidth, &menuWidth, XmNheight, &menuHeight,
2454       XmNx, &x, XmNy, &y, NULL);
2455 
2456 // Make sure the pointer is in the menu
2457 
2458    if ((event->x_root < x) || (event->x_root > (x + menuWidth)))
2459       return (NoItem);
2460 
2461    if ((event->y_root < y) || (event->y_root > (y + menuHeight)))
2462       return (NoItem);
2463 
2464 // Make sure the pointer is on the confines of the shadow
2465 
2466    if ((event->x < ShadowThickness) || (event->x > (menuWidth - (2 * ShadowThickness))))
2467       return (NoItem);
2468 
2469    if ((event->y < ShadowThickness) || (event->y > (menuHeight - (2 * ShadowThickness))))
2470       return (NoItem);
2471 
2472 /*
2473    Now we are just concerned with the y-position.  Subtract off the
2474    shadow thickness to normalize the location
2475 */
2476 
2477    int   yPos = event->y - ShadowThickness;
2478 
2479 // Compute which item the mouse is in
2480 
2481    int itemHeight = (VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent);
2482 
2483    Item item = (Item)(yPos / itemHeight);
2484 
2485 // Validate that the item is not grayed-out
2486 
2487    if (_win->minimized ( ))
2488    {
2489       if ((item == Size) || (item == Minimize))
2490          item = NoItem;
2491    }
2492    else if (_win->maximized ( ))
2493    {
2494       if (item == Maximize)
2495          item = NoItem;
2496    }
2497    else if (item == Restore)
2498       item = NoItem;
2499 
2500    return (item);
2501 }
2502 
2503 // _grabPointer
2504 
_grabPointer()2505 Boolean _XsMotifMenu::_grabPointer ( )
2506 {
2507 
2508 // Sync everything up before being grabby
2509 
2510    XSync (XtDisplay (_base), False);
2511 
2512 // Grab the pointer
2513 
2514    if (XGrabPointer (XtDisplay (_base), XtWindow (_base), False,
2515       (unsigned int)(ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
2516       EnterWindowMask | LeaveWindowMask), GrabModeAsync,
2517       GrabModeAsync, None, _cursor, CurrentTime) != GrabSuccess)
2518    {
2519       XBell (XtDisplay (_base), 100);
2520       return (False);
2521    }
2522 
2523    return (True);
2524 }
2525 
2526 // _ungrabPointer
2527 
_ungrabPointer()2528 void _XsMotifMenu::_ungrabPointer ( )
2529 {
2530 
2531 // Ungrab the pointer
2532 
2533    XUngrabPointer (XtDisplay (_base), CurrentTime);
2534 
2535 // Sync everything back up
2536 
2537    XSync (XtDisplay (_base), False);
2538 }
2539 
2540 // _map
2541 
_map()2542 void _XsMotifMenu::_map ( )
2543 {
2544 
2545 // Call the base-class
2546 
2547    _XsMotifBase::_map ( );
2548 
2549    unsigned long valuemask;
2550    XGCValues   values;
2551    Pixel foreground;
2552    Pixel background;
2553 
2554 // Get the pixels
2555 
2556    XtVaGetValues (XtParent (_base), XmNforeground, &foreground, NULL);
2557    XtVaGetValues (_base, XmNbackground, &background, NULL);
2558 
2559 // Create the font graphics context
2560 
2561    valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
2562 
2563    values.foreground = foreground;
2564    values.background = background;
2565    values.font = _menuFont->fid;
2566    values.graphics_exposures = False;
2567 
2568    _fontGC = XtGetGC (_base, valuemask, &values);
2569 
2570 // Create the insensitive font graphics context
2571 
2572    valuemask |= (GCFillStyle | GCTile);
2573 
2574    values.fill_style = FillTiled;
2575    values.tile = _stipple;
2576 
2577    _grayGC = XtGetGC (_base, valuemask, &values);
2578 
2579 // Create the background contexts
2580 
2581    valuemask = GCForeground | GCLineWidth | GCGraphicsExposures;
2582    values.line_width = 0;
2583    values.graphics_exposures = False;
2584    values.foreground = background;
2585 
2586    _backgroundGC = XtGetGC (_base, valuemask, &values);
2587 }
2588 
2589 // _workProc
2590 
_workProc(XtPointer clientData)2591 Boolean _XsMotifMenu::_workProc (XtPointer clientData)
2592 {
2593    _XsMotifMenu *obj = (_XsMotifMenu*)clientData;
2594    if (obj->_curItem != NoItem)
2595       obj->_processItem (obj->_curItem);
2596 
2597    return (True);
2598 }
2599 
2600 /*
2601    ----------------------------------------------------------------------------
2602    XsMotifWindow
2603 */
2604 
2605 // Static definitions
2606 
2607 XtResource XsMotifWindow::_resourceList[] = {
2608    {
2609       "showBorder",
2610       "ShowBorder",
2611       XmRBoolean,
2612       sizeof (Boolean),
2613       XtOffset (XsMotifWindow*, _showBorder),
2614       XmRImmediate,
2615       (XtPointer)True
2616    },
2617    {
2618       "showResize",
2619       "ShowResize",
2620       XmRBoolean,
2621       sizeof (Boolean),
2622       XtOffset (XsMotifWindow*, _showResize),
2623       XmRImmediate,
2624       (XtPointer)True
2625    },
2626    {
2627       "showTitle",
2628       "ShowTitle",
2629       XmRBoolean,
2630       sizeof (Boolean),
2631       XtOffset (XsMotifWindow*, _showTitle),
2632       XmRImmediate,
2633       (XtPointer)True
2634    },
2635    {
2636       "showMenu",
2637       "ShowMenu",
2638       XmRBoolean,
2639       sizeof (Boolean),
2640       XtOffset (XsMotifWindow*, _showMenu),
2641       XmRImmediate,
2642       (XtPointer)True
2643    },
2644    {
2645       "showMinimize",
2646       "ShowMinimize",
2647       XmRBoolean,
2648       sizeof (Boolean),
2649       XtOffset (XsMotifWindow*, _showMinimize),
2650       XmRImmediate,
2651       (XtPointer)True
2652    },
2653    {
2654       "showMaximize",
2655       "ShowMaximize",
2656       XmRBoolean,
2657       sizeof (Boolean),
2658       XtOffset (XsMotifWindow*, _showMaximize),
2659       XmRImmediate,
2660       (XtPointer)True
2661    },
2662    {
2663       "lowerOnIconify",
2664       "LowerOnIconify",
2665       XmRBoolean,
2666       sizeof (Boolean),
2667       XtOffset (XsMotifWindow*, _lowerOnIconify),
2668       XmRImmediate,
2669       (XtPointer)False
2670    },
2671    {
2672       XmNminWidth,
2673       XmCMinWidth,
2674       XmRDimension,
2675       sizeof (Dimension),
2676       XtOffset (XsMotifWindow*, _minW),
2677       XmRImmediate,
2678       (XtPointer)((BorderSize_ + ButtonSize_) * 3)
2679    },
2680    {
2681       XmNmaxWidth,
2682       XmCMaxWidth,
2683       XmRDimension,
2684       sizeof (Dimension),
2685       XtOffset (XsMotifWindow*, _maxW),
2686       XmRImmediate,
2687       (XtPointer)-1
2688    },
2689    {
2690       XmNminHeight,
2691       XmCMinHeight,
2692       XmRDimension,
2693       sizeof (Dimension),
2694       XtOffset (XsMotifWindow*, _minH),
2695       XmRImmediate,
2696       (XtPointer)((BorderSize_ + ButtonSize_) * 3)
2697    },
2698    {
2699       XmNmaxHeight,
2700       XmCMaxHeight,
2701       XmRDimension,
2702       sizeof (Dimension),
2703       XtOffset (XsMotifWindow*, _maxH),
2704       XmRImmediate,
2705       (XtPointer)-1
2706    }
2707 };
2708 
2709 // Constructor
2710 
XsMotifWindow(const char * name)2711 XsMotifWindow::XsMotifWindow (const char *name) : XsMDIWindow (name)
2712 {
2713    int   loop;
2714 
2715 // Initialize
2716 
2717    for (loop = 0; loop < _XsMotifSide::Max; loop++)
2718    {
2719       _corners[loop] = 0;
2720       _sides[loop] = 0;
2721    }
2722 
2723    for (loop = 0; loop < _XsMotifButton::Max; loop++)
2724       _buttons[loop] = 0;
2725 
2726    _title = 0;
2727    _icon = 0;
2728    _menu = 0;
2729 
2730    _maximized = False;
2731    _minimized = False;
2732 }
2733 
2734 // Destructor
2735 
~XsMotifWindow()2736 XsMotifWindow::~XsMotifWindow ( )
2737 {
2738    int   loop;
2739 
2740    for (loop = 0; loop < _XsMotifSide::Max; loop++)
2741    {
2742       delete _corners[loop];
2743       delete _sides[loop];
2744    }
2745 
2746    for (loop = 0; loop < _XsMotifButton::Max; loop++)
2747       delete _buttons[loop];
2748 
2749    delete _title;
2750    delete _icon;
2751    delete _menu;
2752 }
2753 
2754 // raise
2755 
raise()2756 void XsMotifWindow::raise ( )
2757 {
2758    Widget w = (_minimized == True) ? _icon->base ( ) : _base;
2759    assert (w != 0);
2760    XRaiseWindow (XtDisplay (w), XtWindow (w));
2761 }
2762 
2763 // lower
2764 
lower()2765 void XsMotifWindow::lower ( )
2766 {
2767    Widget w = (_minimized == True) ? _icon->base ( ) : _base;
2768    assert (w != 0);
2769    XLowerWindow (XtDisplay (w), XtWindow (w));
2770 }
2771 
2772 // minimize
2773 
minimize()2774 void XsMotifWindow::minimize ( )
2775 {
2776    assert (_base != 0);
2777 
2778 // Check if we are already minimized
2779 
2780    if (_minimized == True)
2781       return;
2782 
2783 // Minimize the window
2784 
2785    hide ( );
2786 
2787    _minimized = True;
2788 
2789 // Lower (if necessary)
2790 
2791    if (_lowerOnIconify)
2792       lower ( );
2793 
2794    _icon->show ( );
2795 }
2796 
2797 // maximize
2798 
maximize()2799 void XsMotifWindow::maximize ( )
2800 {
2801    assert (_base != 0);
2802 
2803 // Check if we are already in this state
2804 
2805    if (_maximized == True)
2806       return;
2807 
2808 // Restore (if necessary)
2809 
2810    if (_minimized)
2811       restore ( );
2812 
2813 // Save current dimensions
2814 
2815    XtVaGetValues (_base, XmNx, &_savedX, XmNy, &_savedY, XmNwidth,
2816       &_savedWidth, XmNheight, &_savedHeight, NULL);
2817 
2818 /*
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.
2821 */
2822 
2823    const Dimension offset = 5;      // Border around max'd window
2824 
2825    Widget clipWindow = XtParent (XtParent (_base));
2826    assert (clipWindow != 0);
2827    Dimension   clipW, clipH;
2828    Window      child;
2829    int         newX, newY;
2830 
2831    XtVaGetValues (clipWindow, XmNheight, &clipH, XmNwidth, &clipW, NULL);
2832 
2833 // Add in offset
2834 
2835    if (clipW > (offset * 2))
2836       clipW -= (offset * 2);
2837 
2838    if (clipH > (offset * 2))
2839       clipH -= (offset * 2);
2840 
2841 // Compute the new window position (map clip-window to work-area)
2842 
2843    XTranslateCoordinates (XtDisplay (_base), XtWindow (clipWindow),
2844       XtWindow (XtParent (_base)), (int)offset, (int)offset,
2845       &newX, &newY, &child);
2846 
2847 // Set new maximum dimensions
2848 
2849    setPosition ((Position)newX, (Position)newY);
2850    setSize (clipW, clipH);
2851 
2852    _maximized = True;
2853 
2854 // Redraw the maximize button
2855 
2856    _buttons[_XsMotifButton::Maximize]->redraw ( );
2857 }
2858 
2859 // restore
2860 
restore()2861 void XsMotifWindow::restore ( )
2862 {
2863    assert (_base != 0);
2864 
2865 // Check if we are already restored
2866 
2867    if ((_maximized == False) && (_minimized == False))
2868       return;
2869 
2870 // Either un-minimize or un-maximize
2871 
2872    if (_minimized)
2873    {
2874 
2875 // Restore the window
2876 
2877       _icon->hide ( );
2878       _minimized = False;
2879 
2880 // If maximized, restore again
2881 
2882       if (_maximized)
2883          restore ( );
2884 
2885 // Show the window
2886 
2887       show ( );
2888    }
2889    else
2890    {
2891 
2892 // Restore saved dimensions
2893 
2894       setPosition (_savedX, _savedY);
2895       setSize (_savedWidth, _savedHeight);
2896    }
2897 }
2898 
2899 // close
2900 
close()2901 void XsMotifWindow::close ( )
2902 {
2903 
2904 /*
2905    Don't delete the window (because its not ours to delete).
2906    Just hide it.
2907 */
2908 
2909    if (_minimized)
2910       _icon->hide ( );
2911    else
2912       hide ( );
2913 }
2914 
2915 // setTitle
2916 
setTitle(const char * title)2917 void XsMotifWindow::setTitle (const char *title)
2918 {
2919    if (_title != 0)
2920       _title->setTitle (title);
2921 }
2922 
2923 // setIconName
2924 
setIconName(const char * iconName)2925 void XsMotifWindow::setIconName (const char *iconName)
2926 {
2927    if (_icon != 0)
2928       _icon->setIconName (iconName);
2929 }
2930 
2931 // setPixmap
2932 
setPixmap(Pixmap pixmap)2933 void XsMotifWindow::setPixmap (Pixmap pixmap)
2934 {
2935    if (_icon != 0)
2936       _icon->setPixmap (pixmap);
2937 }
2938 
2939 // popupMenu
2940 
popupMenu(Boolean b)2941 void XsMotifWindow::popupMenu (Boolean b)
2942 {
2943    if (_menu != 0)
2944       _menu->popup (b);
2945 }
2946 
2947 // setPosition
2948 
setPosition(Position x,Position y)2949 void XsMotifWindow::setPosition (Position x, Position y)
2950 {
2951    if (_base != 0)
2952    {
2953       Widget w = (_minimized == True) ? _icon->base ( ) : _base;
2954       assert (w != 0);
2955       XtVaSetValues (w, XmNx, x, XmNy, y, NULL);
2956    }
2957    else
2958       XsMDIWindow::setPosition (x, y);    // Cache the points
2959 }
2960 
2961 // setSize
2962 
setSize(Dimension w,Dimension h)2963 void XsMotifWindow::setSize (Dimension w, Dimension h)
2964 {
2965 
2966 // Set the window size
2967 
2968    if (_base != 0)
2969    {
2970       if (w < _minW)
2971          w = _minW;
2972       else if ((_maxW != (Dimension)-1) && (w > _maxW))
2973          w = _maxW;
2974 
2975       if (h < _minH)
2976          h = _minH;
2977       else if ((_maxH != (Dimension)-1) && (h > _maxH))
2978          h = _maxH;
2979 
2980       if (_minimized == False)
2981          XtVaSetValues (_base, XmNwidth, w, XmNheight, h, NULL);
2982 
2983 // If window was maximized, change the window state back to normal
2984 
2985       if (_maximized == True)
2986       {
2987          _maximized = False;
2988 
2989 // Redraw the maximize button
2990 
2991          _buttons[_XsMotifButton::Maximize]->redraw ( );
2992       }
2993    }
2994    else
2995       XsMDIWindow::setSize (w, h);     // Cache the points
2996 }
2997 
2998 // className
2999 
className()3000 const char* XsMotifWindow::className ( ) const
3001 {
3002    return ("XsMotifWindow");
3003 }
3004 
3005 // _createWindow
3006 
_createWindow(Widget parent)3007 void XsMotifWindow::_createWindow (Widget parent)
3008 {
3009    assert (parent != 0);
3010 
3011 // Create the window frame
3012 
3013    _base = XtVaCreateWidget (_name, xmFormWidgetClass, parent,
3014       XmNborderWidth, (Dimension)1, NULL);
3015 
3016 // Install destroy handler
3017 
3018    _installDestroyHandler ( );
3019 
3020 // Get resources
3021 
3022    _getResources (_resourceList, XtNumber (_resourceList));
3023 
3024 /*
3025    Fix configuration inter-dependencies.  Here are the rules:
3026 
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)
3029 */
3030 
3031    if (_showBorder == False)
3032       _showResize = False;
3033 
3034    if (_showTitle == False)
3035    {
3036       _showMenu = False;
3037       _showMinimize = False;
3038       _showMaximize = False;
3039    }
3040 
3041 /*
3042    Corners
3043 */
3044 
3045    if (_showResize)
3046    {
3047 
3048 // Top-Left
3049 
3050       _corners[_XsMotifCorner::TopLeft] = new _XsMotifCorner ("topLeft", this, _XsMotifCorner::TopLeft);
3051 
3052       XtVaSetValues (_corners[_XsMotifCorner::TopLeft]->base ( ), XmNtopAttachment,
3053          XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment,
3054          XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
3055 
3056 // Top-Right
3057 
3058       _corners[_XsMotifCorner::TopRight] = new _XsMotifCorner ("topRight", this, _XsMotifCorner::TopRight);
3059 
3060       XtVaSetValues (_corners[_XsMotifCorner::TopRight]->base ( ), XmNtopAttachment,
3061          XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment,
3062          XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
3063 
3064 // Bottom-Left
3065 
3066       _corners[_XsMotifCorner::BottomLeft] = new _XsMotifCorner ("bottomLeft", this, _XsMotifCorner::BottomLeft);
3067 
3068       XtVaSetValues (_corners[_XsMotifCorner::BottomLeft]->base ( ), XmNtopAttachment,
3069          XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
3070          XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
3071 
3072 // Bottom-Right
3073 
3074       _corners[_XsMotifCorner::BottomRight] = new _XsMotifCorner ("bottomRight", this, _XsMotifCorner::BottomRight);
3075 
3076       XtVaSetValues (_corners[_XsMotifCorner::BottomRight]->base ( ), XmNtopAttachment,
3077          XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
3078          XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
3079    }
3080 
3081 /*
3082    Sides
3083 */
3084 
3085    if (_showBorder)
3086    {
3087 
3088 // Top
3089 
3090       _sides[_XsMotifSide::Top] = new _XsMotifSide ("top", this, _XsMotifSide::Top);
3091 
3092       XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ),  XmNtopAttachment,
3093          XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, NULL);
3094 
3095       if (_showResize)
3096       {
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);
3101       }
3102       else
3103       {
3104          XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ), XmNleftAttachment,
3105             XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
3106       }
3107 
3108 // Bottom
3109 
3110       _sides[_XsMotifSide::Bottom] = new _XsMotifSide ("bottom", this, _XsMotifSide::Bottom);
3111 
3112       XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNtopAttachment,
3113          XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, NULL);
3114 
3115       if (_showResize)
3116       {
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);
3121       }
3122       else
3123       {
3124          XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNleftAttachment,
3125             XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
3126       }
3127 
3128 // Left side
3129 
3130       _sides[_XsMotifSide::Left] = new _XsMotifSide ("left", this, _XsMotifSide::Left);
3131 
3132       XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNleftAttachment,
3133          XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
3134 
3135       if (_showResize)
3136       {
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);
3141       }
3142       else
3143       {
3144          XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNtopAttachment,
3145             XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL);
3146       }
3147 
3148 // Right side
3149 
3150       _sides[_XsMotifSide::Right] = new _XsMotifSide ("right", this, _XsMotifSide::Right);
3151 
3152       XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNleftAttachment,
3153          XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
3154 
3155       if (_showResize)
3156       {
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);
3161       }
3162       else
3163       {
3164          XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNtopAttachment,
3165             XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL);
3166       }
3167    }
3168 
3169 // Menu button
3170 
3171    if (_showMenu)
3172    {
3173       _buttons[_XsMotifButton::Menu] = new _XsMotifButton ("menu", this, _XsMotifButton::Menu);
3174 
3175       XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNbottomAttachment,
3176          XmATTACH_NONE, XmNrightAttachment, XmATTACH_NONE, NULL);
3177 
3178       if (_showBorder)
3179       {
3180          XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNleftAttachment,
3181             XmATTACH_WIDGET, XmNleftWidget, _sides[_XsMotifSide::Left]->base ( ),
3182             XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
3183             NULL);
3184       }
3185       else
3186       {
3187          XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNleftAttachment,
3188             XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, NULL);
3189       }
3190    }
3191 
3192 // Maximize button
3193 
3194    if (_showMaximize)
3195    {
3196       _buttons[_XsMotifButton::Maximize] = new _XsMotifButton ("maximize", this, _XsMotifButton::Maximize);
3197 
3198       XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNbottomAttachment,
3199          XmATTACH_NONE, XmNleftAttachment, XmATTACH_NONE, NULL);
3200 
3201       if (_showBorder)
3202       {
3203          XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNtopAttachment,
3204             XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
3205             XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, _sides[_XsMotifSide::Right]->base ( ),
3206             NULL);
3207       }
3208       else
3209       {
3210          XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNtopAttachment,
3211             XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
3212       }
3213    }
3214 
3215 // Minimize button
3216 
3217    if (_showMinimize)
3218    {
3219       _buttons[_XsMotifButton::Minimize] = new _XsMotifButton ("minimize", this, _XsMotifButton::Minimize);
3220 
3221       XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
3222          XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_NONE,
3223          NULL);
3224 
3225       if (_showBorder)
3226       {
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);
3231       }
3232       else
3233       {
3234          XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
3235             XmNtopAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM,
3236             NULL);
3237       }
3238 
3239       if (_showMaximize)
3240       {
3241          XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
3242             XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
3243             _buttons[_XsMotifButton::Maximize]->base ( ), NULL);
3244       }
3245    }
3246 
3247 /*
3248    Titlebar
3249 */
3250 
3251    if (_showTitle)
3252    {
3253       _title = new _XsMotifTitle ("title", this);
3254 
3255       XtVaSetValues (_title->base ( ), XmNbottomAttachment, XmATTACH_NONE,
3256          NULL);
3257 
3258       if (_showBorder)
3259       {
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 ( ),
3265             NULL);
3266       }
3267       else
3268       {
3269          XtVaSetValues (_title->base ( ), XmNtopAttachment, XmATTACH_FORM,
3270             XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM,
3271             NULL);
3272       }
3273 
3274       if (_showMenu)
3275       {
3276          XtVaSetValues (_title->base ( ), XmNleftAttachment, XmATTACH_WIDGET,
3277             XmNleftWidget, _buttons[_XsMotifButton::Menu]->base ( ), NULL);
3278       }
3279 
3280       Widget ba = (_buttons[_XsMotifButton::Minimize] != 0) ?
3281          _buttons[_XsMotifButton::Minimize]->base ( ) :
3282          (_buttons[_XsMotifButton::Maximize] != 0) ?
3283          _buttons[_XsMotifButton::Maximize]->base ( ) : 0;
3284 
3285       if (ba)
3286       {
3287          XtVaSetValues (_title->base ( ), XmNrightAttachment, XmATTACH_WIDGET,
3288             XmNrightWidget, ba, NULL);
3289       }
3290    }
3291 
3292 /*
3293    Icon
3294 */
3295 
3296    _icon = new _XsMotifIcon ("icon", this, parent);
3297 
3298 /*
3299    Menu
3300 */
3301 
3302    _menu = new _XsMotifMenu ("menu", this);
3303 
3304 /*
3305    Client Area
3306 */
3307 
3308    _clientArea = XtVaCreateWidget ("clientArea", xmFormWidgetClass, _base, NULL);
3309 
3310    if (_showBorder)
3311    {
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);
3317    }
3318    else
3319    {
3320       XtVaSetValues (_clientArea, XmNleftAttachment, XmATTACH_FORM,
3321          XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM,
3322          NULL);
3323    }
3324 
3325    Widget topW = (_showTitle) ? _title->base ( ) :
3326                  (_showBorder) ? _sides[_XsMotifSide::Top]->base ( ) : 0;
3327 
3328    if (topW)
3329    {
3330       XtVaSetValues (_clientArea, XmNtopAttachment, XmATTACH_WIDGET,
3331          XmNtopWidget, topW, NULL);
3332    }
3333    else
3334       XtVaSetValues (_clientArea, XmNtopAttachment, XmATTACH_FORM, NULL);
3335 
3336 // Call the class function to create the contents of the window
3337 
3338    _buildClientArea (_clientArea);
3339 
3340 // Add an event handler to be called when this window is mapped
3341 
3342    XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
3343 
3344 // Show everything
3345 
3346    int   loop;
3347 
3348    for (loop = 0; loop < _XsMotifSide::Max; loop++)
3349    {
3350       if (_corners[loop] != 0)
3351          _corners[loop]->show ( );
3352       if (_sides[loop] != 0)
3353          _sides[loop]->show ( );
3354    }
3355 
3356    for (loop = 0; loop < _XsMotifButton::Max; loop++)
3357    {
3358       if (_buttons[loop] != 0)
3359          _buttons[loop]->show ( );
3360    }
3361 
3362    if (_title != 0)
3363       _title->show ( );
3364 }
3365 
3366 // _mapEvent
3367 
_mapEvent()3368 void XsMotifWindow::_mapEvent ( )
3369 {
3370 
3371 // Raise the client-area
3372 
3373    XRaiseWindow (XtDisplay (_clientArea), XtWindow (_clientArea));
3374 }
3375 
3376 // _mapEventHandler
3377 
_mapEventHandler(Widget,XtPointer clientData,XEvent * event,Boolean *)3378 void XsMotifWindow::_mapEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
3379 {
3380    if (event->type == MapNotify)
3381    {
3382       XsMotifWindow *obj = (XsMotifWindow*)clientData;
3383       obj->_mapEvent ( );
3384       XtRemoveEventHandler (obj->_base, StructureNotifyMask, False, obj->_mapEventHandler, clientData);
3385    }
3386 }
3387