From 1cef2d7cbea407eaeff5c65e9594e03fabe3bf5e Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 2 Jan 2019 17:55:45 +0200 Subject: [PATCH] Fix text direction of the HarfBuzz shaping buffer * src/indent.c (scan_for_column, compute_motion): * src/xdisp.c (CHAR_COMPOSED_P): Pass PDIR argument to composition_reseat_it. * src/composite.c (composition_reseat_it): Accept an additional argument PDIR that provides the current paragraph's base direction; all callers changed. Use PDIR to fix calculation of the DIRECTION argument to autocmp_chars. (Bug#33944) * src/composite.h: Include dispextern.h. (composition_reseat_it): Update prototype. --- src/composite.c | 20 +++++++++++++++----- src/composite.h | 3 ++- src/indent.c | 4 ++-- src/xdisp.c | 1 + 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/composite.c b/src/composite.c index 48824946e64..7cb97934a20 100644 --- a/src/composite.c +++ b/src/composite.c @@ -1167,7 +1167,9 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos, characters to be composed. FACE, if non-NULL, is a base face of the character. If STRING is not nil, it is a string containing the character to check, and CHARPOS and BYTEPOS are indices in the - string. In that case, FACE must not be NULL. + string. In that case, FACE must not be NULL. PDIR is the base + direction of the current paragraph, and is used to calculate the + direction argument to pass to the font shaper. If the character is composed, setup members of CMP_IT (id, nglyphs, from, to, reversed_p), and return true. Otherwise, update @@ -1176,7 +1178,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos, bool composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t endpos, struct window *w, - struct face *face, Lisp_Object string) + bidi_dir_t pdir, struct face *face, Lisp_Object string) { if (cmp_it->ch == -2) { @@ -1206,7 +1208,7 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos, else if (w) { Lisp_Object lgstring = Qnil; - Lisp_Object val, elt; + Lisp_Object val, elt, direction = Qnil; val = CHAR_TABLE_REF (Vcomposition_function_table, cmp_it->ch); for (EMACS_INT i = 0; i < cmp_it->rule_idx; i++, val = XCDR (val)) @@ -1221,8 +1223,12 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos, continue; if (XFIXNAT (AREF (elt, 1)) != cmp_it->lookback) goto no_composition; + if (pdir == L2R) + direction = QL2R; + else if (pdir == R2L) + direction = QR2L; lgstring = autocmp_chars (elt, charpos, bytepos, endpos, - w, face, string, QL2R); + w, face, string, direction); if (composition_gstring_p (lgstring)) break; lgstring = Qnil; @@ -1246,8 +1252,12 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos, else bpos = CHAR_TO_BYTE (cpos); } + if (pdir == L2R) + direction = QR2L; + else if (pdir == R2L) + direction = QL2R; lgstring = autocmp_chars (elt, cpos, bpos, charpos + 1, w, face, - string, QR2L); + string, direction); if (! composition_gstring_p (lgstring) || cpos + LGSTRING_CHAR_LEN (lgstring) - 1 != charpos) /* Composition failed or didn't cover the current diff --git a/src/composite.h b/src/composite.h index ad39a08dca3..44f7ab7f616 100644 --- a/src/composite.h +++ b/src/composite.h @@ -26,6 +26,7 @@ along with GNU Emacs. If not, see . */ #define EMACS_COMPOSITE_H #include "font.h" +#include "dispextern.h" INLINE_HEADER_BEGIN @@ -321,7 +322,7 @@ extern void composition_compute_stop_pos (struct composition_it *, Lisp_Object); extern bool composition_reseat_it (struct composition_it *, ptrdiff_t, ptrdiff_t, ptrdiff_t, struct window *, - struct face *, Lisp_Object); + bidi_dir_t, struct face *, Lisp_Object); extern int composition_update_it (struct composition_it *, ptrdiff_t, ptrdiff_t, Lisp_Object); diff --git a/src/indent.c b/src/indent.c index 18855768d37..e0d35f87652 100644 --- a/src/indent.c +++ b/src/indent.c @@ -599,7 +599,7 @@ scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol, ptrdiff_t *prevcol) if (cmp_it.id >= 0 || (scan == cmp_it.stop_pos && composition_reseat_it (&cmp_it, scan, scan_byte, end, - w, NULL, Qnil))) + w, NEUTRAL_DIR, NULL, Qnil))) composition_update_it (&cmp_it, scan, scan_byte, Qnil); if (cmp_it.id >= 0) { @@ -1506,7 +1506,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos, if (cmp_it.id >= 0 || (pos == cmp_it.stop_pos && composition_reseat_it (&cmp_it, pos, pos_byte, to, win, - NULL, Qnil))) + NEUTRAL_DIR, NULL, Qnil))) composition_update_it (&cmp_it, pos, pos_byte, Qnil); if (cmp_it.id >= 0) { diff --git a/src/xdisp.c b/src/xdisp.c index 4d9990cf46c..413d64f80c7 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -6906,6 +6906,7 @@ static next_element_function const get_next_element[NUM_IT_METHODS] = || ((IT)->cmp_it.stop_pos == (CHARPOS) \ && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \ END_CHARPOS, (IT)->w, \ + (IT)->bidi_it.paragraph_dir, \ FACE_FROM_ID_OR_NULL ((IT)->f, \ (IT)->face_id), \ (IT)->string))) -- 2.39.2