Beispiel #1
0
void
on_double_click(void)
{
    MARK save;

    save = DOT;
    TRACE(("MOUSE double-click DOT %d.%d\n", line_no(curbp, DOT.l), DOT.o));
    sel_release();
    if (!is_at_end_of_line(DOT)
	&& !isSpace(CharAtDot())) {
	while (DOT.o > 0) {
	    DOT.o -= BytesBefore(DOT.l, DOT.o);
	    if (isSpace(CharAtDot())) {
		DOT.o += BytesAt(DOT.l, DOT.o);
		break;
	    }
	}
	sel_begin();
	MK = DOT;
	while (!is_at_end_of_line(DOT)) {
	    DOT.o += BytesAt(DOT.l, DOT.o);
	    if (is_at_end_of_line(DOT)
		|| isSpace(CharAtDot())) {
		DOT.o -= BytesBefore(DOT.l, DOT.o);
		break;
	    }
	}
	sel_extend(FALSE, TRUE);
    }
    DOT = save;
    update(TRUE);
}
Beispiel #2
0
// Get current mouse position.  If the mouse is above/below the current
// window then scroll the window down/up proportionally to the time the LMB
// is held down.  This function is called from autoscroll_thread() when the
// mouse is captured and a wipe selection is active.
static void
AutoScroll(WINDOW *wp)
{
#define DVSR    10
#define INCR    6
#define TRIGGER (DVSR + INCR)

    POINT current;
    int Scroll = 0;
    static int ScrollCount = 0, Throttle = INCR;

    GetMousePos(&current);

    if (wp == 0)
	return;

    // Determine if we are above or below the window,
    // and if so, how far...
    if (current.y < wp->w_toprow) {
	// Above the window
	// Scroll = wp->w_toprow - current.y;
	Scroll = 1;
    }
    if (current.y > mode_row(wp)) {
	// Below
	// Scroll = current.y - mode_row(wp);
	// Scroll *= -1;
	Scroll = -1;
    }
    if (Scroll) {
	int row;
	if (Scroll > 0) {
	    row = wp->w_toprow;
	} else {
	    row = mode_row(wp) - 1;
	}

	// Scroll the pre-determined amount, ensuring at least one line of
	// window movement per timer tick.  Note also that ScrollScale is
	// signed, so it will be negative if we want to scroll down.
	mvupwind(TRUE, Scroll * max(ScrollCount, TRIGGER) / (Throttle + DVSR));

	// Set the cursor. Column doesn't really matter, it will
	// get updated as soon as we get back into the window...
	setcursor(row, 0) && sel_extend(TRUE, TRUE);
	(void) update(TRUE);
	ScrollCount++;
	if (ScrollCount > TRIGGER && Throttle > 0 && ScrollCount % INCR == 0)
	    Throttle--;
    } else {
	// Reset counters
	Throttle = INCR;
	ScrollCount = 0;
    }
#undef DVSR
#undef INCR
#undef TRIGGER
}
Beispiel #3
0
/*
 * FUNCTION
 *   mousemove(int    *sel_pending,
 *             POINT  *first,
 *             POINT  *current,
 *             MARK   *lmbdn_mark,
 *             int    rect_rgn)
 *
 *   sel_pending - Boolean, T -> client has recorded a left mouse button (LMB)
 *                 click, and so, a selection is pending.
 *
 *   first       - editor row/col coordinates where LMB was initially recorded.
 *
 *   latest      - during the mouse move, assuming the LMB is still down,
 *                 "latest" tracks the cursor position wrt window resizing
 *                 operations (via a modeline drag).
 *
 *   current     - current cursor row/col coordiantes.
 *
 *   lmbdn_mark  - editor MARK when "LMB down" was initially recorded.
 *
 *   rect_rgn    - Boolean, T -> user wants rectangular region selection.
 *
 * DESCRIPTION
 *   Using several state variables, this function handles all the semantics
 *   of a left mouse button "MOVE" event.  The semantics are as follows:
 *
 *   1) This function will not be called unless the LMB is down and the
 *      cursor is not being used to drage the mode line (enforced by caller).
 *   2) a LMB move within the current editor window selects a region of text.
 *      Later, when the user releases the LMB, that text is yanked to the
 *      unnamed register (the yank code is not handled in this function).
 *
 * RETURNS
 *   None
 */
static void
mousemove(int *sel_pending,
	  COORD * first,
	  COORD * current,
	  MARK *lmbdn_mark,
	  int rect_rgn)
{
    int dummy;

    if (WaitForSingleObject(hAsMutex, AS_TMOUT) == WAIT_OBJECT_0) {
	if (*sel_pending) {
	    /*
	     * Selection pending.  If the mouse has moved at least one char,
	     * start a selection.
	     */

	    if (MouseClickSetPos(current, &dummy)) {
		/* ignore mouse jitter */

		if (current->X != first->X || current->Y != first->Y) {
		    *sel_pending = FALSE;
		    DOT = *lmbdn_mark;
		    (void) sel_begin();
		    (void) update(TRUE);
		} else {
		    (void) ReleaseMutex(hAsMutex);
		    return;
		}
	    }
	}
	if (mouse_wp != row2window(current->Y)) {
	    /*
	     * mouse moved into a different editor window or row2window()
	     * returned a NULL ptr.
	     */

	    (void) ReleaseMutex(hAsMutex);
	    return;
	}
	if (!setcursor(current->Y, current->X)) {
	    (void) ReleaseMutex(hAsMutex);
	    return;
	}
	if (rect_rgn)
	    (void) sel_setshape(rgn_RECTANGLE);
	if (sel_extend(TRUE, TRUE))
	    (void) update(TRUE);
	(void) ReleaseMutex(hAsMutex);
    }
    /*
     * Else either the worker thread abandonded the mutex (not possible as
     * currently coded) or timed out.  If the latter, something is
     * hung--don't do anything.
     */
}
Beispiel #4
0
void
on_triple_click(void)
{
    MARK save;

    save = DOT;
    TRACE(("MOUSE triple-click DOT %d.%d\n", line_no(curbp, DOT.l), DOT.o));
    sel_release();
    gotobol(FALSE, 1);
    sel_begin();
    MK = DOT;
    gotoeol(FALSE, 1);
    sel_extend(FALSE, TRUE);
    DOT = save;
    update(TRUE);
}
Beispiel #5
0
/* select all text in curbp and yank to unnamed register */
int
sel_all(int f GCC_UNUSED, int n GCC_UNUSED)
{
    int rc;
    MARK savedot;

    savedot = DOT;
    gotobob(0, 0);
    sel_begin();
    gotoeob(0, 0);
    gotoeol(0, 0);
    (void) sel_setshape(rgn_EXACT);
    rc = sel_extend(TRUE, TRUE);
    DOT = savedot;
    if (rc)
	sel_yank(0);
    return (rc);
}
Beispiel #6
0
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;
}