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