diff --git a/ChangeLog b/ChangeLog
index 582b2ff3815b86395cb97a2b9457acdef29821b1..7c3afa0a00a9e239436b225091d8d6cd3767d9a1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -32,11 +32,15 @@ CVS Code -
 - nano.c:
   do_char()
 	- Remove unneeded check_statblank() (David Benbennick).
-  do_preserve_msg():
-	- Unsplit error message into a single fprintf call (Jordi).
   do_int_spell_fix(), do_int_speller()
 	- Fix crashes with mark position, current_x position, 
 	  and edit_update args (David Benbennick).
+  do_mouse()
+	- Fix the mouse code to work with lines longer than COLS and
+	  with the proper positioning, including special characters
+	  (David Benbennick).
+  do_preserve_msg():
+	- Unsplit error message into a single fprintf call (Jordi).
   main()
 	- Call load_file with arg 0 for insert, as we aren't really
 	  doing an insert, allows new_file() to run if we open a 
diff --git a/nano.c b/nano.c
index b4a05526672b8e63e4a29e711e7cce7d157ba639..b91b79fb12ff75c0608f48df7301aaf5b7d2a86c 100644
--- a/nano.c
+++ b/nano.c
@@ -910,49 +910,40 @@ void do_mouse(void)
 	return;
 
     /* If mouse not in edit or bottom window, return */
-    if (wenclose(edit, mevent.y, mevent.x)) {
-
-	/* Don't let people screw with the marker when they're in a
-	 * subfunction. */
-	if (currshortcut != main_list)
-	    return;
+    if (wenclose(edit, mevent.y, mevent.x) && currshortcut == main_list) {
+	int sameline;
+	    /* Did they click on the line with the cursor?  If they
+	       clicked on the cursor, we set the mark. */
+	size_t xcur;
+	    /* The character they clicked on. */
 
 	/* Subtract out size of topwin.  Perhaps we need a constant
 	 * somewhere? */
 	mevent.y -= 2;
 
-	/* Selecting where the cursor is sets the mark.  Selecting
-	 * beyond the line length with the cursor at the end of the line
-	 * sets the mark as well. */
-	if ((mevent.y == current_y) &&
-	    ((mevent.x == current_x) || (current_x == strlen(current->data)
-					 && (mevent.x >
-					     strlen(current->data))))) {
+	sameline = mevent.y == current_y;
+
+	/* Move to where the click occurred. */
+	for(; current_y < mevent.y && current->next != NULL; current_y++)
+	    current = current->next;
+	for(; current_y > mevent.y && current->prev != NULL; current_y--)
+	    current = current->prev;
+
+	xcur = actual_x(current, get_page_start(xplustabs()) + mevent.x);
+
+	/* Selecting where the cursor is toggles the mark.  As does
+	   selecting beyond the line length with the cursor at the end of
+	   the line. */
+	if (sameline && xcur == current_x) {
 	    if (ISSET(VIEW_MODE)) {
 		print_view_warning();
 		return;
 	    }
 	    do_mark();
-	} else if (mevent.y > current_y) {
-	    while (mevent.y > current_y) {
-		if (current->next != NULL)
-		    current = current->next;
-		else
-		    break;
-		current_y++;
-	    }
-	} else if (mevent.y < current_y) {
-	    while (mevent.y < current_y) {
-		if (current->prev != NULL)
-		    current = current->prev;
-		else
-		    break;
-		current_y--;
-	    }
 	}
-	current_x = actual_x(current, mevent.x);
-	placewewant = current_x;
-	update_cursor();
+
+	current_x = xcur;
+	placewewant = xplustabs();
 	edit_refresh();
     } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
 	int i, k;