emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master b5997c0f10: Optionally allow point to enter composed character se


From: Eli Zaretskii
Subject: master b5997c0f10: Optionally allow point to enter composed character sequences
Date: Sat, 12 Feb 2022 13:42:57 -0500 (EST)

branch: master
commit b5997c0f108d265917f899f6558ac56a8638451d
Author: Eli Zaretskii <eliz@gnu.org>
Commit: Eli Zaretskii <eliz@gnu.org>

    Optionally allow point to enter composed character sequences
    
    This changeset is based on code originally posted by
    Kenichi Handa <handa@gnu.org> as part of discussing bug#20140,
    with a few adjustments and changes, mainly to support R2L
    text and provide a user option to control the feature.
    * src/xdisp.c (compute_stop_pos, next_element_from_buffer)
    (composition_reseat_it): Don't allow auto-composing characters
    past point when 'composition-break-at-point' is non-nil.
    (syms_of_xdisp) <composition-break-at-point>: New boolean variable.
    (redisplay_internal, redisplay_window): Disable "just move the
    cursor" optimizations when 'composition-break-at-point' is non-nil.
    * src/keyboard.c (command_loop_1): Force redisplay when
    'composition-break-at-point' is non-nil.
    
    * lisp/cus-start.el (standard): Provide customization form for
    'composition-break-at-point'.
    
    * etc/NEWS: Announce the new feature.
---
 etc/NEWS          | 11 +++++++++++
 lisp/cus-start.el |  1 +
 src/composite.c   | 10 ++++++++++
 src/keyboard.c    | 42 ++++++++++++++++++++++++++----------------
 src/xdisp.c       | 34 +++++++++++++++++++++++++++++++---
 5 files changed, 79 insertions(+), 19 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 6f19224026..1b0e26da9b 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -476,6 +476,17 @@ The options 'mouse-wheel-down-alternate-event', 
'mouse-wheel-up-alternate-event'
 been added to better support systems where two kinds of wheel events can be
 received.
 
+** Editing complex text layout (CTL) scripts
+
+*** The <Delete> function key now allows deleting the entire composed sequence.
+For the details, see the item about the 'delete-forward-char' command
+above.
+
+*** New user option 'composition-break-at-point'.
+Setting it to a non-nil value temporarily disables automatic
+composition of character sequences at point, and thus makes it easier
+to edit such sequences by allowing point to "enter" the sequence.
+
 
 * Changes in Specialized Modes and Packages in Emacs 29.1
 
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index afdbd82457..f8bab89e90 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -811,6 +811,7 @@ since it could result in memory overflow and make Emacs 
crash."
                character)
               "27.1"
               :safe (lambda (value) (or (characterp value) (null value))))
+             (composition-break-at-point display boolean "29.1")
             ;; xfaces.c
             (scalable-fonts-allowed
               display (choice (const :tag "Don't allow scalable fonts" nil)
diff --git a/src/composite.c b/src/composite.c
index 17563201e2..c3e9afc807 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -1292,6 +1292,16 @@ composition_reseat_it (struct composition_it *cmp_it, 
ptrdiff_t charpos,
          if (cmp_it->lookback > 0)
            {
              cpos = charpos - cmp_it->lookback;
+             /* Reject the composition if it starts before ENDPOS,
+                which here can only happen if
+                composition-break-at-point is non-nil and point is
+                inside the composition.  */
+             if (cpos < endpos)
+               {
+                 eassert (composition_break_at_point);
+                 eassert (endpos == PT);
+                 goto no_composition;
+               }
              if (STRINGP (string))
                bpos = string_char_to_byte (string, cpos);
              else
diff --git a/src/keyboard.c b/src/keyboard.c
index 6b66a71593..be9fb665d7 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1603,23 +1603,33 @@ command_loop_1 (void)
 
       if (current_buffer == prev_buffer
          && XBUFFER (XWINDOW (selected_window)->contents) == current_buffer
-         && last_point_position != PT
-         && NILP (Vdisable_point_adjustment)
-         && NILP (Vglobal_disable_point_adjustment))
+         && last_point_position != PT)
        {
-         if (last_point_position > BEGV
-             && last_point_position < ZV
-             && (composition_adjust_point (last_point_position,
-                                           last_point_position)
-                 != last_point_position))
-           /* The last point was temporarily set within a grapheme
-              cluster to prevent automatic composition.  To recover
-              the automatic composition, we must update the
-              display.  */
-           windows_or_buffers_changed = 21;
-         if (!already_adjusted)
-           adjust_point_for_property (last_point_position,
-                                      MODIFF != prev_modiff);
+         if (NILP (Vdisable_point_adjustment)
+             && NILP (Vglobal_disable_point_adjustment)
+             && !composition_break_at_point)
+           {
+             if (last_point_position > BEGV
+                 && last_point_position < ZV
+                 && (composition_adjust_point (last_point_position,
+                                               last_point_position)
+                     != last_point_position))
+               /* The last point was temporarily set within a grapheme
+                  cluster to prevent automatic composition.  To recover
+                  the automatic composition, we must update the
+                  display.  */
+               windows_or_buffers_changed = 21;
+             if (!already_adjusted)
+               adjust_point_for_property (last_point_position,
+                                          MODIFF != prev_modiff);
+           }
+         else if (PT > BEGV && PT < ZV
+                  && (composition_adjust_point (last_point_position, PT)
+                      != PT))
+           /* Now point is within a grapheme cluster.  We must update
+              the display so that this cluster is de-composed on the
+              screen and the cursor is correctly placed at point.  */
+           windows_or_buffers_changed = 39;
        }
 
       /* Install chars successfully executed in kbd macro.  */
diff --git a/src/xdisp.c b/src/xdisp.c
index cc1da24aca..ec8d53e5cc 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3984,6 +3984,12 @@ compute_stop_pos (struct it *it)
       pos = next_overlay_change (charpos);
       if (pos < it->stop_charpos)
        it->stop_charpos = pos;
+      /* If we are breaking compositions at point, stop at point.  */
+      if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
+         && !NILP (Vauto_composition_mode)
+         && composition_break_at_point
+         && charpos < PT && PT < it->stop_charpos)
+       it->stop_charpos = PT;
 
       /* Set up variables for computing the stop position from text
          property changes.  */
@@ -3995,7 +4001,8 @@ compute_stop_pos (struct it *it)
         chunks.  We play safe here by assuming that only SPC, TAB,
         FF, and NL cannot be in some composition; in particular, most
         ASCII punctuation characters could be composed into ligatures.  */
-      if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
+      if (!composition_break_at_point
+         && !NILP (BVAR (current_buffer, enable_multibyte_characters))
          && !NILP (Vauto_composition_mode))
        {
          ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
@@ -9186,7 +9193,19 @@ next_element_from_buffer (struct it *it)
          && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
        run_redisplay_end_trigger_hook (it);
 
-      stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
+      if (composition_break_at_point
+         && !NILP (BVAR (current_buffer, enable_multibyte_characters))
+         && !NILP (Vauto_composition_mode))
+       {
+         /* Limit search for composable characters to point's position.  */
+         if (it->bidi_it.scan_dir < 0)
+           stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
+         else
+           stop = (IT_CHARPOS (*it) < PT
+                   && PT < it->end_charpos) ? PT : it->end_charpos;
+       }
+      else
+       stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
       if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
                           stop)
          && next_element_from_composition (it))
@@ -16390,7 +16409,8 @@ redisplay_internal (void)
       /* If highlighting the region, or if the cursor is in the echo area,
         then we can't just move the cursor.  */
       else if (NILP (Vshow_trailing_whitespace)
-              && !cursor_in_echo_area)
+              && !cursor_in_echo_area
+              && !composition_break_at_point)
        {
          struct it it;
          struct glyph_row *row;
@@ -18928,6 +18948,7 @@ redisplay_window (Lisp_Object window, bool 
just_this_one_p)
        && !current_buffer->clip_changed
        && !current_buffer->prevent_redisplay_optimizations_p
        && !window_outdated (w)
+       && !composition_break_at_point
        && !hscrolling_current_line_p (w));
 
   beg_unchanged = BEG_UNCHANGED;
@@ -36527,6 +36548,13 @@ Otherwise, use custom-tailored code after resizing 
minibuffer windows to try
 and display the most important part of the minibuffer.   */);
   /* See bug#43519 for some discussion around this.  */
   redisplay_adhoc_scroll_in_resize_mini_windows = true;
+
+  DEFVAR_BOOL ("composition-break-at-point",
+              composition_break_at_point,
+              doc: /* If non-nil, prevent auto-composition of characters 
around point.
+This makes it easier to edit character sequences that are
+composed on display.  */);
+  composition_break_at_point = false;
 }
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]