]> git.saurik.com Git - wxWidgets.git/blob - src/motif/toolbar.cpp
Assert correction.
[wxWidgets.git] / src / motif / toolbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: motif/toolbar.cpp
3 // Purpose: wxToolBar
4 // Author: Julian Smart
5 // Modified by: 13.12.99 by VZ during toolbar classes reorganization
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "toolbar.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __VMS
28 #define XtDisplay XTDISPLAY
29 #endif
30
31 #include "wx/settings.h"
32 #include "wx/app.h"
33 #include "wx/timer.h"
34 #include "wx/toolbar.h"
35 #include "wx/frame.h"
36
37 #ifdef __VMS__
38 #pragma message disable nosimpint
39 #endif
40 #include <Xm/Xm.h>
41 #include <Xm/PushBG.h>
42 #include <Xm/PushB.h>
43 #include <Xm/Label.h>
44 #include <Xm/ToggleB.h>
45 #include <Xm/ToggleBG.h>
46 #include <Xm/Form.h>
47 #ifdef __VMS__
48 #pragma message enable nosimpint
49 #endif
50
51 #include "wx/motif/private.h"
52 #include "wx/motif/bmpmotif.h"
53
54 // ----------------------------------------------------------------------------
55 // wxWin macros
56 // ----------------------------------------------------------------------------
57
58 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
59
60 // ----------------------------------------------------------------------------
61 // private functions
62 // ----------------------------------------------------------------------------
63
64 static void wxToolButtonCallback (Widget w, XtPointer clientData,
65 XtPointer ptr);
66 static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
67 XEvent *event, Boolean *continue_to_dispatch);
68
69 // ----------------------------------------------------------------------------
70 // private classes
71 // ----------------------------------------------------------------------------
72
73 class wxToolBarTimer : public wxTimer
74 {
75 public:
76 virtual void Notify();
77
78 static Widget help_popup;
79 static Widget buttonWidget;
80 static wxString helpString;
81 };
82
83 class wxToolBarTool : public wxToolBarToolBase
84 {
85 public:
86 wxToolBarTool(wxToolBar *tbar,
87 int id,
88 const wxString& label,
89 const wxBitmap& bmpNormal,
90 const wxBitmap& bmpToggled,
91 wxItemKind kind,
92 wxObject *clientData,
93 const wxString& shortHelp,
94 const wxString& longHelp)
95 : wxToolBarToolBase(tbar, id, label, bmpNormal, bmpToggled, kind,
96 clientData, shortHelp, longHelp)
97 {
98 Init();
99 }
100
101 wxToolBarTool(wxToolBar *tbar, wxControl *control)
102 : wxToolBarToolBase(tbar, control)
103 {
104 Init();
105 }
106
107 virtual ~wxToolBarTool();
108
109 // accessors
110 void SetWidget(Widget widget) { m_widget = widget; }
111 Widget GetButtonWidget() const { return m_widget; }
112
113 Pixmap GetArmPixmap()
114 {
115 m_bitmapCache.SetBitmap( GetNormalBitmap() );
116 return (Pixmap)m_bitmapCache.GetArmPixmap( (WXWidget)m_widget );
117 }
118
119 Pixmap GetInsensPixmap()
120 {
121 m_bitmapCache.SetBitmap( GetNormalBitmap() );
122 return (Pixmap)m_bitmapCache.GetInsensPixmap( (WXWidget)m_widget );
123 }
124 protected:
125 void Init();
126
127 Widget m_widget;
128 wxBitmapCache m_bitmapCache;
129 };
130
131 // ----------------------------------------------------------------------------
132 // globals
133 // ----------------------------------------------------------------------------
134
135 static wxToolBarTimer* wxTheToolBarTimer = (wxToolBarTimer*) NULL;
136
137 Widget wxToolBarTimer::help_popup = (Widget) 0;
138 Widget wxToolBarTimer::buttonWidget = (Widget) 0;
139 wxString wxToolBarTimer::helpString;
140
141 // ============================================================================
142 // implementation
143 // ============================================================================
144
145 // ----------------------------------------------------------------------------
146 // wxToolBarTool
147 // ----------------------------------------------------------------------------
148
149 wxToolBarToolBase *wxToolBar::CreateTool(int id,
150 const wxString& label,
151 const wxBitmap& bmpNormal,
152 const wxBitmap& bmpToggled,
153 wxItemKind kind,
154 wxObject *clientData,
155 const wxString& shortHelp,
156 const wxString& longHelp)
157 {
158 return new wxToolBarTool(this, id, label, bmpNormal, bmpToggled, kind,
159 clientData, shortHelp, longHelp);
160 }
161
162
163 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
164 {
165 return new wxToolBarTool(this, control);
166 }
167
168 void wxToolBarTool::Init()
169 {
170 m_widget = (Widget)0;
171 }
172
173 wxToolBarTool::~wxToolBarTool()
174 {
175 if ( m_widget )
176 XtDestroyWidget(m_widget);
177 }
178
179 // ----------------------------------------------------------------------------
180 // wxToolBar construction
181 // ----------------------------------------------------------------------------
182
183 void wxToolBar::Init()
184 {
185 m_maxWidth = -1;
186 m_maxHeight = -1;
187 m_defaultWidth = 24;
188 m_defaultHeight = 22;
189 m_toolPacking = 2;
190 m_toolSeparation = 8;
191 m_xMargin = 2;
192 m_yMargin = 2;
193 m_maxRows = 100;
194 m_maxCols = 100;
195 }
196
197 bool wxToolBar::Create(wxWindow *parent,
198 wxWindowID id,
199 const wxPoint& pos,
200 const wxSize& size,
201 long style,
202 const wxString& name)
203 {
204 if( !wxControl::CreateControl( parent, id, pos, size, style,
205 wxDefaultValidator, name ) )
206 return false;
207
208 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
209
210 Widget parentWidget = (Widget) parent->GetClientWidget();
211
212 Widget toolbar = XtVaCreateManagedWidget("toolbar",
213 xmBulletinBoardWidgetClass, (Widget) parentWidget,
214 XmNmarginWidth, 0,
215 XmNmarginHeight, 0,
216 XmNresizePolicy, XmRESIZE_NONE,
217 NULL);
218 /*
219 Widget toolbar = XtVaCreateManagedWidget("toolbar",
220 xmFormWidgetClass, (Widget) m_clientWidget,
221 XmNtraversalOn, False,
222 XmNhorizontalSpacing, 0,
223 XmNverticalSpacing, 0,
224 XmNleftOffset, 0,
225 XmNrightOffset, 0,
226 XmNmarginWidth, 0,
227 XmNmarginHeight, 0,
228 NULL);
229 */
230
231 m_mainWidget = (WXWidget) toolbar;
232
233 ChangeFont(false);
234
235 wxPoint rPos = pos;
236 wxSize rSize = size;
237
238 if( rPos.x == -1 ) rPos.x = 0;
239 if( rPos.y == -1 ) rPos.y = 0;
240 if( rSize.x == -1 && GetParent() )
241 rSize.x = GetParent()->GetSize().x;
242
243 AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
244 rPos.x, rPos.y, rSize.x, rSize.y);
245
246 ChangeBackgroundColour();
247
248 return true;
249 }
250
251 wxToolBar::~wxToolBar()
252 {
253 delete wxTheToolBarTimer;
254 wxTheToolBarTimer = NULL;
255 }
256
257 bool wxToolBar::Realize()
258 {
259 if ( m_tools.GetCount() == 0 )
260 {
261 // nothing to do
262 return true;
263 }
264
265 bool isVertical = GetWindowStyle() & wxTB_VERTICAL;
266
267 // Separator spacing
268 const int separatorSize = GetToolSeparation(); // 8;
269 wxSize margins = GetToolMargins();
270 int packing = GetToolPacking();
271 int marginX = margins.x;
272 int marginY = margins.y;
273
274 int currentX = marginX;
275 int currentY = marginY;
276
277 int buttonHeight = 0, buttonWidth = 0;
278
279 int currentSpacing = 0;
280
281 Widget button;
282 Pixmap pixmap, insensPixmap;
283 wxBitmap bmp, insensBmp;
284
285 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
286 while ( node )
287 {
288 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
289
290 switch ( tool->GetStyle() )
291 {
292 case wxTOOL_STYLE_CONTROL:
293 {
294 wxControl* control = tool->GetControl();
295 wxSize sz = control->GetSize();
296 wxPoint pos = control->GetPosition();
297 // Allow a control to specify a y[x]-offset by setting
298 // its initial position, but still don't allow it to
299 // position itself above the top[left] margin.
300 int controlY = (pos.y > 0) ? pos.y : currentY;
301 int controlX = (pos.x > 0) ? pos.x : currentX;
302 control->Move( isVertical ? controlX : currentX,
303 isVertical ? currentY : controlY );
304 if ( isVertical )
305 currentY += sz.y + packing;
306 else
307 currentX += sz.x + packing;
308
309 break;
310 }
311 case wxTOOL_STYLE_SEPARATOR:
312 // skip separators for vertical toolbars
313 if( !isVertical )
314 {
315 currentX += separatorSize;
316 }
317 break;
318
319 case wxTOOL_STYLE_BUTTON:
320 button = (Widget) 0;
321
322 if ( tool->CanBeToggled() && !tool->GetButtonWidget() )
323 {
324 button = XtVaCreateWidget("toggleButton",
325 xmToggleButtonWidgetClass, (Widget) m_mainWidget,
326 XmNx, currentX, XmNy, currentY,
327 XmNindicatorOn, False,
328 XmNshadowThickness, 2,
329 XmNborderWidth, 0,
330 XmNspacing, 0,
331 XmNmarginWidth, 0,
332 XmNmarginHeight, 0,
333 XmNmultiClick, XmMULTICLICK_KEEP,
334 XmNlabelType, XmPIXMAP,
335 NULL);
336 XtAddCallback ((Widget) button,
337 XmNvalueChangedCallback,
338 (XtCallbackProc) wxToolButtonCallback,
339 (XtPointer) this);
340
341 XtVaSetValues ((Widget) button,
342 XmNselectColor,
343 m_backgroundColour.AllocColour
344 (XtDisplay((Widget) button)),
345 NULL);
346 }
347 else if( !tool->GetButtonWidget() )
348 {
349 button = XtVaCreateWidget("button",
350 xmPushButtonWidgetClass, (Widget) m_mainWidget,
351 XmNx, currentX, XmNy, currentY,
352 XmNpushButtonEnabled, True,
353 XmNmultiClick, XmMULTICLICK_KEEP,
354 XmNlabelType, XmPIXMAP,
355 NULL);
356 XtAddCallback (button,
357 XmNactivateCallback,
358 (XtCallbackProc) wxToolButtonCallback,
359 (XtPointer) this);
360 }
361
362 if( !tool->GetButtonWidget() )
363 {
364 wxDoChangeBackgroundColour((WXWidget) button,
365 m_backgroundColour, true);
366
367 tool->SetWidget(button);
368 }
369 else
370 {
371 button = (Widget)tool->GetButtonWidget();
372 XtVaSetValues( button,
373 XmNx, currentX, XmNy, currentY,
374 NULL );
375 }
376
377 // For each button, if there is a mask, we must create
378 // a new wxBitmap that has the correct background colour
379 // for the button. Otherwise the background will just be
380 // e.g. black if a transparent XPM has been loaded.
381 bmp = tool->GetNormalBitmap();
382 insensBmp = tool->GetDisabledBitmap();
383 if ( bmp.GetMask() || insensBmp.GetMask() )
384 {
385 int backgroundPixel;
386 XtVaGetValues(button, XmNbackground, &backgroundPixel,
387 NULL);
388
389 wxColour col;
390 col.SetPixel(backgroundPixel);
391
392 if( bmp.Ok() && bmp.GetMask() )
393 {
394 bmp = wxCreateMaskedBitmap(bmp, col);
395 tool->SetNormalBitmap(bmp);
396 }
397
398 if( insensBmp.Ok() && insensBmp.GetMask() )
399 {
400 insensBmp = wxCreateMaskedBitmap(insensBmp, col);
401 tool->SetDisabledBitmap(insensBmp);
402 }
403 }
404
405 // Create a selected/toggled bitmap. If there isn't a 2nd
406 // bitmap, we need to create it (with a darker, selected
407 // background)
408 int backgroundPixel;
409 if ( tool->CanBeToggled() )
410 XtVaGetValues(button, XmNselectColor, &backgroundPixel,
411 NULL);
412 else
413 XtVaGetValues(button, XmNarmColor, &backgroundPixel,
414 NULL);
415 wxColour col;
416 col.SetPixel(backgroundPixel);
417
418 pixmap = (Pixmap) bmp.GetDrawable();
419 {
420 wxBitmap tmp = tool->GetDisabledBitmap();
421
422 insensPixmap = tmp.Ok() ?
423 (Pixmap)tmp.GetDrawable() :
424 tool->GetInsensPixmap();
425 }
426
427 if (tool->CanBeToggled())
428 {
429 // Toggle button
430 Pixmap pixmap2 = tool->GetArmPixmap();
431 Pixmap insensPixmap2 = tool->GetInsensPixmap();
432
433 XtVaSetValues (button,
434 XmNfillOnSelect, True,
435 XmNlabelPixmap, pixmap,
436 XmNselectPixmap, pixmap2,
437 XmNlabelInsensitivePixmap, insensPixmap,
438 XmNselectInsensitivePixmap, insensPixmap2,
439 XmNlabelType, XmPIXMAP,
440 NULL);
441 }
442 else
443 {
444 Pixmap pixmap2 = tool->GetArmPixmap();
445
446 // Normal button
447 XtVaSetValues(button,
448 XmNlabelPixmap, pixmap,
449 XmNlabelInsensitivePixmap, insensPixmap,
450 XmNarmPixmap, pixmap2,
451 NULL);
452 }
453
454 XtManageChild(button);
455
456 {
457 Dimension width, height;
458 XtVaGetValues(button,
459 XmNwidth, &width,
460 XmNheight, & height,
461 NULL);
462 if ( isVertical )
463 currentY += height + packing;
464 else
465 currentX += width + packing;
466 buttonHeight = wxMax(buttonHeight, height);
467 buttonWidth = wxMax(buttonWidth, width);
468 }
469
470 XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
471 False, wxToolButtonPopupCallback, (XtPointer) this);
472
473 currentSpacing = 0;
474 break;
475 }
476
477 node = node->GetNext();
478 }
479
480 SetSize( -1, -1,
481 isVertical ? buttonWidth + 2 * marginX : -1,
482 isVertical ? -1 : buttonHeight + 2*marginY );
483
484 return true;
485 }
486
487 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
488 wxCoord WXUNUSED(y)) const
489 {
490 wxFAIL_MSG( _T("TODO") );
491
492 return (wxToolBarToolBase *)NULL;
493 }
494
495 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
496 {
497 tool->Attach(this);
498
499 return true;
500 }
501
502 bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool)
503 {
504 tool->Detach();
505
506 bool isVertical = GetWindowStyle() & wxTB_VERTICAL;
507 const int separatorSize = GetToolSeparation(); // 8;
508 int packing = GetToolPacking();
509 int offset = 0;
510
511 for( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
512 node; node = node->GetNext() )
513 {
514 wxToolBarTool *t = (wxToolBarTool*)node->GetData();
515
516 if( t == tool )
517 {
518 switch ( t->GetStyle() )
519 {
520 case wxTOOL_STYLE_CONTROL:
521 {
522 wxSize size = t->GetControl()->GetSize();
523 offset = isVertical ? size.y : size.x;
524 offset += packing;
525 break;
526 }
527 case wxTOOL_STYLE_SEPARATOR:
528 offset = isVertical ? 0 : separatorSize;
529 break;
530 case wxTOOL_STYLE_BUTTON:
531 {
532 Widget w = t->GetButtonWidget();
533 Dimension width, height;
534
535 XtVaGetValues( w,
536 XmNwidth, &width,
537 XmNheight, &height,
538 NULL );
539
540 offset = isVertical ? height : width;
541 offset += packing;
542 break;
543 }
544 }
545 }
546 else if( offset )
547 {
548 switch ( t->GetStyle() )
549 {
550 case wxTOOL_STYLE_CONTROL:
551 {
552 wxPoint pos = t->GetControl()->GetPosition();
553
554 if( isVertical )
555 pos.y -= offset;
556 else
557 pos.x -= offset;
558
559 t->GetControl()->Move( pos );
560 break;
561 }
562 case wxTOOL_STYLE_SEPARATOR:
563 break;
564 case wxTOOL_STYLE_BUTTON:
565 {
566 Dimension x, y;
567 XtVaGetValues( t->GetButtonWidget(),
568 XmNx, &x,
569 XmNy, &y,
570 NULL );
571
572 if( isVertical )
573 y -= offset;
574 else
575 x -= offset;
576
577 XtVaSetValues( t->GetButtonWidget(),
578 XmNx, x,
579 XmNy, y,
580 NULL );
581 break;
582 }
583 }
584 }
585 }
586
587 return true;
588 }
589
590 void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
591 {
592 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
593 if (tool->GetButtonWidget()){
594 XtSetSensitive(tool->GetButtonWidget(), (Boolean) enable);
595 } else if (wxTOOL_STYLE_CONTROL == tool->GetStyle()){
596 // Controls (such as wxChoice) do not have button widgets
597 tool->GetControl()->Enable(enable);
598 }
599 }
600
601 void wxToolBar::DoToggleTool(wxToolBarToolBase *toolBase, bool toggle)
602 {
603 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
604
605 XmToggleButtonSetState(tool->GetButtonWidget(), (Boolean) toggle, False);
606 }
607
608 void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
609 bool WXUNUSED(toggle))
610 {
611 // nothing to do
612 }
613
614 void wxToolBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
615 {
616 int old_width, old_height;
617 GetSize(&old_width, &old_height);
618
619 // Correct width and height if needed.
620 if ( width == -1 || height == -1 )
621 {
622 wxSize defaultSize = GetSize();
623
624 if ( width == -1 )
625 width = defaultSize.x;
626 if ( height == -1 )
627 height = defaultSize.y;
628 }
629
630 wxToolBarBase::DoSetSize(x, y, width, height, sizeFlags);
631
632 // We must refresh the frame size when the toolbar changes size
633 // otherwise the toolbar can be shown incorrectly
634 if ( old_width != width || old_height != height )
635 {
636 // But before we send the size event check it
637 // we have a frame that is not being deleted.
638 wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
639 if ( frame && !frame->IsBeingDeleted() )
640 {
641 frame->SendSizeEvent();
642 }
643 }
644 }
645
646 // ----------------------------------------------------------------------------
647 // Motif callbacks
648 // ----------------------------------------------------------------------------
649
650 wxToolBarToolBase *wxToolBar::FindToolByWidget(WXWidget w) const
651 {
652 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
653 while ( node )
654 {
655 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
656 if ( tool->GetButtonWidget() == w)
657 {
658 return tool;
659 }
660
661 node = node->GetNext();
662 }
663
664 return (wxToolBarToolBase *)NULL;
665 }
666
667 static void wxToolButtonCallback(Widget w,
668 XtPointer clientData,
669 XtPointer WXUNUSED(ptr))
670 {
671 wxToolBar *toolBar = (wxToolBar *) clientData;
672 wxToolBarToolBase *tool = toolBar->FindToolByWidget((WXWidget) w);
673 if ( !tool )
674 return;
675
676 if ( tool->CanBeToggled() )
677 tool->Toggle();
678
679 if ( !toolBar->OnLeftClick(tool->GetId(), tool->IsToggled()) )
680 {
681 // revert
682 tool->Toggle();
683 }
684 }
685
686
687 static void wxToolButtonPopupCallback(Widget w,
688 XtPointer client_data,
689 XEvent *event,
690 Boolean *WXUNUSED(continue_to_dispatch))
691 {
692 // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
693 static const int delayMilli = 800;
694
695 wxToolBar* toolBar = (wxToolBar*) client_data;
696 wxToolBarToolBase *tool = toolBar->FindToolByWidget((WXWidget) w);
697
698 if ( !tool )
699 return;
700
701 wxString tooltip = tool->GetShortHelp();
702 if ( !tooltip )
703 return;
704
705 if (!wxTheToolBarTimer)
706 wxTheToolBarTimer = new wxToolBarTimer;
707
708 wxToolBarTimer::buttonWidget = w;
709 wxToolBarTimer::helpString = tooltip;
710
711 /************************************************************/
712 /* Popup help label */
713 /************************************************************/
714 if (event->type == EnterNotify)
715 {
716 if (wxToolBarTimer::help_popup != (Widget) 0)
717 {
718 XtDestroyWidget (wxToolBarTimer::help_popup);
719 XtPopdown (wxToolBarTimer::help_popup);
720 }
721 wxToolBarTimer::help_popup = (Widget) 0;
722
723 // One shot
724 wxTheToolBarTimer->Start(delayMilli, true);
725
726 }
727 /************************************************************/
728 /* Popdown help label */
729 /************************************************************/
730 else if (event->type == LeaveNotify)
731 {
732 if (wxTheToolBarTimer)
733 wxTheToolBarTimer->Stop();
734 if (wxToolBarTimer::help_popup != (Widget) 0)
735 {
736 XtDestroyWidget (wxToolBarTimer::help_popup);
737 XtPopdown (wxToolBarTimer::help_popup);
738 }
739 wxToolBarTimer::help_popup = (Widget) 0;
740 }
741 }
742
743 void wxToolBarTimer::Notify()
744 {
745 Position x, y;
746
747 /************************************************************/
748 /* Create shell without window decorations */
749 /************************************************************/
750 help_popup = XtVaCreatePopupShell ("shell",
751 overrideShellWidgetClass, (Widget) wxTheApp->GetTopLevelWidget(),
752 NULL);
753
754 /************************************************************/
755 /* Get absolute position on display of toolbar button */
756 /************************************************************/
757 XtTranslateCoords (buttonWidget,
758 (Position) 0,
759 (Position) 0,
760 &x, &y);
761
762 // Move the tooltip more or less above the button
763 int yOffset = 20; // TODO: What should be really?
764 y -= yOffset;
765 if (y < yOffset) y = 0;
766
767 /************************************************************/
768 /* Set the position of the help popup */
769 /************************************************************/
770 XtVaSetValues (help_popup,
771 XmNx, (Position) x,
772 XmNy, (Position) y,
773 NULL);
774
775 /************************************************************/
776 /* Create help label */
777 /************************************************************/
778 XmString text = XmStringCreateSimple ((char*) (const char*) helpString);
779 XtVaCreateManagedWidget ("help_label",
780 xmLabelWidgetClass, help_popup,
781 XmNlabelString, text,
782 XtVaTypedArg,
783 XmNforeground, XtRString, "black",
784 strlen("black")+1,
785 XtVaTypedArg,
786 XmNbackground, XtRString, "LightGoldenrod",
787 strlen("LightGoldenrod")+1,
788 NULL);
789 XmStringFree (text);
790
791 /************************************************************/
792 /* Popup help label */
793 /************************************************************/
794 XtPopup (help_popup, XtGrabNone);
795 }
796