From 0be99a51dce3de01e85e95591571e6582e751126 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Thu, 28 Jun 2007 16:26:15 +0000 Subject: [PATCH] in do_mouseinput(), add mouse wheel support, per Helmut Jarausch's suggestion, and add various mouse support-related simplifications git-svn-id: svn://svn.savannah.gnu.org/nano/branches/nano_2_0_branch/nano@4114 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 18 ++++ src/browser.c | 52 ++++++------ src/nano.c | 69 +++++++--------- src/prompt.c | 56 ++++++------- src/proto.h | 6 +- src/winio.c | 224 +++++++++++++++++++++++++++++++------------------- 6 files changed, 240 insertions(+), 185 deletions(-) diff --git a/ChangeLog b/ChangeLog index 464f22f4..600c936f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,25 @@ CVS code - +- General: + - Simplify processing of mouse events. Instead of calling + wenclose() to get the window a mouse event took place in and + manually adjusting the returned coordinates to be relative to + that window the mouse event took place in, call + wmouse_trafo(), which does both. Changes to do_browser(), + do_mouse(), do_statusbar_mouse(), do_yesno_prompt(), and + do_mouseinput(). (DLR) - winio.c: get_key_buffer() - Fix inaccurate comments. (DLR) + do_mouseinput() + - Add mouse wheel support. Now, if mouse support is enabled, + and nano is using a version of ncurses compiled with the + --enable-ext-mouse option, rolling the mouse wheel up or down + will move the cursor three lines up or down. Note that + ncurses built without --enable-ext-mouse needs to handle both + clicks and releases of the first mouse button, but ncurses + built with --enable-ext-mouse only needs to handle releases, + so keep dealing with both events. (DLR, suggested by Helmut + Jarausch) GNU nano 2.0.6 - 2007.04.26 - text.c: diff --git a/src/browser.c b/src/browser.c index 44d94825..b04c3662 100644 --- a/src/browser.c +++ b/src/browser.c @@ -131,38 +131,32 @@ char *do_browser(char *path, DIR *dir) { int mouse_x, mouse_y; - if (!get_mouseinput(&mouse_x, &mouse_y, TRUE)) { - /* We can click in the edit window to select a - * filename. */ - if (wenclose(edit, mouse_y, mouse_x)) { - /* Subtract out the size of topwin. */ - mouse_y -= 2 - no_more_space(); - - /* longest is the width of each column. - * There are two spaces between each - * column. */ - selected = (fileline / editwinrows) * + /* We can click on the edit window to select a + * filename. */ + if (get_mouseinput(&mouse_x, &mouse_y, TRUE) == 0 && + wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) { + /* longest is the width of each column. There + * are two spaces between each column. */ + selected = (fileline / editwinrows) * (editwinrows * width) + (mouse_y * width) + (mouse_x / (longest + 2)); - /* If they clicked beyond the end of a row, - * select the filename at the end of that - * row. */ - if (mouse_x > width * (longest + 2)) - selected--; - - /* If we're off the screen, select the last - * filename. */ - if (selected > filelist_len - 1) - selected = filelist_len - 1; - - /* If we selected the same filename as last - * time, put back the Enter key so that it's - * read in. */ - if (old_selected == selected) - unget_kbinput(NANO_ENTER_KEY, FALSE, - FALSE); - } + /* If they clicked beyond the end of a row, + * select the filename at the end of that + * row. */ + if (mouse_x > width * (longest + 2)) + selected--; + + /* If we're off the screen, select the last + * filename. */ + if (selected > filelist_len - 1) + selected = filelist_len - 1; + + /* If we selected the same filename as last + * time, put back the Enter key so that it's + * read in. */ + if (old_selected == selected) + unget_kbinput(NANO_ENTER_KEY, FALSE, FALSE); } } break; diff --git a/src/nano.c b/src/nano.c index 66f6f4a3..59d498c1 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1332,7 +1332,7 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool /* If we got a mouse click and it was on a shortcut, read in the * shortcut character. */ if (*func_key && input == KEY_MOUSE) { - if (do_mouse()) + if (do_mouse() == 1) input = get_kbinput(edit, meta_key, func_key); else { *meta_key = FALSE; @@ -1490,50 +1490,43 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool #ifndef DISABLE_MOUSE /* Handle a mouse click on the edit window or the shortcut list. */ -bool do_mouse(void) +int do_mouse(void) { int mouse_x, mouse_y; - bool retval = get_mouseinput(&mouse_x, &mouse_y, TRUE); - - if (!retval) { - /* We can click in the edit window to move the cursor. */ - if (wenclose(edit, mouse_y, mouse_x)) { - bool sameline; - /* Did they click on the line with the cursor? If they - * clicked on the cursor, we set the mark. */ - const filestruct *current_save = openfile->current; - size_t current_x_save = openfile->current_x; - size_t pww_save = openfile->placewewant; - - /* Subtract out the size of topwin. */ - mouse_y -= 2 - no_more_space(); - - sameline = (mouse_y == openfile->current_y); - - /* Move to where the click occurred. */ - for (; openfile->current_y < mouse_y && - openfile->current != openfile->filebot; - openfile->current_y++) - openfile->current = openfile->current->next; - for (; openfile->current_y > mouse_y && - openfile->current != openfile->fileage; - openfile->current_y--) - openfile->current = openfile->current->prev; - - openfile->current_x = actual_x(openfile->current->data, + int retval = get_mouseinput(&mouse_x, &mouse_y, TRUE); + + /* We can click on the edit window to move the cursor. */ + if (retval == 0 && wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) { + bool sameline; + /* Did they click on the line with the cursor? If they + * clicked on the cursor, we set the mark. */ + const filestruct *current_save = openfile->current; + size_t current_x_save = openfile->current_x; + size_t pww_save = openfile->placewewant; + + sameline = (mouse_y == openfile->current_y); + + /* Move to where the click occurred. */ + for (; openfile->current_y < mouse_y && openfile->current != + openfile->filebot; openfile->current_y++) + openfile->current = openfile->current->next; + for (; openfile->current_y > mouse_y && openfile->current != + openfile->fileage; openfile->current_y--) + openfile->current = openfile->current->prev; + + openfile->current_x = actual_x(openfile->current->data, get_page_start(xplustabs()) + mouse_x); - openfile->placewewant = xplustabs(); + openfile->placewewant = xplustabs(); #ifndef NANO_TINY - /* Clicking where the cursor is toggles the mark, as does - * clicking beyond the line length with the cursor at the - * end of the line. */ - if (sameline && openfile->current_x == current_x_save) - do_mark(); + /* Clicking where the cursor is toggles the mark, as does + * clicking beyond the line length with the cursor at the end of + * the line. */ + if (sameline && openfile->current_x == current_x_save) + do_mark(); #endif - edit_redraw(current_save, pww_save); - } + edit_redraw(current_save, pww_save); } return retval; diff --git a/src/prompt.c b/src/prompt.c index af1c7dd7..a213efe2 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -76,7 +76,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t, /* If we got a mouse click and it was on a shortcut, read in the * shortcut character. */ if (*func_key && input == KEY_MOUSE) { - if (do_statusbar_mouse()) + if (do_statusbar_mouse() == 1) input = get_kbinput(bottomwin, meta_key, func_key); else { *meta_key = FALSE; @@ -273,37 +273,32 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t, #ifndef DISABLE_MOUSE /* Handle a mouse click on the statusbar prompt or the shortcut list. */ -bool do_statusbar_mouse(void) +int do_statusbar_mouse(void) { int mouse_x, mouse_y; - bool retval = get_mouseinput(&mouse_x, &mouse_y, TRUE); + int retval = get_mouseinput(&mouse_x, &mouse_y, TRUE); - if (!retval) { - /* We can click in the statusbar window text to move the - * cursor. */ - if (wenclose(bottomwin, mouse_y, mouse_x)) { - size_t start_col; + /* We can click on the statusbar window text to move the cursor. */ + if (retval == 0 && wmouse_trafo(bottomwin, &mouse_y, &mouse_x, + FALSE)) { + size_t start_col; - assert(prompt != NULL); + assert(prompt != NULL); - start_col = strlenpt(prompt) + 1; + start_col = strlenpt(prompt) + 1; - /* Subtract out the sizes of topwin and edit. */ - mouse_y -= (2 - no_more_space()) + editwinrows; + /* Move to where the click occurred. */ + if (mouse_x > start_col && mouse_y == 0) { + size_t pww_save = statusbar_pww; - /* Move to where the click occurred. */ - if (mouse_x > start_col && mouse_y == 0) { - size_t pww_save = statusbar_pww; - - statusbar_x = actual_x(answer, + statusbar_x = actual_x(answer, get_statusbar_page_start(start_col, start_col + - statusbar_xplustabs()) + mouse_x - start_col - - 1); - statusbar_pww = statusbar_xplustabs(); + statusbar_xplustabs()) + mouse_x - + start_col - 1); + statusbar_pww = statusbar_xplustabs(); - if (need_statusbar_horizontal_update(pww_save)) - update_statusbar_line(answer, statusbar_x); - } + if (need_statusbar_horizontal_update(pww_save)) + update_statusbar_line(answer, statusbar_x); } } @@ -1337,18 +1332,17 @@ int do_yesno_prompt(bool all, const char *msg) break; #ifndef DISABLE_MOUSE case KEY_MOUSE: - get_mouseinput(&mouse_x, &mouse_y, FALSE); - - if (wenclose(bottomwin, mouse_y, mouse_x) && - !ISSET(NO_HELP) && mouse_x < (width * 2) && - mouse_y - (2 - no_more_space()) - - editwinrows - 1 >= 0) { + /* We can click on the shortcut list to select an + * answer. */ + if (get_mouseinput(&mouse_x, &mouse_y, FALSE) == 0 && + wmouse_trafo(bottomwin, &mouse_y, &mouse_x, + FALSE) && !ISSET(NO_HELP) && mouse_x < + (width * 2) && mouse_y > 0) { int x = mouse_x / width; /* Calculate the x-coordinate relative to the * two columns of the Yes/No/All shortcuts in * bottomwin. */ - int y = mouse_y - (2 - no_more_space()) - - editwinrows - 1; + int y = mouse_y - 1; /* Calculate the y-coordinate relative to the * beginning of the Yes/No/All shortcuts in * bottomwin, i.e. with the sizes of topwin, diff --git a/src/proto.h b/src/proto.h index 0250b5a0..2bd0bfde 100644 --- a/src/proto.h +++ b/src/proto.h @@ -485,7 +485,7 @@ void terminal_init(void); int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool *ran_func, bool *finished, bool allow_funcs); #ifndef DISABLE_MOUSE -bool do_mouse(void); +int do_mouse(void); #endif void do_output(char *output, size_t output_len, bool allow_cntrls); @@ -494,7 +494,7 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t, bool *ran_func, bool *finished, bool allow_funcs, void (*refresh_func)(void)); #ifndef DISABLE_MOUSE -bool do_statusbar_mouse(void); +int do_statusbar_mouse(void); #endif void do_statusbar_output(char *output, size_t output_len, bool *got_enter, bool allow_cntrls); @@ -749,7 +749,7 @@ void unparse_kbinput(char *output, size_t output_len); int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len); int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len); #ifndef DISABLE_MOUSE -bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts); +int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts); #endif const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool *meta_key, bool *func_key); diff --git a/src/winio.c b/src/winio.c index b3082b84..9569f060 100644 --- a/src/winio.c +++ b/src/winio.c @@ -1621,15 +1621,19 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len) } #ifndef DISABLE_MOUSE -/* Check for a mouse event, and if one's taken place, save the - * coordinates where it took place in mouse_x and mouse_y. After that, - * assuming allow_shortcuts is FALSE, if the shortcut list on the - * bottom two lines of the screen is visible and the mouse event took - * place on it, figure out which shortcut was clicked and put back the - * equivalent keystroke(s). Return FALSE if no keystrokes were - * put back, or TRUE if at least one was. Assume that KEY_MOUSE has +/* Handle any mouse events that may have occurred. We currently handle + * releases/clicks of the first mouse button. If allow_shortcuts is + * TRUE, releasing/clicking on a visible shortcut will put back the + * keystroke associated with that shortcut. If NCURSES_MOUSE_VERSION is + * at least 2, we also currently handle presses of the fourth mouse + * button (upward rolls of the mouse wheel) by putting back the + * keystrokes to move up, and presses of the fifth mouse button + * (downward rolls of the mouse wheel) by putting back the keystrokes to + * move down. Return -1 on error, 0 if the mouse event needs to be + * handled, 1 if it's been handled by putting back keystrokes that need + * to be handled. or 2 if it's been ignored. Assume that KEY_MOUSE has * already been read in. */ -bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts) +int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts) { MEVENT mevent; @@ -1638,90 +1642,142 @@ bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts) /* First, get the actual mouse event. */ if (getmouse(&mevent) == ERR) - return FALSE; - - /* If it's not a release or click of the first mouse button, get - * out. */ - if (!(mevent.bstate & (BUTTON1_RELEASED | BUTTON1_CLICKED))) - return FALSE; + return -1; /* Save the screen coordinates where the mouse event took place. */ *mouse_x = mevent.x; *mouse_y = mevent.y; - /* If we're allowing shortcuts, the current shortcut list is being - * displayed on the last two lines of the screen, and the mouse - * event took place inside it, we need to figure out which shortcut - * was clicked and put back the equivalent keystroke(s) for it. */ - if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin, - *mouse_y, *mouse_x)) { - int i, j; - size_t currslen; - /* The number of shortcuts in the current shortcut list. */ - const shortcut *s = currshortcut; - /* The actual shortcut we clicked on, starting at the first - * one in the current shortcut list. */ - - /* Get the shortcut lists' length. */ - if (currshortcut == main_list) - currslen = MAIN_VISIBLE; - else { - currslen = length_of_list(currshortcut); - - /* We don't show any more shortcuts than the main list - * does. */ - if (currslen > MAIN_VISIBLE) + /* Handle clicks/releases of the first mouse button. */ + if (mevent.bstate & (BUTTON1_RELEASED | BUTTON1_CLICKED)) { + /* If we're allowing shortcuts, the current shortcut list is + * being displayed on the last two lines of the screen, and the + * first mouse button was released on/clicked inside it, we need + * to figure out which shortcut was released on/clicked and put + * back the equivalent keystroke(s) for it. */ + if (allow_shortcuts && !ISSET(NO_HELP) && + wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE)) { + int i; + /* The width of all the shortcuts, except for the last + * two, in the shortcut list in bottomwin. */ + int j; + /* The y-coordinate relative to the beginning of the + * shortcut list in bottomwin. */ + size_t currslen; + /* The number of shortcuts in the current shortcut + * list. */ + const shortcut *s; + /* The actual shortcut we released on, starting at the + * first one in the current shortcut list. */ + + /* Ignore releases/clicks of the first mouse button on the + * statusbar. */ + if (*mouse_y == 0) + return 2; + + /* Calculate the y-coordinate relative to the beginning of + * the shortcut list in bottomwin. */ + j = *mouse_y - 1; + + /* Get the shortcut lists' length. */ + if (currshortcut == main_list) currslen = MAIN_VISIBLE; - } + else { + currslen = length_of_list(currshortcut); - /* Calculate the width of all of the shortcuts in the list - * except for the last two, which are longer by (COLS % i) - * columns so as to not waste space. */ - if (currslen < 2) - i = COLS / (MAIN_VISIBLE / 2); - else - i = COLS / ((currslen / 2) + (currslen % 2)); - - /* Calculate the y-coordinate relative to the beginning of - * the shortcut list in bottomwin, i.e. with the sizes of - * topwin, edit, and the first line of bottomwin subtracted - * out, and set j to it. */ - j = *mouse_y - (2 - no_more_space()) - editwinrows - 1; - - /* If we're on the statusbar, don't do anything. */ - if (j < 0) - return FALSE; - - /* Calculate the x-coordinate relative to the beginning of the - * shortcut list in bottomwin, and add it to j. j should now be - * the index in the shortcut list of the shortcut we clicked. */ - j = (*mouse_x / i) * 2 + j; - - /* Adjust j if we clicked in the last two shortcuts. */ - if ((j >= currslen) && (*mouse_x % i < COLS % i)) - j -= 2; - - /* If we're beyond the last shortcut, don't do anything. */ - if (j >= currslen) - return FALSE; - - /* Go through the shortcut list to determine which shortcut was - * clicked. */ - for (; j > 0; j--) - s = s->next; - - /* And put back the equivalent key. Assume that each shortcut - * has, at the very least, an equivalent control key, an - * equivalent primary meta key sequence, or both. */ - if (s->ctrlval != NANO_NO_KEY) { - unget_kbinput(s->ctrlval, FALSE, FALSE); - return TRUE; - } else if (s->metaval != NANO_NO_KEY) { - unget_kbinput(s->metaval, TRUE, FALSE); - return TRUE; - } + /* We don't show any more shortcuts than the main list + * does. */ + if (currslen > MAIN_VISIBLE) + currslen = MAIN_VISIBLE; + } + + /* Calculate the width of all of the shortcuts in the list + * except for the last two, which are longer by (COLS % i) + * columns so as to not waste space. */ + if (currslen < 2) + i = COLS / (MAIN_VISIBLE / 2); + else + i = COLS / ((currslen / 2) + (currslen % 2)); + + /* Calculate the x-coordinate relative to the beginning of + * the shortcut list in bottomwin, and add it to j. j + * should now be the index in the shortcut list of the + * shortcut we released/clicked on. */ + j = (*mouse_x / i) * 2 + j; + + /* Adjust j if we released on the last two shortcuts. */ + if ((j >= currslen) && (*mouse_x % i < COLS % i)) + j -= 2; + + /* Ignore releases/clicks of the first mouse button beyond + * the last shortcut. */ + if (j >= currslen) + return 2; + + /* Go through the shortcut list to determine which shortcut + * we released/clicked on. */ + s = currshortcut; + + for (; j > 0; j--) + s = s->next; + + /* And put back the equivalent key. Assume that each + * shortcut has, at the very least, an equivalent control + * key, an equivalent primary meta key sequence, or both. */ + if (s->ctrlval != NANO_NO_KEY) { + unget_kbinput(s->ctrlval, FALSE, FALSE); + return 1; + } else if (s->metaval != NANO_NO_KEY) { + unget_kbinput(s->metaval, TRUE, FALSE); + return 1; + } + } else + /* Handle releases/clicks of the first mouse button that + * aren't on the current shortcut list elsewhere. */ + return 0; } - return FALSE; +#if NCURSES_MOUSE_VERSION >= 2 + /* Handle presses of the fourth mouse button (upward rolls of the + * mouse wheel) and presses of the fifth mouse button (downward + * rolls of the mouse wheel) . */ + else if (mevent.bstate & (BUTTON4_PRESSED | BUTTON5_PRESSED)) { + bool in_edit = wmouse_trafo(edit, mouse_y, mouse_x, FALSE); + bool in_bottomwin = wmouse_trafo(bottomwin, mouse_y, mouse_x, + FALSE); + + if (in_edit || in_bottomwin) { + int i; + /* The y-coordinate relative to the beginning of the + * shortcut list in bottomwin. */ + + /* Ignore presses of the fourth mouse button and presses of + * the fifth mouse button below the statusbar. */ + if (in_bottomwin && *mouse_y > 0) + return 2; + + /* Calculate the y-coordinate relative to the beginning of + * the shortcut list in bottomwin. */ + i = *mouse_y - 1; + + /* One upward roll of the mouse wheel is equivalent to + * moving up three lines, and one downward roll of the mouse + * wheel is equivalent to moving down three lines. */ + for (i = 0; i < 3; i++) + unget_kbinput((mevent.bstate & BUTTON4_PRESSED) ? + NANO_PREVLINE_KEY : NANO_NEXTLINE_KEY, FALSE, + FALSE); + + return 1; + } else + /* Ignore presses of the fourth mouse button and presses of + * the fifth mouse buttons that aren't on the edit window or + * the statusbar. */ + return 2; + } +#endif + else + /* Ignore all other mouse events. */ + return 2; } #endif /* !DISABLE_MOUSE */ -- 2.39.5