mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
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.
This commit is contained in:
parent
ee2e0031d8
commit
430088c9cc
10 changed files with 324 additions and 38 deletions
|
|
@ -5400,6 +5400,7 @@ if that value is non-nil."
|
||||||
(setq-local custom--invocation-options nil
|
(setq-local custom--invocation-options nil
|
||||||
custom--hidden-state 'hidden)
|
custom--hidden-state 'hidden)
|
||||||
(setq-local revert-buffer-function #'custom--revert-buffer)
|
(setq-local revert-buffer-function #'custom--revert-buffer)
|
||||||
|
(setq-local text-conversion-style 'action)
|
||||||
(make-local-variable 'custom-options)
|
(make-local-variable 'custom-options)
|
||||||
(make-local-variable 'custom-local-buffer)
|
(make-local-variable 'custom-local-buffer)
|
||||||
(custom--initialize-widget-variables)
|
(custom--initialize-widget-variables)
|
||||||
|
|
|
||||||
|
|
@ -7050,6 +7050,7 @@ mark_frame (struct Lisp_Vector *ptr)
|
||||||
mark_object (f->conversion.compose_region_start);
|
mark_object (f->conversion.compose_region_start);
|
||||||
mark_object (f->conversion.compose_region_end);
|
mark_object (f->conversion.compose_region_end);
|
||||||
mark_object (f->conversion.compose_region_overlay);
|
mark_object (f->conversion.compose_region_overlay);
|
||||||
|
mark_object (f->conversion.field);
|
||||||
|
|
||||||
for (tem = f->conversion.actions; tem; tem = tem->next)
|
for (tem = f->conversion.actions; tem; tem = tem->next)
|
||||||
mark_object (tem->data);
|
mark_object (tem->data);
|
||||||
|
|
|
||||||
|
|
@ -6265,14 +6265,24 @@ android_update_selection (struct frame *f, struct window *w)
|
||||||
jobject extracted;
|
jobject extracted;
|
||||||
jstring string;
|
jstring string;
|
||||||
bool mark_active;
|
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))
|
if (MARKERP (f->conversion.compose_region_start))
|
||||||
{
|
{
|
||||||
eassert (MARKERP (f->conversion.compose_region_end));
|
eassert (MARKERP (f->conversion.compose_region_end));
|
||||||
|
|
||||||
/* Indexing in android starts from 0 instead of 1. */
|
/* Indexing in android starts from 0 instead of 1. */
|
||||||
start = marker_position (f->conversion.compose_region_start) - 1;
|
start = marker_position (f->conversion.compose_region_start);
|
||||||
end = marker_position (f->conversion.compose_region_end) - 1;
|
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
|
else
|
||||||
start = -1, end = -1;
|
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
|
/* Figure out where the point and mark are. If the mark is not
|
||||||
active, then point is set to equal mark. */
|
active, then point is set to equal mark. */
|
||||||
b = XBUFFER (w->contents);
|
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));
|
TYPE_MAXIMUM (jint));
|
||||||
mark = ((!NILP (BVAR (b, mark_active))
|
mark = ((!NILP (BVAR (b, mark_active))
|
||||||
&& w->last_mark != -1)
|
&& 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);
|
: point);
|
||||||
|
|
||||||
/* Send the update. Android doesn't employ a concept of ``point''
|
/* Send the update. Android doesn't employ a concept of "point" and
|
||||||
and ``mark''; instead, it only has a selection, where the start
|
"mark"; instead, it only has a selection, where the start of the
|
||||||
of the selection is less than or equal to the end, and the region
|
selection is less than or equal to the end, and the region is
|
||||||
is ``active'' when those two values differ. Also, convert the
|
"active" when those two values differ. The indices will have been
|
||||||
indices from 1-based Emacs indices to 0-based Android ones. */
|
converted from 1-based Emacs indices to 0-based Android ones. */
|
||||||
android_update_ic (FRAME_ANDROID_WINDOW (f), min (point, mark) - 1,
|
android_update_ic (FRAME_ANDROID_WINDOW (f), min (point, mark),
|
||||||
max (point, mark) - 1, start, end);
|
max (point, mark), start, end);
|
||||||
|
|
||||||
/* Update the extracted text as well, if the input method has asked
|
/* Update the extracted text as well, if the input method has asked
|
||||||
for updates. 1 is
|
for updates. 1 is InputConnection.GET_EXTRACTED_TEXT_MONITOR. */
|
||||||
InputConnection.GET_EXTRACTED_TEXT_MONITOR. */
|
|
||||||
|
|
||||||
if (FRAME_ANDROID_OUTPUT (f)->extracted_text_flags & 1)
|
if (FRAME_ANDROID_OUTPUT (f)->extracted_text_flags & 1)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -370,7 +370,7 @@ at POSITION. */)
|
||||||
Either BEG or END may be 0, in which case the corresponding value
|
Either BEG or END may be 0, in which case the corresponding value
|
||||||
is not stored. */
|
is not stored. */
|
||||||
|
|
||||||
static void
|
void
|
||||||
find_field (Lisp_Object pos, Lisp_Object merge_at_boundary,
|
find_field (Lisp_Object pos, Lisp_Object merge_at_boundary,
|
||||||
Lisp_Object beg_limit,
|
Lisp_Object beg_limit,
|
||||||
ptrdiff_t *beg, Lisp_Object end_limit, ptrdiff_t *end)
|
ptrdiff_t *beg, Lisp_Object end_limit, ptrdiff_t *end)
|
||||||
|
|
|
||||||
|
|
@ -1001,6 +1001,7 @@ make_frame (bool mini_p)
|
||||||
f->conversion.compose_region_start = Qnil;
|
f->conversion.compose_region_start = Qnil;
|
||||||
f->conversion.compose_region_end = Qnil;
|
f->conversion.compose_region_end = Qnil;
|
||||||
f->conversion.compose_region_overlay = Qnil;
|
f->conversion.compose_region_overlay = Qnil;
|
||||||
|
f->conversion.field = Qnil;
|
||||||
f->conversion.batch_edit_count = 0;
|
f->conversion.batch_edit_count = 0;
|
||||||
f->conversion.batch_edit_flags = 0;
|
f->conversion.batch_edit_flags = 0;
|
||||||
f->conversion.actions = NULL;
|
f->conversion.actions = NULL;
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,10 @@ struct text_conversion_state
|
||||||
/* Overlay representing the composing region. */
|
/* Overlay representing the composing region. */
|
||||||
Lisp_Object compose_region_overlay;
|
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
|
/* The number of ongoing ``batch edits'' that are causing point
|
||||||
reporting to be delayed. */
|
reporting to be delayed. */
|
||||||
int batch_edit_count;
|
int batch_edit_count;
|
||||||
|
|
|
||||||
|
|
@ -4933,6 +4933,8 @@ extern void unmark_main_thread (void);
|
||||||
|
|
||||||
/* Defined in editfns.c. */
|
/* Defined in editfns.c. */
|
||||||
extern void insert1 (Lisp_Object);
|
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_save (union specbinding *);
|
||||||
extern void save_excursion_restore (Lisp_Object, Lisp_Object);
|
extern void save_excursion_restore (Lisp_Object, Lisp_Object);
|
||||||
extern Lisp_Object save_restriction_save (void);
|
extern Lisp_Object save_restriction_save (void);
|
||||||
|
|
@ -5496,6 +5498,7 @@ extern char *emacs_root_dir (void);
|
||||||
#ifdef HAVE_TEXT_CONVERSION
|
#ifdef HAVE_TEXT_CONVERSION
|
||||||
/* Defined in textconv.c. */
|
/* Defined in textconv.c. */
|
||||||
extern void reset_frame_state (struct frame *);
|
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_selected_window_change (struct frame *);
|
||||||
extern void report_point_change (struct frame *, struct window *,
|
extern void report_point_change (struct frame *, struct window *,
|
||||||
struct buffer *);
|
struct buffer *);
|
||||||
|
|
|
||||||
|
|
@ -1367,6 +1367,20 @@ and some related functions, which use zero-indexing for POSITION. */)
|
||||||
if (NILP (histpos))
|
if (NILP (histpos))
|
||||||
XSETFASTINT (histpos, 0);
|
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,
|
val = read_minibuf (keymap, initial_contents, prompt,
|
||||||
!NILP (read),
|
!NILP (read),
|
||||||
histvar, histpos, default_value,
|
histvar, histpos, default_value,
|
||||||
|
|
|
||||||
296
src/textconv.c
296
src/textconv.c
|
|
@ -195,6 +195,15 @@ textconv_query (struct frame *f, struct textconv_callback_struct *query,
|
||||||
: f->selected_window), Qt);
|
: f->selected_window), Qt);
|
||||||
w = XWINDOW (selected_window);
|
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
|
/* Now find the appropriate text bounds for QUERY. First, move
|
||||||
point QUERY->position steps forward or backwards. */
|
point QUERY->position steps forward or backwards. */
|
||||||
|
|
||||||
|
|
@ -488,6 +497,17 @@ record_buffer_change (ptrdiff_t beg, ptrdiff_t end,
|
||||||
Vtext_conversion_edits);
|
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
|
/* Reset text conversion state of frame F. Delete any overlays or
|
||||||
markers inside. */
|
markers inside. */
|
||||||
|
|
||||||
|
|
@ -530,6 +550,15 @@ reset_frame_state (struct frame *f)
|
||||||
/* Clear batch edit state. */
|
/* Clear batch edit state. */
|
||||||
f->conversion.batch_edit_count = 0;
|
f->conversion.batch_edit_count = 0;
|
||||||
f->conversion.batch_edit_flags = 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
|
/* 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. */
|
redisplay. */
|
||||||
select_window (f->old_selected_window, Qt);
|
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. */
|
/* Figure out where to start deleting from. */
|
||||||
|
|
||||||
a = get_mark ();
|
a = get_mark ();
|
||||||
|
|
@ -1078,6 +1116,115 @@ really_delete_surrounding_text (struct frame *f, ptrdiff_t left,
|
||||||
unbind_to (count, Qnil);
|
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
|
/* 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
|
edit is in progress, schedule the update for when it finishes
|
||||||
instead. */
|
instead. */
|
||||||
|
|
@ -1085,6 +1232,8 @@ really_delete_surrounding_text (struct frame *f, ptrdiff_t left,
|
||||||
static void
|
static void
|
||||||
really_request_point_update (struct frame *f)
|
really_request_point_update (struct frame *f)
|
||||||
{
|
{
|
||||||
|
struct window *w;
|
||||||
|
|
||||||
/* If F's old selected window is no longer live, fail. */
|
/* If F's old selected window is no longer live, fail. */
|
||||||
|
|
||||||
if (!WINDOW_LIVE_P (f->old_selected_window))
|
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)
|
if (f->conversion.batch_edit_count > 0)
|
||||||
f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
|
f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
|
||||||
else if (text_interface && text_interface->point_changed)
|
else if (text_interface && text_interface->point_changed)
|
||||||
text_interface->point_changed (f,
|
{
|
||||||
XWINDOW (f->old_selected_window),
|
w = XWINDOW (f->old_selected_window);
|
||||||
current_buffer);
|
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
|
/* 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)
|
if (f->conversion.batch_edit_count > 0)
|
||||||
f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
|
f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
|
||||||
else if (text_interface && text_interface->point_changed)
|
else if (text_interface && text_interface->point_changed)
|
||||||
text_interface->point_changed (f,
|
{
|
||||||
XWINDOW (f->old_selected_window),
|
w = XWINDOW (f->old_selected_window);
|
||||||
current_buffer);
|
locate_and_save_position_in_field (f, w, false);
|
||||||
|
text_interface->point_changed (f, w, current_buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Set the point. */
|
/* Set the point. */
|
||||||
|
|
@ -1331,7 +1484,10 @@ complete_edit_check (void *ptr)
|
||||||
if (f->conversion.batch_edit_count > 0)
|
if (f->conversion.batch_edit_count > 0)
|
||||||
f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
|
f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
|
||||||
else
|
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;
|
break;
|
||||||
|
|
||||||
if (f->conversion.batch_edit_flags & PENDING_POINT_CHANGE)
|
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)
|
if (f->conversion.batch_edit_flags & PENDING_COMPOSE_CHANGE)
|
||||||
text_interface->compose_region_changed (f);
|
text_interface->compose_region_changed (f);
|
||||||
|
|
@ -1529,7 +1688,10 @@ handle_pending_conversion_events (void)
|
||||||
if (f->conversion.batch_edit_count > 0)
|
if (f->conversion.batch_edit_count > 0)
|
||||||
f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
|
f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
|
||||||
else
|
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;
|
last_point = w->ephemeral_last_point;
|
||||||
|
|
@ -1564,6 +1726,39 @@ handle_pending_conversion_events (void)
|
||||||
unbind_to (count, Qnil);
|
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,
|
/* Start a ``batch edit'' in frame F. During a batch edit,
|
||||||
point_changed will not be called until the batch edit ends.
|
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
|
/* 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
|
The ``composing region'' is a region of text in the buffer that is
|
||||||
about to undergo editing by the input method. */
|
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)
|
ptrdiff_t end, unsigned long counter)
|
||||||
{
|
{
|
||||||
struct text_conversion_action *action, **last;
|
struct text_conversion_action *action, **last;
|
||||||
|
ptrdiff_t field_start, field_end, temp;
|
||||||
|
|
||||||
start = min (start, MOST_POSITIVE_FIXNUM);
|
if (start > end)
|
||||||
end = min (end, MOST_POSITIVE_FIXNUM);
|
{
|
||||||
|
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 = xmalloc (sizeof *action);
|
||||||
action->operation = TEXTCONV_SET_COMPOSING_REGION;
|
action->operation = TEXTCONV_SET_COMPOSING_REGION;
|
||||||
action->data = Fcons (make_fixnum (start),
|
action->data = Fcons (make_fixnum (start), make_fixnum (end));
|
||||||
make_fixnum (end));
|
|
||||||
action->next = NULL;
|
action->next = NULL;
|
||||||
action->counter = counter;
|
action->counter = counter;
|
||||||
for (last = &f->conversion.actions; *last; last = &(*last)->next)
|
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)
|
ptrdiff_t mark, unsigned long counter)
|
||||||
{
|
{
|
||||||
struct text_conversion_action *action, **last;
|
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 = xmalloc (sizeof *action);
|
||||||
action->operation = TEXTCONV_SET_POINT_AND_MARK;
|
action->operation = TEXTCONV_SET_POINT_AND_MARK;
|
||||||
|
|
@ -1809,10 +2018,11 @@ textconv_barrier (struct frame *f, unsigned long counter)
|
||||||
input_pending = true;
|
input_pending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove the composing region. Replace the text between START and
|
/* Remove the composing region. Replace the text between START and END
|
||||||
END within F's selected window with TEXT; deactivate the mark if it
|
(whose order, as in `set_composing_region', is not significant)
|
||||||
is active. Subsequently, set point to POSITION relative to TEXT,
|
within F's selected window with TEXT; deactivate the mark if it is
|
||||||
much as `commit_text' would. */
|
active. Subsequently, set point to POSITION relative to TEXT, as
|
||||||
|
`commit_text' would. */
|
||||||
|
|
||||||
void
|
void
|
||||||
replace_text (struct frame *f, ptrdiff_t start, ptrdiff_t end,
|
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)
|
unsigned long counter)
|
||||||
{
|
{
|
||||||
struct text_conversion_action *action, **last;
|
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 = xmalloc (sizeof *action);
|
||||||
action->operation = TEXTCONV_REPLACE_TEXT;
|
action->operation = TEXTCONV_REPLACE_TEXT;
|
||||||
|
|
@ -1858,6 +2080,7 @@ get_extracted_text (struct frame *f, ptrdiff_t n,
|
||||||
specpdl_ref count;
|
specpdl_ref count;
|
||||||
ptrdiff_t start, end, start_byte, end_byte, mark;
|
ptrdiff_t start, end, start_byte, end_byte, mark;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
ptrdiff_t field_start, field_end;
|
||||||
|
|
||||||
if (!WINDOW_LIVE_P (f->old_selected_window))
|
if (!WINDOW_LIVE_P (f->old_selected_window))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1907,6 +2130,15 @@ get_extracted_text (struct frame *f, ptrdiff_t n,
|
||||||
goto finish;
|
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);
|
start = max (start, BEGV);
|
||||||
end = min (end, ZV);
|
end = min (end, ZV);
|
||||||
|
|
||||||
|
|
@ -1935,7 +2167,8 @@ get_extracted_text (struct frame *f, ptrdiff_t n,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the offsets. */
|
/* 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);
|
*start_offset = min (mark - start, PT - start);
|
||||||
*end_offset = max (mark - start, PT - start);
|
*end_offset = max (mark - start, PT - start);
|
||||||
*length = end - start;
|
*length = end - start;
|
||||||
|
|
@ -1968,6 +2201,7 @@ get_surrounding_text (struct frame *f, ptrdiff_t left,
|
||||||
{
|
{
|
||||||
specpdl_ref count;
|
specpdl_ref count;
|
||||||
ptrdiff_t start, end, start_byte, end_byte, mark, temp;
|
ptrdiff_t start, end, start_byte, end_byte, mark, temp;
|
||||||
|
ptrdiff_t field_start, field_end;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
|
||||||
if (!WINDOW_LIVE_P (f->old_selected_window))
|
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))
|
|| ckd_add (&end, end, right))
|
||||||
goto finish;
|
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);
|
start = max (start, BEGV);
|
||||||
end = min (end, ZV);
|
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
|
/* Return the offsets. Unlike `get_extracted_text', this need not
|
||||||
sort mark and point. */
|
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;
|
*start_return = mark - start;
|
||||||
*end_return = PT - start;
|
*end_return = PT - start;
|
||||||
*length = end - start;
|
*length = end - start;
|
||||||
|
|
@ -2110,7 +2354,10 @@ report_point_change (struct frame *f, struct window *window,
|
||||||
if (f->conversion.batch_edit_count > 0)
|
if (f->conversion.batch_edit_count > 0)
|
||||||
f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
|
f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
|
||||||
else
|
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
|
/* 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,
|
Otherwise, it is either a string containing text that was inserted,
|
||||||
text deleted before point, or nil if text was deleted after point.
|
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 list contents are arranged in the reverse of the order of editing,
|
||||||
the latest edit first, so you must iterate through the list in reverse. */);
|
i.e. latest edit first, so you must iterate through the list in
|
||||||
|
reverse. */);
|
||||||
Vtext_conversion_edits = Qnil;
|
Vtext_conversion_edits = Qnil;
|
||||||
|
|
||||||
DEFVAR_LISP ("overriding-text-conversion-style",
|
DEFVAR_LISP ("overriding-text-conversion-style",
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,7 @@ extern char *get_surrounding_text (struct frame *, ptrdiff_t,
|
||||||
extern bool conversion_disabled_p (void);
|
extern bool conversion_disabled_p (void);
|
||||||
extern void check_postponed_buffers (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 *);
|
extern void register_textconv_interface (struct textconv_interface *);
|
||||||
|
|
||||||
#endif /* _TEXTCONV_H_ */
|
#endif /* _TEXTCONV_H_ */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue