remove OSF1 support
[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 preceding 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         /*--------------------------------------------------------
443          * Requestor Mode
444          *
445          *      Just tell server to do actual editing and wait
446          *      for DTPAD_DONE msg from server to exit (or exit
447          *      immediately if -noBlocking).
448          *
449          *-------------------------------------------------------*/
450
451         /* Send message to dtpad server to either open-and-edit a
452          * file or to restart a session.  Also set up callbacks to
453          * handle success, failure and done-editing notification.
454          */
455         SendMessageToServer(pPad, argc, argv);
456     }
457
458     XtAppMainLoop(pPad->app_context);
459     exit(0);
460
461 }
462
463
464 /************************************************************************
465  * CreateFirstPad - Performs initialization common to all modes of
466  *      operation (i.e. to requestor mode, server mode and standAlone
467  *      mode).
468  *
469  *   This routine initializes the primary sturcture used by dtpad, pPadList
470  *   which is a list of Editor structs (pPad) with one entry per edit request.
471  *
472  *   Specifically, this routine:
473  *
474  *   1) creates the first entry in pPadList and returns a pointer to it
475  *   2) initializes Xt and the display, and creates the top level widget
476  *   3) adds the "save yourself" protocol to the top level widget
477  *   4) creates the applic shell widget and applic context
478  *   5) loads the application resources to the initial pPad and sets some
479  *      initial editing process values
480  *
481  *   Creation of subsequent entries in the pPadList (1) and creation of
482  *   corresponding applic shells and contexts (4) are also done by the server
483  *   (via TTmedia_ptype_declareCB) for each new edit request that it receives.
484  *   This means that there is one top level widget and display connection
485  *   per process and one applic shell widget and applic context PER EDIT
486  *   REQUEST (i.e. per entry in pPadList).
487  *
488  *   Note that CreateFirstPad is run in all modes the first time the requestor
489  *   or server starts up and that resource are only loaded via this routine.
490  *   This means that resources are obtained (via XtGetApplicationResources)
491  *   on both the requestor and the server and saved in the initial pPad Editor
492  *   on the requestor or server.  This also means that for requestor dtpads, a 
493  *   pPad struct is created on both the requestor and the server (the server
494  *   pPad may be the initial struct created by CreateFirstPad or it may be a
495  *   subsequent pPad created by TTmedia_ptype_declareCB but with the initial
496  *   server resource values).  For requestor mode, the dtpad pPad resources are
497  *   shipped to the server (in the TTDT_EDIT request) where they override
498  *   resources in the corresponding pPad struct on the server.
499  *
500  *   XXX - Some of the stuff in this routine probably does not need to be
501  *         done in all modes of operation - primarily in requestor mode.
502  *         Note that resources need to be loaded in all modes.
503  *
504  * [SuG 5/12/95] Modified for fishy argument checking.
505  ************************************************************************/
506 static Editor * 
507 CreateFirstPad(
508         int *pArgc,
509         char **argv)
510 {
511     int argc_l;
512     char **argv_l, **c_argv_l;
513     Editor *pPad;
514     Arg al[10];
515     register int ac;
516     Widget foo;
517     int i;
518     /* Added for the argument fix*/
519     char* inS;
520     int in;
521     Atom xa_WM_SAVE_YOURSELF;
522     extern char *optarg;
523     extern int optind, opterr, optind;
524     char c;
525
526     /* Create the 1st Editor entry in list of Editor instances.
527      * This is also done in FindOrCreatePad() for each Editor pad instance */
528     CreatePad(&pPad);
529
530     if (pPad->progname=MbStrrchr(argv[0], '/'))
531         pPad->progname++;
532     else
533         pPad->progname = argv[0];
534
535     /* Initialize the toolkit, open the display and create top level widget */
536     topLevelWithWmCommand = XtInitialize(argv[0], DTPAD_CLASS_NAME, 
537                                    option_list, XtNumber(option_list), 
538                                    (int *) pArgc, argv);
539
540 #if 0
541         /*
542          * At this point Xt has stripped for us all valid arguments. 
543          * If number of arguments is <= 2, first one is program name and second
544          * one will be file name always (we don't care if it has a '-').
545          */
546         if (*pArgc > 2) {
547                  /*
548                  * Now we check for illegal arguments, note argv[0] is 
549                  * progname, so we skip that, argv[last] should be file name 
550                  * so we check for '-' character in (i = 1 to i = (n-1)) to 
551                  * catch inbetween invalids.
552                  * Any extras with '-' as first characters are treated as 
553                  * illegal options and ones without it as superfluous 
554                  * arguments.
555                  */
556                 for (i = 1; i < ((*pArgc) - 1); i++)
557                 {
558                     inS = MbStrchri(argv[i], '-', &in);
559                     if (inS != NULL) {
560                         if (in == 0)
561                         {
562                             printf(GETMESSAGE(2, 2,"dtpad: illegal option: %s"),
563                                    argv[i]);
564                             printf("\n");
565                             exit(1);
566                         }
567                     }
568                     else {
569                         printf(GETMESSAGE(2, 3, "dtpad: extra argument: %s"),
570                                argv[i]);
571                         printf("\n");
572                         exit(1);
573                     }
574                 }
575         }
576 #endif
577
578     ac = 0;
579     XtSetArg(al[ac], XmNgeometry, &pPad->geometry); ac++;
580     XtGetValues(topLevelWithWmCommand, al, ac);
581
582     /* Realize the top level widget */
583     XtSetMappedWhenManaged(topLevelWithWmCommand, False);
584     XtRealizeWidget(topLevelWithWmCommand);
585
586     /* Determine the display connection */
587     if (!(pPad->display = XtDisplay(topLevelWithWmCommand))) {
588         XtError((char *) GETMESSAGE(7, 5, 
589           "Can not open display ... exiting Text Editor."));
590     }
591
592     /* TTT - ToolTalk Debug
593      * XSynchronize(pPad->display, True);
594      */
595
596     /* Add the Save-Yourself protocol to the top level widget.
597      * Application shell widgets (one per Editor request) don't need it,
598      * since they don't have a WM_COMMAND property on them. */
599     xa_WM_SAVE_YOURSELF = XInternAtom(pPad->display, 
600                                              "WM_SAVE_YOURSELF", False);
601     XmAddWMProtocolCallback(topLevelWithWmCommand, xa_WM_SAVE_YOURSELF, 
602                            (XtCallbackProc)SaveSessionCB, (XtPointer)pPadList);
603
604      
605     /* Create the application shell widget and obtain the application context.
606      * This is also done in FindOrCreatePad() for each Editor pad instance */
607     ac = 0;
608     XtSetArg(al[ac], XmNargv, &argv_l); ac++;
609     XtSetArg(al[ac], XmNargc, &argc_l); ac++;
610     XtGetValues(topLevelWithWmCommand, al, ac);
611
612     c_argv_l = (char **) XtMalloc(argc_l * sizeof(char*));
613     for (i=0; i<argc_l; i++)
614       c_argv_l[i] = strdup(argv_l[i]);
615
616     ac = 0;
617     XtSetArg(al[ac], XmNargv, argv_l); ac++;
618     XtSetArg(al[ac], XmNargc, argc_l); ac++;
619     pPad->app_shell = XtAppCreateShell(pPad->progname, DTPAD_CLASS_NAME,
620                                            applicationShellWidgetClass,
621                                            pPad->display, al, ac);
622     pPad->app_context = XtWidgetToApplicationContext(pPad->app_shell);
623
624     /* Get the application resources */
625     XtGetApplicationResources(pPad->app_shell, &pPad->xrdb, resources,
626                               XtNumber(resources), NULL, 0);
627     if (pPad->xrdb.server) {
628         initialServerResources = pPad->xrdb;
629         initialServerResources.server = False; /* so window will be mapped */ 
630         initialServerGeometry = pPad->geometry;
631         if(pPad->xrdb.workspaceList)
632                 pPad->xrdb.workspaceList = strdup(pPad->xrdb.workspaceList);
633         if(pPad->xrdb.session)
634                 pPad->xrdb.session = strdup(pPad->xrdb.session);
635         pPad->geometry = strdup(pPad->geometry);
636     }
637
638     /* Set some initial Editor instance values */
639     if (pPad->xrdb.server == False) {
640         pPad->inUse = True;
641     }
642
643     return pPad;
644 }
645
646
647 /************************************************************************
648  * CreatePad - creates a new entry in the pPadList of Editor structs.
649  *      Both the top of the list (the global, pPadList) and the current
650  *      entry (whose address is passed as a parameter) are updated to
651  *      point to the newly created entry.
652  ************************************************************************/
653 /* ARGSUSED */
654 void 
655 CreatePad(
656         Editor **ppPad)
657 {
658     Editor *pPad;
659
660     pPad = *ppPad = (Editor *) XtCalloc(1, sizeof(Editor));
661     pPad->pPrevPad = (Editor *)NULL;
662
663     if (pPadList == (Editor *)NULL) {
664         pPadList = pPad;
665         pPad->pNextPad = (Editor *)NULL;
666     } else {
667         Editor *pTemp = pPadList;
668         pPadList = pPad;
669         pPad->pNextPad = pTemp;
670         pTemp->pPrevPad = pPad;
671     }
672 }
673
674 /************************************************************************
675  * SetupLoadArgs - pack requestor options into the Edit request
676  ************************************************************************/
677 /* ARGSUSED */
678 void
679 SetupLoadArgs(Tt_message m, Editor *pPad)
680 {
681     ApplicationDataPtr pArgs = &pPad->xrdb;
682     
683     /* -----> Ignore all other resources if restoring a session.
684      * XXX  - Currently, an Edit request is not used to restore a session.
685      *        Instead a "private" ToolTalk request, DtPadSession_Run is
686      *        used (which is sent in SendMessageToServer() and handled in
687      *        HandleTtRequest() - the handler is setup in main()) */
688     if (pPad->xrdb.session != (char *)NULL) {
689       tt_message_context_set(m, "SESSION", pArgs->session);
690       return;
691     }
692
693     /* -----> The following is the only resource passed to the text editor
694      *        server which is not a text editor specific resource.
695      *        It is always passed. */
696     if (pPad->geometry != (char *)NULL) {
697       tt_message_context_set(m, "GEOMETRY", pPad->geometry);
698     }
699
700     /* -----> Basic options */
701     tt_message_context_set(m, "STATUSLINE", pArgs->statusLine ? "t" : "f");
702     tt_message_context_set(m, "WINDOWWORDWRAP", pArgs->wordWrap ? "t" : "f");
703     tt_message_context_set(m, "OVERSTRIKE", pArgs->overstrike ? "t" : "f");
704     tt_message_context_set(m, "SAVEONCLOSE", pArgs->saveOnClose ? "t" : "f");
705     tt_message_context_set(m, "MISSINGFILEWARNING", pArgs->missingFileWarning ? "t" : "f");
706     tt_message_context_set(m, "NOREADONLYWARNING",
707                                 pArgs->readOnlyWarning ? "t" : "f");
708     tt_message_context_set(m, "NONAMECHANGE",
709                                 pArgs->nameChange ? "t" : "f");
710     tt_message_context_set(m, "VIEWONLY", pArgs->viewOnly ? "t" : "f");
711     tt_message_context_set(m, "WORKSPACELIST", pArgs->workspaceList);
712
713     /* -----> client/server control options */
714     if (pArgs->blocking == True) {
715         char *buf = (char *)XtMalloc(32);
716         sprintf(buf, "%ld", (long)getpid());
717         tt_message_context_set(m, "BLOCKING", buf);
718         pPad->blockChannel = buf;
719     }
720 }
721
722
723 /************************************************************************
724  * pLoadMsgCB - requestor side ttmedia_load() callback setup in
725  *      SendMessageToServer() to handle Replies from the dtpad server.
726  *
727  *      Replies are sent by the server via the following functions:
728  *      
729  *      ttMediaLoadReply (in TTmediaReply).  TTmediaReply is executed when:
730  *
731  *        1) an Edit or Display request is being processed and either the
732  *           edit window is closed or a new file is selected by the user
733  *        2) an Instantiate request is being processed and the edit window
734  *           is closed
735  *        3) a Quit request is handled which matches the Edit request
736  *
737  *      tttk_message_fail.  tttk_message_fail is normally called whenever
738  *
739  *        1) the edit/display/instantiate request can't be handled
740  *        2) a buffer is being edited and the user closed the window
741  *           (XXX - actually, this should only be done if a buffer
742  *                  is being edited and there are unsaved changes
743  *                  - otherwise ttMediaLoadReply should be used)
744  *        3) a Quit request is handled for the window and there are
745  *           unsaved changed  
746  *
747  ************************************************************************/
748 Tt_message
749 pLoadMsgCB(Tt_message msg,
750            void *clientData,
751            Tttk_op op,
752            unsigned char *contents,
753            int len,
754            char *file)
755 {
756     Tt_state state = tt_message_state(msg);
757     StartupStruct *pStruct = (StartupStruct *)tt_message_user(msg, 0);
758
759     if (state == TT_HANDLED) {
760         tttk_message_destroy(msg);
761         exit(0);
762     } else if (state == TT_FAILED) {
763         pStruct->pPad->inUse = True;
764         pStruct->pPad->xrdb.server = False;
765         pStruct->pPad->xrdb.standAlone = True;
766         InitEditSessionAndFirstPad(pStruct->pPad, pStruct->argc, pStruct->argv);
767         return 0;
768     } else {
769         return 0;
770     }
771 }
772
773
774 /************************************************************************
775  * pStatusCB - requestor side ttdt_subcontract_manage() callback setup in
776  *      SendMessageToServer() to handle Status messages from the dtpad
777  *      server.
778  *
779  *      The server sends a Status message via ttdt_message_accept() when
780  *      it determines that it can actually handle the EDIT request.
781  *
782  ************************************************************************/
783 Tt_message
784 pStatusCB(Tt_message msg,
785           void *clientdata,
786           Tt_message contract)
787 {
788     if (clientdata) {
789         /* This is the blocking case, just return 0 (we'll exit in
790          * pLoadMsgCB when we get a Reply from the dtpad server when it's
791          * done handling the request).*/
792         return 0;
793     } else {
794         /* This is the non-blocking case, exit if this is a Status notice */
795         if (tttk_string_op(tt_message_op(msg)) == TTDT_STATUS) {
796             exit(0);
797         } else {
798             return 0;
799         }
800     }
801 }
802           
803
804 /************************************************************************
805  * SendMessageToServer - requestor mode routine to setup callbacks and send
806  *      a message to the dtpad "server" to do one of the following:
807  *
808  *   case 1) restore dtpad session & exit dtpad requestor immediately
809  *   case 2) edit a file & exit dtpad requestor immediately
810  *   case 3) edit a file & and wait till editing is done before exiting
811  *           requestor dtpad
812  *
813  ************************************************************************/
814 static void 
815 SendMessageToServer(
816         Editor *pPad,
817         int argc,
818         char **argv)
819 {
820     StartupStruct *pStruct = (StartupStruct *)XtMalloc(sizeof(StartupStruct));
821     char *fileName, *pArgs;
822     Tt_message msg;
823     Tt_status status;
824     Tttk_op op;
825
826     if (pPad->xrdb.session != (char *)NULL) {
827         fileName = pPad->xrdb.session;
828     } else if (argc > 1) {
829         fileName = argv[argc - 1];
830     } else {
831         fileName = "*";
832     }
833
834     /* -----> Obtain the netfile name of the file to be edited.  If the
835      *        directory can't be accessed via the requestor's host, don't
836      *        use the server since we can't pass it a netfile name and we
837      *        can't assume the filename is appropriate on the server's host.
838      */
839     pPad->fileStuff.netfile = tt_file_netfile(fileName);
840     status = tt_ptr_error(pPad->fileStuff.netfile);
841     if (status != TT_OK) {
842         tt_free(pPad->fileStuff.netfile);
843         pPad->fileStuff.netfile = (char *) NULL;
844         pPad->xrdb.standAlone = True;
845         InitEditSessionAndFirstPad(pPad, argc, argv);   /* start standAlone  */
846         TTwarning( pPad, status,
847                    GETMESSAGE(7, 12, "Running in standalone mode ...") );
848         return;
849     }
850
851     /*
852      * Keep from saving our session if we've sent a message to the server.
853      * We'll restore this to true iff the server sends a failure notification.
854      */
855     pPad->inUse = False;
856
857     pStruct->pPad = pPad;
858     pStruct->argc = argc;
859     pStruct->argv = argv;
860
861 #ifdef HAVE_EDITRES
862     XtAddEventHandler(topLevelWithWmCommand, 0, True,
863                       (XtEventHandler) _XEditResCheckMessages,
864                       (XtPointer) NULL);
865 #endif
866
867     status = TTstartDesktopMediaExchange(topLevelWithWmCommand, pPad);
868     if (TT_OK != status) {
869         tt_free(pPad->fileStuff.netfile);
870         pPad->fileStuff.netfile = (char *) NULL;
871         pPad->xrdb.standAlone = True;
872         InitEditSessionAndFirstPad(pPad, argc, argv);
873         TTwarning( pPad, status,
874                    GETMESSAGE(7, 12, "Running in standalone mode ...") );
875         return;
876     }
877
878     /*--------------------------------------------------------
879      * case 2 (noBlocking) - exit if the request is successfully
880      *          handled by the dtpad server.
881      * case 3 (Blocking) - do nothing if the request is successfully
882      *          handled, then wait for a Reply from the dtpad
883      *          server to exit.
884      *
885      * Build and send either a TTME_EDIT request if a file is specified
886      * or TTME_INSTANTIATE if no file is specified.  These requests
887      * are handled via TTmedia_ptype_declareCB() on the dtpad server.
888      *
889      * 1. If server can not handle the request, it will fail the request
890      *    immediately.  pLoadMsgCB will receive the reply message and
891      *    start a standAlone dtpad.
892      * 2. If server can handle the request, it will send a Status notice.
893      *    pStatusCB will receive the notice and either exit (noBlocking)
894      *    or do nothing (Blocking).  The server will then reply to a
895      *    TTME_EDIT request when editing for the specified file/buffer
896      *    is done (the edit window may still remain open though) and
897      *    to a TTME_INSTANTIATE request when the edit window is closed.
898      *-------------------------------------------------------*/
899
900      if (strcmp(fileName, "*") == 0) {
901          op = TTME_INSTANTIATE;
902      } else {
903          op = TTME_EDIT;
904      }
905
906      msg = ttmedia_load(0,
907                         pLoadMsgCB,
908                         NULL,
909                         op,
910                         "C_STRING",
911                         NULL,
912                         0,
913                         fileName,
914                         NULL,
915                         0);
916      
917      status = tt_ptr_error(msg);
918      if (tt_is_err(status))
919      {
920           /* Error message */
921           return;
922      }
923
924      ttdt_subcontract_manage(msg,
925                         pStatusCB,
926                         NULL,
927                         (void *) ((XtArgVal) pPad->xrdb.blocking));/* client data */
928
929      /* Add pArgs to msg using tt_message_context_set */
930      SetupLoadArgs(msg, pPad);
931      tt_message_user_set(msg, 0, pStruct);
932      tt_message_send(msg);
933 }
934
935
936 /************************************************************************
937  * InitEditSessionAndFirstPad - performs initialization related to
938  *      starting the edit session and then calls the routine that creates
939  *      the first pPad Editor.
940  *
941  * (was InitGlobalAndFirstPad)          
942  ************************************************************************/
943 /* ARGSUSED */
944 static void 
945 InitEditSessionAndFirstPad(
946         Editor *pPad,
947         int argc,
948         char **argv)
949 {
950     char *pTmp = (char *)NULL;
951
952     CreateDefaultImage ((char *) warningBits, 32, 32, "warn_image");
953
954     xa_WM_DELETE_WINDOW = XInternAtom(pPad->display, 
955                                              "WM_DELETE_WINDOW", False);
956
957     /* get the users group and user id for file type checking */
958     pPad->group_id = getgid();
959     pPad->user_id = getuid();
960
961     /* Set up file name */
962     if (pPad->saveRestore == True && argv[3] != NULL) {
963         pTmp = argv[3];
964     } else if (argc > 1) {
965         pTmp = argv[argc - 1];
966     }
967
968     if (pTmp != (char *)NULL) {
969         pPad->fileStuff.fileName = (char *) XtMalloc(strlen(pTmp) + 1);
970         strcpy(pPad->fileStuff.fileName, pTmp);
971     } else {
972         pPad->fileStuff.fileName = (char *)NULL;
973     }
974     pPad->fileStuff.lastIncludeName = (char *)NULL;
975     RealizeNewPad(pPad);        /* display first pPad Editor window */
976
977     setPanicConditions();       /* Set up emergency calls to PanicSave */
978
979     /*
980      * Set up a handler for SIGCLD so that the command invoker library
981      * doesn't leave zombies.
982      */
983     {
984         struct sigaction act;
985         sigfillset(&act.sa_mask);
986         act.sa_flags = 0;
987         act.sa_handler = SigcldHndlr;
988         sigaction(SIGCHLD, &act, (struct sigaction *)NULL);
989     }
990 }
991
992
993 /************************************************************************
994  * RealizeNewPad - creates the GUI components of a pPad Editor, sets
995  *      pPad resources, maps the window and loads the file to be edited.
996  *
997  *  NOTE: This routine in normally called only when a new edit window is to
998  *        be displayed.  However, it is also called when the server is first
999  *        started (when no edit requests have been received).  In this
1000  *        situation, the window is not mapped and the file is not loaded.
1001  *        These actions are done when the dummy pPad is "reused" when the
1002  *        actual edit request is received from the requestor dtpad.
1003  *
1004  ************************************************************************/
1005 void
1006 RealizeNewPad(
1007         Editor *pPad)
1008 {
1009     Arg al[5];                  /* arg list */
1010     register int ac;            /* arg count */
1011
1012     /* Create the title */
1013     pPad->dialogTitle = DialogTitle(pPad);
1014
1015     /* Set some applic shell resources */
1016     ac = 0;
1017     XtSetArg(al[ac], XmNuseAsyncGeometry, True); ac++;
1018     XtSetArg(al[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
1019     XtSetArg(al[ac], XmNgeometry, NULL); ac++;
1020     XtSetValues(pPad->app_shell, al, ac);
1021
1022     if (pPad->xrdb.session != NULL) {
1023        restoreSession(pPad);
1024     }
1025     pPad->nodo = False;
1026
1027     /* Create Main Window */
1028     pPad->mainWindow = XmCreateMainWindow (pPad->app_shell, "main", al, 0);
1029     XtManageChild (pPad->mainWindow);
1030
1031     /* Create MenuBar in Main Window */
1032     CreateMenuBar(pPad);
1033     XtManageChild (pPad->menu_bar);
1034
1035     /* Create the DT Editor Widget in the Main Window. */
1036     CreateEditorWidget (pPad);
1037     XtManageChild (pPad->editor);
1038
1039 #ifdef POPUP
1040     /* Create the popup for the editor */
1041     CreatePopupMenu (pPad);
1042 #endif
1043
1044     /* Associate menu bar and editor widgets created above with menu bar and
1045      * work area of the main window (the main window command line area and
1046      * the horizontal/vertical scroll bars are not used) */
1047     XmMainWindowSetAreas(pPad->mainWindow, pPad->menu_bar,
1048                 (Widget) NULL, (Widget) NULL, (Widget) NULL,
1049                 pPad->editor);
1050
1051     /* Realize toplevel widgets. */
1052     XtSetMappedWhenManaged(pPad->app_shell, False);
1053     XtRealizeWidget (pPad->app_shell);
1054
1055     /* Set the window title */
1056     ChangeMainWindowTitle(pPad);
1057
1058     XSync(pPad->display, 0);
1059
1060     /* setup where a close by the window manager will be handled */
1061     XmAddWMProtocolCallback(pPad->app_shell, xa_WM_DELETE_WINDOW,
1062                             (XtCallbackProc) closeCB, (XtPointer)pPad);
1063
1064     /* reset the "save with newLines" flag */
1065     pPad->fileStuff.saveWithNewlines = True;
1066
1067     /* set app shell geometry (pixels), resize hints, position & size hints */
1068     SetWindowSize(pPad);
1069
1070     /* set the state of the pPad based on its resources */
1071     SetStateFromResources(pPad);
1072     
1073     /* set File menu SaveAs label/mnemonic based on xrdb.nameChange */
1074     SetSaveAsLabelAndDialog(pPad);
1075
1076     ChangeMainWindowTitle(pPad);
1077
1078     /* If we're the server initially starting up, this is a "dummy" edit
1079      * request and we really don't want to map anything to the display yet
1080      * (this will be done when the actual edit request comes in and this
1081      * dummy pPad is reused and mapped). */
1082     if (pPad->xrdb.server == False) {
1083         XtSetMappedWhenManaged(pPad->app_shell, True);
1084         XtPopup(pPad->app_shell, XtGrabNone);
1085         XtMapWidget(pPad->app_shell);
1086         numActivePads++;
1087     }
1088
1089     /* load the file (if there's actually a file name specified) */
1090     LoadFile(pPad, NULL);
1091
1092 }
1093
1094
1095 /************************************************************************
1096  * ManageOldPad - opens a new file in an exiting Editor pad "window".
1097  * 
1098  *      Existing windows have their widget structure already created but
1099  *      may or may not be managed/visible.   The existing window could be
1100  *      any of the following:
1101  *
1102  *        o the initial "dummy" window created when the server was started
1103  *          up (this window is not managed until the actual edit message
1104  *          from the requestor is received)
1105  *        o a window which has been closed previously
1106  *        o a window that is currently managed/visible and is to be reused
1107  *          (and is identified by the window id resource)
1108  ************************************************************************/
1109 void
1110 ManageOldPad(
1111         Editor *pPad,
1112         Boolean isCurrentlyVisible)
1113 {
1114
1115     if(pPad->xrdb.session != NULL)
1116        restoreSession(pPad);
1117
1118     /*.. create the title */
1119     ChangeMainWindowTitle(pPad);
1120     SetStateFromResources(pPad);  /* set the pPad state based on resources */
1121     pPad->nodo = False;
1122     
1123     /* set File menu SaveAs label/mnemonic based on xrdb.nameChange */
1124     SetSaveAsLabelAndDialog(pPad);
1125
1126     /* set app shell geometry (pixels), resize hints, position & size hints */
1127     SetWindowSize(pPad);
1128
1129     ChangeMainWindowTitle(pPad);
1130
1131     /* If the window is iconified and autoRaise is disabled, then
1132      * we don't what to deiconify the window.
1133      */
1134     if (!isCurrentlyVisible) {
1135        XtSetMappedWhenManaged(pPad->app_shell, True);
1136        XtPopup(pPad->app_shell, XtGrabNone);
1137        XtMapWidget(pPad->app_shell);
1138     }
1139
1140     LoadFile(pPad, NULL);
1141 }
1142
1143
1144 /************************************************************************
1145  * StartDbUpdate - 
1146  ************************************************************************/
1147 /* ARGSUSED */
1148 void
1149 StartDbUpdate(
1150         XtPointer clientData)
1151 {
1152
1153    /* Read in the new databases */
1154    DtDbLoad();
1155    ActionDBInitialized = True;
1156 }
1157
1158
1159 /************************************************************************
1160  * exitCB - 
1161  ************************************************************************/
1162 /* ARGSUSED */
1163 void
1164 exitCB(Widget w, XtPointer callData, XtPointer clientData)
1165 {
1166     exit((XtArgVal) clientData);
1167 }
1168
1169 /************************************************************************
1170  * setPanicConditions - 
1171  ************************************************************************/
1172 void
1173 setPanicConditions(void)
1174 {
1175     struct sigaction act;
1176
1177     sigfillset(&act.sa_mask);
1178     /*
1179     signal(SIGHUP, (void (*)(int))PanicSave);
1180     signal(SIGINT, (void (*)(int))PanicSave);
1181     signal(SIGQUIT, (void (*)(int))PanicSave);
1182     signal(SIGILL, (void (*)(int))PanicSave);
1183     signal(SIGABRT, (void (*)(int))PanicSave);
1184     signal(SIGIOT, (void (*)(int))PanicSave);
1185     signal(SIGEMT, (void (*)(int))PanicSave);
1186     signal(SIGFPE, (void (*)(int))PanicSave);
1187     signal(SIGBUS, (void (*)(int))PanicSave);
1188     signal(SIGSEGV, (void (*)(int))PanicSave);
1189     signal(SIGSYS, (void (*)(int))PanicSave);
1190     signal(SIGPIPE, (void (*)(int))PanicSave);
1191     signal(SIGTERM, (void (*)(int))PanicSave);
1192     */
1193     sigfillset(&act.sa_mask);
1194     act.sa_flags = 0;
1195     act.sa_handler = (void (*)(int))PanicSave;
1196     sigaction(SIGHUP, &act, (struct sigaction *)NULL);
1197     sigaction(SIGINT, &act, (struct sigaction *)NULL);
1198     sigaction(SIGQUIT, &act, (struct sigaction *)NULL);
1199     sigaction(SIGILL, &act, (struct sigaction *)NULL);
1200     sigaction(SIGABRT, &act, (struct sigaction *)NULL);
1201     sigaction(SIGIOT, &act, (struct sigaction *)NULL);
1202 #ifdef SIGEMT
1203     sigaction(SIGEMT, &act, (struct sigaction *)NULL);
1204 #endif
1205     sigaction(SIGFPE, &act, (struct sigaction *)NULL);
1206     sigaction(SIGBUS, &act, (struct sigaction *)NULL);
1207     sigaction(SIGSEGV, &act, (struct sigaction *)NULL);
1208 #ifdef SIGSYS
1209     sigaction(SIGSYS, &act, (struct sigaction *)NULL);
1210 #endif
1211     sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
1212     sigaction(SIGTERM, &act, (struct sigaction *)NULL);
1213
1214     /* TTT - comment out for debugging TookTalk code */
1215 #if 0
1216     XSetErrorHandler((int (*)()) PanicSave);
1217     XSetIOErrorHandler((int (*)())PanicSave);
1218 #endif
1219     XSetErrorHandler(dtpadXErrorHandler);
1220     XSetIOErrorHandler(dtpadXIOErrorHandler);
1221 }
1222
1223
1224 /************************************************************************
1225  * GetAdjustedResizeHints - returns the size hints for the pPad Dt Editor
1226  *      widget with its min_height incremented by the height of dtpad's
1227  *      menu bar.
1228  ************************************************************************/
1229 static void
1230 GetAdjustedResizeHints(
1231         Editor *pPad,
1232         XSizeHints *pHints)
1233 {
1234     Arg al[2];                  /* arg list */
1235     register int ac;            /* arg count */
1236     Dimension MBheight;
1237
1238     /* get Dt Editor widget size hints */
1239     DtEditorGetSizeHints(pPad->editor, pHints);
1240     
1241     /* get the menu bar height */
1242     XtSetArg(al[0], XmNheight, &MBheight);
1243     XtGetValues(pPad->menu_bar, al, 1);
1244
1245     /* adjust the editor widget min height by menu bar height */
1246     pHints->min_height += MBheight;
1247     pHints->base_height += MBheight;
1248
1249 }
1250
1251
1252 /************************************************************************
1253  * SetAppShellResizeHints - sets the app_shell's normal resize hints
1254  *      (resize increment, minimum window size, etc.) based on the resize
1255  *      hints returned from the Dt Editor widget but with the dtpad menu
1256  *      bar height added to the min_height.
1257  ************************************************************************/
1258 void
1259 SetAppShellResizeHints(
1260         Editor *pPad)
1261 {
1262     XSizeHints  size_hints;
1263     long supplied_return;
1264
1265     /* make sure stuff not set by GetAdjustedResizeHints is not lost */
1266     XGetWMSizeHints(pPad->display, XtWindow(pPad->app_shell), &size_hints,
1267                                           &supplied_return, XA_WM_NORMAL_HINTS);
1268
1269     GetAdjustedResizeHints(pPad, &size_hints);  /* consider the menu bar */
1270
1271     XSetWMSizeHints(pPad->display, XtWindow(pPad->app_shell), &size_hints,
1272                     XA_WM_NORMAL_HINTS);
1273 }
1274
1275
1276 /************************************************************************
1277  * SetPadGeometry - sets the pad's width, height and x & y IN PIXELS
1278  *      based on the pad's geometry string.  Returns a flag
1279  *      indicating which geometry components were specified.
1280  ************************************************************************/
1281 static int
1282 SetPadGeometry(
1283         Editor *pPad)
1284 {
1285     int                  geometryBits;
1286     int                  geometryX;
1287     int                  geometryY;
1288     unsigned int         geometryWidth;
1289     unsigned int         geometryHeight;
1290     XSizeHints  size_hints;
1291
1292
1293     /* -----> convert geometry string to integers */
1294     geometryBits = XParseGeometry(pPad->geometry,   /* geometry string  */
1295                                   &geometryX,       /* x position return*/
1296                                   &geometryY,       /* y position return*/
1297                                   &geometryWidth,   /* width return     */
1298                                   &geometryHeight); /* height return    */
1299
1300     if (!(geometryBits & WidthValue))
1301         geometryWidth  = DEFAULT_COLS;
1302     if (!(geometryBits & HeightValue))
1303         geometryHeight = DEFAULT_ROWS;
1304
1305     /* -----> Get width/height increments and minimum sizes in pixels
1306      *        and then compute window width/height in pixels. 
1307      *        The min_width & min_height size hints include a character. */
1308     GetAdjustedResizeHints(pPad, &size_hints);  /* consider the menu bar */
1309     geometryWidth = geometryWidth * size_hints.width_inc +
1310                         size_hints.min_width - size_hints.width_inc;
1311     geometryHeight = geometryHeight * size_hints.height_inc +
1312                         size_hints.min_height - size_hints.height_inc;
1313
1314      /* -----> allow for negative X and Y values */
1315     if (geometryBits & XValue) {
1316         if (geometryBits & XNegative) {
1317             geometryX += DisplayWidth(pPad->display,
1318                                       DefaultScreen(pPad->display)) -
1319                                       geometryWidth -
1320                                       2 * pPad->app_shell->core.border_width;
1321         }
1322     } else {
1323         geometryX = 0;
1324     }
1325     if (geometryBits & YValue) {
1326         if (geometryBits & YNegative) {
1327             geometryY += DisplayHeight(pPad->display,
1328                                        DefaultScreen(pPad->display)) -
1329                                        geometryHeight -
1330                                        2 * pPad->app_shell->core.border_width;
1331         }
1332     } else {
1333         geometryY = 0;
1334     }
1335
1336     /* -----> set pad's pixel geometry */
1337     pPad->width = geometryWidth;
1338     pPad->height = geometryHeight;
1339     pPad->x =  geometryX;
1340     pPad->y = geometryY;
1341
1342     return geometryBits;
1343 }
1344
1345
1346 /************************************************************************
1347  * SetWindowSize - sets the following for the pad's application shell:
1348  *
1349  *      1) geometry (in pixels) - after converting the geometry string
1350  *                      to pixel values and storing in the pad struct
1351  *      2) resize hints (PMinSize, PResizeInc and PBaseSize)
1352  *      3) position and size hints (PPosition and PSize)
1353  *
1354  ************************************************************************/
1355 void
1356 SetWindowSize(
1357         Editor *pPad)
1358 {
1359     Arg al[10];                 /* arg list */
1360     register int ac;            /* arg count */
1361     XSizeHints  size_hints;
1362     XWMHints   *wmhints;
1363     long supplied_return;
1364     int geometryBits;
1365     XWindowChanges changesStruct;
1366     WMShellWidget wm;
1367
1368     /* -----> set pad's app_shell geometry (in pixels) */
1369     ac = 0;
1370     if (pPad->saveRestore == True) {
1371         /* if we're restoring a session, the geometry is already in
1372          * pixel values so set the app_shell geometry directly */
1373         wm = (WMShellWidget)(pPad->app_shell);
1374         wm->wm.size_hints.flags |= USSize|USPosition;
1375         wm->wm.size_hints.flags |= PMinSize|PResizeInc|PBaseSize;
1376         XtSetArg (al[ac], XmNx, pPad->x);  ac++;
1377         XtSetArg (al[ac], XmNy, pPad->y);  ac++;
1378         XtSetArg (al[ac], XmNwidth, pPad->width);  ac++;
1379         XtSetArg (al[ac], XmNheight, pPad->height);  ac++;
1380         XtSetValues(pPad->app_shell, al, ac);
1381     }  else {
1382         /* parse the pPad->geometry STRING into 
1383          * pPad->geometry[Width|Height|X|Y] PIXELS values and
1384          * return flags indicating which geometry parts were specified */
1385         geometryBits = SetPadGeometry(pPad); /* parse geometry str to pixels */
1386         wm = (WMShellWidget)(pPad->app_shell);
1387
1388         /* set only the geometry parts that were specified */
1389         if (geometryBits & XValue) {
1390             wm->wm.size_hints.flags |= USPosition;
1391             XtSetArg (al[ac], XmNx, pPad->x);  ac++; 
1392         }
1393         if (geometryBits & YValue) {
1394             wm->wm.size_hints.flags |= USPosition;
1395             XtSetArg (al[ac], XmNy, pPad->y);  ac++; 
1396         }
1397         if (geometryBits & WidthValue) {
1398             wm->wm.size_hints.flags |= USSize;
1399             XtSetArg (al[ac], XmNwidth, pPad->width);  ac++;
1400         }
1401         if (geometryBits & HeightValue) {
1402             wm->wm.size_hints.flags |= USSize;
1403             XtSetArg (al[ac], XmNheight, pPad->height);  ac++;
1404         }
1405         if (ac > 0) {
1406             XtSetValues(pPad->app_shell, al, ac);
1407         }
1408     }
1409
1410     /* -----> set app_shell resize hints based on resize hints returned
1411      *        from the Dt Editor widget (PMinSize, PResizeInc and PBaseSize)
1412      *        and adjusted by the dtpad menu bar */ 
1413     SetAppShellResizeHints(pPad);
1414
1415
1416     /* -----> set app_shell position and size hints
1417      *        (and whether user specified (US) or program specified (P) */
1418     XGetWMSizeHints(pPad->display, XtWindow(pPad->app_shell), &size_hints,
1419                                           &supplied_return, XA_WM_NORMAL_HINTS);
1420     wm->wm.size_hints.flags |= PMinSize|PResizeInc|PBaseSize;/* set previously*/
1421     if (pPad->saveRestore == True) {
1422         wm->wm.size_hints.x = pPad->x;
1423         wm->wm.size_hints.y = pPad->y;
1424         wm->wm.size_hints.width = pPad->width;
1425         wm->wm.size_hints.height = pPad->height;
1426         wm->wm.size_hints.min_width = size_hints.min_width;
1427         wm->wm.size_hints.min_height = size_hints.min_height;
1428         wm->wm.size_hints.width_inc = size_hints.width_inc;
1429         wm->wm.size_hints.height_inc = size_hints.height_inc;
1430         wm->wm.base_width = size_hints.base_width;
1431         wm->wm.base_height = size_hints.base_height;
1432         wm->wm.size_hints.flags |= USSize|USPosition;
1433     } else {
1434         if (geometryBits & XValue && geometryBits & YValue) {
1435             wm->wm.size_hints.x = pPad->x;
1436             wm->wm.size_hints.y = pPad->y;
1437             wm->wm.size_hints.flags |= USPosition;
1438         } else {
1439             wm->wm.size_hints.flags |= PPosition;
1440         }
1441         if (geometryBits & WidthValue && geometryBits & HeightValue) {
1442             wm->wm.size_hints.width = pPad->width;
1443             wm->wm.size_hints.height = pPad->height;
1444             wm->wm.size_hints.min_width = size_hints.min_width;
1445             wm->wm.size_hints.min_height = size_hints.min_height;
1446             wm->wm.size_hints.width_inc = size_hints.width_inc;
1447             wm->wm.size_hints.height_inc = size_hints.height_inc;
1448             wm->wm.base_width = size_hints.base_width;
1449             wm->wm.base_height = size_hints.base_height;
1450             wm->wm.size_hints.flags |= USSize;
1451         } else {
1452             wm->wm.size_hints.flags |= PSize;
1453         }
1454     }
1455
1456     /* Remove the iconify hint from the current shell */
1457     wmhints = XGetWMHints(XtDisplay(pPad->app_shell), 
1458                            XtWindow(pPad->app_shell));
1459     wmhints->flags |= IconWindowHint;
1460     if (pPad->iconic)
1461         wmhints->initial_state = IconicState;
1462     else
1463         wmhints->initial_state = NormalState;
1464     XSetWMHints(XtDisplay(pPad->app_shell), 
1465                  XtWindow(pPad->app_shell), wmhints);
1466
1467     changesStruct.x = pPad->x;
1468     changesStruct.y = pPad->y;
1469     changesStruct.width = pPad->width;
1470     changesStruct.height = pPad->height;
1471     XConfigureWindow(pPad->display, XtWindow(pPad->app_shell), 
1472                      CWWidth | CWHeight, &changesStruct);
1473 }
1474
1475
1476 /************************************************************************
1477  * SetInitialMenuSensitivity - sets the initial sensitivity of various menu
1478         items primarily based on whether or not we're in viewOnly mode.
1479  ************************************************************************/
1480 static void
1481 SetInitialMenuSensitivity(
1482         Editor *pPad)
1483 {
1484     Boolean editable = ! pPad->xrdb.viewOnly;
1485
1486     /* -----> set sensitivity of File menu items */
1487     XtSetSensitive(pPad->fileStuff.fileWidgets.newBtn, editable);
1488         /****Begin Change - SuG 5/5/95 */
1489     XtSetSensitive(pPad->fileStuff.fileWidgets.openBtn, editable);
1490     XtSetSensitive(pPad->fileStuff.fileWidgets.includeBtn, editable);
1491     XtSetSensitive(pPad->fileStuff.fileWidgets.saveBtn, editable);
1492
1493     /* -----> set sensitivity of Edit menu items
1494      * Edit Menu items that deal with the current selection (Cut, Copy,
1495      * Clear and Delete) are made sensitive/insensitive via the DtEditor
1496      * widget's DtNtextSelectCallback and DtNtextDeselectCallback.
1497      * Currently nothing is being done with Paste based on text
1498      * selected/deselected outside the edit window.
1499      * findChangeBtn is left sensitive since the DtEditor widget will
1500      * enable/disable changes in the Find/Change dialog based on the
1501      * DtNeditable resource. */
1502     XtSetSensitive(pPad->editStuff.widgets.undoBtn, editable);
1503     XtSetSensitive(pPad->editStuff.widgets.pasteBtn, editable);
1504     if (pPad->editStuff.widgets.checkSpellingBtn != (Widget) NULL) {
1505         XtSetSensitive(pPad->editStuff.widgets.checkSpellingBtn, editable);
1506     }
1507     SetSelectionMenuItems(pPad, False); /* set Cut, Copy, Clear & Delete */
1508
1509      /* -----> set sensitivity of Format menu */
1510     XtSetSensitive(pPad->formatStuff.widgets.formatBtn, editable);
1511
1512     /* -----> set sensitivity of Options menu items */
1513     XtSetSensitive(pPad->optionsStuff.widgets.overstrikeBtn, editable);
1514     XtSetSensitive(pPad->optionsStuff.widgets.wordWrapBtn, editable);
1515     
1516 }
1517
1518
1519 /************************************************************************
1520  * SetStateFromResources - set pPad's state (e.g. GUI components) based on
1521  *      current pPad->xrdb resource values.  The resources are initially
1522  *      obtained from either:
1523  *
1524  *      1) the dtpad requestor's resource data base and command line
1525  *         options - if running in standAlone mode or in server mode and
1526  *         handling an Edit request containing resource context fields
1527  *      2) the server's data base - if running in server mode and
1528  *         handling an Edit request without resource context fields
1529  *
1530  ************************************************************************/
1531 static void
1532 SetStateFromResources(
1533         Editor *pPad)
1534 {
1535     Arg al[1];                  /* arg list */
1536     OptionsMenuWidgets *pWidg = &pPad->optionsStuff.widgets;
1537     
1538     SetWorkSpaceHints(pPad->app_shell, pPad->xrdb.workspaceList);
1539     /* Create the title */
1540     pPad->dialogTitle = DialogTitle(pPad);
1541
1542     /* -----> Set the overstrike, wordWrap and statusLine for the Editor
1543      *        widget and corresponding Options menu toggle buttons.
1544      *        This is done in one place - in the valueChanged callback for
1545      *        each option - which is called only if parameter 3 is True AND
1546      *        the state being set is different than what it currently is.
1547      *        The first XmToggleButtonSetState (with parm 3 = False) ensures
1548      *        that the state is opposite of what we want it to be so that
1549      *        when we set it, the valueChanged callback will be called. */
1550
1551     if (pPad->xrdb.overstrike == XmToggleButtonGetState(pWidg->overstrikeBtn))
1552         XmToggleButtonSetState(pWidg->overstrikeBtn,
1553                                 !pPad->xrdb.overstrike, False);
1554     XmToggleButtonSetState(pWidg->overstrikeBtn,
1555                                 pPad->xrdb.overstrike, True);
1556
1557     if (pPad->xrdb.wordWrap == XmToggleButtonGetState(pWidg->wordWrapBtn))
1558         XmToggleButtonSetState(pWidg->wordWrapBtn,
1559                                 !pPad->xrdb.wordWrap, False);
1560     XmToggleButtonSetState(pWidg->wordWrapBtn,
1561                                 pPad->xrdb.wordWrap, True);
1562
1563     if (pPad->xrdb.statusLine == XmToggleButtonGetState(pWidg->statusLineBtn))
1564         XmToggleButtonSetState(pWidg->statusLineBtn,
1565                                 !pPad->xrdb.statusLine, False);
1566     XmToggleButtonSetState(pWidg->statusLineBtn,
1567                                 pPad->xrdb.statusLine, True);
1568
1569     /* -----> Set whether text can be edited */
1570     XtSetArg(al[0], DtNeditable, !pPad->xrdb.viewOnly);
1571     XtSetValues(pPad->editor, al, 1);
1572     SetInitialMenuSensitivity(pPad);
1573
1574 }
1575
1576
1577 /************************************************************************
1578  * SigcldHndlr - 
1579  ************************************************************************/
1580 /* ARGSUSED */
1581 void SigcldHndlr (int dummy)
1582 {
1583     int   status, w;
1584     struct sigaction act;
1585     sigfillset(&act.sa_mask);
1586     act.sa_flags = 0;
1587     act.sa_handler = SigcldHndlr;
1588
1589     w = wait (&status);
1590
1591     /*
1592      * Is this really necessary?
1593      */
1594     sigaction(SIGCHLD, &act, (struct sigaction *)NULL);
1595 }
1596
1597
1598 /************************************************************************
1599  * UnmanageAllDialogs - unmanages all the dialogs which may be managed
1600  *      when a pad gets closed or withdrawn.
1601  ************************************************************************/
1602 void
1603 UnmanageAllDialogs(
1604     Editor *pPad)
1605 {
1606     HelpStruct *pHelp;
1607     /*
1608      * Unmanage all Modal dialogs that might possibly be up.
1609      */
1610     if (pPad->fileStuff.fileWidgets.saveAs.alrdy_exist != (Widget)NULL &&
1611         pPad->fileStuff.fileWidgets.saveAs.alrdy_exist->core.managed == True)
1612     {
1613         XtUnmanageChild(pPad->fileStuff.fileWidgets.saveAs.alrdy_exist);
1614     }
1615
1616     if (pPad->fileStuff.fileWidgets.select.save_warning != (Widget)NULL &&
1617         pPad->fileStuff.fileWidgets.select.save_warning->core.managed == True)
1618     {
1619         XtUnmanageChild(pPad->fileStuff.fileWidgets.select.save_warning);
1620     }
1621
1622     if (pPad->fileStuff.fileWidgets.gen_warning != (Widget)NULL &&
1623         pPad->fileStuff.fileWidgets.gen_warning->core.managed == True)
1624     {
1625         XtUnmanageChild(pPad->fileStuff.fileWidgets.gen_warning);
1626     }
1627     
1628     /*
1629      * Unmanage File menu dialogs that might be posted.
1630      * The Edit and Format menu dialogs are managed by the DtEditor widget.
1631      * XXX - unmanage print dialog too.
1632      */
1633     if (pPad->fileStuff.fileWidgets.select.file_dialog != (Widget)NULL &&
1634         pPad->fileStuff.fileWidgets.select.file_dialog->core.managed == True)
1635     {
1636         XtUnmanageChild(pPad->fileStuff.fileWidgets.select.file_dialog);
1637     }
1638
1639     if (pPad->fileStuff.fileWidgets.saveAs.saveAs_form != (Widget)NULL &&
1640         pPad->fileStuff.fileWidgets.saveAs.saveAs_form->core.managed == True)
1641     {
1642         XtUnmanageChild(pPad->fileStuff.fileWidgets.saveAs.saveAs_form);
1643     }
1644
1645     /*
1646      * Unmanage help if it's up.
1647      */
1648     if (pPad->MainHelp != (Widget)NULL && pPad->MainHelp->core.managed == True)
1649     {
1650         XtUnmanageChild(pPad->MainHelp);
1651     }
1652     for (pHelp = pPad->pHelpCache; pHelp != (HelpStruct *)NULL;
1653          pHelp = pHelp->pNext)
1654     {
1655         if (pHelp->dialog != (Widget)NULL &&
1656             pHelp->dialog->core.managed == True)
1657         {
1658             XtUnmanageChild(pHelp->dialog);
1659         }
1660     }
1661 }
1662
1663
1664 /************************************************************************
1665  * RestoreInitialServerResources - 
1666  ************************************************************************/
1667 void
1668 RestoreInitialServerResources(
1669         Editor *pPad)
1670 {
1671     /* -----> free resource strings */
1672     if (pPad->xrdb.workspaceList != (char *)NULL)
1673         XtFree(pPad->xrdb.workspaceList);
1674     if (pPad->xrdb.session != (char *)NULL)
1675         XtFree(pPad->xrdb.session);
1676     if (pPad->geometry != (char *)NULL)
1677         XtFree(pPad->geometry );
1678
1679     pPad->xrdb = initialServerResources;
1680
1681     /* -----> duplicate resource strings */
1682     if (initialServerResources.workspaceList != (char *)NULL)
1683         pPad->xrdb.workspaceList = strdup(initialServerResources.workspaceList);
1684     if (initialServerResources.session != (char *)NULL)
1685         pPad->xrdb.session = strdup(initialServerResources.session);
1686     if (initialServerGeometry != (char *)NULL)
1687         pPad->geometry = strdup(initialServerGeometry);
1688
1689 }
1690
1691
1692 #ifndef NO_MESSAGE_CATALOG
1693 /*****************************************************************************
1694  *  _DtpadGetMessage - obtains a localized message from dtpad's message catalog
1695  *
1696  * Parameters:
1697  *
1698  *   int        set -           The message catalog set number.
1699  *   int        number -        The message number.
1700  *   char       *string -       The default message if the message is not
1701  *                              retrieved from a message catalog.
1702  *
1703  * Returns: the message string for set 'set' and number 'number'.
1704  *
1705  *****************************************************************************/
1706 char *
1707 _DtpadGetMessage(
1708     int set,
1709     int number,
1710     char *string )
1711 {
1712     char *msg;
1713     nl_catd catopen();
1714     char *catgets();
1715     static int first = 1;
1716     static nl_catd nlmsg_fd;
1717
1718     if ( first ) {
1719         first = 0;
1720         nlmsg_fd = catopen(_DTPAD_CAT_NAME, NL_CAT_LOCALE);
1721     }
1722 #if defined(hpV4)
1723     msg = _DtCatgetsCached(nlmsg_fd, set, number, string);
1724 #else
1725     msg = catgets(nlmsg_fd, set, number, string);
1726 #endif
1727     return (msg);
1728 }
1729
1730 #endif /* NO_MESSAGE_CATALOG */
1731
1732 /************************************************************************
1733  * HostCB - message callback for (op) Get_SysInfo message
1734  ************************************************************************/
1735 /* ARGSUSED */
1736 static
1737 Tt_callback_action
1738 HostCB(Tt_message m, Tt_pattern p)
1739 {
1740   Tt_state state = tt_message_state(m);
1741
1742   if (state == TT_HANDLED) {
1743     value = tt_message_arg_val(m, 1);
1744     waitCB = 0;
1745   }
1746 }
1747
1748 /************************************************************************
1749  *
1750  *  Usage
1751  *      When incorrect parameters have been specified on the command
1752  *      line, print out a set of messages detailing the correct use
1753  *      and exit.
1754  *
1755  ************************************************************************/
1756
1757 static void
1758 Usage(
1759         char **argv )
1760 {
1761    char * template;
1762    char * message_string1 = "'%s' is a bad option.\nUsage: %s...\n"
1763                          "   -saveOnClose\n\t"
1764                          "Dtpad automatically and silently saves the current text when there\n\t"
1765                          "are unsaved changes and the Text Editor is closed.\n\n"
1766                          "   -missingFileWarning\n\t"
1767                          "Posts a warning dialog whenever a file name is specified and\n\t"
1768                          "the file dones not exist or cannot be accessed.\n\n"
1769                          "   -noReadOnlyWarning\n\t"
1770                          "Disables the warning dialog posted whenever a file is\n\t"
1771                          "specified for which the user does not have write permission.\n\n"
1772                          "   -noNameChange\n\t"
1773                          "Indicates that the default file name associated with the\n\t"
1774                          "current text is not to change when the text is saved under a\n\t"
1775                          "name different than what it was read in under.\n\n"
1776                          "   -viewOnly\n\t"
1777                          "Disallows editing of text in the edit window, essentially\n\t"
1778                          "turning the Text Editor into a Text Viewer.\n\n"
1779                          "   -statusLine\n\t"
1780                          "Displays a status line at the bottom of the edit window.  The\n\t"
1781                          "status line shows the line number of the line where the text\n\t"
1782                          "cursor is currently positioned.\n\n"
1783                          "   -wrapToFit\n\t"
1784                          "Initially turns on wrap-to-fit mode.\n\n"
1785                          "   -workspaceList WorkspaceList\n\t"
1786                          "Displays the edit window for the current invocation of the\n\t"
1787                          "Text Editor in the specified workspace or workspaces.\n\n"
1788                          "   -session SessionFile\n";
1789
1790    char * message_string2 = "\tRestores the Text Editor to all text editing windows and\n\t"
1791                          "settings that were in effect at a previous CDE shutdown.  All\n\t"
1792                          "other command-line options are ignored when this option is\n\t"
1793                          "specified.\n\n"
1794                          "   -standAlone\n\t"
1795                          "Forces the current invocation of the Text Editor to do its\n\t"
1796                          "own text processing in its own window, independent of the\n\t"
1797                          "Text Editor server.\n\n"
1798                          "   -noBlocking\n\t"
1799                          "Terminates the Text Editor requestor process as soon as the\n\t"
1800                          "Text Editor server determines that it can handle the\n\t"
1801                          "requestor's edit request.\n\n"
1802                          "   -server\n\t"
1803                          "Forces a Text Editor server to be started up (if one is not\n\t"
1804                          "already running) to process all subsequent edit requests for\n\t"
1805                          "the display.\n\n"
1806                          "   -exitOnLastClose\n\t"
1807                          "Specifies that the Text Editor server process is to terminate\n\t"
1808                          "when the last edit window for the display is closed.  It\n\t"
1809                          "should only be used with the -server option since it only\n\t"
1810                          "applies to the server process.\n\n"
1811                          "See the dtpad man page for more details on any of these options.\n\n";
1812
1813
1814    template = (GETMESSAGE(7,9, message_string1));
1815
1816    fprintf (stderr, template, argv[1], argv[0]);
1817
1818    template = (GETMESSAGE(7,10, message_string2));
1819
1820    fprintf (stderr, "%s", template);
1821
1822    exit (0);
1823 }
1824
1825
1826
1827 /************************************************************************
1828  *
1829  *  dtpadXErrorHandler
1830  *
1831  ************************************************************************/
1832
1833 static int
1834 dtpadXErrorHandler(
1835         Display *display,
1836         XErrorEvent *xerr)
1837 {
1838     #define _DTPAD_BUFSIZE 1024
1839     static char msg[_DTPAD_BUFSIZE];
1840
1841     /* log error */
1842     _DtPrintDefaultErrorSafe(display, xerr, msg, _DTPAD_BUFSIZE);
1843     _DtSimpleError("dtpad", DtWarning, NULL, msg, NULL);
1844
1845     /*
1846      * if the error occurred on the print display we're going to set
1847      * a variable so that and when the job is done, right before calling
1848      * XpEndJob, we call XpCancelJob, and notify the user.
1849      */
1850
1851     if (PrintJobIsActivePrintDisplay(display) && xerr->error_code == BadAlloc)
1852     {
1853         PrintJobSetErrorPrintDisplay(display);
1854         return 1;
1855     }
1856
1857     XGetErrorText(display, xerr->error_code, msg, 1024);
1858     fprintf(stderr, "Error Code %s\n", msg);
1859     PanicSave();
1860     return 1;
1861 }
1862
1863
1864
1865 /************************************************************************
1866  *
1867  *  dtpadXIOErrorHandler
1868  *
1869  ************************************************************************/
1870
1871 static int
1872 dtpadXIOErrorHandler(
1873         Display *display)
1874 {
1875     static char msg[1024];
1876
1877     fprintf(stderr, "X IO Error");
1878     PanicSave();
1879 }