Subject: bug#33640: 27.0.50; Wrong column when prompt contains combining characters

From: Juri Linkov <[email-masked]>
Date: Thu, 06 Dec 2018 01:05:24 +0200

Tags: patch

If the minibuffer prompt contains combining characters in such cases
when for example dired-do-async-shell-command is invoked on a file
whose name contains COMBINING ACUTE ACCENT, then navigating the
minibuffer history with M-n and M-p puts point at incorrect positions.

This is because currently next-line-or-history-element and
previous-line-or-history-element subtract the point's position
from the column number that takes into account character composition.

This patch uses only columns in calculations.

Eli, do you think this fix should be installed to the emacs-26 branch?

diff --git a/lisp/simple.el b/lisp/simple.el
index e1922384f2..4c6ca0619a 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -2172,7 +2172,11 @@ next-line-or-history-element
 	 (prompt-end (minibuffer-prompt-end))
 	 (old-column (unless (and (eolp) (> (point) prompt-end))
 		       (if (= (line-number-at-pos) 1)
-			   (max (- (current-column) (1- prompt-end)) 0)
+			   (max (- (current-column)
+				   (save-excursion
+				     (goto-char (1- prompt-end))
+				     (current-column)))
+				0)
 			 (current-column)))))
     (condition-case nil
 	(with-no-warnings
@@ -2191,7 +2195,10 @@ next-line-or-history-element
        (goto-char (point-max))
        (when old-column
 	 (if (= (line-number-at-pos) 1)
-	     (move-to-column (+ old-column (1- (minibuffer-prompt-end))))
+	     (move-to-column (+ old-column
+				(save-excursion
+				  (goto-char (1- (minibuffer-prompt-end)))
+				  (current-column))))
 	   (move-to-column old-column)))))))
 
 (defun previous-line-or-history-element (&optional arg)
@@ -2206,7 +2213,11 @@ previous-line-or-history-element
 	 (prompt-end (minibuffer-prompt-end))
 	 (old-column (unless (and (eolp) (> (point) prompt-end))
 		       (if (= (line-number-at-pos) 1)
-			   (max (- (current-column) (1- prompt-end)) 0)
+			   (max (- (current-column)
+				   (save-excursion
+				     (goto-char (1- prompt-end))
+				     (current-column)))
+				0)
 			 (current-column)))))
     (condition-case nil
 	(with-no-warnings
@@ -2225,7 +2236,10 @@ previous-line-or-history-element
        (goto-char (minibuffer-prompt-end))
        (if old-column
 	   (if (= (line-number-at-pos) 1)
-	       (move-to-column (+ old-column (1- (minibuffer-prompt-end))))
+	       (move-to-column (+ old-column
+				  (save-excursion
+				    (goto-char (1- (minibuffer-prompt-end)))
+				    (current-column))))
 	     (move-to-column old-column))
 	 ;; Put the cursor at the end of the visual line instead of the
 	 ;; logical line, so the next `previous-line-or-history-element'