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