55a61c898cffad05043110f6ab172fbc26d75b6d
[oweals/cde.git] / cde / programs / dtpad / fileDlg.c
1 /* $TOG: fileDlg.c /main/8 1999/09/15 15:15:56 mgreess $ */
2 /**********************************<+>*************************************
3 ***************************************************************************
4 **
5 **  File:        fileDlg.c
6 **
7 **  Project:     DT dtpad, a memo maker type editor based on the Dt Editor
8 **               widget.
9 **
10 **  Description:  Routines which manipulate the dialogs associated with
11 **                operations in the File menu.
12 **  -----------
13 **
14 *******************************************************************
15 **  (c) Copyright Hewlett-Packard Company, 1990, 1991, 1992.  All rights are
16 **  reserved.  Copying or other reproduction of this program
17 **  except for archival purposes is prohibited without prior
18 **  written consent of Hewlett-Packard Company.
19 ********************************************************************
20 **
21 *******************************************************************
22 **  (c) Copyright 1993, 1994 Hewlett-Packard Company
23 **  (c) Copyright 1993, 1994 International Business Machines Corp.
24 **  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
25 **  (c) Copyright 1993, 1994 Novell, Inc.
26 ********************************************************************
27 **
28 **
29 **************************************************************************
30 **********************************<+>*************************************/
31 #include "dtpad.h"
32 #include <Xm/DialogS.h>
33 #include <Xm/Form.h>
34 #include <Xm/FileSB.h>
35 #include <Xm/Separator.h>
36 #include <Xm/MwmUtil.h>
37 #include <Dt/HourGlass.h>
38
39 #define MAX_DIR_PATH_LEN    1024
40
41 #define SAVE_CH ((char *)GETMESSAGE(5, 1, "Save changes to %s?"))
42 #define SAVE_CH_NONAME ((char *)GETMESSAGE(5, 2, "The current file has no name.\nDo you want to save it?"))
43 #define SAVE_CH_BUF ((char *)GETMESSAGE(5, 40, "Save changes?"))
44 #define SAVE_CH_DOC ((char *)GETMESSAGE(5, 41, "Save changes to \"%s?\""))
45 #define SAVE_DROP  ((char *)GETMESSAGE(5, 3, "Do you want to save the current copy of %s\nbefore you Edit %s?"))
46 #define MSG1 ((char *)GETMESSAGE(5, 5, "The file %s already exists.\nDo you want to over write that file\nwith the contents within this edit session? "))
47
48
49 /************************************************************************
50  *                      Forward Declarations
51  ************************************************************************/
52 static void CreateFileSelectionDialog(
53         Editor *pPad );
54 static void CreateSaveWarning(
55         Editor *pPad );
56
57
58 /************************************************************************
59  *  PostAlreadyExistsDlg - Setup and post dialog to determine whether
60  *      the user wishes to clobber existing file or try saving it under a
61  *      new name.
62  *
63  *      Inputs: pPad->fileStuff.savingName - name of file to save
64  ************************************************************************/
65 void
66 PostAlreadyExistsDlg(
67         Editor *pPad)
68 {
69     Arg args[10];
70     int n;
71     char *tmpMess;
72     XmString tmpMessStr;
73     SaveAs *pSaveAs = &pPad->fileStuff.fileWidgets.saveAs;
74
75     /* create the dialog if it is the first time */
76     if (!pSaveAs->alrdy_exist)
77     {
78         Pixel foreground;       /* dialog foreground */
79         Pixel background;       /* dialog background */
80         Pixmap pixmap;          /* dialog pixmap */
81         XmString tempStr, tempStr2;
82         char buf[256];
83
84         n = 0;
85         strcpy(buf, DialogTitle(pPad));
86         strcat(buf, (char *)GETMESSAGE(5, 6, "Warning"));
87         tempStr = XmStringCreateLocalized(buf);
88         XtSetArg(args[n], XmNdialogTitle, tempStr); n++;
89         XtSetArg (args[n], XmNokLabelString,
90                   XmStringCreateLocalized((String) _DtOkString));  n++;
91         tempStr2 = XmStringCreateLocalized((char *)GETMESSAGE(2, 1, "Help"));
92         XtSetArg (args[n], XmNhelpLabelString, tempStr2); n++;
93         XtSetArg (args[n], XmNcancelLabelString,
94                   XmStringCreateLocalized((String) _DtCancelString));  n++;
95         pSaveAs->alrdy_exist = XmCreateMessageDialog (pPad->app_shell, "Warn",
96                                                       args, n);
97         XmStringFree(tempStr);
98         XmStringFree(tempStr2);
99         n=0;
100         XtSetArg(args[n], XmNmwmInputMode,
101                  MWM_INPUT_PRIMARY_APPLICATION_MODAL);n++;
102         XtSetValues(XtParent(pSaveAs->alrdy_exist), args, n);
103
104
105         n = 0;
106         XtSetArg(args[n], XmNforeground, &foreground); n++;
107         XtSetArg(args[n], XmNbackground, &background); n++;
108         XtGetValues(pSaveAs->alrdy_exist, args, n);
109
110         n = 0;
111         pixmap = XmGetPixmap(XtScreen(pSaveAs->alrdy_exist), "warn_image",
112                                         foreground, background);
113         XtSetArg(args[n], XmNsymbolPixmap, pixmap); n++;
114         XtSetValues(pSaveAs->alrdy_exist, args, n);
115
116         XtAddCallback (pSaveAs->alrdy_exist, XmNokCallback,
117                         (XtCallbackProc) AlrdyExistsOkCB,
118                         (XtPointer) pPad);
119         XtAddCallback (pSaveAs->alrdy_exist, XmNcancelCallback,
120                         (XtCallbackProc) AlrdyExistsCancelCB,
121                         (XtPointer) pPad);
122         XtAddCallback (pSaveAs->alrdy_exist, XmNhelpCallback,
123                         (XtCallbackProc) HelpFileAlreadyExistsCB,
124                         (XtPointer) pPad);
125
126         XtRealizeWidget (pSaveAs->alrdy_exist);
127     }
128
129     tmpMess =
130         (char *)XtMalloc(strlen(MSG1) + strlen(pPad->fileStuff.savingName) + 1);
131     sprintf(tmpMess, MSG1, pPad->fileStuff.savingName);
132     tmpMessStr = XmStringCreateLocalized(tmpMess);
133     n = 0;
134     XtSetArg(args[n], XmNmessageString, tmpMessStr); n++;
135     XtSetValues(pSaveAs->alrdy_exist, args, n);
136     XtFree(tmpMess);
137     XmStringFree(tmpMessStr);
138
139     XtManageChild (pSaveAs->alrdy_exist);
140
141 }
142
143
144 /************************************************************************
145  * SetSaveAsDirAndFile - Seeds the directory and file name fields of
146  *      the SaveAs File Selection Box.
147  *
148  *    The possibilities for an initial directory are:
149  *
150  *      1.  The user's previously entered path.
151  *      2.  We're editing a file, so use its path.
152  *      3.  Use the CWD of our process.
153  *
154  ************************************************************************/
155 void
156 SetSaveAsDirAndFile(Editor *pPad)
157 {
158     char dirbuf[MAX_DIR_PATH_LEN], *currentVal, *directoryVal,
159          *lastSlash, *pColon;
160     int firstSelect = -1, lastSelect = -1;
161     Widget textField;
162     Arg args[5];
163     register int n;
164     XmString dirString;
165     dirbuf[0] = (char) '\0';
166
167     /* -----> Get the file name field from the previous SaveAs FSB.
168      *        XXX - Should use GetValues to get XmNdirSpec. */
169     textField = XmFileSelectionBoxGetChild(
170                         pPad->fileStuff.fileWidgets.saveAs.saveAs_form,
171                         XmDIALOG_TEXT);
172     currentVal = XmTextFieldGetString(textField);
173
174     /* -----> If the user previously entered a file name via the SaveAs FSB,
175      *        use its values. */
176     if (currentVal != (char *)NULL && *currentVal != (char)'\0') {
177         /* -----> If the file name begins with '/', it has a pathname and we
178          *        can use it for the initial directory */
179         if ( currentVal[0] == '/' ) {
180             strcpy(dirbuf, currentVal);
181             /* Trim off everything behind the last slash */
182             if ((lastSlash = MbStrrchr(dirbuf, '/')) != (char *)NULL) {
183                 *(lastSlash + 1) = (char)'\0';
184             }
185         } else {
186             /* -----> The filename does not have a directory, so use the value
187              *        from the directory field. */
188             n=0;
189             XtSetArg( args[n], XmNdirectory, &dirString ); n++;
190             XtGetValues(pPad->fileStuff.fileWidgets.saveAs.saveAs_form, args, n);
191             directoryVal = (char *) XtMalloc( sizeof(char) *
192                                          (MAX_DIR_PATH_LEN + 1) );
193             XmStringGetLtoR( dirString, XmFONTLIST_DEFAULT_TAG, &directoryVal );
194             strcpy(dirbuf, directoryVal);
195             XmStringFree(dirString);
196             XtFree( directoryVal );
197         }
198         XtFree (currentVal);
199     /* -----> No file name was not previously entered via a SaveAs FSB so use
200      *        other defaults. */
201     } else {
202         if (pPad->fileStuff.pathDir[0] != (char)'\0')
203             strcpy(dirbuf, pPad->fileStuff.pathDir);
204         /* -----> make sure dir ends in '/' */
205         if (dirbuf[0] != (char )'\0') {
206             if (dirbuf[strlen(dirbuf) - 1] != (char)'/')
207                 strcat(dirbuf, "/");
208         } else {
209             getcwd(dirbuf, MAX_DIR_PATH_LEN - 16);
210             strcat(dirbuf, "/");
211         }
212     }
213
214     /* -----> set the SaveAs FSB directory mask */
215     firstSelect = strlen(dirbuf);
216     strcat(dirbuf, "[^.]*");
217     dirString = XmStringCreateLocalized(dirbuf);
218     n = 0;
219     XtSetArg(args[n], XmNdirMask, dirString); n++;
220     XtSetValues(pPad->fileStuff.fileWidgets.saveAs.saveAs_form, args, n);
221     XmStringFree(dirString);
222     dirbuf[firstSelect] = (char)'\0';
223
224     /* -----> set the default file name and select it */
225     strcpy(dirbuf, GETMESSAGE(5, 21, "UNTITLED"));
226     lastSelect = strlen(dirbuf);
227     XmTextFieldSetString(textField, dirbuf);
228     XmTextFieldSetSelection(textField, 0, lastSelect, CurrentTime);
229 }
230
231
232 /************************************************************************
233  * CreateNewLineToggles - used by CreateSaveAsDialog and CreateSaveWarning
234  *      to create a radio box within 'parent' with two toggle buttons
235  *      for adding or not adding new lines if word wrap mode is on.
236  ************************************************************************/
237 static void
238 CreateNewLineToggles(
239         Editor *pPad,
240         Widget parent,
241         ToggleWidgets *pToggleWidgets)
242 {
243     Arg args[20];
244     register int n;
245     XmString label_string;
246
247     /* -----> Create Radio Box */
248     n = 0;
249     XtSetArg(args[n], XmNshadowThickness, 0);                   n++;
250     XtSetArg(args[n], XmNtraversalOn, True);                    n++;
251     XtSetArg(args[n], XmNorientation, XmVERTICAL );             n++;
252     pToggleWidgets->newl_radio = XmCreateRadioBox(parent, "radioBox",
253                                                 args, n);
254
255     /* -----> Create the toggle button for adding newlines. */
256     label_string = XmStringCreateLocalized(((char *)GETMESSAGE(5, 44,
257                 "Add newline characters to the end of wrap-to-fit lines.")));
258     n = 0;
259     XtSetArg(args[n], XmNshadowThickness, 0);                   n++;
260     XtSetArg(args[n], XmNlabelString, label_string);            n++;
261     pToggleWidgets->with_newl = XmCreateToggleButtonGadget(
262                                         pToggleWidgets->newl_radio,
263                                         "with_nl", args, n);
264     XmStringFree(label_string);
265     XtAddCallback(pToggleWidgets->with_newl, XmNvalueChangedCallback,
266                         SaveNewLinesCB, (XtPointer) pPad);
267     XtManageChild(pToggleWidgets->with_newl);
268
269     /* -----> Create the toggle button for not adding newlines. */
270     label_string = XmStringCreateLocalized(((char *)GETMESSAGE(5, 45,
271 "Do not add newlines.  Only line breaks created by [Return]\nwill be preserved.")));
272     n = 0;
273     XtSetArg(args[n], XmNshadowThickness, 0);                   n++;
274     XtSetArg(args[n], XmNlabelString, label_string); n++;
275     pToggleWidgets->without_newl = XmCreateToggleButtonGadget(
276                                         pToggleWidgets->newl_radio,
277                                         "without_nl", args, n);
278     XmStringFree(label_string);
279     XtAddCallback(pToggleWidgets->without_newl, XmNvalueChangedCallback,
280                         SaveNewLinesCB, (XtPointer) pPad);
281     XtManageChild(pToggleWidgets->without_newl);
282
283     /* -----> Set the default to add newlines (if wordwrap is on) */
284     pPad->fileStuff.saveWithNewlines = True;
285     XmToggleButtonGadgetSetState(pToggleWidgets->with_newl, True, False);
286
287     /* -----> Display the radio box containing the two toggle buttons only
288      *        if wordwrap is on */
289     if (pPad->xrdb.wordWrap == True)
290         XtManageChild(pToggleWidgets->newl_radio);
291
292 }
293
294
295 /************************************************************************
296  * CreateSaveAsDialog
297  ************************************************************************/
298 void
299 CreateSaveAsDialog(Editor *pPad)
300 {
301     Arg args[20];
302     register int n;
303     XmString label_string;
304     char buf[256];
305     SaveAs *pSaveAs = &pPad->fileStuff.fileWidgets.saveAs;
306
307     _DtTurnOnHourGlass(pPad->app_shell);
308
309     /* -----> Create the FileSelectionDialog */
310     strcpy(buf, DialogTitle(pPad));
311     if (pPad->xrdb.nameChange) {
312         strcat(buf, (char *)GETMESSAGE(5, 7, "Save As"));
313     } else {
314         strcat(buf, (char *)GETMESSAGE(5, 43, "Copy To File"));
315     }
316     label_string = XmStringCreateLocalized(buf);
317     n = 0;
318     XtSetArg(args[n], XmNdialogTitle, label_string); n++;
319     XtSetArg(args[n], XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE);  n++;
320     XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_BORDER | MWM_DECOR_TITLE);
321     n++;
322     XtSetArg (args[n], XmNallowShellResize, False);              n++;
323     pSaveAs->saveAs_form = XmCreateFileSelectionDialog(pPad->app_shell,
324                                                         "save_dialog", args, n);
325     XmStringFree(label_string);
326
327     /* -----> Add the FSB cancel, ok, and help callbacks */
328     XtAddCallback(pSaveAs->saveAs_form,
329                         XmNcancelCallback,
330                         (XtCallbackProc) SaveAsCancelCB,
331                         (XtPointer) pPad);
332     XtAddCallback(pSaveAs->saveAs_form,
333                         XmNokCallback,
334                         (XtCallbackProc) SaveAsOkCB,
335                         (XtPointer) pPad);
336     XtAddCallback(pSaveAs->saveAs_form,
337                         XmNhelpCallback,
338                         (XtCallbackProc)HelpSaveAsDialogCB,
339                         (XtPointer) pPad);
340
341     /* ----->  Don't show the filter stuff when saving
342      *XtUnmanageChild(XmFileSelectionBoxGetChild(pSaveAs->saveAs_form,
343      *                                          XmDIALOG_FILTER_TEXT));
344      *XtUnmanageChild(XmFileSelectionBoxGetChild(pSaveAs->saveAs_form,
345      *                                          XmDIALOG_FILTER_LABEL));
346      */
347
348     /* -----> Set the useAsyncGeo on the shell */
349     n = 0;
350     XtSetArg(args[n], XmNuseAsyncGeometry, True); n++;
351     XtSetValues (pPad->app_shell, args, n);
352
353     /* -----> Set the ok button to the default for the bulletin board.
354      *        This causes the return key from the text widget to be properly
355      *        processed. */
356     XtSetArg(args[0], XmNdefaultButton,
357                 XmFileSelectionBoxGetChild(pSaveAs->saveAs_form,
358                 XmDIALOG_OK_BUTTON));
359     XtSetValues (pSaveAs->saveAs_form, args, 1);
360
361     /* -----> Create a radio box with two toggle buttons for either adding
362      *        or not adding new lines if word wrap mode is on. */
363     CreateNewLineToggles(pPad,
364                         pSaveAs->saveAs_form,           /* parent widget */
365                         &pSaveAs->toggleWidgets);       /* new widgets */
366
367     _DtTurnOffHourGlass(pPad->app_shell);
368 }
369
370
371 /************************************************************************
372  * ExtractAndStoreDir - extracts the directory from the specified
373  *      /dir/filename and stores it in pPad->fileStuff.pathDir.
374  ************************************************************************/
375 void
376 ExtractAndStoreDir(
377         Editor *pPad,
378         char *fileName,
379         short type)
380 {
381     char *pFirstSlash, *pLastSlash;
382
383     pFirstSlash = MbStrchr(fileName, '/');
384     if(type == OPEN) {
385        if (pFirstSlash != (char *)NULL) {
386            pLastSlash = MbStrrchr(fileName, '/');
387            strncpy(pPad->fileStuff.pathDir, pFirstSlash,
388                    pLastSlash - pFirstSlash + 1);
389            pPad->fileStuff.pathDir[pLastSlash - pFirstSlash + 1] = '\0';
390        }
391     }
392     else {
393        if (pFirstSlash != (char *)NULL) {
394            pLastSlash = MbStrrchr(fileName, '/');
395            strncpy(pPad->fileStuff.includePathDir, pFirstSlash,
396                    pLastSlash - pFirstSlash + 1);
397            pPad->fileStuff.includePathDir[pLastSlash - pFirstSlash + 1] = '\0';
398            if(pPad->fileStuff.lastIncludeName != NULL)
399               XtFree(pPad->fileStuff.lastIncludeName);
400            pLastSlash++;
401            pPad->fileStuff.lastIncludeName = XtNewString(pLastSlash);
402        }
403     }
404
405 }
406
407
408 /************************************************************************
409  *  GetFileName - Ask for a file name via an Xm File Selection Box
410  ************************************************************************/
411 void
412 GetFileName(
413         Editor *pPad,
414         XmString title,
415         short type)
416 {
417     char dirbuf[MAX_DIR_PATH_LEN];
418     Arg al[5];
419     int ac;
420     int firstSelect = -1;
421     XmString dirString, tmpStr;
422     Select *pSelect = &pPad->fileStuff.fileWidgets.select;
423     FileStuff *pStuff = &pPad->fileStuff;
424
425     dirbuf[0] = (char) '\0';
426
427     _DtTurnOnHourGlass(pPad->app_shell);
428
429     /* -----> create the FSB if it doesn't exits */
430     if (pSelect->file_dialog == NULL) {
431         CreateFileSelectionDialog(pPad);
432     }
433
434     /* Just in case, it was unmanaged */
435     XtManageChild(pSelect->file_dialog);
436
437     /* -----> set the FSB "ok" and "help" button callbacks */
438     XtRemoveAllCallbacks(pSelect->file_dialog, XmNokCallback);
439     XtAddCallback(pSelect->file_dialog, XmNokCallback,
440                         (XtCallbackProc) pStuff->pendingFileFunc,
441                         (XtPointer)pPad);
442     pStuff->pendingFileFunc = (void(*)())NULL;
443     XtRemoveAllCallbacks(pSelect->file_dialog, XmNhelpCallback);
444     XtAddCallback(pSelect->file_dialog, XmNhelpCallback,
445                         (XtCallbackProc) pStuff->pendingFileHelpFunc,
446                         (XtPointer)pPad);
447     pStuff->pendingFileHelpFunc = (void (*)())NULL;
448
449     /* -----> seed FSB directory from either fileName */
450     if(type == OPEN) {
451        if (pStuff->pathDir[0] == (char)'\0') {
452            if (pStuff->fileName != NULL) {
453                /* set pStuff->pathDir*/
454                ExtractAndStoreDir(pPad, pStuff->fileName, OPEN);
455            }
456            else {
457                if (pStuff->pathDir[0] != (char)'\0')
458                    strcpy(dirbuf, pStuff->pathDir);
459                /* -----> make sure dir ends in '/' */
460                if (dirbuf[0] != (char )'\0') {
461                    if (dirbuf[strlen(dirbuf) - 1] != (char)'/')
462                        strcat(dirbuf, "/");
463                } else {
464                    getcwd(dirbuf, MAX_DIR_PATH_LEN - 16);
465                    strcat(dirbuf, "/");
466                }
467
468                firstSelect = strlen(dirbuf);
469                strcat(dirbuf, "[^.]*");
470                dirString = XmStringCreateLocalized(dirbuf);
471                ac = 0;
472                XtSetArg(al[ac], XmNdirMask, dirString); ac++;
473                XtSetValues(pStuff->fileWidgets.select.file_dialog, al, ac);
474                XmStringFree(dirString);
475            }
476        }
477
478        if (pStuff->pathDir[0] != (char)'\0') {
479            tmpStr = XmStringCreateLocalized(pStuff->pathDir);
480            XtSetArg(al[0], XmNdirectory, tmpStr);
481            XtSetValues(pSelect->file_dialog, al, 1);
482            XmStringFree(tmpStr);
483        }
484     }
485     else {
486        /* -----> seed FSB directory with include dir */
487        if (pStuff->includePathDir[0] == (char)'\0') {
488            if (pStuff->fileName != (char *)NULL) {
489                /* set pStuff->pathDir*/
490                ExtractAndStoreDir(pPad, pStuff->fileName, INCLUDE);
491            }
492        }
493        if (pStuff->includePathDir[0] != (char)'\0') {
494            tmpStr = XmStringCreateLocalized(pStuff->includePathDir);
495            XtSetArg(al[0], XmNdirectory, tmpStr);
496            XtSetValues(pSelect->file_dialog, al, 1);
497            XmStringFree(tmpStr);
498        }
499     }
500
501     /* -----> find the seeded directory */
502     /*XmFileSelectionDoSearch(pSelect->file_dialog, NULL);*/
503
504     /* -----> set the FSB title (as passed in) */
505     XtSetArg(al[0], XmNdialogTitle, title);
506     XtSetValues(pSelect->file_dialog, al, 1);
507
508     /* -----> delete the first entry from the list of dirs
509      * if(!pPad->nodo) {
510      *     XmListDeletePos(pSelect->dir_list, 1);
511      * }
512      */
513     pPad->nodo = False;
514
515     if(type == INCLUDE) {
516        if(pStuff->lastIncludeName != NULL) {
517           tmpStr = XmStringCreateLocalized(pStuff->lastIncludeName);
518           XmListSelectItem(XmFileSelectionBoxGetChild(pSelect->file_dialog,
519                                         XmDIALOG_LIST), tmpStr, False);
520           XtSetArg(al[0], XmNtextString, tmpStr);
521           XtSetValues(pSelect->file_dialog, al, 1);
522           XmStringFree(tmpStr);
523        }
524     }
525
526     /* -----> manage the FSB */
527     XtManageChild (pSelect->file_dialog);
528     XmProcessTraversal(XmFileSelectionBoxGetChild(pSelect->file_dialog,
529                                         XmDIALOG_TEXT), XmTRAVERSE_CURRENT);
530     XSync(pPad->display, 0);
531
532     _DtTurnOffHourGlass(pPad->app_shell);
533 }
534
535
536 /************************************************************************
537  * CreateFileSelectionDialog -
538  ************************************************************************/
539 static void
540 CreateFileSelectionDialog(
541         Editor *pPad )
542 {
543     Arg al[10];             /* arg list */
544     register int ac;        /* arg count */
545     XmString tmpStr;
546     Select *pSelect = &pPad->fileStuff.fileWidgets.select;
547
548     ac = 0;
549     tmpStr = XmStringCreateLocalized((char *)GETMESSAGE(2, 1, "Help"));
550     XtSetArg (al[ac], XmNhelpLabelString, tmpStr);      ac++;
551
552     pSelect->file_dialog = XmCreateFileSelectionDialog(pPad->app_shell,
553                                         "file_sel_dlg", al, ac);
554     XmStringFree(tmpStr);
555
556     XtAddCallback(pSelect->file_dialog, XmNcancelCallback,
557                         (XtCallbackProc) CancelFileSelectCB, (XtPointer)pPad );
558
559     XtRealizeWidget (pSelect->file_dialog);
560     XSync(pPad->display, 0);
561
562 /* XXX
563  *  pSelect->dir_list = FS_DirList(pSelect->file_dialog);
564  */
565
566     pSelect->filter_text = XmFileSelectionBoxGetChild(pSelect->file_dialog,
567                                         XmDIALOG_FILTER_TEXT);
568     pSelect->select_text = XmFileSelectionBoxGetChild(pSelect->file_dialog,
569                                         XmDIALOG_TEXT);
570     pSelect->file_list = XmFileSelectionBoxGetChild(pSelect->file_dialog,
571                                         XmDIALOG_LIST);
572 }
573
574
575 /************************************************************************
576  * CreateSaveWarning - Builds a PromptDialog to ask if the current contents
577  *      are to be saved prior to some operation.  Also used to ask if new
578  *      lines characters are to be inserted when word wrap is on.
579  *
580  *      PromptDialog
581  *          (message)                           (unmanaged)
582  *          (text input region)                 (unmanaged)
583  *          Form                                work area
584  *              RowColumn                       horz orientation
585  *                  LabelGadget                 exclamation symbol
586  *                  LabelGadget                 prompt text
587  *              Separator
588  *              RadioBox                        contains two new line toggles
589  *          (buttons)                           OK, Apply, Cancel, Help
590  *
591  *      The RadioBox is managed only if wordwrap is on.
592  *
593  ************************************************************************/
594 static void
595 CreateSaveWarning(
596         Editor *pPad )
597 {
598     Arg al[10];                 /* arg list */
599     register int ac;            /* arg count */
600     char buf[256];
601     Widget w, kid[5];
602     Pixel foreground, background;
603     Pixmap pixmap;              /* dialog pixmap */
604     XmString tmpStr1, tmpStr2, tmpStr3, tmpStr4, tmpStr5;
605     Select *pSelect = &pPad->fileStuff.fileWidgets.select;
606
607     /* -----> Create a SelectionBox PromptDialog with appropriate title and
608      *        button labels */
609     tmpStr1 = XmStringCreateLocalized(((char *)GETMESSAGE(5, 14, "No")));
610     tmpStr2 = XmStringCreateLocalized(((char *)GETMESSAGE(5, 15, "Yes")));
611     strcpy(buf, DialogTitle(pPad));
612     strcat(buf, (char *)GETMESSAGE(5, 16, "Save?"));
613     tmpStr3 = XmStringCreateLocalized(buf);
614     tmpStr4 = XmStringCreateLocalized(((char *)GETMESSAGE(2, 1, "Help")));
615     tmpStr5 = XmStringCreateLocalized((String) _DtCancelString);
616     ac = 0;
617     XtSetArg(al[ac], XmNapplyLabelString, tmpStr1); ac++;
618     XtSetArg(al[ac], XmNokLabelString, tmpStr2); ac++;
619     XtSetArg(al[ac], XmNdialogTitle, tmpStr3); ac++;
620     XtSetArg(al[ac], XmNhelpLabelString, tmpStr4); ac++;
621     XtSetArg(al[ac], XmNcancelLabelString, tmpStr5); ac++;
622     XtSetArg(al[ac], XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE);  ac++;
623     XtSetArg(al[ac], XmNmwmDecorations, MWM_DECOR_BORDER | MWM_DECOR_TITLE);
624     ac++;
625     XtSetArg (al[ac], XmNallowShellResize, False);              ac++;
626     pSelect->save_warning = XmCreatePromptDialog(pPad->app_shell, "save_warn",
627                                                         al, ac);
628     XmStringFree(tmpStr1);
629     XmStringFree(tmpStr2);
630     XmStringFree(tmpStr3);
631     XmStringFree(tmpStr4);
632     XmStringFree(tmpStr5);
633
634     /* -----> Set the dialog input mode */
635     ac=0;
636     XtSetArg(al[ac], XmNmwmInputMode, MWM_INPUT_PRIMARY_APPLICATION_MODAL);ac++;
637     XtSetValues(XtParent(pSelect->save_warning), al, ac);
638
639     /* -----> Create Form to contain the prompt symbol and text (in a RowColumn)
640     *         and the "insert new lines?" toggles (in a RadioBox) */
641     ac = 0;
642     XtSetArg(al[ac], XmNshadowThickness, 0); ac++;
643     pSelect->work_area = XmCreateForm(pSelect->save_warning, "wkarea",  al, ac);
644     XtManageChild(pSelect->work_area);
645
646     /* -----> Create a horizontal RowColumn container for the warning symbol
647      *        and text prompt */
648     ac = 0;
649     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
650     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
651     XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
652     pSelect->row_col = XmCreateRowColumn(pSelect->work_area, "rowCol", al, ac);
653     XtManageChild(pSelect->row_col);
654
655     /* -----> Place the warning symbol in RowColumn container */
656     ac = 0;
657     XtSetArg(al[ac], XmNforeground, &foreground); ac++;
658     XtSetArg(al[ac], XmNbackground, &background); ac++;
659     XtGetValues(pSelect->save_warning, al, ac);
660     ac = 0;
661     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
662     pixmap = XmGetPixmap(XtScreen(pSelect->save_warning), "warn_image",
663                                 foreground, background);
664     XtSetArg(al[ac], XmNlabelPixmap, pixmap); ac++;
665     w = XmCreateLabelGadget(pSelect->row_col, "pixmap_label", al, ac);
666     XtManageChild(w);
667
668     /* -----> Place the prompt string in the RowColumn container
669      *        (the prompt string is set in AskIfSave() based on whether
670      *        or not a file name has been specified among other things) */
671     ac = 0;
672     pSelect->wkArea_textLabel = XmCreateLabelGadget(pSelect->row_col,
673                                                         "txt_lab", al, ac);
674     XtManageChild(pSelect->wkArea_textLabel);
675
676
677     /* -----> Create a separator between message and new line toggles */
678     ac = 0;
679     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
680     XtSetArg(al[ac], XmNtopWidget, pSelect->row_col); ac++;
681     XtSetArg(al[ac], XmNtopOffset, 5); ac++;
682     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
683     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
684     pSelect->separator = XmCreateSeparator(pSelect->work_area, "sep", al, ac);
685     if (pPad->xrdb.wordWrap == True)
686         XtManageChild(pSelect->separator);
687
688     /* -----> Create a radio box with two toggle buttons for either adding
689      *        or not adding new lines if word wrap mode is on. */
690     CreateNewLineToggles(pPad,
691                         pSelect->work_area,             /* parent widget */
692                         &pSelect->toggleWidgets);       /* new widgets */
693
694     /* -----> Place toggle buttons below separator */
695     ac = 0;
696     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
697     XtSetArg(al[ac], XmNtopWidget, pSelect->separator); ac++;
698     XtSetArg(al[ac], XmNtopOffset, 5); ac++;
699     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
700     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
701     XtSetValues(pSelect->toggleWidgets.newl_radio, al, ac);
702
703     /* -----> manage the apply button of the SelectionBox PromptDialog */
704     w = XmSelectionBoxGetChild (pSelect->save_warning, XmDIALOG_APPLY_BUTTON);
705     XtManageChild(w);
706
707     /* -----> don't need the SelectionBox PromptDialog text input field and
708      *        label */
709     ac = 0;
710     kid[ac++] = XmSelectionBoxGetChild (pSelect->save_warning, XmDIALOG_TEXT);
711     kid[ac++] = XmSelectionBoxGetChild (pSelect->save_warning,
712                                         XmDIALOG_SELECTION_LABEL);
713     XtUnmanageChildren (kid, ac);
714
715     /* -----> set the SelectionBox PromptDialog [No] [Cancel] [Help] callbacks
716      *        (the [Yes] XmNokCallback is set in AskIfSave() based on whether
717      *        or not a file name has been specified among other things) */
718     XtAddCallback(pSelect->save_warning, XmNapplyCallback,
719                 (XtCallbackProc) NoSaveCB, (XtPointer) pPad);
720     XtAddCallback(pSelect->save_warning, XmNcancelCallback,
721                 (XtCallbackProc) AskIfSaveCancelCB, (XtPointer) pPad);
722     XtAddCallback(pSelect->save_warning, XmNhelpCallback,
723                 (XtCallbackProc) HelpAskIfSaveDialogCB, (XtPointer) pPad);
724
725     /* -----> save the widget id of the Cancel button so that it can be
726      *        unmanaged (in AskIfSave) if a "forced" TTDT_QUIT is being
727      *        processed */
728     pSelect->cancelBtn = XmSelectionBoxGetChild(
729                                 pSelect->save_warning, XmDIALOG_APPLY_BUTTON);
730
731     XtRealizeWidget(pSelect->save_warning);
732
733 }
734
735
736 /************************************************************************
737  *  Warning - posts a information/warning/error message dialog
738  ************************************************************************/
739 void
740 Warning(
741         Editor *pPad,
742         char *mess ,
743         unsigned char dialogType)
744 {
745     Arg al[10];
746     int ac;
747     char *tmpMess, buf[256];
748     FileWidgets *pFileWidgets = &pPad->fileStuff.fileWidgets;
749     XmString tempStr;
750
751     tmpMess = strdup(mess);
752
753     /* create the dialog if it is the first time */
754     if (!pFileWidgets->gen_warning)
755     {
756         ac = 0;
757         XtSetArg(al[ac], XmNokLabelString,
758                  XmStringCreateLocalized((String) _DtOkString));  ac++;
759         pFileWidgets->gen_warning = XmCreateMessageDialog (pPad->app_shell,
760                                                         "Warn", al, ac);
761         /* Unmanage unneeded children. */
762         XtUnmanageChild(XmMessageBoxGetChild(pFileWidgets->gen_warning,
763                                                 XmDIALOG_CANCEL_BUTTON) );
764         XtUnmanageChild(XmMessageBoxGetChild(pFileWidgets->gen_warning,
765                                                 XmDIALOG_HELP_BUTTON) );
766
767         XtRealizeWidget(pFileWidgets->gen_warning);
768         ac=0;
769         XtSetArg(al[ac], XmNmwmInputMode,
770                         MWM_INPUT_PRIMARY_APPLICATION_MODAL);ac++;
771         XtSetValues(XtParent(pFileWidgets->gen_warning), al, ac);
772     }
773
774     strcpy(buf, DialogTitle(pPad));
775     switch(dialogType)
776     {
777         case XmDIALOG_ERROR:
778             strcat(buf, (char *)GETMESSAGE(5, 17, "Error"));
779             break;
780         case XmDIALOG_INFORMATION:
781             strcat(buf, (char *)GETMESSAGE(5, 20, "Information"));
782             break;
783         case XmDIALOG_WARNING:
784         default:
785             strcat(buf, (char *)GETMESSAGE(5, 6, "Warning"));
786             break;
787     }
788
789     ac = 0;
790     tempStr = XmStringCreateLocalized(buf);
791     XtSetArg(al[ac], XmNdialogTitle, tempStr); ac++;
792     XtSetArg(al[ac], XmNdialogType, dialogType); ac++;
793     XtSetArg(al[ac], XmNmessageString,
794                 XmStringCreateLocalized(tmpMess)); ac++;
795     XtSetValues(pFileWidgets->gen_warning, al, ac);
796     XmStringFree(tempStr);
797
798     XtManageChild (pFileWidgets->gen_warning);
799 }
800
801
802 /************************************************************************
803  * PostSaveError - posts a dialog displaying the status returned by
804  *      DtEditorSaveContentsToFile() (when called by the "File" menu
805  *      callbacks).
806  ************************************************************************/
807 void
808 PostSaveError(
809         Editor *pPad,
810         char *saveName,
811         DtEditorErrorCode errorCode)
812 {
813     char errorMsg[256], *errorReason;
814
815     /* -----> determine the reason why save failed */
816     switch(errorCode) {
817         case DtEDITOR_NO_ERRORS:
818             return;
819         case DtEDITOR_INVALID_FILENAME:
820             Warning(pPad, ((char *)
821                     GETMESSAGE(5, 31, "Unable to save file.\nFile name was not specified.")),
822                     XmDIALOG_ERROR);
823             return;
824         case DtEDITOR_UNWRITABLE_FILE:
825             errorReason = strdup( (char *)
826                     GETMESSAGE(5, 46, "Either file is unwritable or path to\nfile does not exist."));
827             break;
828         case DtEDITOR_DIRECTORY:
829             errorReason = strdup((char *)
830                     GETMESSAGE(5, 35, "File is a directory."));
831             break;
832         case DtEDITOR_CHAR_SPECIAL_FILE:
833             errorReason = strdup((char *)
834                     GETMESSAGE(5, 36, "File is a character special device."));
835             break;
836         case DtEDITOR_BLOCK_MODE_FILE:
837             errorReason = strdup((char *)
838                     GETMESSAGE(5, 37, "File is a block mode device."));
839             break;
840         case DtEDITOR_INSUFFICIENT_MEMORY:
841             errorReason = strdup((char *)
842                     GETMESSAGE(5, 47, "Operation failed due to insufficient memory.\nTry increasing swap space."));
843             break;
844         case DtEDITOR_INVALID_TYPE:     /* this should never occur */
845             errorReason = strdup((char *)
846                     GETMESSAGE(5, 38, "Invalid file format."));
847             break;
848         case DtEDITOR_SAVE_FAILED:      /* this should catch everything else */
849         default:                        /* - but just in case */
850             errorReason = strdup((char *)
851                     GETMESSAGE(5, 39, "Unknown reason - possibly not enough disk space."));
852             break;
853     }
854
855     /* -----> format and display error messages containing the
856      *        file name and reason why the save failed */
857     sprintf(errorMsg,
858             (char *) GETMESSAGE(5, 30, "Unable to save %1$s.\n%2$s"),
859             saveName,
860             errorReason);
861     Warning(pPad, errorMsg, XmDIALOG_ERROR);
862     free(errorReason);
863
864     if (pPad->fileStuff.pendingFileFunc == FileExitCB) {
865         TTfailPendingQuit(pPad);
866     }
867
868 }
869
870
871 /************************************************************************
872  * AskIfSave - creates a dialog and corresponding "o.k." button callback
873  *      to save the current text to a file.  The dialog message and
874  *      o.k. callback depend on whether or not a name is associated
875  *      with the text.
876  ************************************************************************/
877 void
878 AskIfSave(
879         Editor *pPad)
880 {
881     Arg al[10];             /* arg list */
882     register int ac;        /* arg count */
883     char *tmp = NULL;
884     XmString tmpStr;
885     Select *pSelect = &pPad->fileStuff.fileWidgets.select;
886
887     if (pSelect->save_warning == (Widget) NULL)
888         CreateSaveWarning(pPad);
889
890     if (pPad->ttQuitReq.contract && pPad->ttQuitReq.force) {
891         XtUnmanageChild(pSelect->cancelBtn);
892     } else {
893         XtManageChild(pSelect->cancelBtn);
894     }
895
896     XtRemoveAllCallbacks(pSelect->save_warning, XmNokCallback);
897
898     if (pPad->ttEditReq.contract &&
899       pPad->ttEditReq.docName && *pPad->ttEditReq.docName) {
900         /* -----> TT docName supplied in media request, so ask:
901          *        "Save changes to "<docName>"?" */
902         tmp = (char *)XtMalloc(strlen(SAVE_CH_DOC) +
903                                 strlen(pPad->ttEditReq.docName) + 4);
904         sprintf(tmp,SAVE_CH_DOC, pPad->ttEditReq.docName);
905         XtAddCallback(pSelect->save_warning, XmNokCallback,
906                         (XtCallbackProc) FileSaveCB, (XtPointer) pPad);
907     } else if (pPad->fileStuff.fileName && *pPad->fileStuff.fileName) {
908         /* -----> TT or non-TT filename given, so ask:
909          *        "Save changes to <file>?" */
910         tmp = (char *)XtMalloc(strlen(SAVE_CH) +
911                                 strlen(pPad->fileStuff.fileName) + 4);
912         sprintf(tmp,SAVE_CH, pPad->fileStuff.fileName);
913         XtAddCallback(pSelect->save_warning, XmNokCallback,
914                         (XtCallbackProc) FileSaveCB, (XtPointer) pPad);
915     } else if (pPad->ttEditReq.contract && pPad->ttEditReq.contents) {
916         /* -----> TT buffer being edited w/o a docName, so simply ask:
917          *        "Save Changes?" */
918         tmp = (char *)XtMalloc(strlen(SAVE_CH_BUF) + 4);
919         sprintf(tmp,"%s",SAVE_CH_BUF);
920         XtAddCallback(pSelect->save_warning, XmNokCallback,
921                         (XtCallbackProc) FileSaveCB, (XtPointer) pPad);
922     } else {
923         /* -----> no file/doc name (and not a TT buffer), so ask:
924          *        "File has no name. Do you wash to save it?" */
925         tmp = (char *)XtMalloc(strlen(SAVE_CH_NONAME) + 4);
926         sprintf(tmp,"%s",SAVE_CH_NONAME);
927         XtAddCallback(pSelect->save_warning, XmNokCallback,
928                         (XtCallbackProc) FileSaveAsCB, (XtPointer) pPad);
929     }
930
931     tmpStr = XmStringCreateLocalized(tmp);
932     ac = 0;
933     XtSetArg(al[ac], XmNlabelString, tmpStr); ac++;
934     XtSetValues(pSelect->wkArea_textLabel, al, ac);
935     XmStringFree(tmpStr);
936     XtFree(tmp);
937
938     /*
939      * Make sure that the AskIfSave will be visible in case the
940      * main window is iconified and the user is closing the window
941      * from a window manager menu.
942      */
943     XtPopup(pPad->app_shell, XtGrabNone);
944     XtMapWidget(pPad->app_shell);
945
946     XtManageChild (pSelect->save_warning);
947     XmProcessTraversal(XmSelectionBoxGetChild(pSelect->save_warning,
948                         XmDIALOG_OK_BUTTON), XmTRAVERSE_CURRENT);
949 }
950
951 char*
952 DialogTitle(Editor *pPad)
953 {
954     if (pPad->dialogTitle == NULL)
955       pPad->dialogTitle = strdup((char *)GETMESSAGE(7, 2, "Text Editor - "));
956     
957     return pPad->dialogTitle;
958 }