/* * This routine rebuilds the text for the * list buffers command. Return pointer * to new list if everything works. * Return NULL if there is an error (if * there is no memory). */ static struct buffer * makelist(void) { int w = ncol / 2; struct buffer *bp, *blp; struct line *lp; if ((blp = bfind("*Buffer List*", TRUE)) == NULL) return (NULL); if (bclear(blp) != TRUE) return (NULL); blp->b_flag &= ~BFCHG; /* Blow away old. */ blp->b_flag |= BFREADONLY; listbuf_ncol = ncol; /* cache ncol for listbuf_goto_buffer */ if (addlinef(blp, "%-*s%s", w, " MR Buffer", "Size File") == FALSE || addlinef(blp, "%-*s%s", w, " -- ------", "---- ----") == FALSE) return (NULL); for (bp = bheadp; bp != NULL; bp = bp->b_bufp) { RSIZE nbytes; nbytes = 0; /* Count bytes in buf. */ if (bp != blp) { lp = bfirstlp(bp); while (lp != bp->b_headp) { nbytes += llength(lp) + 1; lp = lforw(lp); } if (nbytes) nbytes--; /* no bonus newline */ } if (addlinef(blp, "%c%c%c %-*.*s%c%-6d %-*s", (bp == curbp) ? '.' : ' ', /* current buffer ? */ ((bp->b_flag & BFCHG) != 0) ? '*' : ' ', /* changed ? */ ((bp->b_flag & BFREADONLY) != 0) ? ' ' : '*', w - 5, /* four chars already written */ w - 5, /* four chars already written */ bp->b_bname, /* buffer name */ strlen(bp->b_bname) < w - 5 ? ' ' : '$', /* truncated? */ nbytes, /* buffer size */ w - 7, /* seven chars already written */ bp->b_fname) == FALSE) return (NULL); } blp->b_dotp = bfirstlp(blp); /* put dot at beginning of * buffer */ blp->b_doto = 0; return (blp); /* All done */ }
/* ARGSUSED */ int d_expunge(int f, int n) { struct line *lp, *nlp; char fname[NFILEN]; for (lp = bfirstlp(curbp); lp != curbp->b_headp; lp = nlp) { nlp = lforw(lp); if (llength(lp) && lgetc(lp, 0) == 'D') { switch (d_makename(lp, fname, sizeof(fname))) { case ABORT: ewprintf("Bad line in dired buffer"); return (FALSE); case FALSE: if (unlink(fname) < 0) { ewprintf("Could not delete '%s'", basename(fname)); return (FALSE); } break; case TRUE: if (rmdir(fname) < 0) { ewprintf("Could not delete directory '%s'", basename(fname)); return (FALSE); } break; } lfree(lp); curwp->w_bufp->b_lines--; curwp->w_flag |= WFFULL; } } return (TRUE); }
/* * Read the file "fname" into the current buffer. Make all of the text * in the buffer go away, after checking for unsaved changes. This is * called by the "read" command, the "visit" command, and the mainline * (for "mg file"). */ int readin(char *fname) { struct mgwin *wp; int status, i, ro = FALSE; PF *ael; /* might be old */ if (bclear(curbp) != TRUE) return (TRUE); /* Clear readonly. May be set by autoexec path */ curbp->b_flag &= ~BFREADONLY; if ((status = insertfile(fname, fname, TRUE)) != TRUE) { ewprintf("File is not readable: %s", fname); return (FALSE); } for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { if (wp->w_bufp == curbp) { if ((fisdir(fname)) != TRUE) { wp->w_dotp = wp->w_linep = bfirstlp(curbp); wp->w_doto = 0; wp->w_markp = NULL; wp->w_marko = 0; } } } /* * Call auto-executing function if we need to. */ if ((ael = find_autoexec(fname)) != NULL) { for (i = 0; ael[i] != NULL; i++) (*ael[i])(0, 1); free(ael); } /* no change */ curbp->b_flag &= ~BFCHG; /* * We need to set the READONLY flag after we insert the file, * unless the file is a directory. */ if (access(fname, W_OK) && errno != ENOENT) ro = TRUE; if (fisdir(fname) == TRUE) ro = TRUE; if (ro == TRUE) curbp->b_flag |= BFREADONLY; if (startrow) { gotoline(FFARG, startrow); startrow = 0; } undo_add_modified(); return (status); }
/* * Go to the beginning of the * buffer. Setting WFFULL is conservative, * but almost always the case. */ int gotobob(int f, int n) { (void) setmark(f, n); curwp->w_dotp = bfirstlp(curbp); curwp->w_doto = 0; curwp->w_rflag |= WFFULL; curwp->w_dotline = 1; return (TRUE); }
/* ARGSUSED */ int bufferinsert(int f, int n) { struct buffer *bp; struct line *clp; int clo, nline; char bufn[NBUFN], *bufp; /* Get buffer to use from user */ if (curbp->b_altb != NULL) bufp = eread("Insert buffer: (default %s) ", bufn, NBUFN, EFNUL | EFNEW | EFBUF, curbp->b_altb->b_bname); else bufp = eread("Insert buffer: ", bufn, NBUFN, EFNEW | EFBUF); if (bufp == NULL) return (ABORT); if (bufp[0] == '\0' && curbp->b_altb != NULL) bp = curbp->b_altb; else if ((bp = bfind(bufn, FALSE)) == NULL) return (FALSE); if (bp == curbp) { dobeep(); ewprintf("Cannot insert buffer into self"); return (FALSE); } /* insert the buffer */ nline = 0; clp = bfirstlp(bp); for (;;) { for (clo = 0; clo < llength(clp); clo++) if (linsert(1, lgetc(clp, clo)) == FALSE) return (FALSE); if ((clp = lforw(clp)) == bp->b_headp) break; if (enewline(FFRAND, 1) == FALSE) /* fake newline */ return (FALSE); nline++; } if (nline == 1) ewprintf("[Inserted 1 line]"); else ewprintf("[Inserted %d lines]", nline); clp = curwp->w_linep; /* cosmetic adjustment */ if (curwp->w_dotp == clp) { /* for offscreen insert */ while (nline-- && lback(clp) != curbp->b_headp) clp = lback(clp); curwp->w_linep = clp; /* adjust framing. */ curwp->w_rflag |= WFFULL; } return (TRUE); }
/* * Popbuf and set all windows to top of buffer. */ int popbuftop(struct buffer *bp, int flags) { struct mgwin *wp; bp->b_dotp = bfirstlp(bp); bp->b_doto = 0; if (bp->b_nwnd != 0) { for (wp = wheadp; wp != NULL; wp = wp->w_wndp) if (wp->w_bufp == bp) { wp->w_dotp = bp->b_dotp; wp->w_doto = 0; wp->w_rflag |= WFFULL; } } return (popbuf(bp, flags) != NULL); }
/* ARGSUSED */ int evalbuffer(int f, int n) { struct line *lp; struct buffer *bp = curbp; int s; static char excbuf[128]; for (lp = bfirstlp(bp); lp != bp->b_headp; lp = lforw(lp)) { if (llength(lp) >= 128) return (FALSE); (void)strncpy(excbuf, ltext(lp), llength(lp)); /* make sure it's terminated */ excbuf[llength(lp)] = '\0'; if ((s = excline(excbuf)) != TRUE) return (s); } return (TRUE); }
/* * Incremental Search. * dir is used as the initial direction to search. * ^S switch direction to forward * ^R switch direction to reverse * ^Q quote next character (allows searching for ^N etc.) * <ESC> exit from Isearch * <DEL> undoes last character typed. (tricky job to do this correctly). * other ^ exit search, don't set mark * else accumulate into search string */ static int isearch(int dir) { struct line *clp; /* Saved line pointer */ int c; int cbo; /* Saved offset */ int success; int pptr; int firstc; int xcase; int i; char opat[NPAT]; int cdotline; /* Saved line number */ #ifndef NO_MACRO if (macrodef) { ewprintf("Can't isearch in macro"); return (FALSE); } #endif /* !NO_MACRO */ for (cip = 0; cip < NSRCH; cip++) cmds[cip].s_code = SRCH_NOPR; (void)strlcpy(opat, pat, sizeof(opat)); cip = 0; pptr = -1; clp = curwp->w_dotp; cbo = curwp->w_doto; cdotline = curwp->w_dotline; is_lpush(); is_cpush(SRCH_BEGIN); success = TRUE; is_prompt(dir, TRUE, success); for (;;) { update(); switch (c = getkey(FALSE)) { case CCHR('['): /* * If new characters come in the next 300 msec, * we can assume that they belong to a longer * escaped sequence so we should ungetkey the * ESC to avoid writing out garbage. */ if (ttwait(300) == FALSE) ungetkey(c); srch_lastdir = dir; curwp->w_markp = clp; curwp->w_marko = cbo; curwp->w_markline = cdotline; ewprintf("Mark set"); return (TRUE); case CCHR('G'): if (success != TRUE) { while (is_peek() == SRCH_ACCM) is_undo(&pptr, &dir); success = TRUE; is_prompt(dir, pptr < 0, success); break; } curwp->w_dotp = clp; curwp->w_doto = cbo; curwp->w_dotline = cdotline; curwp->w_rflag |= WFMOVE; srch_lastdir = dir; (void)ctrlg(FFRAND, 0); (void)strlcpy(pat, opat, sizeof(pat)); return (ABORT); case CCHR('S'): if (dir == SRCH_BACK) { dir = SRCH_FORW; is_lpush(); is_cpush(SRCH_FORW); success = TRUE; } if (success == FALSE && dir == SRCH_FORW) { /* wrap the search to beginning */ curwp->w_dotp = bfirstlp(curbp); curwp->w_doto = 0; curwp->w_dotline = 1; if (is_find(dir) != FALSE) { is_cpush(SRCH_MARK); success = TRUE; } ewprintf("Overwrapped I-search: %s", pat); break; } is_lpush(); pptr = strlen(pat); (void)forwchar(FFRAND, 1); if (is_find(SRCH_FORW) != FALSE) is_cpush(SRCH_MARK); else { (void)backchar(FFRAND, 1); ttbeep(); success = FALSE; ewprintf("Failed I-search: %s", pat); } is_prompt(dir, pptr < 0, success); break; case CCHR('R'): if (dir == SRCH_FORW) { dir = SRCH_BACK; is_lpush(); is_cpush(SRCH_BACK); success = TRUE; } if (success == FALSE && dir == SRCH_BACK) { /* wrap the search to end */ curwp->w_dotp = blastlp(curbp); curwp->w_doto = llength(curwp->w_dotp); curwp->w_dotline = curwp->w_bufp->b_lines; if (is_find(dir) != FALSE) { is_cpush(SRCH_MARK); success = TRUE; } ewprintf("Overwrapped I-search: %s", pat); break; } is_lpush(); pptr = strlen(pat); (void)backchar(FFRAND, 1); if (is_find(SRCH_BACK) != FALSE) is_cpush(SRCH_MARK); else { (void)forwchar(FFRAND, 1); ttbeep(); success = FALSE; } is_prompt(dir, pptr < 0, success); break; case CCHR('W'): /* add the rest of the current word to the pattern */ clp = curwp->w_dotp; cbo = curwp->w_doto; firstc = 1; if (pptr == -1) pptr = 0; if (dir == SRCH_BACK) { /* when isearching backwards, cbo is the start of the pattern */ cbo += pptr; } /* if the search is case insensitive, add to pattern using lowercase */ xcase = 0; for (i = 0; pat[i]; i++) if (ISUPPER(CHARMASK(pat[i]))) xcase = 1; while (cbo < llength(clp)) { c = lgetc(clp, cbo++); if ((!firstc && !isalnum(c))) break; if (pptr == NPAT - 1) { ttbeep(); break; } firstc = 0; if (!xcase && ISUPPER(c)) c = TOLOWER(c); pat[pptr++] = c; pat[pptr] = '\0'; /* cursor only moves when isearching forwards */ if (dir == SRCH_FORW) { curwp->w_doto = cbo; curwp->w_rflag |= WFMOVE; update(); } } is_prompt(dir, pptr < 0, success); break; case CCHR('H'): case CCHR('?'): is_undo(&pptr, &dir); if (is_peek() != SRCH_ACCM) success = TRUE; is_prompt(dir, pptr < 0, success); break; case CCHR('\\'): case CCHR('Q'): c = (char)getkey(FALSE); goto addchar; case CCHR('M'): c = CCHR('J'); goto addchar; default: if (ISCTRL(c)) { ungetkey(c); curwp->w_markp = clp; curwp->w_marko = cbo; curwp->w_markline = cdotline; ewprintf("Mark set"); curwp->w_rflag |= WFMOVE; return (TRUE); } /* FALLTHRU */ case CCHR('I'): case CCHR('J'): addchar: if (pptr == -1) pptr = 0; if (pptr == 0) success = TRUE; if (pptr == NPAT - 1) ttbeep(); else { pat[pptr++] = c; pat[pptr] = '\0'; } is_lpush(); if (success != FALSE) { if (is_find(dir) != FALSE) is_cpush(c); else { success = FALSE; ttbeep(); is_cpush(SRCH_ACCM); } } else is_cpush(SRCH_ACCM); is_prompt(dir, FALSE, success); } } /* NOTREACHED */ }
/* * Read the file "fname" into the current buffer. Make all of the text * in the buffer go away, after checking for unsaved changes. This is * called by the "read" command, the "visit" command, and the mainline * (for "mg file"). */ int readin(char *fname) { struct mgwin *wp; struct stat statbuf; int status, ro = FALSE; char dp[NFILEN]; /* might be old */ if (bclear(curbp) != TRUE) return (TRUE); /* Clear readonly. May be set by autoexec path */ curbp->b_flag &= ~BFREADONLY; if ((status = insertfile(fname, fname, TRUE)) != TRUE) { dobeep(); ewprintf("File is not readable: %s", fname); return (FALSE); } for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { if (wp->w_bufp == curbp) { wp->w_dotp = wp->w_linep = bfirstlp(curbp); wp->w_doto = 0; wp->w_markp = NULL; wp->w_marko = 0; } } /* no change */ curbp->b_flag &= ~BFCHG; /* * Set the buffer READONLY flag if any of following are true: * 1. file is a directory. * 2. file is read-only. * 3. file doesn't exist and directory is read-only. */ if (fisdir(fname) == TRUE) { ro = TRUE; } else if ((access(fname, W_OK) == -1)) { if (errno != ENOENT) { ro = TRUE; } else if (errno == ENOENT) { (void)xdirname(dp, fname, sizeof(dp)); (void)strlcat(dp, "/", sizeof(dp)); /* Missing directory; keep buffer rw, like emacs */ if (stat(dp, &statbuf) == -1 && errno == ENOENT) { if (eyorn("Missing directory, create") == TRUE) (void)do_makedir(dp); } else if (access(dp, W_OK) == -1 && errno == EACCES) { ewprintf("File not found and directory" " write-protected"); ro = TRUE; } } } if (ro == TRUE) curbp->b_flag |= BFREADONLY; if (startrow) { gotoline(FFARG, startrow); startrow = 0; } undo_add_modified(); return (status); }
struct buffer * compile_mode(const char *name, const char *command) { struct buffer *bp; FILE *fpipe; char *buf; size_t len; int ret, n; char cwd[NFILEN], qcmd[NFILEN]; char timestr[NTIME]; time_t t; n = snprintf(qcmd, sizeof(qcmd), "%s 2>&1", command); if (n < 0 || n >= sizeof(qcmd)) return (NULL); bp = bfind(name, TRUE); if (bclear(bp) != TRUE) return (NULL); if (getbufcwd(bp->b_cwd, sizeof(bp->b_cwd)) != TRUE) return (NULL); addlinef(bp, "cd %s", bp->b_cwd); addline(bp, qcmd); addline(bp, ""); if (getcwd(cwd, sizeof(cwd)) == NULL) panic("Can't get current directory!"); if (chdir(bp->b_cwd) == -1) { dobeep(); ewprintf("Can't change dir to %s", bp->b_cwd); return (NULL); } if ((fpipe = popen(qcmd, "r")) == NULL) { dobeep(); ewprintf("Problem opening pipe"); return (NULL); } /* * We know that our commands are nice and the last line will end with * a \n, so we don't need to try to deal with the last line problem * in fgetln. */ while ((buf = fgetln(fpipe, &len)) != NULL) { buf[len - 1] = '\0'; addline(bp, buf); } ret = pclose(fpipe); t = time(NULL); strftime(timestr, sizeof(timestr), "%a %b %e %T %Y", localtime(&t)); addline(bp, ""); if (ret != 0) addlinef(bp, "Command exited abnormally with code %d" " at %s", ret, timestr); else addlinef(bp, "Command finished at %s", timestr); bp->b_dotp = bfirstlp(bp); bp->b_modes[0] = name_mode("fundamental"); bp->b_modes[1] = name_mode("compile"); bp->b_nmodes = 1; compile_buffer = bp; if (chdir(cwd) == -1) { dobeep(); ewprintf("Can't change dir back to %s", cwd); return (NULL); } return (bp); }
/* * XXX dname needs to have enough place to store an additional '/'. */ struct buffer * dired_(char *dname) { struct buffer *bp; FILE *dirpipe; char line[256]; int len, ret; #ifdef MONA DIR *dirp; struct dirent *dent; char* month_names[] = {"Jan", "Feb" ,"Mar" ,"Apr" ,"May" ,"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; #endif if ((dname = adjustname(dname, FALSE)) == NULL) { ewprintf("Bad directory name"); return (NULL); } /* this should not be done, instead adjustname() should get a flag */ len = strlen(dname); if (dname[len - 1] != '/') { dname[len++] = '/'; dname[len] = '\0'; } if ((bp = findbuffer(dname)) == NULL) { ewprintf("Could not create buffer"); return (NULL); } if (bclear(bp) != TRUE) return (NULL); bp->b_flag |= BFREADONLY; #ifdef MONA dirp = opendir(dname); assert(dirp); while ((dent = readdir(dirp)) != NULL) { snprintf(line, sizeof(line), "%s/%s", dname, dent->d_name); int year, month, day, hour, min, sec, size; mona_get_file_datetime_size(line, &year, &month, &day, &hour, &min, &sec, &size); char* month_name; if (month <= 12 && month >= 1) { month_name = month_names[month - 1]; } else { // assert(0); month_name = "---"; } snprintf(line, sizeof(line), " %crwxrwxrwx 1 mona mona %d %s %02d %02d:%02d %s", fisdir(line) ? 'd' : '-', size, month_name, day, hour, min, dent->d_name); addline(bp, line); } closedir(dirp); #else #ifdef GNU_LS # ifdef __CYGWIN__ /* On Windows platforms the user or group name can be two * words, such as "Domain Users" or "First Last." So, we must * use the --numeric-uid-gid option of ls, or else we don't * know where the filename starts. */ ret = snprintf(line, sizeof(line), "ls -aln --time-style='+%%b %%d %%H:%%M' '%s'", dname); # else ret = snprintf(line, sizeof(line), "ls -al --time-style='+%%b %%d %%H:%%M' '%s'", dname); # endif #else ret = snprintf(line, sizeof(line), "ls -al '%s'", dname); #endif /* GNU_LS */ if (ret < 0 || ret >= sizeof(line)) { ewprintf("Path too long"); return (NULL); } if ((dirpipe = popen(line, "r")) == NULL) { ewprintf("Problem opening pipe to ls"); return (NULL); } line[0] = line[1] = ' '; while (fgets(&line[2], sizeof(line) - 2, dirpipe) != NULL) { line[strcspn(line, "\n")] = '\0'; /* remove ^J */ (void) addline(bp, line); } if (pclose(dirpipe) == -1) { ewprintf("Problem closing pipe to ls : %s", strerror(errno)); return (NULL); } #endif bp->b_dotp = bfirstlp(bp); (void)strlcpy(bp->b_fname, dname, sizeof(bp->b_fname)); (void)strlcpy(bp->b_cwd, dname, sizeof(bp->b_cwd)); if ((bp->b_modes[1] = name_mode("dired")) == NULL) { bp->b_modes[0] = name_mode("fundamental"); ewprintf("Could not find mode dired"); return (NULL); } bp->b_nmodes = 1; return (bp); }