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