#include "ded.h" #include "jmp.h" #include "match.h" #include "char.h" #include "ter.h" #include "range.h" /************************************************************************ * * * copyright Richard Bornat 1981 * * * ************************************************************************/ struct COMMANDS { char *str; int (*func)(); char params; /* params=0 means no parameters, * 1 means parameters, leading spaces insignificant * 2 means parameters, leading spaces to be preserved */ }; /* forward declarations */ int do_unix(), /* unix.c */ do_exclam(), do_plus(), do_quote(), do_dollar(), do_percent(), do_ampersand(), do_prime(), do_minus(), do_mark(), do_slash(), do_semicolon(), do_equals(), #ifdef QMC & V6 do_at(), #endif do_uparrow(), do_break(), do_bell(), do_copy(), do_delete(), #ifdef DBUG do_dbug(), do_unbug(), #endif do_eof(), do_first(), do_file(), do_first(), do_last(), do_move(), do_exit(), do_printscreen(), do_wrdel(), do_appdel(), do_append(), /* iocomm.c */ do_quit(), do_read(), do_rquit(), do_rwrite(), /* iocomm.c */ do_schange(), do_tab(), do_tabset(), do_tof(), do_write(), /* iocomm.c */ do_xchange(), do_edit(), do_redit(), do_wedit(), do_restart(); struct COMMANDS commands[] = { "!", do_exclam, 1, "+", do_plus, 1, /* write file then do_unix UMIST */ "\"", do_quote, 0, "$", do_dollar, 0, "%", do_percent, 0, "&", do_ampersand, 0, "'", do_prime, 1, "-", do_minus, 0, ".", do_mark, 1, "/", do_slash, 2, ";", do_semicolon, 2, "=", do_equals, 1, #ifdef QMC # ifdef V6 "@", do_at, 0, # endif #endif "^", do_tof, 0, "a", do_append, 1, "ad", do_appdel, 1, "b", do_break, 1, "bell", do_bell, 1, "c", do_copy, 1, "d", do_delete, 1, "da", do_appdel, 1, #ifdef DBUG "dbug", do_dbug, 1, #endif "edit", do_edit, 1, "e", do_edit, 1, /* for 'em' compatibility - UMIST */ "eof", do_eof, 0, "f", do_first, 1, "file", do_file, 0, "l", do_last, 1, "m", do_move, 1, "ok", do_exit, 0, "p", do_printscreen, 0, "q", do_quit, 0, "r", do_read, 1, "reallyedit", do_redit, 1, "reallyquit", do_rquit, 0, "reallywrite", do_rwrite, 0, "restart", do_restart, 0, "s", do_schange, 1, "t", do_tab, 1, "tab", do_tabset, 2, /* user defined tab width - UMIST */ "tof", do_tof, 0, #ifdef DBUG "unbug", do_unbug, 1, #endif "w", do_write, 1, "wd", do_wrdel, 1, "wedit", do_wedit, 1, "x", do_xchange, 1, 0, }; do_command() { char line[ENOUGH]; struct COMMANDS *com=commands; char str[ENOUGH]; register char *sp=str, *lp=line; register int lnum=0; int i; /* set jumpout position */ switch (i=setjmp(dc_env)) { case 0: break; case OK: return(true); case NOT_OK: return(false); default: editerror("val %d in longjmp to dc_env", i); } /* find command string */ diag_clear(); copyrow(EDITROW,1,line); /* remember current position */ if (mode==INMODE) in_c = virt_c; else edit_c = virt_c; /* position for cursor after an interrupt */ ab_line=topl+in_c.row; ab_col=in_c.col; /* pick up command */ while (*lp==' ') lp++; if (*lp==0) tdiag("?? no command"); else if (alpha(*lp)) while (alpha(*lp)) *sp++ = lcase(*lp++); else if (digit(*lp)) { do lnum = lnum*10+(*lp++ - '0'); while (digit(*lp)); lnum--; /* ded numbers lines from zero */ if (*lp != 0) tdiag("!! command follows number !!"); else if (lnum<0 || lnum>maxl) tdiag("!! no such line !!"); else { blobit(); disp_range(lnum, lnum, true, true); /* no return */ } } else /* if no alpha character, accept first character */ *sp++ = *lp++; /* find procedure indexed by command, call it */ *sp=0; while (com->str != 0) if (streq(str,com->str)) { if (com->params || *lp==0) { blobit(); /* find first character of command */ if (com->params==1) while(*lp==' ') lp++; (*(com->func))(lp); diag_clear(); leave_command(OK); /* procedure will call tdiag or fdiag on error */ } else fdiag("?? no parameters allowed ??"); } else com++; /* exit from loop only on error */ tdiag("?? unrecognisable command"); } /* leave do_command, resetting the cursor. Result is OK/NOT_OK */ leave_command(val) register int val; { if (mode==INMODE) virt_c = in_c; else virt_c = edit_c; longjmp(dc_env, val); } /* check when dangerous commands are attempted */ check_replay(message) char *message; { return(NORMAL_INPUT || query(message)); } /* fill in missing argument from memory */ char *fillin(arg, old_arg, message) char *arg, *old_arg, *message; { register char *a, *oa; if (arg==0 || *arg==0) { if (*old_arg==0) tdiag("?? %s ??", message); /* 'else' removed to quieten lint */ diag_clear(); redraw(EDITROW, lastcol(EDITROW)+1, old_arg); blobit(); return(old_arg); } else { a = arg; oa = old_arg; while (*oa++ = *a++); return(arg); } } do_exit() { longjmp(mn_env, OK); } /************************************************************************ * * * deleting lines and ranges * * * ************************************************************************/ #define SIMPLE (ter.scrseq.hardscroll || brange==erange) do_delete(str) register char *str; { char crange; int brange, erange; str = get_range(str, &crange, &brange, &erange); if (*str!=0) fdiag("!! only one argument allowed !!"); if (erangetopl+LASTINROW) shuffile(erange+1, -(erange-brange+1), 0); else { if (brangetopl+LASTINROW) /* delete the lines after end of screen */ { shuffile(erange, -(erange-(topl+LASTINROW)), 0); erange = topl+LASTINROW; } /* now the whole thing is on the screen */ { struct CURSOR tmp; tmp = virt_c; virt_c = in_c; if (ter.scrseq.hardscroll) while (erange+1>brange) { del_row(erange-topl); erange--; } else { int i = erange-brange+1; savescreen(); shuffile(erange+1, -i, 0); if (EOF) { while (EOF && topl>0 && l_offset[maxl]==(unsigned)-1 && (i-- > 0)) dec_topl(); if (!EOF) inc_topl(); } virt_c.row = brange-topl; refreshscreen(); } /* not hardscroll */ in_c = virt_c; virt_c = tmp; } } if (mode!=INMODE) mark(in_c.row); } /* procedures to create ranges */ do_first(str) char *str; { register char c, rc; c = one_letter(str); rc = c-'a'; b_range[rc] = topl+in_c.row; if (e_range[rc] == -1 || e_range[rc] < b_range[rc]) e_range[rc] = b_range[rc]; val_range(c); show_range(); } do_last(str) char *str; { register char c, rc; c = one_letter(str); rc = c-'a'; e_range[rc] = topl+in_c.row; if (b_range[rc]==-1 || e_range[rc] < b_range[rc]) b_range[rc] = e_range[rc]; val_range(c); show_range(); } do_mark(str) char *str; { register char c, rc; c = one_letter(str); rc = c-'a'; b_range[rc] = e_range[rc] = topl+in_c.row; val_range(c); show_range(); } /* routines to move blocks of lines about */ do_move(str) char *str; { shift_range(str, true); } do_copy(str) char *str; { shift_range(str, false); } /* get a single range argument from the command string */ char *get_range(str, a_char, a_first, a_second) char *str; char *a_char; int *a_first, *a_second; { char foo; return(one_range(str, a_char, a_first, a_second, false, &foo)); } /* this tells about a position - it gives a line number and a marker * which is after ('+'), before ('-') or neutral (0) */ char *get_pos(str, a_char, a_line, a_after) char *str; char *a_char; int *a_line; char *a_after; { int first, second; str = one_range(str, a_char, &first, &second, true, a_after); if (*a_after=='-') *a_line = first; else *a_line = second; return(str); } /* display a range on screen */ do_prime(str) char *str; { int begin, end; int before; char c0; char afterc; str = one_range(str, &c0, &begin, &end, true, &afterc); if (afterc=='-' || afterc==0) before = true; else before = false; if (*str != 0) fdiag("!! invalid range !!"); else disp_range(begin, end, before, true); } /* give information about ranges */ do_equals(str) char *str; { char crange; int brange, erange; str = get_range(str, &crange, &brange, &erange); if (*str!=0) fdiag("!! range must be single character !!"); else tell_range(crange); } /* routines to change to another screenful */ do_quote() { if (topl+LASTINROW < maxl) { set_topl(topl+NINROWS, true); i_mode(0,MARGIN); } else complain(); } do_ampersand() { if (topl > 0) { set_topl(topl-NINROWS, true); i_mode(0,MARGIN); } else complain(); } do_tof() { if (topl+in_c.row != 0) set_topl(0, true); else complain(); i_mode(0,MARGIN); } do_eof() { int lc; if (topl+LASTINROWbline) { sline=bline; scol=ncols; } if (*str==0) { if ( find(direction, sline, scol, tline, bline) ) { set_topl(enclose_range(ms_line, mf_line, true), true); complain(); /* bleep */ i_mode(ms_line-topl, ms_col); } else tdiag("!! can't find it !!"); } else fdiag("!! pattern continues after '%c'", range); } /************************************************************************ * * * procedures for string-substitution commands * * * ************************************************************************/ do_xchange(str) char *str; { make_change(str, false); } do_schange(str) char *str; { make_change(str, true); } make_change(str, silence) char *str; int silence; { char first_ch; register int sline=topl+in_c.row, scol=in_c.col; str = fillin(str, old_pat, "no search pattern"); if ((first_ch = *str) != '/' && first_ch != ';') fdiag("!! pattern must start with '/' or ';' !!"); str = build_re(str+1); if (*str==0) fdiag("!! no replacement pattern !!"); { char *sp=str, cp, range; int tline=0, bline=maxl; while ((cp = *sp++)!=0) { if (cp=='\'' && *sp++==0) break; /* skip the next character */ else if (cp=='/' || cp==';') { if (*sp==0) break; else { sp=get_range(sp, &range, &tline, &bline); if (*sp!=0) fdiag("!! command continues after '%c'", range); else break; } } } if (slinebline) { sline=bline; scol=ncols; } change(str, (first_ch=='/' ? FORWARD : BACKWARD), sline, scol, tline, bline, silence); } } do_percent() { int fline; fline = topl+in_c.row; set_topl(fline-NINROWS/2, true); i_mode(fline-topl,in_c.col); } do_exclam(comm) char *comm; { do_unix(comm, '!'); } do_plus(comm) char *comm; { savescreen(); if (tmp_changed) savefile(tdiag, true); do_unix(comm, '+'); } #ifdef QMC & V6 do_at() { do_unix((char *)0, '@'); } /* activates a newsh */ #endif do_minus() { do_unix((char *)0, '-'); } /* activates a sh */ do_printscreen() { savescreen(); setupscreen(); } /************************************************************************ * * * procedures to set options * * * ************************************************************************/ do_tab(str) char *str; { option(str,"t",&tbout); } do_tabset(str) /* PLS 18/12/82 */ char *str; { int num = 0; while (*str == ' ') str++; while (digit(*str)) num = num*10 + (*str++ - '0'); if (*str == 0) tabsiz = num; else tdiag("!! arg must be a number !!"); } do_break(str) char *str; { option(str,"b",&txin); } do_bell(str) char *str; { option(str, "bell", &ringing); } option(str, com, var) char *str, *com; int *var; { if (*str==0) fdiag("?? no option follows %s ??", com); else if (*str=='+' && str[1]==0) *var = true; else if (*str=='-' && str[1]==0) *var = false; else fdiag("?? unrecognisable option after %s ??", com); } i_mode(srow,scol) int srow,scol; { diag_clear(); in_mode(srow, scol); } in_mode(srow, scol) int srow, scol; { set_c(srow, scol, &in_c); /* if (mode==INMODE) */ leave_command(OK); /* else etoi(); */ } /* put a selected line on-screen */ i_display(fline) int fline; { if (fline