dtcm: Resolve CID 87801
[oweals/cde.git] / cde / programs / dtterm / DtTermMain.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 librararies 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 #ifndef lint
24 #ifdef  VERBOSE_REV_INFO
25 static char rcs_id[] = "$TOG: DtTermMain.c /main/19 1999/09/17 13:26:34 mgreess $";
26 #endif  /* VERBOSE_REV_INFO */
27 #endif  /* lint */
28
29 /*                                                                      *
30  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
31  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
32  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
33  * (c) Copyright 1993, 1994 Novell, Inc.                                *
34  */
35
36 #ifdef sun
37 #include <dlfcn.h>
38 #endif /* sun */
39 #include "TermHeader.h"
40 #include "TermPrim.h"
41 #include "TermPrimDebug.h"
42 #include <fcntl.h>
43 #include <sys/types.h>
44 #include <sys/stat.h> 
45 #include <string.h>
46 #include <locale.h>
47 #include <ctype.h>
48 #include <signal.h>
49 #include <Xm/Form.h>
50 #include <Xm/TextF.h>
51 #include <Xm/PushBG.h>
52 #include <Xm/LabelG.h>
53 #include <Xm/Protocols.h>
54 #include <Xm/Display.h>
55 /*
56  * This for the sleazy hack to get the window manager frame width/height
57  */
58 #include <Xm/VendorSEP.h>
59 #define DEBUG_INCLUDES  /*DKS*/
60 #ifdef  DEBUG_INCLUDES
61 #include "TermPrimBufferP.h"
62 #include "TermPrimParserP.h"
63 #include "TermPrimPendingTextP.h"
64 #include "TermPrimSelectP.h"
65 #include "TermPrimP.h"
66 #include "TermPrimRenderP.h"
67 #include "TermPrimLineDrawP.h"
68 #include "TermPrimLineFontP.h"
69 #include "TermBufferP.h"
70 #include "TermP.h"
71 #include "TermParseTableP.h"
72 #include "TermFunction.h"
73 /* #include "TermFunctionKeyP.h" */
74 #include "TermViewP.h"
75 #endif  /* DEBUG_INCLUDES */
76 #include "TermPrim.h"
77 #include "TermView.h"
78 #include "TermViewMenu.h"
79 #include "DtTermMain.h"
80 #include "DtTermSyntax.h"
81 #ifdef  TERMINAL_SERVER
82 #include "DtTermServer.h"
83 #endif  /* TERMINAL_SERVER */
84 #include "TermPrimWMProtocols.h"
85 #include "TermPrimMessageCatI.h"
86 #ifdef  LOG_USAGE
87 #include "DtTermLogit.h"
88 #endif  /* LOG_USAGE */
89 #ifdef  HPVUE
90 #include <Xv/Session.h>
91 #include <Xv/EnvControl.h>
92 #define DtSessionSavePath       XvSessionSavePath 
93 #define DtSessionRestorePath    XvSessionRestorePath 
94 #define DtWsmGetWorkspacesOccupied XvGetWorkspacePresence
95 #define DtWsmSetWorkspacesOccupied XvSetWorkspaceHints
96 #else   /*  HPVUE */
97 #include <Dt/Dt.h>
98 #include <Dt/Wsm.h>
99 #include <Dt/EnvControlP.h>
100 #endif  /* HPVUE */ 
101
102 /* From Xm/BaseClassI.h */
103 extern XmWidgetExtData _XmGetWidgetExtData( 
104                         Widget widget,
105 #if NeedWidePrototypes
106                         unsigned int extType) ;
107 #else
108                         unsigned char extType) ;
109 #endif /* NeedWidePrototypes */
110
111 /* forward declarations... */
112 static void activateCallback(
113     Widget                w,
114     XtPointer             client_data,
115     XtPointer             call_data
116 );
117
118 static void ToggleMenuBar(
119     Widget                w,
120     XtPointer             client_data,
121     XtPointer             call_data
122 );
123
124 static void SaveSessionCB(
125         Widget w,                       
126         caddr_t client_data,    
127         caddr_t call_data );
128 static Boolean RestoreSession(
129         Widget topDog,
130         Arg *arglist,
131         int i);
132 static void SaveTerm(
133         DtTermViewWidget dtvw,
134         int cloneNum,
135         int fd);
136 static void RestoreTerm(
137         Widget shellWidget,
138         DtTermViewWidget dtvw,
139         int termNum,
140         XrmDatabase db);
141 static void SetWorkSpaceHints(
142         Widget shell,
143         char *workspaces );
144
145 static XtEventHandler TestProbeHandler(
146         Widget  w,
147         XtPointer       client_data,
148         XEvent          *event,
149         Boolean         *ctd);
150 static void RegisterTestProbe(
151     Widget                topLevel,
152     DtTermViewWidget      tw);
153
154 static char defaultIgnoredKeysyms[] = "\
155 <Key>F1\n\
156 <Key>F2\n\
157 <Key>F3\n\
158 <Key>F4\n\
159 <Key>F5\n\
160 <Key>F6\n\
161 <Key>F7\n\
162 <Key>F8\n\
163 <Key>F9\n\
164 <Key>F10\n\
165 <Key>F11\n\
166 <Key>F12\
167 ";
168
169 typedef struct _termattrs {
170         char    *debugString;
171         char    *ignoredKeysyms;
172         char    *session;
173         Boolean  loginShell;
174 #ifdef TERMINAL_SERVER
175         Boolean  block;
176         Boolean  exitOnLastClose;
177         Boolean  server;
178         char    *serverId;
179         Boolean  standAlone;
180         int      PingInterval;
181 #endif
182 #ifdef SUN_TERMINAL_SERVER
183        Boolean server;
184 #endif   
185         char *title;
186         char *icon_name;
187         char *dtterm_name;
188 } TERMATTRS;
189
190 #ifdef TERMINAL_SERVER
191 static TERMATTRS attrs = { NULL, defaultIgnoredKeysyms, NULL, False,
192                            TRUE, False, False, NULL, False, 5, NULL, NULL, NULL};
193 #elif SUN_TERMINAL_SERVER
194 static TERMATTRS attrs = { NULL, defaultIgnoredKeysyms, NULL, False, False, NULL, NULL, NULL};
195 #else
196 static TERMATTRS attrs = { NULL, defaultIgnoredKeysyms, NULL, False, NULL, NULL, NULL };
197 #endif
198
199 static Atom xa_MOTIF_WM_MESSAGES = None;
200 static Atom xa_DTTERM_TOGGLE_MENUBAR = None;
201 static Atom xa_DTTERM_TEST_PROBE_IDS = None;
202 static Atom xa_DTTERM_REMOTE_PROBE_REQUEST = None;
203 static Atom xa_WM_SAVE_YOURSELF;
204 static XtAppContext appContext;
205 static Widget topLevel;
206 static Widget topShell;
207 static char *title = NULL;
208 static DtTermViewWidget *instance_list = NULL;
209 static Boolean RestoringTerms = False;
210 static int  savedArgc = 0;
211 static char     **savedArgv = NULL;
212
213 #ifdef SUN_TERMINAL_SERVER
214 int InstanceCount = 0;
215 #else
216 #ifndef TERMINAL_SERVER
217 static int InstanceCount = 0;
218 #endif  /* TERMINAL_SERVER */
219 #endif /* SUN_TERMINAL_SERVER */
220
221 static const char _true[] = "true";
222 static const char _false[] = "false";
223
224 /* command line options...
225  */
226 static XrmOptionDescRec optionDescList[] = {
227 /* special (not end user) options...
228  */
229 {"-~",             "*debugLevel",       XrmoptionSepArg, (XtPointer) NULL},
230 {"-debugLevel",    "*debugLevel",       XrmoptionSepArg, (XtPointer) NULL},
231 {"-session",       "*session",          XrmoptionSepArg, (XtPointer) NULL},
232
233 #ifdef  TERMINAL_SERVER
234 /* server options...
235  */
236 {"-noBlocking",    "*blocking",         XrmoptionNoArg,  (XtPointer) _false},
237 {"-server",        "*server",           XrmoptionNoArg,  (XtPointer) _true},
238 {"-serverId",      "*serverId",         XrmoptionSepArg, (XtPointer) NULL},
239 #endif  /* TERMINAL_SERVER */
240 #ifdef  SUN_TERMINAL_SERVER
241 {"-dtserver",      "*server",           XrmoptionNoArg,  (XtPointer) _true},
242 {"-sdtserver",     "*server",           XrmoptionNoArg,  (XtPointer) _true},
243 #endif  /* SUN_TERMINAL_SERVER */
244
245 /* terminal emulation options...
246  */
247 {"-132",           "*c132",             XrmoptionNoArg,  (XtPointer) _true},
248 {"+132",           "*c132",             XrmoptionNoArg,  (XtPointer) _false},
249 {"-aw",            "*autoWrap",         XrmoptionNoArg,  (XtPointer) _true},
250 {"+aw",            "*autoWrap",         XrmoptionNoArg,  (XtPointer) _false},
251 {"-bs",            "*backgroundIsSelect",
252                                         XrmoptionNoArg,  (XtPointer) _true},
253 {"+bs",            "*backgroundIsSelect",
254                                         XrmoptionNoArg,  (XtPointer) _false},
255 {"-C",             "*consoleMode",      XrmoptionNoArg,  (XtPointer) _true},
256 {"-cc",            "*charClass",        XrmoptionSepArg, (XtPointer) NULL},
257 {"-cu",            "*curses",           XrmoptionNoArg,  (XtPointer) _true},
258 {"+cu",            "*curses",           XrmoptionNoArg,  (XtPointer) _false},
259 {"-e",             NULL,                XrmoptionSkipLine,
260                                                          (XtPointer) NULL},
261 {"-fb",            "*userBoldFont",     XrmoptionSepArg, (XtPointer) NULL},
262 {"-fn",            "*userFont",         XrmoptionSepArg, (XtPointer) NULL},
263 {"+iconic",        ".iconic",           XrmoptionNoArg,  (XtPointer) _false},
264 {"-j",             "*jumpScroll",       XrmoptionNoArg,  (XtPointer) _true},
265 {"+j",             "*jumpScroll",       XrmoptionNoArg,  (XtPointer) _false},
266 {"-kshMode",       "*kshMode",          XrmoptionNoArg,  (XtPointer) _true},
267 {"+kshMode",       "*kshMode",          XrmoptionNoArg,  (XtPointer) _false},
268 {"-l",             "*logging",          XrmoptionNoArg,  (XtPointer) _true},
269 {"+l",             "*logging",          XrmoptionNoArg,  (XtPointer) _false},
270 {"-lf",            "*logFile",          XrmoptionSepArg, (XtPointer) NULL},
271 {"-ls",            "*loginShell",       XrmoptionNoArg,  (XtPointer) _true},
272 {"+ls",            "*loginShell",       XrmoptionNoArg,  (XtPointer) _false},
273 {"-map",           "*mapOnOutput",      XrmoptionNoArg,  (XtPointer) _true},
274 {"+map",           "*mapOnOutput",      XrmoptionNoArg,  (XtPointer) _false},
275 {"-mb",            "*marginBell",       XrmoptionNoArg,  (XtPointer) _true},
276 {"+mb",            "*marginBell",       XrmoptionNoArg,  (XtPointer) _false},
277 {"-ms",            "*pointerColor",     XrmoptionSepArg, (XtPointer) NULL},
278 {"-n",             "*iconName",         XrmoptionSepArg, (XtPointer) NULL},
279 {"-nb",            "*nMarginBell",      XrmoptionSepArg, (XtPointer) NULL},
280 {"-rw",            "*reverseWrap",      XrmoptionNoArg,  (XtPointer) _true},
281 {"+rw",            "*reverseWrap",      XrmoptionNoArg,  (XtPointer) _false},
282 {"-sb",            "*scrollBar",        XrmoptionNoArg,  (XtPointer) _true},
283 {"+sb",            "*scrollBar",        XrmoptionNoArg,  (XtPointer) _false},
284 {"-sf",            "*sunFunctionKeys",  XrmoptionNoArg,  (XtPointer) _true},
285 {"+sf",            "*sunFunctionKeys",  XrmoptionNoArg,  (XtPointer) _false},
286 {"-si",            "*scrollTtyOutput",  XrmoptionNoArg,  (XtPointer) _true},
287 {"+si",            "*scrollTtyOutput",  XrmoptionNoArg,  (XtPointer) _false},
288 {"-sk",            "*scrollKey",        XrmoptionNoArg,  (XtPointer) _true},
289 {"+sk",            "*scrollKey",        XrmoptionNoArg,  (XtPointer) _false},
290 {"-sl",            "*saveLines",        XrmoptionSepArg, (XtPointer) NULL},
291 {"-ti",            "*termId",           XrmoptionSepArg, (XtPointer) NULL},
292 {"-tm",            "*ttyModes",         XrmoptionSepArg, (XtPointer) NULL},
293 {"-tn",            "*termName",         XrmoptionSepArg, (XtPointer) NULL},
294 {"-standAlone",    "*standAlone",       XrmoptionNoArg,  (XtPointer) _true},
295 {"-vb",            "*visualBell",       XrmoptionNoArg,  (XtPointer) _true},
296 {"+vb",            "*visualBell",       XrmoptionNoArg,  (XtPointer) _false},
297 /* legacy options that are ignored...
298  */
299 {"-ah",            NULL,                XrmoptionNoArg,  (XtPointer) _true},
300 {"+ah",            NULL,                XrmoptionNoArg,  (XtPointer) _false},
301 {"-b",             NULL,                XrmoptionSepArg, (XtPointer) NULL},
302 {"-cb",            NULL,                XrmoptionNoArg,  (XtPointer) _true},
303 {"+cb",            NULL,                XrmoptionNoArg,  (XtPointer) _false},
304 {"-cn",            NULL,                XrmoptionNoArg,  (XtPointer) _true},
305 {"+cn",            NULL,                XrmoptionNoArg,  (XtPointer) _false},
306 {"-cr",            NULL,                XrmoptionSepArg, (XtPointer) NULL},
307 {"-s",             NULL,                XrmoptionNoArg,  (XtPointer) _true},
308 {"+s",             NULL,                XrmoptionNoArg,  (XtPointer) _false},
309 {"-t",             NULL,                XrmoptionNoArg,  (XtPointer) _true},
310 {"+t",             NULL,                XrmoptionNoArg,  (XtPointer) _false},
311 {"-ut",            NULL,                XrmoptionNoArg,  (XtPointer) _true},
312 {"+ut",            NULL,                XrmoptionNoArg,  (XtPointer) _false},
313 {"-wf",            NULL,                XrmoptionNoArg,  (XtPointer) _true},
314 {"+wf",            NULL,                XrmoptionNoArg,  (XtPointer) _false},
315 };
316
317 /* application specific resources...
318  */
319 static XtResource applicationResources[] = {
320     {"debugLevel", "DebugLevel", XtRString, sizeof(char *),
321             XtOffsetOf(TERMATTRS, debugString), XtRImmediate, NULL},
322     {"ignoredKeysyms", "IgnoredKeysyms", XtRString, sizeof(char *),
323             XtOffsetOf(TERMATTRS, ignoredKeysyms), XtRImmediate, NULL},
324     {"loginShell", "LoginShell", XtRBoolean, sizeof(Boolean),
325             XtOffsetOf(TERMATTRS, loginShell), XtRString, "false"},
326     {"session", "Session", XtRString, sizeof(char *),
327             XtOffsetOf(TERMATTRS, session), XtRString, NULL},
328 #ifdef  TERMINAL_SERVER
329     {"blocking", "Blocking", XtRBoolean, sizeof(Boolean),
330             XtOffsetOf(TERMATTRS, block), XtRString, "true"},
331     {"exitOnLastClose", "ExitOnLastClose", XtRBoolean, sizeof(Boolean),
332             XtOffsetOf(TERMATTRS, exitOnLastClose), XtRString, "false"},
333     {"server", "Server", XtRBoolean, sizeof(Boolean),
334             XtOffsetOf(TERMATTRS, server), XtRString, "false"},
335     {"serverId", "ServerId", XtRString, sizeof(char *),
336             XtOffsetOf(TERMATTRS, serverId), XtRImmediate, NULL},
337     {"standAlone", "StandAlone", XtRBoolean, sizeof(Boolean),
338             XtOffsetOf(TERMATTRS, standAlone), XtRString, "false"},
339     {"pingInterval", "PingInterval", XtRInt, sizeof(int),
340             XtOffsetOf(TERMATTRS, PingInterval), XtRString, "5"},
341 #endif  /* TERMINAL_SERVER */
342 #ifdef  SUN_TERMINAL_SERVER
343     {"server", "Server", XtRBoolean, sizeof(Boolean),
344             XtOffsetOf(TERMATTRS, server), XtRString, "false"},
345 #endif  /* SUN_TERMINAL_SERVER */
346     {XtNtitle, XtCTitle, XtRString, sizeof(char *),
347         XtOffsetOf(TERMATTRS, title), XtRString, (caddr_t) NULL},
348     {XtNiconName, XtCIconName, XtRString, sizeof(char *),
349         XtOffsetOf(TERMATTRS, icon_name), XtRString, (caddr_t) NULL},
350     {"name", "Name", XtRString, sizeof(char *),
351         XtOffsetOf(TERMATTRS, dtterm_name), XtRString, (caddr_t) NULL},
352 };
353
354 extern String fallbackResources[];
355
356 #ifdef sun
357 void
358 sunSetupIA(Widget w)
359 {
360     int i, major_op, first_event, first_err;
361     int *pids;
362     void        (*IAptr)()=(void (*)())NULL;
363     DtTermPrimitiveWidget tw;
364
365     if ((IAptr = (void (*)())dlsym(RTLD_NEXT, "XSolarisIASetProcessInfo"))!=NULL) {
366         pids = (int *)malloc(sizeof(int) * (InstanceCount + 1));
367         pids[0] = getpid();
368         for (i = 0; i < InstanceCount; i++) {
369             tw = (DtTermPrimitiveWidget)instance_list[i]->termview.term;
370             pids[i + 1] = tw->term.subprocessPid;
371         }
372         if (XQueryExtension(XtDisplay(w), "SolarisIA",
373                         &major_op, &first_event, &first_err))
374             (*IAptr)(XtDisplay(w),pids,
375                  0x1,InstanceCount + 1);
376         free(pids);
377     }
378 }
379 #endif /* sun */
380
381 #ifdef  DELAY_DESTROY
382 static void
383 DestroyTree(XtPointer client_data, XtIntervalId *id)
384 {
385     (void) XtDestroyWidget((Widget) client_data);
386 }
387 #endif  /* DELAY_DESTROY */
388
389 /*ARGSUSED*/
390 static void
391 DestroyDtTerm(Widget w, XtPointer client_data, XtPointer call_data)
392 {
393     /* destroy the whole interface... */
394     (void) XtDestroyWidget((Widget) client_data);
395 }
396
397 /*ARGSUSED*/
398 static void
399 ExitTimeout(XtPointer client_data, XtIntervalId *id)
400 {
401     if (title) {
402       XtFree(title);
403     }
404     (void) exit(0);
405 }
406
407 /*ARGSUSED*/
408 static void
409 DecrementInstanceCountAndExit(Widget w, XtPointer client_data,
410         XtPointer call_data)
411 {
412     DtTermViewWidget *new_instance_list;
413     int i,j;
414     
415 /****************
416  *
417  * First, update the instance list cache by "deleting" the current instance
418  *
419  ****************/
420     InstanceCount--;
421     if (InstanceCount > 0)
422     {
423         new_instance_list = (DtTermViewWidget *)XtMalloc(sizeof(DtTermViewWidget *)*InstanceCount);
424         for (j = 0,i = 0; i < (InstanceCount+1); i++)
425             if (instance_list[i] != (DtTermViewWidget )w)
426             {
427                 new_instance_list[j] = instance_list[i];
428                 j++;
429             }
430         XtFree((char *)instance_list);
431         instance_list = new_instance_list;
432     }
433     else 
434         XtFree((char *)instance_list);
435                 
436     /* check off this instance... */
437 #ifdef  TERMINAL_SERVER
438     if (attrs.standAlone || !attrs.serverId) {
439 #endif  /* TERMINAL_SERVER */
440 #ifdef notdef
441     if (!attrs.server) {
442 #endif /* notdef */
443         if (InstanceCount <= 0) {
444             /* use a timeout so that the toolkit can finish killing off
445              * this widget...
446              */
447             (void) XtAppAddTimeOut(XtWidgetToApplicationContext(w), 0,
448                     ExitTimeout, (XtPointer) 0);
449         }
450 #ifdef  TERMINAL_SERVER
451     } else {
452         ServerInstanceTerminated((Widget) client_data);
453     }
454 #endif  /* TERMINAL_SERVER */
455 #ifdef  notdef
456     } else {
457         /* Here is where one would add the call into sunDtTermServer.c
458          * implement a "lurking" dtterm server. */
459     }
460 #endif  /* notdef */
461 }
462
463 /***************************************************************************
464  *                                                                         *
465  * RegisterTestProbe - shoves a property on the root window that says      *
466  * we're ready to be tested, and sets up the event handler for the client  *
467  * messages.                                                               *
468  *                                                                         *
469  ***************************************************************************/
470 static void RegisterTestProbe(
471     Widget                topLevel,
472     DtTermViewWidget      tw
473 )
474 {
475     Window win = XtWindow(topLevel);
476
477     if (xa_DTTERM_TEST_PROBE_IDS == None) 
478     {
479         xa_DTTERM_TEST_PROBE_IDS = XInternAtom(XtDisplay(topLevel),
480                 "_DTTERM_TEST_PROBE_IDS", False);
481     }
482     if (xa_DTTERM_REMOTE_PROBE_REQUEST == None) 
483     {
484         xa_DTTERM_REMOTE_PROBE_REQUEST = XInternAtom(XtDisplay(topLevel),
485                 "_DTTERM_REMOTE_PROBE_REQUEST", False);
486     }
487     
488     XChangeProperty(XtDisplay(topLevel), RootWindowOfScreen(XtScreen(topLevel)),
489                     xa_DTTERM_TEST_PROBE_IDS, xa_DTTERM_TEST_PROBE_IDS,
490                     32, PropModeReplace, (unsigned char *)&win, 1);
491     XtAddEventHandler(topLevel, NoEventMask , True, (XtEventHandler )TestProbeHandler, 
492                       (XtPointer )tw);
493 }
494
495 #define ONE_BYTE 0
496 #define TWO_BYTE 1
497 #define FOUR_BYTE 2
498 #define FOUR_BYTE_PTR 3
499 #define GET_USER_KEY_LOCK 4
500 #define GET_AUTO_LINE_FEED 5
501 #define GET_CURSOR_VISIBLE 6
502 #define GET_SCROLLBAR_WINDOW 7
503 /***************************************************************************
504  *                                                                         *
505  * TestProbeHandler - handle the client message for test probes            *
506  *                                                                         *
507  ***************************************************************************/
508 static XtEventHandler TestProbeHandler(
509         Widget  w,
510         XtPointer       client_data,
511         XEvent          *event,
512         Boolean         *ctd)
513 {
514     XClientMessageEvent *cm = (XClientMessageEvent *)event;
515     DtTermViewWidget tw = (DtTermViewWidget )client_data;
516     Window win;
517     Atom   prop_name, actual_type;
518     int    prop_type;           /* THIS WILL BREAK ON A 16-BIT INT SYSTEM */
519     int    actual_format;
520     long   offset, length;
521     unsigned long nitems, bytes_left;
522     unsigned char *data;
523     typedef union {
524         char c;
525         unsigned char uc;
526         int i;
527         short s;
528         char *cp;
529     } alltype;
530
531     alltype fourbyte;
532     alltype twobyte;
533     alltype onebyte;
534     unsigned char  *reply;
535     Arg   al[5];
536     
537     *ctd = True;
538     if (cm->send_event == False) return 0;
539     if (cm->message_type != xa_DTTERM_REMOTE_PROBE_REQUEST) return 0;
540     
541     reply = (unsigned char*) malloc(sizeof(unsigned char) * 1024);
542
543 /****************
544  *
545  * If it's a xa_DTTERM_REMOTE_PROBE_REQUEST, then the data is three 32-bit
546  * quantities: 0 is the window ID, 1 is the property atom to get off the
547  * window, and 2 is the number of bytes required to getvalues the requested 
548  *  data.
549  *
550  ****************/
551
552     *ctd = False;
553     win = cm->data.l[0];
554     prop_name = cm->data.l[1];  
555     prop_type = cm->data.l[2];
556     offset = 0;
557     length = 1000L;
558         
559     if (XGetWindowProperty(XtDisplay(w), win, prop_name, offset, length,
560                            False, AnyPropertyType, &actual_type,&actual_format,
561                            &nitems, &bytes_left, &data) == Success)
562     {
563         switch(prop_type) 
564         {
565             case GET_CURSOR_VISIBLE:
566                 sprintf((char *)reply,"%d", (int )_DtTermPrimGetCursorVisible(tw->termview.term));
567                 break;
568     
569             case GET_USER_KEY_LOCK:
570                 sprintf((char *)reply,"%d", (int )_DtTermGetUserKeyLock(tw->termview.term));
571                 break;
572
573             case GET_AUTO_LINE_FEED:
574                 sprintf((char *)reply,"%d", (int )_DtTermGetAutoLineFeed(tw->termview.term));
575                 break;
576
577             case GET_SCROLLBAR_WINDOW:
578                 sprintf((char *)reply, "0x%lx", tw->termview.scrollBar.widget ?
579                         XtWindow(tw->termview.scrollBar.widget) : 0);
580                 break;
581
582             case ONE_BYTE:
583                 XtSetArg(al[0], (XtPointer ) data,&onebyte);
584                 if (!strcmp((char *)data, XmNmenuBar) ||
585                     !strcmp((char *)data, DtNscrollBar))
586                     XtGetValues((Widget)tw, al, 1);
587                 else
588                     XtGetValues(tw->termview.term, al, 1);
589                 sprintf((char *)reply,"%d", onebyte.uc);
590                 break;
591
592             case TWO_BYTE:
593                 XtSetArg(al[0], (XtPointer ) data,&twobyte);
594                 XtGetValues(tw->termview.term, al, 1);
595                 sprintf((char *)reply,"%d", twobyte.s);
596                 break;
597                 
598             case FOUR_BYTE:
599             case FOUR_BYTE_PTR:
600                 XtSetArg(al[0], (XtPointer ) data,&fourbyte);
601                 XtGetValues(tw->termview.term, al, 1);
602                 if (prop_type == FOUR_BYTE_PTR)
603                     if (fourbyte.cp) {
604                         sprintf((char *)reply,"%s", fourbyte.cp);
605                     } else {
606                         sprintf((char *)reply,"%s", "<NULL>");
607                     }
608                 else 
609                     sprintf((char *)reply,"%d", fourbyte.i);
610                 break;
611              default:
612                 sprintf((char *)reply,"%s","ERROR");
613         }
614              
615         XChangeProperty(XtDisplay(w), win, prop_name, prop_name, 8,
616                         PropModeReplace, reply, strlen((char *)reply));
617         XSync(XtDisplay(w),False);
618     }
619     free(reply);
620 }
621
622         
623 static void
624 AddMenubarToggle
625 (
626     Widget                topLevel,
627     Widget                termViewWidget
628 )
629 {
630     Arg al[20];
631     int ac;
632     char *menu;
633     char buffer[BUFSIZ];
634
635     /* intern the necessary atoms... */
636     if (xa_MOTIF_WM_MESSAGES == None) {
637         /* get the atom value... */
638         xa_MOTIF_WM_MESSAGES = XInternAtom(XtDisplay(topLevel),
639                 "_MOTIF_WM_MESSAGES", False);
640     }
641     if (xa_DTTERM_TOGGLE_MENUBAR == None) {
642         /* get the atom value... */
643         xa_DTTERM_TOGGLE_MENUBAR = XInternAtom(XtDisplay(topLevel),
644                 "_DTTERM_TOGGLE_MENUBAR", False);
645     }
646
647     /* add a menubar toggle to the mwm pulldown... */
648     ac = 0;
649     menu = GETMESSAGE(NL_SETN_Main,1,"\
650         Sep             f.separator\n\
651         Toggle\\ Menu\\ Bar  f.send_msg %d\
652         ");
653     (void) sprintf(buffer, menu, xa_DTTERM_TOGGLE_MENUBAR);
654     (void) XtSetArg(al[ac], XmNmwmMenu, buffer); ac++;
655     (void) XtSetValues(topLevel, al, ac);
656
657     /* add a protocoll handler for MOTIF_WM_MESSAGES... */
658     if (xa_MOTIF_WM_MESSAGES != None) {
659         (void) XmAddProtocols(topLevel, xa_MOTIF_WM_MESSAGES,
660                 &xa_DTTERM_TOGGLE_MENUBAR, 1);
661         (void) XmAddProtocolCallback(topLevel, xa_MOTIF_WM_MESSAGES,
662                 xa_DTTERM_TOGGLE_MENUBAR,
663                 ToggleMenuBar, (XtPointer) termViewWidget);
664     }
665 }
666
667 static void
668 CloneCallback(Widget wid, XtPointer client_data, XtPointer call_data)
669 {
670     register DtTermViewWidget w = (DtTermViewWidget) wid;
671     DtTermViewCallbackStruct *termCB = (DtTermViewCallbackStruct *) call_data;
672
673     Widget parent = XtParent((Widget) w);
674     Widget shellWidget;
675     Widget termWidget;
676     Arg arglist[10];
677     int i;
678     /* duplicate the dtterm widget's parent widget...
679      */
680     if (XtIsShell(parent)) {
681         int argc;
682         String *argv;
683         Boolean allowShellResize;
684 #ifdef  COPY_WHEN_CLONING
685         String geometry;
686         Dimension width;
687         Dimension height;
688 #endif  /* COPY_WHEN_CLONING */
689         char *topShellIconName;
690
691         i = 0;
692         if (XtIsApplicationShell(parent)) {
693             (void) XtSetArg(arglist[i], XmNargc, &argc); i++;
694             (void) XtSetArg(arglist[i], XmNargv, &argv); i++;
695         }
696 #ifdef  COPY_WHEN_CLONING
697         (void) XtSetArg(arglist[i], XmNgeometry, &geometry); i++;
698         (void) XtSetArg(arglist[i], XmNwidth, &width); i++;
699         (void) XtSetArg(arglist[i], XmNheight, &height); i++;
700 #endif  /* COPY_WHEN_CLONING */
701         (void) XtSetArg(arglist[i], XmNallowShellResize, &allowShellResize);
702                 i++;
703         (void) XtGetValues(parent, arglist, i);
704
705         i = 0;
706         if (XtIsApplicationShell(parent)) {
707             (void) XtSetArg(arglist[i], XmNargc, argc); i++;
708             (void) XtSetArg(arglist[i], XmNargv, argv); i++;
709         }
710 #ifdef  COPY_WHEN_CLONING
711         (void) XtSetArg(arglist[i], XmNgeometry, geometry); i++;
712         (void) XtSetArg(arglist[i], XmNwidth, width); i++;
713         (void) XtSetArg(arglist[i], XmNheight, height); i++;
714 #endif  /* COPY_WHEN_CLONING */
715         (void) XtSetArg(arglist[i], XmNallowShellResize, allowShellResize); i++;
716         /* Set the title (and icon name) for the clone (new) dtterm window 
717            the same as the initial title (and icon name) of the top level 
718            shell dtterm window 
719          */
720         (void) XtSetArg(arglist[i], XmNtitle, attrs.title); i++;
721         if (attrs.icon_name)
722             topShellIconName = attrs.icon_name;
723         else if (attrs.dtterm_name)
724             topShellIconName = attrs.dtterm_name;
725         else topShellIconName = attrs.title;
726         (void) XtSetArg(arglist[i], XmNiconName, topShellIconName); i++;
727
728         shellWidget = XtAppCreateShell((char *) 0, "Dtterm",
729                 XtClass(parent), XtDisplay((Widget) w), arglist, i);
730     } else {
731         i = 0;
732         (void) XtSetArg(arglist[i], XmNallowShellResize, True); i++;
733         shellWidget = XtAppCreateShell((char *) 0, "Dtterm",
734                 applicationShellWidgetClass, XtDisplay((Widget) w), arglist, i);
735     }
736
737 #ifdef  COPY_WHEN_CLONING
738     termWidget = DtCreateTermView(shellWidget, "dtTermView", termCB->arglist,
739             termCB->argcount);
740 #else   /* COPY_WHEN_CLONING */
741     termWidget = DtCreateTermView(shellWidget, "dtTermView", termCB->arglist,
742             0);
743 #endif  /* COPY_WHEN_CLONING */
744
745     /* add a menubar toggle to the mwm pulldown... */
746     (void) AddMenubarToggle(shellWidget, termWidget);
747
748     (void) InstanceCount++;
749     (void) XtManageChild(termWidget);
750
751     /* destroy the widget on child termination... */
752     (void) XtAddCallback(termWidget, DtNsubprocessTerminationCallback,
753             DestroyDtTerm, (XtPointer) shellWidget);
754     (void) XtAddCallback(termWidget, XmNdestroyCallback,
755             DecrementInstanceCountAndExit, (XtPointer) topLevel);
756     (void) _DtTermPrimAddDeleteWindowCallback(shellWidget, DestroyDtTerm,
757             (XtPointer) shellWidget);
758     (void) XtAddCallback(termWidget, DtNnewCallback,
759             CloneCallback, (XtPointer) 0);
760     instance_list = (DtTermViewWidget *)XtRealloc((char *)instance_list,
761                                                 (sizeof(DtTermViewWidget *)*InstanceCount));
762     instance_list[InstanceCount - 1] = (DtTermViewWidget )termWidget;
763
764     (void) XtRealizeWidget(shellWidget);
765     return;
766 }
767
768 static void
769 ToggleMenuBar
770 (
771     Widget                w,
772     XtPointer             client_data,
773     XtPointer             call_data
774 )
775 {
776     XmAnyCallbackStruct  *cb = (XmAnyCallbackStruct *) call_data;
777
778     if (cb->event->xclient.message_type == xa_MOTIF_WM_MESSAGES) {
779         /* can't use case here, since we are not switching on a pre-defined
780          * value...
781          */
782         if (cb->event->xclient.data.l[0] == xa_DTTERM_TOGGLE_MENUBAR) {
783             (void) _DtTermViewMenuToggleMenuBar((Widget) client_data);
784         }
785     }
786 }
787 #ifdef SUN_TERMINAL_SERVER
788 Boolean
789 #else
790 static void
791 #endif /* SUN_TERMINAL_SERVER */
792 CreateInstance
793 (
794     Widget                topLevelWidget,
795     char                 *name,
796     Arg                  *arglist,
797     int                   argcnt,
798     Boolean               enableCloneCallback
799 )
800 {
801     Widget termViewWidget;
802
803     /* bump our session count... */
804 #ifdef  LOG_USAGE
805     (void) LogBumpSessionCount(1);
806 #endif  /* LOG_USAGE */
807
808     termViewWidget = DtCreateTermView(topLevelWidget, name, arglist, argcnt);
809
810     /* add a menubar toggle to the mwm pulldown... */
811     (void) AddMenubarToggle(topLevelWidget, termViewWidget);
812
813 #ifdef  TERMINAL_SERVER
814     if (attrs.standAlone || !attrs.serverId) {
815 #endif  /* TERMINAL_SERVER */
816         (void) InstanceCount++;
817 #ifdef  TERMINAL_SERVER
818     }
819 #endif  /* TERMINAL_SERVER */
820     (void) XtManageChild(termViewWidget);
821     /* destroy the widget on termination... */
822     (void) XtAddCallback(termViewWidget, DtNsubprocessTerminationCallback,
823             DestroyDtTerm, (XtPointer) topLevelWidget);
824     (void) XtAddCallback(termViewWidget, XmNdestroyCallback,
825             DecrementInstanceCountAndExit, (XtPointer) topLevelWidget);
826     (void) _DtTermPrimAddDeleteWindowCallback(topLevelWidget, DestroyDtTerm,
827             (XtPointer) topLevelWidget);
828     instance_list = (DtTermViewWidget * )XtRealloc((char *)instance_list,(sizeof(DtTermViewWidget *)*InstanceCount));
829     instance_list[InstanceCount - 1] = (DtTermViewWidget )termViewWidget;
830     if (enableCloneCallback)
831         (void) XtAddCallback(termViewWidget, DtNnewCallback,
832                 CloneCallback, (XtPointer) 0);
833 }
834
835 void
836 AtExitProc()
837 {
838     static int i = 0;
839
840     i++;
841 #ifdef  BBA
842     _bA_dump();
843 #endif  /* BBA */
844 }
845
846 void
847 SignalHandler
848 (
849     int                   sig
850 )
851 {
852     DebugF('s', 10, fprintf(stderr, ">>SignalHandler() starting\n"));
853     _DtTermPrimPtyCleanup();
854     _DtTermPrimUtmpCleanup();
855     _DtTermPrimLogFileCleanup();
856     DebugF('s', 10, fprintf(stderr, ">>SignalHandler() finished\n"));
857     (void) exit(0);
858 }
859
860 static int signalList[] = {
861     SIGHUP,
862     SIGINT,
863     SIGQUIT,
864     /* SIGILL, */
865     /* SIGTRAP, */
866     /* SIGABRT, */
867     /* SIGIOT, */
868     /* SIGEMT, */
869     /* SIGFPE, */
870     SIGKILL,
871     /* SIGBUS, */
872     /* SIGSEGV, */
873     /* SIGSYS, */
874     SIGPIPE,
875     SIGALRM,
876     SIGTERM,
877     SIGUSR1,
878     SIGUSR2,
879     /* SIGVTALRM, */
880     /* SIGPROF, */
881     /* SIGLOST, */
882 };
883
884 static Boolean
885 GetBindingsProperty
886 (
887     Display              *display,
888     String                property,
889     String               *binding
890 )
891 {
892     char                 *prop = (char *) 0;
893     Atom                  actualType;
894     int                   actualFormat;
895     unsigned long         numItems;
896     unsigned long         bytesAfter;
897
898     (void) XGetWindowProperty(display,
899             RootWindow(display, 0),
900             XmInternAtom(display, property, FALSE),
901             0,
902             (long) 1000000,
903             FALSE,
904             XA_STRING,
905             &actualType,
906             &actualFormat,
907             &numItems,
908             &bytesAfter,
909             (unsigned char **) &prop);
910
911     if ((actualType != XA_STRING) ||
912             (actualFormat != 8) ||
913             (numItems == 0)) {
914         if (prop) {
915             XFree(prop);
916         }
917         return(False);
918     } else {
919         *binding = prop;
920         return(True);
921     }
922 }
923
924 #ifndef XmNdefaultVirtualBindings
925 #define XmNdefaultVirtualBindings       "defaultVirtualBindings"
926 #endif  /* XmNdefaultVirtualBindings */
927 static void
928 FixOSFBindings
929 (
930     Display              *display
931 )
932 {
933     Widget                w;
934     Arg                   al[10];
935     int                   ac;
936     char                 *origDisplayBindings,*freeOrigBindings=NULL;
937     char                 *newDisplayBindings;
938     char                 *c1;
939     char                 *c2;
940     char                 *cHold;
941     int                   i1;
942     char                **ignoredKeysymList;
943     int                   numIgnoredKeysyms;
944     
945     /* malloc a copy of the ignoredKeysym string... */
946     if (attrs.ignoredKeysyms && *attrs.ignoredKeysyms) {
947         c1 = XtMalloc(strlen(attrs.ignoredKeysyms) + 1);
948         (void) strcpy(c1, attrs.ignoredKeysyms);
949         attrs.ignoredKeysyms = c1;
950     }
951
952     /* count the number of keysyms in the list... */
953     for (c1 = attrs.ignoredKeysyms, numIgnoredKeysyms = 0; c1 && *c1; ) {
954         numIgnoredKeysyms++;
955         c1 = strchr(c1, '\n');
956         if (c1) {
957             (void) c1++;
958         }
959     }
960
961     /* malloc space for the array... */
962     ignoredKeysymList = (char **) XtMalloc((numIgnoredKeysyms + 1) *
963             sizeof(char *));
964
965     /* build the list... */
966     for (c1 = attrs.ignoredKeysyms, i1 = 0; i1 < numIgnoredKeysyms; i1++) {
967         ignoredKeysymList[i1] = c1;
968         c1 = strchr(c1, '\n');
969         if (c1 && *c1) {
970             *c1++ = '\0';
971         }
972     }
973
974     /* null terminate the list... */
975     ignoredKeysymList[i1] = (char *) 0;
976
977
978     w = XmGetXmDisplay(display);
979
980     ac = 0;
981     (void) XtSetArg(al[ac], XmNdefaultVirtualBindings, &origDisplayBindings);
982             ac++;
983     (void) XtGetValues(w, al, ac);
984
985     if (!origDisplayBindings) {
986         GetBindingsProperty(display, "_MOTIF_BINDINGS", &origDisplayBindings);
987         freeOrigBindings = origDisplayBindings ;
988     }
989
990     if (!origDisplayBindings) {
991         GetBindingsProperty(display, "_MOTIF_DEFAULT_BINDINGS",
992                 &origDisplayBindings);
993         freeOrigBindings = origDisplayBindings ;
994     }
995
996     if (!origDisplayBindings) {
997         if (ignoredKeysymList) XtFree((char *)ignoredKeysymList);
998         return;
999     }
1000
1001     DebugF('b', 10, fprintf(stderr,
1002             "FixOSFBindings(): bindings: %s\n", origDisplayBindings));
1003     newDisplayBindings = XtMalloc(strlen(origDisplayBindings) + 1);
1004     c1 = origDisplayBindings;
1005     c2 = newDisplayBindings;
1006     while (*c1) {
1007         /* remember the current position in the new string... */
1008         cHold = c2;
1009
1010         /* copy over everything up to the '\n' or null... */
1011         while (*c1 && (*c1 != '\n')) {
1012             *c2++ = *c1++;
1013         }
1014
1015         /* null terminate the string... */
1016         *c2 = '\0';
1017
1018         /* run through the exclusion list and look for a match... */
1019         for (i1 = 0; i1 < numIgnoredKeysyms; i1++) {
1020             DebugF('b', 10, fprintf(stderr, "!strcmp(\"%s\", \"%s\") = %d\n",
1021                     c2 - strlen(ignoredKeysymList[i1]),
1022                     ignoredKeysymList[i1],
1023                     !strcmp(c2 - strlen(ignoredKeysymList[i1]),
1024                     ignoredKeysymList[i1])));
1025             if ((strlen(ignoredKeysymList[i1]) <= (size_t)(c2 - cHold)) &&
1026                     !strcmp(c2 - strlen(ignoredKeysymList[i1]),
1027                     ignoredKeysymList[i1])) {
1028                 /* we hit a match... */
1029                 DebugF('b', 10, fprintf(stderr, "match!\n"));
1030                 break;
1031             }
1032         }
1033
1034         /* if we hit a match, back up the string... */
1035         if (i1 < numIgnoredKeysyms) {
1036             DebugF('b', 10, fprintf(stderr, "dropping %s\n", cHold));
1037             c2 = cHold;
1038             /* skip over whitespace in the source... */
1039             while (isspace(*c1)) {
1040                 c1++;
1041             }
1042         } else {
1043             /* copy over whitespace in the source... */
1044             DebugF('b', 10, fprintf(stderr, "keeping %s\n", cHold));
1045             while (isspace(*c1)) {
1046                 *c2++ = *c1++;
1047             }
1048             cHold = c2;
1049         }
1050     }
1051
1052     /* null terminate the string... */
1053     *c2 = '\0';
1054
1055     /* and set this new bindings string... */
1056     ac = 0;
1057     (void) XtSetArg(al[ac], XmNdefaultVirtualBindings, newDisplayBindings);
1058             ac++;
1059     (void) XtSetValues(w, al, ac);
1060
1061   /* changed from XtFree to free as it was allocated with malloc to avoid FMM */
1062     if (freeOrigBindings) free(origDisplayBindings);
1063
1064     if (ignoredKeysymList) XtFree((char *)ignoredKeysymList);
1065
1066     /* and finally, reparse the string... */
1067     _XmVirtKeysInitialize(w);
1068 }
1069
1070 static void
1071 removeWmCommandCallback
1072 (
1073     Widget                w,
1074     XtPointer             clientData,
1075     XEvent               *event,
1076     Boolean              *cont
1077 )
1078 {
1079     static Atom           xa_WM_STATE = None;
1080     Boolean               firstTime = True;
1081
1082     if (firstTime) {
1083         xa_WM_STATE = XInternAtom(XtDisplay(w), "WM_STATE", True);
1084         firstTime = False;
1085     }
1086
1087     if (((XPropertyEvent *) event)->atom == xa_WM_STATE) {
1088         /* blow away the atom... */
1089         (void) XDeleteProperty(XtDisplay(w), XtWindow(w),
1090                 XA_WM_COMMAND);
1091
1092         /* we have done our job and don't need to be called again... */
1093         (void) XtRemoveEventHandler(w, (EventMask) XtAllEvents,
1094                 True, removeWmCommandCallback, clientData);
1095     }
1096 }
1097
1098 static char *
1099 base_name(
1100      char *name
1101 )
1102 {
1103         register char *cp;
1104
1105         cp = strrchr(name, '/');
1106         return(cp ? cp + 1 : name);
1107 }
1108
1109 int
1110 main(int argc, char **argv)
1111 {
1112     Arg                   arglist[20];
1113     int                   i;
1114     char                 *c;
1115     char                 *c2;
1116     char                 *saved_arg0;
1117     char                **commandToExecute = (char **) 0;
1118     int                   ptyMasterFd = -1;
1119     struct sigaction      sa;
1120 #ifdef SUN_TERMINAL_SERVER
1121     Boolean               iAmTheServer = False;
1122 #endif /* SUN_TERMINAL_SERVER */
1123     
1124     (void) atexit(AtExitProc);
1125
1126     if (c = getenv("dttermDebugFlags")) {
1127         (void) setDebugFlags(c);
1128     }
1129     if (isDebugSet('T')) {
1130 #ifdef  BBA
1131 #pragma BBA_IGNORE
1132 #endif  /*BBA*/
1133         (void) timeStamp("starting");
1134     }
1135
1136     if (c = getenv("dttermDelayFlags"))
1137     {
1138         if (NULL != c)
1139         {
1140             int delay = atoi(c);
1141             pid_t pid = getpid();
1142             printf("dtterm (%d) sleeping for %d seconds\n", pid, delay);
1143             sleep(delay);
1144         }
1145     }
1146
1147     /* before we do anything, let's set up signal handlers to clean up
1148      * after ourself...
1149      */
1150     (void) sigemptyset(&sa.sa_mask);
1151     sa.sa_flags = 0;
1152
1153     sa.sa_handler = SignalHandler;
1154     /* trap all signals that we want to clean up after... */
1155     for (i = 0; i < (sizeof(signalList) / sizeof(signalList[0])); i++) {
1156         (void) sigaction(signalList[i], &sa, (struct sigaction *) 0);
1157     }
1158
1159     /* ignore SIGHUP... */
1160     sa.sa_handler = SIG_IGN;
1161     (void) sigaction(SIGHUP, &sa, (struct sigaction *) 0);
1162
1163     /*
1164     ** set up the environment variables for this client...
1165     */
1166 #if defined(HPVUE)
1167 #if       (OSMINORVERSION > 01)
1168     VuEnvControl(VUE_ENV_SET);
1169 #endif /* (OSMINORVERSION > 01) */
1170 #else
1171     _DtEnvControl(DT_ENV_SET);
1172 #endif   /* HPVUE */
1173
1174     /* set up the I18N world... */
1175     (void) XtSetLanguageProc(NULL, NULL, NULL);
1176
1177     if (isDebugSet('T')) {
1178 #ifdef  BBA
1179 #pragma BBA_IGNORE
1180 #endif  /*BBA*/
1181         (void) timeStamp("XtSetLangProc() finished");
1182     }
1183
1184     /* before we initialize Xt, let's save argv and argc... */
1185     savedArgc = argc;
1186     savedArgv = (char **) XtMalloc((argc + 1) * sizeof(char *));
1187     for (i = 0; i < argc; i++) {
1188         savedArgv[i] = XtMalloc(strlen(argv[i]) + 1);
1189         (void) strcpy(savedArgv[i], argv[i]);
1190 #ifdef SUN_TERMINAL_SERVER
1191         if ((!strcmp(argv[i], "-sdtserver")) || (!strcmp(argv[i], "-dtserver")))
1192             iAmTheServer = TRUE;
1193 #endif /* SUN_TERMINAL_SERVER */
1194     }
1195     savedArgv[i] = (char *) 0;
1196
1197 #ifdef sun
1198     (void) setsid();
1199 #endif /* sun */
1200
1201
1202     /* before we do anything with the toolkit, let's usurp the constraint
1203      * initialize proc for the XmManager widget class.  This will allow us
1204      * to prevent it from performing that awful
1205      * DoMagicBBCompatibilityStuff() on us that steals (among other things)
1206      * our return key.  Note that currently, this is all that the
1207      * XmManager widget does for widgets, but if it did more than we
1208      * would loose out on that.
1209      */
1210     /* initialize Xt and the X world... */
1211     (void) DtTermInitialize();
1212
1213     i = 0;
1214     (void) XtSetArg(arglist[i], XmNallowShellResize, True); i++;
1215
1216     topLevel = XtAppInitialize(&appContext,
1217             "Dtterm",
1218             optionDescList,
1219             XtNumber(optionDescList),
1220             &argc,
1221             argv,
1222             fallbackResources,
1223             arglist,
1224             i);
1225
1226 #ifdef SUN_TERMINAL_SERVER
1227     if (iAmTheServer) {
1228        (void) ServerStartSession(topLevel, savedArgc, savedArgv,
1229                 attrs.loginShell,
1230                 commandToExecute);
1231     } 
1232 #endif /* SUN_TERMINAL_SERVER */
1233
1234     /* get application specific resources... */
1235     i = 0;
1236     /* Need to specify base address of the resources. In our case, attrs */
1237     (void) XtGetApplicationResources(topLevel, (XtPointer)&attrs, 
1238                                      applicationResources,
1239                                      XtNumber(applicationResources), 
1240                                      arglist, i);    
1241
1242     /* set all the debug flags... */
1243     (void) setDebugFlags(attrs.debugString);
1244     
1245     (void) FixOSFBindings(XtDisplay(topLevel));
1246
1247     /* Add the Save_yourself callback... */
1248     xa_WM_SAVE_YOURSELF = XInternAtom(XtDisplay(topLevel),
1249                                       "WM_SAVE_YOURSELF", False);
1250     XmAddWMProtocolCallback(topLevel, xa_WM_SAVE_YOURSELF,
1251                            (XtCallbackProc)SaveSessionCB, (XtPointer)NULL);
1252     
1253     i = 0;
1254     (void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
1255     (void) XtSetArg(arglist[i], XmNallowShellResize, True); i++;
1256     topShell = XtAppCreateShell((char *) 0, "Dtterm",
1257                 applicationShellWidgetClass, XtDisplay(topLevel), arglist, i);
1258
1259     if (attrs.session != NULL)
1260        RestoringTerms = TRUE;
1261
1262     if (isDebugSet('T')) {
1263 #ifdef  BBA
1264 #pragma BBA_IGNORE
1265 #endif  /*BBA*/
1266         (void) timeStamp("XtAppInitialize() finished");
1267     }
1268
1269     for (i = 1; i < argc; i++) {
1270         if (argv[i][0] != '-') {
1271             (void) Syntax(argv[0], argv[i]);
1272             exit(1);
1273         }
1274
1275         switch(argv[i][1]) {
1276         case 'S' :
1277             /* slave mode...
1278              */
1279             /* skip past the '-S'... */
1280             c = argv[i] + 2;
1281             if (c2 = strchr(c, '.')) {
1282                 /* skip past the '.'... */
1283                 (void) c2++;
1284             } else {
1285                 /* skip past the first 2 characters since they are the
1286                  * name of the pty...
1287                  */
1288                 c2 = c + 2;
1289             }
1290             /* use scanf instead of atoi since it won't change the value
1291              * of ptyMasterFd if the string does not contain a valid
1292              * number...
1293              */
1294             (void) sscanf(c2, "%d", &ptyMasterFd);
1295             break;
1296
1297         case 'e' :
1298             /* command to exec...
1299              */
1300             (void) i++;
1301             if (i < argc) {
1302                 commandToExecute = &argv[i];
1303                 i = argc;
1304             }
1305             break;
1306         case 'h' :
1307         case 'u' :
1308             /* help/usage...
1309              */
1310             (void) Help(argv[0]);
1311             exit(0);
1312             break;
1313
1314         default :
1315             (void) Syntax(argv[0], argv[i]);
1316             (void) exit(1);
1317             break;
1318         }
1319     }
1320
1321 #ifdef  TERMINAL_SERVER
1322     if (attrs.standAlone || !attrs.serverId) {
1323 #endif  /* TERMINAL_SERVER */
1324         /* log our startup... */
1325 #ifdef  LOG_USAGE
1326         (void) LogStart(0, argc, argv);
1327 #endif  /* LOG_USAGE */
1328
1329         i = 0;
1330         if (commandToExecute) {     
1331             (void) XtSetArg(arglist[i], DtNsubprocessArgv, commandToExecute);
1332                     i++;
1333         }
1334         
1335         if (!RestoringTerms || !RestoreSession(topShell, arglist, i)) {
1336
1337             RestoringTerms = False;
1338
1339             if (ptyMasterFd >= 0) {
1340                 /* set the workspace for the initial dtterm instance... */
1341                 (void) XtSetArg(arglist[i], DtNtermDevice, ptyMasterFd); i++;
1342                 (void) XtSetArg(arglist[i], DtNtermDeviceAllocate, False); i++;
1343                 (void) XtSetArg(arglist[i], DtNsubprocessExec, False); i++;
1344                 (void) CreateInstance(topShell, "dtTermView", arglist, i, False);
1345             } 
1346             else {
1347                 (void) CreateInstance(topShell, "dtTermView", arglist, i, True);
1348             }
1349         }
1350
1351         /* realize the interface... */
1352         i = 0;
1353         (void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
1354         (void) XtSetValues(topLevel, arglist, i);
1355         (void) XtRealizeWidget(topLevel);
1356
1357 #ifdef SUN_TERMINAL_SERVER
1358         if (iAmTheServer)
1359             FinishToolTalkInit(topLevel);
1360 #endif /* SUN_TERMINAL_SERVER */
1361
1362         /* Set title to the command to execute (if any) 
1363          */
1364         if (commandToExecute && !attrs.title) {
1365            attrs.title = base_name (commandToExecute[0]);
1366         }
1367
1368         /* Else set title to default ("Terminal")
1369          */
1370         if (!attrs.title) {         
1371             title = XtMalloc(strlen(GETMESSAGE(NL_SETN_Main, 3, "Terminal")) + 1);
1372             (void) strcpy(title, GETMESSAGE(NL_SETN_Main, 3, "Terminal"));
1373             attrs.title = title;
1374         }
1375
1376         /* realize the interface... */
1377         i = 0;
1378         (void) XtSetArg(arglist[i], XmNtitle, attrs.title); i++;
1379         if ((!attrs.icon_name) && (!attrs.dtterm_name))
1380           (void) XtSetArg(arglist[i], XmNiconName, attrs.title); i++;
1381         (void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
1382         (void) XtSetArg(arglist[i], XmNgeometry, NULL); i++;
1383         (void) XtSetValues(topShell, arglist, i);
1384         (void) XtRealizeWidget(topShell);
1385
1386         if (RestoringTerms != True) {
1387             /* use the wm command to pass the -xrm resource to the wm... */
1388             (void) XSetCommand(XtDisplay(topShell), XtWindow(topShell),
1389                     savedArgv, savedArgc);
1390             /* add a callback to remove it after it has been seen... */
1391             (void) XtAddEventHandler(topShell, (EventMask) PropertyChangeMask,
1392                     False, removeWmCommandCallback, (XtPointer) 0);
1393         }
1394
1395         (void) XtSetArg(arglist[0], XmNmappedWhenManaged, True); 
1396         (void) XtSetValues(topShell, arglist, 1);
1397         XtMapWidget(topShell);
1398         RegisterTestProbe(topShell,instance_list[0]);
1399         
1400         if (ptyMasterFd >= 0) {
1401             /* write out the window id... */
1402             char buffer[BUFSIZ];
1403
1404             (void) sprintf(buffer, "%lx\n", XtWindow(topLevel));
1405             (void) write(ptyMasterFd, buffer, strlen(buffer));
1406         }
1407 #ifdef sun
1408         sunSetupIA(topLevel);
1409 #endif /* sun */
1410
1411 #ifdef  TERMINAL_SERVER
1412     } else {
1413         if (ptyMasterFd >= 0) {
1414             (void) fprintf(stderr,
1415                     GETMESSAGE(NL_SETN_Main,2, "%s: the -S option cannot be used with the -server or -serverid options\n"),
1416                     argv[0]);
1417             (void) exit(1);
1418         }
1419
1420         i = 0;
1421         (void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
1422         (void) XtSetValues(topLevel, arglist, i);
1423         (void) XtRealizeWidget(topLevel);
1424
1425         (void) ServerStartSession(topLevel, savedArgc, savedArgv,
1426                 attrs.server, attrs.serverId, attrs.exitOnLastClose, 
1427                 attrs.block, attrs.loginShell,
1428                 commandToExecute);
1429     }
1430 #endif  /* TERMINAL_SERVER */
1431
1432     /* and hand off to Xt... */
1433     (void) XtAppMainLoop(appContext);
1434 }
1435
1436 /************************************************************************
1437  *
1438  *  SaveSessionCB 
1439  *
1440  ************************************************************************/
1441
1442 /* ARGSUSED */
1443 static void 
1444 SaveSessionCB(
1445         Widget w,                       /* widget id */
1446         caddr_t client_data,            /* data from application  */
1447         caddr_t call_data )             /* data from widget class */
1448 {
1449     char *longpath, *fileName;
1450     char bufr[1024];
1451     int fd;
1452     char *xa_CommandStr[1024];
1453     int i,j;
1454     
1455      if(!XtIsShell(w))
1456         w = XtParent(w);
1457
1458     DtSessionSavePath(w, &longpath, &fileName);
1459
1460     /*  Create the session file  */
1461     if ((fd = creat (longpath, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP)) == -1)
1462     {
1463         return;
1464     }
1465
1466     sprintf(bufr, "*dtterm.numClonedTerms: %d\n", InstanceCount);
1467     write (fd, bufr, strlen(bufr));
1468
1469     for(i = 0; i < InstanceCount; i++)
1470         SaveTerm(instance_list[i], i, fd);
1471
1472     sprintf(bufr,
1473           "*dtterm.sessionFileVersionId: dttermSessionFileVersion.1.0.0\n");
1474     write (fd, bufr, strlen(bufr));
1475
1476     close(fd);
1477
1478     i = 0;
1479     xa_CommandStr[i] = savedArgv[0]; i++;
1480     xa_CommandStr[i] =  "-session"; i++;
1481     xa_CommandStr[i] =  fileName; i++;
1482 /****************
1483  *
1484  * Now restore the command line minus the old session parameter 
1485  *
1486  ****************/
1487     for (j = 1; j < savedArgc; j++)
1488     {
1489         if (strcmp(savedArgv[j], "-session") == 0)
1490         {
1491             j++;
1492             continue;
1493         }
1494         else
1495         {
1496             xa_CommandStr[i] =  savedArgv[j];
1497             i++;
1498         }
1499     }
1500
1501     XSetCommand(XtDisplay(topLevel), 
1502                 XtWindow(topLevel), xa_CommandStr, i);
1503
1504
1505     XtFree ((char *)fileName);
1506 }
1507
1508 static void 
1509 SaveTerm(
1510         DtTermViewWidget dtvw,
1511         int cloneNum,
1512         int fd)
1513 {
1514     char *bufr = malloc(1024);
1515     Position x,y;
1516     Dimension width, height;
1517     Atom *pWsPresence;
1518     unsigned long numInfo;
1519     unsigned char         charCursorStyle;
1520     int                   blinkRate;
1521     Boolean               jumpScroll;
1522     Boolean               marginBell;
1523     int                   nMarginBell;
1524     Boolean               visualBell;
1525     Boolean               reverseVideo;
1526     Boolean               cursorMode;
1527     Boolean               keypadMode;
1528     Boolean               autoWrap;
1529     Boolean               reverseWrap;
1530     Boolean               c132;
1531     Boolean               lockState;
1532     Boolean               autoLineFeed;
1533     Boolean               menuBar;
1534     Boolean               scrollBar;
1535     short                 rows;
1536     short                 columns;
1537     char                 *cwd;
1538     static char          *defaultCwd = (char *) 0;
1539     Arg                   al[30];
1540     int                   ac;
1541     char                  buffer[BUFSIZ];
1542     DtTermWidget dtw = (DtTermWidget )dtvw->termview.term;
1543     static Boolean        firstTime = True;
1544     static Atom           xa_WM_STATE = None;
1545     struct _wmStateStruct {
1546         CARD32            state;
1547         Window            icon;
1548     }                    *prop;
1549     Atom                  actualType;
1550     int                   actualFormat;
1551     unsigned long         nItems;
1552     unsigned long         bytesAfter;
1553
1554     XmVendorShellExtObject vendorExt;
1555     XmWidgetExtData        extData;
1556
1557     x = XtX(XtParent(dtvw));
1558     y = XtY(XtParent(dtvw));
1559
1560     /*
1561      * Modify x & y to take into account window mgr frames
1562      * This is pretty bogus, but I don't know a better way to do it.
1563      */
1564     extData = _XmGetWidgetExtData(XtParent(dtvw), XmSHELL_EXTENSION);
1565     vendorExt = (XmVendorShellExtObject)extData->widget;
1566     x -= vendorExt->vendor.xOffset;
1567     y -= vendorExt->vendor.yOffset;
1568     width = XtWidth(XtParent(dtvw));
1569     height = XtHeight(XtParent(dtvw));
1570
1571     sprintf(bufr, "*dtterm_%d.x: %d\n", cloneNum, x);
1572     sprintf(bufr, "%s*dtterm_%d.y: %d\n", bufr, cloneNum, y);
1573     sprintf(bufr, "%s*dtterm_%d.width: %d\n", bufr, cloneNum, width);
1574     sprintf(bufr, "%s*dtterm_%d.height: %d\n", bufr, cloneNum, height);
1575
1576     /* Write out iconic state...
1577      */
1578     if (firstTime) {
1579         xa_WM_STATE = XInternAtom(XtDisplay(dtvw), "WM_STATE", True);
1580         firstTime = False;
1581     }
1582     if (xa_WM_STATE && (Success == XGetWindowProperty(
1583             XtDisplay(dtvw),
1584             XtWindow(XtParent(dtvw)),
1585             xa_WM_STATE,
1586             0L,
1587             (sizeof(struct _wmStateStruct) + 3) / 4,
1588             False,
1589             AnyPropertyType,
1590             &actualType,
1591             &actualFormat,
1592             &nItems,
1593             &bytesAfter,
1594             (unsigned char **) &prop))) {
1595         if (prop->state == IconicState) {
1596             sprintf(bufr, "%s*dtterm_%d.iconify: %s\n", bufr, cloneNum,
1597                     "True");
1598         } else {
1599             sprintf(bufr, "%s*dtterm_%d.iconify: %s\n", bufr, cloneNum,
1600                     "False");
1601         }
1602     }
1603         
1604     if(DtWsmGetWorkspacesOccupied(XtDisplay(dtvw), 
1605                                   XtWindow(XtParent(dtvw)), &pWsPresence,
1606                                   &numInfo) == Success)
1607     {
1608         int i;
1609         sprintf(bufr, "%s*dtterm_%d.workspaceList: ", bufr, cloneNum);
1610         for(i = 0; i < numInfo; i++)
1611         {
1612             char *name =  XGetAtomName(XtDisplay(dtvw),
1613                                        pWsPresence[i]);
1614             sprintf(bufr, "%s %s", bufr, name);
1615             XtFree(name);
1616         }
1617         sprintf(bufr, "%s\n", bufr);
1618         XtFree((char *)pWsPresence);
1619     }
1620
1621     write (fd, bufr, strlen(bufr));
1622
1623     sprintf(bufr, "*dtterm_%d.userFontListIndex: %d\n", cloneNum,
1624             _DtTermViewGetUserFontListIndex((Widget )dtvw));
1625     write (fd, bufr, strlen(bufr));
1626
1627     /* get the current widget values... */
1628     ac = 0;
1629     (void) XtSetArg(al[ac], DtNmenuBar, &menuBar);                      ac++;
1630     (void) XtSetArg(al[ac], DtNscrollBar, &scrollBar);                  ac++;
1631     (void) XtGetValues((Widget)dtvw, al, ac);
1632     ac = 0;
1633     (void) XtSetArg(al[ac], DtNrows, &rows);                            ac++;
1634     (void) XtSetArg(al[ac], DtNcolumns, &columns);                      ac++;
1635     (void) XtSetArg(al[ac], DtNblinkRate, &blinkRate);                  ac++;
1636     (void) XtSetArg(al[ac], DtNcharCursorStyle, &charCursorStyle);      ac++;
1637     (void) XtSetArg(al[ac], DtNblinkRate, &blinkRate);                  ac++;
1638     (void) XtSetArg(al[ac], DtNjumpScroll, &jumpScroll);                ac++;
1639     (void) XtSetArg(al[ac], DtNmarginBell, &marginBell);                ac++;
1640     (void) XtSetArg(al[ac], DtNnMarginBell, &nMarginBell);              ac++;
1641     (void) XtSetArg(al[ac], DtNvisualBell, &visualBell);                ac++;
1642     (void) XtSetArg(al[ac], DtNreverseVideo, &reverseVideo);            ac++;
1643     (void) XtSetArg(al[ac], DtNappCursorDefault, &cursorMode);          ac++;
1644     (void) XtSetArg(al[ac], DtNappKeypadDefault, &keypadMode);          ac++;
1645     (void) XtSetArg(al[ac], DtNautoWrap, &autoWrap);                    ac++;
1646     (void) XtSetArg(al[ac], DtNreverseWrap, &reverseWrap);              ac++;
1647     (void) XtSetArg(al[ac], DtNc132, &c132);                            ac++;
1648     (void) XtGetValues((Widget)dtw, al, ac);
1649     lockState = _DtTermGetUserKeyLock((Widget) dtw);
1650     autoLineFeed = _DtTermGetAutoLineFeed((Widget) dtw);
1651
1652     /* get the current working directory if it was saved... */
1653     cwd = _DtTermGetCurrentWorkingDirectory((Widget) dtw);
1654     if (!cwd || !*cwd) {
1655         /* no saved cwd, use the one we were started from... */
1656         if (!defaultCwd) {
1657             /* first time through, use getcwd() to get it... */
1658             if (getcwd(buffer, sizeof(buffer))) {
1659                 defaultCwd = XtMalloc(strlen(buffer) + 1);
1660                 (void) strcpy(defaultCwd, buffer);
1661             }
1662         }
1663         cwd = defaultCwd;
1664     }
1665
1666     (void) sprintf(bufr, "*dtterm_%d*rows: %d\n", cloneNum, rows);
1667     (void) write(fd, bufr, strlen(bufr));
1668     (void) sprintf(bufr, "*dtterm_%d*columns: %d\n", cloneNum, columns);
1669     (void) write(fd, bufr, strlen(bufr));
1670
1671     if(menuBar == False)
1672     {
1673         sprintf(bufr, "*dtterm_%d*menuBar: False\n", cloneNum);
1674         write (fd, bufr, strlen(bufr));
1675     }
1676     if(scrollBar == False)
1677     {
1678         sprintf(bufr, "*dtterm_%d*scrollBar: False\n", cloneNum);
1679         write (fd, bufr, strlen(bufr));
1680     }
1681     if (_DtTermPrimGetCursorVisible((Widget )dtw))
1682     {
1683         if (charCursorStyle == DtTERM_CHAR_CURSOR_BAR)
1684             sprintf(bufr, "*dtterm_%d*charCursorStyle: CHARCURSOR_BAR\n", cloneNum);
1685         else
1686             sprintf(bufr, "*dtterm_%d*charCursorStyle: CHARCURSOR_BOX\n", cloneNum);
1687     }
1688     else 
1689         sprintf(bufr, "*dtterm_%d*charCursorStyle: CHARCURSOR_INVISIBLE\n", cloneNum);
1690     write (fd, bufr, strlen(bufr));
1691     
1692
1693     sprintf(bufr, "*dtterm_%d*blinkRate: %d\n", cloneNum,blinkRate);
1694     write (fd, bufr, strlen(bufr));
1695
1696     if(jumpScroll == False)
1697     {
1698         sprintf(bufr, "*dtterm_%d*jumpScroll: False\n", cloneNum);
1699         write (fd, bufr, strlen(bufr));
1700     }
1701     if(marginBell == True)
1702     {
1703         sprintf(bufr, "*dtterm_%d*marginBell: True\n", cloneNum);
1704         write (fd, bufr, strlen(bufr));
1705         sprintf(bufr, "*dtterm_%d*nMarginBell: %d\n", cloneNum,nMarginBell);
1706         write (fd, bufr, strlen(bufr));
1707     }
1708     if(visualBell == True)
1709     {
1710         sprintf(bufr, "*dtterm_%d*visualBell: True\n", cloneNum);
1711         write (fd, bufr, strlen(bufr));
1712     }
1713     if(reverseVideo == True)
1714     {
1715         sprintf(bufr, "*dtterm_%d*reverseVideo: True\n", cloneNum);
1716         write (fd, bufr, strlen(bufr));
1717     }
1718     if(cursorMode == True)
1719     {
1720         sprintf(bufr, "*dtterm_%d*appCursorDefault: True\n", cloneNum);
1721         write (fd, bufr, strlen(bufr));
1722     }
1723     if(keypadMode == True)
1724     {
1725         sprintf(bufr, "*dtterm_%d*appKeypadDefault: True\n", cloneNum);
1726         write (fd, bufr, strlen(bufr));
1727     }
1728     if(autoWrap == False)
1729     {
1730         sprintf(bufr, "*dtterm_%d*autoWrap: False\n", cloneNum);
1731         write (fd, bufr, strlen(bufr));
1732     }
1733     if(reverseWrap == True)
1734     {
1735         sprintf(bufr, "*dtterm_%d*reverseWrap: True\n", cloneNum);
1736         write (fd, bufr, strlen(bufr));
1737     }
1738     if(c132 == True)
1739     {
1740         sprintf(bufr, "*dtterm_%d*c132: True\n", cloneNum);
1741         write (fd, bufr, strlen(bufr));
1742     }
1743     if(lockState == False)
1744         sprintf(bufr, "*dtterm_%d*userKeyLock: False\n", cloneNum);
1745     else
1746         sprintf(bufr, "*dtterm_%d*userKeyLock: True\n", cloneNum);
1747     write (fd, bufr, strlen(bufr));
1748     if(autoLineFeed == False)
1749         sprintf(bufr, "*dtterm_%d*autoLineFeed: False\n", cloneNum);
1750     else
1751         sprintf(bufr, "*dtterm_%d*autoLineFeed: True\n", cloneNum);
1752     write (fd, bufr, strlen(bufr));
1753
1754     if (cwd && *cwd) {
1755         (void) sprintf(bufr, "*dtterm_%d*currentWorkingDirectory: %s\n",
1756                 cloneNum, cwd);
1757         (void) write(fd, bufr, strlen(bufr));
1758     }
1759     free(bufr);
1760 }
1761
1762 /***********************************************************************
1763  *
1764  * RestoreSession - returns True for success, False for failure...
1765  *
1766  ***********************************************************************/
1767 static Boolean
1768 RestoreSession(
1769             Widget topDog,
1770             Arg *passedAl,
1771             int passedAc)
1772 {
1773     char *fileName = attrs.session;
1774     char *path;
1775     XrmDatabase db;
1776     char *tmpStr;
1777     XrmName xrm_name[5];
1778     XrmRepresentation rep_type;
1779     XrmValue value;
1780     Widget ShellWidget;
1781     int numToRestore, i, j;
1782     Arg                   al[30];
1783     int                   ac;
1784     
1785     if(DtSessionRestorePath(topLevel, &path, fileName) == False)
1786         path = fileName;
1787
1788     /*  Open the file as a resource database */
1789     if ((db = XrmGetFileDatabase (path)) == NULL) 
1790     {
1791       /* if we got a bogus filename, bail out... */
1792       return(False);
1793     }
1794
1795     xrm_name[0] = XrmStringToQuark ("dtterm");
1796     xrm_name[1] = XrmStringToQuark ("numClonedTerms");
1797     xrm_name[2] = 0;
1798     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1799
1800     /* if we got nothing back, bail out... */
1801     if (!value.addr || !*((char *) value.addr)) {
1802         return(False);
1803     }
1804
1805     numToRestore = atoi((char *)value.addr);
1806     /* if we don't have at least one to restore, bail out... */
1807     if (numToRestore < 1) {
1808         return(False);
1809     }
1810
1811     ShellWidget = topDog;
1812         
1813     for (j = 0; j < numToRestore; j++)
1814     {
1815         /* use the passed arglist as a starting point... */
1816         for (ac = 0; ac < passedAc; ac++) {
1817             al[ac].value = passedAl[ac].value;
1818             al[ac].name = passedAl[ac].name;
1819         }
1820
1821         (void) CreateInstance(ShellWidget, "dtTermView", al, ac, True);
1822         RestoreTerm(ShellWidget, instance_list[j], j, db);
1823         (void) XtSetArg(al[0], XmNmappedWhenManaged, True); 
1824         (void) XtSetValues(ShellWidget, al, 1);
1825         /* mapping the shell widget here is redundant, and it turns out
1826          * was responsible for CMVC7216: broken restoring of
1827          * iconified instances in multiple workspaces...
1828          */
1829
1830         ac = 0;
1831         (void) XtSetArg(al[ac], XmNallowShellResize, True); ac++;
1832         (void) XtSetArg(al[ac], XmNmappedWhenManaged, True); ac++;
1833         ShellWidget = XtAppCreateShell((char *) 0, "Dtterm",
1834                     applicationShellWidgetClass, XtDisplay(topDog), al, ac);
1835     }
1836     /* success, return True... */
1837     return(True);
1838 }
1839
1840 static void
1841 RestoreTerm(
1842         Widget shellWidget,
1843         DtTermViewWidget dtvw,
1844         int termNum,
1845         XrmDatabase db)
1846 {
1847     char buf[1024];
1848     XrmName xrm_name[5];
1849     XrmRepresentation rep_type;
1850     XrmValue value;
1851     DtTermWidget dtw = (DtTermWidget )dtvw->termview.term;
1852     Position x,y;
1853     Dimension width, height;
1854     char                  *ws_list;
1855     unsigned char         charCursorStyle;
1856     int                   blinkRate;
1857     Boolean               jumpScroll;
1858     Boolean               marginBell;
1859     int                   nMarginBell;
1860     Boolean               visualBell;
1861     Boolean               reverseVideo;
1862     Boolean               cursorMode;
1863     Boolean               keypadMode;
1864     Boolean               autoWrap;
1865     Boolean               reverseWrap;
1866     Boolean               c132;
1867     Boolean               lockState;
1868     Boolean               autoLineFeed;
1869     Boolean               menuBar;
1870     Boolean               scrollBar;
1871     char                 *cwd;
1872     Arg                   al[30];
1873     int                   ac;
1874     int                   rows = 0;
1875     int                   columns = 0;
1876
1877     sprintf(buf, "dtterm_%d", termNum);
1878     xrm_name[0] = XrmStringToQuark(buf);
1879     xrm_name[2] = 0;
1880
1881 /* Pass 1, before widget realization...
1882  */
1883
1884     /* get x position */
1885     xrm_name[1] = XrmStringToQuark ("x");
1886     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1887     x = atoi((char *)value.addr);
1888
1889     /* get y position */
1890     xrm_name [1] = XrmStringToQuark ("y");
1891     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1892     y = atoi((char *)value.addr);
1893
1894     /* get width */
1895     xrm_name [1] = XrmStringToQuark ("width");
1896     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1897     width = atoi((char *)value.addr);
1898
1899     /* get height */
1900     xrm_name [1] = XrmStringToQuark ("height");
1901     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1902     height = atoi((char *)value.addr);
1903
1904 /****************
1905  *
1906  * First the shell resources...
1907  *
1908  ****************/
1909     ac = 0;
1910     (void) XtSetArg(al[ac], XmNx, x);                   ac++;
1911     (void) XtSetArg(al[ac], XmNy, y);                   ac++;
1912     (void) XtSetArg(al[ac], XmNwidth, width);                   ac++;
1913     (void) XtSetArg(al[ac], XmNheight, height);                 ac++;
1914
1915     /* get iconify... */
1916     xrm_name[1] = XrmStringToQuark("iconify");
1917     if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value)) {
1918         if (!strcmp((char *)value.addr, "True")) {
1919             (void) XtSetArg(al[ac], XmNinitialState, IconicState); ac++;
1920         } else {
1921             (void) XtSetArg(al[ac], XmNinitialState, NormalState); ac++;
1922         }
1923     } else {
1924         (void) XtSetArg(al[ac], XmNinitialState, NormalState);
1925     }
1926
1927     (void) XtSetValues(XtParent((Widget)dtvw), al, ac);
1928
1929 /****************
1930  *
1931  * Now the TermView resources...
1932  *
1933  ****************/
1934     ac = 0;
1935     xrm_name[1] = XrmStringToQuark ("rows");
1936     if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value)) {
1937         rows = atoi((char *)value.addr);
1938         (void) XtSetArg(al[ac], DtNrows, rows); ac++;
1939     }
1940
1941     xrm_name[1] = XrmStringToQuark ("columns");
1942     if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value)) {
1943         columns = atoi((char *)value.addr);
1944         (void) XtSetArg(al[ac], DtNcolumns, columns); ac++;
1945     }
1946
1947     xrm_name[1] = XrmStringToQuark ("menuBar");
1948     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
1949         {(void) XtSetArg(al[ac], XmNmenuBar, False);    ac++;}
1950     xrm_name[1] = XrmStringToQuark ("scrollBar");
1951     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
1952         {(void) XtSetArg(al[ac], DtNscrollBar, False);  ac++;}
1953
1954     xrm_name[1] = XrmStringToQuark ("userFontListIndex");
1955     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True) {
1956         _DtTermViewSetUserFontListIndex((Widget )dtvw, atol(value.addr));
1957     }
1958
1959     (void) XtSetValues((Widget)dtvw, al, ac);
1960
1961 /****************
1962  *
1963  * And finally the termprim stuff...
1964  *
1965  ****************/
1966     ac = 0;
1967     if(rows > 0) {
1968         (void) XtSetArg(al[ac], DtNrows, rows); ac++;
1969     }
1970
1971     if(columns > 0) {
1972         (void) XtSetArg(al[ac], DtNcolumns, columns); ac++;
1973     }
1974
1975     xrm_name[1] = XrmStringToQuark ("charCursorStyle");
1976     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1977     if (!strcmp(value.addr, "CHARCURSOR_INVISIBLE"))
1978         _DtTermPrimSetCursorVisible((Widget )dtw, False);
1979     else  
1980     {
1981         if (!strcmp(value.addr, "CHARCURSOR_BAR"))
1982               (void) XtSetArg(al[ac], DtNcharCursorStyle, DtTERM_CHAR_CURSOR_BAR);
1983         else 
1984               (void) XtSetArg(al[ac], DtNcharCursorStyle, DtTERM_CHAR_CURSOR_BOX);
1985         ac++;
1986     }
1987     
1988     xrm_name [1] = XrmStringToQuark ("blinkRate");
1989     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1990     blinkRate = atoi((char *)value.addr);
1991     (void) XtSetArg(al[ac], DtNblinkRate, blinkRate);                   ac++;
1992
1993     xrm_name[1] = XrmStringToQuark ("jumpScroll");
1994     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
1995         {(void) XtSetArg(al[ac], DtNjumpScroll, False); ac++;}
1996
1997     xrm_name[1] = XrmStringToQuark ("marginBell");
1998     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
1999     {
2000         (void) XtSetArg(al[ac], DtNmarginBell, True);   ac++;
2001          xrm_name [1] = XrmStringToQuark ("nMarginBell");
2002          XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
2003          nMarginBell = atoi((char *)value.addr);
2004          (void) XtSetArg(al[ac], DtNnMarginBell, nMarginBell);ac++;
2005     }
2006
2007     xrm_name[1] = XrmStringToQuark ("visualBell");
2008     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2009         {(void) XtSetArg(al[ac], DtNvisualBell, True);  ac++;}
2010
2011     xrm_name[1] = XrmStringToQuark ("reverseVideo");
2012     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2013         {(void) XtSetArg(al[ac], DtNreverseVideo, True);        ac++;}
2014
2015     xrm_name[1] = XrmStringToQuark ("appCursorDefault");
2016     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2017         {(void) XtSetArg(al[ac], DtNappCursorDefault, True);    ac++;}
2018
2019     xrm_name[1] = XrmStringToQuark ("appKeypadDefault");
2020     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2021         {(void) XtSetArg(al[ac], DtNappKeypadDefault, True);    ac++;}
2022
2023     xrm_name[1] = XrmStringToQuark ("autoWrap");
2024     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2025         {(void) XtSetArg(al[ac], DtNautoWrap, False);   ac++;}
2026
2027     xrm_name[1] = XrmStringToQuark ("reverseWrap");
2028     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2029         {(void) XtSetArg(al[ac], DtNreverseWrap, True); ac++;}
2030
2031     xrm_name[1] = XrmStringToQuark ("c132");
2032     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2033         {(void) XtSetArg(al[ac], DtNc132, True);        ac++;}
2034
2035     xrm_name[1] = XrmStringToQuark ("reverseVideo");
2036     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2037         {(void) XtSetArg(al[ac], DtNreverseVideo, True);        ac++;}
2038
2039     xrm_name[1] = XrmStringToQuark ("userKeyLock");
2040     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
2041     if (!strcmp(value.addr, "True"))
2042          _DtTermSetUserKeyLock((Widget) dtw, True);
2043     else 
2044          _DtTermSetUserKeyLock((Widget) dtw, False);
2045
2046     xrm_name[1] = XrmStringToQuark ("autoLineFeed");
2047     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
2048     if (!strcmp(value.addr, "True"))
2049          _DtTermSetAutoLineFeed((Widget) dtw, True);
2050     else 
2051          _DtTermSetAutoLineFeed((Widget) dtw, False);
2052
2053     (void) XtSetValues((Widget)dtw, al, ac);
2054
2055     xrm_name[1] = XrmStringToQuark ("currentWorkingDirectory");
2056     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
2057     if (value.addr && *value.addr) {
2058         _DtTermSetCurrentWorkingDirectory((Widget) dtw, value.addr);
2059     }
2060
2061     /* realize the interface...
2062      */
2063     (void) XtRealizeWidget(shellWidget);
2064
2065
2066
2067 /* Pass 2, after widget realization...
2068  */
2069
2070     /* get workspace list */
2071     xrm_name[1] = XrmStringToQuark("workspaceList");
2072     XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value);
2073     SetWorkSpaceHints( XtParent((Widget)dtvw),(char *) value.addr);
2074 }
2075
2076 static void
2077 SetWorkSpaceHints
2078 (
2079     Widget shell,
2080     char *workspaces
2081 )
2082 {
2083     char * ptr;
2084     Atom * workspace_atoms = NULL;
2085     int num_workspaces=0;
2086     Atom thisWsAtom;
2087
2088     if (workspaces) {
2089         do {
2090             ptr = strchr (workspaces, ' ');
2091             if (ptr != NULL)
2092                 *ptr = 0;
2093             thisWsAtom = None;
2094
2095             /* if we haven't hit a match, try interning the atom... */
2096             if (thisWsAtom == None) {
2097                 thisWsAtom = XmInternAtom (XtDisplay(shell), workspaces, True);
2098             }
2099
2100             if (thisWsAtom != None) {
2101                 workspace_atoms = (Atom *) XtRealloc ((char *)workspace_atoms,
2102                         sizeof (Atom) * (num_workspaces + 1));
2103                 workspace_atoms[num_workspaces] = thisWsAtom;
2104                 num_workspaces++;
2105             }
2106
2107             if (ptr != NULL) {
2108                 *ptr = ' ';
2109                 workspaces = ptr + 1;
2110             }
2111         } while (ptr != NULL);
2112
2113         if (num_workspaces > 0) {
2114             DtWsmSetWorkspacesOccupied(XtDisplay(shell), XtWindow (shell),
2115                     workspace_atoms, num_workspaces);
2116         }
2117
2118         XtFree ((char *) workspace_atoms);
2119         workspace_atoms = NULL;
2120     }
2121 }