Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
7.9 KiB

  1. /*
  2. *
  3. * Basic file I/O routines.
  4. */
  5. #include "stevie.h"
  6. #include <io.h>
  7. #include <errno.h>
  8. void
  9. filemess(s)
  10. char *s;
  11. {
  12. smsg("\"%s\" %s", (Filename == NULL) ? "" : Filename, s);
  13. flushbuf();
  14. }
  15. void
  16. renum()
  17. {
  18. LNPTR *p;
  19. unsigned long l = 0;
  20. for (p = Filemem; p != NULL ;p = nextline(p), l += LINEINC)
  21. if (p->linep)
  22. p->linep->num = l;
  23. Fileend->linep->num = 0xffffffff;
  24. }
  25. #define MAXLINE 512 /* maximum size of a line */
  26. bool_t
  27. readfile(fname,fromp,nochangename)
  28. char *fname;
  29. LNPTR *fromp;
  30. bool_t nochangename; /* if TRUE, don't change the Filename */
  31. {
  32. FILE *f;
  33. register LINE *curr;
  34. char buff[MAXLINE], buf2[80];
  35. register int i, c;
  36. register long nchars = 0;
  37. int linecnt = 0;
  38. bool_t wasempty = bufempty();
  39. int nulls = 0; /* count nulls */
  40. bool_t incomplete = FALSE; /* was the last line incomplete? */
  41. bool_t toolong = FALSE; /* a line was too long */
  42. int ctoolong = 0;
  43. bool_t readonly = FALSE; /* file is not writable */
  44. curr = fromp->linep;
  45. if ( ! nochangename ) {
  46. Filename = strsave(fname);
  47. setviconsoletitle();
  48. }
  49. if((_access(fname,2) == -1) && (errno == EACCES)) {
  50. readonly = TRUE;
  51. }
  52. if ( (f=fopen(fixname(fname),"r")) == NULL )
  53. return TRUE;
  54. filemess("");
  55. i = 0;
  56. do {
  57. c = getc(f);
  58. if (c == EOF) {
  59. if (i == 0) /* normal loop termination */
  60. break;
  61. /*
  62. * If we get EOF in the middle of a line, note the
  63. * fact and complete the line ourselves.
  64. */
  65. incomplete = TRUE;
  66. c = NL;
  67. }
  68. /*
  69. * Abort if we get an interrupt, but finished reading the
  70. * current line first.
  71. */
  72. if (got_int && i == 0)
  73. break;
  74. /*
  75. * If we reached the end of the line, OR we ran out of
  76. * space for it, then process the complete line.
  77. */
  78. if (c == NL || i == (MAXLINE-1)) {
  79. LINE *lp;
  80. if (c != NL) {
  81. toolong = TRUE;
  82. ctoolong++;
  83. }
  84. buff[i] = '\0';
  85. if ((lp = newline(strlen(buff))) == NULL)
  86. exit(1);
  87. strcpy(lp->s, buff);
  88. curr->next->prev = lp; /* new line to next one */
  89. lp->next = curr->next;
  90. curr->next = lp; /* new line to prior one */
  91. lp->prev = curr;
  92. curr = lp; /* new line becomes current */
  93. i = 0;
  94. linecnt++;
  95. if (toolong) {
  96. buff[i++] = (char)c;
  97. toolong = FALSE;
  98. }
  99. } else if (c == NUL)
  100. nulls++; /* count and ignore nulls */
  101. else {
  102. buff[i++] = (char)c; /* normal character */
  103. }
  104. nchars++;
  105. } while (!incomplete);
  106. fclose(f);
  107. /*
  108. * If the buffer was empty when we started, we have to go back
  109. * and remove the "dummy" line at Filemem and patch up the ptrs.
  110. */
  111. if (wasempty && nchars != 0) {
  112. LINE *dummy = Filemem->linep; /* dummy line ptr */
  113. free(dummy->s); /* free string space */
  114. Filemem->linep = Filemem->linep->next;
  115. free((char *)dummy); /* free LINE struct */
  116. Filemem->linep->prev = Filetop->linep;
  117. Filetop->linep->next = Filemem->linep;
  118. Curschar->linep = Filemem->linep;
  119. Topchar->linep = Filemem->linep;
  120. }
  121. renum();
  122. if (got_int) {
  123. smsg("\"%s\" Interrupt", fname);
  124. got_int = FALSE;
  125. return FALSE; /* an interrupt isn't really an error */
  126. }
  127. if (ctoolong != 0) {
  128. smsg("\"%s\" %d Line(s) too long - split", fname, ctoolong);
  129. return FALSE;
  130. }
  131. sprintf(buff, "\"%s\" %s%s%d line%s, %ld character%s",
  132. fname,
  133. readonly ? "[Read only] " : "",
  134. incomplete ? "[Incomplete last line] " : "",
  135. linecnt, (linecnt != 1) ? "s" : "",
  136. nchars, (nchars != 1) ? "s" : "");
  137. buf2[0] = NUL;
  138. if (nulls) {
  139. sprintf(buf2, " (%d null)", nulls);
  140. }
  141. strcat(buff, buf2);
  142. msg(buff);
  143. return FALSE;
  144. }
  145. /*
  146. * writeit - write to file 'fname' lines 'start' through 'end'
  147. *
  148. * If either 'start' or 'end' contain null line pointers, the default
  149. * is to use the start or end of the file respectively.
  150. */
  151. bool_t
  152. writeit(fname, start, end)
  153. char *fname;
  154. LNPTR *start, *end;
  155. {
  156. FILE *f;
  157. FILE *fopenb(); /* open in binary mode, where needed */
  158. char *backup;
  159. register char *s;
  160. register long nchars;
  161. register int lines;
  162. register LNPTR *p;
  163. if((_access(fname,2) == -1) && (errno == EACCES)) {
  164. msg("Write access to file is denied");
  165. return FALSE;
  166. }
  167. smsg("\"%s\"", fname);
  168. /*
  169. * Form the backup file name - change foo.* to foo.bak
  170. */
  171. backup = alloc((unsigned) (strlen(fname) + 5));
  172. strcpy(backup, fname);
  173. for (s = backup; *s && *s != '.' ;s++)
  174. ;
  175. *s = NUL;
  176. strcat(backup, ".bak");
  177. /*
  178. * Delete any existing backup and move the current version
  179. * to the backup. For safety, we don't remove the backup
  180. * until the write has finished successfully. And if the
  181. * 'backup' option is set, leave it around.
  182. */
  183. rename(fname, backup);
  184. f = P(P_CR) ? fopen(fixname(fname), "w") : fopenb(fixname(fname), "w");
  185. if (f == NULL) {
  186. emsg("Can't open file for writing!");
  187. free(backup);
  188. return FALSE;
  189. }
  190. /*
  191. * If we were given a bound, start there. Otherwise just
  192. * start at the beginning of the file.
  193. */
  194. if (start == NULL || start->linep == NULL)
  195. p = Filemem;
  196. else
  197. p = start;
  198. lines = nchars = 0;
  199. do {
  200. if (p->linep) {
  201. if (fprintf(f, "%s\n", p->linep->s) < 0) {
  202. emsg("Can't write file!");
  203. return FALSE;
  204. }
  205. nchars += strlen(p->linep->s) + 1;
  206. lines++;
  207. }
  208. /*
  209. * If we were given an upper bound, and we just did that
  210. * line, then bag it now.
  211. */
  212. if (end != NULL && end->linep != NULL) {
  213. if (end->linep == p->linep)
  214. break;
  215. }
  216. } while ((p = nextline(p)) != NULL);
  217. fclose(f);
  218. smsg("\"%s\" %d line%s, %ld character%s", fname,
  219. lines, (lines > 1) ? "s" : "",
  220. nchars, (nchars > 1) ? "s" : "");
  221. UNCHANGED;
  222. /*
  223. * Remove the backup unless they want it left around
  224. */
  225. if (!P(P_BK))
  226. remove(backup);
  227. free(backup);
  228. return TRUE;
  229. }