dtpad: Fix 64-bit crash on file open/save
[oweals/cde.git] / cde / programs / dtpad / fileCB.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: fileCB.c /main/13 1999/11/08 08:23:14 mgreess $ */
24 /**********************************<+>*************************************
25 ***************************************************************************
26 **
27 **  File:        fileCB.c
28 **
29 **  Project:     DT dtpad, a memo maker type editor based on the Dt Editor
30 **               widget.
31 **
32 **  Description: 
33 **  -----------
34 **
35 **      This file contains the callbacks for the "File" menu items.
36 **      There's some hair here, due to the nested nature of some of
37 **      the dialogs.  The "New, "Open" and "Exit" callbacks can cause
38 **      the opening of a do-you-wish-to-save dialog, and we have to
39 **      remember how we got there.  This is done through the use
40 **      of the pendingFileFunc field of the Editor struct.
41 **
42 *******************************************************************
43 **  (c) Copyright Hewlett-Packard Company, 1991.  All rights are
44 **  reserved.  Copying or other reproduction of this program
45 **  except for archival purposes is prohibited without prior
46 **  written consent of Hewlett-Packard Company.
47 ********************************************************************
48 **
49 ********************************************************************
50 **  (c) Copyright 1993, 1994 Hewlett-Packard Company
51 **  (c) Copyright 1993, 1994 International Business Machines Corp.
52 **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
53 **  (c) Copyright 1993, 1994 Novell, Inc.
54 ********************************************************************
55 **
56 **
57 **************************************************************************
58 **********************************<+>*************************************/
59 #include <Dt/DtpadM.h>
60 #include <Dt/Action.h>
61
62 #include <Xm/XmPrivate.h> /* _XmStringUngenerate */
63
64 #include "dtpad.h"
65
66 extern int numActivePads;  /* declared in main.c */
67
68
69 /************************************************************************
70  *                      Forward Declarations
71  ************************************************************************/
72 static void FileDoXpPrint(
73         Editor* pPad,
74         Boolean silent);
75 static void FileOpenOkCB(
76         Widget w,
77         caddr_t client_data,
78         caddr_t call_data );
79 static void IncludeFile(
80         Widget w,
81         caddr_t client_data,
82         caddr_t call_data );
83 static Boolean SaveUnsaved(
84         Editor* pPad,
85         void (*callingFunc)() );
86 static Boolean FileExitWP(
87         XtPointer client_data);
88
89
90 /************************************************************************
91  * FileCascadingCB -  callback assigned to "File" menu to determine
92  *      whether Save button in menu is labeled "Save" or "Save (needed)".
93  ************************************************************************/
94 /* ARGSUSED */
95 void
96 FileCascadingCB(
97         Widget w,
98         caddr_t client_data,
99         caddr_t call_data )
100 {
101     Editor *pPad = (Editor *)client_data;
102     Arg al[1];
103
104     if (DtEditorCheckForUnsavedChanges(pPad->editor)) {
105         XtSetArg(al[0], XmNlabelString, pPad->fileStuff.saveNeededBtnLabel);
106     } else {
107         XtSetArg(al[0], XmNlabelString, pPad->fileStuff.saveBtnLabel);
108     }
109     XtSetValues(pPad->fileStuff.fileWidgets.saveBtn, al, 1);
110
111 }
112
113
114 /************************************************************************
115  * FileNewCB -  callback assigned to "File" menu "New" button which
116  *      saves the current text if it hasn't been saved and then calls
117  *      LoadFile().  Since pPad->fileStuff.fileName is NULL, LoadFile
118  *      sets the contents to "" rather than loading a file.
119  ************************************************************************/
120 /* ARGSUSED */
121 void
122 FileNewCB(
123         Widget w,
124         caddr_t client_data,
125         caddr_t call_data )
126 {
127     Editor *pPad = (Editor *)client_data;
128
129     if (SaveUnsaved(pPad, FileNewCB)) {
130         return;
131     }
132
133     if (pPad->ttEditReq.contract && pPad->ttEditReq.op != TTME_INSTANTIATE) {
134         TTmediaReply(pPad);     /* reply/close ToolTalk media request */
135     }
136
137     if (pPad->fileStuff.fileName != (char *)NULL) {
138         XtFree(pPad->fileStuff.fileName);
139         pPad->fileStuff.fileName = (char *)NULL;
140     }
141     _DtTurnOnHourGlass(pPad->app_shell);
142     LoadFile(pPad, NULL);
143     ChangeMainWindowTitle(pPad);
144     _DtTurnOffHourGlass(pPad->app_shell);
145 }
146
147
148 /************************************************************************
149  * FileOpenCB - callback assigned to "File" menu "Open..." button
150  ************************************************************************/
151 /* ARGSUSED */
152 void
153 FileOpenCB(
154         Widget w,
155         caddr_t client_data,
156         caddr_t call_data )
157 {
158     Editor *pPad = (Editor *)client_data;
159     FileStuff *pStuff = &pPad->fileStuff;
160
161     if (SaveUnsaved(pPad, FileOpenCB)) {
162         return;
163     }
164
165     /* ToolTalk media requests are replied to (and closed) in FileOpenOkCB */
166     
167     /* -----> set FSB title passed GetFileName */
168     if(pStuff->openTitle == (XmString)NULL) {
169         char buf[256];
170
171         strcpy(buf, DialogTitle(pPad));
172         strcat(buf, (char *)GETMESSAGE(4, 1, "Open a File"));
173         pStuff->openTitle = XmStringCreateLocalized(buf);
174     }
175
176     /* -----> obtain the name of the file to open (via a Xm file selection box)
177      *        and load its contents (via FileOpenOkCB) to the Editor widget */
178     pStuff->pendingFileFunc = FileOpenOkCB;     /* FSB XmNokCallback */
179     pStuff->pendingFileHelpFunc = HelpOpenDialogCB;  /* FSB XmNhelpCallback */
180     GetFileName(pPad, pStuff->openTitle, OPEN);
181 }
182
183
184 /************************************************************************
185  * FileIncludeCB - callback assigned to "File" menu "Include..." button
186  ************************************************************************/
187 /* ARGSUSED */
188 void
189 FileIncludeCB(
190         Widget w,
191         caddr_t client_data,
192         caddr_t call_data )
193 {
194     Editor *pPad = (Editor *)client_data;
195     FileStuff *pStuff = &pPad->fileStuff;
196
197     if (pStuff->includeTitle == (XmString)NULL) {
198         char buf[256];
199
200         strcpy(buf, DialogTitle(pPad));
201         strcat(buf, (char *)GETMESSAGE(4, 3, "Include a File"));
202         pStuff->includeTitle = XmStringCreateLocalized(buf);
203     }
204     pPad->fileStuff.pendingFileFunc = IncludeFile;
205     pPad->fileStuff.pendingFileHelpFunc = HelpIncludeDialogCB;
206     GetFileName(pPad, pStuff->includeTitle, INCLUDE);
207 }
208
209
210 /************************************************************************
211  * FileSaveCB - callback assigned to "File" menu "Save" button and to the
212  *      AskIfSave dialog's "OK" button (which is displayed when there are
213  *      unsaved changes when switching to a new file/buffer).
214  *
215  *
216  ************************************************************************/
217 void
218 FileSaveCB(
219         Widget w,
220         caddr_t client_data,
221         caddr_t call_data )
222 {
223     Editor *pPad = (Editor *)client_data;
224     void (*pFunc)();
225     DtEditorErrorCode errorCode;
226     Boolean addNewlines = pPad->xrdb.wordWrap == True &&
227                           pPad->fileStuff.saveWithNewlines == True;
228     Tt_message m;
229
230     if (pPad->fileStuff.fileName && *pPad->fileStuff.fileName) { /* filename? */
231         /* -----> if called directly from [Save] menu and word wrap is on,
232          *         display Save dialog so that saveWithNewlines can be set */
233         if (pPad->xrdb.wordWrap &&
234           !pPad->fileStuff.pendingFileFunc && !pPad->ttSaveReq.contract) {
235             AskIfSave(pPad);  
236             pPad->fileStuff.pendingFileFunc = FileSaveCB;
237             return;
238         }
239         _DtTurnOnHourGlass(pPad->app_shell);
240         errorCode = DtEditorSaveContentsToFile(
241                         pPad->editor,
242                         pPad->fileStuff.fileName,
243                         True,                   /* overwrite existing file */
244                         addNewlines,            /* replace soft line feeds? */
245                         True);                  /* mark contents as saved */
246         _DtTurnOffHourGlass(pPad->app_shell);
247         if (errorCode != DtEDITOR_NO_ERRORS) {
248             PostSaveError(pPad, pPad->fileStuff.fileName, errorCode);
249             pPad->fileStuff.pendingFileFunc = (void(*)()) NULL;
250             TTfailPendingSave(pPad);
251             return;
252         }
253         if (pPad->ttEditReq.contract) {
254             /* ZZZ -----> Create and send Saved notice */
255             m = ttdt_file_notice(
256                         pPad->ttEditReq.contract,       /* context */
257                         TTDT_SAVED,                     /* op */
258                         TT_SESSION,                     /* Tt_scope */
259                         pPad->fileStuff.fileName,       /* msg file name */
260                         True);                          /* send & destroy */
261         }
262         if (pPad->ttSaveReq.contract) {
263             if (! pPad->ttEditReq.contract) {
264                 TTfailPendingSave(pPad);
265             } else {
266                 tt_message_reply(pPad->ttSaveReq.contract);
267                 tttk_message_destroy(pPad->ttSaveReq.contract);
268             }
269         }
270     } else {    /* no fileName associated with current text */
271         if (pPad->ttEditReq.contract) {
272             if (pPad->ttEditReq.contents) {
273                 if (TTmediaDepositContents(pPad) != 0) {
274                     if (pPad->fileStuff.pendingFileFunc == FileExitCB) {
275                         TTfailPendingQuit(pPad);
276                     }
277                     TTfailPendingSave(pPad);
278                     pPad->fileStuff.pendingFileFunc = (void(*)()) NULL;
279                     return;     /* deposit failed */
280                 }
281             } else {    /* TT request without fileName and contents */
282                 FileSaveAsCB(w, client_data, call_data);
283                 return;
284             }
285             if (pPad->ttSaveReq.contract) {
286                 tt_message_reply(pPad->ttSaveReq.contract);
287                 tttk_message_destroy(pPad->ttSaveReq.contract);
288             }
289         } else {  /* non-TT request and no file name */
290             if (pPad->ttSaveReq.contract) {
291                 TTfailPendingSave(pPad);
292             } else {
293                 FileSaveAsCB(w, client_data, call_data);
294             }
295             return;
296         }
297     }
298
299     if ((pFunc = pPad->fileStuff.pendingFileFunc) != (void (*)())NULL)  {
300         pPad->fileStuff.pendingFileFunc = (void(*)()) NULL;
301         if (pFunc != FileSaveCB) {
302             (*pFunc)(w, client_data, call_data);
303         }
304     }
305
306 }
307
308
309 /************************************************************************
310  * FileSaveAsCB - callback assigned to "File" menu "SaveAs..." button
311  ************************************************************************/
312 void
313 FileSaveAsCB(
314         Widget w,
315         caddr_t client_data,
316         caddr_t call_data )
317 {
318     Editor *pPad = (Editor *)client_data;
319     SaveAs *pSaveAs = &pPad->fileStuff.fileWidgets.saveAs;
320     Widget textField;
321
322     if (!pSaveAs->saveAs_form) {
323         CreateSaveAsDialog(pPad);
324         XtManageChild (pSaveAs->saveAs_form);
325 /*
326  * XXX - Should be dealing with the FSB instead of the text field directly.
327  *       Also, should be setting an XmString, rather than a char *
328  */
329         textField = XmFileSelectionBoxGetChild(
330                         pPad->fileStuff.fileWidgets.saveAs.saveAs_form,
331                         XmDIALOG_TEXT);
332         XmTextFieldSetString(textField, "");
333     } else {
334         XtManageChild (pSaveAs->saveAs_form);
335         textField = XmFileSelectionBoxGetChild(
336                         pPad->fileStuff.fileWidgets.saveAs.saveAs_form,
337                         XmDIALOG_TEXT);
338     }
339
340     SetSaveAsDirAndFile(pPad); /* seed the SaveAs FSB dir and file fields */
341
342     /* Force the focus to the text field */
343     XmProcessTraversal(textField, XmTRAVERSE_CURRENT);
344     XSync(pPad->display, 0);
345
346     _DtTurnOffHourGlass(pPad->app_shell);
347 }
348
349
350 extern Boolean ActionDBInitialized; /* declared in main.c */
351
352
353 /************************************************************************
354  * PrintActionCB - callback assigned to "File" menu "Print" button
355  ************************************************************************/
356 /* ARGSUSED */
357 void
358 PrintActionCB(
359         DtActionInvocationID actionID,
360         XtPointer client_data,
361         DtActionArg *actionArgp,
362         int argCount,
363         DtActionStatus actionStatus)
364 {
365     Editor *pPad = (Editor *) client_data;
366     switch ((DtActionStatus) actionStatus) {
367         case DtACTION_INVOKED:
368         case DtACTION_STATUS_UPDATE:
369             /* break; */
370         case DtACTION_DONE:
371         case DtACTION_FAILED:
372         case DtACTION_CANCELED:
373         default:
374 /*          XtSetSensitive(pPad->app_shell, True); */
375             _DtTurnOffHourGlass(pPad->app_shell);
376             break;
377     }
378 }
379
380
381 /************************************************************************
382  * FilePrintCB - callback assigned to "File" menu "Print" button
383  ************************************************************************/
384 /* ARGSUSED */
385 void
386 FilePrintCB(
387         Widget w,
388         caddr_t client_data,
389         caddr_t call_data)
390 {
391     Editor *pPad = (Editor *) client_data;
392     DtActionArg *actionArgp = (DtActionArg *) XtCalloc(2,sizeof(DtActionArg));
393     DtActionInvocationID actionID;
394     char *pr_name = (char *) NULL, *user_name;
395     DtEditorErrorCode errorCode;
396
397     Boolean addNewlines = pPad->xrdb.wordWrap == True &&
398                           pPad->fileStuff.saveWithNewlines == True;
399
400     _DtTurnOnHourGlass(pPad->app_shell);
401     /* -----> Disallow keyboard, button, motion, window enter/leave & focus
402      *        events till print (dialog) action is done
403      * XtSetSensitive(pPad->app_shell, False);
404      */
405
406     /* -----> Get a place to temporarily write the text */
407     if ((pr_name = GetTempFile()) == (char *)NULL) {
408         _DtTurnOffHourGlass(pPad->app_shell);
409         Warning(pPad, ((char *)
410                 GETMESSAGE(4, 5, "Unable to create a temporary file.")),                XmDIALOG_ERROR);
411         return;
412     }
413
414     /* -----> Write the contents to the temp file */
415     errorCode = DtEditorSaveContentsToFile(
416                         pPad->editor,
417                         pr_name,
418                         True,           /* overwrite existing file */
419                         addNewlines,    /* replace soft line feeds? */
420                         False);         /* don't mark contents as saved */
421     if (errorCode != SUCCESS) {         /* this should never occur */
422         _DtTurnOffHourGlass(pPad->app_shell);
423         PostSaveError(pPad, pr_name, errorCode);
424         return;
425     }
426
427     /* -----> Load the action database */
428     if (! ActionDBInitialized) {
429         StartDbUpdate( (XtPointer) NULL );
430         /* register interest in Action DB changes (for printing) */
431         DtDbReloadNotify( StartDbUpdate, (XtPointer) NULL );
432     }
433
434     /* -----> Determine the name the user will see in the Print dialog */
435     if (pPad->ttEditReq.contract &&
436                 (pPad->ttEditReq.docName && *pPad->ttEditReq.docName)) {
437         user_name = strdup(pPad->ttEditReq.docName);
438     } else if (pPad->fileStuff.fileName && *pPad->fileStuff.fileName) {
439         user_name = strdup(pPad->fileStuff.fileName);
440     } else {
441         user_name = strdup(UNNAMED_TITLE_P);
442     }
443
444     /* ----> Setup the action arguments - one for the filename as known by
445      *       the user (Arg_1) and one for the temporary print file (Arg_2).
446      *       PRINT_DTPAD_TEMPFILE does something like:
447      *          /usr/dt/bin/dtlp -u %(String)Arg_2% -e %(File)Arg_1%
448      *       dtlp displays a dialog to gather lp paramters and then prints
449      *       the file.  The -e says to remove the temporary file after it
450      *       it has been passed to lp. */
451     actionArgp[0].argClass = DtACTION_FILE;
452     actionArgp[0].u.file.name = pr_name;
453     actionArgp[1].argClass = DtACTION_FILE;
454     actionArgp[1].u.file.name = user_name;
455
456     /* XXX - Try this after everything's working - don't directly output to
457      *       a temp file but to a buffer and pass the buffer to the action
458      *       and let the action automatically create/remove the temp file.
459      *       This'll require a new action w/o -e.
460      * actionArgp[0].argClass = DtACTION_BUFFER;
461      * actionArgp[0].u.buffer.bp = (void *) buffer;
462      * actionArgp[0].u.buffer.size = strlen(buffer;
463      * actionArgp[0].u.buffer.type = TEXT;
464      * actionArgp[0].u.buffer.writable = False;
465      */
466
467     /* XXX - Also, may want to set XtNsensitive to False on pPad->app_shell
468      *       and turn it back on in PrintActionCB() when it receives a
469      *       DtACTION_DONE status */ 
470     /* ----> Invoke the print action */
471     actionID = DtActionInvoke(pPad->app_shell,
472                 "PRINT_DTPAD_TEMPFILE",         /* action */
473                 actionArgp, 2,                  /* action arguments & count */
474                 (char *) NULL,                  /* terminal options */
475                 (char *) NULL,                  /* execution host */
476                 (char *) NULL,                  /* context dir */
477                 False,                          /* no "use indicator" */
478                 PrintActionCB,                  /* action callback */
479                 (XtPointer) pPad);              /* callback client data */
480
481     XtFree(pr_name);
482     XtFree(user_name);
483
484    /*  _DtTurnOffHourGlass(pPad->app_shell);  this is done in PrintActionCB */
485 }
486
487
488
489
490 /************************************************************************
491  * FileDoXpPrint - procedure doing the work of the XpPrint callbacks
492  ************************************************************************/
493 /* ARGSUSED */
494 static void FileDoXpPrint(Editor *pPad, Boolean silent)
495 {
496     PrintJob *pJob;
497
498     DtActionArg *actionArgp = (DtActionArg *) XtCalloc(2,sizeof(DtActionArg));
499     DtActionInvocationID actionID;
500     DtEditorErrorCode errorCode;
501
502     char *pr_name = (char *) NULL, *user_name;
503
504     Boolean addNewlines = pPad->xrdb.wordWrap == True &&
505                           pPad->fileStuff.saveWithNewlines == True;
506
507     _DtTurnOnHourGlass(pPad->app_shell);
508     /* -----> Disallow keyboard, button, motion, window enter/leave & focus
509      *        events till print (dialog) action is done
510      * XtSetSensitive(pPad->app_shell, False);
511      */
512
513     /* -----> Get a place to temporarily write the text */
514     if ((pr_name = GetTempFile()) == (char *)NULL) {
515         _DtTurnOffHourGlass(pPad->app_shell);
516         Warning(pPad, ((char *)
517                 GETMESSAGE(4, 5, "Unable to create a temporary file.")),                XmDIALOG_ERROR);
518         return;
519     }
520
521     /* -----> Write the contents to the temp file */
522     errorCode = DtEditorSaveContentsToFile(
523                         pPad->editor,
524                         pr_name,
525                         True,           /* overwrite existing file */
526                         addNewlines,    /* replace soft line feeds? */
527                         False);         /* don't mark contents as saved */
528     if (errorCode != SUCCESS) {         /* this should never occur */
529         _DtTurnOffHourGlass(pPad->app_shell);
530         PostSaveError(pPad, pr_name, errorCode);
531         return;
532     }
533
534     /* -----> Determine the name the user will see in the Print dialog */
535     if (pPad->ttEditReq.contract &&
536                 (pPad->ttEditReq.docName && *pPad->ttEditReq.docName)) {
537         user_name = strdup(pPad->ttEditReq.docName);
538     } else if (pPad->fileStuff.fileName && *pPad->fileStuff.fileName) {
539         user_name = strdup(pPad->fileStuff.fileName);
540     } else {
541         user_name = strdup(UNNAMED_TITLE_P);
542     }
543
544     /* ----> XPPRINT:  Create and execute a print job. */
545     pJob = PrintJobCreate(user_name, pr_name, silent, pPad);
546     PrintJobExecute(pJob);
547
548     XtFree(pr_name);
549     XtFree(user_name);
550
551    _DtTurnOffHourGlass(pPad->app_shell);
552 }
553
554 /************************************************************************
555  * FileXpPrintCB - callback assigned to "File" menu "Print..." button
556  ************************************************************************/
557 /* ARGSUSED */
558 void
559 FileXpPrintCB(
560         Widget w,
561         caddr_t client_data,
562         caddr_t call_data)
563 {
564     Editor *pPad = (Editor *) client_data;
565     FileDoXpPrint(pPad, FALSE);
566 }
567
568
569 /************************************************************************
570  * FileExitCB - callback assigned to "File" menu "Close" button
571  ************************************************************************/
572 /* ARGSUSED */
573 void
574 FileExitCB(
575         Widget w,
576         caddr_t client_data,
577         caddr_t call_data)
578 {
579     Editor *pPad = (Editor *)client_data;
580
581     if (SaveUnsaved(pPad, FileExitCB)) {
582         /*
583          * If SaveUnsaved() returns True, don't close the window at this
584          * time since either:
585          *
586          * 1) a dialog has been posted which needs to be responded to
587          *    (and pendingFileFunc has been set to FileExitCB so that
588          *    this function will be resumed after the response) or
589          * 2) an error has occurred (in which case we abort the exit operation,
590          *    failing the TTDT_QUIT request if it initiated the exit).
591          */
592         if (pPad->fileStuff.pendingFileFunc != FileExitCB) { /* error occurred */
593             TTfailPendingQuit(pPad);
594         }
595         return;
596     }
597
598     if (pPad->numPendingTasks > 0)
599     {
600         char    *msg;
601
602         msg =
603         GETMESSAGE(14, 20, "Close pending:  waiting for task to terminate ...");
604         SetStatusMessage(pPad, msg);
605
606         if (pPad->fileExitWorkprocID == 0)
607           pPad->fileExitWorkprocID = XtAppAddWorkProc(
608                                         pPad->app_context,
609                                         FileExitWP, pPad);
610     }
611     else
612         FileExitWP((XtPointer) pPad);
613 }
614
615
616 /************************************************************************
617  * FileExitWP - workproc called from FileExitCB
618  ************************************************************************/
619 /* ARGSUSED */
620 static Boolean
621 FileExitWP(XtPointer client_data)
622 {
623     Editor *pPad = (Editor *)client_data;
624     Tt_status status;
625
626     if (pPad->numPendingTasks > 0)
627       return FALSE;
628
629     if (pPad->fileExitWorkprocID != 0)
630     {
631         XtRemoveWorkProc(pPad->fileExitWorkprocID);
632         pPad->fileExitWorkprocID = 0;
633     }
634
635     if (pPad->ttQuitReq.contract) {  /* reply to ToolTalk Quit request */
636         status = tt_message_reply(pPad->ttQuitReq.contract);
637         status = tttk_message_destroy(pPad->ttQuitReq.contract);
638     }
639
640     if (pPad->ttEditReq.contract) {
641         TTmediaReply(pPad);     /* reply/close ToolTalk Edit/Display request */
642     }
643
644     if (pPad->xrdb.standAlone) {
645         exit(pPad->confirmStuff.confirmationStatus);
646     }
647
648     pPad->inUse = False;
649     numActivePads--;
650     UnmanageAllDialogs(pPad);
651     XtSetMappedWhenManaged(pPad->app_shell, False);
652         XmImUnregister(pPad->editor);
653     XtPopdown(pPad->app_shell);
654     XWithdrawWindow(pPad->display, XtWindow(pPad->app_shell),
655                         XDefaultScreen(pPad->display));
656     XFlush(pPad->display);
657
658     /* -----> Send "DONE" notice if dealing with a requestor dtpad */
659 /*     if (!pPad->ttEditReq.contract && pPad->xrdb.blocking) { */
660 /*      char numBuf[10]; */
661 /*      sprintf(numBuf, "%d", pPad->confirmStuff.confirmationStatus); */
662 /*      _DtSendSuccessNotification( */
663 /*                      "*", */
664 /*                      (DtString) NULL, */
665 /*                      (DtString) DTPAD_DONE, */
666 /*                      pPad->blockChannel, numBuf, NULL); */
667 /*     } */
668
669     if (numActivePads == 0 && pPad->xrdb.exitOnLastClose) {
670         exit(pPad->confirmStuff.confirmationStatus);
671     }
672
673     /*
674      * If we're going to remain around, clean up Pad for its next use.
675      * This speeds up opening a cached Pad at the expense of cycles at
676      * close time.  Perception is reality.
677      */
678
679     /* -----> clear ToolTalk message info */
680     TTresetQuitArgs(pPad);
681     pPad->ttEditReq.contract = 0;
682     if (pPad->ttEditReq.msg_id != (char *)NULL) {
683         XtFree(pPad->ttEditReq.msg_id);
684         pPad->ttEditReq.msg_id = (char *)NULL;
685     }
686     if (pPad->ttEditReq.vtype != (char *)NULL) {
687         XtFree(pPad->ttEditReq.vtype);
688         pPad->ttEditReq.vtype = (char *)NULL;
689     }
690     if (pPad->ttEditReq.fileName != (char *)NULL) {
691         XtFree(pPad->ttEditReq.fileName);
692         pPad->ttEditReq.fileName = (char *)NULL;
693     }
694     if (pPad->ttEditReq.docName != (char *)NULL) {
695         XtFree(pPad->ttEditReq.docName);
696         pPad->ttEditReq.docName = (char *)NULL;
697     }
698     if (pPad->ttEditReq.savePattern) {
699         tt_pattern_destroy(pPad->ttEditReq.savePattern);
700         pPad->ttEditReq.savePattern = NULL;
701     }
702
703     if (pPad->dialogTitle != (char *)NULL) {
704         XtFree(pPad->dialogTitle);
705         pPad->dialogTitle = NULL;
706     }
707
708     pPad->saveRestore = False;
709
710     pPad->fileStuff.pendingFileFunc = (void (*)())NULL;
711     pPad->fileStuff.pendingFileHelpFunc = (void (*)())NULL;
712     pPad->fileStuff.fileExists = False;
713     pPad->fileStuff.saveWithNewlines = True;
714     pPad->fileStuff.readOnly = False;
715     if (pPad->fileStuff.fileName != (char *) NULL) {
716         XtFree(pPad->fileStuff.fileName);
717         pPad->fileStuff.fileName = (char *) NULL;
718     }
719     if (pPad->fileStuff.netfile != (char *) NULL) {
720         tt_free(pPad->fileStuff.netfile);
721          pPad->fileStuff.netfile = (char *) NULL;
722     }
723
724     /* -----> Clear contents, undo, find/change, format and message area */
725     DtEditorReset(pPad->editor);
726
727     /* -----> Reset resources to server's initial resource state */
728     RestoreInitialServerResources(pPad);
729
730     /* -----> Set iconic state to false */
731     pPad->iconic = False;
732
733     /* -----> Set app shell geo (pixels), resize hints, position & size hints */
734     SetWindowSize(pPad);
735
736     /* -----> Clear director "seed" in SaveAs FSB */
737     if (pPad->fileStuff.fileWidgets.saveAs.saveAs_form != (Widget)NULL) {
738         Widget textField = XmFileSelectionBoxGetChild(
739                                 pPad->fileStuff.fileWidgets.saveAs.saveAs_form,
740                                 XmDIALOG_TEXT);
741         XmTextFieldSetString(textField, "");
742     }
743
744     return TRUE;
745 }
746
747
748 /************************************************************************
749  * oldFileExitCB - callback assigned to "File" menu "Close" button
750  ************************************************************************/
751 /* ARGSUSED */
752 void
753 oldFileExitCB(
754         Widget w,
755         caddr_t client_data,
756         caddr_t call_data)
757 {
758     Editor *pPad = (Editor *)client_data;
759     Tt_status status;
760
761     if (SaveUnsaved(pPad, FileExitCB)) {
762         /*
763          * If SaveUnsaved() returns True, don't close the window at this
764          * time since either:
765          *
766          * 1) a dialog has been posted which needs to be responded to
767          *    (and pendingFileFunc has been set to FileExitCB so that
768          *    this function will be resumed after the response) or
769          * 2) an error has occurred (in which case we abort the exit operation,
770          *    failing the TTDT_QUIT request if it initiated the exit).
771          */
772         if (pPad->fileStuff.pendingFileFunc != FileExitCB) { /* error occurred */
773             TTfailPendingQuit(pPad);
774         }
775         return;
776     }
777
778     if (pPad->ttQuitReq.contract) {  /* reply to ToolTalk Quit request */
779         status = tt_message_reply(pPad->ttQuitReq.contract);
780         status = tttk_message_destroy(pPad->ttQuitReq.contract);
781     }
782
783     if (pPad->ttEditReq.contract) {
784         TTmediaReply(pPad);     /* reply/close ToolTalk Edit/Display request */
785     }
786
787     if (pPad->xrdb.standAlone) {
788         exit(pPad->confirmStuff.confirmationStatus);
789     }
790
791     pPad->inUse = False;
792     numActivePads--;
793     UnmanageAllDialogs(pPad);
794     XtSetMappedWhenManaged(pPad->app_shell, False);
795         XmImUnregister(pPad->editor);
796     XtPopdown(pPad->app_shell);
797     XWithdrawWindow(pPad->display, XtWindow(pPad->app_shell),
798                         XDefaultScreen(pPad->display));
799     XFlush(pPad->display);
800
801     /* -----> Send "DONE" notice if dealing with a requestor dtpad */
802 /*     if (!pPad->ttEditReq.contract && pPad->xrdb.blocking) { */
803 /*      char numBuf[10]; */
804 /*      sprintf(numBuf, "%d", pPad->confirmStuff.confirmationStatus); */
805 /*      _DtSendSuccessNotification( */
806 /*                      "*", */
807 /*                      (DtString) NULL, */
808 /*                      (DtString) DTPAD_DONE, */
809 /*                      pPad->blockChannel, numBuf, NULL); */
810 /*     } */
811
812     if (numActivePads == 0 && pPad->xrdb.exitOnLastClose) {
813         exit(pPad->confirmStuff.confirmationStatus);
814     }
815
816     /*
817      * If we're going to remain around, clean up Pad for its next use.
818      * This speeds up opening a cached Pad at the expense of cycles at
819      * close time.  Perception is reality.
820      */
821
822     /* -----> clear ToolTalk message info */
823     TTresetQuitArgs(pPad);
824     pPad->ttEditReq.contract = 0;
825     if (pPad->ttEditReq.msg_id != (char *)NULL) {
826         XtFree(pPad->ttEditReq.msg_id);
827         pPad->ttEditReq.msg_id = (char *)NULL;
828     }
829     if (pPad->ttEditReq.vtype != (char *)NULL) {
830         XtFree(pPad->ttEditReq.vtype);
831         pPad->ttEditReq.vtype = (char *)NULL;
832     }
833     if (pPad->ttEditReq.fileName != (char *)NULL) {
834         XtFree(pPad->ttEditReq.fileName);
835         pPad->ttEditReq.fileName = (char *)NULL;
836     }
837     if (pPad->ttEditReq.docName != (char *)NULL) {
838         XtFree(pPad->ttEditReq.docName);
839         pPad->ttEditReq.docName = (char *)NULL;
840     }
841     if (pPad->ttEditReq.savePattern) {
842         tt_pattern_destroy(pPad->ttEditReq.savePattern);
843         pPad->ttEditReq.savePattern = NULL;
844     }
845
846     if (pPad->dialogTitle != (char *)NULL) {
847         XtFree(pPad->dialogTitle);
848     }
849
850     pPad->saveRestore = False;
851
852     pPad->fileStuff.pendingFileFunc = (void (*)())NULL;
853     pPad->fileStuff.pendingFileHelpFunc = (void (*)())NULL;
854     pPad->fileStuff.fileExists = False;
855     pPad->fileStuff.saveWithNewlines = True;
856     pPad->fileStuff.readOnly = False;
857     if (pPad->fileStuff.fileName != (char *) NULL) {
858         XtFree(pPad->fileStuff.fileName);
859         pPad->fileStuff.fileName = (char *) NULL;
860     }
861     if (pPad->fileStuff.netfile != (char *) NULL) {
862         tt_free(pPad->fileStuff.netfile);
863          pPad->fileStuff.netfile = (char *) NULL;
864     }
865
866     /* -----> Clear contents, undo, find/change, format and message area */
867     DtEditorReset(pPad->editor);
868
869     /* -----> Reset resources to server's initial resource state */
870     RestoreInitialServerResources(pPad);
871
872     /* -----> Set iconic state to false */
873     pPad->iconic = False;
874
875     /* -----> Set app shell geo (pixels), resize hints, position & size hints */
876     SetWindowSize(pPad);
877
878     /* -----> Clear director "seed" in SaveAs FSB */
879     if (pPad->fileStuff.fileWidgets.saveAs.saveAs_form != (Widget)NULL) {
880         Widget textField = XmFileSelectionBoxGetChild(
881                                 pPad->fileStuff.fileWidgets.saveAs.saveAs_form,
882                                 XmDIALOG_TEXT);
883         XmTextFieldSetString(textField, "");
884     }
885 }
886
887
888 /************************************************************************
889  * NoSaveCB - callback associated with the [No] button in the "Save changes
890  *      to <file>?" PromptDialog created by CreateSaveWarning().
891  ************************************************************************/
892 void
893 NoSaveCB(
894         Widget w,
895         caddr_t client_data,
896         caddr_t call_data )
897 {
898     Editor *pPad = (Editor *)client_data;
899     void (*pFunc)();
900
901     XtUnmanageChild(pPad->fileStuff.fileWidgets.select.save_warning);
902
903
904     if ((pFunc = pPad->fileStuff.pendingFileFunc) != (void(*)()) NULL)  {
905         /* -----> don't clear the pending function if it calls SaveUnsaved() */
906         if (pPad->fileStuff.pendingFileFunc != FileNewCB &&
907           pPad->fileStuff.pendingFileFunc != FileOpenCB &&
908           pPad->fileStuff.pendingFileFunc != FileExitCB) {
909             pPad->fileStuff.pendingFileFunc = (void(*)()) NULL;
910         }
911         if (pFunc != FileSaveCB) {
912             (*pFunc)(w, client_data, call_data);
913         }
914     }
915 }
916
917
918 /************************************************************************
919  * CancelFileSelectCB - 
920  ************************************************************************/
921 /* ARGSUSED */
922 void
923 CancelFileSelectCB(
924         Widget w,
925         caddr_t client_data,
926         caddr_t call_data )
927 {
928     Editor *pPad = (Editor *)client_data;
929
930     pPad->fileStuff.pendingFileFunc = (void(*)()) NULL;
931     pPad->fileStuff.pendingFileHelpFunc = (void(*)()) NULL;
932
933     /* popdown the file selection box */
934     XtUnmanageChild (w);
935     _DtTurnOffHourGlass(w);
936     _DtTurnOffHourGlass(pPad->app_shell);
937 }
938
939
940 /************************************************************************
941  * FileOpenOkCB - saves the name of a file to be opened and its directory,
942  *      and then loads its contents into the DtEditor widget.
943  *
944  *      This callback is assigned to the "Ok" button of the File
945  *      Selection Box displayed by the callback, FileOpenCB() assigned
946  *      to the "File" menu "Open" button.
947  ************************************************************************/
948 static void
949 FileOpenOkCB(
950         Widget w,
951         caddr_t client_data,
952         caddr_t call_data )
953 {
954     Editor      *pPad = (Editor *)client_data;
955     FileStuff   *pStuff = &pPad->fileStuff;
956     XmFileSelectionBoxCallbackStruct *cb = (XmFileSelectionBoxCallbackStruct *)
957                                            call_data;
958     char *name = (char *) XtMalloc( sizeof(char) * cb->length + 1 );
959     name[0] ='\0';
960
961     _DtTurnOnHourGlass(pPad->app_shell);
962     _DtTurnOnHourGlass(w);
963
964     if (pPad->ttEditReq.contract && pPad->ttEditReq.op != TTME_INSTANTIATE) {
965         TTmediaReply(pPad);     /* reply/close ToolTalk media request */
966     }
967
968     /* -----> Get the name of the directory and file.
969      * XXX - Eventually, it makes sense to store the name/etc. as an XmString
970      * rather than convert everything to a string.  This will mean
971      * changing the pPad.fileName type.
972      * Additionally, we can get quit saving the text field ID and
973      * deal only with the FSB. */
974
975     name = (char *) _XmStringUngenerate(cb->value, NULL,
976                                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
977
978     if (pStuff->fileName != (char *)NULL) {
979         XtFree(pStuff->fileName);
980     }
981     pStuff->fileName = name;
982     ExtractAndStoreDir(pPad, name, OPEN); /* store pPad->fileStuff.pathDir */
983
984     LoadFile(pPad, NULL);               /* this is always successful */
985     ChangeMainWindowTitle(pPad);
986
987     CancelFileSelectCB(w, client_data, call_data);
988 }
989
990
991 /************************************************************************
992  * IncludeFile - obtains the name of a file to include (via a Xm FSB),
993  *      parses the name and then
994  *      inserts the file contents into the Dt Editor Widget (via LoadFile).
995  *
996  *      This callback is assigned to the "Ok" button of the
997  *      File Selection Box displayed by the callback,
998  *      FileIncludeCB() assigned to the "File" menu "Include" button.
999  ************************************************************************/
1000 static void
1001 IncludeFile(
1002         Widget w,
1003         caddr_t client_data,
1004         caddr_t call_data )
1005 {
1006     Editor      *pPad = (Editor *)client_data;
1007     XmFileSelectionBoxCallbackStruct *cb = (XmFileSelectionBoxCallbackStruct *)
1008                                            call_data;
1009     char *name = (char *) XtMalloc( sizeof(char) * cb->length + 1 );
1010     name[0] ='\0';
1011
1012     _DtTurnOnHourGlass(pPad->app_shell);
1013     _DtTurnOnHourGlass(w);
1014
1015     /*
1016      *  Get the name of the file
1017      * ******
1018      * Eventually, it makes sense to store the name/etc. as an XmString
1019      * rather than convert everything to a string.  This will mean
1020      * changing the pPad.fileName type.
1021      * Additionally, we can get quit saving the text field ID and
1022      * deal only with the FSB.
1023      */
1024
1025     name = (char *) _XmStringUngenerate(cb->value, NULL,
1026                                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
1027
1028     ExtractAndStoreDir(pPad, name, INCLUDE); /* store pPad->fileStuff.pathDir */
1029
1030     LoadFile(pPad, name);
1031     ChangeMainWindowTitle(pPad);
1032     CancelFileSelectCB(w, client_data, call_data);
1033     if (name != (char *)NULL)
1034         XtFree(name);
1035 }
1036
1037
1038 /************************************************************************
1039  * SaveUnsaved - allows unsaved changes to be saved to the current file
1040  *      or buffer.  If the AskIfSave dialog is posted, sets the global
1041  *      pendingFileFunc to the callingFunc so that the calling function
1042  *      can be reentered to finish its processing.
1043  *
1044  *      Returns True if the calling function should not continue due to:
1045  *
1046  *      1) some error condition (e.g. the file couldn't be saved), or
1047  *      2) a dialog has been posted which needs to be responded to
1048  *         (pPad->fileStuff.pendingFileFunc will be set to the calling
1049  *         function which may again be executed via a callback set on
1050  *         the posted dialog)
1051  *
1052  ************************************************************************/
1053 static Boolean
1054 SaveUnsaved(
1055         Editor* pPad,
1056         void (*callingFunc)() )
1057 {
1058     Boolean addNewlines;
1059     Tt_message m;
1060
1061     /*
1062      * If there are unsaved changes, ask the user if they wish to
1063      * write them out.  If saveOnClose is True, then just write it.
1064      */
1065     if (DtEditorCheckForUnsavedChanges(pPad->editor)) {
1066
1067         /* -----> If handling a "silent" TTDT_QUIT request, don't AskIfSave
1068          *        and don't save any unsaved changes (TTDT_SAVE does this) */
1069         if (callingFunc == FileExitCB && 
1070           pPad->ttQuitReq.contract && pPad->ttQuitReq.silent) {
1071             if (pPad->ttQuitReq.force) {
1072                 return False;   /* close edit window */
1073             } else {
1074                 return True;    /* don't close edit window */
1075             }
1076         }
1077
1078         pPad->ttEditReq.returnBufContents = True;
1079
1080         if ((pPad->xrdb.saveOnClose) && 
1081                 (pPad->fileStuff.fileName && *pPad->fileStuff.fileName)) {
1082             DtEditorErrorCode errorCode;
1083             addNewlines = pPad->xrdb.wordWrap == True &&
1084                                   pPad->fileStuff.saveWithNewlines == True;
1085             _DtTurnOnHourGlass(pPad->app_shell);
1086             errorCode = DtEditorSaveContentsToFile(
1087                         pPad->editor,
1088                         pPad->fileStuff.fileName,
1089                         True,                   /* overwrite existing file */
1090                         addNewlines,            /* replace soft line feeds? */
1091                         True);                  /* mark contents as saved */
1092             _DtTurnOffHourGlass(pPad->app_shell);
1093             if (errorCode != SUCCESS) {
1094                 PostSaveError(pPad, pPad->fileStuff.fileName, errorCode);
1095                 if (callingFunc == FileExitCB) {
1096                     /* Set saveOnClose to False to force user to explicitly
1097                      * choose to not save changes in order to exit. */
1098                     pPad->xrdb.saveOnClose = False;
1099                 }
1100                 pPad->fileStuff.pendingFileFunc = (void(*)()) NULL;
1101                 return True;    /* don't finish calling func */
1102             } else {
1103                 if (pPad->ttEditReq.contract) {
1104                     /* ZZZ -----> Create and send Saved notice */
1105                     m = ttdt_file_notice(
1106                         pPad->ttEditReq.contract,       /* context */
1107                         TTDT_SAVED,                     /* op */
1108                         TT_SESSION,                     /* Tt_scope */
1109                         pPad->fileStuff.fileName,       /* msg file name */
1110                         True);                          /* send & destroy */
1111                 }
1112             }
1113         } else {
1114             if (callingFunc == pPad->fileStuff.pendingFileFunc) {
1115                 /* We've already did AskIfSave but the user responded
1116                  * "No" so lets not keep asking (NoSaveCB does not clear
1117                  * pPad->fileStuff.pendingFileFunc). */
1118                 pPad->fileStuff.pendingFileFunc = (void(*)()) NULL;
1119                 pPad->ttEditReq.returnBufContents = False;
1120             } else {
1121                 /* AskIfSave assigns either FileSaveAsCB or FileSaveCB to the
1122                  * the o.k. dialog button that it posts.  These callbacks
1123                  * execute pPad->fileStuff.pendingFileFunc when done. */
1124                 pPad->fileStuff.pendingFileFunc = callingFunc;
1125                 AskIfSave(pPad);
1126                 return True;    /* don't finish calling func */
1127             }
1128         }
1129     } else {    /* no unsaved contents */
1130         pPad->ttEditReq.returnBufContents = False;
1131     }
1132
1133     return False;       /* finish calling funct */
1134 }
1135
1136
1137 /************************************************************************
1138  * SaveNewLinesCB - 
1139  ************************************************************************/
1140 /* ARGSUSED */
1141 void 
1142 SaveNewLinesCB( 
1143         Widget w,
1144         XtPointer client_data,
1145         XtPointer call_data) 
1146 {
1147     Editor *pPad = (Editor *)client_data;
1148
1149     if (w == pPad->fileStuff.fileWidgets.saveAs.toggleWidgets.with_newl ||
1150         w == pPad->fileStuff.fileWidgets.select.toggleWidgets.with_newl)
1151         pPad->fileStuff.saveWithNewlines = True;
1152     else
1153         pPad->fileStuff.saveWithNewlines = False;
1154 }
1155
1156
1157 /************************************************************************
1158  * SaveAsOkCB - save the file
1159  ************************************************************************/
1160 void
1161 SaveAsOkCB(
1162         Widget w,
1163         caddr_t client_data,
1164         caddr_t call_data )
1165 {
1166     Editor *pPad = (Editor *)client_data;
1167     SaveAs *pSaveAs = &pPad->fileStuff.fileWidgets.saveAs;
1168     void (*pFunc)();
1169     Widget textField = XmFileSelectionBoxGetChild(
1170                     pPad->fileStuff.fileWidgets.saveAs.saveAs_form,
1171                     XmDIALOG_TEXT);
1172     DtEditorErrorCode errorCode;
1173     Tt_message m;
1174     Boolean addNewlines = pPad->xrdb.wordWrap == True &&
1175                           pPad->fileStuff.saveWithNewlines == True;
1176     Boolean overWrite, markSaved;
1177     XmFileSelectionBoxCallbackStruct *cb = (XmFileSelectionBoxCallbackStruct *)
1178                                            call_data;
1179     char *name = (char *) XtMalloc( sizeof(char) * cb->length + 1 );
1180     name[0] ='\0';
1181
1182     _DtTurnOnHourGlass(pPad->app_shell);
1183     _DtTurnOnHourGlass(pSaveAs->saveAs_form);
1184
1185     /* -----> Get the "save as" file name */
1186
1187     name = (char *) _XmStringUngenerate(cb->value, NULL,
1188                                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
1189
1190     pPad->fileStuff.savingName = name;
1191     ExtractAndStoreDir(pPad, name, OPEN);  /* store pPad->fileStuff.pathDir */
1192
1193     /*
1194      * Normally, we would first try writing without overwriting the file
1195      * in which case we would get an error if the file pre-exists and we
1196      * would post a dialog asking the user if they wished to overwrite it.
1197      * However, if the name of the file to save is the same as the file
1198      * being edited, the user opened the file and knows that it exists.
1199      * In this case we would overwrite it without presenting the overwrite
1200      * option dialog.
1201      */
1202     if (strcmp(pPad->fileStuff.fileName, pPad->fileStuff.savingName) == 0) {
1203         overWrite = True;                       /* overwrite */
1204     } else {
1205         overWrite = False;                      /* don't overwrite yet */
1206     }
1207
1208     /* -----> Don't mark the current contents as saved if saved to a
1209      *        file different than the (to be) current file */
1210     if (! pPad->xrdb.nameChange &&
1211       pPad->fileStuff.fileName &&   /* allow for -noNameChange w/o a fileName */
1212       ! overWrite) {
1213         markSaved = False;
1214     } else {
1215         markSaved = True;
1216     }
1217
1218     errorCode = DtEditorSaveContentsToFile(
1219                         pPad->editor,
1220                         pPad->fileStuff.savingName,
1221                         overWrite,
1222                         addNewlines,            /* replace soft line feeds? */
1223                         markSaved);             /* mark contents as saved? */
1224     if (errorCode == DtEDITOR_WRITABLE_FILE) { /* file exists & not overwriting */
1225         PostAlreadyExistsDlg(pPad);     /* save handled in AlrdyExistsOkCB */
1226         XtUnmanageChild (pSaveAs->saveAs_form);
1227         _DtTurnOffHourGlass(pSaveAs->saveAs_form);
1228         _DtTurnOffHourGlass(pPad->app_shell);
1229         return;
1230     }
1231     if (errorCode != SUCCESS) {
1232         PostSaveError(pPad, pPad->fileStuff.savingName, errorCode);
1233         XtFree(pPad->fileStuff.savingName);
1234         pPad->fileStuff.savingName = (char *)NULL;
1235         pPad->fileStuff.pendingFileFunc = (void(*)()) NULL;
1236     } else {
1237         if (pPad->ttEditReq.contract) {
1238             /* ZZZ -----> Create and send Saved notice */
1239             m = ttdt_file_notice(
1240                         pPad->ttEditReq.contract,       /* context */
1241                         TTDT_SAVED,                     /* op */
1242                         TT_SESSION,                     /* Tt_scope */
1243                         pPad->fileStuff.savingName,     /* msg file name */
1244                         True);                          /* send & destroy */
1245             
1246         }
1247         if (pPad->xrdb.nameChange == True) {
1248             if (pPad->ttEditReq.contract && pPad->ttEditReq.op != TTME_INSTANTIATE) {
1249                 pPad->ttEditReq.returnBufContents = False;  /* drop chgs w/o notice */
1250                 TTmediaReply(pPad);     /* reply/close ToolTalk media request */
1251             }
1252             XtFree(pPad->fileStuff.fileName);
1253             pPad->fileStuff.fileName = pPad->fileStuff.savingName;
1254             ChangeMainWindowTitle(pPad);
1255         }
1256     }
1257
1258     pPad->nodo = TRUE;
1259     XtUnmanageChild (pSaveAs->saveAs_form);
1260     _DtTurnOffHourGlass(pSaveAs->saveAs_form);
1261     _DtTurnOffHourGlass(pPad->app_shell);
1262     if ((pFunc = pPad->fileStuff.pendingFileFunc) != (void (*)())NULL)  {
1263         pPad->fileStuff.pendingFileFunc = (void(*)()) NULL;
1264         (*pFunc)(w, client_data, call_data);
1265     }
1266 }
1267
1268
1269 /************************************************************************
1270  * AlrdyExistsOkCB - the ok callback for a saveAs of a file which already
1271  *      exists.  Specifically, this routine:
1272  *
1273  *      - saves the current text to the file specified by
1274  *        pPad->fileStuff.savingName
1275  *      - if appropriate, resets the name of the current file
1276  *        (pPad->fileStuff.fileName) to pPad->fileStuff.savingName and
1277  *        frees pPad->fileStuff.savingName
1278  *      - executes pPad->fileStuff.pendingFileFunc if specified
1279  
1280  ************************************************************************/
1281 void
1282 AlrdyExistsOkCB(
1283         Widget w,
1284         caddr_t client_data,
1285         caddr_t call_data )
1286 {
1287     Editor *pPad = (Editor *)client_data;
1288     void (*pFunc)();
1289     DtEditorErrorCode errorCode;
1290     Boolean addNewlines = pPad->xrdb.wordWrap == True &&
1291                           pPad->fileStuff.saveWithNewlines == True;
1292     Boolean markSaved;
1293     Tt_message m;
1294
1295     _DtTurnOnHourGlass(pPad->app_shell);
1296     _DtTurnOnHourGlass(w);
1297
1298     /* -----> Don't mark the current contents as saved if saved to a
1299      *        file different than the (to be) current file */
1300     if (! pPad->xrdb.nameChange && 
1301       pPad->fileStuff.fileName &&   /* allow for -noNameChange w/o a fileName */
1302       (strcmp(pPad->fileStuff.fileName, pPad->fileStuff.savingName) != 0)) {
1303         markSaved = False;
1304     } else {
1305         markSaved = True;
1306     }
1307
1308     errorCode = DtEditorSaveContentsToFile(
1309                         pPad->editor,
1310                         pPad->fileStuff.savingName,
1311                         True,                   /* overwrite existing file */
1312                         addNewlines,            /* replace soft line feeds? */
1313                         markSaved);             /* mark contents as saved? */
1314
1315     XtUnmanageChild (w);
1316     _DtTurnOffHourGlass(w);
1317     _DtTurnOffHourGlass(pPad->app_shell);
1318
1319     if (errorCode == SUCCESS) {
1320         if (pPad->ttEditReq.contract) {
1321             /* ZZZ -----> Create and send Saved notice */
1322             m = ttdt_file_notice(
1323                         pPad->ttEditReq.contract,       /* context */
1324                         TTDT_SAVED,                     /* op */
1325                         TT_SESSION,                     /* Tt_scope */
1326                         pPad->fileStuff.savingName,     /* msg file name */
1327                         True);                          /* send & destroy */
1328         }
1329         if (pPad->xrdb.nameChange == True) {
1330             if (pPad->ttEditReq.contract && pPad->ttEditReq.op != TTME_INSTANTIATE) {
1331                 pPad->ttEditReq.returnBufContents = False;  /* drop chgs w/o notice */
1332                 TTmediaReply(pPad);     /* reply/close ToolTalk media request */
1333             }
1334             XtFree(pPad->fileStuff.fileName);
1335             pPad->fileStuff.fileName = pPad->fileStuff.savingName;
1336             ChangeMainWindowTitle(pPad);
1337         }
1338     } else {
1339         PostSaveError(pPad, pPad->fileStuff.savingName, errorCode);
1340     }
1341     if (pPad->fileStuff.savingName != pPad->fileStuff.fileName)
1342         XtFree(pPad->fileStuff.savingName);
1343     pPad->fileStuff.savingName = (char *)NULL;
1344
1345     if ((pFunc = pPad->fileStuff.pendingFileFunc) != (void (*)())NULL)  {
1346         pPad->fileStuff.pendingFileFunc = (void(*)()) NULL;
1347         (*pFunc)(w, client_data, call_data);
1348     }
1349 }
1350
1351
1352 /************************************************************************
1353  * SaveAsCancelCB - Unmanage the SaveAs dialog
1354  ************************************************************************/
1355 /* ARGSUSED */
1356 void
1357 SaveAsCancelCB(
1358         Widget w,
1359         caddr_t client_data,
1360         caddr_t call_data )
1361 {
1362     Editor *pPad = (Editor *) client_data;
1363
1364     XtUnmanageChild ((Widget) pPad->fileStuff.fileWidgets.saveAs.saveAs_form);
1365     pPad->fileStuff.pendingFileFunc = (void (*)())NULL;
1366     pPad->fileStuff.pendingFileHelpFunc = (void (*)())NULL;
1367 }
1368
1369
1370 /************************************************************************
1371  * AlrdyExistsCancelCB - Unmanage the AlreadyExists dialog
1372  ************************************************************************/
1373 /* ARGSUSED */
1374 void
1375 AlrdyExistsCancelCB(
1376         Widget w,
1377         caddr_t client_data,
1378         caddr_t call_data )
1379 {
1380     Editor *pPad = (Editor *)client_data;
1381     XtUnmanageChild ((Widget) pPad->fileStuff.fileWidgets.saveAs.alrdy_exist);
1382     XtFree(pPad->fileStuff.savingName);
1383     pPad->fileStuff.savingName = (char *) NULL;
1384     pPad->fileStuff.pendingFileFunc = (void (*)())NULL;
1385     pPad->fileStuff.pendingFileHelpFunc = (void (*)())NULL;
1386 }
1387
1388
1389 /************************************************************************
1390  * AskIfSaveCancelCB - 
1391  ************************************************************************/
1392 /* ARGSUSED */
1393 void
1394 AskIfSaveCancelCB(
1395         Widget w,
1396         caddr_t client_data,
1397         caddr_t call_data )
1398 {
1399     Editor *pPad = (Editor *)client_data;
1400
1401     XtUnmanageChild ((Widget) pPad->fileStuff.fileWidgets.select.save_warning);
1402     if (pPad->fileStuff.pendingFileFunc == FileExitCB) {
1403         TTfailPendingQuit(pPad);
1404     }
1405     pPad->fileStuff.pendingFileFunc = (void (*)())NULL;
1406     pPad->fileStuff.pendingFileHelpFunc = (void (*)())NULL;
1407 }
1408