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