#include "ded.h" #include "jmp.h" #include "ter.h" /************************************************************************ * * * copyright Richard Bornat 1981 * * * ************************************************************************/ mainloop(pmode) int pmode; { char *ctab; int (*changemode)(); /* by which I mean - changemode is the address of a function */ switch (mode=setjmp(mn_env)) { case 0: if ((mode=pmode)==INMODE) goto inmode; else goto edmode; case INMODE: inmode: ctab = ictab; changemode = itoe; virt_c = in_c; toprow=0; bottomrow=LASTINROW; leftcol=2; rightcol=RIGHTCOL; break; case EDMODE: edmode: { int col = rmargin(EDITROW); ctab = ectab; changemode = etoi; /* avoid diagnostic messages */ virt_c = edit_c; if (col<=virt_c.col) virt_c.col=col; toprow=bottomrow=EDITROW; leftcol=1; rightcol=RIGHTCOL-1; } break; case OK: return(true); case NOT_OK: return(false); default: editerror("val %d in longjmp to mn_env", mode); } fixpos(); /* ttyflush is now part of ttyin */ while (true) { char c = ttyin(); register int ctype; register int vcol = virt_c.col, vrow = virt_c.row; retry: /* see action after SPECIAL below */ ctype = ctab[c]; reswitch: switch (ctype) { case IGN: complain(); break; /* don't type those */ case SPECIAL: if ( (ctype = (*ter.special)(true, c)) >= 0) goto reswitch; else { c = -ctype; goto retry; } case TAB: if (overtype) { if (vcol >= rmargin(vrow)) complain(); vcol = nextab(vcol); break; } /* else fall through */ case ONE: case SPACE: case MODIFY: /* visible characters */ case CONTROL: case TWO: if (vcol>BELLMARGIN && txin && mode==INMODE && !overtype && line_break(vcol, ctype)) if (ctype==SPACE || ctype==TAB) goto curset; /* else fall through (saves a few bytes) */ case RUBOUT: case ERASE: case WRUBOUT: /* line control characters */ case WERASE: case HEADRUBOUT: case TAILERASE: case LINEERASE: draw(c,ctype); goto curset; case UP: if (vrow<=toprow) { upwards(); goto curset; } else vrow--; break; case DOWN: if (vrow>=bottomrow) { downwards(); goto curset; } else vrow++; break; case LEFT: if (vcol<=leftcol) { vcol=leftcol; complain(); } else vcol--; break; case RIGHT: { int rm = rmargin(vrow); if (vcol>=rm) { vcol=rm; complain(); } else vcol++; } break; case WLEFT: { int lw = left_word(vcol); if (lw==vcol) complain(); else vcol = lw; break; } case WRIGHT: { int rw = right_word(vcol); if (rw==vcol) complain(); else vcol = rw; break; } case CR: /*if (!overtype) {*/ split_row(&virt_c.row, &virt_c.col); goto curset; /*} */ /* fall through to NL in overtype mode */ case NL: if (vrow >= bottomrow) { if (downwards()) vrow=virt_c.row; else goto curset; /* end of file */ } else vrow++; vcol = leftcol; break; case LSTART: lstart: /* sorry */ { int fc = firstcol(vrow); if (fc<=rightcol) { if (fc==vcol) complain(); else vcol = fc; } else { complain(); vcol = leftcol; } } break; case LMIDDLE: vcol=(linend(vrow)+1)/2; break; case LEND: lend: /* sorry */ { int lc = lastcol(vrow); if (lc >= leftcol) { lc = right_word(lc); if (lc==vcol) complain(); else vcol = lc; } else { complain(); vcol = leftcol; } } break; case SEND: { c = ttyin(); ctype = ctab[c]; resend: switch(ctype) { case WLEFT: goto lstart; case WRIGHT: goto lend; case UP: goto topscreen; case DOWN: goto botscreen; case LEFT: if (vcol==leftcol) complain(); vcol = leftcol; break; case RIGHT: if (vcol==rightcol) complain(); vcol = rightcol; break; case SEND: goto command; #ifdef INTSPELL case READPIPE: showerror(SEND); if (mode==INMODE) virt_c = in_c; else mark(in_c.row); goto curset; #endif case SPECIAL: if ((ctype=(*ter.special)(true,c))>=0) goto resend; /* else fall through */ default: complain(); break; } } break; case COMMAND: command: /* sorry */ if (do_command()) etoi(); else complain(); goto curset; case CMDSTAY: /* UMIST addition */ if (do_command() && !diag_printed) { mark(in_c.row); itoe(true); } else complain(); goto curset; case TOPSCREEN: topscreen: /* sorry */ if (vrow != toprow) vrow=toprow; else { upwards(); goto curset; } break; case BOTSCREEN: botscreen: /* sorry */ if (vrow != bottomrow) vrow=bottomrow; else { downwards(); goto curset; } break; case CHMODE: (*changemode)(false); case ENTERedit: itoe(true); goto curset; case NEXTPAGE: /* UMIST addition */ if (topl+LASTINROW < maxl) set_topl(topl+NINROWS, true); else complain(); break; case LASTPAGE: /* UMIST addition */ if (topl > 0) set_topl(topl-NINROWS, true); else complain(); break; #ifdef INTCOMP case READPIPE: /* UMIST addition */ showerror(READPIPE); if (mode==INMODE) virt_c = in_c; else mark(in_c.row); goto curset; #endif case OVER: /* UMIST addition */ overtype = !overtype; if (overtype) { redisplay(EDITROW, 0, ']'|0200); diag("switching to overtype mode"); } else { redisplay(EDITROW, 0, '>'); diag("returning to insert mode"); } goto curset; default: editerror("bad character type (%d) in input",ctype); } /* dump the registers */ virt_c.row = vrow; virt_c.col = vcol; /* come here when the cursor has been set */ curset: fixpos(); } } /************************************************************************ * * * up and down a bit * * * ************************************************************************/ upwards() { virt_c.row=toprow; if (topl==0) cdiag("!! top of file !!"); else { scrdown(SCROLL, true); virt_c.row--; } } downwards() { virt_c.row=bottomrow; if (topl+virt_c.row>=maxl) { cdiag("!! end of file !!"); return(false); } else { scrup(SCROLL, true); virt_c.row++; return(true); } } linend(vrow) register int vrow; { return right_word(vrow,lastcol(vrow)); } /************************************************************************ * * * change mode and edit line * * * ************************************************************************/ itoe(wipe) register int wipe; { /* change from input to edit mode */ register int lmar = lmargin(EDITROW); if (wipe) { redraw(EDITROW, 1, ""); edit_c.col = lmar; } if (mode==INMODE) { in_c = virt_c; mark(virt_c.row); longjmp(mn_env, EDMODE); } else if (wipe) { if (virt_c.col==lmar) complain(); else virt_c.col = lmar; } } etoi() { /* change from edit to input mode */ if (mode==EDMODE) { edit_c = virt_c; unmark(); longjmp(mn_env, INMODE); } } mark(row) register int row; { if (MARGIN>1) { unmark(); if (row<0) row=0; else if (row>LASTINROW) row=LASTINROW; move_to(row,1); display('>'|0200); } } unmark() { register int row; if (MARGIN>1) { for (row=0; row<=LASTINROW; row++) if ((rowmap[row])[1] != ' ') { move_to(row,1); display(' '); } } }