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 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:
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 ...") );
442 /*--------------------------------------------------------
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).
449 *-------------------------------------------------------*/
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.
455 SendMessageToServer(pPad, argc, argv);
458 XtAppMainLoop(pPad->app_context);
464 /************************************************************************
465 * CreateFirstPad - Performs initialization common to all modes of
466 * operation (i.e. to requestor mode, server mode and standAlone
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.
472 * Specifically, this routine:
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
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).
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.
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.
504 * [SuG 5/12/95] Modified for fishy argument checking.
505 ************************************************************************/
512 char **argv_l, **c_argv_l;
518 /* Added for the argument fix*/
521 Atom xa_WM_SAVE_YOURSELF;
523 extern int optind, opterr, optind;
526 /* Create the 1st Editor entry in list of Editor instances.
527 * This is also done in FindOrCreatePad() for each Editor pad instance */
530 if (pPad->progname=MbStrrchr(argv[0], '/'))
533 pPad->progname = argv[0];
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);
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 '-').
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
556 for (i = 1; i < ((*pArgc) - 1); i++)
558 inS = MbStrchri(argv[i], '-', &in);
562 printf(GETMESSAGE(2, 2,"dtpad: illegal option: %s"),
569 printf(GETMESSAGE(2, 3, "dtpad: extra argument: %s"),
579 XtSetArg(al[ac], XmNgeometry, &pPad->geometry); ac++;
580 XtGetValues(topLevelWithWmCommand, al, ac);
582 /* Realize the top level widget */
583 XtSetMappedWhenManaged(topLevelWithWmCommand, False);
584 XtRealizeWidget(topLevelWithWmCommand);
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."));
592 /* TTT - ToolTalk Debug
593 * XSynchronize(pPad->display, True);
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);
605 /* Create the application shell widget and obtain the application context.
606 * This is also done in FindOrCreatePad() for each Editor pad instance */
608 XtSetArg(al[ac], XmNargv, &argv_l); ac++;
609 XtSetArg(al[ac], XmNargc, &argc_l); ac++;
610 XtGetValues(topLevelWithWmCommand, al, ac);
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]);
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);
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);
638 /* Set some initial Editor instance values */
639 if (pPad->xrdb.server == False) {
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 ************************************************************************/
660 pPad = *ppPad = (Editor *) XtCalloc(1, sizeof(Editor));
661 pPad->pPrevPad = (Editor *)NULL;
663 if (pPadList == (Editor *)NULL) {
665 pPad->pNextPad = (Editor *)NULL;
667 Editor *pTemp = pPadList;
669 pPad->pNextPad = pTemp;
670 pTemp->pPrevPad = pPad;
674 /************************************************************************
675 * SetupLoadArgs - pack requestor options into the Edit request
676 ************************************************************************/
679 SetupLoadArgs(Tt_message m, Editor *pPad)
681 ApplicationDataPtr pArgs = &pPad->xrdb;
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);
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);
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);
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;
723 /************************************************************************
724 * pLoadMsgCB - requestor side ttmedia_load() callback setup in
725 * SendMessageToServer() to handle Replies from the dtpad server.
727 * Replies are sent by the server via the following functions:
729 * ttMediaLoadReply (in TTmediaReply). TTmediaReply is executed when:
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
735 * 3) a Quit request is handled which matches the Edit request
737 * tttk_message_fail. tttk_message_fail is normally called whenever
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
747 ************************************************************************/
749 pLoadMsgCB(Tt_message msg,
752 unsigned char *contents,
756 Tt_state state = tt_message_state(msg);
757 StartupStruct *pStruct = (StartupStruct *)tt_message_user(msg, 0);
759 if (state == TT_HANDLED) {
760 tttk_message_destroy(msg);
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);
774 /************************************************************************
775 * pStatusCB - requestor side ttdt_subcontract_manage() callback setup in
776 * SendMessageToServer() to handle Status messages from the dtpad
779 * The server sends a Status message via ttdt_message_accept() when
780 * it determines that it can actually handle the EDIT request.
782 ************************************************************************/
784 pStatusCB(Tt_message msg,
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).*/
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) {
804 /************************************************************************
805 * SendMessageToServer - requestor mode routine to setup callbacks and send
806 * a message to the dtpad "server" to do one of the following:
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
813 ************************************************************************/
820 StartupStruct *pStruct = (StartupStruct *)XtMalloc(sizeof(StartupStruct));
821 char *fileName, *pArgs;
826 if (pPad->xrdb.session != (char *)NULL) {
827 fileName = pPad->xrdb.session;
828 } else if (argc > 1) {
829 fileName = argv[argc - 1];
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.
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 ...") );
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.
857 pStruct->pPad = pPad;
858 pStruct->argc = argc;
859 pStruct->argv = argv;
862 XtAddEventHandler(topLevelWithWmCommand, 0, True,
863 (XtEventHandler) _XEditResCheckMessages,
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 ...") );
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
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.
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 *-------------------------------------------------------*/
900 if (strcmp(fileName, "*") == 0) {
901 op = TTME_INSTANTIATE;
906 msg = ttmedia_load(0,
917 status = tt_ptr_error(msg);
918 if (tt_is_err(status))
924 ttdt_subcontract_manage(msg,
927 (void *) ((XtArgVal) pPad->xrdb.blocking));/* client data */
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);
936 /************************************************************************
937 * InitEditSessionAndFirstPad - performs initialization related to
938 * starting the edit session and then calls the routine that creates
939 * the first pPad Editor.
941 * (was InitGlobalAndFirstPad)
942 ************************************************************************/
945 InitEditSessionAndFirstPad(
950 char *pTmp = (char *)NULL;
952 CreateDefaultImage ((char *) warningBits, 32, 32, "warn_image");
954 xa_WM_DELETE_WINDOW = XInternAtom(pPad->display,
955 "WM_DELETE_WINDOW", False);
957 /* get the users group and user id for file type checking */
958 pPad->group_id = getgid();
959 pPad->user_id = getuid();
961 /* Set up file name */
962 if (pPad->saveRestore == True && argv[3] != NULL) {
964 } else if (argc > 1) {
965 pTmp = argv[argc - 1];
968 if (pTmp != (char *)NULL) {
969 pPad->fileStuff.fileName = (char *) XtMalloc(strlen(pTmp) + 1);
970 strcpy(pPad->fileStuff.fileName, pTmp);
972 pPad->fileStuff.fileName = (char *)NULL;
974 pPad->fileStuff.lastIncludeName = (char *)NULL;
975 RealizeNewPad(pPad); /* display first pPad Editor window */
977 setPanicConditions(); /* Set up emergency calls to PanicSave */
980 * Set up a handler for SIGCLD so that the command invoker library
981 * doesn't leave zombies.
984 struct sigaction act;
985 sigfillset(&act.sa_mask);
987 act.sa_handler = SigcldHndlr;
988 sigaction(SIGCHLD, &act, (struct sigaction *)NULL);
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.
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.
1004 ************************************************************************/
1009 Arg al[5]; /* arg list */
1010 int ac; /* arg count */
1012 /* Create the title */
1013 pPad->dialogTitle = DialogTitle(pPad);
1015 /* Set some applic shell resources */
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);
1022 if (pPad->xrdb.session != NULL) {
1023 restoreSession(pPad);
1027 /* Create Main Window */
1028 pPad->mainWindow = XmCreateMainWindow (pPad->app_shell, "main", al, 0);
1029 XtManageChild (pPad->mainWindow);
1031 /* Create MenuBar in Main Window */
1032 CreateMenuBar(pPad);
1033 XtManageChild (pPad->menu_bar);
1035 /* Create the DT Editor Widget in the Main Window. */
1036 CreateEditorWidget (pPad);
1037 XtManageChild (pPad->editor);
1040 /* Create the popup for the editor */
1041 CreatePopupMenu (pPad);
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,
1051 /* Realize toplevel widgets. */
1052 XtSetMappedWhenManaged(pPad->app_shell, False);
1053 XtRealizeWidget (pPad->app_shell);
1055 /* Set the window title */
1056 ChangeMainWindowTitle(pPad);
1058 XSync(pPad->display, 0);
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);
1064 /* reset the "save with newLines" flag */
1065 pPad->fileStuff.saveWithNewlines = True;
1067 /* set app shell geometry (pixels), resize hints, position & size hints */
1068 SetWindowSize(pPad);
1070 /* set the state of the pPad based on its resources */
1071 SetStateFromResources(pPad);
1073 /* set File menu SaveAs label/mnemonic based on xrdb.nameChange */
1074 SetSaveAsLabelAndDialog(pPad);
1076 ChangeMainWindowTitle(pPad);
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);
1089 /* load the file (if there's actually a file name specified) */
1090 LoadFile(pPad, NULL);
1095 /************************************************************************
1096 * ManageOldPad - opens a new file in an exiting Editor pad "window".
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:
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 ************************************************************************/
1112 Boolean isCurrentlyVisible)
1115 if(pPad->xrdb.session != NULL)
1116 restoreSession(pPad);
1118 /*.. create the title */
1119 ChangeMainWindowTitle(pPad);
1120 SetStateFromResources(pPad); /* set the pPad state based on resources */
1123 /* set File menu SaveAs label/mnemonic based on xrdb.nameChange */
1124 SetSaveAsLabelAndDialog(pPad);
1126 /* set app shell geometry (pixels), resize hints, position & size hints */
1127 SetWindowSize(pPad);
1129 ChangeMainWindowTitle(pPad);
1131 /* If the window is iconified and autoRaise is disabled, then
1132 * we don't what to deiconify the window.
1134 if (!isCurrentlyVisible) {
1135 XtSetMappedWhenManaged(pPad->app_shell, True);
1136 XtPopup(pPad->app_shell, XtGrabNone);
1137 XtMapWidget(pPad->app_shell);
1140 LoadFile(pPad, NULL);
1144 /************************************************************************
1146 ************************************************************************/
1150 XtPointer clientData)
1153 /* Read in the new databases */
1155 ActionDBInitialized = True;
1159 /************************************************************************
1161 ************************************************************************/
1164 exitCB(Widget w, XtPointer callData, XtPointer clientData)
1166 exit((XtArgVal) clientData);
1169 /************************************************************************
1170 * setPanicConditions -
1171 ************************************************************************/
1173 setPanicConditions(void)
1175 struct sigaction act;
1177 sigfillset(&act.sa_mask);
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);
1193 sigfillset(&act.sa_mask);
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);
1203 sigaction(SIGEMT, &act, (struct sigaction *)NULL);
1205 sigaction(SIGFPE, &act, (struct sigaction *)NULL);
1206 sigaction(SIGBUS, &act, (struct sigaction *)NULL);
1207 sigaction(SIGSEGV, &act, (struct sigaction *)NULL);
1209 sigaction(SIGSYS, &act, (struct sigaction *)NULL);
1211 sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
1212 sigaction(SIGTERM, &act, (struct sigaction *)NULL);
1214 /* TTT - comment out for debugging TookTalk code */
1216 XSetErrorHandler((int (*)()) PanicSave);
1217 XSetIOErrorHandler((int (*)())PanicSave);
1219 XSetErrorHandler(dtpadXErrorHandler);
1220 XSetIOErrorHandler(dtpadXIOErrorHandler);
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
1228 ************************************************************************/
1230 GetAdjustedResizeHints(
1234 Arg al[2]; /* arg list */
1235 int ac; /* arg count */
1238 /* get Dt Editor widget size hints */
1239 DtEditorGetSizeHints(pPad->editor, pHints);
1241 /* get the menu bar height */
1242 XtSetArg(al[0], XmNheight, &MBheight);
1243 XtGetValues(pPad->menu_bar, al, 1);
1245 /* adjust the editor widget min height by menu bar height */
1246 pHints->min_height += MBheight;
1247 pHints->base_height += MBheight;
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 ************************************************************************/
1259 SetAppShellResizeHints(
1262 XSizeHints size_hints;
1263 long supplied_return;
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);
1269 GetAdjustedResizeHints(pPad, &size_hints); /* consider the menu bar */
1271 XSetWMSizeHints(pPad->display, XtWindow(pPad->app_shell), &size_hints,
1272 XA_WM_NORMAL_HINTS);
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 ************************************************************************/
1288 unsigned int geometryWidth;
1289 unsigned int geometryHeight;
1290 XSizeHints size_hints;
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 */
1300 if (!(geometryBits & WidthValue))
1301 geometryWidth = DEFAULT_COLS;
1302 if (!(geometryBits & HeightValue))
1303 geometryHeight = DEFAULT_ROWS;
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;
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)) -
1320 2 * pPad->app_shell->core.border_width;
1325 if (geometryBits & YValue) {
1326 if (geometryBits & YNegative) {
1327 geometryY += DisplayHeight(pPad->display,
1328 DefaultScreen(pPad->display)) -
1330 2 * pPad->app_shell->core.border_width;
1336 /* -----> set pad's pixel geometry */
1337 pPad->width = geometryWidth;
1338 pPad->height = geometryHeight;
1339 pPad->x = geometryX;
1340 pPad->y = geometryY;
1342 return geometryBits;
1346 /************************************************************************
1347 * SetWindowSize - sets the following for the pad's application shell:
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)
1354 ************************************************************************/
1359 Arg al[10]; /* arg list */
1360 int ac; /* arg count */
1361 XSizeHints size_hints;
1363 long supplied_return;
1365 XWindowChanges changesStruct;
1368 /* -----> set pad's app_shell geometry (in pixels) */
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);
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);
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++;
1393 if (geometryBits & YValue) {
1394 wm->wm.size_hints.flags |= USPosition;
1395 XtSetArg (al[ac], XmNy, pPad->y); ac++;
1397 if (geometryBits & WidthValue) {
1398 wm->wm.size_hints.flags |= USSize;
1399 XtSetArg (al[ac], XmNwidth, pPad->width); ac++;
1401 if (geometryBits & HeightValue) {
1402 wm->wm.size_hints.flags |= USSize;
1403 XtSetArg (al[ac], XmNheight, pPad->height); ac++;
1406 XtSetValues(pPad->app_shell, al, ac);
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);
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;
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;
1439 wm->wm.size_hints.flags |= PPosition;
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;
1452 wm->wm.size_hints.flags |= PSize;
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;
1461 wmhints->initial_state = IconicState;
1463 wmhints->initial_state = NormalState;
1464 XSetWMHints(XtDisplay(pPad->app_shell),
1465 XtWindow(pPad->app_shell), wmhints);
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);
1476 /************************************************************************
1477 * SetInitialMenuSensitivity - sets the initial sensitivity of various menu
1478 items primarily based on whether or not we're in viewOnly mode.
1479 ************************************************************************/
1481 SetInitialMenuSensitivity(
1484 Boolean editable = ! pPad->xrdb.viewOnly;
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);
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);
1507 SetSelectionMenuItems(pPad, False); /* set Cut, Copy, Clear & Delete */
1509 /* -----> set sensitivity of Format menu */
1510 XtSetSensitive(pPad->formatStuff.widgets.formatBtn, editable);
1512 /* -----> set sensitivity of Options menu items */
1513 XtSetSensitive(pPad->optionsStuff.widgets.overstrikeBtn, editable);
1514 XtSetSensitive(pPad->optionsStuff.widgets.wordWrapBtn, editable);
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:
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
1530 ************************************************************************/
1532 SetStateFromResources(
1535 Arg al[1]; /* arg list */
1536 OptionsMenuWidgets *pWidg = &pPad->optionsStuff.widgets;
1538 SetWorkSpaceHints(pPad->app_shell, pPad->xrdb.workspaceList);
1539 /* Create the title */
1540 pPad->dialogTitle = DialogTitle(pPad);
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. */
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);
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);
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);
1569 /* -----> Set whether text can be edited */
1570 XtSetArg(al[0], DtNeditable, !pPad->xrdb.viewOnly);
1571 XtSetValues(pPad->editor, al, 1);
1572 SetInitialMenuSensitivity(pPad);
1577 /************************************************************************
1579 ************************************************************************/
1581 void SigcldHndlr (int dummy)
1584 struct sigaction act;
1585 sigfillset(&act.sa_mask);
1587 act.sa_handler = SigcldHndlr;
1592 * Is this really necessary?
1594 sigaction(SIGCHLD, &act, (struct sigaction *)NULL);
1598 /************************************************************************
1599 * UnmanageAllDialogs - unmanages all the dialogs which may be managed
1600 * when a pad gets closed or withdrawn.
1601 ************************************************************************/
1608 * Unmanage all Modal dialogs that might possibly be up.
1610 if (pPad->fileStuff.fileWidgets.saveAs.alrdy_exist != (Widget)NULL &&
1611 pPad->fileStuff.fileWidgets.saveAs.alrdy_exist->core.managed == True)
1613 XtUnmanageChild(pPad->fileStuff.fileWidgets.saveAs.alrdy_exist);
1616 if (pPad->fileStuff.fileWidgets.select.save_warning != (Widget)NULL &&
1617 pPad->fileStuff.fileWidgets.select.save_warning->core.managed == True)
1619 XtUnmanageChild(pPad->fileStuff.fileWidgets.select.save_warning);
1622 if (pPad->fileStuff.fileWidgets.gen_warning != (Widget)NULL &&
1623 pPad->fileStuff.fileWidgets.gen_warning->core.managed == True)
1625 XtUnmanageChild(pPad->fileStuff.fileWidgets.gen_warning);
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.
1633 if (pPad->fileStuff.fileWidgets.select.file_dialog != (Widget)NULL &&
1634 pPad->fileStuff.fileWidgets.select.file_dialog->core.managed == True)
1636 XtUnmanageChild(pPad->fileStuff.fileWidgets.select.file_dialog);
1639 if (pPad->fileStuff.fileWidgets.saveAs.saveAs_form != (Widget)NULL &&
1640 pPad->fileStuff.fileWidgets.saveAs.saveAs_form->core.managed == True)
1642 XtUnmanageChild(pPad->fileStuff.fileWidgets.saveAs.saveAs_form);
1646 * Unmanage help if it's up.
1648 if (pPad->MainHelp != (Widget)NULL && pPad->MainHelp->core.managed == True)
1650 XtUnmanageChild(pPad->MainHelp);
1652 for (pHelp = pPad->pHelpCache; pHelp != (HelpStruct *)NULL;
1653 pHelp = pHelp->pNext)
1655 if (pHelp->dialog != (Widget)NULL &&
1656 pHelp->dialog->core.managed == True)
1658 XtUnmanageChild(pHelp->dialog);
1664 /************************************************************************
1665 * RestoreInitialServerResources -
1666 ************************************************************************/
1668 RestoreInitialServerResources(
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 );
1679 pPad->xrdb = initialServerResources;
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);
1692 #ifndef NO_MESSAGE_CATALOG
1693 /*****************************************************************************
1694 * _DtpadGetMessage - obtains a localized message from dtpad's message catalog
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.
1703 * Returns: the message string for set 'set' and number 'number'.
1705 *****************************************************************************/
1715 static int first = 1;
1716 static nl_catd nlmsg_fd;
1720 nlmsg_fd = catopen(_DTPAD_CAT_NAME, NL_CAT_LOCALE);
1723 msg = _DtCatgetsCached(nlmsg_fd, set, number, string);
1725 msg = catgets(nlmsg_fd, set, number, string);
1730 #endif /* NO_MESSAGE_CATALOG */
1732 /************************************************************************
1733 * HostCB - message callback for (op) Get_SysInfo message
1734 ************************************************************************/
1738 HostCB(Tt_message m, Tt_pattern p)
1740 Tt_state state = tt_message_state(m);
1742 if (state == TT_HANDLED) {
1743 value = tt_message_arg_val(m, 1);
1748 /************************************************************************
1751 * When incorrect parameters have been specified on the command
1752 * line, print out a set of messages detailing the correct use
1755 ************************************************************************/
1762 char * message_string1 = "'%s' is a bad option.\nUsage: %s...\n"
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"
1777 "Disallows editing of text in the edit window, essentially\n\t"
1778 "turning the Text Editor into a Text Viewer.\n\n"
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"
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";
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"
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"
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"
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"
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";
1814 template = (GETMESSAGE(7,9, message_string1));
1816 fprintf (stderr, template, argv[1], argv[0]);
1818 template = (GETMESSAGE(7,10, message_string2));
1820 fprintf (stderr, "%s", template);
1827 /************************************************************************
1829 * dtpadXErrorHandler
1831 ************************************************************************/
1838 #define _DTPAD_BUFSIZE 1024
1839 static char msg[_DTPAD_BUFSIZE];
1842 _DtPrintDefaultErrorSafe(display, xerr, msg, _DTPAD_BUFSIZE);
1843 _DtSimpleError("dtpad", DtWarning, NULL, msg, NULL);
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.
1851 if (PrintJobIsActivePrintDisplay(display) && xerr->error_code == BadAlloc)
1853 PrintJobSetErrorPrintDisplay(display);
1857 XGetErrorText(display, xerr->error_code, msg, 1024);
1858 fprintf(stderr, "Error Code %s\n", msg);
1865 /************************************************************************
1867 * dtpadXIOErrorHandler
1869 ************************************************************************/
1872 dtpadXIOErrorHandler(
1875 static char msg[1024];
1877 fprintf(stderr, "X IO Error");
1880 /* Man page for XSetIOErrorhandler says this is a fatal error and
1881 * should not return */