home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-06-08 | 44.2 KB | 1,354 lines |
- /* FILE.C: for MicroEMACS
-
- The routines in this file handle the reading, writing
- and lookup of disk files. All of details about the
- reading and writing of the disk are in "fileio.c".
-
- */
-
- /* Modifications:
- 12-Sep-89 Mike Burrow (INMOS) Added folding.
- 11-Oct-89 Bob Green (INMOS) Added dynamic fold info tables.
- */
-
-
- /*{{{ include files*/
-
- #include <stdio.h>
- #include <string.h>
- #include "estruct.h"
- #include "etype.h"
- #include "edef.h"
- #include "elang.h"
-
- /*}}}*/
-
- /*{{{ PASCAL NEAR fileread(f, n)*/
- PASCAL NEAR fileread(f, n)
-
- /*
- * Read a file into the current
- * buffer. This is really easy; all you do is
- * find the name of the file, and call the standard
- * "read a file into the current buffer" code.
- * Bound to "C-X C-R".
- */
-
- int f, n; /* default and numeric arguments (unused) */
-
- {
- register int s; /* status return */
- char *fname; /* file name to read */
-
- if (restflag) /* don't allow this command if restricted */
- return(resterr());
-
- if ((fname = gtfilename(TEXT131)) == NULL)
- /* "Read file" */
- return(FALSE);
-
- /* exit any folds, so we overwrite the whole buffer */
- exitallfolds();
- return(readin(fname, TRUE));
- }
- /*}}}*/
-
- /*{{{ PASCAL NEAR insfile(f, n)*/
- PASCAL NEAR insfile(f, n)
- /*
- * Insert a file into the current
- * buffer. This is really easy; all you do it
- * find the name of the file, and call the standard
- * "insert a file into the current buffer" code.
- * Bound to "C-X C-I".
- */
- {
- register int s;
- char *fname; /* file name */
-
- if (restflag) /* don't allow this command if restricted */
- return(resterr());
- if (curbp->b_mode&MDVIEW) /* don't allow this command if */
- return(rdonly()); /* we are in read only mode */
-
- if ((fname = gtfilename(TEXT132)) == NULL)
- /* "Insert file" */
- return(FALSE);
- return(ifile(fname));
- }
- /*}}}*/
-
- /*{{{ PASCAL NEAR filefind(f, n)*/
- PASCAL NEAR filefind(f, n)
-
- /*
- * 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.
- */
- {
- char *fname; /* file user wishes to find */ /* file name */
- register int s; /* status return */
-
- if (restflag) /* don't allow this command if restricted */
- return(resterr());
-
- if ((fname = gtfilename(TEXT133)) == NULL)
- /* "Find file" */
- return(FALSE);
- return(getfile(fname, TRUE));
- }
- /*}}}*/
-
- /*{{{ PASCAL NEAR viewfile(f, n) - visit a file in VIEW mode*/
- PASCAL NEAR viewfile(f, n) /* visit a file in VIEW mode */
- {
- char *fname; /* file user wishes to find */ /* file name */
- register int s; /* status return */
-
- if (restflag) /* don't allow this command if restricted */
- return(resterr());
-
- if ((fname = gtfilename(TEXT134)) == NULL)
- /* "View file" */
- return(FALSE);
- s = getfile(fname, FALSE);
- if (s) { /* if we succeed, put it in view mode */
- curwp->w_bufp->b_mode |= MDVIEW;
- upmode();
- }
- return(s);
- }
- /*}}}*/
-
- #if CRYPT
- /*{{{ PASCAL NEAR resetkey() - reset the encryption key if needed */
- PASCAL NEAR resetkey() /* reset the encryption key if needed */
-
- {
- register int s; /* return status */
-
- /* turn off the encryption flag */
- cryptflag = FALSE;
-
- /* if we are in crypt mode */
- if (curbp->b_mode & MDCRYPT) {
- if (curbp->b_key[0] == 0) {
- s = setekey(FALSE, 0);
- if (s != TRUE)
- return(s);
- }
-
- /* let others know... */
- cryptflag = TRUE;
-
- /* and set up the key to be used! */
- /* de-encrypt it */
- crypt((char *)NULL, 0);
- crypt(curbp->b_key, strlen(curbp->b_key));
-
- /* re-encrypt it...seeding it to start */
- crypt((char *)NULL, 0);
- crypt(curbp->b_key, strlen(curbp->b_key));
- }
-
- return(TRUE);
- }
- /*}}}*/
- #endif
-
- /*{{{ PASCAL NEAR getfile(fname, lockfl)*/
- PASCAL NEAR getfile(fname, lockfl)
-
- char fname[]; /* file name to find */
- int lockfl; /* check the file for locks? */
-
- {
- register BUFFER *bp;
- register LINE *lp;
- register int i;
- register int s;
- register int cmark; /* current mark */
- char bname[NBUFN]; /* buffer name to put file */
-
- #if MSDOS | OS2 | AOSVS | RISCOS
- mklower(fname); /* msdos/arc isn't case sensitive */
- #endif
-
- /*{{{ look for file in an existing buffer*/
- for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
- if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0) {
- 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(TEXT135); /* "[Old buffer]" */
- return(TRUE);
- }
- }
- /*}}}*/
-
- makename(bname, fname); /* New buffer name. */
-
- /*{{{ deal with conflicting buffer names*/
- while ((bp=bfind(bname, FALSE, 0)) != NULL) {
- /* old buffer name conflict code */
- s = mlreply(TEXT136, bname, NBUFN); /* "Buffer name: " */
- if (s == ABORT) /* ^G to just quit */
- return(s);
- if (s == FALSE) { /* CR to clobber it */
- makename(bname, fname);
- break;
- }
- }
- /*}}}*/
-
- /*{{{ try to make buffer*/
- if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) {
- mlwrite(TEXT137); /* "Cannot create buffer" */
- return(FALSE);
- }
- /*}}}*/
-
- if (--curbp->b_nwnd == 0) { /* Undisplay. */
- curbp->b_dotp = curwp->w_dotp;
- curbp->b_doto = curwp->w_doto;
- for (cmark = 0; cmark < NMARKS; cmark++) {
- curbp->b_markp[cmark] = curwp->w_markp[cmark];
- curbp->b_marko[cmark] = curwp->w_marko[cmark];
- }
- curbp->b_fcol = curwp->w_fcol;
- }
- curbp = bp; /* Switch to it. */
- curwp->w_bufp = bp;
- curbp->b_nwnd++;
- return(readin(fname, lockfl)); /* Read it in. */
- }
- /*}}}*/
-
- /*{{{ PASCAL NEAR indx(s, t)*/
- PASCAL NEAR indx(s, t)
-
- /* Index routine, since sun one only works for characters.
- * Return index of t in s, -1 if none.
- * MJB: 18-Sep-89.
- */
- char s[], t[];
- {
- int i, j, k;
-
- for (i = 0; s[i] != '\0'; i++) {
- for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++)
- /* loop */ ;
- if (t[k] == '\0')
- return(i);
- if ((s[i] != '\t') && (s[i] != ' '))
- return(-1); /* only white space prefix */
- }
- return(-1);
- }
- /*}}}*/
- /*{{{ PASCAL NEAR tindx(s, t, l)*/
- PASCAL NEAR tindx(s, t, l)
- /* Index routine, since sun one only works for characters.
- * Return index of t in s, -1 if none.
- * This one works with a length for s, a non null terminated string.
- * MJB: 26-Sep-89.
- */
- char s[], t[];
- int l;
- {
- int i, j, k;
-
- for (i = 0; i <= l; i++) {
- for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++)
- /* loop */ ;
- if (t[k] == '\0')
- return(i);
- if ((s[i] != '\t') && (s[i] != ' '))
- return(-1); /* only white space prefix */
- }
- return(-1);
- }
- /*}}}*/
-
-
- /*{{{ int PASCAL NEAR popmargin(lp)*/
- int PASCAL NEAR popmargin(lp)
- /*
- * popmargin -- Find the minimum left margin value for the
- * subsquent lines. Searches back up line in enclosing
- * open fold. MJB: 20-Oct-89.
- */
- LINE *lp;
- {
- /*
- while ((lp != curwp->w_bufp->b_linep) &&
- (lp->l_type != LNORMAL)) {
- if ((lp->l_type == LEOFOLD) ||
- (lp->l_type == LEOEFOLD))
- lp = lp->l_foldp;
- lp = lp->l_bp;
- }
- if (lp->l_type == LNORMAL)
- return(lp->l_lmargin);
- else
- return(0);
- */
- /* MJB 27-Feb-90 */
- /* isn't this what we need! */
- if ((lp->l_type == LEOFOLD) ||
- (lp->l_type == LEOEFOLD))
- lp = lp->l_foldp;
- return(lp->l_lmargin);
- }
- /*}}}*/
-
- /*{{{ PASCAL NEAR readin(fname, lockfl)*/
- PASCAL NEAR readin(fname, lockfl)
-
- /*
- 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.
- The command in $readhook is called after the buffer is set up
- and before it is read.
-
- Folding requirements: The file type is identified and stored
- in the buffer. MJB 13-Sep-89.
- */
-
-
- char fname[]; /* name of file to read */
- int lockfl; /* check for file locks? */
-
- {
- /*{{{ declare vars*/
- register LINE *lp1;
- register LINE *lp2;
- register int i;
- register WINDOW *wp;
- register BUFFER *bp;
- register int s;
- register int nbytes;
- register int nline;
- register int cmark; /* current mark */
- char mesg[NSTRING];
- register int pidx;
- register FOLDMARKENT *tp;
- char str[NSTRING];
- int lmargin;
- /*}}}*/
-
-
- #if FILOCK
- if (lockfl && lockchk(fname) == ABORT)
- return(ABORT);
- #endif
-
- /*{{{ prepare the buffer*/
- bp = curbp; /* Cheap. */
- mlwrite("[Tidying]");
- if ((s=bclear(bp)) != TRUE) /* Might be old. */
- return(s);
- bp->b_flag &= ~(BFINVS|BFCHG);
-
- strcpy(bp->b_fname, fname);
- /*}}}*/
-
- /*{{{ find file type*/
- if (getftype(fname, bp->b_ftype)) /* dd: MAY-91 */
- {
- tp = setfolds(bp->b_ftype);
- strcpy(mesg,"[file type ");
- strcat(mesg,bp->b_ftype);
- strcat(mesg,"]");
- mlwrite(mesg);
- }
- else tp = NULL;
- /*}}}*/
-
- /*{{{ call user's read-hook*/
- /* let a user macro get hold of things...if he wants */
- execkey(&readhook, FALSE, 1);
- /*}}}*/
-
- #if CRYPT
- /*{{{ prepare to decrypt*/
- /* set up for decryption */
- s = resetkey();
- if (s != TRUE)
- return(s);
- /*}}}*/
- #endif
-
- /*{{{ turn off kybd translation*/
- /* turn off ALL keyboard translation in case we get a dos error */
- TTkclose();
- /*}}}*/
-
- if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
- goto out;
-
- if (s == FIOFNF) { /* File not found. */
- mlwrite(TEXT138); /* "[New file]" */
- goto out;
- }
-
- /* read the file in */
- #if 1
- mlwrite(TEXT139); /* "[Reading file]" */
- #endif
- nline = 0;
- lmargin = 0;
-
- while ((s=ffgetline()) == FIOSUC) {
- /* Allow for a file with blank lines - ned? */
- nbytes = (strlen(fline) > lmargin) ? strlen(fline) : lmargin;
- if ((lp1=lalloc(nbytes)) == NULL) {
- s = FIOMEM; /* Keep message on the */
- break; /* display. */
- }
-
- /* If it was blank, we had better initialise it! */
- if (strlen(fline) < lmargin)
- for (i = strlen(fline); i < lmargin; i++)
- fline[i] = ' ';
-
- lp2 = curbp->b_linep->l_bp;
- lp2->l_fp = lp1;
- lp1->l_fp = curbp->b_linep;
- lp1->l_bp = lp2;
- curbp->b_linep->l_bp = lp1;
-
- /* check for fold lines. MJB: 15-Sep-89 */
- if ((tp != (FOLDMARKENT *)NULL) &&
- (pidx = indx(fline, tp->fm_startopen)) != -1)
-
- /*{{{ start of fold symbol*/
- {
- /* offset */
- strncpy(str, fline, pidx);
- str[pidx] = '\0';
- /* fold symbol */
- strcat(str, FOLDSYMBOL);
- /* comment */
- strcat(str, &fline[pidx + strlen(tp->fm_startopen)]);
- /* make sure string is long enough to remove close */
- if ((strlen(str) - pidx - strlen(FOLDSYMBOL))
- >= strlen(tp->fm_startclose))
- str[strlen(str) - strlen(tp->fm_startclose)] = '\0';
- /* back to fline, and adjust byte count */
- strcpy(fline, str);
- nbytes = strlen(fline);
- lp1->l_used = nbytes;
- /* set line type, and record start of fold */
- lp1->l_type = LSOFOLD;
- lp1->l_lmargin = lmargin;
- lmargin = pidx;
- pushline(lp1);
- }
- /*}}}*/
-
- else if ((tp != (FOLDMARKENT *)NULL) &&
- (pidx = indx(fline, tp->fm_end)) != -1)
-
- /*{{{ end of fold symbol*/
- {
- if (linelist->fll_bp->fll_line != (LINE *)NULL) {
- /* offset */
- strncpy(str, fline, pidx);
- str[pidx] = '\0';
- /* fold symbol */
- strcat(str, ENDFOLD);
- /* end fold comment from ned or the like! */
- strcat(str, &fline[pidx + strlen(tp->fm_end)]);
- /* back to fline, and adjust byte count */
- strcpy(fline, str);
- nbytes = strlen(fline);
- lp1->l_used = nbytes;
- /* set line type, and record start of fold */
- lp1->l_type = LEOFOLD;
- lp1->l_foldp = popline();
- lp1->l_foldp->l_foldp = lp1;
- lmargin = popmargin(lp1); /* recalculation */
- lp1->l_lmargin = lmargin;
- }
- else { /* Just to be safe! */
- lp1->l_type = LNORMAL;
- lp1->l_foldp = (LINE *)NULL;
- mlwrite(TEXT231); /* "Missing start-fold Marker */
- }
- }
- /*}}}*/
-
- else {
- lp1->l_type = LNORMAL;
- lp1->l_foldp = (LINE *)NULL;
- lp1->l_lmargin = lmargin;
- }
- for (i=0; i<nbytes; ++i)
- lputc(lp1, i, fline[i]);
- ++nline;
- }
- ffclose(); /* Ignore errors. */
- strcpy(mesg, "[");
- if (s==FIOERR) {
- strcat(mesg, TEXT141);
- /* "I/O ERROR, " */
- curbp->b_flag |= BFTRUNC;
- }
- if (s == FIOMEM) {
- strcat(mesg, TEXT142);
- /* "OUT OF MEMORY, " */
- curbp->b_flag |= BFTRUNC;
- }
- /* check to see if matching number of start/end fold markers */
- /* if not try to tidy up a bit. MJB: 22-Sep-89 */
- while (linelist->fll_bp->fll_line != (LINE *)NULL) {
- lp1 = popline();
- lp1->l_type = LNORMAL;
- mlwrite(TEXT230);
- /* "Missing end-fold Marker " */
- s = FIOERR;
- }
-
- /*{{{ show no lines read*/
- strcat(mesg, TEXT140); /* "Read " */
- strcat(mesg, int_asc(nline));
- strcat(mesg, TEXT143); /* " line" */
- if (nline > 1)
- strcat(mesg, "s");
- strcat(mesg, "]");
- mlwrite(mesg);
- /*}}}*/
-
- out:
- TTkopen(); /* open the keyboard again */
- 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;
- for (cmark = 0; cmark < NMARKS; cmark++) {
- wp->w_markp[cmark] = NULL;
- wp->w_marko[cmark] = 0;
- }
- wp->w_flag |= WFMODE|WFHARD;
- }
- }
- if (s == FIOERR || s == FIOFNF) /* False if error. */
- return(FALSE);
- return(TRUE);
- }
- /*}}}*/
-
- /*{{{ char *PASCAL NEAR makename(bname, fname)*/
- char *PASCAL NEAR makename(bname, fname)
- /*
- * 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.
- * Returns a pointer into fname indicating the end of the file path; i.e.,
- * 1 character BEYOND the path name.
- */
- char bname[];
- char fname[];
- {
- register char *cp1;
- register char *cp2;
- register char *pathp;
-
- #if AOSVS | MV_UX
- resolve_full_pathname(fname, fname);
- mklower(fname); /* aos/vs not case sensitive */
- #endif
- cp1 = &fname[0];
- while (*cp1 != 0)
- ++cp1;
-
- #if AMIGA
- while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/')
- --cp1;
- #endif
- #if AOSVS | MV_UX
- while (cp1!=&fname[0] && cp1[-1]!=':')
- --cp1;
- #endif
- #if VMS
- while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
- --cp1;
- #endif
- #if MSDOS | MSDOS
- while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
- --cp1;
- #endif
- #if ST520
- while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\')
- --cp1;
- #endif
- #if FINDER
- while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
- --cp1;
- #endif
- #if V7 | USG | HPUX | BSD | SUN | XENIX
- while (cp1!=&fname[0] && cp1[-1]!='/')
- --cp1;
- #endif
- #if WMCS
- while (cp1!=&fname[0] && cp1[-1]!='_' && cp1[-1]!='/')
- --cp1;
- #endif
- #if RISCOS
- while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='.')
- --cp1;
- #endif
- /* cp1 is pointing to the first real filename char */
- pathp = cp1;
-
- cp2 = &bname[0];
- while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
- *cp2++ = *cp1++;
- *cp2 = 0;
-
- return(pathp);
- }
- /*}}}*/
-
- /*{{{ FOLDMARKENT *PASCAL NEAR setfolds(ftype)*/
- FOLDMARKENT *PASCAL NEAR setfolds(ftype)
- /*
- * set fold markers according to file type
- */
- char *ftype;
- {
- /*{{{ declare vars*/
- register FOLDMARKENT *tp,*catchall;
-
-
-
-
- /*}}}*/
-
- /* compare ftype with all the extensions in the table */
-
- tp = foldmarktab;
- catchall = NULL;
- while (tp != NULL) {
- if (strcmp("*", tp->fm_extension) == 0)
- catchall = tp;
-
- if (strcmp(ftype, tp->fm_extension) == 0)
- return(tp);
- else
- tp = tp->fm_next;
- }
- return(catchall);
- }
- /*}}}*/
-
- #if RISCOS
- /*{{{ int PASCAL NEAR knowntype(ftype)*/
- int PASCAL NEAR knowntype(ftype)
- /*
- * see if ftype is known
- */
- char *ftype;
- {
-
-
- /* compare ftype with all the extensions in the table */
-
- register FOLDMARKENT *tp = foldmarktab;
-
- while (tp != NULL) {
- if (strcmp("*", tp->fm_extension) == 0)
- return(1);
-
- if (strcmp(ftype, tp->fm_extension) == 0)
- return(1);
- else
- tp = tp->fm_next;
- }
- return(0);
- }
- /*}}}*/
- #endif
-
- /*{{{ int PASCAL NEAR getftype(fname,ftype)*/
- int PASCAL NEAR getftype(fname,ftype)
- /*
- * Take a file name, and from it identify the file type.
- * MJB: 13-Sep-89.
- * div - riscos vsn, tries to get riscos file type, if there is no sign
- of an extension at start or end
- returns pointer to fold marker set, and also copies textual type
- to ftype buffer
-
- * used to also set the fold markers, but no longer...
- */
- char *fname;
- char *ftype;
-
- #if RISCOS
-
- /*{{{ riscos vsn*/
- {
- /*{{{ declare vars*/
- _kernel_osfile_block block;
- register char *cp1, *cp2 = ftype;
-
- *ftype = 0;
- /*}}}*/
-
- /*{{{ look for form path.c.filename*/
- if (cp1 = strrchr(fname,'.'))
-
- {
- /*{{{ find next-last dot, or start of fname*/
- for (--cp1; (cp1 > fname) && (*cp1 != '.'); --cp1);
-
- if (*cp1=='.') ++cp1;
- /*}}}*/
-
-
- for (cp2=ftype; *cp1 != '.';)
- if (!(*cp2++ = *cp1++))
- return(0); /* something went wrong - expected a . */
-
- *cp2 = 0;
-
- if (knowntype(ftype)) /* if recognised the file type */
- return(1);
- }
- /*}}}*/
-
- /*{{{ look for recognized type after a _*/
- if ((cp1 = strrchr(fname,'_')) && knowntype(cp1+1))
-
- { strcpy(ftype,cp1+1);
- return(1);
- }
-
- /*}}}*/
-
- /*{{{ try to get file type, though its usually Text !*/
-
- if
- /*{{{ its a file with a type stamp*/
- ((_kernel_osfile(17, fname, &block)==1) &&
- ((block.load & 0xfff00000) == 0xfff00000))
- /*}}}*/
-
- /*{{{ translate it to a name in ftype and return*/
- { _kernel_swi_regs regs;
-
- regs.r[0] = 18;
- regs.r[2] = (block.load >> 8) & 0xfff; /* file type */
-
- _kernel_swi(0x29, ®s, ®s); /* os_fscontrol 18 */
-
- for (cp1 = (char *) (®s.r[2]), cp2=ftype;
- (cp2 < ftype+8) && (*cp1 != ' ');
- *cp2++ = *cp1++);
- *cp2=0;
-
- if (knowntype(ftype))
- return(1);
-
- }
- /*}}}*/
- /*}}}*/
-
- return(0); /* failed */
-
- }
- /*}}}*/
-
- #else
-
- /*{{{ original-ish vsn*/
- {
- register char *cp1;
-
-
- # if AOSVS | MV_UX
- resolve_full_pathname(fname, fname);
- mklower(fname); /* aos/vs not case sensitive */
- # endif
-
- cp1 = &fname[0];
- while (*cp1 != 0)
- ++cp1;
-
- while (cp1!=&fname[0] && cp1[-1]!='.')
- --cp1;
-
- if (cp1 = fname)
- return(*ftype=0); /* no extension */
-
- /* cp1 is pointing to the first character of extention */
-
- strcpy(ftype, cp1);
-
- return(1);
- }
- /*}}}*/
-
- #endif
- /*}}}*/
-
- /*{{{ PASCAL NEAR unqname(name) - make sure a buffer name is unique*/
- PASCAL NEAR unqname(name) /* make sure a buffer name is unique */
-
- char *name; /* name to check on */
-
- {
- register char *sp;
-
- /* check to see if it is in the buffer list */
- while (bfind(name, 0, FALSE) != NULL) {
-
- /* go to the end of the name */
- sp = name;
- while (*sp)
- ++sp;
- if (sp == name || (*(sp-1) <'0' || *(sp-1) > '8')) {
- *sp++ = '0';
- *sp = 0;
- } else
- *(--sp) += 1;
- }
- }
- /*}}}*/
-
- /*{{{ PASCAL NEAR filewrite(f, n)*/
- PASCAL NEAR filewrite(f, n)
- /*
- * 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".
- */
- {
- register int s;
- char fname[NFILEN];
-
- if (restflag) /* don't allow this command if restricted */
- return(resterr());
- if ((s=mlreply(TEXT144, fname, NFILEN)) != TRUE)
- /* "Write file: " */
- return(s);
- if ((s=writeout(fname)) == TRUE) {
- strcpy(curbp->b_fname, fname);
- curbp->b_flag &= ~BFCHG;
- /* Update mode lines. */
- upmode();
- }
- return(s);
- }
- /*}}}*/
-
- /*{{{ PASCAL NEAR filesave(f, n)*/
- PASCAL NEAR filesave(f, n)
- /*
- * Save the contents of the current
- * buffer in its associatd file. Do 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".
- */
- {
- register int s;
-
- if (curbp->b_mode&MDVIEW) /* don't allow this command if */
- return(rdonly()); /* we are in read only mode */
- if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */
- return(TRUE);
- if (curbp->b_fname[0] == 0) { /* Must have a name. */
- mlwrite(TEXT145);
- /* "No file name" */
- return(FALSE);
- }
-
- /* complain about truncated files */
- if ((curbp->b_flag&BFTRUNC) != 0) {
- if (mlyesno(TEXT146) == FALSE) {
- /* "Truncated file..write it out" */
- mlwrite(TEXT8);
- /* "[Aborted]" */
- return(FALSE);
- }
- }
-
- /* complain about narrowed buffers */
- if ((curbp->b_flag&BFNAROW) != 0) {
- if (mlyesno(TEXT147) == FALSE) {
- /* "Narrowed Buffer..write it out" */
- mlwrite(TEXT8);
- /* "[Aborted]" */
- return(FALSE);
- }
- }
-
- if ((s=writeout(curbp->b_fname)) == TRUE) {
- curbp->b_flag &= ~BFCHG;
- /* Update mode lines. */
- upmode();
- }
- return(s);
- }
- /*}}}*/
-
- /*{{{ int PASCAL NEAR fileisfolded()*/
- int PASCAL NEAR fileisfolded()
- /* fileisfolded: check to see if a file contains folds
- */
-
- {
- register LINE *lp = curbp->b_linep->l_fp; /* first line */
-
- while (lp != curbp->b_linep) {
- if (lp->l_type != LNORMAL)
- return TRUE;
-
- lp = lp->l_fp; /* next line */
- }
-
- return FALSE;
- }
- /*}}}*/
-
- /*{{{ PASCAL NEAR writeout(fn)*/
- PASCAL NEAR writeout(fn)
- /*
- * This function performs the details of file writing. It uses
- * the file management routines in the "fileio.c" package. The
- * number of lines written is displayed. Several errors are
- * posible, and cause writeout to return a FALSE result. When
- * $ssave is TRUE, the buffer is written out to a temporary
- * file, and then the old file is unlinked and the temporary
- * renamed to the original name. Before the file is written,
- * a user specifyable routine (in $writehook) can be run.
- */
-
-
- char *fn; /* name of file to write current buffer to */
-
- {
- register LINE *lp; /* line to scan while writing */
- register char *sp; /* temporary string pointer */
- register int nline; /* number of lines written */
- int status; /* return status */
- int sflag; /* are we safe saving? */
- char tname[NSTRING]; /* temporary file name */
- #if RISCOS
- char ttype[NTYPEN]; /* temporary file type */
- #endif
- char buf[NSTRING]; /* message buffer */
- register int pidx;
- register FOLDMARKENT *tp;
- char str[NSTRING];
-
- /* let a user macro get hold of things...if he wants */
- execkey(&writehook, FALSE, 1);
-
- /* Exit from any entered folds. MJB: 22-Sep-89. */
- exitallfolds();
-
- /* Set foldmarker table pointer for this file type. MJB: 18-Sep-89 */
- tp = setfolds(curbp->b_ftype); /* BG: 11-Oct-89; dd may-91 */
- if (tp == NULL)
- if (fileisfolded() == TRUE) {
- mlwrite(TEXT237);
- return(FIODEL); /* Fail, no fold marks set */
- }
-
- /* determine if we will use the save method */
- sflag = FALSE;
- if (ssave && fexist(fn))
- sflag = TRUE;
-
- #if CRYPT
- /* set up for file encryption */
- status = resetkey();
- if (status != TRUE)
- return(status);
- #endif
-
- /* turn off ALL keyboard translation in case we get a dos error */
- TTkclose();
-
- /* Perform Safe Save..... */
- if (sflag) {
- /* duplicate original file name, and find where to trunc it */
- sp = tname + (makename(tname, fn) - fn) + 1;
- strcpy(tname, fn);
-
- /* create a unique name, using random numbers */
- do {
- *sp = 0;
- strcat(tname, int_asc(ernd()));
- } while(fexist(tname));
-
- /* open the temporary file */
- #if AOSVS
- status = ffwopen(fn, tname);
- #else
- status = ffwopen(tname);
- #endif
- } else
- #if AOSVS
- status = ffwopen(fn, NULL);
- #else
- status = ffwopen(fn);
- #endif
-
- /* if the open failed.. clean up and abort */
- if (status != FIOSUC) {
- TTkopen();
- return(FALSE);
- }
-
- /* write the current buffer's lines to the open disk file */
- mlwrite(TEXT148); /* tell us that we're writing */
- /* "[Writing...]" */
-
- /* Check to see if lines are open folds, and if so substitute the
- * markers for the fold symbol. MJB: 18-Sep-89.
- */
-
- lp = curbp->b_linep->l_fp; /* start at the first line. */
- nline = 0; /* track the Number of lines */
- while (lp != curbp->b_linep) {
- if (lp->l_type == LSOFOLD) {
- if ((pidx = indx(lp->l_text, FOLDSYMBOL)) != -1) {
- /* indentation */
- strncpy(str, lp->l_text, pidx);
- str[pidx] = '\0';
- /* fold symbol */
- strcat(str, tp->fm_startopen);
- /* comment */
- if (pidx + strlen(FOLDSYMBOL) < llength(lp))
- strncat(str,
- &lp->l_text[pidx + strlen(FOLDSYMBOL)],
- (llength(lp) - strlen(FOLDSYMBOL) - pidx));
- strcat(str, tp->fm_startclose);
- if ((status = ffputline(&str[0], strlen(str)))
- != FIOSUC)
- break;
- }
- else
- if ((status = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
- break;
- }
- else if (lp->l_type == LSOEFOLD) {
- if ((pidx = indx(lp->l_text, BEGINFOLD)) != -1) {
- /* indentation */
- strncpy(str, lp->l_text, pidx);
- str[pidx] = '\0';
- /* fold symbol */
- strcat(str, tp->fm_startopen);
- /* comment */
- if (pidx + strlen(BEGINFOLD) < llength(lp))
- strncat(str,
- &lp->l_text[pidx + strlen(FOLDSYMBOL)],
- (llength(lp) - strlen(FOLDSYMBOL) - pidx));
- strcat(str, tp->fm_startclose);
- if ((status = ffputline(&str[0], strlen(str)))
- != FIOSUC)
- break;
- }
- else
- if ((status = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
- break;
- }
- else if ((lp->l_type == LEOFOLD) || (lp->l_type == LEOEFOLD)) {
- if ((pidx = indx(lp->l_text, ENDFOLD)) != -1) {
- /* indentation */
- strncpy(str, lp->l_text, pidx);
- str[pidx] = '\0';
- /* fold symbol */
- strcat(str, tp->fm_end);
- /* trailer - from ned or the like! */
- if (pidx + strlen(ENDFOLD) < llength(lp))
- strncat(str, &lp->l_text[pidx + strlen(FOLDSYMBOL)],
- llength(lp) - strlen(ENDFOLD) - pidx);
- if ((status = ffputline(&str[0], strlen(str)))
- != FIOSUC)
- break;
- }
- else
- if ((status = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
- break;
- }
- else if ((status = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
- break;
- ++nline;
- lp = lp->l_fp;
- }
-
-
- /* report on status of file write */
- *buf = 0;
- status |= ffclose();
- if (status == FIOSUC) {
- /* report on success (or lack therof) */
- strcpy(buf, TEXT149);
- /* "[Wrote " */
- strcat(buf, int_asc(nline));
- strcat(buf, TEXT143);
- /* " line" */
- if (nline > 1)
- strcat(buf, "s");
-
- if (sflag) {
- /* erase original file */
- /* rename temporary file to original name */
- if (unlink(fn) == 0 && rename(tname, fn) == 0)
- ;
- else {
- strcat(buf, TEXT150);
- /* ", saved as " */
- strcat(buf, tname);
- status = FIODEL; /* failed */
- }
- }
- strcat(buf, "]");
- mlwrite(buf);
- }
-
- /* reopen the keyboard, and return our status */
- TTkopen();
- return(status == FIOSUC);
- }
- /*}}}*/
-
- /*{{{ PASCAL NEAR filename(f, n)*/
- PASCAL NEAR filename(f, n)
- /*
- * The command allows the user
- * to modify the file name associated with
- * the current buffer. It is like the "f" command
- * in UNIX "ed". The operation is simple; just zap
- * the name in the BUFFER structure, and mark the windows
- * as needing an update. You can type a blank line at the
- * prompt if you wish.
- */
-
-
- {
- register int s;
- char fname[NFILEN];
-
- if (restflag) /* don't allow this command if restricted */
- return(resterr());
- if ((s=mlreply(TEXT151, fname, NFILEN)) == ABORT)
- /* "Name: " */
- return(s);
- if (s == FALSE)
- strcpy(curbp->b_fname, "");
- else
- strcpy(curbp->b_fname, fname);
- /* Update mode lines. */
- upmode();
- curbp->b_mode &= ~MDVIEW; /* no longer read only mode */
- return(TRUE);
- }
- /*}}}*/
-
- /*{{{ PASCAL NEAR ifile(fname)*/
- PASCAL NEAR ifile(fname)
- /*
- * Insert file "fname" into the current
- * buffer, Called by insert file command. Return the final
- * status of the read.
- */
- char fname[];
- {
- register LINE *lp0;
- register LINE *lp1;
- register LINE *lp2;
- register int i;
- register BUFFER *bp;
- register int s;
- register int nbytes;
- register int nline;
- int cmark; /* current mark */
- char mesg[NSTRING];
- char str[NSTRING];
- register int pidx;
- register int lmargin;
- register FOLDMARKENT *tp;
- char ftype[NTYPEN];
-
- bp = curbp; /* Cheap. */
- if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */
- goto out;
- if (s == FIOFNF) { /* File not found. */
- mlwrite(TEXT152);
- /* "[No such file]" */
- return(FALSE);
- }
- mlwrite(TEXT153);
- /* "[Inserting file]" */
-
- #if CRYPT
- s = resetkey();
- if (s != TRUE)
- return(s);
- #endif
- if (getftype(fname, ftype))
- tp = setfolds(ftype);
-
- lmargin = 0;
-
- /* back up a line and save the mark here */
- curwp->w_dotp = curwp->w_dotp->l_bp;
- curwp->w_doto = 0;
- for (cmark = 0; cmark < NMARKS; cmark++) {
- curwp->w_markp[cmark] = curwp->w_dotp;
- curwp->w_marko[cmark] = 0;
- }
-
- nline = 0;
- while ((s=ffgetline()) == FIOSUC) {
- nbytes = strlen(fline);
- if ((lp1=lalloc(nbytes)) == NULL) {
- s = FIOMEM; /* Keep message on the */
- break; /* display. */
- }
-
- if ((tp != (FOLDMARKENT *)NULL) &&
- (pidx = indx(fline, tp->fm_startopen)) != -1) {
- /* offset */
- strncpy(str, fline, pidx);
- str[pidx] = '\0';
- /* fold symbol */
- strcat(str, FOLDSYMBOL);
- /* comment */
- strcat(str, &fline[pidx + strlen(tp->fm_startopen)]);
- /* make sure string is long enough to remove close */
- if ((strlen(str) - pidx - strlen(FOLDSYMBOL))
- >= strlen(tp->fm_startclose))
- str[strlen(str) - strlen(tp->fm_startclose)] = '\0';
- /* back to fline, and adjust byte count */
- strcpy(fline, str);
- nbytes = strlen(fline);
- lp1->l_used = nbytes;
- /* set line type, and record start of fold */
- lp1->l_type = LSOFOLD;
- lp1->l_lmargin = lmargin;
- lmargin = pidx;
- pushline(lp1);
- }
- else if ((tp != (FOLDMARKENT *)NULL) &&
- (pidx = indx(fline, tp->fm_end)) != -1) {
- if (linelist->fll_bp->fll_line != (LINE *)NULL) {
- /* offset */
- strncpy(str, fline, pidx);
- str[pidx] = '\0';
- /* fold symbol */
- strcat(str, ENDFOLD);
- /* back to fline, and adjust byte count */
- strcpy(fline, str);
- nbytes = strlen(fline);
- lp1->l_used = nbytes;
- /* set line type, and record start of fold */
- lp1->l_type = LEOFOLD;
- lp1->l_foldp = popline();
- lp1->l_foldp->l_foldp = lp1;
- lmargin = popmargin(lp1); /* recalculation */
- lp1->l_lmargin = lmargin;
- }
- else { /* Just to be safe! */
- lp1->l_type = LNORMAL;
- lp1->l_foldp = (LINE *)NULL;
- mlwrite(TEXT231);
- /* "Missing start-fold Marker */
- }
- }
- else {
- lp1->l_type = LNORMAL;
- lp1->l_foldp = (LINE *)NULL;
- lp1->l_lmargin = lmargin;
- }
-
- lp0 = curwp->w_dotp; /* line previous to insert */
- lp2 = lp0->l_fp; /* line after insert */
-
- /* re-link new line between lp0 and lp2 */
- lp2->l_bp = lp1;
- lp0->l_fp = lp1;
- lp1->l_bp = lp0;
- lp1->l_fp = lp2;
-
- /* and advance and write out the current line */
- curwp->w_dotp = lp1;
- for (i=0; i<nbytes; ++i)
- lputc(lp1, i, fline[i]);
- ++nline;
- }
-
- ffclose(); /* Ignore errors. */
- curwp->w_markp[0] = lforw(curwp->w_markp[0]);
- strcpy(mesg, "[");
-
- if (s==FIOERR) {
- strcat(mesg, TEXT141);
- /* "I/O ERROR, " */
- curbp->b_flag |= BFTRUNC;
- }
- if (s == FIOMEM) {
- strcat(mesg, TEXT142);
- /* "OUT OF MEMORY, " */
- curbp->b_flag |= BFTRUNC;
- }
- strcat(mesg, TEXT154);
- /* "Inserted " */
- strcat(mesg, int_asc(nline));
- strcat(mesg, TEXT143);
- /* " line" */
- if (nline > 1)
- strcat(mesg, "s");
- strcat(mesg, "]");
- mlwrite(mesg);
-
- out:
- bp->b_flag |= BFCHG; /* we have changed */
- bp->b_flag &= ~BFINVS; /* and are not temporary*/
-
- /* advance to the next line and mark the window for changes */
- curwp->w_dotp = lforw(curwp->w_dotp);
- curwp->w_flag |= WFHARD | WFMODE;
-
- /* copy window parameters back to the buffer structure */
- curbp->b_dotp = curwp->w_dotp;
- curbp->b_doto = curwp->w_doto;
- for (cmark = 0; cmark < NMARKS; cmark++) {
- curbp->b_markp[cmark] = curwp->w_markp[cmark];
- curbp->b_marko[cmark] = curwp->w_marko[cmark];
- }
- curbp->b_fcol = curwp->w_fcol;
-
- if (s == FIOERR) /* False if error. */
- return(FALSE);
- return(TRUE);
- }
- /*}}}*/
-
-