fileIo.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  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. /* $XConsortium: fileIo.c /main/4 1996/10/04 17:24:28 drk $ */
  24. /**********************************<+>*************************************
  25. ***************************************************************************
  26. **
  27. ** File: fileIo.c
  28. **
  29. ** Project: DT dtpad, a memo maker type editor based on the Dt Editor
  30. ** widget.
  31. **
  32. ** Description:
  33. ** -----------
  34. **
  35. *******************************************************************
  36. ** (c) Copyright Hewlett-Packard Company, 1991, 1992. All rights are
  37. ** reserved. Copying or other reproduction of this program
  38. ** except for archival purposes is prohibited without prior
  39. ** written consent of Hewlett-Packard Company.
  40. ********************************************************************
  41. **
  42. ********************************************************************
  43. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  44. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  45. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  46. ** (c) Copyright 1993, 1994 Novell, Inc.
  47. ********************************************************************
  48. **
  49. ** ToDo: roll in fixes for 10.0 ivepad
  50. **
  51. **
  52. **************************************************************************
  53. **********************************<+>*************************************/
  54. #include "dtpad.h"
  55. #include <Xm/TextP.h>
  56. #include <sys/types.h>
  57. #include <sys/wait.h>
  58. #include <Xm/TextF.h>
  59. #include <Xm/LabelG.h>
  60. /************************************************************************
  61. * LoadFile - Opens the specified file and loads its contents to the
  62. * DtEditor widget.
  63. *
  64. * The filename is specified either by pPad->fileStuff.fileName or
  65. * the 'include' argument. If the filename is specified via include,
  66. * the file is inserted at the current cursor location. In both
  67. * instances, the filename is assumed to be relative to the local host
  68. * where dtpad is running.
  69. *
  70. ************************************************************************/
  71. /* [SuG 5/18/95] Done
  72. The NOT_SAMPLE warnings/errors need to be added to the message
  73. catalog. Removed ifdefs.*/
  74. void
  75. LoadFile(
  76. Editor *pPad,
  77. char *include)
  78. {
  79. char * localName;
  80. DtEditorErrorCode errorCode;
  81. DtEditorContentRec contentRec;
  82. Boolean fileLoaded = False;
  83. Boolean fileLoadError = False;
  84. if (include != (char *)NULL) {
  85. localName = include;
  86. } else {
  87. localName = pPad->fileStuff.fileName;
  88. pPad->fileStuff.readOnly = False;
  89. }
  90. if (localName && *localName) {
  91. /* try to load the file to the Dt Editor widget */
  92. _DtTurnOnHourGlass(pPad->app_shell);
  93. XSync(XtDisplay(pPad->editor), False);
  94. if (include != (char *) NULL) {
  95. errorCode = DtEditorInsertFromFile(
  96. pPad->editor,
  97. localName);
  98. } else {
  99. pPad->fileStuff.fileExists = True;
  100. errorCode = DtEditorSetContentsFromFile(
  101. pPad->editor,
  102. localName);
  103. }
  104. _DtTurnOffHourGlass(pPad->app_shell);
  105. switch (errorCode) {
  106. case DtEDITOR_NO_ERRORS: /* file is read/writeable */
  107. fileLoaded = True;
  108. break;
  109. case DtEDITOR_READ_ONLY_FILE:
  110. fileLoaded = True;
  111. if (include == (char *) NULL) {
  112. pPad->fileStuff.readOnly = True;
  113. if (pPad->xrdb.readOnlyWarning &&
  114. ! pPad->xrdb.statusLine &&
  115. ! pPad->xrdb.viewOnly) {
  116. Warning(pPad, (char *) GETMESSAGE(6, 1,
  117. "This file has been opened for reading only."),
  118. XmDIALOG_WARNING);
  119. }
  120. }
  121. break;
  122. case DtEDITOR_NONEXISTENT_FILE:
  123. if (include != (char *) NULL ) {
  124. Warning(pPad, (char *) GETMESSAGE(6, 2,
  125. "This file does not exist."),
  126. XmDIALOG_ERROR);
  127. fileLoadError = True;
  128. } else if (pPad->xrdb.viewOnly) {
  129. Warning(pPad, (char *) GETMESSAGE(6, 2,
  130. "This file does not exist."),
  131. XmDIALOG_ERROR);
  132. } else if (pPad->xrdb.missingFileWarning) {
  133. Warning(pPad, (char *) GETMESSAGE(6, 2,
  134. "This file does not exist."),
  135. XmDIALOG_WARNING);
  136. }
  137. break;
  138. case DtEDITOR_DIRECTORY:
  139. Warning(pPad, (char *) GETMESSAGE(6, 3,
  140. "Unable to edit a Directory."),
  141. XmDIALOG_ERROR);
  142. fileLoadError = True;
  143. break;
  144. case DtEDITOR_CHAR_SPECIAL_FILE:
  145. Warning(pPad, (char *) GETMESSAGE(6, 4,
  146. "Unable to edit a character special device file."),
  147. XmDIALOG_ERROR);
  148. fileLoadError = True;
  149. break;
  150. case DtEDITOR_BLOCK_MODE_FILE:
  151. Warning(pPad, (char *) GETMESSAGE(6, 5,
  152. "Unable to edit a block mode device file."),
  153. XmDIALOG_ERROR);
  154. fileLoadError = True;
  155. break;
  156. case DtEDITOR_NULLS_REMOVED:
  157. Warning(pPad, (char *) GETMESSAGE(6, 6,
  158. "Embedded Nulls stripped from file."),
  159. XmDIALOG_WARNING);
  160. fileLoaded = True;
  161. break;
  162. case DtEDITOR_INSUFFICIENT_MEMORY:
  163. Warning(pPad, (char*) GETMESSAGE(6, 7,
  164. "Unable to load file (insufficient memory)."),
  165. XmDIALOG_ERROR);
  166. fileLoadError = True;
  167. break;
  168. case DtEDITOR_NO_FILE_ACCESS:
  169. Warning(pPad, (char *) GETMESSAGE(6, 8,
  170. "Unable to access file (can't determine its status)."),
  171. XmDIALOG_ERROR);
  172. fileLoadError = True;
  173. break;
  174. case DtEDITOR_UNREADABLE_FILE:
  175. Warning(pPad, (char *) GETMESSAGE(6, 9,
  176. "Unable to read from the file (probably no read permission)."),
  177. XmDIALOG_ERROR);
  178. fileLoadError = True;
  179. break;
  180. default:
  181. Warning(pPad, (char *) GETMESSAGE(6, 12,
  182. "Unable to read from the file (unknown reason)."),
  183. XmDIALOG_ERROR);
  184. fileLoadError = True;
  185. break;
  186. } /* switch (errorCode) */
  187. } /* file name specified */
  188. if (include != (char *)NULL)
  189. return;
  190. /*
  191. * We only get this far if the current file was to be changed
  192. * (i.e. the file was not included)
  193. */
  194. SetStatusLineMsg(pPad); /* set readOnly/viewOnly in status line msg */
  195. if (fileLoaded) {
  196. pPad->fileStuff.fileExists = True;
  197. } else {
  198. pPad->fileStuff.fileExists = False;
  199. /* null out Editor widget */
  200. contentRec.type = DtEDITOR_TEXT;
  201. contentRec.value.string = "";
  202. errorCode = DtEditorSetContents(pPad->editor, &contentRec);
  203. if (errorCode != DtEDITOR_NO_ERRORS)
  204. Warning(pPad,"Internal Error: Unable to NULL Editor Widget.",XmDIALOG_ERROR);
  205. /* clear stale file stuff */
  206. if (fileLoadError) {
  207. if (pPad->fileStuff.fileName && *pPad->fileStuff.fileName)
  208. XtFree(pPad->fileStuff.fileName);
  209. pPad->fileStuff.fileName = NULL;
  210. ChangeMainWindowTitle(pPad);
  211. return;
  212. }
  213. /* set the pathDir and fileName */
  214. if (pPad->fileStuff.fileName && *pPad->fileStuff.fileName) {
  215. char *lastSlash;
  216. strcpy(pPad->fileStuff.pathDir, pPad->fileStuff.fileName);
  217. if ((lastSlash = MbStrrchr(pPad->fileStuff.pathDir, '/')) !=
  218. (char *)NULL) {
  219. *(lastSlash + 1) = (char)'\0';
  220. }
  221. lastSlash = MbStrrchr(pPad->fileStuff.fileName, '/');
  222. if (lastSlash != (char *)NULL) {
  223. lastSlash++;
  224. } else {
  225. lastSlash = pPad->fileStuff.fileName;
  226. }
  227. if (*lastSlash == (char)'-' || *lastSlash == (char)'*') {
  228. XtFree(pPad->fileStuff.fileName);
  229. pPad->fileStuff.fileName = (char *)NULL;
  230. }
  231. }
  232. } /* ! fileLoaded */
  233. }
  234. /************************************************************************
  235. * GetTempFile - generates a file name for a temporary file that can be
  236. * used for writing.
  237. ************************************************************************/
  238. char *
  239. GetTempFile(void)
  240. {
  241. char *tempname = (char *)XtMalloc(L_tmpnam); /* Temporary file name. */
  242. FILE *tfp;
  243. (void)tmpnam(tempname);
  244. if ((tfp = fopen(tempname, "w")) == NULL)
  245. {
  246. pid_t pid;
  247. /*
  248. * If tmpnam fails, then try to create our own temp name.
  249. * Try a couple of different names if necessary.
  250. */
  251. XtFree(tempname);
  252. tempname = XtMalloc(256);
  253. pid = getpid();
  254. sprintf(tempname, "/usr/tmp/editor%ld", (long)pid);
  255. if ((tfp = fopen(tempname, "w")) == NULL)
  256. {
  257. sprintf(tempname, "/tmp/editor%ld", (long)pid);
  258. if ((tfp = fopen(tempname, "w")) == NULL)
  259. {
  260. XtFree(tempname);
  261. return (char *)NULL;
  262. }
  263. }
  264. }
  265. fclose(tfp);
  266. return tempname;
  267. }
  268. extern Editor *pPadList; /* declared/set in main.c */
  269. /************************************************************************
  270. * AddPound - add a "#" character to the beginning of the base name of
  271. * the file name passed in the nameBuf parameter. A pointer to the
  272. * new name is returned. The name is constructed in a static buffer.
  273. * If nameBuf is empty, it returns the file name "#UNTITLED#".
  274. ************************************************************************/
  275. static char *
  276. AddPound(
  277. char *nameBuf)
  278. {
  279. char tempBuf[512];
  280. static char returnBuf[512];
  281. if (nameBuf != (char *)NULL && nameBuf[0] != (char) '\0') {
  282. char *baseName;
  283. strcpy(tempBuf, nameBuf);
  284. baseName = MbStrrchr(tempBuf, '/');
  285. if (baseName != (char *)NULL) {
  286. strncpy(returnBuf, tempBuf, (baseName - tempBuf) + 1);
  287. returnBuf[(baseName - tempBuf) + 1] = (char)'\0';
  288. baseName++;
  289. strcat(returnBuf, "#");
  290. strcat(returnBuf, baseName);
  291. if (returnBuf[strlen(returnBuf) - 1] != (char)'#')
  292. strcat(returnBuf, "#");
  293. } else {
  294. sprintf(returnBuf, "#%s", tempBuf);
  295. if(strlen(returnBuf) && returnBuf[strlen(returnBuf) - 1] != (char)'#')
  296. strcat(returnBuf, "#");
  297. }
  298. } else {
  299. sprintf(returnBuf, "#%s#", GETMESSAGE(5, 21, "UNTITLED"));
  300. }
  301. return returnBuf;
  302. }
  303. /************************************************************************
  304. * PanicSave - immediately saves the text for each edit session handled
  305. * by the text editor to #[#]<filename>.
  306. ************************************************************************/
  307. void
  308. PanicSave(void)
  309. {
  310. Editor *pPad;
  311. struct stat statbuf; /* Information on a file. */
  312. Boolean addNewLines;
  313. DtEditorErrorCode errorCode;
  314. for (pPad = pPadList; pPad != (Editor *)NULL; pPad = pPad->pNextPad) {
  315. char *fileName = pPad->fileStuff.fileName;
  316. if (pPad->inUse != True || pPad->editor == NULL ||
  317. (! DtEditorCheckForUnsavedChanges(pPad->editor)))
  318. continue;
  319. /* -----> Try to cook up a name for a file that doesn't already exist */
  320. fileName = AddPound(pPad->fileStuff.fileName);
  321. if (stat(fileName, &statbuf) == 0) {
  322. fileName = AddPound(fileName);
  323. if (stat(fileName, &statbuf) == 0) {
  324. fileName = AddPound(fileName);
  325. if (stat(fileName, &statbuf) == 0) {
  326. /* Give up. We've tried enough names. The user loses. */
  327. continue;
  328. }
  329. }
  330. }
  331. addNewLines = pPad->xrdb.wordWrap == True &&
  332. pPad->fileStuff.saveWithNewlines == True;
  333. errorCode = DtEditorSaveContentsToFile(
  334. pPad->editor,
  335. fileName,
  336. False, /* don't overwrite existing file */
  337. addNewLines, /* replace soft line feeds? */
  338. False); /* don't mark contents as saved */
  339. /* don't really care about errorCode since we're in a hurry and
  340. * can't do anything about it anyway */
  341. }
  342. exit(1);
  343. }
  344. /************************************************************************
  345. * SetStatusLineMsg - sets the message (XmTextField) portion of the
  346. * DtEditor widget's status line based on whether the pad is in
  347. * viewOnly mode or the file being edited/displayed is readOnly.
  348. ************************************************************************/
  349. /* ARGSUSED */
  350. void
  351. SetStatusLineMsg(
  352. Editor *pPad)
  353. {
  354. char *message="";
  355. if (pPad->xrdb.viewOnly) {
  356. message = (char *) GETMESSAGE(6, 10, "View Only");
  357. } else if (pPad->fileStuff.readOnly) {
  358. message = (char *) GETMESSAGE(6, 11, "Read Only");
  359. }
  360. XmTextFieldSetString(pPad->statusLineMsg, message);
  361. }