PROC scroll(bool down) { int i; if (count <= 0) count = dofscroll; strput(CURoff); if (down) { curr = min(bufmax-1, nextline(TRUE, curr, count)); i = min(bufmax-1, nextline(TRUE, pend, count)); if (i > pend) scrollforward(i); } else { curr = bseekeol(max(0,nextline(FALSE, curr, count))); i = bseekeol(max(0,nextline(FALSE, ptop, count))); if (i < ptop) if (canUPSCROLL) scrollback(i); else { ptop = i; setend(); redisplay(TRUE); } } strput(CURon); setpos(skipws(curr)); /* initialize new position - first nonwhite */ yp = setY(curr); mvcur(yp, xp); /* go there */ }
PROC scrollback(int curr) { mvcur(0,0); /* move to the top line */ do { ptop = bseekeol(ptop-1); strput(UpS); writeline(0, 0, ptop); } while (ptop > curr); setend(); }
int PROC getcontext(char c, bool begline) { int i; if (c == '\'') c = '`'; if (c >= '`' && c <= 'z') i = contexts[c-'`']; else i = -1; if (begline && i>=0) return(bseekeol(i)); return(i); }
int PROC nextline(bool advance, int dest, int count) { if (advance) do { dest = fseekeol(dest) + 1; count--; } while (count>0 && dest<bufmax); else do { dest = bseekeol(dest) - 1; count--; } while (count>0 && dest>=0); return(dest); }
PROC adjuster(bool sleft, int endd, int sw) { bool noerror; int np, ts, ip, ss, adjp, DLEnum; if (sw == -1) sw = shiftwidth; if (sleft) sw = -sw; curr = bseekeol(curr); ip = curr; noerror = TRUE; do { DLEnum = sw + findDLE(ip, &np, bufmax,0); if (DLEnum >= 0 && DLEnum <= COLS && core[np] != EOL && np < bufmax) { ts = DLEnum / tabsize; ss = DLEnum % tabsize; adjp = ts+ss+ip; if (np-adjp < 0) { /* expand the buf */ moveright(&core[np], &core[adjp], bufmax-np); insert_to_undo(&undo, adjp, adjp - np); } else delete_to_undo(&undo, adjp, np - adjp); endd += (adjp-np); noerror = move_to_undo(&undo, ip, ts+ss); fillchar(&core[ip], ts, TAB); fillchar(&core[ip+ts], ss, 32); } else if (np > ip) { /* remove the indent code */ noerror = delete_to_undo(&undo, ip, np-ip); endd += (ip - np); } ip = 1 + fseekeol(ip); } while (noerror && ip < endd); if (!noerror) error(); newc = skipws(curr); disp = curr; newend = endd; endY = setY(min(newend, pend)); }
PROC findback(char *pattern, int start, int endp) /* look for a regular expression backwards */ { int ep,i, j; while (start > endp) { ep = bseekeol(start); if ((j = REmatch(pattern, ep, start)) <= start) { i = j; while((j=REmatch(pattern, i+1, start)) <= start) { i = j; } return i; } start = ep-1; } return ERR; }
char * PROC findparse(char *src, int *idx, int start) /* driver for ?, /, && : lineranges */ { int addr = start; char c; s_wrapped = 0; switch (*src) { case '/': case '?': /* get a token for find & find it in the buffer */ src = search(src,&addr); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* fabricate a count */ count = 0; while (*src >= '0' && *src <= '9') count = (count*10) + *(src++) - '0'; addr = to_index(count); break; case '$': addr = bufmax-1; src++; break; case '.' : src++; break; case '`': case '\'': addr = getcontext(*(src+1), (*src == '\'')); src += 2; break; } while (addr>=0 && (*src =='+' || *src == '-')) { c = *(src++); /* skip delimiter */ if (*src == '/' || *src == '?') { count = 1; if ((src = search(src,&addr)) == NULL) break; } else { if (*src >= '0' && *src <= '9') { /* fabricate a count */ count = 0; while (*src >= '0' && *src <= '9') count = (count*10) + *(src++) - '0'; } else count = -1; /* for naked + & - */ if (count == 0) /* +0 goes to beginning of line */ addr = bseekeol(addr); else { addr = nextline((c=='+'), addr, count); if (c=='-' && addr > 0) addr = bseekeol(addr); } if (addr >= bufmax) addr = -1; } } *idx = addr; return(src); }
PROC docommand(cmdtype cmd) { cmdtype movecmd; /* movement command for y, d, c */ char cmdch; int oldc; /* old count */ int endp; /* end position before change */ extern bool s_wrapped; resetX(); /* un-derange the cursor */ oldc = newc = -1; endY = yp; newend = disp = curr; ok = TRUE; /* so far everything is working */ cmdch = ch; if (cmd != UNDO_C && cmd != YANK_C) { if (macro<0) zerostack(&undo); if (redoing != TRUE) { rcp = rcb; /* point at start of redo buffer */ if (count > 1) { /* put in a count? */ numtoa(rcb,count); rcp += strlen(rcb); } *rcp++ = cmdch; /* the command char goes in... */ xerox = TRUE; /* hoist the magical flags */ } } if (cmd <= YANK_C) { readchar(); if (ch >= '0' && ch <= '9') { oldc = count; gcount(); /* get a new count */ if (cmd == ADJUST_C) /* special for >>,<< wierdness */ swap(&count, &oldc); /* reverse sw & count */ else count = count*max(oldc,1); /* combine them */ } if (ch == cmdch) { /* diddle lines */ yank.lines = TRUE; endp = nextline(TRUE, curr, count); curr = bseekeol(curr); disp = curr; } else { /* diddle 'things' */ yank.lines = FALSE; movecmd = movemap[ch]; if (ok = (findCP(curr,&endp,movecmd) == LEGALMOVE)) { if (curr > endp) { swap(&curr,&endp); ok = (cmd != CHANGE_C); } if (adjcurr[movecmd]) curr++; if (adjendp[movecmd]) endp++; } if (!ok) { if (ch != ESC) error(); goto killredo; } } endY = setY(endp); newend = curr; disp = curr; switch (cmd) { case DELETE_C: ok = deletion(curr, endp); break; case ADJUST_C: adjuster((cmdch == '<'), endp-1, oldc); break; case CHANGE_C: if (endp <= pend+1) { mvcur(setY(endp-1), setX(endp-1)); printch('$'); mvcur(yp, xp); } if (deletion(curr, endp)) ok = ((newend = insertion(1, 0, &disp, &endY, TRUE)) >= 0); else ok = FALSE; break; case YANK_C: if (!doyank(curr, endp)) error(); return 0; /* xerox will not be true, nor will redoing */ } } else { endp = curr; endY = yp; switch (cmd) { case I_AT_NONWHITE: case A_AT_END: case APPEND_C: case INSERT_C: /* variations on insert */ if (cmd != INSERT_C) { if (cmd == APPEND_C) curr = min(curr+1, lend); else if (cmd == A_AT_END) curr = lend; else /* if (cmd == I_AT_NONWHITE) */ curr = skipws(lstart); xp = setX(curr); mvcur(yp,xp); } newend = insertion(count, 0, &disp, &endY, TRUE); ok = (newend >= 0); break; case OPEN_C: case OPENUP_C: newend = insertion(1,setstep[ (cmd==OPENUP_C)&1 ], &disp,&endY,TRUE)-1; ok = (newend >= 0); break; case REPLACE_C: case TWIDDLE_C: if (cmd == REPLACE_C) { if ((cmdch = readchar()) == ESC) goto killredo; } if (findCP(curr, &endp, GO_RIGHT) == LEGALMOVE) squiggle(endp-1, cmdch, (cmd==REPLACE_C)); break; case PUT_BEFORE: case PUT_AFTER: ok = put(cmd==PUT_AFTER); break; case BIG_REPL_C: bigreplace(); break; case RESUBST_C: ok = FALSE; if (dst[0] != 0) { newend = chop(curr, &lend, TRUE, &ok); if (newend >= 0) { endY = setY(newend+strlen(dst)); ok = TRUE; } } break; case JOIN_C: join(count); /* join lines */ break; case UNDO_C: /* undo last modification */ ok = fixcore(&newend) >= 0; disp = newend; endY = MAGICNUMBER; break; } } if (ok) { setpos((newc<0)?newend:newc); setend(); if (curr < ptop || curr > pend) { yp = settop(12); redisplay(TRUE); } else { yp = setY(curr); if (endY != setY(newend)) /* shuffled lines */ refresh(setY(disp), setX(disp), disp, pend, TRUE); else /* refresh to end position */ refresh(setY(disp), setX(disp), disp, newend, FALSE); } if (curr >= bufmax && bufmax > 0) { /* adjust off end of buffer */ setpos(bufmax-1); yp = setY(curr); } if (s_wrapped) { prompt(FALSE, "search wrapped around end of buffer"); s_wrapped = 0; } else clrprompt(); modified = TRUE; } else { error(); killredo: rcb[0] = 0; } mvcur(yp, xp); if (xerox) *rcp = 0; /* terminate the redo */ redoing = FALSE; xerox = FALSE; core[bufmax] = EOL; }