2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $TOG: main.c /main/27 1999/09/15 15:16:51 mgreess $ */
24 /**********************************<+>*************************************
25 ***************************************************************************
29 ** Project: DT dtpad, a memo maker type editor based on the Dt Editor
35 ** Dtpad is basically a wrapper around the DT Editor widget providing:
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
44 ** This file contains the routines that control the client/server architecture
45 ** of dtpad and creation of the top level widgets.
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:
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
64 ** CreatePopupMenu: XmCreatePopupMenu() pPad->popup
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.
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 ********************************************************************
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 ********************************************************************
93 **************************************************************************
94 **********************************<+>*************************************/
97 #include "messageParam.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>
110 #include <X11/Xmu/Editres.h>
113 #ifndef NO_MESSAGE_CATALOG
116 # include <nl_types.h>
117 # if !defined(NL_CAT_LOCALE)
118 # define NL_CAT_LOCALE 0
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 */
129 /************************************************************************
131 ************************************************************************/
133 Atom xa_WM_DELETE_WINDOW;
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
150 static XtResource resources[] = {
151 {"statusLine", "StatusLine", XmRBoolean, sizeof(Boolean),
152 XtOffset(ApplicationDataPtr,statusLine), XmRImmediate, (XtPointer)False,
154 {"wrapToFit", "WrapToFit", XmRBoolean, sizeof(Boolean),
155 XtOffset(ApplicationDataPtr,wordWrap), XmRImmediate, (XtPointer)False,
157 {"overstrike", "Overstrike", XmRBoolean, sizeof(Boolean),
158 XtOffset(ApplicationDataPtr,overstrike), XmRImmediate, (XtPointer)False,
160 {"saveOnClose", "SaveOnClose", XmRBoolean, sizeof(Boolean),
161 XtOffset(ApplicationDataPtr,saveOnClose), XmRImmediate, (XtPointer)False,
163 {"missingFileWarning", "MissingFileWarning", XmRBoolean, sizeof(Boolean),
164 XtOffset(ApplicationDataPtr,missingFileWarning), XmRImmediate, (XtPointer)False,
166 {"readOnlyWarning", "ReadOnlyWarning", XmRBoolean, sizeof(Boolean),
167 XtOffset(ApplicationDataPtr,readOnlyWarning), XmRImmediate, (XtPointer)True,
169 {"nameChange", "NameChange", XmRBoolean, sizeof(Boolean),
170 XtOffset(ApplicationDataPtr,nameChange), XmRImmediate, (XtPointer)True,
172 {"viewOnly", "ViewOnly", XmRBoolean, sizeof(Boolean),
173 XtOffset(ApplicationDataPtr,viewOnly), XmRImmediate, (XtPointer)False,
175 {"workspaceList", "WorkspaceList", XmRString, sizeof(char *),
176 XtOffset(ApplicationDataPtr,workspaceList), XmRImmediate,(XtPointer)NULL,
178 {"session", "Session", XmRString, sizeof(char *),
179 XtOffset(ApplicationDataPtr,session), XmRImmediate, (XtPointer)NULL,
182 {"standAlone", "StandAlone", XmRBoolean, sizeof(Boolean),
183 XtOffset(ApplicationDataPtr,standAlone), XmRImmediate, (XtPointer)False,
185 {"blocking", "Blocking", XmRBoolean, sizeof(Boolean),
186 XtOffset(ApplicationDataPtr,blocking), XmRImmediate, (XtPointer)True,
188 {"server", "Server", XmRBoolean, sizeof(Boolean),
189 XtOffset(ApplicationDataPtr,server), XmRImmediate, (XtPointer)False,
191 {"exitOnLastClose", "ExitOnLastClose", XmRBoolean, sizeof(Boolean),
192 XtOffset(ApplicationDataPtr,exitOnLastClose), XmRImmediate, (XtPointer)False,
196 static XrmOptionDescRec option_list[] =
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},
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"},
215 static String fallbacks[] =
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",
224 ApplicationData initialServerResources;
225 char *initialServerGeometry;
226 Editor *pPadList = (Editor *)NULL;
227 int numActivePads = 0;
228 Widget topLevelWithWmCommand;
229 Boolean ActionDBInitialized = False;
237 /************************************************************************
238 * Forward Declarations
239 ************************************************************************/
241 static Editor *CreateFirstPad(
244 static void SendMessageToServer(
248 static void InitEditSessionAndFirstPad(
252 static void SetStateFromResources(
254 static Tt_callback_action HostCB(
259 static int dtpadXErrorHandler(
262 static int dtpadXIOErrorHandler(
267 /************************************************************************
268 * main - controls the high level client/server processing of dtpad based
269 * on the three modes of operation:
271 * 1) requestor mode - send message to dtpad server to do actual
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
278 ************************************************************************/
286 char *sessId, *tmpStr;
287 Tt_pattern requests2Handle;
289 Tt_status status = TT_OK;
290 int ttFd; /* ToolTalk file descriptor */
292 /* Set up the environment to allow relocation of the various bitmaps
293 * and message catalogs. */
294 (void)_DtEnvControl(DT_ENV_SET);
296 (void) XtSetLanguageProc((XtAppContext)NULL, (XtLanguageProc)NULL,
301 pPad = CreateFirstPad(&argc, argv);
302 XtAppSetFallbackResources(pPad->app_context, fallbacks);
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."));
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;
319 if (pPad->xrdb.standAlone) {
321 /*--------------------------------------------------------
324 * Initialize self as an editing session.
326 *-------------------------------------------------------*/
327 InitEditSessionAndFirstPad(pPad, argc, argv);
329 } else if (pPad->xrdb.server) {
330 /*--------------------------------------------------------
333 * Indicate the types of messages interested in and
334 * callbacks to process each message type, then
335 * initialize self as an editing session.
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;
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.
348 while(validTT && notDone)
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 ...") );
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) {
372 /* set the ptype to DTPAD */
373 status = tt_message_handler_ptype_set(msg, "DTPAD");
374 if(status != TT_OK) {
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
383 status = tt_message_arg_add(msg, TT_OUT, "string", 0);
384 if(status != TT_OK) {
388 status = tt_message_arg_add(msg, TT_OUT, "string", 0);
389 if(status != TT_OK) {
394 /* Finally, Let's send the Message ... */
395 status = tt_message_send(msg);
396 if(status != TT_OK) {
401 /* block for 10 seconds or until the HostCB is called */
402 tttk_block_while(pPad->app_context, &waitCB, 10000);
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
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);
413 sprintf(tmpStr, GETMESSAGE(7, 7, "ERROR: A dtpad server on %s\nis already serving this display."), value);
414 Warning(pPad, tmpStr, XmDIALOG_ERROR);
417 /* ToolTalk connection/message was bogus or unable to get
418 * hostname in Callback.
420 Warning(pPad, GETMESSAGE(7, 8, "ERROR: A dtpad server is already\nserving this display."), XmDIALOG_ERROR);
422 XtAddCallback (pFileWidgets->gen_warning, XmNokCallback,
423 exitCB, (XtPointer) pPad);
424 XFlush(pPad->display);
425 XSync(pPad->display, False);
428 InitEditSessionAndFirstPad(pPad, argc, argv);
430 /* -----> Initialize TT connection & process start message */
431 status = TTstartDesktopMediaExchange(topLevelWithWmCommand, pPad);
433 tttk_Xt_input_handler(0, 0, 0);
435 TTwarning( pPad, status,
436 GETMESSAGE(7, 11, "Exiting text editor ...") );
443 /* Temporary work around for action database problem(platinum BL5 03/29/95). */
444 StartDbUpdate((XtPointer) NULL);
447 /*--------------------------------------------------------
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).
454 *-------------------------------------------------------*/
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.
460 SendMessageToServer(pPad, argc, argv);
463 XtAppMainLoop(pPad->app_context);
469 /************************************************************************
470 * CreateFirstPad - Performs initialization common to all modes of
471 * operation (i.e. to requestor mode, server mode and standAlone
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.
477 * Specifically, this routine:
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
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).
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.
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.
509 * [SuG 5/12/95] Modified for fishy argument checking.
510 ************************************************************************/
517 char **argv_l, **c_argv_l;
523 /* Added for the argument fix*/
526 Atom xa_WM_SAVE_YOURSELF;
528 extern int optind, opterr, optind;
531 /* Create the 1st Editor entry in list of Editor instances.
532 * This is also done in FindOrCreatePad() for each Editor pad instance */
535 if (pPad->progname=MbStrrchr(argv[0], '/'))
538 pPad->progname = argv[0];
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);
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 '-').
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
561 for (i = 1; i < ((*pArgc) - 1); i++)
563 inS = MbStrchri(argv[i], '-', &in);
567 printf(GETMESSAGE(2, 2,"dtpad: illegal option: %s"),
574 printf(GETMESSAGE(2, 3, "dtpad: extra argument: %s"),
584 XtSetArg(al[ac], XmNgeometry, &pPad->geometry); ac++;
585 XtGetValues(topLevelWithWmCommand, al, ac);
587 /* Realize the top level widget */
588 XtSetMappedWhenManaged(topLevelWithWmCommand, False);
589 XtRealizeWidget(topLevelWithWmCommand);
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."));
597 /* TTT - ToolTalk Debug
598 * XSynchronize(pPad->display, True);
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);
610 /* Create the application shell widget and obtain the application context.
611 * This is also done in FindOrCreatePad() for each Editor pad instance */
613 XtSetArg(al[ac], XmNargv, &argv_l); ac++;
614 XtSetArg(al[ac], XmNargc, &argc_l); ac++;
615 XtGetValues(topLevelWithWmCommand, al, ac);
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]);
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);
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);
643 /* Set some initial Editor instance values */
644 if (pPad->xrdb.server == False) {
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 ************************************************************************/
665 pPad = *ppPad = (Editor *) XtCalloc(1, sizeof(Editor));
666 pPad->pPrevPad = (Editor *)NULL;
668 if (pPadList == (Editor *)NULL) {
670 pPad->pNextPad = (Editor *)NULL;
672 Editor *pTemp = pPadList;
674 pPad->pNextPad = pTemp;
675 pTemp->pPrevPad = pPad;
679 /************************************************************************
680 * SetupLoadArgs - pack requestor options into the Edit request
681 ************************************************************************/
684 SetupLoadArgs(Tt_message m, Editor *pPad)
686 ApplicationDataPtr pArgs = &pPad->xrdb;
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);
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);
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);
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;
728 /************************************************************************
729 * pLoadMsgCB - requestor side ttmedia_load() callback setup in
730 * SendMessageToServer() to handle Replies from the dtpad server.
732 * Replies are sent by the server via the following functions:
734 * ttMediaLoadReply (in TTmediaReply). TTmediaReply is executed when:
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
740 * 3) a Quit request is handled which matches the Edit request
742 * tttk_message_fail. tttk_message_fail is normally called whenever
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
752 ************************************************************************/
754 pLoadMsgCB(Tt_message msg,
757 unsigned char *contents,
761 Tt_state state = tt_message_state(msg);
762 StartupStruct *pStruct = (StartupStruct *)tt_message_user(msg, 0);
764 if (state == TT_HANDLED) {
765 tttk_message_destroy(msg);
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);
779 /************************************************************************
780 * pStatusCB - requestor side ttdt_subcontract_manage() callback setup in
781 * SendMessageToServer() to handle Status messages from the dtpad
784 * The server sends a Status message via ttdt_message_accept() when
785 * it determines that it can actually handle the EDIT request.
787 ************************************************************************/
789 pStatusCB(Tt_message msg,
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).*/
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) {
809 /************************************************************************
810 * SendMessageToServer - requestor mode routine to setup callbacks and send
811 * a message to the dtpad "server" to do one of the following:
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
818 ************************************************************************/
825 StartupStruct *pStruct = (StartupStruct *)XtMalloc(sizeof(StartupStruct));
826 char *fileName, *pArgs;
831 if (pPad->xrdb.session != (char *)NULL) {
832 fileName = pPad->xrdb.session;
833 } else if (argc > 1) {
834 fileName = argv[argc - 1];
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.
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 ...") );
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.
862 pStruct->pPad = pPad;
863 pStruct->argc = argc;
864 pStruct->argv = argv;
867 XtAddEventHandler(topLevelWithWmCommand, 0, True,
868 (XtEventHandler) _XEditResCheckMessages,
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 ...") );
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
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.
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 *-------------------------------------------------------*/
905 if (strcmp(fileName, "*") == 0) {
906 op = TTME_INSTANTIATE;
911 msg = ttmedia_load(0,
922 status = tt_ptr_error(msg);
923 if (tt_is_err(status))
929 ttdt_subcontract_manage(msg,
932 (void *) ((XtArgVal) pPad->xrdb.blocking));/* client data */
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);
941 /************************************************************************
942 * InitEditSessionAndFirstPad - performs initialization related to
943 * starting the edit session and then calls the routine that creates
944 * the first pPad Editor.
946 * (was InitGlobalAndFirstPad)
947 ************************************************************************/
950 InitEditSessionAndFirstPad(
955 char *pTmp = (char *)NULL;
957 CreateDefaultImage ((char *) warningBits, 32, 32, "warn_image");
959 xa_WM_DELETE_WINDOW = XInternAtom(pPad->display,
960 "WM_DELETE_WINDOW", False);
962 /* get the users group and user id for file type checking */
963 pPad->group_id = getgid();
964 pPad->user_id = getuid();
966 /* Set up file name */
967 if (pPad->saveRestore == True && argv[3] != NULL) {
969 } else if (argc > 1) {
970 pTmp = argv[argc - 1];
973 if (pTmp != (char *)NULL) {
974 pPad->fileStuff.fileName = (char *) XtMalloc(strlen(pTmp) + 1);
975 strcpy(pPad->fileStuff.fileName, pTmp);
977 pPad->fileStuff.fileName = (char *)NULL;
979 pPad->fileStuff.lastIncludeName = (char *)NULL;
980 RealizeNewPad(pPad); /* display first pPad Editor window */
982 setPanicConditions(); /* Set up emergency calls to PanicSave */
985 * Set up a handler for SIGCLD so that the command invoker library
986 * doesn't leave zombies.
989 struct sigaction act;
990 sigfillset(&act.sa_mask);
992 act.sa_handler = SigcldHndlr;
993 sigaction(SIGCHLD, &act, (struct sigaction *)NULL);
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.
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.
1009 ************************************************************************/
1014 Arg al[5]; /* arg list */
1015 register int ac; /* arg count */
1017 /* Create the title */
1018 pPad->dialogTitle = DialogTitle(pPad);
1020 /* Set some applic shell resources */
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);
1027 if (pPad->xrdb.session != NULL) {
1028 restoreSession(pPad);
1032 /* Create Main Window */
1033 pPad->mainWindow = XmCreateMainWindow (pPad->app_shell, "main", al, 0);
1034 XtManageChild (pPad->mainWindow);
1036 /* Create MenuBar in Main Window */
1037 CreateMenuBar(pPad);
1038 XtManageChild (pPad->menu_bar);
1040 /* Create the DT Editor Widget in the Main Window. */
1041 CreateEditorWidget (pPad);
1042 XtManageChild (pPad->editor);
1045 /* Create the popup for the editor */
1046 CreatePopupMenu (pPad);
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,
1056 /* Realize toplevel widgets. */
1057 XtSetMappedWhenManaged(pPad->app_shell, False);
1058 XtRealizeWidget (pPad->app_shell);
1060 /* Set the window title */
1061 ChangeMainWindowTitle(pPad);
1063 XSync(pPad->display, 0);
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);
1069 /* reset the "save with newLines" flag */
1070 pPad->fileStuff.saveWithNewlines = True;
1072 /* set app shell geometry (pixels), resize hints, position & size hints */
1073 SetWindowSize(pPad);
1075 /* set the state of the pPad based on its resources */
1076 SetStateFromResources(pPad);
1078 /* set File menu SaveAs label/mnemonic based on xrdb.nameChange */
1079 SetSaveAsLabelAndDialog(pPad);
1081 ChangeMainWindowTitle(pPad);
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);
1094 /* load the file (if there's actually a file name specified) */
1095 LoadFile(pPad, NULL);
1100 /************************************************************************
1101 * ManageOldPad - opens a new file in an exiting Editor pad "window".
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:
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 ************************************************************************/
1117 Boolean isCurrentlyVisible)
1120 if(pPad->xrdb.session != NULL)
1121 restoreSession(pPad);
1123 /*.. create the title */
1124 ChangeMainWindowTitle(pPad);
1125 SetStateFromResources(pPad); /* set the pPad state based on resources */
1128 /* set File menu SaveAs label/mnemonic based on xrdb.nameChange */
1129 SetSaveAsLabelAndDialog(pPad);
1131 /* set app shell geometry (pixels), resize hints, position & size hints */
1132 SetWindowSize(pPad);
1134 ChangeMainWindowTitle(pPad);
1136 /* If the window is iconified and autoRaise is disabled, then
1137 * we don't what to deiconify the window.
1139 if (!isCurrentlyVisible) {
1140 XtSetMappedWhenManaged(pPad->app_shell, True);
1141 XtPopup(pPad->app_shell, XtGrabNone);
1142 XtMapWidget(pPad->app_shell);
1145 LoadFile(pPad, NULL);
1149 /************************************************************************
1151 ************************************************************************/
1155 XtPointer clientData)
1158 /* Read in the new databases */
1160 ActionDBInitialized = True;
1164 /************************************************************************
1166 ************************************************************************/
1169 exitCB(Widget w, XtPointer callData, XtPointer clientData)
1171 exit((XtArgVal) clientData);
1174 /************************************************************************
1175 * setPanicConditions -
1176 ************************************************************************/
1178 setPanicConditions(void)
1180 struct sigaction act;
1182 sigfillset(&act.sa_mask);
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);
1198 sigfillset(&act.sa_mask);
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);
1208 sigaction(SIGEMT, &act, (struct sigaction *)NULL);
1210 sigaction(SIGFPE, &act, (struct sigaction *)NULL);
1211 sigaction(SIGBUS, &act, (struct sigaction *)NULL);
1212 sigaction(SIGSEGV, &act, (struct sigaction *)NULL);
1214 sigaction(SIGSYS, &act, (struct sigaction *)NULL);
1216 sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
1217 sigaction(SIGTERM, &act, (struct sigaction *)NULL);
1219 /* TTT - comment out for debugging TookTalk code */
1221 XSetErrorHandler((int (*)()) PanicSave);
1222 XSetIOErrorHandler((int (*)())PanicSave);
1224 XSetErrorHandler(dtpadXErrorHandler);
1225 XSetIOErrorHandler(dtpadXIOErrorHandler);
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
1233 ************************************************************************/
1235 GetAdjustedResizeHints(
1239 Arg al[2]; /* arg list */
1240 register int ac; /* arg count */
1243 /* get Dt Editor widget size hints */
1244 DtEditorGetSizeHints(pPad->editor, pHints);
1246 /* get the menu bar height */
1247 XtSetArg(al[0], XmNheight, &MBheight);
1248 XtGetValues(pPad->menu_bar, al, 1);
1250 /* adjust the editor widget min height by menu bar height */
1251 pHints->min_height += MBheight;
1252 pHints->base_height += MBheight;
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 ************************************************************************/
1264 SetAppShellResizeHints(
1267 XSizeHints size_hints;
1268 long supplied_return;
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);
1274 GetAdjustedResizeHints(pPad, &size_hints); /* consider the menu bar */
1276 XSetWMSizeHints(pPad->display, XtWindow(pPad->app_shell), &size_hints,
1277 XA_WM_NORMAL_HINTS);
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 ************************************************************************/
1293 unsigned int geometryWidth;
1294 unsigned int geometryHeight;
1295 XSizeHints size_hints;
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 */
1305 if (!(geometryBits & WidthValue))
1306 geometryWidth = DEFAULT_COLS;
1307 if (!(geometryBits & HeightValue))
1308 geometryHeight = DEFAULT_ROWS;
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;
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)) -
1325 2 * pPad->app_shell->core.border_width;
1330 if (geometryBits & YValue) {
1331 if (geometryBits & YNegative) {
1332 geometryY += DisplayHeight(pPad->display,
1333 DefaultScreen(pPad->display)) -
1335 2 * pPad->app_shell->core.border_width;
1341 /* -----> set pad's pixel geometry */
1342 pPad->width = geometryWidth;
1343 pPad->height = geometryHeight;
1344 pPad->x = geometryX;
1345 pPad->y = geometryY;
1347 return geometryBits;
1351 /************************************************************************
1352 * SetWindowSize - sets the following for the pad's application shell:
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)
1359 ************************************************************************/
1364 Arg al[10]; /* arg list */
1365 register int ac; /* arg count */
1366 XSizeHints size_hints;
1368 long supplied_return;
1370 XWindowChanges changesStruct;
1373 /* -----> set pad's app_shell geometry (in pixels) */
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);
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);
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++;
1398 if (geometryBits & YValue) {
1399 wm->wm.size_hints.flags |= USPosition;
1400 XtSetArg (al[ac], XmNy, pPad->y); ac++;
1402 if (geometryBits & WidthValue) {
1403 wm->wm.size_hints.flags |= USSize;
1404 XtSetArg (al[ac], XmNwidth, pPad->width); ac++;
1406 if (geometryBits & HeightValue) {
1407 wm->wm.size_hints.flags |= USSize;
1408 XtSetArg (al[ac], XmNheight, pPad->height); ac++;
1411 XtSetValues(pPad->app_shell, al, ac);
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);
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;
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;
1444 wm->wm.size_hints.flags |= PPosition;
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;
1457 wm->wm.size_hints.flags |= PSize;
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;
1466 wmhints->initial_state = IconicState;
1468 wmhints->initial_state = NormalState;
1469 XSetWMHints(XtDisplay(pPad->app_shell),
1470 XtWindow(pPad->app_shell), wmhints);
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);
1481 /************************************************************************
1482 * SetInitialMenuSensitivity - sets the initial sensitivity of various menu
1483 items primarily based on whether or not we're in viewOnly mode.
1484 ************************************************************************/
1486 SetInitialMenuSensitivity(
1489 Boolean editable = ! pPad->xrdb.viewOnly;
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);
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);
1512 SetSelectionMenuItems(pPad, False); /* set Cut, Copy, Clear & Delete */
1514 /* -----> set sensitivity of Format menu */
1515 XtSetSensitive(pPad->formatStuff.widgets.formatBtn, editable);
1517 /* -----> set sensitivity of Options menu items */
1518 XtSetSensitive(pPad->optionsStuff.widgets.overstrikeBtn, editable);
1519 XtSetSensitive(pPad->optionsStuff.widgets.wordWrapBtn, editable);
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:
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
1535 ************************************************************************/
1537 SetStateFromResources(
1540 Arg al[1]; /* arg list */
1541 OptionsMenuWidgets *pWidg = &pPad->optionsStuff.widgets;
1543 SetWorkSpaceHints(pPad->app_shell, pPad->xrdb.workspaceList);
1544 /* Create the title */
1545 pPad->dialogTitle = DialogTitle(pPad);
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. */
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);
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);
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);
1574 /* -----> Set whether text can be edited */
1575 XtSetArg(al[0], DtNeditable, !pPad->xrdb.viewOnly);
1576 XtSetValues(pPad->editor, al, 1);
1577 SetInitialMenuSensitivity(pPad);
1582 /************************************************************************
1584 ************************************************************************/
1586 void SigcldHndlr (int dummy)
1589 struct sigaction act;
1590 sigfillset(&act.sa_mask);
1592 act.sa_handler = SigcldHndlr;
1597 * Is this really necessary?
1599 sigaction(SIGCHLD, &act, (struct sigaction *)NULL);
1603 /************************************************************************
1604 * UnmanageAllDialogs - unmanages all the dialogs which may be managed
1605 * when a pad gets closed or withdrawn.
1606 ************************************************************************/
1613 * Unmanage all Modal dialogs that might possibly be up.
1615 if (pPad->fileStuff.fileWidgets.saveAs.alrdy_exist != (Widget)NULL &&
1616 pPad->fileStuff.fileWidgets.saveAs.alrdy_exist->core.managed == True)
1618 XtUnmanageChild(pPad->fileStuff.fileWidgets.saveAs.alrdy_exist);
1621 if (pPad->fileStuff.fileWidgets.select.save_warning != (Widget)NULL &&
1622 pPad->fileStuff.fileWidgets.select.save_warning->core.managed == True)
1624 XtUnmanageChild(pPad->fileStuff.fileWidgets.select.save_warning);
1627 if (pPad->fileStuff.fileWidgets.gen_warning != (Widget)NULL &&
1628 pPad->fileStuff.fileWidgets.gen_warning->core.managed == True)
1630 XtUnmanageChild(pPad->fileStuff.fileWidgets.gen_warning);
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.
1638 if (pPad->fileStuff.fileWidgets.select.file_dialog != (Widget)NULL &&
1639 pPad->fileStuff.fileWidgets.select.file_dialog->core.managed == True)
1641 XtUnmanageChild(pPad->fileStuff.fileWidgets.select.file_dialog);
1644 if (pPad->fileStuff.fileWidgets.saveAs.saveAs_form != (Widget)NULL &&
1645 pPad->fileStuff.fileWidgets.saveAs.saveAs_form->core.managed == True)
1647 XtUnmanageChild(pPad->fileStuff.fileWidgets.saveAs.saveAs_form);
1651 * Unmanage help if it's up.
1653 if (pPad->MainHelp != (Widget)NULL && pPad->MainHelp->core.managed == True)
1655 XtUnmanageChild(pPad->MainHelp);
1657 for (pHelp = pPad->pHelpCache; pHelp != (HelpStruct *)NULL;
1658 pHelp = pHelp->pNext)
1660 if (pHelp->dialog != (Widget)NULL &&
1661 pHelp->dialog->core.managed == True)
1663 XtUnmanageChild(pHelp->dialog);
1669 /************************************************************************
1670 * RestoreInitialServerResources -
1671 ************************************************************************/
1673 RestoreInitialServerResources(
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 );
1684 pPad->xrdb = initialServerResources;
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);
1697 #ifndef NO_MESSAGE_CATALOG
1698 /*****************************************************************************
1699 * _DtpadGetMessage - obtains a localized message from dtpad's message catalog
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.
1708 * Returns: the message string for set 'set' and number 'number'.
1710 *****************************************************************************/
1720 static int first = 1;
1721 static nl_catd nlmsg_fd;
1725 nlmsg_fd = catopen(_DTPAD_CAT_NAME, NL_CAT_LOCALE);
1728 msg = _DtCatgetsCached(nlmsg_fd, set, number, string);
1730 msg = catgets(nlmsg_fd, set, number, string);
1735 #endif /* NO_MESSAGE_CATALOG */
1737 /************************************************************************
1738 * HostCB - message callback for (op) Get_SysInfo message
1739 ************************************************************************/
1743 HostCB(Tt_message m, Tt_pattern p)
1745 Tt_state state = tt_message_state(m);
1747 if (state == TT_HANDLED) {
1748 value = tt_message_arg_val(m, 1);
1753 /************************************************************************
1756 * When incorrect parameters have been specified on the command
1757 * line, print out a set of messages detailing the correct use
1760 ************************************************************************/
1767 char * message_string1 = "'%s' is a bad option.\nUsage: %s...\n"
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"
1782 "Disallows editing of text in the edit window, essentially\n\t"
1783 "turning the Text Editor into a Text Viewer.\n\n"
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"
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";
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"
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"
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"
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"
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";
1819 template = (GETMESSAGE(7,9, message_string1));
1821 fprintf (stderr, template, argv[1], argv[0]);
1823 template = (GETMESSAGE(7,10, message_string2));
1825 fprintf (stderr, "%s", template);
1832 /************************************************************************
1834 * dtpadXErrorHandler
1836 ************************************************************************/
1843 #define _DTPAD_BUFSIZE 1024
1844 static char msg[_DTPAD_BUFSIZE];
1847 _DtPrintDefaultErrorSafe(display, xerr, msg, _DTPAD_BUFSIZE);
1848 _DtSimpleError("dtpad", DtWarning, NULL, msg, NULL);
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.
1856 if (PrintJobIsActivePrintDisplay(display) && xerr->error_code == BadAlloc)
1858 PrintJobSetErrorPrintDisplay(display);
1862 XGetErrorText(display, xerr->error_code, msg, 1024);
1863 fprintf(stderr, "Error Code %s\n", msg);
1870 /************************************************************************
1872 * dtpadXIOErrorHandler
1874 ************************************************************************/
1877 dtpadXIOErrorHandler(
1880 static char msg[1024];
1882 fprintf(stderr, "X IO Error");