This source file includes following definitions.
- copy_buffer
- get_mark
- select_window
- textconv_query
- sync_overlay
- record_buffer_change
- reset_frame_state
- detect_conversion_events
- restore_selected_window
- really_commit_text
- really_finish_composing_text
- really_set_composing_text
- really_set_composing_region
- really_delete_surrounding_text
- really_request_point_update
- really_set_point_and_mark
- complete_edit
- complete_edit_check
- handle_pending_conversion_events_1
- decrement_inside
- handle_pending_conversion_events
- start_batch_edit
- end_batch_edit
- commit_text
- finish_composing_text
- set_composing_text
- set_composing_region
- textconv_set_point_and_mark
- delete_surrounding_text
- request_point_update
- textconv_barrier
- get_extracted_text
- get_surrounding_text
- conversion_disabled_p
- report_selected_window_change
- report_point_change
- disable_text_conversion
- resume_text_conversion
- register_textconv_interface
- check_postponed_buffers
- syms_of_textconv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <config.h>
34
35 #include "textconv.h"
36 #include "buffer.h"
37 #include "syntax.h"
38 #include "blockinput.h"
39 #include "keyboard.h"
40
41
42
43
44
45 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
46 #if 0
47 #include <android/log.h>
48
49 #define TEXTCONV_DEBUG(fmt, ...) \
50 __android_log_print (ANDROID_LOG_VERBOSE, "EmacsInputConnection", \
51 "%s: " fmt, __func__, ## __VA_ARGS__)
52 #endif
53 #endif
54
55 #ifndef TEXTCONV_DEBUG
56 #define TEXTCONV_DEBUG(...) ((void) 0)
57 #endif
58
59
60
61
62
63
64 static struct textconv_interface *text_interface;
65
66
67
68 static int suppress_conversion_count;
69
70
71
72
73 enum textconv_batch_edit_flags
74 {
75 PENDING_POINT_CHANGE = 1,
76 PENDING_COMPOSE_CHANGE = 2,
77 };
78
79
80
81
82
83
84
85 static void
86 copy_buffer (ptrdiff_t beg, ptrdiff_t beg_byte,
87 ptrdiff_t end, ptrdiff_t end_byte,
88 char *buffer)
89 {
90 ptrdiff_t beg0, end0, beg1, end1, size;
91
92 if (beg_byte < GPT_BYTE && GPT_BYTE < end_byte)
93 {
94
95 beg0 = beg_byte;
96 end0 = GPT_BYTE;
97 beg1 = GPT_BYTE + GAP_SIZE - BEG_BYTE;
98 end1 = end_byte + GAP_SIZE - BEG_BYTE;
99 }
100 else
101 {
102
103 beg0 = beg_byte;
104 end0 = end_byte;
105 beg1 = -1;
106 end1 = -1;
107 }
108
109 size = end0 - beg0;
110 memcpy (buffer, BYTE_POS_ADDR (beg0), size);
111 if (beg1 != -1)
112 memcpy (buffer + size, BEG_ADDR + beg1, end1 - beg1);
113 }
114
115
116
117
118
119
120
121
122 static ptrdiff_t
123 get_mark (void)
124 {
125 if (!NILP (BVAR (current_buffer, mark_active))
126 && XMARKER (BVAR (current_buffer, mark))->buffer)
127 return marker_position (BVAR (current_buffer,
128 mark));
129
130 return -1;
131 }
132
133
134
135
136
137 static void
138 select_window (Lisp_Object window, Lisp_Object norecord)
139 {
140 struct window *w;
141
142 w = XWINDOW (window);
143
144 if (MINI_WINDOW_P (w)
145 && WINDOW_LIVE_P (window)
146 && !EQ (window, Factive_minibuffer_window ()))
147 window = WINDOW_XFRAME (w)->selected_window;
148
149 Fselect_window (window, norecord);
150 }
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 int
173 textconv_query (struct frame *f, struct textconv_callback_struct *query,
174 int flags)
175 {
176 specpdl_ref count;
177 ptrdiff_t pos, pos_byte, end, end_byte, start;
178 ptrdiff_t temp, temp1, mark;
179 char *buffer;
180 struct window *w;
181
182
183
184 count = SPECPDL_INDEX ();
185 record_unwind_protect_excursion ();
186
187
188 specbind (Qinhibit_quit, Qt);
189
190
191
192 select_window ((WINDOW_LIVE_P (f->old_selected_window)
193 ? f->old_selected_window
194 : f->selected_window), Qt);
195 w = XWINDOW (selected_window);
196
197
198
199
200 pos = PT;
201
202
203
204
205
206
207 mark = get_mark ();
208
209 if (query->position == EMACS_INT_MAX)
210 {
211 pos = (mark == -1
212 ? w->ephemeral_last_point
213 : max (w->ephemeral_last_point, mark));
214 goto escape1;
215 }
216 else if (query->position == TYPE_MINIMUM (EMACS_INT))
217 {
218 pos = (mark == -1
219 ? w->ephemeral_last_point
220 : min (w->ephemeral_last_point, mark));
221 goto escape1;
222 }
223
224
225
226
227
228 if (flags & TEXTCONV_SKIP_CONVERSION_REGION
229 && MARKERP (f->conversion.compose_region_start))
230 {
231 start = marker_position (f->conversion.compose_region_start);
232 end = marker_position (f->conversion.compose_region_end);
233
234 if (pos >= start && pos < end)
235 {
236 switch (query->direction)
237 {
238 case TEXTCONV_FORWARD_CHAR:
239 case TEXTCONV_FORWARD_WORD:
240 case TEXTCONV_CARET_DOWN:
241 case TEXTCONV_NEXT_LINE:
242 case TEXTCONV_LINE_START:
243 pos = end;
244 break;
245
246 default:
247 pos = max (BEGV, start - 1);
248 break;
249 }
250 }
251 }
252
253
254
255
256
257 if (ckd_add (&pos, pos, query->position))
258 pos = PT;
259
260 escape1:
261
262 if (pos < BEGV)
263 pos = BEGV;
264
265 if (pos > ZV)
266 pos = ZV;
267
268
269 set_point (pos);
270 pos = PT;
271 pos_byte = PT_BYTE;
272
273
274
275 switch (query->direction)
276 {
277 case TEXTCONV_FORWARD_CHAR:
278
279 if (ckd_add (&end, pos, query->factor) || end > ZV)
280 end = ZV;
281
282 end_byte = CHAR_TO_BYTE (end);
283 break;
284
285 case TEXTCONV_BACKWARD_CHAR:
286
287 if (ckd_sub (&end, pos, query->factor) || end < BEGV)
288 end = BEGV;
289
290 end_byte = CHAR_TO_BYTE (end);
291 break;
292
293 case TEXTCONV_FORWARD_WORD:
294
295 end = scan_words (pos, (EMACS_INT) query->factor);
296
297 if (!end)
298 {
299 end = ZV;
300 end_byte = ZV_BYTE;
301 }
302 else
303 end_byte = CHAR_TO_BYTE (end);
304
305 break;
306
307 case TEXTCONV_BACKWARD_WORD:
308
309 end = scan_words (pos, 0 - (EMACS_INT) query->factor);
310
311 if (!end)
312 {
313 end = BEGV;
314 end_byte = BEGV_BYTE;
315 }
316 else
317 end_byte = CHAR_TO_BYTE (end);
318
319 break;
320
321 case TEXTCONV_CARET_UP:
322
323 Fvertical_motion (Fcons (Fcurrent_column (), make_fixnum (-1)),
324 Qnil, Qnil);
325 end = PT;
326 end_byte = PT_BYTE;
327 break;
328
329 case TEXTCONV_CARET_DOWN:
330
331
332 Fvertical_motion (Fcons (Fcurrent_column (), make_fixnum (1)),
333 Qnil, Qnil);
334 end = PT;
335 end_byte = PT_BYTE;
336 break;
337
338 case TEXTCONV_NEXT_LINE:
339
340 scan_newline (pos, pos_byte, ZV, ZV_BYTE,
341 query->factor, false);
342 end = PT;
343 end_byte = PT_BYTE;
344 break;
345
346 case TEXTCONV_PREVIOUS_LINE:
347
348 scan_newline (pos, pos_byte, BEGV, BEGV_BYTE,
349 0 - (EMACS_INT) query->factor, false);
350 end = PT;
351 end_byte = PT_BYTE;
352 break;
353
354 case TEXTCONV_LINE_START:
355
356 Fbeginning_of_line (Qnil);
357 end = PT;
358 end_byte = PT_BYTE;
359 break;
360
361 case TEXTCONV_LINE_END:
362
363 Fend_of_line (Qnil);
364 end = PT;
365 end_byte = PT_BYTE;
366 break;
367
368 case TEXTCONV_ABSOLUTE_POSITION:
369
370 SET_PT (query->factor);
371 end = PT;
372 end_byte = PT_BYTE;
373 break;
374
375 default:
376 unbind_to (count, Qnil);
377 return 1;
378 }
379
380
381
382 if (end < pos)
383 {
384 eassert (end_byte < pos_byte);
385 temp = pos_byte;
386 temp1 = pos;
387 pos_byte = end_byte;
388 pos = end;
389 end = temp1;
390 end_byte = temp;
391 }
392
393
394 buffer = xmalloc (end_byte - pos_byte);
395 copy_buffer (pos, pos_byte, end, end_byte, buffer);
396 query->text.text = buffer;
397 query->text.length = end - pos;
398 query->text.bytes = end_byte - pos_byte;
399
400
401
402 switch (query->operation)
403 {
404 case TEXTCONV_SUBSTITUTION:
405 if (safe_del_range (pos, end))
406 {
407
408 unbind_to (count, Qnil);
409 return 1;
410 }
411
412 default:
413 break;
414 }
415
416
417 unbind_to (count, Qnil);
418 return 0;
419 }
420
421
422
423
424 static void
425 sync_overlay (struct frame *f)
426 {
427 if (MARKERP (f->conversion.compose_region_start)
428 && !NILP (Vtext_conversion_face))
429 {
430 if (NILP (f->conversion.compose_region_overlay))
431 {
432 f->conversion.compose_region_overlay
433 = Fmake_overlay (f->conversion.compose_region_start,
434 f->conversion.compose_region_end, Qnil,
435 Qt, Qnil);
436 Foverlay_put (f->conversion.compose_region_overlay,
437 Qface, Vtext_conversion_face);
438 }
439
440 Fmove_overlay (f->conversion.compose_region_overlay,
441 f->conversion.compose_region_start,
442 f->conversion.compose_region_end, Qnil);
443 }
444 else if (!NILP (f->conversion.compose_region_overlay))
445 {
446 Fdelete_overlay (f->conversion.compose_region_overlay);
447 f->conversion.compose_region_overlay = Qnil;
448 }
449 }
450
451
452
453
454
455
456
457 static void
458 record_buffer_change (ptrdiff_t beg, ptrdiff_t end,
459 Lisp_Object ephemeral)
460 {
461 Lisp_Object buffer, beg_marker, end_marker;
462
463 XSETBUFFER (buffer, current_buffer);
464
465
466 beg_marker = build_marker (current_buffer, beg,
467 CHAR_TO_BYTE (beg));
468
469
470
471
472 if (beg == end)
473 end_marker = beg_marker;
474 else
475 {
476 end_marker = build_marker (current_buffer, end,
477 CHAR_TO_BYTE (end));
478
479
480
481 Fset_marker_insertion_type (end_marker, Qt);
482 }
483
484 Vtext_conversion_edits
485 = Fcons (list4 (buffer, beg_marker, end_marker,
486 ephemeral),
487 Vtext_conversion_edits);
488 }
489
490
491
492
493 void
494 reset_frame_state (struct frame *f)
495 {
496 struct text_conversion_action *last, *next;
497
498
499
500 if (!NILP (f->conversion.compose_region_start))
501 {
502 Fset_marker (f->conversion.compose_region_start, Qnil, Qnil);
503 Fset_marker (f->conversion.compose_region_end, Qnil, Qnil);
504 f->conversion.compose_region_start = Qnil;
505 f->conversion.compose_region_end = Qnil;
506 }
507
508
509
510 if (!NILP (f->conversion.compose_region_overlay))
511 Fdelete_overlay (f->conversion.compose_region_overlay);
512
513
514
515 next = f->conversion.actions;
516 while (next)
517 {
518 last = next;
519 next = next->next;
520
521
522 if (text_interface && text_interface->notify_conversion)
523 text_interface->notify_conversion (last->counter);
524
525 xfree (last);
526 }
527 f->conversion.actions = NULL;
528
529
530 f->conversion.batch_edit_count = 0;
531 f->conversion.batch_edit_flags = 0;
532 }
533
534
535
536
537 bool
538 detect_conversion_events (void)
539 {
540 Lisp_Object tail, frame;
541
542 FOR_EACH_FRAME (tail, frame)
543 {
544
545 if (XFRAME (frame)->conversion.actions
546 && ((XFRAME (frame)->conversion.actions->operation
547 != TEXTCONV_BARRIER)
548 || (kbd_fetch_ptr == kbd_store_ptr)))
549 return true;
550 }
551
552 return false;
553 }
554
555
556
557 static void
558 restore_selected_window (Lisp_Object window)
559 {
560
561 select_window (window, Qt);
562 }
563
564
565
566
567
568
569
570
571
572
573
574
575 static void
576 really_commit_text (struct frame *f, EMACS_INT position,
577 Lisp_Object text)
578 {
579 specpdl_ref count;
580 ptrdiff_t wanted, start, end, mark;
581 struct window *w;
582
583
584
585 if (!WINDOW_LIVE_P (f->old_selected_window))
586 return;
587
588 count = SPECPDL_INDEX ();
589 record_unwind_protect (restore_selected_window,
590 selected_window);
591
592
593
594 select_window (f->old_selected_window, Qt);
595
596
597
598
599
600 mark = get_mark ();
601 if (MARKERP (f->conversion.compose_region_start) || mark != -1)
602 {
603
604
605
606 if (MARKERP (f->conversion.compose_region_start))
607 {
608 start = marker_position (f->conversion.compose_region_start);
609 end = marker_position (f->conversion.compose_region_end);
610 }
611 else
612 {
613
614 start = min (mark, PT);
615 end = max (mark, PT);
616 }
617
618
619
620 del_range_1 (start, end, true, false);
621 record_buffer_change (start, start, Qt);
622
623
624
625 if (SCHARS (text))
626 {
627
628
629
630
631
632 insert_from_string (text, 0, 0, SCHARS (text),
633 SBYTES (text), true);
634 record_buffer_change (start, PT, text);
635 }
636
637
638
639 if (position <= 0)
640 {
641
642
643 wanted = start;
644
645 if (INT_ADD_WRAPV (wanted, position, &wanted)
646 || wanted < BEGV)
647 wanted = BEGV;
648
649 if (wanted > ZV)
650 wanted = ZV;
651
652 set_point (wanted);
653 }
654 else
655 {
656
657
658 wanted = PT;
659
660 if (INT_ADD_WRAPV (wanted, position - 1, &wanted)
661 || wanted > ZV)
662 wanted = ZV;
663
664 if (wanted < BEGV)
665 wanted = BEGV;
666
667 set_point (wanted);
668 }
669
670
671
672 if (!NILP (f->conversion.compose_region_start))
673 {
674 Fset_marker (f->conversion.compose_region_start, Qnil, Qnil);
675 Fset_marker (f->conversion.compose_region_end, Qnil, Qnil);
676 f->conversion.compose_region_start = Qnil;
677 f->conversion.compose_region_end = Qnil;
678 }
679
680
681
682 if (!NILP (f->conversion.compose_region_overlay))
683 Fdelete_overlay (f->conversion.compose_region_overlay);
684 }
685 else
686 {
687
688
689 wanted = PT;
690
691
692
693 if (SCHARS (text))
694 {
695
696
697
698
699
700 insert_from_string (text, 0, 0, SCHARS (text),
701 SBYTES (text), true);
702
703 record_buffer_change (wanted, PT, text);
704 }
705
706 if (position <= 0)
707 {
708 if (INT_ADD_WRAPV (wanted, position, &wanted)
709 || wanted < BEGV)
710 wanted = BEGV;
711
712 if (wanted > ZV)
713 wanted = ZV;
714
715 set_point (wanted);
716 }
717 else
718 {
719 wanted = PT;
720
721 if (INT_ADD_WRAPV (wanted, position - 1, &wanted)
722 || wanted > ZV)
723 wanted = ZV;
724
725 if (wanted < BEGV)
726 wanted = BEGV;
727
728 set_point (wanted);
729 }
730 }
731
732
733 call0 (Qdeactivate_mark);
734
735
736 TEXTCONV_DEBUG ("text inserted: %s, point now: %zd",
737 SSDATA (text), PT);
738
739
740 w = XWINDOW (selected_window);
741 w->ephemeral_last_point = PT;
742 unbind_to (count, Qnil);
743 }
744
745
746
747
748
749 static void
750 really_finish_composing_text (struct frame *f, bool update)
751 {
752 if (!NILP (f->conversion.compose_region_start))
753 {
754 Fset_marker (f->conversion.compose_region_start, Qnil, Qnil);
755 Fset_marker (f->conversion.compose_region_end, Qnil, Qnil);
756 f->conversion.compose_region_start = Qnil;
757 f->conversion.compose_region_end = Qnil;
758
759 if (update && text_interface
760 && text_interface->compose_region_changed)
761 (*text_interface->compose_region_changed) (f);
762 }
763
764
765
766 if (!NILP (f->conversion.compose_region_overlay))
767 Fdelete_overlay (f->conversion.compose_region_overlay);
768
769 TEXTCONV_DEBUG ("conversion region removed");
770 }
771
772
773
774
775
776
777
778 static void
779 really_set_composing_text (struct frame *f, ptrdiff_t position,
780 Lisp_Object text)
781 {
782 specpdl_ref count;
783 ptrdiff_t start, wanted, end;
784 struct window *w;
785
786
787
788 if (!WINDOW_LIVE_P (f->old_selected_window))
789 return;
790
791 count = SPECPDL_INDEX ();
792 record_unwind_protect (restore_selected_window,
793 selected_window);
794
795
796
797 w = XWINDOW (f->old_selected_window);
798 select_window (f->old_selected_window, Qt);
799
800
801
802 if (!MARKERP (f->conversion.compose_region_start))
803 {
804
805 start = PT;
806 wanted = end = get_mark ();
807
808
809
810 if (end == -1)
811 end = start;
812 else
813 {
814
815 start = min (start, end);
816 end = max (PT, wanted);
817 }
818
819
820
821
822 if (end != start)
823 {
824 del_range_1 (start, end, true, false);
825 set_point (start);
826 record_buffer_change (start, start, Qt);
827 }
828
829
830 f->conversion.compose_region_start
831 = build_marker (current_buffer, PT, PT_BYTE);
832 f->conversion.compose_region_end
833 = build_marker (current_buffer, PT, PT_BYTE);
834
835 Fset_marker_insertion_type (f->conversion.compose_region_end,
836 Qt);
837 }
838 else
839 {
840
841
842 start = marker_position (f->conversion.compose_region_start);
843 end = marker_position (f->conversion.compose_region_end);
844 del_range_1 (start, end, true, false);
845 set_point (start);
846
847 if (start != end)
848 record_buffer_change (start, start, Qt);
849 }
850
851
852
853
854
855 insert_from_string (text, 0, 0, SCHARS (text),
856 SBYTES (text), true);
857
858 if (start != PT)
859 record_buffer_change (start, PT, Qt);
860
861
862 if (position <= 0)
863 {
864 wanted = start;
865
866 if (INT_SUBTRACT_WRAPV (wanted, position, &wanted)
867 || wanted < BEGV)
868 wanted = BEGV;
869
870 if (wanted > ZV)
871 wanted = ZV;
872 }
873 else
874 {
875 end = marker_position (f->conversion.compose_region_end);
876 wanted = end;
877
878
879 eassert (end == PT);
880
881 if (INT_ADD_WRAPV (wanted, position - 1, &wanted)
882 || wanted > ZV)
883 wanted = ZV;
884
885 if (wanted < BEGV)
886 wanted = BEGV;
887 }
888
889 set_point (wanted);
890
891
892 call0 (Qdeactivate_mark);
893
894
895 sync_overlay (f);
896
897
898
899
900 if (!SCHARS (text))
901 really_finish_composing_text (f, false);
902
903
904
905
906 if (PT == w->ephemeral_last_point
907 && text_interface
908 && text_interface->compose_region_changed)
909 {
910 if (f->conversion.batch_edit_count > 0)
911 f->conversion.batch_edit_flags |= PENDING_COMPOSE_CHANGE;
912 else
913 text_interface->compose_region_changed (f);
914 }
915
916
917 w = XWINDOW (selected_window);
918 w->ephemeral_last_point = PT;
919
920 if (SCHARS (text))
921 TEXTCONV_DEBUG ("conversion region set to: %td %td",
922 marker_position (f->conversion.compose_region_start),
923 marker_position (f->conversion.compose_region_end));
924 else
925 TEXTCONV_DEBUG ("conversion region removed; PT is now: %td", PT);
926
927 unbind_to (count, Qnil);
928 }
929
930
931
932
933 static void
934 really_set_composing_region (struct frame *f, ptrdiff_t start,
935 ptrdiff_t end)
936 {
937 specpdl_ref count;
938 struct window *w;
939
940
941
942 if (!WINDOW_LIVE_P (f->old_selected_window))
943 return;
944
945
946
947
948 if (max (0, start) == max (0, end))
949 {
950 really_finish_composing_text (f, false);
951 return;
952 }
953
954 count = SPECPDL_INDEX ();
955 record_unwind_protect (restore_selected_window,
956 selected_window);
957
958
959
960 select_window (f->old_selected_window, Qt);
961
962
963
964 if (!MARKERP (f->conversion.compose_region_start))
965 {
966 f->conversion.compose_region_start = Fmake_marker ();
967 f->conversion.compose_region_end = Fmake_marker ();
968 Fset_marker_insertion_type (f->conversion.compose_region_end,
969 Qt);
970 }
971
972 Fset_marker (f->conversion.compose_region_start,
973 make_fixnum (start), Qnil);
974 Fset_marker (f->conversion.compose_region_end,
975 make_fixnum (end), Qnil);
976 sync_overlay (f);
977
978 TEXTCONV_DEBUG ("composing region set to: %td, %td; point is: %td",
979 start, end, PT);
980
981
982 w = XWINDOW (selected_window);
983 w->ephemeral_last_point = PT;
984
985 unbind_to (count, Qnil);
986 }
987
988
989
990
991
992 static void
993 really_delete_surrounding_text (struct frame *f, ptrdiff_t left,
994 ptrdiff_t right)
995 {
996 specpdl_ref count;
997 ptrdiff_t start, end, a, b, a1, b1, lstart, rstart;
998 struct window *w;
999 Lisp_Object text;
1000
1001
1002
1003 if (!WINDOW_LIVE_P (f->old_selected_window))
1004 return;
1005
1006 count = SPECPDL_INDEX ();
1007 record_unwind_protect (restore_selected_window,
1008 selected_window);
1009
1010
1011
1012 select_window (f->old_selected_window, Qt);
1013
1014
1015
1016 a = get_mark ();
1017
1018 if (a != -1 && a != PT)
1019 lstart = rstart = max (a, PT);
1020 else
1021 lstart = rstart = PT;
1022
1023
1024
1025
1026
1027 if (MARKERP (f->conversion.compose_region_start))
1028 {
1029 a = marker_position (f->conversion.compose_region_start);
1030 b = marker_position (f->conversion.compose_region_end);
1031
1032 a1 = min (a, b);
1033 b1 = max (a, b);
1034
1035 lstart = min (lstart, min (PT, a1));
1036 rstart = max (rstart, max (PT, b1));
1037 }
1038
1039 if (lstart == rstart)
1040 {
1041 start = max (BEGV, lstart - left);
1042 end = min (ZV, rstart + right);
1043
1044 text = del_range_1 (start, end, true, true);
1045 record_buffer_change (start, start, text);
1046 }
1047 else
1048 {
1049
1050
1051
1052 start = rstart;
1053 end = min (ZV, rstart + right);
1054 text = del_range_1 (start, end, true, true);
1055 record_buffer_change (start, start, Qnil);
1056
1057
1058
1059 start = max (BEGV, lstart - left);
1060 end = lstart;
1061 text = del_range_1 (start, end, true, true);
1062 record_buffer_change (start, start, text);
1063 }
1064
1065 TEXTCONV_DEBUG ("deleted surrounding text: %td, %td; PT is now %td",
1066 left, right, PT);
1067
1068
1069
1070 if (get_mark () == PT)
1071 call0 (Qdeactivate_mark);
1072
1073
1074 w = XWINDOW (selected_window);
1075 w->ephemeral_last_point = PT;
1076
1077 unbind_to (count, Qnil);
1078 }
1079
1080
1081
1082
1083
1084 static void
1085 really_request_point_update (struct frame *f)
1086 {
1087
1088
1089 if (!WINDOW_LIVE_P (f->old_selected_window))
1090 return;
1091
1092 if (f->conversion.batch_edit_count > 0)
1093 f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
1094 else if (text_interface && text_interface->point_changed)
1095 text_interface->point_changed (f,
1096 XWINDOW (f->old_selected_window),
1097 current_buffer);
1098 }
1099
1100
1101
1102
1103
1104
1105
1106
1107 static void
1108 really_set_point_and_mark (struct frame *f, ptrdiff_t point,
1109 ptrdiff_t mark)
1110 {
1111 specpdl_ref count;
1112 struct window *w;
1113
1114
1115
1116 if (!WINDOW_LIVE_P (f->old_selected_window))
1117 return;
1118
1119 count = SPECPDL_INDEX ();
1120 record_unwind_protect (restore_selected_window,
1121 selected_window);
1122
1123
1124
1125 select_window (f->old_selected_window, Qt);
1126
1127 if (point == PT)
1128 {
1129 if (f->conversion.batch_edit_count > 0)
1130 f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
1131 else if (text_interface && text_interface->point_changed)
1132 text_interface->point_changed (f,
1133 XWINDOW (f->old_selected_window),
1134 current_buffer);
1135 }
1136 else
1137
1138 Fgoto_char (make_fixnum (point));
1139
1140 if (mark == point
1141 && !NILP (BVAR (current_buffer, mark_active)))
1142 call0 (Qdeactivate_mark);
1143 else
1144 call1 (Qpush_mark, make_fixnum (mark));
1145
1146
1147 w = XWINDOW (selected_window);
1148 w->ephemeral_last_point = PT;
1149
1150 TEXTCONV_DEBUG ("set point and mark: %td %td",
1151 PT, get_mark ());
1152
1153 unbind_to (count, Qnil);
1154 }
1155
1156
1157
1158 static void
1159 complete_edit (void *token)
1160 {
1161 if (text_interface && text_interface->notify_conversion)
1162 text_interface->notify_conversion (*(unsigned long *) token);
1163 }
1164
1165
1166
1167 struct complete_edit_check_context
1168 {
1169
1170 struct window *w;
1171
1172
1173 bool check;
1174 };
1175
1176
1177
1178
1179
1180 static void
1181 complete_edit_check (void *ptr)
1182 {
1183 struct complete_edit_check_context *context;
1184 struct frame *f;
1185
1186 context = ptr;
1187
1188 if (!context->check)
1189 {
1190
1191 context->w->ephemeral_last_point
1192 = window_point (context->w);
1193
1194
1195
1196 f = WINDOW_XFRAME (context->w);
1197
1198 if (!FRAME_LIVE_P (f))
1199 return;
1200
1201 if (text_interface && text_interface->point_changed)
1202 {
1203 if (f->conversion.batch_edit_count > 0)
1204 f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
1205 else
1206 text_interface->point_changed (f, context->w, NULL);
1207 }
1208 }
1209 }
1210
1211
1212
1213
1214
1215
1216 static struct window *
1217 handle_pending_conversion_events_1 (struct frame *f,
1218 struct text_conversion_action *action)
1219 {
1220 Lisp_Object data;
1221 enum text_conversion_operation operation;
1222 struct buffer *buffer UNINIT;
1223 struct window *w;
1224 specpdl_ref count;
1225 unsigned long token;
1226 struct complete_edit_check_context context;
1227
1228
1229
1230 data = action->data;
1231 operation = action->operation;
1232 token = action->counter;
1233 xfree (action);
1234
1235
1236
1237
1238
1239 if (conversion_disabled_p ())
1240 return NULL;
1241
1242
1243
1244 context.check = false;
1245
1246
1247 count = SPECPDL_INDEX ();
1248 record_unwind_protect_ptr (complete_edit, &token);
1249 w = NULL;
1250
1251 if (WINDOW_LIVE_P (f->old_selected_window))
1252 {
1253 w = XWINDOW (f->old_selected_window);
1254 buffer = XBUFFER (WINDOW_BUFFER (w));
1255 context.w = w;
1256
1257
1258 record_unwind_protect_ptr (complete_edit_check, &context);
1259 }
1260
1261 switch (operation)
1262 {
1263 case TEXTCONV_START_BATCH_EDIT:
1264 f->conversion.batch_edit_count++;
1265 break;
1266
1267 case TEXTCONV_END_BATCH_EDIT:
1268 if (f->conversion.batch_edit_count > 0)
1269 f->conversion.batch_edit_count--;
1270
1271 if (!WINDOW_LIVE_P (f->old_selected_window))
1272 break;
1273
1274 if (f->conversion.batch_edit_flags & PENDING_POINT_CHANGE)
1275 text_interface->point_changed (f, w, buffer);
1276
1277 if (f->conversion.batch_edit_flags & PENDING_COMPOSE_CHANGE)
1278 text_interface->compose_region_changed (f);
1279
1280 f->conversion.batch_edit_flags = 0;
1281 break;
1282
1283 case TEXTCONV_COMMIT_TEXT:
1284 really_commit_text (f, XFIXNUM (XCAR (data)), XCDR (data));
1285 break;
1286
1287 case TEXTCONV_FINISH_COMPOSING_TEXT:
1288 really_finish_composing_text (f, !NILP (data));
1289 break;
1290
1291 case TEXTCONV_SET_COMPOSING_TEXT:
1292 really_set_composing_text (f, XFIXNUM (XCAR (data)),
1293 XCDR (data));
1294 break;
1295
1296 case TEXTCONV_SET_COMPOSING_REGION:
1297 really_set_composing_region (f, XFIXNUM (XCAR (data)),
1298 XFIXNUM (XCDR (data)));
1299 break;
1300
1301 case TEXTCONV_SET_POINT_AND_MARK:
1302 really_set_point_and_mark (f, XFIXNUM (XCAR (data)),
1303 XFIXNUM (XCDR (data)));
1304 break;
1305
1306 case TEXTCONV_DELETE_SURROUNDING_TEXT:
1307 really_delete_surrounding_text (f, XFIXNUM (XCAR (data)),
1308 XFIXNUM (XCDR (data)));
1309 break;
1310
1311 case TEXTCONV_REQUEST_POINT_UPDATE:
1312 really_request_point_update (f);
1313 break;
1314
1315 case TEXTCONV_BARRIER:
1316 if (kbd_fetch_ptr != kbd_store_ptr)
1317 emacs_abort ();
1318
1319
1320
1321
1322
1323
1324 if (w)
1325 w->ephemeral_last_point = window_point (w);
1326 break;
1327 }
1328
1329
1330 context.check = true;
1331 unbind_to (count, Qnil);
1332
1333 return w;
1334 }
1335
1336
1337
1338 static void
1339 decrement_inside (void *ptr)
1340 {
1341 int *i;
1342
1343 i = ptr;
1344 (*i)--;
1345 }
1346
1347
1348
1349
1350 void
1351 handle_pending_conversion_events (void)
1352 {
1353 struct frame *f;
1354 Lisp_Object tail, frame;
1355 struct text_conversion_action *action, *next;
1356 bool handled;
1357 static int inside;
1358 specpdl_ref count;
1359 ptrdiff_t last_point;
1360 struct window *w;
1361
1362 handled = false;
1363
1364
1365
1366
1367 if (!inside)
1368 Vtext_conversion_edits = Qnil;
1369
1370 inside++;
1371
1372 count = SPECPDL_INDEX ();
1373 record_unwind_protect_ptr (decrement_inside, &inside);
1374
1375 FOR_EACH_FRAME (tail, frame)
1376 {
1377 f = XFRAME (frame);
1378 last_point = -1;
1379 w = NULL;
1380
1381
1382
1383 while (true)
1384 {
1385
1386
1387 if (w && (last_point != w->ephemeral_last_point))
1388 {
1389 if (handled
1390 && last_point != -1
1391 && text_interface
1392 && text_interface->point_changed)
1393 {
1394 if (f->conversion.batch_edit_count > 0)
1395 f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
1396 else
1397 text_interface->point_changed (f, NULL, NULL);
1398 }
1399
1400 last_point = w->ephemeral_last_point;
1401 }
1402
1403
1404
1405 action = f->conversion.actions;
1406
1407
1408
1409 if (!action)
1410 break;
1411
1412
1413
1414
1415 if (action->operation == TEXTCONV_BARRIER
1416 && kbd_store_ptr != kbd_fetch_ptr)
1417 break;
1418
1419
1420 next = action->next;
1421 f->conversion.actions = next;
1422
1423
1424 w = handle_pending_conversion_events_1 (f, action);
1425 handled = true;
1426 }
1427 }
1428
1429 unbind_to (count, Qnil);
1430 }
1431
1432
1433
1434
1435
1436
1437
1438
1439 void
1440 start_batch_edit (struct frame *f, unsigned long counter)
1441 {
1442 struct text_conversion_action *action, **last;
1443
1444 action = xmalloc (sizeof *action);
1445 action->operation = TEXTCONV_START_BATCH_EDIT;
1446 action->data = Qnil;
1447 action->next = NULL;
1448 action->counter = counter;
1449 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1450 ;;
1451 *last = action;
1452 input_pending = true;
1453 }
1454
1455
1456
1457
1458
1459
1460 void
1461 end_batch_edit (struct frame *f, unsigned long counter)
1462 {
1463 struct text_conversion_action *action, **last;
1464
1465 action = xmalloc (sizeof *action);
1466 action->operation = TEXTCONV_END_BATCH_EDIT;
1467 action->data = Qnil;
1468 action->next = NULL;
1469 action->counter = counter;
1470 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1471 ;;
1472 *last = action;
1473 input_pending = true;
1474 }
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484 void
1485 commit_text (struct frame *f, Lisp_Object string,
1486 ptrdiff_t position, unsigned long counter)
1487 {
1488 struct text_conversion_action *action, **last;
1489
1490 action = xmalloc (sizeof *action);
1491 action->operation = TEXTCONV_COMMIT_TEXT;
1492 action->data = Fcons (make_fixnum (position), string);
1493 action->next = NULL;
1494 action->counter = counter;
1495 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1496 ;;
1497 *last = action;
1498 input_pending = true;
1499 }
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509 void
1510 finish_composing_text (struct frame *f, unsigned long counter,
1511 bool update)
1512 {
1513 struct text_conversion_action *action, **last;
1514
1515 action = xmalloc (sizeof *action);
1516 action->operation = TEXTCONV_FINISH_COMPOSING_TEXT;
1517 action->data = update ? Qt : Qnil;
1518 action->next = NULL;
1519 action->counter = counter;
1520 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1521 ;;
1522 *last = action;
1523 input_pending = true;
1524 }
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541 void
1542 set_composing_text (struct frame *f, Lisp_Object object,
1543 ptrdiff_t new_point, unsigned long counter)
1544 {
1545 struct text_conversion_action *action, **last;
1546
1547 action = xmalloc (sizeof *action);
1548 action->operation = TEXTCONV_SET_COMPOSING_TEXT;
1549 action->data = Fcons (make_fixnum (new_point),
1550 object);
1551 action->next = NULL;
1552 action->counter = counter;
1553 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1554 ;;
1555 *last = action;
1556 input_pending = true;
1557 }
1558
1559
1560
1561
1562
1563
1564
1565 void
1566 set_composing_region (struct frame *f, ptrdiff_t start,
1567 ptrdiff_t end, unsigned long counter)
1568 {
1569 struct text_conversion_action *action, **last;
1570
1571 if (start > MOST_POSITIVE_FIXNUM)
1572 start = MOST_POSITIVE_FIXNUM;
1573
1574 if (end > MOST_POSITIVE_FIXNUM)
1575 end = MOST_POSITIVE_FIXNUM;
1576
1577 action = xmalloc (sizeof *action);
1578 action->operation = TEXTCONV_SET_COMPOSING_REGION;
1579 action->data = Fcons (make_fixnum (start),
1580 make_fixnum (end));
1581 action->next = NULL;
1582 action->counter = counter;
1583 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1584 ;;
1585 *last = action;
1586 input_pending = true;
1587 }
1588
1589
1590
1591
1592
1593 void
1594 textconv_set_point_and_mark (struct frame *f, ptrdiff_t point,
1595 ptrdiff_t mark, unsigned long counter)
1596 {
1597 struct text_conversion_action *action, **last;
1598
1599 if (point > MOST_POSITIVE_FIXNUM)
1600 point = MOST_POSITIVE_FIXNUM;
1601
1602 action = xmalloc (sizeof *action);
1603 action->operation = TEXTCONV_SET_POINT_AND_MARK;
1604 action->data = Fcons (make_fixnum (point),
1605 make_fixnum (mark));
1606 action->next = NULL;
1607 action->counter = counter;
1608 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1609 ;;
1610 *last = action;
1611 input_pending = true;
1612 }
1613
1614
1615
1616
1617 void
1618 delete_surrounding_text (struct frame *f, ptrdiff_t left,
1619 ptrdiff_t right, unsigned long counter)
1620 {
1621 struct text_conversion_action *action, **last;
1622
1623 action = xmalloc (sizeof *action);
1624 action->operation = TEXTCONV_DELETE_SURROUNDING_TEXT;
1625 action->data = Fcons (make_fixnum (left),
1626 make_fixnum (right));
1627 action->next = NULL;
1628 action->counter = counter;
1629 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1630 ;;
1631 *last = action;
1632 input_pending = true;
1633 }
1634
1635
1636
1637
1638 void
1639 request_point_update (struct frame *f, unsigned long counter)
1640 {
1641 struct text_conversion_action *action, **last;
1642
1643 action = xmalloc (sizeof *action);
1644 action->operation = TEXTCONV_REQUEST_POINT_UPDATE;
1645 action->data = Qnil;
1646 action->next = NULL;
1647 action->counter = counter;
1648 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1649 ;;
1650 *last = action;
1651 input_pending = true;
1652 }
1653
1654
1655
1656
1657
1658
1659
1660
1661 void
1662 textconv_barrier (struct frame *f, unsigned long counter)
1663 {
1664 struct text_conversion_action *action, **last;
1665
1666 action = xmalloc (sizeof *action);
1667 action->operation = TEXTCONV_BARRIER;
1668 action->data = Qnil;
1669 action->next = NULL;
1670 action->counter = counter;
1671 for (last = &f->conversion.actions; *last; last = &(*last)->next)
1672 ;;
1673 *last = action;
1674 input_pending = true;
1675 }
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693 char *
1694 get_extracted_text (struct frame *f, ptrdiff_t n,
1695 ptrdiff_t *start_return,
1696 ptrdiff_t *start_offset,
1697 ptrdiff_t *end_offset, ptrdiff_t *length,
1698 ptrdiff_t *bytes, bool *mark_active)
1699 {
1700 specpdl_ref count;
1701 ptrdiff_t start, end, start_byte, end_byte, mark;
1702 char *buffer;
1703
1704 if (!WINDOW_LIVE_P (f->old_selected_window))
1705 return NULL;
1706
1707
1708
1709 count = SPECPDL_INDEX ();
1710 record_unwind_protect_excursion ();
1711
1712
1713 specbind (Qinhibit_quit, Qt);
1714
1715
1716
1717 select_window (f->old_selected_window, Qt);
1718 buffer = NULL;
1719
1720
1721 if (n != -1)
1722 {
1723
1724
1725 n = max (4, n);
1726
1727 start = PT - n / 2;
1728 end = PT + n - n / 2;
1729 }
1730 else
1731 {
1732 if (!NILP (BVAR (current_buffer, mark_active))
1733 && XMARKER (BVAR (current_buffer, mark))->buffer)
1734 {
1735 start = marker_position (BVAR (current_buffer, mark));
1736 end = PT;
1737
1738
1739
1740
1741 if (start > end)
1742 {
1743 start_byte = end;
1744 end = start;
1745 start = start_byte;
1746 }
1747 }
1748 else
1749 goto finish;
1750 }
1751
1752 start = max (start, BEGV);
1753 end = min (end, ZV);
1754
1755
1756
1757 if (!(start <= PT && PT <= end))
1758 goto finish;
1759
1760
1761 start_byte = CHAR_TO_BYTE (start);
1762 end_byte = CHAR_TO_BYTE (end);
1763
1764
1765 buffer = xmalloc (end_byte - start_byte);
1766 copy_buffer (start, start_byte, end, end_byte,
1767 buffer);
1768
1769
1770
1771 mark = get_mark ();
1772 *mark_active = true;
1773
1774 if (mark == -1)
1775 {
1776 mark = PT;
1777 *mark_active = false;
1778 }
1779
1780
1781 *start_return = start;
1782 *start_offset = min (mark - start, PT - start);
1783 *end_offset = max (mark - start, PT - start);
1784 *length = end - start;
1785 *bytes = end_byte - start_byte;
1786
1787 TEXTCONV_DEBUG ("get_extracted_text: PT, mark, start: %td, %td, %td",
1788 PT, mark, start);
1789
1790 finish:
1791 unbind_to (count, Qnil);
1792 return buffer;
1793 }
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804 char *
1805 get_surrounding_text (struct frame *f, ptrdiff_t left,
1806 ptrdiff_t right, ptrdiff_t *length,
1807 ptrdiff_t *bytes, ptrdiff_t *offset,
1808 ptrdiff_t *start_return,
1809 ptrdiff_t *end_return)
1810 {
1811 specpdl_ref count;
1812 ptrdiff_t start, end, start_byte, end_byte, mark, temp;
1813 char *buffer;
1814
1815 if (!WINDOW_LIVE_P (f->old_selected_window))
1816 return NULL;
1817
1818
1819
1820 count = SPECPDL_INDEX ();
1821 record_unwind_protect_excursion ();
1822
1823
1824 specbind (Qinhibit_quit, Qt);
1825
1826
1827
1828 select_window (f->old_selected_window, Qt);
1829 buffer = NULL;
1830
1831
1832
1833
1834 end = get_mark ();
1835 start = PT;
1836
1837
1838
1839 if (end == -1)
1840 end = start;
1841
1842
1843
1844 if (end < start)
1845 {
1846 temp = start;
1847 start = end;
1848 end = temp;
1849 }
1850
1851
1852
1853 if (INT_SUBTRACT_WRAPV (start, left, &start)
1854 || INT_ADD_WRAPV (end, right, &end))
1855 goto finish;
1856
1857 start = max (start, BEGV);
1858 end = min (end, ZV);
1859
1860
1861
1862 if (!(start <= PT && PT <= end))
1863 goto finish;
1864
1865
1866 start_byte = CHAR_TO_BYTE (start);
1867 end_byte = CHAR_TO_BYTE (end);
1868
1869
1870 buffer = xmalloc (end_byte - start_byte);
1871 copy_buffer (start, start_byte, end, end_byte,
1872 buffer);
1873
1874
1875
1876 mark = get_mark ();
1877
1878 if (mark == -1)
1879 mark = PT;
1880
1881
1882
1883
1884 *offset = start;
1885 *start_return = mark - start;
1886 *end_return = PT - start;
1887 *length = end - start;
1888 *bytes = end_byte - start_byte;
1889
1890 finish:
1891 unbind_to (count, Qnil);
1892 return buffer;
1893 }
1894
1895
1896
1897
1898
1899 bool
1900 conversion_disabled_p (void)
1901 {
1902 return suppress_conversion_count > 0;
1903 }
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913 void
1914 report_selected_window_change (struct frame *f)
1915 {
1916 struct window *w;
1917
1918 reset_frame_state (f);
1919
1920 if (!text_interface)
1921 return;
1922
1923
1924
1925
1926
1927
1928 if (WINDOWP (f->selected_window))
1929 {
1930 w = XWINDOW (f->selected_window);
1931 w->ephemeral_last_point = window_point (w);
1932 }
1933
1934 text_interface->reset (f);
1935 }
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946 void
1947 report_point_change (struct frame *f, struct window *window,
1948 struct buffer *buffer)
1949 {
1950 if (!text_interface || !text_interface->point_changed)
1951 return;
1952
1953 if (f->conversion.batch_edit_count > 0)
1954 f->conversion.batch_edit_flags |= PENDING_POINT_CHANGE;
1955 else
1956 text_interface->point_changed (f, window, buffer);
1957 }
1958
1959
1960
1961
1962 void
1963 disable_text_conversion (void)
1964 {
1965 Lisp_Object tail, frame;
1966 struct frame *f;
1967
1968 suppress_conversion_count++;
1969
1970 if (!text_interface || suppress_conversion_count > 1)
1971 return;
1972
1973
1974
1975
1976 FOR_EACH_FRAME (tail, frame)
1977 {
1978 f = XFRAME (frame);
1979 reset_frame_state (f);
1980
1981 if (FRAME_WINDOW_P (f) && FRAME_VISIBLE_P (f))
1982 text_interface->reset (f);
1983 }
1984 }
1985
1986
1987
1988 void
1989 resume_text_conversion (void)
1990 {
1991 Lisp_Object tail, frame;
1992 struct frame *f;
1993
1994 suppress_conversion_count--;
1995 eassert (suppress_conversion_count >= 0);
1996
1997 if (!text_interface || suppress_conversion_count)
1998 return;
1999
2000
2001
2002
2003 FOR_EACH_FRAME (tail, frame)
2004 {
2005 f = XFRAME (frame);
2006 reset_frame_state (f);
2007
2008 if (FRAME_WINDOW_P (f) && FRAME_VISIBLE_P (f))
2009 text_interface->reset (f);
2010 }
2011 }
2012
2013
2014
2015 void
2016 register_textconv_interface (struct textconv_interface *interface)
2017 {
2018 text_interface = interface;
2019 }
2020
2021
2022
2023
2024
2025 static Lisp_Object postponed_buffers;
2026
2027
2028
2029
2030
2031 void
2032 check_postponed_buffers (void)
2033 {
2034 Lisp_Object buffer, tail, frame;
2035 struct buffer *b;
2036 struct frame *f;
2037
2038 buffer = postponed_buffers;
2039 postponed_buffers = Qnil;
2040
2041 if (!text_interface->reset)
2042 return;
2043
2044 FOR_EACH_TAIL (buffer)
2045 {
2046 b = XBUFFER (XCAR (buffer));
2047
2048
2049
2050 if (!BUFFER_LIVE_P (b))
2051 continue;
2052
2053
2054
2055 if (!buffer_window_count (b))
2056 continue;
2057
2058
2059
2060 FOR_EACH_FRAME (tail, frame)
2061 {
2062 f = XFRAME (frame);
2063
2064 if (WINDOW_LIVE_P (f->old_selected_window)
2065 && FRAME_WINDOW_P (f)
2066
2067
2068 && EQ (XWINDOW (f->old_selected_window)->contents,
2069 XCAR (buffer)))
2070 {
2071 block_input ();
2072 reset_frame_state (f);
2073 text_interface->reset (f);
2074 unblock_input ();
2075 }
2076 }
2077 }
2078 }
2079
2080
2081
2082 DEFUN ("set-text-conversion-style", Fset_text_conversion_style,
2083 Sset_text_conversion_style, 1, 2, 0,
2084 doc:
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101 )
2102 (Lisp_Object value, Lisp_Object after_key_sequence)
2103 {
2104 Lisp_Object tail, frame;
2105 struct frame *f;
2106 Lisp_Object buffer;
2107
2108 bset_text_conversion_style (current_buffer, value);
2109
2110 if (!text_interface)
2111 return Qnil;
2112
2113
2114
2115
2116 if (buffer_window_count (current_buffer))
2117 {
2118 buffer = Fcurrent_buffer ();
2119
2120
2121
2122
2123
2124 if (reading_key_sequence && !NILP (after_key_sequence))
2125 {
2126 if (NILP (Fmemq (buffer, postponed_buffers)))
2127
2128
2129
2130 postponed_buffers = Fcons (buffer, postponed_buffers);
2131 return Qnil;
2132 }
2133
2134 FOR_EACH_FRAME (tail, frame)
2135 {
2136 f = XFRAME (frame);
2137
2138 if (WINDOW_LIVE_P (f->old_selected_window)
2139 && FRAME_WINDOW_P (f)
2140 && EQ (XWINDOW (f->old_selected_window)->contents,
2141 buffer))
2142 {
2143 block_input ();
2144 reset_frame_state (f);
2145 text_interface->reset (f);
2146 unblock_input ();
2147 }
2148 }
2149 }
2150
2151 return Qnil;
2152 }
2153
2154
2155
2156 void
2157 syms_of_textconv (void)
2158 {
2159 DEFSYM (Qaction, "action");
2160 DEFSYM (Qtext_conversion, "text-conversion");
2161 DEFSYM (Qpush_mark, "push-mark");
2162 DEFSYM (Qunderline, "underline");
2163 DEFSYM (Qoverriding_text_conversion_style,
2164 "overriding-text-conversion-style");
2165
2166 DEFVAR_LISP ("text-conversion-edits", Vtext_conversion_edits,
2167 doc:
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190 );
2191 Vtext_conversion_edits = Qnil;
2192
2193 DEFVAR_LISP ("overriding-text-conversion-style",
2194 Voverriding_text_conversion_style,
2195 doc:
2196
2197
2198
2199
2200 );
2201 Voverriding_text_conversion_style = Qlambda;
2202
2203 DEFVAR_LISP ("text-conversion-face", Vtext_conversion_face,
2204 doc:
2205 );
2206 Vtext_conversion_face = Qunderline;
2207
2208 defsubr (&Sset_text_conversion_style);
2209
2210 postponed_buffers = Qnil;
2211 staticpro (&postponed_buffers);
2212 }