d3b02c7d1204153839c86221b066491c05f6e6e0
[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 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 #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 void 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 void 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;
539     if (cm->message_type != xa_DTTERM_REMOTE_PROBE_REQUEST) return;
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 #ifdef SUN_TERMINAL_SERVER
835     return(True);
836 #endif
837 }
838
839 void
840 AtExitProc(void)
841 {
842     static int i = 0;
843
844     i++;
845 #ifdef  BBA
846     _bA_dump();
847 #endif  /* BBA */
848 }
849
850 void
851 SignalHandler
852 (
853     int                   sig
854 )
855 {
856     DebugF('s', 10, fprintf(stderr, ">>SignalHandler() starting\n"));
857     _DtTermPrimPtyCleanup();
858     _DtTermPrimUtmpCleanup();
859     _DtTermPrimLogFileCleanup();
860     DebugF('s', 10, fprintf(stderr, ">>SignalHandler() finished\n"));
861     (void) exit(0);
862 }
863
864 static int signalList[] = {
865     SIGHUP,
866     SIGINT,
867     SIGQUIT,
868     /* SIGILL, */
869     /* SIGTRAP, */
870     /* SIGABRT, */
871     /* SIGIOT, */
872     /* SIGEMT, */
873     /* SIGFPE, */
874     SIGKILL,
875     /* SIGBUS, */
876     /* SIGSEGV, */
877     /* SIGSYS, */
878     SIGPIPE,
879     SIGALRM,
880     SIGTERM,
881     SIGUSR1,
882     SIGUSR2,
883     /* SIGVTALRM, */
884     /* SIGPROF, */
885     /* SIGLOST, */
886 };
887
888 static Boolean
889 GetBindingsProperty
890 (
891     Display              *display,
892     String                property,
893     String               *binding
894 )
895 {
896     char                 *prop = (char *) 0;
897     Atom                  actualType;
898     int                   actualFormat;
899     unsigned long         numItems;
900     unsigned long         bytesAfter;
901
902     (void) XGetWindowProperty(display,
903             RootWindow(display, 0),
904             XmInternAtom(display, property, FALSE),
905             0,
906             (long) 1000000,
907             FALSE,
908             XA_STRING,
909             &actualType,
910             &actualFormat,
911             &numItems,
912             &bytesAfter,
913             (unsigned char **) &prop);
914
915     if ((actualType != XA_STRING) ||
916             (actualFormat != 8) ||
917             (numItems == 0)) {
918         if (prop) {
919             XFree(prop);
920         }
921         return(False);
922     } else {
923         *binding = prop;
924         return(True);
925     }
926 }
927
928 #ifndef XmNdefaultVirtualBindings
929 #define XmNdefaultVirtualBindings       "defaultVirtualBindings"
930 #endif  /* XmNdefaultVirtualBindings */
931 static void
932 FixOSFBindings
933 (
934     Display              *display
935 )
936 {
937     Widget                w;
938     Arg                   al[10];
939     int                   ac;
940     char                 *origDisplayBindings,*freeOrigBindings=NULL;
941     char                 *newDisplayBindings;
942     char                 *c1;
943     char                 *c2;
944     char                 *cHold;
945     int                   i1;
946     char                **ignoredKeysymList;
947     int                   numIgnoredKeysyms;
948     
949     /* malloc a copy of the ignoredKeysym string... */
950     if (attrs.ignoredKeysyms && *attrs.ignoredKeysyms) {
951         c1 = XtMalloc(strlen(attrs.ignoredKeysyms) + 1);
952         (void) strcpy(c1, attrs.ignoredKeysyms);
953         attrs.ignoredKeysyms = c1;
954     }
955
956     /* count the number of keysyms in the list... */
957     for (c1 = attrs.ignoredKeysyms, numIgnoredKeysyms = 0; c1 && *c1; ) {
958         numIgnoredKeysyms++;
959         c1 = strchr(c1, '\n');
960         if (c1) {
961             (void) c1++;
962         }
963     }
964
965     /* malloc space for the array... */
966     ignoredKeysymList = (char **) XtMalloc((numIgnoredKeysyms + 1) *
967             sizeof(char *));
968
969     /* build the list... */
970     for (c1 = attrs.ignoredKeysyms, i1 = 0; i1 < numIgnoredKeysyms; i1++) {
971         ignoredKeysymList[i1] = c1;
972         c1 = strchr(c1, '\n');
973         if (c1 && *c1) {
974             *c1++ = '\0';
975         }
976     }
977
978     /* null terminate the list... */
979     ignoredKeysymList[i1] = (char *) 0;
980
981
982     w = XmGetXmDisplay(display);
983
984     ac = 0;
985     (void) XtSetArg(al[ac], XmNdefaultVirtualBindings, &origDisplayBindings);
986             ac++;
987     (void) XtGetValues(w, al, ac);
988
989     if (!origDisplayBindings) {
990         GetBindingsProperty(display, "_MOTIF_BINDINGS", &origDisplayBindings);
991         freeOrigBindings = origDisplayBindings ;
992     }
993
994     if (!origDisplayBindings) {
995         GetBindingsProperty(display, "_MOTIF_DEFAULT_BINDINGS",
996                 &origDisplayBindings);
997         freeOrigBindings = origDisplayBindings ;
998     }
999
1000     if (!origDisplayBindings) {
1001         if (ignoredKeysymList) XtFree((char *)ignoredKeysymList);
1002         return;
1003     }
1004
1005     DebugF('b', 10, fprintf(stderr,
1006             "FixOSFBindings(): bindings: %s\n", origDisplayBindings));
1007     newDisplayBindings = XtMalloc(strlen(origDisplayBindings) + 1);
1008     c1 = origDisplayBindings;
1009     c2 = newDisplayBindings;
1010     while (*c1) {
1011         /* remember the current position in the new string... */
1012         cHold = c2;
1013
1014         /* copy over everything up to the '\n' or null... */
1015         while (*c1 && (*c1 != '\n')) {
1016             *c2++ = *c1++;
1017         }
1018
1019         /* null terminate the string... */
1020         *c2 = '\0';
1021
1022         /* run through the exclusion list and look for a match... */
1023         for (i1 = 0; i1 < numIgnoredKeysyms; i1++) {
1024             DebugF('b', 10, fprintf(stderr, "!strcmp(\"%s\", \"%s\") = %d\n",
1025                     c2 - strlen(ignoredKeysymList[i1]),
1026                     ignoredKeysymList[i1],
1027                     !strcmp(c2 - strlen(ignoredKeysymList[i1]),
1028                     ignoredKeysymList[i1])));
1029             if ((strlen(ignoredKeysymList[i1]) <= (size_t)(c2 - cHold)) &&
1030                     !strcmp(c2 - strlen(ignoredKeysymList[i1]),
1031                     ignoredKeysymList[i1])) {
1032                 /* we hit a match... */
1033                 DebugF('b', 10, fprintf(stderr, "match!\n"));
1034                 break;
1035             }
1036         }
1037
1038         /* if we hit a match, back up the string... */
1039         if (i1 < numIgnoredKeysyms) {
1040             DebugF('b', 10, fprintf(stderr, "dropping %s\n", cHold));
1041             c2 = cHold;
1042             /* skip over whitespace in the source... */
1043             while (isspace(*c1)) {
1044                 c1++;
1045             }
1046         } else {
1047             /* copy over whitespace in the source... */
1048             DebugF('b', 10, fprintf(stderr, "keeping %s\n", cHold));
1049             while (isspace(*c1)) {
1050                 *c2++ = *c1++;
1051             }
1052             cHold = c2;
1053         }
1054     }
1055
1056     /* null terminate the string... */
1057     *c2 = '\0';
1058
1059     /* and set this new bindings string... */
1060     ac = 0;
1061     (void) XtSetArg(al[ac], XmNdefaultVirtualBindings, newDisplayBindings);
1062             ac++;
1063     (void) XtSetValues(w, al, ac);
1064
1065   /* changed from XtFree to free as it was allocated with malloc to avoid FMM */
1066     if (freeOrigBindings) free(origDisplayBindings);
1067
1068     XtFree((char *)ignoredKeysymList);
1069
1070     /* and finally, reparse the string... */
1071     _XmVirtKeysInitialize(w);
1072 }
1073
1074 static void
1075 removeWmCommandCallback
1076 (
1077     Widget                w,
1078     XtPointer             clientData,
1079     XEvent               *event,
1080     Boolean              *cont
1081 )
1082 {
1083     static Atom           xa_WM_STATE = None;
1084     Boolean               firstTime = True;
1085
1086     if (firstTime) {
1087         xa_WM_STATE = XInternAtom(XtDisplay(w), "WM_STATE", True);
1088         firstTime = False;
1089     }
1090
1091     if (((XPropertyEvent *) event)->atom == xa_WM_STATE) {
1092         /* blow away the atom... */
1093         (void) XDeleteProperty(XtDisplay(w), XtWindow(w),
1094                 XA_WM_COMMAND);
1095
1096         /* we have done our job and don't need to be called again... */
1097         (void) XtRemoveEventHandler(w, (EventMask) XtAllEvents,
1098                 True, removeWmCommandCallback, clientData);
1099     }
1100 }
1101
1102 static char *
1103 base_name(
1104      char *name
1105 )
1106 {
1107         register char *cp;
1108
1109         cp = strrchr(name, '/');
1110         return(cp ? cp + 1 : name);
1111 }
1112
1113 int
1114 main(int argc, char **argv)
1115 {
1116     Arg                   arglist[20];
1117     int                   i;
1118     char                 *c;
1119     char                 *c2;
1120     char                 *saved_arg0;
1121     char                **commandToExecute = (char **) 0;
1122     int                   ptyMasterFd = -1;
1123     struct sigaction      sa;
1124 #ifdef SUN_TERMINAL_SERVER
1125     Boolean               iAmTheServer = False;
1126 #endif /* SUN_TERMINAL_SERVER */
1127     
1128     (void) atexit(AtExitProc);
1129
1130     if (c = getenv("dttermDebugFlags")) {
1131         (void) setDebugFlags(c);
1132     }
1133     if (isDebugSet('T')) {
1134 #ifdef  BBA
1135 #pragma BBA_IGNORE
1136 #endif  /*BBA*/
1137         (void) timeStamp("starting");
1138     }
1139
1140     if (c = getenv("dttermDelayFlags"))
1141     {
1142         if (NULL != c)
1143         {
1144             int delay = atoi(c);
1145             pid_t pid = getpid();
1146             printf("dtterm (%d) sleeping for %d seconds\n", pid, delay);
1147             sleep(delay);
1148         }
1149     }
1150
1151     /* before we do anything, let's set up signal handlers to clean up
1152      * after ourself...
1153      */
1154     (void) sigemptyset(&sa.sa_mask);
1155     sa.sa_flags = 0;
1156
1157     sa.sa_handler = SignalHandler;
1158     /* trap all signals that we want to clean up after... */
1159     for (i = 0; i < (sizeof(signalList) / sizeof(signalList[0])); i++) {
1160         (void) sigaction(signalList[i], &sa, (struct sigaction *) 0);
1161     }
1162
1163     /* ignore SIGHUP... */
1164     sa.sa_handler = SIG_IGN;
1165     (void) sigaction(SIGHUP, &sa, (struct sigaction *) 0);
1166
1167     /*
1168     ** set up the environment variables for this client...
1169     */
1170 #if defined(HPVUE)
1171 #if       (OSMINORVERSION > 01)
1172     VuEnvControl(VUE_ENV_SET);
1173 #endif /* (OSMINORVERSION > 01) */
1174 #else
1175     _DtEnvControl(DT_ENV_SET);
1176 #endif   /* HPVUE */
1177
1178     /* set up the I18N world... */
1179     (void) XtSetLanguageProc(NULL, NULL, NULL);
1180
1181     if (isDebugSet('T')) {
1182 #ifdef  BBA
1183 #pragma BBA_IGNORE
1184 #endif  /*BBA*/
1185         (void) timeStamp("XtSetLangProc() finished");
1186     }
1187
1188     /* before we initialize Xt, let's save argv and argc... */
1189     savedArgc = argc;
1190     savedArgv = (char **) XtMalloc((argc + 1) * sizeof(char *));
1191     for (i = 0; i < argc; i++) {
1192         savedArgv[i] = XtMalloc(strlen(argv[i]) + 1);
1193         (void) strcpy(savedArgv[i], argv[i]);
1194 #ifdef SUN_TERMINAL_SERVER
1195         if ((!strcmp(argv[i], "-sdtserver")) || (!strcmp(argv[i], "-dtserver")))
1196             iAmTheServer = TRUE;
1197 #endif /* SUN_TERMINAL_SERVER */
1198     }
1199     savedArgv[i] = (char *) 0;
1200
1201 #ifdef sun
1202     (void) setsid();
1203 #endif /* sun */
1204
1205
1206     /* before we do anything with the toolkit, let's usurp the constraint
1207      * initialize proc for the XmManager widget class.  This will allow us
1208      * to prevent it from performing that awful
1209      * DoMagicBBCompatibilityStuff() on us that steals (among other things)
1210      * our return key.  Note that currently, this is all that the
1211      * XmManager widget does for widgets, but if it did more than we
1212      * would loose out on that.
1213      */
1214     /* initialize Xt and the X world... */
1215     (void) DtTermInitialize();
1216
1217     i = 0;
1218     (void) XtSetArg(arglist[i], XmNallowShellResize, True); i++;
1219
1220     topLevel = XtAppInitialize(&appContext,
1221             "Dtterm",
1222             optionDescList,
1223             XtNumber(optionDescList),
1224             &argc,
1225             argv,
1226             fallbackResources,
1227             arglist,
1228             i);
1229
1230 #ifdef SUN_TERMINAL_SERVER
1231     if (iAmTheServer) {
1232        (void) ServerStartSession(topLevel, savedArgc, savedArgv,
1233                 attrs.loginShell,
1234                 commandToExecute);
1235     } 
1236 #endif /* SUN_TERMINAL_SERVER */
1237
1238     /* get application specific resources... */
1239     i = 0;
1240     /* Need to specify base address of the resources. In our case, attrs */
1241     (void) XtGetApplicationResources(topLevel, (XtPointer)&attrs, 
1242                                      applicationResources,
1243                                      XtNumber(applicationResources), 
1244                                      arglist, i);    
1245
1246     /* set all the debug flags... */
1247     (void) setDebugFlags(attrs.debugString);
1248     
1249     (void) FixOSFBindings(XtDisplay(topLevel));
1250
1251     /* Add the Save_yourself callback... */
1252     xa_WM_SAVE_YOURSELF = XInternAtom(XtDisplay(topLevel),
1253                                       "WM_SAVE_YOURSELF", False);
1254     XmAddWMProtocolCallback(topLevel, xa_WM_SAVE_YOURSELF,
1255                            (XtCallbackProc)SaveSessionCB, (XtPointer)NULL);
1256     
1257     i = 0;
1258     (void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
1259     (void) XtSetArg(arglist[i], XmNallowShellResize, True); i++;
1260     topShell = XtAppCreateShell((char *) 0, "Dtterm",
1261                 applicationShellWidgetClass, XtDisplay(topLevel), arglist, i);
1262
1263     if (attrs.session != NULL)
1264        RestoringTerms = TRUE;
1265
1266     if (isDebugSet('T')) {
1267 #ifdef  BBA
1268 #pragma BBA_IGNORE
1269 #endif  /*BBA*/
1270         (void) timeStamp("XtAppInitialize() finished");
1271     }
1272
1273     for (i = 1; i < argc; i++) {
1274         if (argv[i][0] != '-') {
1275             (void) Syntax(argv[0], argv[i]);
1276             exit(1);
1277         }
1278
1279         switch(argv[i][1]) {
1280         case 'S' :
1281             /* slave mode...
1282              */
1283             /* skip past the '-S'... */
1284             c = argv[i] + 2;
1285             if (c2 = strchr(c, '.')) {
1286                 /* skip past the '.'... */
1287                 (void) c2++;
1288             } else {
1289                 /* skip past the first 2 characters since they are the
1290                  * name of the pty...
1291                  */
1292                 c2 = c + 2;
1293             }
1294             /* use scanf instead of atoi since it won't change the value
1295              * of ptyMasterFd if the string does not contain a valid
1296              * number...
1297              */
1298             (void) sscanf(c2, "%d", &ptyMasterFd);
1299             break;
1300
1301         case 'e' :
1302             /* command to exec...
1303              */
1304             (void) i++;
1305             if (i < argc) {
1306                 commandToExecute = &argv[i];
1307                 i = argc;
1308             }
1309             break;
1310         case 'h' :
1311         case 'u' :
1312             /* help/usage...
1313              */
1314             (void) Help(argv[0]);
1315             exit(0);
1316             break;
1317
1318         default :
1319             (void) Syntax(argv[0], argv[i]);
1320             (void) exit(1);
1321             break;
1322         }
1323     }
1324
1325 #ifdef  TERMINAL_SERVER
1326     if (attrs.standAlone || !attrs.serverId) {
1327 #endif  /* TERMINAL_SERVER */
1328         /* log our startup... */
1329 #ifdef  LOG_USAGE
1330         (void) LogStart(0, argc, argv);
1331 #endif  /* LOG_USAGE */
1332
1333         i = 0;
1334         if (commandToExecute) {     
1335             (void) XtSetArg(arglist[i], DtNsubprocessArgv, commandToExecute);
1336                     i++;
1337         }
1338         
1339         if (!RestoringTerms || !RestoreSession(topShell, arglist, i)) {
1340
1341             RestoringTerms = False;
1342
1343             if (ptyMasterFd >= 0) {
1344                 /* set the workspace for the initial dtterm instance... */
1345                 (void) XtSetArg(arglist[i], DtNtermDevice, ptyMasterFd); i++;
1346                 (void) XtSetArg(arglist[i], DtNtermDeviceAllocate, False); i++;
1347                 (void) XtSetArg(arglist[i], DtNsubprocessExec, False); i++;
1348                 (void) CreateInstance(topShell, "dtTermView", arglist, i, False);
1349             } 
1350             else {
1351                 (void) CreateInstance(topShell, "dtTermView", arglist, i, True);
1352             }
1353         }
1354
1355         /* realize the interface... */
1356         i = 0;
1357         (void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
1358         (void) XtSetValues(topLevel, arglist, i);
1359         (void) XtRealizeWidget(topLevel);
1360
1361 #ifdef SUN_TERMINAL_SERVER
1362         if (iAmTheServer)
1363             FinishToolTalkInit(topLevel);
1364 #endif /* SUN_TERMINAL_SERVER */
1365
1366         /* Set title to the command to execute (if any) 
1367          */
1368         if (commandToExecute && !attrs.title) {
1369            attrs.title = base_name (commandToExecute[0]);
1370         }
1371
1372         /* Else set title to default ("Terminal")
1373          */
1374         if (!attrs.title) {         
1375             title = XtMalloc(strlen(GETMESSAGE(NL_SETN_Main, 3, "Terminal")) + 1);
1376             (void) strcpy(title, GETMESSAGE(NL_SETN_Main, 3, "Terminal"));
1377             attrs.title = title;
1378         }
1379
1380         /* realize the interface... */
1381         i = 0;
1382     (void) XtSetArg(arglist[i], XmNtitle, attrs.title); i++;
1383         if ((!attrs.icon_name) && (!attrs.dtterm_name)) {
1384           (void) XtSetArg(arglist[i], XmNiconName, attrs.title); i++;
1385         }
1386         (void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
1387         (void) XtSetArg(arglist[i], XmNgeometry, NULL); i++;
1388         (void) XtSetValues(topShell, arglist, i);
1389         (void) XtRealizeWidget(topShell);
1390
1391         if (RestoringTerms != True) {
1392             /* use the wm command to pass the -xrm resource to the wm... */
1393             (void) XSetCommand(XtDisplay(topShell), XtWindow(topShell),
1394                     savedArgv, savedArgc);
1395             /* add a callback to remove it after it has been seen... */
1396             (void) XtAddEventHandler(topShell, (EventMask) PropertyChangeMask,
1397                     False, removeWmCommandCallback, (XtPointer) 0);
1398         }
1399
1400         (void) XtSetArg(arglist[0], XmNmappedWhenManaged, True); 
1401         (void) XtSetValues(topShell, arglist, 1);
1402         XtMapWidget(topShell);
1403         RegisterTestProbe(topShell,instance_list[0]);
1404         
1405         if (ptyMasterFd >= 0) {
1406             /* write out the window id... */
1407             char buffer[BUFSIZ];
1408
1409             (void) sprintf(buffer, "%lx\n", XtWindow(topLevel));
1410             (void) write(ptyMasterFd, buffer, strlen(buffer));
1411         }
1412 #ifdef sun
1413         sunSetupIA(topLevel);
1414 #endif /* sun */
1415
1416 #ifdef  TERMINAL_SERVER
1417     } else {
1418         if (ptyMasterFd >= 0) {
1419             (void) fprintf(stderr,
1420                     GETMESSAGE(NL_SETN_Main,2, "%s: the -S option cannot be used with the -server or -serverid options\n"),
1421                     argv[0]);
1422             (void) exit(1);
1423         }
1424
1425         i = 0;
1426         (void) XtSetArg(arglist[i], XmNmappedWhenManaged, False); i++;
1427         (void) XtSetValues(topLevel, arglist, i);
1428         (void) XtRealizeWidget(topLevel);
1429
1430         (void) ServerStartSession(topLevel, savedArgc, savedArgv,
1431                 attrs.server, attrs.serverId, attrs.exitOnLastClose, 
1432                 attrs.block, attrs.loginShell,
1433                 commandToExecute);
1434     }
1435 #endif  /* TERMINAL_SERVER */
1436
1437     /* and hand off to Xt... */
1438     (void) XtAppMainLoop(appContext);
1439 }
1440
1441 /************************************************************************
1442  *
1443  *  SaveSessionCB 
1444  *
1445  ************************************************************************/
1446
1447 /* ARGSUSED */
1448 static void 
1449 SaveSessionCB(
1450         Widget w,                       /* widget id */
1451         caddr_t client_data,            /* data from application  */
1452         caddr_t call_data )             /* data from widget class */
1453 {
1454     char *longpath, *fileName;
1455     char bufr[1024];
1456     int fd;
1457     char *xa_CommandStr[1024];
1458     int i,j;
1459     
1460      if(!XtIsShell(w))
1461         w = XtParent(w);
1462
1463     DtSessionSavePath(w, &longpath, &fileName);
1464
1465     /*  Create the session file  */
1466     if ((fd = creat (longpath, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP)) == -1)
1467     {
1468         return;
1469     }
1470
1471     sprintf(bufr, "*dtterm.numClonedTerms: %d\n", InstanceCount);
1472     write (fd, bufr, strlen(bufr));
1473
1474     for(i = 0; i < InstanceCount; i++)
1475         SaveTerm(instance_list[i], i, fd);
1476
1477     sprintf(bufr,
1478           "*dtterm.sessionFileVersionId: dttermSessionFileVersion.1.0.0\n");
1479     write (fd, bufr, strlen(bufr));
1480
1481     close(fd);
1482
1483     i = 0;
1484     xa_CommandStr[i] = savedArgv[0]; i++;
1485     xa_CommandStr[i] =  "-session"; i++;
1486     xa_CommandStr[i] =  fileName; i++;
1487 /****************
1488  *
1489  * Now restore the command line minus the old session parameter 
1490  *
1491  ****************/
1492     for (j = 1; j < savedArgc; j++)
1493     {
1494         if (strcmp(savedArgv[j], "-session") == 0)
1495         {
1496             j++;
1497             continue;
1498         }
1499         else
1500         {
1501             xa_CommandStr[i] =  savedArgv[j];
1502             i++;
1503         }
1504     }
1505
1506     XSetCommand(XtDisplay(topLevel), 
1507                 XtWindow(topLevel), xa_CommandStr, i);
1508
1509
1510     XtFree ((char *)fileName);
1511 }
1512
1513 static void 
1514 SaveTerm(
1515         DtTermViewWidget dtvw,
1516         int cloneNum,
1517         int fd)
1518 {
1519     char *bufr = malloc(1024);
1520     Position x,y;
1521     Dimension width, height;
1522     Atom *pWsPresence;
1523     unsigned long numInfo;
1524     unsigned char         charCursorStyle;
1525     int                   blinkRate;
1526     Boolean               jumpScroll;
1527     Boolean               marginBell;
1528     int                   nMarginBell;
1529     Boolean               visualBell;
1530     Boolean               reverseVideo;
1531     Boolean               cursorMode;
1532     Boolean               keypadMode;
1533     Boolean               autoWrap;
1534     Boolean               reverseWrap;
1535     Boolean               c132;
1536     Boolean               lockState;
1537     Boolean               autoLineFeed;
1538     Boolean               menuBar;
1539     Boolean               scrollBar;
1540     short                 rows;
1541     short                 columns;
1542     char                 *cwd;
1543     static char          *defaultCwd = (char *) 0;
1544     Arg                   al[30];
1545     int                   ac;
1546     char                  buffer[BUFSIZ];
1547     DtTermWidget dtw = (DtTermWidget )dtvw->termview.term;
1548     static Boolean        firstTime = True;
1549     static Atom           xa_WM_STATE = None;
1550     struct _wmStateStruct {
1551         CARD32            state;
1552         Window            icon;
1553     }                    *prop;
1554     Atom                  actualType;
1555     int                   actualFormat;
1556     unsigned long         nItems;
1557     unsigned long         bytesAfter;
1558
1559     XmVendorShellExtObject vendorExt;
1560     XmWidgetExtData        extData;
1561
1562     x = XtX(XtParent(dtvw));
1563     y = XtY(XtParent(dtvw));
1564
1565     /*
1566      * Modify x & y to take into account window mgr frames
1567      * This is pretty bogus, but I don't know a better way to do it.
1568      */
1569     extData = _XmGetWidgetExtData(XtParent(dtvw), XmSHELL_EXTENSION);
1570     vendorExt = (XmVendorShellExtObject)extData->widget;
1571     x -= vendorExt->vendor.xOffset;
1572     y -= vendorExt->vendor.yOffset;
1573     width = XtWidth(XtParent(dtvw));
1574     height = XtHeight(XtParent(dtvw));
1575
1576     sprintf(bufr, "*dtterm_%d.x: %d\n", cloneNum, x);
1577     sprintf(bufr, "%s*dtterm_%d.y: %d\n", bufr, cloneNum, y);
1578     sprintf(bufr, "%s*dtterm_%d.width: %d\n", bufr, cloneNum, width);
1579     sprintf(bufr, "%s*dtterm_%d.height: %d\n", bufr, cloneNum, height);
1580
1581     /* Write out iconic state...
1582      */
1583     if (firstTime) {
1584         xa_WM_STATE = XInternAtom(XtDisplay(dtvw), "WM_STATE", True);
1585         firstTime = False;
1586     }
1587     if (xa_WM_STATE && (Success == XGetWindowProperty(
1588             XtDisplay(dtvw),
1589             XtWindow(XtParent(dtvw)),
1590             xa_WM_STATE,
1591             0L,
1592             (sizeof(struct _wmStateStruct) + 3) / 4,
1593             False,
1594             AnyPropertyType,
1595             &actualType,
1596             &actualFormat,
1597             &nItems,
1598             &bytesAfter,
1599             (unsigned char **) &prop))) {
1600         if (prop->state == IconicState) {
1601             sprintf(bufr, "%s*dtterm_%d.iconify: %s\n", bufr, cloneNum,
1602                     "True");
1603         } else {
1604             sprintf(bufr, "%s*dtterm_%d.iconify: %s\n", bufr, cloneNum,
1605                     "False");
1606         }
1607     }
1608         
1609     if(DtWsmGetWorkspacesOccupied(XtDisplay(dtvw), 
1610                                   XtWindow(XtParent(dtvw)), &pWsPresence,
1611                                   &numInfo) == Success)
1612     {
1613         int i;
1614         sprintf(bufr, "%s*dtterm_%d.workspaceList: ", bufr, cloneNum);
1615         for(i = 0; i < numInfo; i++)
1616         {
1617             char *name =  XGetAtomName(XtDisplay(dtvw),
1618                                        pWsPresence[i]);
1619             sprintf(bufr, "%s %s", bufr, name);
1620             XtFree(name);
1621         }
1622         sprintf(bufr, "%s\n", bufr);
1623         XtFree((char *)pWsPresence);
1624     }
1625
1626     write (fd, bufr, strlen(bufr));
1627
1628     sprintf(bufr, "*dtterm_%d.userFontListIndex: %d\n", cloneNum,
1629             _DtTermViewGetUserFontListIndex((Widget )dtvw));
1630     write (fd, bufr, strlen(bufr));
1631
1632     /* get the current widget values... */
1633     ac = 0;
1634     (void) XtSetArg(al[ac], DtNmenuBar, &menuBar);                      ac++;
1635     (void) XtSetArg(al[ac], DtNscrollBar, &scrollBar);                  ac++;
1636     (void) XtGetValues((Widget)dtvw, al, ac);
1637     ac = 0;
1638     (void) XtSetArg(al[ac], DtNrows, &rows);                            ac++;
1639     (void) XtSetArg(al[ac], DtNcolumns, &columns);                      ac++;
1640     (void) XtSetArg(al[ac], DtNblinkRate, &blinkRate);                  ac++;
1641     (void) XtSetArg(al[ac], DtNcharCursorStyle, &charCursorStyle);      ac++;
1642     (void) XtSetArg(al[ac], DtNblinkRate, &blinkRate);                  ac++;
1643     (void) XtSetArg(al[ac], DtNjumpScroll, &jumpScroll);                ac++;
1644     (void) XtSetArg(al[ac], DtNmarginBell, &marginBell);                ac++;
1645     (void) XtSetArg(al[ac], DtNnMarginBell, &nMarginBell);              ac++;
1646     (void) XtSetArg(al[ac], DtNvisualBell, &visualBell);                ac++;
1647     (void) XtSetArg(al[ac], DtNreverseVideo, &reverseVideo);            ac++;
1648     (void) XtSetArg(al[ac], DtNappCursorDefault, &cursorMode);          ac++;
1649     (void) XtSetArg(al[ac], DtNappKeypadDefault, &keypadMode);          ac++;
1650     (void) XtSetArg(al[ac], DtNautoWrap, &autoWrap);                    ac++;
1651     (void) XtSetArg(al[ac], DtNreverseWrap, &reverseWrap);              ac++;
1652     (void) XtSetArg(al[ac], DtNc132, &c132);                            ac++;
1653     (void) XtGetValues((Widget)dtw, al, ac);
1654     lockState = _DtTermGetUserKeyLock((Widget) dtw);
1655     autoLineFeed = _DtTermGetAutoLineFeed((Widget) dtw);
1656
1657     /* get the current working directory if it was saved... */
1658     cwd = _DtTermGetCurrentWorkingDirectory((Widget) dtw);
1659     if (!cwd || !*cwd) {
1660         /* no saved cwd, use the one we were started from... */
1661         if (!defaultCwd) {
1662             /* first time through, use getcwd() to get it... */
1663             if (getcwd(buffer, sizeof(buffer))) {
1664                 defaultCwd = XtMalloc(strlen(buffer) + 1);
1665                 (void) strcpy(defaultCwd, buffer);
1666             }
1667         }
1668         cwd = defaultCwd;
1669     }
1670
1671     (void) sprintf(bufr, "*dtterm_%d*rows: %d\n", cloneNum, rows);
1672     (void) write(fd, bufr, strlen(bufr));
1673     (void) sprintf(bufr, "*dtterm_%d*columns: %d\n", cloneNum, columns);
1674     (void) write(fd, bufr, strlen(bufr));
1675
1676     if(menuBar == False)
1677     {
1678         sprintf(bufr, "*dtterm_%d*menuBar: False\n", cloneNum);
1679         write (fd, bufr, strlen(bufr));
1680     }
1681     if(scrollBar == False)
1682     {
1683         sprintf(bufr, "*dtterm_%d*scrollBar: False\n", cloneNum);
1684         write (fd, bufr, strlen(bufr));
1685     }
1686     if (_DtTermPrimGetCursorVisible((Widget )dtw))
1687     {
1688         if (charCursorStyle == DtTERM_CHAR_CURSOR_BAR)
1689             sprintf(bufr, "*dtterm_%d*charCursorStyle: CHARCURSOR_BAR\n", cloneNum);
1690         else
1691             sprintf(bufr, "*dtterm_%d*charCursorStyle: CHARCURSOR_BOX\n", cloneNum);
1692     }
1693     else 
1694         sprintf(bufr, "*dtterm_%d*charCursorStyle: CHARCURSOR_INVISIBLE\n", cloneNum);
1695     write (fd, bufr, strlen(bufr));
1696     
1697
1698     sprintf(bufr, "*dtterm_%d*blinkRate: %d\n", cloneNum,blinkRate);
1699     write (fd, bufr, strlen(bufr));
1700
1701     if(jumpScroll == False)
1702     {
1703         sprintf(bufr, "*dtterm_%d*jumpScroll: False\n", cloneNum);
1704         write (fd, bufr, strlen(bufr));
1705     }
1706     if(marginBell == True)
1707     {
1708         sprintf(bufr, "*dtterm_%d*marginBell: True\n", cloneNum);
1709         write (fd, bufr, strlen(bufr));
1710         sprintf(bufr, "*dtterm_%d*nMarginBell: %d\n", cloneNum,nMarginBell);
1711         write (fd, bufr, strlen(bufr));
1712     }
1713     if(visualBell == True)
1714     {
1715         sprintf(bufr, "*dtterm_%d*visualBell: True\n", cloneNum);
1716         write (fd, bufr, strlen(bufr));
1717     }
1718     if(reverseVideo == True)
1719     {
1720         sprintf(bufr, "*dtterm_%d*reverseVideo: True\n", cloneNum);
1721         write (fd, bufr, strlen(bufr));
1722     }
1723     if(cursorMode == True)
1724     {
1725         sprintf(bufr, "*dtterm_%d*appCursorDefault: True\n", cloneNum);
1726         write (fd, bufr, strlen(bufr));
1727     }
1728     if(keypadMode == True)
1729     {
1730         sprintf(bufr, "*dtterm_%d*appKeypadDefault: True\n", cloneNum);
1731         write (fd, bufr, strlen(bufr));
1732     }
1733     if(autoWrap == False)
1734     {
1735         sprintf(bufr, "*dtterm_%d*autoWrap: False\n", cloneNum);
1736         write (fd, bufr, strlen(bufr));
1737     }
1738     if(reverseWrap == True)
1739     {
1740         sprintf(bufr, "*dtterm_%d*reverseWrap: True\n", cloneNum);
1741         write (fd, bufr, strlen(bufr));
1742     }
1743     if(c132 == True)
1744     {
1745         sprintf(bufr, "*dtterm_%d*c132: True\n", cloneNum);
1746         write (fd, bufr, strlen(bufr));
1747     }
1748     if(lockState == False)
1749         sprintf(bufr, "*dtterm_%d*userKeyLock: False\n", cloneNum);
1750     else
1751         sprintf(bufr, "*dtterm_%d*userKeyLock: True\n", cloneNum);
1752     write (fd, bufr, strlen(bufr));
1753     if(autoLineFeed == False)
1754         sprintf(bufr, "*dtterm_%d*autoLineFeed: False\n", cloneNum);
1755     else
1756         sprintf(bufr, "*dtterm_%d*autoLineFeed: True\n", cloneNum);
1757     write (fd, bufr, strlen(bufr));
1758
1759     if (cwd && *cwd) {
1760         (void) sprintf(bufr, "*dtterm_%d*currentWorkingDirectory: %s\n",
1761                 cloneNum, cwd);
1762         (void) write(fd, bufr, strlen(bufr));
1763     }
1764     free(bufr);
1765 }
1766
1767 /***********************************************************************
1768  *
1769  * RestoreSession - returns True for success, False for failure...
1770  *
1771  ***********************************************************************/
1772 static Boolean
1773 RestoreSession(
1774             Widget topDog,
1775             Arg *passedAl,
1776             int passedAc)
1777 {
1778     char *fileName = attrs.session;
1779     char *path;
1780     XrmDatabase db;
1781     char *tmpStr;
1782     XrmName xrm_name[5];
1783     XrmRepresentation rep_type;
1784     XrmValue value;
1785     Widget ShellWidget;
1786     int numToRestore, i, j;
1787     Arg                   al[30];
1788     int                   ac;
1789     
1790     if(DtSessionRestorePath(topLevel, &path, fileName) == False)
1791         path = fileName;
1792
1793     /*  Open the file as a resource database */
1794     if ((db = XrmGetFileDatabase (path)) == NULL) 
1795     {
1796       /* if we got a bogus filename, bail out... */
1797       return(False);
1798     }
1799
1800     xrm_name[0] = XrmStringToQuark ("dtterm");
1801     xrm_name[1] = XrmStringToQuark ("numClonedTerms");
1802     xrm_name[2] = 0;
1803     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1804
1805     /* if we got nothing back, bail out... */
1806     if (!value.addr || !*((char *) value.addr)) {
1807         return(False);
1808     }
1809
1810     numToRestore = atoi((char *)value.addr);
1811     /* if we don't have at least one to restore, bail out... */
1812     if (numToRestore < 1) {
1813         return(False);
1814     }
1815
1816     ShellWidget = topDog;
1817         
1818     for (j = 0; j < numToRestore; j++)
1819     {
1820         /* use the passed arglist as a starting point... */
1821         for (ac = 0; ac < passedAc; ac++) {
1822             al[ac].value = passedAl[ac].value;
1823             al[ac].name = passedAl[ac].name;
1824         }
1825
1826         (void) CreateInstance(ShellWidget, "dtTermView", al, ac, True);
1827         RestoreTerm(ShellWidget, instance_list[j], j, db);
1828         (void) XtSetArg(al[0], XmNmappedWhenManaged, True); 
1829         (void) XtSetValues(ShellWidget, al, 1);
1830         /* mapping the shell widget here is redundant, and it turns out
1831          * was responsible for CMVC7216: broken restoring of
1832          * iconified instances in multiple workspaces...
1833          */
1834
1835         ac = 0;
1836         (void) XtSetArg(al[ac], XmNallowShellResize, True); ac++;
1837         (void) XtSetArg(al[ac], XmNmappedWhenManaged, True); ac++;
1838         ShellWidget = XtAppCreateShell((char *) 0, "Dtterm",
1839                     applicationShellWidgetClass, XtDisplay(topDog), al, ac);
1840     }
1841     /* success, return True... */
1842     return(True);
1843 }
1844
1845 static void
1846 RestoreTerm(
1847         Widget shellWidget,
1848         DtTermViewWidget dtvw,
1849         int termNum,
1850         XrmDatabase db)
1851 {
1852     char buf[1024];
1853     XrmName xrm_name[5];
1854     XrmRepresentation rep_type;
1855     XrmValue value;
1856     DtTermWidget dtw = (DtTermWidget )dtvw->termview.term;
1857     Position x,y;
1858     Dimension width, height;
1859     char                  *ws_list;
1860     unsigned char         charCursorStyle;
1861     int                   blinkRate;
1862     Boolean               jumpScroll;
1863     Boolean               marginBell;
1864     int                   nMarginBell;
1865     Boolean               visualBell;
1866     Boolean               reverseVideo;
1867     Boolean               cursorMode;
1868     Boolean               keypadMode;
1869     Boolean               autoWrap;
1870     Boolean               reverseWrap;
1871     Boolean               c132;
1872     Boolean               lockState;
1873     Boolean               autoLineFeed;
1874     Boolean               menuBar;
1875     Boolean               scrollBar;
1876     char                 *cwd;
1877     Arg                   al[30];
1878     int                   ac;
1879     int                   rows = 0;
1880     int                   columns = 0;
1881
1882     sprintf(buf, "dtterm_%d", termNum);
1883     xrm_name[0] = XrmStringToQuark(buf);
1884     xrm_name[2] = 0;
1885
1886 /* Pass 1, before widget realization...
1887  */
1888
1889     /* get x position */
1890     xrm_name[1] = XrmStringToQuark ("x");
1891     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1892     x = atoi((char *)value.addr);
1893
1894     /* get y position */
1895     xrm_name [1] = XrmStringToQuark ("y");
1896     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1897     y = atoi((char *)value.addr);
1898
1899     /* get width */
1900     xrm_name [1] = XrmStringToQuark ("width");
1901     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1902     width = atoi((char *)value.addr);
1903
1904     /* get height */
1905     xrm_name [1] = XrmStringToQuark ("height");
1906     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1907     height = atoi((char *)value.addr);
1908
1909 /****************
1910  *
1911  * First the shell resources...
1912  *
1913  ****************/
1914     ac = 0;
1915     (void) XtSetArg(al[ac], XmNx, x);                   ac++;
1916     (void) XtSetArg(al[ac], XmNy, y);                   ac++;
1917     (void) XtSetArg(al[ac], XmNwidth, width);                   ac++;
1918     (void) XtSetArg(al[ac], XmNheight, height);                 ac++;
1919
1920     /* get iconify... */
1921     xrm_name[1] = XrmStringToQuark("iconify");
1922     if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value)) {
1923         if (!strcmp((char *)value.addr, "True")) {
1924             (void) XtSetArg(al[ac], XmNinitialState, IconicState); ac++;
1925         } else {
1926             (void) XtSetArg(al[ac], XmNinitialState, NormalState); ac++;
1927         }
1928     } else {
1929         (void) XtSetArg(al[ac], XmNinitialState, NormalState);
1930     }
1931
1932     (void) XtSetValues(XtParent((Widget)dtvw), al, ac);
1933
1934 /****************
1935  *
1936  * Now the TermView resources...
1937  *
1938  ****************/
1939     ac = 0;
1940     xrm_name[1] = XrmStringToQuark ("rows");
1941     if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value)) {
1942         rows = atoi((char *)value.addr);
1943         (void) XtSetArg(al[ac], DtNrows, rows); ac++;
1944     }
1945
1946     xrm_name[1] = XrmStringToQuark ("columns");
1947     if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value)) {
1948         columns = atoi((char *)value.addr);
1949         (void) XtSetArg(al[ac], DtNcolumns, columns); ac++;
1950     }
1951
1952     xrm_name[1] = XrmStringToQuark ("menuBar");
1953     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
1954         {(void) XtSetArg(al[ac], XmNmenuBar, False);    ac++;}
1955     xrm_name[1] = XrmStringToQuark ("scrollBar");
1956     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
1957         {(void) XtSetArg(al[ac], DtNscrollBar, False);  ac++;}
1958
1959     xrm_name[1] = XrmStringToQuark ("userFontListIndex");
1960     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True) {
1961         _DtTermViewSetUserFontListIndex((Widget )dtvw, atol(value.addr));
1962     }
1963
1964     (void) XtSetValues((Widget)dtvw, al, ac);
1965
1966 /****************
1967  *
1968  * And finally the termprim stuff...
1969  *
1970  ****************/
1971     ac = 0;
1972     if(rows > 0) {
1973         (void) XtSetArg(al[ac], DtNrows, rows); ac++;
1974     }
1975
1976     if(columns > 0) {
1977         (void) XtSetArg(al[ac], DtNcolumns, columns); ac++;
1978     }
1979
1980     xrm_name[1] = XrmStringToQuark ("charCursorStyle");
1981     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1982     if (!strcmp(value.addr, "CHARCURSOR_INVISIBLE"))
1983         _DtTermPrimSetCursorVisible((Widget )dtw, False);
1984     else  
1985     {
1986         if (!strcmp(value.addr, "CHARCURSOR_BAR"))
1987               (void) XtSetArg(al[ac], DtNcharCursorStyle, DtTERM_CHAR_CURSOR_BAR);
1988         else 
1989               (void) XtSetArg(al[ac], DtNcharCursorStyle, DtTERM_CHAR_CURSOR_BOX);
1990         ac++;
1991     }
1992     
1993     xrm_name [1] = XrmStringToQuark ("blinkRate");
1994     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1995     blinkRate = atoi((char *)value.addr);
1996     (void) XtSetArg(al[ac], DtNblinkRate, blinkRate);                   ac++;
1997
1998     xrm_name[1] = XrmStringToQuark ("jumpScroll");
1999     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2000         {(void) XtSetArg(al[ac], DtNjumpScroll, False); ac++;}
2001
2002     xrm_name[1] = XrmStringToQuark ("marginBell");
2003     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2004     {
2005         (void) XtSetArg(al[ac], DtNmarginBell, True);   ac++;
2006          xrm_name [1] = XrmStringToQuark ("nMarginBell");
2007          XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
2008          nMarginBell = atoi((char *)value.addr);
2009          (void) XtSetArg(al[ac], DtNnMarginBell, nMarginBell);ac++;
2010     }
2011
2012     xrm_name[1] = XrmStringToQuark ("visualBell");
2013     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2014         {(void) XtSetArg(al[ac], DtNvisualBell, True);  ac++;}
2015
2016     xrm_name[1] = XrmStringToQuark ("reverseVideo");
2017     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2018         {(void) XtSetArg(al[ac], DtNreverseVideo, True);        ac++;}
2019
2020     xrm_name[1] = XrmStringToQuark ("appCursorDefault");
2021     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2022         {(void) XtSetArg(al[ac], DtNappCursorDefault, True);    ac++;}
2023
2024     xrm_name[1] = XrmStringToQuark ("appKeypadDefault");
2025     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2026         {(void) XtSetArg(al[ac], DtNappKeypadDefault, True);    ac++;}
2027
2028     xrm_name[1] = XrmStringToQuark ("autoWrap");
2029     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2030         {(void) XtSetArg(al[ac], DtNautoWrap, False);   ac++;}
2031
2032     xrm_name[1] = XrmStringToQuark ("reverseWrap");
2033     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2034         {(void) XtSetArg(al[ac], DtNreverseWrap, True); ac++;}
2035
2036     xrm_name[1] = XrmStringToQuark ("c132");
2037     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2038         {(void) XtSetArg(al[ac], DtNc132, True);        ac++;}
2039
2040     xrm_name[1] = XrmStringToQuark ("reverseVideo");
2041     if(XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value) == True)
2042         {(void) XtSetArg(al[ac], DtNreverseVideo, True);        ac++;}
2043
2044     xrm_name[1] = XrmStringToQuark ("userKeyLock");
2045     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
2046     if (!strcmp(value.addr, "True"))
2047          _DtTermSetUserKeyLock((Widget) dtw, True);
2048     else 
2049          _DtTermSetUserKeyLock((Widget) dtw, False);
2050
2051     xrm_name[1] = XrmStringToQuark ("autoLineFeed");
2052     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
2053     if (!strcmp(value.addr, "True"))
2054          _DtTermSetAutoLineFeed((Widget) dtw, True);
2055     else 
2056          _DtTermSetAutoLineFeed((Widget) dtw, False);
2057
2058     (void) XtSetValues((Widget)dtw, al, ac);
2059
2060     xrm_name[1] = XrmStringToQuark ("currentWorkingDirectory");
2061     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
2062     if (value.addr && *value.addr) {
2063         _DtTermSetCurrentWorkingDirectory((Widget) dtw, value.addr);
2064     }
2065
2066     /* realize the interface...
2067      */
2068     (void) XtRealizeWidget(shellWidget);
2069
2070
2071
2072 /* Pass 2, after widget realization...
2073  */
2074
2075     /* get workspace list */
2076     xrm_name[1] = XrmStringToQuark("workspaceList");
2077     XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value);
2078     SetWorkSpaceHints( XtParent((Widget)dtvw),(char *) value.addr);
2079 }
2080
2081 static void
2082 SetWorkSpaceHints
2083 (
2084     Widget shell,
2085     char *workspaces
2086 )
2087 {
2088     char * ptr;
2089     Atom * workspace_atoms = NULL;
2090     int num_workspaces=0;
2091     Atom thisWsAtom;
2092
2093     if (workspaces) {
2094         do {
2095             ptr = strchr (workspaces, ' ');
2096             if (ptr != NULL)
2097                 *ptr = 0;
2098             thisWsAtom = None;
2099
2100             /* if we haven't hit a match, try interning the atom... */
2101             if (thisWsAtom == None) {
2102                 thisWsAtom = XmInternAtom (XtDisplay(shell), workspaces, True);
2103             }
2104
2105             if (thisWsAtom != None) {
2106                 workspace_atoms = (Atom *) XtRealloc ((char *)workspace_atoms,
2107                         sizeof (Atom) * (num_workspaces + 1));
2108                 workspace_atoms[num_workspaces] = thisWsAtom;
2109                 num_workspaces++;
2110             }
2111
2112             if (ptr != NULL) {
2113                 *ptr = ' ';
2114                 workspaces = ptr + 1;
2115             }
2116         } while (ptr != NULL);
2117
2118         if (num_workspaces > 0) {
2119             DtWsmSetWorkspacesOccupied(XtDisplay(shell), XtWindow (shell),
2120                     workspace_atoms, num_workspaces);
2121         }
2122
2123         XtFree ((char *) workspace_atoms);
2124         workspace_atoms = NULL;
2125     }
2126 }