static void not_found_msg(int wrapok, int dir) { if (wrapok || global_b_val(MDTERSE)) mlforce(notfoundmsg); else mlforce(hitendmsg, ((dir == FORWARD) ? "bottom" : "top")); }
/* ARGSUSED */ int spawncli(int f, int n) { /* i never thought i'd see an ifdef like this one... strange bedfellows */ #if DISP_X11 || SYS_WIN31 mlforce("[This version of vile cannot spawn an interactive shell]"); return FALSE; #else #if SYS_UNIX bottomleft(); ttclean(TRUE); TTputc('\n'); (void)system_SHELL((char *)0); TTflush(); ttunclean(); sgarbf = TRUE; return AfterShell(); #endif /* SYS_UNIX */ #if SYS_VMS bottomleft(); mlforce("[Starting DCL]\r\n"); TTflush(); /* Ignore "ttcol". */ sgarbf = TRUE; return sys(NULL); /* NULL => DCL. */ #endif #if SYS_MSDOS || SYS_OS2 || SYS_WINNT bottomleft(); TTflush(); TTkclose(); { char *shell; if ((shell = getenv("COMSPEC")) == NULL) { #if SYS_OS2 shell = "cmd.exe"; #else shell = "command.com"; #endif system(shell); /* Will search path */ } else { #if SYS_OS2 /* * spawn it if we know it. Some 3rd party command processors fail * if they system themselves (eg 4OS2). CCM 24-MAR-94 */ spawnl( P_WAIT, shell, shell, NULL); #else system(shell); #endif } } TTkopen(); sgarbf = TRUE; return AfterShell(); #endif #endif }
static void sweepmsg(const char *msg) { char temp[NLINE]; (void) kcod2pstr(fnc2kcod(&f_multimotion), temp, (int) sizeof(temp)); mlforce("[%s (end with %.*s)]", msg, CharOf(*temp), temp + 1); }
/* ARGSUSED */ int showversion(int f GCC_UNUSED, int n) { personals(n); mlforce("%s", getversion()); return TRUE; }
static void promptpattern(const char *prompt) { /* check to see if we are executing a command line */ if (!clexec) { TBUFF *temp = tb_visbuf(tb_values(searchpat), tb_length(searchpat)); mlforce("%s[%s]: ", prompt, temp ? tb_values(temp) : ""); tb_free(&temp); } }
static int release_selection(int status) { TRACE(("MOUSE release selection\n")); if (doingsweep) { do_sweep(FALSE); if (status != TRUE) mlforce("[Sweeping: Aborted]"); else mlerase(); } sel_release(); return status; }
int operdel(int f, int n) { int status; opcmd = OPDEL; lines_deleted = 0; status = operator(f, n, killregion, regionshape == FULLLINE ? "Delete of full lines" : "Delete"); if (do_report(lines_deleted)) mlforce("[%d lines deleted]", lines_deleted); return status; }
int operdel(int f, int n) { int status; opcmd = OPDEL; lines_deleted = 0; status = vile_op(f, n, killregion, ((regionshape == rgn_FULLLINE) ? "Delete of full lines" : "Delete")); if (do_report(lines_deleted)) mlforce("[%d lines deleted]", lines_deleted); return status; }
/* * when desparate to communicate an error, enable popup messages and * use mlforce(). */ static void lastditch_msg(char *msg) { #if OPT_POPUP_MSGS int save = global_g_val(GMDPOPUP_MSGS); set_global_g_val(GMDPOPUP_MSGS, TRUE); #endif mlforce(msg); #if OPT_POPUP_MSGS update(FALSE); popup_msgs(); update(FALSE); set_global_g_val(GMDPOPUP_MSGS, save); #endif }
/* * user changed icursor mode * * Insertion cursor mode is a string that may be used to either set a fixed * block cursor height or set the block cursor heights in insertion and * command mode. Supported syntax: * * "<fixed_block_height>" * * or * * "<insmode_height>,<cmdmode_height>" * * The valid range of <fixed_block_cursor_height> is 0-100. Specifying 0 * forces the editor to revert to the cursor height in effect when the * editor was invoked. * * The valid range of <insmode_height> and <cmdmode_height> is 1-100. */ int chgd_icursor(BUFFER *bp, VALARGS * args, int glob_vals, int testing) { if (!testing) { int revert_cursor; char *val = args->global->vp->p; if (!parse_icursor_string(val, &revert_cursor)) { mlforce("[invalid icursor syntax]"); return (FALSE); } if (!revert_cursor) { chgd_cursor = TRUE; icursor = (icursor_insmode != icursor_cmdmode); if (icursor) term.icursor(insertmode); else { /* just set a block cursor */ show_cursor(TRUE, icursor_cmdmode); } } else { /* * user wants to disable previous changes made to cursor, * thereby reverting to cursor height in effect when the editor * was invoked. */ if (chgd_cursor) { /* * NB -- don't reset "chgd_cursor" here. special cleanup * is required in ntconio_close(). */ if (origcci_ok) show_cursor(TRUE, origcci.dwSize); } } } return (TRUE); }
/* ARGSUSED */ int bktoshell(int f, int n) /* suspend and wait to wake up */ { #if SYS_UNIX && defined(SIGTSTP) && !DISP_X11 int forced = (f && n == SPECIAL_BANG_ARG); /* then it was :stop! */ /* take care of autowrite */ if (!forced && writeall(f,n,FALSE,TRUE,TRUE) != TRUE) return FALSE; ttclean(TRUE); /* #define simulate_job_control_for_debug */ # ifdef simulate_job_control_for_debug rtfrmshell(SIGCONT); # else (void)signal_pg(SIGTSTP); # endif return TRUE; #else mlforce("[Job control unavailable]"); return FALSE; #endif /* SIGTSTP */ }
/* * set a variable * * int f; default flag * int n; numeric arg (can overide prompted value) */ int setvar(int f, int n) { int status; /* status return */ #if DEBUGM char *sp; /* temp string pointer */ char *ep; /* ptr to end of outline */ #endif struct variable_description vd; /* variable num/type */ char var[NVSIZE + 1]; /* name of variable to fetch */ char value[NSTRING]; /* value to set variable to */ /* first get the variable to set.. */ if (clexec == FALSE) { status = mlreply("Variable to set: ", &var[0], NVSIZE); if (status != TRUE) return status; } else { /* macro line argument */ /* grab token and skip it */ execstr = token(execstr, var, NVSIZE + 1); } /* check the legality and find the var */ findvar(var, &vd, NVSIZE + 1); /* if its not legal....bitch */ if (vd.v_type == -1) { mlwrite("%%No such variable as '%s'", var); return FALSE; } /* get the value for that variable */ if (f == TRUE) strcpy(value, itoa(n)); else { status = mlreply("Value: ", &value[0], NSTRING); if (status != TRUE) return status; } /* and set the appropriate value */ status = svar(&vd, value); #if DEBUGM /* if $debug == TRUE, every assignment will echo a statment to that effect here. */ if (macbug) { strcpy(outline, "((("); /* assignment status */ strcat(outline, ltos(status)); strcat(outline, ":"); /* variable name */ strcat(outline, var); strcat(outline, ":"); /* and lastly the value we tried to assign */ strcat(outline, value); strcat(outline, ")))"); /* expand '%' to "%%" so mlwrite wont bitch */ sp = outline; while (*sp) if (*sp++ == '%') { /* advance to the end */ ep = --sp; while (*ep++); /* null terminate the string one out */ *(ep + 1) = 0; /* copy backwards */ while (ep-- > sp) *(ep + 1) = *ep; /* and advance sp past the new % */ sp += 2; } /* write out the debug line */ mlforce(outline); update(TRUE); /* and get the keystroke to hold the output */ if (get1key() == abortc) { mlforce("(Macro aborted)"); status = FALSE; } } #endif /* and return it */ return status; }
/* the #ifdefs have been totally separated, for readability */ static int spawn1(int rerun, int pressret) { #if DISP_IBMPC int closed; #endif #if COMMON_SH_PROMPT register int s; char line[NLINE]; /* command line send to shell */ if ((s = ShellPrompt(&save_shell[0], line, rerun)) != TRUE) return s; #endif /* COMMON_SH_PROMPT */ /* take care of autowrite */ if (writeall(FALSE,1,FALSE,TRUE,TRUE) != TRUE) return FALSE; #if SYS_UNIX #if DISP_X11 (void)system_SHELL(line); #else ttclean(TRUE); (void)system_SHELL(line); TTflush(); ttunclean(); if (pressret) pressreturn(); TTopen(); TTkopen(); TTflush(); sgarbf = TRUE; #endif /* DISP_X11 */ return AfterShell(); #endif /* SYS_UNIX */ #if SYS_VMS TTputc('\n'); /* Already have '\r' */ TTflush(); s = sys(line); /* Run the command. */ mlforce("\r\n\n[End]"); /* Pause. */ TTflush(); (void)keystroke(); sgarbf = TRUE; return (s); #endif #if SYS_WIN31 mlforce("[Not in Windows 3.1]"); return FALSE; #endif #if SYS_MSDOS || SYS_OS2 || SYS_WINNT bottomleft(); TTputc('\n'); TTflush(); TTkclose(); #if DISP_IBMPC /* If we don't reset to 80x25, parts of the shell-output will go * astray. */ closed = term.t_ncol != 80 || term.t_nrow != 25; if (closed) TTclose(); #endif system(line); TTkopen(); /* if we are interactive, pause here */ if (pressret) { pressreturn(); } #if DISP_IBMPC /* Reopen the display _after_ the prompt, to keep the shell-output * in the same type of screen as the prompt. */ if (closed) TTopen(); #endif sgarbf = TRUE; return AfterShell(); #endif }
void regerror(const char *s) { mlforce("[Bad pattern: %s ]", s); }
/* * backhunt -- repeat previous forward search */ int backhunt(int f, int n) { int status = TRUE; int wrapok; MARK curpos; int didwrap; assert(curwp != 0); wrapok = window_b_val(curwp, MDWRAPSCAN); if (f && n < 0) /* search forwards */ return (forwhunt(f, -n)); if (n == 0) n = 1; /* Make sure a pattern exists */ if (tb_length(searchpat) == 0) { mlforce("[No pattern set]"); return FALSE; } ignorecase = window_b_val(curwp, MDIGNCASE); if (curwp == 0) return FALSE; /* find n'th occurrence of pattern */ curpos = DOT; scanboundry(wrapok, DOT, REVERSE); didwrap = FALSE; while (n--) { movenext(&(DOT), REVERSE); status = scanner(gregexp, REVERSE, wrapok, &didwrap); if (didwrap) { mlwrite("[Search wrapped past start of buffer]"); didwrap = FALSE; } if (status != TRUE) break; } if (status == TRUE) { savematch(DOT, gregexp->mlen); if (samepoint(DOT, curpos)) { mlwrite(onlyonemsg); } } else if (status == FALSE) { movenext(&(DOT), FORWARD); not_found_msg(wrapok, REVERSE); } else if (status == ABORT) { mlwarn("[Aborted]"); DOT = curpos; return status; } attrib_matches(); return status; }
/* * scanner -- Search for a pattern in either direction. can optionally * wrap around end of buffer. */ int scanner( regexp * exp, /* the compiled expression */ int direct, /* up or down */ int wrapok, /* ok to wrap around end of buffer? */ int *wrappedp) { MARK curpos; int found; int wrapped = FALSE; int leftmargin = b_left_margin(curbp); TRACE((T_CALLED "scanner %s %s\n", ((direct == FORWARD) ? "forward" : "backward"), (wrapok ? "wrapok" : "nowrapok"))); if (!exp) { mlforce("BUG: null exp"); returnCode(FALSE); } /* Set starting search position to current position */ curpos = DOT; if (curpos.o < leftmargin) curpos.o = leftmargin; /* Scan each character until we hit the scan boundary */ for_ever { int startoff, srchlim; if (interrupted()) { if (wrappedp) *wrappedp = wrapped; returnCode(ABORT); } if (sameline(curpos, scanboundpos)) { if (scanbound_is_header) { /* if we're on the header, nothing can match */ found = FALSE; srchlim = leftmargin; } else { if (direct == FORWARD) { if (wrapped) { startoff = curpos.o; srchlim = scanboundpos.o; } else { startoff = curpos.o; srchlim = ((scanboundpos.o > startoff) ? scanboundpos.o : llength(curpos.l)); } } else { if (wrapped) { startoff = scanboundpos.o; srchlim = llength(curpos.l); } else { startoff = leftmargin; srchlim = scanboundpos.o + 1; } } found = lregexec(exp, curpos.l, startoff, srchlim); } } else { if (direct == FORWARD) { startoff = curpos.o; srchlim = llength(curpos.l); } else { startoff = leftmargin; srchlim = curpos.o + 1; if (srchlim > llength(curpos.l)) srchlim = llength(curpos.l); } found = lregexec(exp, curpos.l, startoff, srchlim); } if (found) { char *txt = lvalue(curpos.l); char *got = exp->startp[0]; C_NUM next; C_NUM last = curpos.o; if (direct == REVERSE) { /* find the last one */ int end = FALSE; char *tst = 0; last++; while (testit(curpos.l, exp, &end, srchlim)) { got = exp->startp[0]; /* guard against infinite loop: "?$" * or "?.*" */ if (tst == got) break; tst = got; } if (end) last++; if (!lregexec(exp, curpos.l, (int) (got - txt), srchlim)) { mlforce("BUG: prev. match no good"); returnCode(FALSE); } } else if (llength(curpos.l) <= leftmargin || last < llength(curpos.l)) { last--; } next = (C_NUM) (got - txt); if (next != last) { DOT.l = curpos.l; DOT.o = next; curwp->w_flag |= WFMOVE; /* flag that we have moved */ if (wrappedp) *wrappedp = wrapped; #if OPT_TRACE trace_mark("...scanner", &DOT, curbp); #endif returnCode(TRUE); } } else { if (sameline(curpos, scanboundpos) && (!wrapok || wrapped)) break; } if (direct == FORWARD) { curpos.l = lforw(curpos.l); } else { curpos.l = lback(curpos.l); } if (is_header_line(curpos, curbp)) { wrapped = TRUE; if (sameline(curpos, scanboundpos) && (!wrapok || wrapped)) break; if (direct == FORWARD) curpos.l = lforw(curpos.l); else curpos.l = lback(curpos.l); } if (direct == FORWARD) { curpos.o = leftmargin; } else { if ((curpos.o = llength(curpos.l) - 1) < leftmargin) curpos.o = leftmargin; } } if (wrappedp) *wrappedp = wrapped; returnCode(FALSE); /* We could not find a match. */ }
/* For the "operator" commands -- the following command is a motion, or * the operator itself is repeated. All operate on regions. */ int vile_op(int f, int n, OpsFunc fn, const char *str) { int c = 0; int thiskey; int status; const CMDFUNC *cfp; /* function to execute */ const CMDFUNC *save_cmd_motion = cmd_motion; BUFFER *ourbp; #if OPT_MOUSE WINDOW *wp0 = curwp; #endif TRACE((T_CALLED "vile_op(%s)\n", str)); doingopcmd = TRUE; pre_op_dot = DOT; ourbp = curbp; if (havemotion != NULL) { cfp = havemotion; havemotion = NULL; } else { TBUFF *tok = 0; mlwrite("%s operation pending...", str); (void) update(FALSE); /* get the next command from the keyboard */ /* or a command line, as approp. */ if (clexec) { char *value = mac_unquotedarg(&tok); /* get the next token */ if (value != 0 && strcmp(value, "lines")) cfp = engl2fnc(value); else cfp = &f_godotplus; } else { thiskey = lastkey; c = kbd_seq(); #if OPT_MOUSE if (curwp != wp0) { unkeystroke(c); doingopcmd = FALSE; returnCode(FALSE); } #endif /* allow second chance for entering counts */ do_repeats(&c, &f, &n); if (thiskey == lastkey) cfp = &f_godotplus; else cfp = DefaultKeyBinding(c); } if (cfp != 0) { mlerase(); } else { if (!clexec) { char temp[NSTRING]; lsprintf(temp, "(%d)", c); tb_scopy(&tok, temp); } (void) no_such_function(tb_values(tok)); } tb_free(&tok); } if (!cfp) { status = FALSE; } else if ((cfp->c_flags & MOTION) == 0) { kbd_alarm(); status = ABORT; } else { /* motion is interpreted as affecting full lines */ if (regionshape == rgn_EXACT) { if (cfp->c_flags & FL) regionshape = rgn_FULLLINE; if (cfp->c_flags & VL_RECT) regionshape = rgn_RECTANGLE; } /* and execute the motion */ if ((status = execute(cfp, f, n)) == TRUE) { post_op_dot = DOT; } else { mlforce("[Motion failed]"); status = FALSE; } } if (status == TRUE) { opcmd = 0; MK = pre_op_dot; /* we've successfully set up a region */ if (!fn) { /* be defensive */ mlforce("BUG -- null func pointer in operator"); status = FALSE; } else if (fn == user_operator) { swapmark(); cmd_motion = cfp; status = dobuf(find_b_name(str), 1, f ? n : 1); } else { status = (fn) (); } if (ourbp == curbp) /* in case the func switched buffers on us */ swapmark(); if (regionshape == rgn_FULLLINE) (void) firstnonwhite(FALSE, 1); } regionshape = rgn_EXACT; doingopcmd = FALSE; haveregion = FALSE; cmd_motion = save_cmd_motion; returnCode(status); }
static BUFFER * gettagsfile(int n, int *endofpathflagp, int *did_read) { #ifdef MDCHK_MODTIME time_t current; #endif char *tagsfile; BUFFER *tagbp; char tagbufname[NBUFN]; char tagfilename[NFILEN]; *endofpathflagp = FALSE; *did_read = FALSE; (void) lsprintf(tagbufname, TAGFILE_BufName, n + 1); /* is the buffer around? */ if ((tagbp = find_b_name(tagbufname)) == NULL) { char *tagf = global_b_val_ptr(VAL_TAGS); nth_name(tagfilename, tagf, n); if (!doglob(tagfilename) || tagfilename[0] == EOS) { *endofpathflagp = TRUE; return NULL; } /* look up the tags file */ tagsfile = cfg_locate(tagfilename, LOCATE_TAGS); /* if it isn't around, don't sweat it */ if (tagsfile == NULL) { return NULL; } /* find the pointer to that buffer */ if ((tagbp = bfind(tagbufname, BFINVS)) == NULL) { mlforce("[Can't create tags buffer]"); return NULL; } if (readin(tagsfile, FALSE, tagbp, FALSE) != TRUE) { zotbuf(tagbp); return NULL; } *did_read = TRUE; } #ifdef MDCHK_MODTIME /* * Re-read the tags buffer if we are checking modification-times and * find that the tags file's been changed. We check the global mode * value because it's too awkward to set the local mode value for a * scratch buffer. */ if (global_b_val(MDCHK_MODTIME) && get_modtime(tagbp, ¤t) && tagbp->b_modtime != current) { if (!*did_read && readin(tagbp->b_fname, FALSE, tagbp, FALSE) != TRUE) { zotbuf(tagbp); return NULL; } set_modtime(tagbp, tagbp->b_fname); *did_read = TRUE; } #endif b_set_invisible(tagbp); return tagbp; }
static int doshowhypercmd(char *cmd) { mlforce("%s", cmd); return 1; }
int multimotion(int f, int n) { const CMDFUNC *cfp; int status, c, waserr; int pasting; REGIONSHAPE shape; MARK savedot; MARK savemark; MARK realdot; BUFFER *origbp = curbp; static int wassweephack = FALSE; /* Use the repeat-count as a shortcut to specify the type of selection. * I'd use int-casts of the enum value, but declaring enums with * specific values isn't 100% portable. */ n = need_at_least(f, n, 1); if (n == 3) regionshape = rgn_RECTANGLE; else if (n == 2) regionshape = rgn_FULLLINE; else regionshape = rgn_EXACT; shape = regionshape; sweephack = FALSE; savedot = DOT; switch (doingsweep) { case TRUE: /* the same command terminates as starts the sweep */ if (doingsweep) { do_sweep(FALSE); } mlforce("[Sweeping: Completed]"); regionshape = shape; /* since the terminating 'q' is executed as a motion, we have now lost the value of sweephack we were interested in, the one that tells us to include DOT.o in the selection. so we preserved it in wassweephack, and restore it here. */ if (wassweephack) sweephack = wassweephack; return TRUE; case SORTOFTRUE: if (doingsweep != TRUE) { do_sweep(TRUE); } sweepmsg("Begin cursor sweep..."); sel_extend(TRUE, (regionshape != rgn_RECTANGLE && sweephack)); savedot = MK; TRACE(("MOUSE BEGIN DOT: %d.%d MK %d.%d\n", line_no(curbp, DOT.l), DOT.o, line_no(curbp, MK.l), MK.o)); break; case FALSE: if (doingsweep != TRUE) { do_sweep(TRUE); } sweepmsg("Begin cursor sweep..."); (void) sel_begin(); (void) sel_setshape(shape); break; } waserr = TRUE; /* to force message "state-machine" */ realdot = DOT; pasting = FALSE; while (doingsweep) { /* Fix up the screen */ (void) update(FALSE); /* get the next command from the keyboard */ c = kbd_seq(); if (ABORTED(c) || curbp != origbp) { return release_selection(FALSE); } f = FALSE; n = 1; do_repeats(&c, &f, &n); /* and execute the command */ cfp = SelectKeyBinding(c); if ((cfp != NULL) && ((cfp->c_flags & (GOAL | MOTION)) != 0)) { MARK testdot; wassweephack = sweephack; sweephack = FALSE; TRACE(("MOUSE TEST DOT: %d.%d MK %d.%d\n", line_no(curbp, DOT.l), DOT.o, line_no(curbp, MK.l), MK.o)); testdot = DOT; status = execute(cfp, f, n); switch (status) { case SEL_RELEASE: TRACE(("MOUSE SEL_RELEASE %d.%d\n", line_no(curbp, DOT.l), DOT.o)); return release_selection(TRUE); case SEL_PASTE: pasting = TRUE; /* FALLTHRU */ case SEL_FINISH: do_sweep(FALSE); break; case SORTOFTRUE: TRACE(("MOUSE selection pending %d.%d -> %d.%d\n", line_no(curbp, realdot.l), realdot.o, line_no(curbp, testdot.l), testdot.o)); realdot = testdot; break; case SEL_BEGIN: savedot = MK; TRACE(("MOUSE SEL_BEGIN...\n")); /*FALLTHRU */ case SEL_EXTEND: TRACE(("MOUSE SEL_EXTEND from %d.%d to %d.%d\n", line_no(curbp, savedot.l), savedot.o, line_no(curbp, DOT.l), DOT.o)); /*FALLTHRU */ case TRUE: if (waserr && doingsweep) { sweepmsg("Sweeping..."); waserr = FALSE; } realdot = DOT; DOT = savedot; (void) sel_begin(); DOT = realdot; TRACE(("MOUSE LOOP save: %d.%d real %d.%d, mark %d.%d\n", line_no(curbp, savedot.l), savedot.o, line_no(curbp, realdot.l), realdot.o, line_no(curbp, MK.l), MK.o)); (void) sel_setshape(shape); /* we sometimes want to include DOT.o in the selection (unless it's a rectangle, in which case it's taken care of elsewhere) */ sel_extend(TRUE, (regionshape != rgn_RECTANGLE && sweephack)); break; default: sweepmsg("Sweeping: Motion failed."); waserr = TRUE; break; } } else { sweepmsg("Sweeping: Only motions permitted"); waserr = TRUE; } } regionshape = shape; /* if sweephack is set here, it's because the last motion had it set */ if (doingopcmd) pre_op_dot = savedot; savedot = DOT; savemark = MK; DOT = realdot; TRACE(("MOUSE SAVE DOT: %d.%d MK %d.%d\n", line_no(curbp, DOT.l), DOT.o, line_no(curbp, MK.l), MK.o)); if ((regionshape != rgn_RECTANGLE) && sweephack) { if (dot_vs_mark() < 0) MK.o += BytesAt(MK.l, MK.o); else DOT.o += BytesAt(DOT.l, DOT.o); } status = yankregion(); DOT = savedot; MK = savemark; sweephack = wassweephack = FALSE; if (status == TRUE && pasting) status = SEL_PASTE; return status; }
/* * dobuf: * execute the contents of the buffer pointed to * by the passed BP * * Directives start with a "!" and include: * * !endm End a macro * !if (cond) conditional execution * !else * !endif * !return Return (terminating current macro) * !goto <label> Jump to a label in the current macro * !force Force macro to continue...even if command fails * !while (cond) Execute a loop if the condition is true * !endwhile * * Line Labels begin with a "*" as the first nonblank char, like: * * *LBL01 * * struct buffer *bp; buffer to execute */ int dobuf(struct buffer *bp) { int status; /* status return */ struct line *lp; /* pointer to line to execute */ struct line *hlp; /* pointer to line header */ struct line *glp; /* line to goto */ struct line *mp; /* Macro line storage temp */ int dirnum; /* directive index */ int linlen; /* length of line to execute */ int i; /* index */ int c; /* temp character */ int force; /* force TRUE result? */ struct window *wp; /* ptr to windows to scan */ struct while_block *whlist; /* ptr to !WHILE list */ struct while_block *scanner; /* ptr during scan */ struct while_block *whtemp; /* temporary ptr to a struct while_block */ char *einit; /* initial value of eline */ char *eline; /* text of line to execute */ char *tkn; /* buffer to evaluate an expresion in */ #if DEBUGM char *sp; /* temp for building debug string */ char *ep; /* ptr to end of outline */ #endif tkn = alloca(NSTRING * sizeof(char)); /* clear IF level flags/while ptr */ execlevel = 0; whlist = NULL; scanner = NULL; /* scan the buffer to execute, building WHILE header blocks */ hlp = bp->b_linep; lp = hlp->l_fp; while (lp != hlp) { /* scan the current line */ eline = lp->l_text; i = lp->l_used; /* trim leading whitespace */ while (i-- > 0 && (*eline == ' ' || *eline == '\t')) ++eline; /* if theres nothing here, don't bother */ if (i <= 0) goto nxtscan; /* if is a while directive, make a block... */ if (eline[0] == '!' && eline[1] == 'w' && eline[2] == 'h') { whtemp = (struct while_block *)malloc(sizeof(struct while_block)); if (whtemp == NULL) { noram:mlwrite ("%%Out of memory during while scan"); failexit:freewhile (scanner); freewhile(whlist); return FALSE; } whtemp->w_begin = lp; whtemp->w_type = BTWHILE; whtemp->w_next = scanner; scanner = whtemp; } /* if is a BREAK directive, make a block... */ if (eline[0] == '!' && eline[1] == 'b' && eline[2] == 'r') { if (scanner == NULL) { mlwrite ("%%!BREAK outside of any !WHILE loop"); goto failexit; } whtemp = (struct while_block *)malloc(sizeof(struct while_block)); if (whtemp == NULL) goto noram; whtemp->w_begin = lp; whtemp->w_type = BTBREAK; whtemp->w_next = scanner; scanner = whtemp; } /* if it is an endwhile directive, record the spot... */ if (eline[0] == '!' && strncmp(&eline[1], "endw", 4) == 0) { if (scanner == NULL) { mlwrite ("%%!ENDWHILE with no preceding !WHILE in '%s'", bp->b_bname); goto failexit; } /* move top records from the scanner list to the whlist until we have moved all BREAK records and one WHILE record */ do { scanner->w_end = lp; whtemp = whlist; whlist = scanner; scanner = scanner->w_next; whlist->w_next = whtemp; } while (whlist->w_type == BTBREAK); } nxtscan: /* on to the next line */ lp = lp->l_fp; } /* while and endwhile should match! */ if (scanner != NULL) { mlwrite("%%!WHILE with no matching !ENDWHILE in '%s'", bp->b_bname); goto failexit; } /* let the first command inherit the flags from the last one.. */ thisflag = lastflag; /* starting at the beginning of the buffer */ hlp = bp->b_linep; lp = hlp->l_fp; while (lp != hlp) { /* allocate eline and copy macro line to it */ linlen = lp->l_used; if ((einit = eline = malloc(linlen + 1)) == NULL) { mlwrite("%%Out of Memory during macro execution"); freewhile(whlist); return FALSE; } strncpy(eline, lp->l_text, linlen); eline[linlen] = 0; /* make sure it ends */ /* trim leading whitespace */ while (*eline == ' ' || *eline == '\t') ++eline; /* dump comments and blank lines */ if (*eline == ';' || *eline == 0) goto onward; #if DEBUGM /* if $debug == TRUE, every line to execute gets echoed and a key needs to be pressed to continue ^G will abort the command */ if (macbug) { strcpy(outline, "<<<"); /* debug macro name */ strcat(outline, bp->b_bname); strcat(outline, ":"); /* debug if levels */ strcat(outline, itoa(execlevel)); strcat(outline, ":"); /* and lastly the line */ strcat(outline, eline); strcat(outline, ">>>"); /* change all '%' to ':' so mlwrite won't expect arguments */ sp = outline; while (*sp) if (*sp++ == '%') { /* advance to the end */ ep = --sp; while (*ep++); /* null terminate the string one out */ *(ep + 1) = 0; /* copy backwards */ while (ep-- > sp) *(ep + 1) = *ep; /* and advance sp past the new % */ sp += 2; } /* write out the debug line */ mlforce(outline); update(TRUE); /* and get the keystroke */ if ((c = get1key()) == abortc) { mlforce("(Macro aborted)"); freewhile(whlist); return FALSE; } if (c == metac) macbug = FALSE; } #endif /* Parse directives here.... */ dirnum = -1; if (*eline == '!') { /* Find out which directive this is */ ++eline; for (dirnum = 0; dirnum < NUMDIRS; dirnum++) if (strncmp(eline, dname[dirnum], strlen(dname[dirnum])) == 0) break; /* and bitch if it's illegal */ if (dirnum == NUMDIRS) { mlwrite("%%Unknown Directive"); freewhile(whlist); return FALSE; } /* service only the !ENDM macro here */ if (dirnum == DENDM) { mstore = FALSE; bstore = NULL; goto onward; } /* restore the original eline.... */ --eline; } /* if macro store is on, just salt this away */ if (mstore) { /* allocate the space for the line */ linlen = strlen(eline); if ((mp = lalloc(linlen)) == NULL) { mlwrite ("Out of memory while storing macro"); return FALSE; } /* copy the text into the new line */ for (i = 0; i < linlen; ++i) lputc(mp, i, eline[i]); /* attach the line to the end of the buffer */ bstore->b_linep->l_bp->l_fp = mp; mp->l_bp = bstore->b_linep->l_bp; bstore->b_linep->l_bp = mp; mp->l_fp = bstore->b_linep; goto onward; } force = FALSE; /* dump comments */ if (*eline == '*') goto onward; /* now, execute directives */ if (dirnum != -1) { /* skip past the directive */ while (*eline && *eline != ' ' && *eline != '\t') ++eline; execstr = eline; switch (dirnum) { case DIF: /* IF directive */ /* grab the value of the logical exp */ if (execlevel == 0) { if (macarg(tkn) != TRUE) goto eexec; if (stol(tkn) == FALSE) ++execlevel; } else ++execlevel; goto onward; case DWHILE: /* WHILE directive */ /* grab the value of the logical exp */ if (execlevel == 0) { if (macarg(tkn) != TRUE) goto eexec; if (stol(tkn) == TRUE) goto onward; } /* drop down and act just like !BREAK */ case DBREAK: /* BREAK directive */ if (dirnum == DBREAK && execlevel) goto onward; /* jump down to the endwhile */ /* find the right while loop */ whtemp = whlist; while (whtemp) { if (whtemp->w_begin == lp) break; whtemp = whtemp->w_next; } if (whtemp == NULL) { mlwrite ("%%Internal While loop error"); freewhile(whlist); return FALSE; } /* reset the line pointer back.. */ lp = whtemp->w_end; goto onward; case DELSE: /* ELSE directive */ if (execlevel == 1) --execlevel; else if (execlevel == 0) ++execlevel; goto onward; case DENDIF: /* ENDIF directive */ if (execlevel) --execlevel; goto onward; case DGOTO: /* GOTO directive */ /* .....only if we are currently executing */ if (execlevel == 0) { /* grab label to jump to */ eline = token(eline, golabel, NPAT); linlen = strlen(golabel); glp = hlp->l_fp; while (glp != hlp) { if (*glp->l_text == '*' && (strncmp (&glp->l_text[1], golabel, linlen) == 0)) { lp = glp; goto onward; } glp = glp->l_fp; } mlwrite("%%No such label"); freewhile(whlist); return FALSE; } goto onward; case DRETURN: /* RETURN directive */ if (execlevel == 0) goto eexec; goto onward; case DENDWHILE: /* ENDWHILE directive */ if (execlevel) { --execlevel; goto onward; } else { /* find the right while loop */ whtemp = whlist; while (whtemp) { if (whtemp->w_type == BTWHILE && whtemp->w_end == lp) break; whtemp = whtemp->w_next; } if (whtemp == NULL) { mlwrite ("%%Internal While loop error"); freewhile(whlist); return FALSE; } /* reset the line pointer back.. */ lp = whtemp->w_begin->l_bp; goto onward; } case DFORCE: /* FORCE directive */ force = TRUE; } } /* execute the statement */ status = docmd(eline); if (force) /* force the status */ status = TRUE; /* check for a command error */ if (status != TRUE) { /* look if buffer is showing */ wp = wheadp; while (wp != NULL) { if (wp->w_bufp == bp) { /* and point it */ wp->w_dotp = lp; wp->w_doto = 0; wp->w_flag |= WFHARD; } wp = wp->w_wndp; } /* in any case set the buffer . */ bp->b_dotp = lp; bp->b_doto = 0; free(einit); execlevel = 0; freewhile(whlist); return status; } onward: /* on to the next line */ free(einit); lp = lp->l_fp; } eexec: /* exit the current function */ execlevel = 0; freewhile(whlist); return TRUE; }
/* For the "operator" commands -- the following command is a motion, or * the operator itself is repeated. All operate on regions. */ int operator(int f, int n, OpsFunc fn, const char *str) { int c; int thiskey; int status; const CMDFUNC *cfp; /* function to execute */ char tok[NSTRING]; /* command incoming */ BUFFER *ourbp; #if OPT_MOUSE WINDOW *wp0 = curwp; #endif doingopcmd = TRUE; pre_op_dot = DOT; ourbp = curbp; if (havemotion != NULL) { cfp = havemotion; havemotion = NULL; } else { mlwrite("%s operation pending...",str); (void)update(FALSE); /* get the next command from the keyboard */ /* or a command line, as approp. */ if (clexec) { macarg(tok); /* get the next token */ if (!strcmp(tok,"lines")) cfp = &f_godotplus; else cfp = engl2fnc(tok); } else { thiskey = lastkey; c = kbd_seq(); #if OPT_MOUSE if (curwp != wp0) { unkeystroke(c); doingopcmd = FALSE; return FALSE; } #endif /* allow second chance for entering counts */ do_repeats(&c,&f,&n); if (thiskey == lastkey) cfp = &f_godotplus; else cfp = kcod2fnc(c); } if (cfp) mlerase(); else mlforce("[No such function]"); } if (!cfp) { doingopcmd = FALSE; return FALSE; } if ((cfp->c_flags & MOTION) == 0) { kbd_alarm(); doingopcmd = FALSE; return(ABORT); } /* motion is interpreted as affecting full lines */ if (regionshape == EXACT) { if (cfp->c_flags & FL) regionshape = FULLLINE; if (cfp->c_flags & RECT) regionshape = RECTANGLE; } /* and execute the motion */ status = execute(cfp, f,n); if (status != TRUE) { doingopcmd = FALSE; regionshape = EXACT; mlforce("[Motion failed]"); return FALSE; } opcmd = 0; MK = pre_op_dot; /* we've successfully set up a region */ if (!fn) { /* be defensive */ mlforce("BUG -- null func pointer in operator"); status = FALSE; } else { status = (fn)(); } if (ourbp == curbp) /* in case the func switched buffers on us */ swapmark(); if (regionshape == FULLLINE) (void)firstnonwhite(FALSE,1); regionshape = EXACT; doingopcmd = FALSE; haveregion = FALSE; return status; }
static void handle_mouse_event(MOUSE_EVENT_RECORD mer) { static DWORD lastclick = 0; static int clicks = 0; int onmode = FALSE; COORD current, first, latest; MARK lmbdn_mark; /* left mouse button down here */ int sel_pending = 0, state; DWORD thisclick; UINT clicktime = GetDoubleClickTime(); buttondown = FALSE; for_ever { current = mer.dwMousePosition; switch (mer.dwEventFlags) { case 0: state = mer.dwButtonState; if (state == 0) { /* button released */ thisclick = GetTickCount(); TRACE(("CLICK %d/%d\n", lastclick, thisclick)); if (thisclick - lastclick < clicktime) { clicks++; TRACE(("MOUSE CLICKS %d\n", clicks)); } else { clicks = 0; } lastclick = thisclick; switch (clicks) { case 1: on_double_click(); break; case 2: on_triple_click(); break; } if (buttondown) { int dummy; halt_autoscroll_thread(); /* Finalize cursor position. */ (void) MouseClickSetPos(¤t, &dummy); if (!(onmode || sel_pending)) sel_yank(0); } return; } if (state & FROM_LEFT_1ST_BUTTON_PRESSED) { if (MouseClickSetPos(¤t, &onmode)) { first = latest = current; lmbdn_mark = DOT; sel_pending = FALSE; mouse_wp = row2window(latest.Y); if (onmode) { buttondown = TRUE; sel_release(); update(TRUE); } else { HWND hwnd; (void) update(TRUE); /* possible wdw change */ buttondown = FALSE; /* until all inits are successful */ /* Capture mouse to console vile's window handle. */ hwnd = GetVileWindow(); (void) SetCapture(hwnd); /* Compute pixel height of each row on screen. */ (void) GetClientRect(hwnd, &client_rect); row_height = client_rect.bottom / term.rows; /* * Create mutex to ensure that main thread and worker * thread don't update display at the same time. */ if ((hAsMutex = CreateMutex(0, FALSE, 0)) == NULL) mlforce("[Can't create autoscroll mutex]"); else { /* * Setup a worker thread to act as a pseudo * timer that kicks off autoscroll when * necessary. */ if (_beginthread(autoscroll_thread, 0, NULL) == (unsigned long) -1) { (void) CloseHandle(hAsMutex); mlforce("[Can't create autoscroll thread]"); } else sel_pending = buttondown = TRUE; } if (!buttondown) (void) ReleaseCapture(); } } } else if (state & FROM_LEFT_2ND_BUTTON_PRESSED) { if (MouseClickSetPos(¤t, &onmode) && !onmode) { sel_yank(0); sel_release(); paste_selection(); (void) update(TRUE); } return; } else { if (MouseClickSetPos(¤t, &onmode) && onmode) { sel_release(); update(TRUE); } else { kbd_alarm(); } } break; case MOUSE_MOVED: if (!buttondown) return; if (onmode) { /* on mode line, resize window (if possible). */ if (!adjust_window(mouse_wp, ¤t, &latest)) { /* * left mouse button still down, but cursor moved off mode * line. Update latest to keep track of cursor in case * it wanders back on the mode line. */ latest = current; } } else { mousemove(&sel_pending, &first, ¤t, &lmbdn_mark, (mer.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) ); } break; #ifdef MOUSE_WHEELED case MOUSE_WHEELED: /* * Trial and error experimentation shows that dwButtonState * has its high bit set when the wheel moves back and not * set otherwise. */ mvupwind(TRUE, ((long) mer.dwButtonState < 0) ? -3 : 3); update(TRUE); return; #endif /* MOUSE_WHEELED */ } for_ever { INPUT_RECORD ir; DWORD nr; int key; if (!ReadConsoleInput(hConsoleInput, &ir, 1, &nr)) imdying(0); switch (ir.EventType) { case KEY_EVENT: key = decode_key_event(&ir); if (key == ESC) { if (buttondown) halt_autoscroll_thread(); sel_release(); (void) update(TRUE); return; } continue; case MOUSE_EVENT: mer = ir.Event.MouseEvent; break; } break; } } }