fileIo.c 12 KB

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