all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: handa <handa@gnu.org>
To: Nima Aryan <nimawebgard@gmail.com>
Cc: b.riefenstahl@turtle-trading.net, 28339@debbugs.gnu.org
Subject: bug#28339: 25.2; Emacs shows ZWNJ character (Zero Width non-Joiner) as Space
Date: Fri, 06 Oct 2017 19:05:41 +0900	[thread overview]
Message-ID: <87infszj4a.fsf@gnu.org> (raw)
In-Reply-To: <CALp2H_2MWgjoEEm6Rp5+5uOdMk-RbFWzaCrweo=pbdzAaq8btA@mail.gmail.com> (message from Nima Aryan on Tue, 19 Sep 2017 13:53:31 +0000)

In article <CALp2H_2MWgjoEEm6Rp5+5uOdMk-RbFWzaCrweo=pbdzAaq8btA@mail.gmail.com>, Nima Aryan <nimawebgard@gmail.com> writes:

> As a user I prefer absorb mode by default but some times thin-space (and
> not simple space) might be a good option to consider.

Attached patch introduces a customizable variable
arabic-shaper-ZWNJ-handling.  Shall I install it?

---
K. Handa
handa@gnu.org

------------------------------------------------------------
diff --git a/lisp/composite.el b/lisp/composite.el
index ab39e08..72b0ffc 100644
--- a/lisp/composite.el
+++ b/lisp/composite.el
@@ -442,8 +442,10 @@ lglyph-set-width
 (defsubst lglyph-set-adjustment (glyph &optional xoff yoff wadjust)
   (aset glyph 9 (vector (or xoff 0) (or yoff 0) (or wadjust 0))))
 
+;; Return the shallow Copy of GLYPH.
 (defsubst lglyph-copy (glyph) (copy-sequence glyph))
 
+;; Insert GLYPH at the index IDX of GSTRING.
 (defun lgstring-insert-glyph (gstring idx glyph)
   (let ((nglyphs (lgstring-glyph-len gstring))
 	(i idx))
@@ -459,6 +461,18 @@ lgstring-insert-glyph
     (lgstring-set-glyph gstring i glyph)
     gstring))
 
+;; Remove glyph at IDX from GSTRING.
+(defun lgstring-remove-glyph (gstring idx)
+  (setq gstring (copy-sequence gstring))
+  (lgstring-set-id gstring nil)
+  (let ((len (length gstring)))
+    (setq idx (+ idx 3))
+    (while (< idx len)
+      (aset gstring (1- idx) (aref gstring idx))
+      (setq idx (1+ idx)))
+    (aset gstring (1- len) nil))
+  gstring)
+
 (defun compose-glyph-string (gstring from to)
   (let ((glyph (lgstring-glyph gstring from))
 	from-pos to-pos)
diff --git a/lisp/language/misc-lang.el b/lisp/language/misc-lang.el
index 2843c7c..4e10227 100644
--- a/lisp/language/misc-lang.el
+++ b/lisp/language/misc-lang.el
@@ -75,12 +75,72 @@ 'cp1256
 	    (sample-text . "Persian	فارسی")
 	    (documentation . "Bidirectional editing is supported.")))
 
+(defcustom arabic-shaper-ZWNJ-handling nil
+  "How to handle ZWMJ in Arabic text renderling.
+This variable controls the way to handle a glyph for ZWNJ
+returned by the underling shaping engine.
+
+The default value is nil, which means that the ZWNJ glyph is
+displayed as is.
+
+If the value is `absorb', ZWNJ is absorbed into the previous
+grapheme cluster, and not displayed.
+
+If the value is `as-space', the glyph is displayed by a
+thin (i.e. 1-dot width) space.
+
+Customizing the value takes effect when you start Emacs next time."
+  :group 'mule
+  :version "27.1"
+  :type '(choice
+          (const :tag "default" nil)
+          (const :tag "as space" as-space)
+          (const :tag "absorb" absorb)))
+
+(defvar arabic-shape-log nil)
+
+(defun arabic-shape-gstring (gstring)
+  (setq gstring (font-shape-gstring gstring))
+  (push arabic-shaper-ZWNJ-handling arabic-shape-log)
+  (condition-case err
+      (when arabic-shaper-ZWNJ-handling
+        (let ((font (lgstring-font gstring))
+              (i 1)
+              (len (lgstring-glyph-len gstring))
+              (modified nil))
+          (while (< i len)
+            (let ((glyph (lgstring-glyph gstring i)))
+              (when (eq (lglyph-char glyph) #x200c)
+                (cond
+                 ((eq arabic-shaper-ZWNJ-handling 'as-space)
+                  (if (> (- (lglyph-rbearing glyph) (lglyph-lbearing glyph)) 0)
+                      (let ((space-glyph (aref (font-get-glyphs font 0 1 " ") 0)))
+                        (when space-glyph
+                          (lglyph-set-code glyph (aref space-glyph 3))
+                          (lglyph-set-width glyph (aref space-glyph 4)))))
+                  (lglyph-set-adjustment glyph 0 0 1)
+                  (setq modified t))
+                 ((eq arabic-shaper-ZWNJ-handling 'absorb)
+                  (let ((prev (lgstring-glyph gstring (1- i))))
+                    (lglyph-set-from-to prev (lglyph-from prev) (lglyph-to glyph))
+                    (push (cons "remove" (lgstring-glyph gstring i))
+                          arabic-shape-log)
+                    (setq gstring (lgstring-remove-glyph gstring i))
+                    (setq len (1- len)))
+                  (setq modified t)))))
+            (setq i (1+ i)))
+          (if modified
+              (lgstring-set-id gstring nil))))
+    (error (push err arabic-shape-log)))
+  gstring)
+
 (set-char-table-range
  composition-function-table
  '(#x600 . #x74F)
- (list (vector "[\u0600-\u074F\u200C\u200D]+" 0 'font-shape-gstring)
-       (vector "[\u200C\u200D][\u0600-\u074F\u200C\u200D]+"
-               1 'font-shape-gstring)))
+ (list (vector "[\u0600-\u074F\u200C\u200D]+" 0
+               'arabic-shape-gstring)
+       (vector "[\u200C\u200D][\u0600-\u074F\u200C\u200D]+" 1
+               'arabic-shape-gstring)))
 
 (provide 'misc-lang)
 







  parent reply	other threads:[~2017-10-06 10:05 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-03 15:57 bug#28339: 25.2; Emacs shows ZWNJ character (Zero Width non-Joiner) as Space Nima Aryan
2017-09-03 17:06 ` Eli Zaretskii
2017-09-03 17:11   ` Eli Zaretskii
2017-09-03 19:31     ` Nima Aryan
2017-09-04  4:26       ` Eli Zaretskii
2017-09-04  5:05         ` sadid sahami
2017-09-04  9:15           ` Eli Zaretskii
2017-09-04 11:43             ` Nima Aryan
2017-09-04 11:49               ` Nima Aryan
2017-09-04 12:11               ` Eli Zaretskii
2017-09-06 23:25           ` handa
2017-09-07  2:40             ` Eli Zaretskii
     [not found] ` <CALp2H_0RgoW6NL-N3yLA_io38-y8noymU4gGwEbLGcDV4AX9_g@mail.gmail.com>
2017-09-10 23:08   ` handa
2017-09-11 16:19     ` Eli Zaretskii
2017-09-13 14:06       ` handa
2017-09-13 15:02         ` Eli Zaretskii
2017-09-14 12:24           ` handa
2017-09-14 17:15             ` Eli Zaretskii
2017-09-16  1:32               ` handa
2017-09-16  4:05                 ` Nima Aryan
2017-09-16  7:24                 ` Eli Zaretskii
2017-09-16 17:30               ` Benjamin Riefenstahl
2017-09-16 17:42                 ` Eli Zaretskii
2017-09-16 18:05                   ` Benjamin Riefenstahl
2017-09-16 18:23                     ` Eli Zaretskii
2017-09-16 18:20                   ` Eli Zaretskii
2017-09-18  1:52                   ` handa
2017-09-18 15:16                     ` Eli Zaretskii
2017-09-19 12:18                       ` handa
2017-09-20  7:25                         ` Eli Zaretskii
2017-09-18 15:22                     ` Benjamin Riefenstahl
2017-09-14 21:13           ` Nima Aryan
     [not found] ` <CALp2H_2w50RrBiaWV1dpg760cUpamy1nZdRgrwJKAjESq3no3Q@mail.gmail.com>
2017-09-13 14:02   ` handa
     [not found] ` <CALp2H_3tLC71X6-jvH2XD-6qX8O=KE5wHa561QPk-w2OoCX9HA@mail.gmail.com>
2017-09-16 12:36   ` handa
     [not found] ` <CALp2H_2MWgjoEEm6Rp5+5uOdMk-RbFWzaCrweo=pbdzAaq8btA@mail.gmail.com>
2017-10-06 10:05   ` handa [this message]
2017-10-06 12:14     ` Eli Zaretskii
2017-10-07  1:11       ` handa
2020-09-04  5:12       ` Lars Ingebrigtsen

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

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

  git send-email \
    --in-reply-to=87infszj4a.fsf@gnu.org \
    --to=handa@gnu.org \
    --cc=28339@debbugs.gnu.org \
    --cc=b.riefenstahl@turtle-trading.net \
    --cc=nimawebgard@gmail.com \
    /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 external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.