diff --git a/ChangeLog b/ChangeLog
index dc4c9a9aa7b18bcf2cf1634a16b4292b499618a2..02667d0e2e94d283a1f70bb67bcbaf95e40c39e8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2007-05-15  David Lawrence Ramsey  <pooka109@gmail.com>
+
+	* winio.c (do_mouseinput): Add mouse wheel support, per Helmut
+	Jarausch's suggestion.  Now, if nano is built with mouse support
+	and 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.
+
 2007-04-23  David Lawrence Ramsey  <pooka109@gmail.com>
 
 	* TODO: Add entries for fixing limitations with pasting text and
diff --git a/src/winio.c b/src/winio.c
index 5c0251c4b2b68a80cfe9d1bc69dab3e93c17ae97..95a4c9049e686fa75f6dde2f3250a015e16ad6ef 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -1624,14 +1624,17 @@ 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
- * already been read in. */
+/* Handle any mouse events that may have occurred.  We currently handle
+ * releases or clicks of the first mouse button.  If allow_shortcuts is
+ * TRUE, releasing or 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 FALSE if we don't put back any keystrokes in the
+ * course of handling mouse events, or TRUE if we do.  Assume that
+ * KEY_MOUSE has already been read in. */
 bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
 {
     MEVENT mevent;
@@ -1643,88 +1646,117 @@ bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
     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;
-
-    /* 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 releases or clicks of the first mouse button. */
+    if (mevent.bstate & (BUTTON1_RELEASED | BUTTON1_CLICKED)) {
+	/* 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;
-	}
-
-	/* 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;
+	    else {
+		currslen = length_of_list(currshortcut);
 
-	/* Adjust j if we clicked in the last two shortcuts. */
-	if ((j >= currslen) && (*mouse_x % i < COLS % i))
-	    j -= 2;
+		/* We don't show any more shortcuts than the main list
+		 * does. */
+		if (currslen > MAIN_VISIBLE)
+		    currslen = MAIN_VISIBLE;
+	    }
 
-	/* If we're beyond the last shortcut, don't do anything. */
-	if (j >= currslen)
+	    /* 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;
+	    }
+	} else
 	    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;
-	}
     }
-    return FALSE;
+#if NCURSES_MOUSE_VERSION >= 2
+    /* Handle presses of the fourth mouse button (upward rolls of the
+     * mouse wheel). */
+    else if (mevent.bstate & BUTTON4_PRESSED) {
+	int i = 0;
+
+	/* One upward roll of the mouse wheel is equivalent to moving up
+	 * three lines. */
+	for (; i < 3; i++)
+	    unget_kbinput(NANO_PREVLINE_KEY, FALSE, FALSE);
+
+	return TRUE;
+    /* Handle presses of the fifth mouse button (downward rolls of the
+     * mouse wheel). */
+    } else if (mevent.bstate & BUTTON5_PRESSED) {
+	int i = 0;
+
+	/* One downward roll of the mouse wheel is equivalent to moving
+	 * down three lines. */
+	for (; i < 3; i++)
+	    unget_kbinput(NANO_NEXTLINE_KEY, FALSE, FALSE);
+
+	return TRUE;
+    }
+#endif
+    else
+	return FALSE;
 }
 #endif /* !DISABLE_MOUSE */