getstutter(void) { int thiskey; if (!clexec) { thiskey = lastkey; kbd_seq(); if (thiskey != lastkey) { return FALSE; } } 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; }
/* 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); }
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; }