summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2024-04-21 21:51:09 +0800
committerPo Lu <luangruo@yahoo.com>2024-04-29 12:34:39 +0800
commit430088c9ccec5fe9be57d267f45acdc87aa3b28e (patch)
treea953f845c4176e4a18a542c1e321f80ad34ab4af /src
parentee2e0031d8cc32bb7837ea97ce07ef3b25463223 (diff)
downloademacs-430088c9ccec5fe9be57d267f45acdc87aa3b28e.tar.gz
emacs-430088c9ccec5fe9be57d267f45acdc87aa3b28e.tar.bz2
emacs-430088c9ccec5fe9be57d267f45acdc87aa3b28e.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c1
-rw-r--r--src/androidterm.c39
-rw-r--r--src/editfns.c2
-rw-r--r--src/frame.c1
-rw-r--r--src/frame.h4
-rw-r--r--src/lisp.h3
-rw-r--r--src/minibuf.c14
-rw-r--r--src/textconv.c296
-rw-r--r--src/textconv.h1
9 files changed, 323 insertions, 38 deletions
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_ */