fileCB.c 46 KB

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