fileDlg.c 35 KB

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