#include "ded.h" #include "char.h" /* make the necessary movements on the screen */ draw(ch, chtype) char ch; int chtype; { register char c; register int ctype; char tail[ENOUGH]; int i; int col, col1, col2; int ntpos; int fline; c=ch; ctype=chtype; do { switch (ctype) { case CONTROL: case ONE: case MODIFY: case SPACE: if (!roomfor(1, virt_c.row)) break; else { copytail(tail); show(c); if (virt_c.col<rightcol) { virt_c.col++; showtail(tail); } } return; case TWO: if (!roomfor(2, virt_c.row)) break; else { copytail(tail); show(c_MODIFY); virt_c.col++; show(unmodify(c)); if (virt_c.col<rightcol) { virt_c.col++; showtail(tail); } } return; case TAB: if ((ntpos = nextab(virt_c.col)) > BELLMARGIN); /* complain(); * (too bloody loud) */ col = virt_c.col; while ((rowmap[virt_c.row])[col]==c_SPACE && col<ntpos) col++; if (!roomfor(ntpos-col, virt_c.row)) cdiag("!! no room on line !!"); else { virt_c.col = col; if (virt_c.col != ntpos) { copytail(tail); while (virt_c.col < ntpos) { show(c_SPACE); adj_virt_c(0,1); } showtail(tail); } } return; case RUBOUT: if (virt_c.col<=leftcol) { virt_c.col=leftcol; if (mode==INMODE) { if (virt_c.row==toprow) scrdown(SCROLL); if (virt_c.row==toprow) cdiag("!! top of file !!"); else if (!roomfor(lastcol(virt_c.row)+2, virt_c.row-1)) cdiag("!! no room on line above !!"); else { copytail(tail); fline = topl+virt_c.row; del_row(virt_c.row, &virt_c); virt_c.row = fline-topl-1; position(virt_c.row, lastcol(virt_c.row)+2); showtail(tail); } /* shift line */ } /* mode==INMODE */ else complain(); /* edit mode bleep at left col */ } else { copytail(tail); virt_c.col--; showtail(tail); } return; case CERASE: copytail(tail); if (*tail == 0) complain(); else showtail(tail+1); return; case WRUBOUT: if (virt_c.col<=leftcol) complain(); else { col = backword(virt_c.col); copyrow(virt_c.row, virt_c.col, tail); virt_c.col = col; showtail(tail); } return; case WERASE: if (virt_c.col > lastpos(virt_c.row) || (mode==EDMODE && hit_diagnostic()) ) complain(); else { col = nextword(virt_c.col); copyrow(virt_c.row,col,tail); showtail(tail); } return; case HEADERASE: if (virt_c.col <= leftcol) { virt_c.col=leftcol; complain(); } else { copytail(tail); virt_c.col = leftcol; showtail(tail); } return; case TAILERASE: if (lastcol(virt_c.row)<virt_c.col) complain(); else cleartail(); return; default: editerror("invalid character type in draw %d",ctype); } /* come here (via 'break') when line is absolutely full * - break line in two if possible */ col1 = sp_right(virt_c.col)+1; col2 = sp_left(virt_c.col-1)+1; if (txin && mode==INMODE && ( (col1>BELLMARGIN && (col=col2)>0) || (col=col1)>0 )) { copyrow(virt_c.row, col, tail); redraw(virt_c.row, col, " "); ins_row(virt_c.row, tail, &virt_c.row); if (col<virt_c.col) { virt_c.row++; virt_c.col =- col; } continue; } else { cdiag("!! no room on line !!"); return; } } while (true); } roomfor(num, srow) int num, srow; { register char *sp; register int n; n=num; sp = rowmap[srow]+rightcol; while (n-- > 0) if (*sp-- != c_SPACE) return(false); return(true); } show(c) char c; { register char rc; fixpos(); ttyout(rc=c); (rowmap[real_c.row])[real_c.col] = rc; if (++real_c.col >= ncols) { if (++real_c.row >= nrows) editerror("rolled off bottom of screen"); /* god only knows where it goes */ real_c.col = ncols*10; real_c.row = nrows*10; } } showtail(s) char *s; { redraw(virt_c.row, virt_c.col, s); } copytail(tail) char *tail; { copyrow(virt_c.row, virt_c.col, tail); } /* in order to avoid too many characters, only draw those * characters which have altered */ char blanks[] " "; redraw(srow,scol,p_newrow) int srow,scol; char *p_newrow; { struct CURSOR tmp; register char *oldrow, *newrow; register char c; char *oldrowlim; store_c(&virt_c, &tmp); if ((newrow=p_newrow) == 0) newrow = blanks; oldrow = rowmap[srow]+scol; oldrowlim = rowmap[srow]+(srow==FOOTROW ? ncols-2 : ncols-1); virt_c.row = srow; while (oldrow <= oldrowlim) { if ((c = *newrow++) != *oldrow++ || c==0) { if (c==0) { newrow = blanks; oldrow--; } else { virt_c.col=oldrow-rowmap[srow]-1; show(c); } } } store_c(&tmp,&virt_c); } cleartail() { redraw(virt_c.row, virt_c.col, blanks); } backword(scol) int scol; { register char *rp, *rplim; rp = rowmap[virt_c.row] + scol; rplim = rowmap[virt_c.row] + leftcol; if (rp>rplim) { rp--; /* move back to previous character */ /* the next piece of nastiness moves back to the previous character * if the cursor is pointing at a space */ if (rp>rplim && *rp ==c_SPACE && *--rp ==c_SPACE) { while (rp>rplim && *(rp-1) == c_SPACE) rp--; /* space sequence */ if (rp!=rplim) rp++; /* move one right except at lhs */ } else if (rp>rplim && alphmer(*rp)) /* word */ while (rp>rplim && alphmer(*(rp-1))) rp--; /* it was punctuation - do nothing else */ } return(rp-rowmap[virt_c.row]); } nextword(scol) int scol; { register char *rp, *rplim; if (mode==EDMODE && hit_diagnostic()) return(virt_c.col); rp = rowmap[virt_c.row]+scol; rplim = rowmap[virt_c.row] + rightcol; if (rp<rplim && *rp==c_SPACE) /* space */ { if (scol==0 || rp[-1] == c_SPACE) while (rp<rplim && *rp==c_SPACE) rp++; /* skip all the spaces in a sequence */ } else if (rp<rplim && alphmer(*rp)) /* word */ while (rp<rplim && alphmer(*rp)) rp++; /* skip word */ else /* punctuation */ if (rp<rplim) rp++; /* whatever happens, skip space following */ if (rp<rplim && *rp==c_SPACE) rp++; return(rp-rowmap[virt_c.row]); } int sp_right(scol) int scol; { register int i; register char *rp; rp = rowmap[virt_c.row]+scol; for (i=scol; i<=rightcol; i++) if (*rp++ == c_SPACE) return(i); return(-1); } int sp_left(scol) int scol; { register int i; register char *rp; rp = rowmap[virt_c.row]+scol; for (i=scol; i>=leftcol; i--) if (*rp-- == c_SPACE) return(i); return(-1); }