Fix typo in license headers
[oweals/cde.git] / cde / programs / dtpad / main.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: main.c /main/27 1999/09/15 15:16:51 mgreess $ */
24 /**********************************<+>*************************************
25 ***************************************************************************
26 **
27 **  File:        main.c
28 **
29 **  Project:     DT dtpad, a memo maker type editor based on the Dt Editor
30 **               widget.
31 **
32 **  Description:
33 **  -----------
34 **
35 **  Dtpad is basically a wrapper around the DT Editor widget providing:
36 **
37 **    o a menu interface to Editor widget features
38 **    o client/server architecture (via the DtSvc library)
39 **    o session save/restore
40 **    o wm_delete protocol and "panic save" signal handling
41 **    o ToolTalk support of media exchange and desktop message sets
42 **    o printing
43 **
44 **  This file contains the routines that control the client/server architecture
45 **  of dtpad and creation of the top level widgets.
46 **
47 **  See the comments preceeding main() for a description of the client/server
48 **  architecture of dtpad as well as an overview of the routine hierarchy of
49 **  dtpad.  The widget hierarchy of dtpad goes something like this:
50 **
51 **      Creating Routine        Creating Function       Widget
52 **      ----------------------  ----------------------  -----------------------
53 **  (1) CreateFirstPad:         XtInitialize()          topLevelWithWmCommand
54 **  (2) CreateFirstPad:         XtAppCreateShell()        pPad->app_shell
55 **  (3)   RealizeNewPad:        XmCreateMainWindow()        pPad->mainWindow
56 **          CreateMenuBar:      XmCreateMenuBar()             pPad->menu_bar
57 **            CreateFileMenu:   XmCreatePulldownMenu()          (file_pane)
58 **            CreateEditMenu:   XmCreatePulldownMenu()          (edit_pane)
59 **            CreateFormatMenu: XmCreatePulldownMenu()          (format_pane)
60 **            CreateOptionsMenu:XmCreatePulldownMenu()          (options_pane)
61 **            CreateHelpMenu:   XmCreatePulldownMenu()          (help_pane)
62 **          CreateEditorWidget: DtCreateEditor()              pPad->editor
63 **      #ifdef POPUP
64 **          CreatePopupMenu:    XmCreatePopupMenu()           pPad->popup
65 **      #endif
66 **
67 **  (1) The topLevelWithWmCommand is only created once whereas the others
68 **      are created and realized whenever a Editor window is opened.
69 **      The display is opened once but stored in the pPad Editor struct
70 **      associated with each opened edit window.
71 **  (2) The pPad->app_shell is created initially (in CreateFirstPad) and
72 **      (in dtpad.c:FindOrCreatePad) whenever the server receives a message
73 **      (via messageCB.c:OpenNewPadCB) to start another edit session.
74 **  (3) The pPad->mainWindow as well as the pPad->menu_bar and pPad->editor
75 **      are only created via RealizeNewPad.  RealizeNewPad is called
76 **      whenever an app_shell is created and also when a session is restored.
77 **
78 *******************************************************************
79 **  (c) Copyright Hewlett-Packard Company, 1990 - 1995.  All rights are
80 **  reserved.  Copying or other reproduction of this program
81 **  except for archival purposes is prohibited without prior
82 **  written consent of Hewlett-Packard Company.
83 ********************************************************************
84 **
85 ********************************************************************
86 **  (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
87 **  (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
88 **  (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
89 **  (c) Copyright 1993, 1994, 1995 Novell, Inc.
90 ********************************************************************
91 **
92 **
93 **************************************************************************
94 **********************************<+>*************************************/
95 #include "dtpad.h"
96 #include "stdlib.h"
97 #include "messageParam.h"
98 #include "signal.h"
99 #include <locale.h>
100 #include <sys/wait.h>
101 #include <Xm/MwmUtil.h>
102 #include <Dt/EnvControlP.h>
103 #include <Dt/DtpadM.h>
104 #include <Dt/MsgCatP.h>
105 #include "X11/Xutil.h"
106 #include <X11/StringDefs.h>
107 #include <X11/ShellP.h>
108
109 #ifdef HAVE_EDITRES
110 #include <X11/Xmu/Editres.h>
111 #endif
112
113 #ifndef NO_MESSAGE_CATALOG
114 # define TRUE 1
115 # define FALSE 0
116 # include <nl_types.h>
117 # if !defined(NL_CAT_LOCALE)
118 #  define NL_CAT_LOCALE 0
119 # endif
120 # ifdef __ultrix
121 #  define _DTPAD_CAT_NAME "dtpad.cat"
122 # else  /* __ultrix */
123 static const char catalogName[] = "dtpad";
124 #  define _DTPAD_CAT_NAME catalogName
125 # endif /* __ultrix */
126 #endif
127
128
129 /************************************************************************
130  *                      Global Definitions
131  ************************************************************************/
132
133 Atom            xa_WM_DELETE_WINDOW;
134
135 /* bits for exclamation point in dialog */
136 unsigned char warningBits[] = {
137    0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
138    0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
139    0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
140    0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
141    0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
142    0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
143    0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
144    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00,
145    0x00, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00,
146    0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xe0, 0x07, 0x00,
147    0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
148 };
149
150 static XtResource resources[] = {
151   {"statusLine", "StatusLine", XmRBoolean, sizeof(Boolean),
152       XtOffset(ApplicationDataPtr,statusLine), XmRImmediate, (XtPointer)False,
153   },
154   {"wrapToFit", "WrapToFit", XmRBoolean, sizeof(Boolean),
155       XtOffset(ApplicationDataPtr,wordWrap), XmRImmediate, (XtPointer)False,
156   },
157   {"overstrike", "Overstrike", XmRBoolean, sizeof(Boolean),
158       XtOffset(ApplicationDataPtr,overstrike), XmRImmediate, (XtPointer)False,
159   },
160   {"saveOnClose", "SaveOnClose", XmRBoolean, sizeof(Boolean),
161       XtOffset(ApplicationDataPtr,saveOnClose), XmRImmediate, (XtPointer)False,
162   },
163   {"missingFileWarning", "MissingFileWarning", XmRBoolean, sizeof(Boolean),
164       XtOffset(ApplicationDataPtr,missingFileWarning), XmRImmediate, (XtPointer)False,
165   },
166   {"readOnlyWarning", "ReadOnlyWarning", XmRBoolean, sizeof(Boolean),
167       XtOffset(ApplicationDataPtr,readOnlyWarning), XmRImmediate, (XtPointer)True,
168   },
169   {"nameChange", "NameChange", XmRBoolean, sizeof(Boolean),
170       XtOffset(ApplicationDataPtr,nameChange), XmRImmediate, (XtPointer)True,
171   },
172   {"viewOnly", "ViewOnly", XmRBoolean, sizeof(Boolean),
173       XtOffset(ApplicationDataPtr,viewOnly), XmRImmediate, (XtPointer)False,
174   },
175   {"workspaceList", "WorkspaceList", XmRString, sizeof(char *),
176       XtOffset(ApplicationDataPtr,workspaceList), XmRImmediate,(XtPointer)NULL,
177   },
178   {"session", "Session", XmRString, sizeof(char *),
179       XtOffset(ApplicationDataPtr,session), XmRImmediate, (XtPointer)NULL,
180   },
181
182   {"standAlone", "StandAlone", XmRBoolean, sizeof(Boolean),
183       XtOffset(ApplicationDataPtr,standAlone), XmRImmediate, (XtPointer)False,
184   },
185   {"blocking", "Blocking", XmRBoolean, sizeof(Boolean),
186       XtOffset(ApplicationDataPtr,blocking), XmRImmediate, (XtPointer)True,
187   },
188   {"server", "Server", XmRBoolean, sizeof(Boolean),
189       XtOffset(ApplicationDataPtr,server), XmRImmediate, (XtPointer)False,
190   },
191   {"exitOnLastClose", "ExitOnLastClose", XmRBoolean, sizeof(Boolean),
192       XtOffset(ApplicationDataPtr,exitOnLastClose), XmRImmediate, (XtPointer)False,
193   },
194 };
195
196 static XrmOptionDescRec option_list[] =
197 {
198    {"-statusLine", "statusLine", XrmoptionNoArg,(caddr_t)"TRUE"},
199    {"-wrapToFit", "wrapToFit", XrmoptionNoArg, (caddr_t)"TRUE"},
200    {"-overstrike", "overstrike", XrmoptionNoArg, (caddr_t)"TRUE"},
201    {"-saveOnClose", "saveOnClose", XrmoptionNoArg, (caddr_t)"TRUE"},
202    {"-missingFileWarning", "missingFileWarning", XrmoptionNoArg, (caddr_t)"TRUE"},
203    {"-noReadOnlyWarning", "readOnlyWarning", XrmoptionNoArg, (caddr_t)"FALSE"},
204    {"-noNameChange", "nameChange", XrmoptionNoArg, (caddr_t)"FALSE"},
205    {"-viewOnly", "viewOnly", XrmoptionNoArg, (caddr_t)"TRUE"},
206    {"-workspaceList", "workspaceList", XrmoptionSepArg, (caddr_t)NULL},
207    {"-session", "session", XrmoptionSepArg, (caddr_t)NULL},
208
209    {"-standAlone", "standAlone", XrmoptionNoArg, (caddr_t)"TRUE"},
210    {"-noBlocking", "blocking", XrmoptionNoArg, (caddr_t)"FALSE"},
211    {"-server", "server", XrmoptionNoArg, (caddr_t)"TRUE"},
212    {"-exitOnLastClose", "exitOnLastClose", XrmoptionNoArg, (caddr_t)"TRUE"},
213 };
214
215 static String fallbacks[] =
216 {
217     "Dtpad.Print.width:8.5in",
218     "Dtpad.Print.height:11.0in",
219     "Dtpad.Print*renderTable:-adobe-courier-medium-r-normal--0-140-0-0-m-0-iso8859-1",
220     "Dtpad.Print*shadowThickness:0",
221     NULL
222 };
223
224 ApplicationData initialServerResources;
225 char *initialServerGeometry;
226 Editor *pPadList = (Editor *)NULL;
227 int numActivePads = 0;
228 Widget topLevelWithWmCommand;
229 Boolean ActionDBInitialized = False;
230 int waitCB = 1;
231 char *value = NULL;
232
233 char **pArgv = NULL;
234 int pArgc = 0;
235
236
237 /************************************************************************
238  *                      Forward Declarations
239  ************************************************************************/
240
241 static Editor *CreateFirstPad(
242         int *pArgc,
243         char **argv);
244 static void SendMessageToServer(
245         Editor *pPad,
246         int argc,
247         char **argv);
248 static void InitEditSessionAndFirstPad(
249         Editor *pPad,
250         int argc,
251         char **argv);
252 static void SetStateFromResources(
253         Editor *pPad);
254 static Tt_callback_action HostCB(
255         Tt_message m, 
256         Tt_pattern p);
257 static void Usage(
258         char **argv );
259 static int dtpadXErrorHandler(
260         Display *display,
261         XErrorEvent *xerr);
262 static int dtpadXIOErrorHandler(
263         Display *display);
264
265
266
267 /************************************************************************
268  * main - controls the high level client/server processing of dtpad based 
269  *      on the three modes of operation:
270  *
271  *      1) requestor mode -     send message to dtpad server to do actual
272  *                              editing
273  *      2) server mode -        do editing for one or more dtpad requestors
274  *                              (via multiple edit windows)
275  *      3) standAlone mode -    do all editing alone (via a single
276  *                              edit window)
277  *
278  ************************************************************************/ 
279 int 
280 main(
281         int argc,
282         char **argv )
283 {
284     Editor *pPad;
285
286     char *sessId, *tmpStr;
287     Tt_pattern requests2Handle;
288     Tt_message msg;
289     Tt_status status = TT_OK;
290     int ttFd;    /* ToolTalk file descriptor */
291
292     /* Set up the environment to allow relocation of the various bitmaps
293      * and message catalogs. */
294     (void)_DtEnvControl(DT_ENV_SET);
295
296     (void) XtSetLanguageProc((XtAppContext)NULL, (XtLanguageProc)NULL, 
297                              (XtPointer)NULL);
298
299     pArgc = argc;
300     pArgv = argv;
301     pPad = CreateFirstPad(&argc, argv);
302     XtAppSetFallbackResources(pPad->app_context, fallbacks);
303
304     if (DtInitialize(pPad->display, topLevelWithWmCommand, pPad->progname,
305                      DTPAD_TOOL_CLASS) != True ) {
306         XtError((char *) GETMESSAGE(7, 4,
307           "Unable to initialize Desktop services ... exiting Text Editor."));
308     }
309
310     /* -----> Resolve conficts between -standAlone, -session and -server */
311     if (pPad->xrdb.standAlone) {        /* standAlone takes precedence */
312         pPad->xrdb.session = (char *) NULL;
313         pPad->xrdb.server = False;
314     } else if (pPad->xrdb.session) {    /* session is 2nd in precedence */
315         pPad->xrdb.server = False;
316         pPad->xrdb.blocking = False;
317     }
318
319     if (pPad->xrdb.standAlone) {
320
321         /*--------------------------------------------------------
322          * StandAlone Mode
323          *
324          *      Initialize self as an editing session.
325          *
326          *-------------------------------------------------------*/
327         InitEditSessionAndFirstPad(pPad, argc, argv);
328
329     } else if (pPad->xrdb.server) {
330         /*--------------------------------------------------------
331          * Server Mode
332          *
333          *      Indicate the types of messages interested in and
334          *      callbacks to process each message type, then
335          *      initialize self as an editing session.
336          *
337          *-------------------------------------------------------*/
338         /* Exit if there's another dtpad server servicing the display */
339         if (_DtGetLock(pPad->display, DTPAD_CLASS_NAME) == 0) {
340            FileWidgets *pFileWidgets = &pPad->fileStuff.fileWidgets;
341            Boolean validTT= True;
342            Boolean notDone= True;
343
344            /* we want to get the hostname of where the server is running.
345             * To do that, we need to open a ToolTalk connection, the use 
346             * the Desktop request "Get_Sysinfo" to get the host name.
347             */
348            while(validTT && notDone)
349            {
350               /* go open a simple ToolTalk connection */
351               status = TTdesktopOpen( &ttFd, pPad, False );
352               if (TT_OK != status) {
353                 TTwarning( pPad, status,
354                            GETMESSAGE(7, 11, "Exiting text editor ...") );
355                 exit(status);
356               }
357
358               /* Create the message */
359               msg = tttk_message_create(
360                    0,                              /* no inherited context */
361                    TT_REQUEST,                     /* class */
362                    TT_SESSION,                     /* scope */
363                    0,                              /* TT_PROCEDURE addr */
364                    "Get_Sysinfo",                  /* op */
365                    (Tt_message_callback) HostCB);  /* msg callback */
366               status = tt_ptr_error(msg);
367               if(status != TT_OK) {
368                  validTT= False;
369                  break;
370               }
371
372               /* set the ptype to DTPAD */
373               status = tt_message_handler_ptype_set(msg, "DTPAD");
374               if(status != TT_OK) {
375                  validTT= False;
376                  break;
377               }
378             
379               /* the first two variable returned by Get_Sysinfo is all we need
380                * to get the hostname.  hostname is the 2nd variable.  Let's
381                * register that we want them 
382                */
383               status = tt_message_arg_add(msg, TT_OUT, "string", 0);
384               if(status != TT_OK) {
385                  validTT= False;
386                  break;
387               }
388               status = tt_message_arg_add(msg, TT_OUT, "string", 0);
389               if(status != TT_OK) {
390                  validTT= False;
391                  break;
392               }
393
394               /* Finally, Let's send the Message ... */
395               status = tt_message_send(msg);
396               if(status != TT_OK) {
397                  validTT= False;
398                  break;
399               }
400
401               /* block for 10 seconds or until the HostCB is called */
402               tttk_block_while(pPad->app_context, &waitCB, 10000);
403               notDone = False;
404            }
405    
406            /* If we sent a valid ToolTalk message and the Callback set value
407             * to something other then NULL, lets use it to print out the 
408             * message.
409             */
410            if(validTT && value != NULL) {
411               tmpStr = (char *)XtMalloc(strlen(GETMESSAGE(7, 7, "ERROR: A dtpad server on %s\nis already serving this display.")) + strlen(value) + 10);
412
413               sprintf(tmpStr, GETMESSAGE(7, 7, "ERROR: A dtpad server on %s\nis already serving this display."), value);
414               Warning(pPad, tmpStr, XmDIALOG_ERROR);
415            }
416            else
417               /* ToolTalk connection/message was bogus or unable to get 
418                * hostname in Callback.
419                */
420               Warning(pPad, GETMESSAGE(7, 8, "ERROR: A dtpad server is already\nserving this display."), XmDIALOG_ERROR);
421
422            XtAddCallback (pFileWidgets->gen_warning, XmNokCallback,
423                            exitCB, (XtPointer) pPad);
424            XFlush(pPad->display);
425            XSync(pPad->display, False);
426         }
427       
428         InitEditSessionAndFirstPad(pPad, argc, argv);
429
430         /* -----> Initialize TT connection & process start message */
431         status = TTstartDesktopMediaExchange(topLevelWithWmCommand, pPad);
432         if (TT_OK == status)
433           tttk_Xt_input_handler(0, 0, 0);
434         else {
435           TTwarning( pPad, status,
436                      GETMESSAGE(7, 11, "Exiting text editor ...") );
437           exit(status);
438         }
439       
440     } else {
441
442 #ifdef __osf__
443 /* Temporary work around for action database problem(platinum BL5 03/29/95). */
444       StartDbUpdate((XtPointer) NULL);
445 #endif
446
447         /*--------------------------------------------------------
448          * Requestor Mode
449          *
450          *      Just tell server to do actual editing and wait
451          *      for DTPAD_DONE msg from server to exit (or exit
452          *      immediately if -noBlocking).
453          *
454          *-------------------------------------------------------*/
455
456         /* Send message to dtpad server to either open-and-edit a
457          * file or to restart a session.  Also set up callbacks to
458          * handle success, failure and done-editing notification.
459          */
460         SendMessageToServer(pPad, argc, argv);
461     }
462
463     XtAppMainLoop(pPad->app_context);
464     exit(0);
465
466 }
467
468
469 /************************************************************************
470  * CreateFirstPad - Performs initialization common to all modes of
471  *      operation (i.e. to requestor mode, server mode and standAlone
472  *      mode).
473  *
474  *   This routine initializes the primary sturcture used by dtpad, pPadList
475  *   which is a list of Editor structs (pPad) with one entry per edit request.
476  *
477  *   Specifically, this routine:
478  *
479  *   1) creates the first entry in pPadList and returns a pointer to it
480  *   2) initializes Xt and the display, and creates the top level widget
481  *   3) adds the "save yourself" protocol to the top level widget
482  *   4) creates the applic shell widget and applic context
483  *   5) loads the application resources to the initial pPad and sets some
484  *      initial editing process values
485  *
486  *   Creation of subsequent entries in the pPadList (1) and creation of
487  *   corresponding applic shells and contexts (4) are also done by the server
488  *   (via TTmedia_ptype_declareCB) for each new edit request that it receives.
489  *   This means that there is one top level widget and display connection
490  *   per process and one applic shell widget and applic context PER EDIT
491  *   REQUEST (i.e. per entry in pPadList).
492  *
493  *   Note that CreateFirstPad is run in all modes the first time the requestor
494  *   or server starts up and that resource are only loaded via this routine.
495  *   This means that resources are obtained (via XtGetApplicationResources)
496  *   on both the requestor and the server and saved in the initial pPad Editor
497  *   on the requestor or server.  This also means that for requestor dtpads, a 
498  *   pPad struct is created on both the requestor and the server (the server
499  *   pPad may be the initial struct created by CreateFirstPad or it may be a
500  *   subsequent pPad created by TTmedia_ptype_declareCB but with the initial
501  *   server resource values).  For requestor mode, the dtpad pPad resources are
502  *   shipped to the server (in the TTDT_EDIT request) where they override
503  *   resources in the corresponding pPad struct on the server.
504  *
505  *   XXX - Some of the stuff in this routine probably does not need to be
506  *         done in all modes of operation - primarily in requestor mode.
507  *         Note that resources need to be loaded in all modes.
508  *
509  * [SuG 5/12/95] Modified for fishy argument checking.
510  ************************************************************************/
511 static Editor * 
512 CreateFirstPad(
513         int *pArgc,
514         char **argv)
515 {
516     int argc_l;
517     char **argv_l, **c_argv_l;
518     Editor *pPad;
519     Arg al[10];
520     register int ac;
521     Widget foo;
522     int i;
523     /* Added for the argument fix*/
524     char* inS;
525     int in;
526     Atom xa_WM_SAVE_YOURSELF;
527     extern char *optarg;
528     extern int optind, opterr, optind;
529     char c;
530
531     /* Create the 1st Editor entry in list of Editor instances.
532      * This is also done in FindOrCreatePad() for each Editor pad instance */
533     CreatePad(&pPad);
534
535     if (pPad->progname=MbStrrchr(argv[0], '/'))
536         pPad->progname++;
537     else
538         pPad->progname = argv[0];
539
540     /* Initialize the toolkit, open the display and create top level widget */
541     topLevelWithWmCommand = XtInitialize(argv[0], DTPAD_CLASS_NAME, 
542                                    option_list, XtNumber(option_list), 
543                                    (int *) pArgc, argv);
544
545 #if 0
546         /*
547          * At this point Xt has stripped for us all valid arguments. 
548          * If number of arguments is <= 2, first one is program name and second
549          * one will be file name always (we don't care if it has a '-').
550          */
551         if (*pArgc > 2) {
552                  /*
553                  * Now we check for illegal arguments, note argv[0] is 
554                  * progname, so we skip that, argv[last] should be file name 
555                  * so we check for '-' character in (i = 1 to i = (n-1)) to 
556                  * catch inbetween invalids.
557                  * Any extras with '-' as first characters are treated as 
558                  * illegal options and ones without it as superfluous 
559                  * arguments.
560                  */
561                 for (i = 1; i < ((*pArgc) - 1); i++)
562                 {
563                     inS = MbStrchri(argv[i], '-', &in);
564                     if (inS != NULL) {
565                         if (in == 0)
566                         {
567                             printf(GETMESSAGE(2, 2,"dtpad: illegal option: %s"),
568                                    argv[i]);
569                             printf("\n");
570                             exit(1);
571                         }
572                     }
573                     else {
574                         printf(GETMESSAGE(2, 3, "dtpad: extra argument: %s"),
575                                argv[i]);
576                         printf("\n");
577                         exit(1);
578                     }
579                 }
580         }
581 #endif
582
583     ac = 0;
584     XtSetArg(al[ac], XmNgeometry, &pPad->geometry); ac++;
585     XtGetValues(topLevelWithWmCommand, al, ac);
586
587     /* Realize the top level widget */
588     XtSetMappedWhenManaged(topLevelWithWmCommand, False);
589     XtRealizeWidget(topLevelWithWmCommand);
590
591     /* Determine the display connection */
592     if (!(pPad->display = XtDisplay(topLevelWithWmCommand))) {
593         XtError((char *) GETMESSAGE(7, 5, 
594           "Can not open display ... exiting Text Editor."));
595     }
596
597     /* TTT - ToolTalk Debug
598      * XSynchronize(pPad->display, True);
599      */
600
601     /* Add the Save-Yourself protocol to the top level widget.
602      * Application shell widgets (one per Editor request) don't need it,
603      * since they don't have a WM_COMMAND property on them. */
604     xa_WM_SAVE_YOURSELF = XInternAtom(pPad->display, 
605                                              "WM_SAVE_YOURSELF", False);
606     XmAddWMProtocolCallback(topLevelWithWmCommand, xa_WM_SAVE_YOURSELF, 
607                            (XtCallbackProc)SaveSessionCB, (XtPointer)pPadList);
608
609      
610     /* Create the application shell widget and obtain the application context.
611      * This is also done in FindOrCreatePad() for each Editor pad instance */
612     ac = 0;
613     XtSetArg(al[ac], XmNargv, &argv_l); ac++;
614     XtSetArg(al[ac], XmNargc, &argc_l); ac++;
615     XtGetValues(topLevelWithWmCommand, al, ac);
616
617     c_argv_l = (char **) XtMalloc(argc_l * sizeof(char*));
618     for (i=0; i<argc_l; i++)
619       c_argv_l[i] = strdup(argv_l[i]);
620
621     ac = 0;
622     XtSetArg(al[ac], XmNargv, argv_l); ac++;
623     XtSetArg(al[ac], XmNargc, argc_l); ac++;
624     pPad->app_shell = XtAppCreateShell(pPad->progname, DTPAD_CLASS_NAME,
625                                            applicationShellWidgetClass,
626                                            pPad->display, al, ac);
627     pPad->app_context = XtWidgetToApplicationContext(pPad->app_shell);
628
629     /* Get the application resources */
630     XtGetApplicationResources(pPad->app_shell, &pPad->xrdb, resources,
631                               XtNumber(resources), NULL, 0);
632     if (pPad->xrdb.server) {
633         initialServerResources = pPad->xrdb;
634         initialServerResources.server = False; /* so window will be mapped */ 
635         initialServerGeometry = pPad->geometry;
636         if(pPad->xrdb.workspaceList)
637                 pPad->xrdb.workspaceList = strdup(pPad->xrdb.workspaceList);
638         if(pPad->xrdb.session)
639                 pPad->xrdb.session = strdup(pPad->xrdb.session);
640         pPad->geometry = strdup(pPad->geometry);
641     }
642
643     /* Set some initial Editor instance values */
644     if (pPad->xrdb.server == False) {
645         pPad->inUse = True;
646     }
647
648     return pPad;
649 }
650
651
652 /************************************************************************
653  * CreatePad - creates a new entry in the pPadList of Editor structs.
654  *      Both the top of the list (the global, pPadList) and the current
655  *      entry (whose address is passed as a parameter) are updated to
656  *      point to the newly created entry.
657  ************************************************************************/
658 /* ARGSUSED */
659 void 
660 CreatePad(
661         Editor **ppPad)
662 {
663     Editor *pPad;
664
665     pPad = *ppPad = (Editor *) XtCalloc(1, sizeof(Editor));
666     pPad->pPrevPad = (Editor *)NULL;
667
668     if (pPadList == (Editor *)NULL) {
669         pPadList = pPad;
670         pPad->pNextPad = (Editor *)NULL;
671     } else {
672         Editor *pTemp = pPadList;
673         pPadList = pPad;
674         pPad->pNextPad = pTemp;
675         pTemp->pPrevPad = pPad;
676     }
677 }
678
679 /************************************************************************
680  * SetupLoadArgs - pack requestor options into the Edit request
681  ************************************************************************/
682 /* ARGSUSED */
683 void
684 SetupLoadArgs(Tt_message m, Editor *pPad)
685 {
686     ApplicationDataPtr pArgs = &pPad->xrdb;
687     
688     /* -----> Ignore all other resources if restoring a session.
689      * XXX  - Currently, an Edit request is not used to restore a session.
690      *        Instead a "private" ToolTalk request, DtPadSession_Run is
691      *        used (which is sent in SendMessageToServer() and handled in
692      *        HandleTtRequest() - the handler is setup in main()) */
693     if (pPad->xrdb.session != (char *)NULL) {
694       tt_message_context_set(m, "SESSION", pArgs->session);
695       return;
696     }
697
698     /* -----> The following is the only resource passed to the text editor
699      *        server which is not a text editor specific resource.
700      *        It is always passed. */
701     if (pPad->geometry != (char *)NULL) {
702       tt_message_context_set(m, "GEOMETRY", pPad->geometry);
703     }
704
705     /* -----> Basic options */
706     tt_message_context_set(m, "STATUSLINE", pArgs->statusLine ? "t" : "f");
707     tt_message_context_set(m, "WINDOWWORDWRAP", pArgs->wordWrap ? "t" : "f");
708     tt_message_context_set(m, "OVERSTRIKE", pArgs->overstrike ? "t" : "f");
709     tt_message_context_set(m, "SAVEONCLOSE", pArgs->saveOnClose ? "t" : "f");
710     tt_message_context_set(m, "MISSINGFILEWARNING", pArgs->missingFileWarning ? "t" : "f");
711     tt_message_context_set(m, "NOREADONLYWARNING",
712                                 pArgs->readOnlyWarning ? "t" : "f");
713     tt_message_context_set(m, "NONAMECHANGE",
714                                 pArgs->nameChange ? "t" : "f");
715     tt_message_context_set(m, "VIEWONLY", pArgs->viewOnly ? "t" : "f");
716     tt_message_context_set(m, "WORKSPACELIST", pArgs->workspaceList);
717
718     /* -----> client/server control options */
719     if (pArgs->blocking == True) {
720         char *buf = (char *)XtMalloc(32);
721         sprintf(buf, "%ld", (long)getpid());
722         tt_message_context_set(m, "BLOCKING", buf);
723         pPad->blockChannel = buf;
724     }
725 }
726
727
728 /************************************************************************
729  * pLoadMsgCB - requestor side ttmedia_load() callback setup in
730  *      SendMessageToServer() to handle Replies from the dtpad server.
731  *
732  *      Replies are sent by the server via the following functions:
733  *      
734  *      ttMediaLoadReply (in TTmediaReply).  TTmediaReply is executed when:
735  *
736  *        1) an Edit or Display request is being processed and either the
737  *           edit window is closed or a new file is selected by the user
738  *        2) an Instantiate request is being processed and the edit window
739  *           is closed
740  *        3) a Quit request is handled which matches the Edit request
741  *
742  *      tttk_message_fail.  tttk_message_fail is normally called whenever
743  *
744  *        1) the edit/display/instantiate request can't be handled
745  *        2) a buffer is being edited and the user closed the window
746  *           (XXX - actually, this should only be done if a buffer
747  *                  is being edited and there are unsaved changes
748  *                  - otherwise ttMediaLoadReply should be used)
749  *        3) a Quit request is handled for the window and there are
750  *           unsaved changed  
751  *
752  ************************************************************************/
753 Tt_message
754 pLoadMsgCB(Tt_message msg,
755            void *clientData,
756            Tttk_op op,
757            unsigned char *contents,
758            int len,
759            char *file)
760 {
761     Tt_state state = tt_message_state(msg);
762     StartupStruct *pStruct = (StartupStruct *)tt_message_user(msg, 0);
763
764     if (state == TT_HANDLED) {
765         tttk_message_destroy(msg);
766         exit(0);
767     } else if (state == TT_FAILED) {
768         pStruct->pPad->inUse = True;
769         pStruct->pPad->xrdb.server = False;
770         pStruct->pPad->xrdb.standAlone = True;
771         InitEditSessionAndFirstPad(pStruct->pPad, pStruct->argc, pStruct->argv);
772         return 0;
773     } else {
774         return 0;
775     }
776 }
777
778
779 /************************************************************************
780  * pStatusCB - requestor side ttdt_subcontract_manage() callback setup in
781  *      SendMessageToServer() to handle Status messages from the dtpad
782  *      server.
783  *
784  *      The server sends a Status message via ttdt_message_accept() when
785  *      it determines that it can actually handle the EDIT request.
786  *
787  ************************************************************************/
788 Tt_message
789 pStatusCB(Tt_message msg,
790           void *clientdata,
791           Tt_message contract)
792 {
793     if (clientdata) {
794         /* This is the blocking case, just return 0 (we'll exit in
795          * pLoadMsgCB when we get a Reply from the dtpad server when it's
796          * done handling the request).*/
797         return 0;
798     } else {
799         /* This is the non-blocking case, exit if this is a Status notice */
800         if (tttk_string_op(tt_message_op(msg)) == TTDT_STATUS) {
801             exit(0);
802         } else {
803             return 0;
804         }
805     }
806 }
807           
808
809 /************************************************************************
810  * SendMessageToServer - requestor mode routine to setup callbacks and send
811  *      a message to the dtpad "server" to do one of the following:
812  *
813  *   case 1) restore dtpad session & exit dtpad requestor immediately
814  *   case 2) edit a file & exit dtpad requestor immediately
815  *   case 3) edit a file & and wait till editing is done before exiting
816  *           requestor dtpad
817  *
818  ************************************************************************/
819 static void 
820 SendMessageToServer(
821         Editor *pPad,
822         int argc,
823         char **argv)
824 {
825     StartupStruct *pStruct = (StartupStruct *)XtMalloc(sizeof(StartupStruct));
826     char *fileName, *pArgs;
827     Tt_message msg;
828     Tt_status status;
829     Tttk_op op;
830
831     if (pPad->xrdb.session != (char *)NULL) {
832         fileName = pPad->xrdb.session;
833     } else if (argc > 1) {
834         fileName = argv[argc - 1];
835     } else {
836         fileName = "*";
837     }
838
839     /* -----> Obtain the netfile name of the file to be edited.  If the
840      *        directory can't be accessed via the requestor's host, don't
841      *        use the server since we can't pass it a netfile name and we
842      *        can't assume the filename is appropriate on the server's host.
843      */
844     pPad->fileStuff.netfile = tt_file_netfile(fileName);
845     status = tt_ptr_error(pPad->fileStuff.netfile);
846     if (status != TT_OK) {
847         tt_free(pPad->fileStuff.netfile);
848         pPad->fileStuff.netfile = (char *) NULL;
849         pPad->xrdb.standAlone = True;
850         InitEditSessionAndFirstPad(pPad, argc, argv);   /* start standAlone  */
851         TTwarning( pPad, status,
852                    GETMESSAGE(7, 12, "Running in standalone mode ...") );
853         return;
854     }
855
856     /*
857      * Keep from saving our session if we've sent a message to the server.
858      * We'll restore this to true iff the server sends a failure notification.
859      */
860     pPad->inUse = False;
861
862     pStruct->pPad = pPad;
863     pStruct->argc = argc;
864     pStruct->argv = argv;
865
866 #ifdef HAVE_EDITRES
867     XtAddEventHandler(topLevelWithWmCommand, 0, True,
868                       (XtEventHandler) _XEditResCheckMessages,
869                       (XtPointer) NULL);
870 #endif
871
872     status = TTstartDesktopMediaExchange(topLevelWithWmCommand, pPad);
873     if (TT_OK != status) {
874         tt_free(pPad->fileStuff.netfile);
875         pPad->fileStuff.netfile = (char *) NULL;
876         pPad->xrdb.standAlone = True;
877         InitEditSessionAndFirstPad(pPad, argc, argv);
878         TTwarning( pPad, status,
879                    GETMESSAGE(7, 12, "Running in standalone mode ...") );
880         return;
881     }
882
883     /*--------------------------------------------------------
884      * case 2 (noBlocking) - exit if the request is successfully
885      *          handled by the dtpad server.
886      * case 3 (Blocking) - do nothing if the request is successfully
887      *          handled, then wait for a Reply from the dtpad
888      *          server to exit.
889      *
890      * Build and send either a TTME_EDIT request if a file is specified
891      * or TTME_INSTANTIATE if no file is specified.  These requests
892      * are handled via TTmedia_ptype_declareCB() on the dtpad server.
893      *
894      * 1. If server can not handle the request, it will fail the request
895      *    immediately.  pLoadMsgCB will receive the reply message and
896      *    start a standAlone dtpad.
897      * 2. If server can handle the request, it will send a Status notice.
898      *    pStatusCB will receive the notice and either exit (noBlocking)
899      *    or do nothing (Blocking).  The server will then reply to a
900      *    TTME_EDIT request when editing for the specified file/buffer
901      *    is done (the edit window may still remain open though) and
902      *    to a TTME_INSTANTIATE request when the edit window is closed.
903      *-------------------------------------------------------*/
904
905      if (strcmp(fileName, "*") == 0) {
906          op = TTME_INSTANTIATE;
907      } else {
908          op = TTME_EDIT;
909      }
910
911      msg = ttmedia_load(0,
912                         pLoadMsgCB,
913                         NULL,
914                         op,
915                         "C_STRING",
916                         NULL,
917                         0,
918                         fileName,
919                         NULL,
920                         0);
921      
922      status = tt_ptr_error(msg);
923      if (tt_is_err(status))
924      {
925           /* Error message */
926           return;
927      }
928
929      ttdt_subcontract_manage(msg,
930                         pStatusCB,
931                         NULL,
932                         (void *) ((XtArgVal) pPad->xrdb.blocking));/* client data */
933
934      /* Add pArgs to msg using tt_message_context_set */
935      SetupLoadArgs(msg, pPad);
936      tt_message_user_set(msg, 0, pStruct);
937      tt_message_send(msg);
938 }
939
940
941 /************************************************************************
942  * InitEditSessionAndFirstPad - performs initialization related to
943  *      starting the edit session and then calls the routine that creates
944  *      the first pPad Editor.
945  *
946  * (was InitGlobalAndFirstPad)          
947  ************************************************************************/
948 /* ARGSUSED */
949 static void 
950 InitEditSessionAndFirstPad(
951         Editor *pPad,
952         int argc,
953         char **argv)
954 {
955     char *pTmp = (char *)NULL;
956
957     CreateDefaultImage ((char *) warningBits, 32, 32, "warn_image");
958
959     xa_WM_DELETE_WINDOW = XInternAtom(pPad->display, 
960                                              "WM_DELETE_WINDOW", False);
961
962     /* get the users group and user id for file type checking */
963     pPad->group_id = getgid();
964     pPad->user_id = getuid();
965
966     /* Set up file name */
967     if (pPad->saveRestore == True && argv[3] != NULL) {
968         pTmp = argv[3];
969     } else if (argc > 1) {
970         pTmp = argv[argc - 1];
971     }
972
973     if (pTmp != (char *)NULL) {
974         pPad->fileStuff.fileName = (char *) XtMalloc(strlen(pTmp) + 1);
975         strcpy(pPad->fileStuff.fileName, pTmp);
976     } else {
977         pPad->fileStuff.fileName = (char *)NULL;
978     }
979     pPad->fileStuff.lastIncludeName = (char *)NULL;
980     RealizeNewPad(pPad);        /* display first pPad Editor window */
981
982     setPanicConditions();       /* Set up emergency calls to PanicSave */
983
984     /*
985      * Set up a handler for SIGCLD so that the command invoker library
986      * doesn't leave zombies.
987      */
988     {
989         struct sigaction act;
990         sigfillset(&act.sa_mask);
991         act.sa_flags = 0;
992         act.sa_handler = SigcldHndlr;
993         sigaction(SIGCHLD, &act, (struct sigaction *)NULL);
994     }
995 }
996
997
998 /************************************************************************
999  * RealizeNewPad - creates the GUI components of a pPad Editor, sets
1000  *      pPad resources, maps the window and loads the file to be edited.
1001  *
1002  *  NOTE: This routine in normally called only when a new edit window is to
1003  *        be displayed.  However, it is also called when the server is first
1004  *        started (when no edit requests have been received).  In this
1005  *        situation, the window is not mapped and the file is not loaded.
1006  *        These actions are done when the dummy pPad is "reused" when the
1007  *        actual edit request is received from the requestor dtpad.
1008  *
1009  ************************************************************************/
1010 void
1011 RealizeNewPad(
1012         Editor *pPad)
1013 {
1014     Arg al[5];                  /* arg list */
1015     register int ac;            /* arg count */
1016
1017     /* Create the title */
1018     pPad->dialogTitle = DialogTitle(pPad);
1019
1020     /* Set some applic shell resources */
1021     ac = 0;
1022     XtSetArg(al[ac], XmNuseAsyncGeometry, True); ac++;
1023     XtSetArg(al[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
1024     XtSetArg(al[ac], XmNgeometry, NULL); ac++;
1025     XtSetValues(pPad->app_shell, al, ac);
1026
1027     if (pPad->xrdb.session != NULL) {
1028        restoreSession(pPad);
1029     }
1030     pPad->nodo = False;
1031
1032     /* Create Main Window */
1033     pPad->mainWindow = XmCreateMainWindow (pPad->app_shell, "main", al, 0);
1034     XtManageChild (pPad->mainWindow);
1035
1036     /* Create MenuBar in Main Window */
1037     CreateMenuBar(pPad);
1038     XtManageChild (pPad->menu_bar);
1039
1040     /* Create the DT Editor Widget in the Main Window. */
1041     CreateEditorWidget (pPad);
1042     XtManageChild (pPad->editor);
1043
1044 #ifdef POPUP
1045     /* Create the popup for the editor */
1046     CreatePopupMenu (pPad);
1047 #endif
1048
1049     /* Associate menu bar and editor widgets created above with menu bar and
1050      * work area of the main window (the main window command line area and
1051      * the horizontal/vertical scroll bars are not used) */
1052     XmMainWindowSetAreas(pPad->mainWindow, pPad->menu_bar,
1053                 (Widget) NULL, (Widget) NULL, (Widget) NULL,
1054                 pPad->editor);
1055
1056     /* Realize toplevel widgets. */
1057     XtSetMappedWhenManaged(pPad->app_shell, False);
1058     XtRealizeWidget (pPad->app_shell);
1059
1060     /* Set the window title */
1061     ChangeMainWindowTitle(pPad);
1062
1063     XSync(pPad->display, 0);
1064
1065     /* setup where a close by the window manager will be handled */
1066     XmAddWMProtocolCallback(pPad->app_shell, xa_WM_DELETE_WINDOW,
1067                             (XtCallbackProc) closeCB, (XtPointer)pPad);
1068
1069     /* reset the "save with newLines" flag */
1070     pPad->fileStuff.saveWithNewlines = True;
1071
1072     /* set app shell geometry (pixels), resize hints, position & size hints */
1073     SetWindowSize(pPad);
1074
1075     /* set the state of the pPad based on its resources */
1076     SetStateFromResources(pPad);
1077     
1078     /* set File menu SaveAs label/mnemonic based on xrdb.nameChange */
1079     SetSaveAsLabelAndDialog(pPad);
1080
1081     ChangeMainWindowTitle(pPad);
1082
1083     /* If we're the server initially starting up, this is a "dummy" edit
1084      * request and we really don't want to map anything to the display yet
1085      * (this will be done when the actual edit request comes in and this
1086      * dummy pPad is reused and mapped). */
1087     if (pPad->xrdb.server == False) {
1088         XtSetMappedWhenManaged(pPad->app_shell, True);
1089         XtPopup(pPad->app_shell, XtGrabNone);
1090         XtMapWidget(pPad->app_shell);
1091         numActivePads++;
1092     }
1093
1094     /* load the file (if there's actually a file name specified) */
1095     LoadFile(pPad, NULL);
1096
1097 }
1098
1099
1100 /************************************************************************
1101  * ManageOldPad - opens a new file in an exiting Editor pad "window".
1102  * 
1103  *      Existing windows have their widget structure already created but
1104  *      may or may not be managed/visible.   The existing window could be
1105  *      any of the following:
1106  *
1107  *        o the initial "dummy" window created when the server was started
1108  *          up (this window is not managed until the actual edit message
1109  *          from the requestor is received)
1110  *        o a window which has been closed previously
1111  *        o a window that is currently managed/visible and is to be reused
1112  *          (and is identified by the window id resource)
1113  ************************************************************************/
1114 void
1115 ManageOldPad(
1116         Editor *pPad,
1117         Boolean isCurrentlyVisible)
1118 {
1119
1120     if(pPad->xrdb.session != NULL)
1121        restoreSession(pPad);
1122
1123     /*.. create the title */
1124     ChangeMainWindowTitle(pPad);
1125     SetStateFromResources(pPad);  /* set the pPad state based on resources */
1126     pPad->nodo = False;
1127     
1128     /* set File menu SaveAs label/mnemonic based on xrdb.nameChange */
1129     SetSaveAsLabelAndDialog(pPad);
1130
1131     /* set app shell geometry (pixels), resize hints, position & size hints */
1132     SetWindowSize(pPad);
1133
1134     ChangeMainWindowTitle(pPad);
1135
1136     /* If the window is iconified and autoRaise is disabled, then
1137      * we don't what to deiconify the window.
1138      */
1139     if (!isCurrentlyVisible) {
1140        XtSetMappedWhenManaged(pPad->app_shell, True);
1141        XtPopup(pPad->app_shell, XtGrabNone);
1142        XtMapWidget(pPad->app_shell);
1143     }
1144
1145     LoadFile(pPad, NULL);
1146 }
1147
1148
1149 /************************************************************************
1150  * StartDbUpdate - 
1151  ************************************************************************/
1152 /* ARGSUSED */
1153 void
1154 StartDbUpdate(
1155         XtPointer clientData)
1156 {
1157
1158    /* Read in the new databases */
1159    DtDbLoad();
1160    ActionDBInitialized = True;
1161 }
1162
1163
1164 /************************************************************************
1165  * exitCB - 
1166  ************************************************************************/
1167 /* ARGSUSED */
1168 void
1169 exitCB(Widget w, XtPointer callData, XtPointer clientData)
1170 {
1171     exit((XtArgVal) clientData);
1172 }
1173
1174 /************************************************************************
1175  * setPanicConditions - 
1176  ************************************************************************/
1177 void
1178 setPanicConditions(void)
1179 {
1180     struct sigaction act;
1181
1182     sigfillset(&act.sa_mask);
1183     /*
1184     signal(SIGHUP, (void (*)(int))PanicSave);
1185     signal(SIGINT, (void (*)(int))PanicSave);
1186     signal(SIGQUIT, (void (*)(int))PanicSave);
1187     signal(SIGILL, (void (*)(int))PanicSave);
1188     signal(SIGABRT, (void (*)(int))PanicSave);
1189     signal(SIGIOT, (void (*)(int))PanicSave);
1190     signal(SIGEMT, (void (*)(int))PanicSave);
1191     signal(SIGFPE, (void (*)(int))PanicSave);
1192     signal(SIGBUS, (void (*)(int))PanicSave);
1193     signal(SIGSEGV, (void (*)(int))PanicSave);
1194     signal(SIGSYS, (void (*)(int))PanicSave);
1195     signal(SIGPIPE, (void (*)(int))PanicSave);
1196     signal(SIGTERM, (void (*)(int))PanicSave);
1197     */
1198     sigfillset(&act.sa_mask);
1199     act.sa_flags = 0;
1200     act.sa_handler = (void (*)(int))PanicSave;
1201     sigaction(SIGHUP, &act, (struct sigaction *)NULL);
1202     sigaction(SIGINT, &act, (struct sigaction *)NULL);
1203     sigaction(SIGQUIT, &act, (struct sigaction *)NULL);
1204     sigaction(SIGILL, &act, (struct sigaction *)NULL);
1205     sigaction(SIGABRT, &act, (struct sigaction *)NULL);
1206     sigaction(SIGIOT, &act, (struct sigaction *)NULL);
1207 #ifdef SIGEMT
1208     sigaction(SIGEMT, &act, (struct sigaction *)NULL);
1209 #endif
1210     sigaction(SIGFPE, &act, (struct sigaction *)NULL);
1211     sigaction(SIGBUS, &act, (struct sigaction *)NULL);
1212     sigaction(SIGSEGV, &act, (struct sigaction *)NULL);
1213 #ifdef SIGSYS
1214     sigaction(SIGSYS, &act, (struct sigaction *)NULL);
1215 #endif
1216     sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
1217     sigaction(SIGTERM, &act, (struct sigaction *)NULL);
1218
1219     /* TTT - comment out for debugging TookTalk code */
1220 #if 0
1221     XSetErrorHandler((int (*)()) PanicSave);
1222     XSetIOErrorHandler((int (*)())PanicSave);
1223 #endif
1224     XSetErrorHandler(dtpadXErrorHandler);
1225     XSetIOErrorHandler(dtpadXIOErrorHandler);
1226 }
1227
1228
1229 /************************************************************************
1230  * GetAdjustedResizeHints - returns the size hints for the pPad Dt Editor
1231  *      widget with its min_height incremented by the height of dtpad's
1232  *      menu bar.
1233  ************************************************************************/
1234 static void
1235 GetAdjustedResizeHints(
1236         Editor *pPad,
1237         XSizeHints *pHints)
1238 {
1239     Arg al[2];                  /* arg list */
1240     register int ac;            /* arg count */
1241     Dimension MBheight;
1242
1243     /* get Dt Editor widget size hints */
1244     DtEditorGetSizeHints(pPad->editor, pHints);
1245     
1246     /* get the menu bar height */
1247     XtSetArg(al[0], XmNheight, &MBheight);
1248     XtGetValues(pPad->menu_bar, al, 1);
1249
1250     /* adjust the editor widget min height by menu bar height */
1251     pHints->min_height += MBheight;
1252     pHints->base_height += MBheight;
1253
1254 }
1255
1256
1257 /************************************************************************
1258  * SetAppShellResizeHints - sets the app_shell's normal resize hints
1259  *      (resize increment, minimum window size, etc.) based on the resize
1260  *      hints returned from the Dt Editor widget but with the dtpad menu
1261  *      bar height added to the min_height.
1262  ************************************************************************/
1263 void
1264 SetAppShellResizeHints(
1265         Editor *pPad)
1266 {
1267     XSizeHints  size_hints;
1268     long supplied_return;
1269
1270     /* make sure stuff not set by GetAdjustedResizeHints is not lost */
1271     XGetWMSizeHints(pPad->display, XtWindow(pPad->app_shell), &size_hints,
1272                                           &supplied_return, XA_WM_NORMAL_HINTS);
1273
1274     GetAdjustedResizeHints(pPad, &size_hints);  /* consider the menu bar */
1275
1276     XSetWMSizeHints(pPad->display, XtWindow(pPad->app_shell), &size_hints,
1277                     XA_WM_NORMAL_HINTS);
1278 }
1279
1280
1281 /************************************************************************
1282  * SetPadGeometry - sets the pad's width, height and x & y IN PIXELS
1283  *      based on the pad's geometry string.  Returns a flag
1284  *      indicating which geometry components were specified.
1285  ************************************************************************/
1286 static int
1287 SetPadGeometry(
1288         Editor *pPad)
1289 {
1290     int                  geometryBits;
1291     int                  geometryX;
1292     int                  geometryY;
1293     unsigned int         geometryWidth;
1294     unsigned int         geometryHeight;
1295     XSizeHints  size_hints;
1296
1297
1298     /* -----> convert geometry string to integers */
1299     geometryBits = XParseGeometry(pPad->geometry,   /* geometry string  */
1300                                   &geometryX,       /* x position return*/
1301                                   &geometryY,       /* y position return*/
1302                                   &geometryWidth,   /* width return     */
1303                                   &geometryHeight); /* height return    */
1304
1305     if (!(geometryBits & WidthValue))
1306         geometryWidth  = DEFAULT_COLS;
1307     if (!(geometryBits & HeightValue))
1308         geometryHeight = DEFAULT_ROWS;
1309
1310     /* -----> Get width/height increments and minimum sizes in pixels
1311      *        and then compute window width/height in pixels. 
1312      *        The min_width & min_height size hints include a character. */
1313     GetAdjustedResizeHints(pPad, &size_hints);  /* consider the menu bar */
1314     geometryWidth = geometryWidth * size_hints.width_inc +
1315                         size_hints.min_width - size_hints.width_inc;
1316     geometryHeight = geometryHeight * size_hints.height_inc +
1317                         size_hints.min_height - size_hints.height_inc;
1318
1319      /* -----> allow for negative X and Y values */
1320     if (geometryBits & XValue) {
1321         if (geometryBits & XNegative) {
1322             geometryX += DisplayWidth(pPad->display,
1323                                       DefaultScreen(pPad->display)) -
1324                                       geometryWidth -
1325                                       2 * pPad->app_shell->core.border_width;
1326         }
1327     } else {
1328         geometryX = 0;
1329     }
1330     if (geometryBits & YValue) {
1331         if (geometryBits & YNegative) {
1332             geometryY += DisplayHeight(pPad->display,
1333                                        DefaultScreen(pPad->display)) -
1334                                        geometryHeight -
1335                                        2 * pPad->app_shell->core.border_width;
1336         }
1337     } else {
1338         geometryY = 0;
1339     }
1340
1341     /* -----> set pad's pixel geometry */
1342     pPad->width = geometryWidth;
1343     pPad->height = geometryHeight;
1344     pPad->x =  geometryX;
1345     pPad->y = geometryY;
1346
1347     return geometryBits;
1348 }
1349
1350
1351 /************************************************************************
1352  * SetWindowSize - sets the following for the pad's application shell:
1353  *
1354  *      1) geometry (in pixels) - after converting the geometry string
1355  *                      to pixel values and storing in the pad struct
1356  *      2) resize hints (PMinSize, PResizeInc and PBaseSize)
1357  *      3) position and size hints (PPosition and PSize)
1358  *
1359  ************************************************************************/
1360 void
1361 SetWindowSize(
1362         Editor *pPad)
1363 {
1364     Arg al[10];                 /* arg list */
1365     register int ac;            /* arg count */
1366     XSizeHints  size_hints;
1367     XWMHints   *wmhints;
1368     long supplied_return;
1369     int geometryBits;
1370     XWindowChanges changesStruct;
1371     WMShellWidget wm;
1372
1373     /* -----> set pad's app_shell geometry (in pixels) */
1374     ac = 0;
1375     if (pPad->saveRestore == True) {
1376         /* if we're restoring a session, the geometry is already in
1377          * pixel values so set the app_shell geometry directly */
1378         wm = (WMShellWidget)(pPad->app_shell);
1379         wm->wm.size_hints.flags |= USSize|USPosition;
1380         wm->wm.size_hints.flags |= PMinSize|PResizeInc|PBaseSize;
1381         XtSetArg (al[ac], XmNx, pPad->x);  ac++;
1382         XtSetArg (al[ac], XmNy, pPad->y);  ac++;
1383         XtSetArg (al[ac], XmNwidth, pPad->width);  ac++;
1384         XtSetArg (al[ac], XmNheight, pPad->height);  ac++;
1385         XtSetValues(pPad->app_shell, al, ac);
1386     }  else {
1387         /* parse the pPad->geometry STRING into 
1388          * pPad->geometry[Width|Height|X|Y] PIXELS values and
1389          * return flags indicating which geometry parts were specified */
1390         geometryBits = SetPadGeometry(pPad); /* parse geometry str to pixels */
1391         wm = (WMShellWidget)(pPad->app_shell);
1392
1393         /* set only the geometry parts that were specified */
1394         if (geometryBits & XValue) {
1395             wm->wm.size_hints.flags |= USPosition;
1396             XtSetArg (al[ac], XmNx, pPad->x);  ac++; 
1397         }
1398         if (geometryBits & YValue) {
1399             wm->wm.size_hints.flags |= USPosition;
1400             XtSetArg (al[ac], XmNy, pPad->y);  ac++; 
1401         }
1402         if (geometryBits & WidthValue) {
1403             wm->wm.size_hints.flags |= USSize;
1404             XtSetArg (al[ac], XmNwidth, pPad->width);  ac++;
1405         }
1406         if (geometryBits & HeightValue) {
1407             wm->wm.size_hints.flags |= USSize;
1408             XtSetArg (al[ac], XmNheight, pPad->height);  ac++;
1409         }
1410         if (ac > 0) {
1411             XtSetValues(pPad->app_shell, al, ac);
1412         }
1413     }
1414
1415     /* -----> set app_shell resize hints based on resize hints returned
1416      *        from the Dt Editor widget (PMinSize, PResizeInc and PBaseSize)
1417      *        and adjusted by the dtpad menu bar */ 
1418     SetAppShellResizeHints(pPad);
1419
1420
1421     /* -----> set app_shell position and size hints
1422      *        (and whether user specified (US) or program specified (P) */
1423     XGetWMSizeHints(pPad->display, XtWindow(pPad->app_shell), &size_hints,
1424                                           &supplied_return, XA_WM_NORMAL_HINTS);
1425     wm->wm.size_hints.flags |= PMinSize|PResizeInc|PBaseSize;/* set previously*/
1426     if (pPad->saveRestore == True) {
1427         wm->wm.size_hints.x = pPad->x;
1428         wm->wm.size_hints.y = pPad->y;
1429         wm->wm.size_hints.width = pPad->width;
1430         wm->wm.size_hints.height = pPad->height;
1431         wm->wm.size_hints.min_width = size_hints.min_width;
1432         wm->wm.size_hints.min_height = size_hints.min_height;
1433         wm->wm.size_hints.width_inc = size_hints.width_inc;
1434         wm->wm.size_hints.height_inc = size_hints.height_inc;
1435         wm->wm.base_width = size_hints.base_width;
1436         wm->wm.base_height = size_hints.base_height;
1437         wm->wm.size_hints.flags |= USSize|USPosition;
1438     } else {
1439         if (geometryBits & XValue && geometryBits & YValue) {
1440             wm->wm.size_hints.x = pPad->x;
1441             wm->wm.size_hints.y = pPad->y;
1442             wm->wm.size_hints.flags |= USPosition;
1443         } else {
1444             wm->wm.size_hints.flags |= PPosition;
1445         }
1446         if (geometryBits & WidthValue && geometryBits & HeightValue) {
1447             wm->wm.size_hints.width = pPad->width;
1448             wm->wm.size_hints.height = pPad->height;
1449             wm->wm.size_hints.min_width = size_hints.min_width;
1450             wm->wm.size_hints.min_height = size_hints.min_height;
1451             wm->wm.size_hints.width_inc = size_hints.width_inc;
1452             wm->wm.size_hints.height_inc = size_hints.height_inc;
1453             wm->wm.base_width = size_hints.base_width;
1454             wm->wm.base_height = size_hints.base_height;
1455             wm->wm.size_hints.flags |= USSize;
1456         } else {
1457             wm->wm.size_hints.flags |= PSize;
1458         }
1459     }
1460
1461     /* Remove the iconify hint from the current shell */
1462     wmhints = XGetWMHints(XtDisplay(pPad->app_shell), 
1463                            XtWindow(pPad->app_shell));
1464     wmhints->flags |= IconWindowHint;
1465     if (pPad->iconic)
1466         wmhints->initial_state = IconicState;
1467     else
1468         wmhints->initial_state = NormalState;
1469     XSetWMHints(XtDisplay(pPad->app_shell), 
1470                  XtWindow(pPad->app_shell), wmhints);
1471
1472     changesStruct.x = pPad->x;
1473     changesStruct.y = pPad->y;
1474     changesStruct.width = pPad->width;
1475     changesStruct.height = pPad->height;
1476     XConfigureWindow(pPad->display, XtWindow(pPad->app_shell), 
1477                      CWWidth | CWHeight, &changesStruct);
1478 }
1479
1480
1481 /************************************************************************
1482  * SetInitialMenuSensitivity - sets the initial sensitivity of various menu
1483         items primarily based on whether or not we're in viewOnly mode.
1484  ************************************************************************/
1485 static void
1486 SetInitialMenuSensitivity(
1487         Editor *pPad)
1488 {
1489     Boolean editable = ! pPad->xrdb.viewOnly;
1490
1491     /* -----> set sensitivity of File menu items */
1492     XtSetSensitive(pPad->fileStuff.fileWidgets.newBtn, editable);
1493         /****Begin Change - SuG 5/5/95 */
1494     XtSetSensitive(pPad->fileStuff.fileWidgets.openBtn, editable);
1495     XtSetSensitive(pPad->fileStuff.fileWidgets.includeBtn, editable);
1496     XtSetSensitive(pPad->fileStuff.fileWidgets.saveBtn, editable);
1497
1498     /* -----> set sensitivity of Edit menu items
1499      * Edit Menu items that deal with the current selection (Cut, Copy,
1500      * Clear and Delete) are made sensitive/insensitive via the DtEditor
1501      * widget's DtNtextSelectCallback and DtNtextDeselectCallback.
1502      * Currently nothing is being done with Paste based on text
1503      * selected/deselected outside the edit window.
1504      * findChangeBtn is left sensitive since the DtEditor widget will
1505      * enable/disable changes in the Find/Change dialog based on the
1506      * DtNeditable resource. */
1507     XtSetSensitive(pPad->editStuff.widgets.undoBtn, editable);
1508     XtSetSensitive(pPad->editStuff.widgets.pasteBtn, editable);
1509     if (pPad->editStuff.widgets.checkSpellingBtn != (Widget) NULL) {
1510         XtSetSensitive(pPad->editStuff.widgets.checkSpellingBtn, editable);
1511     }
1512     SetSelectionMenuItems(pPad, False); /* set Cut, Copy, Clear & Delete */
1513
1514      /* -----> set sensitivity of Format menu */
1515     XtSetSensitive(pPad->formatStuff.widgets.formatBtn, editable);
1516
1517     /* -----> set sensitivity of Options menu items */
1518     XtSetSensitive(pPad->optionsStuff.widgets.overstrikeBtn, editable);
1519     XtSetSensitive(pPad->optionsStuff.widgets.wordWrapBtn, editable);
1520     
1521 }
1522
1523
1524 /************************************************************************
1525  * SetStateFromResources - set pPad's state (e.g. GUI components) based on
1526  *      current pPad->xrdb resource values.  The resources are initially
1527  *      obtained from either:
1528  *
1529  *      1) the dtpad requestor's resource data base and command line
1530  *         options - if running in standAlone mode or in server mode and
1531  *         handling an Edit request containing resource context fields
1532  *      2) the server's data base - if running in server mode and
1533  *         handling an Edit request without resource context fields
1534  *
1535  ************************************************************************/
1536 static void
1537 SetStateFromResources(
1538         Editor *pPad)
1539 {
1540     Arg al[1];                  /* arg list */
1541     OptionsMenuWidgets *pWidg = &pPad->optionsStuff.widgets;
1542     
1543     SetWorkSpaceHints(pPad->app_shell, pPad->xrdb.workspaceList);
1544     /* Create the title */
1545     pPad->dialogTitle = DialogTitle(pPad);
1546
1547     /* -----> Set the overstrike, wordWrap and statusLine for the Editor
1548      *        widget and corresponding Options menu toggle buttons.
1549      *        This is done in one place - in the valueChanged callback for
1550      *        each option - which is called only if parameter 3 is True AND
1551      *        the state being set is different than what it currently is.
1552      *        The first XmToggleButtonSetState (with parm 3 = False) ensures
1553      *        that the state is opposite of what we want it to be so that
1554      *        when we set it, the valueChanged callback will be called. */
1555
1556     if (pPad->xrdb.overstrike == XmToggleButtonGetState(pWidg->overstrikeBtn))
1557         XmToggleButtonSetState(pWidg->overstrikeBtn,
1558                                 !pPad->xrdb.overstrike, False);
1559     XmToggleButtonSetState(pWidg->overstrikeBtn,
1560                                 pPad->xrdb.overstrike, True);
1561
1562     if (pPad->xrdb.wordWrap == XmToggleButtonGetState(pWidg->wordWrapBtn))
1563         XmToggleButtonSetState(pWidg->wordWrapBtn,
1564                                 !pPad->xrdb.wordWrap, False);
1565     XmToggleButtonSetState(pWidg->wordWrapBtn,
1566                                 pPad->xrdb.wordWrap, True);
1567
1568     if (pPad->xrdb.statusLine == XmToggleButtonGetState(pWidg->statusLineBtn))
1569         XmToggleButtonSetState(pWidg->statusLineBtn,
1570                                 !pPad->xrdb.statusLine, False);
1571     XmToggleButtonSetState(pWidg->statusLineBtn,
1572                                 pPad->xrdb.statusLine, True);
1573
1574     /* -----> Set whether text can be edited */
1575     XtSetArg(al[0], DtNeditable, !pPad->xrdb.viewOnly);
1576     XtSetValues(pPad->editor, al, 1);
1577     SetInitialMenuSensitivity(pPad);
1578
1579 }
1580
1581
1582 /************************************************************************
1583  * SigcldHndlr - 
1584  ************************************************************************/
1585 /* ARGSUSED */
1586 void SigcldHndlr (int dummy)
1587 {
1588     int   status, w;
1589     struct sigaction act;
1590     sigfillset(&act.sa_mask);
1591     act.sa_flags = 0;
1592     act.sa_handler = SigcldHndlr;
1593
1594     w = wait (&status);
1595
1596     /*
1597      * Is this really necessary?
1598      */
1599     sigaction(SIGCHLD, &act, (struct sigaction *)NULL);
1600 }
1601
1602
1603 /************************************************************************
1604  * UnmanageAllDialogs - unmanages all the dialogs which may be managed
1605  *      when a pad gets closed or withdrawn.
1606  ************************************************************************/
1607 void
1608 UnmanageAllDialogs(
1609     Editor *pPad)
1610 {
1611     HelpStruct *pHelp;
1612     /*
1613      * Unmanage all Modal dialogs that might possibly be up.
1614      */
1615     if (pPad->fileStuff.fileWidgets.saveAs.alrdy_exist != (Widget)NULL &&
1616         pPad->fileStuff.fileWidgets.saveAs.alrdy_exist->core.managed == True)
1617     {
1618         XtUnmanageChild(pPad->fileStuff.fileWidgets.saveAs.alrdy_exist);
1619     }
1620
1621     if (pPad->fileStuff.fileWidgets.select.save_warning != (Widget)NULL &&
1622         pPad->fileStuff.fileWidgets.select.save_warning->core.managed == True)
1623     {
1624         XtUnmanageChild(pPad->fileStuff.fileWidgets.select.save_warning);
1625     }
1626
1627     if (pPad->fileStuff.fileWidgets.gen_warning != (Widget)NULL &&
1628         pPad->fileStuff.fileWidgets.gen_warning->core.managed == True)
1629     {
1630         XtUnmanageChild(pPad->fileStuff.fileWidgets.gen_warning);
1631     }
1632     
1633     /*
1634      * Unmanage File menu dialogs that might be posted.
1635      * The Edit and Format menu dialogs are managed by the DtEditor widget.
1636      * XXX - unmanage print dialog too.
1637      */
1638     if (pPad->fileStuff.fileWidgets.select.file_dialog != (Widget)NULL &&
1639         pPad->fileStuff.fileWidgets.select.file_dialog->core.managed == True)
1640     {
1641         XtUnmanageChild(pPad->fileStuff.fileWidgets.select.file_dialog);
1642     }
1643
1644     if (pPad->fileStuff.fileWidgets.saveAs.saveAs_form != (Widget)NULL &&
1645         pPad->fileStuff.fileWidgets.saveAs.saveAs_form->core.managed == True)
1646     {
1647         XtUnmanageChild(pPad->fileStuff.fileWidgets.saveAs.saveAs_form);
1648     }
1649
1650     /*
1651      * Unmanage help if it's up.
1652      */
1653     if (pPad->MainHelp != (Widget)NULL && pPad->MainHelp->core.managed == True)
1654     {
1655         XtUnmanageChild(pPad->MainHelp);
1656     }
1657     for (pHelp = pPad->pHelpCache; pHelp != (HelpStruct *)NULL;
1658          pHelp = pHelp->pNext)
1659     {
1660         if (pHelp->dialog != (Widget)NULL &&
1661             pHelp->dialog->core.managed == True)
1662         {
1663             XtUnmanageChild(pHelp->dialog);
1664         }
1665     }
1666 }
1667
1668
1669 /************************************************************************
1670  * RestoreInitialServerResources - 
1671  ************************************************************************/
1672 void
1673 RestoreInitialServerResources(
1674         Editor *pPad)
1675 {
1676     /* -----> free resource strings */
1677     if (pPad->xrdb.workspaceList != (char *)NULL)
1678         XtFree(pPad->xrdb.workspaceList);
1679     if (pPad->xrdb.session != (char *)NULL)
1680         XtFree(pPad->xrdb.session);
1681     if (pPad->geometry != (char *)NULL)
1682         XtFree(pPad->geometry );
1683
1684     pPad->xrdb = initialServerResources;
1685
1686     /* -----> duplicate resource strings */
1687     if (initialServerResources.workspaceList != (char *)NULL)
1688         pPad->xrdb.workspaceList = strdup(initialServerResources.workspaceList);
1689     if (initialServerResources.session != (char *)NULL)
1690         pPad->xrdb.session = strdup(initialServerResources.session);
1691     if (initialServerGeometry != (char *)NULL)
1692         pPad->geometry = strdup(initialServerGeometry);
1693
1694 }
1695
1696
1697 #ifndef NO_MESSAGE_CATALOG
1698 /*****************************************************************************
1699  *  _DtpadGetMessage - obtains a localized message from dtpad's message catalog
1700  *
1701  * Parameters:
1702  *
1703  *   int        set -           The message catalog set number.
1704  *   int        number -        The message number.
1705  *   char       *string -       The default message if the message is not
1706  *                              retrieved from a message catalog.
1707  *
1708  * Returns: the message string for set 'set' and number 'number'.
1709  *
1710  *****************************************************************************/
1711 char *
1712 _DtpadGetMessage(
1713     int set,
1714     int number,
1715     char *string )
1716 {
1717     char *msg;
1718     nl_catd catopen();
1719     char *catgets();
1720     static int first = 1;
1721     static nl_catd nlmsg_fd;
1722
1723     if ( first ) {
1724         first = 0;
1725         nlmsg_fd = catopen(_DTPAD_CAT_NAME, NL_CAT_LOCALE);
1726     }
1727 #if defined(hpV4)
1728     msg = _DtCatgetsCached(nlmsg_fd, set, number, string);
1729 #else
1730     msg = catgets(nlmsg_fd, set, number, string);
1731 #endif
1732     return (msg);
1733 }
1734
1735 #endif /* NO_MESSAGE_CATALOG */
1736
1737 /************************************************************************
1738  * HostCB - message callback for (op) Get_SysInfo message
1739  ************************************************************************/
1740 /* ARGSUSED */
1741 static
1742 Tt_callback_action
1743 HostCB(Tt_message m, Tt_pattern p)
1744 {
1745   Tt_state state = tt_message_state(m);
1746
1747   if (state == TT_HANDLED) {
1748     value = tt_message_arg_val(m, 1);
1749     waitCB = 0;
1750   }
1751 }
1752
1753 /************************************************************************
1754  *
1755  *  Usage
1756  *      When incorrect parameters have been specified on the command
1757  *      line, print out a set of messages detailing the correct use
1758  *      and exit.
1759  *
1760  ************************************************************************/
1761
1762 static void
1763 Usage(
1764         char **argv )
1765 {
1766    char * template;
1767    char * message_string1 = "'%s' is a bad option.\nUsage: %s...\n"
1768                          "   -saveOnClose\n\t"
1769                          "Dtpad automatically and silently saves the current text when there\n\t"
1770                          "are unsaved changes and the Text Editor is closed.\n\n"
1771                          "   -missingFileWarning\n\t"
1772                          "Posts a warning dialog whenever a file name is specified and\n\t"
1773                          "the file dones not exist or cannot be accessed.\n\n"
1774                          "   -noReadOnlyWarning\n\t"
1775                          "Disables the warning dialog posted whenever a file is\n\t"
1776                          "specified for which the user does not have write permission.\n\n"
1777                          "   -noNameChange\n\t"
1778                          "Indicates that the default file name associated with the\n\t"
1779                          "current text is not to change when the text is saved under a\n\t"
1780                          "name different than what it was read in under.\n\n"
1781                          "   -viewOnly\n\t"
1782                          "Disallows editing of text in the edit window, essentially\n\t"
1783                          "turning the Text Editor into a Text Viewer.\n\n"
1784                          "   -statusLine\n\t"
1785                          "Displays a status line at the bottom of the edit window.  The\n\t"
1786                          "status line shows the line number of the line where the text\n\t"
1787                          "cursor is currently positioned.\n\n"
1788                          "   -wrapToFit\n\t"
1789                          "Initially turns on wrap-to-fit mode.\n\n"
1790                          "   -workspaceList WorkspaceList\n\t"
1791                          "Displays the edit window for the current invocation of the\n\t"
1792                          "Text Editor in the specified workspace or workspaces.\n\n"
1793                          "   -session SessionFile\n";
1794
1795    char * message_string2 = "\tRestores the Text Editor to all text editing windows and\n\t"
1796                          "settings that were in effect at a previous CDE shutdown.  All\n\t"
1797                          "other command-line options are ignored when this option is\n\t"
1798                          "specified.\n\n"
1799                          "   -standAlone\n\t"
1800                          "Forces the current invocation of the Text Editor to do its\n\t"
1801                          "own text processing in its own window, independent of the\n\t"
1802                          "Text Editor server.\n\n"
1803                          "   -noBlocking\n\t"
1804                          "Terminates the Text Editor requestor process as soon as the\n\t"
1805                          "Text Editor server determines that it can handle the\n\t"
1806                          "requestor's edit request.\n\n"
1807                          "   -server\n\t"
1808                          "Forces a Text Editor server to be started up (if one is not\n\t"
1809                          "already running) to process all subsequent edit requests for\n\t"
1810                          "the display.\n\n"
1811                          "   -exitOnLastClose\n\t"
1812                          "Specifies that the Text Editor server process is to terminate\n\t"
1813                          "when the last edit window for the display is closed.  It\n\t"
1814                          "should only be used with the -server option since it only\n\t"
1815                          "applies to the server process.\n\n"
1816                          "See the dtpad man page for more details on any of these options.\n\n";
1817
1818
1819    template = (GETMESSAGE(7,9, message_string1));
1820
1821    fprintf (stderr, template, argv[1], argv[0]);
1822
1823    template = (GETMESSAGE(7,10, message_string2));
1824
1825    fprintf (stderr, "%s", template);
1826
1827    exit (0);
1828 }
1829
1830
1831
1832 /************************************************************************
1833  *
1834  *  dtpadXErrorHandler
1835  *
1836  ************************************************************************/
1837
1838 static int
1839 dtpadXErrorHandler(
1840         Display *display,
1841         XErrorEvent *xerr)
1842 {
1843     #define _DTPAD_BUFSIZE 1024
1844     static char msg[_DTPAD_BUFSIZE];
1845
1846     /* log error */
1847     _DtPrintDefaultErrorSafe(display, xerr, msg, _DTPAD_BUFSIZE);
1848     _DtSimpleError("dtpad", DtWarning, NULL, msg, NULL);
1849
1850     /*
1851      * if the error occured on the print display we're going to set
1852      * a variable so that and when the job is done, right before calling
1853      * XpEndJob, we call XpCancelJob, and notify the user.
1854      */
1855
1856     if (PrintJobIsActivePrintDisplay(display) && xerr->error_code == BadAlloc)
1857     {
1858         PrintJobSetErrorPrintDisplay(display);
1859         return 1;
1860     }
1861
1862     XGetErrorText(display, xerr->error_code, msg, 1024);
1863     fprintf(stderr, "Error Code %s\n", msg);
1864     PanicSave();
1865     return 1;
1866 }
1867
1868
1869
1870 /************************************************************************
1871  *
1872  *  dtpadXIOErrorHandler
1873  *
1874  ************************************************************************/
1875
1876 static int
1877 dtpadXIOErrorHandler(
1878         Display *display)
1879 {
1880     static char msg[1024];
1881
1882     fprintf(stderr, "X IO Error");
1883     PanicSave();
1884 }