// 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(¤t); 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 }
/* * Shrink a window by dragging the modeline */ static int adjust_window(WINDOW *wp, COORD * current, COORD * latest) { if (latest->Y == mode_row(wp)) { if (current->Y != latest->Y) { WINDOW *save_wp = curwp; set_curwp(wp); shrinkwind(FALSE, latest->Y - current->Y); set_curwp(save_wp); update(TRUE); } *latest = *current; return TRUE; } return FALSE; }
static int MouseClickSetPos(COORD * result, int *onmode) { WINDOW *wp; TRACE(("GETC:setcursor(%d, %d)\n", result->Y, result->X)); /* * If we're getting a button-down in a window, allow it to begin a * selection. A button-down on its modeline will allow resizing the * window. */ *onmode = FALSE; if ((wp = row2window(result->Y)) != 0) { if (result->Y == mode_row(wp)) { *onmode = TRUE; return TRUE; } return setcursor(result->Y, result->X); } return FALSE; }
static int xterm_button(int c) { WINDOW *wp; int event; int button; int x; int y; int status; #if OPT_XTERM >= 3 int save_row = ttrow; int save_col = ttcol; int firstrow, lastrow; int startx, endx, mousex; int starty, endy, mousey; MARK save_dot; char temp[NSTRING]; static const char *fmt = "\033[%d;%d;%d;%d;%dT"; #endif /* OPT_XTERM >= 3 */ if (insertmode) return ABORT; if ((status = (global_g_val(GMDXTERM_MOUSE))) != 0) { beginDisplay; switch(c) { case 'M': /* button-event */ event = keystroke(); x = XtermPos() + x_origin; y = XtermPos() + y_origin; button = (event & 3) + 1; TRACE(("M-button event:%d x:%d y:%d\n", event, x, y)) if (button > 3) { endofDisplay; return TRUE; /* button up */ } wp = row2window(y-1); #if OPT_XTERM >= 3 /* Tell the xterm how to highlight the selection. * It won't do anything else until we do this. */ if (wp != 0) { firstrow = wp->w_toprow + 1; lastrow = mode_row(wp) + 1; } else { /* from message-line */ firstrow = term.t_nrow ; lastrow = term.t_nrow + 1; } if (y >= lastrow) /* don't select modeline */ y = lastrow - 1; (void)lsprintf(temp, fmt, 1, x, y, firstrow, lastrow); putpad(temp); TTflush(); #endif /* OPT_XTERM >= 3 */ /* Set the dot-location if button 1 was pressed in a * window. */ if (wp != 0 && button == 1 && !reading_msg_line && setcursor(y-1, x-1)) { /*mlerase();*/ (void)update(TRUE); status = TRUE; } else if (button <= 3) { #if OPT_XTERM >= 3 /* abort the selection */ (void)lsprintf(temp, fmt, 0, x, y, firstrow, lastrow); putpad(temp); TTflush(); #endif /* OPT_XTERM >= 3 */ status = ABORT; } else { status = FALSE; } break; #if OPT_XTERM >= 3 case 't': /* reports valid text-location */ x = XtermPos(); y = XtermPos(); TRACE(("t: x:%d y:%d\n", x, y)) setwmark(y-1, x-1); yankregion(); movecursor(save_row, save_col); /*mlerase();*/ (void)update(TRUE); break; case 'T': /* reports invalid text-location */ /* * The starting-location returned is not the location * at which the mouse was pressed. Instead, it is the * top-most location of the selection. In turn, the * ending-location is the bottom-most location of the * selection. The mouse-up location is not necessarily * a pointer to valid text. * * This case handles multi-clicking events as well as * selections whose start or end location was not * pointing to text. */ save_dot = DOT; startx = XtermPos(); /* starting-location */ starty = XtermPos(); endx = XtermPos(); /* ending-location */ endy = XtermPos(); mousex = XtermPos(); /* location at mouse-up */ mousey = XtermPos(); TRACE(("T: start(%d,%d) end(%d,%d) mouse(%d,%d)\n", starty, startx, endy, endx, mousey, mousex)) setcursor(starty - 1, startx - 1); setwmark (endy - 1, endx - 1); if (MK.o != 0 && !is_at_end_of_line(MK)) MK.o += 1; yankregion(); DOT = save_dot; movecursor(save_row, save_col); /*mlerase();*/ (void)update(TRUE); break; #endif /* OPT_XTERM >= 3 */ default: status = FALSE; } endofDisplay; }
/* * On button press, we get an explicit number (1,2,3), and on release we don't * really know which button, but assume it is the last-pressed button. */ int on_mouse_click(int button, int y, int x) { static int first_x, first_y, pending; WINDOW *this_wp, *that_wp; int status; if (button > 0) { if (valid_window(this_wp = row2window(y)) && (y != mode_row(this_wp))) { /* * If we get a click on the "<" marking the left side * of a shifted window, force the screen right. This * makes it more consistent if there's a tab. */ if (w_val(this_wp, WVAL_SIDEWAYS) && x == 0) { mvleftwind(FALSE, 1); } if (!doingsweep) { if (button == BTN_EXTEND) { first_x = offs2col(this_wp, this_wp->w_dot.l, this_wp->w_dot.o); first_y = line_no(this_wp->w_bufp, this_wp->w_dot.l) - line_no(this_wp->w_bufp, this_wp->w_line.l); } else { first_x = x; first_y = y; } } status = setcursor(y, x); /* * Check for button1-down while we're in multimotion * sweep, so we can suppress highlighting extension. */ if (button != BTN_EXTEND && status == TRUE && doingsweep) { status = SORTOFTRUE; if (button == BTN_BEGIN) { first_x = x; first_y = y; } } } else { /* pressed button on modeline */ status = SORTOFTRUE; first_x = x; first_y = y; } pending = button; } else if (pending) { button = pending; pending = FALSE; this_wp = row2window(y); that_wp = row2window(first_y); if (this_wp == 0 || that_wp == 0 || reading_msg_line) { TRACE(("MOUSE cannot move msg-line\n")); status = FALSE; } else if (insertmode && (this_wp != curwp || that_wp != curwp)) { TRACE(("MOUSE cannot move from window while inserting\n")); kbd_alarm(); status = ABORT; } else if (first_y == mode_row(that_wp)) { /* drag modeline? */ if (first_y == y) { sel_release(); status = SEL_RELEASE; } else { WINDOW *save_wp = curwp; TRACE(("MOUSE dragging modeline\n")); set_curwp(that_wp); status = shrinkwind(FALSE, first_y - y); set_curwp(save_wp); } } else if (y != first_y || x != first_x) { /* drag selection */ if (button == BTN_PASTE) { (void) setcursor(y, x); status = paste_selection(); } else if (doingsweep) { switch (button) { case BTN_BEGIN: (void) release_selection(TRUE); status = setcursor(first_y, first_x); if (status == TRUE) { MK = DOT; status = SEL_BEGIN; TRACE(("MOUSE setting SEL_BEGIN MK %d.%d\n", line_no(curbp, MK.l), MK.o)); } break; default: (void) setcursor(y, x); status = SEL_EXTEND; TRACE(("MOUSE setting SEL_EXTEND DOT %d.%d MK %d.%d\n", line_no(curbp, MK.l), MK.o, line_no(curbp, DOT.l), DOT.o)); break; } } else { TRACE(("MOUSE begin multimotion on button%d-up\n", button)); if (button == BTN_EXTEND) { (void) setcursor(y, x); y = first_y; x = first_x; } do_sweep(SORTOFTRUE); (void) sel_begin(); (void) sel_setshape(rgn_EXACT); (void) setcursor(y, x); status = multimotion(TRUE, 1); TRACE(("MOUSE end multimotion after button%d-up\n", button)); if (status == SEL_PASTE) status = paste_selection(); } } else { /* position the cursor */ TRACE(("MOUSE button %d position cursor\n", button)); (void) setcursor(y, x); switch (button) { case BTN_BEGIN: status = SEL_FINISH; break; case BTN_PASTE: status = paste_selection(); break; default: status = release_selection(TRUE); break; } } } else { TRACE(("MOUSE ignored (illegal state)\n")); status = FALSE; } if (status == TRUE || status >= SORTOFTRUE) (void) update(TRUE); TRACE(("MOUSE status:%d\n", status)); return status; }