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