emacs-diffs
[Top][All Lists]
Advanced

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

master 430088c9cce 3/3: Take fields into account during text conversion


From: Po Lu
Subject: master 430088c9cce 3/3: Take fields into account during text conversion
Date: Mon, 29 Apr 2024 00:35:17 -0400 (EDT)

branch: master
commit 430088c9ccec5fe9be57d267f45acdc87aa3b28e
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Take fields into account during text conversion
    
    * lisp/cus-edit.el (Custom-mode): Enable text conversion, now
    that fields are correctly treated.
    
    * src/alloc.c (mark_frame): Mark f->conversion.field.
    
    * src/androidterm.c (android_update_selection): Adjust
    conversion region and selection position by the field start and
    end.
    
    * src/editfns.c (find_field): Export function.
    
    * src/frame.c (make_frame): Clear f->conversion.field.
    
    * src/frame.h (struct text_conversion_state) <field>: New field.
    
    * src/lisp.h (find_fields, reset_frame_conversion): Export
    functions.
    
    * src/minibuf.c (Fread_from_minibuffer): Reset frame conversion
    if Voverriding_text_conversion_style is set.
    
    * src/textconv.c (textconv_query): Narrow to field.
    (reset_frame_conversion): New function.
    (reset_frame_state): Clear conversion field.
    (really_delete_surrounding_text): Narrow to field.
    (locate_and_save_position_in_field): New function.
    (really_request_point_update, really_set_point_and_mark)
    (complete_edit_check, handle_pending_conversion_events_1)
    (handle_pending_conversion_events, get_conversion_field)
    (set_composing_region, textconv_set_point_and_mark, replace_text)
    (get_extracted_text, get_surrounding_text, report_point_change):
    Compute, narrow to and offset by the currently active field
    whenever point is updated or a command is received.
    (syms_of_textconv): Revise doc strings.
    
    * src/textconv.h (get_conversion_field): Export function.
---
 lisp/cus-edit.el  |   1 +
 src/alloc.c       |   1 +
 src/androidterm.c |  39 ++++---
 src/editfns.c     |   2 +-
 src/frame.c       |   1 +
 src/frame.h       |   4 +
 src/lisp.h        |   3 +
 src/minibuf.c     |  14 +++
 src/textconv.c    | 296 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 src/textconv.h    |   1 +
 10 files changed, 324 insertions(+), 38 deletions(-)

diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index 8915500a501..1659c285d84 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -5400,6 +5400,7 @@ if that value is non-nil."
   (setq-local custom--invocation-options nil
               custom--hidden-state 'hidden)
   (setq-local revert-buffer-function #'custom--revert-buffer)
+  (setq-local text-conversion-style 'action)
   (make-local-variable 'custom-options)
   (make-local-variable 'custom-local-buffer)
   (custom--initialize-widget-variables)
diff --git a/src/alloc.c b/src/alloc.c
index a8dfde56739..47a8e4f4bd2 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -7050,6 +7050,7 @@ mark_frame (struct Lisp_Vector *ptr)
   mark_object (f->conversion.compose_region_start);
   mark_object (f->conversion.compose_region_end);
   mark_object (f->conversion.compose_region_overlay);
+  mark_object (f->conversion.field);
 
   for (tem = f->conversion.actions; tem; tem = tem->next)
     mark_object (tem->data);
diff --git a/src/androidterm.c b/src/androidterm.c
index 4549941ee2e..f849f0d9919 100644
--- a/src/androidterm.c
+++ b/src/androidterm.c
@@ -6265,14 +6265,24 @@ android_update_selection (struct frame *f, struct 
window *w)
   jobject extracted;
   jstring string;
   bool mark_active;
+  ptrdiff_t field_start, field_end;
+
+  /* Offset these values by the start offset of the field.  */
+  get_conversion_field (f, &field_start, &field_end);
 
   if (MARKERP (f->conversion.compose_region_start))
     {
       eassert (MARKERP (f->conversion.compose_region_end));
 
       /* Indexing in android starts from 0 instead of 1.  */
-      start = marker_position (f->conversion.compose_region_start) - 1;
-      end = marker_position (f->conversion.compose_region_end) - 1;
+      start = marker_position (f->conversion.compose_region_start);
+      end = marker_position (f->conversion.compose_region_end);
+
+      /* Offset and detect underflow.  */
+      start = max (start, field_start) - field_start - 1;
+      end = min (end, field_end) - field_start - 1;
+      if (end < 0 || start < 0)
+       end = start = -1;
     }
   else
     start = -1, end = -1;
@@ -6288,24 +6298,27 @@ android_update_selection (struct frame *f, struct 
window *w)
   /* Figure out where the point and mark are.  If the mark is not
      active, then point is set to equal mark.  */
   b = XBUFFER (w->contents);
-  point = min (w->ephemeral_last_point,
+  point = min (min (max (w->ephemeral_last_point,
+                        field_start),
+                   field_end) - field_start,
               TYPE_MAXIMUM (jint));
   mark = ((!NILP (BVAR (b, mark_active))
           && w->last_mark != -1)
-         ? min (w->last_mark, TYPE_MAXIMUM (jint))
+         ? min (min (max (w->last_mark, field_start),
+                     field_end) - field_start,
+                TYPE_MAXIMUM (jint))
          : point);
 
-  /* Send the update.  Android doesn't employ a concept of ``point''
-     and ``mark''; instead, it only has a selection, where the start
-     of the selection is less than or equal to the end, and the region
-     is ``active'' when those two values differ.  Also, convert the
-     indices from 1-based Emacs indices to 0-based Android ones.  */
-  android_update_ic (FRAME_ANDROID_WINDOW (f), min (point, mark) - 1,
-                    max (point, mark) - 1, start, end);
+  /* Send the update.  Android doesn't employ a concept of "point" and
+     "mark"; instead, it only has a selection, where the start of the
+     selection is less than or equal to the end, and the region is
+     "active" when those two values differ.  The indices will have been
+     converted from 1-based Emacs indices to 0-based Android ones.  */
+  android_update_ic (FRAME_ANDROID_WINDOW (f), min (point, mark),
+                    max (point, mark), start, end);
 
   /* Update the extracted text as well, if the input method has asked
-     for updates.  1 is
-     InputConnection.GET_EXTRACTED_TEXT_MONITOR.  */
+     for updates.  1 is InputConnection.GET_EXTRACTED_TEXT_MONITOR.  */
 
   if (FRAME_ANDROID_OUTPUT (f)->extracted_text_flags & 1)
     {
diff --git a/src/editfns.c b/src/editfns.c
index 4ccf765bd4b..fbfaaf66644 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -370,7 +370,7 @@ at POSITION.  */)
    Either BEG or END may be 0, in which case the corresponding value
    is not stored.  */
 
-static void
+void
 find_field (Lisp_Object pos, Lisp_Object merge_at_boundary,
            Lisp_Object beg_limit,
            ptrdiff_t *beg, Lisp_Object end_limit, ptrdiff_t *end)
diff --git a/src/frame.c b/src/frame.c
index ff99b0353af..a671dbaa31d 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1001,6 +1001,7 @@ make_frame (bool mini_p)
   f->conversion.compose_region_start = Qnil;
   f->conversion.compose_region_end = Qnil;
   f->conversion.compose_region_overlay = Qnil;
+  f->conversion.field = Qnil;
   f->conversion.batch_edit_count = 0;
   f->conversion.batch_edit_flags = 0;
   f->conversion.actions = NULL;
diff --git a/src/frame.h b/src/frame.h
index e03362361a7..63bcce259af 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -126,6 +126,10 @@ struct text_conversion_state
   /* Overlay representing the composing region.  */
   Lisp_Object compose_region_overlay;
 
+  /* Cons of (START END . WINDOW) holding the field to which text
+     conversion should be confined, or nil if no such field exists.  */
+  Lisp_Object field;
+
   /* The number of ongoing ``batch edits'' that are causing point
      reporting to be delayed.  */
   int batch_edit_count;
diff --git a/src/lisp.h b/src/lisp.h
index 526248dd2ba..4487948b007 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4933,6 +4933,8 @@ extern void unmark_main_thread (void);
 
 /* Defined in editfns.c.  */
 extern void insert1 (Lisp_Object);
+extern void find_field (Lisp_Object, Lisp_Object, Lisp_Object,
+                       ptrdiff_t *, Lisp_Object, ptrdiff_t *);
 extern void save_excursion_save (union specbinding *);
 extern void save_excursion_restore (Lisp_Object, Lisp_Object);
 extern Lisp_Object save_restriction_save (void);
@@ -5496,6 +5498,7 @@ extern char *emacs_root_dir (void);
 #ifdef HAVE_TEXT_CONVERSION
 /* Defined in textconv.c.  */
 extern void reset_frame_state (struct frame *);
+extern void reset_frame_conversion (struct frame *);
 extern void report_selected_window_change (struct frame *);
 extern void report_point_change (struct frame *, struct window *,
                                 struct buffer *);
diff --git a/src/minibuf.c b/src/minibuf.c
index 51816133fb2..1029fcdb1ba 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -1367,6 +1367,20 @@ and some related functions, which use zero-indexing for 
POSITION.  */)
   if (NILP (histpos))
     XSETFASTINT (histpos, 0);
 
+#ifdef HAVE_TEXT_CONVERSION
+  /* If overriding-text-conversion-style is set, assume that it was
+     changed prior to this call and force text conversion to be reset,
+     since redisplay might conclude that the value was retained
+     unmodified from a previous call to Fread_from_minibuffer as the
+     selected window will not have changed.  */
+  if (!EQ (Voverriding_text_conversion_style, Qlambda)
+      /* Separate minibuffer frames are not material here, since they
+         will already be selected if the situation that this is meant to
+         prevent is possible.  */
+      && FRAME_WINDOW_P (SELECTED_FRAME ()))
+    reset_frame_conversion (SELECTED_FRAME ());
+#endif /* HAVE_TEXT_CONVERSION */
+
   val = read_minibuf (keymap, initial_contents, prompt,
                      !NILP (read),
                      histvar, histpos, default_value,
diff --git a/src/textconv.c b/src/textconv.c
index 9625c884e16..8850f3cc6be 100644
--- a/src/textconv.c
+++ b/src/textconv.c
@@ -195,6 +195,15 @@ textconv_query (struct frame *f, struct 
textconv_callback_struct *query,
                  : f->selected_window), Qt);
   w = XWINDOW (selected_window);
 
+  /* Narrow to the field, if any.  */
+  if (!NILP (f->conversion.field))
+    {
+      record_unwind_protect (save_restriction_restore,
+                            save_restriction_save ());
+      Fnarrow_to_region (XCAR (f->conversion.field),
+                        XCAR (XCDR (f->conversion.field)));
+    }
+
   /* Now find the appropriate text bounds for QUERY.  First, move
      point QUERY->position steps forward or backwards.  */
 
@@ -488,6 +497,17 @@ record_buffer_change (ptrdiff_t beg, ptrdiff_t end,
             Vtext_conversion_edits);
 }
 
+/* Reset text conversion state of frame F, and resume text conversion.
+   Delete any overlays or markers inside.  */
+
+void
+reset_frame_conversion (struct frame *f)
+{
+  reset_frame_state (f);
+  if (text_interface && FRAME_WINDOW_P (f) && FRAME_VISIBLE_P (f))
+    text_interface->reset (f);
+}
+
 /* Reset text conversion state of frame F.  Delete any overlays or
    markers inside.  */
 
@@ -530,6 +550,15 @@ reset_frame_state (struct frame *f)
   /* Clear batch edit state.  */
   f->conversion.batch_edit_count = 0;
   f->conversion.batch_edit_flags = 0;
+
+  /* Clear active field.  */
+  if (!NILP (f->conversion.field))
+    {
+      Fset_marker (XCAR (f->conversion.field), Qnil, Qnil);
+      Fset_marker (XCAR (XCDR (f->conversion.field)), Qnil,
+                  Qnil);
+    }
+  f->conversion.field = Qnil;
 }
 
 /* Return whether or not there are pending edits from an input method
@@ -1012,6 +1041,15 @@ really_delete_surrounding_text (struct frame *f, 
ptrdiff_t left,
      redisplay.  */
   select_window (f->old_selected_window, Qt);
 
+  /* Narrow to the field, if any.  */
+  if (!NILP (f->conversion.field))
+    {
+      record_unwind_protect (save_restriction_restore,
+                            save_restriction_save ());
+      Fnarrow_to_region (XCAR (f->conversion.field),
+                        XCAR (XCDR (f->conversion.field)));
+    }
+
   /* Figure out where to start deleting from.  */
 
   a = get_mark ();
@@ -1078,6 +1116,115 @@ really_delete_surrounding_text (struct frame *f, 
ptrdiff_t left,
   unbind_to (count, Qnil);
 }
 
+/* Save the confines of the field surrounding point in w into F's text
+   conversion state.  If NOTIFY_COMPOSE, notify the input method of
+   changes to the composition region if they arise in this process.  */
+
+static void
+locate_and_save_position_in_field (struct frame *f, struct window *w,
+                                  bool notify_compose)
+{
+  Lisp_Object pos, window, c1, c2;
+  specpdl_ref count;
+  ptrdiff_t beg, end, cstart, cend, newstart, newend;
+
+  /* Set the current buffer to W's.  */
+  count = SPECPDL_INDEX ();
+  record_unwind_protect (restore_selected_window, selected_window);
+  XSETWINDOW (window, w);
+  select_window (window, Qt);
+
+  /* Search for a field around the current editing position; this should
+     also serve to confine text conversion to the visible region.  */
+  XSETFASTINT (pos, min (max (w->ephemeral_last_point, BEGV), ZV));
+  find_field (pos, Qnil, Qnil, &beg, Qnil, &end);
+
+  /* If beg is 1 and end is ZV, disable the active field entirely.  */
+  if (beg == 1 && end == ZV)
+    {
+      f->conversion.field = Qnil;
+      goto exit;
+    }
+
+  /* Don't cons if a pair already exists.  */
+  if (!NILP (f->conversion.field))
+    {
+      c1 = f->conversion.field;
+      c2 = XCDR (c1);
+      Fset_marker (XCAR (c1), make_fixed_natnum (beg), Qnil);
+      Fset_marker (XCAR (c2), make_fixed_natnum (end), Qnil);
+      XSETCDR (c2, window);
+    }
+  else
+    {
+      c1 = build_marker (current_buffer, beg, CHAR_TO_BYTE (beg));
+      c2 = build_marker (current_buffer, end, CHAR_TO_BYTE (end));
+      Fset_marker_insertion_type (c2, Qt);
+      f->conversion.field = Fcons (c1, Fcons (c2, window));
+    }
+
+  /* If the composition region is active and oversteps the active field,
+     restrict it to the same.  */
+
+  if (!NILP (f->conversion.compose_region_start))
+    {
+      cstart = marker_position (f->conversion.compose_region_start);
+      cend   = marker_position (f->conversion.compose_region_end);
+
+      if (cend < beg || cstart > end)
+       {
+         /* Remove the composition region in whole.  */
+         /* Make the composition region markers point elsewhere.  */
+
+         if (!NILP (f->conversion.compose_region_start))
+           {
+             Fset_marker (f->conversion.compose_region_start, Qnil, Qnil);
+             Fset_marker (f->conversion.compose_region_end, Qnil, Qnil);
+             f->conversion.compose_region_start = Qnil;
+             f->conversion.compose_region_end = Qnil;
+           }
+
+         /* Delete the composition region overlay.  */
+
+         if (!NILP (f->conversion.compose_region_overlay))
+           Fdelete_overlay (f->conversion.compose_region_overlay);
+
+         TEXTCONV_DEBUG ("removing composing region outside active field");
+       }
+      else
+       {
+         newstart = max (beg, min (cstart, end));
+         newend   = max (beg, min (cend, end));
+
+         if (newstart != cstart || newend != cend)
+           {
+             TEXTCONV_DEBUG ("confined composing region to %td, %td",
+                             newstart, newend);
+             Fset_marker (f->conversion.compose_region_end,
+                          make_fixed_natnum (newstart), Qnil);
+             Fset_marker (f->conversion.compose_region_end,
+                          make_fixed_natnum (newend), Qnil);
+           }
+         else
+           notify_compose = false;
+       }
+    }
+  else
+    notify_compose = false;
+
+  if (notify_compose
+      && text_interface->compose_region_changed)
+    {
+      if (f->conversion.batch_edit_count > 0)
+       f->conversion.batch_edit_flags |= PENDING_COMPOSE_CHANGE;
+      else
+       text_interface->compose_region_changed (f);
+    }
+
+ exit:
+  unbind_to (count, Qnil);
+}
+
 /* Update the interface with frame F's new point and mark.  If a batch
    edit is in progress, schedule the update for when it finishes
    instead.  */
@@ -1085,6 +1232,8 @@ really_delete_surrounding_text (struct frame *f, 
ptrdiff_t left,
 static void
 really_request_point_update (struct frame *f)
 {
+  struct window *w;
+
   /* If F's old selected window is no longer live, fail.  */
 
   if (!WINDOW_LIVE_P (f->old_selected_window))
@@ -1093,9 +1242,11 @@ really_request_point_update (struct frame *f)
   if (f->conversion.batch_edit_count > 0)
     f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
   else if (text_interface && text_interface->point_changed)
-    text_interface->point_changed (f,
-                                  XWINDOW (f->old_selected_window),
-                                  current_buffer);
+    {
+      w = XWINDOW (f->old_selected_window);
+      locate_and_save_position_in_field (f, w, false);
+      text_interface->point_changed (f, w, current_buffer);
+    }
 }
 
 /* Set point in frame F's selected window to POSITION.  If MARK is not
@@ -1130,9 +1281,11 @@ really_set_point_and_mark (struct frame *f, ptrdiff_t 
point,
       if (f->conversion.batch_edit_count > 0)
        f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
       else if (text_interface && text_interface->point_changed)
-       text_interface->point_changed (f,
-                                      XWINDOW (f->old_selected_window),
-                                      current_buffer);
+       {
+         w = XWINDOW (f->old_selected_window);
+         locate_and_save_position_in_field (f, w, false);
+         text_interface->point_changed (f, w, current_buffer);
+       }
     }
   else
     /* Set the point.  */
@@ -1331,7 +1484,10 @@ complete_edit_check (void *ptr)
          if (f->conversion.batch_edit_count > 0)
            f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
          else
-           text_interface->point_changed (f, context->w, NULL);
+           {
+             locate_and_save_position_in_field (f, context->w, false);
+             text_interface->point_changed (f, context->w, NULL);
+           }
        }
     }
 }
@@ -1400,7 +1556,10 @@ handle_pending_conversion_events_1 (struct frame *f,
        break;
 
       if (f->conversion.batch_edit_flags & PENDING_POINT_CHANGE)
-       text_interface->point_changed (f, w, buffer);
+       {
+         locate_and_save_position_in_field (f, w, false);
+         text_interface->point_changed (f, w, buffer);
+       }
 
       if (f->conversion.batch_edit_flags & PENDING_COMPOSE_CHANGE)
        text_interface->compose_region_changed (f);
@@ -1529,7 +1688,10 @@ handle_pending_conversion_events (void)
                  if (f->conversion.batch_edit_count > 0)
                    f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
                  else
-                   text_interface->point_changed (f, NULL, NULL);
+                   {
+                     locate_and_save_position_in_field (f, w, false);
+                     text_interface->point_changed (f, NULL, NULL);
+                   }
                }
 
              last_point = w->ephemeral_last_point;
@@ -1564,6 +1726,39 @@ handle_pending_conversion_events (void)
   unbind_to (count, Qnil);
 }
 
+/* Return the confines of the field to which editing operations on frame
+   F should be constrained in *BEG and *END.  Should no field be active,
+   set *END to MOST_POSITIVE_FIXNUM.  */
+
+void
+get_conversion_field (struct frame *f, ptrdiff_t *beg, ptrdiff_t *end)
+{
+  Lisp_Object c1, c2;
+  struct window *w;
+
+  if (!NILP (f->conversion.field))
+    {
+      c1 = f->conversion.field;
+      c2 = XCDR (c1);
+
+      if (!EQ (XCDR (c2), f->old_selected_window))
+       {
+         /* Update this outdated field location.  */
+         w = XWINDOW (f->old_selected_window);
+         locate_and_save_position_in_field (f, w, true);
+         get_conversion_field (f, beg, end);
+         return;
+       }
+
+      *beg = marker_position (XCAR (c1));
+      *end = marker_position (XCAR (c2));
+      return;
+    }
+
+  *beg = 1;
+  *end = MOST_POSITIVE_FIXNUM;
+}
+
 /* Start a ``batch edit'' in frame F.  During a batch edit,
    point_changed will not be called until the batch edit ends.
 
@@ -1694,7 +1889,8 @@ set_composing_text (struct frame *f, Lisp_Object object,
 }
 
 /* Make the region between START and END the currently active
-   ``composing region'' on frame F.
+   ``composing region'' on frame F.  Which of START and END is the
+   larger value is not significant.
 
    The ``composing region'' is a region of text in the buffer that is
    about to undergo editing by the input method.  */
@@ -1704,14 +1900,22 @@ set_composing_region (struct frame *f, ptrdiff_t start,
                      ptrdiff_t end, unsigned long counter)
 {
   struct text_conversion_action *action, **last;
+  ptrdiff_t field_start, field_end, temp;
+
+  if (start > end)
+    {
+      temp  = end;
+      end   = start;
+      start = temp;
+    }
 
-  start = min (start, MOST_POSITIVE_FIXNUM);
-  end = min (end, MOST_POSITIVE_FIXNUM);
+  get_conversion_field (f, &field_start, &field_end);
+  start = min (start + field_start - 1, MOST_POSITIVE_FIXNUM);
+  end = max (start, min (end + field_start - 1, field_end));
 
   action = xmalloc (sizeof *action);
   action->operation = TEXTCONV_SET_COMPOSING_REGION;
-  action->data = Fcons (make_fixnum (start),
-                       make_fixnum (end));
+  action->data = Fcons (make_fixnum (start), make_fixnum (end));
   action->next = NULL;
   action->counter = counter;
   for (last = &f->conversion.actions; *last; last = &(*last)->next)
@@ -1730,8 +1934,13 @@ textconv_set_point_and_mark (struct frame *f, ptrdiff_t 
point,
                             ptrdiff_t mark, unsigned long counter)
 {
   struct text_conversion_action *action, **last;
+  ptrdiff_t field_start, field_end;
 
-  point = min (point, MOST_POSITIVE_FIXNUM);
+  get_conversion_field (f, &field_start, &field_end);
+  point = min (max (point + field_start - 1, field_start),
+              field_end);
+  mark = min (max (mark + field_start - 1, field_start),
+             field_end);
 
   action = xmalloc (sizeof *action);
   action->operation = TEXTCONV_SET_POINT_AND_MARK;
@@ -1809,10 +2018,11 @@ textconv_barrier (struct frame *f, unsigned long 
counter)
   input_pending = true;
 }
 
-/* Remove the composing region.  Replace the text between START and
-   END within F's selected window with TEXT; deactivate the mark if it
-   is active.  Subsequently, set point to POSITION relative to TEXT,
-   much as `commit_text' would.  */
+/* Remove the composing region.  Replace the text between START and END
+   (whose order, as in `set_composing_region', is not significant)
+   within F's selected window with TEXT; deactivate the mark if it is
+   active.  Subsequently, set point to POSITION relative to TEXT, as
+   `commit_text' would.  */
 
 void
 replace_text (struct frame *f, ptrdiff_t start, ptrdiff_t end,
@@ -1820,6 +2030,18 @@ replace_text (struct frame *f, ptrdiff_t start, 
ptrdiff_t end,
              unsigned long counter)
 {
   struct text_conversion_action *action, **last;
+  ptrdiff_t field_start, field_end, temp;
+
+  if (start > end)
+    {
+      temp  = end;
+      end   = start;
+      start = temp;
+    }
+
+  get_conversion_field (f, &field_start, &field_end);
+  start = min (start + field_start - 1, MOST_POSITIVE_FIXNUM);
+  end = max (start, min (end + field_start - 1, field_end));
 
   action = xmalloc (sizeof *action);
   action->operation = TEXTCONV_REPLACE_TEXT;
@@ -1858,6 +2080,7 @@ get_extracted_text (struct frame *f, ptrdiff_t n,
   specpdl_ref count;
   ptrdiff_t start, end, start_byte, end_byte, mark;
   char *buffer;
+  ptrdiff_t field_start, field_end;
 
   if (!WINDOW_LIVE_P (f->old_selected_window))
     return NULL;
@@ -1907,6 +2130,15 @@ get_extracted_text (struct frame *f, ptrdiff_t n,
        goto finish;
     }
 
+  /* Narrow to the field, if any.  */
+  if (!NILP (f->conversion.field))
+    {
+      record_unwind_protect (save_restriction_restore,
+                            save_restriction_save ());
+      Fnarrow_to_region (XCAR (f->conversion.field),
+                        XCAR (XCDR (f->conversion.field)));
+    }
+
   start = max (start, BEGV);
   end = min (end, ZV);
 
@@ -1935,7 +2167,8 @@ get_extracted_text (struct frame *f, ptrdiff_t n,
     }
 
   /* Return the offsets.  */
-  *start_return = start;
+  get_conversion_field (f, &field_start, &field_end);
+  *start_return = max (1, start - field_start + 1);
   *start_offset = min (mark - start, PT - start);
   *end_offset = max (mark - start, PT - start);
   *length = end - start;
@@ -1968,6 +2201,7 @@ get_surrounding_text (struct frame *f, ptrdiff_t left,
 {
   specpdl_ref count;
   ptrdiff_t start, end, start_byte, end_byte, mark, temp;
+  ptrdiff_t field_start, field_end;
   char *buffer;
 
   if (!WINDOW_LIVE_P (f->old_selected_window))
@@ -2012,6 +2246,15 @@ get_surrounding_text (struct frame *f, ptrdiff_t left,
       || ckd_add (&end, end, right))
     goto finish;
 
+  /* Narrow to the field, if any.  */
+  if (!NILP (f->conversion.field))
+    {
+      record_unwind_protect (save_restriction_restore,
+                            save_restriction_save ());
+      Fnarrow_to_region (XCAR (f->conversion.field),
+                        XCAR (XCDR (f->conversion.field)));
+    }
+
   start = max (start, BEGV);
   end = min (end, ZV);
 
@@ -2038,7 +2281,8 @@ get_surrounding_text (struct frame *f, ptrdiff_t left,
   /* Return the offsets.  Unlike `get_extracted_text', this need not
      sort mark and point.  */
 
-  *offset = start;
+  get_conversion_field (f, &field_start, &field_end);
+  *offset = max (1, start - field_start + 1);
   *start_return = mark - start;
   *end_return = PT - start;
   *length = end - start;
@@ -2110,7 +2354,10 @@ report_point_change (struct frame *f, struct window 
*window,
   if (f->conversion.batch_edit_count > 0)
     f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
   else
-    text_interface->point_changed (f, window, buffer);
+    {
+      locate_and_save_position_in_field (f, window, false);
+      text_interface->point_changed (f, window, buffer);
+    }
 }
 
 /* Temporarily disable text conversion.  Must be paired with a
@@ -2348,8 +2595,9 @@ as indenting or automatically filling text, should not 
take place.
 Otherwise, it is either a string containing text that was inserted,
 text deleted before point, or nil if text was deleted after point.
 
-The list contents are ordered in the reverse order of editing, i.e.
-the latest edit first, so you must iterate through the list in reverse.  */);
+The list contents are arranged in the reverse of the order of editing,
+i.e. latest edit first, so you must iterate through the list in
+reverse.  */);
   Vtext_conversion_edits = Qnil;
 
   DEFVAR_LISP ("overriding-text-conversion-style",
diff --git a/src/textconv.h b/src/textconv.h
index 61f13ebcb43..e87ff5cd1f8 100644
--- a/src/textconv.h
+++ b/src/textconv.h
@@ -155,6 +155,7 @@ extern char *get_surrounding_text (struct frame *, 
ptrdiff_t,
 extern bool conversion_disabled_p (void);
 extern void check_postponed_buffers (void);
 
+extern void get_conversion_field (struct frame *, ptrdiff_t *, ptrdiff_t *);
 extern void register_textconv_interface (struct textconv_interface *);
 
 #endif /* _TEXTCONV_H_ */



reply via email to

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