📄 io.c
字号:
/*************************************************************************** * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * * is provided to you without charge, and with no warranty. You may give * * away copies of JOVE, including sources, provided that this notice is * * included in all the files. * ***************************************************************************/#include "jove.h"#include "list.h"#include "fp.h"#include "termcap.h"#include "ctype.h"#include "disp.h"#include "scandir.h"#ifdef IPROCS# include <signal.h>#endif#ifdef MAC# include "mac.h"#else# include <sys/stat.h>#endif#ifdef UNIX# include <sys/file.h>#endif#ifdef MSDOS# include <fcntl.h># include <io.h># include <direct.h># include <dos.h>#endif /* MSDOS */#include <errno.h>private struct block *lookup proto((int /* promoted short */));private char#ifdef MSDOS *fixpath proto((char *)),#endif *getblock proto((daddr, bool));private bool f_getputl proto((struct line *line,struct FileStruct *fp));private void#ifdef MSDOS abspath proto((char *, char *)),#endif file_backup proto((char *fname));#ifdef MSDOSprivate int Dchdir proto((char *));#endiflong io_chars; /* number of chars in this open_file */int io_lines; /* number of lines in this open_file */#ifdef pdp11char *iobuff, *genbuf, *linebuf;#elsechar iobuff[LBSIZE], genbuf[LBSIZE], linebuf[LBSIZE];#endif#ifdef BACKUPFILESbool BkupOnWrite = OFF;#endif#ifndef MSDOS#define Dchdir(to) chdir(to)#else /* MSDOS */private int /* chdir + drive */Dchdir(to)char *to;{ unsigned d, dd, n; if (to[1] == ':') { d = CharUpcase(to[0]) - 'A'; /* ??? only 16 drives? */ if (d >= 16) complain("invalid drive"); _dos_getdrive(&dd); if (dd != d) _dos_setdrive(d, &n); if (to[2] == '\0') { /* ??? Is this correct? DHR * Current path on this drive might not be the root. */ return 0; } } return chdir(to);}private char *fixpath(p)char *p;{ char *pp = p; while (*p) { if (*p == '\\') *p = '/'; p++; } return strlwr(pp);}private voidabspath(so, dest)char *so, *dest;{ char cwd[FILESIZE], cwdD[3], cwdDIR[FILESIZE], cwdF[9], cwdEXT[5], soD[3], soDIR[FILESIZE], soF[9], soEXT[5]; char *drive, *path; _splitpath(fixpath(so), soD, soDIR, soF, soEXT); getcwd(cwd, FILESIZE); if (*soD != '\0') { Dchdir(soD); /* this is kinda messy */ getcwd(cwdDIR, FILESIZE); /* should probably just */ Dchdir(cwd); /* call DOS to do it */ strcpy(cwd, cwdDIR); } (void) fixpath(cwd); if (cwd[strlen(cwd)-1] != '/') strcat(cwd, "/x.x"); /* need dummy filename */ _splitpath(fixpath(cwd), cwdD, cwdDIR, cwdF, cwdEXT); drive = (*soD == '\0') ? cwdD : soD; if (*soDIR != '/') path = strcat(cwdDIR, soDIR); else path = soDIR; _makepath(dest, drive, path, soF, soEXT); fixpath(dest); /* can't do it often enough */}#endif /* MSDOS */voidclose_file(fp)File *fp;{ if (fp) { if (fp->f_flags & F_TELLALL) add_mess(" %d lines, %D characters.", io_lines, io_chars); f_close(fp); }}/* Write the region from line1/char1 to line2/char2 to FP. This never CLOSES the file since we don't know if we want to. */bool EndWNewline = 1;voidputreg(fp, line1, char1, line2, char2, makesure)register File *fp;Line *line1, *line2;int char1, char2;bool makesure;{ register int c; register char *lp; if (makesure) (void) fixorder(&line1, &char1, &line2, &char2); while (line1 != line2->l_next) { lp = lcontents(line1) + char1; if (line1 == line2) { fputnchar(lp, (char2 - char1), fp); io_chars += (char2 - char1); } else { while ((c = *lp++) != '\0') { jputc(c, fp); io_chars += 1; } } if (line1 != line2) { io_lines += 1; io_chars += 1;#ifdef MSDOS jputc('\r', fp);#endif /* MSDOS */ jputc('\n', fp); } line1 = line1->l_next; char1 = 0; } flushout(fp);}private voiddofread(fp)register File *fp;{ char end[LBSIZE]; bool xeof; Line *savel = curline; int savec = curchar; strcpy(end, linebuf + curchar); xeof = f_gets(fp, linebuf + curchar, (size_t) (LBSIZE - curchar)); SavLine(curline, linebuf); while(!xeof) { curline = listput(curbuf, curline); xeof = f_getputl(curline, fp); } getDOT(); linecopy(linebuf, (curchar = strlen(linebuf)), end); SavLine(curline, linebuf); IFixMarks(savel, savec, curline, curchar);}voidread_file(file, is_insert)char *file;bool is_insert;{ Bufpos save; File *fp; int rdonly; if (!is_insert) curbuf->b_ntbf = NO; fp = open_file(file, iobuff, F_READ, NO, NO); if (fp == NULL) { if (!is_insert && errno == ENOENT) s_mess("(new file)"); else s_mess(IOerr("open", file)); return; } rdonly = (fp->f_flags & F_READONLY)? 1 : 0; DOTsave(&save); dofread(fp); if (is_insert && io_chars > 0) { modify(); set_mark(); } SetDot(&save); getDOT(); close_file(fp); /* just guessing that if this is moved here */ /* then the bug on SunOS that seems to alter */ /* mtime under our feet will disappear */ if (!is_insert) { set_ino(curbuf); set_arg_value(rdonly); TogMinor(ReadOnly); }}voidSaveFile(){ if (IsModified(curbuf)) { if (curbuf->b_fname == NULL) WriteFile(); else { filemunge(curbuf->b_fname); chk_mtime(curbuf, curbuf->b_fname, "save"); file_write(curbuf->b_fname, NO); } } else message("No changes need to be written.");}char *HomeDir; /* home directory */size_t HomeLen; /* length of home directory string */private List *DirStack = NULL;#define dir_name(dp) ((char *) list_data((dp)))#define PWD_PTR (list_data(DirStack))#define PWD ((char *) PWD_PTR)char *pwd(){ return (char *) PWD_PTR;}char *pr_name(fname, okay_home)char *fname;int okay_home;{ int n; if (fname != NULL) { n = numcomp(fname, PWD); if ((PWD[n] == '\0') && /* Matched to end of PWD */ (fname[n] == '/')) return fname + n + 1; if (okay_home && strcmp(HomeDir, "/") != 0 && strncmp(fname, HomeDir, HomeLen) == 0 && fname[HomeLen] == '/') { static char name_buf[100]; swritef(name_buf, sizeof(name_buf), "~%s", fname + HomeLen); return name_buf; } } return fname;}voidChdir(){ char dirbuf[FILESIZE];#ifdef MSDOS fmask = 0x10;#endif (void) ask_file((char *)NULL, PWD, dirbuf);#ifdef MSDOS fmask = 0x13;#endif if (Dchdir(dirbuf) == -1) { s_mess("cd: cannot change into %s.", dirbuf); return; } UpdModLine = YES; setCWD(dirbuf); prCWD();#ifdef MAC Bufchange = YES;#endif}#ifdef UNIX# ifndef BSD4_2char *getwd(buffer)char *buffer;{ Buffer *old = curbuf; char *ret_val; SetBuf(do_select((Window *)NULL, "pwd-output")); curbuf->b_type = B_PROCESS; (void) UnixToBuf("pwd-output", (char *)NULL, NO, 0, YES, "/bin/pwd", (char *) NULL); ToFirst(); strcpy(buffer, linebuf); SetBuf(old); return buffer;}# endif /* not BSD4_2 *//* Check if dn is the name of the current working directory and that it is in cannonical form */boolchkCWD(dn)char *dn;{ char filebuf[FILESIZE]; struct stat dnstat, dotstat; if (dn[0] != '/') return FALSE; /* need absolute pathname */ PathParse(dn, filebuf); return stat(filebuf, &dnstat) == 0 && stat(".", &dotstat) == 0 && dnstat.st_dev == dotstat.st_dev && dnstat.st_ino == dotstat.st_ino;}#endif /* UNIX */voidsetCWD(d)char *d;{ if (DirStack == NULL) list_push(&DirStack, (UnivPtr)NULL); PWD_PTR = (PWD == NULL) ? (UnivPtr) emalloc((size_t) (strlen(d) + 1)) : (UnivPtr) freealloc((UnivPtr) PWD, strlen(d) + 1); strcpy(PWD, d);}voidgetCWD(){ char *cwd; char pathname[FILESIZE];#ifndef MSDOS cwd = getenv("CWD"); if (cwd == NULL || !chkCWD(cwd)) { cwd = getenv("PWD"); if (cwd == NULL || !chkCWD(cwd)) {#ifdef HAVE_GETWD cwd = getwd(pathname);#else /* System Vr4, and who else? */ extern char *getcwd proto((char *, int/*!!!*/)); cwd = getcwd(pathname, (int) sizeof(pathname));#endif /* HAVE_GETWD */ } }#else /* MSDOS */ { extern char *getcwd(); cwd = fixpath(getcwd(pathname, FILESIZE)); }#endif /* MSDOS */ setCWD(cwd);}voidprDIRS(){ register List *lp; s_mess(": %f "); for (lp = DirStack; lp != NULL; lp = list_next(lp)) add_mess("%s ", pr_name(dir_name(lp), YES));}voidprCWD(){ s_mess(": %f => \"%s\"", PWD);}voidPushd(){ char *newdir, dirbuf[FILESIZE];#ifdef MSDOS fmask = 0x10;#endif newdir = ask_file((char *)NULL, NullStr, dirbuf);#ifdef MSDOS fmask = 0x13;#endif UpdModLine = YES; if (*newdir == '\0') { /* Wants to swap top two entries */ char *old_top; if (list_next(DirStack) == NULL) complain("pushd: no other directory."); old_top = PWD; list_data(DirStack) = (UnivPtr) dir_name(list_next(DirStack)); list_data(list_next(DirStack)) = (UnivPtr) old_top; (void) Dchdir(PWD); } else { if (Dchdir(dirbuf) == -1) { s_mess("pushd: cannot change into %s.", dirbuf); return; } (void) list_push(&DirStack, (UnivPtr)NULL); setCWD(dirbuf); } prDIRS();}voidPopd(){ if (list_next(DirStack) == NULL) complain("popd: directory stack is empty."); UpdModLine = YES; free((UnivPtr) list_pop(&DirStack)); (void) Dchdir(PWD); /* If this doesn't work, we's in deep shit. */ prDIRS();}private voiddfollow(file, into)char *file, *into;{ char *dp, *sp;#ifndef MSDOS if (*file == '/') { /* Absolute pathname */ strcpy(into, "/"); file += 1; } else { strcpy(into, PWD); }#else /* MSDOS */ char filefix[FILESIZE]; abspath(file, filefix); /* convert to absolute pathname */ strcpy(into, filefix); /* and forget about drives */ into[3] = '\0'; into = &(into[2]); file = &(filefix[3]);#endif /* MSDOS */ dp = into + strlen(into); for (;;) { if (*file == '\0') break; if ((sp = strchr(file, '/')) != NULL) *sp = '\0'; if (*file == '\0' || strcmp(file, ".") == 0) { /* So it will get to the end of the loop */ } else if (strcmp(file, "..") == 0) { for (;;) { if (dp == into) { *dp++ = '/'; break; } if (*--dp == '/') break; } *dp = '\0'; } else { if (dp!=into && dp[-1]!='/') *dp++ = '/'; strcpy(dp, file); dp += strlen(dp); /* stay at the end */ } if (sp == NULL) break; file = sp + 1; }}#ifdef UNIX# ifdef YP_PASSWD#include <pwd.h>private voidget_hdir(user, buf)register char *user, *buf;{ struct passwd *p; p = getpwnam(user); endpwent(); if (p == NULL) { add_mess(" [unknown user: %s]", user); SitFor(7); complain((char *)NULL); /* NOTREACHED */ } strcpy(buf, p->pw_dir);}#else#include "re.h"private voidget_hdir(user, buf)register char *user, *buf;{ char fbuf[LBSIZE], pattern[100]; register int u_len; File *fp; u_len = strlen(user); fp = open_file("/etc/passwd", fbuf, F_READ, YES, YES); swritef(pattern, sizeof(pattern), "%s:[^:]*:[^:]*:[^:]*:[^:]*:\\([^:]*\\):", user); while (!f_gets(fp, genbuf, LBSIZE)) if ((strncmp(genbuf, user, u_len) == 0) && LookingAt(pattern, genbuf, 0)) { putmatch(1, buf, FILESIZE); close_file(fp); return; } close_file(fp); add_mess(" [unknown user: %s]", user); SitFor(7); complain((char *)NULL);}#endif /* YP_PASSWD */#endif /* UNIX */voidPathParse(name, intobuf)char *name, *intobuf;{ char localbuf[FILESIZE]; intobuf[0] = localbuf[0] = '\0'; if (*name == '\0') return; if (*name == '~') { if (name[1] == '/' || name[1] == '\0') { strcpy(localbuf, HomeDir); name += 1; }#ifdef UNIX /* may add for mac in future */ else { char *uendp = strchr(name, '/'), unamebuf[30]; if (uendp == NULL) uendp = name + strlen(name); name += 1; null_ncpy(unamebuf, name, (size_t) (uendp - name)); get_hdir(unamebuf, localbuf); name = uendp; }#endif#ifndef MSDOS } else if (*name == '\\') { /* allow quoting of ~ (but \ is a path separator in MSDOS) */ name += 1;#endif /* MSDOS */ } (void) strcat(localbuf, name); dfollow(localbuf, intobuf);}voidfilemunge(newname)char *newname;{ struct stat stbuf; if (newname == NULL) return; if (stat(newname, &stbuf)) return; if (#ifndef MSDOS ((stbuf.st_dev != curbuf->b_dev) || (stbuf.st_ino != curbuf->b_ino)) &&#endif /* !MSDOS */#ifndef MAC ((stbuf.st_mode & S_IFMT) != S_IFCHR) &&#endif /* !MAC */ (curbuf->b_fname==NULL || strcmp(newname, curbuf->b_fname) != 0)) { rbell(); confirm("\"%s\" already exists; overwrite it? ", newname); }}int CreatMode = DFLT_MODE;private voidDoWriteReg(app)bool app;{ char fnamebuf[FILESIZE], *fname; Mark *mp = CurMark(); File *fp; /* Won't get here if there isn't a Mark */ fname = ask_file((char *)NULL, (char *)NULL, fnamebuf);#ifdef BACKUPFILES if (app == NO) { filemunge(fname); if (BkupOnWrite) file_backup(fname); }#else if (!app) filemunge(fname);#endif fp = open_file(fname, iobuff, app ? F_APPEND : F_WRITE, YES, NO); putreg(fp, mp->m_line, mp->m_char, curline, curchar, YES); close_file(fp);}voidWrtReg(){ DoWriteReg(NO);}voidAppReg(){ DoWriteReg(YES);}bool OkayBadChars = NO;voidWriteFile(){ char *fname,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -