/* * Set the line number and switch to it. */ int setlineno(int n) { struct line *clp; if (n >= 0) { if (n == 0) n++; curwp->w_dotline = n; clp = lforw(curbp->b_headp); /* "clp" is first line */ while (--n > 0) { if (lforw(clp) == curbp->b_headp) { curwp->w_dotline = curwp->w_bufp->b_lines; break; } clp = lforw(clp); } } else { curwp->w_dotline = curwp->w_bufp->b_lines + n; clp = lback(curbp->b_headp); /* "clp" is last line */ while (n < 0) { if (lback(clp) == curbp->b_headp) { curwp->w_dotline = 1; break; } clp = lback(clp); n++; } } curwp->w_dotp = clp; curwp->w_doto = 0; curwp->w_rflag |= WFMOVE; return (TRUE); }
/* * Write a buffer to the already opened file. bp points to the * buffer. Return the status. */ int ffputbuf(FILE *ffp, struct buffer *bp) { struct line *lp, *lpend; lpend = bp->b_headp; for (lp = lforw(lpend); lp != lpend; lp = lforw(lp)) { if (fwrite(ltext(lp), 1, llength(lp), ffp) != llength(lp)) { dobeep(); ewprintf("Write I/O error"); return (FIOERR); } if (lforw(lp) != lpend) /* no implied \n on last line */ putc('\n', ffp); } /* * XXX should be variable controlled (once we have variables) */ if (llength(lback(lpend)) != 0) { if (eyorn("No newline at end of file, add one") == TRUE) { lnewline_at(lback(lpend), llength(lback(lpend))); putc('\n', ffp); } } return (FIOSUC); }
/* ARGSUSED */ int backline(int f, int n) { struct line *dlp; if (n < 0) return (forwline(f | FFRAND, -n)); if ((lastflag & CFCPCN) == 0) /* Fix goal. */ setgoal(); thisflag |= CFCPCN; dlp = curwp->w_dotp; if (lback(dlp) == curbp->b_headp) { if (!(f & FFRAND)) { dobeep(); ewprintf("Beginning of buffer"); } return(TRUE); } while (n-- && lback(dlp) != curbp->b_headp) { dlp = lback(dlp); curwp->w_dotline--; } if (n > 0 && !(f & FFRAND)) { dobeep(); ewprintf("Beginning of buffer"); } curwp->w_dotp = dlp; curwp->w_doto = getgoal(dlp); curwp->w_rflag |= WFMOVE; return (TRUE); }
/* ARGSUSED */ int gotobop(int f, int n) { int col, nospace; /* the other way... */ if (n < 0) return (gotoeop(f, -n)); while (n-- > 0) { nospace = 0; while (lback(curwp->w_dotp) != curbp->b_headp) { curwp->w_doto = 0; col = 0; while (col < llength(curwp->w_dotp) && (isspace(lgetc(curwp->w_dotp, col)))) col++; if (col >= llength(curwp->w_dotp)) { if (nospace) break; } else nospace = 1; curwp->w_dotline--; curwp->w_dotp = lback(curwp->w_dotp); } } /* force screen update */ curwp->w_rflag |= WFMOVE; return (TRUE); }
/* * This routine does the real work of a backward search. The pattern is * sitting in the external variable "pat". If found, dot is updated, the * window system is notified of the change, and TRUE is returned. If the * string isn't found, FALSE is returned. */ int backsrch(void) { struct line *clp, *tlp; int cbo, tbo, c, i, xcase = 0; char *epp, *pp; int nline, pline; for (epp = &pat[0]; epp[1] != 0; ++epp); clp = curwp->w_dotp; cbo = curwp->w_doto; nline = curwp->w_dotline; for (i = 0; pat[i]; i++) if (ISUPPER(CHARMASK(pat[i]))) xcase = 1; for (;;) { if (cbo == 0) { clp = lback(clp); if (clp == curbp->b_headp) return (FALSE); nline--; cbo = llength(clp) + 1; } if (--cbo == llength(clp)) c = CCHR('J'); else c = lgetc(clp, cbo); if (eq(c, *epp, xcase) != FALSE) { tlp = clp; tbo = cbo; pp = epp; pline = nline; while (pp != &pat[0]) { if (tbo == 0) { tlp = lback(tlp); if (tlp == curbp->b_headp) goto fail; nline--; tbo = llength(tlp) + 1; } if (--tbo == llength(tlp)) c = CCHR('J'); else c = lgetc(tlp, tbo); if (eq(c, *--pp, xcase) == FALSE) { nline = pline; goto fail; } } curwp->w_dotp = tlp; curwp->w_doto = tbo; curwp->w_dotline = nline; curwp->w_rflag |= WFMOVE; return (TRUE); } fail: ; } /* NOTREACHED */ }
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 */ }
/* * This routine figures out the bound of the region in the current window, * and stores the results into the fields of the REGION structure. Dot and * mark are usually close together, but I don't know the order, so I scan * outward from dot, in both directions, looking for mark. The size is kept * in a long. At the end, after the size is figured out, it is assigned to * the size field of the region structure. If this assignment loses any bits, * then we print an error. This is "type independent" overflow checking. All * of the callers of this routine should be ready to get an ABORT status, * because I might add a "if regions is big, ask before clobbering" flag. */ static int getregion(struct region *rp) { struct line *flp, *blp; long fsize, bsize; if (curwp->w_markp == NULL) { dobeep(); ewprintf("No mark set in this window"); return (FALSE); } /* "r_size" always ok */ if (curwp->w_dotp == curwp->w_markp) { rp->r_linep = curwp->w_dotp; rp->r_lineno = curwp->w_dotline; if (curwp->w_doto < curwp->w_marko) { rp->r_offset = curwp->w_doto; rp->r_size = (RSIZE)(curwp->w_marko - curwp->w_doto); } else { rp->r_offset = curwp->w_marko; rp->r_size = (RSIZE)(curwp->w_doto - curwp->w_marko); } return (TRUE); } /* get region size */ flp = blp = curwp->w_dotp; bsize = curwp->w_doto; fsize = llength(flp) - curwp->w_doto + 1; while (lforw(flp) != curbp->b_headp || lback(blp) != curbp->b_headp) { if (lforw(flp) != curbp->b_headp) { flp = lforw(flp); if (flp == curwp->w_markp) { rp->r_linep = curwp->w_dotp; rp->r_offset = curwp->w_doto; rp->r_lineno = curwp->w_dotline; return (setsize(rp, (RSIZE)(fsize + curwp->w_marko))); } fsize += llength(flp) + 1; } if (lback(blp) != curbp->b_headp) { blp = lback(blp); bsize += llength(blp) + 1; if (blp == curwp->w_markp) { rp->r_linep = blp; rp->r_offset = curwp->w_marko; rp->r_lineno = curwp->w_markline; return (setsize(rp, (RSIZE)(bsize - curwp->w_marko))); } } } dobeep(); ewprintf("Bug: lost mark"); return (FALSE); }
/* * Shrink the current window. * Find the window that gains space. Hack at * the window descriptions. Ask the redisplay to * do all the hard work. */ shrinkwind(f, n) { register WINDOW *adjwp; register LINE *lp; register int i; if (n < 0) return enlargewind(f, -n); if (wheadp->w_wndp == NULL) { ewprintf("Only one window"); return FALSE; } /* * Bit of flakiness - KRANDOM means it was an internal call, and * to be trusted implicitly about sizes. */ if ( !(f & FFRAND) && curwp->w_ntrows <= n) { ewprintf("Impossible change"); return (FALSE); } if ((adjwp=curwp->w_wndp) == NULL) { adjwp = wheadp; while (adjwp->w_wndp != curwp) adjwp = adjwp->w_wndp; } if (curwp->w_wndp == adjwp) { /* Grow below. */ lp = adjwp->w_linep; for (i=n-adjwp->w_lines; i>0 && lback(lp)!=adjwp->w_bufp->b_linep; ) { lp = lback(lp); i -= countlines(lp); } if (i>0) i = 0; if (i<0) i = -i; adjwp->w_linep = lp; adjwp->w_lines = i; adjwp->w_toprow -= n; } else { /* Grow above. */ lp = curwp->w_linep; for (i=n + curwp->w_lines; i>0 && lp!=curbp->b_linep;) { i -= countlines(lp); if (i<0) break; lp = lforw(lp); } if (i>0) i=countlines(lp)-1; /* LAST row */ if (i<0) i=countlines(lp)+i; curwp->w_linep = lp; curwp->w_lines = i; curwp->w_toprow += n; } curwp->w_ntrows -= n; adjwp->w_ntrows += n; curwp->w_flag |= WFMODE|WFHARD; adjwp->w_flag |= WFMODE|WFHARD; return (TRUE); }
/* * This routine figures out the * bounds of the region in the current window, and * fills in the fields of the "REGION" structure pointed * to by "rp". Because the dot and mark are usually very * close together, we scan outward from dot looking for * mark. This should save time. Return a standard code. * Callers of this routine should be prepared to get * an "ABORT" status; we might make this have the * conform thing later. */ int getregion(REGION *rp, LINE *markp, int marko) { register LINE *flp; register LINE *blp; long fsize; register long bsize; if (markp == NULL) { return (FALSE); } if (curwp->w_dotp == markp) { rp->r_linep = curwp->w_dotp; if (curwp->w_doto < marko) { rp->r_offset = curwp->w_doto; rp->r_size = marko - curwp->w_doto; } else { rp->r_offset = marko; rp->r_size = curwp->w_doto - marko; } return (TRUE); } blp = curwp->w_dotp; bsize = curwp->w_doto; flp = curwp->w_dotp; fsize = llength(flp)-curwp->w_doto+1; while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) { if (flp != curbp->b_linep) { flp = lforw(flp); if (flp == markp) { rp->r_linep = curwp->w_dotp; rp->r_offset = curwp->w_doto; rp->r_size = fsize + marko; return (TRUE); } fsize += llength(flp) + 1; } if (lback(blp) != curbp->b_linep) { blp = lback(blp); bsize += llength(blp)+1; if (blp == markp) { rp->r_linep = blp; rp->r_offset = marko; rp->r_size = bsize - marko; return (TRUE); } } } emlwrite("Bug: lost mark", NULL); return (FALSE); }
/* * readbuf - reads in a buffer. */ void readbuf(char **buf) { register LINE *lp1; register LINE *lp2; register BUFFER *bp; register WINDOW *wp; register int i; register int s; char *sptr; /* pointer into buffer string */ int nbytes; char line[NLINE]; CELL ac; bp = curbp; bp->b_flag &= ~(BFTEMP|BFCHG); sptr = *buf; ac.a = 0; while((s=sgetline(&sptr,&nbytes,line,NLINE)) == FIOSUC || s == FIOLNG){ if ((lp1=lalloc(nbytes)) == NULL) { s = FIOERR; /* Keep message on the */ break; /* display. */ } 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){ ac.c = line[i]; lputc(lp1, i, ac); } } for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) { if (wp->w_bufp == curbp) { wheadp->w_linep = lforw(curbp->b_linep); wheadp->w_dotp = lback(curbp->b_linep); wheadp->w_doto = 0; wheadp->w_markp = NULL; wheadp->w_marko = 0; wheadp->w_flag |= WFHARD; } } strncpy(bp->b_bname, "main", sizeof(bp->b_bname)); bp->b_bname[sizeof(bp->b_bname)-1] = '\0'; strncpy(bp->b_fname, "", sizeof(bp->b_fname)); bp->b_fname[sizeof(bp->b_fname)-1] = '\0'; bp->b_dotp = bp->b_linep; bp->b_doto = 0; }
/* * getfile() * * char fname[]; file name to find * int lockfl; check the file for locks? */ int getfile(char *fname, int lockfl) { struct buffer *bp; struct line *lp; int i; int s; char bname[NBUFN]; /* buffer name to put file */ #if MSDOS mklower(fname); /* msdos isn't case sensitive */ #endif 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; cknewwindow(); mlwrite("(Old buffer)"); return TRUE; } } makename(bname, fname); /* New buffer name. */ while ((bp = bfind(bname, FALSE, 0)) != NULL) { /* old buffer name conflict code */ 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 == NULL && (bp = bfind(bname, TRUE, 0)) == NULL) { 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++; s = readin(fname, lockfl); /* Read it in. */ cknewwindow(); return s; }
/* 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); }
/* * This routine does the real work of a backward search. The pattern is sitting * in the external variable "re_pat". If found, dot is updated, the window * system is notified of the change, and TRUE is returned. If the string isn't * found, FALSE is returned. */ static int re_backsrch(void) { struct line *clp; int tbo; regmatch_t lastmatch; lastmatch.rm_eo = 0; clp = curwp->w_dotp; tbo = curwp->w_doto; /* Start search one position to the left of dot */ tbo = tbo - 1; if (tbo < 0) { /* must move up one line */ clp = lback(clp); tbo = llength(clp); } /* * Note this loop does not process the last line, but this editor * always makes the last line empty so this is good. */ while (clp != (curbp->b_headp)) { regex_match[0].rm_so = 0; regex_match[0].rm_eo = llength(clp); lastmatch.rm_so = -1; /* * Keep searching until we don't match any longer. Assumes a * non-match does not modify the regex_match array. We have to * do this character-by-character after the first match since * POSIX regexps don't give you a way to do reverse matches. */ while (!regexec_new(&re_buff, ltext(clp), RE_NMATCH, regex_match, REG_STARTEND) && regex_match[0].rm_so < tbo) { memcpy(&lastmatch, ®ex_match[0], sizeof(regmatch_t)); regex_match[0].rm_so++; regex_match[0].rm_eo = llength(clp); } if (lastmatch.rm_so == -1) { clp = lback(clp); tbo = llength(clp); } else { memcpy(®ex_match[0], &lastmatch, sizeof(regmatch_t)); curwp->w_doto = regex_match[0].rm_so; curwp->w_dotp = clp; curwp->w_rflag |= WFMOVE; return (TRUE); } } return (FALSE); }
/* * Find a non-blank line, searching backwards from the supplied line pointer. * For C, nonblank is non-preprocessor, non C++, and accounts * for complete C-style comments. */ static struct line * findnonblank(struct line *lp) { int lo; int nonblankp = FALSE; int commentp = FALSE; int slashp; int astp; int c; while (lback(lp) != curbp->b_headp && (commentp || !nonblankp)) { lp = lback(lp); slashp = FALSE; astp = FALSE; /* Potential nonblank? */ nonblankp = isnonblank(lp, llength(lp)); /* * Search from end, removing complete C-style * comments. If one is found, ignore it and * test for nonblankness from where it starts. */ slashp = FALSE; /* Scan backwards from end to find C-style comment */ for (lo = llength(lp) - 1; lo >= 0; lo--) { if (!isspace(c = lgetc(lp, lo))) { if (commentp) { /* find comment "open" */ if (c == '*') astp = TRUE; else if (astp && c == '/') { commentp = FALSE; /* whitespace to here? */ nonblankp = isnonblank(lp, lo); } } else { /* find comment "close" */ if (c == '/') slashp = TRUE; else if (slashp && c == '*') /* found a comment */ commentp = TRUE; } } } } /* Rewound to start of file? */ if (lback(lp) == curbp->b_headp && !nonblankp) return (curbp->b_headp); return (lp); }
/*ARGSUSED*/ enlargewind(f, n) { register WINDOW *adjwp; register LINE *lp; register int i; if (n < 0) return shrinkwind(f, -n); if (wheadp->w_wndp == NULL) { ewprintf("Only one window"); return FALSE; } if ((adjwp=curwp->w_wndp) == NULL) { adjwp = wheadp; while (adjwp->w_wndp != curwp) adjwp = adjwp->w_wndp; } if (adjwp->w_ntrows <= n) { ewprintf("Impossible change"); return FALSE; } if (curwp->w_wndp == adjwp) { /* Shrink below. */ lp = adjwp->w_linep; for (i=n+adjwp->w_lines; i>0 && lp!=adjwp->w_bufp->b_linep; ) { i -= countlines(lp); if (i < 0) break; lp = lforw(lp); } if (i>0) i=countlines(lp)-1; /* LAST row */ if (i<0) i=countlines(lp)+i; adjwp->w_linep = lp; adjwp->w_lines = i; adjwp->w_toprow += n; } else { /* Shrink above. */ lp = curwp->w_linep; for (i=n-curwp->w_lines; i>0 && lback(lp)!=curbp->b_linep; ){ lp = lback(lp); i -= countlines(lp); } if (i>0) i= 0; if (i<0) i= -i; curwp->w_linep = lp; curwp->w_lines = i; curwp->w_toprow -= n; } curwp->w_ntrows += n; adjwp->w_ntrows -= n; curwp->w_flag |= WFMODE|WFHARD; adjwp->w_flag |= WFMODE|WFHARD; return TRUE; }
/* * Shrink the current window. Find the window that gains space. Hack at the * window descriptions. Ask the redisplay to do all the hard work. */ int shrinkwind(int f, int n) { struct mgwin *adjwp; struct line *lp; int i; if (n < 0) return (enlargewind(f, -n)); if (wheadp->w_wndp == NULL) { dobeep(); ewprintf("Only one window"); return (FALSE); } /* * Bit of flakiness - FFRAND means it was an internal call, and * to be trusted implicitly about sizes. */ if (!(f & FFRAND) && curwp->w_ntrows <= n) { dobeep(); ewprintf("Impossible change"); return (FALSE); } if ((adjwp = curwp->w_wndp) == NULL) { adjwp = wheadp; while (adjwp->w_wndp != curwp) adjwp = adjwp->w_wndp; } /* grow below */ if (curwp->w_wndp == adjwp) { lp = adjwp->w_linep; for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_headp; ++i) lp = lback(lp); adjwp->w_linep = lp; adjwp->w_toprow -= n; /* grow above */ } else { lp = curwp->w_linep; for (i = 0; i < n && lp != curbp->b_headp; ++i) lp = lforw(lp); curwp->w_linep = lp; curwp->w_toprow += n; } curwp->w_ntrows -= n; adjwp->w_ntrows += n; curwp->w_rflag |= WFMODE | WFFULL; adjwp->w_rflag |= WFMODE | WFFULL; return (TRUE); }
/* ARGSUSED */ int d_undelbak(int f, int n) { if (n < 0) return (d_undel(f, -n)); while (n--) { if (llength(curwp->w_dotp) > 0) lputc(curwp->w_dotp, 0, ' '); if (lback(curwp->w_dotp) != curbp->b_headp) curwp->w_dotp = lback(curwp->w_dotp); } curwp->w_doto = 0; curwp->w_flag |= WFEDIT | WFMOVE; return (TRUE); }
/* * Go to the end of the current paragraph. */ int gotoeop(int f, int n) { MARK odot; int was_at_bol; int was_on_empty; int fc; n = need_a_count(f, n, 1); fc = firstchar(DOT.l); was_on_empty = is_empty_line(DOT); was_at_bol = ((fc >= 0 && DOT.o <= fc) || fc < 0); odot = DOT; while (n) { if (findpat(TRUE, 1, b_val_rexp(curbp, VAL_PARAGRAPHS)->reg, FORWARD) != TRUE) { DOT = curbp->b_line; } else if (is_empty_line(DOT)) { /* special case -- if we found an empty line. */ /* either as the very next line, or at the end of our search */ if ((was_on_empty && lback(DOT.l) == odot.l) || (n > 0 && llength(lback(DOT.l)) == 0)) { /* then we haven't really found what we wanted. keep going */ skipblanksf(); continue; } } n--; } if (doingopcmd) { /* if we're now at the beginning of a line and we can back up, do so to avoid eating the newline and leading whitespace */ fc = firstchar(DOT.l); if (((fc >= 0 && DOT.o <= fc) || fc < 0) && !is_first_line(DOT, curbp) && !sameline(DOT, odot)) { backchar(TRUE, DOT.o + 1); } /* if we started at the start of line, eat the whole line */ if (!sameline(DOT, odot) && was_at_bol) regionshape = rgn_FULLLINE; } return TRUE; }
/* ARGSUSED */ int gotoline(int f, int n) { struct line *clp; char buf[32], *bufp; const char *err; if (!(f & FFARG)) { if ((bufp = eread("Goto line: ", buf, sizeof(buf), EFNUL | EFNEW | EFCR)) == NULL) return (ABORT); if (bufp[0] == '\0') return (ABORT); n = (int)strtonum(buf, INT_MIN, INT_MAX, &err); if (err) { ewprintf("Line number %s", err); return (FALSE); } } if (n >= 0) { if (n == 0) n++; curwp->w_dotline = n; clp = lforw(curbp->b_headp); /* "clp" is first line */ while (--n > 0) { if (lforw(clp) == curbp->b_headp) { curwp->w_dotline = curwp->w_bufp->b_lines; break; } clp = lforw(clp); } } else { curwp->w_dotline = curwp->w_bufp->b_lines + n; clp = lback(curbp->b_headp); /* "clp" is last line */ while (n < 0) { if (lback(clp) == curbp->b_headp) { curwp->w_dotline = 1; break; } clp = lback(clp); n++; } } curwp->w_dotp = clp; curwp->w_doto = 0; curwp->w_rflag |= WFMOVE; return (TRUE); }
/* ARGSUSED */ int gotoeob(int f GCC_UNUSED, int n GCC_UNUSED) { DOT.l = lback(buf_head(curbp)); curwp->w_flag |= WFMOVE; return firstnonwhite(FALSE, 1); }
/* * Move to a particular line (the argument). Count from bottom of file if * argument is negative. */ int vl_gotoline(int n) { int status = TRUE; /* status return */ MARK odot; if (n == 0) /* if a bogus argument...then leave */ return (FALSE); odot = DOT; DOT.o = w_left_margin(curwp); if (n < 0) { DOT.l = lback(buf_head(curbp)); status = backline(TRUE, -n - 1); } else { DOT.l = lforw(buf_head(curbp)); status = forwline(TRUE, n - 1); } if (status != TRUE) { DOT = odot; return status; } (void) firstnonwhite(FALSE, 1); curwp->w_flag |= WFMOVE; return TRUE; }
/* * Move the cursor backwards by "n" characters. If "n" is less than zero call * "forwchar" to actually do the move. Otherwise compute the new cursor * location. Error if you try and move out of the buffer. Set the flag if the * line pointer for dot changes. */ PASCAL NEAR backchar( int f, int n )/* prefix flag and argument */ { register LINE *lp; if (n < 0) return(forwchar(f, -n)); while (n--) { if (curwp->w_doto == 0) { if ((lp=lback(curwp->w_dotp)) == curbp->b_linep) return(FALSE); curwp->w_dotp = lp; curwp->w_doto = llength(lp); curwp->w_flag |= WFMOVE; } else curwp->w_doto--; } #if DBCS return(stopback()); #else return(TRUE); #endif }
/* * Search for and display a matching character. * * This routine does the real work of searching backward * for a balancing character. If such a balancing character * is found, it uses displaymatch() to display the match. */ static int balance(void) { struct line *clp; int cbo; int c, i, depth; int rbal, lbal; rbal = key.k_chars[key.k_count - 1]; /* See if there is a matching character -- default to the same */ lbal = rbal; for (i = 0; bal[i].right != '\0'; i++) if (bal[i].right == rbal) { lbal = bal[i].left; break; } /* * Move behind the inserted character. We are always guaranteed * that there is at least one character on the line, since one was * just self-inserted by blinkparen. */ clp = curwp->w_dotp; cbo = curwp->w_doto - 1; /* init nesting depth */ depth = 0; for (;;) { if (cbo == 0) { clp = lback(clp); /* beginning of line */ if (clp == curbp->b_headp) return (FALSE); cbo = llength(clp) + 1; } if (--cbo == llength(clp)) c = '\n'; /* end of line */ else c = lgetc(clp, cbo); /* somewhere in middle */ /* * Check for a matching character. If still in a nested * level, pop out of it and continue search. This check * is done before the nesting check so single-character * matches will work too. */ if (c == lbal) { if (depth == 0) { displaymatch(clp, cbo); return (TRUE); } else depth--; } /* Check for another level of nesting. */ if (c == rbal) depth++; } /* NOTREACHED */ }
/* ARGSUSED */ int backchar(int f, int n) { struct line *lp; if (n < 0) return (forwchar(f, -n)); while (n--) { if (curwp->w_doto == 0) { if ((lp = lback(curwp->w_dotp)) == curbp->b_headp) { if (!(f & FFRAND)) { dobeep(); ewprintf("Beginning of buffer"); } return (FALSE); } curwp->w_dotp = lp; curwp->w_doto = llength(lp); curwp->w_rflag |= WFMOVE; curwp->w_dotline--; } else curwp->w_doto--; } return (TRUE); }
/* * movenext -- move to next character in either direction, but * don't return it. will wrap, and doesn't set motion flags. */ static void movenext(MARK *pdot, int dir) { LINE *curline; int curoff; curline = pdot->l; curoff = pdot->o; if (dir == FORWARD) { if (curoff == llength(curline)) { curline = lforw(curline); /* skip to next line */ curoff = 0; } else { curoff += BytesAt(curline, curoff); } } else { if (curoff == 0) { curline = lback(curline); curoff = llength(curline); } else { curoff -= BytesBefore(curline, curoff); } } pdot->l = curline; pdot->o = curoff; }
/* ARGSUSED */ int clear_match_attrs(int f GCC_UNUSED, int n GCC_UNUSED) { int status; MARK origdot, origmark; if ((curbp->b_highlight & HILITE_ON) == 0) return TRUE; origdot = DOT; origmark = MK; DOT.l = lforw(buf_head(curbp)); DOT.o = 0; MK.l = lback(buf_head(curbp)); MK.o = llength(MK.l) - 1; videoattribute = VOWN_MATCHES; if ((status = attributeregion()) == TRUE) { DOT = origdot; MK = origmark; curbp->b_highlight = 0; #if OPT_HILITEMATCH hilite_suppressed = TRUE; #endif } return status; }
/* return a region which goes from DOT to the far end of the current selection region. shape is maintained. returns pointer to static region struct. */ static REGION * extended_region(void) { BUFFER *bp = curbp; REGION *rp = NULL; static REGION a, b; MARK savemark; savemark = MK; regionshape = selregion.ar_shape; MK = selregion.ar_region.r_orig; DOT.o += BytesAt(DOT.l, DOT.o); if (getregion(bp, &a) == TRUE) { DOT.o -= BytesBefore(DOT.l, DOT.o); MK = selregion.ar_region.r_end; if (regionshape == rgn_FULLLINE) MK.l = lback(MK.l); /* region b is to the end of the selection */ if (getregion(bp, &b) == TRUE) { /* if a is bigger, it's the one we want */ if (a.r_size > b.r_size) rp = &a; else rp = &b; } } else { DOT.o -= BytesBefore(DOT.l, DOT.o); } MK = savemark; return rp; }
/* ARGSUSED */ int killline(int f, int n) { struct line *nextp; RSIZE chunk; int i, c; /* clear kill buffer if last wasn't a kill */ if ((lastflag & CFKILL) == 0) kdelete(); thisflag |= CFKILL; if (!(f & FFARG)) { for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i) if ((c = lgetc(curwp->w_dotp, i)) != ' ' && c != '\t') break; if (i == llength(curwp->w_dotp)) chunk = llength(curwp->w_dotp) - curwp->w_doto + 1; else { chunk = llength(curwp->w_dotp) - curwp->w_doto; if (chunk == 0) chunk = 1; } } else if (n > 0) { chunk = llength(curwp->w_dotp) - curwp->w_doto; nextp = lforw(curwp->w_dotp); if (nextp != curbp->b_headp) chunk++; /* newline */ if (nextp == curbp->b_headp) goto done; /* EOL */ i = n; while (--i) { chunk += llength(nextp); nextp = lforw(nextp); if (nextp != curbp->b_headp) chunk++; /* newline */ if (nextp == curbp->b_headp) break; /* EOL */ } } else { /* n <= 0 */ chunk = curwp->w_doto; curwp->w_doto = 0; i = n; while (i++) { if (lforw(curwp->w_dotp)) chunk++; curwp->w_dotp = lback(curwp->w_dotp); curwp->w_rflag |= WFMOVE; chunk += llength(curwp->w_dotp); } } /* * KFORW here is a bug. Should be KBACK/KFORW, but we need to * rewrite the ldelete code (later)? */ done: if (chunk) return (ldelete(chunk, KFORW)); return (TRUE); }
/* ARGSUSED */ int forwline(int f, int n) { struct line *dlp; if (n < 0) return (backline(f | FFRAND, -n)); if ((dlp = curwp->w_dotp) == curbp->b_headp) return(TRUE); if ((lastflag & CFCPCN) == 0) /* Fix goal. */ setgoal(); thisflag |= CFCPCN; if (n == 0) return (TRUE); while (n--) { dlp = lforw(dlp); if (dlp == curbp->b_headp) { curwp->w_dotp = lback(dlp); curwp->w_doto = llength(curwp->w_dotp); curwp->w_rflag |= WFMOVE; return (TRUE); } curwp->w_dotline++; } curwp->w_rflag |= WFMOVE; curwp->w_dotp = dlp; curwp->w_doto = getgoal(dlp); return (TRUE); }
/* push an unreal line onto the undo stack * lp should be the new line, _after_ insertion, so * lforw() and lback() are right */ int tag_for_undo(LINE *lp) { int status = FALSE; LINE *nlp; TRACE2((T_CALLED "tag_for_undo(%p)\n", lp)); if (needundocleanup) preundocleanup(); if (liscopied(lp)) { status = TRUE; } else if ((nlp = lalloc(LINENOTREAL, curbp)) == 0) { TRACE(("tag_for_undo: no memory\n")); status = ABORT; } else { set_lforw(nlp, lforw(lp)); set_lback(nlp, lback(lp)); pushline(nlp, BACKSTK(curbp)); lsetcopied(lp); FORWDOT(curbp).l = lp; FORWDOT(curbp).o = DOT.o; status = TRUE; } return2Code(status); }