-
Notifications
You must be signed in to change notification settings - Fork 2
/
file.c
319 lines (298 loc) · 8.17 KB
/
file.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/*
* The routines in this file handle the reading and writing of disk files.
* All details about the reading and writing of the disk are in "fileio.c"
*/
#include <string.h> /* strncpy(3) */
#include "estruct.h"
#include "edef.h"
extern int getfilename (char *prompt, char *buf, int nbuf);
extern int mlreply (char *prompt, char *buf, int nbuf);
extern int swbuffer (BUFFER *bp);
extern void mlwrite (char *,...);
extern int bclear (BUFFER *bp);
extern int ffropen (char *fn);
extern int ffgetline (char buf[], int nbuf);
extern int ffwopen (char *fn);
extern int ffclose ();
extern int ffputline (char buf[], int nbuf);
extern int togglereadonly(int, int);
extern BUFFER *bfind ();
extern LINE *lalloc ();
int filefind (int f, int n);
int viewfile (int f, int n);
int getfile (char fname[]);
int readin (char fname[]);
void makename (char bname[], char fname[]);
int filewrite (int f, int n);
int filesave (int f, int n);
int writeout (char *fn);
/*
* Select a file for editing. Look around to see if you can find the fine in
* another buffer; if you can find it just switch to the buffer. If you cannot
* find the file, create a new buffer, read in the text, and switch to the new
* buffer. Bound to C-X C-F.
*/
int filefind (int f, int n)
{
char fname[NFILEN]; /* file user wishes to find */
int s; /* status return */
if ((s = getfilename("Find File: ", fname, NFILEN)) != TRUE)
return (s);
return (getfile (fname));
}
int viewfile (int f, int n)
{
char fname[NFILEN]; /* file user wishes to find */
int s; /* status return */
if ((s = getfilename("View File: ", fname, NFILEN)) != TRUE)
return (s);
if ( (s = (getfile (fname))) == TRUE)
togglereadonly(f,n);
return s;
}
int getfile (char fname[])
{
BUFFER *bp;
LINE *lp;
char bname[NBUFN]; /* buffer name to put file */
int i, s;
for (bp = bheadp; bp != (BUFFER*)0; bp = bp->b_bufp)
{
if ((bp->b_flag & BFTEMP) == 0 && strcmp (bp->b_fname, fname) == 0)
{
if (--curbp->b_nwnd == 0)
{
curbp->b_dotp = curwp->w_dotp;
curbp->b_doto = curwp->w_doto;
curbp->b_markp = curwp->w_markp;
curbp->b_marko = curwp->w_marko;
}
swbuffer (bp);
lp = curwp->w_dotp;
i = curwp->w_ntrows / 2;
while (i-- && lback (lp) != curbp->b_linep)
lp = lback (lp);
curwp->w_linep = lp;
curwp->w_flag |= WFMODE | WFHARD;
mlwrite ("[Old buffer]");
return (TRUE);
}
}
makename (bname, fname); /* New buffer name */
while ((bp = bfind (bname, FALSE, 0)) != (BUFFER*)0)
{
s = mlreply ("Buffer name: ", bname, NBUFN);
if (s == ABORT) /* ^G to just quit */
return (s);
if (s == FALSE)
{ /* CR to clobber it */
makename (bname, fname);
break;
}
}
if (bp == (BUFFER*)0 && (bp = bfind (bname, TRUE, 0)) == (BUFFER*)0)
{
mlwrite ("Cannot create buffer");
return (FALSE);
}
if (--curbp->b_nwnd == 0)
{ /* Undisplay */
curbp->b_dotp = curwp->w_dotp;
curbp->b_doto = curwp->w_doto;
curbp->b_markp = curwp->w_markp;
curbp->b_marko = curwp->w_marko;
}
curbp = bp; /* Switch to it */
curwp->w_bufp = bp;
curbp->b_nwnd++;
return (readin (fname)); /* Read it in */
}
/*
* Read file "fname" into the current buffer, blowing away any text found
* there. Called by both the read and find commands. Return the final status
* of the read. Also called by the mainline, to read in a file specified on
* the command line as an argument.
*/
int readin (char fname[])
{
LINE *lp1, *lp2;
WINDOW *wp;
BUFFER *bp;
char line[NLINE];
int nbytes, nline, s, i;
int lflag; /* any lines longer than allowed? */
bp = curbp; /* Cheap */
if ((s = bclear (bp)) != TRUE) /* Might be old */
return (s);
bp->b_flag &= ~(BFTEMP | BFCHG);
strncpy (bp->b_fname, fname, NFILEN);
if ((s = ffropen (fname)) == FIOERR) /* Hard file open */
goto out;
if (s == FIOFNF)
{ /* File not found */
mlwrite ("[New file]");
goto out;
}
mlwrite ("[Reading file]");
nline = 0;
lflag = FALSE;
while ((s = ffgetline (line, NLINE)) == FIOSUC || s == FIOLNG)
{
if (s == FIOLNG)
lflag = TRUE;
nbytes = strlen (line);
if ((lp1 = lalloc (nbytes)) == NULL)
{
s = FIOERR; /* Keep message on the display */
break;
}
lp2 = lback (curbp->b_linep);
lp2->l_fp = lp1;
lp1->l_fp = curbp->b_linep;
lp1->l_bp = lp2;
curbp->b_linep->l_bp = lp1;
for (i = 0; i < nbytes; ++i)
lputc (lp1, i, line[i]);
++nline;
}
ffclose (); /* Ignore errors */
if (s == FIOEOF)
{ /* Don't zap message! */
if (nline == 1)
mlwrite ("[Read 1 line]");
else
mlwrite ("[Read %d lines]", nline);
}
if (lflag)
mlwrite ("[Read %d line(s), Long lines wrapped]", nline);
out:
for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
{
if (wp->w_bufp == curbp)
{
wp->w_linep = lforw (curbp->b_linep);
wp->w_dotp = lforw (curbp->b_linep);
wp->w_doto = 0;
wp->w_markp = NULL;
wp->w_marko = 0;
wp->w_flag |= WFMODE | WFHARD;
}
}
if (s == FIOERR || s == FIOFNF) /* False if error */
return (FALSE);
return (TRUE);
}
/*
* Take a file name, and from it fabricate a buffer name. This routine knows
* about the syntax of file names on the target system. I suppose that this
* information could be put in a better place than a line of code.
*/
void makename (char bname[], char fname[])
{
char *cp1, *cp2;
cp1 = &fname[0];
while (*cp1 != 0)
++cp1;
while (cp1 != &fname[0] && cp1[-1] != '/')
--cp1;
cp2 = &bname[0];
while (cp2 != &bname[NBUFN - 1] && *cp1 != 0 && *cp1 != ';')
*cp2++ = *cp1++;
*cp2 = 0;
}
/*
* Ask for a file name, and write the contents of the current buffer to that
* file. Update the remembered file name and clear the buffer changed flag.
* This handling of file names is different from the earlier versions, and is
* more compatable with Gosling EMACS than with ITS EMACS. Bound to "C-X C-W".
*/
int filewrite (int f, int n)
{
WINDOW *wp;
char fname[NFILEN];
int s;
if ((s = mlreply ("Write File: ", fname, NFILEN)) != TRUE)
return (s);
if ((s = writeout (fname)) == TRUE)
{
strncpy (curbp->b_fname, fname, NFILEN);
curbp->b_flag &= ~BFCHG;
wp = wheadp; /* Update mode lines */
while (wp != NULL)
{
if (wp->w_bufp == curbp)
wp->w_flag |= WFMODE;
wp = wp->w_wndp;
}
}
return (s);
}
/*
* Save the contents of the current buffer in its associatd file. No nothing
* if nothing has changed (this may be a bug, not a feature). Error if there
* is no remembered file name for the buffer. Bound to "C-X C-S". May get
* called by "C-Z"
*/
int filesave (int f, int n)
{
WINDOW *wp;
int s;
if ((curbp->b_flag & BFCHG) == 0) /* Return, no changes */
return (TRUE);
if (curbp->b_fname[0] == 0)
{ /* Must have a name */
mlwrite ("No file name");
return (FALSE);
}
if ((s = writeout (curbp->b_fname)) == TRUE)
{
curbp->b_flag &= ~BFCHG;
wp = wheadp; /* Update mode lines */
while (wp != NULL)
{
if (wp->w_bufp == curbp)
wp->w_flag |= WFMODE;
wp = wp->w_wndp;
}
}
return (s);
}
/*
* This function performs the details of file writing. Uses the file
* management routines in the "fileio.c" package. The number of lines written
* is displayed. Sadly, it looks inside a LINE; provide a macro for this. Most
* of the grief is error checking of some sort.
*/
int writeout (char *fn)
{
LINE *lp;
int nline, s;
if ((s = ffwopen (fn)) != FIOSUC) /* Open writes message */
return (FALSE);
mlwrite ("[Writing]"); /* tell us were writing */
lp = lforw (curbp->b_linep); /* First line */
nline = 0; /* Number of lines */
while (lp != curbp->b_linep)
{
if ((s = ffputline (&lp->l_text[0], llength (lp))) != FIOSUC)
break;
++nline;
lp = lforw (lp);
}
if (s == FIOSUC)
{ /* No write error */
s = ffclose ();
if (s == FIOSUC)
{ /* No close error */
if (nline == 1)
mlwrite ("[Wrote 1 line]");
else
mlwrite ("[Wrote %d lines]", nline);
}
}
else /* ignore close error */
ffclose (); /* if a write error */
if (s != FIOSUC) /* some sort of error */
return (FALSE);
return (TRUE);
}