fileCB.c 46 KB

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