source: trunk/third/wcl/Xmp/Xmp.c @ 8837

Revision 8837, 28.3 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8836, which included commits to RCS files with non-trunk default branches.
Line 
1#include <X11/Xmp/COPY.h>
2/*
3* SCCS_data: %Z% %M%    %I% %E% %U%
4*
5* Xmp - Motif Public Utilities for Wcl - Xmp.c
6*
7* This file contains Motif specific converters, actions, and convenience
8* functions for Motif and Xmp widgets.
9*
10*******************************************************************************
11*/
12
13#include <X11/IntrinsicP.h>
14
15#ifdef sun
16#include <X11/ObjectP.h>        /* why don't they just use X from mit!?! */
17#include <X11/RectObjP.h>
18#endif
19
20#include <X11/StringDefs.h>
21#include <Xm/Xm.h>
22#include <Xm/RowColumnP.h>      /* RC_Type */
23#include <Xm/MenuShell.h>       /* xmMenuShellWidgetClass */
24#include <Xm/Text.h>            /* xmTextWidgetClass */
25#include <X11/Shell.h>          /* wmShellWidgetClass */
26#include <X11/Wc/WcCreateP.h>
27
28#include <X11/Xmp/Table.h>
29#include <X11/Xmp/XmpP.h>
30
31/******************************************************************************
32* Private_macro_definitions.
33******************************************************************************/
34
35/* The `done' macro, used by the converters, is defined in WcCreateP.h */
36
37/******************************************************************************
38**  Motif specific resource converters
39******************************************************************************/
40
41/*
42    -- Convert String To XmString
43*******************************************************************************
44    This conversion converts strings into XmStrings.  This one overrides
45    the one provided by Motif which calls XmCreateString.  Instead, this
46    one uses XmCreateStringLtoR which allows multi-line strings to be
47    created by embedding "\n" in a resource specification.  In order to
48    allow this to be used, XmpRegAll MUST install this converter AFTER
49    Motif has installed its broken converter.
50*/
51/*ARGSUSED*/
52void XmpCvtStringToXmString (args, num_args, fromVal, toVal)
53    XrmValue *args;
54    Cardinal *num_args;
55    XrmValue *fromVal;
56    XrmValue *toVal;
57{
58    XmString xmString;
59    xmString = XmStringCreateLtoR( fromVal->addr, XmSTRING_DEFAULT_CHARSET );
60    done( XmString, xmString );
61}
62
63/* -- Register all converters provided by Motif
64*******************************************************************************
65*/
66
67void XmpAddMotifConverters ( app )
68    XtAppContext app;
69{
70    ONCE_PER_XtAppContext( app );
71
72    XmRegisterConverters();
73#ifdef XmRTearOffModel
74    XmRepTypeInstallTearOffModelConverter();
75#endif
76#ifndef VMS
77    _XmRegisterPixmapConverters();
78#endif
79    XtAppAddConverter(  app, XmRString, XmRUnitType,
80                        XmCvtStringToUnitType,
81                        (XtConvertArgList)0, (Cardinal)0 );
82}
83
84/* -- Register all converters provided by Xmp
85*******************************************************************************
86*/
87
88void XmpAddConverters ( app )
89    XtAppContext app;
90{
91    ONCE_PER_XtAppContext( app );
92
93    /* Some, not all, old versions of Motif incorrectly say some resources
94    ** which should be of type "Widget" are of type "Window"
95    */
96#ifdef XtSpecificationRelease
97    /* Must use new style converter if available to avoid cache,
98     * because the cache is not cleared when named widgets get destroyed!
99     */
100    XtAppSetTypeConverter( app, XtRString, "Window",
101                           WcCvtStringToWidget,
102                           wcWidgetCvtArgs, wcWidgetCvtArgsCount,
103                           XtCacheNone, (XtDestructor)0 );
104
105    XtAppSetTypeConverter( app, XtRString, XmRMenuWidget,
106                           WcCvtStringToWidget,
107                           wcWidgetCvtArgs, wcWidgetCvtArgsCount,
108                           XtCacheNone, (XtDestructor)0 );
109#else
110    /* R3 does not cache conversions, so there is nothing to worry about.
111    */
112    XtAppAddConverter(  app, XtRString, "Window",
113                        WcCvtStringToWidget,
114                        wcWidgetCvtArgs, wcWidgetCvtArgsCount );
115
116    XtAppAddConverter(  app, XtRString, XmRMenuWidget,
117                        WcCvtStringToWidget,
118                        wcWidgetCvtArgs, wcWidgetCvtArgsCount );
119
120#endif
121
122    XtAppAddConverter(  app, XtRString, XmRXmString,
123                        XmpCvtStringToXmString,
124                        (XtConvertArgList)0, (Cardinal)0 );
125}
126
127
128/* -- Action to fix broken translations in XmText widgets.
129*******************************************************************************
130*/
131/*ARGSUSED*/
132void XmpFixTranslationsACT( w, unusedEvent, params, num_params )
133    Widget      w;
134    XEvent     *unusedEvent;
135    String     *params;
136    Cardinal   *num_params;
137{
138    static int            firstTime = 1;
139    static XtTranslations transTable;
140    static char           fixedTranslations[] = "<Key>Return: newline()";
141
142    int     i;
143
144    if (firstTime)
145    {
146        firstTime = 0;
147        transTable = XtParseTranslationTable(fixedTranslations);
148    }
149
150    if ( *num_params == 0 )
151    {
152        WcWARN( w, "XmpFixTranslations", "usage",
153                "Xmp Usage: XmpFixTranslations( widget [widgetName] ...)");
154        return;
155    }
156
157    for ( i = 0 ; i < *num_params ; i++ )
158    {
159        Widget toFix = WcFullNameToWidget( w, params[i] );
160
161        if (!toFix)
162        {
163            WcWARN1( w, "XmpFixTranslations", "notFound",
164                   "Xmp Warning: XmpFixTranslations(%s) - Widget not found",
165                    params[i] );
166            return;
167        }
168
169        if (XtIsSubclass( toFix, xmTextWidgetClass ))
170            XtOverrideTranslations( toFix, transTable );
171        else
172        {
173            WcWARN1( w, "XmpFixTranslations", "notText",
174                   "Xmp Warning: XmpFixTranslations(%s) - Not an XmText widget",
175                     params[i] );
176            return;
177        }
178    }
179}
180
181/*ARGSUSED*/
182void XmpFixTranslationsCB( w, widgetNames, ignore )
183    Widget      w;
184    XtPointer   widgetNames;
185    XtPointer   ignore;
186{
187    WcInvokeAction( XmpFixTranslationsACT, w, widgetNames );
188}
189
190
191/* -- Action to popup a Motif PopupMenu
192*******************************************************************************
193   Gotta do debugging with fprintf() because there is a server grab
194   in effect, in all probability.
195*/
196
197void XmpPopupACT( w, event, params, num_params )
198    Widget      w;
199    XEvent     *event;
200    String     *params;
201    Cardinal   *num_params;
202{
203    Widget        menuPane, menu;
204    unsigned char rowColumnType;
205
206    if (*num_params < 1)
207    {
208        WcWARN( w, "XmpPopup", "noParams",
209"Xmp Warning: XmpPopup() - No menu pane name provided." );
210        return;
211    }
212
213    if ( *num_params > 1 )
214    {
215        WcWARN2( w, "XmpPopup", "tooManyParams",
216"Xmp Warning: XmpPopup( %s %s ... ) - Only one menu pane name allowed." ,
217                params[0], params[1] );
218        return;
219    }
220
221    menuPane = WcFullNameToWidget( w, params[0] );
222
223    if ( menuPane == (Widget)0 )
224    {
225        String fullName = WcWidgetToFullName( w );
226        WcWARN3( w, "XmpPopup", "notFound",
227"Xmp Warning: XmpPopup( %s ) - Couldn't find menu pane widget `%s' from `%s'",
228                params[0], params[0], fullName );
229        XtFree( fullName );
230        return;
231    }
232
233    if ( !XtIsSubclass( menuPane, xmRowColumnWidgetClass ) )
234    {
235        String fullName = WcWidgetToFullName( menuPane );
236        WcWARN2( w, "XmpPopup", "notXmRowColumn",
237"Xmp Warning: XmpPopup( %s ) - %s is not menu pane (not XmRowColumn)",
238                params[0], fullName );
239        XtFree( fullName );
240        return;
241    }
242
243    XtVaGetValues( menuPane, XmNrowColumnType, &rowColumnType, NULL );
244
245    if ( rowColumnType != XmMENU_POPUP )
246    {
247        String fullName = WcWidgetToFullName( menuPane );
248        WcWARN2( w, "XmpPopup", "notPopupMenuRowColumn",
249"Xmp Warning: XmpPopup( %s ) - %s is not menu pane (not XmMENU_POPUP)",
250                params[0], fullName );
251        XtFree( fullName );
252        return;
253    }
254
255    menu = XtParent( menuPane );
256
257    if ( !XtIsSubclass( menu, xmMenuShellWidgetClass ) )
258    {
259        String fullName = WcWidgetToFullName( menuPane );
260        WcWARN2( w, "XmpPopup", "notChildOfXmMenu",
261"Xmp Warning: XmpPopup( %s ) - %s is not menu pane (child of XmMenuShell)",
262                params[0], fullName );
263        XtFree( fullName );
264        return;
265    }
266
267    if ( event->type != ButtonPress )
268    {
269        WcWARN2( w, "XmpPopup", "notButtonPressEvent",
270"Xmp Warning: XmpPopup( %s ) - event type `%s' is not ButtonPress event.",
271                params[0], WcXEventName( event ) );
272        return;
273    }
274
275    /* OK! we have 1 named widget which resolves to a XmRowColumn of
276     * type XmMENU_POPUP which is a child of a XmMenuShell, and a
277     * ButtonPress event invoked this action.  Therefore, lets go ahead.
278     */
279    XmMenuPosition( menuPane, (XButtonPressedEvent*)event );
280    XtManageChild( menuPane );
281}
282
283
284/*
285    -- Provide `Close' callback
286*******************************************************************************
287    Provide a callback which gets invoked when the user select `Close' from
288    the Mwm frame menu on the top level shell.  MUST be done after shell widget
289    is realized!
290*/
291
292void XmpAddMwmCloseCallback( shell, callback, clientData )
293    Widget         shell;
294    XtCallbackProc callback;
295    XtPointer      clientData;
296{
297    Atom wmProtocol, wmDeleteWindow, wmSaveYourself;
298    wmProtocol    =XmInternAtom( XtDisplay(shell), "WM_PROTOCOLS",     False );
299
300    wmDeleteWindow=XmInternAtom( XtDisplay(shell), "WM_DELETE_WINDOW", False );
301    wmSaveYourself=XmInternAtom( XtDisplay(shell), "WM_SAVE_YOURSELF", False );
302    XmAddProtocolCallback( shell, wmProtocol, wmDeleteWindow,
303                           callback, clientData );
304    XmAddProtocolCallback( shell, wmProtocol, wmSaveYourself,
305                           callback, clientData );
306}
307
308/*
309    -- Action and callback to invoke XmpAddMwmCloseCallback
310*******************************************************************************
311*/
312/*ARGSUSED*/
313void XmpAddMwmCloseCallbackCB( w, widget_callbackList, notUsed )
314    Widget      w;
315    XtPointer   widget_callbackList;
316    XtPointer   notUsed;
317{
318    char                widgetName[MAX_XRMSTRING];
319    String              callbackListString;
320    Widget              target;
321    XtCallbackRec*      callbackList;
322    XtCallbackRec*      cb;
323
324    callbackListString = WcCleanName( (char*)widget_callbackList, widgetName );
325    callbackListString = WcSkipWhitespace_Comma( callbackListString );
326
327    target = WcFullNameToWidget( w, widgetName );
328
329    if ( (Widget)0 == (target = WcFullNameToWidget( w, widgetName )) )
330    {
331        WcWARN1( w, "XmpAddMwmCloseCallback", "targetNotFound",
332"Xmp Warning: XmpAddMwmCloseCallback( %s ... ) - Target widget not found",
333                widgetName );
334        return;
335    }
336
337    callbackList = WcStringToCallbackList( w, callbackListString );
338
339    for ( cb = callbackList  ;
340          cb != (XtCallbackRec*)0 && cb->callback != (XtCallbackProc)0  ;
341          cb++ )
342        XmpAddMwmCloseCallback( target, cb->callback, cb->closure );
343
344    WcFreeCallbackList( callbackList );
345}
346
347/*ARGSUSED*/
348void XmpAddMwmCloseCallbackACT( w, unusedEvent, params, num_params )
349    Widget      w;
350    XEvent     *unusedEvent;
351    String     *params;
352    Cardinal   *num_params;
353{
354    WcInvokeCallback( XmpAddMwmCloseCallbackCB, w, params, num_params );
355}
356
357/*  -- Define a Widget as a Tab Group
358*******************************************************************************
359    If no widget is named, then use the widget argument.
360    If the widget is a  manager widget, then this means all the children
361    are in a tab group together.  If a widget is a primitive, then that
362    widget is in its own tab group (this is the default).
363*/
364/*ARGSUSED*/
365void XmpAddTabGroupACT( w, unusedEvent, params, num_params )
366    Widget      w;
367    XEvent     *unusedEvent;
368    String     *params;
369    Cardinal   *num_params;
370{
371    if (*num_params == 0)
372    {
373        XmAddTabGroup(w);
374    }
375    else if (*num_params == 1)
376    {
377        Widget target = WcFullNameToWidget( w, params[0] );
378
379        if ((Widget)0 != target)
380        {
381            XmAddTabGroup(w);
382        }
383        else
384        {
385            WcWARN1( w, "XmpAddTabGroup", "notFound",
386                "Xmp Warning: XmpAddTabGroup(%s) - Widget not found",
387                params[0] );
388        }
389       
390    }
391    else
392    {
393        WcWARN( w, "XmpAddTabGroup", "usage",
394"Xmp Warning: XmpAddTabGroup() requires 0 or 1 widget name argument.");
395    }
396}
397
398/*ARGSUSED*/
399void XmpAddTabGroupCB( w, widgetName, notUsed )
400    Widget      w;
401    XtPointer   widgetName;
402    XtPointer   notUsed;
403{
404    WcInvokeAction( XmpAddTabGroupACT,  w, widgetName );
405}
406
407/*  -- Specify a text widget to take Wcl messages
408*******************************************************************************
409*/
410
411static void   XmpxPrint                  _(( String, ... ));
412static void   XmpxMessageWidgetDestroyCB _(( Widget, XtPointer, XtPointer ));
413static int    XmpxLinesIn                _(( String ));
414static int    XmpxEntireMessageLen       _(( String, va_list ));
415static String XmpxMakeEntireMessage      _(( String, va_list ));
416
417static Widget xmpMessageWidget;         /* an XmText widget */
418
419static WcPrintProc XmpxDefaultWcPrintProc;
420
421typedef struct _MessageOptions {
422    int         maxLines;
423    int         columns;
424    String      linesLostMsg;
425    int         linesInLinesLostMsg;
426    Boolean     popup, raise, brokenXmTextShowPosition;
427} MessageOptionsRec, *MessageOptions;
428
429static MessageOptionsRec xmpMessageOptionsRec;
430static MessageOptions    xmpMessageOptions = &xmpMessageOptionsRec;
431
432#ifdef XtOffsetOf
433#define FLD(n)  XtOffsetOf(MessageOptionsRec,n)
434#else
435#define FLD(n)  XtOffset(MessageOptions,n)
436#endif
437
438static XtResource xmxMessageRes[] = {
439  {  XmpNmessageMaxLines, XmpCMessageMaxLines, XtRInt, sizeof(int),
440     FLD(maxLines), XtRString, (XtPointer)"100"
441  },
442  {  XmpNmessageColumns, XmpCMessageColumns, XtRInt, sizeof(int),
443     FLD(columns), XtRString, (XtPointer)"80"
444  },
445  {  XmpNmessageLinesLostMsg, XmpCMessageLinesLostMsg,
446     XtRString, sizeof(String),
447     FLD(linesLostMsg), XtRString, (XtPointer)"... some lines lost...\n"
448  },
449  {  XmpNmessagePopup, XmpCMessagePopup, XtRBoolean, sizeof(Boolean),
450     FLD(popup), XtRString, (XtPointer)"True"
451  },
452  {  XmpNmessageRaise, XmpCMessageRaise, XtRBoolean, sizeof(Boolean),
453     FLD(raise), XtRString, (XtPointer)"False"
454  },
455  {  XmpNmessageBrokenXmTextShowPosition,
456     XmpCMessageBrokenXmTextShowPosition, XtRBoolean, sizeof(Boolean),
457     FLD(brokenXmTextShowPosition), XtRString, (XtPointer)"False"
458  },
459};
460#undef FLD
461
462/* Set Messages to go to an XmText widget
463*******************************************************************************
464   Only get the default print proc once, but allow the message widget
465   to be changed at any time.
466*/
467/*ARGSUSED*/
468void XmpMessageWidgetCB( widget, client, call )
469    Widget      widget;
470    XtPointer   client, call;
471{
472    String      name = (String)client;
473
474    if ( WcNonNull( name ) )
475    {
476        Widget messageWidget = WcFullNameToWidget( widget, name );
477
478        if ( messageWidget == (Widget)0 )
479        {
480            String fullName = WcWidgetToFullName( widget );
481            WcWARN2( widget, "XmpMessageWidget", "notFound",
482"Xmp Warning: XmpMessageWidget could not find %s from %s\n",
483                     name, fullName );
484            XtFree(fullName);
485            return;
486        }
487
488        XmpMessageWidget( messageWidget );
489    }
490    else
491        XmpMessageWidget( widget );
492}
493
494/*ARGSUSED*/
495void XmpMessageWidgetACT( widget, unused, params, num_params )
496    Widget      widget;
497    XEvent*     unused;
498    char**      params;
499    Cardinal*   num_params;
500{
501    if ( *num_params == 0 )
502        XmpMessageWidgetCB( widget, NULL, NULL );
503    else if ( *num_params == 1 )
504        XmpMessageWidgetCB( widget, params[0], NULL );
505    else
506        WcWARN( widget, "XmpMessageWidget", "usage",
507                "Xmp Usage: XmpMessageWidget( [messageWidgetName] )" );
508}
509
510void XmpMessageWidget( widget )
511    Widget widget;
512{
513    if ( widget == (Widget)0 && XmpxDefaultWcPrintProc != (WcPrintProc)0 )
514    {
515        /* Reset back to initial state - use default WcPrint method
516        */
517        WcPrint = XmpxDefaultWcPrintProc;
518        XmpxDefaultWcPrintProc = (WcPrintProc)0;
519        xmpMessageWidget = (Widget)0;
520        return;
521    }
522
523    if ( !XmIsText( widget ) )
524    {
525        /* Message widget MUST be an XmText widget - leave in current state.
526        */
527        String fullName = WcWidgetToFullName( widget );
528        WcWARN1( widget, "XmpMessageWidget", "notXmText",
529                 "Xmp Warning: XmpMessageWidget(%s) - not an XmTextWidget",
530                 fullName );
531        XtFree( fullName );
532        return;
533    }
534
535    /* New XmText widget
536    */
537    if ( XmpxDefaultWcPrintProc == (WcPrintProc)0 )
538    {
539        XmpxDefaultWcPrintProc = WcPrint;
540        WcPrint = XmpxPrint;
541    }
542
543    xmpMessageWidget = widget;
544
545    XtGetApplicationResources(  xmpMessageWidget, (XtPointer)xmpMessageOptions,
546                                xmxMessageRes, XtNumber( xmxMessageRes ),
547                                NULL, 0 );
548
549    xmpMessageOptions->linesInLinesLostMsg =
550                                XmpxLinesIn( xmpMessageOptions->linesLostMsg );
551
552    XtAddCallback( widget, XtNdestroyCallback,
553                   XmpxMessageWidgetDestroyCB, (XtPointer)0 );
554}
555
556/* Send Messages to the Message Widget
557*******************************************************************************
558   Invoked via pointer to procedure WcPrint.  Used to print Wcl messages
559   and any other messages printed via WcWARN or WcPrint.
560
561   Note: XmpMessageWidget must ensure that if WcPrint is XmpPrint,
562   then xmpMessageWidget is an XmTextWidget.
563*/
564#if NeedFunctionPrototypes
565static void XmpxPrint( String msg, ... )
566#else
567static void XmpxPrint( msg, va_alist )
568    String      msg;
569    va_dcl
570#endif
571{
572    String      entireMsg;
573    va_list     argPtr;
574
575    Va_start( argPtr, msg );            /* point at 1st unnamed arg     */
576
577    entireMsg = XmpxMakeEntireMessage( msg, argPtr );
578
579    if ( WcNonNull( entireMsg ) )
580    {
581        /* Put the message into the XmTextWidget
582        */
583        XmTextPosition  chPos;  /* a long int */
584        String          existingText = XmTextGetString( xmpMessageWidget );
585        int             linesInExistingText = XmpxLinesIn( existingText );
586        int             linesInEntireMsg    = XmpxLinesIn( entireMsg );
587        int             lines = linesInExistingText + linesInEntireMsg;
588
589        if ( lines >= xmpMessageOptions->maxLines )
590        {
591            /* Too many lines:  First line in XmText probably has the
592             * "... some lines lost ..." message already.  Therefore,
593             * always throw that message away and enough to show entire
594             * new message.
595             */
596            int linesToReplace = xmpMessageOptions->linesInLinesLostMsg +
597                                 (lines - xmpMessageOptions->maxLines);
598
599            for ( lines = 0, chPos = 0  ;  existingText[chPos]  ;  chPos++ )
600            {
601                if ( existingText[chPos] == '\n' )
602                    ++lines;
603                if ( lines > linesToReplace )
604                    break;
605            }
606            /* lines >= 2 because we must always replace at least one line
607             * AFTER the linesLostMsg which is (except the 1st time) on the
608             * first line.  Replace the 1st lines with the linesLostMsg.
609             */
610            XmTextReplace( xmpMessageWidget, (XmTextPosition)0, chPos,
611                           xmpMessageOptions->linesLostMsg );
612        }
613        /* Find the new last position, append entireMsg to end.
614        */
615        chPos = XmTextGetLastPosition( xmpMessageWidget );
616
617        if ( chPos != 0 )
618            XmTextInsert( xmpMessageWidget, chPos++, "\n" );
619        XmTextInsert( xmpMessageWidget, chPos, entireMsg );
620
621        if ( xmpMessageOptions->brokenXmTextShowPosition )
622        {
623            /* Cause text to scroll to show beginning of new message.
624            */
625            XmTextShowPosition(  xmpMessageWidget, chPos );
626        }
627
628        XtFree( existingText );
629        XtFree( entireMsg );
630
631        /* Maybe cause shell to appear, and maybe raise that shell.
632        */
633        if ( xmpMessageOptions->popup || xmpMessageOptions->raise )
634        {
635            Widget childOfShell = xmpMessageWidget;
636            Widget shell        = XtParent( childOfShell );
637
638            /* Go up widget tree to find nearest shell ancestor, and its child
639            */
640            while ( !XtIsShell( shell ) )
641            {
642                childOfShell = shell;
643                shell = XtParent( childOfShell );
644            }
645
646            if ( xmpMessageOptions->popup )
647            {
648                if ( XmIsDialogShell( shell ) )
649                {
650                    XtManageChild( childOfShell );
651                }
652                else
653                {
654                    if ( !XtIsManaged( childOfShell ) )
655                    {
656                        XtManageChild( childOfShell );
657                    }
658                    XtPopup( shell, XtGrabNone );
659                }
660            }
661
662            if ( xmpMessageOptions->raise )
663            {
664                if ( !XtIsManaged( childOfShell ) )
665                {
666                    XtManageChild( childOfShell );
667                }
668                XtRealizeWidget( shell );
669                XRaiseWindow( XtDisplay(shell), XtWindow(shell) );
670                XFlush( XtDisplay(shell) );
671            }
672        }
673    }
674
675    va_end( argPtr );                   /* clean up */
676}
677
678/*ARGSUSED*/
679static void XmpxMessageWidgetDestroyCB( widget, client, call )
680    Widget      widget;
681    XtPointer   client, call;
682{
683    /* Reset back to initial state - use default WcPrint method
684    */
685    WcPrint = XmpxDefaultWcPrintProc;
686    XmpxDefaultWcPrintProc = (WcPrintProc)0;
687    xmpMessageWidget = (Widget)0;
688}
689
690static int XmpxLinesIn( cp )
691    String cp;
692{
693    int lines;
694
695    for ( lines = 1  ;  *cp  ;  ++cp )
696    {
697        if ( *cp == '\n' )
698            ++lines;
699    }
700    return lines;
701}
702
703static int XmpxEntireMessageLen( msg, argPtr )
704    String      msg;
705    va_list     argPtr;
706{
707    int len = WcStrLen( msg );
708
709    if ( msg == NULL )
710        return 0;
711
712    msg = va_arg( argPtr, String );     /* get unnamed string arg       */
713    while ( msg != NULL )
714    {
715        len += WcStrLen( msg );
716        msg = va_arg( argPtr, String ); /* get next unnamed string arg  */
717    }
718
719    return len;
720}
721
722static String XmpxMakeEntireMessage( msg, argPtr )
723    String      msg;
724    va_list      argPtr;
725{
726    int    entireLen = XmpxEntireMessageLen( msg, argPtr );
727    String entireMsg = XtMalloc( entireLen + 1 );
728
729    if ( entireMsg == NULL )
730        return NULL;            /* malloc failed */
731
732    strcpy( entireMsg, msg );
733
734    msg = va_arg( argPtr, String );     /* get unnamed string arg       */
735    while ( msg != NULL )
736    {
737        strcat( entireMsg, msg );
738        msg = va_arg( argPtr, String ); /* get next unnamed string arg  */
739    }
740
741    return entireMsg;
742}
743
744/*  -- XmpTable Callbacks and Actions
745*******************************************************************************
746    These callbacks and actions make the XmpTable convenience functions
747    accessible via the Xrm database.
748*/
749
750/*ARGSUSED*/
751void XmpTableChildConfigCB( w, client, ignored )
752    Widget      w;
753    XtPointer   client;
754    XtPointer   ignored;
755{
756    WcInvokeAction( XmpTableChildConfigACT, w, client );
757}
758
759/*ARGSUSED*/
760void XmpTableChildConfigACT( w, unusedEvent, params, num_params )
761    Widget      w;
762    XEvent     *unusedEvent;
763    String     *params;
764    Cardinal   *num_params;
765{
766    Widget      widget;
767    Position    col;
768    Position    row;
769    Dimension   hSpan = 1;              /* optional arg, default */
770    Dimension   vSpan = 1;              /* optional arg, default */
771    XmpTableOpts opt  = TBL_DEF_OPT;    /* optional arg, default */
772
773    if (*num_params < 3 || 6 < *num_params )
774    {
775        WcWARN( w, "XmpTableChildConfig", "wrongNumArgs",
776"Xmp Warning: XmpTableChildConfig( ... ) - Wrong number of arguments.\n\
777Xmp Usage: XmpTableChildConfig( w col row [h_span [v_span [opts]]] )" );
778        return;
779    }
780
781    widget = WcFullNameToWidget( w, params[0] );
782    col = atoi( params[1] );
783    row = atoi( params[2] );
784
785    if ((Widget)0 == widget)
786    {
787        WcWARN1( w, "XmpTableChildConfig", "widgetNotFound",
788"Xmp Warning: XmpTableChildConfig( %s ... ) - Could not find widget.",
789                        params[0] );
790        return;
791    }
792    else if ( ! XtIsSubclass( XtParent(widget), xmpTableWidgetClass ))
793    {
794        WcWARN1( w, "XmpTableChildConfig", "notXmpTable",
795"Xmp Warning: XmpTableChildConfig( %s ... ) - Widget not child of an XmpTable.",
796                        params[0] );
797        return;
798    }
799
800    if ( 3 < *num_params )
801        hSpan = atoi( params[3] );
802    if ( 4 < *num_params )
803        vSpan = atoi( params[4] );
804    if ( 5 < *num_params )
805        opt = XmpTableOptsParse( params[5] );
806
807    XmpTableChildConfig( widget, col, row, hSpan, vSpan, opt );
808}
809
810/*ARGSUSED*/
811void XmpTableChildPositionCB( w, client, ignored )
812    Widget      w;
813    XtPointer   client;
814    XtPointer   ignored;
815{
816    WcInvokeAction( XmpTableChildPositionACT, w, client );
817}
818
819/*ARGSUSED*/
820void XmpTableChildPositionACT( w, unusedEvent, params, num_params )
821    Widget      w;
822    XEvent     *unusedEvent;
823    String     *params;
824    Cardinal   *num_params;
825{
826    Widget      widget;
827    Position    col;
828    Position    row;
829
830    if (*num_params != 3 )
831    {
832        WcWARN( w, "XmpTableChildPosition", "wrongNumArgs",
833"Xmp Warning: XmpTableChildPosition( ... ) - Wrong number of arguments.\n\
834Xmp Usage: XmpTableChildPosition( w col row )" );
835        return;
836    }
837
838    widget = WcFullNameToWidget( w, params[0] );
839    col = atoi( params[1] );
840    row = atoi( params[2] );
841
842    if ((Widget)0 == widget)
843    {
844        WcWARN1( w, "XmpTableChildPosition", "widgetNotFound",
845"Xmp Warning: XmpTableChildPosition( %s ... ) could not find widget.",
846                        params[0] );
847        return;
848    }
849    else if ( ! XtIsSubclass( XtParent(widget), xmpTableWidgetClass ))
850    {
851        WcWARN1( w, "XmpTableChildPosition", "notXmpTable",
852"Xmp Warning: XmpTableChildPosition( %s ... ) Widget not child of an XmpTable.",
853                        params[0] );
854        return;
855    }
856
857    XmpTableChildPosition( widget, col, row );
858}
859
860/*ARGSUSED*/
861void XmpTableChildResizeCB( w, client, ignored )
862    Widget      w;
863    XtPointer   client;
864    XtPointer   ignored;
865{
866    WcInvokeAction( XmpTableChildResizeACT, w, client );
867}
868
869/*ARGSUSED*/
870void XmpTableChildResizeACT( w, unusedEvent, params, num_params )
871    Widget      w;
872    XEvent     *unusedEvent;
873    String     *params;
874    Cardinal   *num_params;
875{
876    Widget      widget;
877    Dimension   hSpan;
878    Dimension   vSpan;
879
880    if (*num_params != 3 )
881    {
882        WcWARN( w, "XmpTableChildResize", "wrongNumArgs",
883"Xmp Warning: XmpTableChildResize( ... ) Wrong number of arguments.\n\
884Xmp Usage: XmpTableChildResize( w h_span v_span )" );
885        return;
886    }
887
888    widget = WcFullNameToWidget( w, params[0] );
889    hSpan = atoi( params[1] );
890    vSpan = atoi( params[2] );
891
892    if ((Widget)0 == widget)
893    {
894        WcWARN1( w, "XmpTableChildResize", "widgetNotFound",
895"Xmp Warning: XmpTableChildResize( %s ... ) - Widget not found.",
896                        params[0] );
897        return;
898    }
899    else if ( ! XtIsSubclass( XtParent(widget), xmpTableWidgetClass ))
900    {
901        WcWARN1( w, "XmpTableChildResize", "notXmpTable",
902"Xmp Warning: XmpTableChildResize( %s ... ) - Widget not child of an XmpTable.",
903                        params[0] );
904        return;
905    }
906
907    XmpTableChildResize( widget, hSpan, vSpan );
908}
909
910/*ARGSUSED*/
911void XmpTableChildOptionsCB( w, client, ignored )
912    Widget      w;
913    XtPointer   client;
914    XtPointer   ignored;
915{
916    WcInvokeAction( XmpTableChildOptionsACT, w, client );
917}
918
919/*ARGSUSED*/
920void XmpTableChildOptionsACT( w, unusedEvent, params, num_params )
921    Widget      w;
922    XEvent     *unusedEvent;
923    String     *params;
924    Cardinal   *num_params;
925{
926    Widget       widget;
927    XmpTableOpts opt;
928
929    if (*num_params != 2 )
930    {
931        WcWARN( w, "XmpTableChildOptions", "wrongNumArgs",
932"Xmp Warning: XmpTableChildOptions() - Wrong number of arguments.\n\
933Xmp Usage: XmpTableChildOptions( w options )" );
934        return;
935    }
936
937    if ((Widget)0 == (widget = WcFullNameToWidget( w, params[0] )) )
938    {
939        WcWARN1( w, "XmpTableChildOptions", "widgetNotFound",
940"Xmp Warning: XmpTableChildOptions( %s ... ) - Widget not found.",
941                        params[0] );
942        return;
943    }
944    else if ( ! XtIsSubclass( XtParent(widget), xmpTableWidgetClass ))
945    {
946        WcWARN1( w, "XmpTableChildOptions", "notXmpTable",
947"Xmp Warning: XmpTableChildOptions( %s ... ) Widget not child of an XmpTable.",
948                        params[0] );
949        return;
950    }
951
952    opt = XmpTableOptsParse( params[1] );
953    XmpTableChildOptions( widget, opt );
954}
955
956/* -- Register all Xmp provided actions and callbacks.
957*******************************************************************************
958*/
959
960void XmpAddActionsAndCallbacks ( app )
961    XtAppContext app;
962{
963    static XtActionsRec XmpActions[] = {
964        {"XmpPopup",                    XmpPopupACT                     },
965        {"XmpPopupACT",                 XmpPopupACT                     },
966        {"XmpFixTranslations",          XmpFixTranslationsACT           },
967        {"XmpFixTranslationsACT",       XmpFixTranslationsACT           },
968        {"XmpAddMwmCloseCallback",      XmpAddMwmCloseCallbackACT       },
969        {"XmpAddMwmCloseCallbackACT",   XmpAddMwmCloseCallbackACT       },
970        {"XmpAddTabGroup",              XmpAddTabGroupACT               },
971        {"XmpAddTabGroupACT",           XmpAddTabGroupACT               },
972        {"XmpMessageWidget",            XmpMessageWidgetACT             },
973        {"XmpMessageWidgetACT",         XmpMessageWidgetACT             },
974        {"XmpTableChildConfig",         XmpTableChildConfigACT          },
975        {"XmpTableChildConfigACT",      XmpTableChildConfigACT          },
976        {"XmpTableChildPosition",       XmpTableChildPositionACT        },
977        {"XmpTableChildPositionACT",    XmpTableChildPositionACT        },
978        {"XmpTableChildResize",         XmpTableChildResizeACT          },
979        {"XmpTableChildResizeACT",      XmpTableChildResizeACT          },
980        {"XmpTableChildOptions",        XmpTableChildOptionsACT         },
981        {"XmpTableChildOptionsACT",     XmpTableChildOptionsACT         },
982        /* -- compatibility: */
983        {"MriPopup",                    XmpPopupACT                     },
984        {"MriPopupACT",                 XmpPopupACT                     },
985    };
986
987    ONCE_PER_XtAppContext( app );
988
989/* -- Register Motif specific action functions */
990    XtAppAddActions(app, XmpActions, XtNumber(XmpActions));
991
992/* -- Register Motif specific callback functions */
993#define RCALL( name, func ) WcRegisterCallback ( app, name, func, (XtPointer)0 )
994
995    RCALL("XmpFixTranslations",         XmpFixTranslationsCB            );
996    RCALL("XmpFixTranslationsCB",       XmpFixTranslationsCB            );
997    RCALL("XmpAddMwmCloseCallback",     XmpAddMwmCloseCallbackCB        );
998    RCALL("XmpAddMwmCloseCallbackCB",   XmpAddMwmCloseCallbackCB        );
999    RCALL("XmpAddTabGroup",             XmpAddTabGroupCB                );
1000    RCALL("XmpAddTabGroupCB",           XmpAddTabGroupCB                );
1001    RCALL("XmpMessageWidget",           XmpMessageWidgetCB              );
1002    RCALL("XmpMessageWidgetCB",         XmpMessageWidgetCB              );
1003    RCALL("XmpTableChildConfig",        XmpTableChildConfigCB           );
1004    RCALL("XmpTableChildConfigCB",      XmpTableChildConfigCB           );
1005    RCALL("XmpTableChildPosition",      XmpTableChildPositionCB         );
1006    RCALL("XmpTableChildPositionCB",    XmpTableChildPositionCB         );
1007    RCALL("XmpTableChildResize",        XmpTableChildResizeCB           );
1008    RCALL("XmpTableChildResizeCB",      XmpTableChildResizeCB           );
1009    RCALL("XmpTableChildOptions",       XmpTableChildOptionsCB          );
1010    RCALL("XmpTableChildOptionsCB",     XmpTableChildOptionsCB          );
1011}
Note: See TracBrowser for help on using the repository browser.