Remove hpversion.h from repository
[oweals/cde.git] / cde / programs / dtksh / dtkcmds.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: dtkcmds.c /main/13 1997/07/14 18:16:01 samborn $ */
24 /*      Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */
25 /*      All Rights Reserved     */
26
27 /*      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF          */
28 /*      UNIX System Laboratories, Inc.                          */
29 /*      The copyright notice above does not evidence any        */
30 /*      actual or intended publication of such source code.     */
31
32 /* X includes */
33
34 #include        "name.h" 
35 #include        "shell.h" 
36 #include <signal.h>
37 #include <fcntl.h>
38 #include <X11/X.h>
39 #include <X11/Intrinsic.h>
40 #include <X11/IntrinsicP.h>
41 #include <X11/CoreP.h>
42 #include <X11/StringDefs.h>
43 #include <Xm/XmStrDefs.h>
44 #include <setjmp.h>
45 #include <string.h>
46 #include <ctype.h>
47 #include <Xm/Xm.h>
48 #include <Xm/Protocols.h>
49 #include <Dt/Service.h>
50 #include <Dt/Wsm.h>
51 #include <Dt/HourGlass.h>
52 #include <Dt/Help.h>
53 #include <Dt/Action.h>
54 #include <Dt/Dts.h>
55 #include <Dt/Print.h>
56 #include <Tt/tttk.h>
57 #include <Tt/tt_c.h>
58 #include "hash.h"
59 #include "stdio.h"
60 #define NO_AST
61 #include "dtksh.h"
62 #undef NO_AST
63 #include "xmksh.h"
64 #include "dtkcmds.h"
65 #include "xmcvt.h"
66 #include "widget.h"
67 #include "extra.h"
68 #include "xmwidgets.h"
69 #include "msgs.h"
70 #include <locale.h>
71
72 extern Namval_t *sh_assignok(Namval_t *np,int add);
73
74
75 static void PendingDestroy( 
76                         Widget w,
77                         wtab_t *wtab,
78                         caddr_t callData) ;
79 static Boolean WtabDestroy( 
80                         caddr_t callData) ;
81 static int _CreateWidget( 
82                         Widget (*func)(),
83                         int argc,
84                         char *argv[]) ;
85 static int _DTKSH_XtDestroyWidget( 
86                         Widget w) ;
87 static int do_single_widget_arg_func( 
88                         int (*func)(),
89                         int argc,
90                         char **argv) ;
91 static void mainloopsighandler( 
92                         int sig) ;
93 static int XtCallCallbacks_usage( 
94                         char *arg0) ;
95 static void RegisterCmdStr( 
96                         char type,
97                         long id,
98                         char *cmd) ;
99 static void RemoveCmdStr( 
100                         char type,
101                         long id) ;
102 static int do_RootWindowCmd( 
103                         int (*func)(),
104                         int argc,
105                         char *argv[]) ;
106 static int cvtfontstruct( 
107                         char *name,
108                         XFontStruct **fn) ;
109 static int CatchNonFatalFontError( 
110                         Display *display,
111                         XErrorEvent *event) ;
112 static int cvtfont( 
113                         Display *display,
114                         char *name,
115                         Font *fn) ;
116 static int cvtcolor( 
117                         char *name,
118                         Pixel *pix) ;
119 static int invokeXDrawFunction( 
120                         int function,
121                         int argc,
122                         char *argv[]) ;
123 static int XtAddInputUsage( 
124                         char *arg0) ;
125 static void DestroyInputRecord(
126                         XtInputId id) ;
127 static int FindInputRecord(
128                         XtInputId id) ;
129 static Boolean ProcessInput(
130                         inputrec_t * inp,
131                         int source,
132                         XtInputId id,
133                         Boolean eofFound) ;
134 static int VerifyString_usage( 
135                         char *arg0) ;
136 static int XtSetSensitive_usage( 
137                         char *arg0) ;
138 static int GetDisplayHandle(
139                         int argc,
140                         char **argv,
141                         Widget (*func)());
142 static int RegisterTranslations( 
143                         void (*func)(),
144                         int argc,
145                         char *argv[]) ;
146 static int LocateEHRecord( 
147                         wtab_t *w,
148                         char *ksh_cmd) ;
149 static int GetWorkspaceList( 
150                         char *usageMsg,
151                         Boolean getOccupied,
152                         int argc,
153                         char *argv[]) ;
154 static int DtTurnOnOrOffHourGlass( 
155                         void (*func)(),
156                         int argc,
157                         char *argv[]) ;
158 static int WsmCommonProc(
159                         int argc,
160                         char *argv[],
161                         void (*func)());
162 static int ttdt_SaveOrRevert(
163                         Tt_status (*func)(),
164                         int argc,
165                         char *argv[] ) ;
166 static int message_DestroyOrReply( 
167                         Tt_status (*func)(),
168                         int argc,
169                         char *argv[] );
170 static int message_FailOrReject( 
171                         Tt_status (*func)(),
172                         int argc,
173                         char *argv[] );
174 static Tt_message TtFileCB(
175                         Tt_message msg,
176                         Tttk_op op,
177                         char * pathName,
178                         void * clientData,
179                         int sameEuidEgid,
180                         int sameProcId ) ;
181 static int tt_netfile_handler( 
182                         int paramCount,
183                         char * (*func)(),
184                         char * usageMsg,
185                         int argc,
186                         char *argv[] ) ;
187 static Namval_t * CreateEmptyNameValuePair( 
188                         Namval_t *np,
189                         char *name,
190                         Namfun_t *fp) ;
191 static Namval_t * ProcessIntValue( 
192                         int value,
193                         Namval_t *np,
194                         char *name,
195                         Namfun_t *fp,
196                         char *format,
197                         Namfun_t *fp_new) ;
198 static Namval_t * ProcessStringValue( 
199                         char *value,
200                         Namval_t *np,
201                         char *name,
202                         Namfun_t *fp) ;
203 static Namval_t * ProcessBooleanIntValue( 
204                         int value,
205                         Namval_t *np,
206                         char *name,
207                         Namfun_t *fp,
208                         Namfun_t *fp_new) ;
209 static Namval_t * ProcessTraversalDirection( 
210                         XmTraversalDirection dir,
211                         Namval_t *np,
212                         char *name,
213                         Namfun_t *fp) ;
214 static Namval_t * ProcessSelectionType( 
215                         char selType,
216                         Namval_t *np,
217                         char *name,
218                         Namfun_t *fp) ;
219 static Namval_t * ProcessIntTable( 
220                         int *table,
221                         int count,
222                         Namval_t *np,
223                         char *name,
224                         Namfun_t *fp) ;
225 static Namval_t * ProcessXmStringTable( 
226                         XmString *table,
227                         int count,
228                         Namval_t *np,
229                         char *name,
230                         Namfun_t *fp) ;
231 static Namval_t * ProcessWidgetHandle( 
232                         Widget handle,
233                         Namval_t *np,
234                         char *name,
235                         Namfun_t *fp) ;
236 static Namval_t * ProcessXmStringValue( 
237                         XmString xmstring,
238                         Namval_t *np,
239                         char *name,
240                         Namfun_t *fp) ;
241 static Namval_t * ProcessHyperType( 
242                         int hyperType,
243                         Namval_t *np,
244                         char *name,
245                         Namfun_t *fp) ;
246 static void InitEventTables( void ) ;
247 static Namval_t * ProcessCallbackEvent( 
248                         XEvent *event,
249                         Namval_t *np,
250                         char *name,
251                         Namfun_t *fp) ;
252 static Namval_t * _IntProcessCallbackReason( 
253                         struct named_integer *table,
254                         XmAnyCallbackStruct *cbData,
255                         Namval_t *np,
256                         char *name,
257                         Namfun_t *fp) ;
258 static Namval_t * ProcessCallbackReason( 
259                         XmAnyCallbackStruct *cbData,
260                         Namval_t *np,
261                         char *name,
262                         Namfun_t *fp) ;
263 static Namval_t * ProcessHelpCallbackReason( 
264                         XmAnyCallbackStruct *cbData,
265                         Namval_t *np,
266                         char *name,
267                         Namfun_t *fp) ;
268 static void _DtActionInvokeUsage( void ) ;
269 static void DtkReloadHandler( 
270                         XtPointer clientData ) ;
271 static Namfun_t * CloneDiscipline(
272                         Namdisc_t * discipline );
273 static void FreeDiscipline(
274                         Namfun_t * discipline );
275 static Namdisc_t * CheckClassDisciplines(
276                         WidgetClass class,
277                         char *cbname) ;
278 void SetTextDoit(
279                         Namval_t *np,
280                         char *name,
281                         Namfun_t *fp);
282 void SetTextStartPos(
283                         Namval_t *np,
284                         char *name,
285                         Namfun_t *fp);
286 void SetTextEndPos(
287                         Namval_t *np,
288                         char *name,
289                         Namfun_t *fp);
290 void SetTextPtr(
291                         Namval_t *np,
292                         char *name,
293                         Namfun_t *fp);
294 void SetTextLen(
295                         Namval_t *np,
296                         char *name,
297                         Namfun_t *fp);
298 void SetTextFormat(
299                         Namval_t *np,
300                         char *name,
301                         Namfun_t *fp);
302 void SetTextWCSptr(
303                         Namval_t *np,
304                         char *name,
305                         Namfun_t *fp);
306 void SetTextWCSlen(
307                         Namval_t *np,
308                         char *name,
309                         Namfun_t *fp);
310
311
312
313 #define CLEAR_AREA        0
314 #define CLEAR_WINDOW      1
315 #define DRAW_ARC          2
316 #define DRAW_IMAGE_STRING 3
317 #define DRAW_LINE         4
318 #define DRAW_LINES        5
319 #define DRAW_POINT        6
320 #define DRAW_POINTS       7
321 #define DRAW_RECTANGLE    8
322 #define DRAW_SEGMENTS     9
323 #define DRAW_STRING       10
324 #define FILL_ARC          11
325 #define FILL_POLYGON      12
326 #define FILL_RECTANGLE    13
327 #define COPY_AREA         14
328
329 #define WORKPROC_CMDS     0
330 #define TIMEOUT_CMDS      1
331
332
333 #define MAXARGS 4096
334 #define SLISTITEMSIZE   16
335
336 Widget Toplevel;
337 Boolean invalidFont;
338
339 /* List of all name/value pairs created during handling of a callback */
340 Namval_t *** npTable = NULL;
341 int npTableSize = 0;
342 int * npListSizes = NULL;
343 int nestingLevel = -1;
344
345 static Namdisc_t transDiscipline ={0, NULL, NULL, NULL, NULL, 
346                                   (Namval_t *(*)())transCreateDisc, NULL, NULL};
347 static Namdisc_t ehDiscipline = {0, NULL, NULL, NULL, NULL, 
348                                   (Namval_t *(*)())ehCreateDisc, NULL, NULL};
349 static Namdisc_t dftDiscipline = {0, NULL, NULL, NULL, NULL, 
350                                   (Namval_t *(*)())dftCreateDisc, NULL, NULL};
351 static Namdisc_t nopDiscipline = {0, NULL, NULL, NULL, NULL, 
352                                   (Namval_t *(*)())nopCreateDisc, NULL, NULL};
353
354 static Namdisc_t text_doit_disc = {0, (void (*)())SetTextDoit, NULL, NULL, NULL,
355                                   NULL, NULL, NULL};
356 static Namdisc_t text_startpos_disc = {0, (void (*)())SetTextStartPos, NULL, 
357                                   NULL, NULL,NULL, NULL, NULL};
358 static Namdisc_t text_endpos_disc = {0, (void (*)())SetTextEndPos, NULL, NULL, 
359                                   NULL, NULL, NULL, NULL};
360 static Namdisc_t text_ptr_disc = {0, (void (*)())SetTextPtr, NULL, NULL, NULL,
361                                   NULL, NULL, NULL};
362 static Namdisc_t text_len_disc = {0, (void (*)())SetTextLen, NULL, NULL, NULL,
363                                   NULL, NULL, NULL};
364 static Namdisc_t text_format_disc = {0, (void (*)())SetTextFormat, NULL, NULL, 
365                                   NULL, NULL, NULL, NULL};
366 static Namdisc_t text_wcsptr_disc = {0, (void (*)())SetTextWCSptr, NULL, NULL, 
367                                   NULL, NULL, NULL, NULL};
368 static Namdisc_t text_wcslen_disc = {0, (void (*)())SetTextWCSlen, NULL, NULL, 
369                                   NULL, NULL, NULL, NULL};
370
371 static const XtActionsRec Ksh_actions[] = {
372         { "ksh_eval",   Translation_ksh_eval }
373 };
374
375 static dtksh_client_data_t ** cbDataTable = NULL;
376 static int cbDataTableSize = 0;
377 static dtksh_event_handler_data_t ** ehDataTable = NULL;
378 static int ehDataTableSize = 0;
379
380 static char * str_XtRString = XtRString;
381
382 char str_s_eq_s[] = "%s=%s";
383 char str_s_eq[] = "%s=";
384 char str_nill[] = "";
385
386 typedef struct
387 {
388    int state;
389    Window icon;
390 } WmStateData;
391
392 typedef struct
393 {
394    long id;
395    char * cmd;
396 } CommandString;
397
398 CommandString * workProcCmds = NULL;
399 int workProcCmdsSize = 0;
400 CommandString * timeOutCmds = NULL;
401 int timeOutCmdsSize = 0;
402
403
404 typedef struct {
405    char * ksh_cmd;
406    Tt_pattern * patterns;
407 } Ttdt_file_cb_data;
408
409 Ttdt_file_cb_data ** fileCBList = 0;
410 int sizeFileCBList = 0;
411
412 typedef struct {
413    char * fieldName;
414    char * representation;
415    Cardinal valueOffset;
416    Cardinal valueSize;
417 } EventEntryTable;
418
419 typedef struct {
420    char * eventType;
421    EventEntryTable * table;
422 } XEventTable;
423
424
425 /* Keeps track of file input generated by XtAddInput() */
426 typedef struct {
427    Boolean inUse;
428    XtInputId id;
429    inputrec_t * inp;
430 } InputRecord;
431
432 InputRecord * activeInputs = NULL;
433 int numActiveInputs = 0;
434
435
436
437 /*
438  * When we are notified that a widget is being destroyed (through the
439  * widget's destroy callback, it is not yet safe for us to remove all
440  * internal knowledge of that widget, because the shell script may have
441  * also added a destroy callback, which gets call AFTER ours.  Therefore,
442  * all we can do is mark the widget as 'pending destroy', and add a 
443  * workproc; the workproc will then take care of removing the widget.
444  */
445
446 static Boolean workProcAdded = False;
447
448 static void
449 PendingDestroy(
450         Widget w,
451         wtab_t *wtab,
452         caddr_t callData )
453 {
454    wtab->mask |= DT_PENDING_DESTROY;
455    if (!workProcAdded)
456    {
457       workProcAdded = True;
458       XtAddWorkProc((XtWorkProc)WtabDestroy, NULL);
459    }
460 }
461
462
463 static Boolean
464 WtabDestroy(
465         caddr_t callData )
466 {
467    int i;
468
469    for (i = 0; i < NumW; i++)
470    {
471       if ((W[i]->type == TAB_WIDGET) && (W[i]->mask & DT_PENDING_DESTROY))
472       {
473          XtFree(W[i]->wname);
474          XtFree(W[i]->widid);
475          if (W[i]->envar) {
476                 char *val = env_get(W[i]->envar);
477
478                 /*
479                  * Blank out the environment variable holding the
480                  * widget handle, but only if it still holds the
481                  * handle!  This guards against the possibility that
482                  * the user has re-used the same variable for another
483                  * widget later.
484                  */
485                 if (val && W[i]->widid && strcmp(val, W[i]->widid) == 0) {
486                         env_blank(W[i]->envar);
487                 }
488                 XtFree(W[i]->envar);
489          }
490          W[i]->type = TAB_EMPTY;
491          Wtab_free++;
492       }
493    }
494
495    workProcAdded = False;
496    return(True);
497 }
498
499 wtab_t *
500 set_up_w(
501         Widget wid,
502         wtab_t *parent,
503         char *var,
504         char *name,
505         classtab_t *class )
506 {
507         char widid[8];
508         static wtab_t *w;
509
510         get_new_wtab(&w, widid);
511         if (var) {
512                 env_set_var(var, widid);
513                 w->envar = strdup(var);
514         } else {
515                 w->envar = strdup("none");
516         }
517         w->type = TAB_WIDGET;
518         w->wname = name ? strdup(name) : strdup(XtName(wid));
519         w->wclass = class;
520         w->parent = parent;
521         w->widid = strdup(widid);
522         w->w = wid;
523         w->mask = 0;
524         XtAddCallback(wid, XtNdestroyCallback, (XtCallbackProc)PendingDestroy, 
525                       (caddr_t)w);
526         return(w);
527 }
528
529 static short Needfree[MAXARGS];
530
531 void
532 parse_args(
533         char *arg0,
534         int argc,
535         char **argv,
536         wtab_t *w,
537         wtab_t *parent,
538         classtab_t *class,
539         int *n,
540         Arg *args,
541         int * pargc,
542         char ** pargv ,
543         Boolean postponePixmaps )
544 {
545         int i;
546         char *colon, *resource, *val, *p;
547         XtArgVal argval;
548         int freeflag, len;
549         char * errmsg;
550         int conversionResult;
551
552         if (pargc)
553                 (*pargc) = 0;
554         *n = 0;
555         for (i = 0; i < argc; i++) {
556                 if (i >= MAXARGS) {
557                         errmsg = strdup(GETMESSAGE(5,1, 
558                                       "Too many resource parameters have been specified; skipping '%s'"));
559                         printerrf(arg0, errmsg,
560                                  argv[*n], NULL, NULL, NULL, NULL, NULL,
561                                  NULL, NULL);
562                         free(errmsg);
563                         continue;
564                 }
565                 if ((colon = strchr(argv[i], ':')) == NULL)
566                 {
567                         errmsg = strdup(GETMESSAGE(5,2, 
568                                 "Bad resource specification; should be of the form 'name:value' : %s"));
569                         printerrf(arg0, errmsg,
570                              argv[i], NULL, NULL, NULL, NULL, NULL, NULL, NULL);
571                         free(errmsg);
572                         continue;
573                 }
574                 val = &colon[1];
575                 len = colon - argv[i];
576                 resource = XtMalloc(len + 1);
577                 strncpy(resource, argv[i], len);
578                 resource[len] = '\0';
579
580                 /*
581                  * The following special check fixes a bug in Xt, where the
582                  * string defined for the XmNwaitForWm resource does not
583                  * follow the naming conventions, and is set to "waitforwm".
584                  * In dtksh, users expect the naming conventions to be
585                  * followed, and this breaks for this one resource.
586                  */
587                 if (strcmp(resource, "waitForWm") == 0)
588                         strcpy(resource, XmNwaitForWm);
589
590                 if ((conversionResult = ConvertStringToType(arg0, w, parent, 
591                         class, resource, val, &argval, &freeflag, 
592                         postponePixmaps)) == CONVERT_SUCCEEDED) 
593                 {
594                         XtSetArg(args[*n], resource, argval);
595
596                         /* 
597                          * The following is a memory leak, but it allows us to
598                          * comply with what Xt has spec'ed as the required
599                          * behavior of the geometry string (It is a bogus
600                          * requirement!).  The Xt Shell widget does not make 
601                          * a copy of the incoming 'geometry' string, but 
602                          * instead, simply keeps a pointer to the string 
603                          * passed-in by the application.  For dtksh, this is 
604                          * a problem, because we would typically free up the 
605                          * string right away.  This hack causes us to not free 
606                          * up the string.
607                          */
608                         if (strcmp(resource, XmNgeometry) == 0)
609                            Needfree[*n] = False;
610                         else
611                            Needfree[*n] = freeflag;
612
613                         (*n)++;
614                 }
615                 else if (conversionResult == CONVERT_POSTPONED)
616                 {
617                         /*
618                          * Postpone processing this resource until after the
619                          * the widget has been created, or, in the case of a
620                          * pixmap resource, until any new colors have been set.
621                          */
622                         if (pargc)
623                         {
624                                 pargv[*pargc] = argv[i];
625                                 (*pargc)++;
626                         }
627                         XtFree(resource);
628                 }
629                 else
630                 {
631                         XtFree(resource);
632                 }
633         }
634 }
635
636 void
637 free_args(
638         int n,
639         Arg *args )
640 {
641         int i;
642
643         /*
644          * Free up argument pointers
645          */
646         for (i = 0; i < n; i++) {
647                 XtFree(args[i].name);
648                 if (Needfree[i]) {
649                         XtFree((String)args[i].value);
650                 }
651         }
652 }
653
654
655 int
656 do_XtInitialize(
657         int argc,
658         char *argv[] )
659 {
660         int ret;
661         char *dtkdb_hook;
662         char * errmsg;
663         int * lockedFds;
664
665         if (Toplevel != NULL)
666         {
667                 errmsg = strdup(GETMESSAGE(5,4, 
668                             "The toolkit has already been initialized"));
669                 printerr(argv[0], errmsg, NULL);
670                 free(errmsg);
671                 return(1);
672         }
673
674         if (argc < 4) {
675            errmsg =strdup(GETMESSAGE(5,5, 
676                       "Usage: XtInitialize variable applicationName applicationClass [args ...]"));
677            printerr(str_nill, errmsg, NULL);
678            free(errmsg);
679            return(1);
680         }
681         lockedFds = LockKshFileDescriptors();
682         ret = toolkit_initialize(argc, argv);
683         UnlockKshFileDescriptors(lockedFds);
684         XtAddActions((XtActionList)Ksh_actions, XtNumber(Ksh_actions));
685         if ((dtkdb_hook = env_get("DTKDB_HOOK")) != NULL) {
686                 ksh_eval(dtkdb_hook);
687         }
688         return(ret);
689 }
690
691 static int
692 _CreateWidget(
693         Widget (*func)(),
694         int argc,
695         char *argv[] )
696 {
697         Widget widget;
698         classtab_t *class;
699         char *arg0 = argv[0];
700         wtab_t *w, *pw, *wtab;
701         char *wname, *wclass, *parentid, *var;
702         Arg     args[MAXARGS];
703         int     i;
704         int n;
705         char * errmsg;
706         int pargc;
707         char ** pargv;
708
709         if (argc < 5) {
710                 errmsg = strdup(GETMESSAGE(5,6, 
711                         "Usage: %s variable name class parent [arg:val ...]"));
712                 printerrf(str_nill, errmsg,
713                   argv[0], NULL, NULL, NULL, NULL, NULL, NULL, NULL);
714                 free(errmsg);
715                 return(1);
716         }
717         var = argv[1];
718         wname = argv[2];
719         wclass = argv[3];
720         parentid = argv[4];
721         pw = str_to_wtab(argv[0], parentid);
722         if (pw == NULL) {
723                 errmsg = strdup(GetSharedMsg(DT_NO_PARENT));
724                 printerr(argv[0], errmsg, NULL);
725                 free(errmsg);
726                 return(1);
727         }
728         argv += 5;
729         argc -= 5;
730         if ((class = str_to_class(arg0, wclass)) == NULL) {
731                 return(1);
732         }
733         pargc = 0;
734         if (argc > 0) { 
735                 pargv = (char **)XtMalloc(sizeof(char *) * argc);
736         }
737         else {
738                 pargv = NULL;
739         }
740         n = 0;
741         parse_args(arg0, argc, argv, NULL, pw, class, &n, args, &pargc, pargv,
742                    True);
743         widget = func(wname, class->class, pw->w, args, n);
744         if (widget != NULL) {
745                 wtab = set_up_w(widget, pw, var, wname, class);
746
747                 /* Process any postponed resources */
748                 if (pargc > 0)
749                 {
750                         free_args(n, args);
751                         n = 0;
752                         parse_args(arg0, pargc, pargv, wtab, pw, class, &n, 
753                                    args, NULL, NULL, False);
754                         XtSetValues(widget, args, n);
755                 }
756         } else {
757                 errmsg = strdup(GetSharedMsg(DT_WIDGET_CREATE_FAILED));
758                 printerrf(argv[0], errmsg, wname, 
759                          NULL, NULL, NULL, NULL, NULL, NULL, NULL);
760                 free(errmsg);
761                 env_blank(argv[1]);
762         }
763         free_args(n, args);
764         XtFree((char *)pargv);
765
766         return(0);
767 }
768
769 int
770 do_XtCreateApplicationShell(
771         int argc,
772         char *argv[] )
773 {
774         Widget widget;
775         classtab_t *class;
776         char *arg0 = argv[0];
777         wtab_t *w, *wtab;
778         char *wname, *wclass, *var;
779         Arg     args[MAXARGS];
780         int     i;
781         int n;
782         char * errmsg;
783         int pargc;
784         char ** pargv;
785
786         if (argc < 4) {
787            errmsg=strdup(GETMESSAGE(5,7, 
788                     "Usage: XtCreateApplicationShell variable name class [arg:val ...]"));
789            printerr(str_nill, errmsg, NULL);
790            free(errmsg);
791            return(1);
792         }
793         var = argv[1];
794         wname = argv[2];
795         wclass = argv[3];
796         argv += 4;
797         argc -= 4;
798         if ((class = str_to_class(arg0, wclass)) == NULL) {
799                 return(1);
800         }
801         pargc = 0;
802         if (argc > 0) {
803                 pargv = (char **)XtMalloc(sizeof(char *) * argc);
804         }
805         else {
806                 pargv = NULL;
807         }
808         n = 0;
809         parse_args(arg0, argc, argv, NULL, NULL, class, &n, args, &pargc,
810                    pargv, True);
811         widget = XtCreateApplicationShell(wname, class->class, args, n);
812         if (widget != NULL) {
813                 wtab = set_up_w(widget, NULL, var, wname, class);
814         
815                 /* Process any postponed resources */
816                 if (pargc > 0)
817                 {
818                         free_args(n, args);
819                         n = 0;
820                         parse_args(arg0, pargc, pargv, wtab, NULL, class, 
821                                    &n, args, NULL, NULL, False);
822                         XtSetValues(widget, args, n);
823                 }
824         } else {
825                 errmsg = strdup(GetSharedMsg(DT_WIDGET_CREATE_FAILED));
826                 printerrf(argv[0], errmsg, wname,
827                          NULL, NULL, NULL, NULL, NULL, NULL, NULL);
828                 free(errmsg);
829                 env_blank(argv[1]);
830         }
831         free_args(n, args);
832         XtFree((char *)pargv);
833
834         return(0);
835 }
836
837 int
838 do_XtCreatePopupShell(
839         int argc,
840         char *argv[] )
841 {
842         return(_CreateWidget(XtCreatePopupShell, argc, argv));
843 }
844
845 int
846 do_XtCreateManagedWidget(
847         int argc,
848         char *argv[] )
849 {
850         return(_CreateWidget(XtCreateManagedWidget, argc, argv));
851 }
852
853 int
854 do_XtCreateWidget(
855         int argc,
856         char *argv[] )
857 {
858         return(_CreateWidget(XtCreateWidget, argc, argv));
859 }
860
861 int
862 do_XtPopup(
863         int argc,
864         char *argv[] )
865 {
866    wtab_t *w;
867    XtGrabKind grab;
868    char * errmsg;
869
870    if (argc != 3) 
871    {
872       errmsg=strdup(GETMESSAGE(5,8, 
873               "Usage: XtPopup widget GrabNone|GrabNonexclusive|GrabExclusive"));
874       printerr(str_nill, errmsg, NULL);
875       free(errmsg);
876       return(1);
877    }
878    w = str_to_wtab(argv[0], argv[1]);
879    if (w == NULL) 
880       return(1);
881    else 
882    {
883       grab = XtGrabNone;
884       if (argc < 3 || strcmp(argv[2], "GrabNone") == 0) 
885          grab = XtGrabNone;
886       else if (strcmp(argv[2], "GrabNonexclusive") == 0) 
887          grab = XtGrabNonexclusive;
888       else if (strcmp(argv[2], "GrabExclusive") == 0) 
889          grab = XtGrabExclusive;
890       else 
891       {
892          errmsg=strdup(GETMESSAGE(5,9, 
893                    "The grab type '%s' is not recognized; using 'GrabNone'"));
894          printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
895                    NULL, NULL);
896          free(errmsg);
897       }
898
899       XtPopup(w->w, grab);
900    }
901    return(0);
902 }
903
904 static int
905 _DTKSH_XtDestroyWidget(
906         Widget w )
907 {
908    XtDestroyWidget(w);
909    return(1);
910 }
911
912 static int
913 do_single_widget_arg_func(
914         int (*func)(),
915         int argc,
916         char **argv )
917 {
918         wtab_t *w;
919         int i;
920         char * errmsg;
921
922         if (argc < 2) {
923                 errmsg = strdup(GetSharedMsg(DT_USAGE_WIDGET));
924                 printerrf(str_nill, errmsg, argv[0], NULL, NULL,
925                          NULL, NULL, NULL, NULL, NULL);
926                 free(errmsg);
927                 return(1);
928         }
929         for (i = 1; i < argc; i++) {
930                 w = str_to_wtab(argv[0], argv[i]);
931                 if (w != NULL) {
932                         func(w->w);
933                 }
934         }
935         return(0);
936 }
937
938 int
939 do_XtDestroyWidget(
940         int argc,
941         char *argv[] )
942 {
943    return(do_single_widget_arg_func(_DTKSH_XtDestroyWidget, argc, argv));
944 }
945
946 int
947 do_single_widget_test_func(
948         int (*func)(),
949         int argc,
950         char **argv )
951 {
952         wtab_t *w;
953         int i;
954         char * errmsg;
955
956         if (argc != 2) {
957                 errmsg=strdup(GetSharedMsg(DT_USAGE_WIDGET));
958                 printerrf(str_nill, errmsg, argv[0], NULL, NULL,
959                           NULL, NULL, NULL, NULL, NULL);
960                 free(errmsg);
961                 return(1);
962         }
963         w = str_to_wtab(argv[0], argv[1]);
964         if (w != NULL) {
965                 return(!func(w->w));
966         }
967         return(255);
968 }
969
970 int
971 do_XtIsSensitive(
972         int argc,
973         char *argv[] )
974 {
975    return(do_single_widget_test_func((int(*)())XtIsSensitive, argc, argv));
976 }
977
978
979 /*
980  * XtIsShell() is a macro, so we can't use do_single_widget_test_func().
981  */
982 int
983 do_XtIsShell(
984         int argc,
985         char *argv[] )
986 {
987    wtab_t *w;
988    int i;
989    char * errmsg;
990
991    if (argc != 2) 
992    {
993       errmsg = strdup(GETMESSAGE(5,10, "Usage: XtIsShell widget"));
994       printerr(str_nill, errmsg, NULL);
995       free(errmsg);
996       return(1);
997    }
998
999    w = str_to_wtab(argv[0], argv[1]);
1000    if (w != NULL) 
1001       return(!XtIsShell(w->w));
1002    return(255);
1003 }
1004
1005 int
1006 do_XtIsManaged(
1007         int argc,
1008         char *argv[] )
1009 {
1010    return(do_single_widget_test_func((int(*)())XtIsManaged, argc, argv));
1011 }
1012
1013 int
1014 do_XtIsRealized(
1015         int argc,
1016         char *argv[] )
1017 {
1018    return(do_single_widget_test_func((int(*)())XtIsRealized, argc, argv));
1019 }
1020
1021 int
1022 do_XtRealizeWidget(
1023         int argc,
1024         char *argv[] )
1025 {
1026    return(do_single_widget_arg_func((int(*)())XtRealizeWidget, argc, argv));
1027 }
1028
1029 int
1030 do_XtUnrealizeWidget(
1031         int argc,
1032         char *argv[] )
1033 {
1034    return(do_single_widget_arg_func((int(*)())XtUnrealizeWidget, argc, argv));
1035 }
1036
1037 /*
1038  * XtMapWidget() is a macro, so can't use do_single_widget_arg_func()
1039  */
1040
1041 int
1042 do_XtMapWidget(
1043         int argc,
1044         char *argv[] )
1045 {
1046         wtab_t *w;
1047         int i;
1048         char * errmsg;
1049
1050         if (argc < 2) {
1051                 errmsg = strdup(GETMESSAGE(5,11, "Usage: XtMapWidget widget"));
1052                 printerr(str_nill, errmsg, NULL);
1053                 free(errmsg);
1054                 return(1);
1055         }
1056         for (i = 1; i < argc; i++) {
1057                 w = str_to_wtab(argv[0], argv[i]);
1058                 if (w != NULL) {
1059                         XtMapWidget(w->w);
1060                 }
1061         }
1062         return(0);
1063 }
1064
1065 int
1066 do_XtUnmapWidget(
1067         int argc,
1068         char **argv )
1069 {
1070         wtab_t *w;
1071         int i;
1072         char * errmsg;
1073
1074         if (argc < 2) {
1075            errmsg = strdup(GETMESSAGE(5,12, "Usage: XtUnmapWidget widget"));
1076            printerr(str_nill, errmsg, NULL);
1077            free(errmsg);
1078            return(1);
1079         }
1080         for (i = 1; i < argc; i++) {
1081                 w = str_to_wtab(argv[0], argv[i]);
1082                 if (w != NULL) {
1083                         XtUnmapWidget(w->w);
1084                 }
1085         }
1086         return(0);
1087 }
1088
1089 int
1090 do_XtPopdown(
1091         int argc,
1092         char **argv )
1093 {
1094    return(do_single_widget_arg_func((int(*)())XtPopdown, argc, argv));
1095 }
1096
1097 int
1098 do_XtMainLoop(
1099         int argc,
1100         char **argv )
1101 {
1102         /* 
1103          * Required to guarantee that all of the shell script's "echo"
1104          * requests have been taken care of, before we drop into the
1105          * the black hole called XtMainLoop.
1106          */
1107         fflush(stdout);
1108
1109         XtMainLoop();
1110         return(1);
1111 }
1112
1113
1114 int
1115 do_XtDisplay(
1116         int argc,
1117         char **argv )
1118 {
1119    return(GetDisplayHandle(argc, argv, (Widget (*)())XtDisplay));
1120 }
1121
1122
1123 int
1124 do_XtDisplayOfObject(
1125         int argc,
1126         char **argv )
1127 {
1128    return(GetDisplayHandle(argc, argv, (Widget (*)())XtDisplayOfObject));
1129 }
1130
1131
1132 static int
1133 GetDisplayHandle(
1134         int argc,
1135         char **argv,
1136         Widget (*func)())
1137 {
1138    wtab_t *w;
1139    char *arg0 = argv[0];
1140    char * variable = argv[1];
1141    char buf[128];
1142    char * errmsg;
1143
1144    if (argc != 3)
1145    {
1146       errmsg = strdup(GETMESSAGE(5,13, "Usage: %s variable widget"));
1147       printerrf(str_nill, errmsg, arg0, NULL, NULL, NULL, NULL, NULL,
1148                 NULL, NULL);
1149       free(errmsg);
1150       return(1);
1151    }
1152
1153    w = str_to_wtab(arg0, argv[2]);
1154    if (w == NULL) 
1155       return(1);
1156
1157    sprintf(buf, "0x%lx", (long)(*func)(w->w));
1158    alt_env_set_var(variable, buf);
1159    return(0);
1160 }
1161
1162
1163 int
1164 do_XtNameToWidget(
1165         int argc,
1166         char *argv[] )
1167 {
1168    char *arg0 = argv[0];
1169    wtab_t * w;
1170    char * variable = argv[1]; 
1171    Widget child;
1172    classtab_t *ctab;
1173    char * errmsg;
1174
1175    if (argc != 4) 
1176    {
1177       errmsg = strdup(GETMESSAGE(5,82, 
1178             "Usage: XtNameToWidget variable referenceWidget names"));
1179       printerr(str_nill, errmsg, NULL);
1180       free(errmsg);
1181       return(1);
1182    }
1183
1184    w = str_to_wtab(arg0, argv[2]);
1185    if (w == NULL) {
1186         alt_env_set_var(variable, str_nill); 
1187         return(1);
1188    }
1189
1190    child = XtNameToWidget(w->w, argv[3]);
1191  
1192    if (child == NULL)
1193    {
1194       alt_env_set_var(variable, str_nill); 
1195       return(1);
1196    }
1197
1198    w = widget_to_wtab(child);
1199    if (w == NULL) {
1200         alt_env_set_var(variable, str_nill); 
1201         return(1);
1202    }
1203    /*
1204     * If the widget class has no resources registered, then this is
1205     * the first known instance of this widget class, so we need to
1206     * force the resource list to be loaded.  This can frequently
1207     * occur if a Motif convenience function is used, which creates
1208     * a 'hidden' parent.
1209     */
1210    ctab = w->wclass;
1211    if (ctab->res == NULL)
1212       (void)str_to_class(arg0, ctab->cname);
1213
1214    alt_env_set_var(variable,  w->widid); 
1215    return(0);
1216 }
1217
1218
1219 int
1220 do_XtScreen(
1221         int argc,
1222         char **argv )
1223 {
1224    wtab_t *w;
1225    char *arg0 = argv[0];
1226    char * variable = argv[1];
1227    char buf[128];
1228    char * errmsg;
1229
1230    if (argc != 3)
1231    {
1232       errmsg = strdup(GETMESSAGE(5,14, "Usage: XtScreen variable widget"));
1233       printerr(str_nill, errmsg, NULL);
1234       free(errmsg);
1235       return(1);
1236    }
1237
1238    w = str_to_wtab(arg0, argv[2]);
1239    if (w == NULL) 
1240       return(1);
1241
1242    sprintf(buf, "0x%lx", (long)XtScreen(w->w));
1243    alt_env_set_var(variable, buf);
1244    return(0);
1245 }
1246
1247
1248 int
1249 do_XtWindow(
1250         int argc,
1251         char **argv )
1252 {
1253    wtab_t *w;
1254    char *arg0 = argv[0];
1255    char * variable = argv[1];
1256    char buf[128];
1257    char * errmsg;
1258
1259    if (argc != 3)
1260    {
1261       errmsg = strdup(GETMESSAGE(5,15, "Usage: XtWindow variable widget"));
1262       printerr(str_nill, errmsg, NULL);
1263       free(errmsg);
1264       return(1);
1265    }
1266
1267    w = str_to_wtab(arg0, argv[2]);
1268    if (w == NULL) 
1269       return(1);
1270
1271    sprintf(buf, "0x%lx", (long)XtWindow(w->w));
1272    alt_env_set_var(variable, buf);
1273    return(0);
1274 }
1275
1276
1277 static int
1278 XtCallCallbacks_usage(
1279         char *arg0 )
1280 {
1281    char * errmsg;
1282
1283    errmsg = strdup(GETMESSAGE(5,16, 
1284                    "Usage: XtCallCallbacks widget callbackName"));
1285    printerr(str_nill, errmsg, NULL);
1286    free(errmsg);
1287    return(1);
1288 }
1289
1290
1291 int
1292 do_XtCallCallbacks(
1293         int argc,
1294         char **argv )
1295 {
1296    wtab_t *w;
1297    char *arg0 = argv[0];
1298
1299    if (argc != 3)
1300       return(XtCallCallbacks_usage(arg0));
1301
1302    w = str_to_wtab(argv[0], argv[1]);
1303    if (w == NULL) 
1304       return(1);
1305    else
1306       XtCallCallbacks(w->w, argv[2], NULL);
1307    return(0);
1308 }
1309
1310
1311 int
1312 do_XtHasCallbacks(
1313         int argc,
1314         char **argv )
1315 {
1316    wtab_t *w;
1317    char *arg0 = argv[0];
1318    char * msg;
1319    char * variable = argv[1];
1320    XtCallbackStatus callbackStatus;
1321    XrmValue fval, tval;
1322    char * errmsg;
1323
1324    if (argc != 4)
1325    {
1326       errmsg = strdup(GETMESSAGE(5,17, 
1327                    "Usage: XtHasCallbacks variable widget callbackName"));
1328       printerr(str_nill, errmsg, NULL);
1329       free(errmsg);
1330       return(1);
1331    }
1332
1333    w = str_to_wtab(argv[0], argv[2]);
1334    if (w == NULL) 
1335       return(1);
1336    else
1337       callbackStatus = XtHasCallbacks(w->w, argv[3]);
1338
1339    switch (callbackStatus)
1340    {
1341       case XtCallbackNoList:
1342       {
1343          msg = "CallbackNoList";
1344          break;
1345       }
1346       case XtCallbackHasNone:
1347       {
1348          msg = "CallbackHasNone";
1349          break;
1350       }
1351       case XtCallbackHasSome:
1352       {
1353          msg = "CallbackHasSome";
1354          break;
1355       }
1356    }
1357    alt_env_set_var(variable, msg);
1358    return(0);
1359 }
1360
1361 int
1362 do_XtAddCallback(
1363         int argc,
1364         char **argv )
1365 {
1366    char * errmsg;
1367
1368    if (argc != 4)
1369    {
1370       errmsg = strdup(GETMESSAGE(5,18, 
1371                   "Usage: XtAddCallback widget callbackName ksh-command"));
1372       printerr(str_nill, errmsg, NULL);
1373       free(errmsg);
1374       return(1);
1375    }
1376
1377    return(AddOneCallback(argv[0], argv[1], argv[2], argv[3], NULL));
1378 }
1379
1380
1381 /*
1382  * This function is used to add both regular Xt Callbacks, and
1383  * Motif WMProtocol callback.
1384  */
1385 int
1386 AddOneCallback(
1387         char *cmd,
1388         char *widget,
1389         char *cbName,
1390         char *kshcmd,
1391         char *propAtomStr )
1392 {
1393    wtab_t *w;
1394    dtksh_client_data_t *cdata;
1395    char * p;
1396    Atom propAtom;
1397    char * errmsg;
1398
1399    w = str_to_wtab(cmd, widget);
1400    if (w == NULL) 
1401       return(1);
1402
1403    if (propAtomStr)
1404    {
1405       propAtom = (Atom)strtoul(propAtomStr, &p, 0);
1406       if (p == propAtomStr)
1407       {
1408          errmsg = strdup(GetSharedMsg(DT_BAD_ATOM));
1409          printerrf(cmd, errmsg, propAtomStr, NULL, NULL, NULL, NULL, NULL,
1410                    NULL, NULL);
1411          free(errmsg);
1412          return(1);
1413       }
1414    }
1415    else
1416       propAtom = None;
1417
1418    cdata = GetNewCBData(kshcmd, w, cbName, propAtom);
1419
1420    if (strcmp(cmd, "XtAddCallback") == 0)
1421       XtAddCallback(w->w, cbName, (XtCallbackProc)stdCB, (XtPointer)cdata);
1422    else
1423    {
1424       XmAddWMProtocolCallback(w->w, propAtom, (XtCallbackProc)stdCB, 
1425                               (XtPointer)cdata);
1426    }
1427
1428    return(0);
1429 }
1430
1431 int
1432 do_XtRemoveCallback(
1433         int argc,
1434         char **argv )
1435 {
1436    char * errmsg;
1437
1438    if (argc != 4)
1439    {
1440       errmsg = strdup(GETMESSAGE(5,19, 
1441                   "Usage: XtRemoveCallback widget callbackName ksh-command"));
1442       printerr(str_nill, errmsg, NULL);
1443       free(errmsg);
1444       return(1);
1445    }
1446
1447    return(RemoveOneCallback (argv[0], argv[1], argv[2], argv[3], NULL, NULL));
1448 }
1449
1450 /*
1451  * This function is used to delete both regular Xt Callbacks, and
1452  * Motif WMProtocol callback.
1453  */
1454 int
1455 RemoveOneCallback(
1456         char *cmd,
1457         char *widget,
1458         char *cbName,
1459         char *kshcmd,
1460         char *propAtomStr,
1461         char *handleStr )
1462 {
1463    wtab_t *w;
1464    dtksh_client_data_t *cdata;
1465    int i;
1466    Atom propAtom;
1467    char * p;
1468    DtWsmCBContext handle;
1469    char * errmsg;
1470
1471    w = str_to_wtab(cmd, widget);
1472    if (w == NULL) 
1473       return(1);
1474
1475    if (propAtomStr)
1476    {
1477       propAtom = (Atom)strtoul(propAtomStr, &p, 0);
1478       if (p == propAtomStr)
1479       {
1480          errmsg = strdup(GetSharedMsg(DT_BAD_ATOM));
1481          printerrf(cmd, errmsg, propAtomStr, NULL, NULL, NULL, NULL, NULL,
1482                    NULL, NULL);
1483          free(errmsg);
1484          return(1);
1485       }
1486    }
1487    else
1488       propAtom = None;
1489
1490    if (handleStr)
1491    {
1492       handle = (DtWsmCBContext)strtoul(handleStr, &p, 0);
1493       if (p == handleStr)
1494       {
1495          errmsg = strdup(GETMESSAGE(5,20, 
1496                       "The following is an invalid callback handle: %s"));
1497          printerrf(cmd, errmsg, handleStr, NULL, NULL, NULL, NULL, NULL,
1498                    NULL, NULL);
1499          free(errmsg);
1500          return(1);
1501       }
1502    }
1503    else
1504       handle = NULL;
1505
1506    /* Locate the matching table entry */
1507    if ((i = LocateCBRecord (w, cbName, kshcmd, propAtom, handle)) >= 0)
1508    {
1509       cdata = cbDataTable[i];
1510       if (strcmp(cmd, "XtRemoveCallback") == 0)
1511          XtRemoveCallback(w->w, cbName, (XtCallbackProc)stdCB,(XtPointer)cdata);
1512       else if (strcmp(cmd, "XmRemoveWMProtocolCallback") == 0)
1513       {
1514          XmRemoveWMProtocolCallback(w->w, propAtom, (XtCallbackProc)stdCB, 
1515                                     (XtPointer)cdata);
1516       }
1517       else 
1518       {
1519          DtWsmRemoveWorkspaceCallback(handle);
1520       }
1521
1522       if (--(cdata->refCount) <= 0)
1523       {
1524          XtFree(cdata->ksh_cmd);
1525          XtFree(cdata->cbname);
1526          XtFree((XtPointer)cdata);
1527          cbDataTable[i] = NULL;
1528          return(0);
1529       }
1530
1531       return(0);
1532    }
1533
1534    errmsg = strdup(GETMESSAGE(5,21, 
1535             "The specified callback is not registered"));
1536    printerr(cmd, errmsg, NULL);
1537    free(errmsg);
1538    return(1);
1539 }
1540
1541 int
1542 do_XtAddEventHandler(
1543         int argc,
1544         char **argv )
1545 {
1546    wtab_t *w;
1547    char *arg0 = argv[0];
1548    dtksh_event_handler_data_t *ehdata;
1549    Boolean nonMaskable;
1550    EventMask eventMask;
1551    XrmValue fval, tval;
1552    char * errmsg;
1553
1554    if (argc != 5)
1555    {
1556       errmsg=strdup(GETMESSAGE(5,22, 
1557                "Usage: XtAddEventHandler widget mask nonMaskable ksh-command"));
1558       printerr(str_nill, errmsg, NULL);
1559       free(errmsg);
1560       return(1);
1561    }
1562
1563    w = str_to_wtab(arg0, argv[1]);
1564    if (w == NULL) 
1565       return(1);
1566
1567    fval.addr = argv[3];
1568    fval.size = strlen(argv[3]);
1569    XtConvert(Toplevel, XtRString, &fval, XtRBoolean, &tval);
1570
1571    if (tval.size != 0) 
1572       nonMaskable = *((Boolean *)(tval.addr));
1573    else
1574       return(1);
1575
1576    fval.addr = argv[2];
1577    fval.size = strlen(argv[2]);
1578    XtConvert(Toplevel, XtRString, &fval, "EventMask", &tval);
1579
1580    if (tval.size != 0) 
1581       eventMask = *((EventMask *)(tval.addr));
1582    else
1583       return(1);
1584
1585    if ((eventMask == 0) && (nonMaskable == False))
1586       return(1);
1587
1588    ehdata = GetNewEHData(argv[4], w, eventMask, nonMaskable);
1589
1590    XtAddEventHandler(w->w, eventMask, nonMaskable, (XtEventHandler)stdEH, 
1591                      (XtPointer)ehdata);
1592
1593    return(0);
1594 }
1595
1596 int
1597 do_XtRemoveEventHandler(
1598         int argc,
1599         char **argv )
1600 {
1601    wtab_t *w;
1602    char *arg0 = argv[0];
1603    dtksh_event_handler_data_t *ehdata;
1604    int i;
1605    Boolean nonMaskable;
1606    EventMask eventMask;
1607    XrmValue fval, tval;
1608    char * errmsg;
1609
1610    if (argc != 5)
1611    {
1612       errmsg =strdup(GETMESSAGE(5,23, 
1613             "Usage: XtRemoveEventHandler widget mask nonMaskable ksh-command"));
1614       printerr(str_nill, errmsg, NULL);
1615       free(errmsg);
1616       return(1);
1617    }
1618
1619    w = str_to_wtab(arg0, argv[1]);
1620    if (w == NULL) 
1621       return(1);
1622
1623    /* Locate the matching table entry */
1624    if ((i = LocateEHRecord (w, argv[4])) >= 0)
1625    {
1626       ehdata = ehDataTable[i];
1627
1628       fval.addr = argv[3];
1629       fval.size = strlen(argv[3]);
1630       XtConvert(Toplevel, XtRString, &fval, XtRBoolean, &tval);
1631
1632       if (tval.size != 0) 
1633       {
1634          nonMaskable = *((Boolean *)(tval.addr));
1635
1636          /* See if non-maskable event processing has been turned off */
1637          if (nonMaskable)
1638             ehdata->nonMaskable = False;
1639       }
1640       else
1641          return(1);
1642
1643       fval.addr = argv[2];
1644       fval.size = strlen(argv[2]);
1645       XtConvert(Toplevel, XtRString, &fval, "EventMask", &tval);
1646
1647       if (tval.size != 0) 
1648       {
1649          eventMask = *((EventMask *)(tval.addr));
1650
1651          /* Disable the specified set of events */
1652          ehdata->eventMask &= ~eventMask;
1653       }
1654       else
1655          return(1);
1656
1657       XtRemoveEventHandler (w->w, eventMask, nonMaskable, (XtEventHandler)stdEH,
1658                             (XtPointer)ehdata);
1659
1660       if ((ehdata->eventMask == 0) && (ehdata->nonMaskable == False))
1661       {
1662          /* It is now safe to remove this entry */
1663          XtFree(ehdata->ksh_cmd);
1664          XtFree((XtPointer)ehdata);
1665          ehDataTable[i] = NULL;
1666          return(0);
1667       }
1668
1669       return(0);
1670    }
1671
1672    errmsg = strdup(GETMESSAGE(5,24, 
1673                    "The specified event handler is not registered"));
1674    printerr(arg0, errmsg, NULL);
1675    free(errmsg);
1676    return(1);
1677 }
1678
1679 int
1680 do_XtGetValues(
1681         int argc,
1682         char **argv )
1683 {
1684         int i, j;
1685         int n;
1686         char *arg0 = argv[0];
1687         char *val, *p, *str;
1688         Arg args[MAXARGS];
1689         char *envar[MAXARGS];
1690         wtab_t *w;
1691         char * errmsg;
1692
1693         if (argc < 3) {
1694                 errmsg = strdup(GETMESSAGE(5,25, 
1695                         "Usage: XtGetValues widget resource:variable ..."));
1696                 printerr(str_nill, errmsg, NULL);
1697                 free(errmsg);
1698                 return(1);
1699         }
1700         w = str_to_wtab(argv[0], argv[1]);
1701         argv += 2;
1702         argc -= 2;
1703         if (w == NULL) {
1704                 return(1);
1705         }
1706         /*
1707          * Arguments are of the form:
1708          *
1709          *     resource:envar
1710          */
1711
1712         for (i = 0, n = 0; i < argc; i++) {
1713                 if ((p = strchr(argv[i], ':')) == NULL) {
1714                         errmsg=strdup(GETMESSAGE(5,26, 
1715                                 "The following resource parameter is incorrectly formed: %s"));
1716                         printerrf(arg0, errmsg, argv[i],
1717                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1718                         free(errmsg);
1719                         continue;
1720                 }
1721                 *p = '\0';
1722
1723                 /*
1724                  * The following special check fixes a bug in Xt, where the
1725                  * string defined for the XmNwaitForWm resource does not
1726                  * follow the naming conventions, and is set to "waitforwm".
1727                  * In dtksh, users expect the naming conventions to be
1728                  * followed, and this breaks for this one resource.
1729                  */
1730                 if (strcmp(argv[n], "waitForWm") == 0)
1731                         args[n].name = strdup(XmNwaitForWm);
1732                 else
1733                         args[n].name = strdup(argv[n]);
1734
1735                 envar[n] = &p[1];
1736                 *p = ':';
1737                 args[n].value = (XtArgVal)stakalloc(256);
1738                 n++;
1739         }
1740         XtGetValues(w->w, args, n);
1741         for (i = 0; i < n; i++) {
1742                 if (ConvertTypeToString(arg0, w->wclass, w, w->parent, args[i].name, args[i].value, &str) != FAIL) {
1743                         env_set_var(envar[i], str);
1744                 }
1745                 else
1746                         env_blank(envar[i]);
1747                 XtFree(args[i].name);
1748         }
1749         return(0);
1750 }
1751
1752 int
1753 do_XtSetValues(
1754         int argc,
1755         char **argv )
1756 {
1757         int n;
1758         char *arg0 = argv[0];
1759         Arg args[MAXARGS];
1760         wtab_t *w;
1761         char * errmsg;
1762         int pargc;
1763         char ** pargv;
1764
1765         if (argc < 3) {
1766                 errmsg = strdup(GETMESSAGE(5,27, 
1767                             "Usage: XtSetValues widget arg:val ..."));
1768                 printerr(str_nill, errmsg, NULL);
1769                 free(errmsg);
1770                 return(1);
1771         }
1772         w = str_to_wtab(argv[0], argv[1]);
1773         argv += 2;
1774         argc -= 2;
1775         if (w == NULL) {
1776                 return(1);
1777         } else {
1778                 pargc = 0;
1779                 pargv = (char **)XtMalloc(sizeof(char *) * argc);
1780                 n = 0;
1781                 parse_args(arg0, argc, argv, w, w->parent, w->wclass, &n, args,
1782                            &pargc, pargv, True);
1783                 if (n > 0) 
1784                         XtSetValues(w->w, args, n);
1785
1786                 /* Process any postponed resources */
1787                 if (pargc > 0)
1788                 {
1789                         free_args(n, args);
1790                         n = 0;
1791                         parse_args(arg0, pargc, pargv, w, w->parent, 
1792                                 w->wclass, &n, args, NULL, NULL, False);
1793                         XtSetValues(w->w, args, n);
1794                 }
1795                 free_args(n, args);
1796                 XtFree((char *)pargv);
1797         }
1798         return(0);
1799 }
1800
1801
1802 /*
1803  * When a timeout or work proc is added, the memory allocated for the
1804  * clientData (i.e. the command string) will be lost, unless we provide
1805  * a means of associating the string with the workproc/timeout id, and
1806  * then free up the memory when the workproc/timeout is removed.  The
1807  * following two functions implement such a mechanism.  This prevents
1808  * a memory leak from occurring.
1809  */
1810
1811 static void
1812 RegisterCmdStr(
1813         char type,
1814         long id,
1815         char *cmd )
1816 {
1817    CommandString **table;
1818    int * tableSize;
1819
1820    if (type == WORKPROC_CMDS)
1821    {
1822       table = &workProcCmds;
1823       tableSize = &workProcCmdsSize;
1824    }
1825    else
1826    {
1827       table = &timeOutCmds;
1828       tableSize = &timeOutCmdsSize;
1829    }
1830
1831    (*tableSize)++;
1832    *table = (CommandString *)XtRealloc((char *)*table,
1833                                        sizeof(CommandString) * (*tableSize));
1834    (*table)[(*tableSize)-1].id = id;
1835    (*table)[(*tableSize)-1].cmd = cmd;
1836 }
1837
1838 static void
1839 RemoveCmdStr(
1840         char type,
1841         long id )
1842 {
1843    CommandString **table;
1844    int * tableSize;
1845    int i, j;
1846
1847    if (type == WORKPROC_CMDS)
1848    {
1849       table = &workProcCmds;
1850       tableSize = &workProcCmdsSize;
1851    }
1852    else
1853    {
1854       table = &timeOutCmds;
1855       tableSize = &timeOutCmdsSize;
1856    }
1857
1858    for (i = 0; i < (*tableSize); i++)
1859    {
1860       if (id == (*table)[i].id)
1861       {
1862          XtFree((*table)[i].cmd);
1863          (*tableSize)--;
1864
1865          for (j = i; j < (*tableSize); j++)
1866             (*table)[j] = (*table)[j+1];
1867  
1868          *table = (CommandString *)XtRealloc((char *) (*table),
1869                                     sizeof(CommandString) * (*tableSize));
1870          break;
1871       }
1872    }
1873 }
1874
1875
1876 int
1877 do_XtAddWorkProc(
1878         int argc,
1879         char *argv[] )
1880 {
1881    char *variable;
1882    char *cmd;
1883    char buf[256];
1884    XtWorkProcId id;
1885    char * errmsg;
1886
1887    if (argc != 3) 
1888    {
1889       errmsg = strdup(GETMESSAGE(5,28, 
1890                       "Usage: XtAddWorkProc variable command"));
1891       printerr(str_nill, errmsg, NULL);
1892       free(errmsg);
1893       return(1);
1894    }
1895
1896    variable = argv[1];
1897    cmd = strdup((char *)argv[2]);
1898    id = XtAddWorkProc((XtWorkProc)stdWorkProcCB, (XtPointer)cmd);
1899    RegisterCmdStr(WORKPROC_CMDS, (long)id, cmd);
1900    sprintf(buf, "0x%lx", (long)id);
1901    alt_env_set_var(variable, buf);
1902    return(0);
1903 }
1904
1905 int
1906 do_XtRemoveWorkProc(
1907         int argc,
1908         char *argv[] )
1909 {
1910    XtWorkProcId id;
1911    char *p;
1912    char * errmsg;
1913
1914    if (argc != 2) 
1915    {
1916       errmsg = strdup(GETMESSAGE(5,29, "Usage: XtRemoveWorkProc workProcId"));
1917       printerr(str_nill, errmsg, NULL);
1918       free(errmsg);
1919       return(1);
1920    }
1921
1922    id = strtoul(argv[1], &p, 16);
1923    if (p == argv[1]) 
1924    {
1925       errmsg=strdup(GETMESSAGE(5,30, 
1926                    "The workProcId parameter must be a hex number: %s"));
1927       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
1928                 NULL, NULL);
1929       free(errmsg);
1930       return(1);
1931    }
1932    XtRemoveWorkProc(id);
1933    RemoveCmdStr(WORKPROC_CMDS, (long)id);
1934    return(0);
1935 }
1936
1937 int
1938 do_XtAddTimeOut(
1939         int argc,
1940         char *argv[] )
1941 {
1942    unsigned long milliseconds = 0;
1943    wtab_t *w;
1944    char *variable;
1945    char *cmd;
1946    char buf[256];
1947    XtIntervalId id;
1948    char * errmsg;
1949
1950    if (argc != 4) 
1951    {
1952       errmsg = strdup(GETMESSAGE(5,31, 
1953                "Usage: XtAddTimeOut variable milliseconds command"));
1954       printerr(str_nill, errmsg, NULL);
1955       free(errmsg);
1956       return(1);
1957    }
1958
1959    variable = argv[1];
1960    if ((milliseconds = atol(argv[2])) <= 0) 
1961    {
1962       errmsg = strdup(GETMESSAGE(5,32, 
1963                 "The milliseconds parameter must be greater than zero"));
1964       printerr(argv[0], errmsg, NULL);
1965       free(errmsg);
1966       alt_env_set_var(variable, str_nill);
1967       return(1);
1968    }
1969
1970    cmd = strdup((char *)argv[3]);
1971    id = XtAddTimeOut(milliseconds, (XtTimerCallbackProc)stdTimerCB, 
1972                      (XtPointer)cmd);
1973    RegisterCmdStr(TIMEOUT_CMDS, (long)id, cmd);
1974    sprintf(buf, "0x%lx", (long)id);
1975    alt_env_set_var(variable, buf);
1976    return(0);
1977 }
1978
1979 int
1980 do_XtRemoveTimeOut(
1981         int argc,
1982         char *argv[] )
1983 {
1984    XtIntervalId id;
1985    char *p;
1986    char * errmsg;
1987
1988    if (argc != 2) 
1989    {
1990       errmsg = strdup(GETMESSAGE(5,33, "Usage: XtRemoveTimeOut intervalId"));
1991       printerr(str_nill, errmsg, NULL);
1992       free(errmsg);
1993       return(1);
1994    }
1995
1996    id = strtoul(argv[1], &p, 16);
1997    if (p == argv[1]) {
1998       errmsg = strdup(GETMESSAGE(5,34, 
1999                    "The intervalId parameter must be a hex number: %s"));
2000       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
2001                 NULL, NULL);
2002       free(errmsg);
2003       return(1);
2004    }
2005    XtRemoveTimeOut(id);
2006    RemoveCmdStr(TIMEOUT_CMDS, (long)id);
2007    return(0);
2008 }
2009
2010 int
2011 do_XtUnmanageChildren(
2012         int argc,
2013         char *argv[] )
2014 {
2015         return(do_managelist_func(argc, argv, (int (*)())XtUnmanageChildren));
2016 }
2017
2018 int
2019 do_XtManageChildren(
2020         int argc,
2021         char *argv[] )
2022 {
2023         return(do_managelist_func(argc, argv, (int (*)())XtManageChildren));
2024 }
2025
2026 int
2027 do_managelist_func(
2028         int argc,
2029         char *argv[],
2030         int (*func)() )
2031 {
2032         wtab_t *w;
2033         int i;
2034         Widget widgets[MAXARGS];
2035         Cardinal nwidgets;
2036         char * errmsg;
2037
2038         if (argc < 2) {
2039                 errmsg = strdup(GETMESSAGE(5,35, "Usage: %s widget ..."));
2040                 printerrf(str_nill, errmsg, argv[0], NULL, NULL,
2041                           NULL, NULL, NULL, NULL, NULL);
2042                 free(errmsg);
2043                 return(1);
2044         }
2045         for (nwidgets = 0, i = 1; i < argc && nwidgets < MAXARGS; i++) {
2046                 w = str_to_wtab(argv[0], argv[i]);
2047                 if (w != NULL) {
2048                         widgets[nwidgets++] = w->w;
2049                 }
2050         }
2051         func(widgets, nwidgets);
2052         return(0);
2053 }
2054
2055
2056 int
2057 do_XtIsSubclass(
2058         int argc,
2059         char *argv[] )
2060 {
2061    wtab_t *w;
2062    int i;
2063    char * errmsg;
2064
2065    if (argc != 3) 
2066    {
2067       errmsg = strdup(GETMESSAGE(5,120, 
2068                "Usage: XtIsSubclass widget class"));
2069       printerr(str_nill, errmsg, NULL);
2070       free(errmsg);
2071       return(1);
2072    }
2073
2074    w = str_to_wtab(argv[0], argv[1]);
2075    if (w != NULL) 
2076    {
2077       for (i = 0; C[i].cname; i++)
2078       {
2079          if (strcmp(argv[2], C[i].cname) == 0)
2080             return(!XtIsSubclass(w->w, C[i].class));
2081       }
2082    }
2083    errmsg = strdup(GETMESSAGE(5,121, 
2084                "%s is not a valid widget class name"));
2085    printerrf(str_nill, errmsg, argv[2], NULL, NULL,
2086              NULL, NULL, NULL, NULL, NULL);
2087    free(errmsg);
2088    return(255);
2089 }
2090
2091
2092 int
2093 do_XtClass(
2094         int argc,
2095         char *argv[] )
2096 {
2097    wtab_t *w;
2098    int i;
2099    char * errmsg;
2100    WidgetClass class;
2101
2102    if (argc != 3) 
2103    {
2104       errmsg = strdup(GETMESSAGE(5,122, 
2105                "Usage: XtClass variable widget"));
2106       printerr(str_nill, errmsg, NULL);
2107       free(errmsg);
2108       return(1);
2109    }
2110
2111    w = str_to_wtab(argv[0], argv[2]);
2112
2113    if (w != NULL) 
2114    {
2115       class = XtClass(w->w);
2116       for (i = 0; C[i].cname; i++)
2117       {
2118          if (C[i].class == class)
2119          {
2120             alt_env_set_var(argv[1], C[i].cname);
2121             return(0);
2122          }
2123       }
2124    }
2125
2126    alt_env_set_var(argv[1], str_nill);
2127    return(255);
2128 }
2129
2130
2131
2132 #define PARSE_POINTLIST (-1)
2133 #define PARSE_SEGMENTLIST (-2)
2134 #define PARSE_AREA (-3)
2135
2136 GC Standard_GC;
2137
2138 int
2139 create_standard_gc(
2140         Display *display,
2141         Window drawable )
2142 {
2143    Standard_GC = XCreateGC(display, drawable, 0, NULL);
2144    return(0);
2145 }
2146
2147 int
2148 do_XBell(
2149         int argc,
2150         char *argv[] )
2151 {
2152    int volume;
2153    Display * display;
2154    char * p;
2155    char * errmsg;
2156
2157    if (argc != 3) 
2158    {
2159       errmsg=strdup(GETMESSAGE(5,36, "Usage: XBell display volume"));
2160       printerr(str_nill, errmsg, NULL);
2161       free(errmsg);
2162       return(1);
2163    } 
2164    else
2165       volume = atoi(argv[2]);
2166
2167    display = (Display *)strtoul(argv[1], &p, 0);
2168    if (p == argv[1]) 
2169    {
2170       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
2171       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
2172                 NULL, NULL);
2173       free(errmsg);
2174       return(1);
2175    }
2176
2177    if (volume < -100)
2178       volume = -100;
2179    else if (volume > 100)
2180       volume = 100;
2181
2182    XBell(display, volume);
2183    return(0);
2184 }
2185
2186 static int
2187 do_RootWindowCmd(
2188         int (*func)(),
2189         int argc,
2190         char *argv[] )
2191 {
2192    Screen * screen;
2193    char * p;
2194    char buf[128];
2195    char * errmsg;
2196
2197    if (argc != 3) 
2198    {
2199       errmsg = strdup(GETMESSAGE(5,37, "Usage: %s variable screen"));
2200       printerrf(str_nill, errmsg, argv[0], NULL, NULL, NULL, NULL, NULL, 
2201                 NULL, NULL);
2202       free(errmsg);
2203       return(1);
2204    } 
2205
2206    screen = (Screen *)strtoul(argv[2], &p, 0);
2207    if (p == argv[2]) 
2208    {
2209       errmsg = strdup(GETMESSAGE(5,38, "The screen parameter is invalid: %s"));
2210       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
2211                 NULL, NULL);
2212       free(errmsg);
2213       return(1);
2214    }
2215
2216    sprintf(buf, "%ld", (long)(*func)(screen));
2217    alt_env_set_var(argv[1], buf);
2218    return(0);
2219 }
2220
2221 int
2222 do_XRootWindowOfScreen(
2223         int argc,
2224         char *argv[] )
2225 {
2226    return(do_RootWindowCmd((int (*)())XRootWindowOfScreen, argc, argv));
2227 }
2228
2229 int
2230 do_XWidthOfScreen(
2231         int argc,
2232         char *argv[] )
2233 {
2234    return(do_RootWindowCmd(XWidthOfScreen, argc, argv));
2235 }
2236
2237 int
2238 do_XHeightOfScreen(
2239         int argc,
2240         char *argv[] )
2241 {
2242    return(do_RootWindowCmd(XHeightOfScreen, argc, argv));
2243 }
2244
2245 int
2246 do_XDefineCursor(
2247         int argc,
2248         char *argv[] )
2249 {
2250    Cursor cursor;
2251    Display * display;
2252    Window window;
2253    char * p;
2254    char * errmsg;
2255
2256    if (argc != 4) 
2257    {
2258       errmsg = strdup(GETMESSAGE(5,39, 
2259                       "Usage: XDefineCursor display window cursorId"));
2260       printerr(str_nill, errmsg, NULL);
2261       free(errmsg);
2262       return(1);
2263    } 
2264
2265    display = (Display *)strtoul(argv[1], &p, 0);
2266    if (p == argv[1]) 
2267    {
2268       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
2269       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
2270                 NULL, NULL);
2271       free(errmsg);
2272       return(1);
2273    }
2274
2275    window = (Window)strtoul(argv[2], &p, 0);
2276    if (p == argv[2]) 
2277    {
2278       errmsg = strdup(GetSharedMsg(DT_BAD_WINDOW));
2279       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
2280                 NULL, NULL);
2281       free(errmsg);
2282       return(1);
2283    }
2284
2285    cursor = (Cursor)strtoul(argv[3], &p, 0);
2286    if (p == argv[3]) 
2287    {
2288       errmsg = strdup(GETMESSAGE(5,40, 
2289                       "The cursorId parameter is invalid: %s"));
2290       printerrf(argv[0], errmsg, argv[3], NULL, NULL, NULL, NULL, NULL,
2291                 NULL, NULL);
2292       free(errmsg);
2293       return(1);
2294    }
2295
2296    XDefineCursor(display, window, cursor);
2297    return(0);
2298 }
2299
2300 int
2301 do_XUndefineCursor(
2302         int argc,
2303         char *argv[] )
2304 {
2305    Display * display;
2306    Window window;
2307    char * p;
2308    char * errmsg;
2309
2310    if (argc != 3) 
2311    {
2312       errmsg = strdup(GETMESSAGE(5,41, 
2313                       "Usage: XUndefineCursor display window"));
2314       printerr(str_nill, errmsg, NULL);
2315       free(errmsg);
2316       return(1);
2317    } 
2318
2319    display = (Display *)strtoul(argv[1], &p, 0);
2320    if (p == argv[1]) 
2321    {
2322       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
2323       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
2324                 NULL, NULL);
2325       free(errmsg);
2326       return(1);
2327    }
2328
2329    window = (Window)strtoul(argv[2], &p, 0);
2330    if (p == argv[2]) 
2331    {
2332       errmsg = strdup(GetSharedMsg(DT_BAD_WINDOW));
2333       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
2334                 NULL, NULL);
2335       free(errmsg);
2336       return(1);
2337    }
2338
2339    XUndefineCursor(display, window);
2340    return(0);
2341 }
2342
2343 int
2344 do_XtRemoveAllCallbacks(
2345         int argc,
2346         char *argv[] )
2347 {
2348         wtab_t *w;
2349         int i;
2350         char * errmsg;
2351
2352         if (argc != 3) {
2353                 errmsg = strdup(GETMESSAGE(5,42, 
2354                           "Usage: XtRemoveAllCallbacks widget callbackName"));
2355                 printerr(str_nill, errmsg, NULL);
2356                 free(errmsg);
2357                 return(1);
2358         }
2359         w = str_to_wtab(argv[0], argv[1]);
2360         if (w != NULL) {
2361                 XtRemoveAllCallbacks(w->w, argv[2]);
2362                 return(0);
2363         } else
2364                 return(1);
2365 }
2366
2367 static int
2368 cvtfontstruct(
2369         char *name,
2370         XFontStruct **fn )
2371 {
2372         XrmValue fval, tval;
2373
2374         fval.addr = name;
2375         fval.size = strlen(name);
2376         XtConvert(Toplevel, XtRString, &fval, XtRFontStruct, &tval);
2377
2378         if (tval.size != 0) {
2379                 *fn = ((XFontStruct **)(tval.addr))[0];
2380                 return(SUCCESS);
2381         } else
2382                 return(FAIL);
2383 }
2384
2385 static int
2386 CatchNonFatalFontError(
2387         Display *display,
2388         XErrorEvent *event )
2389
2390 {
2391    invalidFont = True;
2392 }
2393
2394 static int
2395 cvtfont(
2396         Display *display,
2397         char *name,
2398         Font *fn )
2399 {
2400    int (*oldHandler)();
2401
2402    invalidFont = False;
2403    oldHandler = XSetErrorHandler(CatchNonFatalFontError);
2404    *fn = XLoadFont(display, name);
2405    XSync(display, False);
2406    XSetErrorHandler(oldHandler);
2407
2408    if (!invalidFont)
2409       return(SUCCESS);
2410    else
2411       return(FAIL);
2412 }
2413
2414 static int
2415 cvtcolor(
2416         char *name,
2417         Pixel *pix )
2418 {
2419         XrmValue fval, tval;
2420
2421         fval.addr = name;
2422         fval.size = strlen(name);
2423         XtConvert(Toplevel, XtRString, &fval, XtRPixel, &tval);
2424
2425         if (tval.size != 0) {
2426                 *pix = ((Pixel *)(tval.addr))[0];
2427                 return(SUCCESS);
2428         } else
2429                 return(FAIL);
2430 }
2431
2432 int
2433 do_XTextWidth(
2434         int argc,
2435         char *argv[] )
2436 {
2437    XFontStruct *fn;
2438    char *s;
2439    char buf[128];
2440    char * errmsg;
2441
2442    if (argc != 4) 
2443    {
2444       errmsg = strdup(GETMESSAGE(5,43, 
2445                       "Usage: XTextWidth variable fontName string"));
2446       printerr(str_nill, errmsg, NULL);
2447       free(errmsg);
2448       return(1);
2449    }
2450    if (cvtfontstruct(argv[2], &fn) != SUCCESS)
2451    {
2452       errmsg = strdup(GetSharedMsg(DT_BAD_FONT));
2453       printerrf(argv[0], errmsg, argv[2], NULL,
2454                 NULL, NULL, NULL, NULL, NULL, NULL);
2455       free(errmsg);
2456       return(1);
2457    }
2458    s = argv[3];
2459    sprintf(buf, "%ld", (long)XTextWidth(fn, s, strlen(s)));
2460    alt_env_set_var(argv[1], buf);
2461    return(0);
2462 }
2463
2464 #define MAXDRAWARGS 6
2465 #define LINE_ARGS 1
2466 #define POLYGON_ARGS 2
2467
2468 static int
2469 invokeXDrawFunction(
2470         int function,
2471         int argc,
2472         char *argv[] )
2473 {
2474    char * functionName = argv[0];
2475    Display * display;
2476    Window drawable;
2477    Window destination;
2478    int srcX, srcY;
2479    int destX, destY;
2480    unsigned int width, height;
2481    char *s;
2482    char *sp;
2483    int i;
2484    int mode, parse;
2485    int text = FALSE;
2486    int (*func)();
2487    int argtype = 0;
2488    int polymode;
2489    int coordmode;
2490    GC  gc = NULL;
2491    int p[MAXDRAWARGS];
2492    int returnVal = 0;
2493    Boolean unknownOption;
2494    Boolean userSpecifiedGC = False;
2495    char * errmsg;
2496
2497    if (argc < 3)
2498    {
2499       errmsg = strdup(GETMESSAGE(5,44, 
2500                       "Usage: %s display drawable [args ...]"));
2501       printerrf(str_nill, errmsg, functionName, NULL, NULL, NULL, NULL, NULL, 
2502                 NULL, NULL);
2503       free(errmsg);
2504       return(1);
2505    }
2506
2507    display = (Display *)strtoul(argv[1], &sp, 0);
2508    if (sp == argv[1]) 
2509    {
2510       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
2511       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
2512                 NULL, NULL);
2513       free(errmsg);
2514       return(1);
2515    }
2516    drawable = (Window)strtoul(argv[2], &sp, 0);
2517    if (sp == argv[2]) 
2518    {
2519       errmsg = strdup(GETMESSAGE(5,45, 
2520                       "The drawable parameter is invalid: %s"));
2521       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
2522                 NULL, NULL);
2523       free(errmsg);
2524       return(1);
2525    }
2526
2527    if (function == COPY_AREA) 
2528    {
2529       parse = 0;
2530       func = XCopyArea;
2531
2532       destination = (Window)strtoul(argv[3], &sp, 0);
2533       if (sp == argv[3]) 
2534       {
2535          errmsg = strdup(GETMESSAGE(5,46, 
2536                          "The destination parameter is invalid: %s"));
2537          printerrf(argv[0], errmsg, argv[3], NULL, NULL, NULL, NULL, NULL,
2538                 NULL, NULL);
2539          free(errmsg);
2540          return(1);
2541       }
2542       srcX = atoi(argv[4]);
2543       srcY = atoi(argv[5]);
2544       width = atoi(argv[6]);
2545       height = atoi(argv[7]);
2546       destX = atoi(argv[8]);
2547       destY = atoi(argv[9]);
2548       argc -= 7;
2549       argv += 7;
2550    } 
2551    else if (function == DRAW_RECTANGLE) 
2552    {
2553       parse = 4;
2554       func = XDrawRectangle;
2555    } 
2556    else if (function == FILL_RECTANGLE) 
2557    {
2558       parse = 4;
2559       func = XFillRectangle;
2560    } 
2561    else if (function == FILL_POLYGON) 
2562    {
2563       parse = PARSE_POINTLIST;
2564       func = XFillPolygon;
2565       argtype = POLYGON_ARGS;
2566       polymode = Complex;
2567       coordmode = CoordModeOrigin;
2568       if (argc > 3)
2569       {
2570          while (argv[3][0] == '-') 
2571          {
2572             if (strcmp(argv[3], "-Complex") == 0) 
2573                polymode = Complex;
2574             else if (strcmp(argv[3], "-Convex") == 0) 
2575                polymode = Convex;
2576             else if (strcmp(argv[3], "-Nonconvex") == 0)
2577                polymode = Nonconvex;
2578             else if (strcmp(argv[3], "-CoordModeOrigin") == 0) 
2579                coordmode = CoordModeOrigin;
2580             else if (strcmp(argv[3], "-CoordModePrevious") == 0) 
2581                coordmode = CoordModePrevious;
2582             else
2583                break;
2584
2585             argc--;
2586             argv++;
2587          }
2588       }
2589    } 
2590    else if (function == DRAW_LINE) 
2591    {
2592       parse = 4;
2593       func = XDrawLine;
2594    } 
2595    else if (function == DRAW_SEGMENTS) 
2596    {
2597       parse = PARSE_SEGMENTLIST;
2598       func = XDrawSegments;
2599    } 
2600    else if (function == DRAW_LINES) 
2601    {
2602       parse = PARSE_POINTLIST;
2603       func = XDrawLines;
2604       argtype = LINE_ARGS;
2605       coordmode = CoordModeOrigin;
2606       if (argc > 3)
2607       {
2608          while (argv[3][0] == '-') 
2609          {
2610             if (strcmp(argv[3], "-CoordModeOrigin") == 0) 
2611                coordmode = CoordModeOrigin;
2612             else if (strcmp(argv[3], "-CoordModePrevious") == 0) 
2613                coordmode = CoordModePrevious;
2614             else
2615                break;
2616
2617             argc--;
2618             argv++;
2619          }
2620       }
2621    } 
2622    else if (function == DRAW_STRING) 
2623    {
2624       parse = 2;
2625       text = TRUE;
2626       func = XDrawString;
2627    } 
2628    else if (function == DRAW_IMAGE_STRING) 
2629    {
2630       parse = 2;
2631       text = TRUE;
2632       func = XDrawImageString;
2633    } 
2634    else if (function == DRAW_ARC) 
2635    {
2636       parse = 6;
2637       func = XDrawArc;
2638    } 
2639    else if (function == FILL_ARC) 
2640    {
2641       parse = 6;
2642       func = XFillArc;
2643    } 
2644    else if (function == DRAW_POINT) 
2645    {
2646       parse = 2;
2647       func = XDrawPoint;
2648    } 
2649    else if (function == DRAW_POINTS) 
2650    {
2651       parse = PARSE_POINTLIST;
2652       func = XDrawPoints;
2653       argtype = LINE_ARGS;
2654       coordmode = CoordModeOrigin;
2655       if (argc > 3)
2656       {
2657          while (argv[3][0] == '-') 
2658          {
2659             if (strcmp(argv[3], "-CoordModeOrigin") == 0) 
2660                coordmode = CoordModeOrigin;
2661             else if (strcmp(argv[3], "-CoordModePrevious") == 0)
2662                coordmode = CoordModePrevious;
2663             else
2664                break;
2665
2666             argc--;
2667             argv++;
2668          }
2669       }
2670    } 
2671    else if (function == CLEAR_WINDOW) 
2672    {
2673       parse = 0;
2674       func = XClearWindow;
2675    } 
2676    else if (function == CLEAR_AREA) 
2677    {
2678       parse = PARSE_AREA;
2679       func = XClearArea;
2680    }
2681
2682    if (Standard_GC == NULL)
2683       create_standard_gc(display, drawable);
2684
2685    while (argc > 4 && argv[3][0] == '-') 
2686    {
2687       if (gc == NULL)
2688          gc = XCreateGC(display, drawable, 0, NULL);
2689
2690       if (strcmp(argv[3], "-gc") == 0) 
2691       {
2692          XFreeGC(display, gc);
2693          gc = (GC) atol(argv[4]);
2694          userSpecifiedGC = True;
2695       } 
2696       else if (strcmp(argv[3], "-foreground") == 0) 
2697       {
2698          Pixel pix;
2699
2700          if (cvtcolor(argv[4], &pix) == SUCCESS)
2701             XSetForeground(display, gc, pix);
2702       } 
2703       else if (strcmp(argv[3], "-background") == 0) 
2704       {
2705          Pixel pix;
2706
2707          if (cvtcolor(argv[4], &pix) == SUCCESS)
2708             XSetBackground(display, gc, pix);
2709       } 
2710       else if (strcmp(argv[3], "-font") == 0) 
2711       {
2712          Font fn;
2713
2714          if (cvtfont(display, argv[4], &fn) == SUCCESS)
2715             XSetFont(display, gc, fn);
2716          else
2717          {
2718             errmsg = strdup(GetSharedMsg(DT_BAD_FONT));
2719             printerrf(functionName, errmsg, argv[4], NULL, NULL, NULL, 
2720                       NULL, NULL, NULL, NULL);
2721             free(errmsg);
2722             returnVal = 1;
2723          }
2724       } 
2725       else if (strcmp(argv[3], "-line_width") == 0) 
2726       {
2727          XGCValues v;
2728
2729          v.line_width = atoi(argv[4]);
2730          XChangeGC(display, gc, GCLineWidth, &v);
2731       } 
2732       else if (strcmp(argv[3], "-function") == 0) 
2733       {
2734          XGCValues v;
2735          long f;
2736
2737          unknownOption = False;
2738
2739          if (strcmp(argv[4], "xor") == 0) 
2740             f = GXxor;
2741          else if (strcmp(argv[4], "or") == 0)
2742             f = GXor;
2743          else if (strcmp(argv[4], "clear") == 0)
2744             f = GXclear;
2745          else if (strcmp(argv[4], "and") == 0)
2746             f = GXand;
2747          else if (strcmp(argv[4], "copy") == 0)
2748             f = GXcopy;
2749          else if (strcmp(argv[4], "noop") == 0)
2750             f = GXnoop;
2751          else if (strcmp(argv[4], "nor") == 0)
2752             f = GXnor;
2753          else if (strcmp(argv[4], "nand") == 0)
2754             f = GXnand;
2755          else if (strcmp(argv[4], "set") == 0)
2756             f = GXset;
2757          else if (strcmp(argv[4], "invert") == 0)
2758             f = GXinvert;
2759          else if (strcmp(argv[4], "equiv") == 0)
2760             f = GXequiv;
2761          else if (strcmp(argv[4], "andReverse") == 0)
2762             f = GXandReverse;
2763          else if (strcmp(argv[4], "orReverse") == 0)
2764             f = GXorReverse;
2765          else if (strcmp(argv[4], "copyInverted") == 0)
2766             f = GXcopyInverted;
2767          else 
2768          {
2769             errmsg = strdup(GETMESSAGE(5,47, 
2770                       "Unrecognized graphics function name: %s"));
2771             printerrf(functionName, errmsg, argv[4],
2772                       NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2773             free(errmsg);
2774             returnVal = 1;
2775             unknownOption = True;
2776          }
2777
2778          if (!unknownOption)
2779          {
2780             v.function = f;
2781             XChangeGC(display, gc, GCFunction, &v);
2782          }
2783       } 
2784       else if (strcmp(argv[3], "-line_style") == 0) 
2785       {
2786          XGCValues v;
2787          long f;
2788
2789          unknownOption = False;
2790
2791          if (strcmp(argv[4], "LineSolid") == 0)
2792             f = LineSolid;
2793          else if (strcmp(argv[4], "LineDoubleDash") == 0)
2794             f = LineDoubleDash;
2795          else if (strcmp(argv[4], "LineOnOffDash") == 0)
2796             f = LineOnOffDash;
2797          else {
2798             errmsg = strdup(GETMESSAGE(5,48, "Unrecognized line style: %s"));
2799             printerrf(functionName, errmsg,
2800                        argv[4], NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2801             free(errmsg);
2802             returnVal = 1;
2803             unknownOption = True;
2804          }
2805
2806          if (!unknownOption)
2807          {
2808             v.line_style = f;
2809             XChangeGC(display, gc, GCLineStyle, &v);
2810          }
2811       } 
2812       else 
2813       {
2814          errmsg = strdup(GETMESSAGE(5,49, "Unrecognized drawing option: %s"));
2815          printerrf(functionName, errmsg, argv[3], NULL, NULL,
2816                    NULL, NULL, NULL, NULL, NULL);
2817          free(errmsg);
2818          returnVal = 1;
2819       }
2820
2821       argv += 2;
2822       argc -= 2;
2823    }
2824
2825    if (gc == NULL)
2826       gc = Standard_GC;
2827
2828    argc -= 3;
2829    argv += 3;
2830    if (parse == PARSE_POINTLIST) 
2831    {
2832       XPoint *points = (XPoint *)malloc(sizeof(XPoint )*(argc/2+1));
2833       int npoints = 0;
2834
2835       for (i = 0; i < argc-1; i += 2, npoints++) 
2836       {
2837          points[npoints].x = atoi(argv[i]);
2838          points[npoints].y = atoi(argv[i+1]);
2839       }
2840
2841       switch (argtype) 
2842       {
2843          case POLYGON_ARGS:
2844          {
2845             (*func)(display, drawable, gc, points, argc/2, polymode, coordmode);
2846             break;
2847          }
2848
2849          case LINE_ARGS:
2850          {
2851             (*func)(display, drawable, gc, points, argc/2, coordmode);
2852             break;
2853          }
2854       }
2855
2856       free(points);
2857       argc -= 2*npoints;
2858       argv += 2*npoints;
2859    }
2860    else if (parse == PARSE_SEGMENTLIST) 
2861    {
2862       XSegment *segments;
2863       int nsegments = 0;
2864
2865       segments = (XSegment *)malloc(sizeof(XSegment )*(argc/4+1));
2866
2867       for (i = 0; i < argc-1; i += 4, nsegments++) 
2868       {
2869          segments[nsegments].x1 = atoi(argv[i]);
2870          segments[nsegments].y1 = atoi(argv[i+1]);
2871          segments[nsegments].x2 = atoi(argv[i+2]);
2872          segments[nsegments].y2 = atoi(argv[i+3]);
2873       }
2874
2875       (*func)(display, drawable, gc, segments, argc/4);
2876       free(segments);
2877       argc -= 4*nsegments;
2878       argv += 4*nsegments;
2879    } 
2880    else if (parse == PARSE_AREA) 
2881    {
2882       Boolean exposures = False;
2883       XrmValue fval, tval;
2884
2885       for (i = 0; i < 4 && argc > 0; i++) 
2886       {
2887          p[i] = atoi(argv[0]);
2888          argc --;
2889          argv ++;
2890       }
2891
2892       if (argc > 0)
2893       {
2894          fval.addr = argv[0];
2895          fval.size = strlen(argv[0]);
2896          XtConvert(Toplevel, XtRString, &fval, XtRBoolean, &tval);
2897
2898          if (tval.size != 0) 
2899             exposures = *((Boolean *)(tval.addr));
2900
2901          argc --;
2902          argv ++;
2903       }
2904
2905       (*func)(display, drawable, p[0], p[1], p[2], p[3], exposures);
2906    }
2907    else 
2908    {
2909       while (argc >= parse) 
2910       {
2911          for (i = 0; i < parse && i < argc; i++) 
2912             p[i] = atoi(argv[i]);
2913
2914          if (text) 
2915          {
2916             (*func)(display, drawable, gc, 
2917                     p[0], p[1], argv[i], strlen(argv[i]));
2918             argc--;
2919             argv++;
2920          } 
2921          else if (func == XClearWindow)
2922             (*func)(display, drawable);
2923          else if (func == XCopyArea)
2924          {
2925             (*func)(display, drawable, destination, gc,
2926                     srcX, srcY, width, height, destX, destY);
2927          }
2928          else
2929          {
2930             (*func)(display, drawable, gc, 
2931                     p[0], p[1], p[2], p[3], p[4], p[5]);
2932          }
2933
2934          argc -= parse;
2935          argv += parse;
2936          if (parse == 0)
2937             break;
2938       }
2939    }
2940
2941    if ((gc != Standard_GC) && !userSpecifiedGC)
2942       XFreeGC(display, gc);
2943
2944    if (argc != 0) 
2945    {
2946       errmsg = strdup(GETMESSAGE(5,50, 
2947                   "There were left over points which were ignored"));
2948       printerr(functionName, errmsg, NULL);
2949       free(errmsg);
2950       returnVal = 1;
2951    }
2952
2953    return(returnVal);
2954
2955 }
2956 #undef LINE_ARGS 
2957 #undef POLYGON_ARGS
2958
2959 int
2960 do_XDrawArc(
2961         int argc,
2962         char *argv[] )
2963 {
2964    invokeXDrawFunction(DRAW_ARC, argc, argv);
2965 }
2966
2967 int
2968 do_XDrawImageString(
2969         int argc,
2970         char *argv[] )
2971 {
2972    invokeXDrawFunction(DRAW_IMAGE_STRING, argc, argv);
2973 }
2974
2975 int
2976 do_XDrawLine(
2977         int argc,
2978         char *argv[] )
2979 {
2980    invokeXDrawFunction(DRAW_LINE, argc, argv);
2981 }
2982
2983 int
2984 do_XDrawLines(
2985         int argc,
2986         char *argv[] )
2987 {
2988    invokeXDrawFunction(DRAW_LINES, argc, argv);
2989 }
2990
2991 int
2992 do_XDrawPoint(
2993         int argc,
2994         char *argv[] )
2995 {
2996    invokeXDrawFunction(DRAW_POINT, argc, argv);
2997 }
2998
2999 int
3000 do_XDrawPoints(
3001         int argc,
3002         char *argv[] )
3003 {
3004    invokeXDrawFunction(DRAW_POINTS, argc, argv);
3005 }
3006
3007 int
3008 do_XDrawRectangle(
3009         int argc,
3010         char *argv[] )
3011 {
3012    invokeXDrawFunction(DRAW_RECTANGLE, argc, argv);
3013 }
3014
3015 int
3016 do_XCopyArea(
3017         int argc,
3018         char *argv[] )
3019 {
3020    char * errmsg;
3021
3022    if (argc < 10)
3023    {
3024      errmsg = strdup(GETMESSAGE(5,51, 
3025               "Usage: XCopyArea display source dest sourceX sourceY width height destX destY [args ...]"));
3026       printerr(str_nill, errmsg, NULL);
3027       free(errmsg);
3028       return(1);
3029    }
3030
3031    invokeXDrawFunction(COPY_AREA, argc, argv);
3032 }
3033
3034 int
3035 do_XDrawSegments(
3036         int argc,
3037         char *argv[] )
3038 {
3039    invokeXDrawFunction(DRAW_SEGMENTS, argc, argv);
3040 }
3041
3042 int
3043 do_XDrawString(
3044         int argc,
3045         char *argv[] )
3046 {
3047    invokeXDrawFunction(DRAW_STRING, argc, argv);
3048 }
3049
3050 int
3051 do_XFillArc(
3052         int argc,
3053         char *argv[] )
3054 {
3055    invokeXDrawFunction(FILL_ARC, argc, argv);
3056 }
3057
3058 int
3059 do_XFillPolygon(
3060         int argc,
3061         char *argv[] )
3062 {
3063    invokeXDrawFunction(FILL_POLYGON, argc, argv);
3064 }
3065
3066 int
3067 do_XFillRectangle(
3068         int argc,
3069         char *argv[] )
3070 {
3071    invokeXDrawFunction(FILL_RECTANGLE, argc, argv);
3072 }
3073
3074 int
3075 do_XClearArea(
3076         int argc,
3077         char *argv[] )
3078 {
3079    invokeXDrawFunction(CLEAR_AREA, argc, argv);
3080 }
3081
3082 int
3083 do_XClearWindow(
3084         int argc,
3085         char *argv[] )
3086 {
3087    invokeXDrawFunction(CLEAR_WINDOW, argc, argv);
3088 }
3089
3090 int
3091 ConvertTypeToString(
3092         char *arg0,
3093         classtab_t *class,
3094         wtab_t *w,
3095         wtab_t *parent,
3096         char *resource,
3097         XtArgVal val,
3098         char **ret )
3099 {
3100         char *from_type;
3101         XtResourceList res;
3102         XrmValue    fr_val, to_val;
3103         char *nam;
3104         char * errmsg;
3105
3106         if ((nam = hashget((Hash_table_t*)class->res, resource)) == NULL) {
3107                 /* If we didn't find it in this widget's class record,
3108                  * see if the parent is a constraint widget class, and
3109                  * if so then see if we can find the class there.
3110                  */
3111                 if (parent == NULL || parent->wclass == NULL ||
3112                   parent->wclass->con == NULL ||
3113                   (nam = hashget((Hash_table_t*)parent->wclass->con, resource))
3114                           == NULL)
3115                 {
3116                         errmsg = strdup(GetSharedMsg(DT_UNDEF_RESOURCE));
3117                         printerrf(arg0, errmsg, 
3118                                 (char *)(class->cname), resource, NULL, NULL,
3119                                 NULL, NULL, NULL, NULL);
3120                         free(errmsg);
3121                         return(FAIL);
3122                 }
3123         }
3124         res = (XtResourceList)nam;
3125
3126         /*
3127          * unfortunately, we have to have a special case for String
3128          * type resources, since their size may vary.
3129          */
3130         if (strcmp(res->resource_type, str_XtRString) == 0) {
3131                 *ret = ((String *)val)[0];
3132                 return(0);
3133         }
3134         fr_val.size = res->resource_size;
3135         fr_val.addr = (caddr_t)val;
3136         to_val.size = 0;
3137         to_val.addr = NULL;
3138
3139         XtConvert(
3140             w ? w->w : Toplevel,
3141             res->resource_type, /* from type */
3142             &fr_val,    /* from value */
3143             str_XtRString,      /* to type */
3144             &to_val     /* the converted value */
3145         );
3146         if ((to_val.addr) || (strcmp(res->resource_type, XmRXmString) == 0)) {
3147                 *ret = to_val.addr;
3148         } else {
3149             errmsg=strdup(GETMESSAGE(5,52, 
3150                    "Unable to convert resource type '%s' to 'String'"));
3151             printerrf(arg0, errmsg,
3152                       res->resource_type, NULL, NULL, NULL, NULL, NULL,
3153                       NULL, NULL);
3154             free(errmsg);
3155             return(FAIL);
3156         }
3157         return(SUCCESS);
3158 }
3159
3160 wtab_t *DTKSHConversionWidget;
3161 classtab_t *DTKSHConversionClass;
3162 char *DTKSHConversionResource;
3163
3164 int
3165 ConvertStringToType(
3166         char *arg0,
3167         wtab_t *w,
3168         wtab_t *parent,
3169         classtab_t *class,
3170         char *resource,
3171         char *val,
3172         XtArgVal *ret,
3173         int *freeit,
3174         Boolean postponePixmaps )
3175 {
3176         char *to_type;
3177         XtResourceList res;
3178         XrmValue    fr_val, to_val;
3179         char *nam;
3180         char * errmsg;
3181
3182         DTKSHConversionClass = class;   /* needed by callback converter */
3183         DTKSHConversionResource = resource;  /* needed by callback converter */
3184         DTKSHConversionWidget = w;      /* needed by callback converter */
3185
3186         if ((nam = hashget((Hash_table_t*)class->res, resource)) == NULL) {
3187                 /* If we didn't find it in this widget's class record,
3188                  * see if the parent is a constraint widget class, and
3189                  * if so then see if we can find the class there.
3190                  */
3191                 if (parent == NULL || parent->wclass == NULL ||
3192                         parent->wclass->con == NULL ||
3193                         (nam = hashget((Hash_table_t*)parent->wclass->con, 
3194                                         resource)) == NULL)
3195                 {
3196                         errmsg = strdup(GetSharedMsg(DT_UNDEF_RESOURCE));
3197                         printerrf(arg0, errmsg,
3198                                 (char *)(class->cname), resource, NULL,
3199                                 NULL, NULL, NULL, NULL, NULL);
3200                         free(errmsg);
3201                         return(CONVERT_FAILED);
3202                 }
3203         }
3204         res = (XtResourceList)nam;
3205
3206         /*
3207          * Unfortunately, because String types can be variable in size,
3208          * we have to handle this as a special case.
3209          */
3210         if (strcmp(res->resource_type, str_XtRString) == 0) {
3211                 *ret = (XtArgVal)strdup(val);
3212                 *freeit = TRUE;
3213                 return(CONVERT_SUCCEEDED);
3214         }
3215
3216         fr_val.size = strlen(val) + 1;
3217         fr_val.addr = (caddr_t)val;
3218         to_val.size = 0;
3219         to_val.addr = NULL;
3220
3221         /*
3222          * Hook to allow us to postpone processing of certain classes of
3223          * resources.  In particular, Dimension based resources can't be
3224          * converted until the widget exists, nor can gadget pixmap resources.
3225          * Any other pixmap resource needs to be postponed until after any
3226          * color changes have taken effect, otherwise the string to pixmap
3227          * converter uses the existing colors, instead of the new colors.
3228          */
3229         if (toolkit_special_resource(arg0, res, w, parent, 
3230                 class, resource, val, ret, 
3231                 freeit, postponePixmaps)) {
3232                 return(CONVERT_POSTPONED);
3233         }
3234         XtConvert(
3235             w ? w->w : Toplevel,
3236             str_XtRString,      /* from type */
3237             &fr_val,    /* from value */
3238             res->resource_type, /* to type */
3239             &to_val     /* the converted value */
3240         );
3241         if (to_val.size && to_val.addr) {
3242                 switch(to_val.size) {
3243                 case sizeof(char):
3244                     *ret = ((char *)to_val.addr)[0];
3245                     *freeit = FALSE;
3246                     break;
3247                 case sizeof(short):
3248                     *ret = (XtArgVal)((short *)to_val.addr)[0];
3249                     *freeit = FALSE;
3250                     break;
3251                 case sizeof(int):
3252                     *ret = (XtArgVal)((int *)to_val.addr)[0];
3253                     *freeit = FALSE;
3254                     break;
3255                 default:
3256                     /*
3257                      * Deal with sizeof(long) != sizeof(int) here.
3258                      * Bit of a cheat but it's a simple change.
3259                      */
3260                     if (to_val.size == sizeof(long)) {
3261                         *ret = (XtArgVal)((long *)to_val.addr)[0];
3262                         *freeit = FALSE;
3263                         break;
3264                     }
3265
3266                     /*
3267                      * There is a possibility that some
3268                      * coverters will return malloc'ed space and this
3269                      * is really unnecessary and will leak memory.  About
3270                      * the only way to handle this is to handle such types as
3271                      * special cases.  Maybe we need a hash table that
3272                      * contains the names of types that need the malloc?
3273                      * The X specs should really have some mechanism for
3274                      * knowing when to free the results of a conversion.
3275                      */
3276                     *ret = (XtArgVal)XtMalloc(to_val.size);
3277                     memcpy((char *)ret, to_val.addr, to_val.size);
3278                     *freeit = TRUE;
3279                 }
3280         } else {
3281             errmsg=strdup(GETMESSAGE(5,53, 
3282                    "Unable to convert resource type 'String' to type '%s'"));
3283             printerrf(arg0, errmsg,
3284                       res->resource_type, NULL, NULL, NULL, NULL, NULL,
3285                       NULL, NULL);
3286             free(errmsg);
3287             return(CONVERT_FAILED);
3288         }
3289         return(CONVERT_SUCCEEDED);
3290 }
3291
3292 static int
3293 XtAddInputUsage(
3294         char *arg0 )
3295 {
3296         char * errmsg;
3297
3298         errmsg=strdup(GETMESSAGE(5,54, 
3299           "Usage: XtAddInput variable [-r] fileDescriptor kshCommand"));
3300         printerr(str_nill, errmsg, NULL);
3301         free(errmsg);
3302         return(1);
3303 }
3304
3305 int
3306 do_XtAddInput(
3307         int argc,
3308         char *argv[] )
3309 {
3310    int i, j;
3311    int fd;
3312    char *arg0 = argv[0];
3313    char *variable;
3314    char *cmd;
3315    inputrec_t *inp;
3316    XtInputId id;
3317    char buf[256];
3318    char * errmsg;
3319    unsigned char modeFlags = LINE_INPUT_MODE;
3320
3321
3322    if (argc < 4)
3323       return(XtAddInputUsage(arg0));
3324
3325    variable = argv[1];
3326    argv+=2;
3327    argc-=2;
3328
3329    if (strcmp(argv[0], "-r") == 0)
3330    {
3331       /* Raw mode; the registered handler will take care of reading input */
3332       modeFlags = RAW_INPUT_MODE;
3333       argv++;
3334       argc--;
3335    }
3336
3337    if (argc != 2)
3338       return(XtAddInputUsage(arg0));
3339
3340    fd = atoi(argv[0]);
3341    argv++;
3342    argc--;
3343
3344    inp = (inputrec_t *)XtMalloc(sizeof(inputrec_t));
3345    if (modeFlags & RAW_INPUT_MODE)
3346    {
3347       /* Raw mode; the registered handler will do all buffering */
3348       inp->lnbufsize = 0;
3349       inp->lnbuf = NULL;
3350    }
3351    else
3352    {
3353       inp->lnbufsize = LINESIZE;
3354       inp->lnbuf = XtMalloc(inp->lnbufsize);
3355    }
3356    inp->fd = fd;
3357    inp->flags = modeFlags;
3358    inp->lnend = 0;
3359    inp->cmd = strdup(argv[0]);
3360    inp->lastCharIsBackslash = False;
3361    inp->lineWasTouched = False;
3362
3363    id = XtAddInput(fd, (XtPointer)XtInputReadMask, 
3364                    (XtInputCallbackProc)stdInputCB, (caddr_t)inp);
3365
3366    /* 
3367     * Save a record of this input, so that we can destroy the buffer
3368     * information when the input handler is unregistered.
3369     */
3370    for (i = 0; i < numActiveInputs; i++)
3371    {
3372       if (activeInputs[i].inUse == False)
3373          break;
3374    }
3375
3376    if ( i >= numActiveInputs)
3377    {
3378       /* Grow the array */
3379       numActiveInputs += 5;
3380       activeInputs = (InputRecord *)XtRealloc((char *)activeInputs,
3381                                       sizeof(InputRecord) * numActiveInputs);
3382       for (j = i; j < numActiveInputs; j++)
3383       {
3384          activeInputs[j].inUse = False;
3385          activeInputs[j].inp = NULL;
3386          activeInputs[j].id = 0;
3387       }
3388    }
3389    activeInputs[i].inUse = True;
3390    activeInputs[i].id = id;
3391    activeInputs[i].inp = inp;
3392
3393    sprintf(buf, "0x%lx", (long)id);
3394    alt_env_set_var(variable, buf);
3395    return(0);
3396 }
3397
3398 int
3399 do_XtRemoveInput(
3400         int argc,
3401         char *argv[] )
3402 {
3403    XtInputId id;
3404    char *p;
3405    char * errmsg;
3406
3407    if (argc != 2) 
3408    {
3409       errmsg = strdup(GETMESSAGE(5,56, "Usage: XtRemoveInput inputId"));
3410       printerr(str_nill, errmsg, NULL);
3411       free(errmsg);
3412       return(1);
3413    }
3414
3415    id = strtoul(argv[1], &p, 16);
3416    if (p == argv[1]) 
3417    {
3418       errmsg = strdup(GETMESSAGE(5,57, 
3419                         "The inputId parameter must be a hex number: %s"));
3420       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL,
3421                 NULL, NULL, NULL);
3422       free(errmsg);
3423       return(1);
3424    }
3425
3426    DestroyInputRecord(id);
3427    return(0);
3428 }
3429
3430
3431 /*
3432  * This function will attempt to remove the indicated input source.  If,
3433  * however, the source is busy (i.e. the XtRemoveInput() request came
3434  * from within the input handler), then we will simply mark the input
3435  * source as 'pending destroy', and will allow stdInputCB to do the
3436  * actual removing when it is safe.
3437  */
3438 static void
3439 DestroyInputRecord(
3440         XtInputId id )
3441 {
3442    inputrec_t * inp;
3443    int entryIndex;
3444
3445    if ((entryIndex = FindInputRecord(id)) >= 0)
3446    {
3447       inp = activeInputs[entryIndex].inp;
3448
3449       if (inp->flags & INPUT_SOURCE_BUSY)
3450          inp->flags |= INPUT_SOURCE_PENDING_DELETE;
3451       else
3452       {
3453          /* It's ok to delete the source now */
3454          XtRemoveInput(id);
3455          activeInputs[entryIndex].inUse = False;
3456          activeInputs[entryIndex].id = 0;
3457          activeInputs[entryIndex].inp = NULL;
3458          XtFree(inp->lnbuf);
3459          XtFree((char *)inp);
3460       }
3461    }
3462 }
3463
3464
3465 static int
3466 FindInputRecord(
3467         XtInputId id )
3468 {
3469    int i;
3470
3471    for (i = 0; i < numActiveInputs; i++)
3472    {
3473       if ((activeInputs[i].inUse) && (activeInputs[i].id == id))
3474          return(i);
3475    }
3476
3477    return(-1);
3478 }
3479
3480
3481 /*
3482  * This function will initialize some environment variables, and then
3483  * invoke the handler registered for this input source.  If will return
3484  * 'True' if the handler called XtRemoveInput on this source; if this
3485  * has happened, then the 'inp' structure MUST NOT be touched again,
3486  * since it will have been freed up.
3487  */
3488 static Boolean
3489 ProcessInput(
3490         inputrec_t * inp,
3491         int source,
3492         XtInputId id,
3493         Boolean eofFound )
3494 {
3495    Namval_t * sourceVar = nv_search("INPUT_SOURCE", sh.var_tree, NV_ADD);
3496    Namval_t * idVar = nv_search("INPUT_ID", sh.var_tree, NV_ADD);
3497    Namval_t * eofVar = nv_search("INPUT_EOF", sh.var_tree, NV_ADD);
3498    Namval_t * lineVar = nv_search("INPUT_LINE", sh.var_tree, NV_ADD);
3499    char strBuf[25];
3500
3501    /* Initialize the environment variables */
3502    sprintf(strBuf, "%d", source);
3503    nv_putval(sourceVar, strBuf, NV_RDONLY);
3504    sprintf(strBuf, "0x%lx", (long)id);
3505    nv_putval(idVar, strBuf, NV_RDONLY);
3506    sprintf(strBuf, "%s", (eofFound ? "true" : "false"));
3507    nv_putval(eofVar, strBuf, NV_RDONLY);
3508    if ((inp->flags & RAW_INPUT_MODE) || (inp->lnend == 0))
3509    {
3510       strBuf[0] = '\0';
3511       nv_putval(lineVar, strBuf, NV_RDONLY);
3512    }
3513    else
3514       nv_putval(lineVar, inp->lnbuf, NV_RDONLY);
3515
3516    /* Invoke the registered handler */
3517    inp->flags |= INPUT_SOURCE_BUSY;
3518    ksh_eval(inp->cmd);
3519    inp->flags &= ~INPUT_SOURCE_BUSY;
3520
3521    /* Clean up the environment variables */
3522    nv_newattr(sourceVar, 0, 0);
3523    nv_close(sourceVar);
3524    nv_newattr(idVar, 0, 0);
3525    nv_close(idVar);
3526    nv_newattr(eofVar, 0, 0);
3527    nv_close(eofVar);
3528    nv_newattr(lineVar, 0, 0);
3529    nv_close(lineVar);
3530
3531    /* If the handler removed the input source, then process it now */
3532    if (inp->flags & INPUT_SOURCE_PENDING_DELETE)
3533    {
3534       DestroyInputRecord(id);
3535       return(True);
3536    }
3537
3538    return(False);
3539 }
3540
3541
3542 void
3543 Translation_ksh_eval(
3544         Widget w,
3545         XEvent *event,
3546         String *params,
3547         Cardinal *num_params )
3548 {
3549    char buf[128];
3550    int i;
3551    Namval_t * np;
3552    Namval_t * np2;
3553    wtab_t *wtab = NULL;
3554    Namfun_t * clonedDisc;
3555
3556    if (w != NULL) 
3557       wtab = widget_to_wtab(w);
3558
3559    nestingLevel++;
3560    np2 = GetNameValuePair("TRANSLATION_WIDGET");
3561    nv_newattr(np2, 0, 0);
3562    nv_putval(np2, (wtab ? wtab->widid : "Unknown"), NV_RDONLY);
3563    nv_newattr(np2, NV_RDONLY, 0);
3564
3565    np = GetNameValuePair("TRANSLATION_EVENT");
3566    nv_newattr(np, 0, 0);
3567    sprintf(buf, "0x%lx", (long)event);
3568    nv_putval(np, buf, NV_RDONLY);
3569    nv_newattr(np, NV_RDONLY, 0);
3570    clonedDisc = CloneDiscipline(&transDiscipline);
3571    nv_stack(np, clonedDisc);
3572
3573    for (i = 0; i < *num_params; i++) 
3574       ksh_eval(params[i]);
3575
3576    /* Remove the discipline for the hierarchical variables */
3577    nv_stack(np, NULL);
3578    FreeDiscipline(clonedDisc);
3579
3580    /* Free up all of the name/value pairs we created */
3581    FreeNestedVariables();
3582    nestingLevel--;
3583 }
3584
3585
3586 void
3587 RestorePriorEnvVarValues(
3588         Namval_t *np1,
3589         char *value1,
3590         Namval_t *np2,
3591         char *value2 )
3592 {
3593    if (value1 && np1)
3594    {
3595       nv_newattr(np1, 0, 0);
3596       nv_putval(np1, value1, NV_RDONLY);
3597       nv_newattr(np1, NV_RDONLY, 0);
3598    }
3599    if (value2 && np2)
3600    {
3601       nv_newattr(np2, 0, 0);
3602       nv_putval(np2, value2, NV_RDONLY);
3603       nv_newattr(np2, NV_RDONLY, 0);
3604    }
3605 }
3606
3607 /*
3608  * stdCB() is the central routine from which all callback
3609  * functions are dispatched (specified by clientData).  The
3610  * variables "CB_WIDGET" and "CB_CALL_DATA" will be placed in 
3611  * the environment to represent the CallBackWidget handle.  
3612  */
3613
3614 void
3615 stdCB(
3616         void *widget,
3617         caddr_t clientData,
3618         caddr_t callData )
3619 {
3620    char buf[128];
3621    dtksh_client_data_t *cdata = (dtksh_client_data_t *)clientData;
3622    Namval_t * np;
3623    Namval_t * np2;
3624    WidgetClass class;
3625    Namdisc_t * discipline = NULL;
3626    int i;
3627    char * oldCB_WIDGET_value = NULL;
3628    char * oldCB_CALL_DATA_value = NULL;
3629    char * ptr;
3630    Namfun_t * clonedDisc;
3631
3632    /*
3633     * The wtab_t entry of the cdata need not be filled in since
3634     * it could have been set via direct resource setting at widget
3635     * creation time, and the converter for string to callback would
3636     * not have had access to this information (since the widget
3637     * was not created yet.
3638     * Thus, we set it here.  Note that this will happen at most
3639     * one time, since we are modifying the cdata structure.
3640     */
3641    if (cdata->w == NULL) 
3642       cdata->w = widget_to_wtab(widget);
3643
3644    nestingLevel++;
3645    np2 = GetNameValuePair("CB_WIDGET");
3646    nv_newattr(np2, 0, 0);
3647    if (ptr = nv_getval(np2))
3648       oldCB_WIDGET_value = strdup(ptr);
3649    nv_putval(np2, (cdata->w ? cdata->w->widid : "Unknown"), NV_RDONLY);
3650    nv_newattr(np2, NV_RDONLY, 0);
3651
3652    /* Certain callbacks don't pass structures as the calldata */
3653    if ((cdata->cbname) && 
3654        ((strcmp(cdata->cbname, XmNpopupCallback) == 0) ||
3655         (strcmp(cdata->cbname, XmNpopdownCallback) == 0)))
3656    {
3657       /* The calldata indicates the grab type */
3658       XtGrabKind * grabKind = (XtGrabKind *)callData;
3659       switch (*grabKind)
3660       {
3661          case XtGrabNonexclusive:
3662          {
3663             strcpy(buf, "GrabNonexclusive");
3664             break;
3665          }
3666
3667          case XtGrabExclusive:
3668          {
3669             strcpy(buf, "GrabExclusive");
3670             break;
3671          }
3672
3673          default:
3674          {
3675             strcpy(buf, "GrabNone");
3676             break;
3677          }
3678       }
3679    }
3680    else
3681       sprintf(buf, "0x%lx", (long)callData);
3682
3683    np = GetNameValuePair("CB_CALL_DATA");
3684    nv_newattr(np, 0, 0);
3685    if (ptr = nv_getval(np))
3686       oldCB_CALL_DATA_value = strdup(ptr);
3687    nv_putval(np, buf, NV_RDONLY);
3688    nv_newattr(np, NV_RDONLY, 0);
3689
3690    /* 
3691     * Add a discipline for hierarchical variables.
3692     * Need to add a different discipline, based on the callback type,
3693     * since the fields within the callback structure differ depending
3694     * upon the type of callback and the widget.  NOTE: the WMProtocol
3695     * callback will use the default discipline.
3696     */
3697    if (cdata->cbname)
3698    {
3699       if ((strcmp(cdata->cbname, XmNpopupCallback) == 0) ||
3700           (strcmp(cdata->cbname, XmNpopdownCallback) == 0) ||
3701           (strcmp(cdata->cbname, XmNdestroyCallback) == 0))
3702       {
3703          discipline = &nopDiscipline;
3704       }
3705       else if (strcmp(cdata->cbname, XmNhelpCallback) == 0)
3706          discipline = &dftDiscipline;
3707       else
3708       {
3709          class = XtClass(cdata->w->w);
3710          while (class)
3711          {
3712             if (discipline = CheckClassDisciplines(class, cdata->cbname))
3713                break;
3714
3715             class = class->core_class.superclass;
3716          }
3717       }
3718    }
3719
3720    /* 
3721     * If a discipline was found, then use it; otherwise, we MUST set up
3722     * a default discipline; otherwise, any hierarchical variables 
3723     * referenced by the user are not under our control, thus never getting
3724     * freed up, and then also preventing future disciplines from getting
3725     * called when they should have.
3726     */
3727    if (discipline)
3728       clonedDisc = CloneDiscipline(discipline);
3729    else
3730       clonedDisc = CloneDiscipline(&dftDiscipline);
3731    nv_stack(np, clonedDisc);
3732
3733    ksh_eval((char *)cdata->ksh_cmd);
3734
3735    /* We may be nested, so restore old CB_WIDGET & CB_CALL_DATA values */
3736    RestorePriorEnvVarValues(np2, oldCB_WIDGET_value, np, oldCB_CALL_DATA_value);
3737    XtFree(oldCB_WIDGET_value);
3738    XtFree(oldCB_CALL_DATA_value);
3739
3740    /* Remove the discipline for the hierarchical variables */
3741    nv_stack(np, NULL);
3742    FreeDiscipline(clonedDisc);
3743
3744    /* Free up all of the name/value pairs we created */
3745    FreeNestedVariables();
3746    nestingLevel--;
3747
3748    return;
3749 }
3750
3751 /*
3752  * This is the callback handler for the 'workspace changed' callback.
3753  */
3754 void
3755 stdWSCB(
3756         void *widget,
3757         Atom atom,
3758         caddr_t clientData )
3759 {
3760    char buf[128];
3761    dtksh_client_data_t *cdata = (dtksh_client_data_t *)clientData;
3762    Namval_t * np;
3763    Namval_t * np2;
3764    int i;
3765    char * oldCB_WIDGET_value = NULL;
3766    char * oldCB_CALL_DATA_value = NULL;
3767    char * ptr;
3768    Namfun_t * clonedDisc;
3769
3770    nestingLevel++;
3771    np2 = GetNameValuePair("CB_WIDGET");
3772    nv_newattr(np2, 0, 0);
3773    if (ptr = nv_getval(np2))
3774       oldCB_WIDGET_value = strdup(ptr);
3775    nv_putval(np2, cdata->w->widid, NV_RDONLY);
3776    nv_newattr(np2, NV_RDONLY, 0);
3777
3778    np = GetNameValuePair("CB_CALL_DATA");
3779    nv_newattr(np, 0, 0);
3780    sprintf(buf, "0x%lx", (long)atom);
3781    if (ptr = nv_getval(np))
3782       oldCB_CALL_DATA_value = strdup(ptr);
3783    nv_putval(np, buf, NV_RDONLY);
3784    nv_newattr(np, NV_RDONLY, 0);
3785    clonedDisc = CloneDiscipline(&nopDiscipline);
3786    nv_stack(np, clonedDisc);
3787
3788    ksh_eval((char *)cdata->ksh_cmd);
3789
3790    /* We may be nested, so restore old CB_WIDGET & CB_CALL_DATA values */
3791    RestorePriorEnvVarValues(np2, oldCB_WIDGET_value, np, oldCB_CALL_DATA_value);
3792    XtFree(oldCB_WIDGET_value);
3793    XtFree(oldCB_CALL_DATA_value);
3794
3795    /* Remove the discipline for the hierarchical variables */
3796    nv_stack(np, NULL);
3797    FreeDiscipline(clonedDisc);
3798
3799    /* Free up all of the name/value pairs we created */
3800    FreeNestedVariables();
3801    nestingLevel--;
3802 }
3803
3804 void
3805 stdInputCB(
3806         inputrec_t *inp,
3807         int *source,
3808         XtInputId *id )
3809 {
3810    char buf[LINESIZE];
3811    char cmdbuf[LINESIZE];
3812    int cmd;
3813    char *p;
3814    int i, n, j;
3815    char * errmsg;
3816    int len;
3817
3818    /* If in 'raw' mode, then simply let the handler do all the work */
3819    if (inp->flags & RAW_INPUT_MODE)
3820    {
3821       ProcessInput(inp, *source, *id, False);
3822       return;
3823    }
3824
3825    /* try to read some input from the fd */
3826    if ((n = read(inp->fd, buf, sizeof(buf)-1)) <= 0) 
3827    {
3828       /* EOF; notify handler, passing in any remaining buffered data */
3829       if ((inp->lnend > 0) || (inp->lineWasTouched))
3830       {
3831          /* Force one call with the data, and a 2nd with the EOF */
3832          inp->lnbuf[inp->lnend] = '\0';
3833          ProcessInput(inp, *source, *id, False);
3834       }
3835       inp->lastCharIsBackslash = False;
3836       inp->lineWasTouched = False;
3837       inp->lnbuf[0] = '\0';
3838       inp->lnend = 0;
3839       ProcessInput(inp, *source, *id, True);
3840       return;
3841    }
3842
3843    /* 
3844     * Go through appending to current line, execute line if you 
3845     * get an unquoted newline.  Strip off the newline, so that
3846     * we are consistent with the ksh 'read' command, remove
3847     * escaped newlines, and do backslash processing.
3848     */
3849    for (i = 0; i < n; ) 
3850    {
3851 #ifdef NLS16
3852       len = mblen(buf+i, MB_CUR_MAX);
3853 #else
3854       len = 1;
3855 #endif
3856       inp->lineWasTouched = True;
3857
3858       if ((inp->lnend + len) >= (inp->lnbufsize-1))
3859       {
3860          /* Grow the input buffer */
3861          inp->lnbufsize += (n + LINESIZE + 5);
3862          inp->lnbuf = XtRealloc(inp->lnbuf, inp->lnbufsize);
3863       }
3864
3865       /* Perform backslash processing */
3866       if ((len == 1) && (buf[i] == '\\') && (!inp->lastCharIsBackslash))
3867       {
3868          /* Skip this character; the next character will be treated specially */
3869          inp->lastCharIsBackslash = True;
3870          i++;
3871          continue;
3872       }
3873
3874       /*
3875        * If the previous character has been a backslash, then the current
3876        * character gets placed into the buffer without any special
3877        * processing; the exception is the newline character, which gets
3878        * dumped.
3879        */
3880       if ((len == 1) && (buf[i] == '\n'))
3881       {
3882          /* 
3883           * If the newline is escaped, then drop it, and continue.
3884           * Otherwise, process the line.
3885           */
3886          i++;
3887          if (inp->lastCharIsBackslash)
3888          {
3889             inp->lastCharIsBackslash = False;
3890             continue;
3891          }
3892
3893          inp->lnbuf[inp->lnend] = '\0';
3894          if (ProcessInput(inp, *source, *id, False))
3895          {
3896             /* The handler called XtRemoveInput() on this source; abort */
3897             return;
3898          }
3899          inp->lnend = 0;
3900          inp->lineWasTouched = False;
3901       }
3902       else
3903       {
3904          /* Simply copy the next character into the buffer */
3905          inp->lastCharIsBackslash = False;
3906          for (j = 0; j < len; j++)
3907             inp->lnbuf[inp->lnend++] = buf[i++];
3908       }
3909    }
3910 }
3911
3912 int
3913 stdWorkProcCB(
3914         char *clientData )
3915 {
3916    int retcode;
3917    int i;
3918
3919    retcode = ksh_eval((char *)clientData);
3920    if (retcode != 0)
3921    {
3922       /* This is tricky, because we do not have the workproc id */
3923       for (i = 0; i < workProcCmdsSize; i++)
3924       {
3925          if (clientData == workProcCmds[i].cmd)
3926          {
3927             RemoveCmdStr(WORKPROC_CMDS, (long)workProcCmds[i].id);
3928             break;
3929          }
3930       }
3931    }
3932    return(retcode);
3933 }
3934
3935 void
3936 stdTimerCB(
3937         char *clientData,
3938         long *id )
3939 {
3940         ksh_eval((char *)clientData);
3941         RemoveCmdStr(TIMEOUT_CMDS, (long)*id);
3942         return;
3943 }
3944
3945
3946 int
3947 do_XFlush(
3948         int argc,
3949         char *argv[] )
3950 {
3951    char *p;
3952    Display * display;
3953    char * errmsg;
3954
3955    if (argc != 2) 
3956    {
3957       errmsg = strdup(GETMESSAGE(5,59, "Usage: XFlush display"));
3958       printerr(str_nill, errmsg, NULL);
3959       free(errmsg);
3960       return(1);
3961    }
3962
3963    display = (Display *)strtoul(argv[1], &p, 0);
3964    if (p == argv[1]) 
3965    {
3966       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
3967       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
3968                 NULL, NULL);
3969       free(errmsg);
3970       return(1);
3971    }
3972
3973    XFlush(display);
3974    return(0);
3975 }
3976
3977 int
3978 do_XSync(
3979         int argc,
3980         char *argv[] )
3981 {
3982    Boolean discard;
3983    XrmValue fval, tval;
3984    char *p;
3985    Display * display;
3986    char * errmsg;
3987
3988    if (argc != 3) 
3989    {
3990       errmsg = strdup(GETMESSAGE(5,60, "Usage: XSync display discard"));
3991       printerr(str_nill, errmsg, NULL);
3992       free(errmsg);
3993       return(1);
3994    }
3995
3996    display = (Display *)strtoul(argv[1], &p, 0);
3997    if (p == argv[1]) 
3998    {
3999       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
4000       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
4001                 NULL, NULL);
4002       free(errmsg);
4003       return(1);
4004    }
4005
4006    fval.addr = argv[2];
4007    fval.size = strlen(argv[2]);
4008    XtConvert(Toplevel, XtRString, &fval, XtRBoolean, &tval);
4009
4010    if (tval.size != 0) 
4011       discard = *((Boolean *)(tval.addr));
4012    else
4013       return(1);
4014
4015    XSync(display, discard);
4016    return(0);
4017 }
4018
4019 int
4020 do_XRaiseWindow(
4021         int argc,
4022         char *argv[] )
4023 {
4024    Boolean discard;
4025    XrmValue fval, tval;
4026    wtab_t *w;
4027    char *p;
4028    Display * display;
4029    Window window;
4030    char * errmsg;
4031
4032    if (argc != 3) 
4033    {
4034       errmsg = strdup(GETMESSAGE(5,61, "Usage: XRaiseWindow display window"));
4035       printerr(str_nill, errmsg, NULL);
4036       free(errmsg);
4037       return(1);
4038    }
4039
4040    display = (Display *)strtoul(argv[1], &p, 0);
4041    if (p == argv[1]) 
4042    {
4043       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
4044       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
4045                 NULL, NULL);
4046       free(errmsg);
4047       return(1);
4048    }
4049    window = (Window)strtoul(argv[2], &p, 0);
4050    if (p == argv[2]) 
4051    {
4052       errmsg = strdup(GetSharedMsg(DT_BAD_WINDOW));
4053       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
4054                 NULL, NULL);
4055       free(errmsg);
4056       return(1);
4057    }
4058
4059    XRaiseWindow(display, window);
4060    return(0);
4061 }
4062
4063 static int
4064 XtSetSensitive_usage(
4065         char *arg0 )
4066 {
4067    char * errmsg;
4068
4069    errmsg = strdup(GETMESSAGE(5,62, "Usage: %s widget [True|False]"));
4070    printerrf(str_nill, errmsg, arg0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
4071    free(errmsg);
4072    return(1);
4073 }
4074
4075 int
4076 do_XtSetSensitive(
4077         int argc,
4078         char *argv[] )
4079 {
4080    wtab_t *w;
4081    Boolean bool;
4082    XrmValue fval, tval;
4083
4084    if (argc != 3)
4085       return(XtSetSensitive_usage(argv[0]));
4086
4087    fval.addr = argv[2];
4088    fval.size = strlen(argv[2]);
4089    XtConvert(Toplevel, XtRString, &fval, XtRBoolean, &tval);
4090
4091    if (tval.size != 0) 
4092       bool = *((Boolean *)(tval.addr));
4093    else
4094       return(1);
4095
4096    w = str_to_wtab(argv[0], argv[1]);
4097    if (w != NULL) 
4098       XtSetSensitive(w->w, bool);
4099    else 
4100       return(1);
4101    return(0);
4102 }
4103
4104 static int
4105 RegisterTranslations(
4106         void (*func)(),
4107         int argc,
4108         char *argv[] )
4109 {
4110    wtab_t *w;
4111    XtTranslations translationTable;
4112    XrmValue fval, tval;
4113    char * errmsg;
4114
4115    if (argc != 3)
4116    {
4117       errmsg = strdup(GETMESSAGE(5,63, "Usage: %s widget translations"));
4118       printerrf(str_nill, errmsg, argv[0], NULL, NULL,
4119                NULL, NULL, NULL, NULL, NULL);
4120       free(errmsg);
4121       return(1);
4122    }
4123
4124    w = str_to_wtab(argv[0], argv[1]);
4125    if (w == NULL) 
4126       return(1);
4127
4128    fval.addr = argv[2];
4129    fval.size = strlen(argv[2]);
4130    XtConvert(Toplevel, XtRString, &fval, XtRTranslationTable, &tval);
4131
4132    if (tval.size != 0) 
4133       translationTable = *((XtTranslations *)(tval.addr));
4134    else
4135       return(1);
4136
4137    (*func)(w->w, translationTable);
4138    return(0);
4139 }
4140
4141 int
4142 do_XtOverrideTranslations(
4143         int argc,
4144         char **argv )
4145 {
4146    return(RegisterTranslations(XtOverrideTranslations, argc, argv));
4147 }
4148
4149 int
4150 do_XtAugmentTranslations(
4151         int argc,
4152         char **argv )
4153 {
4154    return(RegisterTranslations(XtAugmentTranslations, argc, argv));
4155 }
4156
4157 int
4158 do_XtUninstallTranslations(
4159         int argc,
4160         char *argv[] )
4161 {
4162    wtab_t *w;
4163    XtTranslations * translationTable;
4164    XrmValue fval, tval;
4165    char * errmsg;
4166
4167    if (argc != 2)
4168    {
4169       errmsg = strdup(GETMESSAGE(5,64, 
4170                       "Usage: XtUninstallTranslations widget"));
4171       printerr(str_nill, errmsg, NULL);
4172       free(errmsg);
4173       return(1);
4174    }
4175
4176    w = str_to_wtab(argv[0], argv[1]);
4177    if (w == NULL) 
4178       return(1);
4179
4180    XtUninstallTranslations(w->w);
4181    return(0);
4182 }
4183
4184 int
4185 do_XtParent(
4186         int argc,
4187         char **argv )
4188 {
4189    char *arg0 = argv[0];
4190    char * wname;
4191    wtab_t *wtab;
4192    classtab_t *ctab;
4193    char buf[128];
4194    char * errmsg;
4195    
4196    if (argc != 3 ) {
4197         errmsg = strdup(GETMESSAGE(5,65, "Usage: XtParent variable widget"));
4198         printerr(str_nill, errmsg, NULL);
4199         free(errmsg);
4200         return(1);
4201    }
4202    wname = argv[2];
4203    wtab = str_to_wtab(arg0, wname);
4204    if (wtab == NULL) {
4205         return(1);
4206    }
4207
4208    if (wtab->parent == NULL) {
4209            wtab = widget_to_wtab(XtParent(wtab->w));
4210            if (wtab == NULL)
4211              return(1);
4212            /*
4213             * If the widget class has no resources registered, then this is
4214             * the first known instance of this widget class, so we need to
4215             * force the resource list to be loaded.  This can frequently
4216             * occur if a Motif convenience function is used, which creates
4217             * a 'hidden' parent.
4218             */
4219            ctab = wtab->wclass;
4220            if (ctab->res == NULL)
4221               (void)str_to_class(arg0, ctab->cname);
4222    } else
4223         wtab = wtab->parent;
4224
4225    sprintf(buf, "%s", wtab->widid);
4226    alt_env_set_var(argv[1], buf);
4227    return(0);
4228 }
4229
4230 int
4231 do_XtLastTimestampProcessed(
4232         int argc,
4233         char **argv )
4234 {
4235    char *arg0 = argv[0];
4236    Display * display;
4237    char * p;
4238    char buf[128];
4239    char * errmsg;
4240    
4241    if (argc != 3 ) {
4242         errmsg = strdup(GETMESSAGE(5,66, 
4243                  "Usage: XtLastTimestampProcessed variable display"));
4244         printerr(str_nill, errmsg, NULL);
4245         free(errmsg);
4246         return(1);
4247    }
4248
4249    display = (Display *)strtoul(argv[2], &p, 0);
4250    if (p == argv[2]) 
4251    {
4252       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
4253       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
4254                 NULL, NULL);
4255       free(errmsg);
4256       return(1);
4257    }
4258
4259    sprintf(buf, "%ld", (long)XtLastTimestampProcessed(display));
4260    alt_env_set_var(argv[1], buf);
4261    return(0);
4262 }
4263
4264 /**********************************************/
4265
4266 /*
4267  * The following two functions work for both standard Xt callbacks
4268  * (which are identified by a callback name) and WM protocol callbacks
4269  * (which are identified by a property atom).  That is why both of
4270  * these parameters are passed in.  It is usually the case that only
4271  * one of the 'cbname' and 'propAtom' parameters are used; the unused
4272  * one should be set to NULL (cbname) or None (propAtom).
4273  */
4274
4275 dtksh_client_data_t *
4276 GetNewCBData(
4277         char *ksh_cmd,
4278         wtab_t *w,
4279         char *cbname,
4280         Atom propAtom )
4281 {
4282    dtksh_client_data_t * cdata;
4283    int i;
4284    int j;
4285
4286    /* Can we reuse an existing entry? */
4287    if ((i = LocateCBRecord (w, cbname, ksh_cmd, propAtom, NULL)) >= 0)
4288    {
4289       cdata = cbDataTable[i];
4290       cdata->refCount++;
4291       return(cdata);
4292    }
4293
4294    /* Look for an open slot */
4295    for (i = 0; i < cbDataTableSize; i++)
4296    {
4297       if (cbDataTable[i] == NULL)
4298          break;
4299    }
4300
4301    if (i >= cbDataTableSize)
4302    {
4303       /* Need to enlarge the table */
4304       cbDataTableSize += 10;
4305       cbDataTable = (dtksh_client_data_t **)
4306                      XtRealloc((XtPointer)cbDataTable,
4307                      sizeof(dtksh_client_data_t *) * cbDataTableSize);
4308       for (j = i; j < cbDataTableSize; j++)
4309          cbDataTable[j] = NULL;
4310    }
4311
4312    cdata = (dtksh_client_data_t *)XtMalloc(sizeof(dtksh_client_data_t));
4313    if (ksh_cmd)
4314       cdata->ksh_cmd = strdup(ksh_cmd);
4315    else
4316       cdata->ksh_cmd = NULL;
4317    cdata->w = w;
4318    if (cbname)
4319       cdata->cbname = strdup(cbname);
4320    else
4321       cdata->cbname = NULL;
4322    cdata->propAtom = propAtom;
4323    cdata->handle = NULL;
4324    cdata->refCount = 1;
4325
4326    cbDataTable[i] = cdata;
4327    return(cdata);
4328 }
4329
4330 int
4331 LocateCBRecord(
4332         wtab_t *w,
4333         char *cbname,
4334         char *ksh_cmd,
4335         Atom propAtom,
4336         DtWsmCBContext handle )
4337 {
4338    int i;
4339
4340    /* Locate the matching table entry */
4341    for (i = 0; i < cbDataTableSize; i++)
4342    {
4343       if (cbDataTable[i])
4344       {
4345          if ((((cbname == NULL) && (cbDataTable[i]->cbname == NULL)) ||
4346              (((cbname != NULL) && (cbDataTable[i]->cbname != NULL)) &&
4347              (strcmp(cbDataTable[i]->cbname, cbname) == 0))) &&
4348              (cbDataTable[i]->w == w) &&
4349              (strcmp(cbDataTable[i]->ksh_cmd, ksh_cmd) == 0) &&
4350              (cbDataTable[i]->propAtom == propAtom) &&
4351              (cbDataTable[i]->handle == (XtPointer)handle))
4352          {
4353             return(i);
4354          }
4355       }
4356    }
4357
4358    return(-1);
4359 }
4360
4361 /**********************************************/
4362
4363 void
4364 stdEH(
4365         void *widget,
4366         caddr_t clientData,
4367         XEvent *event,
4368         Boolean *continueToDispatch )
4369 {
4370    char buf[128];
4371    dtksh_event_handler_data_t *ehdata;
4372    int i;
4373    Namval_t * np;
4374    Namval_t * np2;
4375    Namfun_t * clonedDisc;
4376
4377    ehdata = (dtksh_event_handler_data_t *)clientData;
4378
4379    nestingLevel++;
4380    np2 = GetNameValuePair("EH_WIDGET");
4381    nv_newattr(np2, 0, 0);
4382    nv_putval(np2, ehdata->w->widid, NV_RDONLY);
4383    nv_newattr(np2, NV_RDONLY, 0);
4384
4385    np = GetNameValuePair("EH_EVENT");
4386    nv_newattr(np, 0, 0);
4387    sprintf(buf, "0x%lx", (long)event);
4388    nv_putval(np, buf, NV_RDONLY);
4389    clonedDisc = CloneDiscipline(&ehDiscipline);
4390    nv_stack(np, clonedDisc);
4391
4392    ksh_eval((char *)ehdata->ksh_cmd);
4393
4394    /* Remove the discipline for the hierarchical variables */
4395    nv_stack(np, NULL);
4396    FreeDiscipline(clonedDisc);
4397
4398    /* Free up all of the name/value pairs we created */
4399    FreeNestedVariables();
4400    nestingLevel--;
4401 }
4402
4403 /*
4404  * For a given widget, if the ksh-cmd is the same as one already
4405  * registered for this widget, then we will merge them into a
4406  * single event handler (by merging the event masks), as is done
4407  * by Xt anyways.
4408  */
4409
4410 dtksh_event_handler_data_t *
4411 GetNewEHData(
4412         char *ksh_cmd,
4413         wtab_t *w,
4414         EventMask eventMask,
4415         Boolean nonMaskable )
4416 {
4417    dtksh_event_handler_data_t * ehdata;
4418    int i;
4419    int j;
4420
4421    /* Can we merge with an existing entry? */
4422    if ((i = LocateEHRecord (w, ksh_cmd)) >= 0)
4423    {
4424       ehdata = ehDataTable[i];
4425       if (nonMaskable)
4426          ehdata->nonMaskable = True;
4427       ehdata->eventMask |= eventMask;
4428       return(ehdata);
4429    }
4430
4431    /* Look for an open slot */
4432    for (i = 0; i < ehDataTableSize; i++)
4433    {
4434       if (ehDataTable[i] == NULL)
4435          break;
4436    }
4437
4438    if (i >= ehDataTableSize)
4439    {
4440       /* Need to enlarge the table */
4441       ehDataTableSize += 10;
4442       ehDataTable = (dtksh_event_handler_data_t **)
4443                      XtRealloc((XtPointer)ehDataTable,
4444                      sizeof(dtksh_event_handler_data_t *) * ehDataTableSize);
4445       for (j = i; j < ehDataTableSize; j++)
4446          ehDataTable[j] = NULL;
4447    }
4448
4449    ehdata = (dtksh_event_handler_data_t *)
4450             XtMalloc(sizeof(dtksh_event_handler_data_t));
4451    if (ksh_cmd)
4452       ehdata->ksh_cmd = strdup(ksh_cmd);
4453    else
4454       ehdata->ksh_cmd = NULL;
4455    ehdata->w = w;
4456    ehdata->eventMask = eventMask;
4457    ehdata->nonMaskable = nonMaskable;
4458
4459    ehDataTable[i] = ehdata;
4460    return(ehdata);
4461 }
4462
4463
4464 static int
4465 LocateEHRecord(
4466         wtab_t *w,
4467         char *ksh_cmd )
4468 {
4469    int i;
4470
4471    /* Locate the matching event handler table entry */
4472    for (i = 0; i < ehDataTableSize; i++)
4473    {
4474       if (ehDataTable[i])
4475       {
4476          if ((ehDataTable[i]->w == w) &&
4477              (strcmp(ehDataTable[i]->ksh_cmd, ksh_cmd) == 0))
4478          {
4479             return(i);
4480          }
4481       }
4482    }
4483
4484    return(-1);
4485 }
4486
4487 int
4488 do_DtSessionRestorePath(
4489         int argc,
4490         char *argv[] )
4491 {
4492    wtab_t *w;
4493    char * path;
4494    Boolean status;
4495    char * errmsg;
4496
4497    if (argc != 4) 
4498    {
4499       errmsg = strdup(GETMESSAGE(5,67, 
4500                "Usage: DtSessionRestorePath widget pathVariable saveFile"));
4501       printerr(str_nill, errmsg, NULL);
4502       free(errmsg);
4503       return(1);
4504    }
4505
4506    w = str_to_wtab(argv[0], argv[1]);
4507    if (w == NULL) 
4508       return(1);
4509
4510    status = DtSessionRestorePath(w->w, &path, argv[3]);
4511    if (status)
4512       alt_env_set_var(argv[2], path);
4513    else
4514       alt_env_set_var(argv[2], str_nill);
4515
4516    return (!status);
4517 }
4518
4519 int
4520 do_DtSessionSavePath(
4521         int argc,
4522         char *argv[] )
4523 {
4524    wtab_t *w;
4525    char * path;
4526    char * file;
4527    Boolean status;
4528    char * errmsg;
4529
4530    if (argc != 4) 
4531    {
4532       errmsg = strdup(GETMESSAGE(5,68, 
4533                "Usage: DtSessionSavePath widget pathVariable fileVariable"));
4534       printerr(str_nill, errmsg, NULL);
4535       free(errmsg);
4536       return(1);
4537    }
4538
4539    w = str_to_wtab(argv[0], argv[1]);
4540    if (w == NULL) 
4541       return(1);
4542
4543    status = DtSessionSavePath(w->w, &path, &file);
4544    if (status)
4545    {
4546       env_set_var(argv[2], path);
4547       env_set_var(argv[3], file);
4548    }
4549    else
4550    {
4551       env_blank(argv[2]);
4552       env_blank(argv[3]);
4553    }
4554
4555    return (!status);
4556 }
4557
4558 int
4559 do_DtShellIsIconified(
4560         int argc,
4561         char *argv[] )
4562 {
4563    wtab_t *w;
4564    Boolean status;
4565    Atom actual_type;
4566    int  actual_format;
4567    unsigned long nitems;
4568    unsigned long leftover;
4569    WmStateData * wm_state;
4570    Atom wmStateAtom;
4571    char * errmsg;
4572
4573    if (argc != 2) 
4574    {
4575       errmsg = strdup(GETMESSAGE(5,69, "Usage: DtShellIsIconified widget"));
4576       printerr(str_nill, errmsg, NULL);
4577       free(errmsg);
4578       return(1);
4579    }
4580
4581    w = str_to_wtab(argv[0], argv[1]);
4582    if (w == NULL) 
4583       return(1);
4584
4585    wmStateAtom = XmInternAtom (XtDisplay(w->w), "WM_STATE", False);
4586
4587    /*  Getting the WM_STATE property to see if iconified or not */
4588    XGetWindowProperty(XtDisplay(w->w), XtWindow (w->w),
4589                        wmStateAtom, 0L, (long) LINESIZE, False,
4590                        wmStateAtom, &actual_type, &actual_format,
4591                        &nitems, &leftover, (unsigned char **) &wm_state);
4592
4593    return (wm_state->state != IconicState);
4594 }
4595
4596 int
4597 do_DtSetStartupCommand(
4598         int argc,
4599         char *argv[] )
4600 {
4601    wtab_t *w;
4602    Atom commandAtom;
4603    char * errmsg;
4604
4605    if (argc != 3) 
4606    {
4607       errmsg = strdup(GETMESSAGE(5,70, 
4608                        "Usage: DtSetStartupCommand widget command"));
4609       printerr(str_nill, errmsg, NULL);
4610       free(errmsg);
4611       return(1);
4612    }
4613
4614    w = str_to_wtab(argv[0], argv[1]);
4615    if (w == NULL) 
4616       return(1);
4617
4618    commandAtom = XA_WM_COMMAND;
4619
4620    XChangeProperty(XtDisplay(w->w), XtWindow(w->w), commandAtom,
4621                    XA_STRING, 8, PropModeReplace,
4622                    (unsigned char *)argv[2], strlen(argv[2])+1);
4623    XSync(XtDisplay(w->w), False);
4624
4625    return(0);
4626 }
4627
4628 /* This only works if the widget is not yet realized */
4629 int
4630 do_DtSetIconifyHint(
4631         int argc,
4632         char *argv[] )
4633 {
4634    wtab_t *w;
4635    Boolean state;
4636    XrmValue fval, tval;
4637    XWMHints   *wmhints;
4638    Arg args[5];
4639    char * errmsg;
4640
4641    if (argc != 3) 
4642    {
4643       errmsg = strdup(GETMESSAGE(5,71, 
4644                       "Usage: DtSetIconifyHint widget boolean"));
4645       printerr(str_nill, errmsg, NULL);
4646       free(errmsg);
4647       return(1);
4648    }
4649
4650    w = str_to_wtab(argv[0], argv[1]);
4651    if (w == NULL) 
4652       return(1);
4653
4654    fval.addr = argv[2];
4655    fval.size = strlen(argv[2]);
4656    XtConvert(Toplevel, XtRString, &fval, XtRBoolean, &tval);
4657
4658    if (tval.size != 0) 
4659       state = *((Boolean *)(tval.addr));
4660    else
4661       return(1);
4662
4663    if (state)
4664    {
4665      /* add the iconify hint to the current shell */
4666      XtSetArg(args[0], XmNinitialState, IconicState);
4667      XtSetValues(w->w, args, 1);
4668    }
4669    else
4670    {
4671      /* Remove the iconify hint from the current shell */
4672      wmhints = XGetWMHints(XtDisplay(w->w), XtWindow(w->w));
4673      wmhints->flags |= IconWindowHint;
4674      wmhints->initial_state = NormalState;
4675      XSetWMHints(XtDisplay(w->w), XtWindow(w->w), wmhints);
4676    }
4677
4678    return(0);
4679 }
4680
4681
4682 int
4683 do_DtWsmAddWorkspaceFunctions(
4684         int argc,
4685         char *argv[] )
4686 {
4687    return(WsmCommonProc(argc, argv, (void (*)())DtWsmAddWorkspaceFunctions));
4688 }
4689
4690
4691 int
4692 do_DtWsmRemoveWorkspaceFunctions(
4693         int argc,
4694         char *argv[] )
4695 {
4696    return(WsmCommonProc(argc, argv, (void (*)())DtWsmRemoveWorkspaceFunctions));
4697 }
4698
4699
4700 static int
4701 WsmCommonProc(
4702         int argc,
4703         char *argv[],
4704         void (*func)())
4705 {
4706    wtab_t *w;
4707    Display * display;
4708    Window window;
4709    char * p;
4710    char buf[256];
4711    char * errmsg;
4712
4713    if (argc != 3) 
4714    {
4715       errmsg = strdup(GetSharedMsg(DT_USAGE_DISPLAY_WINDOW));
4716       printerrf(str_nill, errmsg, argv[0], NULL, NULL, NULL, NULL,
4717                 NULL, NULL, NULL);
4718       free(errmsg);
4719       return(1);
4720    }
4721
4722    display = (Display *)strtoul(argv[1], &p, 0);
4723    if (p == argv[1]) 
4724    {
4725       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
4726       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
4727                 NULL, NULL);
4728       free(errmsg);
4729       return(1);
4730    }
4731    window = (Window)strtoul(argv[2], &p, 0);
4732    if (p == argv[2]) 
4733    {
4734       errmsg = strdup(GetSharedMsg(DT_BAD_WINDOW));
4735       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
4736                 NULL, NULL);
4737       free(errmsg);
4738       return(1);
4739    }
4740
4741    (*func)(display, window);
4742    return (0);
4743 }
4744
4745
4746 int
4747 do_DtWsmGetCurrentWorkspace(
4748         int argc,
4749         char *argv[] )
4750 {
4751    wtab_t *w;
4752    Display * display;
4753    Window rootWindow;
4754    char * p;
4755    Atom atom;
4756    char buf[256];
4757    char * errmsg;
4758
4759    if (argc != 4) 
4760    {
4761       errmsg = strdup(GetSharedMsg(DT_USAGE_DISPLAY_ROOT_VAR));
4762       printerrf(str_nill, errmsg, argv[0], NULL, NULL, NULL, NULL, NULL,
4763                 NULL, NULL);
4764       free(errmsg);
4765       return(1);
4766    }
4767
4768    display = (Display *)strtoul(argv[1], &p, 0);
4769    if (p == argv[1]) 
4770    {
4771       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
4772       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
4773                 NULL, NULL);
4774       free(errmsg);
4775       env_blank(argv[3]);
4776       return(1);
4777    }
4778    rootWindow = (Window)strtoul(argv[2], &p, 0);
4779    if (p == argv[2]) 
4780    {
4781       errmsg = strdup(GETMESSAGE(5,73, 
4782                       "The rootWindow parameter is invalid: %s"));
4783       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
4784                 NULL, NULL);
4785       free(errmsg);
4786       env_blank(argv[3]);
4787       return(1);
4788    }
4789
4790    DtWsmGetCurrentWorkspace(display, rootWindow, &atom);
4791    sprintf(buf, "%ld", (long)atom);
4792    env_set_var(argv[3], buf);
4793    return (0);
4794 }
4795
4796
4797 int
4798 do_DtWsmSetCurrentWorkspace(
4799         int argc,
4800         char *argv[] )
4801 {
4802    wtab_t *w;
4803    char * p;
4804    Atom atom;
4805    Status result;
4806    char * errmsg;
4807
4808    if (argc != 3) 
4809    {
4810       errmsg = strdup(GETMESSAGE(5,74, 
4811                       "Usage: DtWsmSetCurrentWorkspace widget atom"));
4812       printerr(str_nill, errmsg, NULL);
4813       free(errmsg);
4814       return(1);
4815    }
4816
4817    w = str_to_wtab(argv[0], argv[1]);
4818    if (w == NULL) 
4819       return(1);
4820
4821    atom = (Atom)strtoul(argv[2], &p, 0);
4822    if (p == argv[2])
4823    {
4824       errmsg = strdup(GETMESSAGE(5,75, "The workspace atom is invalid: %s"));
4825       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
4826                 NULL, NULL);
4827       free(errmsg);
4828       return(1);
4829    }
4830
4831    result = DtWsmSetCurrentWorkspace(w->w, atom);
4832    if (result == DT_SVC_SUCCESS)
4833       return (0);
4834    else
4835       return (1);
4836 }
4837
4838
4839 static int
4840 GetWorkspaceList(
4841         char *usageMsg,
4842         Boolean getOccupied,
4843         int argc,
4844         char *argv[] )
4845 {
4846    wtab_t *w;
4847    char * p;
4848    Display * display;
4849    Window root;
4850    unsigned long numWS;
4851    Atom * wsList;
4852    char * buf;
4853    char atom[128];
4854    int result;
4855    int i;
4856    char * errmsg;
4857
4858    if (argc != 4) 
4859    {
4860       printerrf(str_nill, usageMsg, argv[0], NULL, NULL, NULL, NULL, NULL,
4861                 NULL, NULL);
4862       return(1);
4863    }
4864
4865    display = (Display *)strtoul(argv[1], &p, 0);
4866    if (p == argv[1]) 
4867    {
4868       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
4869       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
4870                 NULL, NULL);
4871       free(errmsg);
4872       env_blank(argv[3]);
4873       return(1);
4874    }
4875    root = (Window)strtoul(argv[2], &p, 0);
4876    if (p == argv[2]) 
4877    {
4878       errmsg = strdup(GetSharedMsg(DT_BAD_WINDOW));
4879       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
4880                 NULL, NULL);
4881       free(errmsg);
4882       env_blank(argv[3]);
4883       return(1);
4884    }
4885
4886    if (getOccupied)
4887       result = DtWsmGetWorkspacesOccupied(display, root, &wsList, &numWS);
4888    else
4889       result = DtWsmGetWorkspaceList(display, root, &wsList, (int *)&numWS);
4890
4891    if (result == Success)
4892    {
4893       buf = XtMalloc(1);
4894       buf[0] = '\0';
4895
4896       for (i = 0; i < numWS; i++)
4897       {
4898          sprintf(atom, "%ld", (long)wsList[i]);
4899          buf = XtRealloc(buf, strlen(buf) + strlen(atom) + 2);
4900          if (i != 0)
4901             strcat(buf, ",");
4902          strcat(buf, atom);
4903       }
4904
4905       env_set_var(argv[3], buf);
4906       XtFree(buf);
4907       XFree (wsList);
4908       return (0);
4909    }
4910    else
4911    {
4912       env_blank(argv[3]);
4913       return (1);
4914    }
4915 }
4916
4917
4918 int
4919 do_DtWsmGetWorkspaceList(
4920         int argc,
4921         char *argv[] )
4922 {
4923    char * errmsg;
4924    int retVal;
4925
4926    errmsg = strdup(GetSharedMsg(DT_USAGE_DISPLAY_ROOT_VAR));
4927    retVal = GetWorkspaceList(errmsg, False, argc, argv);
4928    free(errmsg);
4929    return(retVal);
4930 }
4931
4932
4933 int
4934 do_DtWsmGetWorkspacesOccupied(
4935         int argc,
4936         char *argv[] )
4937 {
4938    char * errmsg;
4939    int retVal;
4940
4941    errmsg = strdup(GetSharedMsg(DT_USAGE_DISPLAY_WINDOW_VAR));
4942    retVal = GetWorkspaceList(errmsg, True, argc, argv);
4943    free(errmsg);
4944    return(retVal);
4945 }
4946
4947
4948 int
4949 do_DtWsmSetWorkspacesOccupied(
4950         int argc,
4951         char *argv[] )
4952 {
4953    char * p;
4954    Display * display;
4955    Window window;
4956    unsigned long numWS;
4957    Atom * wsList;
4958    char * buf;
4959    int i;
4960    char * nextAtom;
4961    char * errmsg;
4962
4963    if (argc != 4) 
4964    {
4965       errmsg = strdup(GETMESSAGE(5,78, 
4966              "Usage: DtWsmSetWorkspacesOccupied display window workspaceList"));
4967       printerr(str_nill, errmsg, NULL);
4968       free(errmsg);
4969       return(1);
4970    }
4971
4972    display = (Display *)strtoul(argv[1], &p, 0);
4973    if (p == argv[1]) 
4974    {
4975       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
4976       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
4977                 NULL, NULL);
4978       free(errmsg);
4979       return(1);
4980    }
4981    window = (Window)strtoul(argv[2], &p, 0);
4982    if (p == argv[2]) 
4983    {
4984       errmsg = strdup(GetSharedMsg(DT_BAD_WINDOW));
4985       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
4986                 NULL, NULL);
4987       free(errmsg);
4988       return(1);
4989    }
4990
4991    numWS = 0;
4992    p = argv[3];
4993
4994    /* Strip leading spaces */
4995    while (*p == ' ')
4996       p++;
4997
4998    nextAtom = strtok(p, ",");
4999
5000    wsList = (Atom *)XtMalloc(1);
5001    wsList[0] = '\0';
5002    while (nextAtom)
5003    {
5004       if (strlen(nextAtom) > 0)
5005       {
5006          wsList = (Atom *)XtRealloc((char *)wsList, sizeof(Atom) * (numWS + 1));
5007          wsList[numWS] = atol(nextAtom);
5008          numWS++;
5009          nextAtom = strtok(NULL, ",");
5010       }
5011    }
5012
5013    DtWsmSetWorkspacesOccupied(display, window, wsList, numWS);
5014    XtFree ((char *)wsList);
5015
5016    return (0);
5017 }
5018
5019
5020 int
5021 do_DtWsmGetCurrentBackdropWindow(
5022         int argc,
5023         char *argv[] )
5024 {
5025    char * p;
5026    Display * display;
5027    Window rootWindow, returnedWin;
5028    char * errmsg;
5029
5030    if (argc != 4) 
5031    {
5032       errmsg = strdup(GetSharedMsg(DT_USAGE_DISPLAY_ROOT_VAR));
5033       printerrf(str_nill, errmsg, argv[0], NULL, NULL, NULL, NULL, NULL,
5034                 NULL, NULL);
5035       free(errmsg);
5036       return(1);
5037    }
5038
5039    display = (Display *)strtoul(argv[1], &p, 0);
5040    if (p == argv[1]) 
5041    {
5042       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
5043       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
5044                 NULL, NULL);
5045       free(errmsg);
5046       env_blank(argv[3]);
5047       return(1);
5048    }
5049    rootWindow = (Window)strtoul(argv[2], &p, 0);
5050    if (p == argv[2]) 
5051    {
5052       errmsg = strdup(GetSharedMsg(DT_BAD_WINDOW));
5053       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
5054                 NULL, NULL);
5055       free(errmsg);
5056       env_blank(argv[3]);
5057       return(1);
5058    }
5059
5060    returnedWin = DtWsmGetCurrentBackdropWindow(display, rootWindow);
5061
5062    if (returnedWin != None)
5063    {
5064       char buf[128];
5065
5066       sprintf(buf, "%d", (int)returnedWin);
5067
5068       env_set_var(argv[3], buf);
5069       return (0);
5070    }
5071    else
5072    {
5073       env_blank(argv[3]);
5074       return (1);
5075    }
5076 }
5077
5078
5079 int
5080 do_DtWsmOccupyAllWorkspaces(
5081         int argc,
5082         char *argv[] )
5083 {
5084    return(WsmCommonProc(argc, argv, (void (*)())DtWsmOccupyAllWorkspaces));
5085 }
5086
5087
5088 int
5089 do__DtGetHourGlassCursor(
5090         int argc,
5091         char *argv[] )
5092 {
5093    char * p;
5094    Display * display;
5095    Cursor cursor;
5096    char buf[128];
5097    char * errmsg;
5098
5099    if (argc != 3) 
5100    {
5101       errmsg = strdup(GETMESSAGE(5,79, 
5102                       "Usage: _DtGetHourGlassCursor variable display"));
5103       printerr(str_nill, errmsg, NULL);
5104       free(errmsg);
5105       return(1);
5106    }
5107
5108    display = (Display *)strtoul(argv[2], &p, 0);
5109    if (p == argv[2]) 
5110    {
5111       errmsg = strdup(GetSharedMsg(DT_BAD_DISPLAY));
5112       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
5113                 NULL, NULL);
5114       free(errmsg);
5115       alt_env_set_var(argv[1], str_nill);
5116       return(1);
5117    }
5118
5119    cursor = _DtGetHourGlassCursor(display);
5120    sprintf(buf, "%d", cursor);
5121    alt_env_set_var(argv[1], buf);
5122
5123    return (0);
5124 }
5125
5126
5127 static int
5128 DtTurnOnOrOffHourGlass(
5129         void (*func)(),
5130         int argc,
5131         char *argv[] )
5132 {
5133    char * p;
5134    Cursor cursor;
5135    char buf[128];
5136    wtab_t *w;
5137    char * errmsg;
5138
5139    if (argc != 2) 
5140    {
5141       errmsg = strdup(GetSharedMsg(DT_USAGE_WIDGET));
5142       printerrf(str_nill, errmsg, argv[0], NULL, NULL, NULL, NULL,
5143                 NULL, NULL, NULL);
5144       free(errmsg);
5145       return(1);
5146    }
5147
5148    w = str_to_wtab(argv[0], argv[1]);
5149    if (w == NULL) 
5150       return(1);
5151
5152    (*func)(w->w);
5153    return (0);
5154 }
5155
5156
5157 int
5158 do__DtTurnOnHourGlass(
5159         int argc,
5160         char *argv[] )
5161 {
5162   return(DtTurnOnOrOffHourGlass(_DtTurnOnHourGlass, argc, argv));
5163 }
5164
5165
5166 int
5167 do__DtTurnOffHourGlass(
5168         int argc,
5169         char *argv[] )
5170 {
5171    return(DtTurnOnOrOffHourGlass(_DtTurnOffHourGlass, argc, argv));
5172 }
5173
5174 int
5175 do_DtWsmAddCurrentWorkspaceCallback(
5176         int argc,
5177         char **argv )
5178 {
5179    wtab_t *w;
5180    dtksh_client_data_t *cdata;
5181    char * p;
5182    Atom propAtom;
5183    DtWsmCBContext handle;
5184    char buf[128];
5185    char * errmsg;
5186
5187    if (argc != 4)
5188    {
5189       errmsg = strdup(GETMESSAGE(5,80, 
5190         "Usage: DtWsmAddCurrentWorkspaceCallback variable widget ksh-command"));
5191       printerr(str_nill, errmsg, NULL);
5192       free(errmsg);
5193       return(1);
5194    }
5195
5196    w = str_to_wtab(argv[0], argv[2]);
5197    if (w == NULL) 
5198    {
5199       alt_env_set_var(argv[1], str_nill);
5200       return(1);
5201    }
5202
5203    /* Always force a new entry */
5204    cdata = GetNewCBData(NULL, NULL, NULL, None);
5205    cdata->w = w;
5206    cdata->ksh_cmd = strdup(argv[3]);
5207
5208    handle = DtWsmAddCurrentWorkspaceCallback(w->w, 
5209                 (DtWsmWsChangeProc)stdWSCB, (XtPointer)cdata);
5210    cdata->handle = (XtPointer)handle;
5211
5212    sprintf(buf, "%ld", (long)handle);
5213    alt_env_set_var(argv[1], buf);
5214
5215    return(0);
5216 }
5217
5218 int
5219 do_DtWsmRemoveWorkspaceCallback(
5220         int argc,
5221         char **argv )
5222 {
5223    char * errmsg, *p;
5224    dtksh_client_data_t *cdata = (dtksh_client_data_t *)NULL;
5225    DtWsmCBContext handle;
5226    int i;
5227
5228    if (argc != 2)
5229    {
5230       errmsg = strdup(GETMESSAGE(5,81, 
5231        "Usage: DtWsmRemoveWorkspaceCallback handle"));
5232       printerr(str_nill, errmsg, NULL);
5233       free(errmsg);
5234       return(1);
5235    }
5236
5237    handle = (DtWsmCBContext)strtoul(argv[1], &p, 0);
5238    if (p != argv[1])
5239    {
5240        for(i = 0; i < cbDataTableSize; i++)
5241        {
5242            if(cbDataTable[i] != (dtksh_client_data_t *)NULL)
5243            {
5244                if(cbDataTable[i]->handle == handle)
5245                {
5246                    cdata = cbDataTable[i];
5247                    break;
5248                }
5249             }
5250        }
5251    }
5252
5253    if(cdata == (dtksh_client_data_t *)NULL)
5254    {
5255       errmsg = strdup(GETMESSAGE(5,20, 
5256                    "The following is an invalid callback handle: %s"));
5257       printerrf(argv[0], errmsg, argv[1], NULL, NULL, NULL, NULL, NULL,
5258                 NULL, NULL);
5259       free(errmsg);
5260       return(1);
5261    }
5262
5263    return(RemoveOneCallback (argv[0], cdata->w->widid, NULL, cdata->ksh_cmd,
5264                              NULL, argv[1]));
5265 }
5266
5267
5268 /*****************************************************************************/
5269 /*****************************************************************************/
5270
5271
5272 int
5273 do_DtDbLoad(
5274         int argc,
5275         char *argv[] )
5276 {
5277    char * errmsg;
5278
5279    if (argc != 1) 
5280    {
5281       errmsg = strdup(GETMESSAGE(5,83, "Usage: DtDbLoad"));
5282       printerr(str_nill, errmsg, NULL);
5283       free(errmsg);
5284       return(1);
5285    }
5286
5287    DtDbLoad();
5288    return (0);
5289 }
5290
5291
5292 /* Only a single handler is allowed */
5293 static char * reloadNotifyCommand = NULL;
5294
5295
5296 /*
5297  * This is our internal 'ReloadNotify' callback; it simply interprets
5298  * the ksh command specified by the shell script.
5299  */
5300 static void
5301 DtkReloadHandler( 
5302         XtPointer clientData )
5303 {
5304    ksh_eval((char *)reloadNotifyCommand);
5305 }
5306
5307
5308 /*
5309  * This command registers a ksh-command string, which will be executed
5310  * whenever a 'ReloadNotify' message is received.  Subsequent calls to
5311  * this command will simply replace the previous ksh-command witht the
5312  * new one.
5313  */
5314 int
5315 do_DtDbReloadNotify(
5316         int argc,
5317         char *argv[] )
5318 {
5319    char * errmsg;
5320    static Boolean firstTime = True;
5321
5322    if (argc != 2) 
5323    {
5324       errmsg = strdup(GETMESSAGE(5,84, "Usage: DtDbReloadNotify ksh-command"));
5325       printerr(str_nill, errmsg, NULL);
5326       free(errmsg);
5327       return(1);
5328    }
5329
5330    if (firstTime)
5331    {
5332       firstTime = False;
5333       DtDbReloadNotify((DtDbReloadCallbackProc)DtkReloadHandler, NULL);
5334    }
5335
5336    XtFree(reloadNotifyCommand);
5337    reloadNotifyCommand = strdup(argv[1]);
5338    return (0);
5339 }
5340
5341
5342 /*
5343  * This command is a boolean command, which returns 'True' if the
5344  * specified name correlates to a defined action.
5345  */
5346 int
5347 do_DtActionExists(
5348         int argc,
5349         char *argv[] )
5350 {
5351    char * errmsg;
5352
5353    if (argc != 2) 
5354    {
5355       errmsg = strdup(GETMESSAGE(5,85, "Usage: DtActionExists actionName"));
5356       printerr(str_nill, errmsg, NULL);
5357       free(errmsg);
5358       return(1);
5359    }
5360
5361    if (DtActionExists(argv[1]))
5362       return(0);
5363    return(255);
5364 }
5365
5366
5367 /*
5368  * This command returns the label associated with an action.  If the
5369  * action is not defined, or if there is no label, then an empty string
5370  * is returned.
5371  */
5372 int
5373 do_DtActionLabel(
5374         int argc,
5375         char *argv[] )
5376 {
5377    char * errmsg;
5378    char * label;
5379
5380    if (argc != 3) 
5381    {
5382       errmsg = strdup(GETMESSAGE(5,86, 
5383                       "Usage: DtActionLabel variable actionName"));
5384       printerr(str_nill, errmsg, NULL);
5385       free(errmsg);
5386       return(1);
5387    }
5388
5389    if (label = DtActionLabel(argv[2]))
5390    {
5391       alt_env_set_var(argv[1], label);
5392       XtFree(label);
5393    }
5394    else
5395       alt_env_set_var(argv[1], str_nill);
5396    return (0);
5397 }
5398
5399
5400 /*
5401  * This command returns the description associated with an action.  If the
5402  * action is not defined, or if there is no description, then an empty string
5403  * is returned.
5404  */
5405 int
5406 do_DtActionDescription(
5407         int argc,
5408         char *argv[] )
5409 {
5410    char * errmsg;
5411    char * description;
5412
5413    if (argc != 3) 
5414    {
5415       errmsg = strdup(GETMESSAGE(5,87, 
5416                       "Usage: DtActionDescription variable actionName"));
5417       printerr(str_nill, errmsg, NULL);
5418       free(errmsg);
5419       return(1);
5420    }
5421
5422    if (description = DtActionDescription(argv[2]))
5423    {
5424       alt_env_set_var(argv[1], description);
5425       XtFree(description);
5426    }
5427    else
5428       alt_env_set_var(argv[1], str_nill);
5429    return (0);
5430 }
5431
5432
5433 static void
5434 _DtActionInvokeUsage( void )
5435 {
5436    char * errmsg;
5437
5438    errmsg = strdup(GETMESSAGE(5,88, 
5439         "Usage: DtActionInvoke widget actionName termParms execHost contextDir useIndicator ksh-command [\"FILE\" fileName] ..."));
5440       printerr(str_nill, errmsg, NULL);
5441       free(errmsg);
5442 }
5443
5444
5445 /*
5446  * This command provides the shell script with the mechanism for requesting
5447  * that an action be invoked.  It accepts a variable list of arguments,
5448  * which can currently only be of type 'ARG_FILE'.
5449  */
5450 int
5451 do_DtActionInvoke(
5452         int argc,
5453         char *argv[] )
5454 {
5455    wtab_t *w;
5456    char * termParms = (char *)NULL;
5457    char * execHost = (char *)NULL;
5458    char * contextDir = (char *)NULL;
5459    Boolean useIndicator;
5460    int aac;
5461    DtActionArg *aap = (DtActionArg *)NULL;
5462    XrmValue fval, tval;
5463    int i;
5464    int idx;
5465    int * lockedFds;
5466
5467    /*
5468     * Either there must be no file args (so argc == 8), or if there are
5469     * file args, then there must be 2 components for each argument.
5470     * This check must change when/if we support arguments other than files.
5471     */
5472    if ((argc < 8) || (((argc - 8) % 2) != 0))
5473    {
5474       _DtActionInvokeUsage();
5475       return(1);
5476    }
5477
5478    w = str_to_wtab(argv[0], argv[1]);
5479    if (w == (wtab_t *)NULL) 
5480       return(1);
5481
5482    /* Get true/false value for useIndicator */
5483    fval.addr = argv[6];
5484    fval.size = strlen(argv[6]);
5485    XtConvert(Toplevel, XtRString, &fval, XtRBoolean, &tval);
5486
5487    if (tval.size != 0) 
5488       useIndicator = *((Boolean *)(tval.addr));
5489    else
5490       return(1);
5491
5492    if (argv[3] && (strlen(argv[3]) > 0))
5493       termParms = argv[3];
5494
5495    if (argv[4] && (strlen(argv[4]) > 0))
5496       execHost = argv[4];
5497
5498    if (argv[5] && (strlen(argv[5]) > 0))
5499       contextDir = argv[5];
5500
5501    /*
5502     * Parse the optional file arguments
5503     * This will have to change when/if we support arguments other than files.
5504     */
5505    if ((aac = (argc - 8) / 2) > 0)
5506    {
5507       aap = (DtActionArg *)XtMalloc(sizeof(DtActionArg) * aac);
5508       for (i = 8; i < argc; i+=2 )
5509       {
5510         if(strcmp(argv[i], "FILE") != 0)
5511         {
5512            _DtActionInvokeUsage();
5513            XtFree((char *)aap);
5514            return(1);
5515         }
5516
5517         idx = (i - 8) / 2;
5518         aap[idx].argClass = DtACTION_FILE;
5519         aap[idx].u.file.name = argv[i + 1];
5520       }
5521    }
5522
5523    /* Force fd above the range reserved by ksh for the user (0 - 9) */
5524    lockedFds = LockKshFileDescriptors();
5525    /*
5526     * Force callback to NULL until we have code in place to support it.
5527     */
5528    DtActionInvoke(w->w, argv[2], aap, aac, termParms, execHost, 
5529                   contextDir, useIndicator, NULL,
5530                   (XtPointer)NULL);
5531    UnlockKshFileDescriptors(lockedFds);
5532
5533    XtFree((char *)aap);
5534
5535    return (0);
5536 }
5537
5538
5539 /*****************************************************************************/
5540 /*****************************************************************************/
5541
5542 int
5543 do_DtDtsLoadDataTypes(
5544         int argc,
5545         char *argv[] )
5546 {
5547    char * errmsg;
5548
5549    if (argc != 1) 
5550    {
5551       errmsg = strdup(GETMESSAGE(5,89, "Usage: DtDtsLoadDataTypes"));
5552       printerr(str_nill, errmsg, NULL);
5553       free(errmsg);
5554       return(1);
5555    }
5556
5557    DtDtsLoadDataTypes();
5558    return (0);
5559 }
5560
5561
5562 int
5563 do_DtDtsFileToDataType(
5564         int argc,
5565         char *argv[] )
5566 {
5567    char * errmsg;
5568    char * datatype;
5569
5570    if (argc != 3) 
5571    {
5572       errmsg = strdup(GETMESSAGE(5,90, 
5573                       "Usage: DtDtsFileToDataType variable fileName"));
5574       printerr(str_nill, errmsg, NULL);
5575       free(errmsg);
5576       return(1);
5577    }
5578
5579    if (datatype = DtDtsFileToDataType(argv[2]))
5580    {
5581       alt_env_set_var(argv[1], datatype);
5582       DtDtsFreeDataType(datatype);
5583    }
5584    else
5585       alt_env_set_var(argv[1], str_nill);
5586    return (0);
5587 }
5588
5589
5590 int
5591 do_DtDtsFileToAttributeValue(
5592         int argc,
5593         char *argv[] )
5594 {
5595    char * errmsg;
5596    char * attribute;
5597
5598    if (argc != 4) 
5599    {
5600       errmsg = strdup(GETMESSAGE(5,91,
5601               "Usage: DtDtsFileToAttributeValue variable fileName attrName"));
5602       printerr(str_nill, errmsg, NULL);
5603       free(errmsg);
5604       return(1);
5605    }
5606
5607    if (attribute = DtDtsFileToAttributeValue(argv[2], argv[3]))
5608    {
5609       alt_env_set_var(argv[1], attribute);
5610       DtDtsFreeAttributeValue(attribute);
5611    }
5612    else
5613       alt_env_set_var(argv[1], str_nill);
5614    return (0);
5615 }
5616
5617
5618 int
5619 do_DtDtsFileToAttributeList(
5620         int argc,
5621         char *argv[] )
5622 {
5623    char * errmsg;
5624    char * attributeList;
5625    DtDtsAttribute ** attributes;
5626    int i;
5627
5628    if (argc != 3) 
5629    {
5630       errmsg = strdup(GETMESSAGE(5,92,
5631               "Usage: DtDtsFileToAttributeList variable fileName"));
5632       printerr(str_nill, errmsg, NULL);
5633       free(errmsg);
5634       return(1);
5635    }
5636
5637    if (attributes = DtDtsFileToAttributeList(argv[2]))
5638    {
5639       attributeList = XtMalloc(1);
5640       attributeList[0] = '\0';
5641       for (i = 0; attributes[i]; i++)
5642       {
5643          attributeList = XtRealloc(attributeList, 
5644                                    strlen(attributeList) + 
5645                                    strlen(attributes[i]->name) + 3);
5646          if (i != 0)
5647             strcat(attributeList, " ");
5648          strcat(attributeList, attributes[i]->name);
5649       }
5650       
5651       alt_env_set_var(argv[1], attributeList);
5652       DtDtsFreeAttributeList(attributes);
5653       XtFree(attributeList);
5654    }
5655    else
5656       alt_env_set_var(argv[1], str_nill);
5657    return (0);
5658 }
5659
5660
5661 int
5662 do_DtDtsDataTypeToAttributeValue(
5663         int argc,
5664         char *argv[] )
5665 {
5666    char * errmsg;
5667    char * attribute;
5668    char * optName;
5669
5670    if ((argc != 4) && (argc != 5))
5671    {
5672       errmsg = strdup(GETMESSAGE(5,93,
5673    "Usage: DtDtsDataTypeToAttributeValue variable dataType attrName optName"));
5674       printerr(str_nill, errmsg, NULL);
5675       free(errmsg);
5676       return(1);
5677    }
5678
5679    if ((argc == 4) || (strlen(argv[4]) == 0))
5680       optName = NULL;
5681    else
5682       optName = argv[4];
5683
5684    if (attribute = DtDtsDataTypeToAttributeValue(argv[2], argv[3], optName))
5685    {
5686       alt_env_set_var(argv[1], attribute);
5687       DtDtsFreeAttributeValue(attribute);
5688    }
5689    else
5690       alt_env_set_var(argv[1], str_nill);
5691    return (0);
5692 }
5693
5694
5695 int
5696 do_DtDtsDataTypeToAttributeList(
5697         int argc,
5698         char *argv[] )
5699 {
5700    char * errmsg;
5701    char * attributeList;
5702    DtDtsAttribute ** attributes;
5703    int i;
5704    char * optName;
5705
5706    if ((argc != 3) && (argc != 4))
5707    {
5708       errmsg = strdup(GETMESSAGE(5,94,
5709         "Usage: DtDtsDataTypeToAttributeList variable dataType optName"));
5710       printerr(str_nill, errmsg, NULL);
5711       free(errmsg);
5712       return(1);
5713    }
5714
5715    if ((argc == 3) || (strlen(argv[3]) == 0))
5716       optName = NULL;
5717    else
5718       optName = argv[3];
5719
5720    if (attributes = DtDtsDataTypeToAttributeList(argv[2], optName))
5721    {
5722       attributeList = XtMalloc(1);
5723       attributeList[0] = '\0';
5724       for (i = 0; attributes[i]; i++)
5725       {
5726          attributeList = XtRealloc(attributeList, 
5727                                    strlen(attributeList) + 
5728                                    strlen(attributes[i]->name) + 3);
5729          if (i != 0)
5730             strcat(attributeList, " ");
5731          strcat(attributeList, attributes[i]->name);
5732       }
5733       
5734       alt_env_set_var(argv[1], attributeList);
5735       DtDtsFreeAttributeList(attributes);
5736       XtFree(attributeList);
5737    }
5738    else
5739       alt_env_set_var(argv[1], str_nill);
5740    return (0);
5741 }
5742
5743
5744 int
5745 do_DtDtsFindAttribute(
5746         int argc,
5747         char *argv[] )
5748 {
5749    char * errmsg;
5750    char * dataTypeList;
5751    char ** dataTypes;
5752    int i;
5753
5754    if (argc != 4)
5755    {
5756       errmsg = strdup(GETMESSAGE(5,95,
5757                    "Usage: DtDtsFindAttribute variable name value"));
5758       printerr(str_nill, errmsg, NULL);
5759       free(errmsg);
5760       return(1);
5761    }
5762
5763    if (dataTypes = DtDtsFindAttribute(argv[2], argv[3]))
5764    {
5765       dataTypeList = XtMalloc(1);
5766       dataTypeList[0] = '\0';
5767       for (i = 0; dataTypes[i]; i++)
5768       {
5769          dataTypeList = XtRealloc(dataTypeList, 
5770                                    strlen(dataTypeList) + 
5771                                    strlen(dataTypes[i]) + 3);
5772          if (i != 0)
5773             strcat(dataTypeList, " ");
5774          strcat(dataTypeList, dataTypes[i]);
5775       }
5776       
5777       alt_env_set_var(argv[1], dataTypeList);
5778       DtDtsFreeDataTypeNames(dataTypes);
5779       XtFree(dataTypeList);
5780    }
5781    else
5782       alt_env_set_var(argv[1], str_nill);
5783    return (0);
5784 }
5785
5786
5787 int
5788 do_DtDtsDataTypeNames(
5789         int argc,
5790         char *argv[] )
5791 {
5792    char * errmsg;
5793    char * dataTypeList;
5794    char ** dataTypes;
5795    int i;
5796
5797    if (argc != 2)
5798    {
5799       errmsg = strdup(GETMESSAGE(5,96, "Usage: DtDtsDataTypeNames variable"));
5800       printerr(str_nill, errmsg, NULL);
5801       free(errmsg);
5802       return(1);
5803    }
5804
5805    if (dataTypes = DtDtsDataTypeNames())
5806    {
5807       dataTypeList = XtMalloc(1);
5808       dataTypeList[0] = '\0';
5809       for (i = 0; dataTypes[i]; i++)
5810       {
5811          dataTypeList = XtRealloc(dataTypeList, 
5812                                    strlen(dataTypeList) + 
5813                                    strlen(dataTypes[i]) + 3);
5814          if (i != 0)
5815             strcat(dataTypeList, " ");
5816          strcat(dataTypeList, dataTypes[i]);
5817       }
5818       
5819       alt_env_set_var(argv[1], dataTypeList);
5820       DtDtsFreeDataTypeNames(dataTypes);
5821       XtFree(dataTypeList);
5822    }
5823    else
5824       alt_env_set_var(argv[1], str_nill);
5825    return (0);
5826 }
5827
5828
5829 int
5830 do_DtDtsSetDataType(
5831         int argc,
5832         char *argv[] )
5833 {
5834    char * errmsg;
5835    char * savedDataType;
5836    Boolean override;
5837
5838    if (argc != 5)
5839    {
5840       errmsg = strdup(GETMESSAGE(5,97, 
5841        "Usage: DtDtsSetDataType variable fileName dataType override"));
5842       printerr(str_nill, errmsg, NULL);
5843       free(errmsg);
5844       return(1);
5845    }
5846
5847    /* Since XtInitialize may not have been called, can't use XtConvert */
5848    if (DtCompareISOLatin1(argv[4], "true"))
5849       override = True;
5850    else if (DtCompareISOLatin1(argv[4], "false"))
5851       override = False;
5852    else
5853       return(1);
5854
5855    if (savedDataType = DtDtsSetDataType(argv[2], argv[3], override))
5856    {
5857       alt_env_set_var(argv[1], savedDataType);
5858       DtDtsFreeDataType(savedDataType);
5859    }
5860    else
5861       alt_env_set_var(argv[1], str_nill);
5862    return (0);
5863 }
5864
5865
5866 int
5867 do_DtDtsDataTypeIsAction(
5868         int argc,
5869         char *argv[] )
5870 {
5871    char * errmsg;
5872
5873    if (argc != 2) 
5874    {
5875       errmsg = strdup(GETMESSAGE(5,98, 
5876                       "Usage: DtDtsDataTypeIsAction dataType"));
5877       printerr(str_nill, errmsg, NULL);
5878       free(errmsg);
5879       return(1);
5880    }
5881
5882    if (DtDtsDataTypeIsAction(argv[1]))
5883       return(0);
5884    return(255);
5885 }
5886
5887
5888 /*****************************************************************************/
5889 /*****************************************************************************/
5890
5891 /*
5892  * This command will attempt to open a ToolTalk communications channel.
5893  */
5894 int
5895 do_ttdt_open(
5896         int argc,
5897         char *argv[] )
5898 {
5899    char * errmsg;
5900    char * procId;
5901    Boolean sendStarted;
5902    XrmValue toVal;
5903    Cardinal nargs;
5904    char * statusString;
5905    char buf[25];
5906    int ttfd;
5907    int * lockedFds;
5908    Tt_status ttStatus;
5909
5910    if (argc != 8) 
5911    {
5912       errmsg = strdup(GETMESSAGE(5,99, 
5913          "Usage: ttdt_open variable status variable2 toolname vendor version sendStarted"));
5914       printerr(str_nill, errmsg, NULL);
5915       free(errmsg);
5916       return(1);
5917    }
5918
5919    /*  Convert "true" or "false" to 1 or 0 */
5920    DtkshCvtStringToBool(argv[7], &toVal);
5921
5922    if (toVal.size != 0) 
5923       sendStarted = *((Boolean *)(toVal.addr));
5924    else
5925       return(1);
5926
5927    /* Force fd above the range reserved by ksh for the user (0 - 9) */
5928    lockedFds = LockKshFileDescriptors();
5929    procId = ttdt_open(&ttfd, argv[4], argv[5], argv[6], (int)sendStarted);
5930    UnlockKshFileDescriptors(lockedFds);
5931
5932    /* Get the ttStatus and the asssociated string */
5933    ttStatus = tt_ptr_error(procId);
5934    DtkshCvtTtStatusToString(ttStatus, &toVal);
5935
5936    if (toVal.size && toVal.addr)
5937       statusString = toVal.addr;
5938    else
5939       statusString = str_nill;
5940    env_set_var(argv[2], statusString);
5941
5942    if (ttStatus == TT_OK)
5943       env_set_var(argv[1], procId);
5944    else
5945    {
5946       env_set_var(argv[1], str_nill);
5947       ttfd = -1;
5948    }
5949
5950    sprintf(buf, "%d", ttfd);
5951    env_set_var(argv[3], buf);
5952
5953    tt_free(procId);
5954    return (0);
5955 }
5956
5957
5958 /* 
5959  * This command is used to close a ToolTalk connection.
5960  */
5961 int
5962 do_ttdt_close(
5963         int argc,
5964         char *argv[] )
5965 {
5966    char * errmsg;
5967    Boolean sendStopped;
5968    XrmValue fval, tval;
5969    Tt_status ttStatus;
5970    char * statusString;
5971    char * procId;
5972    char * newProcId;
5973
5974    if (argc != 5) 
5975    {
5976       errmsg = strdup(GETMESSAGE(5,103, 
5977          "Usage: ttdt_close status procId newProcId sendStopped"));
5978       printerr(str_nill, errmsg, NULL);
5979       free(errmsg);
5980       return(1);
5981    }
5982
5983    /* Need to treat "" equal to a NULL pointer here */
5984    if (strlen(argv[2]) == 0)
5985       procId = NULL;
5986    else
5987       procId = argv[2];
5988
5989    /* Need to treat "" equal to a NULL pointer here */
5990    if (strlen(argv[3]) == 0)
5991       newProcId = NULL;
5992    else
5993       newProcId = argv[3];
5994
5995    DtkshCvtStringToBool(argv[4], &tval);
5996
5997    if (tval.size != 0) 
5998       sendStopped = *((Boolean *)(tval.addr));
5999    else
6000       return(1);
6001
6002    ttStatus = ttdt_close(procId, newProcId, (int)sendStopped);
6003
6004    /* Map the ttStatus into a string */
6005    DtkshCvtTtStatusToString(ttStatus, &tval);
6006
6007    if (tval.size && tval.addr)
6008       statusString = tval.addr;
6009    else
6010       statusString = str_nill;
6011    env_set_var(argv[1], statusString);
6012
6013    return (0);
6014 }
6015
6016
6017 /*
6018  * This is the alternate input handler command for ToolTalk.  Shell scripts
6019  * will invoke it from their alternate input handlers, passing in all of
6020  * the required parameters.  This input handler will cause ToolTalk events
6021  * to be received and dispatched.
6022  */
6023 int
6024 do_tttk_Xt_input_handler(
6025         int argc,
6026         char *argv[] )
6027 {
6028    char * errmsg;
6029    int source;
6030    XtInputId fid;
6031    char * p;
6032
6033    if (argc != 4) 
6034    {
6035       errmsg = strdup(GETMESSAGE(5,100, 
6036          "Usage: tttk_Xt_input_handler procId source id"));
6037       printerr(str_nill, errmsg, NULL);
6038       free(errmsg);
6039       return(1);
6040    }
6041
6042    source = strtoul(argv[2], &p, 0);
6043    if (p == argv[2]) 
6044    {
6045       errmsg=strdup(GETMESSAGE(5,101, 
6046                    "The source parameter must be an integer: %s"));
6047       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
6048                 NULL, NULL);
6049       free(errmsg);
6050       return(1);
6051    }
6052
6053    fid = strtoul(argv[3], &p, 0);
6054    if (p == argv[3]) 
6055    {
6056       errmsg = strdup(GETMESSAGE(5,102, 
6057              "The id parameter must be a hex number: %s")); 
6058       printerrf(argv[0], errmsg, argv[3], NULL, NULL, NULL, NULL, NULL, 
6059                 NULL, NULL);
6060       free(errmsg);
6061       return(1);
6062    }
6063
6064    tttk_Xt_input_handler(argv[1], &source, &fid);
6065    return (0);
6066 }
6067
6068
6069 int
6070 do_ttdt_session_join(
6071         int argc,
6072         char *argv[] )
6073 {
6074    char * errmsg;
6075    Boolean join;
6076    char * sessId;
6077    XrmValue fval, tval;
6078    Tt_status ttStatus;
6079    char * statusString;
6080    char buf[25];
6081    Widget widget;
6082    wtab_t *w;
6083    Tt_pattern * patterns;
6084
6085    if (argc != 6) 
6086    {
6087       errmsg = strdup(GETMESSAGE(5,104, 
6088        "Usage: ttdt_session_join variable status sessId shellWidgetHandle join"
6089         ));
6090       printerr(str_nill, errmsg, NULL);
6091       free(errmsg);
6092       return(1);
6093    }
6094
6095    DtkshCvtStringToBool(argv[5], &tval);
6096
6097    if (tval.size != 0) 
6098       join = *((Boolean *)(tval.addr));
6099    else
6100       return(1);
6101
6102    /* Need to treat "" equal to a NULL pointer here */
6103    if (strlen(argv[3]) == 0)
6104       sessId = NULL;
6105    else
6106       sessId = argv[3];
6107
6108    /* Need to treat "" equal to a NULL pointer here */
6109    if (strlen(argv[4]) == 0)
6110       widget = NULL;
6111    else
6112    {
6113       w = str_to_wtab(argv[0], argv[4]);
6114       if (w == NULL) 
6115          return(1);
6116       widget = w->w;
6117    }
6118
6119    patterns = ttdt_session_join(sessId, NULL, widget, NULL, (int)join);
6120
6121    ttStatus = tt_ptr_error(patterns);
6122
6123    /* Map the ttStatus into a string */
6124    DtkshCvtTtStatusToString(ttStatus, &tval);
6125
6126    if (tval.size && tval.addr)
6127       statusString = tval.addr;
6128    else
6129       statusString = str_nill;
6130    env_set_var(argv[2], statusString);
6131
6132    if (ttStatus == TT_OK)
6133    {
6134       sprintf(buf, "%ld", (long)patterns);
6135       env_set_var(argv[1], buf);
6136    }
6137    else
6138       env_set_var(argv[1], str_nill);
6139
6140    return (0);
6141 }
6142
6143
6144 int
6145 do_ttdt_session_quit(
6146         int argc,
6147         char *argv[] )
6148 {
6149    char * errmsg;
6150    Boolean quit;
6151    char * sessId;
6152    XrmValue fval, tval;
6153    Tt_status ttStatus;
6154    char * statusString;
6155    Tt_pattern * patterns;
6156    char * p;
6157
6158    if (argc != 5) 
6159    {
6160       errmsg = strdup(GETMESSAGE(5,105, 
6161           "Usage: ttdt_session_quit status sessId sessPatterns quit"));
6162       printerr(str_nill, errmsg, NULL);
6163       free(errmsg);
6164       return(1);
6165    }
6166
6167    DtkshCvtStringToBool(argv[4], &tval);
6168
6169    if (tval.size != 0) 
6170       quit = *((Boolean *)(tval.addr));
6171    else
6172       return(1);
6173
6174    /* Need to treat "" equal to a NULL pointer here */
6175    if (strlen(argv[2]) == 0)
6176       sessId = NULL;
6177    else
6178       sessId = argv[2];
6179
6180    /* Need to treat "" equal to a NULL pointer here */
6181    if (strlen(argv[3]) == 0)
6182       patterns = NULL;
6183    else
6184    {
6185       patterns = (Tt_pattern *)strtoul(argv[3], &p, 0);
6186       if (p == argv[3]) 
6187       {
6188          errmsg=strdup(GETMESSAGE(5,106, 
6189                    "The sessPatterns parameter is invalid: %s"));
6190          printerrf(argv[0], errmsg, argv[3], NULL, NULL, NULL, NULL, NULL,
6191                 NULL, NULL);
6192          free(errmsg);
6193          return(1);
6194       }
6195    }
6196
6197    ttStatus = ttdt_session_quit(sessId, patterns, (int)quit);
6198
6199    /* Map the ttStatus into a string */
6200    DtkshCvtTtStatusToString(ttStatus, &tval);
6201
6202    if (tval.size && tval.addr)
6203       statusString = tval.addr;
6204    else
6205       statusString = str_nill;
6206    env_set_var(argv[1], statusString);
6207
6208    return (0);
6209 }
6210
6211
6212 int
6213 do_ttdt_file_event(
6214         int argc,
6215         char *argv[] )
6216 {
6217    char * errmsg;
6218    XrmValue fval, tval;
6219    Tt_status ttStatus;
6220    char * statusString;
6221    Boolean send;
6222    Tt_pattern * patterns;
6223    Tttk_op op;
6224    char * p;
6225
6226    if (argc != 5) 
6227    {
6228       errmsg = strdup(GETMESSAGE(5,107, 
6229           "Usage: ttdt_file_event status op patterns send"));
6230       printerr(str_nill, errmsg, NULL);
6231       free(errmsg);
6232       return(1);
6233    }
6234
6235    fval.addr = argv[2];
6236    fval.size = strlen(argv[2]);
6237    XtConvert(Toplevel, XtRString, &fval, "TtOp", &tval); /* XXX */
6238
6239    if (tval.size != 0) 
6240       op = *((Tttk_op *)(tval.addr));
6241    else
6242       return(1);
6243
6244    /* Need to treat "" equal to a NULL pointer here */
6245    if (strlen(argv[3]) == 0)
6246       patterns = NULL;
6247    else
6248    {
6249       patterns = (Tt_pattern *)strtoul(argv[3], &p, 0);
6250       if (p == argv[3]) 
6251       {
6252          errmsg = strdup(GetSharedMsg(DT_BAD_PATTERN));
6253          printerrf(argv[0], errmsg, argv[3], NULL, NULL, NULL, NULL, NULL,
6254                 NULL, NULL);
6255          free(errmsg);
6256          return(1);
6257       }
6258    }
6259
6260    DtkshCvtStringToBool(argv[4], &tval);
6261
6262    if (tval.size != 0) 
6263       send = *((Boolean *)(tval.addr));
6264    else
6265       return(1);
6266
6267
6268    ttStatus = ttdt_file_event(NULL, op, patterns, (int)send);
6269
6270    /* Map the ttStatus into a string */
6271    DtkshCvtTtStatusToString(ttStatus, &tval);
6272
6273    if (tval.size && tval.addr)
6274       statusString = tval.addr;
6275    else
6276       statusString = str_nill;
6277    env_set_var(argv[1], statusString);
6278
6279    return (0);
6280 }
6281
6282
6283 /*
6284  * This is the internal callback invoked by tooltalk, whenever a message
6285  * is received for a file the user joined (using ttdt_file_join).  We
6286  * need to set up some environment variables, and then interpret the
6287  * ksh-cmd supplied by the shell script.
6288  */
6289
6290 static Tt_message
6291 TtFileCB(
6292         Tt_message msg,
6293         Tttk_op op,
6294         char * pathName,
6295         void * clientData,
6296         int sameEuidEgid,
6297         int sameProcId )
6298 {
6299    Ttdt_file_cb_data *cdata = (Ttdt_file_cb_data *)clientData;
6300    int results;
6301    char strBuf[25];
6302    Namval_t * msgVar;
6303    Namval_t * opVar;
6304    Namval_t * pathVar;
6305    Namval_t * sameProcVar;
6306    Namval_t * sameEuidVar;
6307    XrmValue fval, tval;
6308    int ttmark = tt_mark();;
6309
6310    /* Initialize the environment variables */
6311    msgVar = nv_search("DT_TT_MSG", sh.var_tree, NV_ADD);
6312    sprintf(strBuf, "%ld", (long)msg);
6313    nv_putval(msgVar, strBuf, NV_RDONLY);
6314
6315    opVar = nv_search("DT_TT_OP", sh.var_tree, NV_ADD);
6316    fval.addr = (caddr_t)&op;
6317    fval.size = sizeof(op);
6318    XtConvert(Toplevel, "TtOp", &fval, XtRString, &tval); /* XXX?? */
6319    if (tval.size && tval.addr)
6320       nv_putval(opVar, (char *)tval.addr, NV_RDONLY);
6321    else
6322       nv_putval(opVar, str_nill, NV_RDONLY);
6323
6324    pathVar = nv_search("DT_TT_PATHNAME", sh.var_tree, NV_ADD);
6325    nv_putval(pathVar, pathName, NV_RDONLY);
6326
6327    sameProcVar = nv_search("DT_TT_SAME_PROCID", sh.var_tree, NV_ADD);
6328    if (sameProcId)
6329       nv_putval(sameProcVar, "True", NV_RDONLY);
6330    else
6331       nv_putval(sameProcVar, "False", NV_RDONLY);
6332    sameEuidVar = nv_search("DT_TT_SAME_EUID_EGID", sh.var_tree, NV_ADD);
6333    if (sameProcId)
6334       nv_putval(sameEuidVar, "True", NV_RDONLY);
6335    else
6336       nv_putval(sameEuidVar, "False", NV_RDONLY);
6337
6338    /* Interpret the registered command */
6339    results = ksh_eval((char *)cdata->ksh_cmd);
6340
6341    /* Clean up the environment variables */
6342    nv_newattr(msgVar, 0, 0);
6343    nv_close(msgVar);
6344    nv_newattr(opVar, 0, 0);
6345    nv_close(opVar);
6346    nv_newattr(pathVar, 0, 0);
6347    nv_close(pathVar);
6348    nv_newattr(sameProcVar, 0, 0);
6349    nv_close(sameProcVar);
6350    nv_newattr(sameEuidVar, 0, 0);
6351    nv_close(sameEuidVar);
6352
6353    tt_release(ttmark);
6354    return((Tt_message)results);
6355 }
6356
6357
6358 int
6359 do_ttdt_file_join(
6360         int argc,
6361         char *argv[] )
6362 {
6363    char * errmsg;
6364    XrmValue fval, tval;
6365    Tt_status ttStatus;
6366    char * statusString;
6367    Boolean join;
6368    Tt_scope scope;
6369    Tt_pattern * patterns;
6370    Ttdt_file_cb_data * cData;
6371    char buf[30];
6372    int i, j;
6373
6374    if (argc != 7) 
6375    {
6376       errmsg = strdup(GETMESSAGE(5,115,
6377       "Usage: ttdt_file_join variable status pathName scope join ksh-command"));
6378       printerr(str_nill, errmsg, NULL);
6379       free(errmsg);
6380       return(1);
6381    }
6382
6383    DtkshCvtStringToBool(argv[5], &tval);
6384
6385    if (tval.size != 0) 
6386       join = *((Boolean *)(tval.addr));
6387    else
6388       return(1);
6389
6390    fval.addr = argv[4];
6391    fval.size = strlen(argv[4]);
6392    XtConvert(Toplevel, XtRString, &fval, "TtScope", &tval); /* XXX ??? */
6393
6394    if (tval.size != 0) 
6395       scope = *((Tt_scope *)(tval.addr));
6396    else
6397       return(1);
6398
6399    cData = (Ttdt_file_cb_data *)XtMalloc(sizeof(Ttdt_file_cb_data));
6400
6401    patterns = ttdt_file_join(argv[3], scope, (int)join, TtFileCB, cData);
6402    ttStatus = tt_ptr_error(patterns);
6403
6404    /* Map the ttStatus into a string */
6405    DtkshCvtTtStatusToString(ttStatus, &tval);
6406
6407    if (tval.size && tval.addr)
6408       statusString = tval.addr;
6409    else
6410       statusString = str_nill;
6411    env_set_var(argv[2], statusString);
6412
6413    /* 
6414     * If the request failed, then no callback was added, so we can free
6415     * up the client data; otherwise, we need to finish filling in the
6416     * client data, and then saving it in our storage array, so that we
6417     * can later free it when ttdt_file_quit() is called.
6418     */
6419    if (ttStatus == TT_OK)
6420    {
6421       sprintf(buf, "%ld", (long)patterns);
6422       env_set_var(argv[1], buf);
6423       cData->ksh_cmd = strdup(argv[6]);
6424       cData->patterns = patterns;
6425
6426       /* Add clientData to our storage array */
6427       for (i = 0; i < sizeFileCBList; i++)
6428       {
6429          if (fileCBList[i] == NULL)
6430             break;
6431       }
6432       if (i >= sizeFileCBList)
6433       {
6434         /* Grow the array */
6435         sizeFileCBList += 10;
6436         fileCBList = (Ttdt_file_cb_data **)XtRealloc((char *)fileCBList,
6437                                 sizeof(Ttdt_file_cb_data *) * sizeFileCBList);
6438         for (j = i; j < sizeFileCBList; j++)
6439            fileCBList[j] = NULL;
6440       }
6441       fileCBList[i] = cData;
6442    }
6443    else
6444    {
6445       XtFree((char *)cData);
6446       env_set_var(argv[1], str_nill);
6447    }
6448
6449    return (0);
6450 }
6451
6452
6453 int
6454 do_ttdt_file_quit(
6455         int argc,
6456         char *argv[] )
6457 {
6458    char * errmsg;
6459    XrmValue fval, tval;
6460    Tt_status ttStatus;
6461    char * statusString;
6462    Boolean quit;
6463    Tt_pattern * patterns;
6464    char * p;
6465    int i;
6466
6467    if (argc != 4) 
6468    {
6469       errmsg = strdup(GETMESSAGE(5,108, 
6470           "Usage: ttdt_file_quit status patterns quit"));
6471       printerr(str_nill, errmsg, NULL);
6472       free(errmsg);
6473       return(1);
6474    }
6475
6476    /* Need to treat "" equal to a NULL pointer here */
6477    if (strlen(argv[2]) == 0)
6478       patterns = NULL;
6479    else
6480    {
6481       patterns = (Tt_pattern *)strtoul(argv[2], &p, 0);
6482       if (p == argv[2]) 
6483       {
6484          errmsg = strdup(GetSharedMsg(DT_BAD_PATTERN));
6485          printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
6486                 NULL, NULL);
6487          free(errmsg);
6488          return(1);
6489       }
6490    }
6491
6492    DtkshCvtStringToBool(argv[3], &tval);
6493
6494    if (tval.size != 0) 
6495       quit = *((Boolean *)(tval.addr));
6496    else
6497       return(1);
6498
6499    ttStatus = ttdt_file_quit(patterns, (int)quit);
6500
6501    /* Remove this entry from our list of file callbacks */
6502    for (i = 0; i < sizeFileCBList; i++)
6503    {
6504       if (fileCBList[i] && (fileCBList[i]->patterns == patterns))
6505       {
6506          XtFree(fileCBList[i]->ksh_cmd);
6507          XtFree((char *)fileCBList[i]);
6508          fileCBList[i] = NULL;
6509          break;
6510       }
6511    }
6512
6513    /* Map the ttStatus into a string */
6514    DtkshCvtTtStatusToString(ttStatus, &tval);
6515
6516    if (tval.size && tval.addr)
6517       statusString = tval.addr;
6518    else
6519       statusString = str_nill;
6520    env_set_var(argv[1], statusString);
6521
6522    return (0);
6523 }
6524
6525
6526 int
6527 do_ttdt_Get_Modified(
6528         int argc,
6529         char *argv[] )
6530 {
6531    char * errmsg;
6532    XrmValue fval, tval;
6533    Tt_scope scope;
6534    int timeout;
6535    char * p;
6536
6537    if (argc != 4) 
6538    {
6539       errmsg = strdup(GETMESSAGE(5,109, 
6540           "Usage: ttdt_Get_Modified pathName scope timeout"));
6541       printerr(str_nill, errmsg, NULL);
6542       free(errmsg);
6543       return(1);
6544    }
6545
6546    fval.addr = argv[2];
6547    fval.size = strlen(argv[2]);
6548    XtConvert(Toplevel, XtRString, &fval, "TtScope", &tval); /* XXX ?? */
6549
6550    if (tval.size != 0) 
6551       scope = *((Tt_scope *)(tval.addr));
6552    else
6553       return(1);
6554
6555    timeout = strtoul(argv[3], &p, 0);
6556    if (p == argv[3]) 
6557    {
6558       errmsg = strdup(GetSharedMsg(DT_BAD_TIMEOUT));
6559       printerrf(argv[0], errmsg, argv[3], NULL, NULL, NULL, NULL, NULL,
6560              NULL, NULL);
6561       free(errmsg);
6562       return(1);
6563    }
6564
6565    if (ttdt_Get_Modified(NULL, argv[1], scope, 
6566        XtWidgetToApplicationContext(Toplevel), timeout))
6567    {
6568       return(0);
6569    }
6570    return(255);
6571 }
6572
6573
6574 /*
6575  * Common function for ttdt_Save and ttdt_Revert commands.
6576  */
6577 static int
6578 ttdt_SaveOrRevert(
6579         Tt_status (*func)(),
6580         int argc,
6581         char *argv[] )
6582 {
6583    char * errmsg;
6584    XrmValue fval, tval;
6585    Tt_scope scope;
6586    int timeout;
6587    char * p;
6588    Tt_status ttStatus;
6589    char * statusString;
6590
6591    if (argc != 5) 
6592    {
6593       errmsg = strdup(GETMESSAGE(5,110, 
6594                       "Usage: %s status pathName scope timeout"));
6595       printerrf(str_nill, errmsg, argv[0], NULL, NULL, NULL, NULL, NULL,
6596              NULL, NULL);
6597       free(errmsg);
6598       return(1);
6599    }
6600
6601    fval.addr = argv[3];
6602    fval.size = strlen(argv[3]);
6603    XtConvert(Toplevel, XtRString, &fval, "TtScope", &tval); /* XXX ?? */
6604
6605    if (tval.size != 0) 
6606       scope = *((Tt_scope *)(tval.addr));
6607    else
6608       return(1);
6609
6610    timeout = strtoul(argv[4], &p, 0);
6611    if (p == argv[4]) 
6612    {
6613       errmsg = strdup(GetSharedMsg(DT_BAD_TIMEOUT));
6614       printerrf(argv[0], errmsg, argv[4], NULL, NULL, NULL, NULL, NULL,
6615              NULL, NULL);
6616       free(errmsg);
6617       return(1);
6618    }
6619
6620    ttStatus = (*func)(NULL, argv[2], scope, 
6621                       XtWidgetToApplicationContext(Toplevel), timeout);
6622
6623    /* Map the ttStatus into a string */
6624    DtkshCvtTtStatusToString(ttStatus, &tval);
6625
6626    if (tval.size && tval.addr)
6627       statusString = tval.addr;
6628    else
6629       statusString = str_nill;
6630    env_set_var(argv[1], statusString);
6631
6632    return(0);
6633 }
6634
6635
6636 int
6637 do_ttdt_Save(
6638         int argc,
6639         char *argv[] )
6640 {
6641    return(ttdt_SaveOrRevert(ttdt_Save, argc, argv ));
6642 }
6643
6644
6645 int
6646 do_ttdt_Revert(
6647         int argc,
6648         char *argv[] )
6649 {
6650    return(ttdt_SaveOrRevert(ttdt_Revert, argc, argv ));
6651 }
6652
6653
6654 int
6655 do_tt_error_pointer(
6656         int argc,
6657         char *argv[] )
6658 {
6659    char * errmsg;
6660    XrmValue fval, tval;
6661    Tt_status ttStatus;
6662    void * errPtr;
6663    char buf[25];
6664
6665    if (argc != 3) 
6666    {
6667       errmsg = strdup(GETMESSAGE(5,112,
6668           "Usage: tt_error_pointer variable ttStatus"));
6669       printerr(str_nill, errmsg, NULL);
6670       free(errmsg);
6671       return(1);
6672    }
6673
6674    /* Map the string into a ttStatus */
6675    DtkshCvtStringToTtStatus(argv[2], &tval);
6676
6677    if (tval.size != 0) 
6678       ttStatus = *((Tt_status *)(tval.addr));
6679    else
6680       return(1);
6681
6682    errPtr = tt_error_pointer(ttStatus);
6683    sprintf(buf, "%ld", (long)errPtr);
6684    alt_env_set_var(argv[1], buf);
6685
6686    return (0);
6687 }
6688
6689
6690 static int
6691 message_DestroyOrReply( 
6692         Tt_status (*func)(),
6693         int argc,
6694         char *argv[] )
6695 {
6696    char * errmsg;
6697    XrmValue fval, tval;
6698    Tt_status ttStatus;
6699    char * statusString;
6700    Tt_message message;
6701    char * p;
6702
6703    if (argc != 3) 
6704    {
6705       errmsg = strdup(GETMESSAGE(5,113, "Usage: %s status msg"));
6706       printerrf(str_nill, errmsg, argv[0], NULL, NULL, NULL, NULL, NULL,
6707              NULL, NULL);
6708       free(errmsg);
6709       return(1);
6710    }
6711
6712    message = (Tt_message)strtoul(argv[2], &p, 0);
6713    if (p == argv[2]) 
6714    {
6715       errmsg = strdup(GetSharedMsg(DT_BAD_MESSAGE));
6716       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
6717              NULL, NULL);
6718       free(errmsg);
6719       return(1);
6720    }
6721
6722    ttStatus = (*func)(message);
6723
6724    /* Map the ttStatus into a string */
6725    DtkshCvtTtStatusToString(ttStatus, &tval);
6726
6727    if (tval.size && tval.addr)
6728       statusString = tval.addr;
6729    else
6730       statusString = str_nill;
6731    env_set_var(argv[1], statusString);
6732
6733    return (0);
6734 }
6735
6736
6737 int
6738 do_tttk_message_destroy(
6739         int argc,
6740         char *argv[] )
6741 {
6742    return(message_DestroyOrReply(tttk_message_destroy, argc, argv));
6743 }
6744
6745
6746 int
6747 do_tt_message_reply(
6748         int argc,
6749         char *argv[] )
6750 {
6751    return(message_DestroyOrReply(tt_message_reply, argc, argv));
6752 }
6753
6754
6755 static int
6756 message_FailOrReject( 
6757         Tt_status (*func)(),
6758         int argc,
6759         char *argv[] )
6760 {
6761    char * errmsg;
6762    XrmValue fval, tval;
6763    Tt_status ttStatus;
6764    char * statusString;
6765    Tt_message message;
6766    char * msgStatusString;
6767    Boolean destroy;
6768    char * p;
6769
6770    if (argc != 6) 
6771    {
6772       errmsg = strdup(GETMESSAGE(5,114,
6773                  "Usage: %s status msg msgStatus msgStatusString destroy"));
6774       printerrf(str_nill, errmsg, argv[0], NULL, NULL, NULL, NULL, NULL,
6775              NULL, NULL);
6776       free(errmsg);
6777       return(1);
6778    }
6779
6780    message = (Tt_message)strtoul(argv[2], &p, 0);
6781    if (p == argv[2]) 
6782    {
6783       errmsg = strdup(GetSharedMsg(DT_BAD_MESSAGE));
6784       printerrf(argv[0], errmsg, argv[2], NULL, NULL, NULL, NULL, NULL,
6785              NULL, NULL);
6786       free(errmsg);
6787       return(1);
6788    }
6789
6790    /* Map the string into a ttStatus */
6791    DtkshCvtStringToTtStatus(argv[3], &tval);
6792
6793    if (tval.size != 0) 
6794       ttStatus = *((Tt_status *)(tval.addr));
6795    else
6796       return(1);
6797
6798    /* Need to treat "" equal to a NULL pointer here */
6799    if (strlen(argv[4]) == 0)
6800       msgStatusString = NULL;
6801    else
6802       msgStatusString = argv[4];
6803
6804    /* Convert the boolean value */
6805    DtkshCvtStringToBool(argv[5], &tval);
6806
6807    if (tval.size != 0) 
6808       destroy = *((Boolean *)(tval.addr));
6809    else
6810       return(1);
6811
6812    ttStatus = (*func)(message, ttStatus, msgStatusString, destroy);
6813
6814    /* Map the ttStatus into a string */
6815    DtkshCvtTtStatusToString(ttStatus, &tval);
6816
6817    if (tval.size && tval.addr)
6818       statusString = tval.addr;
6819    else
6820       statusString = str_nill;
6821    env_set_var(argv[1], statusString);
6822
6823    return (0);
6824 }
6825
6826
6827 int
6828 do_tttk_message_reject(
6829         int argc,
6830         char *argv[] )
6831 {
6832    return(message_FailOrReject(tttk_message_reject, argc, argv));
6833 }
6834
6835
6836 int
6837 do_tttk_message_fail(
6838         int argc,
6839         char *argv[] )
6840 {
6841    return(message_FailOrReject(tttk_message_fail, argc, argv));
6842 }
6843
6844
6845 static int
6846 tt_netfile_handler( 
6847         int paramCount,
6848         char * (*func)(),
6849         char * usageMsg,
6850         int argc,
6851         char *argv[] )
6852 {
6853    XrmValue fval, tval;
6854    Tt_status ttStatus;
6855    char * statusString;
6856    char * convertedName;
6857    Cardinal cargc;
6858    XrmValue cargv[1];
6859
6860    if (argc != paramCount) 
6861    {
6862       printerr(str_nill, usageMsg, NULL);
6863       return(1);
6864    }
6865
6866    if (paramCount == 4)
6867       convertedName = (char *)(*func)(argv[3]);
6868    else
6869       convertedName = (char *)(*func)(argv[3], argv[4]);
6870
6871    /* 
6872     * Map the ttStatus into a string.  Note that we can't call the XtConvert
6873     * function, since a shell script may not have called XtInitialize.
6874     */
6875    ttStatus = tt_ptr_error(convertedName);
6876    DtkshCvtTtStatusToString(ttStatus, &tval);
6877
6878    if (ttStatus == TT_OK)
6879       env_set_var(argv[1], convertedName);
6880    else
6881       env_set_var(argv[1], str_nill);
6882
6883    if (tval.size && tval.addr)
6884       statusString = tval.addr;
6885    else
6886       statusString = str_nill;
6887    env_set_var(argv[2], statusString);
6888
6889    tt_free(convertedName);
6890    return (0);
6891 }
6892
6893
6894 int
6895 do_tt_file_netfile(
6896         int argc,
6897         char *argv[] )
6898 {
6899    char * usageMsg;
6900    int results;
6901
6902    usageMsg = strdup(GETMESSAGE(5,116,
6903              "Usage: tt_file_netfile variable status filename"));
6904    results = tt_netfile_handler(4, tt_file_netfile, usageMsg, argc, argv);
6905    XtFree(usageMsg);
6906    return(results);
6907 }
6908
6909
6910 int
6911 do_tt_netfile_file(
6912         int argc,
6913         char *argv[] )
6914 {
6915    char * usageMsg;
6916    int results;
6917
6918    usageMsg = strdup(GETMESSAGE(5,117,
6919              "Usage: tt_netfile_file variable status netfilename"));
6920    results = tt_netfile_handler(4, tt_netfile_file, usageMsg, argc, argv);
6921    XtFree(usageMsg);
6922    return(results);
6923 }
6924
6925
6926 int
6927 do_tt_host_file_netfile(
6928         int argc,
6929         char *argv[] )
6930 {
6931    char * usageMsg;
6932    int results;
6933
6934    usageMsg = strdup(GETMESSAGE(5,118,
6935              "Usage: tt_host_file_netfile variable status host filename"));
6936    results = tt_netfile_handler(5, tt_host_file_netfile, usageMsg, argc, argv);
6937    XtFree(usageMsg);
6938    return(results);
6939 }
6940
6941
6942 int
6943 do_tt_host_netfile_file(
6944         int argc,
6945         char *argv[] )
6946 {
6947    char * usageMsg;
6948    int results;
6949
6950    usageMsg = strdup(GETMESSAGE(5,119,
6951              "Usage: tt_host_netfile_file variable status host netfilename"));
6952    results = tt_netfile_handler(5, tt_host_netfile_file, usageMsg, argc, argv);
6953    XtFree(usageMsg);
6954    return(results);
6955 }
6956
6957
6958
6959 /*****************************************************************************/
6960 /*****************************************************************************/
6961
6962
6963 /*
6964  * Starting with the class of the widget, check to see if it defines the
6965  * indicated callback; if not, then keep checking its superclasses.
6966  */
6967 static Namdisc_t *
6968 CheckClassDisciplines(
6969         WidgetClass class,
6970         char *cbname )
6971 {
6972    int i = 0;
6973    int j = 0;
6974
6975    while (C[i].cname)
6976    {
6977       if (C[i].class == class)
6978       {
6979          if (C[i].disciplines)
6980          {
6981             while(C[i].disciplines[j].callbackName)
6982             {
6983                if (strcmp(cbname, C[i].disciplines[j].callbackName) == 0)
6984                   return(C[i].disciplines[j].discipline);
6985
6986                j++;
6987             }
6988          }
6989       }
6990       i++;
6991    }
6992    return(NULL);
6993 }
6994
6995 /*****************************************************************************/
6996 /*****************************************************************************/
6997
6998 /*
6999  * The following collection of functions deal with handling the dynamic
7000  * setting of an environment variable, when referenced by the shell script.
7001  * All of the environment variables are based off of the CB_CALL_DATA
7002  * environment variable, which is set before the shell script's callback
7003  * is invoked.  After the shell script's callback returns, any dynamically
7004  * created environment variable are removed; thus, the scope is only
7005  * within the context of the callback.
7006  *
7007  * If the shell script attempts to reference a subfield of the CB_CALL_DATA,
7008  * and if the parent has not yet been reference, then the 'name' passed to
7009  * the discipline function will contain all of the previously unreferenced
7010  * portions of the environment variable name.  As an example, if the shell
7011  * script referenced ${CB_CALL_DATA.EVENT.TYPE} , and the "EVENT" portion
7012  * has not yet been referenced, then the incoming name will be "EVENT.TYPE".
7013  * This is why all of the discipline functions below use "strtok()"; this
7014  * allows us to break up the name into each token, and to then initialize
7015  * the token.  Any unrecognized tokens are set to the string "".  In the
7016  * above example, a new name/value pair will be created for both the
7017  * "EVENT" and the "TYPE" portions, and the returned name/value pair will
7018  * be for the "TYPE" portion, since it was the terminal portion of the
7019  * reference.
7020  */
7021
7022
7023 static struct named_integer CallbackReasons[] = {
7024         { "CR_NONE",            XmCR_NONE },
7025         { "CR_HELP",            XmCR_HELP },
7026         { "CR_VALUE_CHANGED",   XmCR_VALUE_CHANGED },
7027         { "CR_INCREMENT",       XmCR_INCREMENT },
7028         { "CR_DECREMENT",       XmCR_DECREMENT },
7029         { "CR_PAGE_INCREMENT",  XmCR_PAGE_INCREMENT },
7030         { "CR_PAGE_DECREMENT",  XmCR_PAGE_DECREMENT },
7031         { "CR_TO_TOP",          XmCR_TO_TOP },
7032         { "CR_TO_BOTTOM",       XmCR_TO_BOTTOM },
7033         { "CR_DRAG",            XmCR_DRAG },
7034         { "CR_ACTIVATE",        XmCR_ACTIVATE },
7035         { "CR_ARM",             XmCR_ARM },
7036         { "CR_DISARM",          XmCR_DISARM },
7037         { "CR_MAP",             XmCR_MAP },
7038         { "CR_UNMAP",           XmCR_UNMAP },
7039         { "CR_FOCUS",           XmCR_FOCUS },
7040         { "CR_LOSING_FOCUS",    XmCR_LOSING_FOCUS },
7041         { "CR_MODIFYING_TEXT_VALUE",    XmCR_MODIFYING_TEXT_VALUE },
7042         { "CR_MOVING_INSERT_CURSOR",    XmCR_MOVING_INSERT_CURSOR },
7043         { "CR_EXECUTE",         XmCR_EXECUTE },
7044         { "CR_SINGLE_SELECT",   XmCR_SINGLE_SELECT },
7045         { "CR_MULTIPLE_SELECT", XmCR_MULTIPLE_SELECT },
7046         { "CR_EXTENDED_SELECT", XmCR_EXTENDED_SELECT },
7047         { "CR_BROWSE_SELECT",   XmCR_BROWSE_SELECT },
7048         { "CR_DEFAULT_ACTION",  XmCR_DEFAULT_ACTION },
7049         { "CR_CLIPBOARD_DATA_REQUEST",  XmCR_CLIPBOARD_DATA_REQUEST },
7050         { "CR_CLIPBOARD_DATA_DELETE",   XmCR_CLIPBOARD_DATA_DELETE },
7051         { "CR_CASCADING",       XmCR_CASCADING },
7052         { "CR_OK",              XmCR_OK },
7053         { "CR_CANCEL",          XmCR_CANCEL },
7054         { "CR_APPLY",           XmCR_APPLY },
7055         { "CR_NO_MATCH",        XmCR_NO_MATCH },
7056         { "CR_COMMAND_ENTERED", XmCR_COMMAND_ENTERED },
7057         { "CR_COMMAND_CHANGED", XmCR_COMMAND_CHANGED },
7058         { "CR_EXPOSE",          XmCR_EXPOSE },
7059         { "CR_RESIZE",          XmCR_RESIZE },
7060         { "CR_INPUT",           XmCR_INPUT },
7061         { "CR_GAIN_PRIMARY",    XmCR_GAIN_PRIMARY },
7062         { "CR_LOSE_PRIMARY",    XmCR_LOSE_PRIMARY },
7063         { "CR_CREATE",          XmCR_CREATE },
7064         { "CR_TEAR_OFF_ACTIVATE",       XmCR_TEAR_OFF_ACTIVATE },
7065         { "CR_TEAR_OFF_DEACTIVATE",     XmCR_TEAR_OFF_DEACTIVATE },
7066         { "CR_OBSCURED_TRAVERSAL",      XmCR_OBSCURED_TRAVERSAL },
7067         { "CR_PROTOCOLS",       6666 },
7068         { NULL,                         NULL },
7069 };
7070
7071
7072 static struct named_integer HelpCallbackReasons[] = {
7073         { "HELP_CR_CLOSE",              DtCR_HELP_CLOSE },
7074         { "HELP_CR_LINK_ACTIVATE",      DtCR_HELP_LINK_ACTIVATE },
7075         { NULL,                         NULL },
7076 };
7077
7078
7079 /*
7080  * Create a new name/value pair (if necessary), and add it to the list of
7081  * name/value pairs which must be cleaned up when we are done.
7082  */
7083 Namval_t *
7084 GetNameValuePair(
7085         char *name )
7086 {
7087    Namval_t * np2;
7088    Namval_t** list;
7089    int i;
7090
7091    if (((np2 = nv_search(name, sh.var_tree, 0)) == NULL) ||
7092         (nestingLevel == 0))
7093    {
7094       /* Add to the list only the first time referenced */
7095       if (nestingLevel + 1 > npTableSize)
7096       {
7097          npTable = (Namval_t ***)XtRealloc((char *)npTable,
7098                                      sizeof(Namval_t **) * (nestingLevel+1));
7099          npListSizes = (int *)XtRealloc((char *)npListSizes,
7100                                      sizeof(int) * (nestingLevel+1));
7101          for (i = npTableSize; i < (nestingLevel + 1); i++)
7102          {
7103             npTable[i] = NULL;
7104             npListSizes[i] = 0;
7105          }
7106          npTableSize = nestingLevel + 1;
7107       }
7108
7109       np2 = nv_search(name, sh.var_tree, NV_ADD);
7110       (npListSizes[nestingLevel])++;
7111       list = npTable[nestingLevel] = (Namval_t **)XtRealloc(
7112             (char *)npTable[nestingLevel], 
7113             sizeof(Namval_t *) * npListSizes[nestingLevel]);
7114       list[npListSizes[nestingLevel] - 1] = np2;
7115       /*
7116        * I _think_ this works OK, because I _think_ the subshell code will
7117        * automatically clean up the "extra" Namval_t it might create here.
7118        * As long as we clean up the original, I don't think we leak here.
7119        */
7120       if(sh.subshell)
7121          np2 = sh_assignok(np2, 1);
7122    }
7123    return(np2);
7124 }
7125
7126
7127 /*
7128  * Free only those environment variables created at this nesting level.
7129  */
7130 void
7131 FreeNestedVariables( void )
7132 {
7133    Namval_t** list;
7134    int i;
7135
7136    if ((nestingLevel < 0) || (nestingLevel >= npTableSize))
7137       return;
7138
7139    list = npTable[nestingLevel];
7140
7141    for (i = 0; i < npListSizes[nestingLevel]; i++)
7142    {
7143       nv_newattr(list[i], 0, 0); 
7144       nv_stack(list[i], NULL);
7145       nv_close(list[i]);
7146    }
7147
7148    XtFree((char *)list);
7149    npTable[nestingLevel] = NULL;
7150    npListSizes[nestingLevel] = 0;
7151 }
7152
7153
7154 /* 
7155  * Create an empty name/value pair.  
7156  * THIS FUNCTION ASSUMES THAT THE CALLER HAS DONE THE INITIAL strtok()
7157  * CALL, SO THAT WE CAN DO THE REMAINING ONES, TO INITIALIZE ALL REMAINING
7158  * TOKENS.
7159  */
7160 static Namval_t *
7161 CreateEmptyNameValuePair(
7162         Namval_t *np,
7163         char *name,
7164         Namfun_t *fp )
7165 {
7166    Namval_t * np2;
7167    char buf[128];
7168
7169    np2 = GetNameValuePair(name);
7170    buf[0] = '\0';
7171    nv_putval(np2, buf, NV_RDONLY);
7172
7173    if (name = strtok(NULL, "."))
7174       return(CreateEmptyNameValuePair(np, name, fp));
7175    else
7176       return(np2);
7177 }
7178
7179
7180 static Namval_t *
7181 ProcessIntValue(
7182         int value,
7183         Namval_t *np,
7184         char *name,
7185         Namfun_t *fp,
7186         char *format,
7187         Namfun_t *fp_new) 
7188 {
7189    Namval_t * np2;
7190    char buf[128];
7191
7192    np2 = GetNameValuePair(name);
7193    sprintf(buf, format, value);
7194
7195    nv_stack(np2, NULL);
7196    nv_putval(np2, buf, NV_RDONLY);
7197    if (fp_new)
7198       nv_stack(np2, fp_new);
7199
7200    if (name = strtok(NULL, "."))
7201       np2 = CreateEmptyNameValuePair(np, name, fp);
7202
7203    return(np2);
7204 }
7205
7206
7207 static Namval_t *
7208 ProcessStringValue(
7209         char *value,
7210         Namval_t *np,
7211         char *name,
7212         Namfun_t *fp )
7213 {
7214    Namval_t * np2;
7215
7216    np2 = GetNameValuePair(name);
7217    if (value)
7218       nv_putval(np2, value, NV_RDONLY);
7219    else
7220       nv_putval(np2, str_nill, NV_RDONLY);
7221
7222    if (name = strtok(NULL, "."))
7223       np2 = CreateEmptyNameValuePair(np, name, fp);
7224
7225    return(np2);
7226 }
7227
7228
7229 static Namval_t *
7230 ProcessBooleanIntValue(
7231         int value,
7232         Namval_t *np,
7233         char *name,
7234         Namfun_t *fp,
7235         Namfun_t *fp_new )
7236 {
7237    Namval_t * np2;
7238    char buf[128];
7239
7240    np2 = GetNameValuePair(name);
7241    if (value)
7242       strcpy(buf, "true");
7243    else
7244       strcpy(buf, "false");
7245
7246    /* 
7247     * Any old disciplies MUST be cleared, before setting value.  If this
7248     * is not done, then excessive looping occurs, and the value will not
7249     * be correct, the next time you retrieve it.
7250     */
7251    nv_stack(np2, NULL);
7252    nv_putval(np2, buf, NV_RDONLY);
7253    if (fp_new)
7254       nv_stack(np2, fp_new);
7255
7256    if (name = strtok(NULL, "."))
7257       np2 = CreateEmptyNameValuePair(np, name, fp);
7258
7259    return(np2);
7260 }
7261
7262
7263 static Namval_t *
7264 ProcessTraversalDirection(
7265         XmTraversalDirection dir,
7266         Namval_t *np,
7267         char *name,
7268         Namfun_t *fp )
7269 {
7270    Namval_t * np2;
7271    char buf[128];
7272    XrmValue f, t;
7273    char * value;
7274
7275    np2 = GetNameValuePair(name);
7276
7277    f.addr = (caddr_t)&dir;
7278    f.size = sizeof(XmTraversalDirection);
7279    t.addr = NULL;
7280    t.size = 0;
7281    XtConvert(Toplevel, "TraversalDirection", &f, XtRString, &t);
7282
7283    if (t.size && t.addr)
7284       value = t.addr;
7285    else
7286       value = str_nill;
7287
7288    strcpy(buf, value);
7289    nv_putval(np2, buf, NV_RDONLY);
7290
7291    if (name = strtok(NULL, "."))
7292       np2 = CreateEmptyNameValuePair(np, name, fp);
7293
7294    return(np2);
7295 }
7296
7297
7298 static Namval_t *
7299 ProcessSelectionType(
7300         char selType,
7301         Namval_t *np,
7302         char *name,
7303         Namfun_t *fp )
7304 {
7305    Namval_t * np2;
7306    char buf[128];
7307    XrmValue f, t;
7308    char * value;
7309    int tmpSelType = (int)selType;
7310
7311    np2 = GetNameValuePair(name);
7312
7313    f.addr = (caddr_t)&tmpSelType;
7314    f.size = sizeof(int);
7315    t.addr = NULL;
7316    t.size = 0;
7317    XtConvert(Toplevel, "ListSelectionType", &f, XtRString, &t);
7318
7319    if (t.size && t.addr)
7320       value = t.addr;
7321    else
7322       value = str_nill;
7323
7324    strcpy(buf, value);
7325    nv_putval(np2, buf, NV_RDONLY);
7326
7327    if (name = strtok(NULL, "."))
7328       np2 = CreateEmptyNameValuePair(np, name, fp);
7329
7330    return(np2);
7331 }
7332
7333
7334 static Namval_t *
7335 ProcessIntTable(
7336         int *table,
7337         int count,
7338         Namval_t *np,
7339         char *name,
7340         Namfun_t *fp )
7341 {
7342    Namval_t * np2;
7343    char * buf;
7344    char buf2[25];
7345    int i;
7346
7347    buf = XtMalloc(1);
7348    buf[0] = '\0';
7349
7350    np2 = GetNameValuePair(name);
7351    if (count > 0)
7352    {
7353       for (i = 0; i < count; i++)
7354       {
7355          sprintf(buf2, "%d", table[i]);
7356          buf = XtRealloc(buf, strlen(buf) + strlen(buf2) + (i == 0 ? 1 : 2));
7357          if (i != 0)
7358             strcat(buf, ",");
7359          strcat(buf, buf2);
7360       }
7361    }
7362
7363    nv_putval(np2, buf, NV_RDONLY);
7364    XtFree (buf);
7365
7366    if (name = strtok(NULL, "."))
7367       np2 = CreateEmptyNameValuePair(np, name, fp);
7368
7369    return(np2);
7370 }
7371
7372
7373 static Namval_t *
7374 ProcessXmStringTable(
7375         XmString *table,
7376         int count,
7377         Namval_t *np,
7378         char *name,
7379         Namfun_t *fp )
7380 {
7381    Namval_t * np2;
7382    char * buf;
7383    int i;
7384
7385    np2 = GetNameValuePair(name);
7386    buf = _CvtXmStringTableToString(table, count);
7387    nv_putval(np2, buf, NV_RDONLY);
7388
7389    if (name = strtok(NULL, "."))
7390       np2 = CreateEmptyNameValuePair(np, name, fp);
7391
7392    return(np2);
7393 }
7394
7395
7396 static Namval_t *
7397 ProcessWidgetHandle(
7398         Widget handle,
7399         Namval_t *np,
7400         char *name,
7401         Namfun_t *fp )
7402 {
7403    Namval_t * np2;
7404    char buf[128];
7405    wtab_t * w;
7406
7407    np2 = GetNameValuePair(name);
7408    w = widget_to_wtab(handle);
7409    strcpy(buf, w ? w->widid : "Unknown");
7410    nv_putval(np2, buf, NV_RDONLY);
7411
7412    if (name = strtok(NULL, "."))
7413       np2 = CreateEmptyNameValuePair(np, name, fp);
7414
7415    return(np2);
7416 }
7417
7418
7419 static Namval_t *
7420 ProcessXmStringValue(
7421         XmString xmstring,
7422         Namval_t *np,
7423         char *name,
7424         Namfun_t *fp )
7425 {
7426    Namval_t * np2;
7427    char buf[128];
7428    wtab_t * w;
7429    char * value;
7430
7431    np2 = GetNameValuePair(name);
7432
7433    if ((value = XmStringToString(xmstring)) == NULL)
7434       value = str_nill;
7435
7436    nv_putval(np2, value, NV_RDONLY);
7437
7438    if (name = strtok(NULL, "."))
7439       np2 = CreateEmptyNameValuePair(np, name, fp);
7440
7441    return(np2);
7442 }
7443
7444
7445 static Namval_t *
7446 ProcessHyperType(
7447         int hyperType,
7448         Namval_t *np,
7449         char *name,
7450         Namfun_t *fp )
7451 {
7452    Namval_t * np2;
7453    char buf[128];
7454    wtab_t * w;
7455    XrmValue f, t;
7456    char * value;
7457
7458    np2 = GetNameValuePair(name);
7459
7460    f.addr = (caddr_t)&hyperType;
7461    f.size = sizeof(long);
7462    t.addr = NULL;
7463    t.size = 0;
7464    XtConvert(Toplevel, "HelpHyperType", &f, XtRString, &t);
7465
7466    if (t.addr)
7467       value = t.addr;
7468    else
7469       value = str_nill;
7470
7471    strcpy(buf, value);
7472    nv_putval(np2, buf, NV_RDONLY);
7473
7474    if (name = strtok(NULL, "."))
7475       np2 = CreateEmptyNameValuePair(np, name, fp);
7476
7477    return(np2);
7478 }
7479
7480
7481 static XEventTable eventTable[] = {
7482         {"XANY", NULL},
7483         {"XBUTTON", NULL},
7484         {"XEXPOSE", NULL},
7485         {"XNOEXPOSE", NULL},
7486         {"XGRAPHICSEXPOSE", NULL},
7487         {"XKEY", NULL},
7488         {"XMOTION", NULL},
7489         {NULL, NULL},
7490 };
7491
7492 static EventEntryTable xanyTable[] = {
7493    {"TYPE", "XE_EventType", XtOffsetOf(XEvent, xany.type), sizeof(int)},
7494    {"SERIAL", "XE_IntValue", XtOffsetOf(XEvent, xany.serial), 
7495      sizeof(unsigned long)},
7496    {"SEND_EVENT", "X_Bool", XtOffsetOf(XEvent, xany.send_event),
7497      sizeof(Boolean)},
7498    {"DISPLAY", "XE_HexValue", XtOffsetOf(XEvent, xany.display),
7499      sizeof(Display *)},
7500    {"WINDOW", "XE_Window", XtOffsetOf(XEvent, xany.window),
7501      sizeof(Window)},
7502    {NULL, NULL, 0, 0},
7503 };
7504
7505 static EventEntryTable xbuttonTable[] = {
7506    {"TYPE", "XE_EventType", XtOffsetOf(XEvent, xbutton.type), sizeof(int)},
7507    {"SERIAL", "XE_IntValue", XtOffsetOf(XEvent, xbutton.serial), 
7508      sizeof(unsigned long)},
7509    {"SEND_EVENT", "X_Bool", XtOffsetOf(XEvent, xbutton.send_event),
7510      sizeof(Bool)},
7511    {"DISPLAY", "XE_HexValue", XtOffsetOf(XEvent, xbutton.display),
7512      sizeof(Display *)},
7513    {"WINDOW", "XE_Window", XtOffsetOf(XEvent, xbutton.window),
7514      sizeof(Window)},
7515    {"ROOT", "XE_Window", XtOffsetOf(XEvent, xbutton.root),
7516      sizeof(Window)},
7517    {"SUBWINDOW", "XE_Window", XtOffsetOf(XEvent, xbutton.subwindow),
7518      sizeof(Window)},
7519    {"TIME", "XE_IntValue", XtOffsetOf(XEvent, xbutton.time),
7520      sizeof(unsigned int)},
7521    {"X", "XE_IntValue", XtOffsetOf(XEvent, xbutton.x),
7522      sizeof(int)},
7523    {"Y", "XE_IntValue", XtOffsetOf(XEvent, xbutton.y),
7524      sizeof(int)},
7525    {"X_ROOT", "XE_IntValue", XtOffsetOf(XEvent, xbutton.x_root),
7526      sizeof(int)},
7527    {"Y_ROOT", "XE_IntValue", XtOffsetOf(XEvent, xbutton.y_root),
7528      sizeof(int)},
7529    {"STATE", "XE_ModifierState", XtOffsetOf(XEvent, xbutton.state),
7530      sizeof(unsigned int)},
7531    {"BUTTON", "XE_Button", XtOffsetOf(XEvent, xbutton.button),
7532      sizeof(unsigned int)},
7533    {"SAME_SCREEN", "X_Bool", XtOffsetOf(XEvent, xbutton.same_screen),
7534      sizeof(Bool)},
7535    {NULL, NULL, 0, 0},
7536 };
7537
7538 static EventEntryTable xexposeTable[] = {
7539    {"TYPE", "XE_EventType", XtOffsetOf(XEvent, xexpose.type), sizeof(int)},
7540    {"SERIAL", "XE_IntValue", XtOffsetOf(XEvent, xexpose.serial), 
7541      sizeof(unsigned long)},
7542    {"SEND_EVENT", "X_Bool", XtOffsetOf(XEvent, xexpose.send_event),
7543      sizeof(Bool)},
7544    {"DISPLAY", "XE_HexValue", XtOffsetOf(XEvent, xexpose.display),
7545      sizeof(Display *)},
7546    {"WINDOW", "XE_Window", XtOffsetOf(XEvent, xexpose.window),
7547      sizeof(Window)},
7548    {"X", "XE_IntValue", XtOffsetOf(XEvent, xexpose.x),
7549      sizeof(int)},
7550    {"Y", "XE_IntValue", XtOffsetOf(XEvent, xexpose.y),
7551      sizeof(int)},
7552    {"WIDTH", "XE_IntValue", XtOffsetOf(XEvent, xexpose.width),
7553      sizeof(int)},
7554    {"HEIGHT", "XE_IntValue", XtOffsetOf(XEvent, xexpose.height),
7555      sizeof(int)},
7556    {"COUNT", "XE_IntValue", XtOffsetOf(XEvent, xexpose.count),
7557      sizeof(int)},
7558    {NULL, NULL, 0, 0},
7559 };
7560
7561 static EventEntryTable xnoExposeTable[] = {
7562    {"TYPE", "XE_EventType", XtOffsetOf(XEvent, xnoexpose.type), sizeof(int)},
7563    {"SERIAL", "XE_IntValue", XtOffsetOf(XEvent, xnoexpose.serial), 
7564      sizeof(unsigned long)},
7565    {"SEND_EVENT", "X_Bool", XtOffsetOf(XEvent, xnoexpose.send_event),
7566      sizeof(Bool)},
7567    {"DISPLAY", "XE_HexValue", XtOffsetOf(XEvent, xnoexpose.display),
7568      sizeof(Display *)},
7569    {"DRAWABLE", "XE_Window", XtOffsetOf(XEvent, xnoexpose.drawable),
7570      sizeof(Window)},
7571    {"MAJOR_CODE", "XE_IntValue", XtOffsetOf(XEvent, xnoexpose.major_code),
7572      sizeof(int)},
7573    {"MINOR_CODE", "XE_IntValue", XtOffsetOf(XEvent, xnoexpose.minor_code),
7574      sizeof(int)},
7575    {NULL, NULL, 0, 0},
7576 };
7577
7578 static EventEntryTable xgraphicsExposeTable[] = {
7579    {"TYPE", "XE_EventType", 
7580      XtOffsetOf(XEvent, xgraphicsexpose.type), sizeof(int)},
7581    {"SERIAL", "XE_IntValue", XtOffsetOf(XEvent, xgraphicsexpose.serial), 
7582      sizeof(unsigned long)},
7583    {"SEND_EVENT", "X_Bool", XtOffsetOf(XEvent, xgraphicsexpose.send_event),
7584      sizeof(Bool)},
7585    {"DISPLAY", "XE_HexValue", XtOffsetOf(XEvent, xgraphicsexpose.display),
7586      sizeof(Display *)},
7587    {"DRAWABLE", "XE_Window", XtOffsetOf(XEvent, xgraphicsexpose.drawable),
7588      sizeof(Window)},
7589    {"X", "XE_IntValue", XtOffsetOf(XEvent, xgraphicsexpose.x),
7590      sizeof(int)},
7591    {"Y", "XE_IntValue", XtOffsetOf(XEvent, xgraphicsexpose.y),
7592      sizeof(int)},
7593    {"WIDTH", "XE_IntValue", XtOffsetOf(XEvent, xgraphicsexpose.width),
7594      sizeof(int)},
7595    {"HEIGHT", "XE_IntValue", XtOffsetOf(XEvent, xgraphicsexpose.height),
7596      sizeof(int)},
7597    {"COUNT", "XE_IntValue", XtOffsetOf(XEvent, xgraphicsexpose.count),
7598      sizeof(int)},
7599    {"MAJOR_CODE", "XE_IntValue", 
7600      XtOffsetOf(XEvent, xgraphicsexpose.major_code),
7601      sizeof(int)},
7602    {"MINOR_CODE", "XE_IntValue", XtOffsetOf(XEvent, xgraphicsexpose.minor_code),
7603      sizeof(int)},
7604    {NULL, NULL, 0, 0},
7605 };
7606
7607 static EventEntryTable xkeyTable[] = {
7608    {"TYPE", "XE_EventType", XtOffsetOf(XEvent, xkey.type), sizeof(int)},
7609    {"SERIAL", "XE_IntValue", XtOffsetOf(XEvent, xkey.serial), 
7610      sizeof(unsigned long)},
7611    {"SEND_EVENT", "X_Bool", XtOffsetOf(XEvent, xkey.send_event),
7612      sizeof(Bool)},
7613    {"DISPLAY", "XE_HexValue", XtOffsetOf(XEvent, xkey.display),
7614      sizeof(Display *)},
7615    {"WINDOW", "XE_Window", XtOffsetOf(XEvent, xkey.window),
7616      sizeof(Window)},
7617    {"ROOT", "XE_Window", XtOffsetOf(XEvent, xkey.root),
7618      sizeof(Window)},
7619    {"SUBWINDOW", "XE_Window", XtOffsetOf(XEvent, xkey.subwindow),
7620      sizeof(Window)},
7621    {"TIME", "XE_IntValue", XtOffsetOf(XEvent, xkey.time),
7622      sizeof(unsigned int)},
7623    {"X", "XE_IntValue", XtOffsetOf(XEvent, xkey.x),
7624      sizeof(int)},
7625    {"Y", "XE_IntValue", XtOffsetOf(XEvent, xkey.y),
7626      sizeof(int)},
7627    {"X_ROOT", "XE_IntValue", XtOffsetOf(XEvent, xkey.x_root),
7628      sizeof(int)},
7629    {"Y_ROOT", "XE_IntValue", XtOffsetOf(XEvent, xkey.y_root),
7630      sizeof(int)},
7631    {"STATE", "XE_ModifierState", XtOffsetOf(XEvent, xkey.state),
7632      sizeof(unsigned int)},
7633    {"KEYCODE", "XE_IntValue", XtOffsetOf(XEvent, xkey.keycode),
7634      sizeof(unsigned int)},
7635    {"SAME_SCREEN", "X_Bool", XtOffsetOf(XEvent, xkey.same_screen),
7636      sizeof(Bool)},
7637    {NULL, NULL, 0, 0},
7638 };
7639
7640 static EventEntryTable xmotionTable[] = {
7641    {"TYPE", "XE_EventType", XtOffsetOf(XEvent, xmotion.type), sizeof(int)},
7642    {"SERIAL", "XE_IntValue", XtOffsetOf(XEvent, xmotion.serial), 
7643      sizeof(unsigned long)},
7644    {"SEND_EVENT", "X_Bool", XtOffsetOf(XEvent, xmotion.send_event),
7645      sizeof(Bool)},
7646    {"DISPLAY", "XE_HexValue", XtOffsetOf(XEvent, xmotion.display),
7647      sizeof(Display *)},
7648    {"WINDOW", "XE_Window", XtOffsetOf(XEvent, xmotion.window),
7649      sizeof(Window)},
7650    {"ROOT", "XE_Window", XtOffsetOf(XEvent, xmotion.root),
7651      sizeof(Window)},
7652    {"SUBWINDOW", "XE_Window", XtOffsetOf(XEvent, xmotion.subwindow),
7653      sizeof(Window)},
7654    {"TIME", "XE_IntValue", XtOffsetOf(XEvent, xmotion.time),
7655      sizeof(unsigned int)},
7656    {"X", "XE_IntValue", XtOffsetOf(XEvent, xmotion.x),
7657      sizeof(int)},
7658    {"Y", "XE_IntValue", XtOffsetOf(XEvent, xmotion.y),
7659      sizeof(int)},
7660    {"X_ROOT", "XE_IntValue", XtOffsetOf(XEvent, xmotion.x_root),
7661      sizeof(int)},
7662    {"Y_ROOT", "XE_IntValue", XtOffsetOf(XEvent, xmotion.y_root),
7663      sizeof(int)},
7664    {"STATE", "XE_ModifierState", XtOffsetOf(XEvent, xmotion.state),
7665      sizeof(unsigned int)},
7666    {"IS_HINT", "XE_MotionHint", XtOffsetOf(XEvent, xmotion.is_hint),
7667      sizeof(char)},
7668    {"SAME_SCREEN", "X_Bool", XtOffsetOf(XEvent, xmotion.same_screen),
7669      sizeof(Bool)},
7670    {NULL, NULL, 0, 0},
7671 };
7672
7673 /*
7674  * The order in which the structures are initialized IS important; they
7675  * must be done in the same order as they are defined in the eventTable
7676  * structure.
7677  */
7678 static void
7679 InitEventTables( void )
7680 {
7681    int i = 0;
7682
7683    eventTable[i++].table = xanyTable;
7684    eventTable[i++].table = xbuttonTable;
7685    eventTable[i++].table = xexposeTable;
7686    eventTable[i++].table = xnoExposeTable;
7687    eventTable[i++].table = xgraphicsExposeTable;
7688    eventTable[i++].table = xkeyTable;
7689    eventTable[i++].table = xmotionTable;
7690 }
7691
7692
7693 static Namval_t *
7694 ProcessCallbackEvent(
7695         XEvent *event,
7696         Namval_t *np,
7697         char *name,
7698         Namfun_t *fp )
7699 {
7700    Namval_t * np2;
7701    char buf[128];
7702    static Boolean initialized = False;
7703    int i = 0;
7704    int j = 0;
7705    EventEntryTable * table;
7706    XrmValue fval, tval;
7707    char * ptr;
7708
7709    if (!initialized)
7710    {
7711       InitEventTables();
7712       initialized = True;
7713    }
7714
7715    np2 = GetNameValuePair(name);
7716    sprintf(buf, "0x%lx", (long)event);
7717    nv_putval(np2, buf, NV_RDONLY);
7718
7719    if (name = strtok(NULL, "."))
7720    {
7721       if (event == NULL)
7722          np2 = CreateEmptyNameValuePair(np, name, fp);
7723       else
7724       {
7725          np2 = GetNameValuePair(name);
7726          if (strcmp(name, "TYPE") == 0)
7727          {
7728             fval.addr = (caddr_t)&(event->type);
7729             fval.size = sizeof(long);
7730             XtConvert(Toplevel, "XE_EventType", &fval, XtRString, &tval);
7731             if (tval.size != 0) 
7732                ptr = (char *)(tval.addr);
7733             else
7734                ptr = str_nill;
7735             nv_putval(np2, ptr, NV_RDONLY);
7736          }
7737          else
7738          {
7739             while (eventTable[i].eventType)
7740             {
7741                if (strcmp(eventTable[i].eventType, name) == 0)
7742                {
7743                   sprintf(buf, "0x%lx", (long)event);
7744                   nv_putval(np2, buf, NV_RDONLY);
7745
7746                   if (name = strtok(NULL, "."))
7747                   {
7748                      np2 = GetNameValuePair(name);
7749                      table = eventTable[i].table;
7750                      while (table[j].fieldName)
7751                      {
7752                         if (strcmp(table[j].fieldName, name) == 0)
7753                         {
7754                            if (table[j].valueSize == sizeof(char))
7755                            {
7756                               fval.addr = (caddr_t) ((char *)
7757                                          ((char *)event+table[j].valueOffset));
7758                               fval.size = sizeof(char);
7759                            }
7760                            else if (table[j].valueSize == sizeof(short))
7761                            {
7762                               fval.addr = (caddr_t) ((short *)
7763                                          ((char *)event+table[j].valueOffset));
7764                               fval.size = sizeof(short);
7765                            }
7766                            else if (table[j].valueSize == sizeof(int))
7767                            {
7768                               fval.addr = (caddr_t) ((int *)
7769                                           ((char *)event+table[j].valueOffset));
7770                               fval.size = sizeof(int);
7771                            }
7772                            else if (table[j].valueSize == sizeof(long))
7773                            {
7774                               fval.addr = (caddr_t) ((long *)
7775                                          ((char *)event+table[j].valueOffset));
7776                               fval.size = sizeof(long);
7777                            }
7778                            XtConvert(Toplevel, table[j].representation,
7779                                      &fval, XtRString, &tval);
7780                            if (tval.size != 0) 
7781                                ptr = (char *)(tval.addr);
7782                             else
7783                                ptr = str_nill;
7784                             nv_putval(np2, ptr, NV_RDONLY);
7785                            break;
7786                         }
7787                         j++;
7788                      }
7789                      if (table[j].fieldName == NULL)
7790                         nv_putval(np2, str_nill, NV_RDONLY);
7791
7792                      break;
7793                   }
7794                }
7795                i++;
7796             }
7797             if (eventTable[i].eventType == NULL)
7798                nv_putval(np2, str_nill, NV_RDONLY);
7799          }
7800
7801          if (name = strtok(NULL, "."))
7802             np2 = CreateEmptyNameValuePair(np, name, fp);
7803       }
7804    }
7805    return(np2);
7806 }
7807
7808
7809 static Namval_t *
7810 _IntProcessCallbackReason(
7811         struct named_integer *table,
7812         XmAnyCallbackStruct *cbData,
7813         Namval_t *np,
7814         char *name,
7815         Namfun_t *fp )
7816 {
7817    Namval_t * np2;
7818    char buf[128];
7819
7820    /*
7821     * We won't use an Xt converter here (even though we could), because
7822     * we want to be able to handle the case where the callback reason
7823     * is one we don't know about.
7824     */
7825    np2 = GetNameValuePair(name);
7826    while (table->name)
7827    {
7828       if (table->value == cbData->reason)
7829       {
7830          nv_putval(np2, table->name, NV_RDONLY);
7831          if (name = strtok(NULL, "."))
7832             np2 = CreateEmptyNameValuePair(np, name, fp);
7833          return(np2);
7834       }
7835       table++;
7836    }
7837
7838    /* 
7839     * fdt: someday, allow for an expandable table, which can be 
7840     * added to by the shell script; useful when loading new widgets.
7841     */
7842
7843    /* Unknown callback reason; simply return the integer value */
7844    sprintf(buf, "%d", cbData->reason);
7845    nv_putval(np2, buf, NV_RDONLY);
7846    if (name = strtok(NULL, "."))
7847       np2 = CreateEmptyNameValuePair(np, name, fp);
7848    return(np2);
7849 }
7850
7851
7852 static Namval_t *
7853 ProcessCallbackReason(
7854         XmAnyCallbackStruct *cbData,
7855         Namval_t *np,
7856         char *name,
7857         Namfun_t *fp )
7858 {
7859    return(_IntProcessCallbackReason(CallbackReasons, cbData, np, name, fp));
7860 }
7861
7862
7863 /*
7864  * This requires a separate handler, due to the fact that the help
7865  * callback reasons overlap the standard Motif callback reasons!!
7866  */
7867 static Namval_t *
7868 ProcessHelpCallbackReason(
7869         XmAnyCallbackStruct *cbData,
7870         Namval_t *np,
7871         char *name,
7872         Namfun_t *fp )
7873 {
7874    return(_IntProcessCallbackReason(HelpCallbackReasons, cbData, np, name, fp));
7875 }
7876
7877
7878 /*
7879  * Certain classes of callbacks do not return a structure as the calldata.
7880  * Examples are the destroyCallback, popupCallback, popdownCallback and
7881  * the workspace changed callback. Since the calldata is a value, and not
7882  * a structure, any references to subfields are invalid.
7883  */
7884 Namval_t *
7885 nopCreateDisc(
7886         Namval_t *np,
7887         char *name,
7888         Namfun_t *fp )
7889 {
7890    Namval_t * np2;
7891    char * token;
7892    char * dupName = strdup(name);
7893
7894    token = strtok(dupName, ".");
7895
7896    np2 = CreateEmptyNameValuePair(np, token, fp);
7897    XtFree(dupName);
7898    return(np2);
7899 }
7900
7901
7902 /*
7903  * This function creates a new name/value pair (representing an environment
7904  * variable) when it is referenced.  If the name/value pair already exists,
7905  * then it is simply reused.  We keep track of all the name/value pairs
7906  * we create, so that they can be destroyed when callback processing has
7907  * completed.  This handles the XmAnyCallbackStruct.
7908  */
7909 Namval_t *
7910 dftCreateDisc(
7911         Namval_t *np,
7912         char *name,
7913         Namfun_t *fp )
7914 {
7915    Namval_t * np2;
7916    char buf[128];
7917    XmAnyCallbackStruct * cbData;
7918    char * cbDataAddrStr;
7919    char * p;
7920    char * token;
7921    char * dupName = strdup(name);
7922
7923    cbDataAddrStr = nv_getv(np, fp);
7924    cbData = (XmAnyCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
7925
7926    token = strtok(dupName, ".");
7927
7928    /* cbData can be NULL if invoked from XtCallCallbacks */
7929    if (cbData == NULL)
7930       np2 = CreateEmptyNameValuePair(np, token, fp);
7931    else if (strcmp(token, "REASON") == 0)
7932       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
7933    else if (strcmp(token, "EVENT") == 0)
7934       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
7935    else
7936       np2 = CreateEmptyNameValuePair(np, token, fp);
7937
7938    XtFree(dupName);
7939    return(np2);
7940 }
7941
7942
7943 /*
7944  * This is the discipline handler for an event handler.
7945  * It only knows how to reference the event structure.
7946  */
7947 Namval_t *
7948 ehCreateDisc(
7949         Namval_t *np,
7950         char *name,
7951         Namfun_t *fp )
7952 {
7953    Namval_t * np2;
7954    char buf[128];
7955    XEvent * event;
7956    char * eventAddrStr;
7957    char * p;
7958    char * token;
7959    char * tmpBuf;
7960
7961    eventAddrStr = nv_getv(np, fp);
7962    event = (XEvent *)strtoul(eventAddrStr, &p, 0);
7963    tmpBuf = XtMalloc(strlen(name) + strlen("EH_EVENT") + 2);
7964    sprintf(tmpBuf, "%s.%s", "EH_EVENT", name);
7965    token = strtok(tmpBuf, ".");
7966    np2 = ProcessCallbackEvent(event, np, token, fp);
7967    XtFree(tmpBuf);
7968    return(np2);
7969 }
7970
7971
7972 /*
7973  * This is the discipline handler for the translation handler.
7974  * It only knows how to reference the event structure.
7975  */
7976 Namval_t *
7977 transCreateDisc(
7978         Namval_t *np,
7979         char *name,
7980         Namfun_t *fp )
7981 {
7982    Namval_t * np2;
7983    char buf[128];
7984    XEvent * event;
7985    char * eventAddrStr;
7986    char * p;
7987    char * token;
7988    char * tmpBuf;
7989
7990    eventAddrStr = nv_getv(np, fp);
7991    event = (XEvent *)strtoul(eventAddrStr, &p, 0);
7992    tmpBuf = XtMalloc(strlen(name) + strlen("TRANSLATION_EVENT") + 2);
7993    sprintf(tmpBuf, "%s.%s", "TRANSLATION_EVENT", name);
7994    token = strtok(tmpBuf, ".");
7995    np2 = ProcessCallbackEvent(event, np, token, fp);
7996    XtFree(tmpBuf);
7997    return(np2);
7998 }
7999
8000 /* 
8001  * This is the 'create' discipline function for the scale widget. 
8002  * This handles the XmScaleCallbackStruct.
8003  */
8004 Namval_t *
8005 scaleCreateDisc(
8006         Namval_t *np,
8007         char *name,
8008         Namfun_t *fp )
8009 {
8010    char * cbDataAddrStr;
8011    XmScaleCallbackStruct * cbData;
8012    char * p;
8013    char * token;
8014    char * dupName = strdup(name);
8015    Namval_t * np2;
8016
8017    cbDataAddrStr = nv_getv(np, fp);
8018    cbData = (XmScaleCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8019
8020    token = strtok(dupName, ".");
8021
8022    /* cbData can be NULL if invoked from XtCallCallbacks */
8023    if (cbData == NULL)
8024       np2 = CreateEmptyNameValuePair(np, token, fp);
8025    else if (strcmp(token, "REASON") == 0)
8026       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8027    else if (strcmp(token, "EVENT") == 0)
8028       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8029    else if (strcmp(token, "VALUE") == 0)
8030       np2 = ProcessIntValue((int)cbData->value, np, token, fp, "%d", NULL);
8031    else
8032       np2 = CreateEmptyNameValuePair(np, token, fp);
8033
8034    XtFree(dupName);
8035    return(np2);
8036 }
8037
8038 /* 
8039  * This is the 'create' discipline function for the arrow widget. 
8040  * This handles the XmArrowButtonCallbackStruct.
8041  */
8042 Namval_t *
8043 arrowCreateDisc(
8044         Namval_t *np,
8045         char *name,
8046         Namfun_t *fp )
8047 {
8048    char * cbDataAddrStr;
8049    XmArrowButtonCallbackStruct * cbData;
8050    char * p;
8051    char * token;
8052    char * dupName = strdup(name);
8053    Namval_t * np2;
8054
8055    cbDataAddrStr = nv_getv(np, fp);
8056    cbData = (XmArrowButtonCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8057
8058    token = strtok(dupName, ".");
8059
8060    /* cbData can be NULL if invoked from XtCallCallbacks */
8061    if (cbData == NULL)
8062       np2 = CreateEmptyNameValuePair(np, token, fp);
8063    else if (strcmp(token, "REASON") == 0)
8064       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8065    else if (strcmp(token, "EVENT") == 0)
8066       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8067    else if (strcmp(token, "CLICK_COUNT") == 0)
8068    {
8069       if (cbData->reason == XmCR_ACTIVATE)
8070       {
8071          np2 = ProcessIntValue((int)cbData->click_count, np, token, fp, "%d", 
8072                                NULL);
8073       }
8074       else
8075          np2 = CreateEmptyNameValuePair(np, token, fp);
8076    }
8077    else
8078       np2 = CreateEmptyNameValuePair(np, token, fp);
8079
8080    XtFree(dupName);
8081    return(np2);
8082 }
8083
8084 /* 
8085  * This is the 'create' discipline function for the comboBox widget. 
8086  * This handles the XmComboBoxCallbackStruct.
8087  */
8088 Namval_t *
8089 comboCreateDisc(
8090         Namval_t *np,
8091         char *name,
8092         Namfun_t *fp )
8093 {
8094    char * cbDataAddrStr;
8095    XmComboBoxCallbackStruct * cbData;
8096    char * p;
8097    char * token;
8098    char * dupName = strdup(name);
8099    Namval_t * np2;
8100
8101    cbDataAddrStr = nv_getv(np, fp);
8102    cbData = (XmComboBoxCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8103
8104    token = strtok(dupName, ".");
8105
8106    /* cbData can be NULL if invoked from XtCallCallbacks */
8107    if (cbData == NULL)
8108       np2 = CreateEmptyNameValuePair(np, token, fp);
8109    else if (strcmp(token, "REASON") == 0)
8110       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData,
8111                                   np, token, fp);
8112    else if (strcmp(token, "EVENT") == 0)
8113       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8114    else if (strcmp(token, "ITEM_OR_TEXT") == 0)
8115       np2 = ProcessXmStringValue(cbData->item_or_text, np, token, fp);
8116    else if (strcmp(token, "ITEM_POSITION") == 0)
8117    {
8118       np2 = ProcessIntValue((int)cbData->item_position, np, token, fp, "%d",
8119                             NULL);
8120    }
8121    else
8122       np2 = CreateEmptyNameValuePair(np, token, fp);
8123
8124    XtFree(dupName);
8125    return(np2);
8126 }
8127
8128 /* 
8129  * This is the 'create' discipline function for the command widget. 
8130  * This handles the XmCommandCallbackStruct.
8131  */
8132 Namval_t *
8133 cmdCreateDisc(
8134         Namval_t *np,
8135         char *name,
8136         Namfun_t *fp )
8137 {
8138    char * cbDataAddrStr;
8139    XmCommandCallbackStruct * cbData;
8140    char * p;
8141    char * token;
8142    char * dupName = strdup(name);
8143    Namval_t * np2;
8144    int len;
8145
8146    cbDataAddrStr = nv_getv(np, fp);
8147    cbData = (XmCommandCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8148
8149    token = strtok(dupName, ".");
8150
8151    /* cbData can be NULL if invoked from XtCallCallbacks */
8152    if (cbData == NULL)
8153       np2 = CreateEmptyNameValuePair(np, token, fp);
8154    else if (strcmp(token, "REASON") == 0)
8155       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8156    else if (strcmp(token, "EVENT") == 0)
8157       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8158    else if (strcmp(token, "VALUE") == 0)
8159       np2 = ProcessXmStringValue(cbData->value, np, token, fp);
8160    else if (strcmp(token, "LENGTH") == 0)
8161    {
8162       if ((p = XmStringToString(cbData->value)) == NULL)
8163          len = 0;
8164       else
8165          len = strlen(p);
8166       np2 = ProcessIntValue((int)len, np, token, fp, "%d", NULL);
8167    }
8168    else
8169       np2 = CreateEmptyNameValuePair(np, token, fp);
8170
8171    XtFree(dupName);
8172    return(np2);
8173 }
8174
8175 /* 
8176  * This is the 'create' discipline function for the drawingArea widget. 
8177  * This handles the XmDrawingAreaCallbackStruct.
8178  */
8179 Namval_t *
8180 dAreaCreateDisc(
8181         Namval_t *np,
8182         char *name,
8183         Namfun_t *fp )
8184 {
8185    char * cbDataAddrStr;
8186    XmDrawingAreaCallbackStruct * cbData;
8187    char * p;
8188    char * token;
8189    char * dupName = strdup(name);
8190    Namval_t * np2;
8191
8192    cbDataAddrStr = nv_getv(np, fp);
8193    cbData = (XmDrawingAreaCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8194
8195    token = strtok(dupName, ".");
8196
8197    /* cbData can be NULL if invoked from XtCallCallbacks */
8198    if (cbData == NULL)
8199       np2 = CreateEmptyNameValuePair(np, token, fp);
8200    else if (strcmp(token, "REASON") == 0)
8201       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8202    else if (strcmp(token, "EVENT") == 0)
8203       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8204    else if (strcmp(token, "WINDOW") == 0)
8205       np2 = ProcessIntValue((int)cbData->window, np, token, fp, "0x%x", NULL);
8206    else
8207       np2 = CreateEmptyNameValuePair(np, token, fp);
8208
8209    XtFree(dupName);
8210    return(np2);
8211 }
8212
8213 /* 
8214  * This is the 'create' discipline function for the drawnButton widget. 
8215  * This handles the XmDrawnButtonCallbackStruct.
8216  */
8217 Namval_t *
8218 dbtnCreateDisc(
8219         Namval_t *np,
8220         char *name,
8221         Namfun_t *fp )
8222 {
8223    char * cbDataAddrStr;
8224    XmDrawnButtonCallbackStruct * cbData;
8225    char * p;
8226    char * token;
8227    char * dupName = strdup(name);
8228    Namval_t * np2;
8229
8230    cbDataAddrStr = nv_getv(np, fp);
8231    cbData = (XmDrawnButtonCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8232
8233    token = strtok(dupName, ".");
8234
8235    /* cbData can be NULL if invoked from XtCallCallbacks */
8236    if (cbData == NULL)
8237       np2 = CreateEmptyNameValuePair(np, token, fp);
8238    else if (strcmp(token, "REASON") == 0)
8239       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8240    else if (strcmp(token, "EVENT") == 0)
8241       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8242    else if (strcmp(token, "WINDOW") == 0)
8243       np2 = ProcessIntValue((int)cbData->window, np, token, fp, "0x%x", NULL);
8244    else if (strcmp(token, "CLICK_COUNT") == 0)
8245    {
8246       if (cbData->reason == XmCR_ACTIVATE)
8247       {
8248          np2 = ProcessIntValue((int)cbData->click_count, np, token, fp, "%d", 
8249                                NULL);
8250       }
8251       else
8252          np2 = CreateEmptyNameValuePair(np, token, fp);
8253    }
8254    else
8255       np2 = CreateEmptyNameValuePair(np, token, fp);
8256
8257    XtFree(dupName);
8258    return(np2);
8259 }
8260
8261 /* 
8262  * This is the 'create' discipline function for the file selection widget. 
8263  * This handles the XmFileSelectionBoxCallbackStruct.
8264  */
8265 Namval_t *
8266 fselCreateDisc(
8267         Namval_t *np,
8268         char *name,
8269         Namfun_t *fp )
8270 {
8271    char * cbDataAddrStr;
8272    XmFileSelectionBoxCallbackStruct * cbData;
8273    char * p;
8274    char * token;
8275    char * dupName = strdup(name);
8276    Namval_t * np2;
8277    int len;
8278
8279    cbDataAddrStr = nv_getv(np, fp);
8280    cbData = (XmFileSelectionBoxCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8281
8282    token = strtok(dupName, ".");
8283
8284    /* cbData can be NULL if invoked from XtCallCallbacks */
8285    if (cbData == NULL)
8286       np2 = CreateEmptyNameValuePair(np, token, fp);
8287    else if (strcmp(token, "REASON") == 0)
8288       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8289    else if (strcmp(token, "EVENT") == 0)
8290       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8291    else if (strcmp(token, "VALUE") == 0)
8292       np2 = ProcessXmStringValue(cbData->value, np, token, fp);
8293    else if (strcmp(token, "LENGTH") == 0)
8294    {
8295       if ((p = XmStringToString(cbData->value)) == NULL)
8296          len = 0;
8297       else
8298          len = strlen(p);
8299       np2 = ProcessIntValue(len, np, token, fp, "%d", NULL);
8300    }
8301    else if (strcmp(token, "MASK") == 0)
8302       np2 = ProcessXmStringValue(cbData->mask, np, token, fp);
8303    else if (strcmp(token, "MASK_LENGTH") == 0)
8304    {
8305       if ((p = XmStringToString(cbData->mask)) == NULL)
8306          len = 0;
8307       else
8308          len = strlen(p);
8309       np2 = ProcessIntValue(len, np, token, fp, "%d", NULL);
8310    }
8311    else if (strcmp(token, "DIR") == 0)
8312       np2 = ProcessXmStringValue(cbData->dir, np, token, fp);
8313    else if (strcmp(token, "DIR_LENGTH") == 0)
8314    {
8315       if ((p = XmStringToString(cbData->dir)) == NULL)
8316          len = 0;
8317       else
8318          len = strlen(p);
8319       np2 = ProcessIntValue(len, np, token, fp, "%d", NULL);
8320    }
8321    else if (strcmp(token, "PATTERN") == 0)
8322       np2 = ProcessXmStringValue(cbData->pattern, np, token, fp);
8323    else if (strcmp(token, "PATTERN_LENGTH") == 0)
8324    {
8325       if ((p = XmStringToString(cbData->pattern)) == NULL)
8326          len = 0;
8327       else
8328          len = strlen(p);
8329       np2 = ProcessIntValue(len, np, token, fp, "%d", NULL);
8330    }
8331    else
8332       np2 = CreateEmptyNameValuePair(np, token, fp);
8333
8334    XtFree(dupName);
8335    return(np2);
8336 }
8337
8338 /* 
8339  * This is the 'create' discipline function for the list widget. 
8340  * This handles the XmListCallbackStruct.
8341  */
8342 Namval_t *
8343 listCreateDisc(
8344         Namval_t *np,
8345         char *name,
8346         Namfun_t *fp )
8347 {
8348    char * cbDataAddrStr;
8349    XmListCallbackStruct * cbData;
8350    char * p;
8351    char * token;
8352    char * dupName = strdup(name);
8353    Namval_t * np2;
8354    int len;
8355
8356    cbDataAddrStr = nv_getv(np, fp);
8357    cbData = (XmListCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8358
8359    token = strtok(dupName, ".");
8360
8361    /* cbData can be NULL if invoked from XtCallCallbacks */
8362    if (cbData == NULL)
8363       np2 = CreateEmptyNameValuePair(np, token, fp);
8364    else if (strcmp(token, "REASON") == 0)
8365       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8366    else if (strcmp(token, "EVENT") == 0)
8367       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8368    else if (strcmp(token, "ITEM") == 0)
8369       np2 = ProcessXmStringValue(cbData->item, np, token, fp);
8370    else if (strcmp(token, "ITEM_LENGTH") == 0)
8371    {
8372       if ((p = XmStringToString(cbData->item)) == NULL)
8373          len = 0;
8374       else
8375          len = strlen(p);
8376       np2 = ProcessIntValue(len, np, token, fp, "%d", NULL);
8377    }
8378    else if (strcmp(token, "ITEM_POSITION") == 0)
8379    {
8380       np2 = ProcessIntValue((int)cbData->item_position, np, token, fp, "%d", 
8381                             NULL);
8382    }
8383    else if (strcmp(token, "SELECTED_ITEMS") == 0)
8384    {
8385       if ((cbData->reason == XmCR_DEFAULT_ACTION) ||
8386           (cbData->reason == XmCR_MULTIPLE_SELECT) ||
8387           (cbData->reason == XmCR_EXTENDED_SELECT))
8388       {
8389          np2 = ProcessXmStringTable(cbData->selected_items,
8390                                      cbData->selected_item_count, 
8391                                      np, token, fp);
8392       }
8393       else
8394          np2 =  CreateEmptyNameValuePair(np, token, fp);
8395    }
8396    else if (strcmp(token, "SELECTED_ITEM_COUNT") == 0)
8397    {
8398       if ((cbData->reason == XmCR_DEFAULT_ACTION) ||
8399           (cbData->reason == XmCR_MULTIPLE_SELECT) ||
8400           (cbData->reason == XmCR_EXTENDED_SELECT))
8401       {
8402          np2 = ProcessIntValue((int)cbData->selected_item_count, np, token, 
8403                                 fp, "%d", NULL);
8404       }
8405       else
8406          np2 =  CreateEmptyNameValuePair(np, token, fp);
8407    }
8408    else if (strcmp(token, "SELECTED_ITEM_POSITIONS") == 0)
8409    {
8410       if ((cbData->reason == XmCR_DEFAULT_ACTION) ||
8411           (cbData->reason == XmCR_MULTIPLE_SELECT) ||
8412           (cbData->reason == XmCR_EXTENDED_SELECT))
8413       {
8414          np2 = ProcessIntTable(cbData->selected_item_positions,
8415                                 cbData->selected_item_count,
8416                                 np, token, fp);
8417       }
8418       else
8419          np2 =  CreateEmptyNameValuePair(np, token, fp);
8420    }
8421    else if (strcmp(token, "SELECTION_TYPE") == 0)
8422    {
8423       if (cbData->reason == XmCR_EXTENDED_SELECT)
8424          np2 = ProcessSelectionType(cbData->selection_type, np, token, fp);
8425       else
8426          np2 =  CreateEmptyNameValuePair(np, token, fp);
8427    }
8428    else
8429       np2 =  CreateEmptyNameValuePair(np, token, fp);
8430
8431    XtFree(dupName);
8432    return(np2);
8433 }
8434
8435 /* 
8436  * This is the 'create' discipline function for the pushbutton widget. 
8437  * This handles the XmPushButtonCallbackStruct.
8438  */
8439 Namval_t *
8440 pbtnCreateDisc(
8441         Namval_t *np,
8442         char *name,
8443         Namfun_t *fp )
8444 {
8445    char * cbDataAddrStr;
8446    XmPushButtonCallbackStruct * cbData;
8447    char * p;
8448    char * token;
8449    char * dupName = strdup(name);
8450    Namval_t * np2;
8451
8452    cbDataAddrStr = nv_getv(np, fp);
8453    cbData = (XmPushButtonCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8454
8455    token = strtok(dupName, ".");
8456
8457    /* cbData can be NULL if invoked from XtCallCallbacks */
8458    if (cbData == NULL)
8459       np2 = CreateEmptyNameValuePair(np, token, fp);
8460    else if (strcmp(token, "REASON") == 0)
8461       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8462    else if (strcmp(token, "EVENT") == 0)
8463       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8464    else if (strcmp(token, "CLICK_COUNT") == 0)
8465    {
8466       if (cbData->reason == XmCR_ACTIVATE)
8467       {
8468          np2 = ProcessIntValue((int)cbData->click_count, np, token, fp, "%d", 
8469                                NULL);
8470       }
8471       else
8472          np2 = CreateEmptyNameValuePair(np, token, fp);
8473    }
8474    else
8475       np2 = CreateEmptyNameValuePair(np, token, fp);
8476
8477    XtFree(dupName);
8478    return(np2);
8479 }
8480
8481 /* 
8482  * This is the 'create' discipline function for the rowcolumn widget. 
8483  * This handles the XmRowColumnCallbackStruct.
8484  */
8485 Namval_t *
8486 rcCreateDisc(
8487         Namval_t *np,
8488         char *name,
8489         Namfun_t *fp )
8490 {
8491    char * cbDataAddrStr;
8492    XmRowColumnCallbackStruct * cbData;
8493    char * p;
8494    char * token;
8495    char * dupName = strdup(name);
8496    Namval_t * np2;
8497
8498    cbDataAddrStr = nv_getv(np, fp);
8499    cbData = (XmRowColumnCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8500
8501    token = strtok(dupName, ".");
8502
8503    /* cbData can be NULL if invoked from XtCallCallbacks */
8504    if (cbData == NULL)
8505       np2 = CreateEmptyNameValuePair(np, token, fp);
8506    else if (strcmp(token, "REASON") == 0)
8507    {
8508       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, 
8509                                   fp);
8510    }
8511    else if (strcmp(token, "EVENT") == 0)
8512       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8513    else if ((strcmp(token, "WIDGET") == 0) && 
8514             (cbData->reason == XmCR_ACTIVATE))
8515    {
8516       np2 = ProcessWidgetHandle(cbData->widget, np, token, fp);
8517    }
8518    else if ((strcmp(token, "DATA") == 0) && (cbData->reason == XmCR_ACTIVATE))
8519       np2 = ProcessIntValue((int)cbData->data, np, token, fp, "0x%x", NULL);
8520    else if ((strcmp(token, "CALLBACKSTRUCT") == 0) && 
8521             (cbData->reason == XmCR_ACTIVATE))
8522    {
8523       np2 = ProcessIntValue((int)cbData->callbackstruct, np, token,fp,"0x%x", 
8524                             NULL);
8525    }
8526    else
8527       np2 = CreateEmptyNameValuePair(np, token, fp);
8528
8529    XtFree(dupName);
8530    return(np2);
8531 }
8532
8533 /* 
8534  * This is the 'create' discipline function for the scrollbar widget. 
8535  * This handles the XmScrollBarCallbackStruct.
8536  */
8537 Namval_t *
8538 sbarCreateDisc(
8539         Namval_t *np,
8540         char *name,
8541         Namfun_t *fp )
8542 {
8543    char * cbDataAddrStr;
8544    XmScrollBarCallbackStruct * cbData;
8545    char * p;
8546    char * token;
8547    char * dupName = strdup(name);
8548    Namval_t * np2;
8549
8550    cbDataAddrStr = nv_getv(np, fp);
8551    cbData = (XmScrollBarCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8552
8553    token = strtok(dupName, ".");
8554
8555    /* cbData can be NULL if invoked from XtCallCallbacks */
8556    if (cbData == NULL)
8557       np2 = CreateEmptyNameValuePair(np, token, fp);
8558    else if (strcmp(token, "REASON") == 0)
8559       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8560    else if (strcmp(token, "EVENT") == 0)
8561       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8562    else if (strcmp(token, "VALUE") == 0)
8563       np2 = ProcessIntValue((int)cbData->value, np, token, fp, "%d", NULL);
8564    else if (strcmp(token, "PIXEL") == 0)
8565    {
8566       if ((cbData->reason == XmCR_TO_BOTTOM) || (cbData->reason == XmCR_TO_TOP))
8567          np2 = ProcessIntValue((int)cbData->pixel, np, token,fp,"%d", NULL);
8568       else
8569          np2 = CreateEmptyNameValuePair(np, token, fp);
8570    }
8571    else
8572       np2 = CreateEmptyNameValuePair(np, token, fp);
8573
8574    XtFree(dupName);
8575    return(np2);
8576 }
8577
8578 /* 
8579  * This is the 'create' discipline function for the scrolledwindow widget. 
8580  * This handles the XmTraverseObsuredCallbackStruct.
8581  */
8582 Namval_t *
8583 swinCreateDisc(
8584         Namval_t *np,
8585         char *name,
8586         Namfun_t *fp )
8587 {
8588    char * cbDataAddrStr;
8589    XmTraverseObscuredCallbackStruct * cbData;
8590    char * token;
8591    char * p;
8592    char * dupName = strdup(name);
8593    Namval_t * np2;
8594
8595    cbDataAddrStr = nv_getv(np, fp);
8596    cbData = (XmTraverseObscuredCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8597
8598    token = strtok(dupName, ".");
8599
8600    /* cbData can be NULL if invoked from XtCallCallbacks */
8601    if (cbData == NULL)
8602       np2 = CreateEmptyNameValuePair(np, token, fp);
8603    else if (strcmp(token, "REASON") == 0)
8604       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8605    else if (strcmp(token, "EVENT") == 0)
8606       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8607    else if (strcmp(token, "TRAVERSAL_DESTINATION") == 0)
8608       np2 = ProcessWidgetHandle(cbData->traversal_destination, np, token, fp);
8609    else if (strcmp(token, "DIRECTION") == 0)
8610       np2 = ProcessTraversalDirection(cbData->direction, np, token, fp);
8611    else
8612       np2 = CreateEmptyNameValuePair(np, token, fp);
8613
8614    XtFree(dupName);
8615    return(np2);
8616 }
8617
8618 /* 
8619  * This is the 'create' discipline function for the selection box widget. 
8620  * This handles the XmSelectionBoxCallbackStruct.
8621  */
8622 Namval_t *
8623 sboxCreateDisc(
8624         Namval_t *np,
8625         char *name,
8626         Namfun_t *fp )
8627 {
8628    char * cbDataAddrStr;
8629    XmSelectionBoxCallbackStruct * cbData;
8630    char * p;
8631    char * token;
8632    char * dupName = strdup(name);
8633    Namval_t * np2;
8634    int len;
8635
8636    cbDataAddrStr = nv_getv(np, fp);
8637    cbData = (XmSelectionBoxCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8638
8639    token = strtok(dupName, ".");
8640
8641    /* cbData can be NULL if invoked from XtCallCallbacks */
8642    if (cbData == NULL)
8643       np2 = CreateEmptyNameValuePair(np, token, fp);
8644    else if (strcmp(token, "REASON") == 0)
8645       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8646    else if (strcmp(token, "EVENT") == 0)
8647       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8648    else if (strcmp(token, "VALUE") == 0)
8649       np2 = ProcessXmStringValue(cbData->value, np, token, fp);
8650    else if (strcmp(token, "LENGTH") == 0)
8651    {
8652       if ((p = XmStringToString(cbData->value)) == NULL)
8653          len = 0;
8654       else
8655          len = strlen(p);
8656       np2 = ProcessIntValue(len, np, token, fp, "%d", NULL);
8657    }
8658    else
8659       np2 = CreateEmptyNameValuePair(np, token, fp);
8660
8661    XtFree(dupName);
8662    return(np2);
8663 }
8664
8665 /* 
8666  * This is the 'create' discipline function for the toggle widget. 
8667  * This handles the XmToggleButtonCallbackStruct.
8668  */
8669 Namval_t *
8670 tbtnCreateDisc(
8671         Namval_t *np,
8672         char *name,
8673         Namfun_t *fp )
8674 {
8675    char * cbDataAddrStr;
8676    XmToggleButtonCallbackStruct * cbData;
8677    char * p;
8678    char * token;
8679    char * dupName = strdup(name);
8680    Namval_t * np2;
8681
8682    cbDataAddrStr = nv_getv(np, fp);
8683    cbData = (XmToggleButtonCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8684
8685    token = strtok(dupName, ".");
8686
8687    /* cbData can be NULL if invoked from XtCallCallbacks */
8688    if (cbData == NULL)
8689       np2 = CreateEmptyNameValuePair(np, token, fp);
8690    else if (strcmp(token, "REASON") == 0)
8691       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8692    else if (strcmp(token, "EVENT") == 0)
8693       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8694    else if (strcmp(token, "SET") == 0)
8695       np2 = ProcessBooleanIntValue((int)cbData->set, np, token, fp, NULL);
8696    else
8697       np2 = CreateEmptyNameValuePair(np, token, fp);
8698
8699    XtFree(dupName);
8700    return(np2);
8701 }
8702
8703 /* 
8704  * This is one ofthe 'create' discipline function for the text widget. 
8705  * This handles the XmTextVerifyCallbackStruct.  If a subfield can
8706  * be altered by a shell script (i.e. CB_CALL_DATA.TEXT.PTR), then
8707  * we must assign a discipline to the 'PTR' environment variable,
8708  * so that we will be notified when the assignment occurs, and thus
8709  * can update the real callback structure.
8710  */
8711 Namval_t *
8712 textCreateDisc(
8713         Namval_t *np,
8714         char *name,
8715         Namfun_t *fp )
8716 {
8717    char * cbDataAddrStr;
8718    XmTextVerifyCallbackStruct * cbData;
8719    char * p;
8720    char * token;
8721    XrmValue f, t;
8722    char * value;
8723    char buf[25];
8724    char * dupName = strdup(name);
8725    Namval_t * np2;
8726
8727    cbDataAddrStr = nv_getv(np, fp);
8728    cbData = (XmTextVerifyCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8729
8730    token = strtok(dupName, ".");
8731
8732    /* cbData can be NULL if invoked from XtCallCallbacks */
8733    if (cbData == NULL)
8734       np2 = CreateEmptyNameValuePair(np, token, fp);
8735    else if (strcmp(token, "REASON") == 0)
8736       np2 = ProcessCallbackReason((XmAnyCallbackStruct *)cbData, np, token, fp);
8737    else if (strcmp(token, "EVENT") == 0)
8738       np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
8739    else if (strcmp(token, "DOIT") == 0)
8740    {
8741       static Namfun_t * disc = NULL;
8742
8743       if (disc == NULL)
8744         disc = CloneDiscipline(&text_doit_disc);
8745
8746       np2 = ProcessBooleanIntValue((int)cbData->doit, np, token, fp, disc);
8747    }
8748    else if (strcmp(token, "CURRINSERT") == 0)
8749       np2 = ProcessIntValue((int)cbData->currInsert, np, token, fp, "%d", NULL);
8750    else if (strcmp(token, "NEWINSERT") == 0)
8751       np2 = ProcessIntValue((int)cbData->newInsert, np, token, fp, "%d", NULL);
8752    else if (strcmp(token, "STARTPOS") == 0)
8753    {
8754       static Namfun_t * disc = NULL;
8755
8756       if (disc == NULL)
8757         disc = CloneDiscipline(&text_startpos_disc);
8758
8759       if ((cbData->reason == XmCR_LOSING_FOCUS) ||
8760           (cbData->reason == XmCR_MODIFYING_TEXT_VALUE))
8761       {
8762          np2 = ProcessIntValue((int)cbData->startPos, np, token, fp,"%d", disc);
8763       }
8764       else
8765          np2 = CreateEmptyNameValuePair(np, token, fp);
8766    }
8767    else if (strcmp(token, "ENDPOS") == 0)
8768    {
8769       static Namfun_t * disc = NULL;
8770
8771       if (disc == NULL)
8772         disc = CloneDiscipline(&text_endpos_disc);
8773
8774       if ((cbData->reason == XmCR_LOSING_FOCUS) ||
8775           (cbData->reason == XmCR_MODIFYING_TEXT_VALUE))
8776       {
8777          np2 = ProcessIntValue((int)cbData->endPos, np, token, fp, "%d", disc);
8778       }
8779       else
8780          np2 = CreateEmptyNameValuePair(np, token, fp);
8781    }
8782    else if (strcmp(token, "TEXT") == 0)
8783    {
8784       if (cbData->reason == XmCR_MODIFYING_TEXT_VALUE)
8785       {
8786          np2 = GetNameValuePair(token);
8787          sprintf(buf, "0x%lx", (long)cbData->text);
8788          nv_putval(np2, buf, NV_RDONLY);
8789
8790          /* Need to handle the substructure fields */
8791          if (token = strtok(NULL, "."))
8792          {
8793             np2 = GetNameValuePair(token);
8794             if (strcmp(token, "PTR") == 0)
8795             {
8796                static Namfun_t * disc = NULL;
8797
8798                if (disc == NULL)
8799                  disc = CloneDiscipline(&text_ptr_disc);
8800
8801                /* Any old disciplies MUST be cleared, before setting value */
8802                nv_stack(np2, NULL);
8803                if (cbData->text->ptr)
8804                   nv_putval(np2, cbData->text->ptr, NV_RDONLY);
8805                else
8806                   nv_putval(np2, str_nill, NV_RDONLY);
8807                nv_stack(np2, disc);
8808             }
8809             else if (strcmp(token, "LENGTH") == 0)
8810             {
8811                static Namfun_t * disc = NULL; 
8812
8813                if (disc == NULL)
8814                  disc = CloneDiscipline(&text_len_disc);
8815
8816                /* Any old disciplies MUST be cleared, before setting value */
8817                sprintf(buf, "%d", cbData->text->length);
8818                nv_stack(np2, NULL);
8819                nv_putval(np2, buf, NV_RDONLY);
8820                nv_stack(np2, disc);
8821             }
8822             else if (strcmp(token, "FORMAT") == 0)
8823             {
8824                static Namfun_t * disc = NULL;
8825
8826                if (disc == NULL)
8827                  disc = CloneDiscipline(&text_format_disc);
8828
8829                f.addr = (caddr_t)&(cbData->text->format);
8830                f.size = sizeof(XmTextFormat);
8831                t.addr = NULL;
8832                t.size = 0;
8833                XtConvert(Toplevel, "TextFormat", &f, XtRString, &t);
8834   
8835                /* Any old disciplies MUST be cleared, before setting value */
8836                if (t.size && t.addr)
8837                   value = t.addr;
8838                else
8839                   value = str_nill;
8840                nv_stack(np2, NULL);
8841                nv_putval(np2, value, NV_RDONLY);
8842                nv_stack(np2, disc);
8843             }
8844             else
8845                nv_putval(np2, str_nill, NV_RDONLY);
8846
8847             /* No deeper nesting is supported */
8848             if (token = strtok(NULL, "."))
8849                np2 = CreateEmptyNameValuePair(np, token, fp);
8850          }
8851       }
8852       else
8853          np2 = CreateEmptyNameValuePair(np, token, fp);
8854    }
8855    else
8856       np2 = CreateEmptyNameValuePair(np, token, fp);
8857
8858    XtFree(dupName);
8859    return(np2);
8860 }
8861
8862 /* 
8863  * This is one ofthe 'create' discipline function for the text widget. 
8864  * This handles the XmTextVerifyCallbackStructWcs.
8865  */
8866 Namval_t *
8867 textCreateDisc2(
8868         Namval_t *np,
8869         char *name,
8870         Namfun_t *fp )
8871 {
8872    char * cbDataAddrStr;
8873    XmTextVerifyCallbackStructWcs * cbData;
8874    char * p;
8875    char * token;
8876    Namval_t * np2;
8877    char * nameCopy = strdup(name);
8878    char * dupName = strdup(name);
8879    char buf[25];
8880
8881    cbDataAddrStr = nv_getv(np, fp);
8882    cbData = (XmTextVerifyCallbackStructWcs *)strtoul(cbDataAddrStr, &p, 0);
8883
8884    token = strtok(dupName, ".");
8885
8886    /* cbData can be NULL if invoked from XtCallCallbacks */
8887    if (cbData == NULL)
8888       np2 = CreateEmptyNameValuePair(np, token, fp);
8889    else if (strcmp(token, "TEXT") == 0)
8890    {
8891       np2 = GetNameValuePair(token);
8892       sprintf(buf, "0x%lx", (long)cbData->text);
8893       nv_putval(np2, buf, NV_RDONLY);
8894
8895       /* Need to handle the substructure fields */
8896       if (token = strtok(NULL, "."))
8897       {
8898          np2 = GetNameValuePair(token);
8899          if (strcmp(token, "WCSPTR") == 0)
8900          {
8901             static Namfun_t * disc = NULL;
8902
8903             if (disc == NULL)
8904               disc = CloneDiscipline(&text_wcsptr_disc);
8905
8906             /* Any old disciplies MUST be cleared, before setting value */
8907             nv_stack(np2, NULL);
8908             if (cbData->text->wcsptr)
8909             {
8910                wchar_t * wcBuf;
8911                char * mbBuf;
8912                int mbBufSize;
8913                int count, i;
8914
8915                /* 
8916                 * It appears that the wchar string coming in is NOT NULL
8917                 * terminated; we must make our own copy, before calling
8918                 * wcstombs().
8919                 */
8920                wcBuf = (wchar_t *)XtMalloc((cbData->text->length + 1) * 
8921                                            sizeof(wchar_t));
8922                for ( i = 0; i < cbData->text->length; i++)
8923                   wcBuf[i] = cbData->text->wcsptr[i];
8924                wcBuf[i] = 0;
8925
8926                mbBufSize = ((cbData->text->length + 1) * sizeof(wchar_t));
8927                mbBuf = XtMalloc(mbBufSize);
8928                count = wcstombs(mbBuf, wcBuf, mbBufSize - sizeof(wchar_t));
8929                if (count >= 0)
8930                {
8931                   mbBuf[count] = '\0';
8932                   nv_putval(np2, mbBuf, NV_RDONLY);
8933                }
8934                else
8935                   nv_putval(np2, str_nill, NV_RDONLY);
8936                XtFree(mbBuf);
8937                XtFree((char *)wcBuf);
8938             }
8939             else
8940                nv_putval(np2, str_nill, NV_RDONLY);
8941             nv_stack(np2, disc);
8942          }
8943          else if (strcmp(token, "LENGTH") == 0)
8944          {
8945             static Namfun_t * disc = NULL; 
8946
8947             if (disc == NULL)
8948               disc = CloneDiscipline(&text_wcslen_disc);
8949
8950             /* Any old disciplies MUST be cleared, before setting value */
8951             sprintf(buf, "%d", cbData->text->length);
8952             nv_stack(np2, NULL);
8953             nv_putval(np2, buf, NV_RDONLY);
8954             nv_stack(np2, disc);
8955          }
8956          else
8957             nv_putval(np2, str_nill, NV_RDONLY);
8958
8959          /* No deeper nesting is supported */
8960          if (token = strtok(NULL, "."))
8961             np2 = CreateEmptyNameValuePair(np, token, fp);
8962       }
8963    }
8964    else
8965       np2 = textCreateDisc(np, nameCopy, fp);
8966
8967    XtFree(nameCopy);
8968    XtFree(dupName);
8969    return(np2);
8970 }
8971
8972 /* 
8973  * This is the 'create' discipline function for the help widget. 
8974  * This handles the DtHelpDialogCallbackStruct.
8975  */
8976 Namval_t *
8977 helpCreateDisc(
8978         Namval_t *np,
8979         char *name,
8980         Namfun_t *fp )
8981 {
8982    char * cbDataAddrStr;
8983    DtHelpDialogCallbackStruct * cbData;
8984    char * p;
8985    char * token;
8986    char * dupName = strdup(name);
8987    Namval_t * np2;
8988
8989    cbDataAddrStr = nv_getv(np, fp);
8990    cbData = (DtHelpDialogCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
8991
8992    token = strtok(dupName, ".");
8993
8994    /* cbData can be NULL if invoked from XtCallCallbacks */
8995    if (cbData == NULL)
8996       np2 = CreateEmptyNameValuePair(np, token, fp);
8997    else if (strcmp(token, "REASON") == 0)
8998    {
8999       /*
9000        * Can't use the normal callback reason function, since the help
9001        * callback reasons are not unique!  They overlap with the normal
9002        * callback reasons.
9003        */
9004       np2 = ProcessHelpCallbackReason((XmAnyCallbackStruct *)cbData, np, 
9005                                       token, fp);
9006    }
9007    else if (strcmp(token, "EVENT") == 0)
9008    {
9009       if (cbData->event)
9010          np2 = ProcessCallbackEvent(cbData->event, np, token, fp);
9011       else
9012          np2 = CreateEmptyNameValuePair(np, token, fp);
9013    }
9014    else if (strcmp(token, "LOCATIONID") == 0)
9015    {
9016       if (cbData->reason == DtCR_HELP_LINK_ACTIVATE)
9017          np2 = ProcessStringValue(cbData->locationId, np, token, fp);
9018       else
9019          np2 = CreateEmptyNameValuePair(np, token, fp);
9020    }
9021    else if (strcmp(token, "HELPVOLUME") == 0)
9022    {
9023       if (cbData->reason == DtCR_HELP_LINK_ACTIVATE)
9024          np2 = ProcessStringValue(cbData->helpVolume, np, token, fp);
9025       else
9026          np2 = CreateEmptyNameValuePair(np, token, fp);
9027    }
9028    else if (strcmp(token, "SPECIFICATION") == 0)
9029    {
9030       if (cbData->reason == DtCR_HELP_LINK_ACTIVATE)
9031          np2 = ProcessStringValue(cbData->specification, np, token, fp);
9032       else
9033          np2 = CreateEmptyNameValuePair(np, token, fp);
9034    }
9035    else if (strcmp(token, "HYPERTYPE") == 0)
9036    {
9037       if (cbData->reason == DtCR_HELP_LINK_ACTIVATE)
9038          np2 = ProcessHyperType(cbData->hyperType, np, token, fp);
9039       else
9040          np2 = CreateEmptyNameValuePair(np, token, fp);
9041    }
9042    else
9043       np2 = CreateEmptyNameValuePair(np, token, fp);
9044
9045    XtFree(dupName);
9046    return(np2);
9047 }
9048
9049 /* 
9050  * This is the 'DtPrintSetupProc' discipline function for the DtPrintSetupBox
9051  * widget. It handles the DtPrintSetupData struct with the exception of the
9052  * print_display and print_screen members.
9053  */
9054 Namval_t *
9055 dtPrintSetupProcDisc(
9056         Namval_t *np,
9057         char *name,
9058         Namfun_t *fp )
9059 {
9060    char * cbDataAddrStr;
9061    DtPrintSetupData * cbData;
9062    char * p;
9063    char * token;
9064    char * dupName = strdup(name);
9065    Namval_t * np2;
9066
9067    cbDataAddrStr = nv_getv(np, fp);
9068    cbData = (DtPrintSetupData *)strtoul(cbDataAddrStr, &p, 0);
9069
9070    token = strtok(dupName, ".");
9071
9072    if (cbData == NULL)
9073       np2 = CreateEmptyNameValuePair(np, token, fp);
9074    else if (strcmp(token, "PRINTER_NAME") == 0)
9075       np2 = ProcessStringValue(cbData->printer_name, np, token, fp);
9076    else if (strcmp(token, "DESTINATION") == 0)
9077       np2 = ProcessIntValue(cbData->destination, np, token, fp, "%d", NULL);
9078    else if (strcmp(token, "DEST_INFO") == 0)
9079       np2 = ProcessStringValue(cbData->dest_info, np, token, fp);
9080    else
9081       np2 = CreateEmptyNameValuePair(np, token, fp);
9082
9083    XtFree(dupName);
9084    return(np2);
9085 }
9086
9087
9088 /****************************************************************************
9089  *
9090  * The following functions are used to create and free a copy of a
9091  * discipline structure.  We register a discipline when we want to
9092  * be notified that the shell script has referenced one of our special
9093  * environment variables.  This gives us the ability to dynamically
9094  * assign the value they will receive.  This is used during callback,
9095  * translation and event handling (i.e. CB_CALL_DATA, etc).  We need
9096  * to duplicate the discipline structure due to how ksh handles these
9097  * structures; it stores each successive one in a linked list.  Typically,
9098  * this is not a problem.  However, because callbacks can become nested
9099  * (From within one callback, the script does something which causes another
9100  * callback to fire), if the same discipline structure gets passed in twice,
9101  * when it gets added to the linked list, the original 'next' pointer gets
9102  * trashed; the typical result is that the next time one of the special
9103  * environment variables is referenced, dtksh goes into an infinite loop.
9104  * The solution appears to be to 'clone' the discipline, thus creating
9105  * a unique structure each time, and preventing the 'next' pointer from
9106  * getting trashed.
9107  *
9108  **************************************************************************/
9109
9110 static Namfun_t *
9111 CloneDiscipline(
9112         Namdisc_t * discipline )
9113 {
9114    Namfun_t * clonedDisc;
9115
9116    clonedDisc = (Namfun_t *)XtMalloc(sizeof(Namfun_t));
9117    clonedDisc->disc = discipline;
9118    clonedDisc->next = NULL;
9119    return(clonedDisc);
9120 }
9121
9122
9123 static void
9124 FreeDiscipline(
9125         Namfun_t * discipline )
9126 {
9127    XtFree((char *)discipline);
9128 }
9129
9130
9131 void
9132 SetTextDoit(
9133         Namval_t *np,
9134         char *name,
9135         Namfun_t *fp )
9136 {
9137    XrmValue fval, tval;
9138    Boolean doit = True;
9139    char * cbDataAddrStr;
9140    XmTextVerifyCallbackStruct * cbData;
9141    char * p;
9142    Namval_t *cbDataNp;
9143
9144    /* Convert from string to a boolean */
9145    fval.addr = name;
9146    fval.size = strlen(name);
9147    XtConvert(Toplevel, XtRString, &fval, XtRBoolean, &tval);
9148
9149    if (tval.size != 0)
9150       doit = *((Boolean *)(tval.addr));
9151
9152    if (cbDataNp = nv_open("CB_CALL_DATA", sh.var_tree, 0))
9153    {
9154       cbDataAddrStr = nv_getv(cbDataNp, NULL);
9155       cbData=(XmTextVerifyCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
9156       cbData->doit = doit;
9157    }
9158 }
9159
9160 void
9161 SetTextStartPos(
9162         Namval_t *np,
9163         char *name,
9164         Namfun_t *fp )
9165 {
9166    char * cbDataAddrStr;
9167    XmTextVerifyCallbackStruct * cbData;
9168    char * p;
9169    Namval_t *cbDataNp;
9170
9171    if (cbDataNp = nv_open("CB_CALL_DATA", sh.var_tree, 0))
9172    {
9173       cbDataAddrStr = nv_getv(cbDataNp, NULL);
9174       cbData=(XmTextVerifyCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
9175       cbData->startPos = strtoul(name, &p, 0);
9176    }
9177 }
9178
9179 void
9180 SetTextEndPos(
9181         Namval_t *np,
9182         char *name,
9183         Namfun_t *fp )
9184 {
9185    char * cbDataAddrStr;
9186    XmTextVerifyCallbackStruct * cbData;
9187    char * p;
9188    Namval_t *cbDataNp;
9189
9190    if (cbDataNp = nv_open("CB_CALL_DATA", sh.var_tree, 0))
9191    {
9192       cbDataAddrStr = nv_getv(cbDataNp, NULL);
9193       cbData=(XmTextVerifyCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
9194       cbData->endPos = strtoul(name, &p, 0);
9195    }
9196 }
9197
9198 void
9199 SetTextPtr(
9200         Namval_t *np,
9201         char *name,
9202         Namfun_t *fp )
9203 {
9204    char * cbDataAddrStr;
9205    XmTextVerifyCallbackStruct * cbData;
9206    char * p;
9207    Namval_t *cbDataNp;
9208    static char * staticBuf = NULL;
9209
9210    if (cbDataNp = nv_open("CB_CALL_DATA", sh.var_tree, 0))
9211    {
9212       cbDataAddrStr = nv_getv(cbDataNp, NULL);
9213       cbData=(XmTextVerifyCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
9214
9215       /* fdt
9216        * MOTIF BUG ALERT!!
9217        * Motif will not currently free the original buffer,
9218        * but will instead free our buffer.
9219        *
9220        * XtFree(staticBuf);
9221        */
9222       staticBuf = strdup(name);
9223       cbData->text->ptr = staticBuf;
9224    }
9225 }
9226
9227 void
9228 SetTextLen(
9229         Namval_t *np,
9230         char *name,
9231         Namfun_t *fp )
9232 {
9233    char * cbDataAddrStr;
9234    XmTextVerifyCallbackStruct * cbData;
9235    char * p;
9236    Namval_t *cbDataNp;
9237
9238    if (cbDataNp = nv_open("CB_CALL_DATA", sh.var_tree, 0))
9239    {
9240       cbDataAddrStr = nv_getv(cbDataNp, NULL);
9241       cbData=(XmTextVerifyCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
9242       cbData->text->length = strtoul(name, &p, 0);
9243    }
9244 }
9245
9246 void
9247 SetTextFormat(
9248         Namval_t *np,
9249         char *name,
9250         Namfun_t *fp )
9251 {
9252    XrmValue fval, tval;
9253    Boolean doit = True;
9254    char * cbDataAddrStr;
9255    XmTextVerifyCallbackStruct * cbData;
9256    char * p;
9257    Namval_t *cbDataNp;
9258
9259    /* Convert from string to format type */
9260    fval.addr = name;
9261    fval.size = strlen(name);
9262    XtConvert(Toplevel, XtRString, &fval, "TextFormat", &tval);
9263
9264    if (tval.size && tval.addr &&
9265       (cbDataNp = nv_open("CB_CALL_DATA", sh.var_tree, 0)))
9266    {
9267       cbDataAddrStr = nv_getv(cbDataNp, NULL);
9268       cbData=(XmTextVerifyCallbackStruct *)strtoul(cbDataAddrStr, &p, 0);
9269       cbData->text->format = *((int *)(tval.addr));
9270    }
9271 }
9272
9273 void
9274 SetTextWCSptr(
9275         Namval_t *np,
9276         char *name,
9277         Namfun_t *fp )
9278 {
9279    char * cbDataAddrStr;
9280    XmTextVerifyCallbackStructWcs * cbData;
9281    char * p;
9282    Namval_t *cbDataNp;
9283    static wchar_t * wcBuf = NULL;
9284    int count;
9285
9286    if (cbDataNp = nv_open("CB_CALL_DATA", sh.var_tree, 0))
9287    {
9288       cbDataAddrStr = nv_getv(cbDataNp, NULL);
9289       cbData=(XmTextVerifyCallbackStructWcs *)strtoul(cbDataAddrStr, &p, 0);
9290
9291       /* fdt
9292        * MOTIF BUG ALERT!!
9293        * Motif will not currently free the original buffer,
9294        * but will instead free our buffer.
9295        *
9296        * XtFree(wcBuf);
9297        */
9298       wcBuf = (wchar_t *)XtMalloc((strlen(name) + 1) * sizeof(wchar_t));
9299       count = mbstowcs(wcBuf, name, strlen(name)+1);
9300       cbData->text->wcsptr = wcBuf;
9301    }
9302 }
9303
9304 void
9305 SetTextWCSlen(
9306         Namval_t *np,
9307         char *name,
9308         Namfun_t *fp )
9309 {
9310    char * cbDataAddrStr;
9311    XmTextVerifyCallbackStructWcs * cbData;
9312    char * p;
9313    Namval_t *cbDataNp;
9314
9315    if (cbDataNp = nv_open("CB_CALL_DATA", sh.var_tree, 0))
9316    {
9317       cbDataAddrStr = nv_getv(cbDataNp, NULL);
9318       cbData=(XmTextVerifyCallbackStructWcs *)strtoul(cbDataAddrStr, &p, 0);
9319       cbData->text->length = strtoul(name, &p, 0);
9320    }
9321 }
9322
9323 /*
9324  * stdPrintSetupProc() is the central routine from which the DtPrintSetupBox
9325  * widget's DtPrintSetupProc resources are dispatched.
9326  * The variable "CB_WIDGET" will be placed in the environment to represent
9327  * the CallBackWidget handle.  Because DtPrintSetupProc doesn't work the
9328  * same way as a callback, we had to fudge this to work by storing the command
9329  * string inside the widget's wtab_t->info field.  This is pretty nasty and
9330  * non-generic, but there does not appear to be a good solution.
9331  *
9332  * The call_data is made available through the CD_CALL_DATA variable.
9333  *
9334  * If a new DtPrintSetupProc resource needs to be supported, the list of
9335  * hardcoded procs and associated information have to be updated, as follows:
9336  * - add a #define of the resource in dtksh.h
9337  * - add a new member in the ProcInfo_t to store that command in dtksh.h.
9338  * - add a new function called std<resource_name> which calls
9339  * stdPrintSetupProc().
9340  * - add a new case to set the command to the above function for the new
9341  * resource in DtkshCvtStringToPrintSetupProc().
9342  * - add a new case in the switch statement this function to account for
9343  * the new resource.
9344  *
9345  */
9346
9347 void
9348 stdPrintSetupProc(
9349         int proctype,
9350         void  *widget,
9351         DtPrintSetupData *callData)
9352 {
9353         wtab_t *w;
9354         ProcInfo_t *pinfo;
9355         char buf[128];
9356         Namval_t *np;
9357         Namval_t *np2;
9358         WidgetClass class;
9359         Namdisc_t *discipline = NULL;
9360         char *oldCB_WIDGET_value = NULL;
9361         char *oldCB_CALL_DATA_value = NULL;
9362         char *ptr;
9363         Namfun_t *clonedDisc;
9364
9365         w = widget_to_wtab((Widget)widget);
9366         if (w == NULL)
9367                 return;
9368         pinfo = (ProcInfo_t *) w->info;
9369         if (pinfo == NULL)
9370                 return;
9371
9372         nestingLevel++;
9373         np2 = GetNameValuePair("CB_WIDGET");
9374         nv_newattr(np2, 0, 0);
9375         if (ptr = nv_getval(np2))
9376                 oldCB_WIDGET_value = strdup(ptr);
9377         nv_putval(np2, w->widid, NV_RDONLY);
9378         nv_newattr(np2, NV_RDONLY, 0);
9379
9380         sprintf(buf, "0x%lx", (long)callData);
9381
9382         np = GetNameValuePair("CB_CALL_DATA");
9383         nv_newattr(np, 0, 0);
9384         if (ptr = nv_getval(np))
9385                 oldCB_CALL_DATA_value = strdup(ptr);
9386         nv_putval(np, buf, NV_RDONLY);
9387         nv_newattr(np, NV_RDONLY, 0);
9388
9389         /* look up the discipline for DtPrintSetupProc */
9390         class = XtClass(w->w);
9391         while (class) {
9392                 if (discipline = CheckClassDisciplines(class, DtRPrintSetupProc))
9393                         break;
9394                 class = class->core_class.superclass;
9395         }
9396
9397    /* 
9398     * If a discipline was found, then use it; otherwise, we MUST set up
9399     * a default discipline; otherwise, any hierarchical variables 
9400     * referenced by the user are not under our control, thus never getting
9401     * freed up, and then also preventing future disciplines from getting
9402     * called when they should have.
9403     */
9404    if (discipline)
9405       clonedDisc = CloneDiscipline(discipline);
9406    else
9407       clonedDisc = CloneDiscipline(&dftDiscipline);
9408    nv_stack(np, clonedDisc);
9409
9410         switch (proctype) {
9411         case PRINTER_INFO_PROC:
9412                 ksh_eval(pinfo->printerInfoProcCommand);
9413                 break;
9414         case SELECT_FILE_PROC:
9415                 ksh_eval(pinfo->selectFileProcCommand);
9416                 break;
9417         case SELECT_PRINTER_PROC:
9418                 ksh_eval(pinfo->selectPrinterProcCommand);
9419                 break;
9420         case SETUP_PROC:
9421                 ksh_eval(pinfo->setupProcCommand);
9422                 break;
9423         case VERIFY_PRINTER_PROC:
9424                 ksh_eval(pinfo->verifyPrinterProcCommand);
9425                 break;
9426         }
9427
9428         /* We may be nested, so restore old CB_WIDGET & CB_CALL_DATA values */
9429         RestorePriorEnvVarValues(np2, oldCB_WIDGET_value, np, oldCB_CALL_DATA_value);
9430         XtFree(oldCB_WIDGET_value);
9431         XtFree(oldCB_CALL_DATA_value);
9432
9433         /* Remove the discipline for the hierarchical variables */
9434         nv_stack(np, NULL);
9435         FreeDiscipline(clonedDisc);
9436
9437         /* Free up all of the name/value pairs we created */
9438         FreeNestedVariables();
9439         nestingLevel--;
9440
9441         return;
9442 }
9443
9444 void
9445 stdPrinterInfoProc(
9446         void  *widget,
9447     DtPrintSetupData *callData)
9448 {
9449         stdPrintSetupProc(PRINTER_INFO_PROC, widget, callData);
9450         return;
9451 }
9452
9453 void
9454 stdSelectFileProc(
9455         void  *widget,
9456     DtPrintSetupData *callData)
9457 {
9458         stdPrintSetupProc(SELECT_FILE_PROC, widget, callData);
9459         return;
9460 }
9461
9462 void
9463 stdSelectPrinterProc(
9464         void  *widget,
9465     DtPrintSetupData *psd)
9466 {
9467         stdPrintSetupProc(SELECT_PRINTER_PROC, widget, psd);
9468         return;
9469 }
9470
9471 void
9472 stdSetupProc(
9473         void  *widget,
9474     DtPrintSetupData *callData)
9475 {
9476         stdPrintSetupProc(SETUP_PROC, widget, callData);
9477         return;
9478 }
9479
9480 void
9481 stdVerifyPrinterProc(
9482         void  *widget,
9483     DtPrintSetupData *callData)
9484 {
9485         stdPrintSetupProc(VERIFY_PRINTER_PROC, widget, callData);
9486         return;
9487 }
9488