unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Shingo Tanaka <shingo.fg8@gmail.com>
To: 48149@debbugs.gnu.org
Subject: bug#48149: 27.2; Wrong underline width when the line char has a width of 2
Date: Sun, 02 May 2021 10:12:43 +0900	[thread overview]
Message-ID: <87fsz62b1w.wl-shingo.fg8@gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1611 bytes --]

Hi,

When exporting org-mode document to plain text (either ascii/unicode/utf-8)
with `org-export-dispatch', Emacs inserts lines under headlines, inline
tasks, table rows and titles of the document, TOC, list of listings, list of
tables and footnotes.  The problem is it inserts too long (double width) line
when the line character has a width of 2.

Those lines are made of 3 types of characters below (in ox-ascii.el):
1) org-ascii-underline
2) (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)
3) (if utf8p ?━ ?_)

In case of 1), it correctly takes account of the case in which the character
has a width of 2 in `org-ascii--build-title', by dividing the line width by
`(char-width under-char)' (line 700-701), maybe because the character is user
configurable and its width in unknown.  However, in case of 2) and
3), maybe because the characters is embedded in the code, it looks like only
considering the character always has a width of 1.  But the reality is
character ?─ or ?━ can have a width of 2 in the screen displayed with some
fonts (ex. "Noto Sans Mono CJK JP"), and in that case the line width gets
doubled of the expected width.

Attached one is a potential patch.  The basic concepts are:

a) Do the same in case of 2) and 3) as in case of 1)
   (dividing the line width by `(char-width under-char)',
    assuming `char-width-table' is correctly set)
    
b) Prefer the longer line width if the width is odd, even in case of 1)
   (adding `(1- (char-width under-char))' to dividend,
    just because it should be more beautiful ;-) )

Regards,
---
Shingo Tanaka

[-- Attachment #2: ox-ascii.el.patch --]
[-- Type: application/octet-stream, Size: 6862 bytes --]

--- ox-ascii.el.org	2021-03-26 09:28:44.000000000 +0900
+++ ox-ascii.el	2021-05-02 09:02:41.168565362 +0900
@@ -697,7 +697,8 @@
 			      (plist-get info :ascii-underline))))))
 	 (and under-char
 	      (concat "\n"
-		      (make-string (/ (string-width first-part)
+		      (make-string (/ (+ (string-width first-part)
+                                         (1- (char-width under-char)))
 				      (char-width under-char))
 				   under-char))))))))
 
@@ -748,11 +749,13 @@
 contents according to the specified scope."
   (concat
    (unless scope
-     (let ((title (org-ascii--translate "Table of Contents" info)))
+     (let ((title (org-ascii--translate "Table of Contents" info))
+           (under-char (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)))
        (concat title "\n"
 	       (make-string
-		(string-width title)
-		(if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))
+		(/ (+ (string-width title) (1- (char-width under-char)))
+                   (char-width under-char))
+		under-char)
 	       "\n\n")))
    (let ((text-width
 	  (if keyword (org-ascii--current-text-width keyword info)
@@ -776,11 +779,13 @@
 
 KEYWORD is the keyword that initiated the list of listings
 generation.  INFO is a plist used as a communication channel."
-  (let ((title (org-ascii--translate "List of Listings" info)))
+  (let ((title (org-ascii--translate "List of Listings" info))
+        (under-char (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)))
     (concat
      title "\n"
-     (make-string (string-width title)
-		  (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))
+     (make-string (/ (+ (string-width title) (1- (char-width under-char)))
+                     (char-width under-char))
+		  under-char)
      "\n\n"
      (let ((text-width
 	    (if keyword (org-ascii--current-text-width keyword info)
@@ -816,11 +821,13 @@
 
 KEYWORD is the keyword that initiated the list of tables
 generation.  INFO is a plist used as a communication channel."
-  (let ((title (org-ascii--translate "List of Tables" info)))
+  (let ((title (org-ascii--translate "List of Tables" info))
+        (under-char (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)))
     (concat
      title "\n"
-     (make-string (string-width title)
-		  (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))
+     (make-string (/ (+ (string-width title) (1- (char-width under-char)))
+                     (char-width under-char))
+		  under-char)
      "\n\n"
      (let ((text-width
 	    (if keyword (org-ascii--current-text-width keyword info)
@@ -1030,6 +1037,7 @@
       ;; AUTHOR and its EMAIL are both overlined and an underlined,
       ;; centered.  Date is just below, also centered.
       (let* ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))
+             (line-char (if utf8p ?━ ?_))
 	     ;; Format TITLE.  It may be filled if it is too wide,
 	     ;; that is wider than the two thirds of the total width.
 	     (title-len (min (apply #'max
@@ -1042,11 +1050,14 @@
 				   (org-ascii--fill-string subtitle title-len info)))
 	     (line
 	      (make-string
-	       (min (+ (max title-len
-			    (string-width (or author ""))
-			    (string-width (or email "")))
-		       2)
-		    text-width) (if utf8p ?━ ?_))))
+	       (/ (+ (min (+ (max title-len
+			       (string-width (or author ""))
+			       (string-width (or email "")))
+		          2)
+		          text-width)
+                     (1- (char-width line-char)))
+                  (char-width line-char))
+               line-char)))
 	(org-ascii--justify-lines
 	 (concat line "\n"
 		 (unless utf8p "\n")
@@ -1079,12 +1090,15 @@
 	 (when definitions
 	   (concat
 	    "\n\n\n"
-	    (let ((title (org-ascii--translate "Footnotes" info)))
+	    (let ((title (org-ascii--translate "Footnotes" info))
+                  (under-char (if (eq (plist-get info :ascii-charset) 'utf-8)
+                                  ?─ ?_)))
 	      (concat
 	       title "\n"
 	       (make-string
-		(string-width title)
-		(if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_))))
+		(/ (+ (string-width title) (1- (char-width under-char)))
+                   (char-width under-char))
+		under-char)))
 	    "\n\n"
 	    (let ((text-width (- (plist-get info :ascii-text-width)
 				 global-margin)))
@@ -1381,11 +1395,14 @@
 See `org-ascii-format-inlinetask-function' for a description
 of the parameters."
   (let* ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))
-	 (width (or width (plist-get info :ascii-inlinetask-width))))
+	 (width (or width (plist-get info :ascii-inlinetask-width)))
+         (under-char (if utf8p ?━ ?_)))
     (org-ascii--indent-string
      (concat
       ;; Top line, with an additional blank line if not in UTF-8.
-      (make-string width (if utf8p ?━ ?_)) "\n"
+      (make-string (/ (+ width (1- (char-width under-char)))
+                      (char-width under-char))
+                   under-char) "\n"
       (unless utf8p (concat (make-string width ? ) "\n"))
       ;; Add title.  Fill it if wider than inlinetask.
       (let ((title (org-ascii--build-title inlinetask info width)))
@@ -1395,9 +1412,14 @@
       ;; If CONTENTS is not empty, insert it along with
       ;; a separator.
       (when (org-string-nw-p contents)
-        (concat (make-string width (if utf8p ?─ ?-)) "\n" contents))
+        (concat (make-string (/ (+ width (1- (char-width under-char)))
+                                (char-width under-char))
+                             under-char)
+                "\n" contents))
       ;; Bottom line.
-      (make-string width (if utf8p ?━ ?_)))
+      (make-string (/ (+ width (1- (char-width under-char)))
+                      (char-width under-char))
+                   under-char))
      ;; Flush the inlinetask to the right.
      (- (plist-get info :ascii-text-width) (plist-get info :ascii-global-margin)
 	(if (not (org-export-get-parent-headline inlinetask)) 0
@@ -1948,7 +1970,8 @@
 		(org-element-map table-row 'table-cell
 		  (lambda (cell)
 		    (let ((width (org-ascii--table-cell-width cell info))
-			  (borders (org-export-table-cell-borders cell info)))
+			  (borders (org-export-table-cell-borders cell info))
+                          (horiz-char (string-to-char horiz)))
 		      (concat
 		       ;; In order to know if CELL starts the row, do
 		       ;; not compare it with the first cell in the
@@ -1960,7 +1983,9 @@
 					'identity info t)
 				      cell))
 			 lcorner)
-		       (make-string (+ 2 width) (string-to-char horiz))
+		       (make-string (/ (+ 2 width (1- (char-width horiz-char)))
+                                       (char-width horiz-char))
+                                    horiz-char)
 		       (cond
 			((not (memq 'right borders)) nil)
 			((eq (car (last (org-element-contents table-row))) cell)

             reply	other threads:[~2021-05-02  1:12 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-02  1:12 Shingo Tanaka [this message]
2021-05-02  7:17 ` bug#48149: 27.2; Wrong underline width when the line char has a width of 2 Eli Zaretskii
2021-05-02  8:36   ` Rudolf Schlatte
2021-05-02  9:16     ` Eli Zaretskii
2021-05-02 16:08 ` Nicolas Goaziou
     [not found] ` <87a6pd86el.fsf@nicolasgoaziou.fr>
2021-05-02 16:23   ` Eli Zaretskii
     [not found]   ` <83im416r6h.fsf@gnu.org>
2021-05-09 13:57     ` Shingo Tanaka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87fsz62b1w.wl-shingo.fg8@gmail.com \
    --to=shingo.fg8@gmail.com \
    --cc=48149@debbugs.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).