This source file includes following definitions.
- it_char_has_category
- char_can_wrap_before
- char_can_wrap_after
- fill_column_indicator_column
- redisplay_other_windows
- wset_redisplay
- fset_redisplay
- bset_redisplay
- bset_update_mode_line
- wset_update_mode_line
- ATTRIBUTE_FORMAT_PRINTF
- ATTRIBUTE_FORMAT_PRINTF
- window_text_bottom_y
- window_box_width
- window_box_height
- window_box_left_offset
- window_box_right_offset
- window_box_left
- window_box_right
- window_box
- window_box_edges
- line_bottom_y
- DEFUN
- default_line_pixel_height
- string_from_display_spec
- window_hscroll_limited
- reset_box_start_end_flags
- pos_visible_p
- check_char_and_length
- string_pos_nchars_ahead
- string_pos
- c_string_pos
- number_of_chars
- compute_string_pos
- estimate_mode_line_height
- pixel_to_glyph_coords
- x_y_to_hpos_vpos
- frame_to_window_pixel_xy
- get_glyph_string_clip_rects
- get_glyph_string_clip_rect
- get_phys_cursor_geometry
- remember_mouse_glyph
- adjust_window_ends
- hscrolling_current_line_p
- safe_eval_handler
- safe__call
- safe_call
- safe_call1
- safe__call1
- safe_eval
- safe__eval
- safe_call2
- CHECK_IT
- CHECK_WINDOW_END
- init_iterator
- get_narrowed_width
- get_narrowed_len
- get_medium_narrowing_begv
- get_medium_narrowing_zv
- get_nearby_bol_pos
- get_small_narrowing_begv
- get_large_narrowing_begv
- get_large_narrowing_zv
- unwind_narrowed_begv
- start_display
- in_ellipses_for_invisible_text_p
- init_from_display_pos
- init_to_row_start
- init_to_row_end
- handle_stop
- compute_stop_pos
- compute_display_string_pos
- compute_display_string_end
- handle_fontified_prop
- face_at_pos
- handle_face_prop
- underlying_face_id
- face_before_or_after_it_pos
- handle_invisible_prop
- setup_for_ellipsis
- find_display_property
- get_display_property
- display_min_width
- handle_display_prop
- handle_display_spec
- display_prop_end
- handle_single_display_spec
- display_prop_intangible_p
- single_display_spec_string_p
- display_prop_string_p
- string_buffer_position_lim
- string_buffer_position
- handle_composition_prop
- handle_overlay_change
- next_overlay_string
- compare_overlay_entries
- load_overlay_strings
- get_overlay_strings_1
- get_overlay_strings
- push_it
- iterate_out_of_display_property
- restore_face_box_flags
- pop_it
- back_to_previous_line_start
- strings_with_newlines
- forward_to_next_line_start
- back_to_previous_visible_line_start
- reseat_at_previous_visible_line_start
- reseat_at_next_visible_line_start
- reseat
- reseat_1
- reseat_to_string
- lookup_glyphless_char_display
- merge_escape_glyph_face
- merge_glyphless_glyph_face
- forget_escape_and_glyphless_faces
- get_next_display_element
- set_iterator_to_next
- next_element_from_display_vector
- get_visually_first_element
- next_element_from_string
- next_element_from_c_string
- next_element_from_ellipsis
- next_element_from_image
- next_element_from_xwidget
- next_element_from_stretch
- compute_stop_pos_backwards
- handle_stop_backwards
- next_element_from_buffer
- next_element_from_composition
- move_it_in_display_line_to
- move_it_in_display_line
- move_it_to
- move_it_vertically_backward
- move_it_vertically
- move_it_past_eol
- move_it_by_lines
- partial_line_height
- fast_move_it_horizontally
- in_display_vector_p
- window_text_pixel_size
- DEFUN
- format_nargs
- add_to_log
- vadd_to_log
- message_log_maybe_newline
- message_dolog
- message_log_check_duplicate
- message3
- message_to_stderr
- message3_nolog
- message1
- message1_nolog
- message_with_string
- ATTRIBUTE_FORMAT_PRINTF
- message
- update_echo_area
- ensure_echo_area_buffers
- with_echo_area_buffer
- with_echo_area_buffer_unwind_data
- unwind_with_echo_area_buffer
- setup_echo_area_for_printing
- display_echo_area
- display_echo_area_1
- resize_echo_area_exactly
- resize_mini_window_1
- resize_mini_window
- current_message
- current_message_1
- push_message
- restore_message
- pop_message_unwind
- check_message_stack
- clear_message_stack
- truncate_echo_area
- truncate_message_1
- set_message
- set_message_1
- clear_message
- clear_garbaged_frames
- echo_area_display
- window_buffer_changed
- mode_line_update_needed
- window_frozen_p
- format_mode_line_unwind_data
- unwind_format_mode_line
- store_mode_line_noprop_char
- store_mode_line_noprop
- gui_consider_frame_title
- needs_no_redisplay
- prepare_menu_bars
- update_menu_bar
- restore_selected_window
- restore_frame_selected_window
- update_tab_bar
- display_tab_bar
- build_desired_tab_bar_string
- display_tab_bar_line
- tab_bar_height
- redisplay_tab_bar
- tab_bar_item_info
- get_tab_bar_item
- handle_tab_bar_click
- note_tab_bar_highlight
- tty_get_tab_bar_item
- tty_handle_tab_bar_click
- update_tool_bar
- build_desired_tool_bar_string
- display_tool_bar_line
- tool_bar_height
- redisplay_tool_bar
- tool_bar_item_info
- get_tool_bar_item
- handle_tool_bar_click_with_device
- handle_tool_bar_click
- note_tool_bar_highlight
- hscroll_window_tree
- hscroll_windows
- debug_method_add
- text_outside_line_unchanged_p
- redisplay
- overlay_arrow_string_or_property
- overlay_arrow_in_current_buffer_p
- overlay_arrows_changed_p
- update_overlay_arrows
- overlay_arrow_at_row
- check_point_in_composition
- reconsider_clip_changes
- propagate_buffer_redisplay
- redisplay_internal
- unwind_redisplay_preserve_echo_area
- redisplay_preserve_echo_area
- unwind_redisplay
- unwind_display_working_on_window
- mark_window_display_accurate_1
- mark_window_display_accurate
- disp_char_vector
- block_buffer_flips
- unblock_buffer_flips
- buffer_flipping_blocked_p
- redisplay_windows
- redisplay_window_error
- redisplay_window_0
- redisplay_window_1
- update_redisplay_ticks
- set_cursor_from_row
- run_window_scroll_functions
- cursor_row_fully_visible_p
- try_scrolling
- compute_window_start_on_continuation_line
- try_cursor_movement
- set_vertical_scroll_bar
- set_horizontal_scroll_bar
- window_start_acceptable_p
- DEFUN
- redisplay_window
- try_window
- try_window_reusing_current_matrix
- find_last_row_displaying_text
- find_last_unchanged_at_beg_row
- find_first_unchanged_at_end_row
- sync_frame_with_window_matrix_rows
- row_containing_pos
- try_window_id
- dump_glyph_row
- dump_glyph
- dump_glyph_row
- DEFUN
- DEFUN
- DEFUN
- get_overlay_arrow_glyph_row
- insert_left_trunc_glyphs
- row_hash
- compute_line_metrics
- clear_position
- append_space_for_newline
- extend_face_to_end_of_line
- trailing_whitespace_p
- highlight_trailing_whitespace
- row_for_charpos_p
- cursor_row_p
- push_prefix_prop
- get_it_property
- get_line_prefix_it_property
- handle_line_prefix
- unproduce_glyphs
- find_row_edges
- display_count_lines_logically
- display_count_lines_visually
- maybe_produce_line_number
- should_produce_line_number
- row_text_area_empty
- display_line
- DEFUN
- DEFUN
- DEFUN
- display_menu_bar
- deep_copy_glyph_row
- display_tty_menu_item
- redisplay_mode_lines
- display_mode_lines
- display_mode_line
- move_elt_to_front
- safe_set_text_properties
- display_mode_element
- store_mode_line_string
- pint2str
- pint2hrstr
- decode_mode_spec_coding
- percent99
- decode_mode_spec
- count_lines
- display_count_lines
- display_string
- invisible_prop
- DEFUN
- calc_pixel_width_or_height
- get_font_ascent_descent
- dump_glyph_string
- init_glyph_string
- append_glyph_string_lists
- prepend_glyph_string_lists
- append_glyph_string
- get_char_face_and_encoding
- get_glyph_face_and_encoding
- get_char_glyph_code
- fill_composite_glyph_string
- fill_gstring_glyph_string
- fill_glyphless_glyph_string
- fill_glyph_string
- fill_image_glyph_string
- fill_xwidget_glyph_string
- fill_stretch_glyph_string
- get_per_char_metric
- normal_char_ascent_descent
- normal_char_height
- gui_get_glyph_overhangs
- left_overwritten
- left_overwriting
- right_overwritten
- right_overwriting
- set_glyph_string_background_width
- glyph_string_containing_background_width
- compute_overhangs_and_x
- draw_glyphs
- font_for_underline_metrics
- append_glyph
- append_composite_glyph
- take_vertical_position_into_account
- produce_image_glyph
- produce_xwidget_glyph
- append_stretch_glyph
- produce_stretch_glyph
- produce_special_glyphs
- calc_line_height_property
- append_glyphless_glyph
- produce_glyphless_glyph
- gui_produce_glyphs
- gui_write_glyphs
- gui_insert_glyphs
- gui_clear_end_of_line
- get_specified_cursor_type
- set_frame_cursor_types
- get_window_cursor_type
- notice_overwritten_cursor
- gui_fix_overlapping_area
- draw_phys_cursor_glyph
- erase_phys_cursor
- display_and_set_cursor
- update_window_cursor
- update_cursor_in_window_tree
- gui_update_cursor
- gui_clear_cursor
- draw_row_with_mouse_face
- show_mouse_face
- clear_mouse_face
- coords_in_mouse_face_p
- cursor_in_mouse_face_p
- rows_from_pos_range
- mouse_face_from_buffer_pos
- fast_find_string_pos
- mouse_face_from_string_pos
- on_hot_spot_p
- find_hot_spot
- define_frame_cursor1
- note_mode_line_or_margin_highlight
- note_mouse_highlight
- gui_clear_window_mouse_face
- cancel_mouse_face
- expose_area
- expose_line
- expose_overlaps
- phys_cursor_in_rect_p
- gui_draw_vertical_border
- gui_draw_right_divider
- gui_draw_bottom_divider
- expose_window
- expose_window_tree
- expose_frame
- gui_intersect_rectangles
- syms_of_xdisp
- init_xdisp
- show_hourglass
- start_hourglass
- cancel_hourglass
- adjust_glyph_width_for_mouse_face
- get_cursor_offset_for_mouse_face
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468 #include <config.h>
469 #include <stdlib.h>
470 #include <limits.h>
471 #include <math.h>
472
473 #include "lisp.h"
474 #include "atimer.h"
475 #include "composite.h"
476 #include "keyboard.h"
477 #include "sysstdio.h"
478 #include "systime.h"
479 #include "frame.h"
480 #include "window.h"
481 #include "termchar.h"
482 #include "dispextern.h"
483 #include "character.h"
484 #include "category.h"
485 #include "buffer.h"
486 #include "charset.h"
487 #include "indent.h"
488 #include "commands.h"
489 #include "keymap.h"
490 #include "disptab.h"
491 #include "termhooks.h"
492 #include "termopts.h"
493 #include "intervals.h"
494 #include "coding.h"
495 #include "region-cache.h"
496 #include "font.h"
497 #include "fontset.h"
498 #include "blockinput.h"
499 #include "xwidget.h"
500 #ifdef HAVE_WINDOW_SYSTEM
501 #include TERM_HEADER
502 #endif
503
504 #ifndef FRAME_OUTPUT_DATA
505 #define FRAME_OUTPUT_DATA(f) (NULL)
506 #endif
507
508 #define DISP_INFINITY 10000000
509
510
511 static Lisp_Object list_of_error;
512
513 #ifdef HAVE_WINDOW_SYSTEM
514
515
516
517
518 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \
519 (!NILP (Voverflow_newline_into_fringe) \
520 && FRAME_WINDOW_P ((IT)->f) \
521 && ((IT)->bidi_it.paragraph_dir == R2L \
522 ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
523 : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
524 && (IT)->current_x == (IT)->last_visible_x)
525
526 #else
527 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) false
528 #endif
529
530
531
532
533
534 #define IT_DISPLAYING_WHITESPACE(it) \
535 ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
536 || ((STRINGP (it->string) \
537 && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
538 || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
539 || (it->s \
540 && (it->s[IT_BYTEPOS (*it)] == ' ' \
541 || it->s[IT_BYTEPOS (*it)] == '\t')) \
542 || (IT_BYTEPOS (*it) < ZV_BYTE \
543 && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
544 || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))
545
546
547
548 #define NOT_AT_EOL '<'
549 #define NOT_AT_BOL '>'
550 #define LINE_BREAKABLE '|'
551
552 static bool
553 it_char_has_category(struct it *it, int cat)
554 {
555 int ch = 0;
556 if (it->what == IT_CHARACTER)
557 ch = it->c;
558 else if (STRINGP (it->string))
559 ch = SREF (it->string, IT_STRING_BYTEPOS (*it));
560 else if (it->s)
561 ch = it->s[IT_BYTEPOS (*it)];
562 else if (IT_BYTEPOS (*it) < ZV_BYTE)
563 ch = *BYTE_POS_ADDR (IT_BYTEPOS (*it));
564
565 if (ch == 0)
566 return false;
567 else
568 return CHAR_HAS_CATEGORY (ch, cat);
569 }
570
571
572 static bool
573 char_can_wrap_before (struct it *it)
574 {
575 if (!word_wrap_by_category)
576 return !IT_DISPLAYING_WHITESPACE (it);
577
578
579
580
581 int not_at_bol;
582 if (it->glyph_row && it->glyph_row->reversed_p)
583 not_at_bol = NOT_AT_EOL;
584 else
585 not_at_bol = NOT_AT_BOL;
586
587
588 return (!IT_DISPLAYING_WHITESPACE (it)
589
590 && !it_char_has_category (it, not_at_bol));
591 }
592
593
594 static bool
595 char_can_wrap_after (struct it *it)
596 {
597 if (!word_wrap_by_category)
598 return IT_DISPLAYING_WHITESPACE (it);
599
600
601
602
603 int not_at_eol;
604 if (it->glyph_row && it->glyph_row->reversed_p)
605 not_at_eol = NOT_AT_BOL;
606 else
607 not_at_eol = NOT_AT_EOL;
608
609 return (IT_DISPLAYING_WHITESPACE (it)
610
611 || (it_char_has_category (it, LINE_BREAKABLE)
612 && !it_char_has_category (it, not_at_eol)));
613 }
614
615 #undef IT_DISPLAYING_WHITESPACE
616 #undef NOT_AT_EOL
617 #undef NOT_AT_BOL
618 #undef LINE_BREAKABLE
619
620
621
622
623 static int
624 fill_column_indicator_column (struct it *it, int char_width)
625 {
626 if (display_fill_column_indicator
627 && !it->w->pseudo_window_p
628 && it->continuation_lines_width == 0
629 && CHARACTERP (Vdisplay_fill_column_indicator_character))
630 {
631 Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
632 ? BVAR (current_buffer, fill_column)
633 : Vdisplay_fill_column_indicator_column);
634
635
636
637 if (RANGED_FIXNUMP (0, col, INT_MAX))
638 {
639 int icol = XFIXNUM (col);
640 if (!INT_MULTIPLY_WRAPV (char_width, icol, &icol)
641 && !INT_ADD_WRAPV (it->lnum_pixel_width, icol, &icol))
642 return icol;
643 }
644 }
645 return -1;
646 }
647
648
649
650 bool noninteractive_need_newline;
651
652
653
654 static bool message_log_need_newline;
655
656
657
658
659 static Lisp_Object message_dolog_marker1;
660 static Lisp_Object message_dolog_marker2;
661 static Lisp_Object message_dolog_marker3;
662
663
664
665
666
667
668 static struct text_pos this_line_start_pos;
669
670
671
672
673 static struct text_pos this_line_end_pos;
674
675
676
677 static int this_line_vpos;
678 static int this_line_y;
679 static int this_line_pixel_height;
680
681
682
683
684 static int this_line_start_x;
685
686
687
688
689
690 static struct text_pos this_line_min_pos;
691
692
693
694 static struct buffer *this_line_buffer;
695
696
697
698 static bool overlay_arrow_seen;
699
700
701
702 static Lisp_Object default_invis_vector[3];
703
704
705
706
707
708 Lisp_Object echo_area_window;
709
710
711
712
713 static Lisp_Object Vmessage_stack;
714
715
716
717
718 static bool message_enable_multibyte;
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750 int windows_or_buffers_changed;
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771 int update_mode_lines;
772
773
774
775
776 static bool line_number_displayed;
777
778
779
780
781 Lisp_Object echo_area_buffer[2];
782
783
784
785 static Lisp_Object echo_buffer[2];
786
787
788
789 static Lisp_Object Vwith_echo_area_save_vector;
790
791
792
793
794 static bool display_last_displayed_message_p;
795
796
797
798
799 static bool message_buf_print;
800
801
802
803
804 static bool message_cleared_p;
805
806
807
808
809 #define MAX_SCRATCH_GLYPHS 100
810 static struct glyph_row scratch_glyph_row;
811 static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
812
813
814
815 static int last_height;
816
817
818
819 bool help_echo_showing_p;
820
821
822
823
824
825
826
827 #define TEXT_PROP_DISTANCE_LIMIT 100
828
829
830
831
832
833
834
835
836 #define SAVE_IT(ITCOPY, ITORIG, CACHE) \
837 do { \
838 if (CACHE) \
839 bidi_unshelve_cache (CACHE, true); \
840 ITCOPY = ITORIG; \
841 CACHE = bidi_shelve_cache (); \
842 } while (false)
843
844 #define RESTORE_IT(pITORIG, pITCOPY, CACHE) \
845 do { \
846 if (pITORIG != pITCOPY) \
847 *(pITORIG) = *(pITCOPY); \
848 bidi_unshelve_cache (CACHE, false); \
849 CACHE = NULL; \
850 } while (false)
851
852
853 enum { REDISPLAY_SOME = 2};
854
855 static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
856 struct font *, bool, int *);
857
858 void
859 redisplay_other_windows (void)
860 {
861 if (!windows_or_buffers_changed)
862 windows_or_buffers_changed = REDISPLAY_SOME;
863 }
864
865 void
866 wset_redisplay (struct window *w)
867 {
868
869 if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
870 redisplay_other_windows ();
871 w->redisplay = true;
872 }
873
874 void
875 fset_redisplay (struct frame *f)
876 {
877 redisplay_other_windows ();
878 f->redisplay = true;
879 }
880
881 void
882 bset_redisplay (struct buffer *b)
883 {
884 int count = buffer_window_count (b);
885 if (count > 0)
886 {
887
888 if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
889 redisplay_other_windows ();
890
891
892
893 b->text->redisplay = true;
894 }
895 }
896
897 void
898 bset_update_mode_line (struct buffer *b)
899 {
900 if (!update_mode_lines)
901 update_mode_lines = REDISPLAY_SOME;
902 b->text->redisplay = true;
903 }
904
905 void
906 wset_update_mode_line (struct window *w)
907 {
908 w->update_mode_line = true;
909
910
911
912
913
914
915 wset_redisplay (w);
916 }
917
918 DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
919 Sset_buffer_redisplay, 4, 4, 0,
920 doc:
921 )
922 (Lisp_Object symbol, Lisp_Object newval, Lisp_Object op, Lisp_Object where)
923 {
924 bset_update_mode_line (current_buffer);
925 current_buffer->prevent_redisplay_optimizations_p = true;
926 return Qnil;
927 }
928
929
930
931
932
933 #ifdef GLYPH_DEBUG
934 extern bool trace_redisplay_p EXTERNALLY_VISIBLE;
935 bool trace_redisplay_p;
936 #else
937 enum { trace_redisplay_p = false };
938 #endif
939 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
940 redisplay_trace (char const *fmt, ...)
941 {
942 if (trace_redisplay_p)
943 {
944 va_list ap;
945 va_start (ap, fmt);
946 vprintf (fmt, ap);
947 va_end (ap);
948 }
949 }
950
951 #ifdef DEBUG_TRACE_MOVE
952 extern bool trace_move EXTERNALLY_VISIBLE;
953 bool trace_move;
954 #else
955 enum { trace_move = false };
956 #endif
957 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
958 move_trace (char const *fmt, ...)
959 {
960 if (trace_move)
961 {
962 va_list ap;
963 va_start (ap, fmt);
964 vprintf (fmt, ap);
965 va_end (ap);
966 }
967 }
968
969
970
971 static struct buffer *displayed_buffer;
972
973
974
975 enum prop_handled
976 {
977 HANDLED_NORMALLY,
978 HANDLED_RECOMPUTE_PROPS,
979 HANDLED_OVERLAY_STRING_CONSUMED,
980 HANDLED_RETURN
981 };
982
983
984
985
986 struct props
987 {
988
989 short name;
990
991
992 enum prop_idx idx;
993
994
995
996 enum prop_handled (*handler) (struct it *it);
997 };
998
999 static enum prop_handled handle_face_prop (struct it *);
1000 static enum prop_handled handle_invisible_prop (struct it *);
1001 static enum prop_handled handle_display_prop (struct it *);
1002 static enum prop_handled handle_composition_prop (struct it *);
1003 static enum prop_handled handle_overlay_change (struct it *);
1004 static enum prop_handled handle_fontified_prop (struct it *);
1005
1006
1007
1008 static struct props it_props[] =
1009 {
1010 {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
1011
1012
1013 {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
1014 {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
1015 {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
1016 {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
1017 {0, 0, NULL}
1018 };
1019
1020
1021
1022 enum move_it_result
1023 {
1024
1025 MOVE_UNDEFINED,
1026
1027
1028 MOVE_POS_MATCH_OR_ZV,
1029
1030
1031 MOVE_X_REACHED,
1032
1033
1034
1035 MOVE_LINE_CONTINUED,
1036
1037
1038
1039 MOVE_LINE_TRUNCATED,
1040
1041
1042 MOVE_NEWLINE_OR_CR
1043 };
1044
1045
1046
1047
1048
1049
1050 #define CLEAR_FACE_CACHE_COUNT 500
1051 static int clear_face_cache_count;
1052
1053
1054
1055 #ifdef HAVE_WINDOW_SYSTEM
1056 #define CLEAR_IMAGE_CACHE_COUNT 101
1057 static int clear_image_cache_count;
1058
1059
1060 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
1061 #endif
1062
1063
1064
1065 bool redisplaying_p;
1066
1067
1068
1069
1070
1071
1072
1073
1074 bool display_working_on_window_p;
1075
1076
1077
1078
1079 Lisp_Object help_echo_string;
1080 Lisp_Object help_echo_window;
1081 Lisp_Object help_echo_object;
1082 ptrdiff_t help_echo_pos;
1083
1084
1085
1086 Lisp_Object previous_help_echo_string;
1087
1088
1089
1090 #ifdef HAVE_WINDOW_SYSTEM
1091
1092
1093 static bool hourglass_shown_p;
1094
1095
1096
1097 static struct atimer *hourglass_atimer;
1098
1099 #endif
1100
1101
1102
1103 #define DEFAULT_HOURGLASS_DELAY 1
1104
1105 #ifdef HAVE_WINDOW_SYSTEM
1106
1107
1108 #define THIN_SPACE_WIDTH 1
1109
1110 #endif
1111
1112
1113
1114 static void setup_for_ellipsis (struct it *, int);
1115 static void set_iterator_to_next (struct it *, bool);
1116 static void mark_window_display_accurate_1 (struct window *, bool);
1117 static bool row_for_charpos_p (struct glyph_row *, ptrdiff_t);
1118 static bool cursor_row_p (struct glyph_row *);
1119 static int redisplay_mode_lines (Lisp_Object, bool);
1120
1121 static void handle_line_prefix (struct it *);
1122
1123 static void handle_stop_backwards (struct it *, ptrdiff_t);
1124 static void unwind_with_echo_area_buffer (Lisp_Object);
1125 static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
1126 static bool current_message_1 (void *, Lisp_Object);
1127 static bool truncate_message_1 (void *, Lisp_Object);
1128 static void set_message (Lisp_Object);
1129 static bool set_message_1 (void *, Lisp_Object);
1130 static bool display_echo_area_1 (void *, Lisp_Object);
1131 static bool resize_mini_window_1 (void *, Lisp_Object);
1132 static void unwind_redisplay (void);
1133 static void extend_face_to_end_of_line (struct it *);
1134 static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
1135 static void push_it (struct it *, struct text_pos *);
1136 static void iterate_out_of_display_property (struct it *);
1137 static void pop_it (struct it *);
1138 static void redisplay_internal (void);
1139 static void echo_area_display (bool);
1140 static void block_buffer_flips (void);
1141 static void unblock_buffer_flips (void);
1142 static void redisplay_windows (Lisp_Object);
1143 static void redisplay_window (Lisp_Object, bool);
1144 static Lisp_Object redisplay_window_error (Lisp_Object);
1145 static Lisp_Object redisplay_window_0 (Lisp_Object);
1146 static Lisp_Object redisplay_window_1 (Lisp_Object);
1147 static bool set_cursor_from_row (struct window *, struct glyph_row *,
1148 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
1149 int, int);
1150 static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
1151 static bool update_menu_bar (struct frame *, bool, bool);
1152 static bool try_window_reusing_current_matrix (struct window *);
1153 static int try_window_id (struct window *);
1154 static void maybe_produce_line_number (struct it *);
1155 static bool should_produce_line_number (struct it *);
1156 static bool display_line (struct it *, int);
1157 static int display_mode_lines (struct window *);
1158 static int display_mode_line (struct window *, enum face_id, Lisp_Object);
1159 static int display_mode_element (struct it *, int, int, int, Lisp_Object,
1160 Lisp_Object, bool);
1161 static int store_mode_line_string (const char *, Lisp_Object, bool, int, int,
1162 Lisp_Object);
1163 static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
1164 static void display_menu_bar (struct window *);
1165 static void display_tab_bar (struct window *);
1166 static void update_tab_bar (struct frame *, bool);
1167 static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t,
1168 ptrdiff_t *);
1169 static void pint2str (register char *, register int, register ptrdiff_t);
1170
1171 static int display_string (const char *, Lisp_Object, Lisp_Object,
1172 ptrdiff_t, ptrdiff_t, struct it *, int, int, int,
1173 int);
1174 static void compute_line_metrics (struct it *);
1175 static bool get_overlay_strings (struct it *, ptrdiff_t);
1176 static bool get_overlay_strings_1 (struct it *, ptrdiff_t, bool);
1177 static void next_overlay_string (struct it *);
1178 static void reseat (struct it *, struct text_pos, bool);
1179 static void reseat_1 (struct it *, struct text_pos, bool);
1180 static bool next_element_from_display_vector (struct it *);
1181 static bool next_element_from_string (struct it *);
1182 static bool next_element_from_c_string (struct it *);
1183 static bool next_element_from_buffer (struct it *);
1184 static bool next_element_from_composition (struct it *);
1185 static bool next_element_from_image (struct it *);
1186 static bool next_element_from_stretch (struct it *);
1187 static bool next_element_from_xwidget (struct it *);
1188 static void load_overlay_strings (struct it *, ptrdiff_t);
1189 static bool get_next_display_element (struct it *);
1190 static enum move_it_result
1191 move_it_in_display_line_to (struct it *, ptrdiff_t, int,
1192 enum move_operation_enum);
1193 static void get_visually_first_element (struct it *);
1194 static void compute_stop_pos (struct it *);
1195 static int face_before_or_after_it_pos (struct it *, bool);
1196 static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
1197 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
1198 static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
1199 Lisp_Object, struct text_pos *,
1200 ptrdiff_t, int, bool, bool);
1201 static int underlying_face_id (const struct it *);
1202
1203 #define face_before_it_pos(IT) face_before_or_after_it_pos (IT, true)
1204 #define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false)
1205
1206 #ifdef HAVE_WINDOW_SYSTEM
1207
1208 static void update_tool_bar (struct frame *, bool);
1209 static void gui_draw_bottom_divider (struct window *w);
1210 static void notice_overwritten_cursor (struct window *,
1211 enum glyph_row_area,
1212 int, int, int, int);
1213 static int normal_char_height (struct font *, int);
1214 static void normal_char_ascent_descent (struct font *, int, int *, int *);
1215
1216 static void append_stretch_glyph (struct it *, Lisp_Object,
1217 int, int, int);
1218
1219 static Lisp_Object get_it_property (struct it *, Lisp_Object);
1220 static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
1221 struct font *, int, bool);
1222 static int adjust_glyph_width_for_mouse_face (struct glyph *,
1223 struct glyph_row *,
1224 struct window *, struct face *,
1225 struct face *);
1226 static void get_cursor_offset_for_mouse_face (struct window *w,
1227 struct glyph_row *row,
1228 int *offset);
1229 #endif
1230
1231 static void produce_special_glyphs (struct it *, enum display_element_type);
1232 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
1233 static bool coords_in_mouse_face_p (struct window *, int, int);
1234 static void reset_box_start_end_flags (struct it *);
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248 int
1249 window_text_bottom_y (struct window *w)
1250 {
1251 int height = WINDOW_PIXEL_HEIGHT (w);
1252
1253 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1254
1255 if (window_wants_mode_line (w))
1256 height -= CURRENT_MODE_LINE_HEIGHT (w);
1257
1258 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1259
1260 return height;
1261 }
1262
1263
1264
1265
1266
1267 int
1268 window_box_width (struct window *w, enum glyph_row_area area)
1269 {
1270 int width = w->pixel_width;
1271
1272 if (!w->pseudo_window_p)
1273 {
1274 width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
1275 width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
1276
1277 if (area == TEXT_AREA)
1278 width -= (WINDOW_MARGINS_WIDTH (w)
1279 + WINDOW_FRINGES_WIDTH (w));
1280 else if (area == LEFT_MARGIN_AREA)
1281 width = WINDOW_LEFT_MARGIN_WIDTH (w);
1282 else if (area == RIGHT_MARGIN_AREA)
1283 width = WINDOW_RIGHT_MARGIN_WIDTH (w);
1284 }
1285
1286
1287
1288 return max (0, width);
1289 }
1290
1291
1292
1293
1294
1295 int
1296 window_box_height (struct window *w)
1297 {
1298 struct frame *f = XFRAME (w->frame);
1299 int height = WINDOW_PIXEL_HEIGHT (w);
1300
1301 eassert (height >= 0);
1302
1303 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1304 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1305
1306
1307
1308
1309
1310
1311
1312 if (window_wants_mode_line (w))
1313 {
1314 if (w->mode_line_height >= 0)
1315 height -= w->mode_line_height;
1316 else
1317 {
1318 struct glyph_row *ml_row
1319 = (w->current_matrix && w->current_matrix->rows
1320 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1321 : 0);
1322 if (ml_row && ml_row->mode_line_p)
1323 height -= ml_row->height;
1324 else
1325 height -= estimate_mode_line_height
1326 (f, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w));
1327 }
1328 }
1329
1330 if (window_wants_tab_line (w))
1331 {
1332 if (w->tab_line_height >= 0)
1333 height -= w->tab_line_height;
1334 else
1335 {
1336 struct glyph_row *tl_row
1337 = (w->current_matrix && w->current_matrix->rows
1338 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
1339 : 0);
1340 if (tl_row && tl_row->mode_line_p)
1341 height -= tl_row->height;
1342 else
1343 height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
1344 }
1345 }
1346
1347 if (window_wants_header_line (w))
1348 {
1349 if (w->header_line_height >= 0)
1350 height -= w->header_line_height;
1351 else
1352 {
1353 struct glyph_row *hl_row
1354 = (w->current_matrix && w->current_matrix->rows
1355 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1356 : 0);
1357 if (hl_row && hl_row->mode_line_p)
1358 height -= hl_row->height;
1359 else
1360 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1361 }
1362 }
1363
1364
1365
1366 return max (0, height);
1367 }
1368
1369
1370
1371
1372
1373 int
1374 window_box_left_offset (struct window *w, enum glyph_row_area area)
1375 {
1376 int x;
1377
1378 if (w->pseudo_window_p)
1379 return 0;
1380
1381 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1382
1383 if (area == TEXT_AREA)
1384 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1385 + window_box_width (w, LEFT_MARGIN_AREA));
1386 else if (area == RIGHT_MARGIN_AREA)
1387 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1388 + window_box_width (w, LEFT_MARGIN_AREA)
1389 + window_box_width (w, TEXT_AREA)
1390 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1391 ? 0
1392 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1393 else if (area == LEFT_MARGIN_AREA
1394 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1395 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1396
1397
1398 return min (x, w->pixel_width);
1399 }
1400
1401
1402
1403
1404
1405
1406 static int
1407 window_box_right_offset (struct window *w, enum glyph_row_area area)
1408 {
1409
1410 return min (window_box_left_offset (w, area) + window_box_width (w, area),
1411 w->pixel_width);
1412 }
1413
1414
1415
1416
1417
1418 int
1419 window_box_left (struct window *w, enum glyph_row_area area)
1420 {
1421 struct frame *f = XFRAME (w->frame);
1422 int x;
1423
1424 if (w->pseudo_window_p)
1425 return FRAME_INTERNAL_BORDER_WIDTH (f);
1426
1427 x = (WINDOW_LEFT_EDGE_X (w)
1428 + window_box_left_offset (w, area));
1429
1430 return x;
1431 }
1432
1433
1434
1435
1436
1437
1438 int
1439 window_box_right (struct window *w, enum glyph_row_area area)
1440 {
1441 return window_box_left (w, area) + window_box_width (w, area);
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451 void
1452 window_box (struct window *w, enum glyph_row_area area, int *box_x,
1453 int *box_y, int *box_width, int *box_height)
1454 {
1455 if (box_width)
1456 *box_width = window_box_width (w, area);
1457 if (box_height)
1458 *box_height = window_box_height (w);
1459 if (box_x)
1460 *box_x = window_box_left (w, area);
1461 if (box_y)
1462 {
1463 *box_y = WINDOW_TOP_EDGE_Y (w);
1464 if (window_wants_tab_line (w))
1465 *box_y += CURRENT_TAB_LINE_HEIGHT (w);
1466 if (window_wants_header_line (w))
1467 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1468 }
1469 }
1470
1471 #ifdef HAVE_WINDOW_SYSTEM
1472
1473
1474
1475
1476
1477
1478
1479
1480 static void
1481 window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
1482 int *bottom_right_x, int *bottom_right_y)
1483 {
1484 window_box (w, ANY_AREA, top_left_x, top_left_y,
1485 bottom_right_x, bottom_right_y);
1486 *bottom_right_x += *top_left_x;
1487 *bottom_right_y += *top_left_y;
1488 }
1489
1490 #endif
1491
1492
1493
1494
1495
1496
1497
1498
1499 int
1500 line_bottom_y (struct it *it)
1501 {
1502 int line_height = it->max_ascent + it->max_descent;
1503 int line_top_y = it->current_y;
1504
1505 if (line_height == 0)
1506 {
1507 if (last_height)
1508 line_height = last_height;
1509 else if (IT_CHARPOS (*it) < ZV)
1510 {
1511 move_it_by_lines (it, 1);
1512 line_height = (it->max_ascent || it->max_descent
1513 ? it->max_ascent + it->max_descent
1514 : last_height);
1515 }
1516 else
1517 {
1518 struct glyph_row *row = it->glyph_row;
1519
1520
1521 it->glyph_row = NULL;
1522 it->what = IT_CHARACTER;
1523 it->c = ' ';
1524 it->len = 1;
1525 PRODUCE_GLYPHS (it);
1526 line_height = it->ascent + it->descent;
1527 it->glyph_row = row;
1528 }
1529 }
1530
1531 return line_top_y + line_height;
1532 }
1533
1534 DEFUN ("line-pixel-height", Fline_pixel_height,
1535 Sline_pixel_height, 0, 0, 0,
1536 doc:
1537
1538 )
1539 (void)
1540 {
1541 struct it it;
1542 struct text_pos pt;
1543 struct window *w = XWINDOW (selected_window);
1544 struct buffer *old_buffer = NULL;
1545 Lisp_Object result;
1546
1547 if (XBUFFER (w->contents) != current_buffer)
1548 {
1549 old_buffer = current_buffer;
1550 set_buffer_internal_1 (XBUFFER (w->contents));
1551 }
1552 SET_TEXT_POS (pt, PT, PT_BYTE);
1553 void *itdata = bidi_shelve_cache ();
1554 start_display (&it, w, pt);
1555
1556
1557
1558 move_it_by_lines (&it, 0);
1559 it.vpos = it.current_y = 0;
1560 last_height = 0;
1561 result = make_fixnum (line_bottom_y (&it));
1562 if (old_buffer)
1563 set_buffer_internal_1 (old_buffer);
1564
1565 bidi_unshelve_cache (itdata, false);
1566 return result;
1567 }
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583 int
1584 default_line_pixel_height (struct window *w)
1585 {
1586 struct frame *f = WINDOW_XFRAME (w);
1587 int height = FRAME_LINE_HEIGHT (f);
1588
1589 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1590 {
1591 struct buffer *b = XBUFFER (w->contents);
1592 Lisp_Object val = BVAR (b, extra_line_spacing);
1593
1594 if (NILP (val))
1595 val = BVAR (&buffer_defaults, extra_line_spacing);
1596 if (!NILP (val))
1597 {
1598 if (RANGED_FIXNUMP (0, val, INT_MAX))
1599 height += XFIXNAT (val);
1600 else if (FLOATP (val))
1601 {
1602 int addon = XFLOAT_DATA (val) * height + 0.5;
1603
1604 if (addon >= 0)
1605 height += addon;
1606 }
1607 }
1608 else
1609 height += f->extra_line_spacing;
1610 }
1611
1612 return height;
1613 }
1614
1615
1616
1617 static Lisp_Object
1618 string_from_display_spec (Lisp_Object spec)
1619 {
1620 if (VECTORP (spec))
1621 {
1622 for (ptrdiff_t i = 0; i < ASIZE (spec); i++)
1623 if (STRINGP (AREF (spec, i)))
1624 return AREF (spec, i);
1625 }
1626 else
1627 {
1628 for (; CONSP (spec); spec = XCDR (spec))
1629 if (STRINGP (XCAR (spec)))
1630 return XCAR (spec);
1631 }
1632 return spec;
1633 }
1634
1635
1636
1637
1638
1639 static int
1640 window_hscroll_limited (struct window *w, struct frame *f)
1641 {
1642 ptrdiff_t window_hscroll = w->hscroll;
1643 int window_text_width = window_box_width (w, TEXT_AREA);
1644 int colwidth = FRAME_COLUMN_WIDTH (f);
1645
1646 if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
1647 window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
1648
1649 return window_hscroll;
1650 }
1651
1652
1653
1654
1655
1656 static void
1657 reset_box_start_end_flags (struct it *it)
1658 {
1659
1660
1661 if (it->area == TEXT_AREA
1662
1663 && !(it->what == IT_IMAGE && it->image_id < 0))
1664 {
1665
1666
1667
1668
1669 if (it->face_box_p)
1670 it->start_of_box_run_p = false;
1671 it->end_of_box_run_p = false;
1672 }
1673 }
1674
1675
1676
1677
1678
1679
1680
1681 bool
1682 pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1683 int *rtop, int *rbot, int *rowh, int *vpos)
1684 {
1685 struct it it;
1686 void *itdata = bidi_shelve_cache ();
1687 struct text_pos top;
1688 bool visible_p = false;
1689 struct buffer *old_buffer = NULL;
1690 bool r2l = false;
1691
1692 if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
1693 return visible_p;
1694
1695 if (XBUFFER (w->contents) != current_buffer)
1696 {
1697 old_buffer = current_buffer;
1698 set_buffer_internal_1 (XBUFFER (w->contents));
1699 }
1700
1701 SET_TEXT_POS_FROM_MARKER (top, w->start);
1702
1703
1704
1705
1706 if (CHARPOS (top) > ZV || CHARPOS (top) < BEGV)
1707 SET_TEXT_POS (top, BEGV, BEGV_BYTE);
1708
1709
1710
1711 if (charpos >= 0 && CHARPOS (top) > charpos)
1712 return visible_p;
1713
1714
1715
1716
1717
1718
1719
1720
1721 int prev_mode_line_height = w->mode_line_height;
1722 int prev_header_line_height = w->header_line_height;
1723 int prev_tab_line_height = w->tab_line_height;
1724
1725 if (window_wants_mode_line (w))
1726 {
1727 Lisp_Object window_mode_line_format
1728 = window_parameter (w, Qmode_line_format);
1729
1730 w->mode_line_height
1731 = display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
1732 NILP (window_mode_line_format)
1733 ? BVAR (current_buffer, mode_line_format)
1734 : window_mode_line_format);
1735 }
1736
1737 if (window_wants_tab_line (w))
1738 {
1739 Lisp_Object window_tab_line_format
1740 = window_parameter (w, Qtab_line_format);
1741
1742 w->tab_line_height
1743 = display_mode_line (w, TAB_LINE_FACE_ID,
1744 NILP (window_tab_line_format)
1745 ? BVAR (current_buffer, tab_line_format)
1746 : window_tab_line_format);
1747 }
1748
1749 if (window_wants_header_line (w))
1750 {
1751 Lisp_Object window_header_line_format
1752 = window_parameter (w, Qheader_line_format);
1753
1754 w->header_line_height
1755 = display_mode_line (w, HEADER_LINE_FACE_ID,
1756 NILP (window_header_line_format)
1757 ? BVAR (current_buffer, header_line_format)
1758 : window_header_line_format);
1759 }
1760
1761 start_display (&it, w, top);
1762 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
1763 (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
1764
1765
1766
1767 if (!NILP (Vdisplay_line_numbers)
1768 && it.current_x >= it.first_visible_x
1769 && IT_CHARPOS (it) == charpos
1770 && !it.line_number_produced_p)
1771 {
1772
1773
1774
1775 if (!it.lnum_pixel_width)
1776 {
1777 struct it it2;
1778 void *it2data = NULL;
1779
1780 SAVE_IT (it2, it, it2data);
1781 move_it_by_lines (&it, 1);
1782 it2.lnum_pixel_width = it.lnum_pixel_width;
1783 RESTORE_IT (&it, &it2, it2data);
1784 }
1785 it.current_x += it.lnum_pixel_width;
1786 }
1787
1788 if (charpos >= 0
1789 && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
1790 && IT_CHARPOS (it) >= charpos)
1791
1792
1793
1794 || (it.bidi_p && it.bidi_it.scan_dir == -1
1795 && IT_CHARPOS (it) <= charpos)))
1796 {
1797
1798
1799
1800
1801
1802
1803 int top_x = it.current_x;
1804 int top_y = it.current_y;
1805 int window_top_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
1806 int bottom_y;
1807 struct it save_it;
1808 void *save_it_data = NULL;
1809
1810
1811 SAVE_IT (save_it, it, save_it_data);
1812 last_height = 0;
1813 bottom_y = line_bottom_y (&it);
1814 if (top_y < window_top_y)
1815 visible_p = bottom_y > window_top_y;
1816 else if (top_y < it.last_visible_y)
1817 visible_p = true;
1818 if (bottom_y >= it.last_visible_y
1819 && it.bidi_p && it.bidi_it.scan_dir == -1
1820 && IT_CHARPOS (it) < charpos)
1821 {
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832 int ten_more_lines = 10 * default_line_pixel_height (w);
1833
1834 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1835 MOVE_TO_POS | MOVE_TO_Y);
1836 if (it.current_y > top_y)
1837 visible_p = false;
1838
1839 }
1840 RESTORE_IT (&it, &save_it, save_it_data);
1841 if (visible_p)
1842 {
1843 if (it.method == GET_FROM_DISPLAY_VECTOR)
1844 {
1845
1846
1847 if (charpos < 2 || top.charpos >= charpos)
1848 top_x = it.glyph_row->x;
1849 else
1850 {
1851 struct it it2, it2_prev;
1852
1853
1854
1855
1856
1857
1858 start_display (&it2, w, top);
1859 it2.glyph_row = NULL;
1860 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
1861
1862
1863
1864
1865 if (IT_CHARPOS (it2) != charpos - 1)
1866 it2_prev = it2;
1867 else
1868 {
1869
1870
1871
1872 do {
1873 get_next_display_element (&it2);
1874 PRODUCE_GLYPHS (&it2);
1875 it2_prev = it2;
1876 set_iterator_to_next (&it2, true);
1877 } while (it2.method == GET_FROM_DISPLAY_VECTOR
1878 && IT_CHARPOS (it2) < charpos);
1879 }
1880 if (ITERATOR_AT_END_OF_LINE_P (&it2_prev)
1881 || it2_prev.current_x > it2_prev.last_visible_x)
1882 top_x = it.glyph_row->x;
1883 else
1884 {
1885 top_x = it2_prev.current_x;
1886 top_y = it2_prev.current_y;
1887 }
1888 }
1889 }
1890 else if (IT_CHARPOS (it) != charpos)
1891 {
1892 Lisp_Object cpos = make_fixnum (charpos);
1893 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1894 Lisp_Object string = string_from_display_spec (spec);
1895 struct text_pos tpos;
1896 bool newline_in_string
1897 = (STRINGP (string)
1898 && memchr (SDATA (string), '\n', SBYTES (string)));
1899
1900 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1901 bool replacing_spec_p
1902 = (!NILP (spec)
1903 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1904 charpos, FRAME_WINDOW_P (it.f)));
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921 if (replacing_spec_p)
1922 {
1923 Lisp_Object startpos, endpos;
1924 EMACS_INT start, end;
1925 struct it it3;
1926
1927
1928
1929 endpos =
1930 Fnext_single_char_property_change (cpos, Qdisplay,
1931 Qnil, Qnil);
1932 startpos =
1933 Fprevious_single_char_property_change (endpos, Qdisplay,
1934 Qnil, Qnil);
1935 start = XFIXNAT (startpos);
1936 end = XFIXNAT (endpos);
1937
1938
1939 start_display (&it3, w, top);
1940 if (start > CHARPOS (top))
1941 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
1942
1943
1944
1945
1946 if (it3.method == GET_FROM_BUFFER
1947 && (it3.c == '\n'
1948 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1949 move_it_by_lines (&it3, 1);
1950 else if (move_it_in_display_line_to (&it3, -1,
1951 it3.current_x
1952 + it3.pixel_width,
1953 MOVE_TO_X)
1954 == MOVE_LINE_CONTINUED)
1955 {
1956 move_it_by_lines (&it3, 1);
1957
1958
1959
1960 if (it3.line_wrap == WORD_WRAP)
1961 move_it_by_lines (&it3, -1);
1962 }
1963
1964
1965
1966 top_y = it3.current_y;
1967 if (it3.bidi_p)
1968 {
1969
1970
1971
1972
1973
1974 start_display (&it3, w, top);
1975 move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
1976 if (it3.current_y < top_y)
1977 top_y = it3.current_y;
1978 }
1979
1980
1981
1982 start_display (&it3, w, top);
1983 it3.glyph_row = NULL;
1984 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
1985
1986
1987
1988
1989
1990
1991
1992 bool it3_moved = false;
1993 int top_x_before_string = it3.current_x;
1994
1995
1996
1997
1998
1999 while (get_next_display_element (&it3))
2000 {
2001 if (!EQ (it3.object, string))
2002 top_x_before_string = it3.current_x;
2003 PRODUCE_GLYPHS (&it3);
2004 if ((it3.bidi_it.scan_dir == 1
2005 && IT_CHARPOS (it3) >= charpos)
2006 || (it3.bidi_it.scan_dir == -1
2007 && IT_CHARPOS (it3) <= charpos)
2008 || ITERATOR_AT_END_OF_LINE_P (&it3))
2009 break;
2010 it3_moved = true;
2011 set_iterator_to_next (&it3, false);
2012 }
2013 top_x = it3.current_x - it3.pixel_width;
2014
2015
2016
2017 if (!it3.line_number_produced_p)
2018 {
2019 if (it3.lnum_pixel_width > 0)
2020 {
2021 top_x += it3.lnum_pixel_width;
2022 top_x_before_string += it3.lnum_pixel_width;
2023 }
2024 else if (it.line_number_produced_p)
2025 {
2026 top_x += it.lnum_pixel_width;
2027 top_x_before_string += it3.lnum_pixel_width;
2028 }
2029 }
2030
2031
2032
2033
2034
2035
2036 if (it3_moved
2037 && newline_in_string
2038 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
2039 top_x = top_x_before_string;
2040 }
2041 }
2042
2043 *x = top_x;
2044
2045
2046
2047
2048 if (it.ascent == 0 && it.what == IT_IMAGE
2049 && it.method != GET_FROM_IMAGE
2050 && it.image_id < 0
2051 && it.max_ascent > 0)
2052 *y = max (top_y, window_top_y);
2053 else
2054 *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
2055 *rtop = max (0, window_top_y - top_y);
2056 *rbot = max (0, bottom_y - it.last_visible_y);
2057 *rowh = max (0, (min (bottom_y, it.last_visible_y)
2058 - max (top_y, window_top_y)));
2059 *vpos = it.vpos;
2060 if (it.bidi_it.paragraph_dir == R2L)
2061 r2l = true;
2062 }
2063 }
2064 else
2065 {
2066
2067
2068
2069 struct it it2;
2070 void *it2data = NULL;
2071
2072 SAVE_IT (it2, it, it2data);
2073 if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
2074 move_it_by_lines (&it, 1);
2075 if (charpos < IT_CHARPOS (it)
2076 || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
2077 {
2078 visible_p = true;
2079 RESTORE_IT (&it2, &it2, it2data);
2080 move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
2081 *x = it2.current_x;
2082 if (it2.ascent == 0 && it2.what == IT_IMAGE
2083 && it2.method != GET_FROM_IMAGE
2084 && it2.image_id < 0
2085 && it2.max_ascent > 0)
2086 *y = it2.current_y;
2087 else
2088 *y = it2.current_y + it2.max_ascent - it2.ascent;
2089 *rtop = max (0, -it2.current_y);
2090 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
2091 - it.last_visible_y));
2092 *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
2093 it.last_visible_y)
2094 - max (max (it2.current_y,
2095 WINDOW_TAB_LINE_HEIGHT (w)),
2096 WINDOW_HEADER_LINE_HEIGHT (w))));
2097 *vpos = it2.vpos;
2098 if (it2.bidi_it.paragraph_dir == R2L)
2099 r2l = true;
2100 }
2101 else
2102 bidi_unshelve_cache (it2data, true);
2103 }
2104 bidi_unshelve_cache (itdata, false);
2105
2106 if (old_buffer)
2107 set_buffer_internal_1 (old_buffer);
2108
2109 if (visible_p)
2110 {
2111 if (w->hscroll > 0)
2112 *x -=
2113 window_hscroll_limited (w, WINDOW_XFRAME (w))
2114 * WINDOW_FRAME_COLUMN_WIDTH (w);
2115
2116
2117
2118
2119
2120 if (r2l)
2121 *x = window_box_width (w, TEXT_AREA) - *x - 1;
2122 }
2123
2124 #if false
2125
2126 if (visible_p)
2127 fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
2128 charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
2129 else
2130 fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
2131 #endif
2132
2133
2134 w->mode_line_height = prev_mode_line_height;
2135 w->header_line_height = prev_header_line_height;
2136 w->tab_line_height = prev_tab_line_height;
2137
2138 return visible_p;
2139 }
2140
2141
2142
2143
2144
2145
2146
2147 static int
2148 check_char_and_length (const unsigned char *str, int *len)
2149 {
2150 int c = string_char_and_length (str, len);
2151 if (!CHAR_VALID_P (c))
2152
2153
2154
2155 c = '?';
2156
2157 return c;
2158 }
2159
2160
2161
2162
2163
2164
2165 static struct text_pos
2166 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
2167 {
2168 eassert (STRINGP (string) && nchars >= 0);
2169
2170 if (STRING_MULTIBYTE (string))
2171 {
2172 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
2173
2174 while (nchars--)
2175 {
2176 int len = BYTES_BY_CHAR_HEAD (*p);
2177 p += len;
2178 CHARPOS (pos) += 1;
2179 BYTEPOS (pos) += len;
2180 }
2181 }
2182 else
2183 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
2184
2185 return pos;
2186 }
2187
2188
2189
2190
2191
2192 static struct text_pos
2193 string_pos (ptrdiff_t charpos, Lisp_Object string)
2194 {
2195 struct text_pos pos;
2196 eassert (STRINGP (string));
2197 eassert (charpos >= 0);
2198 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
2199 return pos;
2200 }
2201
2202
2203
2204
2205
2206
2207 static struct text_pos
2208 c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
2209 {
2210 struct text_pos pos;
2211
2212 eassert (s != NULL);
2213 eassert (charpos >= 0);
2214
2215 if (multibyte_p)
2216 {
2217 SET_TEXT_POS (pos, 0, 0);
2218 while (charpos--)
2219 {
2220 int len = BYTES_BY_CHAR_HEAD (*s);
2221 s += len;
2222 CHARPOS (pos) += 1;
2223 BYTEPOS (pos) += len;
2224 }
2225 }
2226 else
2227 SET_TEXT_POS (pos, charpos, charpos);
2228
2229 return pos;
2230 }
2231
2232
2233
2234
2235
2236 static ptrdiff_t
2237 number_of_chars (const char *s, bool multibyte_p)
2238 {
2239 ptrdiff_t nchars;
2240
2241 if (multibyte_p)
2242 {
2243 ptrdiff_t rest = strlen (s);
2244 const unsigned char *p = (const unsigned char *) s;
2245
2246 for (nchars = 0; rest > 0; ++nchars)
2247 {
2248 int len = BYTES_BY_CHAR_HEAD (*p);
2249 rest -= len, p += len;
2250 }
2251 }
2252 else
2253 nchars = strlen (s);
2254
2255 return nchars;
2256 }
2257
2258
2259
2260
2261
2262
2263 static void
2264 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
2265 {
2266 eassert (STRINGP (string));
2267 eassert (CHARPOS (*newpos) >= CHARPOS (pos));
2268
2269 if (STRING_MULTIBYTE (string))
2270 *newpos = string_pos_nchars_ahead (pos, string,
2271 CHARPOS (*newpos) - CHARPOS (pos));
2272 else
2273 BYTEPOS (*newpos) = CHARPOS (*newpos);
2274 }
2275
2276
2277
2278
2279
2280 int
2281 estimate_mode_line_height (struct frame *f, enum face_id face_id)
2282 {
2283 #ifdef HAVE_WINDOW_SYSTEM
2284 if (FRAME_WINDOW_P (f))
2285 {
2286 int height = FONT_HEIGHT (FRAME_FONT (f));
2287
2288
2289
2290 if (FRAME_FACE_CACHE (f))
2291 {
2292 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2293 if (face)
2294 {
2295 if (face->font)
2296 height = normal_char_height (face->font, -1);
2297 if (face->box_horizontal_line_width > 0)
2298 height += 2 * face->box_horizontal_line_width;
2299 }
2300 }
2301
2302 return height;
2303 }
2304 #endif
2305
2306 return 1;
2307 }
2308
2309
2310
2311
2312
2313
2314 void
2315 pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2316 NativeRectangle *bounds, bool noclip)
2317 {
2318
2319 #ifdef HAVE_WINDOW_SYSTEM
2320 if (FRAME_WINDOW_P (f))
2321 {
2322
2323
2324 if (pix_x < 0)
2325 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
2326 if (pix_y < 0)
2327 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
2328
2329 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
2330 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
2331
2332 if (bounds)
2333 STORE_NATIVE_RECT (*bounds,
2334 FRAME_COL_TO_PIXEL_X (f, pix_x),
2335 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
2336 FRAME_COLUMN_WIDTH (f) - 1,
2337 FRAME_LINE_HEIGHT (f) - 1);
2338
2339
2340 if (!noclip)
2341 {
2342 if (pix_x < 0)
2343 pix_x = 0;
2344 else if (pix_x > FRAME_TOTAL_COLS (f))
2345 pix_x = FRAME_TOTAL_COLS (f);
2346
2347 if (pix_y < 0)
2348 pix_y = 0;
2349 else if (pix_y > FRAME_TOTAL_LINES (f))
2350 pix_y = FRAME_TOTAL_LINES (f);
2351 }
2352 }
2353 #endif
2354
2355 *x = pix_x;
2356 *y = pix_y;
2357 }
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368 struct glyph *
2369 x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2370 int *dx, int *dy, int *area)
2371 {
2372 struct glyph *glyph, *end;
2373 struct glyph_row *row = NULL;
2374 int x0, i;
2375
2376
2377 for (i = 0; i < w->current_matrix->nrows; ++i)
2378 {
2379 row = MATRIX_ROW (w->current_matrix, i);
2380 if (!row->enabled_p)
2381 return NULL;
2382 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
2383 break;
2384 }
2385
2386 *vpos = i;
2387 *hpos = 0;
2388
2389
2390 if (i == w->current_matrix->nrows)
2391 return NULL;
2392
2393
2394 if (w->pseudo_window_p)
2395 {
2396 *area = TEXT_AREA;
2397 x0 = 0;
2398 }
2399 else
2400 {
2401 if (x < window_box_left_offset (w, TEXT_AREA))
2402 {
2403 *area = LEFT_MARGIN_AREA;
2404 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
2405 }
2406 else if (x < window_box_right_offset (w, TEXT_AREA))
2407 {
2408 *area = TEXT_AREA;
2409 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
2410 }
2411 else
2412 {
2413 *area = RIGHT_MARGIN_AREA;
2414 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
2415 }
2416 }
2417
2418
2419 glyph = row->glyphs[*area];
2420 end = glyph + row->used[*area];
2421 x -= x0;
2422 while (glyph < end && x >= glyph->pixel_width)
2423 {
2424 x -= glyph->pixel_width;
2425 ++glyph;
2426 }
2427
2428 if (glyph == end)
2429 return NULL;
2430
2431 if (dx)
2432 {
2433 *dx = x;
2434 *dy = y - (row->y + row->ascent - glyph->ascent);
2435 }
2436
2437 *hpos = glyph - row->glyphs[*area];
2438 return glyph;
2439 }
2440
2441
2442
2443
2444 static void
2445 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
2446 {
2447 if (w->pseudo_window_p)
2448 {
2449
2450
2451 struct frame *f = XFRAME (w->frame);
2452 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
2453 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2454 }
2455 else
2456 {
2457 *x -= WINDOW_LEFT_EDGE_X (w);
2458 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2459 }
2460 }
2461
2462 #ifdef HAVE_WINDOW_SYSTEM
2463
2464
2465
2466
2467
2468 int
2469 get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int n)
2470 {
2471 Emacs_Rectangle r;
2472
2473 if (n <= 0)
2474 return 0;
2475
2476 if (s->row->full_width_p)
2477 {
2478
2479 r.x = WINDOW_LEFT_EDGE_X (s->w);
2480 if (s->row->mode_line_p)
2481 r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
2482 else
2483 r.width = WINDOW_PIXEL_WIDTH (s->w);
2484
2485
2486
2487 if (s->w->pseudo_window_p)
2488 r.height = s->row->visible_height;
2489 else
2490 r.height = s->height;
2491 }
2492 else
2493 {
2494
2495 r.x = window_box_left (s->w, s->area);
2496 r.width = window_box_width (s->w, s->area);
2497 r.height = s->row->visible_height;
2498 }
2499
2500 if (s->clip_head)
2501 if (r.x < s->clip_head->x)
2502 {
2503 if (r.width >= s->clip_head->x - r.x)
2504 r.width -= s->clip_head->x - r.x;
2505 else
2506 r.width = 0;
2507 r.x = s->clip_head->x;
2508 }
2509 if (s->clip_tail)
2510 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
2511 {
2512 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2513 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
2514 else
2515 r.width = 0;
2516 }
2517
2518
2519
2520
2521 if (s->for_overlaps)
2522 {
2523 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2524 r.height = window_text_bottom_y (s->w) - r.y;
2525
2526
2527
2528
2529
2530
2531 if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
2532 {
2533 Emacs_Rectangle rc, r_save = r;
2534
2535 rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
2536 rc.y = s->w->phys_cursor.y;
2537 rc.width = s->w->phys_cursor_width;
2538 rc.height = s->w->phys_cursor_height;
2539
2540 gui_intersect_rectangles (&r_save, &rc, &r);
2541 }
2542 }
2543 else
2544 {
2545
2546
2547
2548 if (!s->row->full_width_p
2549 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2550 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2551 else
2552 r.y = max (0, s->row->y);
2553 }
2554
2555 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
2556
2557
2558
2559 if (s->hl == DRAW_CURSOR)
2560 {
2561 struct glyph *glyph = s->first_glyph;
2562 int height, max_y;
2563
2564 if (s->x > r.x)
2565 {
2566 if (r.width >= s->x - r.x)
2567 r.width -= s->x - r.x;
2568 else
2569 r.width = 0;
2570 r.x = s->x;
2571 }
2572 r.width = min (r.width, glyph->pixel_width);
2573
2574
2575 height = min (glyph->ascent + glyph->descent,
2576 min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
2577 max_y = window_text_bottom_y (s->w) - height;
2578 max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
2579 if (s->ybase - glyph->ascent > max_y)
2580 {
2581 r.y = max_y;
2582 r.height = height;
2583 }
2584 else
2585 {
2586
2587 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2588 if (height < r.height)
2589 {
2590 max_y = r.y + r.height;
2591 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2592 r.height = min (max_y - r.y, height);
2593 }
2594 }
2595 }
2596
2597 if (s->row->clip)
2598 {
2599 Emacs_Rectangle r_save = r;
2600
2601 if (! gui_intersect_rectangles (&r_save, s->row->clip, &r))
2602 r.width = 0;
2603 }
2604
2605 if ((s->for_overlaps & OVERLAPS_BOTH) == 0
2606 || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
2607 {
2608 #ifdef CONVERT_FROM_EMACS_RECT
2609 CONVERT_FROM_EMACS_RECT (r, *rects);
2610 #else
2611 *rects = r;
2612 #endif
2613 return 1;
2614 }
2615 else
2616 {
2617
2618
2619
2620
2621 #ifdef CONVERT_FROM_EMACS_RECT
2622 Emacs_Rectangle rs[2];
2623 #else
2624 Emacs_Rectangle *rs = rects;
2625 #endif
2626 int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
2627
2628 if (s->for_overlaps & OVERLAPS_PRED)
2629 {
2630 rs[i] = r;
2631 if (r.y + r.height > row_y)
2632 {
2633 if (r.y < row_y)
2634 rs[i].height = row_y - r.y;
2635 else
2636 rs[i].height = 0;
2637 }
2638 i++;
2639 }
2640 if (s->for_overlaps & OVERLAPS_SUCC)
2641 {
2642 rs[i] = r;
2643 if (r.y < row_y + s->row->visible_height)
2644 {
2645 if (r.y + r.height > row_y + s->row->visible_height)
2646 {
2647 rs[i].y = row_y + s->row->visible_height;
2648 rs[i].height = r.y + r.height - rs[i].y;
2649 }
2650 else
2651 rs[i].height = 0;
2652 }
2653 i++;
2654 }
2655
2656 n = i;
2657 #ifdef CONVERT_FROM_EMACS_RECT
2658 for (i = 0; i < n; i++)
2659 CONVERT_FROM_EMACS_RECT (rs[i], rects[i]);
2660 #endif
2661 return n;
2662 }
2663 }
2664
2665
2666
2667
2668 void
2669 get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2670 {
2671 get_glyph_string_clip_rects (s, nr, 1);
2672 }
2673
2674
2675
2676
2677
2678
2679
2680 void
2681 get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2682 struct glyph *glyph, int *xp, int *yp, int *heightp)
2683 {
2684 struct frame *f = XFRAME (WINDOW_FRAME (w));
2685 int x, y, wd, h, h0, y0, ascent;
2686
2687
2688
2689
2690
2691 wd = glyph->pixel_width;
2692
2693 x = w->phys_cursor.x;
2694 if (x < 0)
2695 {
2696 wd += x;
2697 x = 0;
2698 }
2699
2700 if (glyph->type == STRETCH_GLYPH
2701 && !x_stretch_cursor_p)
2702 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2703 w->phys_cursor_width = wd;
2704
2705
2706
2707 y = w->phys_cursor.y;
2708 ascent = row->ascent;
2709
2710
2711
2712 if (!row->ends_at_zv_p && row->ascent < glyph->ascent)
2713 {
2714 y -= glyph->ascent - row->ascent;
2715 ascent = glyph->ascent;
2716 }
2717
2718
2719 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2720
2721 h = max (h0, ascent + glyph->descent);
2722
2723
2724 h = min (h, row->height);
2725 h0 = min (h0, ascent + glyph->descent);
2726
2727 y0 = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
2728 if (y < y0)
2729 {
2730 h = max (h - (y0 - y) + 1, h0);
2731 y = y0 - 1;
2732 }
2733 else
2734 {
2735 y0 = window_text_bottom_y (w) - h0;
2736 if (y > y0)
2737 {
2738 h += y - y0;
2739 y = y0;
2740 }
2741 }
2742
2743 *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
2744 *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2745 *heightp = h;
2746 }
2747
2748
2749
2750
2751
2752 void
2753 remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2754 {
2755 Lisp_Object window;
2756 struct window *w;
2757 struct glyph_row *r, *gr, *end_row;
2758 enum window_part part;
2759 enum glyph_row_area area;
2760 int x, y, width, height;
2761
2762 if (mouse_fine_grained_tracking)
2763 {
2764 STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
2765 return;
2766 }
2767
2768
2769
2770
2771 if (window_resize_pixelwise)
2772 {
2773 width = height = 1;
2774 goto virtual_glyph;
2775 }
2776 else if (!f->glyphs_initialized_p
2777 || (window = window_from_coordinates (f, gx, gy, &part, false, false),
2778 NILP (window)))
2779 {
2780 width = FRAME_SMALLEST_CHAR_WIDTH (f);
2781 height = FRAME_SMALLEST_FONT_HEIGHT (f);
2782 goto virtual_glyph;
2783 }
2784
2785 w = XWINDOW (window);
2786 width = WINDOW_FRAME_COLUMN_WIDTH (w);
2787 height = WINDOW_FRAME_LINE_HEIGHT (w);
2788
2789 x = window_relative_x_coord (w, part, gx);
2790 y = gy - WINDOW_TOP_EDGE_Y (w);
2791
2792 r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
2793 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
2794
2795 if (w->pseudo_window_p)
2796 {
2797 area = TEXT_AREA;
2798 part = ON_MODE_LINE;
2799 goto text_glyph;
2800 }
2801
2802 switch (part)
2803 {
2804 case ON_LEFT_MARGIN:
2805 area = LEFT_MARGIN_AREA;
2806 goto text_glyph;
2807
2808 case ON_RIGHT_MARGIN:
2809 area = RIGHT_MARGIN_AREA;
2810 goto text_glyph;
2811
2812 case ON_TAB_LINE:
2813 case ON_HEADER_LINE:
2814 case ON_MODE_LINE:
2815 gr = (part == ON_TAB_LINE
2816 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
2817 : (part == ON_HEADER_LINE
2818 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
2819 : MATRIX_MODE_LINE_ROW (w->current_matrix)));
2820 gy = gr->y;
2821 area = TEXT_AREA;
2822 goto text_glyph_row_found;
2823
2824 case ON_TEXT:
2825 area = TEXT_AREA;
2826
2827 text_glyph:
2828 gr = 0; gy = 0;
2829 for (; r <= end_row && r->enabled_p; ++r)
2830 if (r->y + r->height > y)
2831 {
2832 gr = r; gy = r->y;
2833 break;
2834 }
2835
2836 text_glyph_row_found:
2837 if (gr && gy <= y)
2838 {
2839 struct glyph *g = gr->glyphs[area];
2840 struct glyph *end = g + gr->used[area];
2841
2842 height = gr->height;
2843 for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
2844 if (gx + g->pixel_width > x)
2845 break;
2846
2847 if (g < end)
2848 {
2849 if (g->type == IMAGE_GLYPH)
2850 {
2851
2852
2853 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
2854 return;
2855 }
2856 width = g->pixel_width;
2857 }
2858 else
2859 {
2860
2861 x -= gx;
2862 gx += (x / width) * width;
2863 }
2864
2865 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2866 && part != ON_TAB_LINE)
2867 {
2868 gx += window_box_left_offset (w, area);
2869
2870
2871 height = min (height,
2872 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2873 }
2874 }
2875 else
2876 {
2877
2878 gx = (x / width) * width;
2879 y -= gy;
2880 gy += (y / height) * height;
2881 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2882 && part != ON_TAB_LINE)
2883
2884 height = min (height,
2885 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2886 }
2887 break;
2888
2889 case ON_LEFT_FRINGE:
2890 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2891 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2892 : window_box_right_offset (w, LEFT_MARGIN_AREA));
2893 width = WINDOW_LEFT_FRINGE_WIDTH (w);
2894 goto row_glyph;
2895
2896 case ON_RIGHT_FRINGE:
2897 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2898 ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
2899 : window_box_right_offset (w, TEXT_AREA));
2900 if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
2901 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
2902 && !WINDOW_RIGHTMOST_P (w))
2903 if (gx < WINDOW_PIXEL_WIDTH (w) - width)
2904
2905
2906 width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
2907 else
2908 width = WINDOW_PIXEL_WIDTH (w) - gx;
2909 else
2910 width = WINDOW_RIGHT_FRINGE_WIDTH (w);
2911
2912 goto row_glyph;
2913
2914 case ON_VERTICAL_BORDER:
2915 gx = WINDOW_PIXEL_WIDTH (w) - width;
2916 goto row_glyph;
2917
2918 case ON_VERTICAL_SCROLL_BAR:
2919 gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
2920 ? 0
2921 : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
2922 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2923 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
2924 : 0)));
2925 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2926
2927 row_glyph:
2928 gr = 0, gy = 0;
2929 for (; r <= end_row && r->enabled_p; ++r)
2930 if (r->y + r->height > y)
2931 {
2932 gr = r; gy = r->y;
2933 break;
2934 }
2935
2936 if (gr && gy <= y)
2937 height = gr->height;
2938 else
2939 {
2940
2941 y -= gy;
2942 gy += (y / height) * height;
2943 }
2944 break;
2945
2946 case ON_RIGHT_DIVIDER:
2947 gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
2948 width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
2949 gy = 0;
2950
2951 height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2952 goto add_edge;
2953
2954 case ON_BOTTOM_DIVIDER:
2955 gx = 0;
2956 width = WINDOW_PIXEL_WIDTH (w);
2957 gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2958 height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2959 goto add_edge;
2960
2961 default:
2962 ;
2963 virtual_glyph:
2964
2965
2966
2967
2968
2969
2970 if (gx < 0)
2971 gx -= width - 1;
2972 if (gy < 0)
2973 gy -= height - 1;
2974
2975 gx = (gx / width) * width;
2976 gy = (gy / height) * height;
2977
2978 goto store_rect;
2979 }
2980
2981 add_edge:
2982 gx += WINDOW_LEFT_EDGE_X (w);
2983 gy += WINDOW_TOP_EDGE_Y (w);
2984
2985 store_rect:
2986 STORE_NATIVE_RECT (*rect, gx, gy, width, height);
2987
2988
2989 #if false && defined HAVE_X_WINDOWS
2990 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2991 f->output_data.x->normal_gc,
2992 gx, gy, width, height);
2993 #endif
2994 }
2995
2996
2997 #endif
2998
2999 static void
3000 adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
3001 {
3002 eassert (w);
3003 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
3004 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
3005 w->window_end_vpos
3006 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
3007 }
3008
3009 static bool
3010 hscrolling_current_line_p (struct window *w)
3011 {
3012 return (!w->suspend_auto_hscroll
3013 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
3014 Qcurrent_line));
3015 }
3016
3017
3018
3019
3020
3021
3022
3023 static Lisp_Object
3024 safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
3025 {
3026 add_to_log ("Error during redisplay: %S signaled %S",
3027 Flist (nargs, args), arg);
3028 return Qnil;
3029 }
3030
3031
3032
3033
3034
3035 static Lisp_Object
3036 safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
3037 {
3038 Lisp_Object val;
3039
3040 if (inhibit_eval_during_redisplay)
3041 val = Qnil;
3042 else
3043 {
3044 ptrdiff_t i;
3045 specpdl_ref count = SPECPDL_INDEX ();
3046 Lisp_Object *args;
3047 USE_SAFE_ALLOCA;
3048 SAFE_ALLOCA_LISP (args, nargs);
3049
3050 args[0] = func;
3051 for (i = 1; i < nargs; i++)
3052 args[i] = va_arg (ap, Lisp_Object);
3053
3054 specbind (Qinhibit_redisplay, Qt);
3055 if (inhibit_quit)
3056 specbind (Qinhibit_quit, Qt);
3057
3058
3059 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
3060 safe_eval_handler);
3061 val = SAFE_FREE_UNBIND_TO (count, val);
3062 }
3063
3064 return val;
3065 }
3066
3067 Lisp_Object
3068 safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
3069 {
3070 Lisp_Object retval;
3071 va_list ap;
3072
3073 va_start (ap, func);
3074 retval = safe__call (false, nargs, func, ap);
3075 va_end (ap);
3076 return retval;
3077 }
3078
3079
3080
3081
3082 Lisp_Object
3083 safe_call1 (Lisp_Object fn, Lisp_Object arg)
3084 {
3085 return safe_call (2, fn, arg);
3086 }
3087
3088 static Lisp_Object
3089 safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
3090 {
3091 Lisp_Object retval;
3092 va_list ap;
3093
3094 va_start (ap, fn);
3095 retval = safe__call (inhibit_quit, 2, fn, ap);
3096 va_end (ap);
3097 return retval;
3098 }
3099
3100 Lisp_Object
3101 safe_eval (Lisp_Object sexpr)
3102 {
3103 return safe__call1 (false, Qeval, sexpr);
3104 }
3105
3106 static Lisp_Object
3107 safe__eval (bool inhibit_quit, Lisp_Object sexpr)
3108 {
3109 return safe__call1 (inhibit_quit, Qeval, sexpr);
3110 }
3111
3112
3113
3114
3115 Lisp_Object
3116 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
3117 {
3118 return safe_call (3, fn, arg1, arg2);
3119 }
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130 static void
3131 CHECK_IT (struct it *it)
3132 {
3133 #if false
3134 if (it->method == GET_FROM_STRING)
3135 {
3136 eassert (STRINGP (it->string));
3137 eassert (IT_STRING_CHARPOS (*it) >= 0);
3138 }
3139 else
3140 {
3141 eassert (IT_STRING_CHARPOS (*it) < 0);
3142 if (it->method == GET_FROM_BUFFER)
3143 {
3144
3145 eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
3146 }
3147 }
3148
3149 if (it->dpvec)
3150 eassert (it->current.dpvec_index >= 0);
3151 else
3152 eassert (it->current.dpvec_index < 0);
3153 #endif
3154 }
3155
3156
3157
3158
3159
3160 static void
3161 CHECK_WINDOW_END (struct window *w)
3162 {
3163 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3164 if (!MINI_WINDOW_P (w) && w->window_end_valid)
3165 {
3166 struct glyph_row *row;
3167 eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
3168 !row->enabled_p
3169 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
3170 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
3171 }
3172 #endif
3173 }
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198 void
3199 init_iterator (struct it *it, struct window *w,
3200 ptrdiff_t charpos, ptrdiff_t bytepos,
3201 struct glyph_row *row, enum face_id base_face_id)
3202 {
3203 enum face_id remapped_base_face_id = base_face_id;
3204 int body_width = 0, body_height = 0;
3205
3206
3207 eassert (w != NULL && it != NULL);
3208 eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
3209 && charpos <= ZV));
3210
3211
3212
3213
3214
3215 if (!inhibit_free_realized_faces)
3216 {
3217 if (face_change)
3218 {
3219 face_change = false;
3220 XFRAME (w->frame)->face_change = 0;
3221 free_all_realized_faces (Qnil);
3222 }
3223 else if (XFRAME (w->frame)->face_change)
3224 {
3225 XFRAME (w->frame)->face_change = 0;
3226 free_all_realized_faces (w->frame);
3227 }
3228 }
3229
3230
3231 if (! NILP (Vface_remapping_alist))
3232 remapped_base_face_id
3233 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
3234
3235
3236
3237 if (row == NULL)
3238 {
3239 if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
3240 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
3241 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
3242 else if (base_face_id == TAB_LINE_FACE_ID)
3243 row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
3244 else if (base_face_id == HEADER_LINE_FACE_ID)
3245 {
3246
3247 w->desired_matrix->tab_line_p = window_wants_tab_line (w);
3248 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
3249 }
3250 }
3251
3252
3253
3254 memclear (it, sizeof *it);
3255 it->current.overlay_string_index = -1;
3256 it->current.dpvec_index = -1;
3257 it->base_face_id = remapped_base_face_id;
3258 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3259 it->paragraph_embedding = L2R;
3260 it->bidi_it.w = w;
3261
3262
3263 XSETWINDOW (it->window, w);
3264 it->w = w;
3265 it->f = XFRAME (w->frame);
3266
3267 it->cmp_it.id = -1;
3268 it->cmp_it.parent_it = it;
3269
3270 if (max_redisplay_ticks > 0)
3271 update_redisplay_ticks (0, w);
3272
3273
3274 if (base_face_id == DEFAULT_FACE_ID
3275 && FRAME_WINDOW_P (it->f))
3276 {
3277 if (FIXNATP (BVAR (current_buffer, extra_line_spacing)))
3278 it->extra_line_spacing = XFIXNAT (BVAR (current_buffer, extra_line_spacing));
3279 else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
3280 it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
3281 * FRAME_LINE_HEIGHT (it->f));
3282 else if (it->f->extra_line_spacing > 0)
3283 it->extra_line_spacing = it->f->extra_line_spacing;
3284 }
3285
3286
3287
3288
3289
3290 if (FRAME_FACE_CACHE (it->f) == NULL)
3291 init_frame_faces (it->f);
3292 if (FRAME_FACE_CACHE (it->f)->used == 0)
3293 recompute_basic_faces (it->f);
3294
3295 it->override_ascent = -1;
3296
3297
3298 it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
3299
3300
3301
3302
3303 it->selective = (FIXNUMP (BVAR (current_buffer, selective_display))
3304 ? (clip_to_bounds
3305 (-1, XFIXNUM (BVAR (current_buffer, selective_display)),
3306 PTRDIFF_MAX))
3307 : (!NILP (BVAR (current_buffer, selective_display))
3308 ? -1 : 0));
3309 it->selective_display_ellipsis_p
3310 = !NILP (BVAR (current_buffer, selective_display_ellipses));
3311
3312
3313 it->dp = window_display_table (w);
3314
3315
3316 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
3317
3318 it->tab_width = SANE_TAB_WIDTH (current_buffer);
3319
3320
3321 if (TRUNCATE != 0)
3322 it->line_wrap = TRUNCATE;
3323 if (base_face_id == DEFAULT_FACE_ID
3324 && !it->w->hscroll
3325 && (WINDOW_FULL_WIDTH_P (it->w)
3326 || NILP (Vtruncate_partial_width_windows)
3327 || (FIXNUMP (Vtruncate_partial_width_windows)
3328
3329 && (XFIXNUM (Vtruncate_partial_width_windows)
3330 <= WINDOW_TOTAL_COLS (it->w))))
3331 && NILP (BVAR (current_buffer, truncate_lines)))
3332 it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
3333 ? WINDOW_WRAP : WORD_WRAP;
3334
3335
3336
3337
3338
3339
3340
3341 #ifdef HAVE_WINDOW_SYSTEM
3342 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3343 #endif
3344 {
3345 if (it->line_wrap == TRUNCATE)
3346 {
3347
3348 eassert (it->glyph_row == NULL);
3349 produce_special_glyphs (it, IT_TRUNCATION);
3350 it->truncation_pixel_width = it->pixel_width;
3351 }
3352 else
3353 {
3354
3355 eassert (it->glyph_row == NULL);
3356 produce_special_glyphs (it, IT_CONTINUATION);
3357 it->continuation_pixel_width = it->pixel_width;
3358 }
3359 }
3360
3361
3362
3363 it->pixel_width = it->ascent = it->descent = 0;
3364 it->phys_ascent = it->phys_descent = 0;
3365
3366
3367
3368
3369 it->glyph_row = row;
3370 it->area = TEXT_AREA;
3371
3372
3373
3374
3375
3376 if (base_face_id != DEFAULT_FACE_ID)
3377 {
3378
3379 it->first_visible_x = 0;
3380 it->last_visible_x =
3381 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3382 }
3383 else
3384 {
3385
3386
3387
3388
3389
3390
3391 if (hscrolling_current_line_p (w))
3392 {
3393 if (w->min_hscroll > 0)
3394 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
3395 else
3396 it->first_visible_x = 0;
3397 }
3398 else
3399 it->first_visible_x =
3400 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
3401
3402 body_width = window_box_width (w, TEXT_AREA);
3403 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3404 && body_width != w->old_body_pixel_width)
3405 FRAME_WINDOW_CHANGE (it->f) = true;
3406 it->last_visible_x = it->first_visible_x + body_width;
3407
3408
3409
3410
3411 if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
3412 {
3413 if (it->line_wrap == TRUNCATE)
3414 it->last_visible_x -= it->truncation_pixel_width;
3415 else
3416 it->last_visible_x -= it->continuation_pixel_width;
3417 }
3418
3419 it->tab_line_p = window_wants_tab_line (w);
3420 it->header_line_p = window_wants_header_line (w);
3421 body_height = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
3422 it->current_y = body_height + w->vscroll;
3423 }
3424
3425
3426 if (!FRAME_WINDOW_P (it->f)
3427 && !WINDOW_RIGHTMOST_P (it->w))
3428 it->last_visible_x -= 1;
3429
3430 it->last_visible_y = window_text_bottom_y (w);
3431 body_height += it->last_visible_y;
3432 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3433 && body_height != w->old_body_pixel_height)
3434 FRAME_WINDOW_CHANGE (it->f) = true;
3435
3436
3437
3438 if (base_face_id != DEFAULT_FACE_ID)
3439 {
3440 struct face *face;
3441
3442 it->face_id = remapped_base_face_id;
3443
3444
3445
3446 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3447 if (face && face->box != FACE_NO_BOX)
3448 {
3449 int box_thickness = face->box_vertical_line_width;
3450 it->face_box_p = true;
3451 it->start_of_box_run_p = true;
3452
3453
3454 if (box_thickness > 0)
3455 it->last_visible_x -= box_thickness;
3456 }
3457 }
3458
3459
3460
3461 if (charpos >= BUF_BEG (current_buffer))
3462 {
3463 it->stop_charpos = charpos;
3464 it->end_charpos = ZV;
3465 eassert (charpos == BYTE_TO_CHAR (bytepos));
3466 IT_CHARPOS (*it) = charpos;
3467 IT_BYTEPOS (*it) = bytepos;
3468
3469
3470
3471 it->face_id = it->base_face_id;
3472
3473 it->start = it->current;
3474
3475
3476
3477
3478
3479
3480
3481 it->bidi_p =
3482 !redisplay__inhibit_bidi
3483 && !NILP (BVAR (current_buffer, bidi_display_reordering))
3484 && it->multibyte_p;
3485
3486
3487
3488 if (it->bidi_p)
3489 {
3490
3491
3492
3493
3494 if (base_face_id == DEFAULT_FACE_ID
3495 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
3496 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
3497 {
3498 if (it->line_wrap == TRUNCATE)
3499 it->last_visible_x -= it->truncation_pixel_width;
3500 else
3501 it->last_visible_x -= it->continuation_pixel_width;
3502 }
3503
3504
3505 if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3506 Qleft_to_right))
3507 it->paragraph_embedding = L2R;
3508 else if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3509 Qright_to_left))
3510 it->paragraph_embedding = R2L;
3511 else
3512 it->paragraph_embedding = NEUTRAL_DIR;
3513 bidi_unshelve_cache (NULL, false);
3514 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
3515 &it->bidi_it);
3516 }
3517
3518
3519
3520 it->medium_narrowing_begv = 0;
3521
3522
3523 reseat (it, it->current.pos, true);
3524 }
3525
3526 CHECK_IT (it);
3527 }
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615 static int
3616 get_narrowed_width (struct window *w)
3617 {
3618
3619
3620 int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
3621
3622
3623
3624 int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
3625 - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
3626 || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
3627 return fact * max (1, width);
3628 }
3629
3630 static int
3631 get_narrowed_len (struct window *w)
3632 {
3633 int height = window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS);
3634 return get_narrowed_width (w) * max (1, height);
3635 }
3636
3637 static ptrdiff_t
3638 get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
3639 {
3640 int len = get_narrowed_len (w);
3641 return max ((pos / len - 1) * len, BEGV);
3642 }
3643
3644 static ptrdiff_t
3645 get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
3646 {
3647 int len = get_narrowed_len (w);
3648 return min ((pos / len + 1) * len, ZV);
3649 }
3650
3651
3652
3653
3654
3655
3656 static ptrdiff_t
3657 get_nearby_bol_pos (ptrdiff_t pos)
3658 {
3659 ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = pos;
3660 int dist;
3661 for (dist = 500; dist <= 500000; dist *= 10)
3662 {
3663 pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
3664 start = pos - dist < BEGV ? BEGV : pos - dist;
3665 for (cur = start; cur < pos; cur = next)
3666 {
3667 next = find_newline1 (cur, CHAR_TO_BYTE (cur),
3668 pos, pos_bytepos,
3669 1, &found, NULL, false);
3670 if (found)
3671 bol = next;
3672 else
3673 break;
3674 }
3675 if (bol >= BEGV || start == BEGV)
3676 break;
3677 else
3678 pos = pos - dist < BEGV ? BEGV : pos - dist;
3679 }
3680 eassert (bol <= init_pos);
3681 return bol;
3682 }
3683
3684 ptrdiff_t
3685 get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
3686 {
3687 int len = get_narrowed_width (w);
3688 ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
3689 return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
3690 }
3691
3692 ptrdiff_t
3693 get_large_narrowing_begv (ptrdiff_t pos)
3694 {
3695 if (long_line_optimizations_region_size <= 0)
3696 return BEGV;
3697 int len = long_line_optimizations_region_size / 2;
3698 int begv = max (pos - len, BEGV);
3699 int limit = long_line_optimizations_bol_search_limit;
3700 while (limit > 0)
3701 {
3702 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3703 return begv;
3704 begv--;
3705 limit--;
3706 }
3707 return begv;
3708 }
3709
3710 ptrdiff_t
3711 get_large_narrowing_zv (ptrdiff_t pos)
3712 {
3713 if (long_line_optimizations_region_size <= 0)
3714 return ZV;
3715 int len = long_line_optimizations_region_size / 2;
3716 return min (pos + len, ZV);
3717 }
3718
3719 static void
3720 unwind_narrowed_begv (Lisp_Object point_min)
3721 {
3722 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3723 }
3724
3725
3726
3727
3728 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
3729 do { \
3730 if (IT->medium_narrowing_begv) \
3731 { \
3732 specpdl_ref count = SPECPDL_INDEX (); \
3733 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3734 SET_BUF_BEGV (current_buffer, BV); \
3735 DST = EXPR; \
3736 unbind_to (count, Qnil); \
3737 } \
3738 else \
3739 DST = EXPR; \
3740 } while (0)
3741
3742
3743
3744 void
3745 start_display (struct it *it, struct window *w, struct text_pos pos)
3746 {
3747 struct glyph_row *row;
3748 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
3749
3750 row = w->desired_matrix->rows + first_vpos;
3751 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3752 it->first_vpos = first_vpos;
3753
3754
3755
3756 if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
3757 {
3758 int first_y = it->current_y;
3759
3760
3761
3762 bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
3763 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
3764 if (!start_at_line_beg_p)
3765 {
3766 int new_x;
3767
3768 reseat_at_previous_visible_line_start (it);
3769 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
3770
3771 new_x = it->current_x + it->pixel_width;
3772
3773
3774
3775
3776
3777
3778
3779 if (it->current_x > 0
3780 && it->line_wrap != TRUNCATE
3781 && (
3782 new_x > it->last_visible_x
3783
3784
3785 || (new_x == it->last_visible_x
3786 && FRAME_WINDOW_P (it->f)
3787 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
3788 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
3789 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
3790 {
3791 if ((it->current.dpvec_index >= 0
3792 || it->current.overlay_string_index >= 0)
3793
3794
3795
3796
3797
3798 && it->c != '\n')
3799 {
3800 set_iterator_to_next (it, true);
3801 move_it_in_display_line_to (it, -1, -1, 0);
3802 }
3803
3804 it->continuation_lines_width += it->current_x;
3805 }
3806
3807
3808
3809
3810
3811 else if (it->current.dpvec_index >= 0)
3812 it->current.dpvec_index = 0;
3813
3814
3815
3816
3817 it->max_ascent = it->max_descent = 0;
3818 it->max_phys_ascent = it->max_phys_descent = 0;
3819
3820 it->current_y = first_y;
3821 it->vpos = 0;
3822 it->current_x = it->hpos = 0;
3823 }
3824 }
3825 }
3826
3827
3828
3829
3830
3831 static bool
3832 in_ellipses_for_invisible_text_p (struct display_pos *pos, struct window *w)
3833 {
3834 Lisp_Object prop, window;
3835 bool ellipses_p = false;
3836 ptrdiff_t charpos = CHARPOS (pos->pos);
3837
3838
3839
3840
3841
3842 if (pos->dpvec_index >= 0
3843 && pos->overlay_string_index < 0
3844 && CHARPOS (pos->string_pos) < 0
3845 && charpos > BEGV
3846 && (XSETWINDOW (window, w),
3847 prop = Fget_char_property (make_fixnum (charpos),
3848 Qinvisible, window),
3849 TEXT_PROP_MEANS_INVISIBLE (prop) == 0))
3850 {
3851 prop = Fget_char_property (make_fixnum (charpos - 1), Qinvisible,
3852 window);
3853 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
3854 }
3855
3856 return ellipses_p;
3857 }
3858
3859
3860
3861
3862
3863
3864
3865 static bool
3866 init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
3867 {
3868 ptrdiff_t charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3869 int i;
3870 bool overlay_strings_with_newlines = false;
3871
3872
3873
3874
3875
3876 if (in_ellipses_for_invisible_text_p (pos, w))
3877 {
3878 --charpos;
3879 bytepos = 0;
3880 }
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
3892
3893
3894
3895
3896 for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
3897 {
3898 const char *s = SSDATA (it->overlay_strings[i]);
3899 const char *e = s + SBYTES (it->overlay_strings[i]);
3900
3901 while (s < e && *s != '\n')
3902 ++s;
3903
3904 if (s < e)
3905 {
3906 overlay_strings_with_newlines = true;
3907 break;
3908 }
3909 }
3910
3911
3912
3913 if (pos->overlay_string_index >= 0)
3914 {
3915 int relative_index;
3916
3917
3918
3919
3920
3921 if (it->method == GET_FROM_IMAGE)
3922 pop_it (it);
3923
3924
3925
3926
3927 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
3928 {
3929 ptrdiff_t n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
3930 it->current.overlay_string_index = 0;
3931 while (n--)
3932 {
3933 load_overlay_strings (it, 0);
3934 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
3935 }
3936 }
3937
3938 it->current.overlay_string_index = pos->overlay_string_index;
3939 relative_index = (it->current.overlay_string_index
3940 % OVERLAY_STRING_CHUNK_SIZE);
3941 it->string = it->overlay_strings[relative_index];
3942 eassert (STRINGP (it->string));
3943 it->current.string_pos = pos->string_pos;
3944 it->method = GET_FROM_STRING;
3945 it->end_charpos = SCHARS (it->string);
3946
3947 if (it->bidi_p)
3948 {
3949 it->bidi_it.string.lstring = it->string;
3950 it->bidi_it.string.s = NULL;
3951 it->bidi_it.string.schars = SCHARS (it->string);
3952 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
3953 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
3954 it->bidi_it.string.unibyte = !it->multibyte_p;
3955 it->bidi_it.w = it->w;
3956 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3957 FRAME_WINDOW_P (it->f), &it->bidi_it);
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967 if (CHARPOS (pos->string_pos) == 0)
3968 {
3969 get_visually_first_element (it);
3970 if (IT_STRING_CHARPOS (*it) != 0)
3971 do {
3972
3973 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
3974 bidi_move_to_visually_next (&it->bidi_it);
3975 } while (it->bidi_it.charpos != 0);
3976 }
3977 eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
3978 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
3979 }
3980 }
3981
3982 if (CHARPOS (pos->string_pos) >= 0)
3983 {
3984
3985
3986
3987 it->current.string_pos = pos->string_pos;
3988 eassert (STRINGP (it->string));
3989 if (it->bidi_p)
3990 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3991 FRAME_WINDOW_P (it->f), &it->bidi_it);
3992 }
3993
3994
3995
3996 if (pos->dpvec_index >= 0)
3997 {
3998 if (it->dpvec == NULL)
3999 get_next_display_element (it);
4000 eassert (it->dpvec && it->current.dpvec_index == 0);
4001 it->current.dpvec_index = pos->dpvec_index;
4002 }
4003
4004 CHECK_IT (it);
4005 return !overlay_strings_with_newlines;
4006 }
4007
4008
4009
4010
4011
4012 static void
4013 init_to_row_start (struct it *it, struct window *w, struct glyph_row *row)
4014 {
4015 init_from_display_pos (it, w, &row->start);
4016 it->start = row->start;
4017 it->continuation_lines_width = row->continuation_lines_width;
4018 CHECK_IT (it);
4019 }
4020
4021
4022
4023
4024
4025
4026
4027
4028 static bool
4029 init_to_row_end (struct it *it, struct window *w, struct glyph_row *row)
4030 {
4031 bool success = false;
4032
4033 if (init_from_display_pos (it, w, &row->end))
4034 {
4035 if (row->continued_p)
4036 it->continuation_lines_width
4037 = row->continuation_lines_width + row->pixel_width;
4038 CHECK_IT (it);
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048 if (get_next_display_element (it)
4049 && (it->bidi_it.scan_dir == -1 && it->cmp_it.id >= 0))
4050 success = false;
4051 else
4052 success = true;
4053 }
4054
4055 return success;
4056 }
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069 static void
4070 handle_stop (struct it *it)
4071 {
4072 enum prop_handled handled;
4073 bool handle_overlay_change_p;
4074 struct props *p;
4075
4076 it->dpvec = NULL;
4077 it->current.dpvec_index = -1;
4078 handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
4079 it->ellipsis_p = false;
4080
4081
4082 if (it->selective_display_ellipsis_p)
4083 it->saved_face_id = it->face_id;
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127 do
4128 {
4129 handled = HANDLED_NORMALLY;
4130
4131
4132 for (p = it_props; p->handler; ++p)
4133 {
4134 handled = p->handler (it);
4135
4136 if (handled == HANDLED_RECOMPUTE_PROPS)
4137 break;
4138 else if (handled == HANDLED_RETURN)
4139 {
4140
4141
4142 if (!handle_overlay_change_p
4143 || it->sp > 1
4144
4145
4146
4147
4148
4149
4150 || (it->current.overlay_string_index < 0
4151 && !get_overlay_strings_1 (it, 0, false)))
4152 {
4153 if (it->ellipsis_p)
4154 setup_for_ellipsis (it, 0);
4155
4156
4157
4158
4159
4160 if (STRINGP (it->string) && !SCHARS (it->string))
4161 pop_it (it);
4162 return;
4163 }
4164 else if (STRINGP (it->string) && !SCHARS (it->string))
4165 pop_it (it);
4166 else
4167 {
4168 it->string_from_display_prop_p = false;
4169 it->from_disp_prop_p = false;
4170 handle_overlay_change_p = false;
4171 }
4172 handled = HANDLED_RECOMPUTE_PROPS;
4173 break;
4174 }
4175 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
4176 handle_overlay_change_p = false;
4177 }
4178
4179 if (handled != HANDLED_RECOMPUTE_PROPS)
4180 {
4181
4182
4183 if (it->method == GET_FROM_DISPLAY_VECTOR)
4184 handle_overlay_change_p = false;
4185
4186
4187
4188
4189 if (handle_overlay_change_p)
4190 handled = handle_overlay_change (it);
4191 }
4192
4193 if (it->ellipsis_p)
4194 {
4195 setup_for_ellipsis (it, 0);
4196 break;
4197 }
4198 }
4199 while (handled == HANDLED_RECOMPUTE_PROPS);
4200
4201
4202 if (handled == HANDLED_NORMALLY)
4203 compute_stop_pos (it);
4204 }
4205
4206
4207
4208
4209
4210 static void
4211 compute_stop_pos (struct it *it)
4212 {
4213 register INTERVAL iv, next_iv;
4214 Lisp_Object object, limit, position;
4215 ptrdiff_t charpos, bytepos;
4216
4217 if (STRINGP (it->string))
4218 {
4219
4220
4221 it->stop_charpos = it->end_charpos;
4222 object = it->string;
4223 limit = Qnil;
4224 charpos = IT_STRING_CHARPOS (*it);
4225 bytepos = IT_STRING_BYTEPOS (*it);
4226 }
4227 else
4228 {
4229 ptrdiff_t pos;
4230
4231
4232
4233 if (it->end_charpos > ZV)
4234 it->end_charpos = ZV;
4235 it->stop_charpos = it->end_charpos;
4236
4237
4238
4239
4240
4241 charpos = IT_CHARPOS (*it);
4242 bytepos = IT_BYTEPOS (*it);
4243 pos = next_overlay_change (charpos);
4244 if (pos < it->stop_charpos)
4245 it->stop_charpos = pos;
4246
4247 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
4248 && !NILP (Vauto_composition_mode)
4249 && composition_break_at_point
4250 && charpos < PT && PT < it->stop_charpos)
4251 it->stop_charpos = PT;
4252
4253
4254
4255 XSETBUFFER (object, current_buffer);
4256 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4257
4258
4259
4260
4261
4262
4263 if (!composition_break_at_point
4264 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
4265 && !NILP (Vauto_composition_mode))
4266 {
4267 ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
4268 bool found = false;
4269
4270 if (pos > ZV)
4271 pos = ZV;
4272 if (endpos > ZV)
4273 endpos = ZV;
4274 ptrdiff_t bpos = CHAR_TO_BYTE (pos);
4275 while (pos < endpos)
4276 {
4277 int ch = fetch_char_advance_no_check (&pos, &bpos);
4278 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\f')
4279 {
4280 found = true;
4281 break;
4282 }
4283 }
4284 if (found)
4285 pos--;
4286 else if (it->stop_charpos < endpos)
4287 pos = it->stop_charpos;
4288 else
4289 {
4290
4291 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4292 }
4293 }
4294 limit = make_fixnum (pos);
4295 }
4296
4297
4298
4299 position = make_fixnum (charpos);
4300 iv = validate_interval_range (object, &position, &position, false);
4301 if (iv)
4302 {
4303 Lisp_Object values_here[LAST_PROP_IDX];
4304 struct props *p;
4305
4306
4307 for (p = it_props; p->handler; ++p)
4308 values_here[p->idx] = textget (iv->plist,
4309 builtin_lisp_symbol (p->name));
4310
4311
4312
4313 for (next_iv = next_interval (iv);
4314 (next_iv
4315 && (NILP (limit)
4316 || XFIXNAT (limit) > next_iv->position));
4317 next_iv = next_interval (next_iv))
4318 {
4319 for (p = it_props; p->handler; ++p)
4320 {
4321 Lisp_Object new_value = textget (next_iv->plist,
4322 builtin_lisp_symbol (p->name));
4323 if (!EQ (values_here[p->idx], new_value))
4324 break;
4325 }
4326
4327 if (p->handler)
4328 break;
4329 }
4330
4331 if (next_iv)
4332 {
4333 if (FIXNUMP (limit)
4334 && next_iv->position >= XFIXNAT (limit))
4335
4336 it->stop_charpos = min (XFIXNAT (limit), it->stop_charpos);
4337 else
4338
4339 it->stop_charpos = min (it->stop_charpos, next_iv->position);
4340 }
4341 }
4342
4343 if (it->cmp_it.id < 0)
4344 {
4345 ptrdiff_t stoppos = it->end_charpos;
4346
4347 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4348 stoppos = -1;
4349 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
4350 stoppos, it->string);
4351 }
4352
4353 eassert (STRINGP (it->string)
4354 || (it->stop_charpos >= BEGV
4355 && it->stop_charpos >= IT_CHARPOS (*it)));
4356 }
4357
4358
4359
4360
4361 #define MAX_DISP_SCAN 250
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375 ptrdiff_t
4376 compute_display_string_pos (struct text_pos *position,
4377 struct bidi_string_data *string,
4378 struct window *w,
4379 bool frame_window_p, int *disp_prop)
4380 {
4381
4382 Lisp_Object object, object1;
4383 Lisp_Object pos, spec, limpos;
4384 bool string_p = string && (STRINGP (string->lstring) || string->s);
4385 ptrdiff_t eob = string_p ? string->schars : ZV;
4386 ptrdiff_t begb = string_p ? 0 : BEGV;
4387 ptrdiff_t bufpos, charpos = CHARPOS (*position);
4388 ptrdiff_t lim =
4389 (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
4390 struct text_pos tpos;
4391 int rv = 0;
4392
4393 if (string && STRINGP (string->lstring))
4394 object1 = object = string->lstring;
4395 else if (w && !string_p)
4396 {
4397 XSETWINDOW (object, w);
4398 object1 = Qnil;
4399 }
4400 else
4401 object1 = object = Qnil;
4402
4403 *disp_prop = 1;
4404
4405 if (charpos >= eob
4406
4407
4408 || string->from_disp_str
4409
4410 || (string->s && !STRINGP (object)))
4411 {
4412 *disp_prop = 0;
4413 return eob;
4414 }
4415
4416
4417
4418 pos = make_fixnum (charpos);
4419 if (STRINGP (object))
4420 bufpos = string->bufpos;
4421 else
4422 bufpos = charpos;
4423 tpos = *position;
4424 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
4425 && (charpos <= begb
4426 || !EQ (Fget_char_property (make_fixnum (charpos - 1), Qdisplay,
4427 object),
4428 spec))
4429 && (rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos, bufpos,
4430 frame_window_p)))
4431 {
4432 if (rv == 2)
4433 *disp_prop = 2;
4434 return charpos;
4435 }
4436
4437
4438
4439 limpos = make_fixnum (lim);
4440 do {
4441 pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos);
4442 CHARPOS (tpos) = XFIXNAT (pos);
4443 if (CHARPOS (tpos) >= lim)
4444 {
4445 *disp_prop = 0;
4446 break;
4447 }
4448 if (STRINGP (object))
4449 BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
4450 else
4451 BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
4452 spec = Fget_char_property (pos, Qdisplay, object);
4453 if (!STRINGP (object))
4454 bufpos = CHARPOS (tpos);
4455 } while (NILP (spec)
4456 || !(rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos,
4457 bufpos, frame_window_p)));
4458 if (rv == 2)
4459 *disp_prop = 2;
4460
4461 return CHARPOS (tpos);
4462 }
4463
4464
4465
4466
4467
4468
4469 ptrdiff_t
4470 compute_display_string_end (ptrdiff_t charpos, struct bidi_string_data *string)
4471 {
4472
4473 Lisp_Object object =
4474 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
4475 Lisp_Object pos = make_fixnum (charpos);
4476 ptrdiff_t eob =
4477 (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
4478
4479 if (charpos >= eob || (string->s && !STRINGP (object)))
4480 return eob;
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496 if (NILP (Fget_char_property (pos, Qdisplay, object)))
4497 return -1;
4498
4499
4500
4501 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
4502
4503 return XFIXNAT (pos);
4504 }
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516 static enum prop_handled
4517 handle_fontified_prop (struct it *it)
4518 {
4519 Lisp_Object prop, pos;
4520 enum prop_handled handled = HANDLED_NORMALLY;
4521
4522 if (!NILP (Vmemory_full))
4523 return handled;
4524
4525
4526
4527
4528
4529 if (!STRINGP (it->string)
4530 && it->s == NULL
4531 && !NILP (Vfontification_functions)
4532 && !(input_was_pending && redisplay_skip_fontification_on_input)
4533 && !NILP (Vrun_hooks)
4534 && (pos = make_fixnum (IT_CHARPOS (*it)),
4535 prop = Fget_char_property (pos, Qfontified, Qnil),
4536
4537
4538 NILP (prop) && IT_CHARPOS (*it) < Z))
4539 {
4540 specpdl_ref count = SPECPDL_INDEX ();
4541 Lisp_Object val;
4542 struct buffer *obuf = current_buffer;
4543 ptrdiff_t begv = BEGV, zv = ZV;
4544 bool old_clip_changed = current_buffer->clip_changed;
4545 bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
4546
4547 val = Vfontification_functions;
4548 specbind (Qfontification_functions, Qnil);
4549
4550 eassert (it->end_charpos == ZV);
4551
4552 if (current_buffer->long_line_optimizations_p
4553 && long_line_optimizations_region_size > 0)
4554 {
4555 ptrdiff_t begv = it->large_narrowing_begv;
4556 ptrdiff_t zv = it->large_narrowing_zv;
4557 ptrdiff_t charpos = IT_CHARPOS (*it);
4558 if (charpos < begv || charpos > zv)
4559 {
4560 begv = get_large_narrowing_begv (charpos);
4561 zv = get_large_narrowing_zv (charpos);
4562 }
4563 if (begv != BEG || zv != Z)
4564 labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
4565 Qlong_line_optimizations_in_fontification_functions);
4566 }
4567
4568
4569
4570 it->f->inhibit_clear_image_cache = true;
4571
4572 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
4573 safe_call1 (val, pos);
4574 else
4575 {
4576 Lisp_Object fns, fn;
4577
4578 fns = Qnil;
4579
4580 for (; CONSP (val); val = XCDR (val))
4581 {
4582 fn = XCAR (val);
4583
4584 if (EQ (fn, Qt))
4585 {
4586
4587
4588
4589
4590
4591 for (fns = Fdefault_value (Qfontification_functions);
4592 CONSP (fns);
4593 fns = XCDR (fns))
4594 {
4595 fn = XCAR (fns);
4596 if (!EQ (fn, Qt))
4597 safe_call1 (fn, pos);
4598 }
4599 }
4600 else
4601 safe_call1 (fn, pos);
4602 }
4603 }
4604
4605 it->f->inhibit_clear_image_cache = saved_inhibit_flag;
4606 unbind_to (count, Qnil);
4607
4608
4609
4610
4611
4612
4613
4614
4615 if (obuf == current_buffer)
4616 {
4617 if (begv == BEGV && zv == ZV)
4618 current_buffer->clip_changed = old_clip_changed;
4619 }
4620
4621
4622 else if (BUFFER_LIVE_P (obuf))
4623 set_buffer_internal_1 (obuf);
4624
4625
4626
4627
4628
4629
4630 it->end_charpos = ZV;
4631
4632
4633
4634
4635 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
4636 handled = HANDLED_RECOMPUTE_PROPS;
4637 }
4638
4639 return handled;
4640 }
4641
4642
4643
4644
4645
4646
4647
4648 static int
4649 face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
4650 {
4651 ptrdiff_t next_stop;
4652
4653 if (!STRINGP (it->string))
4654 {
4655 return face_at_buffer_position (it->w,
4656 IT_CHARPOS (*it),
4657 &next_stop,
4658 (IT_CHARPOS (*it)
4659 + TEXT_PROP_DISTANCE_LIMIT),
4660 false, it->base_face_id,
4661 attr_filter);
4662 }
4663 else
4664 {
4665 int base_face_id;
4666 ptrdiff_t bufpos;
4667 int i;
4668 Lisp_Object from_overlay
4669 = (it->current.overlay_string_index >= 0
4670 ? it->string_overlays[it->current.overlay_string_index
4671 % OVERLAY_STRING_CHUNK_SIZE]
4672 : Qnil);
4673
4674
4675
4676
4677
4678
4679
4680 if (! NILP (from_overlay))
4681 for (i = it->sp - 1; i >= 0; i--)
4682 {
4683 if (it->stack[i].current.overlay_string_index >= 0)
4684 from_overlay
4685 = it->string_overlays[it->stack[i].current.overlay_string_index
4686 % OVERLAY_STRING_CHUNK_SIZE];
4687 else if (! NILP (it->stack[i].from_overlay))
4688 from_overlay = it->stack[i].from_overlay;
4689
4690 if (!NILP (from_overlay))
4691 break;
4692 }
4693
4694 if (! NILP (from_overlay))
4695 {
4696 bufpos = IT_CHARPOS (*it);
4697
4698
4699 base_face_id
4700 = face_for_overlay_string (it->w,
4701 IT_CHARPOS (*it),
4702 &next_stop,
4703 (IT_CHARPOS (*it)
4704 + TEXT_PROP_DISTANCE_LIMIT),
4705 false,
4706 from_overlay, attr_filter);
4707 }
4708 else
4709 {
4710 bufpos = 0;
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728 base_face_id = it->string_from_prefix_prop_p
4729 ? (!NILP (Vface_remapping_alist)
4730 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4731 : DEFAULT_FACE_ID)
4732 : underlying_face_id (it);
4733 }
4734
4735 return face_at_string_position (it->w,
4736 it->string,
4737 IT_STRING_CHARPOS (*it),
4738 bufpos,
4739 &next_stop,
4740 base_face_id, false,
4741 attr_filter);
4742 }
4743 }
4744
4745
4746
4747
4748 static enum prop_handled
4749 handle_face_prop (struct it *it)
4750 {
4751 specpdl_ref count = SPECPDL_INDEX ();
4752
4753
4754
4755 specbind (Qinhibit_quit, Qt);
4756 const int new_face_id = face_at_pos (it, 0);
4757 unbind_to (count, Qnil);
4758
4759
4760
4761
4762
4763
4764
4765
4766 if (new_face_id != it->face_id)
4767 {
4768 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
4769
4770
4771
4772 struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
4773
4774
4775
4776
4777 if (!STRINGP (it->string)
4778 && !old_face
4779 && IT_CHARPOS (*it) > BEG)
4780 {
4781 const int prev_face_id = face_before_it_pos (it);
4782
4783 old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
4784 }
4785
4786
4787
4788
4789 it->face_id = new_face_id;
4790
4791
4792 if (!(it->start_of_box_run_p && old_face && old_face->box))
4793 it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
4794 && (old_face == NULL || !old_face->box));
4795 it->face_box_p = new_face->box != FACE_NO_BOX;
4796 }
4797
4798 return HANDLED_NORMALLY;
4799 }
4800
4801
4802
4803
4804
4805
4806
4807 static int
4808 underlying_face_id (const struct it *it)
4809 {
4810 int face_id = it->base_face_id, i;
4811
4812 eassert (STRINGP (it->string));
4813
4814 for (i = it->sp - 1; i >= 0; --i)
4815 if (NILP (it->stack[i].string))
4816 face_id = it->stack[i].face_id;
4817
4818 return face_id;
4819 }
4820
4821
4822
4823
4824
4825
4826
4827 static int
4828 face_before_or_after_it_pos (struct it *it, bool before_p)
4829 {
4830 int face_id, limit;
4831 ptrdiff_t next_check_charpos;
4832 struct it it_copy;
4833 void *it_copy_data = NULL;
4834
4835 eassert (it->s == NULL);
4836
4837 if (STRINGP (it->string))
4838 {
4839 ptrdiff_t bufpos, charpos;
4840 int base_face_id;
4841
4842
4843
4844
4845
4846 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
4847 || (IT_STRING_CHARPOS (*it) == 0 && before_p)
4848 || it->current_x <= it->first_visible_x)
4849 return it->face_id;
4850
4851 if (!it->bidi_p)
4852 {
4853
4854
4855
4856 if (before_p)
4857 charpos = IT_STRING_CHARPOS (*it) - 1;
4858 else if (it->what == IT_COMPOSITION)
4859
4860
4861 charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars;
4862 else
4863 charpos = IT_STRING_CHARPOS (*it) + 1;
4864 }
4865 else
4866 {
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877 SAVE_IT (it_copy, *it, it_copy_data);
4878 IT_STRING_CHARPOS (it_copy) = 0;
4879 bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
4880 it_copy.bidi_it.scan_dir = 0;
4881
4882 do
4883 {
4884 charpos = it_copy.bidi_it.charpos;
4885 if (charpos >= SCHARS (it->string))
4886 break;
4887 bidi_move_to_visually_next (&it_copy.bidi_it);
4888 }
4889 while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
4890
4891 if (!before_p)
4892 {
4893
4894
4895
4896 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4897
4898
4899
4900 if (it_copy.bidi_it.first_elt)
4901 n++;
4902 while (n--)
4903 bidi_move_to_visually_next (&it_copy.bidi_it);
4904
4905 charpos = it_copy.bidi_it.charpos;
4906 }
4907
4908 RESTORE_IT (it, it, it_copy_data);
4909 }
4910 eassert (0 <= charpos && charpos <= SCHARS (it->string));
4911
4912 if (it->current.overlay_string_index >= 0)
4913 bufpos = IT_CHARPOS (*it);
4914 else
4915 bufpos = 0;
4916
4917 base_face_id = underlying_face_id (it);
4918
4919
4920 face_id = face_at_string_position (it->w, it->string, charpos,
4921 bufpos, &next_check_charpos,
4922 base_face_id, false, 0);
4923
4924
4925
4926
4927 if (STRING_MULTIBYTE (it->string))
4928 {
4929 struct text_pos pos1 = string_pos (charpos, it->string);
4930 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1);
4931 struct face *face = FACE_FROM_ID (it->f, face_id);
4932 int len, c = check_char_and_length (p, &len);
4933 face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string);
4934 }
4935 }
4936 else
4937 {
4938 struct text_pos pos;
4939
4940 if ((IT_CHARPOS (*it) >= ZV && !before_p)
4941 || (IT_CHARPOS (*it) <= BEGV && before_p))
4942 return it->face_id;
4943
4944 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
4945 pos = it->current.pos;
4946
4947 if (!it->bidi_p)
4948 {
4949 if (before_p)
4950 DEC_TEXT_POS (pos, it->multibyte_p);
4951 else
4952 {
4953 if (it->what == IT_COMPOSITION)
4954 {
4955
4956
4957 pos.charpos += it->cmp_it.nchars;
4958 pos.bytepos += it->len;
4959 }
4960 else
4961 INC_TEXT_POS (pos, it->multibyte_p);
4962 }
4963 }
4964 else
4965 {
4966 if (before_p)
4967 {
4968 int current_x;
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979 if (it->current_x <= it->first_visible_x)
4980 return it->face_id;
4981 SAVE_IT (it_copy, *it, it_copy_data);
4982
4983
4984
4985
4986
4987 current_x = it_copy.current_x;
4988 move_it_vertically_backward (&it_copy, 0);
4989 move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
4990 pos = it_copy.current.pos;
4991 RESTORE_IT (it, it, it_copy_data);
4992 }
4993 else
4994 {
4995
4996
4997
4998 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4999
5000 it_copy = *it;
5001
5002
5003
5004 if (it->bidi_it.first_elt)
5005 n++;
5006 while (n--)
5007 bidi_move_to_visually_next (&it_copy.bidi_it);
5008
5009 SET_TEXT_POS (pos,
5010 it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
5011 }
5012 }
5013 eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
5014
5015
5016 face_id = face_at_buffer_position (it->w,
5017 CHARPOS (pos),
5018 &next_check_charpos,
5019 limit, false, -1, 0);
5020
5021
5022
5023
5024 if (it->multibyte_p)
5025 {
5026 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
5027 struct face *face = FACE_FROM_ID (it->f, face_id);
5028 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
5029 }
5030 }
5031
5032 return face_id;
5033 }
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044 static enum prop_handled
5045 handle_invisible_prop (struct it *it)
5046 {
5047 enum prop_handled handled = HANDLED_NORMALLY;
5048 int invis;
5049 Lisp_Object prop;
5050
5051 if (STRINGP (it->string))
5052 {
5053 Lisp_Object end_charpos, limit;
5054
5055
5056
5057
5058 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
5059 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5060 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5061
5062 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5063 {
5064
5065
5066 bool display_ellipsis_p = (invis == 2);
5067 ptrdiff_t len, endpos;
5068
5069 handled = HANDLED_RECOMPUTE_PROPS;
5070
5071
5072
5073 endpos = len = SCHARS (it->string);
5074 XSETINT (limit, len);
5075 do
5076 {
5077 end_charpos
5078 = Fnext_single_property_change (end_charpos, Qinvisible,
5079 it->string, limit);
5080
5081
5082 eassert (FIXNUMP (end_charpos));
5083 if (FIXNUMP (end_charpos))
5084 {
5085 endpos = XFIXNAT (end_charpos);
5086 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5087 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5088 if (invis == 2)
5089 display_ellipsis_p = true;
5090 }
5091 else
5092 endpos = len;
5093 }
5094 while (invis != 0 && endpos < len);
5095
5096 if (display_ellipsis_p)
5097 it->ellipsis_p = true;
5098
5099 if (endpos < len)
5100 {
5101
5102 struct text_pos old;
5103 ptrdiff_t oldpos;
5104
5105 old = it->current.string_pos;
5106 oldpos = CHARPOS (old);
5107 if (it->bidi_p)
5108 {
5109 if (it->bidi_it.first_elt
5110 && it->bidi_it.charpos < SCHARS (it->string))
5111 bidi_paragraph_init (it->paragraph_embedding,
5112 &it->bidi_it, true);
5113
5114 do
5115 {
5116 bidi_move_to_visually_next (&it->bidi_it);
5117 }
5118 while (oldpos <= it->bidi_it.charpos
5119 && it->bidi_it.charpos < endpos
5120 && it->bidi_it.charpos < it->bidi_it.string.schars);
5121
5122 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5123 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5124 if (IT_CHARPOS (*it) >= endpos)
5125 it->prev_stop = endpos;
5126 }
5127 else
5128 {
5129 IT_STRING_CHARPOS (*it) = endpos;
5130 compute_string_pos (&it->current.string_pos, old, it->string);
5131 }
5132 }
5133 else
5134 {
5135
5136
5137
5138 if (it->current.overlay_string_index >= 0
5139 && !display_ellipsis_p)
5140 {
5141 next_overlay_string (it);
5142
5143
5144 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5145 }
5146 else
5147 {
5148 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
5149 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5150 }
5151 }
5152 }
5153 }
5154 else
5155 {
5156 ptrdiff_t newpos, next_stop, start_charpos, tem;
5157 Lisp_Object pos, overlay;
5158
5159
5160 tem = start_charpos = IT_CHARPOS (*it);
5161 pos = make_fixnum (tem);
5162 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5163 &overlay);
5164 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5165
5166
5167 if (invis != 0 && start_charpos < it->end_charpos)
5168 {
5169
5170
5171 bool display_ellipsis_p = invis == 2;
5172
5173 handled = HANDLED_RECOMPUTE_PROPS;
5174
5175
5176
5177 do
5178 {
5179
5180
5181
5182
5183
5184 newpos = skip_invisible (tem, &next_stop, ZV, it->window);
5185
5186
5187
5188
5189 if (newpos == tem || newpos >= ZV)
5190 invis = 0;
5191 else
5192 {
5193
5194
5195
5196
5197
5198
5199 pos = make_fixnum (newpos);
5200 prop = Fget_char_property (pos, Qinvisible, it->window);
5201 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5202 }
5203
5204
5205
5206 if (invis != 0)
5207 tem = next_stop;
5208
5209
5210
5211 if (invis == 2)
5212 display_ellipsis_p = true;
5213 }
5214 while (invis != 0);
5215
5216
5217 if (it->bidi_p)
5218 {
5219 ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
5220 bool on_newline
5221 = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
5222 bool after_newline
5223 = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
5224
5225
5226
5227
5228
5229
5230
5231
5232 if (on_newline || after_newline)
5233 {
5234 struct text_pos tpos;
5235 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
5236
5237 SET_TEXT_POS (tpos, newpos, bpos);
5238 reseat_1 (it, tpos, false);
5239
5240
5241
5242
5243
5244 if (on_newline)
5245 {
5246 it->bidi_it.first_elt = false;
5247 it->bidi_it.paragraph_dir = pdir;
5248 it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
5249 it->bidi_it.nchars = 1;
5250 it->bidi_it.ch_len = 1;
5251 }
5252 }
5253 else
5254 {
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5266 {
5267
5268
5269
5270
5271
5272
5273
5274 bidi_paragraph_init (it->paragraph_embedding,
5275 &it->bidi_it, true);
5276 }
5277 do
5278 {
5279 bidi_move_to_visually_next (&it->bidi_it);
5280 }
5281 while (it->stop_charpos <= it->bidi_it.charpos
5282 && it->bidi_it.charpos < newpos);
5283 IT_CHARPOS (*it) = it->bidi_it.charpos;
5284 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5285
5286
5287
5288
5289 if (IT_CHARPOS (*it) >= newpos)
5290 it->prev_stop = newpos;
5291 }
5292 }
5293 else
5294 {
5295 IT_CHARPOS (*it) = newpos;
5296 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
5297 }
5298
5299 if (display_ellipsis_p)
5300 {
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313 if (!STRINGP (it->object))
5314 {
5315 it->position.charpos = newpos - 1;
5316 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5317 }
5318 }
5319
5320
5321
5322
5323
5324
5325
5326 if (NILP (overlay)
5327 && get_overlay_strings (it, it->stop_charpos))
5328 {
5329 handled = HANDLED_RECOMPUTE_PROPS;
5330 if (it->sp > 0)
5331 {
5332 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345 it->stack[it->sp - 1].stop_charpos
5346 = CHARPOS (it->stack[it->sp - 1].current.pos);
5347 }
5348 }
5349 else if (display_ellipsis_p)
5350 {
5351 it->ellipsis_p = true;
5352
5353
5354
5355 handled = HANDLED_RETURN;
5356 }
5357 }
5358 }
5359
5360 return handled;
5361 }
5362
5363
5364
5365
5366
5367 static void
5368 setup_for_ellipsis (struct it *it, int len)
5369 {
5370
5371
5372 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5373 {
5374 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5375 it->dpvec = v->contents;
5376 it->dpend = v->contents + v->header.size;
5377 }
5378 else
5379 {
5380
5381 it->dpvec = default_invis_vector;
5382 it->dpend = default_invis_vector + 3;
5383 }
5384
5385 it->dpvec_char_len = len;
5386 it->current.dpvec_index = 0;
5387 it->dpvec_face_id = -1;
5388
5389
5390
5391
5392
5393
5394
5395
5396 if (it->saved_face_id >= 0)
5397 it->face_id = it->saved_face_id;
5398
5399
5400
5401 if (it->method == GET_FROM_BUFFER)
5402 it->ignore_overlay_strings_at_pos_p = false;
5403
5404 it->method = GET_FROM_DISPLAY_VECTOR;
5405 it->ellipsis_p = true;
5406 }
5407
5408
5409 static Lisp_Object
5410 find_display_property (Lisp_Object disp, Lisp_Object prop)
5411 {
5412 if (NILP (disp))
5413 return Qnil;
5414
5415 if (VECTORP (disp))
5416 {
5417 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5418 {
5419 Lisp_Object elem = AREF (disp, i);
5420 if (CONSP (elem)
5421 && CONSP (XCDR (elem))
5422 && EQ (XCAR (elem), prop))
5423 return XCAR (XCDR (elem));
5424 }
5425 return Qnil;
5426 }
5427
5428 else if (CONSP (disp)
5429 && CONSP (XCAR (disp)))
5430 {
5431 while (!NILP (disp))
5432 {
5433 Lisp_Object elem = XCAR (disp);
5434 if (CONSP (elem)
5435 && CONSP (XCDR (elem))
5436 && EQ (XCAR (elem), prop))
5437 return XCAR (XCDR (elem));
5438
5439
5440
5441 if (CONSP (XCDR (disp)))
5442 disp = XCDR (disp);
5443 else
5444 disp = Qnil;
5445 }
5446 return Qnil;
5447 }
5448
5449 else if (CONSP (disp)
5450 && CONSP (XCDR (disp))
5451 && EQ (XCAR (disp), prop))
5452 return XCAR (XCDR (disp));
5453 else
5454 return Qnil;
5455 }
5456
5457 static Lisp_Object
5458 get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object)
5459 {
5460 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5461 Qdisplay, object),
5462 prop);
5463 }
5464
5465 static void
5466 display_min_width (struct it *it, ptrdiff_t bufpos,
5467 Lisp_Object object, Lisp_Object width_spec)
5468 {
5469
5470
5471 if (!NILP (it->min_width_property)
5472 && !EQ (width_spec, it->min_width_property))
5473 {
5474 if (!it->glyph_row)
5475 return;
5476
5477
5478
5479
5480
5481 if ((bufpos == 0
5482 && !EQ (it->min_width_property,
5483 get_display_property (0, Qmin_width, object)))
5484
5485
5486 || (bufpos > BEGV
5487 && EQ (it->min_width_property,
5488 get_display_property (bufpos - 1, Qmin_width, object))))
5489 {
5490 Lisp_Object w = Qnil;
5491 double width;
5492 #ifdef HAVE_WINDOW_SYSTEM
5493 if (FRAME_WINDOW_P (it->f))
5494 {
5495 struct font *font = NULL;
5496 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5497 font = face->font ? face->font : FRAME_FONT (it->f);
5498 calc_pixel_width_or_height (&width, it,
5499 XCAR (it->min_width_property),
5500 font, true, NULL);
5501 width -= it->current_x - it->min_width_start;
5502 w = list1 (make_int (width));
5503 }
5504 else
5505 #endif
5506 {
5507 calc_pixel_width_or_height (&width, it,
5508 XCAR (it->min_width_property),
5509 NULL, true, NULL);
5510 width -= (it->current_x - it->min_width_start) /
5511 FRAME_COLUMN_WIDTH (it->f);
5512 w = make_int (width);
5513 }
5514
5515
5516 it->object = list3 (Qspace, QCwidth, w);
5517 produce_stretch_glyph (it);
5518 if (it->area == TEXT_AREA)
5519 it->current_x += it->pixel_width;
5520 it->min_width_property = Qnil;
5521 }
5522 }
5523
5524
5525
5526
5527 if (CONSP (width_spec))
5528 {
5529 if (bufpos == BEGV
5530
5531 || (bufpos == 0
5532 && !EQ (it->min_width_property,
5533 get_display_property (0, Qmin_width, object)))
5534
5535 || (bufpos > BEGV
5536 && !EQ (width_spec,
5537 get_display_property (bufpos - 1, Qmin_width, object))))
5538 {
5539 it->min_width_property = width_spec;
5540 it->min_width_start = it->current_x;
5541 }
5542 }
5543 }
5544
5545 DEFUN ("get-display-property", Fget_display_property,
5546 Sget_display_property, 2, 4, 0,
5547 doc:
5548
5549
5550
5551
5552 )
5553 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5554 Lisp_Object properties)
5555 {
5556 if (NILP (properties))
5557 properties = Fget_text_property (position, Qdisplay, object);
5558 else
5559 CHECK_LIST (properties);
5560
5561 return find_display_property (properties, prop);
5562 }
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576 static enum prop_handled
5577 handle_display_prop (struct it *it)
5578 {
5579 Lisp_Object propval, object, overlay;
5580 struct text_pos *position;
5581 ptrdiff_t bufpos;
5582
5583 int display_replaced = 0;
5584
5585 if (STRINGP (it->string))
5586 {
5587 object = it->string;
5588 position = &it->current.string_pos;
5589 bufpos = CHARPOS (it->current.pos);
5590 }
5591 else
5592 {
5593 XSETWINDOW (object, it->w);
5594 position = &it->current.pos;
5595 bufpos = CHARPOS (*position);
5596 }
5597
5598
5599 it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
5600 it->space_width = Qnil;
5601 it->font_height = Qnil;
5602 it->voffset = 0;
5603
5604
5605
5606
5607 if (!it->string_from_display_prop_p)
5608 it->area = TEXT_AREA;
5609
5610 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5611 Qdisplay, object, &overlay);
5612
5613
5614 if (!STRINGP (it->string))
5615 object = it->w->contents;
5616
5617
5618 if (!NILP (it->min_width_property)
5619 && NILP (find_display_property (propval, Qmin_width)))
5620 display_min_width (it, bufpos, object, Qnil);
5621
5622 if (NILP (propval))
5623 return HANDLED_NORMALLY;
5624
5625
5626
5627 display_replaced = handle_display_spec (it, propval, object, overlay,
5628 position, bufpos,
5629 FRAME_WINDOW_P (it->f));
5630 return display_replaced != 0 ? HANDLED_RETURN : HANDLED_NORMALLY;
5631 }
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649 static int
5650 handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5651 Lisp_Object overlay, struct text_pos *position,
5652 ptrdiff_t bufpos, bool frame_window_p)
5653 {
5654 int replacing = 0;
5655 bool enable_eval = true;
5656
5657
5658 if (CONSP (spec) && EQ (XCAR (spec), Qdisable_eval))
5659 {
5660 enable_eval = false;
5661 spec = CONSP (XCDR (spec)) ? XCAR (XCDR (spec)) : Qnil;
5662 }
5663
5664 if (CONSP (spec)
5665
5666 && !EQ (XCAR (spec), Qimage)
5667 #ifdef HAVE_XWIDGETS
5668 && !EQ (XCAR (spec), Qxwidget)
5669 #endif
5670 && !EQ (XCAR (spec), Qspace)
5671 && !EQ (XCAR (spec), Qwhen)
5672 && !EQ (XCAR (spec), Qslice)
5673 && !EQ (XCAR (spec), Qspace_width)
5674 && !EQ (XCAR (spec), Qheight)
5675 && !EQ (XCAR (spec), Qraise)
5676
5677 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5678 && !EQ (XCAR (spec), Qleft_fringe)
5679 && !EQ (XCAR (spec), Qright_fringe)
5680 && !EQ (XCAR (spec), Qmin_width)
5681 && !NILP (XCAR (spec)))
5682 {
5683 for (; CONSP (spec); spec = XCDR (spec))
5684 {
5685 int rv = handle_single_display_spec (it, XCAR (spec), object,
5686 overlay, position, bufpos,
5687 replacing, frame_window_p,
5688 enable_eval);
5689 if (rv != 0)
5690 {
5691 replacing = rv;
5692
5693
5694 if (!it || STRINGP (object))
5695 break;
5696 }
5697 }
5698 }
5699 else if (VECTORP (spec))
5700 {
5701 ptrdiff_t i;
5702 for (i = 0; i < ASIZE (spec); ++i)
5703 {
5704 int rv = handle_single_display_spec (it, AREF (spec, i), object,
5705 overlay, position, bufpos,
5706 replacing, frame_window_p,
5707 enable_eval);
5708 if (rv != 0)
5709 {
5710 replacing = rv;
5711
5712
5713 if (!it || STRINGP (object))
5714 break;
5715 }
5716 }
5717 }
5718 else
5719 replacing = handle_single_display_spec (it, spec, object, overlay, position,
5720 bufpos, 0, frame_window_p,
5721 enable_eval);
5722 return replacing;
5723 }
5724
5725
5726
5727
5728 static struct text_pos
5729 display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
5730 {
5731 Lisp_Object end;
5732 struct text_pos end_pos;
5733
5734 end = Fnext_single_char_property_change (make_fixnum (CHARPOS (start_pos)),
5735 Qdisplay, object, Qnil);
5736 CHARPOS (end_pos) = XFIXNAT (end);
5737 if (STRINGP (object))
5738 compute_string_pos (&end_pos, start_pos, it->string);
5739 else
5740 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFIXNAT (end));
5741
5742 return end_pos;
5743 }
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771 static int
5772 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5773 Lisp_Object overlay, struct text_pos *position,
5774 ptrdiff_t bufpos, int display_replaced,
5775 bool frame_window_p, bool enable_eval_p)
5776 {
5777 Lisp_Object form;
5778 Lisp_Object location, value;
5779 struct text_pos start_pos = *position;
5780 void *itdata = NULL;
5781
5782
5783
5784 form = Qt;
5785 if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
5786 {
5787 spec = XCDR (spec);
5788 if (!CONSP (spec))
5789 return 0;
5790 form = XCAR (spec);
5791 spec = XCDR (spec);
5792 }
5793
5794 if (!NILP (form) && !EQ (form, Qt) && !enable_eval_p)
5795 form = Qnil;
5796 if (!NILP (form) && !EQ (form, Qt))
5797 {
5798 specpdl_ref count = SPECPDL_INDEX ();
5799
5800
5801
5802
5803
5804
5805 if (NILP (object))
5806 XSETBUFFER (object, current_buffer);
5807 specbind (Qobject, object);
5808 specbind (Qposition, make_fixnum (CHARPOS (*position)));
5809 specbind (Qbuffer_position, make_fixnum (bufpos));
5810
5811
5812 itdata = bidi_shelve_cache ();
5813 form = safe_eval (form);
5814 bidi_unshelve_cache (itdata, false);
5815 form = unbind_to (count, form);
5816 }
5817
5818 if (NILP (form))
5819 return 0;
5820
5821
5822 if (CONSP (spec)
5823 && EQ (XCAR (spec), Qheight)
5824 && CONSP (XCDR (spec)))
5825 {
5826 if (it)
5827 {
5828 if (!FRAME_WINDOW_P (it->f))
5829 return 0;
5830
5831 it->font_height = XCAR (XCDR (spec));
5832 if (!NILP (it->font_height))
5833 {
5834 int new_height = -1;
5835
5836 if (CONSP (it->font_height)
5837 && (EQ (XCAR (it->font_height), Qplus)
5838 || EQ (XCAR (it->font_height), Qminus))
5839 && CONSP (XCDR (it->font_height))
5840 && RANGED_FIXNUMP (0, XCAR (XCDR (it->font_height)), INT_MAX))
5841 {
5842
5843 int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
5844 if (EQ (XCAR (it->font_height), Qplus))
5845 steps = - steps;
5846 it->face_id = smaller_face (it->f, it->face_id, steps);
5847 }
5848 else if (FUNCTIONP (it->font_height) && enable_eval_p)
5849 {
5850
5851
5852 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5853 Lisp_Object height;
5854 itdata = bidi_shelve_cache ();
5855 height = safe_call1 (it->font_height,
5856 face->lface[LFACE_HEIGHT_INDEX]);
5857 bidi_unshelve_cache (itdata, false);
5858 if (NUMBERP (height))
5859 new_height = XFLOATINT (height);
5860 }
5861 else if (NUMBERP (it->font_height))
5862 {
5863
5864 struct face *f;
5865
5866 f = FACE_FROM_ID (it->f,
5867 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
5868 new_height = (XFLOATINT (it->font_height)
5869 * XFIXNUM (f->lface[LFACE_HEIGHT_INDEX]));
5870 }
5871 else if (enable_eval_p)
5872 {
5873
5874
5875 specpdl_ref count = SPECPDL_INDEX ();
5876 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5877
5878 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
5879 itdata = bidi_shelve_cache ();
5880 value = safe_eval (it->font_height);
5881 bidi_unshelve_cache (itdata, false);
5882 value = unbind_to (count, value);
5883
5884 if (NUMBERP (value))
5885 new_height = XFLOATINT (value);
5886 }
5887
5888 if (new_height > 0)
5889 it->face_id = face_with_height (it->f, it->face_id, new_height);
5890 }
5891 }
5892
5893 return 0;
5894 }
5895
5896
5897 if (CONSP (spec)
5898 && EQ (XCAR (spec), Qspace_width)
5899 && CONSP (XCDR (spec)))
5900 {
5901 if (it)
5902 {
5903 if (!FRAME_WINDOW_P (it->f))
5904 return 0;
5905
5906 value = XCAR (XCDR (spec));
5907 if (NUMBERP (value) && XFLOATINT (value) > 0)
5908 it->space_width = value;
5909 }
5910
5911 return 0;
5912 }
5913
5914
5915 if (CONSP (spec)
5916 && EQ (XCAR (spec), Qmin_width)
5917 && CONSP (XCDR (spec))
5918 && CONSP (XCAR (XCDR (spec))))
5919 {
5920 if (it)
5921 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5922 return 0;
5923 }
5924
5925
5926 if (CONSP (spec)
5927 && EQ (XCAR (spec), Qslice))
5928 {
5929 Lisp_Object tem;
5930
5931 if (it)
5932 {
5933 if (!FRAME_WINDOW_P (it->f))
5934 return 0;
5935
5936 if (tem = XCDR (spec), CONSP (tem))
5937 {
5938 it->slice.x = XCAR (tem);
5939 if (tem = XCDR (tem), CONSP (tem))
5940 {
5941 it->slice.y = XCAR (tem);
5942 if (tem = XCDR (tem), CONSP (tem))
5943 {
5944 it->slice.width = XCAR (tem);
5945 if (tem = XCDR (tem), CONSP (tem))
5946 it->slice.height = XCAR (tem);
5947 }
5948 }
5949 }
5950 }
5951
5952 return 0;
5953 }
5954
5955
5956 if (CONSP (spec)
5957 && EQ (XCAR (spec), Qraise)
5958 && CONSP (XCDR (spec)))
5959 {
5960 if (it)
5961 {
5962 if (!FRAME_WINDOW_P (it->f))
5963 return 0;
5964
5965 #ifdef HAVE_WINDOW_SYSTEM
5966 value = XCAR (XCDR (spec));
5967 if (NUMBERP (value))
5968 {
5969 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5970 it->voffset = - (XFLOATINT (value)
5971 * (normal_char_height (face->font, -1)));
5972 }
5973 #endif
5974 }
5975
5976 return 0;
5977 }
5978
5979
5980
5981 if (it && it->string_from_display_prop_p)
5982 return 0;
5983
5984
5985
5986 if (it)
5987 {
5988 start_pos = *position;
5989 *position = display_prop_end (it, object, start_pos);
5990
5991
5992
5993
5994
5995
5996
5997 if (!NILP (overlay))
5998 {
5999 ptrdiff_t ovendpos = OVERLAY_END (overlay);
6000
6001
6002
6003
6004
6005
6006
6007 ovendpos = clip_to_bounds (BEGV, ovendpos, ZV);
6008
6009 if (ovendpos > CHARPOS (*position))
6010 SET_TEXT_POS (*position, ovendpos, CHAR_TO_BYTE (ovendpos));
6011 }
6012 }
6013 value = Qnil;
6014
6015
6016
6017 if (it)
6018 it->stop_charpos = position->charpos;
6019
6020
6021
6022 if (CONSP (spec)
6023 && (EQ (XCAR (spec), Qleft_fringe)
6024 || EQ (XCAR (spec), Qright_fringe))
6025 && CONSP (XCDR (spec)))
6026 {
6027 if (it)
6028 {
6029 if (!FRAME_WINDOW_P (it->f))
6030
6031
6032 {
6033
6034
6035
6036
6037 if (it->bidi_p)
6038 {
6039 it->position = *position;
6040 iterate_out_of_display_property (it);
6041 *position = it->position;
6042 }
6043 return 1;
6044 }
6045 }
6046 else if (!frame_window_p)
6047 return 1;
6048
6049 #ifdef HAVE_WINDOW_SYSTEM
6050 value = XCAR (XCDR (spec));
6051 int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
6052 if (! fringe_bitmap)
6053
6054
6055 {
6056 if (it && it->bidi_p)
6057 {
6058 it->position = *position;
6059 iterate_out_of_display_property (it);
6060 *position = it->position;
6061 }
6062 return 1;
6063 }
6064
6065 if (it)
6066 {
6067 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
6068
6069 if (CONSP (XCDR (XCDR (spec))))
6070 {
6071 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
6072 int face_id2;
6073
6074
6075
6076 specpdl_ref count1 = SPECPDL_INDEX ();
6077 specbind (Qinhibit_quit, Qt);
6078 face_id2 = lookup_derived_face (it->w, it->f, face_name,
6079 FRINGE_FACE_ID, false);
6080 unbind_to (count1, Qnil);
6081 if (face_id2 >= 0)
6082 face_id = face_id2;
6083 }
6084
6085
6086
6087 push_it (it, position);
6088
6089 it->area = TEXT_AREA;
6090 it->what = IT_IMAGE;
6091 it->image_id = -1;
6092 it->position = start_pos;
6093 it->object = NILP (object) ? it->w->contents : object;
6094 it->method = GET_FROM_IMAGE;
6095 it->from_overlay = Qnil;
6096 it->face_id = face_id;
6097 it->from_disp_prop_p = true;
6098
6099
6100
6101
6102 *position = start_pos;
6103
6104 if (EQ (XCAR (spec), Qleft_fringe))
6105 {
6106 it->left_user_fringe_bitmap = fringe_bitmap;
6107 it->left_user_fringe_face_id = face_id;
6108 }
6109 else
6110 {
6111 it->right_user_fringe_bitmap = fringe_bitmap;
6112 it->right_user_fringe_face_id = face_id;
6113 }
6114 }
6115 #endif
6116 return 1;
6117 }
6118
6119
6120
6121
6122 location = Qunbound;
6123 if (CONSP (spec) && CONSP (XCAR (spec)))
6124 {
6125 Lisp_Object tem;
6126
6127 value = XCDR (spec);
6128 if (CONSP (value))
6129 value = XCAR (value);
6130
6131 tem = XCAR (spec);
6132 if (EQ (XCAR (tem), Qmargin)
6133 && (tem = XCDR (tem),
6134 tem = CONSP (tem) ? XCAR (tem) : Qnil,
6135 (NILP (tem)
6136 || EQ (tem, Qleft_margin)
6137 || EQ (tem, Qright_margin))))
6138 location = tem;
6139 }
6140
6141 if (BASE_EQ (location, Qunbound))
6142 {
6143 location = Qnil;
6144 value = spec;
6145 }
6146
6147
6148
6149
6150
6151
6152
6153
6154 bool valid_p = (STRINGP (value)
6155 #ifdef HAVE_WINDOW_SYSTEM
6156 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6157 && valid_image_p (value))
6158 #endif
6159 || (CONSP (value) && EQ (XCAR (value), Qspace))
6160 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6161 && valid_xwidget_spec_p (value)));
6162
6163 if (valid_p && display_replaced == 0)
6164 {
6165 int retval = 1;
6166
6167 if (!it)
6168 {
6169
6170
6171
6172 if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
6173 retval = 2;
6174 return retval;
6175 }
6176
6177
6178
6179 push_it (it, position);
6180 it->from_overlay = overlay;
6181 it->from_disp_prop_p = true;
6182
6183 if (NILP (location))
6184 it->area = TEXT_AREA;
6185 else if (EQ (location, Qleft_margin))
6186 it->area = LEFT_MARGIN_AREA;
6187 else
6188 it->area = RIGHT_MARGIN_AREA;
6189
6190 if (STRINGP (value))
6191 {
6192 it->string = value;
6193 it->multibyte_p = STRING_MULTIBYTE (it->string);
6194 it->current.overlay_string_index = -1;
6195 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6196 it->end_charpos = it->string_nchars = SCHARS (it->string);
6197 it->method = GET_FROM_STRING;
6198 it->stop_charpos = 0;
6199 it->prev_stop = 0;
6200 it->base_level_stop = 0;
6201 it->string_from_display_prop_p = true;
6202 it->cmp_it.id = -1;
6203
6204
6205
6206 if (BUFFERP (object))
6207 *position = start_pos;
6208
6209
6210
6211
6212 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6213 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6214 else
6215 it->paragraph_embedding = L2R;
6216
6217
6218 if (it->bidi_p)
6219 {
6220 it->bidi_it.string.lstring = it->string;
6221 it->bidi_it.string.s = NULL;
6222 it->bidi_it.string.schars = it->end_charpos;
6223 it->bidi_it.string.bufpos = bufpos;
6224 it->bidi_it.string.from_disp_str = true;
6225 it->bidi_it.string.unibyte = !it->multibyte_p;
6226 it->bidi_it.w = it->w;
6227 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6228 }
6229 }
6230 else if (CONSP (value) && EQ (XCAR (value), Qspace))
6231 {
6232 it->method = GET_FROM_STRETCH;
6233 it->object = value;
6234 *position = it->position = start_pos;
6235 retval = 1 + (it->area == TEXT_AREA);
6236 }
6237 else if (valid_xwidget_spec_p (value))
6238 {
6239 it->what = IT_XWIDGET;
6240 it->method = GET_FROM_XWIDGET;
6241 it->position = start_pos;
6242 it->object = NILP (object) ? it->w->contents : object;
6243 *position = start_pos;
6244 it->xwidget = lookup_xwidget (value);
6245 }
6246 #ifdef HAVE_WINDOW_SYSTEM
6247 else
6248 {
6249 specpdl_ref count = SPECPDL_INDEX ();
6250
6251 it->what = IT_IMAGE;
6252
6253
6254
6255 specbind (Qinhibit_quit, Qt);
6256 it->image_id = lookup_image (it->f, value, it->face_id);
6257 unbind_to (count, Qnil);
6258 it->position = start_pos;
6259 it->object = NILP (object) ? it->w->contents : object;
6260 it->method = GET_FROM_IMAGE;
6261
6262
6263
6264
6265 *position = start_pos;
6266 }
6267 #endif
6268
6269 return retval;
6270 }
6271
6272
6273
6274 *position = start_pos;
6275 return 0;
6276 }
6277
6278
6279
6280
6281
6282
6283 bool
6284 display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
6285 ptrdiff_t charpos, ptrdiff_t bytepos)
6286 {
6287 bool frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
6288 struct text_pos position;
6289
6290 SET_TEXT_POS (position, charpos, bytepos);
6291 return (handle_display_spec (NULL, prop, Qnil, overlay,
6292 &position, charpos, frame_window_p)
6293 != 0);
6294 }
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305 static bool
6306 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
6307 {
6308 if (EQ (string, prop))
6309 return true;
6310
6311
6312 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
6313 {
6314 prop = XCDR (prop);
6315 if (!CONSP (prop))
6316 return false;
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327 prop = XCDR (prop);
6328 }
6329
6330 if (CONSP (prop))
6331
6332 if (EQ (XCAR (prop), Qmargin))
6333 {
6334 prop = XCDR (prop);
6335 if (!CONSP (prop))
6336 return false;
6337
6338 prop = XCDR (prop);
6339 if (!CONSP (prop))
6340 return false;
6341 }
6342
6343 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
6344 }
6345
6346
6347
6348
6349 static bool
6350 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
6351 {
6352 if (CONSP (prop)
6353 && !EQ (XCAR (prop), Qwhen)
6354 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
6355 {
6356
6357 while (CONSP (prop))
6358 {
6359 if (single_display_spec_string_p (XCAR (prop), string))
6360 return true;
6361 prop = XCDR (prop);
6362 }
6363 }
6364 else if (VECTORP (prop))
6365 {
6366
6367 ptrdiff_t i;
6368 for (i = 0; i < ASIZE (prop); ++i)
6369 if (single_display_spec_string_p (AREF (prop, i), string))
6370 return true;
6371 }
6372 else
6373 return single_display_spec_string_p (prop, string);
6374
6375 return false;
6376 }
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388 static ptrdiff_t
6389 string_buffer_position_lim (Lisp_Object string,
6390 ptrdiff_t from, ptrdiff_t to, bool back_p)
6391 {
6392 Lisp_Object limit, prop, pos;
6393 bool found = false;
6394
6395 pos = make_fixnum (max (from, BEGV));
6396
6397 if (!back_p)
6398 {
6399 limit = make_fixnum (min (to, ZV));
6400 while (!found && !EQ (pos, limit))
6401 {
6402 prop = Fget_char_property (pos, Qdisplay, Qnil);
6403 if (!NILP (prop) && display_prop_string_p (prop, string))
6404 found = true;
6405 else
6406 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
6407 limit);
6408 }
6409 }
6410 else
6411 {
6412 limit = make_fixnum (max (to, BEGV));
6413 while (!found && !EQ (pos, limit))
6414 {
6415 prop = Fget_char_property (pos, Qdisplay, Qnil);
6416 if (!NILP (prop) && display_prop_string_p (prop, string))
6417 found = true;
6418 else
6419 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
6420 limit);
6421 }
6422 }
6423
6424 return found ? XFIXNUM (pos) : 0;
6425 }
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436 static ptrdiff_t
6437 string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6438 {
6439 const int MAX_DISTANCE = 1000;
6440 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6441 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6442 forward_limit, false);
6443
6444 if (!found)
6445 {
6446 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6447 found = string_buffer_position_lim (string, around_charpos,
6448 backward_limit, true);
6449 }
6450 return found;
6451 }
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462 static enum prop_handled
6463 handle_composition_prop (struct it *it)
6464 {
6465 Lisp_Object prop, string;
6466 ptrdiff_t pos, pos_byte, start, end;
6467
6468 if (STRINGP (it->string))
6469 {
6470 unsigned char *s;
6471
6472 pos = IT_STRING_CHARPOS (*it);
6473 pos_byte = IT_STRING_BYTEPOS (*it);
6474 string = it->string;
6475 s = SDATA (string) + pos_byte;
6476 if (STRING_MULTIBYTE (string))
6477 it->c = STRING_CHAR (s);
6478 else
6479 it->c = *s;
6480 }
6481 else
6482 {
6483 pos = IT_CHARPOS (*it);
6484 pos_byte = IT_BYTEPOS (*it);
6485 string = Qnil;
6486 it->c = FETCH_CHAR (pos_byte);
6487 }
6488
6489
6490
6491
6492 if (find_composition (pos, -1, &start, &end, &prop, string)
6493 && composition_valid_p (start, end, prop)
6494 && (STRINGP (it->string) || (PT <= start || PT >= end)))
6495 {
6496 if (start < pos)
6497
6498
6499
6500 return HANDLED_NORMALLY;
6501 if (start != pos)
6502 {
6503 if (STRINGP (it->string))
6504 pos_byte = string_char_to_byte (it->string, start);
6505 else
6506 pos_byte = CHAR_TO_BYTE (start);
6507 }
6508 it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
6509 prop, string);
6510
6511 if (it->cmp_it.id >= 0)
6512 {
6513 it->cmp_it.ch = -1;
6514 it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
6515 it->cmp_it.nglyphs = -1;
6516 }
6517 }
6518
6519 return HANDLED_NORMALLY;
6520 }
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531 struct overlay_entry
6532 {
6533 Lisp_Object overlay;
6534 Lisp_Object string;
6535 EMACS_INT priority;
6536 bool after_string_p;
6537 };
6538
6539
6540
6541
6542
6543 static enum prop_handled
6544 handle_overlay_change (struct it *it)
6545 {
6546 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
6547 return HANDLED_RECOMPUTE_PROPS;
6548 else
6549 return HANDLED_NORMALLY;
6550 }
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560 static void
6561 next_overlay_string (struct it *it)
6562 {
6563 ++it->current.overlay_string_index;
6564 if (it->current.overlay_string_index == it->n_overlay_strings)
6565 {
6566
6567
6568
6569
6570 it->ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
6571 pop_it (it);
6572 eassert (it->sp > 0
6573 || (NILP (it->string)
6574 && it->method == GET_FROM_BUFFER
6575 && it->stop_charpos >= BEGV
6576 && it->stop_charpos <= it->end_charpos));
6577 it->current.overlay_string_index = -1;
6578 it->n_overlay_strings = 0;
6579
6580
6581
6582
6583 if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
6584 pop_it (it);
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594 if (it->overlay_strings_charpos == IT_CHARPOS (*it))
6595 it->ignore_overlay_strings_at_pos_p = true;
6596
6597
6598
6599
6600 if (NILP (it->string)
6601 && IT_CHARPOS (*it) >= it->end_charpos
6602 && it->overlay_strings_charpos >= it->end_charpos)
6603 it->overlay_strings_at_end_processed_p = true;
6604
6605
6606
6607
6608
6609
6610
6611 it->overlay_strings_charpos = -1;
6612 }
6613 else
6614 {
6615
6616
6617
6618
6619
6620
6621 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
6622
6623 if (it->current.overlay_string_index && i == 0)
6624 load_overlay_strings (it, it->overlay_strings_charpos);
6625
6626
6627
6628 it->string = it->overlay_strings[i];
6629 it->multibyte_p = STRING_MULTIBYTE (it->string);
6630 SET_TEXT_POS (it->current.string_pos, 0, 0);
6631 it->method = GET_FROM_STRING;
6632 it->stop_charpos = 0;
6633 it->end_charpos = SCHARS (it->string);
6634 if (it->cmp_it.stop_pos >= 0)
6635 it->cmp_it.stop_pos = 0;
6636 it->prev_stop = 0;
6637 it->base_level_stop = 0;
6638
6639
6640 if (it->bidi_p)
6641 {
6642 it->bidi_it.string.lstring = it->string;
6643 it->bidi_it.string.s = NULL;
6644 it->bidi_it.string.schars = SCHARS (it->string);
6645 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
6646 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6647 it->bidi_it.string.unibyte = !it->multibyte_p;
6648 it->bidi_it.w = it->w;
6649 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6650 }
6651 }
6652
6653 CHECK_IT (it);
6654 }
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673 static int
6674 compare_overlay_entries (const void *e1, const void *e2)
6675 {
6676 struct overlay_entry const *entry1 = e1;
6677 struct overlay_entry const *entry2 = e2;
6678 int result;
6679
6680 if (entry1->after_string_p != entry2->after_string_p)
6681 {
6682
6683
6684 if (EQ (entry1->overlay, entry2->overlay))
6685 result = entry1->after_string_p ? 1 : -1;
6686 else
6687 result = entry1->after_string_p ? -1 : 1;
6688 }
6689 else if (entry1->priority != entry2->priority)
6690 {
6691 if (entry1->after_string_p)
6692
6693 result = entry2->priority < entry1->priority ? -1 : 1;
6694 else
6695
6696 result = entry1->priority < entry2->priority ? -1 : 1;
6697 }
6698 else
6699 result = 0;
6700
6701 return result;
6702 }
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729 static void
6730 load_overlay_strings (struct it *it, ptrdiff_t charpos)
6731 {
6732 ptrdiff_t n = 0;
6733 struct overlay_entry entriesbuf[20];
6734 ptrdiff_t size = ARRAYELTS (entriesbuf);
6735 struct overlay_entry *entries = entriesbuf;
6736 struct itree_node *node;
6737
6738 USE_SAFE_ALLOCA;
6739
6740 if (charpos <= 0)
6741 charpos = IT_CHARPOS (*it);
6742
6743
6744
6745
6746
6747 #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
6748 do \
6749 { \
6750 Lisp_Object priority; \
6751 \
6752 if (n == size) \
6753 { \
6754 struct overlay_entry *old = entries; \
6755 SAFE_NALLOCA (entries, 2, size); \
6756 memcpy (entries, old, size * sizeof *entries); \
6757 size *= 2; \
6758 } \
6759 \
6760 entries[n].string = (STRING); \
6761 entries[n].overlay = (OVERLAY); \
6762 priority = Foverlay_get ((OVERLAY), Qpriority); \
6763 entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
6764 entries[n].after_string_p = (AFTER_P); \
6765 ++n; \
6766 } \
6767 while (false)
6768
6769
6770
6771 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6772 {
6773 Lisp_Object overlay = node->data;
6774 eassert (OVERLAYP (overlay));
6775 ptrdiff_t start = node->begin;
6776 ptrdiff_t end = node->end;
6777
6778
6779
6780 if (end != charpos && start != charpos)
6781 continue;
6782
6783
6784 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6785 if (WINDOWP (window) && XWINDOW (window) != it->w)
6786 continue;
6787
6788
6789
6790
6791 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6792 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6793
6794
6795 Lisp_Object str;
6796 if ((start == charpos || (end == charpos && invis != 0))
6797 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6798 && SCHARS (str))
6799 RECORD_OVERLAY_STRING (overlay, str, false);
6800
6801
6802 if ((end == charpos || (start == charpos && invis != 0))
6803 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6804 && SCHARS (str))
6805 RECORD_OVERLAY_STRING (overlay, str, true);
6806 }
6807
6808 #undef RECORD_OVERLAY_STRING
6809
6810
6811 if (n > 1)
6812 qsort (entries, n, sizeof *entries, compare_overlay_entries);
6813
6814
6815 it->n_overlay_strings = n;
6816 it->overlay_strings_charpos = charpos;
6817
6818
6819
6820
6821 ptrdiff_t j = it->current.overlay_string_index;
6822 for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++)
6823 {
6824 it->overlay_strings[i] = entries[j].string;
6825 it->string_overlays[i] = entries[j].overlay;
6826 }
6827
6828 CHECK_IT (it);
6829 SAFE_FREE ();
6830 }
6831
6832
6833
6834
6835
6836
6837 static bool
6838 get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, bool compute_stop_p)
6839 {
6840
6841
6842
6843
6844
6845
6846
6847 it->current.overlay_string_index = 0;
6848 load_overlay_strings (it, charpos);
6849
6850
6851
6852
6853 if (it->n_overlay_strings)
6854 {
6855
6856
6857
6858 if (compute_stop_p)
6859 compute_stop_pos (it);
6860 eassert (it->face_id >= 0);
6861
6862
6863
6864 eassert (!compute_stop_p || it->sp == 0);
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874 if (!(!it->bidi_p
6875 && STRINGP (it->string) && !SCHARS (it->string)))
6876 push_it (it, NULL);
6877
6878
6879
6880 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6881 it->string = it->overlay_strings[0];
6882 it->from_overlay = Qnil;
6883 it->stop_charpos = 0;
6884 eassert (STRINGP (it->string));
6885 it->end_charpos = SCHARS (it->string);
6886 it->prev_stop = 0;
6887 it->base_level_stop = 0;
6888 it->multibyte_p = STRING_MULTIBYTE (it->string);
6889 it->method = GET_FROM_STRING;
6890 it->from_disp_prop_p = 0;
6891 it->cmp_it.id = -1;
6892
6893
6894
6895 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6896 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6897 else
6898 it->paragraph_embedding = L2R;
6899
6900
6901 if (it->bidi_p)
6902 {
6903 ptrdiff_t pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
6904
6905 it->bidi_it.string.lstring = it->string;
6906 it->bidi_it.string.s = NULL;
6907 it->bidi_it.string.schars = SCHARS (it->string);
6908 it->bidi_it.string.bufpos = pos;
6909 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6910 it->bidi_it.string.unibyte = !it->multibyte_p;
6911 it->bidi_it.w = it->w;
6912 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6913 }
6914 return true;
6915 }
6916
6917 it->current.overlay_string_index = -1;
6918 return false;
6919 }
6920
6921 static bool
6922 get_overlay_strings (struct it *it, ptrdiff_t charpos)
6923 {
6924 it->string = Qnil;
6925 it->method = GET_FROM_BUFFER;
6926
6927 get_overlay_strings_1 (it, charpos, true);
6928
6929 CHECK_IT (it);
6930
6931
6932 return STRINGP (it->string);
6933 }
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947 static void
6948 push_it (struct it *it, struct text_pos *position)
6949 {
6950 struct iterator_stack_entry *p;
6951
6952 eassert (it->sp < IT_STACK_SIZE);
6953 p = it->stack + it->sp;
6954
6955 p->stop_charpos = it->stop_charpos;
6956 p->prev_stop = it->prev_stop;
6957 p->base_level_stop = it->base_level_stop;
6958 p->cmp_it = it->cmp_it;
6959 eassert (it->face_id >= 0);
6960 p->face_id = it->face_id;
6961 p->string = it->string;
6962 p->method = it->method;
6963 p->from_overlay = it->from_overlay;
6964 switch (p->method)
6965 {
6966 case GET_FROM_IMAGE:
6967 p->u.image.object = it->object;
6968 p->u.image.image_id = it->image_id;
6969 p->u.image.slice = it->slice;
6970 break;
6971 case GET_FROM_STRETCH:
6972 p->u.stretch.object = it->object;
6973 break;
6974 case GET_FROM_XWIDGET:
6975 p->u.xwidget.object = it->object;
6976 break;
6977 case GET_FROM_BUFFER:
6978 case GET_FROM_DISPLAY_VECTOR:
6979 case GET_FROM_STRING:
6980 case GET_FROM_C_STRING:
6981 break;
6982 default:
6983 emacs_abort ();
6984 }
6985 p->position = position ? *position : it->position;
6986 p->current = it->current;
6987 p->end_charpos = it->end_charpos;
6988 p->string_nchars = it->string_nchars;
6989 p->area = it->area;
6990 p->multibyte_p = it->multibyte_p;
6991 p->avoid_cursor_p = it->avoid_cursor_p;
6992 p->space_width = it->space_width;
6993 p->font_height = it->font_height;
6994 p->voffset = it->voffset;
6995 p->string_from_display_prop_p = it->string_from_display_prop_p;
6996 p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
6997 p->display_ellipsis_p = false;
6998 p->line_wrap = it->line_wrap;
6999 p->bidi_p = it->bidi_p;
7000 p->paragraph_embedding = it->paragraph_embedding;
7001 p->from_disp_prop_p = it->from_disp_prop_p;
7002 ++it->sp;
7003
7004
7005 if (it->bidi_p)
7006 bidi_push_it (&it->bidi_it);
7007 }
7008
7009 static void
7010 iterate_out_of_display_property (struct it *it)
7011 {
7012 bool buffer_p = !STRINGP (it->string);
7013 ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
7014 ptrdiff_t bob = (buffer_p ? BEGV : 0);
7015
7016 eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
7017
7018
7019
7020
7021 if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
7022 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
7023
7024 while (it->bidi_it.charpos >= bob
7025 && it->prev_stop <= it->bidi_it.charpos
7026 && it->bidi_it.charpos < CHARPOS (it->position)
7027 && it->bidi_it.charpos < eob)
7028 bidi_move_to_visually_next (&it->bidi_it);
7029
7030
7031 if (it->bidi_it.charpos > CHARPOS (it->position))
7032 it->prev_stop = CHARPOS (it->position);
7033
7034
7035 if (it->bidi_it.charpos != CHARPOS (it->position))
7036 SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
7037 if (buffer_p)
7038 it->current.pos = it->position;
7039 else
7040 it->current.string_pos = it->position;
7041 }
7042
7043
7044
7045
7046
7047 static void
7048 restore_face_box_flags (struct it *it, int prev_face_id)
7049 {
7050 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
7051
7052 if (face)
7053 {
7054 struct face *prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
7055
7056 if (!(it->start_of_box_run_p && prev_face && prev_face->box))
7057 it->start_of_box_run_p = (face->box != FACE_NO_BOX
7058 && (prev_face == NULL
7059 || prev_face->box == FACE_NO_BOX));
7060 it->face_box_p = face->box != FACE_NO_BOX;
7061 }
7062 }
7063
7064
7065
7066
7067
7068
7069
7070 static void
7071 pop_it (struct it *it)
7072 {
7073 struct iterator_stack_entry *p;
7074 bool from_display_prop = it->from_disp_prop_p;
7075 ptrdiff_t prev_pos = IT_CHARPOS (*it);
7076 int prev_face_id = it->face_id;
7077
7078 eassert (it->sp > 0);
7079 --it->sp;
7080 p = it->stack + it->sp;
7081 it->stop_charpos = p->stop_charpos;
7082 it->prev_stop = p->prev_stop;
7083 it->base_level_stop = p->base_level_stop;
7084 it->cmp_it = p->cmp_it;
7085 it->face_id = p->face_id;
7086 it->current = p->current;
7087 it->position = p->position;
7088 it->string = p->string;
7089 it->from_overlay = p->from_overlay;
7090 if (NILP (it->string))
7091 SET_TEXT_POS (it->current.string_pos, -1, -1);
7092 it->method = p->method;
7093 switch (it->method)
7094 {
7095 case GET_FROM_IMAGE:
7096 it->image_id = p->u.image.image_id;
7097 it->object = p->u.image.object;
7098 it->slice = p->u.image.slice;
7099 break;
7100 case GET_FROM_XWIDGET:
7101 it->object = p->u.xwidget.object;
7102 break;
7103 case GET_FROM_STRETCH:
7104 it->object = p->u.stretch.object;
7105 break;
7106 case GET_FROM_BUFFER:
7107 {
7108 restore_face_box_flags (it, prev_face_id);
7109 it->object = it->w->contents;
7110 }
7111 break;
7112 case GET_FROM_STRING:
7113 {
7114 restore_face_box_flags (it, prev_face_id);
7115 it->object = it->string;
7116 }
7117 break;
7118 case GET_FROM_DISPLAY_VECTOR:
7119 if (it->s)
7120 it->method = GET_FROM_C_STRING;
7121 else if (STRINGP (it->string))
7122 it->method = GET_FROM_STRING;
7123 else
7124 {
7125 it->method = GET_FROM_BUFFER;
7126 it->object = it->w->contents;
7127 }
7128 break;
7129 case GET_FROM_C_STRING:
7130 break;
7131 default:
7132 emacs_abort ();
7133 }
7134 it->end_charpos = p->end_charpos;
7135 it->string_nchars = p->string_nchars;
7136 it->area = p->area;
7137 it->multibyte_p = p->multibyte_p;
7138 it->avoid_cursor_p = p->avoid_cursor_p;
7139 it->space_width = p->space_width;
7140 it->font_height = p->font_height;
7141 it->voffset = p->voffset;
7142 it->string_from_display_prop_p = p->string_from_display_prop_p;
7143 it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
7144 it->line_wrap = p->line_wrap;
7145 it->bidi_p = p->bidi_p;
7146 it->paragraph_embedding = p->paragraph_embedding;
7147 it->from_disp_prop_p = p->from_disp_prop_p;
7148 if (it->bidi_p)
7149 {
7150 bidi_pop_it (&it->bidi_it);
7151
7152
7153
7154
7155
7156
7157
7158 if (from_display_prop
7159 && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
7160 iterate_out_of_display_property (it);
7161
7162 eassert ((BUFFERP (it->object)
7163 && IT_CHARPOS (*it) == it->bidi_it.charpos
7164 && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
7165 || (STRINGP (it->object)
7166 && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
7167 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
7168 || (CONSP (it->object) && it->method == GET_FROM_STRETCH)
7169
7170
7171
7172
7173
7174
7175 || it->sp > 0);
7176 }
7177
7178
7179
7180 if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
7181 it->ignore_overlay_strings_at_pos_p = false;
7182 }
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192 static void
7193 back_to_previous_line_start (struct it *it)
7194 {
7195 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
7196
7197 dec_both (&cp, &bp);
7198 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7199 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
7200 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
7201 }
7202
7203
7204
7205
7206
7207 static bool
7208 strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7209 {
7210 struct itree_node *node;
7211
7212 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7213 {
7214 Lisp_Object overlay = node->data;
7215 eassert (OVERLAYP (overlay));
7216
7217
7218 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7219 if (WINDOWP (window) && XWINDOW (window) != w)
7220 continue;
7221
7222 ptrdiff_t ostart = node->begin;
7223 ptrdiff_t oend = node->end;
7224
7225
7226 if (!((startpos < oend && ostart < endpos)
7227 || (ostart == oend
7228 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7229 continue;
7230
7231 Lisp_Object str;
7232 str = Foverlay_get (overlay, Qbefore_string);
7233 if (STRINGP (str) && SCHARS (str)
7234 && memchr (SDATA (str), '\n', SBYTES (str)))
7235 return true;
7236 str = Foverlay_get (overlay, Qafter_string);
7237 if (STRINGP (str) && SCHARS (str)
7238 && memchr (SDATA (str), '\n', SBYTES (str)))
7239 return true;
7240 }
7241
7242
7243 Lisp_Object cpos = make_fixnum (startpos);
7244 Lisp_Object limpos = make_fixnum (endpos);
7245
7246 while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos),
7247 !(NILP (cpos) || XFIXNAT (cpos) >= endpos)))
7248 {
7249 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
7250 Lisp_Object string = string_from_display_spec (spec);
7251 if (STRINGP (string)
7252 && memchr (SDATA (string), '\n', SBYTES (string)))
7253 return true;
7254 }
7255
7256 return false;
7257 }
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281 static bool
7282 forward_to_next_line_start (struct it *it, bool *skipped_p,
7283 struct bidi_it *bidi_it_prev)
7284 {
7285 ptrdiff_t old_selective;
7286 bool newline_found_p = false;
7287 int n;
7288 const int MAX_NEWLINE_DISTANCE = 500;
7289
7290
7291
7292 if (it->what == IT_CHARACTER
7293 && it->c == '\n'
7294 && CHARPOS (it->position) == IT_CHARPOS (*it))
7295 {
7296 if (it->bidi_p && bidi_it_prev)
7297 *bidi_it_prev = it->bidi_it;
7298 set_iterator_to_next (it, false);
7299 it->c = 0;
7300 return true;
7301 }
7302
7303
7304
7305
7306
7307 old_selective = it->selective;
7308 it->selective = 0;
7309
7310
7311
7312
7313 for (n = 0;
7314 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
7315 n += !STRINGP (it->string))
7316 {
7317 if (!get_next_display_element (it))
7318 return false;
7319 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
7320 if (newline_found_p && it->bidi_p && bidi_it_prev)
7321 *bidi_it_prev = it->bidi_it;
7322 set_iterator_to_next (it, false);
7323 }
7324
7325
7326
7327 if (!newline_found_p)
7328 {
7329 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
7330 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
7331 1, &bytepos);
7332 eassert (!STRINGP (it->string));
7333
7334
7335
7336
7337 bool no_strings_with_newlines = it->stop_charpos >= limit;
7338
7339 if (!no_strings_with_newlines)
7340 {
7341 if (!(current_buffer->long_line_optimizations_p
7342 && it->line_wrap == TRUNCATE))
7343 {
7344
7345
7346 Lisp_Object pos =
7347 Fnext_single_property_change (make_fixnum (start),
7348 Qdisplay, Qnil,
7349 make_fixnum (limit));
7350 no_strings_with_newlines =
7351 (NILP (pos) || XFIXNAT (pos) == limit)
7352 && next_overlay_change (start) == ZV;
7353 }
7354 else
7355 {
7356
7357
7358
7359
7360 no_strings_with_newlines =
7361 !strings_with_newlines (start, limit, it->w);
7362 }
7363 }
7364
7365
7366
7367
7368 if (no_strings_with_newlines)
7369 {
7370 if (!it->bidi_p || !bidi_it_prev)
7371 {
7372
7373 IT_CHARPOS (*it) = limit;
7374 IT_BYTEPOS (*it) = bytepos;
7375 }
7376 else
7377 {
7378
7379
7380
7381 struct bidi_it bprev;
7382
7383
7384
7385
7386 if (it->bidi_it.disp_pos < limit)
7387 {
7388 it->bidi_it.disp_pos = limit;
7389 it->bidi_it.disp_prop = 0;
7390 }
7391 do {
7392 bprev = it->bidi_it;
7393 bidi_move_to_visually_next (&it->bidi_it);
7394 } while (it->bidi_it.charpos != limit);
7395 IT_CHARPOS (*it) = limit;
7396 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7397 if (bidi_it_prev)
7398 *bidi_it_prev = bprev;
7399 }
7400 *skipped_p = newline_found_p = true;
7401 }
7402 else
7403 {
7404
7405 while (!newline_found_p)
7406 {
7407 if (!get_next_display_element (it))
7408 break;
7409 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
7410 if (newline_found_p && it->bidi_p && bidi_it_prev)
7411 *bidi_it_prev = it->bidi_it;
7412 set_iterator_to_next (it, false);
7413 }
7414 }
7415 }
7416
7417 it->selective = old_selective;
7418 return newline_found_p;
7419 }
7420
7421
7422
7423
7424
7425
7426
7427 static void
7428 back_to_previous_visible_line_start (struct it *it)
7429 {
7430 while (IT_CHARPOS (*it) > BEGV)
7431 {
7432 back_to_previous_line_start (it);
7433
7434 if (IT_CHARPOS (*it) <= BEGV)
7435 break;
7436
7437
7438
7439 if (it->selective > 0
7440 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7441 it->selective))
7442 continue;
7443
7444
7445 {
7446 Lisp_Object prop;
7447 prop = Fget_char_property (make_fixnum (IT_CHARPOS (*it) - 1),
7448 Qinvisible, it->window);
7449 if (TEXT_PROP_MEANS_INVISIBLE (prop) != 0)
7450 continue;
7451 }
7452
7453 if (IT_CHARPOS (*it) <= BEGV)
7454 break;
7455
7456 {
7457 struct it it2;
7458 void *it2data = NULL;
7459 ptrdiff_t pos;
7460 ptrdiff_t beg, end;
7461 Lisp_Object val, overlay;
7462
7463 SAVE_IT (it2, *it, it2data);
7464
7465
7466 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
7467 && beg < IT_CHARPOS (*it))
7468 goto replaced;
7469
7470
7471
7472 pos = --IT_CHARPOS (it2);
7473 --IT_BYTEPOS (it2);
7474 it2.sp = 0;
7475 bidi_unshelve_cache (NULL, false);
7476 it2.string_from_display_prop_p = false;
7477 it2.from_disp_prop_p = false;
7478 if (handle_display_prop (&it2) == HANDLED_RETURN
7479 && !NILP (val = get_char_property_and_overlay
7480 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7481 && (OVERLAYP (overlay)
7482 ? (beg = OVERLAY_START (overlay))
7483 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7484 {
7485 RESTORE_IT (it, it, it2data);
7486 goto replaced;
7487 }
7488
7489
7490 RESTORE_IT (it, it, it2data);
7491 break;
7492
7493 replaced:
7494 if (beg < BEGV)
7495 beg = BEGV;
7496 IT_CHARPOS (*it) = beg;
7497 IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
7498 }
7499 }
7500
7501 it->continuation_lines_width = 0;
7502
7503 eassert (IT_CHARPOS (*it) >= BEGV);
7504 eassert (it->medium_narrowing_begv > 0
7505 || IT_CHARPOS (*it) == BEGV
7506 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7507 CHECK_IT (it);
7508 }
7509
7510
7511
7512
7513
7514
7515
7516 void
7517 reseat_at_previous_visible_line_start (struct it *it)
7518 {
7519 back_to_previous_visible_line_start (it);
7520 reseat (it, it->current.pos, true);
7521 CHECK_IT (it);
7522 }
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532 static void
7533 reseat_at_next_visible_line_start (struct it *it, bool on_newline_p)
7534 {
7535 bool skipped_p = false;
7536 struct bidi_it bidi_it_prev;
7537 bool newline_found_p
7538 = forward_to_next_line_start (it, &skipped_p,
7539 on_newline_p ? &bidi_it_prev : NULL);
7540
7541
7542
7543 if (it->selective > 0)
7544 while (IT_CHARPOS (*it) < ZV
7545 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7546 it->selective))
7547 {
7548 eassert (IT_BYTEPOS (*it) == BEGV
7549 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7550 newline_found_p =
7551 forward_to_next_line_start (it, &skipped_p,
7552 on_newline_p ? &bidi_it_prev : NULL);
7553 }
7554
7555
7556 if (on_newline_p && newline_found_p)
7557 {
7558 if (STRINGP (it->string))
7559 {
7560 if (IT_STRING_CHARPOS (*it) > 0)
7561 {
7562 if (!it->bidi_p)
7563 {
7564 --IT_STRING_CHARPOS (*it);
7565 --IT_STRING_BYTEPOS (*it);
7566 }
7567 else
7568 {
7569
7570
7571
7572 it->bidi_it = bidi_it_prev;
7573 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
7574 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
7575 }
7576 }
7577 }
7578 else if (IT_CHARPOS (*it) > BEGV)
7579 {
7580 if (!it->bidi_p)
7581 {
7582 --IT_CHARPOS (*it);
7583 --IT_BYTEPOS (*it);
7584 }
7585 else
7586 {
7587
7588
7589 it->bidi_it = bidi_it_prev;
7590 IT_CHARPOS (*it) = it->bidi_it.charpos;
7591 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7592 }
7593 reseat (it, it->current.pos, false);
7594 }
7595 }
7596 else if (skipped_p)
7597 reseat (it, it->current.pos, false);
7598
7599 CHECK_IT (it);
7600 }
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613 static void
7614 reseat (struct it *it, struct text_pos pos, bool force_p)
7615 {
7616 ptrdiff_t original_pos = IT_CHARPOS (*it);
7617
7618 reseat_1 (it, pos, false);
7619
7620 if (current_buffer->long_line_optimizations_p)
7621 {
7622 if (!it->medium_narrowing_begv)
7623 {
7624 it->medium_narrowing_begv
7625 = get_medium_narrowing_begv (it->w, window_point (it->w));
7626 it->medium_narrowing_zv
7627 = get_medium_narrowing_zv (it->w, window_point (it->w));
7628 it->large_narrowing_begv
7629 = get_large_narrowing_begv (window_point (it->w));
7630 it->large_narrowing_zv
7631 = get_large_narrowing_zv (window_point (it->w));
7632 }
7633 else if ((pos.charpos < it->medium_narrowing_begv
7634 || pos.charpos > it->medium_narrowing_zv)
7635 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7636 {
7637 it->medium_narrowing_begv
7638 = get_medium_narrowing_begv (it->w, pos.charpos);
7639 it->medium_narrowing_zv
7640 = get_medium_narrowing_zv (it->w, pos.charpos);
7641 it->large_narrowing_begv
7642 = get_large_narrowing_begv (window_point (it->w));
7643 it->large_narrowing_zv
7644 = get_large_narrowing_zv (window_point (it->w));
7645 }
7646 }
7647
7648
7649
7650 if (force_p
7651 || CHARPOS (pos) > it->stop_charpos
7652 || CHARPOS (pos) < original_pos)
7653 {
7654 if (it->bidi_p)
7655 {
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666 if (CHARPOS (pos) != it->prev_stop)
7667 it->prev_stop = CHARPOS (pos);
7668 if (CHARPOS (pos) < it->base_level_stop)
7669 it->base_level_stop = 0;
7670 handle_stop (it);
7671 }
7672 else
7673 {
7674 handle_stop (it);
7675 it->prev_stop = it->base_level_stop = 0;
7676 }
7677
7678 }
7679
7680 CHECK_IT (it);
7681 }
7682
7683
7684
7685
7686
7687 static void
7688 reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7689 {
7690
7691 eassert (it->s == NULL);
7692
7693
7694 eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
7695
7696 it->current.pos = it->position = pos;
7697 it->end_charpos = ZV;
7698 it->dpvec = NULL;
7699 it->current.dpvec_index = -1;
7700 it->current.overlay_string_index = -1;
7701 IT_STRING_CHARPOS (*it) = -1;
7702 IT_STRING_BYTEPOS (*it) = -1;
7703 it->string = Qnil;
7704 it->method = GET_FROM_BUFFER;
7705 it->object = it->w->contents;
7706 it->area = TEXT_AREA;
7707 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
7708 it->sp = 0;
7709 it->string_from_display_prop_p = false;
7710 it->string_from_prefix_prop_p = false;
7711
7712 it->from_disp_prop_p = false;
7713 it->face_before_selective_p = false;
7714 if (it->bidi_p)
7715 {
7716 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7717 &it->bidi_it);
7718 bidi_unshelve_cache (NULL, false);
7719 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7720 it->bidi_it.string.s = NULL;
7721 it->bidi_it.string.lstring = Qnil;
7722 it->bidi_it.string.bufpos = 0;
7723 it->bidi_it.string.from_disp_str = false;
7724 it->bidi_it.string.unibyte = false;
7725 it->bidi_it.w = it->w;
7726 }
7727
7728 if (set_stop_p)
7729 {
7730 it->stop_charpos = CHARPOS (pos);
7731 it->base_level_stop = CHARPOS (pos);
7732 }
7733
7734 it->cmp_it.id = -1;
7735 it->min_width_property = Qnil;
7736 }
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757 static void
7758 reseat_to_string (struct it *it, const char *s, Lisp_Object string,
7759 ptrdiff_t charpos, ptrdiff_t precision, int field_width,
7760 int multibyte)
7761 {
7762
7763 it->stop_charpos = -1;
7764
7765
7766 memset (&it->current, 0, sizeof it->current);
7767 it->current.overlay_string_index = -1;
7768 it->current.dpvec_index = -1;
7769 eassert (charpos >= 0);
7770
7771
7772
7773 if (multibyte >= 0)
7774 it->multibyte_p = multibyte > 0;
7775
7776
7777
7778
7779
7780 it->bidi_p =
7781 !redisplay__inhibit_bidi
7782 && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
7783
7784 if (s == NULL)
7785 {
7786 eassert (STRINGP (string));
7787 it->string = string;
7788 it->s = NULL;
7789 it->end_charpos = it->string_nchars = SCHARS (string);
7790 it->method = GET_FROM_STRING;
7791 it->current.string_pos = string_pos (charpos, string);
7792
7793 if (it->bidi_p)
7794 {
7795 it->bidi_it.string.lstring = string;
7796 it->bidi_it.string.s = NULL;
7797 it->bidi_it.string.schars = it->end_charpos;
7798 it->bidi_it.string.bufpos = 0;
7799 it->bidi_it.string.from_disp_str = false;
7800 it->bidi_it.string.unibyte = !it->multibyte_p;
7801 it->bidi_it.w = it->w;
7802 bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
7803 FRAME_WINDOW_P (it->f), &it->bidi_it);
7804 }
7805 }
7806 else
7807 {
7808 it->s = (const unsigned char *) s;
7809 it->string = Qnil;
7810
7811
7812
7813 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
7814 if (it->multibyte_p)
7815 {
7816 it->current.pos = c_string_pos (charpos, s, true);
7817 it->end_charpos = it->string_nchars = number_of_chars (s, true);
7818 }
7819 else
7820 {
7821 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
7822 it->end_charpos = it->string_nchars = strlen (s);
7823 }
7824
7825 if (it->bidi_p)
7826 {
7827 it->bidi_it.string.lstring = Qnil;
7828 it->bidi_it.string.s = (const unsigned char *) s;
7829 it->bidi_it.string.schars = it->end_charpos;
7830 it->bidi_it.string.bufpos = 0;
7831 it->bidi_it.string.from_disp_str = false;
7832 it->bidi_it.string.unibyte = !it->multibyte_p;
7833 it->bidi_it.w = it->w;
7834 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7835 &it->bidi_it);
7836 }
7837 it->method = GET_FROM_C_STRING;
7838 }
7839
7840
7841
7842 if (precision > 0 && it->end_charpos - charpos > precision)
7843 {
7844 it->end_charpos = it->string_nchars = charpos + precision;
7845 if (it->bidi_p)
7846 it->bidi_it.string.schars = it->end_charpos;
7847 }
7848
7849
7850
7851
7852
7853 if (field_width < 0)
7854 field_width = DISP_INFINITY;
7855
7856
7857
7858 if (field_width > it->end_charpos - charpos)
7859 it->end_charpos = charpos + field_width;
7860
7861
7862 if (DISP_TABLE_P (Vstandard_display_table))
7863 it->dp = XCHAR_TABLE (Vstandard_display_table);
7864
7865 it->stop_charpos = charpos;
7866 it->prev_stop = charpos;
7867 it->base_level_stop = 0;
7868 if (it->bidi_p)
7869 {
7870 it->bidi_it.first_elt = true;
7871 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7872 it->bidi_it.disp_pos = -1;
7873 }
7874 if (s == NULL && it->multibyte_p)
7875 {
7876 ptrdiff_t endpos = SCHARS (it->string);
7877 if (endpos > it->end_charpos)
7878 endpos = it->end_charpos;
7879 composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
7880 it->string);
7881 }
7882 CHECK_IT (it);
7883 }
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893 typedef bool (*next_element_function) (struct it *);
7894
7895 static next_element_function const get_next_element[NUM_IT_METHODS] =
7896 {
7897 next_element_from_buffer,
7898 next_element_from_display_vector,
7899 next_element_from_string,
7900 next_element_from_c_string,
7901 next_element_from_image,
7902 next_element_from_stretch,
7903 next_element_from_xwidget,
7904 };
7905
7906 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917 #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS) \
7918 ((IT)->cmp_it.id >= 0 \
7919 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
7920 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
7921 END_CHARPOS, (IT)->w, \
7922 (IT)->bidi_p \
7923 ? (IT)->bidi_it.resolved_level \
7924 : -1, \
7925 FACE_FROM_ID_OR_NULL ((IT)->f, \
7926 (IT)->face_id), \
7927 (IT)->string)))
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937 Lisp_Object
7938 lookup_glyphless_char_display (int c, struct it *it)
7939 {
7940 Lisp_Object glyphless_method = Qnil;
7941
7942 if (CHAR_TABLE_P (Vglyphless_char_display)
7943 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
7944 {
7945 if (c >= 0)
7946 glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
7947 else
7948 glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
7949
7950 if (CONSP (glyphless_method))
7951 glyphless_method = FRAME_WINDOW_P (it->f)
7952 ? XCAR (glyphless_method)
7953 : XCDR (glyphless_method);
7954 }
7955
7956 retry:
7957 if (NILP (glyphless_method))
7958 {
7959 if (c >= 0)
7960
7961 return Qnil;
7962
7963 glyphless_method = Qempty_box;
7964 }
7965 if (EQ (glyphless_method, Qzero_width))
7966 {
7967 if (c >= 0)
7968 return glyphless_method;
7969
7970 glyphless_method = Qempty_box;
7971 }
7972 if (EQ (glyphless_method, Qthin_space))
7973 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
7974 else if (EQ (glyphless_method, Qempty_box))
7975 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
7976 else if (EQ (glyphless_method, Qhex_code))
7977 it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
7978 else if (STRINGP (glyphless_method))
7979 it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
7980 else
7981 {
7982
7983 glyphless_method = Qnil;
7984 goto retry;
7985 }
7986 it->what = IT_GLYPHLESS;
7987 return glyphless_method;
7988 }
7989
7990
7991
7992 static struct frame *last_escape_glyph_frame = NULL;
7993 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
7994 static int last_escape_glyph_merged_face_id = 0;
7995
7996 static int
7997 merge_escape_glyph_face (struct it *it)
7998 {
7999 int face_id;
8000
8001 if (it->f == last_escape_glyph_frame
8002 && it->face_id == last_escape_glyph_face_id)
8003 face_id = last_escape_glyph_merged_face_id;
8004 else
8005 {
8006
8007 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
8008 last_escape_glyph_frame = it->f;
8009 last_escape_glyph_face_id = it->face_id;
8010 last_escape_glyph_merged_face_id = face_id;
8011 }
8012 return face_id;
8013 }
8014
8015
8016
8017 static struct frame *last_glyphless_glyph_frame = NULL;
8018 static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8019 static int last_glyphless_glyph_merged_face_id = 0;
8020
8021 int
8022 merge_glyphless_glyph_face (struct it *it)
8023 {
8024 int face_id;
8025
8026 if (it->f == last_glyphless_glyph_frame
8027 && it->face_id == last_glyphless_glyph_face_id)
8028 face_id = last_glyphless_glyph_merged_face_id;
8029 else
8030 {
8031
8032 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
8033 last_glyphless_glyph_frame = it->f;
8034 last_glyphless_glyph_face_id = it->face_id;
8035 last_glyphless_glyph_merged_face_id = face_id;
8036 }
8037 return face_id;
8038 }
8039
8040
8041
8042
8043 void
8044 forget_escape_and_glyphless_faces (void)
8045 {
8046 last_escape_glyph_frame = NULL;
8047 last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8048 last_glyphless_glyph_frame = NULL;
8049 last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8050 }
8051
8052
8053
8054
8055
8056 static bool
8057 get_next_display_element (struct it *it)
8058 {
8059
8060
8061
8062
8063 bool success_p;
8064
8065 get_next:
8066 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
8067
8068 if (it->what == IT_CHARACTER)
8069 {
8070
8071
8072
8073
8074
8075 if (it->bidi_p && it->bidi_it.type == STRONG_R
8076 && !inhibit_bidi_mirroring)
8077 it->c = bidi_mirror_char (it->c);
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087 if (success_p && it->dpvec == NULL)
8088 {
8089 Lisp_Object dv;
8090 struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
8091 bool nonascii_space_p = false;
8092 bool nonascii_hyphen_p = false;
8093 int c = it->c;
8094
8095 if (! it->multibyte_p && ! ASCII_CHAR_P (c))
8096 {
8097 eassert (SINGLE_BYTE_CHAR_P (c));
8098 if (unibyte_display_via_language_environment)
8099 {
8100 c = DECODE_CHAR (unibyte, c);
8101 if (c < 0)
8102 c = BYTE8_TO_CHAR (it->c);
8103 }
8104 else
8105 c = BYTE8_TO_CHAR (it->c);
8106 }
8107
8108 if (it->dp
8109 && (dv = DISP_CHAR_VECTOR (it->dp, c),
8110 VECTORP (dv)))
8111 {
8112 struct Lisp_Vector *v = XVECTOR (dv);
8113
8114
8115
8116
8117 if (v->header.size)
8118 {
8119 it->dpvec_char_len = it->len;
8120 it->dpvec = v->contents;
8121 it->dpend = v->contents + v->header.size;
8122 it->current.dpvec_index = 0;
8123 it->dpvec_face_id = -1;
8124 it->saved_face_id = it->face_id;
8125 it->method = GET_FROM_DISPLAY_VECTOR;
8126 it->ellipsis_p = false;
8127 }
8128 else
8129 {
8130 set_iterator_to_next (it, false);
8131 }
8132 goto get_next;
8133 }
8134
8135 if (! NILP (lookup_glyphless_char_display (c, it)))
8136 {
8137 if (it->what == IT_GLYPHLESS)
8138 goto done;
8139
8140 set_iterator_to_next (it, false);
8141 goto get_next;
8142 }
8143
8144
8145
8146 if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
8147 {
8148 if (blankp (c))
8149 nonascii_space_p = true;
8150 else if (c == SOFT_HYPHEN || c == HYPHEN
8151 || c == NON_BREAKING_HYPHEN)
8152 nonascii_hyphen_p = true;
8153 }
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166 if (((c < ' ' || c == 127)
8167 ? (it->area != TEXT_AREA
8168
8169 || (c != '\t'
8170 && it->glyph_row
8171 && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
8172 || (c != '\n' && c != '\t'))
8173 : (nonascii_space_p
8174 || nonascii_hyphen_p
8175 || CHAR_BYTE8_P (c)
8176 || ! CHAR_PRINTABLE_P (c))))
8177 {
8178
8179
8180
8181
8182
8183
8184 Lisp_Object gc;
8185 int ctl_len;
8186 int face_id;
8187 int lface_id = 0;
8188 int escape_glyph;
8189
8190
8191
8192 if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
8193 {
8194 int g;
8195
8196 g = '^';
8197
8198 if (it->dp
8199 && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8200 {
8201 g = GLYPH_CODE_CHAR (gc);
8202 lface_id = GLYPH_CODE_FACE (gc);
8203 }
8204
8205 face_id = (lface_id
8206 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8207 : merge_escape_glyph_face (it));
8208
8209 XSETINT (it->ctl_chars[0], g);
8210 XSETINT (it->ctl_chars[1], c ^ 0100);
8211 ctl_len = 2;
8212 goto display_control;
8213 }
8214
8215
8216
8217
8218 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
8219 {
8220
8221 face_id = merge_faces (it->w, Qnobreak_space, 0,
8222 it->face_id);
8223 XSETINT (it->ctl_chars[0],
8224 nobreak_char_ascii_display ? ' ' : it->c);
8225 ctl_len = 1;
8226 goto display_control;
8227 }
8228
8229
8230
8231
8232 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
8233 {
8234
8235 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
8236 it->face_id);
8237 XSETINT (it->ctl_chars[0],
8238 nobreak_char_ascii_display ? '-' : it->c);
8239 ctl_len = 1;
8240 goto display_control;
8241 }
8242
8243
8244
8245
8246 escape_glyph = '\\';
8247
8248 if (it->dp
8249 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8250 {
8251 escape_glyph = GLYPH_CODE_CHAR (gc);
8252 lface_id = GLYPH_CODE_FACE (gc);
8253 }
8254
8255 face_id = (lface_id
8256 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8257 : merge_escape_glyph_face (it));
8258
8259
8260
8261 if (nonascii_space_p || nonascii_hyphen_p)
8262 {
8263 XSETINT (it->ctl_chars[0], escape_glyph);
8264 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
8265 ctl_len = 2;
8266 goto display_control;
8267 }
8268
8269 {
8270 char str[10];
8271 int len, i;
8272
8273 if (CHAR_BYTE8_P (c))
8274
8275 c = CHAR_TO_BYTE8 (c);
8276 const char *format_string = display_raw_bytes_as_hex
8277 ? "x%02x"
8278 : "%03o";
8279 len = sprintf (str, format_string, c + 0u);
8280
8281 XSETINT (it->ctl_chars[0], escape_glyph);
8282 for (i = 0; i < len; i++)
8283 XSETINT (it->ctl_chars[i + 1], str[i]);
8284 ctl_len = len + 1;
8285 }
8286
8287 display_control:
8288
8289 it->dpvec_char_len = it->len;
8290 it->dpvec = it->ctl_chars;
8291 it->dpend = it->dpvec + ctl_len;
8292 it->current.dpvec_index = 0;
8293 it->dpvec_face_id = face_id;
8294 it->saved_face_id = it->face_id;
8295 it->method = GET_FROM_DISPLAY_VECTOR;
8296 it->ellipsis_p = false;
8297 goto get_next;
8298 }
8299 it->char_to_display = c;
8300 }
8301 else if (success_p)
8302 {
8303 it->char_to_display = it->c;
8304 }
8305 }
8306
8307 #ifdef HAVE_WINDOW_SYSTEM
8308
8309
8310 if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
8311 && it->multibyte_p
8312 && success_p
8313 && FRAME_WINDOW_P (it->f))
8314 {
8315 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8316
8317
8318
8319
8320 if (!face)
8321 {
8322 it->what = IT_GLYPHLESS;
8323 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
8324 }
8325 else if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8326 {
8327
8328 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8329
8330 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8331 }
8332 else
8333 {
8334 ptrdiff_t pos = (it->s ? -1
8335 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8336 : IT_CHARPOS (*it));
8337 int c;
8338
8339 if (it->what == IT_CHARACTER)
8340 c = it->char_to_display;
8341 else
8342 {
8343 struct composition *cmp = composition_table[it->cmp_it.id];
8344 int i;
8345
8346 c = ' ';
8347 for (i = 0; i < cmp->glyph_len; i++)
8348
8349
8350 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8351 break;
8352 }
8353 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8354 }
8355 }
8356 #endif
8357
8358 done:
8359
8360
8361 if (it->face_box_p
8362 && it->s == NULL)
8363 {
8364 if (it->method == GET_FROM_STRING && it->sp)
8365 {
8366 int face_id = underlying_face_id (it);
8367 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8368
8369 if (face)
8370 {
8371 if (face->box == FACE_NO_BOX)
8372 {
8373
8374
8375 int string_face_id = face_after_it_pos (it);
8376 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8377 it->end_of_box_run_p = true;
8378 }
8379
8380
8381
8382 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8383
8384
8385
8386 || (it->what == IT_COMPOSITION
8387 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8388 >= SCHARS (it->string))))
8389
8390
8391 && ((it->current.overlay_string_index >= 0
8392 && (it->current.overlay_string_index
8393 == it->n_overlay_strings - 1))
8394
8395 || it->from_disp_prop_p))
8396 {
8397 ptrdiff_t ignore;
8398 int next_face_id;
8399 bool text_from_string = false;
8400
8401
8402 struct text_pos pos = it->current.pos;
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414 if (it->from_disp_prop_p)
8415 {
8416 int stackp = it->sp - 1;
8417
8418
8419 while (stackp >= 0
8420 && STRINGP ((it->stack + stackp)->string))
8421 stackp--;
8422 if (stackp < 0)
8423 {
8424
8425
8426
8427
8428
8429
8430 text_from_string = true;
8431 pos = it->stack[it->sp - 1].position;
8432 }
8433 else
8434 pos = (it->stack + stackp)->position;
8435 }
8436 else
8437 INC_TEXT_POS (pos, it->multibyte_p);
8438
8439 if (text_from_string)
8440 {
8441 Lisp_Object base_string = it->stack[it->sp - 1].string;
8442
8443 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8444 it->end_of_box_run_p = true;
8445 else
8446 {
8447 next_face_id
8448 = face_at_string_position (it->w, base_string,
8449 CHARPOS (pos), 0,
8450 &ignore, face_id,
8451 false, 0);
8452 if (FACE_FROM_ID (it->f, next_face_id)->box
8453 == FACE_NO_BOX)
8454 it->end_of_box_run_p = true;
8455 }
8456 }
8457 else if (CHARPOS (pos) >= ZV)
8458 it->end_of_box_run_p = true;
8459 else
8460 {
8461 next_face_id =
8462 face_at_buffer_position (it->w, CHARPOS (pos),
8463 &ignore,
8464 CHARPOS (pos)
8465 + TEXT_PROP_DISTANCE_LIMIT,
8466 false, -1, 0);
8467 if (FACE_FROM_ID (it->f, next_face_id)->box
8468 == FACE_NO_BOX)
8469 it->end_of_box_run_p = true;
8470 }
8471 }
8472 }
8473 }
8474
8475
8476 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8477 {
8478 int face_id = face_after_it_pos (it);
8479 if (face_id != it->face_id
8480 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8481 it->end_of_box_run_p = true;
8482 }
8483 }
8484
8485
8486
8487
8488
8489 if (!success_p && it->sp > 0)
8490 {
8491 set_iterator_to_next (it, false);
8492 success_p = get_next_display_element (it);
8493 }
8494
8495
8496 return success_p;
8497 }
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515 void
8516 set_iterator_to_next (struct it *it, bool reseat_p)
8517 {
8518
8519 if (max_redisplay_ticks > 0)
8520 update_redisplay_ticks (1, it->w);
8521
8522 switch (it->method)
8523 {
8524 case GET_FROM_BUFFER:
8525
8526
8527
8528 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8529 reseat_at_next_visible_line_start (it, false);
8530 else if (it->cmp_it.id >= 0)
8531 {
8532
8533 if (! it->bidi_p)
8534 {
8535 IT_CHARPOS (*it) += it->cmp_it.nchars;
8536 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8537 }
8538 else
8539 {
8540 int i;
8541
8542
8543
8544
8545 for (i = 0; i < it->cmp_it.nchars; i++)
8546 bidi_move_to_visually_next (&it->bidi_it);
8547 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8548 IT_CHARPOS (*it) = it->bidi_it.charpos;
8549 }
8550
8551 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8552 && it->cmp_it.to < it->cmp_it.nglyphs)
8553 {
8554
8555
8556 it->cmp_it.from = it->cmp_it.to;
8557 }
8558 else if ((it->bidi_p && it->cmp_it.reversed_p)
8559 && it->cmp_it.from > 0)
8560 {
8561
8562
8563 it->cmp_it.to = it->cmp_it.from;
8564 }
8565 else
8566 {
8567
8568
8569 ptrdiff_t stop = it->end_charpos;
8570
8571 if (it->bidi_it.scan_dir < 0)
8572
8573
8574 stop = -1;
8575 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8576 IT_BYTEPOS (*it), stop, Qnil);
8577 }
8578 }
8579 else
8580 {
8581 eassert (it->len != 0);
8582
8583 if (!it->bidi_p)
8584 {
8585 IT_BYTEPOS (*it) += it->len;
8586 IT_CHARPOS (*it) += 1;
8587 }
8588 else
8589 {
8590 int prev_scan_dir = it->bidi_it.scan_dir;
8591
8592
8593 if (it->bidi_it.new_paragraph)
8594 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8595 false);
8596 bidi_move_to_visually_next (&it->bidi_it);
8597 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8598 IT_CHARPOS (*it) = it->bidi_it.charpos;
8599 if (prev_scan_dir != it->bidi_it.scan_dir)
8600 {
8601
8602
8603 ptrdiff_t stop = it->end_charpos;
8604 if (it->bidi_it.scan_dir < 0)
8605 stop = -1;
8606 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8607 IT_BYTEPOS (*it), stop, Qnil);
8608 }
8609 }
8610 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8611 }
8612 break;
8613
8614 case GET_FROM_C_STRING:
8615
8616 if (!it->bidi_p
8617
8618
8619
8620
8621 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8622 {
8623 IT_BYTEPOS (*it) += it->len;
8624 IT_CHARPOS (*it) += 1;
8625 }
8626 else
8627 {
8628 bidi_move_to_visually_next (&it->bidi_it);
8629 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8630 IT_CHARPOS (*it) = it->bidi_it.charpos;
8631 }
8632 break;
8633
8634 case GET_FROM_DISPLAY_VECTOR:
8635
8636
8637
8638
8639 ++it->current.dpvec_index;
8640
8641
8642
8643 it->face_id = it->saved_face_id;
8644
8645 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8646 {
8647 bool recheck_faces = it->ellipsis_p;
8648
8649 if (it->s)
8650 it->method = GET_FROM_C_STRING;
8651 else if (STRINGP (it->string))
8652 it->method = GET_FROM_STRING;
8653 else
8654 {
8655 it->method = GET_FROM_BUFFER;
8656 it->object = it->w->contents;
8657 }
8658
8659 it->dpvec = NULL;
8660 it->current.dpvec_index = -1;
8661
8662
8663 if (it->dpvec_char_len < 0)
8664 reseat_at_next_visible_line_start (it, true);
8665 else if (it->dpvec_char_len > 0)
8666 {
8667 it->len = it->dpvec_char_len;
8668 set_iterator_to_next (it, reseat_p);
8669 }
8670
8671
8672 if (recheck_faces)
8673 {
8674 if (it->method == GET_FROM_STRING)
8675 it->stop_charpos = IT_STRING_CHARPOS (*it);
8676 else
8677 it->stop_charpos = IT_CHARPOS (*it);
8678 }
8679 }
8680 break;
8681
8682 case GET_FROM_STRING:
8683
8684 eassert (it->s == NULL && STRINGP (it->string));
8685
8686
8687
8688
8689
8690 if (it->current.overlay_string_index >= 0)
8691 {
8692
8693
8694
8695 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8696 goto consider_string_end;
8697 }
8698 else
8699 {
8700
8701
8702 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8703 goto consider_string_end;
8704 }
8705 if (it->cmp_it.id >= 0)
8706 {
8707
8708
8709
8710 if (! it->bidi_p)
8711 {
8712 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8713 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8714 }
8715 else
8716 {
8717 int i;
8718
8719 for (i = 0; i < it->cmp_it.nchars; i++)
8720 bidi_move_to_visually_next (&it->bidi_it);
8721 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8722 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8723 }
8724
8725
8726
8727 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8728 && (it->cmp_it.to < it->cmp_it.nglyphs))
8729 {
8730
8731
8732 it->cmp_it.from = it->cmp_it.to;
8733 }
8734 else if ((it->bidi_p && it->cmp_it.reversed_p)
8735 && it->cmp_it.from > 0)
8736 {
8737
8738
8739 it->cmp_it.to = it->cmp_it.from;
8740 }
8741 else
8742 {
8743
8744
8745
8746
8747
8748
8749 ptrdiff_t stop = SCHARS (it->string);
8750
8751 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8752 stop = -1;
8753 else if (it->end_charpos < stop)
8754 {
8755
8756
8757
8758 stop = it->end_charpos;
8759 }
8760 composition_compute_stop_pos (&it->cmp_it,
8761 IT_STRING_CHARPOS (*it),
8762 IT_STRING_BYTEPOS (*it), stop,
8763 it->string);
8764 }
8765 }
8766 else
8767 {
8768 if (!it->bidi_p
8769
8770
8771
8772
8773
8774 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8775 {
8776 IT_STRING_BYTEPOS (*it) += it->len;
8777 IT_STRING_CHARPOS (*it) += 1;
8778 }
8779 else
8780 {
8781 int prev_scan_dir = it->bidi_it.scan_dir;
8782
8783 bidi_move_to_visually_next (&it->bidi_it);
8784 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8785 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8786
8787
8788 if (prev_scan_dir != it->bidi_it.scan_dir)
8789 {
8790 ptrdiff_t stop = SCHARS (it->string);
8791
8792 if (it->bidi_it.scan_dir < 0)
8793 stop = -1;
8794 else if (it->end_charpos < stop)
8795 stop = it->end_charpos;
8796
8797 composition_compute_stop_pos (&it->cmp_it,
8798 IT_STRING_CHARPOS (*it),
8799 IT_STRING_BYTEPOS (*it), stop,
8800 it->string);
8801 }
8802 }
8803 }
8804
8805 consider_string_end:
8806
8807 if (it->current.overlay_string_index >= 0)
8808 {
8809
8810
8811 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8812 {
8813 it->ellipsis_p = false;
8814 next_overlay_string (it);
8815 if (it->ellipsis_p)
8816 setup_for_ellipsis (it, 0);
8817 }
8818 }
8819 else
8820 {
8821
8822
8823
8824
8825 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8826 && it->sp > 0)
8827 {
8828 pop_it (it);
8829 if (it->method == GET_FROM_STRING)
8830 goto consider_string_end;
8831 }
8832 }
8833 break;
8834
8835 case GET_FROM_IMAGE:
8836 case GET_FROM_STRETCH:
8837 case GET_FROM_XWIDGET:
8838
8839
8840
8841
8842 eassert (it->sp > 0);
8843 pop_it (it);
8844 if (it->method == GET_FROM_STRING)
8845 goto consider_string_end;
8846 break;
8847
8848 default:
8849
8850 emacs_abort ();
8851 }
8852
8853 eassert (it->method != GET_FROM_STRING
8854 || (STRINGP (it->string)
8855 && IT_STRING_CHARPOS (*it) >= 0));
8856 }
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867 static bool
8868 next_element_from_display_vector (struct it *it)
8869 {
8870 Lisp_Object gc;
8871 int prev_face_id = it->face_id;
8872 int next_face_id;
8873
8874
8875 eassert (it->dpvec && it->current.dpvec_index >= 0);
8876
8877 it->face_id = it->saved_face_id;
8878
8879
8880
8881 if (it->dpend - it->dpvec > 0
8882 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8883 {
8884 struct face *this_face, *prev_face, *next_face;
8885
8886 it->c = GLYPH_CODE_CHAR (gc);
8887 it->len = CHAR_BYTES (it->c);
8888
8889
8890
8891
8892 if (it->dpvec_face_id >= 0)
8893 it->face_id = it->dpvec_face_id;
8894 else
8895 {
8896 int lface_id = GLYPH_CODE_FACE (gc);
8897 if (lface_id > 0)
8898 it->face_id = merge_faces (it->w, Qt, lface_id,
8899 it->saved_face_id);
8900 }
8901
8902
8903
8904
8905 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8906 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8907
8908
8909 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8910 && (!prev_face
8911 || prev_face->box == FACE_NO_BOX));
8912
8913
8914
8915
8916 next_face_id = it->saved_face_id;
8917 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8918 {
8919 if (it->dpvec_face_id >= 0)
8920 next_face_id = it->dpvec_face_id;
8921 else
8922 {
8923 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8924 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8925
8926 if (lface_id > 0)
8927 next_face_id = merge_faces (it->w, Qt, lface_id,
8928 it->saved_face_id);
8929 }
8930 }
8931 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8932 if (this_face && this_face->box != FACE_NO_BOX
8933 && (!next_face || next_face->box == FACE_NO_BOX))
8934 it->end_of_box_run_p = true;
8935 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8936 }
8937 else
8938
8939 it->c = ' ', it->len = 1;
8940
8941
8942
8943
8944 it->what = IT_CHARACTER;
8945 return true;
8946 }
8947
8948
8949
8950 static void
8951 get_visually_first_element (struct it *it)
8952 {
8953 bool string_p = STRINGP (it->string) || it->s;
8954 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8955 ptrdiff_t bob;
8956 ptrdiff_t obegv = BEGV;
8957
8958 SET_WITH_NARROWED_BEGV (it, bob,
8959 string_p ? 0 :
8960 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8961 it->medium_narrowing_begv);
8962
8963 if (STRINGP (it->string))
8964 {
8965 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8966 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8967 }
8968 else
8969 {
8970 it->bidi_it.charpos = IT_CHARPOS (*it);
8971 it->bidi_it.bytepos = IT_BYTEPOS (*it);
8972 }
8973
8974 if (it->bidi_it.charpos == eob)
8975 {
8976
8977
8978
8979 it->bidi_it.first_elt = false;
8980 }
8981 else if (it->bidi_it.charpos == bob
8982 || (!string_p
8983 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
8984 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
8985 {
8986
8987
8988 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8989 bidi_move_to_visually_next (&it->bidi_it);
8990 }
8991 else
8992 {
8993 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
8994
8995
8996
8997
8998 if (string_p)
8999 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
9000 else
9001 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
9002 find_newline_no_quit (IT_CHARPOS (*it),
9003 IT_BYTEPOS (*it), -1,
9004 &it->bidi_it.bytepos),
9005 it->medium_narrowing_begv);
9006 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
9007 do
9008 {
9009
9010
9011 bidi_move_to_visually_next (&it->bidi_it);
9012 }
9013 while (it->bidi_it.bytepos != orig_bytepos
9014 && it->bidi_it.charpos < eob);
9015 }
9016
9017
9018 if (STRINGP (it->string))
9019 {
9020 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
9021 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
9022 }
9023 else
9024 {
9025 IT_CHARPOS (*it) = it->bidi_it.charpos;
9026 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
9027 }
9028
9029 if (STRINGP (it->string) || !it->s)
9030 {
9031 ptrdiff_t stop, charpos, bytepos;
9032
9033 if (STRINGP (it->string))
9034 {
9035 eassert (!it->s);
9036 stop = SCHARS (it->string);
9037 if (stop > it->end_charpos)
9038 stop = it->end_charpos;
9039 charpos = IT_STRING_CHARPOS (*it);
9040 bytepos = IT_STRING_BYTEPOS (*it);
9041 }
9042 else
9043 {
9044 stop = it->end_charpos;
9045 charpos = IT_CHARPOS (*it);
9046 bytepos = IT_BYTEPOS (*it);
9047 }
9048 if (it->bidi_it.scan_dir < 0)
9049 stop = -1;
9050 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9051 it->string);
9052 }
9053 }
9054
9055
9056
9057
9058
9059
9060 static bool
9061 next_element_from_string (struct it *it)
9062 {
9063 struct text_pos position;
9064
9065 eassert (STRINGP (it->string));
9066 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9067 eassert (IT_STRING_CHARPOS (*it) >= 0);
9068 position = it->current.string_pos;
9069
9070
9071
9072
9073
9074 if (it->bidi_p && it->bidi_it.first_elt)
9075 {
9076 get_visually_first_element (it);
9077 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9078 }
9079
9080
9081 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9082 {
9083 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9084 {
9085 if (!(!it->bidi_p
9086 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9087 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9088 {
9089
9090
9091
9092
9093
9094
9095 handle_stop_backwards (it, it->stop_charpos);
9096 return GET_NEXT_DISPLAY_ELEMENT (it);
9097 }
9098 else
9099 {
9100 if (it->bidi_p)
9101 {
9102
9103
9104 it->prev_stop = it->stop_charpos;
9105
9106
9107
9108 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9109 it->base_level_stop = it->stop_charpos;
9110 }
9111 handle_stop (it);
9112
9113
9114
9115 return GET_NEXT_DISPLAY_ELEMENT (it);
9116 }
9117 }
9118 else if (it->bidi_p
9119
9120
9121
9122 && IT_STRING_CHARPOS (*it) < it->prev_stop
9123
9124
9125
9126
9127 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9128 {
9129
9130
9131
9132
9133 if (it->base_level_stop <= 0
9134 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9135 it->base_level_stop = 0;
9136 handle_stop_backwards (it, it->base_level_stop);
9137 return GET_NEXT_DISPLAY_ELEMENT (it);
9138 }
9139 }
9140
9141 if (it->current.overlay_string_index >= 0)
9142 {
9143
9144
9145
9146 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9147 {
9148 it->what = IT_EOB;
9149 return false;
9150 }
9151 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9152 IT_STRING_BYTEPOS (*it),
9153 it->bidi_it.scan_dir < 0
9154 ? -1
9155 : SCHARS (it->string))
9156 && next_element_from_composition (it))
9157 {
9158 return true;
9159 }
9160 else if (STRING_MULTIBYTE (it->string))
9161 {
9162 const unsigned char *s = (SDATA (it->string)
9163 + IT_STRING_BYTEPOS (*it));
9164 it->c = check_char_and_length (s, &it->len);
9165 }
9166 else
9167 {
9168 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9169 it->len = 1;
9170 }
9171 }
9172 else
9173 {
9174
9175
9176
9177
9178 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9179 {
9180 it->what = IT_EOB;
9181 return false;
9182 }
9183 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9184 {
9185
9186 it->c = ' ', it->len = 1;
9187 CHARPOS (position) = BYTEPOS (position) = -1;
9188 }
9189 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9190 IT_STRING_BYTEPOS (*it),
9191 it->bidi_it.scan_dir < 0
9192 ? -1
9193 : it->string_nchars)
9194 && next_element_from_composition (it))
9195 {
9196 return true;
9197 }
9198 else if (STRING_MULTIBYTE (it->string))
9199 {
9200 const unsigned char *s = (SDATA (it->string)
9201 + IT_STRING_BYTEPOS (*it));
9202 it->c = check_char_and_length (s, &it->len);
9203 }
9204 else
9205 {
9206 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9207 it->len = 1;
9208 }
9209 }
9210
9211
9212 it->what = IT_CHARACTER;
9213 it->object = it->string;
9214 it->position = position;
9215 return true;
9216 }
9217
9218
9219
9220
9221
9222
9223
9224
9225
9226 static bool
9227 next_element_from_c_string (struct it *it)
9228 {
9229 bool success_p = true;
9230
9231 eassert (it->s);
9232 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9233 it->what = IT_CHARACTER;
9234 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9235 it->object = make_fixnum (0);
9236
9237
9238
9239
9240
9241 if (it->bidi_p && it->bidi_it.first_elt)
9242 get_visually_first_element (it);
9243
9244
9245
9246
9247 if (IT_CHARPOS (*it) >= it->end_charpos)
9248 {
9249
9250 it->what = IT_EOB;
9251 success_p = false;
9252 }
9253 else if (IT_CHARPOS (*it) >= it->string_nchars)
9254 {
9255
9256 it->c = ' ', it->len = 1;
9257 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9258 }
9259 else if (it->multibyte_p)
9260 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9261 else
9262 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9263
9264 return success_p;
9265 }
9266
9267
9268
9269
9270
9271
9272
9273 static bool
9274 next_element_from_ellipsis (struct it *it)
9275 {
9276 if (it->selective_display_ellipsis_p)
9277 setup_for_ellipsis (it, it->len);
9278 else
9279 {
9280
9281
9282
9283
9284 it->saved_face_id = it->face_id;
9285 it->method = GET_FROM_BUFFER;
9286 it->object = it->w->contents;
9287 reseat_at_next_visible_line_start (it, true);
9288 it->face_before_selective_p = true;
9289 }
9290
9291 return GET_NEXT_DISPLAY_ELEMENT (it);
9292 }
9293
9294
9295
9296
9297
9298
9299
9300 static bool
9301 next_element_from_image (struct it *it)
9302 {
9303 it->what = IT_IMAGE;
9304 return true;
9305 }
9306
9307 static bool
9308 next_element_from_xwidget (struct it *it)
9309 {
9310 it->what = IT_XWIDGET;
9311 return true;
9312 }
9313
9314
9315
9316
9317
9318
9319 static bool
9320 next_element_from_stretch (struct it *it)
9321 {
9322 it->what = IT_STRETCH;
9323 return true;
9324 }
9325
9326
9327
9328
9329
9330
9331 static void
9332 compute_stop_pos_backwards (struct it *it)
9333 {
9334 const int SCAN_BACK_LIMIT = 1000;
9335 struct text_pos pos;
9336 struct display_pos save_current = it->current;
9337 struct text_pos save_position = it->position;
9338 ptrdiff_t charpos = IT_CHARPOS (*it);
9339 ptrdiff_t where_we_are = charpos;
9340 ptrdiff_t save_stop_pos = it->stop_charpos;
9341 ptrdiff_t save_end_pos = it->end_charpos;
9342
9343 eassert (NILP (it->string) && !it->s);
9344 eassert (it->bidi_p);
9345 it->bidi_p = false;
9346 do
9347 {
9348 it->end_charpos = min (charpos + 1, ZV);
9349 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9350 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9351 reseat_1 (it, pos, false);
9352 compute_stop_pos (it);
9353
9354 if (it->stop_charpos <= charpos)
9355 emacs_abort ();
9356 }
9357 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9358
9359 if (it->stop_charpos <= where_we_are)
9360 it->prev_stop = it->stop_charpos;
9361 else
9362 it->prev_stop = BEGV;
9363 it->bidi_p = true;
9364 it->current = save_current;
9365 it->position = save_position;
9366 it->stop_charpos = save_stop_pos;
9367 it->end_charpos = save_end_pos;
9368 }
9369
9370
9371
9372
9373
9374
9375
9376
9377
9378 static void
9379 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9380 {
9381 bool bufp = !STRINGP (it->string);
9382 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9383 struct display_pos save_current = it->current;
9384 struct text_pos save_position = it->position;
9385 struct composition_it save_cmp_it = it->cmp_it;
9386 struct text_pos pos1;
9387 ptrdiff_t next_stop;
9388
9389
9390 eassert (it->bidi_p);
9391 it->bidi_p = false;
9392 do
9393 {
9394 it->prev_stop = charpos;
9395 if (bufp)
9396 {
9397 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9398 reseat_1 (it, pos1, false);
9399 }
9400 else
9401 it->current.string_pos = string_pos (charpos, it->string);
9402 compute_stop_pos (it);
9403
9404 if (it->stop_charpos <= it->prev_stop)
9405 emacs_abort ();
9406 charpos = it->stop_charpos;
9407 }
9408 while (charpos <= where_we_are);
9409
9410 it->bidi_p = true;
9411 it->current = save_current;
9412 it->position = save_position;
9413 it->cmp_it = save_cmp_it;
9414 next_stop = it->stop_charpos;
9415 it->stop_charpos = it->prev_stop;
9416 handle_stop (it);
9417 it->stop_charpos = next_stop;
9418 }
9419
9420
9421
9422
9423
9424
9425 static bool
9426 next_element_from_buffer (struct it *it)
9427 {
9428 bool success_p = true;
9429
9430 eassert (IT_CHARPOS (*it) >= BEGV);
9431 eassert (NILP (it->string) && !it->s);
9432 eassert (!it->bidi_p
9433 || (NILP (it->bidi_it.string.lstring)
9434 && it->bidi_it.string.s == NULL));
9435
9436
9437
9438
9439
9440 if (it->bidi_p && it->bidi_it.first_elt)
9441 {
9442 get_visually_first_element (it);
9443 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9444 }
9445
9446 if (IT_CHARPOS (*it) >= it->stop_charpos)
9447 {
9448 if (IT_CHARPOS (*it) >= it->end_charpos)
9449 {
9450 bool overlay_strings_follow_p;
9451
9452
9453
9454 if (it->overlay_strings_at_end_processed_p)
9455 overlay_strings_follow_p = false;
9456 else
9457 {
9458 it->overlay_strings_at_end_processed_p = true;
9459 overlay_strings_follow_p = get_overlay_strings (it, 0);
9460 }
9461
9462 if (overlay_strings_follow_p)
9463 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9464 else
9465 {
9466 it->what = IT_EOB;
9467 it->position = it->current.pos;
9468 success_p = false;
9469 }
9470 }
9471 else if (!(!it->bidi_p
9472 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9473 || IT_CHARPOS (*it) == it->stop_charpos))
9474 {
9475
9476
9477
9478
9479
9480
9481 handle_stop_backwards (it, it->stop_charpos);
9482 it->ignore_overlay_strings_at_pos_p = false;
9483 return GET_NEXT_DISPLAY_ELEMENT (it);
9484 }
9485 else
9486 {
9487 if (it->bidi_p)
9488 {
9489
9490
9491 it->prev_stop = it->stop_charpos;
9492
9493
9494
9495 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9496 it->base_level_stop = it->stop_charpos;
9497 }
9498 handle_stop (it);
9499 it->ignore_overlay_strings_at_pos_p = false;
9500 return GET_NEXT_DISPLAY_ELEMENT (it);
9501 }
9502 }
9503 else if (it->bidi_p
9504
9505
9506
9507 && IT_CHARPOS (*it) < it->prev_stop
9508
9509
9510
9511
9512 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9513 {
9514 if (it->base_level_stop <= 0
9515 || IT_CHARPOS (*it) < it->base_level_stop)
9516 {
9517
9518
9519
9520
9521 it->base_level_stop = BEGV;
9522 compute_stop_pos_backwards (it);
9523 handle_stop_backwards (it, it->prev_stop);
9524 }
9525 else
9526 handle_stop_backwards (it, it->base_level_stop);
9527 it->ignore_overlay_strings_at_pos_p = false;
9528 return GET_NEXT_DISPLAY_ELEMENT (it);
9529 }
9530 else
9531 {
9532
9533
9534 unsigned char *p;
9535 ptrdiff_t stop;
9536
9537
9538
9539 it->ignore_overlay_strings_at_pos_p = false;
9540
9541 if (composition_break_at_point
9542 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9543 && !NILP (Vauto_composition_mode))
9544 {
9545
9546 if (it->bidi_it.scan_dir < 0)
9547 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9548 else
9549 stop = (IT_CHARPOS (*it) < PT
9550 && PT < it->end_charpos) ? PT : it->end_charpos;
9551 }
9552 else
9553 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9554 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9555 stop)
9556 && next_element_from_composition (it))
9557 {
9558 return true;
9559 }
9560
9561
9562 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9563 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9564 it->c = string_char_and_length (p, &it->len);
9565 else
9566 it->c = *p, it->len = 1;
9567
9568
9569 it->what = IT_CHARACTER;
9570 it->object = it->w->contents;
9571 it->position = it->current.pos;
9572
9573
9574
9575 if (it->selective)
9576 {
9577 if (it->c == '\n')
9578 {
9579
9580
9581 if (it->selective > 0
9582 && IT_CHARPOS (*it) + 1 < ZV
9583 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9584 IT_BYTEPOS (*it) + 1,
9585 it->selective))
9586 {
9587 success_p = next_element_from_ellipsis (it);
9588 it->dpvec_char_len = -1;
9589 }
9590 }
9591 else if (it->c == '\r' && it->selective == -1)
9592 {
9593
9594
9595
9596 success_p = next_element_from_ellipsis (it);
9597 it->dpvec_char_len = -1;
9598 }
9599 }
9600 }
9601
9602
9603 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9604 return success_p;
9605 }
9606
9607
9608
9609
9610
9611
9612
9613 static bool
9614 next_element_from_composition (struct it *it)
9615 {
9616 it->what = IT_COMPOSITION;
9617 it->len = it->cmp_it.nbytes;
9618 if (STRINGP (it->string))
9619 {
9620 if (it->c < 0)
9621 {
9622 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9623 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9624 return false;
9625 }
9626 it->position = it->current.string_pos;
9627 it->object = it->string;
9628 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9629 IT_STRING_BYTEPOS (*it), it->string);
9630 }
9631 else
9632 {
9633 if (it->c < 0)
9634 {
9635 IT_CHARPOS (*it) += it->cmp_it.nchars;
9636 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9637 if (it->bidi_p)
9638 {
9639 if (it->bidi_it.new_paragraph)
9640 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9641 false);
9642
9643
9644 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9645 bidi_move_to_visually_next (&it->bidi_it);
9646 }
9647 return false;
9648 }
9649 it->position = it->current.pos;
9650 it->object = it->w->contents;
9651 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9652 IT_BYTEPOS (*it), Qnil);
9653 }
9654 return true;
9655 }
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9667 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
9668
9669
9670
9671
9672
9673
9674
9675
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703 static enum move_it_result
9704 move_it_in_display_line_to (struct it *it,
9705 ptrdiff_t to_charpos, int to_x,
9706 enum move_operation_enum op)
9707 {
9708 enum move_it_result result = MOVE_UNDEFINED;
9709 struct glyph_row *saved_glyph_row;
9710 struct it wrap_it, atpos_it, atx_it, ppos_it;
9711 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9712 void *ppos_data = NULL;
9713 bool may_wrap = false;
9714 enum it_method prev_method = it->method;
9715 ptrdiff_t closest_pos UNINIT;
9716 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9717 bool saw_smaller_pos = prev_pos < to_charpos;
9718 bool line_number_pending = false;
9719
9720
9721 saved_glyph_row = it->glyph_row;
9722 it->glyph_row = NULL;
9723
9724
9725
9726
9727
9728
9729 wrap_it.sp = -1;
9730 atpos_it.sp = -1;
9731 atx_it.sp = -1;
9732
9733
9734
9735
9736
9737
9738
9739
9740 if (it->bidi_p)
9741 {
9742 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9743 {
9744 SAVE_IT (ppos_it, *it, ppos_data);
9745 closest_pos = IT_CHARPOS (*it);
9746 }
9747 else
9748 closest_pos = ZV;
9749 }
9750
9751 #define BUFFER_POS_REACHED_P() \
9752 ((op & MOVE_TO_POS) != 0 \
9753 && BUFFERP (it->object) \
9754 && (IT_CHARPOS (*it) == to_charpos \
9755 || ((!it->bidi_p \
9756 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9757 && IT_CHARPOS (*it) > to_charpos) \
9758 || (it->what == IT_COMPOSITION \
9759 && ((IT_CHARPOS (*it) > to_charpos \
9760 && to_charpos >= it->cmp_it.charpos) \
9761 || (IT_CHARPOS (*it) < to_charpos \
9762 && to_charpos <= it->cmp_it.charpos)))) \
9763 && (it->method == GET_FROM_BUFFER \
9764 || (it->method == GET_FROM_DISPLAY_VECTOR \
9765 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9766
9767 if (it->hpos == 0)
9768 {
9769
9770
9771
9772
9773 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9774 && should_produce_line_number (it))
9775 {
9776 if (it->current_x == it->first_visible_x)
9777 maybe_produce_line_number (it);
9778 else
9779 line_number_pending = true;
9780 }
9781
9782 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9783 handle_line_prefix (it);
9784 }
9785
9786 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9787 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9788
9789 while (true)
9790 {
9791 int x, i, ascent = 0, descent = 0;
9792
9793
9794 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9795 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9796 (IT)->max_descent = descent)
9797
9798
9799
9800 if ((op & MOVE_TO_POS) != 0
9801 && BUFFERP (it->object)
9802 && it->method == GET_FROM_BUFFER
9803 && (((!it->bidi_p
9804
9805
9806
9807
9808 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9809 && IT_CHARPOS (*it) > to_charpos)
9810 || (it->bidi_p
9811 && (prev_method == GET_FROM_IMAGE
9812 || prev_method == GET_FROM_STRETCH
9813 || prev_method == GET_FROM_STRING)
9814
9815 && ((prev_pos < to_charpos
9816 && IT_CHARPOS (*it) >= to_charpos)
9817
9818 || (prev_pos > to_charpos
9819 && IT_CHARPOS (*it) <= to_charpos)))))
9820 {
9821 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9822 {
9823 result = MOVE_POS_MATCH_OR_ZV;
9824 break;
9825 }
9826 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9827
9828
9829
9830 SAVE_IT (atpos_it, *it, atpos_data);
9831 }
9832
9833
9834
9835
9836
9837 if (!get_next_display_element (it))
9838 {
9839 result = MOVE_POS_MATCH_OR_ZV;
9840 break;
9841 }
9842
9843 if (it->line_wrap == TRUNCATE)
9844 {
9845
9846
9847
9848
9849
9850
9851 if (BUFFER_POS_REACHED_P ()
9852 && (it->pixel_width > 0
9853 || IT_CHARPOS (*it) > to_charpos
9854 || it->area != TEXT_AREA))
9855 {
9856 result = MOVE_POS_MATCH_OR_ZV;
9857 break;
9858 }
9859 }
9860 else
9861 {
9862 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9863 {
9864 bool next_may_wrap = may_wrap;
9865
9866 if (char_can_wrap_after (it))
9867 next_may_wrap = true;
9868 else
9869 next_may_wrap = false;
9870
9871 if (may_wrap && char_can_wrap_before (it))
9872 {
9873
9874
9875
9876
9877
9878 if (atpos_it.sp >= 0)
9879 {
9880 RESTORE_IT (it, &atpos_it, atpos_data);
9881 result = MOVE_POS_MATCH_OR_ZV;
9882 goto done;
9883 }
9884 if (atx_it.sp >= 0)
9885 {
9886 RESTORE_IT (it, &atx_it, atx_data);
9887 result = MOVE_X_REACHED;
9888 goto done;
9889 }
9890
9891 SAVE_IT (wrap_it, *it, wrap_data);
9892 }
9893
9894 may_wrap = next_may_wrap;
9895 }
9896 }
9897
9898
9899
9900 ascent = it->max_ascent;
9901 descent = it->max_descent;
9902
9903
9904
9905
9906
9907 x = it->current_x;
9908
9909 PRODUCE_GLYPHS (it);
9910
9911 if (it->area != TEXT_AREA)
9912 {
9913 prev_method = it->method;
9914 if (it->method == GET_FROM_BUFFER)
9915 prev_pos = IT_CHARPOS (*it);
9916 set_iterator_to_next (it, true);
9917 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9918 SET_TEXT_POS (this_line_min_pos,
9919 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9920 if (it->bidi_p
9921 && (op & MOVE_TO_POS)
9922 && IT_CHARPOS (*it) > to_charpos
9923 && IT_CHARPOS (*it) < closest_pos)
9924 closest_pos = IT_CHARPOS (*it);
9925 continue;
9926 }
9927
9928
9929
9930
9931
9932
9933
9934
9935
9936
9937
9938
9939
9940
9941
9942
9943
9944
9945
9946 if (it->nglyphs)
9947 {
9948
9949
9950 int single_glyph_width = it->pixel_width / it->nglyphs;
9951 int new_x;
9952 int x_before_this_char = x;
9953 int hpos_before_this_char = it->hpos;
9954
9955 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9956 {
9957 new_x = x + single_glyph_width;
9958
9959
9960 if ((op & MOVE_TO_X) && new_x > to_x)
9961 {
9962 if (BUFFER_POS_REACHED_P ())
9963 {
9964 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9965 goto buffer_pos_reached;
9966 if (atpos_it.sp < 0)
9967 {
9968 SAVE_IT (atpos_it, *it, atpos_data);
9969 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9970 }
9971 }
9972 else
9973 {
9974 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9975 {
9976 it->current_x = x;
9977 result = MOVE_X_REACHED;
9978 break;
9979 }
9980 if (atx_it.sp < 0)
9981 {
9982 SAVE_IT (atx_it, *it, atx_data);
9983 IT_RESET_X_ASCENT_DESCENT (&atx_it);
9984 }
9985 }
9986 }
9987
9988 if (
9989 it->line_wrap != TRUNCATE
9990 && (
9991 new_x > it->last_visible_x
9992
9993
9994 || (new_x == it->last_visible_x
9995 && FRAME_WINDOW_P (it->f)
9996 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
9997 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
9998 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
9999 {
10000 bool moved_forward = false;
10001
10002 if (
10003
10004 it->hpos == 0
10005 || (new_x == it->last_visible_x
10006 && FRAME_WINDOW_P (it->f)))
10007 {
10008 ++it->hpos;
10009 it->current_x = new_x;
10010
10011
10012
10013 if (i == it->nglyphs - 1)
10014 {
10015
10016
10017
10018 if (BUFFER_POS_REACHED_P ())
10019 {
10020 bool can_wrap = true;
10021
10022
10023
10024
10025
10026 if (it->line_wrap == WORD_WRAP
10027 && wrap_it.sp >= 0
10028 && may_wrap
10029 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10030 {
10031 struct it tem_it;
10032 void *tem_data = NULL;
10033
10034 SAVE_IT (tem_it, *it, tem_data);
10035 set_iterator_to_next (it, true);
10036 if (get_next_display_element (it)
10037 && !char_can_wrap_before (it))
10038 can_wrap = false;
10039 RESTORE_IT (it, &tem_it, tem_data);
10040 }
10041 if (it->line_wrap != WORD_WRAP
10042 || wrap_it.sp < 0
10043
10044
10045
10046
10047
10048
10049
10050 || (may_wrap && can_wrap
10051 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10052 {
10053 it->hpos = hpos_before_this_char;
10054 it->current_x = x_before_this_char;
10055 result = MOVE_POS_MATCH_OR_ZV;
10056 break;
10057 }
10058 if (it->line_wrap == WORD_WRAP
10059 && atpos_it.sp < 0)
10060 {
10061 SAVE_IT (atpos_it, *it, atpos_data);
10062 atpos_it.current_x = x_before_this_char;
10063 atpos_it.hpos = hpos_before_this_char;
10064 }
10065 }
10066
10067 prev_method = it->method;
10068 if (it->method == GET_FROM_BUFFER)
10069 prev_pos = IT_CHARPOS (*it);
10070 set_iterator_to_next (it, true);
10071 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10072 SET_TEXT_POS (this_line_min_pos,
10073 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10074
10075
10076
10077
10078
10079
10080
10081 if (!FRAME_WINDOW_P (it->f)
10082 || ((it->bidi_p
10083 && it->bidi_it.paragraph_dir == R2L)
10084 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10085 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10086 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10087 {
10088 if (!get_next_display_element (it))
10089 {
10090 result = MOVE_POS_MATCH_OR_ZV;
10091 break;
10092 }
10093 moved_forward = true;
10094 if (BUFFER_POS_REACHED_P ())
10095 {
10096 if (ITERATOR_AT_END_OF_LINE_P (it))
10097 result = MOVE_POS_MATCH_OR_ZV;
10098 else
10099 result = MOVE_LINE_CONTINUED;
10100 break;
10101 }
10102 if (ITERATOR_AT_END_OF_LINE_P (it)
10103 && (it->line_wrap != WORD_WRAP
10104 || wrap_it.sp < 0
10105 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10106 {
10107 result = MOVE_NEWLINE_OR_CR;
10108 break;
10109 }
10110 }
10111 }
10112 }
10113 else
10114 IT_RESET_X_ASCENT_DESCENT (it);
10115
10116
10117
10118
10119
10120
10121 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10122
10123
10124
10125
10126
10127 && (!moved_forward || char_can_wrap_before (it)))
10128 {
10129
10130
10131 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10132 && atx_it.sp >= 0)
10133 {
10134 RESTORE_IT (it, &atx_it, atx_data);
10135 atpos_it.sp = -1;
10136 atx_it.sp = -1;
10137 result = MOVE_X_REACHED;
10138 break;
10139 }
10140 }
10141 else if (wrap_it.sp >= 0)
10142 {
10143 RESTORE_IT (it, &wrap_it, wrap_data);
10144 atpos_it.sp = -1;
10145 atx_it.sp = -1;
10146 }
10147
10148 move_trace ("move_it_in: continued at %td\n",
10149 IT_CHARPOS (*it));
10150 result = MOVE_LINE_CONTINUED;
10151 break;
10152 }
10153
10154 if (BUFFER_POS_REACHED_P ())
10155 {
10156 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10157 goto buffer_pos_reached;
10158 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10159 {
10160 SAVE_IT (atpos_it, *it, atpos_data);
10161 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10162 }
10163 }
10164
10165 if (new_x > it->first_visible_x)
10166 {
10167
10168
10169 if (line_number_pending)
10170 {
10171 line_number_pending = false;
10172 it->current_x = it->first_visible_x;
10173 maybe_produce_line_number (it);
10174 it->current_x += new_x - it->first_visible_x;
10175 }
10176
10177
10178 ++it->hpos;
10179 }
10180 }
10181
10182 if (result != MOVE_UNDEFINED)
10183 break;
10184 }
10185 else if (BUFFER_POS_REACHED_P ())
10186 {
10187 buffer_pos_reached:
10188 IT_RESET_X_ASCENT_DESCENT (it);
10189 result = MOVE_POS_MATCH_OR_ZV;
10190 break;
10191 }
10192 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10193 {
10194
10195
10196
10197
10198 eassert (it->nglyphs == 0);
10199 result = MOVE_X_REACHED;
10200 break;
10201 }
10202
10203
10204 if (ITERATOR_AT_END_OF_LINE_P (it))
10205 {
10206
10207
10208
10209
10210 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10211 {
10212 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10213 {
10214 if (closest_pos < ZV)
10215 {
10216 RESTORE_IT (it, &ppos_it, ppos_data);
10217
10218
10219 if (closest_pos != to_charpos)
10220 move_it_in_display_line_to (it, closest_pos, -1,
10221 MOVE_TO_POS);
10222 result = MOVE_POS_MATCH_OR_ZV;
10223 }
10224 else
10225 goto buffer_pos_reached;
10226 }
10227 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10228 && IT_CHARPOS (*it) > to_charpos)
10229 goto buffer_pos_reached;
10230 else
10231 result = MOVE_NEWLINE_OR_CR;
10232 }
10233 else
10234 result = MOVE_NEWLINE_OR_CR;
10235
10236
10237
10238
10239 if (it->line_wrap == TRUNCATE
10240 && it->current_x <= it->first_visible_x
10241 && result == MOVE_NEWLINE_OR_CR
10242 && it->char_to_display == '\n')
10243 {
10244 it->max_ascent = it->ascent;
10245 it->max_descent = it->descent;
10246 }
10247
10248
10249
10250 if (result == MOVE_NEWLINE_OR_CR)
10251 it->constrain_row_ascent_descent_p = false;
10252 break;
10253 }
10254
10255 prev_method = it->method;
10256 if (it->method == GET_FROM_BUFFER)
10257 prev_pos = IT_CHARPOS (*it);
10258
10259
10260
10261
10262
10263
10264
10265
10266
10267 bool overwide_wrap_prefix =
10268 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10269 && it->sp > 0 && it->method == GET_FROM_STRETCH
10270 && it->current_x >= it->last_visible_x
10271 && it->continuation_lines_width > 0
10272 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10273
10274
10275 if (!overwide_wrap_prefix)
10276 set_iterator_to_next (it, true);
10277 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10278 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10279 if (IT_CHARPOS (*it) < to_charpos)
10280 saw_smaller_pos = true;
10281 if (it->bidi_p
10282 && (op & MOVE_TO_POS)
10283 && IT_CHARPOS (*it) >= to_charpos
10284 && IT_CHARPOS (*it) < closest_pos)
10285 closest_pos = IT_CHARPOS (*it);
10286
10287
10288
10289 if (it->line_wrap == TRUNCATE
10290 && it->current_x >= it->last_visible_x)
10291 {
10292 if (!FRAME_WINDOW_P (it->f)
10293 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10294 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10295 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10296 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10297 {
10298 bool at_eob_p = false;
10299
10300 if ((at_eob_p = !get_next_display_element (it))
10301 || BUFFER_POS_REACHED_P ()
10302
10303
10304
10305
10306 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10307 && !saw_smaller_pos
10308 && IT_CHARPOS (*it) > to_charpos))
10309 {
10310 if (it->bidi_p
10311 && !BUFFER_POS_REACHED_P ()
10312 && !at_eob_p && closest_pos < ZV)
10313 {
10314 RESTORE_IT (it, &ppos_it, ppos_data);
10315 if (closest_pos != to_charpos)
10316 move_it_in_display_line_to (it, closest_pos, -1,
10317 MOVE_TO_POS);
10318 }
10319 result = MOVE_POS_MATCH_OR_ZV;
10320 break;
10321 }
10322 if (ITERATOR_AT_END_OF_LINE_P (it))
10323 {
10324 result = MOVE_NEWLINE_OR_CR;
10325 break;
10326 }
10327 }
10328 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10329 && !saw_smaller_pos
10330 && IT_CHARPOS (*it) > to_charpos)
10331 {
10332 if (closest_pos < ZV)
10333 {
10334 RESTORE_IT (it, &ppos_it, ppos_data);
10335 if (closest_pos != to_charpos)
10336 move_it_in_display_line_to (it, closest_pos, -1,
10337 MOVE_TO_POS);
10338 }
10339 result = MOVE_POS_MATCH_OR_ZV;
10340 break;
10341 }
10342 result = MOVE_LINE_TRUNCATED;
10343 break;
10344 }
10345 #undef IT_RESET_X_ASCENT_DESCENT
10346 }
10347
10348 #undef BUFFER_POS_REACHED_P
10349
10350
10351
10352
10353
10354
10355 if (result == MOVE_LINE_CONTINUED
10356 && it->line_wrap == WORD_WRAP
10357 && wrap_it.sp >= 0
10358 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10359 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10360 RESTORE_IT (it, &wrap_it, wrap_data);
10361 else if (atpos_it.sp >= 0)
10362 RESTORE_IT (it, &atpos_it, atpos_data);
10363 else if (atx_it.sp >= 0)
10364 RESTORE_IT (it, &atx_it, atx_data);
10365
10366 done:
10367
10368 if (atpos_data)
10369 bidi_unshelve_cache (atpos_data, true);
10370 if (atx_data)
10371 bidi_unshelve_cache (atx_data, true);
10372 if (wrap_data)
10373 bidi_unshelve_cache (wrap_data, true);
10374 if (ppos_data)
10375 bidi_unshelve_cache (ppos_data, true);
10376
10377
10378
10379 it->glyph_row = saved_glyph_row;
10380 return result;
10381 }
10382
10383
10384 void
10385 move_it_in_display_line (struct it *it,
10386 ptrdiff_t to_charpos, int to_x,
10387 enum move_operation_enum op)
10388 {
10389 if (it->line_wrap == WORD_WRAP
10390 && (op & MOVE_TO_X))
10391 {
10392 struct it save_it;
10393 void *save_data = NULL;
10394 int skip;
10395
10396 SAVE_IT (save_it, *it, save_data);
10397 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10398
10399
10400
10401
10402 if (skip == MOVE_LINE_CONTINUED)
10403 {
10404 int prev_x = max (it->current_x - 1, 0);
10405 RESTORE_IT (it, &save_it, save_data);
10406 move_it_in_display_line_to
10407 (it, -1, prev_x, MOVE_TO_X);
10408 }
10409 else
10410 bidi_unshelve_cache (save_data, true);
10411 }
10412 else
10413 move_it_in_display_line_to (it, to_charpos, to_x, op);
10414 }
10415
10416
10417
10418
10419
10420
10421
10422
10423
10424
10425
10426
10427
10428
10429
10430
10431 int
10432 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10433 {
10434 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10435 int line_height, line_start_x = 0, reached = 0;
10436 int max_current_x = 0;
10437 void *backup_data = NULL;
10438 ptrdiff_t orig_charpos = -1;
10439 enum it_method orig_method = NUM_IT_METHODS;
10440
10441 for (;;)
10442 {
10443 orig_charpos = IT_CHARPOS (*it);
10444 orig_method = it->method;
10445 if (op & MOVE_TO_VPOS)
10446 {
10447
10448
10449 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10450 {
10451 if (it->vpos == to_vpos)
10452 {
10453 reached = 1;
10454 break;
10455 }
10456 else
10457 skip = move_it_in_display_line_to (it, -1, -1, 0);
10458 }
10459 else
10460 {
10461
10462
10463 if (it->vpos == to_vpos)
10464 {
10465 reached = 2;
10466 break;
10467 }
10468
10469 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10470
10471 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10472 {
10473 reached = 3;
10474 break;
10475 }
10476 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10477 {
10478
10479 skip = move_it_in_display_line_to (it, to_charpos,
10480 -1, MOVE_TO_POS);
10481 if (skip == MOVE_POS_MATCH_OR_ZV)
10482 {
10483 reached = 4;
10484 break;
10485 }
10486 }
10487 }
10488 }
10489 else if (op & MOVE_TO_Y)
10490 {
10491 struct it it_backup;
10492
10493 if (it->line_wrap == WORD_WRAP)
10494 SAVE_IT (it_backup, *it, backup_data);
10495
10496
10497
10498
10499
10500
10501
10502
10503
10504
10505
10506
10507
10508 skip = move_it_in_display_line_to
10509 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10510 (MOVE_TO_X | (op & MOVE_TO_POS)));
10511
10512
10513 if (skip == MOVE_POS_MATCH_OR_ZV)
10514 reached = 5;
10515 else if (skip == MOVE_X_REACHED)
10516 {
10517
10518
10519
10520
10521 line_height = it->max_ascent + it->max_descent;
10522 if (to_y >= it->current_y
10523 && to_y < it->current_y + line_height)
10524 {
10525 reached = 6;
10526 break;
10527 }
10528 SAVE_IT (it_backup, *it, backup_data);
10529 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10530 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10531 op & MOVE_TO_POS);
10532 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10533 line_height = it->max_ascent + it->max_descent;
10534 move_trace ("move_it: line_height = %d\n", line_height);
10535
10536 if (to_y >= it->current_y
10537 && to_y < it->current_y + line_height)
10538 {
10539
10540
10541
10542
10543
10544
10545
10546
10547 int max_ascent = it->max_ascent;
10548 int max_descent = it->max_descent;
10549
10550 RESTORE_IT (it, &it_backup, backup_data);
10551 it->max_ascent = max_ascent;
10552 it->max_descent = max_descent;
10553 reached = 6;
10554 }
10555 else
10556 {
10557 skip = skip2;
10558 if (skip == MOVE_POS_MATCH_OR_ZV)
10559 {
10560 reached = 7;
10561
10562
10563
10564
10565
10566
10567
10568 if (to_charpos > 0
10569 && IT_CHARPOS (*it) != to_charpos
10570 && ((IT_CHARPOS (it_backup) > to_charpos)
10571 == (IT_CHARPOS (*it) > to_charpos)))
10572 {
10573 int max_ascent = it->max_ascent;
10574 int max_descent = it->max_descent;
10575
10576 RESTORE_IT (it, &it_backup, backup_data);
10577 it->max_ascent = max_ascent;
10578 it->max_descent = max_descent;
10579 }
10580 }
10581 }
10582 }
10583 else
10584 {
10585
10586 line_height = it->max_ascent + it->max_descent;
10587 move_trace ("move_it: line_height = %d\n", line_height);
10588
10589 if (to_y >= it->current_y
10590 && to_y < it->current_y + line_height)
10591 {
10592 if (to_y > it->current_y)
10593 max_current_x = max (it->current_x, max_current_x);
10594
10595
10596
10597
10598
10599 if (skip == MOVE_LINE_CONTINUED
10600 && it->line_wrap == WORD_WRAP)
10601 {
10602 int prev_x = max (it->current_x - 1, 0);
10603 RESTORE_IT (it, &it_backup, backup_data);
10604 skip = move_it_in_display_line_to
10605 (it, -1, prev_x, MOVE_TO_X);
10606 }
10607
10608 reached = 6;
10609 }
10610 }
10611
10612 if (reached)
10613 {
10614 max_current_x = max (it->current_x, max_current_x);
10615 break;
10616 }
10617 }
10618 else if (BUFFERP (it->object)
10619 && (it->method == GET_FROM_BUFFER
10620 || it->method == GET_FROM_STRETCH)
10621 && IT_CHARPOS (*it) >= to_charpos
10622
10623
10624
10625
10626
10627 && !(it->bidi_p
10628 && it->bidi_it.scan_dir == -1))
10629 skip = MOVE_POS_MATCH_OR_ZV;
10630 else
10631 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10632
10633 switch (skip)
10634 {
10635 case MOVE_POS_MATCH_OR_ZV:
10636 max_current_x = max (it->current_x, max_current_x);
10637 reached = 8;
10638 goto out;
10639
10640 case MOVE_NEWLINE_OR_CR:
10641 max_current_x = max (it->current_x, max_current_x);
10642 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10643 it->override_ascent = -1;
10644 set_iterator_to_next (it, true);
10645 it->continuation_lines_width = 0;
10646 break;
10647
10648 case MOVE_LINE_TRUNCATED:
10649 max_current_x = it->last_visible_x;
10650 it->continuation_lines_width = 0;
10651 reseat_at_next_visible_line_start (it, false);
10652 if ((op & MOVE_TO_POS) != 0
10653 && (IT_CHARPOS (*it) > to_charpos
10654 || (IT_CHARPOS (*it) == to_charpos
10655
10656
10657 && to_charpos == ZV
10658 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10659
10660
10661
10662 && (it->sp == 0
10663 || (STRINGP (it->string)
10664 && (it->current.overlay_string_index < 0
10665 || (it->current.overlay_string_index >= 0
10666 && it->current.overlay_string_index
10667 >= it->n_overlay_strings - 1))
10668 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10669 {
10670 reached = 9;
10671 goto out;
10672 }
10673 break;
10674
10675 case MOVE_LINE_CONTINUED:
10676 max_current_x = it->last_visible_x;
10677
10678
10679
10680
10681 if (it->c == '\t')
10682 {
10683 it->continuation_lines_width += it->last_visible_x;
10684
10685
10686
10687 if (it->current_x != it->last_visible_x
10688 && (op & MOVE_TO_VPOS)
10689 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10690 {
10691 line_start_x = it->current_x + it->pixel_width
10692 - it->last_visible_x;
10693 if (FRAME_WINDOW_P (it->f))
10694 {
10695 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10696 struct font *face_font = face->font;
10697
10698
10699
10700
10701
10702
10703
10704 eassert (face_font);
10705 if (face_font)
10706 {
10707 if (line_start_x < face_font->space_width)
10708 line_start_x
10709 += it->tab_width * face_font->space_width;
10710 }
10711 }
10712 set_iterator_to_next (it, false);
10713 }
10714 }
10715 else
10716 {
10717
10718
10719
10720
10721
10722
10723
10724
10725 if (IT_CHARPOS (*it) == orig_charpos
10726 && it->method == orig_method
10727 && orig_method == GET_FROM_BUFFER)
10728 set_iterator_to_next (it, false);
10729 it->continuation_lines_width += it->current_x;
10730 }
10731 break;
10732
10733 default:
10734 emacs_abort ();
10735 }
10736
10737
10738 it->current_x = line_start_x;
10739 line_start_x = 0;
10740 it->hpos = 0;
10741 it->line_number_produced_p = false;
10742 it->current_y += it->max_ascent + it->max_descent;
10743 ++it->vpos;
10744 last_height = it->max_ascent + it->max_descent;
10745 it->max_ascent = it->max_descent = 0;
10746 }
10747
10748 out:
10749
10750
10751
10752
10753
10754
10755 if (!FRAME_WINDOW_P (it->f)
10756 && op & MOVE_TO_POS
10757 && IT_CHARPOS (*it) == to_charpos
10758 && it->what == IT_CHARACTER
10759 && it->nglyphs > 1
10760 && it->line_wrap == WINDOW_WRAP
10761 && it->current_x == it->last_visible_x - 1
10762 && it->c != '\n'
10763 && it->c != '\t'
10764 && it->w->window_end_valid
10765 && it->vpos < it->w->window_end_vpos)
10766 {
10767 it->continuation_lines_width += it->current_x;
10768 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10769 it->current_y += it->max_ascent + it->max_descent;
10770 ++it->vpos;
10771 last_height = it->max_ascent + it->max_descent;
10772 }
10773
10774 if (backup_data)
10775 bidi_unshelve_cache (backup_data, true);
10776
10777 move_trace ("move_it_to: reached %d\n", reached);
10778
10779 return max_current_x;
10780 }
10781
10782
10783
10784
10785
10786
10787
10788
10789
10790
10791
10792 void
10793 move_it_vertically_backward (struct it *it, int dy)
10794 {
10795 int nlines, h;
10796 struct it it2, it3;
10797 void *it2data = NULL, *it3data = NULL;
10798 ptrdiff_t start_pos;
10799 int nchars_per_row
10800 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10801 ptrdiff_t pos_limit;
10802
10803 move_further_back:
10804 eassert (dy >= 0);
10805
10806 start_pos = IT_CHARPOS (*it);
10807
10808
10809 nlines = max (1, dy / default_line_pixel_height (it->w));
10810 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10811 pos_limit = BEGV;
10812 else
10813 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10814
10815
10816
10817
10818 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10819 back_to_previous_visible_line_start (it);
10820
10821
10822
10823
10824
10825 reseat_1 (it, it->current.pos, true);
10826
10827
10828 it->current_x = it->hpos = 0;
10829
10830 it->continuation_lines_width = 0;
10831
10832
10833
10834
10835
10836 SAVE_IT (it2, *it, it2data);
10837 it2.max_ascent = it2.max_descent = 0;
10838 do
10839 {
10840 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10841 MOVE_TO_POS | MOVE_TO_VPOS);
10842 }
10843 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10844
10845
10846
10847
10848
10849
10850 || (it2.method == GET_FROM_STRING
10851 && IT_CHARPOS (it2) == start_pos
10852 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10853 eassert (IT_CHARPOS (*it) >= BEGV);
10854 SAVE_IT (it3, it2, it3data);
10855
10856 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10857 eassert (IT_CHARPOS (*it) >= BEGV);
10858
10859
10860 h = it2.current_y - it->current_y;
10861
10862 nlines = it2.vpos - it->vpos;
10863
10864
10865
10866 it->vpos -= nlines;
10867 it->current_y -= h;
10868
10869 if (dy == 0)
10870 {
10871
10872
10873
10874 RESTORE_IT (it, it, it2data);
10875 if (nlines > 0)
10876 move_it_by_lines (it, nlines);
10877
10878
10879
10880
10881
10882
10883 if (it->bidi_p
10884 && !it->continuation_lines_width
10885 && !STRINGP (it->string)
10886 && IT_CHARPOS (*it) > BEGV
10887 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10888 {
10889 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10890
10891 dec_both (&cp, &bp);
10892 SET_WITH_NARROWED_BEGV (it, cp,
10893 find_newline_no_quit (cp, bp, -1, NULL),
10894 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10895 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10896 }
10897 bidi_unshelve_cache (it3data, true);
10898 }
10899 else
10900 {
10901
10902
10903 int target_y = it->current_y + h - dy;
10904 int y0 = it3.current_y;
10905 int y1;
10906 int line_height;
10907
10908 RESTORE_IT (&it3, &it3, it3data);
10909 y1 = line_bottom_y (&it3);
10910 line_height = y1 - y0;
10911 RESTORE_IT (it, it, it2data);
10912
10913
10914 if (target_y < it->current_y
10915
10916
10917
10918
10919 && (it->current_y - target_y
10920 > min (window_box_height (it->w), line_height * 2 / 3))
10921 && IT_CHARPOS (*it) > BEGV)
10922 {
10923 move_trace (" not far enough -> move_vert %d\n",
10924 target_y - it->current_y);
10925 dy = it->current_y - target_y;
10926 goto move_further_back;
10927 }
10928 else if (target_y >= it->current_y + line_height
10929 && IT_CHARPOS (*it) < ZV)
10930 {
10931
10932
10933
10934
10935
10936
10937
10938
10939 if (!FRAME_WINDOW_P (it->f))
10940 move_it_vertically (it, target_y - it->current_y);
10941 else
10942 {
10943 struct text_pos last_pos;
10944 int last_y, last_vpos;
10945 do
10946 {
10947 last_pos = it->current.pos;
10948 last_y = it->current_y;
10949 last_vpos = it->vpos;
10950 move_it_by_lines (it, 1);
10951 }
10952 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10953 if (it->current_y > target_y)
10954 {
10955 reseat (it, last_pos, true);
10956 it->current_y = last_y;
10957 it->vpos = last_vpos;
10958 }
10959 }
10960 }
10961 }
10962 }
10963
10964
10965
10966
10967
10968
10969 void
10970 move_it_vertically (struct it *it, int dy)
10971 {
10972 if (dy <= 0)
10973 move_it_vertically_backward (it, -dy);
10974 else
10975 {
10976 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
10977 move_it_to (it, ZV, -1, it->current_y + dy, -1,
10978 MOVE_TO_POS | MOVE_TO_Y);
10979 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
10980
10981
10982
10983 if (IT_CHARPOS (*it) == ZV
10984 && ZV > BEGV
10985 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10986 move_it_by_lines (it, 0);
10987 }
10988 }
10989
10990
10991
10992
10993 void
10994 move_it_past_eol (struct it *it)
10995 {
10996 enum move_it_result rc;
10997
10998 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
10999 if (rc == MOVE_NEWLINE_OR_CR)
11000 set_iterator_to_next (it, false);
11001 }
11002
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012 void
11013 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
11014 {
11015
11016
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027
11028
11029
11030
11031
11032 if (dvpos == 0)
11033 {
11034
11035 move_it_vertically_backward (it, 0);
11036
11037 last_height = 0;
11038 }
11039 else if (dvpos > 0)
11040 {
11041 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
11042 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11043 {
11044
11045
11046
11047
11048
11049
11050
11051
11052
11053
11054 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11055 -1, -1, -1, MOVE_TO_POS);
11056 }
11057 }
11058 else
11059 {
11060 struct it it2;
11061 void *it2data = NULL;
11062 ptrdiff_t start_charpos, orig_charpos, i;
11063 int nchars_per_row
11064 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11065 bool hit_pos_limit = false;
11066 ptrdiff_t pos_limit;
11067
11068
11069
11070
11071 dvpos += it->vpos;
11072 orig_charpos = IT_CHARPOS (*it);
11073 move_it_vertically_backward (it, 0);
11074 dvpos -= it->vpos;
11075
11076
11077
11078 start_charpos = IT_CHARPOS (*it);
11079 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11080 pos_limit = BEGV;
11081 else
11082 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11083
11084 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11085 back_to_previous_visible_line_start (it);
11086 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11087 hit_pos_limit = true;
11088 reseat (it, it->current.pos, true);
11089
11090
11091 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11092 {
11093
11094 dvpos += it->vpos;
11095 move_it_vertically_backward (it, 0);
11096 dvpos -= it->vpos;
11097 if (IT_POS_VALID_AFTER_MOVE_P (it))
11098 break;
11099
11100
11101 back_to_previous_visible_line_start (it);
11102 reseat (it, it->current.pos, true);
11103 dvpos--;
11104 }
11105
11106 it->current_x = it->hpos = 0;
11107
11108
11109
11110 SAVE_IT (it2, *it, it2data);
11111 it2.vpos = it2.current_y = 0;
11112 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11113 it->vpos -= it2.vpos;
11114 it->current_y -= it2.current_y;
11115 it->current_x = it->hpos = 0;
11116
11117
11118 if (it2.vpos > -dvpos)
11119 {
11120 int delta = it2.vpos + dvpos;
11121
11122 RESTORE_IT (&it2, &it2, it2data);
11123 SAVE_IT (it2, *it, it2data);
11124 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11125
11126
11127 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11128 RESTORE_IT (it, &it2, it2data);
11129 else
11130 bidi_unshelve_cache (it2data, true);
11131 }
11132 else if (hit_pos_limit && pos_limit > BEGV
11133 && dvpos < 0 && it2.vpos < -dvpos)
11134 {
11135
11136
11137
11138
11139
11140
11141
11142
11143 dvpos += it2.vpos;
11144 RESTORE_IT (it, it, it2data);
11145 for (i = -dvpos; i > 0; --i)
11146 {
11147 back_to_previous_visible_line_start (it);
11148 it->vpos--;
11149 }
11150 reseat_1 (it, it->current.pos, true);
11151 }
11152 else
11153 RESTORE_IT (it, it, it2data);
11154 }
11155 }
11156
11157 int
11158 partial_line_height (struct it *it_origin)
11159 {
11160
11161
11162
11163
11164
11165 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11166 && it_origin->line_wrap == TRUNCATE)
11167 return 0;
11168
11169 int partial_height;
11170 void *it_data = NULL;
11171 struct it it;
11172 SAVE_IT (it, *it_origin, it_data);
11173 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11174 MOVE_TO_POS | MOVE_TO_Y);
11175 if (it.what == IT_EOB)
11176 {
11177 int vis_height = it.last_visible_y - it.current_y;
11178 int height = it.ascent + it.descent;
11179 partial_height = (vis_height < height) ? vis_height : 0;
11180 }
11181 else
11182 {
11183 int last_line_y = it.current_y;
11184 move_it_by_lines (&it, 1);
11185 partial_height = (it.current_y > it.last_visible_y)
11186 ? it.last_visible_y - last_line_y : 0;
11187 }
11188 RESTORE_IT (&it, &it, it_data);
11189 return partial_height;
11190 }
11191
11192
11193
11194
11195
11196
11197
11198
11199
11200
11201
11202
11203 static enum move_it_result
11204 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11205 {
11206 ptrdiff_t nl_bytepos;
11207 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11208 1, &nl_bytepos);
11209 struct text_pos new_pos;
11210 enum move_it_result move_result;
11211
11212 if (nl_pos - IT_CHARPOS (*it) > nchars)
11213 {
11214 SET_TEXT_POS (new_pos,
11215 IT_CHARPOS (*it) + nchars,
11216 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11217 move_result = MOVE_X_REACHED;
11218 }
11219 else
11220 {
11221 if (nl_bytepos < ZV_BYTE
11222 || (nl_bytepos > BEGV_BYTE
11223 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11224 {
11225 nl_pos--;
11226 nl_bytepos--;
11227 move_result = MOVE_NEWLINE_OR_CR;
11228 }
11229 else
11230 move_result = MOVE_POS_MATCH_OR_ZV;
11231 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11232 }
11233 reseat (it, new_pos, false);
11234 return move_result;
11235 }
11236
11237
11238
11239 bool
11240 in_display_vector_p (struct it *it)
11241 {
11242 return (it->method == GET_FROM_DISPLAY_VECTOR
11243 && it->current.dpvec_index > 0
11244 && it->dpvec + it->current.dpvec_index != it->dpend);
11245 }
11246
11247
11248
11249
11250
11251 static Lisp_Object
11252 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11253 Lisp_Object x_limit, Lisp_Object y_limit,
11254 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11255 {
11256 struct window *w = decode_live_window (window);
11257 struct it it;
11258 ptrdiff_t start, end, bpos;
11259 struct text_pos startp;
11260 void *itdata = NULL;
11261 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11262
11263 if (NILP (from))
11264 {
11265 start = BEGV;
11266 bpos = BEGV_BYTE;
11267 }
11268 else if (EQ (from, Qt))
11269 {
11270 start = BEGV;
11271 bpos = BEGV_BYTE;
11272 while (bpos < ZV_BYTE)
11273 {
11274 c = FETCH_BYTE (bpos);
11275 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11276 break;
11277 inc_both (&start, &bpos);
11278 }
11279 while (bpos > BEGV_BYTE)
11280 {
11281 dec_both (&start, &bpos);
11282 c = FETCH_BYTE (bpos);
11283 if (!(c == ' ' || c == '\t'))
11284 break;
11285 }
11286 }
11287 else if (CONSP (from))
11288 {
11289 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11290 bpos = CHAR_TO_BYTE (start);
11291 CHECK_FIXNUM (XCDR (from));
11292 vertical_offset = XFIXNUM (XCDR (from));
11293 }
11294 else
11295 {
11296 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11297 bpos = CHAR_TO_BYTE (start);
11298 }
11299
11300 SET_TEXT_POS (startp, start, bpos);
11301
11302 if (NILP (to))
11303 end = ZV;
11304 else if (EQ (to, Qt))
11305 {
11306 end = ZV;
11307 bpos = ZV_BYTE;
11308 while (bpos > BEGV_BYTE)
11309 {
11310 dec_both (&end, &bpos);
11311 c = FETCH_BYTE (bpos);
11312 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11313 {
11314 inc_both (&end, &bpos);
11315 break;
11316 }
11317 }
11318 while (bpos < ZV_BYTE)
11319 {
11320 c = fetch_char_advance (&end, &bpos);
11321 if (!(c == ' ' || c == '\t'))
11322 break;
11323 }
11324 }
11325 else
11326 end = clip_to_bounds (start, fix_position (to), ZV);
11327
11328 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11329 max_x = XFIXNUM (x_limit);
11330 else if (!NILP (x_limit))
11331 max_x = INT_MAX;
11332
11333 if (NILP (y_limit))
11334 max_y = INT_MAX;
11335 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11336 max_y = XFIXNUM (y_limit);
11337
11338 itdata = bidi_shelve_cache ();
11339
11340 start_display (&it, w, startp);
11341
11342 int start_y = it.current_y;
11343
11344
11345
11346
11347
11348
11349
11350 it.bidi_p = false;
11351
11352 int start_x;
11353 if (vertical_offset != 0)
11354 {
11355 int last_y;
11356 it.current_y = 0;
11357
11358 move_it_by_lines (&it, 0);
11359
11360
11361
11362
11363
11364 if (vertical_offset < 0)
11365 {
11366 while (it.current_y > vertical_offset)
11367 {
11368 last_y = it.current_y;
11369 move_it_vertically_backward (&it,
11370 (abs (vertical_offset)
11371 + it.current_y));
11372
11373 if (it.current_y == last_y)
11374 break;
11375 }
11376 }
11377 else
11378 {
11379 move_it_vertically (&it, vertical_offset);
11380 }
11381
11382 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11383 + WINDOW_HEADER_LINE_HEIGHT (w));
11384 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11385 start_y = it.current_y;
11386 start_x = it.current_x;
11387 }
11388 else
11389 {
11390
11391
11392
11393 reseat_at_previous_visible_line_start (&it);
11394 it.current_x = it.hpos = 0;
11395 if (IT_CHARPOS (it) != start)
11396 {
11397 void *it1data = NULL;
11398 struct it it1;
11399
11400 SAVE_IT (it1, it, it1data);
11401 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11402
11403
11404
11405
11406
11407 if (IT_CHARPOS (it) > start && start > BEGV)
11408 {
11409 ptrdiff_t it1pos = IT_CHARPOS (it1);
11410 int it1_x = it1.current_x;
11411
11412 RESTORE_IT (&it, &it1, it1data);
11413
11414
11415
11416
11417
11418 if (start - 1 > it1pos)
11419 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11420 else
11421 move_it_in_display_line (&it, start, it1_x + 1,
11422 MOVE_TO_POS | MOVE_TO_X);
11423 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11424 start_x = it.current_x;
11425
11426
11427
11428 if (IT_CHARPOS (it) == start - 1)
11429 start_x += it.pixel_width;
11430 }
11431 else
11432 {
11433 start_x = it.current_x;
11434 bidi_unshelve_cache (it1data, true);
11435 }
11436 }
11437 else
11438 start_x = it.current_x;
11439 }
11440
11441
11442 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11443 int to_x = -1;
11444 it.current_y = start_y;
11445
11446
11447 if (FETCH_BYTE (start) == '\n')
11448 it.current_x = 0;
11449 if (!NILP (x_limit))
11450 {
11451 it.last_visible_x = max_x;
11452
11453
11454
11455 move_op |= MOVE_TO_X;
11456 to_x = INT_MAX;
11457 }
11458
11459 void *it2data = NULL;
11460 struct it it2;
11461 SAVE_IT (it2, it, it2data);
11462
11463 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11464
11465
11466
11467
11468
11469 if (IT_CHARPOS (it) > end)
11470 {
11471 end--;
11472 RESTORE_IT (&it, &it2, it2data);
11473 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11474
11475
11476
11477 if (IT_CHARPOS (it) == end)
11478 {
11479 x += it.pixel_width;
11480
11481
11482 if (!NILP (ignore_line_at_end))
11483 doff = (max (it.max_ascent, it.ascent)
11484 + max (it.max_descent, it.descent));
11485 else
11486 {
11487 it.max_ascent = max (it.max_ascent, it.ascent);
11488 it.max_descent = max (it.max_descent, it.descent);
11489 }
11490 }
11491 }
11492 else
11493 bidi_unshelve_cache (it2data, true);
11494
11495 if (!NILP (x_limit))
11496 {
11497
11498 if (x > max_x)
11499 x = max_x;
11500 }
11501
11502
11503
11504
11505 if (it.current_y > start_y)
11506 start_x = 0;
11507
11508
11509
11510 if (!NILP (ignore_line_at_end))
11511 y = (it.current_y + doff
11512 - WINDOW_TAB_LINE_HEIGHT (w)
11513 - WINDOW_HEADER_LINE_HEIGHT (w));
11514 else
11515 y = (it.current_y + it.max_ascent + it.max_descent + doff
11516 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11517
11518
11519 if (y > max_y)
11520 y = max_y;
11521
11522 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11523 && window_wants_tab_line (w))
11524
11525 {
11526 Lisp_Object window_tab_line_format
11527 = window_parameter (w, Qtab_line_format);
11528
11529 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11530 NILP (window_tab_line_format)
11531 ? BVAR (current_buffer, tab_line_format)
11532 : window_tab_line_format);
11533 }
11534
11535 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11536 && window_wants_header_line (w))
11537 {
11538 Lisp_Object window_header_line_format
11539 = window_parameter (w, Qheader_line_format);
11540
11541 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11542 NILP (window_header_line_format)
11543 ? BVAR (current_buffer, header_line_format)
11544 : window_header_line_format);
11545 }
11546
11547 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11548 && window_wants_mode_line (w))
11549 {
11550 Lisp_Object window_mode_line_format
11551 = window_parameter (w, Qmode_line_format);
11552
11553 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11554 NILP (window_mode_line_format)
11555 ? BVAR (current_buffer, mode_line_format)
11556 : window_mode_line_format);
11557 }
11558
11559 bidi_unshelve_cache (itdata, false);
11560
11561 return (!vertical_offset
11562 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11563 : list3i (x - start_x, y, start));
11564 }
11565
11566 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11567 doc:
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615
11616
11617
11618
11619
11620
11621
11622 )
11623 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11624 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11625 {
11626 struct window *w = decode_live_window (window);
11627 struct buffer *b = XBUFFER (w->contents);
11628 struct buffer *old_b = NULL;
11629 Lisp_Object value;
11630
11631 if (b != current_buffer)
11632 {
11633 old_b = current_buffer;
11634 set_buffer_internal_1 (b);
11635 }
11636
11637 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11638 ignore_line_at_end);
11639
11640 if (old_b)
11641 set_buffer_internal_1 (old_b);
11642
11643 return value;
11644 }
11645
11646 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11647 doc:
11648
11649
11650
11651
11652
11653
11654
11655
11656
11657
11658
11659
11660 )
11661 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11662 Lisp_Object y_limit)
11663 {
11664 struct window *w = decode_live_window (window);
11665 struct buffer *b = (NILP (buffer_or_name)
11666 ? current_buffer
11667 : XBUFFER (Fget_buffer (buffer_or_name)));
11668 Lisp_Object buffer, value;
11669 specpdl_ref count = SPECPDL_INDEX ();
11670
11671 XSETBUFFER (buffer, b);
11672
11673
11674
11675
11676 record_unwind_protect (unwind_with_echo_area_buffer,
11677 with_echo_area_buffer_unwind_data (w));
11678
11679 set_buffer_internal_1 (b);
11680
11681 if (!EQ (buffer, w->contents))
11682 {
11683 wset_buffer (w, buffer);
11684 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11685 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11686 }
11687
11688 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11689 Qnil);
11690
11691 unbind_to (count, Qnil);
11692
11693 return value;
11694 }
11695
11696
11697 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11698 Sdisplay__line_is_continued_p, 0, 0, 0,
11699 doc: )
11700 (void)
11701 {
11702 struct buffer *oldb = current_buffer;
11703 struct window *w = XWINDOW (selected_window);
11704 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11705
11706 set_buffer_internal_1 (XBUFFER (w->contents));
11707
11708 if (PT < ZV)
11709 {
11710 struct text_pos startpos;
11711 struct it it;
11712 void *itdata;
11713
11714
11715 Lisp_Object opoint = Fpoint_marker ();
11716
11717
11718
11719 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11720 SET_TEXT_POS (startpos, PT, PT_BYTE);
11721 itdata = bidi_shelve_cache ();
11722 start_display (&it, w, startpos);
11723
11724 if (it.line_wrap != TRUNCATE)
11725 {
11726 it.glyph_row = NULL;
11727 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11728 }
11729 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11730 bidi_unshelve_cache (itdata, false);
11731 }
11732 set_buffer_internal_1 (oldb);
11733
11734 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11735 }
11736
11737
11738
11739
11740
11741
11742
11743
11744 static ptrdiff_t
11745 format_nargs (char const *format)
11746 {
11747 ptrdiff_t nargs = 0;
11748 for (char const *p = format; (p = strchr (p, '%')); p++)
11749 if (p[1] == '%')
11750 p++;
11751 else
11752 nargs++;
11753 return nargs;
11754 }
11755
11756
11757
11758
11759 void
11760 add_to_log (const char *format, ...)
11761 {
11762 va_list ap;
11763 va_start (ap, format);
11764 vadd_to_log (format, ap);
11765 va_end (ap);
11766 }
11767
11768 void
11769 vadd_to_log (char const *format, va_list ap)
11770 {
11771 ptrdiff_t form_nargs = format_nargs (format);
11772 ptrdiff_t nargs = 1 + form_nargs;
11773 Lisp_Object args[10];
11774 eassert (nargs <= ARRAYELTS (args));
11775 AUTO_STRING (args0, format);
11776 args[0] = args0;
11777 for (ptrdiff_t i = 1; i <= nargs; i++)
11778 args[i] = va_arg (ap, Lisp_Object);
11779 Lisp_Object msg = Qnil;
11780 msg = Fformat_message (nargs, args);
11781
11782 ptrdiff_t len = SBYTES (msg) + 1;
11783 USE_SAFE_ALLOCA;
11784 char *buffer = SAFE_ALLOCA (len);
11785 memcpy (buffer, SDATA (msg), len);
11786
11787 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11788 SAFE_FREE ();
11789 }
11790
11791
11792
11793
11794 void
11795 message_log_maybe_newline (void)
11796 {
11797 if (message_log_need_newline)
11798 message_dolog ("", 0, true, false);
11799 }
11800
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811 void
11812 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11813 {
11814 const unsigned char *msg = (const unsigned char *) m;
11815
11816 if (!NILP (Vmemory_full))
11817 return;
11818
11819 if (!NILP (Vmessage_log_max))
11820 {
11821 struct buffer *oldbuf;
11822 Lisp_Object oldpoint, oldbegv, oldzv;
11823 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11824 ptrdiff_t point_at_end = 0;
11825 ptrdiff_t zv_at_end = 0;
11826 Lisp_Object old_deactivate_mark;
11827
11828 old_deactivate_mark = Vdeactivate_mark;
11829 oldbuf = current_buffer;
11830
11831
11832
11833 if (! STRINGP (Vmessages_buffer_name))
11834 Vmessages_buffer_name = build_string ("*Messages*");
11835
11836
11837 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11838 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11839 if (newbuffer
11840 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11841 call0 (intern ("messages-buffer-mode"));
11842
11843 bset_undo_list (current_buffer, Qt);
11844 bset_cache_long_scans (current_buffer, Qnil);
11845
11846 oldpoint = message_dolog_marker1;
11847 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11848 oldbegv = message_dolog_marker2;
11849 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11850 oldzv = message_dolog_marker3;
11851 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11852
11853 if (PT == Z)
11854 point_at_end = 1;
11855 if (ZV == Z)
11856 zv_at_end = 1;
11857
11858 BEGV = BEG;
11859 BEGV_BYTE = BEG_BYTE;
11860 ZV = Z;
11861 ZV_BYTE = Z_BYTE;
11862 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11863
11864
11865
11866 if (multibyte
11867 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11868 {
11869
11870
11871 for (ptrdiff_t i = 0; i < nbytes; )
11872 {
11873 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11874 char work = CHAR_TO_BYTE8 (c);
11875 insert_1_both (&work, 1, 1, true, false, false);
11876 i += char_bytes;
11877 }
11878 }
11879 else if (! multibyte
11880 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11881 {
11882
11883
11884 for (ptrdiff_t i = 0; i < nbytes; i++)
11885 {
11886 int c = make_char_multibyte (msg[i]);
11887 unsigned char str[MAX_MULTIBYTE_LENGTH];
11888 int char_bytes = CHAR_STRING (c, str);
11889 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11890 }
11891 }
11892 else if (nbytes)
11893 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11894 true, false, false);
11895
11896 if (nlflag)
11897 {
11898 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11899 intmax_t dups;
11900
11901
11902
11903
11904
11905 specpdl_ref count = SPECPDL_INDEX ();
11906 specbind (Qinhibit_modification_hooks, Qt);
11907
11908 insert_1_both ("\n", 1, 1, true, false, false);
11909
11910 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11911 this_bol = PT;
11912 this_bol_byte = PT_BYTE;
11913
11914
11915
11916 if (this_bol > BEG)
11917 {
11918 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11919 prev_bol = PT;
11920 prev_bol_byte = PT_BYTE;
11921
11922 dups = message_log_check_duplicate (prev_bol_byte,
11923 this_bol_byte);
11924 if (dups)
11925 {
11926 del_range_both (prev_bol, prev_bol_byte,
11927 this_bol, this_bol_byte, false);
11928 if (dups > 1)
11929 {
11930 char dupstr[sizeof " [ times]"
11931 + INT_STRLEN_BOUND (dups)];
11932
11933
11934
11935 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11936 dups);
11937 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11938 insert_1_both (dupstr, duplen, duplen,
11939 true, false, true);
11940 }
11941 }
11942 }
11943
11944
11945
11946
11947
11948 if (FIXNATP (Vmessage_log_max))
11949 {
11950 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11951 -XFIXNAT (Vmessage_log_max) - 1, false);
11952 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11953 }
11954
11955 unbind_to (count, Qnil);
11956 }
11957 BEGV = marker_position (oldbegv);
11958 BEGV_BYTE = marker_byte_position (oldbegv);
11959
11960 if (zv_at_end)
11961 {
11962 ZV = Z;
11963 ZV_BYTE = Z_BYTE;
11964 }
11965 else
11966 {
11967 ZV = marker_position (oldzv);
11968 ZV_BYTE = marker_byte_position (oldzv);
11969 }
11970
11971 if (point_at_end)
11972 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11973 else
11974
11975
11976 TEMP_SET_PT_BOTH (marker_position (oldpoint),
11977 marker_byte_position (oldpoint));
11978
11979 unchain_marker (XMARKER (oldpoint));
11980 unchain_marker (XMARKER (oldbegv));
11981 unchain_marker (XMARKER (oldzv));
11982
11983
11984
11985
11986
11987
11988
11989 windows_or_buffers_changed = old_windows_or_buffers_changed;
11990 bset_redisplay (current_buffer);
11991
11992 set_buffer_internal (oldbuf);
11993
11994 message_log_need_newline = !nlflag;
11995 Vdeactivate_mark = old_deactivate_mark;
11996 }
11997 }
11998
11999
12000
12001
12002
12003
12004
12005
12006 static intmax_t
12007 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
12008 {
12009 ptrdiff_t i;
12010 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
12011 bool seen_dots = false;
12012 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
12013 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
12014
12015 for (i = 0; i < len; i++)
12016 {
12017 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
12018 seen_dots = true;
12019 if (p1[i] != p2[i])
12020 return seen_dots;
12021 }
12022 p1 += len;
12023 if (*p1 == '\n')
12024 return 2;
12025 if (*p1++ == ' ' && *p1++ == '[')
12026 {
12027 char *pend;
12028 intmax_t n = strtoimax ((char *) p1, &pend, 10);
12029 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
12030 return n + 1;
12031 }
12032 return 0;
12033 }
12034
12035
12036
12037
12038
12039
12040
12041
12042
12043 void
12044 message3 (Lisp_Object m)
12045 {
12046 clear_message (true, true);
12047 cancel_echoing ();
12048
12049
12050 message_log_maybe_newline ();
12051 if (STRINGP (m))
12052 {
12053 ptrdiff_t nbytes = SBYTES (m);
12054 bool multibyte = STRING_MULTIBYTE (m);
12055 char *buffer;
12056 USE_SAFE_ALLOCA;
12057 SAFE_ALLOCA_STRING (buffer, m);
12058 message_dolog (buffer, nbytes, true, multibyte);
12059 SAFE_FREE ();
12060 }
12061 if (! inhibit_message)
12062 message3_nolog (m);
12063 }
12064
12065
12066
12067 static void
12068 message_to_stderr (Lisp_Object m)
12069 {
12070 if (noninteractive_need_newline)
12071 {
12072 noninteractive_need_newline = false;
12073 errputc ('\n');
12074 }
12075 if (STRINGP (m))
12076 {
12077 Lisp_Object coding_system = Vlocale_coding_system;
12078 Lisp_Object s;
12079
12080 if (!NILP (Vcoding_system_for_write))
12081 coding_system = Vcoding_system_for_write;
12082 if (!NILP (coding_system))
12083 s = code_convert_string_norecord (m, coding_system, true);
12084 else
12085 s = m;
12086
12087 errwrite (SDATA (s), SBYTES (s));
12088 }
12089 if (STRINGP (m) || !cursor_in_echo_area)
12090 errputc ('\n');
12091 }
12092
12093
12094
12095
12096
12097
12098 void
12099 message3_nolog (Lisp_Object m)
12100 {
12101 struct frame *sf = SELECTED_FRAME ();
12102
12103 if (FRAME_INITIAL_P (sf))
12104 message_to_stderr (m);
12105
12106
12107
12108 else if (INTERACTIVE && sf->glyphs_initialized_p)
12109 {
12110
12111
12112 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12113 Lisp_Object frame = XWINDOW (mini_window)->frame;
12114 struct frame *f = XFRAME (frame);
12115
12116 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12117 Fmake_frame_visible (frame);
12118
12119 if (STRINGP (m) && SCHARS (m) > 0)
12120 {
12121 set_message (m);
12122 if (minibuffer_auto_raise)
12123 Fraise_frame (frame);
12124
12125
12126 echo_message_buffer = Qnil;
12127 }
12128 else
12129 clear_message (true, true);
12130
12131 do_pending_window_change (false);
12132 echo_area_display (true);
12133 do_pending_window_change (false);
12134 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12135 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12136 }
12137 }
12138
12139
12140
12141
12142
12143
12144
12145
12146
12147
12148 void
12149 message1 (const char *m)
12150 {
12151 message3 (m ? build_unibyte_string (m) : Qnil);
12152 }
12153
12154
12155
12156
12157 void
12158 message1_nolog (const char *m)
12159 {
12160 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12161 }
12162
12163
12164
12165
12166 void
12167 message_with_string (const char *m, Lisp_Object string, bool log)
12168 {
12169 CHECK_STRING (string);
12170
12171 bool need_message;
12172 if (noninteractive)
12173 need_message = !!m;
12174 else if (!INTERACTIVE)
12175 need_message = false;
12176 else
12177 {
12178
12179
12180
12181 Lisp_Object mini_window;
12182 struct frame *f, *sf = SELECTED_FRAME ();
12183
12184
12185
12186 mini_window = FRAME_MINIBUF_WINDOW (sf);
12187 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12188
12189
12190
12191
12192 need_message = f->glyphs_initialized_p;
12193 }
12194
12195 if (need_message)
12196 {
12197 AUTO_STRING (fmt, m);
12198 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12199
12200 if (noninteractive)
12201 message_to_stderr (msg);
12202 else
12203 {
12204 if (log)
12205 message3 (msg);
12206 else
12207 message3_nolog (msg);
12208
12209
12210
12211 message_buf_print = false;
12212 }
12213 }
12214 }
12215
12216
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12228 vmessage (const char *m, va_list ap)
12229 {
12230 if (noninteractive)
12231 {
12232 if (m)
12233 {
12234 if (noninteractive_need_newline)
12235 putc ('\n', stderr);
12236 noninteractive_need_newline = false;
12237 vfprintf (stderr, m, ap);
12238 if (!cursor_in_echo_area)
12239 putc ('\n', stderr);
12240 fflush (stderr);
12241 }
12242 }
12243 else if (INTERACTIVE)
12244 {
12245
12246
12247
12248 Lisp_Object mini_window;
12249 struct frame *f, *sf = SELECTED_FRAME ();
12250
12251
12252
12253 mini_window = FRAME_MINIBUF_WINDOW (sf);
12254 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12255
12256
12257
12258
12259 if (f->glyphs_initialized_p)
12260 {
12261 if (m)
12262 {
12263 ptrdiff_t len;
12264 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12265 USE_SAFE_ALLOCA;
12266 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12267
12268 len = doprnt (message_buf, maxsize, m, 0, ap);
12269
12270 message3 (make_string (message_buf, len));
12271 SAFE_FREE ();
12272 }
12273 else
12274 message1 (0);
12275
12276
12277
12278 message_buf_print = false;
12279 }
12280 }
12281 }
12282
12283
12284 void
12285 message (const char *m, ...)
12286 {
12287 va_list ap;
12288 va_start (ap, m);
12289 vmessage (m, ap);
12290 va_end (ap);
12291 }
12292
12293
12294
12295
12296
12297
12298 void
12299 update_echo_area (void)
12300 {
12301 if (!NILP (echo_area_buffer[0]))
12302 {
12303 Lisp_Object string;
12304 string = Fcurrent_message ();
12305 message3 (string);
12306 }
12307 }
12308
12309
12310
12311
12312
12313 static void
12314 ensure_echo_area_buffers (void)
12315 {
12316 for (int i = 0; i < 2; i++)
12317 if (!BUFFERP (echo_buffer[i])
12318 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12319 {
12320 Lisp_Object old_buffer = echo_buffer[i];
12321 static char const name_fmt[] = " *Echo Area %d*";
12322 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12323 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12324 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12325 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12326
12327
12328
12329
12330 for (int j = 0; j < 2; j++)
12331 if (EQ (old_buffer, echo_area_buffer[j]))
12332 echo_area_buffer[j] = echo_buffer[i];
12333 }
12334 }
12335
12336
12337
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353 static bool
12354 with_echo_area_buffer (struct window *w, int which,
12355 bool (*fn) (void *, Lisp_Object),
12356 void *a1, Lisp_Object a2)
12357 {
12358 Lisp_Object buffer;
12359 bool this_one, the_other, clear_buffer_p, rc;
12360 specpdl_ref count = SPECPDL_INDEX ();
12361
12362
12363 ensure_echo_area_buffers ();
12364
12365 clear_buffer_p = false;
12366
12367 if (which == 0)
12368 this_one = false, the_other = true;
12369 else if (which > 0)
12370 this_one = true, the_other = false;
12371 else
12372 {
12373 this_one = false, the_other = true;
12374 clear_buffer_p = true;
12375
12376
12377
12378 if (!NILP (echo_area_buffer[this_one])
12379 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12380 echo_area_buffer[this_one] = Qnil;
12381 }
12382
12383
12384
12385 if (NILP (echo_area_buffer[this_one]))
12386 {
12387 echo_area_buffer[this_one]
12388 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12389 ? echo_buffer[the_other]
12390 : echo_buffer[this_one]);
12391 clear_buffer_p = true;
12392 }
12393
12394 buffer = echo_area_buffer[this_one];
12395
12396
12397
12398 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12399 cancel_echoing ();
12400
12401 record_unwind_protect (unwind_with_echo_area_buffer,
12402 with_echo_area_buffer_unwind_data (w));
12403
12404
12405
12406
12407
12408
12409
12410
12411 set_buffer_internal_1 (XBUFFER (buffer));
12412 if (w)
12413 {
12414 wset_buffer (w, buffer);
12415 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12416 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12417 }
12418
12419 bset_undo_list (current_buffer, Qt);
12420 bset_read_only (current_buffer, Qnil);
12421 specbind (Qinhibit_read_only, Qt);
12422 specbind (Qinhibit_modification_hooks, Qt);
12423
12424 if (clear_buffer_p && Z > BEG)
12425 del_range (BEG, Z);
12426
12427 eassert (BEGV >= BEG);
12428 eassert (ZV <= Z && ZV >= BEGV);
12429
12430 rc = fn (a1, a2);
12431
12432 eassert (BEGV >= BEG);
12433 eassert (ZV <= Z && ZV >= BEGV);
12434
12435 unbind_to (count, Qnil);
12436 return rc;
12437 }
12438
12439
12440
12441
12442
12443 static Lisp_Object
12444 with_echo_area_buffer_unwind_data (struct window *w)
12445 {
12446 int i = 0;
12447 Lisp_Object vector, tmp;
12448
12449
12450
12451 vector = Vwith_echo_area_save_vector;
12452 Vwith_echo_area_save_vector = Qnil;
12453
12454 if (NILP (vector))
12455 vector = make_nil_vector (11);
12456
12457 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12458 ASET (vector, i, Vdeactivate_mark); ++i;
12459 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12460
12461 if (w)
12462 {
12463 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12464 ASET (vector, i, w->contents); ++i;
12465 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12466 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12467 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12468 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12469 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12470 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12471 }
12472 else
12473 {
12474 int end = i + 8;
12475 for (; i < end; ++i)
12476 ASET (vector, i, Qnil);
12477 }
12478
12479 eassert (i == ASIZE (vector));
12480 return vector;
12481 }
12482
12483
12484
12485
12486
12487 static void
12488 unwind_with_echo_area_buffer (Lisp_Object vector)
12489 {
12490 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12491 Vdeactivate_mark = AREF (vector, 1);
12492 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12493
12494 if (WINDOWP (AREF (vector, 3)))
12495 {
12496 struct window *w;
12497 Lisp_Object buffer;
12498
12499 w = XWINDOW (AREF (vector, 3));
12500 buffer = AREF (vector, 4);
12501
12502 wset_buffer (w, buffer);
12503 set_marker_restricted_both (w->pointm, buffer,
12504 XFIXNAT (AREF (vector, 5)),
12505 XFIXNAT (AREF (vector, 6)));
12506 set_marker_restricted_both (w->old_pointm, buffer,
12507 XFIXNAT (AREF (vector, 7)),
12508 XFIXNAT (AREF (vector, 8)));
12509 set_marker_restricted_both (w->start, buffer,
12510 XFIXNAT (AREF (vector, 9)),
12511 XFIXNAT (AREF (vector, 10)));
12512 }
12513
12514 Vwith_echo_area_save_vector = vector;
12515 }
12516
12517
12518
12519
12520
12521 void
12522 setup_echo_area_for_printing (bool multibyte_p)
12523 {
12524
12525 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12526 Fkill_emacs (Qnil, Qnil);
12527
12528 ensure_echo_area_buffers ();
12529
12530 if (!message_buf_print)
12531 {
12532
12533
12534 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12535 echo_area_buffer[0] = echo_buffer[1];
12536 else
12537 echo_area_buffer[0] = echo_buffer[0];
12538
12539
12540 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12541 bset_truncate_lines (current_buffer, Qnil);
12542
12543 if (Z > BEG)
12544 {
12545 specpdl_ref count = SPECPDL_INDEX ();
12546 specbind (Qinhibit_read_only, Qt);
12547
12548 del_range (BEG, Z);
12549 unbind_to (count, Qnil);
12550 }
12551 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12552
12553
12554
12555
12556
12557
12558
12559 if (unibyte_display_via_language_environment
12560 && !multibyte_p
12561 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12562 Fset_buffer_multibyte (Qnil);
12563 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12564 Fset_buffer_multibyte (Qt);
12565
12566
12567 if (minibuffer_auto_raise)
12568 {
12569 struct frame *sf = SELECTED_FRAME ();
12570 Lisp_Object mini_window;
12571 mini_window = FRAME_MINIBUF_WINDOW (sf);
12572 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12573 }
12574
12575 message_log_maybe_newline ();
12576 message_buf_print = true;
12577 }
12578 else
12579 {
12580 if (NILP (echo_area_buffer[0]))
12581 {
12582 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12583 echo_area_buffer[0] = echo_buffer[1];
12584 else
12585 echo_area_buffer[0] = echo_buffer[0];
12586 }
12587
12588 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12589 {
12590
12591 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12592 bset_truncate_lines (current_buffer, Qnil);
12593 }
12594 }
12595 }
12596
12597
12598
12599
12600
12601
12602
12603 static bool
12604 display_echo_area (struct window *w)
12605 {
12606 bool no_message_p, window_height_changed_p;
12607
12608
12609
12610
12611
12612
12613 specpdl_ref count = inhibit_garbage_collection ();
12614
12615
12616
12617
12618
12619 bool i = display_last_displayed_message_p;
12620
12621
12622
12623 no_message_p = NILP (echo_area_buffer[i]);
12624
12625 window_height_changed_p
12626 = with_echo_area_buffer (w, display_last_displayed_message_p,
12627 display_echo_area_1, w, Qnil);
12628
12629 if (no_message_p)
12630 echo_area_buffer[i] = Qnil;
12631
12632 unbind_to (count, Qnil);
12633 return window_height_changed_p;
12634 }
12635
12636
12637
12638
12639
12640
12641
12642
12643 static bool
12644 display_echo_area_1 (void *a1, Lisp_Object a2)
12645 {
12646 struct window *w = a1;
12647 Lisp_Object window;
12648 struct text_pos start;
12649
12650
12651
12652
12653 forget_escape_and_glyphless_faces ();
12654
12655
12656
12657
12658 bool window_height_changed_p = resize_mini_window (w, false);
12659
12660
12661 SET_TEXT_POS_FROM_MARKER (start, w->start);
12662
12663
12664 clear_glyph_matrix (w->desired_matrix);
12665 XSETWINDOW (window, w);
12666 void *itdata = bidi_shelve_cache ();
12667 try_window (window, start, 0);
12668 bidi_unshelve_cache (itdata, false);
12669
12670 return window_height_changed_p;
12671 }
12672
12673
12674
12675
12676
12677
12678 void
12679 resize_echo_area_exactly (void)
12680 {
12681 if (BUFFERP (echo_area_buffer[0])
12682 && WINDOWP (echo_area_window))
12683 {
12684 struct window *w = XWINDOW (echo_area_window);
12685 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12686 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12687 w, resize_exactly);
12688 if (resized_p)
12689 {
12690 windows_or_buffers_changed = 42;
12691 update_mode_lines = 30;
12692 redisplay_internal ();
12693 }
12694 }
12695 }
12696
12697
12698
12699
12700
12701
12702
12703
12704 static bool
12705 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12706 {
12707 return resize_mini_window (a1, !NILP (exactly));
12708 }
12709
12710
12711
12712
12713
12714
12715
12716
12717
12718
12719
12720
12721
12722 bool
12723 resize_mini_window (struct window *w, bool exact_p)
12724 {
12725 struct frame *f = XFRAME (w->frame);
12726 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12727
12728 eassert (MINI_WINDOW_P (w));
12729
12730
12731
12732
12733
12734
12735
12736 if (!NILP (Vinhibit_redisplay))
12737 return false;
12738
12739
12740 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12741 set_marker_both (w->start, w->contents,
12742 BUF_BEGV (XBUFFER (w->contents)),
12743 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12744
12745
12746 if ((NILP (Vresize_mini_windows)
12747 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12748 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12749 return false;
12750
12751 if (FRAME_MINIBUF_ONLY_P (f))
12752 {
12753 if (!NILP (resize_mini_frames))
12754 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12755 }
12756 else
12757 {
12758 struct it it;
12759 int unit = FRAME_LINE_HEIGHT (f);
12760 int height, max_height;
12761 struct text_pos start;
12762 struct buffer *old_current_buffer = NULL;
12763 int windows_height = FRAME_INNER_HEIGHT (f);
12764
12765 if (current_buffer != XBUFFER (w->contents))
12766 {
12767 old_current_buffer = current_buffer;
12768 set_buffer_internal (XBUFFER (w->contents));
12769 }
12770
12771 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12772
12773
12774 if (FLOATP (Vmax_mini_window_height))
12775 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12776 else if (FIXNUMP (Vmax_mini_window_height))
12777 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12778 else
12779 max_height = windows_height / 4;
12780
12781
12782 max_height = clip_to_bounds (unit, max_height, windows_height);
12783
12784
12785 last_height = 0;
12786 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12787
12788
12789 if (it.max_ascent == 0 && it.max_descent == 0)
12790 {
12791 height = it.current_y;
12792
12793
12794
12795
12796
12797 if (!(it.line_wrap == TRUNCATE
12798 && it.current_x <= it.first_visible_x
12799 && ZV_BYTE > 1
12800 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12801 height += last_height;
12802 }
12803 else
12804 height = it.current_y + it.max_ascent + it.max_descent;
12805 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12806
12807
12808 if (height > max_height)
12809 {
12810 height = (max_height / unit) * unit;
12811 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12812 {
12813 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12814 move_it_vertically_backward (&it, height - unit);
12815
12816
12817
12818
12819
12820
12821
12822
12823
12824 move_it_by_lines (&it, 0);
12825 start = it.current.pos;
12826
12827
12828 w->start_at_line_beg = false;
12829 SET_MARKER_FROM_TEXT_POS (w->start, start);
12830 }
12831 }
12832 else
12833 {
12834 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12835 SET_MARKER_FROM_TEXT_POS (w->start, start);
12836 }
12837
12838 if (EQ (Vresize_mini_windows, Qgrow_only))
12839 {
12840
12841
12842 if (height > old_height)
12843 grow_mini_window (w, height - old_height);
12844 else if (height < old_height && (exact_p || BEGV == ZV))
12845 shrink_mini_window (w);
12846 }
12847 else if (height != old_height)
12848
12849 grow_mini_window (w, height - old_height);
12850
12851 if (old_current_buffer)
12852 set_buffer_internal (old_current_buffer);
12853 }
12854
12855 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12856 }
12857
12858
12859
12860
12861
12862 Lisp_Object
12863 current_message (void)
12864 {
12865 Lisp_Object msg;
12866
12867 if (!BUFFERP (echo_area_buffer[0]))
12868 msg = Qnil;
12869 else
12870 {
12871 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12872 if (NILP (msg))
12873 echo_area_buffer[0] = Qnil;
12874 }
12875
12876 return msg;
12877 }
12878
12879
12880 static bool
12881 current_message_1 (void *a1, Lisp_Object a2)
12882 {
12883 Lisp_Object *msg = a1;
12884
12885 if (Z > BEG)
12886 *msg = make_buffer_string (BEG, Z, true);
12887 else
12888 *msg = Qnil;
12889 return false;
12890 }
12891
12892
12893
12894
12895
12896
12897
12898 bool
12899 push_message (void)
12900 {
12901 Lisp_Object msg = current_message ();
12902 Vmessage_stack = Fcons (msg, Vmessage_stack);
12903 return STRINGP (msg);
12904 }
12905
12906
12907
12908
12909 void
12910 restore_message (void)
12911 {
12912 eassert (CONSP (Vmessage_stack));
12913 message3_nolog (XCAR (Vmessage_stack));
12914 }
12915
12916
12917
12918
12919 void
12920 pop_message_unwind (void)
12921 {
12922
12923 eassert (CONSP (Vmessage_stack));
12924 Vmessage_stack = XCDR (Vmessage_stack);
12925 }
12926
12927
12928
12929
12930
12931
12932 void
12933 check_message_stack (void)
12934 {
12935 if (!NILP (Vmessage_stack))
12936 emacs_abort ();
12937 }
12938
12939 void
12940 clear_message_stack (void)
12941 {
12942 Vmessage_stack = Qnil;
12943 }
12944
12945
12946
12947
12948 void
12949 truncate_echo_area (ptrdiff_t nchars)
12950 {
12951 if (nchars == 0)
12952 echo_area_buffer[0] = Qnil;
12953 else if (!noninteractive
12954 && INTERACTIVE
12955 && !NILP (echo_area_buffer[0]))
12956 {
12957 struct frame *sf = SELECTED_FRAME ();
12958
12959
12960
12961 if (sf->glyphs_initialized_p)
12962 with_echo_area_buffer (0, 0, truncate_message_1,
12963 (void *) (intptr_t) nchars, Qnil);
12964 }
12965 }
12966
12967
12968
12969
12970
12971 static bool
12972 truncate_message_1 (void *a1, Lisp_Object a2)
12973 {
12974 intptr_t nchars = (intptr_t) a1;
12975 if (BEG + nchars < Z)
12976 del_range (BEG + nchars, Z);
12977 if (Z == BEG)
12978 echo_area_buffer[0] = Qnil;
12979 return false;
12980 }
12981
12982 extern intptr_t garbage_collection_inhibited;
12983
12984
12985
12986 static void
12987 set_message (Lisp_Object string)
12988 {
12989 Lisp_Object message = Qnil;
12990
12991 eassert (STRINGP (string));
12992
12993 if (FUNCTIONP (Vset_message_function)
12994
12995
12996
12997 && !garbage_collection_inhibited)
12998 {
12999 specpdl_ref count = SPECPDL_INDEX ();
13000 specbind (Qinhibit_quit, Qt);
13001 message = safe_call1 (Vset_message_function, string);
13002 unbind_to (count, Qnil);
13003
13004 if (STRINGP (message))
13005 {
13006 string = message;
13007 message = Qnil;
13008 }
13009 }
13010
13011 if (NILP (message))
13012 {
13013 message_enable_multibyte = STRING_MULTIBYTE (string);
13014
13015 with_echo_area_buffer (0, -1, set_message_1, 0, string);
13016 message_buf_print = false;
13017 help_echo_showing_p = false;
13018 }
13019
13020 if (STRINGP (Vdebug_on_message)
13021 && STRINGP (string)
13022 && fast_string_match (Vdebug_on_message, string) >= 0)
13023 call_debugger (list2 (Qerror, string));
13024 }
13025
13026
13027
13028
13029
13030
13031 static bool
13032 set_message_1 (void *a1, Lisp_Object string)
13033 {
13034 eassert (STRINGP (string));
13035
13036
13037
13038
13039
13040
13041 if (!message_enable_multibyte
13042 && unibyte_display_via_language_environment
13043 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13044 Fset_buffer_multibyte (Qnil);
13045 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13046 Fset_buffer_multibyte (Qt);
13047
13048 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13049 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13050 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13051
13052
13053 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13054
13055
13056
13057
13058 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13059
13060 return false;
13061 }
13062
13063
13064
13065
13066
13067 void
13068 clear_message (bool current_p, bool last_displayed_p)
13069 {
13070 Lisp_Object preserve = Qnil;
13071
13072 if (current_p)
13073 {
13074 if (FUNCTIONP (Vclear_message_function)
13075
13076 && !garbage_collection_inhibited)
13077 {
13078 specpdl_ref count = SPECPDL_INDEX ();
13079 specbind (Qinhibit_quit, Qt);
13080 preserve = safe_call (1, Vclear_message_function);
13081 unbind_to (count, Qnil);
13082 }
13083
13084 if (!EQ (preserve, Qdont_clear_message))
13085 {
13086 echo_area_buffer[0] = Qnil;
13087 message_cleared_p = true;
13088 }
13089 }
13090
13091 if (last_displayed_p)
13092 echo_area_buffer[1] = Qnil;
13093
13094 message_buf_print = false;
13095 }
13096
13097
13098
13099
13100
13101
13102
13103
13104
13105
13106 static void
13107 clear_garbaged_frames (void)
13108 {
13109 if (frame_garbaged)
13110 {
13111 Lisp_Object tail, frame;
13112 struct frame *sf = SELECTED_FRAME ();
13113
13114 FOR_EACH_FRAME (tail, frame)
13115 {
13116 struct frame *f = XFRAME (frame);
13117
13118 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
13119 {
13120 if (f->resized_p
13121
13122
13123
13124
13125
13126 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13127 redraw_frame (f);
13128 else
13129 clear_current_matrices (f);
13130
13131 #ifdef HAVE_WINDOW_SYSTEM
13132 if (FRAME_WINDOW_P (f)
13133 && FRAME_RIF (f)->clear_under_internal_border)
13134 FRAME_RIF (f)->clear_under_internal_border (f);
13135 #endif
13136 fset_redisplay (f);
13137 f->garbaged = false;
13138 f->resized_p = false;
13139 }
13140 }
13141
13142 frame_garbaged = false;
13143 }
13144 }
13145
13146
13147
13148
13149
13150 static void
13151 echo_area_display (bool update_frame_p)
13152 {
13153 Lisp_Object mini_window;
13154 struct window *w;
13155 struct frame *f;
13156 bool window_height_changed_p = false;
13157 struct frame *sf = SELECTED_FRAME ();
13158
13159 mini_window = FRAME_MINIBUF_WINDOW (sf);
13160 if (NILP (mini_window))
13161 return;
13162
13163 w = XWINDOW (mini_window);
13164 f = XFRAME (WINDOW_FRAME (w));
13165
13166
13167 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
13168 return;
13169
13170 #ifdef HAVE_WINDOW_SYSTEM
13171
13172
13173
13174 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13175 return;
13176 #endif
13177
13178
13179 clear_garbaged_frames ();
13180
13181 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13182 {
13183 echo_area_window = mini_window;
13184 window_height_changed_p = display_echo_area (w);
13185 w->must_be_updated_p = true;
13186
13187
13188
13189
13190
13191 if (update_frame_p && !redisplaying_p)
13192 {
13193 int n = 0;
13194
13195
13196
13197
13198
13199
13200 if (!display_completed)
13201 {
13202 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13203
13204 #ifdef HAVE_WINDOW_SYSTEM
13205 if (FRAME_WINDOW_P (f)
13206 && FRAME_RIF (f)->clear_under_internal_border)
13207 FRAME_RIF (f)->clear_under_internal_border (f);
13208 #endif
13209 }
13210
13211 if (window_height_changed_p
13212
13213
13214 && !NILP (Vrun_hooks))
13215 {
13216
13217
13218
13219 specpdl_ref count = SPECPDL_INDEX ();
13220 specbind (Qredisplay_dont_pause, Qt);
13221 fset_redisplay (f);
13222 redisplay_internal ();
13223 unbind_to (count, Qnil);
13224 }
13225 else if (FRAME_WINDOW_P (f) && n == 0)
13226 {
13227
13228
13229
13230 update_single_window (w);
13231 flush_frame (f);
13232 }
13233 else
13234 update_frame (f, true, true);
13235
13236
13237
13238
13239 if (cursor_in_echo_area)
13240 wset_redisplay (XWINDOW (mini_window));
13241 }
13242 }
13243 else if (!EQ (mini_window, selected_window))
13244 wset_redisplay (XWINDOW (mini_window));
13245
13246
13247 echo_area_buffer[1] = echo_area_buffer[0];
13248
13249 echo_message_buffer = Qnil;
13250
13251
13252
13253
13254 if (EQ (mini_window, selected_window))
13255 CHARPOS (this_line_start_pos) = 0;
13256
13257 if (window_height_changed_p)
13258 {
13259 fset_redisplay (f);
13260
13261
13262
13263
13264
13265 clear_garbaged_frames ();
13266 }
13267 }
13268
13269
13270
13271 static bool
13272 window_buffer_changed (struct window *w)
13273 {
13274 struct buffer *b = XBUFFER (w->contents);
13275
13276 eassert (BUFFER_LIVE_P (b));
13277
13278 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13279 }
13280
13281
13282
13283 static bool
13284 mode_line_update_needed (struct window *w)
13285 {
13286 return (w->column_number_displayed != -1
13287 && !(PT == w->last_point && !window_outdated (w))
13288 && (w->column_number_displayed != current_column ()));
13289 }
13290
13291
13292
13293
13294 static bool
13295 window_frozen_p (struct window *w)
13296 {
13297 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13298 {
13299 Lisp_Object window;
13300
13301 XSETWINDOW (window, w);
13302 if (MINI_WINDOW_P (w))
13303 return false;
13304 else if (EQ (window, selected_window))
13305 return false;
13306 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13307 && EQ (window, Vminibuf_scroll_window))
13308
13309 return false;
13310 else
13311 return true;
13312 }
13313 return false;
13314 }
13315
13316
13317
13318
13319
13320
13321
13322
13323
13324 static char *mode_line_noprop_buf;
13325
13326
13327
13328 static char *mode_line_noprop_buf_end;
13329 static char *mode_line_noprop_ptr;
13330
13331 #define MODE_LINE_NOPROP_LEN(start) \
13332 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13333
13334 static enum {
13335 MODE_LINE_DISPLAY = 0,
13336 MODE_LINE_TITLE,
13337 MODE_LINE_NOPROP,
13338 MODE_LINE_STRING
13339 } mode_line_target;
13340
13341
13342
13343 static Lisp_Object mode_line_proptrans_alist;
13344
13345
13346 static Lisp_Object mode_line_string_list;
13347
13348
13349 static Lisp_Object mode_line_string_face;
13350 static Lisp_Object mode_line_string_face_prop;
13351
13352
13353
13354
13355 static Lisp_Object Vmode_line_unwind_vector;
13356
13357 static Lisp_Object
13358 format_mode_line_unwind_data (struct frame *target_frame,
13359 struct buffer *obuf,
13360 Lisp_Object owin,
13361 bool save_proptrans)
13362 {
13363 Lisp_Object vector, tmp;
13364
13365
13366
13367 vector = Vmode_line_unwind_vector;
13368 Vmode_line_unwind_vector = Qnil;
13369
13370 if (NILP (vector))
13371 vector = make_nil_vector (12);
13372
13373 ASET (vector, 0, make_fixnum (mode_line_target));
13374 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13375 ASET (vector, 2, mode_line_string_list);
13376 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13377 ASET (vector, 4, mode_line_string_face);
13378 ASET (vector, 5, mode_line_string_face_prop);
13379
13380 if (obuf)
13381 XSETBUFFER (tmp, obuf);
13382 else
13383 tmp = Qnil;
13384 ASET (vector, 6, tmp);
13385 ASET (vector, 7, owin);
13386 if (target_frame)
13387 {
13388 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13389 struct buffer *b = XBUFFER (buffer);
13390 struct buffer *cb = current_buffer;
13391
13392
13393
13394
13395 ASET (vector, 8, target_frame->selected_window);
13396 if (FRAME_TERMCAP_P (target_frame))
13397 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13398
13399
13400
13401
13402 ASET (vector, 10, buffer);
13403 current_buffer = b;
13404 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13405 current_buffer = cb;
13406 }
13407
13408 return vector;
13409 }
13410
13411 static void
13412 unwind_format_mode_line (Lisp_Object vector)
13413 {
13414 Lisp_Object old_window = AREF (vector, 7);
13415 Lisp_Object target_frame_window = AREF (vector, 8);
13416 Lisp_Object old_top_frame = AREF (vector, 9);
13417
13418 mode_line_target = XFIXNUM (AREF (vector, 0));
13419 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13420 mode_line_string_list = AREF (vector, 2);
13421 if (! EQ (AREF (vector, 3), Qt))
13422 mode_line_proptrans_alist = AREF (vector, 3);
13423 mode_line_string_face = AREF (vector, 4);
13424 mode_line_string_face_prop = AREF (vector, 5);
13425
13426
13427 if (WINDOW_LIVE_P (old_window))
13428 {
13429
13430
13431
13432 if (WINDOW_LIVE_P (target_frame_window))
13433 {
13434 Lisp_Object frame
13435 = WINDOW_FRAME (XWINDOW (target_frame_window));
13436
13437 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13438 Fselect_window (target_frame_window, Qt);
13439
13440 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13441
13442
13443 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13444 Fselect_frame (old_top_frame, Qt);
13445 }
13446
13447 Fselect_window (old_window, Qt);
13448
13449
13450
13451
13452 if (WINDOW_LIVE_P (target_frame_window))
13453 {
13454 Lisp_Object buffer = AREF (vector, 10);
13455
13456 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13457 {
13458 struct buffer *cb = current_buffer;
13459
13460 current_buffer = XBUFFER (buffer);
13461 set_point_from_marker (AREF (vector, 11));
13462 ASET (vector, 11, Qnil);
13463 current_buffer = cb;
13464 }
13465 }
13466 }
13467
13468 if (!NILP (AREF (vector, 6)))
13469 {
13470 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13471 ASET (vector, 6, Qnil);
13472 }
13473
13474 Vmode_line_unwind_vector = vector;
13475 }
13476
13477
13478
13479
13480
13481 static void
13482 store_mode_line_noprop_char (char c)
13483 {
13484
13485
13486 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13487 {
13488 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13489 ptrdiff_t size = len;
13490 mode_line_noprop_buf =
13491 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13492 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13493 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13494 }
13495
13496 *mode_line_noprop_ptr++ = c;
13497 }
13498
13499
13500
13501
13502
13503
13504
13505
13506
13507
13508 static int
13509 store_mode_line_noprop (const char *string, int field_width, int precision)
13510 {
13511 const unsigned char *str = (const unsigned char *) string;
13512 int n = 0;
13513 ptrdiff_t dummy, nbytes;
13514
13515
13516 nbytes = strlen (string);
13517 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13518 while (nbytes--)
13519 store_mode_line_noprop_char (*str++);
13520
13521
13522 while (field_width > 0
13523 && n < field_width)
13524 {
13525 store_mode_line_noprop_char (' ');
13526 ++n;
13527 }
13528
13529 return n;
13530 }
13531
13532
13533
13534
13535
13536 #ifdef HAVE_WINDOW_SYSTEM
13537
13538
13539
13540
13541
13542 void
13543 gui_consider_frame_title (Lisp_Object frame)
13544 {
13545 struct frame *f = XFRAME (frame);
13546 Lisp_Object format_data;
13547
13548 if ((FRAME_WINDOW_P (f)
13549 || FRAME_MINIBUF_ONLY_P (f)
13550 || f->explicit_name)
13551 && !FRAME_TOOLTIP_P (f))
13552 {
13553
13554 Lisp_Object tail, other_frame, fmt;
13555 ptrdiff_t title_start;
13556 char *title;
13557 ptrdiff_t len;
13558 struct it it;
13559 specpdl_ref count = SPECPDL_INDEX ();
13560
13561 FOR_EACH_FRAME (tail, other_frame)
13562 {
13563 struct frame *tf = XFRAME (other_frame);
13564
13565 if (tf != f
13566 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13567 && !FRAME_MINIBUF_ONLY_P (tf)
13568 && !FRAME_PARENT_FRAME (tf)
13569 && !FRAME_TOOLTIP_P (tf)
13570 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13571 break;
13572 }
13573
13574
13575 multiple_frames = CONSP (tail);
13576
13577
13578
13579
13580
13581
13582
13583
13584
13585
13586
13587
13588 specbind (Qinhibit_redisplay, Qt);
13589
13590
13591
13592
13593
13594
13595
13596
13597 format_data = format_mode_line_unwind_data (f, current_buffer,
13598 selected_window,
13599 false);
13600 record_unwind_protect (unwind_format_mode_line, format_data);
13601
13602 Fselect_window (f->selected_window, Qt);
13603 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13604 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13605 ? Vicon_title_format : Vframe_title_format);
13606
13607 mode_line_target = MODE_LINE_TITLE;
13608 title_start = MODE_LINE_NOPROP_LEN (0);
13609 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13610 NULL, DEFAULT_FACE_ID);
13611 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13612 len = MODE_LINE_NOPROP_LEN (title_start);
13613 title = mode_line_noprop_buf + title_start;
13614
13615
13616 ptrdiff_t nchars = 0;
13617 len = str_as_multibyte ((unsigned char *) title,
13618 mode_line_noprop_buf_end - title,
13619 len, &nchars);
13620 unbind_to (count, Qnil);
13621
13622
13623
13624
13625
13626
13627 if ((! STRINGP (f->name)
13628 || SBYTES (f->name) != len
13629 || memcmp (title, SDATA (f->name), len) != 0)
13630 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13631 {
13632 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13633 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13634 }
13635 }
13636 }
13637
13638 #endif
13639
13640
13641
13642
13643
13644
13645
13646 #define REDISPLAY_SOME_P() \
13647 ((windows_or_buffers_changed == 0 \
13648 || windows_or_buffers_changed == REDISPLAY_SOME) \
13649 && (update_mode_lines == 0 \
13650 || update_mode_lines == REDISPLAY_SOME))
13651
13652 static bool
13653 needs_no_redisplay (struct window *w)
13654 {
13655 struct buffer *buffer = XBUFFER (w->contents);
13656 struct frame *f = XFRAME (w->frame);
13657 return (REDISPLAY_SOME_P ()
13658 && !w->redisplay
13659 && !w->update_mode_line
13660 && !f->face_change
13661 && !f->redisplay
13662 && !buffer->text->redisplay
13663 && window_point (w) == w->last_point);
13664 }
13665
13666
13667
13668
13669 static void
13670 prepare_menu_bars (void)
13671 {
13672 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13673 bool some_windows = REDISPLAY_SOME_P ();
13674
13675 if (FUNCTIONP (Vpre_redisplay_function))
13676 {
13677 Lisp_Object windows = all_windows ? Qt : Qnil;
13678 if (all_windows && some_windows)
13679 {
13680 Lisp_Object ws = window_list ();
13681 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13682 {
13683 Lisp_Object this = XCAR (ws);
13684 struct window *w = XWINDOW (this);
13685
13686
13687 if (!needs_no_redisplay (w))
13688 windows = Fcons (this, windows);
13689 }
13690 }
13691 safe__call1 (true, Vpre_redisplay_function, windows);
13692 }
13693
13694
13695
13696
13697 #ifdef HAVE_WINDOW_SYSTEM
13698 if (all_windows)
13699 {
13700 Lisp_Object tail, frame;
13701
13702 FOR_EACH_FRAME (tail, frame)
13703 {
13704 struct frame *f = XFRAME (frame);
13705 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13706 if (some_windows
13707 && !f->redisplay
13708 && !w->redisplay
13709 && !XBUFFER (w->contents)->text->redisplay)
13710 continue;
13711
13712 if (!FRAME_TOOLTIP_P (f)
13713 && (FRAME_ICONIFIED_P (f)
13714 || FRAME_VISIBLE_P (f) == 1
13715
13716
13717
13718
13719
13720
13721
13722
13723
13724 || (FRAME_VISIBLE_P (f) == 2 && FRAME_WINDOW_P (f))))
13725 gui_consider_frame_title (frame);
13726 }
13727 }
13728 #endif
13729
13730
13731
13732
13733 if (all_windows)
13734 {
13735 Lisp_Object tail, frame;
13736 specpdl_ref count = SPECPDL_INDEX ();
13737
13738
13739 bool menu_bar_hooks_run = false;
13740
13741 record_unwind_save_match_data ();
13742
13743 FOR_EACH_FRAME (tail, frame)
13744 {
13745 struct frame *f = XFRAME (frame);
13746 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13747
13748
13749 if (FRAME_TOOLTIP_P (f))
13750 continue;
13751
13752 if (some_windows
13753 && !f->redisplay
13754 && !w->redisplay
13755 && !XBUFFER (w->contents)->text->redisplay)
13756 continue;
13757
13758 if (!FRAME_PARENT_FRAME (f))
13759 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13760
13761 update_tab_bar (f, false);
13762 #ifdef HAVE_WINDOW_SYSTEM
13763 update_tool_bar (f, false);
13764 #endif
13765 }
13766
13767 unbind_to (count, Qnil);
13768 }
13769 else
13770 {
13771 struct frame *sf = SELECTED_FRAME ();
13772
13773 if (!FRAME_PARENT_FRAME (sf))
13774 update_menu_bar (sf, true, false);
13775
13776 update_tab_bar (sf, true);
13777 #ifdef HAVE_WINDOW_SYSTEM
13778 update_tool_bar (sf, true);
13779 #endif
13780 }
13781 }
13782
13783
13784
13785
13786
13787
13788
13789
13790
13791
13792
13793
13794
13795 static bool
13796 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13797 {
13798 Lisp_Object window;
13799 struct window *w;
13800
13801
13802
13803
13804 if (inhibit_menubar_update)
13805 return hooks_run;
13806
13807 window = FRAME_SELECTED_WINDOW (f);
13808 w = XWINDOW (window);
13809
13810 if (FRAME_WINDOW_P (f)
13811 ?
13812 #ifdef HAVE_EXT_MENU_BAR
13813 FRAME_EXTERNAL_MENU_BAR (f)
13814 #else
13815 FRAME_MENU_BAR_LINES (f) > 0
13816 #endif
13817 : FRAME_MENU_BAR_LINES (f) > 0)
13818 {
13819
13820
13821
13822
13823
13824
13825
13826 if (windows_or_buffers_changed
13827
13828
13829 || update_mode_lines
13830 || window_buffer_changed (w))
13831 {
13832 struct buffer *prev = current_buffer;
13833 specpdl_ref count = SPECPDL_INDEX ();
13834
13835 specbind (Qinhibit_menubar_update, Qt);
13836
13837 set_buffer_internal_1 (XBUFFER (w->contents));
13838 if (save_match_data)
13839 record_unwind_save_match_data ();
13840 if (NILP (Voverriding_local_map_menu_flag))
13841 {
13842 specbind (Qoverriding_terminal_local_map, Qnil);
13843 specbind (Qoverriding_local_map, Qnil);
13844 }
13845
13846 if (!hooks_run)
13847 {
13848
13849 safe_run_hooks (Qactivate_menubar_hook);
13850
13851
13852
13853 safe_run_hooks (Qmenu_bar_update_hook);
13854
13855 hooks_run = true;
13856 }
13857
13858 XSETFRAME (Vmenu_updating_frame, f);
13859 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13860
13861
13862 #ifdef HAVE_EXT_MENU_BAR
13863 if (FRAME_WINDOW_P (f))
13864 {
13865 #if defined (HAVE_NS)
13866
13867
13868 if (f == SELECTED_FRAME ())
13869 #endif
13870 set_frame_menubar (f, false);
13871 }
13872 else
13873
13874
13875 w->update_mode_line = true;
13876 #else
13877
13878
13879 w->update_mode_line = true;
13880 #endif
13881
13882 unbind_to (count, Qnil);
13883 set_buffer_internal_1 (prev);
13884 }
13885 }
13886
13887 return hooks_run;
13888 }
13889
13890
13891
13892
13893
13894
13895
13896
13897
13898
13899
13900
13901 static void
13902 restore_selected_window (Lisp_Object window)
13903 {
13904 if (WINDOW_LIVE_P (window))
13905
13906
13907 {
13908 selected_window = window;
13909 selected_frame = XWINDOW (window)->frame;
13910 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13911 }
13912 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13913
13914
13915 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13916 else
13917
13918
13919
13920 {
13921 Lisp_Object tail;
13922 Lisp_Object frame UNINIT;
13923
13924 FOR_EACH_FRAME (tail, frame)
13925 {
13926 struct frame *f = XFRAME (frame);
13927
13928 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13929 {
13930 selected_frame = frame;
13931 selected_window = FRAME_SELECTED_WINDOW (f);
13932
13933 return;
13934 }
13935 }
13936
13937
13938 emacs_abort ();
13939 }
13940 }
13941
13942
13943 static void
13944 restore_frame_selected_window (Lisp_Object window)
13945 {
13946 if (WINDOW_LIVE_P (window))
13947
13948
13949
13950 {
13951 Lisp_Object frame = XWINDOW (window)->frame;
13952
13953 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13954 if (EQ (frame, selected_frame))
13955 selected_window = window;
13956 }
13957 }
13958
13959
13960
13961
13962
13963
13964 static void
13965 update_tab_bar (struct frame *f, bool save_match_data)
13966 {
13967 bool do_update = false;
13968
13969 #ifdef HAVE_WINDOW_SYSTEM
13970 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
13971 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
13972 do_update = true;
13973 }
13974 else
13975 #endif
13976 if (FRAME_TAB_BAR_LINES (f) > 0)
13977 do_update = true;
13978
13979 if (do_update)
13980 {
13981 Lisp_Object window;
13982 struct window *w;
13983
13984 window = FRAME_SELECTED_WINDOW (f);
13985 w = XWINDOW (window);
13986
13987
13988
13989
13990
13991
13992
13993
13994 if (windows_or_buffers_changed
13995 || w->update_mode_line
13996 || update_mode_lines
13997 || window_buffer_changed (w))
13998 {
13999 struct buffer *prev = current_buffer;
14000 specpdl_ref count = SPECPDL_INDEX ();
14001 Lisp_Object new_tab_bar;
14002 int new_n_tab_bar;
14003
14004
14005
14006
14007 set_buffer_internal_1 (XBUFFER (w->contents));
14008
14009
14010 if (save_match_data)
14011 record_unwind_save_match_data ();
14012
14013
14014 if (NILP (Voverriding_local_map_menu_flag))
14015 {
14016 specbind (Qoverriding_terminal_local_map, Qnil);
14017 specbind (Qoverriding_local_map, Qnil);
14018 }
14019
14020
14021
14022
14023
14024 eassert (EQ (selected_window,
14025
14026
14027 XFRAME (selected_frame)->selected_window));
14028 #ifdef HAVE_WINDOW_SYSTEM
14029 Lisp_Object frame;
14030 record_unwind_protect (restore_selected_window, selected_window);
14031 XSETFRAME (frame, f);
14032 selected_frame = frame;
14033 selected_window = FRAME_SELECTED_WINDOW (f);
14034 #endif
14035
14036
14037 new_tab_bar
14038 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
14039 &new_n_tab_bar);
14040
14041
14042 if (new_n_tab_bar != f->n_tab_bar_items
14043 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14044 {
14045
14046
14047
14048 block_input ();
14049 fset_tab_bar_items (f, new_tab_bar);
14050 f->n_tab_bar_items = new_n_tab_bar;
14051 w->update_mode_line = true;
14052 unblock_input ();
14053 }
14054
14055 unbind_to (count, Qnil);
14056 set_buffer_internal_1 (prev);
14057 }
14058 }
14059 }
14060
14061
14062
14063
14064
14065
14066
14067
14068
14069
14070
14071 static void
14072 display_tab_bar (struct window *w)
14073 {
14074 struct frame *f = XFRAME (WINDOW_FRAME (w));
14075 struct it it;
14076 Lisp_Object items;
14077 int i;
14078
14079
14080 #ifdef HAVE_NTGUI
14081 if (FRAME_W32_P (f))
14082 return;
14083 #endif
14084 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14085 if (FRAME_X_P (f))
14086 return;
14087 #endif
14088
14089 #ifdef HAVE_NS
14090 if (FRAME_NS_P (f))
14091 return;
14092 #endif
14093
14094 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14095 eassert (!FRAME_WINDOW_P (f));
14096 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14097 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14098 TAB_BAR_FACE_ID);
14099 it.first_visible_x = 0;
14100 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14101 #elif defined (HAVE_X_WINDOWS)
14102 if (FRAME_WINDOW_P (f))
14103 {
14104
14105
14106 struct window *tab_w;
14107 tab_w = XWINDOW (f->tab_bar_window);
14108 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14109 TAB_BAR_FACE_ID);
14110 it.first_visible_x = 0;
14111 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14112 }
14113 else
14114 #endif
14115 {
14116
14117
14118 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14119 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14120 TAB_BAR_FACE_ID);
14121 it.first_visible_x = 0;
14122 it.last_visible_x = FRAME_COLS (f);
14123 }
14124
14125
14126
14127
14128 it.paragraph_embedding = L2R;
14129
14130
14131 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14132 {
14133 struct glyph_row *row = it.glyph_row + i;
14134 clear_glyph_row (row);
14135 row->enabled_p = true;
14136 row->full_width_p = true;
14137 row->reversed_p = false;
14138 }
14139
14140
14141 items = it.f->tab_bar_items;
14142 int j;
14143 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14144 {
14145 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14146
14147
14148 if (NILP (string))
14149 break;
14150
14151 if (it.current_x < it.last_visible_x)
14152 display_string (NULL, string, Qnil, 0, 0, &it,
14153 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14154 }
14155
14156
14157 if (it.current_x < it.last_visible_x)
14158 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14159
14160
14161 compute_line_metrics (&it);
14162 }
14163
14164 #ifdef HAVE_WINDOW_SYSTEM
14165
14166
14167
14168
14169
14170 static void
14171 build_desired_tab_bar_string (struct frame *f)
14172 {
14173 int i;
14174 Lisp_Object caption;
14175
14176 caption = Qnil;
14177
14178
14179 fset_desired_tab_bar_string (f, build_string (""));
14180
14181
14182
14183
14184 for (i = 0; i < f->n_tab_bar_items; ++i)
14185 {
14186 #define PROP(IDX) \
14187 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14188
14189 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14190
14191
14192
14193
14194
14195 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14196
14197 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14198 props, caption);
14199
14200 f->desired_tab_bar_string =
14201 concat2 (f->desired_tab_bar_string, caption);
14202
14203 #undef PROP
14204 }
14205 }
14206
14207
14208
14209
14210
14211
14212
14213
14214
14215
14216
14217
14218
14219
14220 static void
14221 display_tab_bar_line (struct it *it, int height)
14222 {
14223 struct glyph_row *row = it->glyph_row;
14224 int max_x = it->last_visible_x;
14225 struct glyph *last;
14226
14227
14228 clear_glyph_row (row);
14229 row->enabled_p = true;
14230 row->y = it->current_y;
14231
14232
14233
14234 it->start_of_box_run_p = true;
14235
14236 bool enough = false;
14237 while (it->current_x < max_x)
14238 {
14239 int x, n_glyphs_before, i, nglyphs;
14240 struct it it_before;
14241
14242
14243 if (!get_next_display_element (it))
14244 {
14245
14246 if (height < 0 && !it->hpos)
14247 return;
14248 break;
14249 }
14250
14251
14252 n_glyphs_before = row->used[TEXT_AREA];
14253 it_before = *it;
14254
14255 PRODUCE_GLYPHS (it);
14256
14257 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14258 i = 0;
14259 x = it_before.current_x;
14260 while (i < nglyphs)
14261 {
14262 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14263
14264 if (x + glyph->pixel_width > max_x)
14265 {
14266
14267 row->used[TEXT_AREA] = n_glyphs_before;
14268 *it = it_before;
14269
14270
14271
14272 if (n_glyphs_before == 0
14273 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14274 break;
14275 goto out;
14276 }
14277
14278 ++it->hpos;
14279 x += glyph->pixel_width;
14280 ++i;
14281 }
14282
14283 enough = ITERATOR_AT_END_OF_LINE_P (it);
14284 set_iterator_to_next (it, true);
14285
14286
14287 if (enough)
14288 break;
14289 }
14290
14291 out:;
14292
14293 row->displays_text_p = row->used[TEXT_AREA] != 0;
14294
14295
14296
14297
14298
14299
14300
14301 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14302 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14303 it->face_id = DEFAULT_FACE_ID;
14304
14305 extend_face_to_end_of_line (it);
14306 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14307 last->right_box_line_p = true;
14308 if (last == row->glyphs[TEXT_AREA])
14309 last->left_box_line_p = true;
14310
14311
14312 if ((height -= it->max_ascent + it->max_descent) > 0)
14313 {
14314
14315 height %= FRAME_LINE_HEIGHT (it->f);
14316 it->max_ascent += height / 2;
14317 it->max_descent += (height + 1) / 2;
14318 }
14319
14320 compute_line_metrics (it);
14321
14322
14323 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14324 {
14325 row->height = row->phys_height = it->last_visible_y - row->y;
14326 row->visible_height = row->height;
14327 row->ascent = row->phys_ascent = 0;
14328 row->extra_line_spacing = 0;
14329 }
14330
14331 row->full_width_p = true;
14332 row->continued_p = false;
14333 row->truncated_on_left_p = false;
14334 row->truncated_on_right_p = false;
14335
14336 it->current_x = it->hpos = 0;
14337 it->current_y += row->height;
14338 ++it->vpos;
14339 ++it->glyph_row;
14340 }
14341
14342
14343
14344
14345
14346 static int
14347 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14348 {
14349 struct window *w = XWINDOW (f->tab_bar_window);
14350 struct it it;
14351
14352
14353
14354 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14355
14356
14357
14358 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14359 temp_row->reversed_p = false;
14360 it.first_visible_x = 0;
14361 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14362 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14363 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14364 it.paragraph_embedding = L2R;
14365
14366 clear_glyph_row (temp_row);
14367 while (!ITERATOR_AT_END_P (&it))
14368 {
14369 it.glyph_row = temp_row;
14370 display_tab_bar_line (&it, -1);
14371 }
14372 clear_glyph_row (temp_row);
14373
14374
14375 if (n_rows)
14376 *n_rows = it.vpos > 0 ? it.vpos : -1;
14377
14378 if (pixelwise)
14379 return it.current_y;
14380 else
14381 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14382 }
14383
14384 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14385 0, 2, 0,
14386 doc:
14387
14388 )
14389 (Lisp_Object frame, Lisp_Object pixelwise)
14390 {
14391 int height = 0;
14392
14393 struct frame *f = decode_any_frame (frame);
14394
14395 if (WINDOWP (f->tab_bar_window)
14396 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14397 {
14398 update_tab_bar (f, true);
14399 if (f->n_tab_bar_items)
14400 {
14401 build_desired_tab_bar_string (f);
14402 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14403 }
14404 }
14405
14406 return make_fixnum (height);
14407 }
14408
14409
14410
14411
14412 static bool
14413 redisplay_tab_bar (struct frame *f)
14414 {
14415 struct window *w;
14416 struct it it;
14417 struct glyph_row *row;
14418
14419 f->tab_bar_redisplayed = true;
14420
14421
14422
14423
14424
14425 if (!WINDOWP (f->tab_bar_window)
14426 || (w = XWINDOW (f->tab_bar_window),
14427 WINDOW_TOTAL_LINES (w) == 0))
14428 {
14429
14430
14431
14432
14433
14434 f->tab_bar_resized = true;
14435
14436 return false;
14437 }
14438
14439
14440 build_desired_tab_bar_string (f);
14441
14442 int new_nrows;
14443 int new_height = tab_bar_height (f, &new_nrows, true);
14444
14445 if (f->n_tab_bar_rows == 0)
14446 {
14447 f->n_tab_bar_rows = new_nrows;
14448 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14449 frame_default_tab_bar_height = new_height;
14450 }
14451
14452
14453
14454 if (new_nrows > f->n_tab_bar_rows
14455 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14456 && !f->minimize_tab_bar_window_p
14457 && new_height > WINDOW_PIXEL_HEIGHT (w))
14458 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14459 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14460 {
14461 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14462 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14463 if (new_nrows != f->n_tab_bar_rows)
14464 f->n_tab_bar_rows = new_nrows;
14465 clear_glyph_matrix (w->desired_matrix);
14466 f->fonts_changed = true;
14467 return true;
14468 }
14469
14470
14471 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14472 it.first_visible_x = 0;
14473 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14474 row = it.glyph_row;
14475 row->reversed_p = false;
14476 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14477 STRING_MULTIBYTE (f->desired_tab_bar_string));
14478
14479
14480
14481
14482
14483
14484
14485 it.paragraph_embedding = L2R;
14486
14487
14488
14489 if (f->n_tab_bar_rows > 0)
14490 {
14491 int border, rows, height, extra;
14492
14493 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14494 border = XFIXNUM (Vtab_bar_border);
14495 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14496 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14497 else if (EQ (Vtab_bar_border, Qborder_width))
14498 border = f->border_width;
14499 else
14500 border = 0;
14501 if (border < 0)
14502 border = 0;
14503
14504 rows = f->n_tab_bar_rows;
14505 height = max (1, (it.last_visible_y - border) / rows);
14506 extra = it.last_visible_y - border - height * rows;
14507
14508 while (it.current_y < it.last_visible_y)
14509 {
14510 int h = 0;
14511 if (extra > 0 && rows-- > 0)
14512 {
14513 h = (extra + rows - 1) / rows;
14514 extra -= h;
14515 }
14516 display_tab_bar_line (&it, height + h);
14517 }
14518 }
14519 else
14520 {
14521 while (it.current_y < it.last_visible_y)
14522 display_tab_bar_line (&it, 0);
14523 }
14524
14525
14526
14527 w->desired_matrix->no_scrolling_p = true;
14528 w->must_be_updated_p = true;
14529
14530 if (!NILP (Vauto_resize_tab_bars))
14531 {
14532 bool change_height_p = false;
14533
14534
14535
14536 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14537 change_height_p = true;
14538
14539
14540
14541
14542
14543 row = it.glyph_row - 1;
14544
14545
14546
14547
14548 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14549 && row->height >= FRAME_LINE_HEIGHT (f))
14550 change_height_p = true;
14551
14552
14553
14554 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14555 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14556 change_height_p = true;
14557
14558
14559
14560 if (change_height_p)
14561 {
14562 int nrows;
14563 int new_height = tab_bar_height (f, &nrows, true);
14564
14565 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14566 && !f->minimize_tab_bar_window_p)
14567 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14568 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14569 f->minimize_tab_bar_window_p = false;
14570
14571 if (change_height_p)
14572 {
14573 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14574 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14575 frame_default_tab_bar_height = new_height;
14576 clear_glyph_matrix (w->desired_matrix);
14577 f->n_tab_bar_rows = nrows;
14578 f->fonts_changed = true;
14579
14580 return true;
14581 }
14582 }
14583 }
14584
14585 f->minimize_tab_bar_window_p = false;
14586 return false;
14587 }
14588
14589
14590
14591
14592
14593
14594
14595 static bool
14596 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14597 int *prop_idx, bool *close_p)
14598 {
14599 Lisp_Object prop;
14600 ptrdiff_t charpos;
14601
14602
14603
14604
14605 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14606 charpos = max (0, charpos);
14607
14608
14609
14610
14611 prop = Fget_text_property (make_fixnum (charpos),
14612 Qmenu_item, f->current_tab_bar_string);
14613 if (! FIXNUMP (prop))
14614 return false;
14615 *prop_idx = XFIXNUM (prop);
14616
14617 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14618 Qclose_tab,
14619 f->current_tab_bar_string));
14620
14621 return true;
14622 }
14623
14624
14625
14626
14627
14628
14629
14630
14631
14632
14633
14634
14635 static int
14636 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14637 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14638 {
14639 struct window *w = XWINDOW (f->tab_bar_window);
14640 int area;
14641
14642
14643 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14644 if (*glyph == NULL)
14645 return -1;
14646
14647
14648
14649 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14650 return -1;
14651
14652 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14653 }
14654
14655
14656
14657
14658
14659
14660
14661
14662 Lisp_Object
14663 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14664 int modifiers)
14665 {
14666 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14667 struct window *w = XWINDOW (f->tab_bar_window);
14668 int hpos, vpos, prop_idx;
14669 bool close_p;
14670 struct glyph *glyph;
14671 Lisp_Object enabled_p;
14672 int ts;
14673
14674 frame_to_window_pixel_xy (w, &x, &y);
14675 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14676 if (ts == -1)
14677 return Fcons (Qtab_bar, Qnil);
14678
14679
14680 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14681 if (NILP (enabled_p))
14682 return Qnil;
14683
14684 if (down_p)
14685 {
14686
14687 if (!NILP (Vmouse_highlight))
14688 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14689 f->last_tab_bar_item = prop_idx;
14690 }
14691 else
14692 {
14693
14694 if (!NILP (Vmouse_highlight))
14695 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14696 f->last_tab_bar_item = -1;
14697 }
14698
14699 Lisp_Object caption =
14700 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14701
14702 AUTO_LIST2 (props, Qmenu_item,
14703 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14704 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14705 close_p ? Qt : Qnil));
14706
14707 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14708 props, caption);
14709
14710 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14711 }
14712
14713
14714
14715
14716
14717
14718 static void
14719 note_tab_bar_highlight (struct frame *f, int x, int y)
14720 {
14721 Lisp_Object window = f->tab_bar_window;
14722 struct window *w = XWINDOW (window);
14723 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14724 int hpos, vpos;
14725 struct glyph *glyph;
14726 struct glyph_row *row;
14727 int i;
14728 Lisp_Object enabled_p;
14729 int prop_idx;
14730 bool close_p;
14731 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14732 int rc;
14733
14734
14735
14736 if (x <= 0 || y <= 0)
14737 {
14738 clear_mouse_face (hlinfo);
14739 return;
14740 }
14741
14742 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14743 if (rc < 0)
14744 {
14745
14746 clear_mouse_face (hlinfo);
14747 return;
14748 }
14749 else if (rc == 0)
14750
14751 goto set_help_echo;
14752
14753 clear_mouse_face (hlinfo);
14754
14755 bool mouse_down_p = false;
14756
14757
14758
14759
14760
14761 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14762 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14763 && f == dpyinfo->last_mouse_frame);
14764
14765 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14766 && f->last_tab_bar_item != -1)
14767 return;
14768 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14769
14770
14771 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14772 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14773 {
14774
14775
14776 row = MATRIX_ROW (w->current_matrix, vpos);
14777 for (i = x = 0; i < hpos; ++i)
14778 x += row->glyphs[TEXT_AREA][i].pixel_width;
14779
14780
14781 hlinfo->mouse_face_beg_col = hpos;
14782 hlinfo->mouse_face_beg_row = vpos;
14783 hlinfo->mouse_face_beg_x = x;
14784 hlinfo->mouse_face_past_end = false;
14785
14786 hlinfo->mouse_face_end_col = hpos + 1;
14787 hlinfo->mouse_face_end_row = vpos;
14788 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14789 hlinfo->mouse_face_window = window;
14790 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14791
14792
14793 show_mouse_face (hlinfo, draw);
14794 }
14795
14796 set_help_echo:
14797
14798
14799
14800 help_echo_object = help_echo_window = Qnil;
14801 help_echo_pos = -1;
14802 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14803 if (NILP (help_echo_string))
14804 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14805 }
14806
14807 #endif
14808
14809
14810 static Lisp_Object
14811 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14812 {
14813 ptrdiff_t clen = 0;
14814
14815 for (int i = 0; i < f->n_tab_bar_items; i++)
14816 {
14817 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14818 + TAB_BAR_ITEM_CAPTION));
14819 if (NILP (caption))
14820 return Qnil;
14821 clen += SCHARS (caption);
14822 if (x < clen)
14823 {
14824 *prop_idx = i;
14825 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14826 - (clen - x)),
14827 Qclose_tab,
14828 caption));
14829 return caption;
14830 }
14831 }
14832 return Qnil;
14833 }
14834
14835
14836
14837
14838
14839
14840 Lisp_Object
14841 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14842 struct input_event *event)
14843 {
14844
14845 if (y < FRAME_MENU_BAR_LINES (f)
14846 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14847 return Qnil;
14848
14849
14850 int prop_idx;
14851 bool close_p;
14852 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14853
14854 if (NILP (caption))
14855 return Qnil;
14856
14857 if (NILP (AREF (f->tab_bar_items,
14858 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14859 return Qnil;
14860
14861 if (down_p)
14862 f->last_tab_bar_item = prop_idx;
14863 else
14864 f->last_tab_bar_item = -1;
14865
14866 caption = Fcopy_sequence (caption);
14867
14868 AUTO_LIST2 (props, Qmenu_item,
14869 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14870 + TAB_BAR_ITEM_KEY),
14871 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14872 + TAB_BAR_ITEM_BINDING),
14873 close_p ? Qt : Qnil));
14874
14875 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14876 props, caption);
14877
14878 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14879 }
14880
14881
14882
14883
14884
14885
14886
14887 #ifdef HAVE_WINDOW_SYSTEM
14888
14889
14890
14891
14892
14893
14894 static void
14895 update_tool_bar (struct frame *f, bool save_match_data)
14896 {
14897 #ifdef HAVE_EXT_TOOL_BAR
14898 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14899 #else
14900 bool do_update = (WINDOWP (f->tool_bar_window)
14901 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14902 #endif
14903
14904 if (do_update)
14905 {
14906 Lisp_Object window;
14907 struct window *w;
14908
14909 window = FRAME_SELECTED_WINDOW (f);
14910 w = XWINDOW (window);
14911
14912
14913
14914
14915
14916
14917
14918
14919 if (windows_or_buffers_changed
14920 || w->update_mode_line
14921 || update_mode_lines
14922 || window_buffer_changed (w))
14923 {
14924 struct buffer *prev = current_buffer;
14925 specpdl_ref count = SPECPDL_INDEX ();
14926 Lisp_Object frame, new_tool_bar;
14927 int new_n_tool_bar;
14928
14929
14930
14931
14932 set_buffer_internal_1 (XBUFFER (w->contents));
14933
14934
14935 if (save_match_data)
14936 record_unwind_save_match_data ();
14937
14938
14939 if (NILP (Voverriding_local_map_menu_flag))
14940 {
14941 specbind (Qoverriding_terminal_local_map, Qnil);
14942 specbind (Qoverriding_local_map, Qnil);
14943 }
14944
14945
14946
14947
14948
14949 eassert (EQ (selected_window,
14950
14951
14952 XFRAME (selected_frame)->selected_window));
14953 record_unwind_protect (restore_selected_window, selected_window);
14954 XSETFRAME (frame, f);
14955 selected_frame = frame;
14956 selected_window = FRAME_SELECTED_WINDOW (f);
14957
14958
14959 new_tool_bar
14960 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
14961 &new_n_tool_bar);
14962
14963
14964 if (new_n_tool_bar != f->n_tool_bar_items
14965 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
14966 {
14967
14968
14969
14970 block_input ();
14971 fset_tool_bar_items (f, new_tool_bar);
14972 f->n_tool_bar_items = new_n_tool_bar;
14973 w->update_mode_line = true;
14974 unblock_input ();
14975 }
14976
14977 unbind_to (count, Qnil);
14978 set_buffer_internal_1 (prev);
14979 }
14980 }
14981 }
14982
14983 #ifndef HAVE_EXT_TOOL_BAR
14984
14985
14986
14987
14988
14989 static void
14990 build_desired_tool_bar_string (struct frame *f)
14991 {
14992 int i, size, size_needed;
14993 Lisp_Object image, plist;
14994
14995 image = plist = Qnil;
14996
14997
14998
14999
15000
15001 size = (STRINGP (f->desired_tool_bar_string)
15002 ? SCHARS (f->desired_tool_bar_string)
15003 : 0);
15004
15005
15006 size_needed = f->n_tool_bar_items;
15007
15008
15009 if (size < size_needed || NILP (f->desired_tool_bar_string))
15010 fset_desired_tool_bar_string
15011 (f, Fmake_string (make_fixnum (size_needed), make_fixnum (' '), Qnil));
15012 else
15013 {
15014 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
15015 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
15016 props, f->desired_tool_bar_string);
15017 }
15018
15019
15020
15021
15022 for (i = 0; i < f->n_tool_bar_items; ++i)
15023 {
15024 #define PROP(IDX) \
15025 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
15026
15027 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
15028 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
15029 int hmargin, vmargin, relief, idx, end;
15030
15031
15032
15033 image = PROP (TOOL_BAR_ITEM_IMAGES);
15034 if (VECTORP (image))
15035 {
15036 if (enabled_p)
15037 idx = (selected_p
15038 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
15039 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
15040 else
15041 idx = (selected_p
15042 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15043 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15044
15045 eassert (ASIZE (image) >= idx);
15046 image = AREF (image, idx);
15047 }
15048 else
15049 idx = -1;
15050
15051
15052 if (!valid_image_p (image))
15053 continue;
15054
15055
15056 plist = Fcopy_sequence (XCDR (image));
15057
15058
15059 relief = (tool_bar_button_relief >= 0
15060 ? min (tool_bar_button_relief,
15061 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15062 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15063 hmargin = vmargin = relief;
15064
15065 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15066 INT_MAX - max (hmargin, vmargin)))
15067 {
15068 hmargin += XFIXNAT (Vtool_bar_button_margin);
15069 vmargin += XFIXNAT (Vtool_bar_button_margin);
15070 }
15071 else if (CONSP (Vtool_bar_button_margin))
15072 {
15073 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15074 INT_MAX - hmargin))
15075 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15076
15077 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15078 INT_MAX - vmargin))
15079 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15080 }
15081
15082 if (auto_raise_tool_bar_buttons_p)
15083 {
15084
15085
15086 if (selected_p)
15087 {
15088 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15089 hmargin -= relief;
15090 vmargin -= relief;
15091 }
15092 }
15093 else
15094 {
15095
15096
15097
15098 plist = plist_put (plist, QCrelief,
15099 (selected_p
15100 ? make_fixnum (-relief)
15101 : make_fixnum (relief)));
15102 hmargin -= relief;
15103 vmargin -= relief;
15104 }
15105
15106
15107 if (hmargin || vmargin)
15108 {
15109 if (hmargin == vmargin)
15110 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15111 else
15112 plist = plist_put (plist, QCmargin,
15113 Fcons (make_fixnum (hmargin),
15114 make_fixnum (vmargin)));
15115 }
15116
15117
15118
15119
15120 if (!enabled_p && idx < 0)
15121 plist = plist_put (plist, QCconversion, Qdisabled);
15122
15123
15124
15125
15126
15127 image = Fcons (Qimage, plist);
15128 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15129 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15130
15131
15132
15133
15134 if (i + 1 == f->n_tool_bar_items)
15135 end = SCHARS (f->desired_tool_bar_string);
15136 else
15137 end = i + 1;
15138 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15139 props, f->desired_tool_bar_string);
15140 #undef PROP
15141 }
15142 }
15143
15144
15145
15146
15147
15148
15149
15150
15151
15152
15153
15154
15155
15156
15157 static void
15158 display_tool_bar_line (struct it *it, int height)
15159 {
15160 struct glyph_row *row = it->glyph_row;
15161 int max_x = it->last_visible_x;
15162 struct glyph *last;
15163
15164
15165 clear_glyph_row (row);
15166 row->enabled_p = true;
15167 row->y = it->current_y;
15168
15169
15170
15171 it->start_of_box_run_p = true;
15172
15173 while (it->current_x < max_x)
15174 {
15175 int x, n_glyphs_before, i, nglyphs;
15176 struct it it_before;
15177
15178
15179 if (!get_next_display_element (it))
15180 {
15181
15182 if (height < 0 && !it->hpos)
15183 return;
15184 break;
15185 }
15186
15187
15188 n_glyphs_before = row->used[TEXT_AREA];
15189 it_before = *it;
15190
15191 PRODUCE_GLYPHS (it);
15192
15193 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15194 i = 0;
15195 x = it_before.current_x;
15196 while (i < nglyphs)
15197 {
15198 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15199
15200 if (x + glyph->pixel_width > max_x)
15201 {
15202
15203 row->used[TEXT_AREA] = n_glyphs_before;
15204 *it = it_before;
15205
15206
15207
15208 if (n_glyphs_before == 0
15209 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15210 break;
15211 goto out;
15212 }
15213
15214 ++it->hpos;
15215 x += glyph->pixel_width;
15216 ++i;
15217 }
15218
15219
15220 if (ITERATOR_AT_END_OF_LINE_P (it))
15221 break;
15222
15223 set_iterator_to_next (it, true);
15224 }
15225
15226 out:;
15227
15228 row->displays_text_p = row->used[TEXT_AREA] != 0;
15229
15230
15231
15232
15233
15234
15235
15236 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15237 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15238 it->face_id = DEFAULT_FACE_ID;
15239
15240 extend_face_to_end_of_line (it);
15241 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15242 last->right_box_line_p = true;
15243 if (last == row->glyphs[TEXT_AREA])
15244 last->left_box_line_p = true;
15245
15246
15247 if ((height -= it->max_ascent + it->max_descent) > 0)
15248 {
15249
15250 height %= FRAME_LINE_HEIGHT (it->f);
15251 it->max_ascent += height / 2;
15252 it->max_descent += (height + 1) / 2;
15253 }
15254
15255 compute_line_metrics (it);
15256
15257
15258 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15259 {
15260 row->height = row->phys_height = it->last_visible_y - row->y;
15261 row->visible_height = row->height;
15262 row->ascent = row->phys_ascent = 0;
15263 row->extra_line_spacing = 0;
15264 }
15265
15266 row->full_width_p = true;
15267 row->continued_p = false;
15268 row->truncated_on_left_p = false;
15269 row->truncated_on_right_p = false;
15270
15271 it->current_x = it->hpos = 0;
15272 it->current_y += row->height;
15273 ++it->vpos;
15274 ++it->glyph_row;
15275 }
15276
15277
15278
15279
15280
15281 static int
15282 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15283 {
15284 struct window *w = XWINDOW (f->tool_bar_window);
15285 struct it it;
15286
15287
15288
15289 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15290
15291
15292
15293 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15294 temp_row->reversed_p = false;
15295 it.first_visible_x = 0;
15296 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15297 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15298 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15299 it.paragraph_embedding = L2R;
15300
15301 while (!ITERATOR_AT_END_P (&it))
15302 {
15303 clear_glyph_row (temp_row);
15304 it.glyph_row = temp_row;
15305 display_tool_bar_line (&it, -1);
15306 }
15307 clear_glyph_row (temp_row);
15308
15309
15310 if (n_rows)
15311 *n_rows = it.vpos > 0 ? it.vpos : -1;
15312
15313 if (pixelwise)
15314 return it.current_y;
15315 else
15316 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15317 }
15318
15319 #endif
15320
15321 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15322 0, 2, 0,
15323 doc:
15324
15325 )
15326 (Lisp_Object frame, Lisp_Object pixelwise)
15327 {
15328 int height = 0;
15329
15330 #ifndef HAVE_EXT_TOOL_BAR
15331 struct frame *f = decode_any_frame (frame);
15332
15333 if (WINDOWP (f->tool_bar_window)
15334 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15335 {
15336 update_tool_bar (f, true);
15337 if (f->n_tool_bar_items)
15338 {
15339 build_desired_tool_bar_string (f);
15340 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15341 }
15342 }
15343 #endif
15344
15345 return make_fixnum (height);
15346 }
15347
15348 #ifndef HAVE_EXT_TOOL_BAR
15349
15350
15351
15352 static bool
15353 redisplay_tool_bar (struct frame *f)
15354 {
15355 struct window *w;
15356 struct it it;
15357 struct glyph_row *row;
15358
15359 f->tool_bar_redisplayed = true;
15360
15361
15362
15363
15364
15365 if (!WINDOWP (f->tool_bar_window)
15366 || (w = XWINDOW (f->tool_bar_window),
15367 WINDOW_TOTAL_LINES (w) == 0))
15368 {
15369
15370
15371
15372
15373
15374 f->tool_bar_resized = true;
15375
15376 return false;
15377 }
15378
15379
15380 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15381 it.first_visible_x = 0;
15382 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15383 row = it.glyph_row;
15384 row->reversed_p = false;
15385
15386
15387 build_desired_tool_bar_string (f);
15388 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15389 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15390
15391
15392
15393
15394
15395
15396
15397 it.paragraph_embedding = L2R;
15398
15399 if (f->n_tool_bar_rows == 0)
15400 {
15401 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15402
15403 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15404 {
15405 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15406 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15407 frame_default_tool_bar_height = new_height;
15408
15409 clear_glyph_matrix (w->desired_matrix);
15410 f->fonts_changed = true;
15411 return true;
15412 }
15413 }
15414
15415
15416
15417 if (f->n_tool_bar_rows > 0)
15418 {
15419 int border, rows, height, extra;
15420
15421 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15422 border = XFIXNUM (Vtool_bar_border);
15423 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15424 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15425 else if (EQ (Vtool_bar_border, Qborder_width))
15426 border = f->border_width;
15427 else
15428 border = 0;
15429 if (border < 0)
15430 border = 0;
15431
15432 rows = f->n_tool_bar_rows;
15433 height = max (1, (it.last_visible_y - border) / rows);
15434 extra = it.last_visible_y - border - height * rows;
15435
15436 while (it.current_y < it.last_visible_y)
15437 {
15438 int h = 0;
15439 if (extra > 0 && rows-- > 0)
15440 {
15441 h = (extra + rows - 1) / rows;
15442 extra -= h;
15443 }
15444 display_tool_bar_line (&it, height + h);
15445 }
15446 }
15447 else
15448 {
15449 while (it.current_y < it.last_visible_y)
15450 display_tool_bar_line (&it, 0);
15451 }
15452
15453
15454
15455 w->desired_matrix->no_scrolling_p = true;
15456 w->must_be_updated_p = true;
15457
15458 if (!NILP (Vauto_resize_tool_bars))
15459 {
15460 bool change_height_p = false;
15461
15462
15463
15464 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15465 change_height_p = true;
15466
15467
15468
15469
15470
15471 row = it.glyph_row - 1;
15472
15473
15474
15475
15476 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15477 && row->height >= FRAME_LINE_HEIGHT (f))
15478 change_height_p = true;
15479
15480
15481
15482 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15483 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15484 change_height_p = true;
15485
15486
15487
15488 if (change_height_p)
15489 {
15490 int nrows;
15491 int new_height = tool_bar_height (f, &nrows, true);
15492
15493 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15494 && !f->minimize_tool_bar_window_p)
15495 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15496 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15497 f->minimize_tool_bar_window_p = false;
15498
15499 if (change_height_p)
15500 {
15501 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15502 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15503 frame_default_tool_bar_height = new_height;
15504 clear_glyph_matrix (w->desired_matrix);
15505 f->n_tool_bar_rows = nrows;
15506 f->fonts_changed = true;
15507
15508 return true;
15509 }
15510 }
15511 }
15512
15513 f->minimize_tool_bar_window_p = false;
15514
15515 return false;
15516 }
15517
15518
15519
15520
15521
15522
15523 static bool
15524 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15525 {
15526 Lisp_Object prop;
15527 ptrdiff_t charpos;
15528
15529
15530
15531
15532 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15533 charpos = max (0, charpos);
15534
15535
15536
15537
15538 prop = Fget_text_property (make_fixnum (charpos),
15539 Qmenu_item, f->current_tool_bar_string);
15540 if (! FIXNUMP (prop))
15541 return false;
15542 *prop_idx = XFIXNUM (prop);
15543 return true;
15544 }
15545
15546
15547
15548
15549
15550
15551
15552
15553
15554
15555
15556
15557 static int
15558 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15559 int *hpos, int *vpos, int *prop_idx)
15560 {
15561 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15562 struct window *w = XWINDOW (f->tool_bar_window);
15563 int area;
15564
15565
15566 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15567 if (*glyph == NULL)
15568 return -1;
15569
15570
15571
15572 if (!tool_bar_item_info (f, *glyph, prop_idx))
15573 return -1;
15574
15575
15576 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15577 && *vpos >= hlinfo->mouse_face_beg_row
15578 && *vpos <= hlinfo->mouse_face_end_row
15579 && (*vpos > hlinfo->mouse_face_beg_row
15580 || *hpos >= hlinfo->mouse_face_beg_col)
15581 && (*vpos < hlinfo->mouse_face_end_row
15582 || *hpos < hlinfo->mouse_face_end_col
15583 || hlinfo->mouse_face_past_end))
15584 return 0;
15585
15586 return 1;
15587 }
15588
15589
15590
15591
15592
15593
15594
15595
15596 void
15597 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15598 int modifiers, Lisp_Object device)
15599 {
15600 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15601 struct window *w = XWINDOW (f->tool_bar_window);
15602 int hpos, vpos, prop_idx;
15603 struct glyph *glyph;
15604 Lisp_Object enabled_p;
15605 int ts;
15606
15607
15608
15609
15610
15611
15612
15613
15614 frame_to_window_pixel_xy (w, &x, &y);
15615 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15616 if (ts == -1
15617 || (ts != 0 && !NILP (Vmouse_highlight)))
15618 return;
15619
15620
15621
15622
15623 if (NILP (Vmouse_highlight) && !down_p)
15624 prop_idx = f->last_tool_bar_item;
15625
15626
15627 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15628 if (NILP (enabled_p))
15629 return;
15630
15631 if (down_p)
15632 {
15633
15634 if (!NILP (Vmouse_highlight))
15635 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15636 f->last_tool_bar_item = prop_idx;
15637 }
15638 else
15639 {
15640 Lisp_Object key, frame;
15641 struct input_event event;
15642 EVENT_INIT (event);
15643
15644
15645 if (!NILP (Vmouse_highlight))
15646 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15647
15648 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15649
15650 XSETFRAME (frame, f);
15651 event.kind = TOOL_BAR_EVENT;
15652 event.frame_or_window = frame;
15653 event.arg = key;
15654 event.modifiers = modifiers;
15655 event.device = device;
15656 kbd_buffer_store_event (&event);
15657 f->last_tool_bar_item = -1;
15658 }
15659 }
15660
15661 void
15662 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15663 int modifiers)
15664 {
15665 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15666 }
15667
15668
15669
15670
15671
15672 static void
15673 note_tool_bar_highlight (struct frame *f, int x, int y)
15674 {
15675 Lisp_Object window = f->tool_bar_window;
15676 struct window *w = XWINDOW (window);
15677 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15678 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15679 int hpos, vpos;
15680 struct glyph *glyph;
15681 struct glyph_row *row;
15682 int i;
15683 Lisp_Object enabled_p;
15684 int prop_idx;
15685 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15686 bool mouse_down_p;
15687 int rc;
15688
15689
15690
15691 if (x <= 0 || y <= 0)
15692 {
15693 clear_mouse_face (hlinfo);
15694 return;
15695 }
15696
15697 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15698 if (rc < 0)
15699 {
15700
15701 clear_mouse_face (hlinfo);
15702 return;
15703 }
15704 else if (rc == 0)
15705
15706 goto set_help_echo;
15707
15708 clear_mouse_face (hlinfo);
15709
15710
15711 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15712 && f == dpyinfo->last_mouse_frame);
15713
15714 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15715 return;
15716
15717 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15718
15719
15720 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15721 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15722 {
15723
15724
15725 row = MATRIX_ROW (w->current_matrix, vpos);
15726 for (i = x = 0; i < hpos; ++i)
15727 x += row->glyphs[TEXT_AREA][i].pixel_width;
15728
15729
15730 hlinfo->mouse_face_beg_col = hpos;
15731 hlinfo->mouse_face_beg_row = vpos;
15732 hlinfo->mouse_face_beg_x = x;
15733 hlinfo->mouse_face_past_end = false;
15734
15735 hlinfo->mouse_face_end_col = hpos + 1;
15736 hlinfo->mouse_face_end_row = vpos;
15737 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15738 hlinfo->mouse_face_window = window;
15739 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15740
15741
15742 show_mouse_face (hlinfo, draw);
15743 }
15744
15745 set_help_echo:
15746
15747
15748
15749 help_echo_object = help_echo_window = Qnil;
15750 help_echo_pos = -1;
15751 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15752 if (NILP (help_echo_string))
15753 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15754 }
15755
15756 #endif
15757
15758 #endif
15759
15760
15761
15762
15763
15764
15765
15766
15767
15768
15769
15770
15771
15772 static bool
15773 hscroll_window_tree (Lisp_Object window)
15774 {
15775 bool hscrolled_p = false;
15776 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15777 int hscroll_step_abs = 0;
15778 double hscroll_step_rel = 0;
15779
15780 if (hscroll_relative_p)
15781 {
15782 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15783 if (hscroll_step_rel < 0)
15784 {
15785 hscroll_relative_p = false;
15786 hscroll_step_abs = 0;
15787 }
15788 }
15789 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15790 {
15791 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15792 if (hscroll_step_abs < 0)
15793 hscroll_step_abs = 0;
15794 }
15795 else
15796 hscroll_step_abs = 0;
15797
15798 while (WINDOWP (window))
15799 {
15800 struct window *w = XWINDOW (window);
15801
15802 if (WINDOWP (w->contents))
15803 hscrolled_p |= hscroll_window_tree (w->contents);
15804 else if (w->cursor.vpos >= 0
15805
15806
15807
15808
15809
15810
15811 && !(w == XWINDOW (echo_area_window)
15812 && !NILP (echo_area_buffer[0])))
15813 {
15814 int h_margin;
15815 int text_area_width;
15816 struct glyph_row *cursor_row;
15817 struct glyph_row *bottom_row;
15818
15819 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15820 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15821 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15822 else
15823 cursor_row = bottom_row - 1;
15824
15825 if (!cursor_row->enabled_p)
15826 {
15827 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15828 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15829 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15830 else
15831 cursor_row = bottom_row - 1;
15832 }
15833 bool row_r2l_p = cursor_row->reversed_p;
15834 bool hscl = hscrolling_current_line_p (w);
15835 int x_offset = 0;
15836
15837
15838 if (!NILP (Vdisplay_line_numbers))
15839 {
15840 struct glyph *g;
15841 if (!row_r2l_p)
15842 {
15843 for (g = cursor_row->glyphs[TEXT_AREA];
15844 g < cursor_row->glyphs[TEXT_AREA]
15845 + cursor_row->used[TEXT_AREA];
15846 g++)
15847 {
15848 if (!(NILP (g->object) && g->charpos < 0))
15849 break;
15850 x_offset += g->pixel_width;
15851 }
15852 }
15853 else
15854 {
15855 for (g = cursor_row->glyphs[TEXT_AREA]
15856 + cursor_row->used[TEXT_AREA];
15857 g > cursor_row->glyphs[TEXT_AREA];
15858 g--)
15859 {
15860 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
15861 break;
15862 x_offset += (g - 1)->pixel_width;
15863 }
15864 }
15865 }
15866 if (cursor_row->truncated_on_left_p)
15867 {
15868
15869 struct frame *f = XFRAME (WINDOW_FRAME (w));
15870 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
15871 }
15872
15873 text_area_width = window_box_width (w, TEXT_AREA);
15874
15875
15876 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
15877 * WINDOW_FRAME_COLUMN_WIDTH (w));
15878
15879
15880
15881 if (w->suspend_auto_hscroll
15882 && NILP (Fequal (Fwindow_point (window),
15883 Fwindow_old_point (window))))
15884 {
15885 w->suspend_auto_hscroll = false;
15886
15887
15888
15889
15890 if (w->min_hscroll == 0 && w->hscroll > 0
15891 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
15892 Qcurrent_line))
15893 SET_FRAME_GARBAGED (XFRAME (w->frame));
15894 }
15895
15896
15897 Fset_marker (w->old_pointm,
15898 ((w == XWINDOW (selected_window))
15899 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
15900 : Fmarker_position (w->pointm)),
15901 w->contents);
15902
15903 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
15904 && !w->suspend_auto_hscroll
15905
15906
15907
15908
15909
15910
15911 && (CHARPOS (cursor_row->start.pos)
15912 >= BUF_BEG (XBUFFER (w->contents)))
15913
15914
15915
15916
15917 && ((!row_r2l_p
15918 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
15919 || (cursor_row->enabled_p
15920 && cursor_row->truncated_on_right_p
15921 && (w->cursor.x >= text_area_width - h_margin))))
15922
15923
15924
15925
15926
15927
15928 || (row_r2l_p
15929 && ((cursor_row->enabled_p
15930
15931
15932
15933 && cursor_row->truncated_on_right_p
15934 && w->cursor.x <= h_margin)
15935 || (w->hscroll
15936 && (w->cursor.x >= (text_area_width - h_margin
15937 - x_offset)))))
15938
15939
15940
15941
15942
15943 || (hscl
15944 && w->hscroll != w->min_hscroll
15945 && !cursor_row->truncated_on_left_p)))
15946 {
15947 struct it it;
15948 ptrdiff_t hscroll;
15949 struct buffer *saved_current_buffer;
15950 ptrdiff_t pt;
15951 int wanted_x;
15952
15953
15954 saved_current_buffer = current_buffer;
15955 current_buffer = XBUFFER (w->contents);
15956
15957 if (w == XWINDOW (selected_window))
15958 pt = PT;
15959 else
15960 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
15961
15962
15963
15964 init_to_row_start (&it, w, cursor_row);
15965 if (hscl)
15966 it.first_visible_x = window_hscroll_limited (w, it.f)
15967 * FRAME_COLUMN_WIDTH (it.f);
15968 it.last_visible_x = DISP_INFINITY;
15969
15970 ptrdiff_t nchars = pt - IT_CHARPOS (it);
15971 if (current_buffer->long_line_optimizations_p
15972 && nchars > large_hscroll_threshold)
15973 {
15974
15975
15976
15977
15978 fast_move_it_horizontally (&it, nchars);
15979 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
15980 }
15981 else
15982 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
15983
15984
15985
15986
15987
15988
15989 if (it.method == GET_FROM_STRING && pt > 1)
15990 {
15991 init_to_row_start (&it, w, cursor_row);
15992 if (hscl)
15993 it.first_visible_x = (window_hscroll_limited (w, it.f)
15994 * FRAME_COLUMN_WIDTH (it.f));
15995 if (current_buffer->long_line_optimizations_p
15996 && nchars > large_hscroll_threshold)
15997 {
15998 fast_move_it_horizontally (&it, nchars - 1);
15999 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
16000 }
16001 else
16002 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
16003 }
16004 current_buffer = saved_current_buffer;
16005
16006
16007 if (!hscroll_relative_p && hscroll_step_abs == 0)
16008 hscroll = max (0, (it.current_x
16009 - (ITERATOR_AT_END_OF_LINE_P (&it)
16010 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
16011 : (text_area_width / 2))))
16012 / FRAME_COLUMN_WIDTH (it.f);
16013 else if ((!row_r2l_p
16014 && w->cursor.x >= text_area_width - h_margin)
16015 || (row_r2l_p && w->cursor.x <= h_margin))
16016 {
16017 if (hscroll_relative_p)
16018 wanted_x = text_area_width * (1 - hscroll_step_rel)
16019 - h_margin;
16020 else
16021 wanted_x = text_area_width
16022 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16023 - h_margin;
16024 hscroll
16025 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16026 }
16027 else
16028 {
16029 if (hscroll_relative_p)
16030 wanted_x =
16031 text_area_width * hscroll_step_rel + h_margin + x_offset;
16032 else
16033 wanted_x =
16034 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16035 + h_margin + x_offset;
16036 hscroll
16037 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16038 }
16039 hscroll = max (hscroll, w->min_hscroll);
16040
16041
16042
16043
16044 if (w->hscroll != hscroll
16045
16046
16047
16048
16049 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16050 {
16051 struct buffer *b = XBUFFER (w->contents);
16052 b->prevent_redisplay_optimizations_p = true;
16053 w->hscroll = hscroll;
16054 hscrolled_p = true;
16055 }
16056 }
16057 }
16058
16059 window = w->next;
16060 }
16061
16062
16063 return hscrolled_p;
16064 }
16065
16066
16067
16068
16069
16070
16071
16072
16073 static bool
16074 hscroll_windows (Lisp_Object window)
16075 {
16076 bool hscrolled_p = hscroll_window_tree (window);
16077 if (hscrolled_p)
16078 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16079 return hscrolled_p;
16080 }
16081
16082
16083
16084
16085
16086
16087
16088
16089
16090
16091 #ifdef GLYPH_DEBUG
16092
16093
16094
16095 static int debug_first_unchanged_at_end_vpos;
16096 static int debug_last_unchanged_at_beg_vpos;
16097
16098
16099
16100 static int debug_dvpos, debug_dy;
16101
16102
16103
16104 static ptrdiff_t debug_delta, debug_delta_bytes;
16105
16106
16107
16108
16109 static ptrdiff_t debug_end_vpos;
16110
16111
16112
16113
16114
16115 static void debug_method_add (struct window *, char const *, ...)
16116 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16117
16118 static void
16119 debug_method_add (struct window *w, char const *fmt, ...)
16120 {
16121 void *ptr = w;
16122 char *method = w->desired_matrix->method;
16123 int len = strlen (method);
16124 int size = sizeof w->desired_matrix->method;
16125 int remaining = size - len - 1;
16126 va_list ap;
16127
16128 if (len && remaining)
16129 {
16130 method[len] = '|';
16131 --remaining, ++len;
16132 }
16133
16134 va_start (ap, fmt);
16135 vsnprintf (method + len, remaining + 1, fmt, ap);
16136 va_end (ap);
16137
16138 if (trace_redisplay_p)
16139 fprintf (stderr, "%p (%s): %s\n",
16140 ptr,
16141 ((BUFFERP (w->contents)
16142 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16143 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16144 : "no buffer"),
16145 method + len);
16146 }
16147
16148 #endif
16149
16150
16151
16152
16153
16154
16155
16156 static bool
16157 text_outside_line_unchanged_p (struct window *w,
16158 ptrdiff_t start, ptrdiff_t end)
16159 {
16160 bool unchanged_p = true;
16161
16162
16163 if (window_outdated (w))
16164 {
16165
16166 if (GPT < start || Z - GPT < end)
16167 unchanged_p = false;
16168
16169
16170 if (unchanged_p
16171 && (BEG_UNCHANGED < start - 1
16172 || END_UNCHANGED < end))
16173 unchanged_p = false;
16174
16175
16176
16177 if (unchanged_p
16178 && FIXNUMP (BVAR (current_buffer, selective_display))
16179 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16180 && (BEG_UNCHANGED < start || GPT <= start))
16181 unchanged_p = false;
16182
16183
16184
16185
16186
16187
16188
16189
16190 if (unchanged_p)
16191 {
16192 if (BEG + BEG_UNCHANGED == start
16193 && overlay_touches_p (start))
16194 unchanged_p = false;
16195 if (END_UNCHANGED == end
16196 && overlay_touches_p (Z - end))
16197 unchanged_p = false;
16198 }
16199
16200
16201
16202
16203
16204
16205
16206
16207 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16208 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16209 unchanged_p = false;
16210 }
16211
16212 return unchanged_p;
16213 }
16214
16215
16216
16217
16218
16219
16220
16221
16222
16223 void
16224 redisplay (void)
16225 {
16226 redisplay_internal ();
16227 }
16228
16229
16230 static Lisp_Object
16231 overlay_arrow_string_or_property (Lisp_Object var)
16232 {
16233 Lisp_Object val;
16234
16235 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16236 return val;
16237
16238 return Voverlay_arrow_string;
16239 }
16240
16241
16242 static bool
16243 overlay_arrow_in_current_buffer_p (void)
16244 {
16245 Lisp_Object vlist;
16246
16247 for (vlist = Voverlay_arrow_variable_list;
16248 CONSP (vlist);
16249 vlist = XCDR (vlist))
16250 {
16251 Lisp_Object var = XCAR (vlist);
16252 Lisp_Object val;
16253
16254 if (!SYMBOLP (var))
16255 continue;
16256 val = find_symbol_value (var);
16257 if (MARKERP (val)
16258 && current_buffer == XMARKER (val)->buffer)
16259 return true;
16260 }
16261 return false;
16262 }
16263
16264
16265
16266
16267
16268
16269
16270 static bool
16271 overlay_arrows_changed_p (bool set_redisplay)
16272 {
16273 Lisp_Object vlist;
16274 bool changed = false;
16275
16276 for (vlist = Voverlay_arrow_variable_list;
16277 CONSP (vlist);
16278 vlist = XCDR (vlist))
16279 {
16280 Lisp_Object var = XCAR (vlist);
16281 Lisp_Object val, pstr;
16282
16283 if (!SYMBOLP (var))
16284 continue;
16285 val = find_symbol_value (var);
16286 if (!MARKERP (val))
16287 continue;
16288 if (! EQ (Fmarker_position (val),
16289
16290
16291 Fget (var, Qlast_arrow_position))
16292 || ! (pstr = overlay_arrow_string_or_property (var),
16293 EQ (pstr, Fget (var, Qlast_arrow_string))))
16294 {
16295 struct buffer *buf = XMARKER (val)->buffer;
16296
16297 if (set_redisplay)
16298 {
16299 if (buf)
16300 bset_redisplay (buf);
16301 changed = true;
16302 }
16303 else
16304 return true;
16305 }
16306 }
16307 return changed;
16308 }
16309
16310
16311
16312 static void
16313 update_overlay_arrows (int up_to_date)
16314 {
16315 Lisp_Object vlist;
16316
16317 for (vlist = Voverlay_arrow_variable_list;
16318 CONSP (vlist);
16319 vlist = XCDR (vlist))
16320 {
16321 Lisp_Object var = XCAR (vlist);
16322
16323 if (!SYMBOLP (var))
16324 continue;
16325
16326 if (up_to_date > 0)
16327 {
16328 Lisp_Object val = find_symbol_value (var);
16329 if (!MARKERP (val))
16330 continue;
16331 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16332 Fput (var, Qlast_arrow_string,
16333 overlay_arrow_string_or_property (var));
16334 }
16335 else if (up_to_date < 0
16336 || !NILP (Fget (var, Qlast_arrow_position)))
16337 {
16338 Fput (var, Qlast_arrow_position, Qt);
16339 Fput (var, Qlast_arrow_string, Qt);
16340 }
16341 }
16342 }
16343
16344
16345
16346
16347
16348
16349 static Lisp_Object
16350 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16351 {
16352 Lisp_Object vlist;
16353
16354 for (vlist = Voverlay_arrow_variable_list;
16355 CONSP (vlist);
16356 vlist = XCDR (vlist))
16357 {
16358 Lisp_Object var = XCAR (vlist);
16359 Lisp_Object val;
16360
16361 if (!SYMBOLP (var))
16362 continue;
16363
16364 val = find_symbol_value (var);
16365
16366 if (MARKERP (val)
16367 && current_buffer == XMARKER (val)->buffer
16368 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16369 {
16370 if (FRAME_WINDOW_P (it->f)
16371
16372
16373 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16374 {
16375 #ifdef HAVE_WINDOW_SYSTEM
16376 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16377 {
16378 int fringe_bitmap = lookup_fringe_bitmap (val);
16379 if (fringe_bitmap != 0)
16380 return make_fixnum (fringe_bitmap);
16381 }
16382 #endif
16383 return make_fixnum (-1);
16384 }
16385 return overlay_arrow_string_or_property (var);
16386 }
16387 }
16388
16389 return Qnil;
16390 }
16391
16392
16393
16394
16395
16396 static bool
16397 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16398 struct buffer *buf, ptrdiff_t pt)
16399 {
16400 ptrdiff_t start, end;
16401 Lisp_Object prop;
16402 Lisp_Object buffer;
16403
16404 XSETBUFFER (buffer, buf);
16405
16406
16407 if (prev_buf == buf)
16408 {
16409 if (prev_pt == pt)
16410
16411 return false;
16412
16413 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16414 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16415 && composition_valid_p (start, end, prop)
16416 && start < prev_pt && end > prev_pt)
16417
16418
16419 return (pt <= start || pt >= end);
16420 }
16421
16422
16423 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16424 && find_composition (pt, -1, &start, &end, &prop, buffer)
16425 && composition_valid_p (start, end, prop)
16426 && start < pt && end > pt);
16427 }
16428
16429
16430
16431 static void
16432 reconsider_clip_changes (struct window *w)
16433 {
16434 struct buffer *b = XBUFFER (w->contents);
16435
16436 if (b->clip_changed
16437 && w->window_end_valid
16438 && w->current_matrix->buffer == b
16439 && w->current_matrix->zv == BUF_ZV (b)
16440 && w->current_matrix->begv == BUF_BEGV (b))
16441 b->clip_changed = false;
16442
16443
16444
16445
16446
16447 if (!b->clip_changed && w->window_end_valid)
16448 {
16449 ptrdiff_t pt = (w == XWINDOW (selected_window)
16450 ? PT : marker_position (w->pointm));
16451
16452 if ((w->current_matrix->buffer != b || pt != w->last_point)
16453 && check_point_in_composition (w->current_matrix->buffer,
16454 w->last_point, b, pt))
16455 b->clip_changed = true;
16456 }
16457 }
16458
16459 static void
16460 propagate_buffer_redisplay (void)
16461 {
16462
16463
16464
16465
16466
16467
16468
16469
16470
16471 Lisp_Object ws = window_list ();
16472 for (; CONSP (ws); ws = XCDR (ws))
16473 {
16474 struct window *thisw = XWINDOW (XCAR (ws));
16475 struct buffer *thisb = XBUFFER (thisw->contents);
16476 if (thisb->text->redisplay)
16477 thisw->redisplay = true;
16478 }
16479 }
16480
16481 #define STOP_POLLING \
16482 do { if (! polling_stopped_here) stop_polling (); \
16483 polling_stopped_here = true; } while (false)
16484
16485 #define RESUME_POLLING \
16486 do { if (polling_stopped_here) start_polling (); \
16487 polling_stopped_here = false; } while (false)
16488
16489
16490
16491
16492 static void
16493 redisplay_internal (void)
16494 {
16495 struct window *w = XWINDOW (selected_window);
16496 struct window *sw;
16497 struct frame *fr;
16498 bool pending;
16499 bool must_finish = false, match_p;
16500 struct text_pos tlbufpos, tlendpos;
16501 int number_of_visible_frames;
16502 struct frame *sf;
16503 bool polling_stopped_here = false;
16504 Lisp_Object tail, frame;
16505
16506
16507
16508
16509 enum { MAX_HSCROLL_RETRIES = 16 };
16510 int hscroll_retries = 0;
16511
16512
16513
16514
16515
16516
16517 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16518 int garbaged_frame_retries = 0;
16519
16520
16521
16522 bool consider_all_windows_p;
16523
16524
16525 bool update_miniwindow_p = false;
16526
16527 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16528
16529
16530
16531
16532 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16533 && redisplay_skip_initial_frame)
16534 || !NILP (Vinhibit_redisplay))
16535 return;
16536
16537
16538
16539
16540 fr = XFRAME (w->frame);
16541 sf = SELECTED_FRAME ();
16542
16543 if (!fr->glyphs_initialized_p)
16544 return;
16545
16546 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16547 if (popup_activated ())
16548 return;
16549 #endif
16550
16551 #if defined (HAVE_HAIKU)
16552 if (popup_activated_p)
16553 return;
16554 #endif
16555
16556
16557 if (redisplaying_p)
16558 return;
16559
16560
16561
16562 specpdl_ref count = SPECPDL_INDEX ();
16563 record_unwind_protect_void (unwind_redisplay);
16564 redisplaying_p = true;
16565 block_buffer_flips ();
16566 specbind (Qinhibit_free_realized_faces, Qnil);
16567
16568
16569 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16570
16571 FOR_EACH_FRAME (tail, frame)
16572 XFRAME (frame)->already_hscrolled_p = false;
16573
16574 reset_outermost_restrictions ();
16575
16576 retry:
16577
16578 sw = w;
16579
16580 pending = false;
16581 forget_escape_and_glyphless_faces ();
16582
16583 inhibit_free_realized_faces = false;
16584
16585
16586
16587
16588 if (face_change)
16589 windows_or_buffers_changed = 47;
16590
16591 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16592 && FRAME_TTY (sf)->previous_frame != sf)
16593 {
16594
16595
16596
16597 SET_FRAME_GARBAGED (sf);
16598 #ifndef DOS_NT
16599 set_tty_color_mode (FRAME_TTY (sf), sf);
16600 #endif
16601 FRAME_TTY (sf)->previous_frame = sf;
16602 }
16603
16604
16605
16606
16607 number_of_visible_frames = 0;
16608
16609 FOR_EACH_FRAME (tail, frame)
16610 {
16611 struct frame *f = XFRAME (frame);
16612
16613 if (FRAME_VISIBLE_P (f))
16614 {
16615 ++number_of_visible_frames;
16616
16617 if (f->fonts_changed)
16618 {
16619 adjust_frame_glyphs (f);
16620
16621
16622
16623
16624
16625
16626 SET_FRAME_GARBAGED (f);
16627 f->fonts_changed = false;
16628 }
16629
16630
16631 if (f != sf && f->cursor_type_changed)
16632 fset_redisplay (f);
16633 }
16634 clear_desired_matrices (f);
16635 }
16636
16637
16638 do_pending_window_change (true);
16639
16640
16641 clear_garbaged_frames ();
16642
16643
16644 if (NILP (Vmemory_full))
16645 prepare_menu_bars ();
16646
16647
16648
16649
16650
16651 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16652 sw = w;
16653
16654 reconsider_clip_changes (w);
16655
16656
16657 match_p = XBUFFER (w->contents) == current_buffer;
16658 if (match_p)
16659 {
16660
16661 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16662 w->update_mode_line = true;
16663
16664 if (mode_line_update_needed (w))
16665 w->update_mode_line = true;
16666
16667
16668
16669
16670 if (current_buffer->clip_changed)
16671 bset_update_mode_line (current_buffer);
16672 }
16673
16674
16675
16676
16677
16678
16679 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16680 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16681 || (message_cleared_p
16682 && minibuf_level == 0
16683
16684
16685 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16686 {
16687 echo_area_display (false);
16688
16689 if (message_cleared_p)
16690 update_miniwindow_p = true;
16691
16692 must_finish = true;
16693
16694
16695
16696
16697
16698 if (!display_last_displayed_message_p)
16699 message_cleared_p = false;
16700 }
16701 else if (EQ (selected_window, minibuf_window)
16702 && (current_buffer->clip_changed || window_outdated (w))
16703 && resize_mini_window (w, false))
16704 {
16705
16706
16707 must_finish = true;
16708
16709
16710
16711
16712 clear_garbaged_frames ();
16713 }
16714
16715 if (!NILP (Vrun_hooks))
16716 run_window_change_functions ();
16717
16718 if (windows_or_buffers_changed && !update_mode_lines)
16719
16720
16721
16722 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16723 ? REDISPLAY_SOME : 32);
16724
16725
16726
16727
16728
16729 overlay_arrows_changed_p (true);
16730
16731 consider_all_windows_p = (update_mode_lines
16732 || windows_or_buffers_changed);
16733
16734 #define AINC(a,i) \
16735 { \
16736 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16737 if (FIXNUMP (entry)) \
16738 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16739 }
16740
16741 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16742 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16743
16744
16745
16746
16747
16748 tlbufpos = this_line_start_pos;
16749 tlendpos = this_line_end_pos;
16750 if (!consider_all_windows_p
16751 && CHARPOS (tlbufpos) > 0
16752 && !w->update_mode_line
16753 && !current_buffer->clip_changed
16754 && !current_buffer->prevent_redisplay_optimizations_p
16755 && FRAME_VISIBLE_P (XFRAME (w->frame))
16756 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16757 && !XFRAME (w->frame)->cursor_type_changed
16758 && !XFRAME (w->frame)->face_change
16759
16760 && this_line_buffer == current_buffer
16761 && match_p
16762 && !w->force_start
16763 && !w->optional_new_start
16764
16765 && PT >= CHARPOS (tlbufpos)
16766 && PT <= Z - CHARPOS (tlendpos)
16767
16768
16769
16770
16771
16772
16773 && (NILP (Vdisplay_line_numbers)
16774 || EQ (Vdisplay_line_numbers, Qvisual))
16775
16776
16777 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16778 CHARPOS (tlendpos)))
16779 {
16780 if (CHARPOS (tlbufpos) > BEGV
16781 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16782 && (CHARPOS (tlbufpos) == ZV
16783 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16784
16785 goto cancel;
16786 else if (window_outdated (w) || MINI_WINDOW_P (w))
16787 {
16788
16789
16790
16791
16792
16793
16794
16795
16796
16797
16798
16799
16800
16801
16802
16803 struct it it;
16804 int line_height_before = this_line_pixel_height;
16805
16806
16807
16808 start_display (&it, w, tlbufpos);
16809
16810
16811 if (it.current_x != this_line_start_x)
16812 goto cancel;
16813
16814
16815
16816
16817 if (it.sp > 1
16818 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16819 goto cancel;
16820 redisplay_trace ("trying display optimization 1\n");
16821 w->cursor.vpos = -1;
16822 overlay_arrow_seen = false;
16823 it.vpos = this_line_vpos;
16824 it.current_y = this_line_y;
16825 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16826 display_line (&it, -1);
16827
16828
16829
16830 if (w->cursor.vpos >= 0
16831
16832
16833 && CHARPOS (this_line_start_pos)
16834
16835 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16836
16837
16838 && this_line_pixel_height == line_height_before
16839
16840
16841
16842
16843 && !hscrolling_current_line_p (w))
16844 {
16845
16846
16847 if (it.current_y < it.last_visible_y)
16848 {
16849 struct glyph_row *row
16850 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
16851 ptrdiff_t delta, delta_bytes;
16852
16853
16854
16855
16856
16857
16858 delta = (Z
16859 - CHARPOS (tlendpos)
16860 - MATRIX_ROW_START_CHARPOS (row));
16861 delta_bytes = (Z_BYTE
16862 - BYTEPOS (tlendpos)
16863 - MATRIX_ROW_START_BYTEPOS (row));
16864
16865 increment_matrix_positions (w->current_matrix,
16866 this_line_vpos + 1,
16867 w->current_matrix->nrows,
16868 delta, delta_bytes);
16869 }
16870
16871
16872
16873
16874 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
16875 {
16876 if (w->window_end_vpos < this_line_vpos)
16877 w->window_end_vpos = this_line_vpos;
16878 }
16879 else if (w->window_end_vpos == this_line_vpos
16880 && this_line_vpos > 0)
16881 w->window_end_vpos = this_line_vpos - 1;
16882 w->window_end_valid = false;
16883
16884
16885 w->desired_matrix->no_scrolling_p = true;
16886
16887 #ifdef GLYPH_DEBUG
16888 *w->desired_matrix->method = 0;
16889 debug_method_add (w, "optimization 1");
16890 #endif
16891 #ifdef HAVE_WINDOW_SYSTEM
16892 update_window_fringes (w, false);
16893 #endif
16894 goto update;
16895 }
16896 else
16897 goto cancel;
16898 }
16899 else if (
16900 PT == w->last_point
16901
16902
16903
16904
16905 && 0 <= w->cursor.vpos
16906 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
16907 {
16908 if (!must_finish)
16909 {
16910 do_pending_window_change (true);
16911
16912 if (WINDOWP (selected_window)
16913 && (w = XWINDOW (selected_window)) != sw)
16914 goto retry;
16915
16916
16917
16918 if (w->cursor_off_p == w->last_cursor_off_p)
16919 goto end_of_redisplay;
16920 }
16921 goto update;
16922 }
16923
16924
16925 else if (NILP (Vshow_trailing_whitespace)
16926 && !cursor_in_echo_area
16927 && !composition_break_at_point)
16928 {
16929 struct it it;
16930 struct glyph_row *row;
16931
16932
16933
16934
16935 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
16936 NULL, DEFAULT_FACE_ID);
16937 it.current_x = this_line_start_x;
16938 it.current_y = this_line_y;
16939 it.vpos = this_line_vpos;
16940
16941 if (current_buffer->long_line_optimizations_p
16942 && it.line_wrap == TRUNCATE
16943 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
16944 {
16945
16946
16947
16948 reseat_at_next_visible_line_start (&it, false);
16949 if (IT_CHARPOS (it) <= PT)
16950 it.vpos = this_line_vpos + 1;
16951 }
16952 else
16953 {
16954
16955
16956 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
16957 }
16958
16959 if (it.vpos == this_line_vpos
16960 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
16961 row->enabled_p))
16962 {
16963 eassert (this_line_vpos == it.vpos);
16964 eassert (this_line_y == it.current_y);
16965 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
16966 if (cursor_row_fully_visible_p (w, false, true, false))
16967 {
16968 #ifdef GLYPH_DEBUG
16969 *w->desired_matrix->method = 0;
16970 debug_method_add (w, "optimization 3");
16971 #endif
16972 goto update;
16973 }
16974 else
16975 goto cancel;
16976 }
16977 else
16978 goto cancel;
16979 }
16980
16981 cancel:
16982
16983 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
16984 }
16985
16986 CHARPOS (this_line_start_pos) = 0;
16987 ++clear_face_cache_count;
16988 #ifdef HAVE_WINDOW_SYSTEM
16989 ++clear_image_cache_count;
16990 #endif
16991
16992
16993
16994
16995
16996
16997 if (consider_all_windows_p)
16998 {
16999 FOR_EACH_FRAME (tail, frame)
17000 XFRAME (frame)->updated_p = false;
17001
17002 propagate_buffer_redisplay ();
17003
17004 FOR_EACH_FRAME (tail, frame)
17005 {
17006 struct frame *f = XFRAME (frame);
17007
17008
17009
17010 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
17011 && !EQ (FRAME_TTY (f)->top_frame, frame))
17012 continue;
17013
17014 retry_frame:
17015 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
17016 {
17017 bool gcscrollbars
17018
17019 = f->redisplay || !REDISPLAY_SOME_P ();
17020 bool f_redisplay_flag = f->redisplay;
17021
17022
17023
17024
17025 if (!FRAME_LIVE_P (f))
17026 continue;
17027
17028
17029
17030 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
17031 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
17032
17033 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
17034 {
17035
17036
17037
17038
17039
17040
17041
17042 f->inhibit_clear_image_cache = true;
17043 redisplay_windows (FRAME_ROOT_WINDOW (f));
17044 }
17045
17046
17047 else if (!REDISPLAY_SOME_P ())
17048 f->redisplay = true;
17049
17050
17051 if (!FRAME_LIVE_P (f))
17052 continue;
17053
17054
17055
17056 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17057 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17058
17059 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
17060 {
17061
17062 if (f->fonts_changed)
17063 {
17064 adjust_frame_glyphs (f);
17065
17066
17067
17068 SET_FRAME_GARBAGED (f);
17069 f->fonts_changed = false;
17070 goto retry_frame;
17071 }
17072
17073
17074 if (!f->already_hscrolled_p)
17075 {
17076 f->already_hscrolled_p = true;
17077 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17078 && hscroll_windows (f->root_window))
17079 {
17080 hscroll_retries++;
17081 goto retry_frame;
17082 }
17083 }
17084
17085
17086
17087
17088
17089
17090
17091
17092
17093
17094
17095
17096 if (!f_redisplay_flag && f->redisplay)
17097 goto retry_frame;
17098
17099
17100
17101
17102
17103
17104
17105
17106
17107 if (FRAME_GARBAGED_P (f)
17108 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17109 goto retry;
17110
17111 #ifdef HAVE_WINDOW_SYSTEM
17112 if (FRAME_WINDOW_P (f)
17113 && FRAME_RIF (f)->clear_under_internal_border)
17114 FRAME_RIF (f)->clear_under_internal_border (f);
17115 #endif
17116
17117
17118
17119 if (interrupt_input)
17120 unrequest_sigio ();
17121 STOP_POLLING;
17122
17123 pending |= update_frame (f, false, false);
17124
17125
17126
17127
17128
17129
17130
17131 if (FRAME_GARBAGED_P (f))
17132 {
17133 fset_redisplay (f);
17134 f->garbaged = false;
17135 goto retry_frame;
17136 }
17137 f->cursor_type_changed = false;
17138 f->updated_p = true;
17139 f->inhibit_clear_image_cache = false;
17140 }
17141 }
17142 }
17143
17144 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17145
17146 if (!pending)
17147 {
17148
17149
17150
17151 FOR_EACH_FRAME (tail, frame)
17152 {
17153 struct frame *f = XFRAME (frame);
17154 if (f->updated_p)
17155 {
17156 f->redisplay = false;
17157 f->garbaged = false;
17158 mark_window_display_accurate (f->root_window, true);
17159 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17160 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17161 }
17162 }
17163 }
17164 }
17165 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
17166 {
17167 sf->inhibit_clear_image_cache = true;
17168 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17169
17170
17171 internal_condition_case_1 (redisplay_window_1, selected_window,
17172 list_of_error,
17173 redisplay_window_error);
17174 if (update_miniwindow_p)
17175 {
17176 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17177
17178 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17179 internal_condition_case_1 (redisplay_window_1, mini_window,
17180 list_of_error,
17181 redisplay_window_error);
17182 }
17183
17184
17185
17186 update:
17187
17188
17189
17190 if (sf->fonts_changed || sf->redisplay)
17191 {
17192 if (sf->redisplay)
17193 {
17194
17195
17196
17197
17198
17199
17200 windows_or_buffers_changed = 50;
17201 }
17202 goto retry;
17203 }
17204
17205
17206
17207 inhibit_free_realized_faces = true;
17208
17209
17210
17211
17212 if (interrupt_input)
17213 unrequest_sigio ();
17214 STOP_POLLING;
17215
17216 if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
17217 {
17218 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17219 && hscroll_windows (selected_window))
17220 {
17221 hscroll_retries++;
17222 goto retry;
17223 }
17224
17225 XWINDOW (selected_window)->must_be_updated_p = true;
17226 pending = update_frame (sf, false, false);
17227 sf->cursor_type_changed = false;
17228 sf->inhibit_clear_image_cache = false;
17229 }
17230
17231
17232
17233
17234
17235
17236 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17237 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17238
17239 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17240 {
17241 XWINDOW (mini_window)->must_be_updated_p = true;
17242 pending |= update_frame (mini_frame, false, false);
17243 mini_frame->cursor_type_changed = false;
17244 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17245 && hscroll_windows (mini_window))
17246 {
17247 hscroll_retries++;
17248 goto retry;
17249 }
17250 }
17251 }
17252
17253
17254
17255 if (pending)
17256 {
17257
17258
17259
17260 CHARPOS (this_line_start_pos) = 0;
17261
17262
17263 update_overlay_arrows (0);
17264
17265
17266
17267 if (!WINDOW_FULL_WIDTH_P (w)
17268 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17269 update_mode_lines = 36;
17270 }
17271 else
17272 {
17273 if (!consider_all_windows_p)
17274 {
17275
17276
17277 if (XBUFFER (w->contents)->text->redisplay
17278 && buffer_window_count (XBUFFER (w->contents)) > 1)
17279
17280
17281 propagate_buffer_redisplay ();
17282 mark_window_display_accurate_1 (w, true);
17283
17284
17285 update_overlay_arrows (1);
17286
17287 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17288 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17289 }
17290
17291 update_mode_lines = 0;
17292 windows_or_buffers_changed = 0;
17293 }
17294
17295
17296
17297
17298
17299 if (interrupt_input)
17300 request_sigio ();
17301 RESUME_POLLING;
17302
17303
17304
17305
17306
17307
17308
17309 if (!pending)
17310 {
17311 int new_count = 0;
17312
17313 FOR_EACH_FRAME (tail, frame)
17314 {
17315 if (XFRAME (frame)->visible)
17316 new_count++;
17317 }
17318
17319 if (new_count != number_of_visible_frames)
17320 windows_or_buffers_changed = 52;
17321 }
17322
17323
17324 do_pending_window_change (true);
17325
17326
17327
17328 if ((windows_or_buffers_changed && !pending)
17329 || (WINDOWP (selected_window)
17330 && (w = XWINDOW (selected_window)) != sw))
17331 goto retry;
17332
17333
17334
17335
17336
17337
17338
17339 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17340 {
17341 clear_face_cache (false);
17342 clear_face_cache_count = 0;
17343 }
17344
17345 #ifdef HAVE_WINDOW_SYSTEM
17346 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17347 {
17348 clear_image_caches (Qnil);
17349 clear_image_cache_count = 0;
17350 }
17351 #endif
17352
17353 end_of_redisplay:
17354 #ifdef HAVE_NS
17355 ns_set_doc_edited ();
17356 #endif
17357 if (interrupt_input && interrupts_deferred)
17358 request_sigio ();
17359
17360
17361
17362 if (max_redisplay_ticks > 0)
17363 update_redisplay_ticks (0, NULL);
17364
17365 unbind_to (count, Qnil);
17366 RESUME_POLLING;
17367 }
17368
17369 static void
17370 unwind_redisplay_preserve_echo_area (void)
17371 {
17372 unblock_buffer_flips ();
17373 }
17374
17375
17376
17377
17378
17379
17380
17381
17382
17383
17384
17385
17386 void
17387 redisplay_preserve_echo_area (int from_where)
17388 {
17389 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17390
17391 block_input ();
17392 specpdl_ref count = SPECPDL_INDEX ();
17393 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17394 block_buffer_flips ();
17395 unblock_input ();
17396
17397 if (!NILP (echo_area_buffer[1]))
17398 {
17399
17400
17401 display_last_displayed_message_p = true;
17402 redisplay_internal ();
17403 display_last_displayed_message_p = false;
17404 }
17405 else
17406 redisplay_internal ();
17407
17408 flush_frame (SELECTED_FRAME ());
17409 unbind_to (count, Qnil);
17410 }
17411
17412
17413
17414
17415 static void
17416 unwind_redisplay (void)
17417 {
17418 redisplaying_p = false;
17419 unblock_buffer_flips ();
17420 }
17421
17422
17423
17424 void
17425 unwind_display_working_on_window (void)
17426 {
17427 display_working_on_window_p = false;
17428 }
17429
17430
17431
17432
17433
17434
17435 static void
17436 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17437 {
17438 struct buffer *b = XBUFFER (w->contents);
17439
17440 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17441 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17442 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17443
17444 if (accurate_p)
17445 {
17446 b->clip_changed = false;
17447 b->prevent_redisplay_optimizations_p = false;
17448 eassert (buffer_window_count (b) > 0);
17449
17450
17451
17452 b->text->redisplay = false;
17453
17454 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17455 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17456 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17457 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17458
17459 w->current_matrix->buffer = b;
17460 w->current_matrix->begv = BUF_BEGV (b);
17461 w->current_matrix->zv = BUF_ZV (b);
17462 w->current_matrix->header_line_p = window_wants_header_line (w);
17463 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17464
17465 w->last_cursor_vpos = w->cursor.vpos;
17466 w->last_cursor_off_p = w->cursor_off_p;
17467
17468 if (w == XWINDOW (selected_window))
17469 w->last_point = BUF_PT (b);
17470 else
17471 w->last_point = marker_position (w->pointm);
17472
17473 w->window_end_valid = true;
17474 w->update_mode_line = false;
17475 w->preserve_vscroll_p = false;
17476 }
17477
17478 w->redisplay = !accurate_p;
17479 }
17480
17481
17482
17483
17484
17485
17486
17487 void
17488 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17489 {
17490 struct window *w;
17491
17492 for (; !NILP (window); window = w->next)
17493 {
17494 w = XWINDOW (window);
17495 if (WINDOWP (w->contents))
17496 mark_window_display_accurate (w->contents, accurate_p);
17497 else
17498 mark_window_display_accurate_1 (w, accurate_p);
17499 }
17500
17501 if (accurate_p)
17502 update_overlay_arrows (1);
17503 else
17504
17505
17506
17507 update_overlay_arrows (-1);
17508 }
17509
17510
17511
17512
17513
17514
17515
17516 Lisp_Object
17517 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17518 {
17519 Lisp_Object val;
17520
17521 if (ASCII_CHAR_P (c))
17522 {
17523 val = dp->ascii;
17524 if (SUB_CHAR_TABLE_P (val))
17525 val = XSUB_CHAR_TABLE (val)->contents[c];
17526 }
17527 else
17528 {
17529 Lisp_Object table;
17530
17531 XSETCHAR_TABLE (table, dp);
17532 val = char_table_ref (table, c);
17533 }
17534 if (NILP (val))
17535 val = dp->defalt;
17536 return val;
17537 }
17538
17539 static int buffer_flip_blocked_depth;
17540
17541 static void
17542 block_buffer_flips (void)
17543 {
17544 eassert (buffer_flip_blocked_depth >= 0);
17545 buffer_flip_blocked_depth++;
17546 }
17547
17548 static void
17549 unblock_buffer_flips (void)
17550 {
17551 eassert (buffer_flip_blocked_depth > 0);
17552 if (--buffer_flip_blocked_depth == 0)
17553 {
17554 Lisp_Object tail, frame;
17555 block_input ();
17556 FOR_EACH_FRAME (tail, frame)
17557 {
17558 struct frame *f = XFRAME (frame);
17559 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17560 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17561 }
17562 unblock_input ();
17563 }
17564 }
17565
17566 bool
17567 buffer_flipping_blocked_p (void)
17568 {
17569 return buffer_flip_blocked_depth > 0;
17570 }
17571
17572
17573
17574
17575
17576
17577
17578
17579 static void
17580 redisplay_windows (Lisp_Object window)
17581 {
17582 while (!NILP (window))
17583 {
17584 struct window *w = XWINDOW (window);
17585
17586 if (WINDOWP (w->contents))
17587 redisplay_windows (w->contents);
17588 else if (BUFFERP (w->contents))
17589 {
17590 displayed_buffer = XBUFFER (w->contents);
17591
17592
17593 internal_condition_case_1 (redisplay_window_0, window,
17594 list_of_error,
17595 redisplay_window_error);
17596 }
17597
17598 window = w->next;
17599 }
17600 }
17601
17602 static Lisp_Object
17603 redisplay_window_error (Lisp_Object error_data)
17604 {
17605 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17606
17607
17608
17609 if (max_redisplay_ticks > 0
17610 && CONSP (error_data)
17611 && EQ (XCAR (error_data), Qerror)
17612 && CONSP (XCDR (error_data))
17613 && STRINGP (XCAR (XCDR (error_data))))
17614 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17615 XCAR (XCDR (error_data))),
17616 Vdelayed_warnings_list);
17617 return Qnil;
17618 }
17619
17620 static Lisp_Object
17621 redisplay_window_0 (Lisp_Object window)
17622 {
17623 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17624 redisplay_window (window, false);
17625 return Qnil;
17626 }
17627
17628 static Lisp_Object
17629 redisplay_window_1 (Lisp_Object window)
17630 {
17631 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17632 redisplay_window (window, true);
17633 return Qnil;
17634 }
17635
17636
17637
17638
17639
17640
17641
17642
17643
17644
17645
17646
17647
17648
17649
17650
17651
17652
17653
17654 void
17655 update_redisplay_ticks (int ticks, struct window *w)
17656 {
17657
17658 static struct window *cwindow;
17659 static EMACS_INT window_ticks;
17660
17661
17662
17663
17664 if (!ticks && w != cwindow)
17665 {
17666 cwindow = w;
17667 window_ticks = 0;
17668 }
17669
17670
17671 if ((!w && !redisplaying_p && !display_working_on_window_p)
17672
17673
17674 || (w && MINI_WINDOW_P (w)))
17675 return;
17676
17677 if (ticks > 0)
17678 window_ticks += ticks;
17679 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17680 {
17681
17682
17683
17684 Lisp_Object contents = w ? w->contents : Qnil;
17685 char *bufname =
17686 NILP (contents)
17687 ? SSDATA (BVAR (current_buffer, name))
17688 : (BUFFERP (contents)
17689 ? SSDATA (BVAR (XBUFFER (contents), name))
17690 : (char *) "<unknown>");
17691
17692 windows_or_buffers_changed = 177;
17693
17694
17695
17696 if (w && w->desired_matrix)
17697 w->desired_matrix->no_scrolling_p = true;
17698 error ("Window showing buffer %s takes too long to redisplay", bufname);
17699 }
17700 }
17701
17702
17703
17704
17705
17706
17707
17708
17709
17710
17711 static bool
17712 set_cursor_from_row (struct window *w, struct glyph_row *row,
17713 struct glyph_matrix *matrix,
17714 ptrdiff_t delta, ptrdiff_t delta_bytes,
17715 int dy, int dvpos)
17716 {
17717 struct glyph *glyph = row->glyphs[TEXT_AREA];
17718 struct glyph *end = glyph + row->used[TEXT_AREA];
17719 struct glyph *cursor = NULL;
17720
17721 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17722 int x = row->x;
17723 ptrdiff_t pt_old = PT - delta;
17724 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17725 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17726 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17727
17728
17729 struct glyph *glyphs_end = end;
17730
17731
17732 bool match_with_avoid_cursor = false;
17733
17734
17735 bool string_seen = false;
17736
17737
17738 ptrdiff_t bpos_max = pos_before;
17739 ptrdiff_t bpos_min = pos_after;
17740
17741
17742 ptrdiff_t bpos_covered = 0;
17743
17744
17745 bool string_from_text_prop = false;
17746
17747
17748
17749
17750 eassert (!row->mode_line_p);
17751 if (row->mode_line_p)
17752 return false;
17753
17754
17755
17756
17757 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17758 {
17759 if (!row->reversed_p)
17760 {
17761 while (glyph < end
17762 && NILP (glyph->object)
17763 && glyph->charpos < 0)
17764 {
17765 x += glyph->pixel_width;
17766 ++glyph;
17767 }
17768 while (end > glyph
17769 && NILP ((end - 1)->object)
17770
17771
17772 && (end - 1)->charpos <= 0)
17773 --end;
17774 glyph_before = glyph - 1;
17775 glyph_after = end;
17776 }
17777 else
17778 {
17779 struct glyph *g;
17780
17781
17782
17783 glyphs_end = end = glyph - 1;
17784 glyph += row->used[TEXT_AREA] - 1;
17785
17786 while (glyph > end + 1
17787 && NILP (glyph->object)
17788 && glyph->charpos < 0)
17789 --glyph;
17790 if (NILP (glyph->object) && glyph->charpos < 0)
17791 --glyph;
17792
17793
17794 for (x = 0, g = end + 1; g < glyph; g++)
17795 x += g->pixel_width;
17796 while (end < glyph
17797 && NILP ((end + 1)->object)
17798 && (end + 1)->charpos <= 0)
17799 ++end;
17800 glyph_before = glyph + 1;
17801 glyph_after = end;
17802 }
17803 }
17804 else if (row->reversed_p)
17805 {
17806
17807
17808
17809 cursor = end - 1;
17810
17811
17812
17813 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
17814 && !WINDOW_RIGHTMOST_P (w)
17815 && cursor == row->glyphs[LAST_AREA] - 1)
17816 cursor--;
17817 x = -1;
17818 }
17819
17820
17821
17822
17823
17824 if (!row->reversed_p)
17825 while (
17826 glyph < end
17827
17828 && !NILP (glyph->object))
17829 {
17830 if (BUFFERP (glyph->object))
17831 {
17832 ptrdiff_t dpos = glyph->charpos - pt_old;
17833
17834 if (glyph->charpos > bpos_max)
17835 bpos_max = glyph->charpos;
17836 if (glyph->charpos < bpos_min)
17837 bpos_min = glyph->charpos;
17838 if (!glyph->avoid_cursor_p)
17839 {
17840
17841
17842 if (dpos == 0)
17843 {
17844 match_with_avoid_cursor = false;
17845 break;
17846 }
17847
17848
17849 if (0 > dpos && dpos > pos_before - pt_old)
17850 {
17851 pos_before = glyph->charpos;
17852 glyph_before = glyph;
17853 }
17854 else if (0 < dpos && dpos < pos_after - pt_old)
17855 {
17856 pos_after = glyph->charpos;
17857 glyph_after = glyph;
17858 }
17859 }
17860 else if (dpos == 0)
17861 match_with_avoid_cursor = true;
17862 }
17863 else if (STRINGP (glyph->object))
17864 {
17865 Lisp_Object chprop;
17866 ptrdiff_t glyph_pos = glyph->charpos;
17867
17868 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
17869 glyph->object);
17870 if (!NILP (chprop))
17871 {
17872
17873
17874
17875
17876
17877
17878
17879
17880
17881
17882 ptrdiff_t prop_pos =
17883 string_buffer_position_lim (glyph->object, pos_before,
17884 pos_after, false);
17885
17886 if (prop_pos >= pos_before)
17887 bpos_max = prop_pos;
17888 }
17889 if (FIXNUMP (chprop))
17890 {
17891 bpos_covered = bpos_max + XFIXNUM (chprop);
17892
17893
17894
17895
17896
17897
17898
17899
17900
17901
17902
17903 if (bpos_max <= pt_old && bpos_covered >= pt_old)
17904 {
17905 cursor = glyph;
17906 break;
17907 }
17908 }
17909
17910 string_seen = true;
17911 }
17912 x += glyph->pixel_width;
17913 ++glyph;
17914 }
17915 else if (glyph > end)
17916 while (!NILP (glyph->object))
17917 {
17918 if (BUFFERP (glyph->object))
17919 {
17920 ptrdiff_t dpos = glyph->charpos - pt_old;
17921
17922 if (glyph->charpos > bpos_max)
17923 bpos_max = glyph->charpos;
17924 if (glyph->charpos < bpos_min)
17925 bpos_min = glyph->charpos;
17926 if (!glyph->avoid_cursor_p)
17927 {
17928 if (dpos == 0)
17929 {
17930 match_with_avoid_cursor = false;
17931 break;
17932 }
17933 if (0 > dpos && dpos > pos_before - pt_old)
17934 {
17935 pos_before = glyph->charpos;
17936 glyph_before = glyph;
17937 }
17938 else if (0 < dpos && dpos < pos_after - pt_old)
17939 {
17940 pos_after = glyph->charpos;
17941 glyph_after = glyph;
17942 }
17943 }
17944 else if (dpos == 0)
17945 match_with_avoid_cursor = true;
17946 }
17947 else if (STRINGP (glyph->object))
17948 {
17949 Lisp_Object chprop;
17950 ptrdiff_t glyph_pos = glyph->charpos;
17951
17952 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
17953 glyph->object);
17954 if (!NILP (chprop))
17955 {
17956 ptrdiff_t prop_pos =
17957 string_buffer_position_lim (glyph->object, pos_before,
17958 pos_after, false);
17959
17960 if (prop_pos >= pos_before)
17961 bpos_max = prop_pos;
17962 }
17963 if (FIXNUMP (chprop))
17964 {
17965 bpos_covered = bpos_max + XFIXNUM (chprop);
17966
17967
17968
17969 if (bpos_max <= pt_old && bpos_covered >= pt_old)
17970 {
17971 cursor = glyph;
17972 break;
17973 }
17974 }
17975 string_seen = true;
17976 }
17977 --glyph;
17978 if (glyph == glyphs_end)
17979 {
17980 x--;
17981 break;
17982 }
17983 x -= glyph->pixel_width;
17984 }
17985
17986
17987
17988
17989 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
17990 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
17991 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
17992 {
17993
17994
17995
17996
17997
17998 bool empty_line_p =
17999 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18000 && NILP (glyph->object) && glyph->charpos > 0
18001
18002
18003
18004
18005 && !(row->continued_p || row->truncated_on_right_p));
18006
18007 if (row->ends_in_ellipsis_p && pos_after == last_pos)
18008 {
18009 ptrdiff_t ellipsis_pos;
18010
18011
18012 if (!row->reversed_p)
18013 {
18014 ellipsis_pos = (glyph - 1)->charpos;
18015 while (glyph > row->glyphs[TEXT_AREA]
18016 && (glyph - 1)->charpos == ellipsis_pos)
18017 glyph--, x -= glyph->pixel_width;
18018
18019
18020
18021 x += glyph->pixel_width;
18022 glyph++;
18023 }
18024 else
18025 {
18026 ellipsis_pos = (glyph + 1)->charpos;
18027 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18028 && (glyph + 1)->charpos == ellipsis_pos)
18029 glyph++, x += glyph->pixel_width;
18030 x -= glyph->pixel_width;
18031 glyph--;
18032 }
18033 }
18034 else if (match_with_avoid_cursor)
18035 {
18036 cursor = glyph_after;
18037 x = -1;
18038 }
18039 else if (string_seen)
18040 {
18041 int incr = row->reversed_p ? -1 : +1;
18042
18043
18044
18045
18046
18047
18048 struct glyph *start, *stop;
18049 ptrdiff_t pos = pos_before;
18050
18051 x = -1;
18052
18053
18054
18055
18056
18057
18058 if (row->ends_in_newline_from_string_p)
18059 {
18060 glyph_after = end;
18061 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18062 }
18063
18064
18065
18066
18067
18068
18069
18070
18071
18072 if (!row->reversed_p)
18073 {
18074 start = min (glyph_before, glyph_after);
18075 stop = max (glyph_before, glyph_after);
18076 }
18077 else
18078 {
18079 start = max (glyph_before, glyph_after);
18080 stop = min (glyph_before, glyph_after);
18081 }
18082 for (glyph = start + incr;
18083 row->reversed_p ? glyph > stop : glyph < stop; )
18084 {
18085
18086
18087
18088
18089 if (STRINGP (glyph->object))
18090 {
18091 Lisp_Object str;
18092 ptrdiff_t tem;
18093
18094
18095 ptrdiff_t lim = pos_after
18096 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18097
18098 string_from_text_prop = false;
18099 str = glyph->object;
18100 tem = string_buffer_position_lim (str, pos, lim, false);
18101 if (tem == 0
18102 || pos <= tem)
18103 {
18104
18105
18106
18107
18108
18109
18110
18111
18112
18113
18114 if (tem == 0
18115 || tem == pt_old
18116 || (tem - pt_old > 0 && tem < pos_after))
18117 {
18118
18119
18120
18121
18122
18123
18124 ptrdiff_t strpos = glyph->charpos;
18125
18126 if (tem)
18127 {
18128 cursor = glyph;
18129 string_from_text_prop = true;
18130 }
18131 for ( ;
18132 (row->reversed_p ? glyph > stop : glyph < stop)
18133 && EQ (glyph->object, str);
18134 glyph += incr)
18135 {
18136 Lisp_Object cprop;
18137 ptrdiff_t gpos = glyph->charpos;
18138
18139 cprop = Fget_char_property (make_fixnum (gpos),
18140 Qcursor,
18141 glyph->object);
18142 if (!NILP (cprop))
18143 {
18144 cursor = glyph;
18145 break;
18146 }
18147 if (tem && glyph->charpos < strpos)
18148 {
18149 strpos = glyph->charpos;
18150 cursor = glyph;
18151 }
18152 }
18153
18154 if (tem == pt_old
18155 || (tem - pt_old > 0 && tem < pos_after))
18156 goto compute_x;
18157 }
18158 if (tem)
18159 pos = tem + 1;
18160 }
18161
18162
18163 while ((row->reversed_p ? glyph > stop : glyph < stop)
18164 && EQ (glyph->object, str))
18165 glyph += incr;
18166 }
18167 else
18168 glyph += incr;
18169 }
18170
18171
18172
18173 if (cursor == NULL
18174 && (row->reversed_p ? glyph <= end : glyph >= end)
18175 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18176 && STRINGP (end->object)
18177 && row->continued_p)
18178 return false;
18179 }
18180
18181
18182
18183
18184
18185 else if (row->truncated_on_left_p && pt_old < bpos_min)
18186 {
18187 cursor = glyph_before;
18188 x = -1;
18189 }
18190 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18191
18192 || (!empty_line_p
18193 && (row->reversed_p
18194 ? glyph_after > glyphs_end
18195 : glyph_after < glyphs_end)))
18196 {
18197 cursor = glyph_after;
18198 x = -1;
18199 }
18200 }
18201
18202 compute_x:
18203 if (cursor != NULL)
18204 glyph = cursor;
18205 else if (glyph == glyphs_end
18206 && pos_before == pos_after
18207 && STRINGP ((row->reversed_p
18208 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18209 : row->glyphs[TEXT_AREA])->object))
18210 {
18211
18212
18213
18214
18215 glyph =
18216 row->reversed_p
18217 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18218 : row->glyphs[TEXT_AREA];
18219 }
18220 if (x < 0)
18221 {
18222 struct glyph *g;
18223
18224
18225 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18226 {
18227 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18228 emacs_abort ();
18229 x += g->pixel_width;
18230 }
18231 }
18232
18233
18234
18235
18236
18237
18238 if (
18239 w->cursor.vpos >= 0
18240
18241 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18242
18243
18244
18245
18246
18247 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18248 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18249 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18250 {
18251 struct glyph *g1
18252 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18253
18254
18255 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18256 return false;
18257
18258
18259 if (
18260 w->cursor.hpos >= 0
18261 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18262 && ((BUFFERP (g1->object)
18263 && (g1->charpos == pt_old
18264 || (BUFFERP (glyph->object)
18265 && eabs (g1->charpos - pt_old)
18266 < eabs (glyph->charpos - pt_old))))
18267
18268
18269 || (STRINGP (g1->object)
18270 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18271 Qcursor, g1->object))
18272
18273
18274
18275 || (EQ (g1->object, glyph->object)
18276 && string_from_text_prop)
18277
18278
18279 || (NILP (glyph->object)
18280 && glyph->charpos != pt_old)))))
18281 return false;
18282
18283 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18284
18285
18286
18287 || (!row->continued_p
18288 && NILP (glyph->object)
18289 && glyph->charpos == 0
18290 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18291
18292
18293
18294
18295
18296 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18297 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18298 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18299 return false;
18300 }
18301 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18302 w->cursor.x = x;
18303 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18304 w->cursor.y = row->y + dy;
18305
18306 if (w == XWINDOW (selected_window))
18307 {
18308 if (!row->continued_p
18309 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18310 && row->x == 0)
18311 {
18312 this_line_buffer = XBUFFER (w->contents);
18313
18314 CHARPOS (this_line_start_pos)
18315 = MATRIX_ROW_START_CHARPOS (row) + delta;
18316 BYTEPOS (this_line_start_pos)
18317 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18318
18319 CHARPOS (this_line_end_pos)
18320 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18321 BYTEPOS (this_line_end_pos)
18322 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18323
18324 this_line_y = w->cursor.y;
18325 this_line_pixel_height = row->height;
18326 this_line_vpos = w->cursor.vpos;
18327 this_line_start_x = row->x;
18328 }
18329 else
18330 CHARPOS (this_line_start_pos) = 0;
18331 }
18332
18333 return true;
18334 }
18335
18336
18337
18338
18339
18340
18341
18342 static struct text_pos
18343 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18344 {
18345 struct window *w = XWINDOW (window);
18346 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18347
18348 eassert (current_buffer == XBUFFER (w->contents));
18349
18350 if (!NILP (Vwindow_scroll_functions))
18351 {
18352 specpdl_ref count = SPECPDL_INDEX ();
18353 specbind (Qinhibit_quit, Qt);
18354 safe_run_hooks_2
18355 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18356 unbind_to (count, Qnil);
18357 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18358
18359 set_buffer_internal (XBUFFER (w->contents));
18360 }
18361
18362 return startp;
18363 }
18364
18365
18366
18367
18368
18369
18370
18371
18372
18373
18374
18375
18376
18377
18378
18379
18380
18381
18382
18383
18384
18385
18386 static bool
18387 cursor_row_fully_visible_p (struct window *w, bool force_p,
18388 bool current_matrix_p,
18389 bool just_test_user_preference_p)
18390 {
18391 struct glyph_matrix *matrix;
18392 struct glyph_row *row;
18393 int window_height;
18394 Lisp_Object mclfv_p =
18395 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18396
18397
18398 if (BASE_EQ (mclfv_p, Qunbound))
18399 mclfv_p = Vmake_cursor_line_fully_visible;
18400
18401
18402 if (FUNCTIONP (mclfv_p))
18403 {
18404 Lisp_Object window;
18405 XSETWINDOW (window, w);
18406
18407
18408 Lisp_Object val = safe_call1 (mclfv_p, window);
18409 if (NILP (val))
18410 return true;
18411 else if (just_test_user_preference_p)
18412 return false;
18413 }
18414 else if (NILP (mclfv_p))
18415 return true;
18416 else if (just_test_user_preference_p)
18417 return false;
18418
18419
18420
18421 if (w->cursor.vpos < 0)
18422 return true;
18423
18424 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18425 row = MATRIX_ROW (matrix, w->cursor.vpos);
18426
18427
18428 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18429 return true;
18430
18431
18432
18433 window_height = window_box_height (w);
18434 if (row->height >= window_height)
18435 {
18436 if (!force_p || MINI_WINDOW_P (w)
18437 || w->vscroll || w->cursor.vpos == 0)
18438 return true;
18439 }
18440 return false;
18441 }
18442
18443
18444
18445
18446
18447
18448
18449
18450
18451
18452
18453
18454
18455
18456
18457
18458
18459
18460
18461
18462 enum
18463 {
18464 SCROLLING_SUCCESS = 1,
18465 SCROLLING_FAILED = 0,
18466 SCROLLING_NEED_LARGER_MATRICES = -1
18467 };
18468
18469
18470
18471
18472
18473 #define SCROLL_LIMIT 100
18474
18475 static int
18476 try_scrolling (Lisp_Object window, bool just_this_one_p,
18477 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18478 bool temp_scroll_step, bool last_line_misfit)
18479 {
18480 struct window *w = XWINDOW (window);
18481 struct text_pos pos, startp;
18482 struct it it;
18483 int this_scroll_margin, scroll_max, rc, height;
18484 int dy = 0, amount_to_scroll = 0;
18485 bool scroll_down_p = false;
18486 int extra_scroll_margin_lines = last_line_misfit;
18487 Lisp_Object aggressive;
18488
18489 int scroll_limit = SCROLL_LIMIT;
18490 int frame_line_height = default_line_pixel_height (w);
18491
18492 #ifdef GLYPH_DEBUG
18493 debug_method_add (w, "try_scrolling");
18494 #endif
18495
18496 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18497
18498 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18499
18500
18501
18502
18503
18504 if (arg_scroll_conservatively > scroll_limit)
18505 {
18506 arg_scroll_conservatively = scroll_limit + 1;
18507 scroll_max = scroll_limit * frame_line_height;
18508 }
18509 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18510
18511
18512 {
18513 intmax_t scroll_lines_max
18514 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18515 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18516 scroll_max = scroll_lines * frame_line_height;
18517 }
18518 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18519 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18520
18521
18522 scroll_max = 10 * frame_line_height;
18523 else
18524 scroll_max = 0;
18525
18526 too_near_end:
18527
18528
18529 if (PT > CHARPOS (startp))
18530 {
18531 int scroll_margin_y;
18532
18533
18534
18535 start_display (&it, w, startp);
18536 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18537 - this_scroll_margin
18538 - frame_line_height * extra_scroll_margin_lines;
18539 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18540 (MOVE_TO_POS | MOVE_TO_Y));
18541
18542 if (PT > CHARPOS (it.current.pos))
18543 {
18544 int y0 = line_bottom_y (&it);
18545
18546
18547
18548
18549
18550 int slack = max (scroll_max, 10 * frame_line_height);
18551 int y_to_move = it.last_visible_y + slack;
18552
18553
18554
18555
18556
18557 move_it_to (&it, PT, -1, y_to_move,
18558 -1, MOVE_TO_POS | MOVE_TO_Y);
18559 dy = line_bottom_y (&it) - y0;
18560
18561 if (dy > scroll_max)
18562 return SCROLLING_FAILED;
18563
18564 if (dy > 0)
18565 scroll_down_p = true;
18566 }
18567 else if (PT == IT_CHARPOS (it)
18568 && IT_CHARPOS (it) < ZV
18569 && it.method == GET_FROM_STRING
18570 && arg_scroll_conservatively > scroll_limit
18571 && it.current_x == 0)
18572 {
18573 enum move_it_result skip;
18574 int y1 = it.current_y;
18575 int vpos;
18576
18577
18578
18579
18580
18581
18582
18583 do {
18584 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18585 if (skip != MOVE_NEWLINE_OR_CR
18586 || IT_CHARPOS (it) != PT
18587 || it.method == GET_FROM_BUFFER)
18588 break;
18589 vpos = it.vpos;
18590 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18591 } while (it.vpos > vpos);
18592
18593 dy = it.current_y - y1;
18594
18595 if (dy > scroll_max)
18596 return SCROLLING_FAILED;
18597
18598 if (dy > 0)
18599 scroll_down_p = true;
18600 }
18601 }
18602
18603 if (scroll_down_p)
18604 {
18605
18606
18607
18608
18609 if (arg_scroll_conservatively)
18610 amount_to_scroll
18611 = min (max (dy, frame_line_height),
18612 frame_line_height * arg_scroll_conservatively);
18613 else if (scroll_step || temp_scroll_step)
18614 amount_to_scroll = scroll_max;
18615 else
18616 {
18617 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18618 height = WINDOW_BOX_TEXT_HEIGHT (w);
18619 if (NUMBERP (aggressive))
18620 {
18621 double float_amount = XFLOATINT (aggressive) * height;
18622 int aggressive_scroll = float_amount;
18623 if (aggressive_scroll == 0 && float_amount > 0)
18624 aggressive_scroll = 1;
18625
18626
18627
18628
18629
18630
18631 if (aggressive_scroll + 2 * this_scroll_margin > height)
18632 aggressive_scroll = height - 2 * this_scroll_margin;
18633 amount_to_scroll = dy + aggressive_scroll;
18634 }
18635 }
18636
18637 if (amount_to_scroll <= 0)
18638 return SCROLLING_FAILED;
18639
18640 start_display (&it, w, startp);
18641 if (arg_scroll_conservatively <= scroll_limit)
18642 move_it_vertically (&it, amount_to_scroll);
18643 else
18644 {
18645
18646
18647
18648
18649
18650
18651 struct it it1;
18652 void *it1data = NULL;
18653
18654
18655 int start_y;
18656
18657 SAVE_IT (it1, it, it1data);
18658 start_y = line_bottom_y (&it1);
18659 do {
18660 RESTORE_IT (&it, &it, it1data);
18661 move_it_by_lines (&it, 1);
18662 SAVE_IT (it1, it, it1data);
18663 } while (IT_CHARPOS (it) < ZV
18664 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18665 bidi_unshelve_cache (it1data, true);
18666 }
18667
18668
18669 if (IT_CHARPOS (it) == CHARPOS (startp))
18670 move_it_by_lines (&it, 1);
18671 startp = it.current.pos;
18672 }
18673 else
18674 {
18675 struct text_pos scroll_margin_pos = startp;
18676 int y_offset = 0;
18677
18678
18679
18680 if (this_scroll_margin)
18681 {
18682 int y_start;
18683
18684 start_display (&it, w, startp);
18685 y_start = it.current_y;
18686 move_it_vertically (&it, this_scroll_margin);
18687 scroll_margin_pos = it.current.pos;
18688
18689
18690
18691 if (IT_CHARPOS (it) == ZV
18692 && it.current_y - y_start < this_scroll_margin)
18693 y_offset = this_scroll_margin - (it.current_y - y_start);
18694 }
18695
18696 if (PT < CHARPOS (scroll_margin_pos))
18697 {
18698
18699
18700 int y0, y_to_move;
18701
18702
18703
18704
18705
18706
18707 SET_TEXT_POS (pos, PT, PT_BYTE);
18708 start_display (&it, w, pos);
18709 y0 = it.current_y;
18710 y_to_move = max (it.last_visible_y,
18711 max (scroll_max, 10 * frame_line_height));
18712 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18713 y_to_move, -1,
18714 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18715 dy = it.current_y - y0;
18716 if (dy > scroll_max
18717 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18718 return SCROLLING_FAILED;
18719
18720
18721 dy += y_offset;
18722
18723
18724 start_display (&it, w, startp);
18725
18726 if (arg_scroll_conservatively)
18727 amount_to_scroll
18728 = min (max (dy, frame_line_height),
18729 frame_line_height * arg_scroll_conservatively);
18730 else if (scroll_step || temp_scroll_step)
18731 amount_to_scroll = scroll_max;
18732 else
18733 {
18734 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18735 height = WINDOW_BOX_TEXT_HEIGHT (w);
18736 if (NUMBERP (aggressive))
18737 {
18738 double float_amount = XFLOATINT (aggressive) * height;
18739 int aggressive_scroll = float_amount;
18740 if (aggressive_scroll == 0 && float_amount > 0)
18741 aggressive_scroll = 1;
18742
18743
18744
18745
18746 if (aggressive_scroll + 2 * this_scroll_margin > height)
18747 aggressive_scroll = height - 2 * this_scroll_margin;
18748 amount_to_scroll = dy + aggressive_scroll;
18749 }
18750 }
18751
18752 if (amount_to_scroll <= 0)
18753 return SCROLLING_FAILED;
18754
18755 move_it_vertically_backward (&it, amount_to_scroll);
18756 startp = it.current.pos;
18757 }
18758 }
18759
18760
18761 startp = run_window_scroll_functions (window, startp);
18762
18763
18764
18765 if (!try_window (window, startp, 0))
18766 rc = SCROLLING_NEED_LARGER_MATRICES;
18767 else if (w->cursor.vpos < 0)
18768 {
18769 clear_glyph_matrix (w->desired_matrix);
18770 rc = SCROLLING_FAILED;
18771 }
18772 else
18773 {
18774
18775 if (!just_this_one_p
18776 || current_buffer->clip_changed
18777 || BEG_UNCHANGED < CHARPOS (startp))
18778 w->base_line_number = 0;
18779
18780
18781
18782 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18783 false, false)
18784
18785
18786
18787 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18788 {
18789 clear_glyph_matrix (w->desired_matrix);
18790 ++extra_scroll_margin_lines;
18791 goto too_near_end;
18792 }
18793 rc = SCROLLING_SUCCESS;
18794 }
18795
18796 return rc;
18797 }
18798
18799
18800
18801
18802
18803
18804
18805
18806
18807
18808
18809
18810 static bool
18811 compute_window_start_on_continuation_line (struct window *w)
18812 {
18813 struct text_pos pos, start_pos, pos_before_pt;
18814 bool window_start_changed_p = false;
18815
18816 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
18817
18818
18819
18820
18821 if (CHARPOS (start_pos) > BEGV
18822 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
18823 {
18824 struct it it;
18825 struct glyph_row *row;
18826
18827
18828 if (CHARPOS (start_pos) < BEGV)
18829 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
18830 else if (CHARPOS (start_pos) > ZV)
18831 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
18832
18833
18834
18835 row = w->desired_matrix->rows + window_wants_tab_line (w)
18836 + window_wants_header_line (w);
18837 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
18838 row, DEFAULT_FACE_ID);
18839 reseat_at_previous_visible_line_start (&it);
18840
18841
18842
18843
18844
18845
18846
18847 if (IT_CHARPOS (it) <= PT
18848 && (CHARPOS (start_pos) - IT_CHARPOS (it)
18849
18850 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
18851 {
18852 int min_distance, distance;
18853
18854
18855
18856
18857
18858
18859
18860 pos_before_pt = pos = it.current.pos;
18861 min_distance = DISP_INFINITY;
18862 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
18863 distance < min_distance)
18864 {
18865 min_distance = distance;
18866 if (CHARPOS (pos) <= PT)
18867 pos_before_pt = pos;
18868 pos = it.current.pos;
18869 if (it.line_wrap == WORD_WRAP)
18870 {
18871
18872
18873
18874
18875
18876
18877
18878
18879
18880 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
18881 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18882 move_it_to (&it, ZV, 0,
18883 it.current_y + it.max_ascent + it.max_descent, -1,
18884 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18885 }
18886 else
18887 move_it_by_lines (&it, 1);
18888 }
18889
18890
18891
18892
18893
18894 if (CHARPOS (pos) > PT)
18895 pos = pos_before_pt;
18896
18897
18898 SET_MARKER_FROM_TEXT_POS (w->start, pos);
18899 window_start_changed_p = true;
18900 }
18901 }
18902
18903 return window_start_changed_p;
18904 }
18905
18906
18907
18908
18909
18910
18911
18912
18913
18914
18915
18916
18917
18918
18919
18920
18921
18922 enum
18923 {
18924 CURSOR_MOVEMENT_SUCCESS,
18925 CURSOR_MOVEMENT_CANNOT_BE_USED,
18926 CURSOR_MOVEMENT_MUST_SCROLL,
18927 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
18928 };
18929
18930 static int
18931 try_cursor_movement (Lisp_Object window, struct text_pos startp,
18932 bool *scroll_step)
18933 {
18934 struct window *w = XWINDOW (window);
18935 struct frame *f = XFRAME (w->frame);
18936 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
18937
18938 #ifdef GLYPH_DEBUG
18939 if (inhibit_try_cursor_movement)
18940 return rc;
18941 #endif
18942
18943
18944
18945
18946 eassert (w->last_point > 0);
18947
18948
18949
18950 eassert (!w->window_end_valid
18951 || w->window_end_vpos < w->current_matrix->nrows);
18952
18953
18954
18955 if (
18956 PT >= CHARPOS (startp)
18957
18958 && !current_buffer->clip_changed
18959
18960
18961
18962
18963 && !update_mode_lines
18964 && !windows_or_buffers_changed
18965 && !f->cursor_type_changed
18966 && NILP (Vshow_trailing_whitespace)
18967
18968
18969 && !EQ (Vdisplay_line_numbers, Qrelative)
18970 && !EQ (Vdisplay_line_numbers, Qvisual)
18971
18972
18973
18974 && !(!NILP (Vdisplay_line_numbers)
18975 && NILP (Finternal_lisp_face_equal_p (Qline_number,
18976 Qline_number_current_line,
18977 w->frame)))
18978
18979
18980
18981
18982
18983
18984 && !EQ (window, minibuf_window)
18985
18986
18987
18988 && !overlay_arrow_in_current_buffer_p ())
18989 {
18990 int this_scroll_margin, top_scroll_margin;
18991 struct glyph_row *row = NULL;
18992
18993 #ifdef GLYPH_DEBUG
18994 debug_method_add (w, "cursor movement");
18995 #endif
18996
18997 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18998
18999 top_scroll_margin = this_scroll_margin;
19000 if (window_wants_tab_line (w))
19001 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
19002 if (window_wants_header_line (w))
19003 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
19004
19005
19006
19007 if (w->last_cursor_vpos < 0
19008 || w->last_cursor_vpos >= w->current_matrix->nrows)
19009 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19010 else
19011 {
19012 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
19013
19014 if (row->tab_line_p)
19015 ++row;
19016 if (row->mode_line_p)
19017 ++row;
19018 if (!row->enabled_p)
19019 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19020 }
19021
19022 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
19023 {
19024 bool scroll_p = false, must_scroll = false;
19025 int last_y = window_text_bottom_y (w) - this_scroll_margin;
19026
19027 if (PT > w->last_point)
19028 {
19029
19030 while (MATRIX_ROW_END_CHARPOS (row) < PT
19031 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19032 {
19033 eassert (row->enabled_p);
19034 ++row;
19035 }
19036
19037
19038
19039
19040 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19041 && MATRIX_ROW_END_CHARPOS (row) == PT
19042 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
19043 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19044 && !cursor_row_p (row))
19045 ++row;
19046
19047
19048
19049
19050
19051 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19052 || PT > MATRIX_ROW_END_CHARPOS (row)
19053
19054
19055 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19056 && PT == MATRIX_ROW_END_CHARPOS (row)
19057 && !row->ends_at_zv_p
19058 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19059 scroll_p = true;
19060 }
19061 else if (PT < w->last_point)
19062 {
19063
19064
19065 struct glyph_row *row0 = row;
19066
19067 while (!row->mode_line_p
19068 && (MATRIX_ROW_START_CHARPOS (row) > PT
19069 || (MATRIX_ROW_START_CHARPOS (row) == PT
19070 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19071 || (
19072 row > w->current_matrix->rows
19073 && (row-1)->ends_in_newline_from_string_p))))
19074 && (row->y > top_scroll_margin
19075 || CHARPOS (startp) == BEGV))
19076 {
19077 eassert (row->enabled_p);
19078 --row;
19079 }
19080
19081
19082
19083
19084
19085 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19086 && PT <= MATRIX_ROW_END_CHARPOS (row))
19087 && row0->continued_p)
19088 {
19089 row = row0;
19090 while (MATRIX_ROW_START_CHARPOS (row) > PT
19091 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19092 {
19093 eassert (row->enabled_p);
19094 ++row;
19095 }
19096 }
19097
19098
19099
19100
19101
19102
19103 if (row < w->current_matrix->rows
19104 || row->mode_line_p)
19105 {
19106 row = w->current_matrix->rows;
19107
19108 if (row->tab_line_p)
19109 ++row;
19110 if (row->mode_line_p)
19111 ++row;
19112 }
19113
19114
19115
19116 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19117 && MATRIX_ROW_END_CHARPOS (row) == PT
19118 && !cursor_row_p (row))
19119 ++row;
19120
19121
19122
19123 if ((row->y < top_scroll_margin
19124 && CHARPOS (startp) != BEGV)
19125 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19126 || PT > MATRIX_ROW_END_CHARPOS (row)
19127 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19128 && PT == MATRIX_ROW_END_CHARPOS (row)
19129 && !row->ends_at_zv_p
19130 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19131 scroll_p = true;
19132 }
19133 else
19134 {
19135
19136
19137 rc = CURSOR_MOVEMENT_SUCCESS;
19138 }
19139
19140 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19141 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19142
19143
19144 || (MATRIX_ROW_END_CHARPOS (row-1)
19145 == MATRIX_ROW_START_CHARPOS (row))))
19146 || PT > MATRIX_ROW_END_CHARPOS (row))
19147 {
19148
19149 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19150 must_scroll = true;
19151 }
19152 else if (rc != CURSOR_MOVEMENT_SUCCESS
19153 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19154 {
19155 struct glyph_row *row1;
19156
19157
19158
19159
19160
19161
19162
19163
19164
19165
19166
19167 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19168 MATRIX_ROW_CONTINUATION_LINE_P (row);
19169 --row)
19170 {
19171
19172
19173
19174 if (row <= row1)
19175 {
19176 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19177 break;
19178 }
19179 eassert (row->enabled_p);
19180 }
19181 }
19182 if (must_scroll)
19183 ;
19184 else if (rc != CURSOR_MOVEMENT_SUCCESS
19185 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19186
19187
19188
19189 && !row->mode_line_p
19190 && !cursor_row_fully_visible_p (w, true, true, true))
19191 {
19192 if (PT == MATRIX_ROW_END_CHARPOS (row)
19193 && !row->ends_at_zv_p
19194 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19195 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19196 else if (row->height > window_box_height (w))
19197 {
19198
19199
19200
19201
19202 *scroll_step = true;
19203 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19204 }
19205 else
19206 {
19207 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19208 if (!cursor_row_fully_visible_p (w, false, true, false))
19209 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19210 else
19211 rc = CURSOR_MOVEMENT_SUCCESS;
19212 }
19213 }
19214 else if (scroll_p)
19215 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19216 else if (rc != CURSOR_MOVEMENT_SUCCESS
19217 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19218 {
19219
19220
19221
19222
19223
19224
19225
19226 bool rv = false;
19227 bool pt_invis = false;
19228 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19229 Qinvisible,
19230 Qnil, NULL);
19231
19232 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19233 pt_invis = true;
19234
19235 do
19236 {
19237 bool at_zv_p = false, exact_match_p = false;
19238
19239
19240
19241
19242
19243 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19244 && PT <= MATRIX_ROW_END_CHARPOS (row)
19245 && cursor_row_p (row))
19246 rv |= set_cursor_from_row (w, row, w->current_matrix,
19247 0, 0, 0, 0);
19248
19249
19250
19251 if (rv)
19252 {
19253 at_zv_p = MATRIX_ROW (w->current_matrix,
19254 w->cursor.vpos)->ends_at_zv_p;
19255 if (!at_zv_p
19256 && w->cursor.hpos >= 0
19257 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19258 w->cursor.vpos))
19259 {
19260 struct glyph_row *candidate =
19261 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19262 struct glyph *g =
19263 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19264 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19265
19266 exact_match_p =
19267 (BUFFERP (g->object) && g->charpos == PT)
19268 || (NILP (g->object)
19269 && (g->charpos == PT
19270 || (g->charpos == 0 && endpos - 1 == PT)));
19271
19272
19273
19274
19275 if (!exact_match_p && pt_invis)
19276 exact_match_p = true;
19277 }
19278 if (at_zv_p || exact_match_p)
19279 {
19280 rc = CURSOR_MOVEMENT_SUCCESS;
19281 break;
19282 }
19283 }
19284 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19285 break;
19286 ++row;
19287 }
19288 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19289 || row->continued_p)
19290 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19291 || (MATRIX_ROW_START_CHARPOS (row) == PT
19292 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19293
19294
19295
19296 if (rc != CURSOR_MOVEMENT_SUCCESS
19297 && !(rv
19298 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19299 && !row->continued_p))
19300 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19301 else if (rv)
19302 rc = CURSOR_MOVEMENT_SUCCESS;
19303 }
19304 else
19305 {
19306 do
19307 {
19308 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19309 {
19310 rc = CURSOR_MOVEMENT_SUCCESS;
19311 break;
19312 }
19313 ++row;
19314 }
19315 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19316 && MATRIX_ROW_START_CHARPOS (row) == PT
19317 && cursor_row_p (row));
19318 }
19319 }
19320 }
19321
19322 return rc;
19323 }
19324
19325
19326 void
19327 set_vertical_scroll_bar (struct window *w)
19328 {
19329 ptrdiff_t start, end, whole;
19330
19331
19332
19333
19334
19335
19336
19337
19338 if (!MINI_WINDOW_P (w)
19339 || (w == XWINDOW (minibuf_window)
19340 && NILP (echo_area_buffer[0])))
19341 {
19342 struct buffer *buf = XBUFFER (w->contents);
19343
19344 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19345 start = marker_position (w->start) - BUF_BEGV (buf);
19346 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19347
19348
19349
19350
19351 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19352 {
19353 struct it it;
19354 struct text_pos start_pos;
19355 struct buffer *obuf = current_buffer;
19356
19357
19358
19359 set_buffer_internal_1 (XBUFFER (w->contents));
19360 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19361 start_display (&it, w, start_pos);
19362 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19363 MOVE_TO_X | MOVE_TO_Y);
19364 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19365 set_buffer_internal_1 (obuf);
19366 }
19367
19368 if (end < start)
19369 end = start;
19370 if (whole < (end - start))
19371 whole = end - start;
19372 }
19373 else
19374 start = end = whole = 0;
19375
19376
19377 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19378 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19379 (w, end - start, whole, start);
19380 }
19381
19382
19383 void
19384 set_horizontal_scroll_bar (struct window *w)
19385 {
19386 int start, end, whole, portion;
19387
19388 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19389 {
19390 struct buffer *b = XBUFFER (w->contents);
19391 struct buffer *old_buffer = NULL;
19392 struct it it;
19393 struct text_pos startp;
19394
19395 if (b != current_buffer)
19396 {
19397 old_buffer = current_buffer;
19398 set_buffer_internal (b);
19399 }
19400
19401 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19402 start_display (&it, w, startp);
19403 it.last_visible_x = INT_MAX;
19404 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19405 MOVE_TO_X | MOVE_TO_Y);
19406
19407
19408
19409
19410 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19411 end = start + window_box_width (w, TEXT_AREA);
19412 portion = end - start;
19413
19414
19415
19416
19417 whole = max (whole, end);
19418
19419 if (it.bidi_p)
19420 {
19421 Lisp_Object pdir;
19422
19423 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19424 if (EQ (pdir, Qright_to_left))
19425 {
19426 start = whole - end;
19427 end = start + portion;
19428 }
19429 }
19430
19431 if (old_buffer)
19432 set_buffer_internal (old_buffer);
19433 }
19434 else
19435 start = end = whole = portion = 0;
19436
19437 w->hscroll_whole = whole;
19438
19439
19440 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19441 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19442 (w, portion, whole, start);
19443 }
19444
19445
19446
19447 static bool
19448 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19449 {
19450 if (!make_window_start_visible)
19451 return true;
19452
19453 struct window *w = XWINDOW (window);
19454 struct frame *f = XFRAME (w->frame);
19455 Lisp_Object startpos = make_fixnum (startp);
19456 Lisp_Object invprop, disp_spec;
19457 struct text_pos ignored;
19458
19459
19460 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19461 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19462 return false;
19463
19464
19465 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19466 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19467 FRAME_WINDOW_P (f)) > 0)
19468 return false;
19469
19470 return true;
19471 }
19472
19473 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19474 0, 0, 0,
19475 doc:
19476
19477 )
19478 (void)
19479 {
19480 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19481 }
19482
19483
19484
19485
19486
19487
19488
19489
19490
19491
19492
19493
19494
19495
19496
19497
19498
19499
19500
19501
19502
19503
19504
19505
19506
19507
19508
19509
19510
19511
19512
19513
19514
19515
19516
19517
19518
19519
19520
19521
19522
19523
19524
19525
19526
19527
19528
19529
19530
19531
19532
19533 static void
19534 redisplay_window (Lisp_Object window, bool just_this_one_p)
19535 {
19536 struct window *w = XWINDOW (window);
19537 struct frame *f = XFRAME (w->frame);
19538 struct buffer *buffer = XBUFFER (w->contents);
19539 struct buffer *old = current_buffer;
19540 struct text_pos lpoint, opoint, startp;
19541 bool update_mode_line;
19542 int tem;
19543 struct it it;
19544
19545 bool current_matrix_up_to_date_p = false;
19546 bool used_current_matrix_p = false;
19547
19548
19549 bool buffer_unchanged_p = false;
19550 bool temp_scroll_step = false;
19551 specpdl_ref count = SPECPDL_INDEX ();
19552 int rc;
19553 int centering_position = -1;
19554 bool last_line_misfit = false;
19555 ptrdiff_t beg_unchanged, end_unchanged;
19556 int frame_line_height, margin;
19557 bool use_desired_matrix;
19558 void *itdata = NULL;
19559
19560 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19561 opoint = lpoint;
19562
19563 #ifdef GLYPH_DEBUG
19564 *w->desired_matrix->method = 0;
19565 #endif
19566
19567 if (!just_this_one_p && needs_no_redisplay (w))
19568 return;
19569
19570
19571 eassert (XMARKER (w->start)->buffer == buffer);
19572 eassert (XMARKER (w->pointm)->buffer == buffer);
19573
19574 reconsider_clip_changes (w);
19575 frame_line_height = default_line_pixel_height (w);
19576 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19577
19578
19579
19580 update_mode_line = (w->update_mode_line
19581 || update_mode_lines
19582 || buffer->clip_changed
19583 || buffer->prevent_redisplay_optimizations_p);
19584
19585 if (!just_this_one_p)
19586
19587
19588 w->must_be_updated_p = true;
19589
19590 if (MINI_WINDOW_P (w))
19591 {
19592 if (w == XWINDOW (echo_area_window)
19593 && !NILP (echo_area_buffer[0]))
19594 {
19595 if (update_mode_line)
19596
19597
19598 goto finish_menu_bars;
19599 else
19600
19601 goto finish_scroll_bars;
19602 }
19603 else if ((w != XWINDOW (minibuf_window)
19604 || minibuf_level == 0)
19605
19606 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19607
19608
19609 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19610 {
19611
19612
19613 int yb = window_text_bottom_y (w);
19614 struct glyph_row *row;
19615 int y;
19616
19617 for (y = 0, row = w->desired_matrix->rows;
19618 y < yb;
19619 y += row->height, ++row)
19620 blank_row (w, row, y);
19621 goto finish_scroll_bars;
19622 }
19623 else if (minibuf_level >= 1)
19624 {
19625
19626
19627
19628 resize_mini_window (w, false);
19629 }
19630
19631 clear_glyph_matrix (w->desired_matrix);
19632 }
19633
19634
19635
19636
19637
19638 set_buffer_internal_1 (XBUFFER (w->contents));
19639
19640 current_matrix_up_to_date_p
19641 = (w->window_end_valid
19642 && !current_buffer->clip_changed
19643 && !current_buffer->prevent_redisplay_optimizations_p
19644 && !window_outdated (w)
19645 && !composition_break_at_point
19646 && !hscrolling_current_line_p (w));
19647
19648 beg_unchanged = BEG_UNCHANGED;
19649 end_unchanged = END_UNCHANGED;
19650
19651 SET_TEXT_POS (opoint, PT, PT_BYTE);
19652
19653 specbind (Qinhibit_point_motion_hooks, Qt);
19654
19655 buffer_unchanged_p
19656 = (w->window_end_valid
19657 && !current_buffer->clip_changed
19658 && !window_outdated (w));
19659
19660
19661
19662 if (windows_or_buffers_changed)
19663 {
19664
19665
19666 if (XMARKER (w->start)->buffer == current_buffer)
19667 compute_window_start_on_continuation_line (w);
19668
19669 w->window_end_valid = false;
19670
19671
19672 current_matrix_up_to_date_p = false;
19673 }
19674
19675
19676 CHECK_WINDOW_END (w);
19677 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19678 emacs_abort ();
19679 if (BYTEPOS (opoint) < CHARPOS (opoint))
19680 emacs_abort ();
19681
19682 if (mode_line_update_needed (w))
19683 update_mode_line = true;
19684
19685
19686
19687 if (!EQ (window, selected_window))
19688 {
19689 ptrdiff_t new_pt = marker_position (w->pointm);
19690 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19691
19692 if (new_pt < BEGV)
19693 {
19694 new_pt = BEGV;
19695 new_pt_byte = BEGV_BYTE;
19696 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19697 }
19698 else if (new_pt > (ZV - 1))
19699 {
19700 new_pt = ZV;
19701 new_pt_byte = ZV_BYTE;
19702 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19703 }
19704
19705
19706 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19707 }
19708
19709
19710
19711
19712
19713
19714 if (current_buffer->width_run_cache
19715 || (current_buffer->base_buffer
19716 && current_buffer->base_buffer->width_run_cache))
19717 {
19718 struct Lisp_Char_Table *disptab = buffer_display_table ();
19719
19720 if (! disptab_matches_widthtab
19721 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19722 {
19723 struct buffer *buf = current_buffer;
19724
19725 if (buf->base_buffer)
19726 buf = buf->base_buffer;
19727 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19728 recompute_width_table (current_buffer, disptab);
19729 }
19730 }
19731
19732
19733 if (!NILP (Vlong_line_threshold)
19734 && !current_buffer->long_line_optimizations_p
19735 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19736 || current_buffer->clip_changed))
19737 {
19738 ptrdiff_t cur, next, found, max = 0, threshold;
19739 threshold = XFIXNUM (Vlong_line_threshold);
19740 for (cur = BEGV; cur < ZV; cur = next)
19741 {
19742 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19743 &found, NULL, true);
19744 if (next - cur > max) max = next - cur;
19745 if (!found || max > threshold) break;
19746 }
19747 if (max > threshold)
19748 current_buffer->long_line_optimizations_p = true;
19749 }
19750
19751
19752 if (XMARKER (w->start)->buffer != current_buffer)
19753 goto recenter;
19754
19755 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19756
19757
19758
19759 if ((w->optional_new_start || window_frozen_p (w))
19760 && CHARPOS (startp) >= BEGV
19761 && CHARPOS (startp) <= ZV)
19762 {
19763 ptrdiff_t it_charpos;
19764
19765 w->optional_new_start = false;
19766 if (!w->force_start)
19767 {
19768 start_display (&it, w, startp);
19769 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19770 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19771
19772
19773 it_charpos = IT_CHARPOS (it);
19774
19775
19776
19777
19778
19779 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19780 {
19781 if (it_charpos == PT)
19782 w->force_start = true;
19783
19784 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19785 w->force_start = true;
19786 #ifdef GLYPH_DEBUG
19787 if (w->force_start)
19788 {
19789 if (window_frozen_p (w))
19790 debug_method_add (w, "set force_start from frozen window start");
19791 else
19792 debug_method_add (w, "set force_start from optional_new_start");
19793 }
19794 #endif
19795 }
19796 }
19797 }
19798
19799 force_start:
19800
19801
19802
19803 if (w->force_start)
19804 {
19805
19806 int new_vpos = -1;
19807
19808 w->force_start = false;
19809
19810
19811
19812
19813 if (!w->preserve_vscroll_p || !window_frozen_p (w))
19814 w->vscroll = 0;
19815
19816 w->preserve_vscroll_p = false;
19817 w->window_end_valid = false;
19818
19819
19820 if (!buffer_unchanged_p)
19821 w->base_line_number = 0;
19822
19823
19824
19825
19826
19827
19828
19829
19830 if (!update_mode_line
19831 || ! NILP (Vwindow_scroll_functions))
19832 {
19833 update_mode_line = true;
19834 w->update_mode_line = true;
19835 startp = run_window_scroll_functions (window, startp);
19836 }
19837
19838 if (CHARPOS (startp) < BEGV)
19839 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
19840 else if (CHARPOS (startp) > ZV)
19841 SET_TEXT_POS (startp, ZV, ZV_BYTE);
19842
19843
19844
19845 if (!window_start_acceptable_p (window, CHARPOS (startp)))
19846 goto ignore_start;
19847
19848
19849
19850
19851
19852
19853 clear_glyph_matrix (w->desired_matrix);
19854 if (!try_window (window, startp, 0))
19855 {
19856 w->force_start = true;
19857 clear_glyph_matrix (w->desired_matrix);
19858 goto need_larger_matrices;
19859 }
19860
19861 if (w->cursor.vpos < 0)
19862 {
19863
19864
19865
19866
19867
19868 struct glyph_row *r = NULL;
19869 Lisp_Object invprop =
19870 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
19871 Qnil, NULL);
19872
19873 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19874 {
19875 ptrdiff_t alt_pt;
19876 Lisp_Object invprop_end =
19877 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
19878 Qnil, Qnil);
19879
19880 if (FIXNATP (invprop_end))
19881 alt_pt = XFIXNAT (invprop_end);
19882 else
19883 alt_pt = ZV;
19884 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
19885 NULL, 0);
19886 }
19887 if (r)
19888 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
19889 else
19890 new_vpos = window_box_height (w) / 2;
19891 }
19892
19893 if (!cursor_row_fully_visible_p (w, false, false, false))
19894 {
19895
19896
19897 new_vpos = window_box_height (w);
19898
19899
19900
19901
19902
19903
19904 if (new_vpos >= w->cursor.y)
19905 {
19906 w->cursor.vpos = -1;
19907 clear_glyph_matrix (w->desired_matrix);
19908 goto try_to_scroll;
19909 }
19910 }
19911 else if (w->cursor.vpos >= 0)
19912 {
19913
19914
19915
19916 int pixel_margin = margin * frame_line_height;
19917 bool tab_line = window_wants_tab_line (w);
19918 bool header_line = window_wants_header_line (w);
19919
19920
19921
19922
19923
19924 if (w->cursor.vpos < margin + tab_line + header_line)
19925 {
19926 w->cursor.vpos = -1;
19927 clear_glyph_matrix (w->desired_matrix);
19928 goto try_to_scroll;
19929 }
19930 else
19931 {
19932 int window_height = window_box_height (w);
19933
19934 if (tab_line)
19935 window_height += CURRENT_TAB_LINE_HEIGHT (w);
19936 if (header_line)
19937 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
19938 if (w->cursor.y >= window_height - pixel_margin)
19939 {
19940 w->cursor.vpos = -1;
19941 clear_glyph_matrix (w->desired_matrix);
19942 goto try_to_scroll;
19943 }
19944 }
19945 }
19946
19947
19948
19949 if (new_vpos >= 0)
19950 {
19951 struct glyph_row *row;
19952
19953 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
19954 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
19955 && !row->ends_at_zv_p)
19956 ++row;
19957
19958 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
19959 MATRIX_ROW_START_BYTEPOS (row));
19960
19961 if (w != XWINDOW (selected_window))
19962 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
19963 else if (current_buffer == old)
19964 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19965
19966 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
19967
19968
19969
19970
19971
19972
19973
19974 w->redisplay = false;
19975 XBUFFER (w->contents)->text->redisplay = false;
19976 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
19977
19978 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
19979 || ((EQ (Vdisplay_line_numbers, Qrelative)
19980 || EQ (Vdisplay_line_numbers, Qvisual))
19981 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
19982 {
19983
19984
19985
19986
19987 clear_glyph_matrix (w->desired_matrix);
19988 if (!try_window (window, startp, 0))
19989 goto need_larger_matrices;
19990 }
19991 }
19992 if (w->cursor.vpos < 0
19993 || !cursor_row_fully_visible_p (w, false, false, false))
19994 {
19995 clear_glyph_matrix (w->desired_matrix);
19996 goto try_to_scroll;
19997 }
19998
19999 #ifdef GLYPH_DEBUG
20000 debug_method_add (w, "forced window start");
20001 #endif
20002 goto done;
20003 }
20004
20005 ignore_start:
20006
20007
20008
20009
20010 if (current_matrix_up_to_date_p
20011 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
20012 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
20013 {
20014 switch (rc)
20015 {
20016 case CURSOR_MOVEMENT_SUCCESS:
20017 used_current_matrix_p = true;
20018 goto done;
20019
20020 case CURSOR_MOVEMENT_MUST_SCROLL:
20021 goto try_to_scroll;
20022
20023 default:
20024 emacs_abort ();
20025 }
20026 }
20027
20028
20029
20030 else if (w->start_at_line_beg
20031 && ((CHARPOS (startp) > BEGV
20032 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
20033 || (CHARPOS (startp) >= BEGV
20034 && CHARPOS (startp) <= ZV
20035 && !window_start_acceptable_p (window, CHARPOS (startp)))))
20036 {
20037 #ifdef GLYPH_DEBUG
20038 debug_method_add (w, "recenter 1");
20039 #endif
20040 goto recenter;
20041 }
20042
20043
20044
20045
20046 else if ((tem = try_window_id (w)) != 0)
20047 {
20048 #ifdef GLYPH_DEBUG
20049 debug_method_add (w, "try_window_id %d", tem);
20050 #endif
20051
20052 if (f->fonts_changed)
20053 goto need_larger_matrices;
20054 if (tem > 0)
20055 goto done;
20056
20057
20058
20059 }
20060 else if (CHARPOS (startp) >= BEGV
20061 && CHARPOS (startp) <= ZV
20062 && PT >= CHARPOS (startp)
20063 && (CHARPOS (startp) < ZV
20064
20065 || CHARPOS (startp) == BEGV
20066 || !window_outdated (w)))
20067 {
20068 int d1, d2, d5, d6;
20069 int rtop, rbot;
20070
20071
20072
20073
20074
20075
20076
20077
20078
20079
20080 if (!w->start_at_line_beg
20081 && NILP (track_mouse)
20082 && CHARPOS (startp) > BEGV
20083 && CHARPOS (startp) > BEG + beg_unchanged
20084 && CHARPOS (startp) <= Z - end_unchanged
20085
20086
20087
20088
20089
20090 && XMARKER (w->start)->buffer == current_buffer
20091 && compute_window_start_on_continuation_line (w)
20092
20093
20094
20095
20096
20097
20098 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20099
20100
20101 && (rtop != 0) == (rbot != 0))
20102 {
20103 w->force_start = true;
20104 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20105 #ifdef GLYPH_DEBUG
20106 debug_method_add (w, "recomputed window start in continuation line");
20107 #endif
20108 goto force_start;
20109 }
20110
20111
20112
20113
20114 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20115 {
20116 #ifdef GLYPH_DEBUG
20117 debug_method_add (w, "recenter 2");
20118 #endif
20119 goto recenter;
20120 }
20121
20122 #ifdef GLYPH_DEBUG
20123 debug_method_add (w, "same window start");
20124 #endif
20125
20126
20127
20128 if (!current_matrix_up_to_date_p
20129
20130
20131
20132 || !NILP (Vwindow_scroll_functions)
20133 || MINI_WINDOW_P (w)
20134 || !(used_current_matrix_p
20135 = try_window_reusing_current_matrix (w)))
20136 {
20137 IF_DEBUG (debug_method_add (w, "1"));
20138 clear_glyph_matrix (w->desired_matrix);
20139 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20140
20141
20142
20143 goto try_to_scroll;
20144 }
20145
20146 if (f->fonts_changed)
20147 goto need_larger_matrices;
20148
20149 if (w->cursor.vpos >= 0)
20150 {
20151 if (!just_this_one_p
20152 || current_buffer->clip_changed
20153 || BEG_UNCHANGED < CHARPOS (startp))
20154
20155 w->base_line_number = 0;
20156
20157 if (!cursor_row_fully_visible_p (w, true, false, false))
20158 {
20159 clear_glyph_matrix (w->desired_matrix);
20160 last_line_misfit = true;
20161 }
20162
20163 else
20164 goto done;
20165 }
20166 else
20167 clear_glyph_matrix (w->desired_matrix);
20168 }
20169
20170 try_to_scroll:
20171
20172
20173 if (!update_mode_line)
20174 {
20175 update_mode_line = true;
20176 w->update_mode_line = true;
20177 }
20178
20179
20180 if ((0 < scroll_conservatively
20181
20182
20183
20184
20185 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20186 || 0 < emacs_scroll_step
20187 || temp_scroll_step
20188 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20189 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20190 && CHARPOS (startp) >= BEGV
20191 && CHARPOS (startp) <= ZV)
20192 {
20193
20194
20195 int ss = try_scrolling (window, just_this_one_p,
20196 ((scroll_minibuffer_conservatively
20197 && MINI_WINDOW_P (w))
20198 ? SCROLL_LIMIT + 1
20199 : scroll_conservatively),
20200 emacs_scroll_step,
20201 temp_scroll_step, last_line_misfit);
20202 switch (ss)
20203 {
20204 case SCROLLING_SUCCESS:
20205 goto done;
20206
20207 case SCROLLING_NEED_LARGER_MATRICES:
20208 goto need_larger_matrices;
20209
20210 case SCROLLING_FAILED:
20211 break;
20212
20213 default:
20214 emacs_abort ();
20215 }
20216 }
20217
20218
20219
20220
20221 recenter:
20222
20223 #ifdef GLYPH_DEBUG
20224 debug_method_add (w, "recenter");
20225 #endif
20226
20227
20228 if (!buffer_unchanged_p)
20229 w->base_line_number = 0;
20230
20231
20232 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20233 it.current_y = it.last_visible_y;
20234 if (centering_position < 0)
20235 {
20236 ptrdiff_t margin_pos = CHARPOS (startp);
20237 Lisp_Object aggressive;
20238 bool scrolling_up;
20239
20240
20241
20242 if (margin
20243
20244
20245
20246
20247
20248
20249 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20250 {
20251 struct it it1;
20252 void *it1data = NULL;
20253
20254 SAVE_IT (it1, it, it1data);
20255 start_display (&it1, w, startp);
20256 move_it_vertically (&it1, margin * frame_line_height);
20257 margin_pos = IT_CHARPOS (it1);
20258 RESTORE_IT (&it, &it, it1data);
20259 }
20260 scrolling_up = PT > margin_pos;
20261 aggressive =
20262 scrolling_up
20263 ? BVAR (current_buffer, scroll_up_aggressively)
20264 : BVAR (current_buffer, scroll_down_aggressively);
20265
20266 if (!MINI_WINDOW_P (w)
20267 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20268 {
20269 int pt_offset = 0;
20270
20271
20272
20273 if (!scroll_conservatively && NUMBERP (aggressive))
20274 {
20275 double float_amount = XFLOATINT (aggressive);
20276
20277 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20278 if (pt_offset == 0 && float_amount > 0)
20279 pt_offset = 1;
20280 if (pt_offset && margin > 0)
20281 margin -= 1;
20282 }
20283
20284
20285
20286 if (scrolling_up)
20287 {
20288 centering_position = it.last_visible_y;
20289 if (pt_offset)
20290 centering_position -= pt_offset;
20291 centering_position -=
20292 (frame_line_height * (1 + margin + last_line_misfit)
20293 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20294
20295
20296 if (centering_position < margin * frame_line_height)
20297 centering_position = margin * frame_line_height;
20298 }
20299 else
20300 centering_position = margin * frame_line_height + pt_offset;
20301 }
20302 else
20303
20304
20305 centering_position = window_box_height (w) / 2;
20306 }
20307 if (current_buffer->long_line_optimizations_p
20308 && it.line_wrap == TRUNCATE)
20309 {
20310
20311
20312
20313 int nlines = centering_position / frame_line_height;
20314
20315 while (nlines-- && IT_CHARPOS (it) > BEGV)
20316 back_to_previous_visible_line_start (&it);
20317 reseat_1 (&it, it.current.pos, true);
20318 }
20319 else
20320 move_it_vertically_backward (&it, centering_position);
20321
20322 eassert (IT_CHARPOS (it) >= BEGV);
20323
20324
20325
20326
20327
20328
20329 if (it.current_y <= 0)
20330 {
20331 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20332 move_it_vertically_backward (&it, 0);
20333 it.current_y = 0;
20334 }
20335
20336 it.current_x = it.hpos = 0;
20337
20338
20339
20340
20341 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20342
20343
20344 startp = run_window_scroll_functions (window, it.current.pos);
20345
20346
20347
20348
20349 itdata = bidi_shelve_cache ();
20350
20351
20352 use_desired_matrix = false;
20353 if (!current_matrix_up_to_date_p
20354 || windows_or_buffers_changed
20355 || f->cursor_type_changed
20356
20357
20358 || !NILP (Vwindow_scroll_functions)
20359 || !just_this_one_p
20360 || MINI_WINDOW_P (w)
20361 || !(used_current_matrix_p
20362 = try_window_reusing_current_matrix (w)))
20363 use_desired_matrix = (try_window (window, startp, 0) == 1);
20364
20365 bidi_unshelve_cache (itdata, false);
20366
20367
20368
20369
20370 if (f->fonts_changed)
20371 goto need_larger_matrices;
20372
20373
20374
20375
20376
20377
20378 if (w->cursor.vpos < 0)
20379 {
20380 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20381 {
20382 clear_glyph_matrix (w->desired_matrix);
20383 move_it_by_lines (&it, 1);
20384 try_window (window, it.current.pos, 0);
20385 }
20386 else if (PT < IT_CHARPOS (it))
20387 {
20388 clear_glyph_matrix (w->desired_matrix);
20389 move_it_by_lines (&it, -1);
20390 try_window (window, it.current.pos, 0);
20391 }
20392 else if (scroll_conservatively > SCROLL_LIMIT
20393 && (it.method == GET_FROM_STRING
20394 || overlay_touches_p (IT_CHARPOS (it)))
20395 && IT_CHARPOS (it) < ZV)
20396 {
20397
20398
20399
20400
20401
20402
20403
20404
20405 ptrdiff_t pos0 = IT_CHARPOS (it);
20406
20407 clear_glyph_matrix (w->desired_matrix);
20408 do {
20409 move_it_by_lines (&it, 1);
20410 } while (IT_CHARPOS (it) == pos0);
20411 try_window (window, it.current.pos, 0);
20412 }
20413 else
20414 {
20415
20416 }
20417 }
20418
20419
20420
20421
20422
20423
20424 if (w->cursor.vpos < 0)
20425 {
20426
20427
20428
20429
20430 struct glyph_matrix *matrix =
20431 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20432
20433 struct glyph_row *row =
20434 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20435
20436
20437
20438
20439
20440
20441
20442 if (!row)
20443 {
20444 Lisp_Object val =
20445 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20446 Qnil, NULL);
20447
20448 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20449 {
20450 ptrdiff_t alt_pos;
20451 Lisp_Object invis_end =
20452 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20453 Qnil, Qnil);
20454
20455 if (FIXNATP (invis_end))
20456 alt_pos = XFIXNAT (invis_end);
20457 else
20458 alt_pos = ZV;
20459 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20460 }
20461 }
20462
20463
20464
20465 if (!row)
20466 {
20467 row = matrix->rows;
20468
20469 if (row->tab_line_p)
20470 ++row;
20471 if (row->mode_line_p)
20472 ++row;
20473 }
20474 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20475 }
20476
20477 if (!cursor_row_fully_visible_p (w, false, false, false))
20478 {
20479
20480 if (w->vscroll)
20481 {
20482 w->vscroll = 0;
20483 clear_glyph_matrix (w->desired_matrix);
20484 goto recenter;
20485 }
20486
20487
20488
20489
20490
20491 if (scroll_conservatively > SCROLL_LIMIT)
20492 {
20493 int window_total_lines
20494 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20495 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20496
20497 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20498 clear_glyph_matrix (w->desired_matrix);
20499 if (1 == try_window (window, it.current.pos,
20500 TRY_WINDOW_CHECK_MARGINS))
20501 goto done;
20502 }
20503
20504
20505
20506
20507 if (centering_position == 0)
20508 goto done;
20509
20510 clear_glyph_matrix (w->desired_matrix);
20511 centering_position = 0;
20512 goto recenter;
20513 }
20514
20515 done:
20516
20517 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20518 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20519 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20520
20521
20522 if ((update_mode_line
20523
20524
20525
20526
20527 || (!just_this_one_p
20528 && !FRAME_WINDOW_P (f)
20529 && !WINDOW_FULL_WIDTH_P (w))
20530
20531 || w->base_line_pos > 0
20532
20533 || (w->column_number_displayed != -1
20534 && (w->column_number_displayed != current_column ())))
20535
20536 && (window_wants_mode_line (w)
20537 || window_wants_header_line (w)
20538 || window_wants_tab_line (w)))
20539 {
20540 specpdl_ref count1 = SPECPDL_INDEX ();
20541
20542 specbind (Qinhibit_quit, Qt);
20543 display_mode_lines (w);
20544 unbind_to (count1, Qnil);
20545
20546
20547
20548 if (window_wants_mode_line (w)
20549 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20550 {
20551 f->fonts_changed = true;
20552 w->mode_line_height = -1;
20553 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20554 = DESIRED_MODE_LINE_HEIGHT (w);
20555 }
20556
20557
20558
20559 if (window_wants_tab_line (w)
20560 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20561 {
20562 f->fonts_changed = true;
20563 w->tab_line_height = -1;
20564 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20565 = DESIRED_TAB_LINE_HEIGHT (w);
20566 }
20567
20568
20569
20570 if (window_wants_header_line (w)
20571 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20572 {
20573 f->fonts_changed = true;
20574 w->header_line_height = -1;
20575 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20576 = DESIRED_HEADER_LINE_HEIGHT (w);
20577 }
20578
20579 if (f->fonts_changed)
20580 goto need_larger_matrices;
20581 }
20582
20583 if (!line_number_displayed && w->base_line_pos != -1)
20584 {
20585 w->base_line_pos = 0;
20586 w->base_line_number = 0;
20587 }
20588
20589 finish_menu_bars:
20590
20591
20592
20593 if (update_mode_line
20594 && EQ (FRAME_SELECTED_WINDOW (f), window))
20595 {
20596 bool redisplay_menu_p;
20597
20598 if (FRAME_WINDOW_P (f))
20599 {
20600 #ifdef HAVE_EXT_MENU_BAR
20601 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20602 #else
20603 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20604 #endif
20605 }
20606 else
20607 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20608
20609 if (redisplay_menu_p)
20610 display_menu_bar (w);
20611
20612 #ifdef HAVE_WINDOW_SYSTEM
20613 if (FRAME_WINDOW_P (f))
20614 {
20615 if (WINDOWP (f->tab_bar_window)
20616 && (FRAME_TAB_BAR_LINES (f) > 0
20617 || !NILP (Vauto_resize_tab_bars))
20618 && redisplay_tab_bar (f))
20619 ignore_mouse_drag_p = true;
20620
20621 #ifdef HAVE_EXT_TOOL_BAR
20622 if (FRAME_EXTERNAL_TOOL_BAR (f))
20623 update_frame_tool_bar (f);
20624 #else
20625 if (WINDOWP (f->tool_bar_window)
20626 && (FRAME_TOOL_BAR_LINES (f) > 0
20627 || !NILP (Vauto_resize_tool_bars))
20628 && redisplay_tool_bar (f))
20629 ignore_mouse_drag_p = true;
20630 #endif
20631 }
20632 else
20633 {
20634 if ((FRAME_TAB_BAR_LINES (f) > 0))
20635 display_tab_bar (w);
20636 }
20637
20638 gui_consider_frame_title (w->frame);
20639 #else
20640 if ((FRAME_TAB_BAR_LINES (f) > 0))
20641 display_tab_bar (w);
20642 #endif
20643 }
20644
20645 #ifdef HAVE_WINDOW_SYSTEM
20646 if (FRAME_WINDOW_P (f)
20647 && update_window_fringes (w, (just_this_one_p
20648 || (!used_current_matrix_p && !overlay_arrow_seen)
20649 || w->pseudo_window_p)))
20650 {
20651 update_begin (f);
20652 block_input ();
20653 if (draw_window_fringes (w, true))
20654 {
20655 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20656 gui_draw_right_divider (w);
20657 else
20658 gui_draw_vertical_border (w);
20659 }
20660 unblock_input ();
20661 update_end (f);
20662 }
20663
20664 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20665 gui_draw_bottom_divider (w);
20666 #endif
20667
20668
20669
20670
20671
20672 need_larger_matrices:
20673 ;
20674 finish_scroll_bars:
20675
20676 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20677 {
20678 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20679
20680 set_vertical_scroll_bar (w);
20681
20682 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20683
20684 set_horizontal_scroll_bar (w);
20685
20686
20687
20688 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20689 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20690 }
20691
20692
20693
20694
20695 if (CHARPOS (opoint) < BEGV)
20696 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20697 else if (CHARPOS (opoint) > ZV)
20698 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20699 else
20700 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20701
20702 set_buffer_internal_1 (old);
20703
20704
20705 if (CHARPOS (lpoint) <= ZV)
20706 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20707
20708 unbind_to (count, Qnil);
20709 }
20710
20711
20712
20713
20714
20715
20716
20717
20718
20719
20720
20721
20722
20723
20724
20725
20726
20727
20728
20729
20730 int
20731 try_window (Lisp_Object window, struct text_pos pos, int flags)
20732 {
20733 struct window *w = XWINDOW (window);
20734 struct it it;
20735 struct glyph_row *last_text_row = NULL;
20736 struct frame *f = XFRAME (w->frame);
20737 int cursor_vpos = w->cursor.vpos;
20738
20739
20740 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20741
20742
20743 w->cursor.vpos = -1;
20744 overlay_arrow_seen = false;
20745
20746
20747 start_display (&it, w, pos);
20748 it.glyph_row->reversed_p = false;
20749
20750
20751 while (it.current_y < it.last_visible_y)
20752 {
20753 int last_row_scale = it.w->nrows_scale_factor;
20754 int last_col_scale = it.w->ncols_scale_factor;
20755 if (display_line (&it, cursor_vpos))
20756 last_text_row = it.glyph_row - 1;
20757 if (f->fonts_changed
20758 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20759
20760
20761 && last_row_scale == it.w->nrows_scale_factor
20762 && last_col_scale == it.w->ncols_scale_factor))
20763 return 0;
20764 }
20765
20766
20767
20768 ptrdiff_t it_charpos = IT_CHARPOS (it);
20769
20770
20771
20772
20773 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20774 && w->vscroll == 0
20775 && !MINI_WINDOW_P (w))
20776 {
20777 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20778 int bot_scroll_margin = top_scroll_margin;
20779 if (window_wants_header_line (w))
20780 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20781 if (window_wants_tab_line (w))
20782 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20783 start_display (&it, w, pos);
20784
20785 if ((w->cursor.y >= 0
20786 && w->cursor.y < top_scroll_margin
20787 && CHARPOS (pos) > BEGV)
20788
20789
20790
20791
20792 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20793 - bot_scroll_margin - 1))
20794 {
20795 w->cursor.vpos = -1;
20796 clear_glyph_matrix (w->desired_matrix);
20797 return -1;
20798 }
20799 }
20800
20801
20802 if (w->window_end_pos <= 0 && Z != it_charpos)
20803 w->update_mode_line = true;
20804
20805
20806
20807
20808 if (last_text_row)
20809 {
20810 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
20811 adjust_window_ends (w, last_text_row, false);
20812 eassert
20813 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
20814 w->window_end_vpos)));
20815 }
20816 else
20817 {
20818 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
20819 w->window_end_pos = Z - ZV;
20820 w->window_end_vpos = 0;
20821 }
20822
20823
20824 w->window_end_valid = false;
20825 return 1;
20826 }
20827
20828
20829
20830
20831
20832
20833
20834
20835
20836
20837
20838
20839 static bool
20840 try_window_reusing_current_matrix (struct window *w)
20841 {
20842 struct frame *f = XFRAME (w->frame);
20843 struct glyph_row *bottom_row;
20844 struct it it;
20845 struct run run;
20846 struct text_pos start, new_start;
20847 int nrows_scrolled, i;
20848 struct glyph_row *last_text_row;
20849 struct glyph_row *last_reused_text_row;
20850 struct glyph_row *start_row;
20851 int start_vpos, min_y, max_y;
20852
20853 #ifdef GLYPH_DEBUG
20854 if (inhibit_try_window_reusing)
20855 return false;
20856 #endif
20857
20858 if (
20859 !FRAME_WINDOW_P (f)
20860
20861
20862 || windows_or_buffers_changed
20863 || f->cursor_type_changed
20864
20865
20866
20867 || overlay_arrow_in_current_buffer_p ())
20868 return false;
20869
20870
20871 if (!NILP (Vshow_trailing_whitespace))
20872 return false;
20873
20874
20875 if (window_wants_tab_line (w)
20876 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
20877 return false;
20878
20879
20880 if (window_wants_header_line (w)
20881 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
20882 return false;
20883
20884
20885
20886 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20887 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
20888 return false;
20889
20890
20891 clear_glyph_matrix (w->desired_matrix);
20892
20893
20894
20895
20896 if (!NILP (Vdisplay_line_numbers))
20897 return false;
20898
20899
20900
20901
20902 #ifdef HAVE_NTGUI
20903 if (w32_use_visible_system_caret)
20904 return false;
20905 #endif
20906
20907
20908
20909 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
20910 start = start_row->minpos;
20911 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
20912
20913 if (CHARPOS (new_start) <= CHARPOS (start))
20914 {
20915
20916
20917
20918
20919 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
20920 return false;
20921
20922 IF_DEBUG (debug_method_add (w, "twu1"));
20923
20924
20925
20926
20927
20928 start_display (&it, w, new_start);
20929 w->cursor.vpos = -1;
20930 last_text_row = last_reused_text_row = NULL;
20931
20932 while (it.current_y < it.last_visible_y && !f->fonts_changed)
20933 {
20934
20935
20936
20937
20938 while (IT_CHARPOS (it) > CHARPOS (start))
20939 {
20940
20941 start_row++;
20942 start = start_row->minpos;
20943
20944 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
20945 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
20946 || CHARPOS (start) == ZV)
20947 {
20948 clear_glyph_matrix (w->desired_matrix);
20949 return false;
20950 }
20951
20952 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
20953 }
20954
20955
20956 if (IT_CHARPOS (it) == CHARPOS (start)
20957
20958
20959
20960
20961
20962 && it.current.dpvec_index < 0)
20963 break;
20964
20965 it.glyph_row->reversed_p = false;
20966 if (display_line (&it, -1))
20967 last_text_row = it.glyph_row - 1;
20968
20969 }
20970
20971
20972
20973
20974 if (it.current_y < it.last_visible_y)
20975 {
20976 struct glyph_row *row;
20977
20978
20979 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
20980
20981
20982 if (w->cursor.vpos < 0)
20983 {
20984 int dy = it.current_y - start_row->y;
20985
20986 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20987 row = row_containing_pos (w, PT, row, NULL, dy);
20988 if (row)
20989 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
20990 dy, nrows_scrolled);
20991 else
20992 {
20993 clear_glyph_matrix (w->desired_matrix);
20994 return false;
20995 }
20996 }
20997
20998
20999
21000
21001
21002
21003
21004 run.current_y = start_row->y;
21005 run.desired_y = it.current_y;
21006 run.height = it.last_visible_y - it.current_y;
21007
21008 if (run.height > 0 && run.current_y != run.desired_y)
21009 {
21010 #ifdef HAVE_WINDOW_SYSTEM
21011 update_begin (f);
21012 gui_update_window_begin (w);
21013 FRAME_RIF (f)->clear_window_mouse_face (w);
21014 FRAME_RIF (f)->scroll_run_hook (w, &run);
21015 gui_update_window_end (w, false, false);
21016 update_end (f);
21017 #endif
21018 }
21019
21020
21021 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21022 rotate_matrix (w->current_matrix,
21023 start_vpos,
21024 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21025 nrows_scrolled);
21026
21027
21028 for (i = 0; i < nrows_scrolled; ++i)
21029 (start_row + i)->enabled_p = false;
21030
21031
21032 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21033 max_y = it.last_visible_y;
21034 for (row = start_row + nrows_scrolled;
21035 row < bottom_row;
21036 ++row)
21037 {
21038 row->y = it.current_y;
21039 row->visible_height = row->height;
21040
21041 if (row->y < min_y)
21042 row->visible_height -= min_y - row->y;
21043 if (row->y + row->height > max_y)
21044 row->visible_height -= row->y + row->height - max_y;
21045 if (row->fringe_bitmap_periodic_p)
21046 row->redraw_fringe_bitmaps_p = true;
21047
21048 it.current_y += row->height;
21049
21050 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21051 last_reused_text_row = row;
21052 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21053 break;
21054 }
21055
21056
21057
21058 for (++row; row < bottom_row; ++row)
21059 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21060 }
21061
21062
21063
21064
21065
21066 if (last_reused_text_row)
21067 adjust_window_ends (w, last_reused_text_row, true);
21068 else if (last_text_row)
21069 adjust_window_ends (w, last_text_row, false);
21070 else
21071 {
21072
21073 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21074 w->window_end_pos = Z - ZV;
21075 w->window_end_vpos = 0;
21076 }
21077 w->window_end_valid = false;
21078
21079
21080 w->desired_matrix->no_scrolling_p = true;
21081
21082 #ifdef GLYPH_DEBUG
21083 debug_method_add (w, "try_window_reusing_current_matrix 1");
21084 #endif
21085 return true;
21086 }
21087 else if (CHARPOS (new_start) > CHARPOS (start))
21088 {
21089 struct glyph_row *pt_row, *row;
21090 struct glyph_row *first_reusable_row;
21091 struct glyph_row *first_row_to_display;
21092 int dy;
21093 int yb = window_text_bottom_y (w);
21094
21095
21096
21097 first_reusable_row = start_row;
21098 while (first_reusable_row->enabled_p
21099 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21100 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21101 < CHARPOS (new_start)))
21102 ++first_reusable_row;
21103
21104
21105 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21106 || !first_reusable_row->enabled_p
21107 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21108 != CHARPOS (new_start)))
21109 return false;
21110
21111
21112
21113
21114
21115 pt_row = NULL;
21116 for (first_row_to_display = first_reusable_row;
21117 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21118 ++first_row_to_display)
21119 {
21120 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21121 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21122 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21123 && first_row_to_display->ends_at_zv_p
21124 && pt_row == NULL)))
21125 pt_row = first_row_to_display;
21126 }
21127
21128 if (first_row_to_display->y >= yb)
21129 return false;
21130
21131
21132 init_to_row_start (&it, w, first_row_to_display);
21133
21134 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21135 - start_vpos);
21136 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21137 - nrows_scrolled);
21138 it.current_y = (first_row_to_display->y - first_reusable_row->y
21139 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21140
21141
21142
21143
21144 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21145 if (pt_row == NULL)
21146 w->cursor.vpos = -1;
21147 last_text_row = NULL;
21148 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21149 if (display_line (&it, w->cursor.vpos))
21150 last_text_row = it.glyph_row - 1;
21151
21152
21153
21154 if (pt_row)
21155 {
21156 w->cursor.vpos -= nrows_scrolled;
21157 w->cursor.y -= first_reusable_row->y - start_row->y;
21158 }
21159
21160
21161
21162
21163
21164 if (w->cursor.vpos < 0)
21165 {
21166 clear_glyph_matrix (w->desired_matrix);
21167 return false;
21168 }
21169
21170
21171 run.current_y = first_reusable_row->y;
21172 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21173 run.height = it.last_visible_y - run.current_y;
21174 dy = run.current_y - run.desired_y;
21175
21176 if (run.height)
21177 {
21178 #ifdef HAVE_WINDOW_SYSTEM
21179 update_begin (f);
21180 gui_update_window_begin (w);
21181 FRAME_RIF (f)->clear_window_mouse_face (w);
21182 FRAME_RIF (f)->scroll_run_hook (w, &run);
21183 gui_update_window_end (w, false, false);
21184 update_end (f);
21185 #endif
21186 }
21187
21188
21189 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21190 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21191 max_y = it.last_visible_y;
21192 for (row = first_reusable_row; row < first_row_to_display; ++row)
21193 {
21194 row->y -= dy;
21195 row->visible_height = row->height;
21196 if (row->y < min_y)
21197 row->visible_height -= min_y - row->y;
21198 if (row->y + row->height > max_y)
21199 row->visible_height -= row->y + row->height - max_y;
21200 if (row->fringe_bitmap_periodic_p)
21201 row->redraw_fringe_bitmaps_p = true;
21202 }
21203
21204
21205 eassert (nrows_scrolled > 0);
21206 rotate_matrix (w->current_matrix,
21207 start_vpos,
21208 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21209 -nrows_scrolled);
21210
21211
21212 for (row -= nrows_scrolled; row < bottom_row; ++row)
21213 row->enabled_p = false;
21214
21215
21216
21217 if (pt_row)
21218 {
21219 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21220 row < bottom_row
21221 && PT >= MATRIX_ROW_END_CHARPOS (row)
21222 && !row->ends_at_zv_p;
21223 row++)
21224 {
21225 w->cursor.vpos++;
21226 w->cursor.y = row->y;
21227 }
21228 if (row < bottom_row)
21229 {
21230
21231
21232
21233
21234 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21235 {
21236 if (!set_cursor_from_row (w, row, w->current_matrix,
21237 0, 0, 0, 0))
21238 {
21239 clear_glyph_matrix (w->desired_matrix);
21240 return false;
21241 }
21242 }
21243 else
21244 {
21245 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21246 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21247
21248 for (; glyph < end
21249 && (!BUFFERP (glyph->object)
21250 || glyph->charpos < PT);
21251 glyph++)
21252 {
21253 w->cursor.hpos++;
21254 w->cursor.x += glyph->pixel_width;
21255 }
21256 }
21257 }
21258 }
21259
21260
21261
21262
21263 if (last_text_row)
21264 adjust_window_ends (w, last_text_row, false);
21265 else
21266 w->window_end_vpos -= nrows_scrolled;
21267
21268 w->window_end_valid = false;
21269 w->desired_matrix->no_scrolling_p = true;
21270
21271 #ifdef GLYPH_DEBUG
21272 debug_method_add (w, "try_window_reusing_current_matrix 2");
21273 #endif
21274 return true;
21275 }
21276
21277 return false;
21278 }
21279
21280
21281
21282
21283
21284
21285
21286 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21287 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21288 ptrdiff_t *, ptrdiff_t *);
21289 static struct glyph_row *
21290 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21291 struct glyph_row *);
21292
21293
21294
21295
21296
21297
21298
21299 static struct glyph_row *
21300 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21301 struct glyph_row *start)
21302 {
21303 struct glyph_row *row, *row_found;
21304
21305
21306
21307
21308 row_found = NULL;
21309 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21310 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21311 {
21312 eassert (row->enabled_p);
21313 row_found = row;
21314 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21315 break;
21316 ++row;
21317 }
21318
21319 return row_found;
21320 }
21321
21322
21323
21324
21325
21326
21327
21328
21329
21330
21331
21332
21333 static struct glyph_row *
21334 find_last_unchanged_at_beg_row (struct window *w)
21335 {
21336 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21337 struct glyph_row *row;
21338 struct glyph_row *row_found = NULL;
21339 int yb = window_text_bottom_y (w);
21340
21341
21342 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21343 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21344 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21345 ++row)
21346 {
21347 if (
21348
21349 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21350
21351
21352 && !row->ends_at_zv_p
21353
21354
21355
21356 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21357 && (row->continued_p
21358 || row->exact_window_width_line_p))
21359
21360
21361
21362
21363
21364
21365
21366 && CHARPOS (row->end.pos) <= ZV)
21367 row_found = row;
21368
21369
21370 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21371 break;
21372 }
21373
21374 return row_found;
21375 }
21376
21377
21378
21379
21380
21381
21382
21383
21384
21385
21386
21387
21388
21389
21390 static struct glyph_row *
21391 find_first_unchanged_at_end_row (struct window *w,
21392 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21393 {
21394 struct glyph_row *row;
21395 struct glyph_row *row_found = NULL;
21396
21397 *delta = *delta_bytes = 0;
21398
21399
21400
21401 eassert (w->window_end_valid);
21402
21403
21404
21405
21406 if (w->window_end_pos >= END_UNCHANGED)
21407 return NULL;
21408
21409
21410 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21411
21412
21413 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21414 {
21415
21416
21417
21418
21419
21420 ptrdiff_t Z_old =
21421 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21422 ptrdiff_t Z_BYTE_old =
21423 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21424 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21425 struct glyph_row *first_text_row
21426 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21427
21428 *delta = Z - Z_old;
21429 *delta_bytes = Z_BYTE - Z_BYTE_old;
21430
21431
21432
21433
21434
21435
21436
21437 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21438 last_unchanged_pos_old = last_unchanged_pos - *delta;
21439
21440
21441
21442 for (; row > first_text_row; --row)
21443 {
21444
21445
21446 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21447 break;
21448
21449 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21450 row_found = row;
21451 }
21452 }
21453
21454 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21455
21456 return row_found;
21457 }
21458
21459
21460
21461
21462
21463
21464
21465
21466 static void
21467 sync_frame_with_window_matrix_rows (struct window *w)
21468 {
21469 struct frame *f = XFRAME (w->frame);
21470 struct glyph_row *window_row, *window_row_end, *frame_row;
21471
21472
21473
21474 eassert (BUFFERP (w->contents));
21475 eassert (WINDOW_FULL_WIDTH_P (w));
21476 eassert (!FRAME_WINDOW_P (f));
21477
21478
21479
21480
21481
21482 window_row = w->current_matrix->rows;
21483 window_row_end = window_row + w->current_matrix->nrows;
21484 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21485 while (window_row < window_row_end)
21486 {
21487 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21488 struct glyph *end = window_row->glyphs[LAST_AREA];
21489
21490 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21491 frame_row->glyphs[TEXT_AREA] = start;
21492 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21493 frame_row->glyphs[LAST_AREA] = end;
21494
21495
21496
21497 if (!window_row->enabled_p)
21498 frame_row->enabled_p = false;
21499
21500 ++window_row, ++frame_row;
21501 }
21502 }
21503
21504
21505
21506
21507
21508
21509
21510 struct glyph_row *
21511 row_containing_pos (struct window *w, ptrdiff_t charpos,
21512 struct glyph_row *start, struct glyph_row *end, int dy)
21513 {
21514 struct glyph_row *row = start;
21515 struct glyph_row *best_row = NULL;
21516 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21517 int last_y;
21518
21519
21520 if (row->tab_line_p)
21521 ++row;
21522 if (row->mode_line_p)
21523 ++row;
21524
21525 if ((end && row >= end) || !row->enabled_p)
21526 return NULL;
21527
21528 last_y = window_text_bottom_y (w) - dy;
21529
21530 while (true)
21531 {
21532
21533 if ((end && row >= end) || !row->enabled_p)
21534 return NULL;
21535
21536
21537
21538 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21539 return NULL;
21540
21541
21542 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21543 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21544
21545
21546
21547
21548 && !row_for_charpos_p (row, charpos)))
21549 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21550 {
21551 struct glyph *g;
21552
21553 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21554 || (!best_row && !row->continued_p))
21555 return row;
21556
21557
21558
21559
21560 for (g = row->glyphs[TEXT_AREA];
21561 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21562 g++)
21563 {
21564 if (!STRINGP (g->object))
21565 {
21566 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21567 {
21568 mindif = eabs (g->charpos - charpos);
21569 best_row = row;
21570
21571 if (mindif == 0)
21572 return best_row;
21573 }
21574 }
21575 }
21576 }
21577 else if (best_row && !row->continued_p)
21578 return best_row;
21579 ++row;
21580 }
21581 }
21582
21583
21584
21585
21586
21587
21588
21589
21590
21591
21592
21593
21594
21595
21596
21597
21598
21599
21600
21601
21602
21603
21604
21605
21606
21607
21608
21609
21610
21611
21612
21613
21614
21615
21616
21617
21618
21619
21620
21621
21622
21623
21624
21625
21626 static int
21627 try_window_id (struct window *w)
21628 {
21629 struct frame *f = XFRAME (w->frame);
21630 struct glyph_matrix *current_matrix = w->current_matrix;
21631 struct glyph_matrix *desired_matrix = w->desired_matrix;
21632 struct glyph_row *last_unchanged_at_beg_row;
21633 struct glyph_row *first_unchanged_at_end_row;
21634 struct glyph_row *row;
21635 struct glyph_row *bottom_row;
21636 int bottom_vpos;
21637 struct it it;
21638 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21639 int dvpos, dy;
21640 struct text_pos start_pos;
21641 struct run run;
21642 int first_unchanged_at_end_vpos = 0;
21643 struct glyph_row *last_text_row, *last_text_row_at_end;
21644 struct text_pos start;
21645 ptrdiff_t first_changed_charpos, last_changed_charpos;
21646
21647 #ifdef GLYPH_DEBUG
21648 if (inhibit_try_window_id)
21649 return 0;
21650 #endif
21651
21652
21653 #if false
21654 #define GIVE_UP(X) \
21655 do { \
21656 redisplay_trace ("try_window_id give up %d\n", X); \
21657 return 0; \
21658 } while (false)
21659 #else
21660 #define GIVE_UP(X) return 0
21661 #endif
21662
21663 SET_TEXT_POS_FROM_MARKER (start, w->start);
21664
21665
21666
21667 if (MINI_WINDOW_P (w))
21668 GIVE_UP (1);
21669
21670
21671 if (windows_or_buffers_changed || f->cursor_type_changed)
21672 GIVE_UP (2);
21673
21674
21675
21676
21677 if (w->last_overlay_modified != OVERLAY_MODIFF)
21678 GIVE_UP (200);
21679
21680
21681
21682
21683
21684 if (current_buffer->clip_changed
21685 || current_buffer->prevent_redisplay_optimizations_p)
21686 GIVE_UP (3);
21687
21688
21689 if (!FRAME_WINDOW_P (f)
21690 && (!FRAME_LINE_INS_DEL_OK (f)
21691 || !WINDOW_FULL_WIDTH_P (w)))
21692 GIVE_UP (4);
21693
21694
21695 if (PT < CHARPOS (start))
21696 GIVE_UP (5);
21697
21698
21699 if (w->last_modified == 0)
21700 GIVE_UP (6);
21701
21702
21703 if (w->hscroll != 0)
21704 GIVE_UP (7);
21705
21706
21707 if (!w->window_end_valid)
21708 GIVE_UP (8);
21709
21710
21711 if (!NILP (Vshow_trailing_whitespace))
21712 GIVE_UP (11);
21713
21714
21715
21716 if (overlay_arrows_changed_p (false))
21717 GIVE_UP (12);
21718
21719
21720
21721
21722
21723 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21724 GIVE_UP (21);
21725
21726
21727
21728
21729
21730
21731
21732
21733
21734 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21735 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21736 GIVE_UP (22);
21737
21738
21739
21740 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21741 GIVE_UP (23);
21742
21743
21744
21745 if (EQ (Vdisplay_line_numbers, Qrelative)
21746 || EQ (Vdisplay_line_numbers, Qvisual)
21747 || (!NILP (Vdisplay_line_numbers)
21748 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21749 Qline_number_current_line,
21750 w->frame))))
21751 GIVE_UP (24);
21752
21753
21754
21755
21756 if (composition_break_at_point)
21757 GIVE_UP (27);
21758
21759
21760
21761
21762
21763 if (MODIFF > SAVE_MODIFF
21764
21765 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21766 {
21767 if (GPT - BEG < BEG_UNCHANGED)
21768 BEG_UNCHANGED = GPT - BEG;
21769 if (Z - GPT < END_UNCHANGED)
21770 END_UNCHANGED = Z - GPT;
21771 }
21772
21773
21774 first_changed_charpos = BEG + BEG_UNCHANGED;
21775 last_changed_charpos = Z - END_UNCHANGED;
21776
21777
21778
21779
21780
21781
21782 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21783 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21784 && ((last_changed_charpos < CHARPOS (start)
21785 && CHARPOS (start) == BEGV)
21786 || (last_changed_charpos < CHARPOS (start) - 1
21787 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21788 {
21789 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21790 struct glyph_row *r0;
21791
21792
21793
21794 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21795 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21796 Z_delta = Z - Z_old;
21797 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
21798
21799
21800
21801
21802 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
21803 GIVE_UP (13);
21804
21805
21806
21807
21808 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21809 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
21810 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
21811
21812 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
21813 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21814 {
21815
21816 if (Z_delta || Z_delta_bytes)
21817 {
21818 struct glyph_row *r1
21819 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
21820 increment_matrix_positions (w->current_matrix,
21821 MATRIX_ROW_VPOS (r0, current_matrix),
21822 MATRIX_ROW_VPOS (r1, current_matrix),
21823 Z_delta, Z_delta_bytes);
21824 }
21825
21826
21827 row = row_containing_pos (w, PT, r0, NULL, 0);
21828 if (row)
21829 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21830 return 1;
21831 }
21832 }
21833
21834
21835
21836
21837
21838 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
21839
21840
21841 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
21842 || first_changed_charpos == last_changed_charpos))
21843 {
21844 struct glyph_row *r0;
21845
21846
21847
21848
21849 if (PT >= MATRIX_ROW_END_CHARPOS (row))
21850 GIVE_UP (14);
21851
21852
21853
21854
21855 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21856 if (TEXT_POS_EQUAL_P (start, r0->minpos)
21857
21858 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
21859 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21860 {
21861
21862
21863 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
21864 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
21865
21866
21867 row = row_containing_pos (w, PT, r0, NULL, 0);
21868 if (row)
21869 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21870 return 2;
21871 }
21872 }
21873
21874
21875
21876
21877
21878
21879
21880
21881 if (CHARPOS (start) >= first_changed_charpos
21882 && CHARPOS (start) <= last_changed_charpos)
21883 GIVE_UP (15);
21884
21885
21886
21887
21888
21889 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
21890 if (!TEXT_POS_EQUAL_P (start, row->minpos))
21891 GIVE_UP (16);
21892
21893
21894
21895 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
21896 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
21897 GIVE_UP (20);
21898
21899
21900
21901
21902
21903 #ifdef HAVE_NTGUI
21904 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
21905 GIVE_UP (25);
21906 #endif
21907
21908
21909
21910
21911
21912
21913
21914 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
21915 if (last_unchanged_at_beg_row)
21916 {
21917
21918
21919
21920
21921 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
21922 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
21923 && last_unchanged_at_beg_row > w->current_matrix->rows)
21924 --last_unchanged_at_beg_row;
21925
21926 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
21927 GIVE_UP (17);
21928
21929 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
21930 GIVE_UP (18);
21931
21932
21933
21934 if (it.sp > 1
21935 && it.method == GET_FROM_IMAGE && it.image_id == -1)
21936 GIVE_UP (26);
21937 start_pos = it.current.pos;
21938
21939
21940
21941
21942 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
21943 current_matrix);
21944 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
21945 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
21946
21947 eassert (it.hpos == 0 && it.current_x == 0);
21948 }
21949 else
21950 {
21951
21952
21953 start_display (&it, w, start);
21954 it.vpos = it.first_vpos;
21955 start_pos = it.current.pos;
21956 }
21957
21958
21959
21960
21961
21962
21963
21964 first_unchanged_at_end_row
21965 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
21966 IF_DEBUG (debug_delta = delta);
21967 IF_DEBUG (debug_delta_bytes = delta_bytes);
21968
21969
21970
21971
21972
21973
21974 stop_pos = 0;
21975 if (first_unchanged_at_end_row)
21976 {
21977 eassert (last_unchanged_at_beg_row == NULL
21978 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
21979
21980
21981
21982
21983
21984 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
21985 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
21986 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
21987 < it.last_visible_y))
21988 ++first_unchanged_at_end_row;
21989
21990 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
21991 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
21992 >= it.last_visible_y))
21993 first_unchanged_at_end_row = NULL;
21994 else
21995 {
21996 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
21997 + delta);
21998 first_unchanged_at_end_vpos
21999 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
22000 eassert (stop_pos >= Z - END_UNCHANGED);
22001 }
22002 }
22003 else if (last_unchanged_at_beg_row == NULL)
22004 GIVE_UP (19);
22005
22006
22007 #ifdef GLYPH_DEBUG
22008
22009
22010
22011
22012 eassert (first_unchanged_at_end_row == NULL
22013 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22014
22015 debug_last_unchanged_at_beg_vpos
22016 = (last_unchanged_at_beg_row
22017 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
22018 : -1);
22019 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
22020
22021 #endif
22022
22023
22024
22025
22026
22027 w->cursor.vpos = -1;
22028 last_text_row = NULL;
22029 overlay_arrow_seen = false;
22030 if (it.current_y < it.last_visible_y
22031 && !f->fonts_changed
22032 && (first_unchanged_at_end_row == NULL
22033 || IT_CHARPOS (it) < stop_pos))
22034 it.glyph_row->reversed_p = false;
22035 while (it.current_y < it.last_visible_y
22036 && !f->fonts_changed
22037 && (first_unchanged_at_end_row == NULL
22038 || IT_CHARPOS (it) < stop_pos))
22039 {
22040 if (display_line (&it, -1))
22041 last_text_row = it.glyph_row - 1;
22042 }
22043
22044 if (f->fonts_changed)
22045 return -1;
22046
22047
22048
22049
22050
22051
22052
22053
22054
22055
22056
22057 if (!w->window_end_valid)
22058 {
22059 clear_glyph_matrix (w->desired_matrix);
22060 return -1;
22061 }
22062
22063
22064
22065
22066 if (first_unchanged_at_end_row
22067
22068
22069 && it.current_y < it.last_visible_y)
22070 {
22071 dvpos = (it.vpos
22072 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22073 current_matrix));
22074 dy = it.current_y - first_unchanged_at_end_row->y;
22075 run.current_y = first_unchanged_at_end_row->y;
22076 run.desired_y = run.current_y + dy;
22077 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22078 }
22079 else
22080 {
22081 delta = delta_bytes = dvpos = dy
22082 = run.current_y = run.desired_y = run.height = 0;
22083 first_unchanged_at_end_row = NULL;
22084 }
22085 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22086
22087
22088
22089
22090
22091
22092
22093
22094
22095
22096 if (w->cursor.vpos < 0)
22097 {
22098
22099 if (PT < CHARPOS (start_pos)
22100 && last_unchanged_at_beg_row)
22101 {
22102 row = row_containing_pos (w, PT,
22103 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22104 last_unchanged_at_beg_row + 1, 0);
22105 if (row)
22106 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22107 }
22108
22109
22110 else if (first_unchanged_at_end_row)
22111 {
22112 row = row_containing_pos (w, PT - delta,
22113 first_unchanged_at_end_row, NULL, 0);
22114 if (row)
22115 set_cursor_from_row (w, row, w->current_matrix, delta,
22116 delta_bytes, dy, dvpos);
22117 }
22118
22119
22120 if (w->cursor.vpos < 0)
22121 {
22122 clear_glyph_matrix (w->desired_matrix);
22123 return -1;
22124 }
22125 }
22126
22127
22128 {
22129 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22130 int bot_scroll_margin = top_scroll_margin;
22131 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22132
22133 if (window_wants_header_line (w))
22134 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22135 if (window_wants_tab_line (w))
22136 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22137
22138 if ((w->cursor.y < top_scroll_margin
22139 && CHARPOS (start) > BEGV)
22140
22141
22142 || (w->cursor.y
22143 + (cursor_row_fully_visible_p (w, false, true, true)
22144 ? 1
22145 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22146 {
22147 w->cursor.vpos = -1;
22148 clear_glyph_matrix (w->desired_matrix);
22149 return -1;
22150 }
22151 }
22152
22153
22154
22155
22156 if (dy && run.height)
22157 {
22158 update_begin (f);
22159
22160 if (FRAME_WINDOW_P (f))
22161 {
22162 #ifdef HAVE_WINDOW_SYSTEM
22163 gui_update_window_begin (w);
22164 FRAME_RIF (f)->clear_window_mouse_face (w);
22165 FRAME_RIF (f)->scroll_run_hook (w, &run);
22166 gui_update_window_end (w, false, false);
22167 #endif
22168 }
22169 else
22170 {
22171
22172
22173 int from_vpos
22174 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22175 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22176 int end = (WINDOW_TOP_EDGE_LINE (w)
22177 + window_wants_tab_line (w)
22178 + window_wants_header_line (w)
22179 + window_internal_height (w));
22180
22181 gui_clear_window_mouse_face (w);
22182
22183
22184 if (dvpos > 0)
22185 {
22186
22187
22188 set_terminal_window (f, end);
22189
22190
22191
22192 if (!FRAME_SCROLL_REGION_OK (f))
22193 ins_del_lines (f, end - dvpos, -dvpos);
22194
22195
22196
22197 ins_del_lines (f, from, dvpos);
22198 }
22199 else if (dvpos < 0)
22200 {
22201
22202
22203 set_terminal_window (f, end);
22204
22205
22206
22207
22208
22209 ins_del_lines (f, from + dvpos, dvpos);
22210
22211
22212
22213 if (!FRAME_SCROLL_REGION_OK (f))
22214 ins_del_lines (f, end + dvpos, -dvpos);
22215 }
22216
22217 set_terminal_window (f, 0);
22218 }
22219
22220 update_end (f);
22221 }
22222
22223
22224
22225
22226 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22227 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22228 if (dvpos < 0)
22229 {
22230 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22231 bottom_vpos, dvpos);
22232 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22233 bottom_vpos);
22234 }
22235 else if (dvpos > 0)
22236 {
22237 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22238 bottom_vpos, dvpos);
22239 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22240 first_unchanged_at_end_vpos + dvpos);
22241 }
22242
22243
22244
22245 if (!FRAME_WINDOW_P (f))
22246 sync_frame_with_window_matrix_rows (w);
22247
22248
22249 if (delta || delta_bytes)
22250 increment_matrix_positions (current_matrix,
22251 first_unchanged_at_end_vpos + dvpos,
22252 bottom_vpos, delta, delta_bytes);
22253
22254
22255 if (dy)
22256 shift_glyph_matrix (w, current_matrix,
22257 first_unchanged_at_end_vpos + dvpos,
22258 bottom_vpos, dy);
22259
22260 if (first_unchanged_at_end_row)
22261 {
22262 first_unchanged_at_end_row += dvpos;
22263 if (first_unchanged_at_end_row->y >= it.last_visible_y
22264 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22265 first_unchanged_at_end_row = NULL;
22266 }
22267
22268
22269
22270 last_text_row_at_end = NULL;
22271 if (dy < 0)
22272 {
22273
22274
22275
22276
22277
22278 int last_vpos = w->window_end_vpos + dvpos;
22279 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22280
22281
22282 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22283
22284
22285
22286
22287 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22288 {
22289 init_to_row_start (&it, w, last_row);
22290 it.vpos = last_vpos;
22291 it.current_y = last_row->y;
22292 }
22293 else
22294 {
22295 init_to_row_end (&it, w, last_row);
22296 it.vpos = 1 + last_vpos;
22297 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22298 ++last_row;
22299 }
22300
22301
22302
22303 it.continuation_lines_width = last_row->continuation_lines_width;
22304 it.hpos = it.current_x = 0;
22305
22306
22307 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22308 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22309 {
22310
22311
22312
22313
22314 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22315 if (display_line (&it, w->cursor.vpos))
22316 last_text_row_at_end = it.glyph_row - 1;
22317 }
22318 }
22319
22320
22321 if (first_unchanged_at_end_row && !last_text_row_at_end)
22322 {
22323
22324
22325
22326
22327 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22328 row = find_last_row_displaying_text (w->current_matrix, &it,
22329 first_unchanged_at_end_row);
22330 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22331 adjust_window_ends (w, row, true);
22332 eassert (w->window_end_bytepos >= 0);
22333 IF_DEBUG (debug_method_add (w, "A"));
22334 }
22335 else if (last_text_row_at_end)
22336 {
22337 adjust_window_ends (w, last_text_row_at_end, false);
22338 eassert (w->window_end_bytepos >= 0);
22339 IF_DEBUG (debug_method_add (w, "B"));
22340 }
22341 else if (last_text_row)
22342 {
22343
22344
22345
22346 adjust_window_ends (w, last_text_row, false);
22347 eassert (w->window_end_bytepos >= 0);
22348 }
22349 else if (first_unchanged_at_end_row == NULL
22350 && last_text_row == NULL
22351 && last_text_row_at_end == NULL)
22352 {
22353
22354
22355 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22356 int vpos = w->window_end_vpos;
22357 struct glyph_row *current_row = current_matrix->rows + vpos;
22358 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22359
22360 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22361 {
22362 eassert (first_vpos <= vpos);
22363 if (desired_row->enabled_p)
22364 {
22365 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22366 row = desired_row;
22367 }
22368 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22369 row = current_row;
22370 }
22371
22372 w->window_end_vpos = vpos + 1;
22373 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22374 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22375 eassert (w->window_end_bytepos >= 0);
22376 IF_DEBUG (debug_method_add (w, "C"));
22377 }
22378 else
22379 emacs_abort ();
22380
22381 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22382 debug_end_vpos = w->window_end_vpos));
22383
22384
22385 w->window_end_valid = false;
22386 w->desired_matrix->no_scrolling_p = true;
22387 return 3;
22388
22389 #undef GIVE_UP
22390 }
22391
22392
22393
22394
22395
22396
22397
22398 #ifdef GLYPH_DEBUG
22399
22400 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22401 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22402 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22403
22404
22405
22406
22407
22408
22409
22410
22411 void
22412 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22413 {
22414 int i;
22415 for (i = 0; i < matrix->nrows; ++i)
22416 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22417 }
22418
22419
22420
22421
22422
22423 void
22424 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22425 {
22426 if (glyph->type == CHAR_GLYPH
22427 || glyph->type == GLYPHLESS_GLYPH)
22428 {
22429 fprintf (stderr,
22430 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22431 glyph - row->glyphs[TEXT_AREA],
22432 (glyph->type == CHAR_GLYPH
22433 ? 'C'
22434 : 'G'),
22435 glyph->charpos,
22436 (BUFFERP (glyph->object)
22437 ? 'B'
22438 : (STRINGP (glyph->object)
22439 ? 'S'
22440 : (NILP (glyph->object)
22441 ? '0'
22442 : '-'))),
22443 glyph->pixel_width,
22444 glyph->u.ch,
22445 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22446 ? (int) glyph->u.ch
22447 : '.'),
22448 glyph->face_id,
22449 glyph->left_box_line_p,
22450 glyph->right_box_line_p);
22451 }
22452 else if (glyph->type == STRETCH_GLYPH)
22453 {
22454 fprintf (stderr,
22455 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22456 glyph - row->glyphs[TEXT_AREA],
22457 'S',
22458 glyph->charpos,
22459 (BUFFERP (glyph->object)
22460 ? 'B'
22461 : (STRINGP (glyph->object)
22462 ? 'S'
22463 : (NILP (glyph->object)
22464 ? '0'
22465 : '-'))),
22466 glyph->pixel_width,
22467 0u,
22468 ' ',
22469 glyph->face_id,
22470 glyph->left_box_line_p,
22471 glyph->right_box_line_p);
22472 }
22473 else if (glyph->type == IMAGE_GLYPH)
22474 {
22475 fprintf (stderr,
22476 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22477 glyph - row->glyphs[TEXT_AREA],
22478 'I',
22479 glyph->charpos,
22480 (BUFFERP (glyph->object)
22481 ? 'B'
22482 : (STRINGP (glyph->object)
22483 ? 'S'
22484 : (NILP (glyph->object)
22485 ? '0'
22486 : '-'))),
22487 glyph->pixel_width,
22488 (unsigned int) glyph->u.img_id,
22489 '.',
22490 glyph->face_id,
22491 glyph->left_box_line_p,
22492 glyph->right_box_line_p);
22493 }
22494 else if (glyph->type == COMPOSITE_GLYPH)
22495 {
22496 fprintf (stderr,
22497 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22498 glyph - row->glyphs[TEXT_AREA],
22499 '+',
22500 glyph->charpos,
22501 (BUFFERP (glyph->object)
22502 ? 'B'
22503 : (STRINGP (glyph->object)
22504 ? 'S'
22505 : (NILP (glyph->object)
22506 ? '0'
22507 : '-'))),
22508 glyph->pixel_width,
22509 (unsigned int) glyph->u.cmp.id);
22510 if (glyph->u.cmp.automatic)
22511 fprintf (stderr,
22512 "[%d-%d]",
22513 glyph->slice.cmp.from, glyph->slice.cmp.to);
22514 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22515 glyph->face_id,
22516 glyph->left_box_line_p,
22517 glyph->right_box_line_p);
22518 }
22519 else if (glyph->type == XWIDGET_GLYPH)
22520 {
22521 #ifndef HAVE_XWIDGETS
22522 eassume (false);
22523 #else
22524 fprintf (stderr,
22525 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22526 glyph - row->glyphs[TEXT_AREA],
22527 'X',
22528 glyph->charpos,
22529 (BUFFERP (glyph->object)
22530 ? 'B'
22531 : (STRINGP (glyph->object)
22532 ? 'S'
22533 : '-')),
22534 glyph->pixel_width,
22535 glyph->u.xwidget,
22536 '.',
22537 glyph->face_id,
22538 glyph->left_box_line_p,
22539 glyph->right_box_line_p);
22540 #endif
22541 }
22542 }
22543
22544
22545
22546
22547
22548
22549
22550 void
22551 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22552 {
22553 if (glyphs != 1)
22554 {
22555 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22556 "==============================================================================\n"),
22557 stderr);
22558 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22559 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22560 vpos,
22561 MATRIX_ROW_START_CHARPOS (row),
22562 MATRIX_ROW_END_CHARPOS (row),
22563 row->used[TEXT_AREA],
22564 row->contains_overlapping_glyphs_p,
22565 row->enabled_p,
22566 row->truncated_on_left_p,
22567 row->truncated_on_right_p,
22568 row->continued_p,
22569 MATRIX_ROW_CONTINUATION_LINE_P (row),
22570 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22571 row->ends_at_zv_p,
22572 row->fill_line_p,
22573 row->ends_in_middle_of_char_p,
22574 row->starts_in_middle_of_char_p,
22575 row->mouse_face_p,
22576 row->x,
22577 row->y,
22578 row->pixel_width,
22579 row->height,
22580 row->visible_height,
22581 row->ascent,
22582 row->phys_ascent);
22583
22584 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22585 row->end.overlay_string_index,
22586 row->continuation_lines_width);
22587 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22588 CHARPOS (row->start.string_pos),
22589 CHARPOS (row->end.string_pos));
22590 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22591 row->end.dpvec_index);
22592 }
22593
22594 if (glyphs > 1)
22595 {
22596 int area;
22597
22598 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22599 {
22600 struct glyph *glyph = row->glyphs[area];
22601 struct glyph *glyph_end = glyph + row->used[area];
22602
22603
22604 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22605 ++glyph_end;
22606
22607 if (glyph < glyph_end)
22608 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22609 stderr);
22610
22611 for (; glyph < glyph_end; ++glyph)
22612 dump_glyph (row, glyph, area);
22613 }
22614 }
22615 else if (glyphs == 1)
22616 {
22617 int area;
22618 char s[SHRT_MAX + 4];
22619
22620 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22621 {
22622 int i;
22623
22624 for (i = 0; i < row->used[area]; ++i)
22625 {
22626 struct glyph *glyph = row->glyphs[area] + i;
22627 if (i == row->used[area] - 1
22628 && area == TEXT_AREA
22629 && NILP (glyph->object)
22630 && glyph->type == CHAR_GLYPH
22631 && glyph->u.ch == ' ')
22632 {
22633 strcpy (&s[i], "[\\n]");
22634 i += 4;
22635 }
22636 else if (glyph->type == CHAR_GLYPH
22637 && glyph->u.ch < 0x80
22638 && glyph->u.ch >= ' ')
22639 s[i] = glyph->u.ch;
22640 else
22641 s[i] = '.';
22642 }
22643
22644 s[i] = '\0';
22645 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22646 }
22647 }
22648 }
22649
22650
22651 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22652 Sdump_glyph_matrix, 0, 1, "p",
22653 doc:
22654
22655
22656
22657
22658
22659 )
22660 (Lisp_Object glyphs)
22661 {
22662 struct window *w = XWINDOW (selected_window);
22663 struct buffer *buffer = XBUFFER (w->contents);
22664
22665 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22666 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22667 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22668 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22669 fputs ("=============================================\n", stderr);
22670 dump_glyph_matrix (w->current_matrix,
22671 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22672 return Qnil;
22673 }
22674
22675
22676 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22677 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22678 )
22679 (void)
22680 {
22681 struct frame *f = XFRAME (selected_frame);
22682
22683 if (f->current_matrix)
22684 dump_glyph_matrix (f->current_matrix, 1);
22685 else
22686 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22687 return Qnil;
22688 }
22689
22690
22691 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22692 doc:
22693
22694
22695
22696
22697 )
22698 (Lisp_Object row, Lisp_Object glyphs)
22699 {
22700 struct glyph_matrix *matrix;
22701 EMACS_INT vpos;
22702
22703 if (NILP (row))
22704 {
22705 int d1, d2, d3, d4, d5, ypos;
22706 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22707 &d1, &d2, &d3, &d4, &d5, &ypos);
22708 if (visible_p)
22709 vpos = ypos;
22710 else
22711 vpos = 0;
22712 }
22713 else
22714 {
22715 CHECK_FIXNUM (row);
22716 vpos = XFIXNUM (row);
22717 }
22718 matrix = XWINDOW (selected_window)->current_matrix;
22719 if (vpos >= 0 && vpos < matrix->nrows)
22720 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22721 vpos,
22722 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22723 return Qnil;
22724 }
22725
22726
22727 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22728 doc:
22729
22730
22731
22732
22733
22734
22735 )
22736 (Lisp_Object row, Lisp_Object glyphs)
22737 {
22738 #if defined (HAVE_WINDOW_SYSTEM)
22739 struct frame *sf = SELECTED_FRAME ();
22740 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22741 ? XWINDOW (sf->tab_bar_window)->current_matrix
22742 : sf->current_matrix;
22743 EMACS_INT vpos;
22744
22745 if (NILP (row))
22746 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22747 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22748 else
22749 {
22750 CHECK_FIXNUM (row);
22751 vpos = XFIXNUM (row);
22752 }
22753 if (vpos >= 0 && vpos < m->nrows)
22754 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22755 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22756 #endif
22757 return Qnil;
22758 }
22759
22760 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22761 doc:
22762
22763
22764
22765
22766
22767
22768 )
22769 (Lisp_Object row, Lisp_Object glyphs)
22770 {
22771 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22772 struct frame *sf = SELECTED_FRAME ();
22773 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22774 EMACS_INT vpos;
22775
22776 if (NILP (row))
22777 vpos = 0;
22778 else
22779 {
22780 CHECK_FIXNUM (row);
22781 vpos = XFIXNUM (row);
22782 }
22783 if (vpos >= 0 && vpos < m->nrows)
22784 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22785 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22786 #endif
22787 return Qnil;
22788 }
22789
22790
22791 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22792 doc:
22793 )
22794 (Lisp_Object arg)
22795 {
22796 if (NILP (arg))
22797 trace_redisplay_p = !trace_redisplay_p;
22798 else
22799 {
22800 arg = Fprefix_numeric_value (arg);
22801 trace_redisplay_p = XFIXNUM (arg) > 0;
22802 }
22803
22804 return Qnil;
22805 }
22806
22807
22808 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
22809 doc:
22810 )
22811 (ptrdiff_t nargs, Lisp_Object *args)
22812 {
22813 Lisp_Object s = Fformat (nargs, args);
22814 fwrite (SDATA (s), 1, SBYTES (s), stderr);
22815 return Qnil;
22816 }
22817
22818 #endif
22819
22820
22821
22822
22823
22824
22825
22826
22827
22828
22829
22830 static struct glyph_row *
22831 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
22832 {
22833 struct frame *f = XFRAME (WINDOW_FRAME (w));
22834 struct buffer *buffer = XBUFFER (w->contents);
22835 struct buffer *old = current_buffer;
22836 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
22837 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
22838 const unsigned char *arrow_end = arrow_string + arrow_len;
22839 const unsigned char *p;
22840 struct it it;
22841 bool multibyte_p;
22842 int n_glyphs_before;
22843
22844 set_buffer_temp (buffer);
22845 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
22846 scratch_glyph_row.reversed_p = false;
22847 it.glyph_row->used[TEXT_AREA] = 0;
22848 SET_TEXT_POS (it.position, 0, 0);
22849
22850 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
22851 p = arrow_string;
22852 while (p < arrow_end)
22853 {
22854 Lisp_Object face, ilisp;
22855
22856
22857 if (multibyte_p)
22858 it.c = it.char_to_display = check_char_and_length (p, &it.len);
22859 else
22860 {
22861 it.c = it.char_to_display = *p, it.len = 1;
22862 if (! ASCII_CHAR_P (it.c))
22863 it.char_to_display = BYTE8_TO_CHAR (it.c);
22864 }
22865 p += it.len;
22866
22867
22868 ilisp = make_fixnum (char_num++);
22869 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
22870 it.face_id = compute_char_face (f, it.char_to_display, face);
22871
22872
22873 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
22874 SET_TEXT_POS (it.position, -1, -1);
22875 PRODUCE_GLYPHS (&it);
22876
22877
22878
22879 if (it.current_x > it.last_visible_x)
22880 {
22881 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
22882 break;
22883 }
22884 }
22885
22886 set_buffer_temp (old);
22887 return it.glyph_row;
22888 }
22889
22890
22891
22892
22893
22894 static void
22895 insert_left_trunc_glyphs (struct it *it)
22896 {
22897 struct it truncate_it;
22898 struct glyph *from, *end, *to, *toend;
22899
22900 eassert (!FRAME_WINDOW_P (it->f)
22901 || (!it->glyph_row->reversed_p
22902 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
22903 || (it->glyph_row->reversed_p
22904 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
22905
22906
22907 truncate_it = *it;
22908 truncate_it.current_x = 0;
22909 truncate_it.face_id = DEFAULT_FACE_ID;
22910 truncate_it.glyph_row = &scratch_glyph_row;
22911 truncate_it.area = TEXT_AREA;
22912 truncate_it.glyph_row->used[TEXT_AREA] = 0;
22913 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
22914 truncate_it.object = Qnil;
22915 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
22916
22917
22918 if (!it->glyph_row->reversed_p)
22919 {
22920 short tused = truncate_it.glyph_row->used[TEXT_AREA];
22921
22922 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
22923 end = from + tused;
22924 to = it->glyph_row->glyphs[TEXT_AREA];
22925 toend = to + it->glyph_row->used[TEXT_AREA];
22926 if (FRAME_WINDOW_P (it->f))
22927 {
22928
22929
22930
22931
22932
22933
22934
22935 int w = 0;
22936 struct glyph *g = to;
22937 short used;
22938
22939
22940
22941
22942
22943
22944 it->glyph_row->x = 0;
22945 while (g < toend && w < it->truncation_pixel_width)
22946 {
22947 w += g->pixel_width;
22948 ++g;
22949 }
22950 if (g - to - tused > 0)
22951 {
22952 memmove (to + tused, g, (toend - g) * sizeof(*g));
22953 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
22954 }
22955 used = it->glyph_row->used[TEXT_AREA];
22956 if (it->glyph_row->truncated_on_right_p
22957 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
22958 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
22959 == STRETCH_GLYPH)
22960 {
22961 int extra = w - it->truncation_pixel_width;
22962
22963 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
22964 }
22965 }
22966
22967 while (from < end)
22968 *to++ = *from++;
22969
22970
22971 if (!FRAME_WINDOW_P (it->f))
22972 {
22973 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
22974 {
22975 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
22976 while (from < end)
22977 *to++ = *from++;
22978 }
22979 }
22980
22981 if (to > toend)
22982 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
22983 }
22984 else
22985 {
22986 short tused = truncate_it.glyph_row->used[TEXT_AREA];
22987
22988
22989
22990 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
22991 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
22992 toend = it->glyph_row->glyphs[TEXT_AREA];
22993 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
22994 if (FRAME_WINDOW_P (it->f))
22995 {
22996 int w = 0;
22997 struct glyph *g = to;
22998
22999 while (g >= toend && w < it->truncation_pixel_width)
23000 {
23001 w += g->pixel_width;
23002 --g;
23003 }
23004 if (to - g - tused > 0)
23005 to = g + tused;
23006 if (it->glyph_row->truncated_on_right_p
23007 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
23008 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
23009 {
23010 int extra = w - it->truncation_pixel_width;
23011
23012 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
23013 }
23014 }
23015
23016 while (from >= end && to >= toend)
23017 *to-- = *from--;
23018 if (!FRAME_WINDOW_P (it->f))
23019 {
23020 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
23021 {
23022 from =
23023 truncate_it.glyph_row->glyphs[TEXT_AREA]
23024 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23025 while (from >= end && to >= toend)
23026 *to-- = *from--;
23027 }
23028 }
23029 if (from >= end)
23030 {
23031
23032
23033 int move_by = from - end + 1;
23034 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
23035 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
23036
23037 for ( ; g >= g0; g--)
23038 g[move_by] = *g;
23039 while (from >= end)
23040 *to-- = *from--;
23041 it->glyph_row->used[TEXT_AREA] += move_by;
23042 }
23043 }
23044 }
23045
23046
23047 unsigned
23048 row_hash (struct glyph_row *row)
23049 {
23050 int area, k;
23051 unsigned hashval = 0;
23052
23053 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23054 for (k = 0; k < row->used[area]; ++k)
23055 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23056 + row->glyphs[area][k].u.val
23057 + row->glyphs[area][k].face_id
23058 + row->glyphs[area][k].padding_p
23059 + (row->glyphs[area][k].type << 2));
23060
23061 return hashval;
23062 }
23063
23064
23065
23066
23067
23068
23069
23070
23071
23072
23073
23074
23075
23076
23077
23078
23079
23080
23081 static void
23082 compute_line_metrics (struct it *it)
23083 {
23084 struct glyph_row *row = it->glyph_row;
23085
23086 if (FRAME_WINDOW_P (it->f))
23087 {
23088 int i, min_y, max_y;
23089
23090
23091
23092
23093 if (row->height == 0)
23094 {
23095 if (it->max_ascent + it->max_descent == 0)
23096 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23097 row->ascent = it->max_ascent;
23098 row->height = it->max_ascent + it->max_descent;
23099 row->phys_ascent = it->max_phys_ascent;
23100 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23101 row->extra_line_spacing = it->max_extra_line_spacing;
23102 }
23103
23104
23105 row->pixel_width = row->x;
23106 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23107 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23108
23109 eassert (row->pixel_width >= 0);
23110 eassert (row->ascent >= 0 && row->height > 0);
23111
23112 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23113 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23114
23115
23116
23117
23118 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23119 && row->phys_ascent > row->ascent)
23120 {
23121 row->height += row->phys_ascent - row->ascent;
23122 row->ascent = row->phys_ascent;
23123 }
23124
23125
23126 row->visible_height = row->height;
23127
23128 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23129 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23130
23131 if (row->y < min_y)
23132 row->visible_height -= min_y - row->y;
23133 if (row->y + row->height > max_y)
23134 row->visible_height -= row->y + row->height - max_y;
23135 }
23136 else
23137 {
23138 row->pixel_width = row->used[TEXT_AREA];
23139 if (row->continued_p)
23140 row->pixel_width -= it->continuation_pixel_width;
23141 else if (row->truncated_on_right_p)
23142 row->pixel_width -= it->truncation_pixel_width;
23143 row->ascent = row->phys_ascent = 0;
23144 row->height = row->phys_height = row->visible_height = 1;
23145 row->extra_line_spacing = 0;
23146 }
23147
23148
23149 row->hash = row_hash (row);
23150
23151 it->max_ascent = it->max_descent = 0;
23152 it->max_phys_ascent = it->max_phys_descent = 0;
23153 }
23154
23155
23156 static void
23157 clear_position (struct it *it)
23158 {
23159 it->position.charpos = 0;
23160 it->position.bytepos = 0;
23161 }
23162
23163
23164
23165
23166
23167
23168
23169
23170
23171
23172
23173
23174
23175 static bool
23176 append_space_for_newline (struct it *it, bool default_face_p)
23177 {
23178 int n = it->glyph_row->used[TEXT_AREA];
23179
23180 if (it->glyph_row->glyphs[TEXT_AREA] + n
23181 < it->glyph_row->glyphs[1 + TEXT_AREA])
23182 {
23183
23184
23185
23186
23187 enum display_element_type saved_what = it->what;
23188 int saved_c = it->c, saved_len = it->len;
23189 int saved_char_to_display = it->char_to_display;
23190 int saved_x = it->current_x;
23191 const int saved_face_id = it->face_id;
23192 bool saved_box_end = it->end_of_box_run_p;
23193 struct text_pos saved_pos = it->position;
23194 Lisp_Object saved_object = it->object;
23195 struct face *face;
23196
23197 it->what = IT_CHARACTER;
23198 clear_position (it);
23199 it->object = Qnil;
23200 it->len = 1;
23201
23202 int char_width = 1;
23203
23204 if (default_face_p
23205 #ifdef HAVE_WINDOW_SYSTEM
23206 || FRAME_WINDOW_P (it->f)
23207 #endif
23208 )
23209 {
23210 const int local_default_face_id =
23211 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23212
23213 #ifdef HAVE_WINDOW_SYSTEM
23214 if (FRAME_WINDOW_P (it->f))
23215 {
23216 struct face *default_face
23217 = FACE_FROM_ID (it->f, local_default_face_id);
23218 struct font *font = (default_face->font
23219 ? default_face->font
23220 : FRAME_FONT (it->f));
23221 char_width = (font->average_width
23222 ? font->average_width
23223 : font->space_width);
23224 }
23225 #endif
23226 if (default_face_p)
23227 it->face_id = local_default_face_id;
23228 }
23229
23230
23231
23232
23233 const int indicator_column =
23234 fill_column_indicator_column (it, char_width);
23235 int saved_end_of_box_run = it->end_of_box_run_p;
23236 bool should_keep_end_of_box_run = false;
23237
23238 if (it->current_x == indicator_column)
23239 {
23240 it->c = it->char_to_display
23241 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23242 it->face_id
23243 = merge_faces (it->w, Qfill_column_indicator,
23244 0, saved_face_id);
23245 face = FACE_FROM_ID (it->f, it->face_id);
23246 }
23247 else
23248 {
23249 it->c = it->char_to_display = ' ';
23250
23251
23252
23253 face = FACE_FROM_ID (it->f, it->face_id);
23254 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23255
23256
23257
23258
23259 if (!(it->glyph_row->reversed_p
23260
23261
23262
23263 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23264 should_keep_end_of_box_run = true;
23265 }
23266 PRODUCE_GLYPHS (it);
23267
23268
23269 if (should_keep_end_of_box_run)
23270 it->end_of_box_run_p = saved_end_of_box_run;
23271 #ifdef HAVE_WINDOW_SYSTEM
23272 if (FRAME_WINDOW_P (it->f))
23273 {
23274
23275
23276
23277 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23278 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23279 if (n == 0)
23280 {
23281 Lisp_Object height, total_height;
23282 int extra_line_spacing = it->extra_line_spacing;
23283 int boff = font->baseline_offset;
23284
23285 if (font->vertical_centering)
23286 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23287
23288 it->object = saved_object;
23289 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23290
23291
23292 height = get_it_property (it, Qline_height);
23293 if (CONSP (height)
23294 && CONSP (XCDR (height))
23295 && NILP (XCDR (XCDR (height))))
23296 {
23297 total_height = XCAR (XCDR (height));
23298 height = XCAR (height);
23299 }
23300 else
23301 total_height = Qnil;
23302 height = calc_line_height_property (it, height, font, boff, true);
23303
23304 if (it->override_ascent >= 0)
23305 {
23306 it->ascent = it->override_ascent;
23307 it->descent = it->override_descent;
23308 boff = it->override_boff;
23309 }
23310 if (EQ (height, Qt))
23311 extra_line_spacing = 0;
23312 else
23313 {
23314 Lisp_Object spacing;
23315
23316 it->phys_ascent = it->ascent;
23317 it->phys_descent = it->descent;
23318 if (!NILP (height)
23319 && XFIXNUM (height) > it->ascent + it->descent)
23320 it->ascent = XFIXNUM (height) - it->descent;
23321
23322 if (!NILP (total_height))
23323 spacing = calc_line_height_property (it, total_height, font,
23324 boff, false);
23325 else
23326 {
23327 spacing = get_it_property (it, Qline_spacing);
23328 spacing = calc_line_height_property (it, spacing, font,
23329 boff, false);
23330 }
23331 if (FIXNUMP (spacing))
23332 {
23333 extra_line_spacing = XFIXNUM (spacing);
23334 if (!NILP (total_height))
23335 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23336 }
23337 }
23338 if (extra_line_spacing > 0)
23339 {
23340 it->descent += extra_line_spacing;
23341 if (extra_line_spacing > it->max_extra_line_spacing)
23342 it->max_extra_line_spacing = extra_line_spacing;
23343 }
23344 it->max_ascent = it->ascent;
23345 it->max_descent = it->descent;
23346
23347 it->glyph_row->height = 0;
23348 }
23349
23350 g->ascent = it->max_ascent;
23351 g->descent = it->max_descent;
23352 }
23353 #endif
23354 it->override_ascent = -1;
23355 it->constrain_row_ascent_descent_p = false;
23356 it->current_x = saved_x;
23357 it->object = saved_object;
23358 it->position = saved_pos;
23359 it->what = saved_what;
23360 it->face_id = saved_face_id;
23361 it->len = saved_len;
23362 it->c = saved_c;
23363 it->char_to_display = saved_char_to_display;
23364 it->end_of_box_run_p = saved_box_end;
23365 return true;
23366 }
23367
23368 return false;
23369 }
23370
23371
23372
23373
23374
23375
23376
23377
23378
23379 static void
23380 extend_face_to_end_of_line (struct it *it)
23381 {
23382 struct frame *f = it->f;
23383
23384
23385
23386
23387
23388
23389 if ((it->current_x >= it->last_visible_x
23390 + (!FRAME_WINDOW_P (f)
23391 && it->glyph_row->reversed_p
23392 && !it->glyph_row->continued_p))
23393
23394
23395 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23396 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23397 return;
23398
23399 specpdl_ref count = SPECPDL_INDEX ();
23400
23401
23402
23403
23404 specbind (Qinhibit_quit, Qt);
23405
23406 struct face *default_face =
23407 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23408 if (!default_face)
23409 return;
23410
23411 const int extend_face_id =
23412 (it->face_id == default_face->id || it->s != NULL)
23413 ? it->face_id
23414 : (it->glyph_row->ends_at_zv_p
23415 ? default_face->id
23416 : face_at_pos (it, LFACE_EXTEND_INDEX));
23417 unbind_to (count, Qnil);
23418
23419
23420
23421
23422 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23423 ? it->saved_face_id
23424 : extend_face_id));
23425
23426 if (FRAME_WINDOW_P (f)
23427 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23428 && face->box == FACE_NO_BOX
23429 && face->underline == FACE_NO_UNDERLINE
23430 && !face->overline_p
23431 && !face->strike_through_p
23432 && face->background == FRAME_BACKGROUND_PIXEL (f)
23433 #ifdef HAVE_WINDOW_SYSTEM
23434 && !face->stipple
23435 #endif
23436 && !it->glyph_row->reversed_p
23437 && !display_fill_column_indicator)
23438 return;
23439
23440
23441
23442 it->glyph_row->fill_line_p = true;
23443
23444 const int orig_face_id = it->face_id;
23445
23446
23447
23448
23449
23450 if (!ASCII_CHAR_P (it->c))
23451 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23452
23453
23454 #ifdef HAVE_WINDOW_SYSTEM
23455 if (FRAME_WINDOW_P (f))
23456 {
23457
23458
23459 if (it->glyph_row->used[TEXT_AREA] == 0)
23460 {
23461 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23462 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23463 it->glyph_row->used[TEXT_AREA] = 1;
23464 }
23465
23466
23467 if (!(it->glyph_row->mode_line_p
23468 || (WINDOWP (f->tab_bar_window)
23469 && it->w == XWINDOW (f->tab_bar_window))
23470 #ifndef HAVE_EXT_TOOL_BAR
23471 || (WINDOWP (f->tool_bar_window)
23472 && it->w == XWINDOW (f->tool_bar_window))
23473 #endif
23474 ))
23475 {
23476 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23477 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23478 {
23479 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23480 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23481 default_face->id;
23482 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23483 }
23484 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23485 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23486 {
23487 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23488 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23489 default_face->id;
23490 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23491 }
23492
23493 struct font *font = (default_face->font
23494 ? default_face->font
23495 : FRAME_FONT (f));
23496
23497 const int char_width = (font->average_width
23498 ? font->average_width
23499 : font->space_width);
23500
23501 const int indicator_column =
23502 fill_column_indicator_column (it, char_width);
23503
23504 const char saved_char = it->char_to_display;
23505 const struct text_pos saved_pos = it->position;
23506 const bool saved_avoid_cursor = it->avoid_cursor_p;
23507 const bool saved_box_start = it->start_of_box_run_p;
23508 Lisp_Object save_object = it->object;
23509 const int saved_face_id = it->face_id;
23510
23511 it->face_id = extend_face_id;
23512 it->avoid_cursor_p = true;
23513 it->object = Qnil;
23514
23515 const int stretch_height = it->ascent + it->descent;
23516 const int stretch_ascent =
23517 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23518
23519 if (indicator_column >= 0
23520 && indicator_column > it->current_x
23521 && indicator_column < it->last_visible_x)
23522 {
23523
23524
23525
23526
23527 const int stretch_width =
23528 indicator_column - it->current_x - char_width;
23529
23530 clear_position (it);
23531
23532
23533
23534 if (stretch_width > 0)
23535 {
23536 append_stretch_glyph (it, Qnil, stretch_width,
23537 stretch_height, stretch_ascent);
23538 }
23539
23540
23541
23542 if (it->current_x < indicator_column)
23543 {
23544 const int save_face_id = it->face_id;
23545 const int save_ascent = it->ascent;
23546 const int save_descent = it->descent;
23547 it->char_to_display
23548 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23549 it->face_id
23550 = merge_faces (it->w, Qfill_column_indicator,
23551 0, extend_face_id);
23552 PRODUCE_GLYPHS (it);
23553 it->face_id = save_face_id;
23554 it->ascent = save_ascent;
23555 it->descent = save_descent;
23556 }
23557 }
23558
23559
23560
23561 if (!it->glyph_row->reversed_p)
23562 {
23563 const int stretch_width = it->last_visible_x - it->current_x;
23564
23565 if (stretch_width > 0)
23566 {
23567 clear_position (it);
23568 append_stretch_glyph (it, Qnil, stretch_width,
23569 stretch_height, stretch_ascent);
23570 }
23571 }
23572
23573 it->char_to_display = saved_char;
23574 it->position = saved_pos;
23575 it->avoid_cursor_p = saved_avoid_cursor;
23576 it->start_of_box_run_p = saved_box_start;
23577 it->object = save_object;
23578 it->face_id = saved_face_id;
23579 }
23580 if (it->glyph_row->reversed_p)
23581 {
23582
23583
23584
23585
23586
23587 struct font *font = face->font ? face->font : FRAME_FONT (f);
23588 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23589 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23590 struct glyph *g;
23591 int row_width, stretch_ascent, stretch_width;
23592 struct text_pos saved_pos;
23593 int saved_face_id;
23594 bool saved_avoid_cursor, saved_box_start;
23595
23596 for (row_width = 0, g = row_start; g < row_end; g++)
23597 row_width += g->pixel_width;
23598
23599
23600
23601
23602 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23603 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23604 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23605 stretch_width = window_box_width (it->w, TEXT_AREA);
23606 else
23607 stretch_width = it->last_visible_x - it->first_visible_x;
23608 stretch_width -= row_width;
23609
23610 if (stretch_width > 0)
23611 {
23612 stretch_ascent =
23613 (((it->ascent + it->descent)
23614 * FONT_BASE (font)) / FONT_HEIGHT (font));
23615 saved_pos = it->position;
23616 clear_position (it);
23617 saved_avoid_cursor = it->avoid_cursor_p;
23618 it->avoid_cursor_p = true;
23619 saved_face_id = it->face_id;
23620 saved_box_start = it->start_of_box_run_p;
23621
23622
23623
23624 it->face_id = (it->glyph_row->ends_at_zv_p ?
23625 default_face->id : face->id);
23626
23627 it->start_of_box_run_p = false;
23628 append_stretch_glyph (it, Qnil, stretch_width,
23629 it->ascent + it->descent, stretch_ascent);
23630 it->position = saved_pos;
23631 it->avoid_cursor_p = saved_avoid_cursor;
23632 it->face_id = saved_face_id;
23633 it->start_of_box_run_p = saved_box_start;
23634 }
23635
23636
23637
23638
23639 if (stretch_width < 0)
23640 it->glyph_row->x = stretch_width;
23641 }
23642 it->face_id = orig_face_id;
23643 }
23644 else
23645 #endif
23646 {
23647
23648 int saved_x = it->current_x;
23649 struct text_pos saved_pos = it->position;
23650 Lisp_Object saved_object = it->object;;
23651 enum display_element_type saved_what = it->what;
23652
23653 it->what = IT_CHARACTER;
23654 clear_position (it);
23655 it->object = Qnil;
23656 it->c = it->char_to_display = ' ';
23657 it->len = 1;
23658
23659 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23660 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23661 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23662 && !it->glyph_row->mode_line_p
23663 && face->background != FRAME_BACKGROUND_PIXEL (f))
23664 {
23665 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23666 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23667
23668 for (it->current_x = 0; g < e; g++)
23669 it->current_x += g->pixel_width;
23670
23671 it->area = LEFT_MARGIN_AREA;
23672 it->face_id = default_face->id;
23673 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23674 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23675 && g < it->glyph_row->glyphs[TEXT_AREA])
23676 {
23677 PRODUCE_GLYPHS (it);
23678
23679
23680 it->current_x += it->pixel_width;
23681 g++;
23682 }
23683
23684 it->current_x = saved_x;
23685 it->area = TEXT_AREA;
23686 }
23687
23688
23689
23690
23691 it->face_id = (it->glyph_row->ends_at_zv_p ?
23692 default_face->id : face->id);
23693
23694
23695
23696
23697
23698 it->current_x = it->glyph_row->used[TEXT_AREA];
23699
23700
23701
23702
23703
23704
23705
23706
23707 const int indicator_column =
23708 fill_column_indicator_column (it, 1) - it->first_visible_x;
23709
23710
23711 while (it->current_x <= it->last_visible_x)
23712 {
23713 if (it->current_x != indicator_column)
23714 PRODUCE_GLYPHS (it);
23715 else
23716 {
23717 int saved_face_id = it->face_id;
23718 it->face_id
23719 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23720 it->c = it->char_to_display
23721 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23722
23723 PRODUCE_GLYPHS (it);
23724
23725 it->face_id = saved_face_id;
23726 it->c = it->char_to_display = ' ';
23727 }
23728 }
23729
23730 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23731 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23732 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23733 && !it->glyph_row->mode_line_p
23734 && face->background != FRAME_BACKGROUND_PIXEL (f))
23735 {
23736 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23737 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23738
23739 for ( ; g < e; g++)
23740 it->current_x += g->pixel_width;
23741
23742 it->area = RIGHT_MARGIN_AREA;
23743 it->face_id = default_face->id;
23744 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23745 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23746 && g < it->glyph_row->glyphs[LAST_AREA])
23747 {
23748 PRODUCE_GLYPHS (it);
23749 it->current_x += it->pixel_width;
23750 g++;
23751 }
23752
23753 it->area = TEXT_AREA;
23754 }
23755
23756
23757
23758 it->current_x = saved_x;
23759 it->object = saved_object;
23760 it->position = saved_pos;
23761 it->what = saved_what;
23762 it->face_id = orig_face_id;
23763 }
23764 }
23765
23766
23767
23768
23769
23770 static bool
23771 trailing_whitespace_p (ptrdiff_t charpos)
23772 {
23773 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23774 int c = 0;
23775
23776 while (bytepos < ZV_BYTE
23777 && (c = FETCH_BYTE (bytepos),
23778 c == ' ' || c == '\t'))
23779 ++bytepos;
23780
23781 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23782 {
23783 if (bytepos != PT_BYTE)
23784 return true;
23785 }
23786 return false;
23787 }
23788
23789
23790
23791
23792 static void
23793 highlight_trailing_whitespace (struct it *it)
23794 {
23795 struct glyph_row *row = it->glyph_row;
23796 int used = row->used[TEXT_AREA];
23797
23798 if (used)
23799 {
23800 struct glyph *start = row->glyphs[TEXT_AREA];
23801 struct glyph *glyph = start + used - 1;
23802
23803 if (row->reversed_p)
23804 {
23805
23806
23807 glyph = start;
23808 start = row->glyphs[TEXT_AREA] + used - 1;
23809 }
23810
23811
23812
23813
23814
23815 if (!row->reversed_p)
23816 {
23817 while (glyph >= start
23818 && (glyph->type == CHAR_GLYPH
23819 || glyph->type == STRETCH_GLYPH)
23820 && NILP (glyph->object))
23821 --glyph;
23822 }
23823 else
23824 {
23825 while (glyph <= start
23826 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
23827 && NILP (glyph->object))
23828 ++glyph;
23829 }
23830
23831
23832
23833
23834 if ((row->reversed_p ? glyph <= start : glyph >= start)
23835 && BUFFERP (glyph->object)
23836 && (glyph->type == STRETCH_GLYPH
23837 || (glyph->type == CHAR_GLYPH
23838 && glyph->u.ch == ' '))
23839 && trailing_whitespace_p (glyph->charpos))
23840 {
23841 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
23842 if (face_id < 0)
23843 return;
23844
23845 if (!row->reversed_p)
23846 {
23847 while (glyph >= start
23848 && BUFFERP (glyph->object)
23849 && (glyph->type == STRETCH_GLYPH
23850 || (glyph->type == CHAR_GLYPH
23851 && glyph->u.ch == ' ')))
23852 (glyph--)->face_id = face_id;
23853 }
23854 else
23855 {
23856 while (glyph <= start
23857 && BUFFERP (glyph->object)
23858 && (glyph->type == STRETCH_GLYPH
23859 || (glyph->type == CHAR_GLYPH
23860 && glyph->u.ch == ' ')))
23861 (glyph++)->face_id = face_id;
23862 }
23863 }
23864 }
23865 }
23866
23867
23868
23869
23870
23871 static bool
23872 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
23873 {
23874 bool result = true;
23875
23876 if (charpos == CHARPOS (row->end.pos)
23877 || charpos == MATRIX_ROW_END_CHARPOS (row))
23878 {
23879
23880
23881
23882
23883
23884
23885
23886
23887 if (CHARPOS (row->end.string_pos) >= 0)
23888 {
23889 if (row->continued_p)
23890 result = true;
23891 else
23892 {
23893
23894 struct glyph *beg = row->glyphs[TEXT_AREA];
23895 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
23896 struct glyph *glyph;
23897
23898 result = false;
23899 for (glyph = end; glyph >= beg; --glyph)
23900 if (STRINGP (glyph->object))
23901 {
23902 Lisp_Object prop
23903 = Fget_char_property (make_fixnum (charpos),
23904 Qdisplay, Qnil);
23905 result =
23906 (!NILP (prop)
23907 && display_prop_string_p (prop, glyph->object));
23908
23909
23910
23911 if (!result)
23912 {
23913 Lisp_Object s = glyph->object;
23914
23915 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
23916 {
23917 ptrdiff_t gpos = glyph->charpos;
23918
23919 if (!NILP (Fget_char_property (make_fixnum (gpos),
23920 Qcursor, s)))
23921 {
23922 result = true;
23923 break;
23924 }
23925 }
23926 }
23927 break;
23928 }
23929 }
23930 }
23931 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
23932 {
23933
23934
23935
23936
23937 if (!row->ends_in_ellipsis_p)
23938 result = row->continued_p;
23939 else
23940
23941
23942
23943
23944 result = false;
23945 }
23946
23947
23948 else
23949 result = row->ends_at_zv_p;
23950 }
23951
23952 return result;
23953 }
23954
23955
23956
23957
23958 static bool
23959 cursor_row_p (struct glyph_row *row)
23960 {
23961 return row_for_charpos_p (row, PT);
23962 }
23963
23964
23965
23966
23967
23968
23969
23970
23971 static bool
23972 push_prefix_prop (struct it *it, Lisp_Object prop)
23973 {
23974 struct text_pos pos =
23975 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
23976
23977 eassert (it->method == GET_FROM_BUFFER
23978 || it->method == GET_FROM_DISPLAY_VECTOR
23979 || it->method == GET_FROM_STRING
23980 || it->method == GET_FROM_IMAGE);
23981
23982
23983
23984
23985
23986 push_it (it, &pos);
23987
23988 if (STRINGP (prop))
23989 {
23990 if (SCHARS (prop) == 0)
23991 {
23992 pop_it (it);
23993 return false;
23994 }
23995
23996 it->string = prop;
23997 it->string_from_prefix_prop_p = true;
23998 it->multibyte_p = STRING_MULTIBYTE (it->string);
23999 it->current.overlay_string_index = -1;
24000 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
24001 it->end_charpos = it->string_nchars = SCHARS (it->string);
24002 it->method = GET_FROM_STRING;
24003 it->stop_charpos = 0;
24004 it->prev_stop = 0;
24005 it->base_level_stop = 0;
24006 it->cmp_it.id = -1;
24007
24008
24009
24010 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
24011 it->paragraph_embedding = it->bidi_it.paragraph_dir;
24012 else
24013 it->paragraph_embedding = L2R;
24014
24015
24016 if (it->bidi_p)
24017 {
24018 it->bidi_it.string.lstring = it->string;
24019 it->bidi_it.string.s = NULL;
24020 it->bidi_it.string.schars = it->end_charpos;
24021 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
24022 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
24023 it->bidi_it.string.unibyte = !it->multibyte_p;
24024 it->bidi_it.w = it->w;
24025 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
24026 }
24027 }
24028 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
24029 {
24030 it->method = GET_FROM_STRETCH;
24031 it->object = prop;
24032 }
24033 #ifdef HAVE_WINDOW_SYSTEM
24034 else if (IMAGEP (prop))
24035 {
24036 it->what = IT_IMAGE;
24037 it->image_id = lookup_image (it->f, prop, it->face_id);
24038 it->method = GET_FROM_IMAGE;
24039 }
24040 #endif
24041 else
24042 {
24043 pop_it (it);
24044 return false;
24045 }
24046
24047 return true;
24048 }
24049
24050
24051
24052 static Lisp_Object
24053 get_it_property (struct it *it, Lisp_Object prop)
24054 {
24055 Lisp_Object position, object = it->object;
24056
24057 if (STRINGP (object))
24058 position = make_fixnum (IT_STRING_CHARPOS (*it));
24059 else if (BUFFERP (object))
24060 {
24061 position = make_fixnum (IT_CHARPOS (*it));
24062 object = it->window;
24063 }
24064 else
24065 return Qnil;
24066
24067 return Fget_char_property (position, prop, object);
24068 }
24069
24070
24071
24072
24073 static Lisp_Object
24074 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24075 {
24076 Lisp_Object prefix = get_it_property (it, prop);
24077
24078
24079
24080 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24081 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24082 it->w->contents);
24083 return prefix;
24084 }
24085
24086
24087
24088 static void
24089 handle_line_prefix (struct it *it)
24090 {
24091 Lisp_Object prefix;
24092
24093 if (it->continuation_lines_width > 0)
24094 {
24095 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24096 if (NILP (prefix))
24097 prefix = Vwrap_prefix;
24098 }
24099 else
24100 {
24101 prefix = get_line_prefix_it_property (it, Qline_prefix);
24102 if (NILP (prefix))
24103 prefix = Vline_prefix;
24104 }
24105 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24106 {
24107
24108
24109
24110 it->line_wrap = TRUNCATE;
24111 it->avoid_cursor_p = true;
24112 }
24113 }
24114
24115
24116
24117
24118
24119
24120
24121 static void
24122 unproduce_glyphs (struct it *it, int n)
24123 {
24124 struct glyph *glyph, *end;
24125
24126 eassert (it->glyph_row);
24127 eassert (it->glyph_row->reversed_p);
24128 eassert (it->area == TEXT_AREA);
24129 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24130
24131 if (n > it->glyph_row->used[TEXT_AREA])
24132 n = it->glyph_row->used[TEXT_AREA];
24133 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24134 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24135 for ( ; glyph < end; glyph++)
24136 glyph[-n] = *glyph;
24137 }
24138
24139
24140
24141 static void
24142 find_row_edges (struct it *it, struct glyph_row *row,
24143 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24144 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24145 {
24146
24147
24148
24149
24150
24151 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24152 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24153 else
24154
24155
24156
24157 row->minpos = row->start.pos;
24158 if (max_pos <= 0)
24159 {
24160 max_pos = CHARPOS (it->current.pos);
24161 max_bpos = BYTEPOS (it->current.pos);
24162 }
24163
24164
24165
24166
24167
24168
24169
24170
24171
24172
24173
24174
24175
24176
24177
24178
24179
24180 if (row->ends_at_zv_p)
24181 row->maxpos = it->current.pos;
24182 else if (row->used[TEXT_AREA])
24183 {
24184 bool seen_this_string = false;
24185 struct glyph_row *r1 = row - 1;
24186
24187
24188 if (STRINGP (it->object)
24189
24190 && row > it->w->desired_matrix->rows
24191
24192 && !r1->mode_line_p
24193
24194 && r1->ends_in_newline_from_string_p)
24195 {
24196 struct glyph *start, *end;
24197
24198
24199
24200
24201
24202 if (!r1->reversed_p)
24203 {
24204 start = r1->glyphs[TEXT_AREA];
24205 end = start + r1->used[TEXT_AREA];
24206
24207 while (end > start
24208 && NILP ((end - 1)->object)
24209 && (end - 1)->charpos <= 0)
24210 --end;
24211 if (end > start)
24212 {
24213 if (EQ ((end - 1)->object, it->object))
24214 seen_this_string = true;
24215 }
24216 else
24217
24218
24219
24220
24221
24222 seen_this_string = true;
24223 }
24224 else
24225 {
24226 end = r1->glyphs[TEXT_AREA] - 1;
24227 start = end + r1->used[TEXT_AREA];
24228 while (end < start
24229 && NILP ((end + 1)->object)
24230 && (end + 1)->charpos <= 0)
24231 ++end;
24232 if (end < start)
24233 {
24234 if (EQ ((end + 1)->object, it->object))
24235 seen_this_string = true;
24236 }
24237 else
24238 seen_this_string = true;
24239 }
24240 }
24241
24242
24243
24244 if (row->ends_in_newline_from_string_p && !seen_this_string)
24245 {
24246
24247
24248
24249
24250
24251
24252
24253
24254 if (CHARPOS (row->end.pos) > max_pos)
24255 inc_both (&max_pos, &max_bpos);
24256 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24257 }
24258 else if (CHARPOS (it->eol_pos) > 0)
24259 SET_TEXT_POS (row->maxpos,
24260 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24261 else if (row->continued_p)
24262 {
24263
24264
24265
24266
24267
24268
24269 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24270 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24271 else
24272 {
24273 inc_both (&max_pos, &max_bpos);
24274 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24275 }
24276 }
24277 else if (row->truncated_on_right_p)
24278
24279
24280
24281 row->maxpos = it->current.pos;
24282 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24283
24284 row->maxpos = row->minpos;
24285 else
24286 emacs_abort ();
24287 }
24288 else
24289 row->maxpos = it->current.pos;
24290 }
24291
24292
24293
24294 static ptrdiff_t
24295 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24296 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24297 {
24298 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24299 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24300
24301 ptrdiff_t val;
24302 specpdl_ref pdl_count = SPECPDL_INDEX ();
24303 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24304 labeled_restrictions_remove_in_current_buffer ();
24305 Fwiden ();
24306 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24307 unbind_to (pdl_count, Qnil);
24308 return val;
24309 }
24310
24311
24312
24313 static ptrdiff_t
24314 display_count_lines_visually (struct it *it)
24315 {
24316 struct it tem_it;
24317 ptrdiff_t to;
24318 struct text_pos from;
24319
24320
24321
24322
24323
24324
24325 if (it->lnum_bytepos > 0)
24326 return it->lnum + 1;
24327 else
24328 {
24329 specpdl_ref count = SPECPDL_INDEX ();
24330
24331 if (IT_CHARPOS (*it) <= PT)
24332 {
24333 from = it->current.pos;
24334 to = PT;
24335 }
24336 else
24337 {
24338 SET_TEXT_POS (from, PT, PT_BYTE);
24339 to = IT_CHARPOS (*it);
24340 }
24341
24342
24343
24344 specbind (Qdisplay_line_numbers, Qrelative);
24345 start_display (&tem_it, it->w, from);
24346
24347
24348
24349
24350 move_it_to (&tem_it, to, -1,
24351 tem_it.last_visible_y
24352 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24353 -1, MOVE_TO_POS | MOVE_TO_Y);
24354 unbind_to (count, Qnil);
24355 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24356 }
24357 }
24358
24359
24360
24361
24362 static void
24363 maybe_produce_line_number (struct it *it)
24364 {
24365 ptrdiff_t last_line = it->lnum;
24366 ptrdiff_t start_from, bytepos;
24367 ptrdiff_t this_line;
24368 bool first_time = false;
24369 ptrdiff_t beg_byte;
24370 ptrdiff_t z_byte;
24371 bool line_numbers_wide;
24372 void *itdata = bidi_shelve_cache ();
24373
24374 if (display_line_numbers_offset
24375 && !display_line_numbers_widen
24376 && !EQ (Vdisplay_line_numbers, Qvisual)
24377 && !EQ (Vdisplay_line_numbers, Qrelative))
24378 line_numbers_wide = true;
24379 else
24380 line_numbers_wide = display_line_numbers_widen;
24381
24382 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24383 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24384
24385 if (EQ (Vdisplay_line_numbers, Qvisual))
24386 this_line = display_count_lines_visually (it);
24387 else
24388 {
24389 if (!last_line)
24390 {
24391
24392 if (it->w->base_line_number > 0
24393 && it->w->base_line_pos > 0
24394 && it->w->base_line_pos <= IT_CHARPOS (*it)
24395
24396
24397
24398
24399 && !(line_numbers_wide
24400 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24401 && !current_buffer->clip_changed)
24402 {
24403 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24404 last_line = it->w->base_line_number - 1;
24405 }
24406 else
24407 start_from = beg_byte;
24408 if (!it->lnum_bytepos)
24409 first_time = true;
24410 }
24411 else
24412 start_from = it->lnum_bytepos;
24413
24414
24415
24416
24417 if (!(beg_byte <= start_from && start_from <= z_byte))
24418 {
24419 last_line = 0;
24420 start_from = beg_byte;
24421 }
24422
24423 this_line =
24424 last_line + display_count_lines_logically (start_from,
24425 IT_BYTEPOS (*it),
24426 IT_CHARPOS (*it), &bytepos);
24427 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24428 eassert (bytepos == IT_BYTEPOS (*it));
24429 }
24430
24431
24432 if (this_line != last_line || !it->lnum_bytepos)
24433 {
24434 it->lnum = this_line;
24435 it->lnum_bytepos = IT_BYTEPOS (*it);
24436 }
24437
24438
24439 struct it tem_it;
24440 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24441 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24442 ptrdiff_t lnum_offset = -1;
24443 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24444 int current_lnum_face_id
24445 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24446
24447
24448 bool save_free_realized_faces = inhibit_free_realized_faces;
24449 inhibit_free_realized_faces = true;
24450
24451 if ((EQ (Vdisplay_line_numbers, Qrelative)
24452 || EQ (Vdisplay_line_numbers, Qvisual)
24453 || lnum_face_id != current_lnum_face_id)
24454 && !it->pt_lnum)
24455 {
24456 ptrdiff_t ignored;
24457 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24458 it->pt_lnum =
24459 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24460 PT, &ignored);
24461 else
24462 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24463 &ignored);
24464 }
24465
24466 if (!it->lnum_width)
24467 {
24468 if (FIXNATP (Vdisplay_line_numbers_width))
24469 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24470
24471
24472
24473 ptrdiff_t max_lnum;
24474
24475 if (NILP (Vdisplay_line_numbers_current_absolute)
24476 && (EQ (Vdisplay_line_numbers, Qrelative)
24477 || EQ (Vdisplay_line_numbers, Qvisual)))
24478
24479
24480 max_lnum = it->w->desired_matrix->nrows - 2;
24481 else if (EQ (Vdisplay_line_numbers, Qvisual))
24482 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24483 else
24484 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24485 max_lnum = max (1, max_lnum);
24486 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24487 eassert (it->lnum_width > 0);
24488 }
24489 if (EQ (Vdisplay_line_numbers, Qrelative))
24490 lnum_offset = it->pt_lnum;
24491 else if (EQ (Vdisplay_line_numbers, Qvisual))
24492 lnum_offset = 0;
24493 else if (display_line_numbers_offset)
24494 lnum_offset -= display_line_numbers_offset;
24495
24496
24497
24498 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24499 if ((EQ (Vdisplay_line_numbers, Qrelative)
24500 || EQ (Vdisplay_line_numbers, Qvisual))
24501 && lnum_to_display == 0
24502 && !NILP (Vdisplay_line_numbers_current_absolute))
24503 lnum_to_display = it->pt_lnum + 1;
24504
24505
24506
24507
24508
24509 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24510 strcat (lnum_buf, " ");
24511
24512
24513 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24514
24515 DEFAULT_FACE_ID);
24516 scratch_glyph_row.reversed_p = false;
24517 scratch_glyph_row.used[TEXT_AREA] = 0;
24518 SET_TEXT_POS (tem_it.position, 0, 0);
24519 tem_it.avoid_cursor_p = true;
24520 tem_it.bidi_p = true;
24521 tem_it.bidi_it.type = WEAK_EN;
24522
24523
24524
24525 tem_it.bidi_it.resolved_level = 2;
24526
24527
24528
24529 int width_limit =
24530 tem_it.last_visible_x - tem_it.first_visible_x
24531 - 3 * FRAME_COLUMN_WIDTH (it->f);
24532
24533 tem_it.face_id = lnum_face_id;
24534
24535
24536 if (lnum_face_id != current_lnum_face_id
24537 && (EQ (Vdisplay_line_numbers, Qvisual)
24538 ? this_line == 0
24539 : this_line == it->pt_lnum)
24540 && it->what != IT_EOB)
24541 tem_it.face_id = current_lnum_face_id;
24542 else if (!beyond_zv)
24543 {
24544 if (display_line_numbers_major_tick > 0
24545 && (lnum_to_display % display_line_numbers_major_tick == 0))
24546 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24547 0, DEFAULT_FACE_ID);
24548 else if (display_line_numbers_minor_tick > 0
24549 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24550 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24551 0, DEFAULT_FACE_ID);
24552 }
24553
24554
24555 for (const char *p = lnum_buf; *p; p++)
24556 {
24557
24558
24559 if (beyond_zv
24560
24561 || (!EQ (Vdisplay_line_numbers, Qvisual)
24562 && (it->continuation_lines_width > 0
24563 || (this_line == last_line && !first_time))))
24564 tem_it.c = tem_it.char_to_display = ' ';
24565 else
24566 tem_it.c = tem_it.char_to_display = *p;
24567 tem_it.len = 1;
24568
24569 SET_TEXT_POS (tem_it.position, -1, -1);
24570 PRODUCE_GLYPHS (&tem_it);
24571
24572
24573
24574 if (tem_it.current_x >= width_limit)
24575 {
24576 it->lnum_width = 0;
24577 it->lnum_pixel_width = 0;
24578 bidi_unshelve_cache (itdata, false);
24579 inhibit_free_realized_faces = save_free_realized_faces;
24580 return;
24581 }
24582 }
24583
24584 inhibit_free_realized_faces = save_free_realized_faces;
24585
24586
24587 it->lnum_pixel_width = tem_it.current_x;
24588
24589 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24590 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24591 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24592 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24593
24594 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24595
24596 for ( ; g < e; g++)
24597 {
24598 it->current_x += g->pixel_width;
24599
24600
24601
24602 if (it->current_x > it->first_visible_x)
24603 it->hpos++;
24604 if (p)
24605 {
24606 *p++ = *g;
24607 (*u)++;
24608 }
24609 }
24610
24611
24612
24613
24614 if (!beyond_zv)
24615 {
24616 if (it->glyph_row)
24617 {
24618 struct glyph_row *row = it->glyph_row;
24619
24620 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24621 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24622 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24623 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24624 tem_it.max_phys_descent);
24625 }
24626 else
24627 {
24628 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24629 it->max_descent = max (it->max_descent, tem_it.max_descent);
24630 it->max_phys_ascent = max (it->max_phys_ascent,
24631 tem_it.max_phys_ascent);
24632 it->max_phys_descent = max (it->max_phys_descent,
24633 tem_it.max_phys_descent);
24634 }
24635 }
24636
24637 it->line_number_produced_p = true;
24638
24639 bidi_unshelve_cache (itdata, false);
24640 }
24641
24642
24643
24644 static bool
24645 should_produce_line_number (struct it *it)
24646 {
24647 if (NILP (Vdisplay_line_numbers))
24648 return false;
24649
24650
24651 if (MINI_WINDOW_P (it->w))
24652 return false;
24653
24654 #ifdef HAVE_WINDOW_SYSTEM
24655
24656 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24657 return false;
24658 #endif
24659
24660
24661
24662
24663
24664 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24665 Qdisplay_line_numbers_disable,
24666 it->window);
24667
24668
24669
24670 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24671 val = disable_line_numbers_overlay_at_eob ();
24672 return NILP (val) ? true : false;
24673 }
24674
24675
24676
24677
24678
24679 static bool
24680 row_text_area_empty (struct glyph_row *row)
24681 {
24682 if (!row->reversed_p)
24683 {
24684 for (struct glyph *g = row->glyphs[TEXT_AREA];
24685 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24686 g++)
24687 if (!NILP (g->object) || g->charpos > 0)
24688 return false;
24689 }
24690 else
24691 {
24692 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24693 g > row->glyphs[TEXT_AREA];
24694 g--)
24695 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24696 return false;
24697 }
24698
24699 return true;
24700 }
24701
24702
24703
24704
24705
24706
24707
24708
24709 static bool
24710 display_line (struct it *it, int cursor_vpos)
24711 {
24712 struct glyph_row *row = it->glyph_row;
24713 Lisp_Object overlay_arrow_string;
24714 struct it wrap_it;
24715 void *wrap_data = NULL;
24716 bool may_wrap = false;
24717 int wrap_x UNINIT;
24718 int wrap_row_used = -1;
24719 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24720 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24721 int wrap_row_extra_line_spacing UNINIT;
24722 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24723 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24724 int cvpos;
24725 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24726 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24727 bool pending_handle_line_prefix = false;
24728 int tab_line = window_wants_tab_line (it->w);
24729 int header_line = window_wants_header_line (it->w);
24730 bool hscroll_this_line = (cursor_vpos >= 0
24731 && it->vpos == cursor_vpos - tab_line - header_line
24732 && hscrolling_current_line_p (it->w));
24733 int first_visible_x = it->first_visible_x;
24734 int last_visible_x = it->last_visible_x;
24735 int x_incr = 0;
24736
24737
24738 eassert (it->hpos == 0 && it->current_x == 0);
24739
24740 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24741 >= it->w->desired_matrix->nrows)
24742 {
24743 it->w->nrows_scale_factor++;
24744 it->f->fonts_changed = true;
24745 return false;
24746 }
24747
24748
24749 prepare_desired_row (it->w, row, false);
24750
24751 row->y = it->current_y;
24752 row->start = it->start;
24753 row->continuation_lines_width = it->continuation_lines_width;
24754 row->displays_text_p = true;
24755 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24756 it->starts_in_middle_of_char_p = false;
24757 it->stretch_adjust = 0;
24758 it->line_number_produced_p = false;
24759
24760
24761
24762
24763 if (hscroll_this_line)
24764 x_incr =
24765 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24766 * FRAME_COLUMN_WIDTH (it->f);
24767
24768 bool line_number_needed = should_produce_line_number (it);
24769
24770
24771
24772
24773 if (it->current_x < it->first_visible_x + x_incr)
24774 {
24775 enum move_it_result move_result;
24776
24777 this_line_min_pos = row->start.pos;
24778 if (hscroll_this_line)
24779 {
24780 it->first_visible_x += x_incr;
24781 it->last_visible_x += x_incr;
24782 }
24783 if (current_buffer->long_line_optimizations_p
24784 && it->line_wrap == TRUNCATE
24785 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24786 {
24787
24788
24789
24790
24791 ptrdiff_t chars_to_skip =
24792 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24793 move_result = fast_move_it_horizontally (it, chars_to_skip);
24794
24795 if (move_result == MOVE_X_REACHED)
24796 it->current_x = it->first_visible_x;
24797 else
24798 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24799 }
24800 else
24801 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
24802 MOVE_TO_POS | MOVE_TO_X);
24803
24804
24805
24806
24807
24808
24809 if (it->current_x < it->first_visible_x
24810 && (move_result == MOVE_NEWLINE_OR_CR
24811 || move_result == MOVE_POS_MATCH_OR_ZV))
24812 it->current_x = it->first_visible_x;
24813
24814
24815
24816 it->line_number_produced_p = false;
24817
24818
24819
24820
24821
24822
24823
24824
24825 min_pos = CHARPOS (this_line_min_pos);
24826 min_bpos = BYTEPOS (this_line_min_pos);
24827
24828
24829 if (line_number_needed)
24830 maybe_produce_line_number (it);
24831 }
24832 else if (it->area == TEXT_AREA)
24833 {
24834
24835 if (line_number_needed)
24836 maybe_produce_line_number (it);
24837
24838
24839
24840 handle_line_prefix (it);
24841 }
24842 else
24843 {
24844
24845
24846
24847
24848
24849
24850
24851 pending_handle_line_prefix = true;
24852 }
24853
24854
24855
24856 row->ascent = it->max_ascent;
24857 row->height = it->max_ascent + it->max_descent;
24858 row->phys_ascent = it->max_phys_ascent;
24859 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
24860 row->extra_line_spacing = it->max_extra_line_spacing;
24861
24862
24863 #define RECORD_MAX_MIN_POS(IT) \
24864 do \
24865 { \
24866 bool composition_p \
24867 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
24868 ptrdiff_t current_pos = \
24869 composition_p ? (IT)->cmp_it.charpos \
24870 : IT_CHARPOS (*(IT)); \
24871 ptrdiff_t current_bpos = \
24872 composition_p ? CHAR_TO_BYTE (current_pos) \
24873 : IT_BYTEPOS (*(IT)); \
24874 if (current_pos < min_pos) \
24875 { \
24876 min_pos = current_pos; \
24877 min_bpos = current_bpos; \
24878 } \
24879 if (IT_CHARPOS (*it) > max_pos) \
24880 { \
24881 max_pos = IT_CHARPOS (*it); \
24882 max_bpos = IT_BYTEPOS (*it); \
24883 } \
24884 } \
24885 while (false)
24886
24887
24888
24889 while (true)
24890 {
24891 int n_glyphs_before, hpos_before, x_before;
24892 int x, nglyphs;
24893 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
24894
24895
24896
24897 if (!get_next_display_element (it))
24898 {
24899 bool row_has_glyphs = false;
24900
24901
24902
24903
24904 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
24905 row->exact_window_width_line_p = true;
24906 else if ((append_space_for_newline (it, true)
24907 && row->used[TEXT_AREA] == 1)
24908 || row->used[TEXT_AREA] == 0
24909 || (row_has_glyphs = row_text_area_empty (row)))
24910 {
24911 row->glyphs[TEXT_AREA]->charpos = -1;
24912
24913
24914 if (!row_has_glyphs)
24915 row->displays_text_p = false;
24916
24917 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
24918 && (!MINI_WINDOW_P (it->w)))
24919 row->indicate_empty_line_p = true;
24920 }
24921
24922 it->continuation_lines_width = 0;
24923
24924
24925
24926
24927 it->font_height = Qnil;
24928 it->voffset = 0;
24929 row->ends_at_zv_p = true;
24930
24931
24932
24933
24934
24935
24936
24937
24938 if (row->reversed_p
24939 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
24940 != DEFAULT_FACE_ID)
24941 extend_face_to_end_of_line (it);
24942 break;
24943 }
24944
24945
24946
24947 n_glyphs_before = row->used[TEXT_AREA];
24948 x = it->current_x;
24949
24950
24951
24952 if (it->line_wrap != TRUNCATE)
24953 {
24954 ascent = it->max_ascent;
24955 descent = it->max_descent;
24956 phys_ascent = it->max_phys_ascent;
24957 phys_descent = it->max_phys_descent;
24958
24959 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
24960 {
24961 bool next_may_wrap = may_wrap;
24962
24963 if (char_can_wrap_after (it))
24964 next_may_wrap = true;
24965 else
24966 next_may_wrap = false;
24967
24968 if (may_wrap && char_can_wrap_before (it))
24969 {
24970 SAVE_IT (wrap_it, *it, wrap_data);
24971 wrap_x = x;
24972 wrap_row_used = row->used[TEXT_AREA];
24973 wrap_row_ascent = row->ascent;
24974 wrap_row_height = row->height;
24975 wrap_row_phys_ascent = row->phys_ascent;
24976 wrap_row_phys_height = row->phys_height;
24977 wrap_row_extra_line_spacing = row->extra_line_spacing;
24978 wrap_row_min_pos = min_pos;
24979 wrap_row_min_bpos = min_bpos;
24980 wrap_row_max_pos = max_pos;
24981 wrap_row_max_bpos = max_bpos;
24982 }
24983
24984 may_wrap = next_may_wrap;
24985 }
24986 }
24987
24988 PRODUCE_GLYPHS (it);
24989
24990
24991
24992 if (it->area != TEXT_AREA)
24993 {
24994 row->ascent = max (row->ascent, it->max_ascent);
24995 row->height = max (row->height, it->max_ascent + it->max_descent);
24996 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
24997 row->phys_height = max (row->phys_height,
24998 it->max_phys_ascent + it->max_phys_descent);
24999 row->extra_line_spacing = max (row->extra_line_spacing,
25000 it->max_extra_line_spacing);
25001 set_iterator_to_next (it, true);
25002
25003
25004
25005 if (it->area == TEXT_AREA && pending_handle_line_prefix)
25006 {
25007
25008 if (line_number_needed)
25009 maybe_produce_line_number (it);
25010
25011 pending_handle_line_prefix = false;
25012 handle_line_prefix (it);
25013 }
25014 continue;
25015 }
25016
25017
25018
25019
25020
25021
25022
25023
25024
25025
25026 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
25027 hpos_before = it->hpos;
25028 x_before = x;
25029
25030 if (
25031 nglyphs > 0
25032
25033 && it->current_x < it->last_visible_x)
25034 {
25035 it->hpos += nglyphs;
25036 row->ascent = max (row->ascent, it->max_ascent);
25037 row->height = max (row->height, it->max_ascent + it->max_descent);
25038 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25039 row->phys_height = max (row->phys_height,
25040 it->max_phys_ascent + it->max_phys_descent);
25041 row->extra_line_spacing = max (row->extra_line_spacing,
25042 it->max_extra_line_spacing);
25043 if (it->current_x - it->pixel_width < it->first_visible_x
25044
25045
25046
25047 && !line_number_needed
25048
25049
25050
25051
25052 && !row->reversed_p)
25053 row->x = x - it->first_visible_x;
25054
25055
25056 if (it->bidi_p)
25057 RECORD_MAX_MIN_POS (it);
25058 }
25059 else
25060 {
25061 int i, new_x;
25062 struct glyph *glyph;
25063
25064 for (i = 0; i < nglyphs; ++i, x = new_x)
25065 {
25066
25067
25068
25069 if (!row->reversed_p)
25070 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25071 else
25072 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25073 new_x = x + glyph->pixel_width;
25074
25075 if (
25076 it->line_wrap != TRUNCATE
25077 && (
25078 new_x > it->last_visible_x
25079
25080 || (new_x == it->last_visible_x
25081 && FRAME_WINDOW_P (it->f)
25082 && (row->reversed_p
25083 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25084 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25085 {
25086
25087
25088 if (it->hpos == 0
25089 || (new_x == it->last_visible_x
25090 && FRAME_WINDOW_P (it->f)
25091 && (row->reversed_p
25092 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25093 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25094 {
25095
25096
25097
25098
25099 row->continued_p = true;
25100 it->current_x = new_x;
25101 it->continuation_lines_width += new_x;
25102 ++it->hpos;
25103 if (i == nglyphs - 1)
25104 {
25105
25106
25107 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25108 && wrap_row_used > 0
25109
25110
25111
25112
25113
25114
25115
25116
25117
25118
25119 && (!may_wrap || !char_can_wrap_before (it)))
25120 goto back_to_wrap;
25121
25122
25123
25124
25125 if (it->bidi_p)
25126 RECORD_MAX_MIN_POS (it);
25127 set_iterator_to_next (it, true);
25128 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25129 {
25130 if (!get_next_display_element (it))
25131 {
25132 row->exact_window_width_line_p = true;
25133 it->continuation_lines_width = 0;
25134 it->font_height = Qnil;
25135 it->voffset = 0;
25136 row->continued_p = false;
25137 row->ends_at_zv_p = true;
25138 }
25139 else if (ITERATOR_AT_END_OF_LINE_P (it))
25140 {
25141 row->continued_p = false;
25142 row->exact_window_width_line_p = true;
25143 }
25144
25145
25146 else if (wrap_row_used > 0
25147
25148
25149
25150
25151
25152
25153
25154
25155
25156 && (!may_wrap || !char_can_wrap_before (it)))
25157 goto back_to_wrap;
25158
25159 }
25160 }
25161 else if (it->bidi_p)
25162 RECORD_MAX_MIN_POS (it);
25163 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25164 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25165 extend_face_to_end_of_line (it);
25166 }
25167 else if (CHAR_GLYPH_PADDING_P (*glyph)
25168 && !FRAME_WINDOW_P (it->f))
25169 {
25170
25171
25172
25173 if (row->reversed_p)
25174 unproduce_glyphs (it, row->used[TEXT_AREA]
25175 - n_glyphs_before);
25176 row->used[TEXT_AREA] = n_glyphs_before;
25177
25178
25179
25180 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25181 < row->glyphs[1 + TEXT_AREA])
25182 produce_special_glyphs (it, IT_CONTINUATION);
25183
25184 row->continued_p = true;
25185 it->current_x = x_before;
25186 it->continuation_lines_width += x_before;
25187
25188
25189
25190 it->max_ascent = ascent;
25191 it->max_descent = descent;
25192 it->max_phys_ascent = phys_ascent;
25193 it->max_phys_descent = phys_descent;
25194 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25195 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25196 extend_face_to_end_of_line (it);
25197 }
25198 else if (wrap_row_used > 0)
25199 {
25200 back_to_wrap:
25201 if (row->reversed_p)
25202 unproduce_glyphs (it,
25203 row->used[TEXT_AREA] - wrap_row_used);
25204 RESTORE_IT (it, &wrap_it, wrap_data);
25205 it->continuation_lines_width += wrap_x;
25206 row->used[TEXT_AREA] = wrap_row_used;
25207 row->ascent = wrap_row_ascent;
25208 row->height = wrap_row_height;
25209 row->phys_ascent = wrap_row_phys_ascent;
25210 row->phys_height = wrap_row_phys_height;
25211 row->extra_line_spacing = wrap_row_extra_line_spacing;
25212 min_pos = wrap_row_min_pos;
25213 min_bpos = wrap_row_min_bpos;
25214 max_pos = wrap_row_max_pos;
25215 max_bpos = wrap_row_max_bpos;
25216 row->continued_p = true;
25217 row->ends_at_zv_p = false;
25218 row->exact_window_width_line_p = false;
25219
25220
25221
25222 extend_face_to_end_of_line (it);
25223 }
25224 else if ((it->what == IT_CHARACTER
25225 || it->what == IT_STRETCH
25226 || it->what == IT_COMPOSITION)
25227 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25228 {
25229
25230
25231
25232
25233
25234 if ((row->reversed_p
25235 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25236 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25237 produce_special_glyphs (it, IT_CONTINUATION);
25238 it->continuation_lines_width += it->last_visible_x;
25239 row->ends_in_middle_of_char_p = true;
25240 row->continued_p = true;
25241 glyph->pixel_width = it->last_visible_x - x;
25242 it->starts_in_middle_of_char_p = true;
25243 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25244 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25245 extend_face_to_end_of_line (it);
25246 }
25247 else
25248 {
25249
25250
25251
25252 if (row->reversed_p)
25253 unproduce_glyphs (it, row->used[TEXT_AREA]
25254 - (n_glyphs_before + i));
25255 row->used[TEXT_AREA] = n_glyphs_before + i;
25256
25257
25258 it->current_x = x_before;
25259 it->continuation_lines_width += x;
25260 if (!FRAME_WINDOW_P (it->f)
25261 || (row->reversed_p
25262 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25263 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25264 produce_special_glyphs (it, IT_CONTINUATION);
25265 row->continued_p = true;
25266
25267 extend_face_to_end_of_line (it);
25268
25269 if (nglyphs > 1 && i > 0)
25270 {
25271 row->ends_in_middle_of_char_p = true;
25272 it->starts_in_middle_of_char_p = true;
25273 }
25274
25275
25276
25277 it->max_ascent = ascent;
25278 it->max_descent = descent;
25279 it->max_phys_ascent = phys_ascent;
25280 it->max_phys_descent = phys_descent;
25281 }
25282
25283 break;
25284 }
25285 else if (new_x > it->first_visible_x)
25286 {
25287
25288 ++it->hpos;
25289
25290
25291
25292
25293 if (it->bidi_p)
25294 RECORD_MAX_MIN_POS (it);
25295
25296 if (x < it->first_visible_x && !row->reversed_p
25297 && !line_number_needed)
25298
25299
25300
25301
25302
25303
25304 row->x = x - it->first_visible_x;
25305
25306
25307
25308
25309
25310
25311 if (row->reversed_p
25312 && new_x > it->last_visible_x
25313 && !line_number_needed
25314 && !(it->line_wrap == TRUNCATE
25315 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25316 {
25317 eassert (FRAME_WINDOW_P (it->f));
25318 row->x = it->last_visible_x - new_x;
25319 }
25320 }
25321 else
25322 {
25323
25324
25325
25326
25327
25328 eassert (it->first_visible_x <= it->last_visible_x);
25329 }
25330 }
25331
25332
25333 if (it->bidi_p && nglyphs == 0)
25334 RECORD_MAX_MIN_POS (it);
25335
25336 row->ascent = max (row->ascent, it->max_ascent);
25337 row->height = max (row->height, it->max_ascent + it->max_descent);
25338 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25339 row->phys_height = max (row->phys_height,
25340 it->max_phys_ascent + it->max_phys_descent);
25341 row->extra_line_spacing = max (row->extra_line_spacing,
25342 it->max_extra_line_spacing);
25343
25344
25345 if (row->continued_p || row->ends_at_zv_p)
25346 break;
25347 }
25348
25349 at_end_of_line:
25350
25351
25352
25353 if (ITERATOR_AT_END_OF_LINE_P (it))
25354 {
25355 int used_before = row->used[TEXT_AREA];
25356
25357 row->ends_in_newline_from_string_p = STRINGP (it->object);
25358
25359
25360
25361 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25362 append_space_for_newline (it, false);
25363
25364
25365 extend_face_to_end_of_line (it);
25366
25367
25368 if (used_before == 0)
25369 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25370
25371
25372
25373 it->eol_pos = it->current.pos;
25374
25375
25376 set_iterator_to_next (it, true);
25377 it->continuation_lines_width = 0;
25378 break;
25379 }
25380
25381
25382
25383
25384
25385
25386
25387
25388 bool overwide_wrap_prefix =
25389 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25390 && it->sp > 0 && it->method == GET_FROM_STRETCH
25391 && it->current_x >= it->last_visible_x
25392 && it->continuation_lines_width > 0
25393 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25394
25395
25396
25397 if (!overwide_wrap_prefix)
25398 set_iterator_to_next (it, true);
25399
25400
25401
25402 if (it->line_wrap == TRUNCATE
25403 && ((FRAME_WINDOW_P (it->f)
25404
25405
25406
25407
25408 && ((row->reversed_p
25409 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25410 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25411 || it->what == IT_IMAGE))
25412 ? (it->current_x >= it->last_visible_x)
25413 : (it->current_x > it->last_visible_x)))
25414 {
25415
25416 if (!FRAME_WINDOW_P (it->f)
25417 || (row->reversed_p
25418 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25419 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25420 {
25421 int i, n;
25422
25423 if (!row->reversed_p)
25424 {
25425 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25426 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25427 break;
25428 }
25429 else
25430 {
25431 for (i = 0; i < row->used[TEXT_AREA]; i++)
25432 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25433 break;
25434
25435
25436
25437
25438
25439 unproduce_glyphs (it, i + 1);
25440
25441 i = row->used[TEXT_AREA] - (i + 1);
25442 }
25443
25444
25445
25446
25447 if (it->current_x > it->last_visible_x)
25448 {
25449 it->current_x = x_before;
25450 if (!FRAME_WINDOW_P (it->f))
25451 {
25452 for (n = row->used[TEXT_AREA]; i < n; ++i)
25453 {
25454 row->used[TEXT_AREA] = i;
25455 produce_special_glyphs (it, IT_TRUNCATION);
25456 }
25457 }
25458 else
25459 {
25460 row->used[TEXT_AREA] = i;
25461 produce_special_glyphs (it, IT_TRUNCATION);
25462 }
25463 it->hpos = hpos_before;
25464 }
25465 }
25466 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25467 {
25468
25469 if (!get_next_display_element (it))
25470 {
25471 it->continuation_lines_width = 0;
25472 it->font_height = Qnil;
25473 it->voffset = 0;
25474 row->ends_at_zv_p = true;
25475 row->exact_window_width_line_p = true;
25476 break;
25477 }
25478 if (ITERATOR_AT_END_OF_LINE_P (it))
25479 {
25480 row->exact_window_width_line_p = true;
25481 goto at_end_of_line;
25482 }
25483 it->current_x = x_before;
25484 it->hpos = hpos_before;
25485 }
25486
25487 row->truncated_on_right_p = true;
25488 it->continuation_lines_width = 0;
25489 reseat_at_next_visible_line_start (it, false);
25490
25491
25492
25493
25494 if (IT_BYTEPOS (*it) > BEG_BYTE)
25495 row->ends_at_zv_p =
25496 IT_BYTEPOS (*it) >= ZV_BYTE
25497 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25498 else
25499 row->ends_at_zv_p = false;
25500 break;
25501 }
25502 }
25503
25504 if (wrap_data)
25505 bidi_unshelve_cache (wrap_data, true);
25506
25507
25508
25509 if (it->first_visible_x
25510 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25511 {
25512 if (!FRAME_WINDOW_P (it->f)
25513 || (((row->reversed_p
25514 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25515 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25516
25517
25518 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25519 insert_left_trunc_glyphs (it);
25520 row->truncated_on_left_p = true;
25521 }
25522
25523
25524
25525
25526
25527
25528 row->end = it->current;
25529 if (!it->bidi_p)
25530 {
25531 row->minpos = row->start.pos;
25532 row->maxpos = row->end.pos;
25533 }
25534 else
25535 {
25536
25537
25538
25539
25540 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25541 }
25542
25543
25544
25545
25546
25547 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25548 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25549 !NILP (overlay_arrow_string)))
25550 {
25551
25552 if (STRINGP (overlay_arrow_string))
25553 {
25554 struct glyph_row *arrow_row
25555 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25556 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25557 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25558 struct glyph *p = row->glyphs[TEXT_AREA];
25559 struct glyph *p2, *end;
25560
25561
25562 while (glyph < arrow_end)
25563 *p++ = *glyph++;
25564
25565
25566 p2 = p;
25567 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25568 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25569 ++p2;
25570 if (p2 > p)
25571 {
25572 while (p2 < end)
25573 *p++ = *p2++;
25574 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25575 }
25576 }
25577 else
25578 {
25579 eassert (FIXNUMP (overlay_arrow_string));
25580 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25581 }
25582 overlay_arrow_seen = true;
25583 }
25584
25585
25586 if (!NILP (Vshow_trailing_whitespace))
25587 highlight_trailing_whitespace (it);
25588
25589
25590 compute_line_metrics (it);
25591
25592
25593
25594
25595
25596
25597
25598 row->ends_in_ellipsis_p
25599 = (it->method == GET_FROM_DISPLAY_VECTOR
25600 && it->ellipsis_p);
25601
25602
25603 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25604 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25605 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25606 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25607
25608 it->left_user_fringe_bitmap = 0;
25609 it->left_user_fringe_face_id = 0;
25610 it->right_user_fringe_bitmap = 0;
25611 it->right_user_fringe_face_id = 0;
25612
25613
25614
25615
25616
25617
25618 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25619 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25620 row->redraw_fringe_bitmaps_p = true;
25621
25622
25623 cvpos = it->w->cursor.vpos;
25624 if ((cvpos < 0
25625
25626
25627
25628
25629
25630
25631
25632
25633 || (it->bidi_p
25634 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25635 && PT >= MATRIX_ROW_START_CHARPOS (row)
25636 && PT <= MATRIX_ROW_END_CHARPOS (row)
25637 && cursor_row_p (row))
25638 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25639
25640
25641
25642
25643
25644 it->current_x = it->hpos = 0;
25645 it->current_y += row->height;
25646
25647
25648 if (hscroll_this_line)
25649 {
25650 it->first_visible_x = first_visible_x;
25651 it->last_visible_x = last_visible_x;
25652 }
25653 SET_TEXT_POS (it->eol_pos, 0, 0);
25654 ++it->vpos;
25655 ++it->glyph_row;
25656
25657
25658
25659
25660 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25661 it->glyph_row->reversed_p = row->reversed_p;
25662 it->start = row->end;
25663 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25664
25665 #undef RECORD_MAX_MIN_POS
25666 }
25667
25668 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25669 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25670 doc:
25671
25672
25673
25674
25675
25676
25677
25678
25679 )
25680 (Lisp_Object buffer)
25681 {
25682 struct buffer *buf = current_buffer;
25683 struct buffer *old = buf;
25684
25685 if (! NILP (buffer))
25686 {
25687 CHECK_BUFFER (buffer);
25688 buf = XBUFFER (buffer);
25689 }
25690
25691 if (NILP (BVAR (buf, bidi_display_reordering))
25692 || NILP (BVAR (buf, enable_multibyte_characters))
25693
25694
25695 || redisplay__inhibit_bidi)
25696 return Qleft_to_right;
25697 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25698 return BVAR (buf, bidi_paragraph_direction);
25699 else
25700 {
25701
25702
25703
25704 struct bidi_it itb;
25705 ptrdiff_t pos = BUF_PT (buf);
25706 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25707 int c;
25708 void *itb_data = bidi_shelve_cache ();
25709
25710 set_buffer_temp (buf);
25711
25712
25713
25714
25715
25716 if (pos >= ZV && pos > BEGV)
25717 dec_both (&pos, &bytepos);
25718 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25719 if (fast_looking_at (trailing_white_space,
25720 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25721 {
25722 while ((c = FETCH_BYTE (bytepos)) == '\n'
25723 || c == ' ' || c == '\t' || c == '\f')
25724 {
25725 if (bytepos <= BEGV_BYTE)
25726 break;
25727 bytepos--;
25728 pos--;
25729 }
25730 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25731 bytepos--;
25732 }
25733 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25734 itb.paragraph_dir = NEUTRAL_DIR;
25735 itb.string.s = NULL;
25736 itb.string.lstring = Qnil;
25737 itb.string.bufpos = 0;
25738 itb.string.from_disp_str = false;
25739 itb.string.unibyte = false;
25740
25741
25742
25743 itb.w = NULL;
25744 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25745 bidi_unshelve_cache (itb_data, false);
25746 set_buffer_temp (old);
25747 switch (itb.paragraph_dir)
25748 {
25749 case L2R:
25750 return Qleft_to_right;
25751 break;
25752 case R2L:
25753 return Qright_to_left;
25754 break;
25755 default:
25756 emacs_abort ();
25757 }
25758 }
25759 }
25760
25761 DEFUN ("bidi-find-overridden-directionality",
25762 Fbidi_find_overridden_directionality,
25763 Sbidi_find_overridden_directionality, 3, 4, 0,
25764 doc:
25765
25766
25767
25768
25769
25770
25771
25772
25773
25774
25775
25776
25777
25778
25779
25780
25781
25782
25783
25784
25785
25786
25787
25788
25789
25790
25791
25792
25793
25794
25795
25796
25797
25798
25799
25800
25801 )
25802 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
25803 {
25804 struct buffer *buf = current_buffer;
25805 struct buffer *old = buf;
25806 struct window *w = NULL;
25807 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
25808 struct bidi_it itb;
25809 ptrdiff_t from_pos, to_pos, from_bpos;
25810 void *itb_data;
25811
25812 if (!NILP (object))
25813 {
25814 if (BUFFERP (object))
25815 buf = XBUFFER (object);
25816 else if (WINDOWP (object))
25817 {
25818 w = decode_live_window (object);
25819 buf = XBUFFER (w->contents);
25820 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
25821 }
25822 else
25823 CHECK_STRING (object);
25824 }
25825
25826 if (STRINGP (object))
25827 {
25828
25829
25830 if (!STRING_MULTIBYTE (object)
25831
25832
25833
25834 || redisplay__inhibit_bidi)
25835 return Qnil;
25836
25837 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
25838 if (from_pos >= SCHARS (object))
25839 return Qnil;
25840
25841
25842 itb_data = bidi_shelve_cache ();
25843 itb.paragraph_dir = NEUTRAL_DIR;
25844 itb.string.lstring = object;
25845 itb.string.s = NULL;
25846 itb.string.schars = SCHARS (object);
25847 itb.string.bufpos = 0;
25848 itb.string.from_disp_str = false;
25849 itb.string.unibyte = false;
25850 itb.w = w;
25851 bidi_init_it (0, 0, frame_window_p, &itb);
25852 }
25853 else
25854 {
25855
25856
25857 if (NILP (BVAR (buf, bidi_display_reordering))
25858 || NILP (BVAR (buf, enable_multibyte_characters))
25859
25860
25861
25862 || redisplay__inhibit_bidi)
25863 return Qnil;
25864
25865 set_buffer_temp (buf);
25866 validate_region (&from, &to);
25867 from_pos = XFIXNUM (from);
25868 to_pos = XFIXNUM (to);
25869 if (from_pos >= ZV)
25870 return Qnil;
25871
25872
25873 itb_data = bidi_shelve_cache ();
25874 from_bpos = CHAR_TO_BYTE (from_pos);
25875 if (from_pos == BEGV)
25876 {
25877 itb.charpos = BEGV;
25878 itb.bytepos = BEGV_BYTE;
25879 }
25880 else if (FETCH_BYTE (from_bpos - 1) == '\n')
25881 {
25882 itb.charpos = from_pos;
25883 itb.bytepos = from_bpos;
25884 }
25885 else
25886 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
25887 -1, &itb.bytepos);
25888 itb.paragraph_dir = NEUTRAL_DIR;
25889 itb.string.s = NULL;
25890 itb.string.lstring = Qnil;
25891 itb.string.bufpos = 0;
25892 itb.string.from_disp_str = false;
25893 itb.string.unibyte = false;
25894 itb.w = w;
25895 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
25896 }
25897
25898 ptrdiff_t found;
25899 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
25900 do {
25901 bidi_paragraph_init (bdir, &itb, false);
25902 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
25903 ;
25904 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
25905
25906 bidi_unshelve_cache (itb_data, false);
25907 set_buffer_temp (old);
25908
25909 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
25910 }
25911
25912 DEFUN ("move-point-visually", Fmove_point_visually,
25913 Smove_point_visually, 1, 1, 0,
25914 doc:
25915
25916
25917
25918 )
25919 (Lisp_Object direction)
25920 {
25921 struct window *w = XWINDOW (selected_window);
25922 struct buffer *b = XBUFFER (w->contents);
25923 struct glyph_row *row;
25924 int dir;
25925 Lisp_Object paragraph_dir;
25926
25927 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
25928 (!(ROW)->continued_p \
25929 && NILP ((GLYPH)->object) \
25930 && (GLYPH)->type == CHAR_GLYPH \
25931 && (GLYPH)->u.ch == ' ' \
25932 && (GLYPH)->charpos >= 0 \
25933 && !(GLYPH)->avoid_cursor_p)
25934
25935 CHECK_FIXNUM (direction);
25936 dir = XFIXNUM (direction);
25937 if (dir > 0)
25938 dir = 1;
25939 else
25940 dir = -1;
25941
25942
25943
25944
25945 if (w->window_end_valid
25946 && !windows_or_buffers_changed
25947 && b
25948 && !b->clip_changed
25949 && !b->prevent_redisplay_optimizations_p
25950 && !window_outdated (w)
25951
25952
25953
25954 && w->last_point == BUF_PT (b)
25955 && w->cursor.vpos >= 0
25956 && w->cursor.vpos < w->current_matrix->nrows
25957 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
25958 {
25959 struct glyph *g = row->glyphs[TEXT_AREA];
25960 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
25961 struct glyph *gpt = g + w->cursor.hpos;
25962
25963 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
25964 {
25965 if (BUFFERP (g->object) && g->charpos != PT)
25966 {
25967 SET_PT (g->charpos);
25968 w->cursor.vpos = -1;
25969 return make_fixnum (PT);
25970 }
25971 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
25972 {
25973 ptrdiff_t new_pos;
25974
25975 if (BUFFERP (gpt->object))
25976 {
25977 new_pos = PT;
25978 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
25979 new_pos += (row->reversed_p ? -dir : dir);
25980 else
25981 new_pos -= (row->reversed_p ? -dir : dir);
25982 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
25983
25984
25985 if (new_pos == PT)
25986 break;
25987 }
25988 else if (BUFFERP (g->object))
25989 new_pos = g->charpos;
25990 else
25991 break;
25992 SET_PT (new_pos);
25993 w->cursor.vpos = -1;
25994 return make_fixnum (PT);
25995 }
25996 else if (ROW_GLYPH_NEWLINE_P (row, g))
25997 {
25998
25999
26000
26001 if (g->charpos > 0)
26002 SET_PT (g->charpos);
26003 else if (row->ends_at_zv_p && PT != ZV)
26004 SET_PT (ZV);
26005 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
26006 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26007 else
26008 break;
26009 w->cursor.vpos = -1;
26010 return make_fixnum (PT);
26011 }
26012 }
26013 if (g == e || NILP (g->object))
26014 {
26015 if (row->truncated_on_left_p || row->truncated_on_right_p)
26016 goto simulate_display;
26017 if (!row->reversed_p)
26018 row += dir;
26019 else
26020 row -= dir;
26021 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
26022 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
26023 goto simulate_display;
26024
26025 if (dir > 0)
26026 {
26027 if (row->reversed_p && !row->continued_p)
26028 {
26029 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26030 w->cursor.vpos = -1;
26031 return make_fixnum (PT);
26032 }
26033 g = row->glyphs[TEXT_AREA];
26034 e = g + row->used[TEXT_AREA];
26035 for ( ; g < e; g++)
26036 {
26037 if (BUFFERP (g->object)
26038
26039
26040
26041 || ROW_GLYPH_NEWLINE_P (row, g)
26042
26043
26044 || (row->ends_at_zv_p
26045 && !row->reversed_p
26046 && NILP (g->object)
26047 && g->type == CHAR_GLYPH
26048 && g->u.ch == ' '))
26049 {
26050 if (g->charpos > 0)
26051 SET_PT (g->charpos);
26052 else if (!row->reversed_p
26053 && row->ends_at_zv_p
26054 && PT != ZV)
26055 SET_PT (ZV);
26056 else
26057 continue;
26058 w->cursor.vpos = -1;
26059 return make_fixnum (PT);
26060 }
26061 }
26062 }
26063 else
26064 {
26065 if (!row->reversed_p && !row->continued_p)
26066 {
26067 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26068 w->cursor.vpos = -1;
26069 return make_fixnum (PT);
26070 }
26071 e = row->glyphs[TEXT_AREA];
26072 g = e + row->used[TEXT_AREA] - 1;
26073 for ( ; g >= e; g--)
26074 {
26075 if (BUFFERP (g->object)
26076 || (ROW_GLYPH_NEWLINE_P (row, g)
26077 && g->charpos > 0)
26078
26079
26080
26081 || g->type == STRETCH_GLYPH
26082 || (row->ends_at_zv_p
26083 && row->reversed_p
26084 && NILP (g->object)
26085 && g->type == CHAR_GLYPH
26086 && g->u.ch == ' '))
26087 {
26088 if (g->charpos > 0)
26089 SET_PT (g->charpos);
26090 else if (row->reversed_p
26091 && row->ends_at_zv_p
26092 && PT != ZV)
26093 SET_PT (ZV);
26094 else
26095 continue;
26096 w->cursor.vpos = -1;
26097 return make_fixnum (PT);
26098 }
26099 }
26100 }
26101 }
26102 }
26103
26104 simulate_display:
26105
26106
26107
26108
26109 if (b)
26110 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26111 else
26112 paragraph_dir = Qleft_to_right;
26113 if (EQ (paragraph_dir, Qright_to_left))
26114 dir = -dir;
26115 if (PT <= BEGV && dir < 0)
26116 xsignal0 (Qbeginning_of_buffer);
26117 else if (PT >= ZV && dir > 0)
26118 xsignal0 (Qend_of_buffer);
26119 else
26120 {
26121 struct text_pos pt;
26122 struct it it;
26123 int pt_x, target_x, pixel_width, pt_vpos;
26124 bool at_eol_p;
26125 bool overshoot_expected = false;
26126 bool target_is_eol_p = false;
26127 void *itdata = bidi_shelve_cache ();
26128
26129
26130 SET_TEXT_POS (pt, PT, PT_BYTE);
26131 start_display (&it, w, pt);
26132
26133
26134
26135
26136
26137
26138 if (it.line_wrap == TRUNCATE)
26139 it.last_visible_x = DISP_INFINITY;
26140
26141 if (it.cmp_it.id < 0
26142 && it.method == GET_FROM_STRING
26143 && it.area == TEXT_AREA
26144 && it.string_from_display_prop_p
26145 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26146 overshoot_expected = true;
26147
26148
26149
26150
26151
26152 reseat:
26153 reseat_at_previous_visible_line_start (&it);
26154 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26155 if (IT_CHARPOS (it) != PT)
26156 {
26157 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26158 -1, -1, -1, MOVE_TO_POS);
26159
26160
26161
26162 if (it.method == GET_FROM_DISPLAY_VECTOR
26163 && it.current.dpvec_index > 0
26164 && !overshoot_expected)
26165 {
26166 overshoot_expected = true;
26167 goto reseat;
26168 }
26169 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26170 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26171 }
26172 pt_x = it.current_x;
26173 pt_vpos = it.vpos;
26174 if (dir > 0 || overshoot_expected)
26175 {
26176 struct glyph_row *row = it.glyph_row;
26177
26178
26179
26180
26181 if (pt_x == 0)
26182 get_next_display_element (&it);
26183 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26184 it.glyph_row = NULL;
26185 PRODUCE_GLYPHS (&it);
26186 it.glyph_row = row;
26187
26188
26189
26190 it.current_x = pt_x;
26191 }
26192 else
26193 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26194 pixel_width = it.pixel_width;
26195 if (overshoot_expected && at_eol_p)
26196 pixel_width = 0;
26197 else if (pixel_width <= 0)
26198 pixel_width = 1;
26199
26200
26201
26202
26203 if (overshoot_expected)
26204 {
26205 if (it.bidi_p)
26206 pt_x += pixel_width * it.bidi_it.scan_dir;
26207 else
26208 pt_x += pixel_width;
26209 }
26210
26211
26212
26213
26214
26215
26216
26217 if (dir > 0)
26218 target_x = pt_x + pixel_width;
26219 else
26220 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26221
26222
26223
26224
26225
26226 if (dir < 0)
26227 {
26228 if (pt_x > 0)
26229 {
26230 start_display (&it, w, pt);
26231 if (it.line_wrap == TRUNCATE)
26232 it.last_visible_x = DISP_INFINITY;
26233 reseat_at_previous_visible_line_start (&it);
26234 it.current_x = it.current_y = it.hpos = 0;
26235 if (pt_vpos != 0)
26236 move_it_by_lines (&it, pt_vpos);
26237 }
26238 else
26239 {
26240 move_it_by_lines (&it, -1);
26241 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26242 target_is_eol_p = true;
26243
26244
26245
26246
26247
26248
26249
26250
26251
26252
26253 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26254 {
26255 void *it_data = NULL;
26256 struct it it2;
26257
26258 SAVE_IT (it2, it, it_data);
26259 move_it_in_display_line_to (&it, ZV, target_x,
26260 MOVE_TO_POS | MOVE_TO_X);
26261
26262
26263 if (it.current_x != target_x)
26264 target_x = it.current_x - 1;
26265 RESTORE_IT (&it, &it2, it_data);
26266 }
26267 }
26268 }
26269 else
26270 {
26271 if (at_eol_p
26272 || (target_x >= it.last_visible_x
26273 && it.line_wrap != TRUNCATE))
26274 {
26275 if (pt_x > 0)
26276 move_it_by_lines (&it, 0);
26277 move_it_by_lines (&it, 1);
26278 target_x = 0;
26279 }
26280 }
26281
26282
26283
26284
26285
26286
26287
26288 if (FRAME_WINDOW_P (it.f) && dir < 0)
26289 {
26290 struct text_pos new_pos;
26291 enum move_it_result rc = MOVE_X_REACHED;
26292
26293 if (it.current_x == 0)
26294 get_next_display_element (&it);
26295 if (it.what == IT_COMPOSITION)
26296 {
26297 new_pos.charpos = it.cmp_it.charpos;
26298 new_pos.bytepos = -1;
26299 }
26300 else
26301 new_pos = it.current.pos;
26302
26303 while (it.current_x + it.pixel_width <= target_x
26304 && (rc == MOVE_X_REACHED
26305
26306
26307
26308 || (it.line_wrap == WORD_WRAP
26309 && rc == MOVE_POS_MATCH_OR_ZV)))
26310 {
26311 int new_x = it.current_x + it.pixel_width;
26312
26313
26314
26315
26316
26317
26318
26319 if (it.what == IT_COMPOSITION)
26320 {
26321 new_pos.charpos = it.cmp_it.charpos;
26322 new_pos.bytepos = -1;
26323 }
26324 else
26325 new_pos = it.current.pos;
26326 if (new_x == it.current_x)
26327 new_x++;
26328 rc = move_it_in_display_line_to (&it, ZV, new_x,
26329 MOVE_TO_POS | MOVE_TO_X);
26330 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26331 break;
26332 }
26333
26334
26335 if (new_pos.bytepos == -1)
26336 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26337 it.current.pos = new_pos;
26338 }
26339 else if (it.current_x != target_x)
26340 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26341
26342
26343
26344 if (dir > 0)
26345 {
26346 while (IT_CHARPOS (it) == PT)
26347 {
26348 set_iterator_to_next (&it, false);
26349 if (!get_next_display_element (&it))
26350 break;
26351 }
26352 }
26353
26354
26355 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26356 bidi_unshelve_cache (itdata, false);
26357 }
26358
26359 return make_fixnum (PT);
26360
26361 #undef ROW_GLYPH_NEWLINE_P
26362 }
26363
26364 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26365 Sbidi_resolved_levels, 0, 1, 0,
26366 doc:
26367
26368
26369
26370
26371
26372
26373
26374
26375
26376
26377
26378
26379
26380
26381
26382
26383
26384
26385
26386
26387
26388
26389
26390
26391
26392 )
26393 (Lisp_Object vpos)
26394 {
26395 struct window *w = XWINDOW (selected_window);
26396 struct buffer *b = XBUFFER (w->contents);
26397 int nrow;
26398 struct glyph_row *row;
26399
26400 if (NILP (vpos))
26401 {
26402 int d1, d2, d3, d4, d5;
26403
26404 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26405 }
26406 else
26407 {
26408 CHECK_FIXNUM (vpos);
26409 nrow = XFIXNUM (vpos);
26410 }
26411
26412
26413 if (w->window_end_valid
26414 && !windows_or_buffers_changed
26415 && b
26416 && !b->clip_changed
26417 && !b->prevent_redisplay_optimizations_p
26418 && !window_outdated (w)
26419 && nrow >= 0
26420 && nrow < w->current_matrix->nrows
26421 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26422 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26423 {
26424 struct glyph *g, *e, *g1;
26425 int nglyphs, i;
26426 Lisp_Object levels;
26427
26428 if (!row->reversed_p)
26429 {
26430 g = g1 = row->glyphs[TEXT_AREA];
26431 e = g + row->used[TEXT_AREA];
26432
26433
26434
26435 while (g < e
26436 && NILP (g->object)
26437 && g->charpos < 0)
26438 g++;
26439 g1 = g;
26440
26441
26442 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26443 nglyphs++;
26444
26445
26446 levels = make_uninit_vector (nglyphs);
26447 for (i = 0; g1 < g; i++, g1++)
26448 ASET (levels, i, make_fixnum (g1->resolved_level));
26449 }
26450 else
26451 {
26452 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26453 e = row->glyphs[TEXT_AREA] - 1;
26454 while (g > e
26455 && NILP (g->object)
26456 && g->charpos < 0)
26457 g--;
26458 g1 = g;
26459 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26460 nglyphs++;
26461 levels = make_uninit_vector (nglyphs);
26462 for (i = 0; g1 > g; i++, g1--)
26463 ASET (levels, i, make_fixnum (g1->resolved_level));
26464 }
26465 return levels;
26466 }
26467 else
26468 return Qnil;
26469 }
26470
26471
26472
26473
26474
26475
26476
26477
26478
26479
26480
26481
26482
26483
26484
26485
26486
26487 static void
26488 display_menu_bar (struct window *w)
26489 {
26490 struct frame *f = XFRAME (WINDOW_FRAME (w));
26491 struct it it;
26492 Lisp_Object items;
26493 int i;
26494
26495
26496 #ifdef HAVE_NTGUI
26497 if (FRAME_W32_P (f))
26498 return;
26499 #endif
26500 #if defined (HAVE_PGTK)
26501 if (FRAME_PGTK_P (f))
26502 return;
26503 #endif
26504
26505 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26506 if (FRAME_X_P (f))
26507 return;
26508 #endif
26509
26510 #ifdef HAVE_NS
26511 if (FRAME_NS_P (f))
26512 return;
26513 #endif
26514
26515 #ifdef HAVE_HAIKU
26516 if (FRAME_HAIKU_P (f))
26517 return;
26518 #endif
26519
26520 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26521 eassert (!FRAME_WINDOW_P (f));
26522 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26523 it.first_visible_x = 0;
26524 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26525 #elif defined (HAVE_X_WINDOWS)
26526 if (FRAME_WINDOW_P (f))
26527 {
26528
26529
26530 struct window *menu_w;
26531 menu_w = XWINDOW (f->menu_bar_window);
26532 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
26533 MENU_FACE_ID);
26534 it.first_visible_x = 0;
26535 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26536 }
26537 else
26538 #endif
26539 {
26540
26541
26542 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26543 MENU_FACE_ID);
26544 it.first_visible_x = 0;
26545 it.last_visible_x = FRAME_COLS (f);
26546 }
26547
26548
26549
26550
26551 it.paragraph_embedding = L2R;
26552
26553
26554 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26555 {
26556 struct glyph_row *row = it.glyph_row + i;
26557 clear_glyph_row (row);
26558 row->enabled_p = true;
26559 row->full_width_p = true;
26560 row->reversed_p = false;
26561 }
26562
26563
26564 items = FRAME_MENU_BAR_ITEMS (it.f);
26565 for (i = 0; i < ASIZE (items); i += 4)
26566 {
26567 Lisp_Object string;
26568
26569
26570 string = AREF (items, i + 1);
26571 if (NILP (string))
26572 break;
26573
26574
26575 ASET (items, i + 3, make_fixnum (it.hpos));
26576
26577
26578 if (it.current_x < it.last_visible_x)
26579 display_string (NULL, string, Qnil, 0, 0, &it,
26580 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26581 }
26582
26583
26584 if (it.current_x < it.last_visible_x)
26585 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26586
26587
26588 compute_line_metrics (&it);
26589 }
26590
26591
26592 static void
26593 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26594 {
26595 struct glyph *pointers[1 + LAST_AREA];
26596 int to_used = to->used[TEXT_AREA];
26597
26598
26599 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26600
26601
26602 *to = *from;
26603
26604
26605 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26606
26607
26608 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26609 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26610
26611
26612
26613 if (to_used > from->used[TEXT_AREA])
26614 fill_up_frame_row_with_spaces (to, to_used);
26615 }
26616
26617
26618
26619
26620
26621
26622
26623
26624
26625
26626
26627
26628
26629
26630
26631
26632
26633
26634
26635
26636
26637
26638 void
26639 display_tty_menu_item (const char *item_text, int width, int face_id,
26640 int x, int y, bool submenu)
26641 {
26642 struct it it;
26643 struct frame *f = SELECTED_FRAME ();
26644 struct window *w = XWINDOW (f->selected_window);
26645 struct glyph_row *row;
26646 size_t item_len = strlen (item_text);
26647
26648 eassert (FRAME_TERMCAP_P (f));
26649
26650
26651
26652
26653
26654
26655 if (y >= f->desired_matrix->nrows)
26656 return;
26657
26658 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26659 it.first_visible_x = 0;
26660 it.last_visible_x = FRAME_COLS (f) - 1;
26661 row = it.glyph_row;
26662
26663 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26664 bool saved_width = row->full_width_p;
26665 row->full_width_p = true;
26666 bool saved_reversed = row->reversed_p;
26667 row->reversed_p = false;
26668 row->enabled_p = true;
26669
26670
26671
26672 eassert (x < f->desired_matrix->matrix_w);
26673 it.current_x = it.hpos = x;
26674 it.current_y = it.vpos = y;
26675 int saved_used = row->used[TEXT_AREA];
26676 bool saved_truncated = row->truncated_on_right_p;
26677 row->used[TEXT_AREA] = x;
26678 it.face_id = face_id;
26679 it.line_wrap = TRUNCATE;
26680
26681
26682
26683
26684
26685
26686 it.paragraph_embedding = L2R;
26687
26688
26689 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26690 width--;
26691
26692 if (submenu)
26693 {
26694 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26695 item_len, 0, FRAME_COLS (f) - 1, -1);
26696 width -= item_len;
26697
26698 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26699 FRAME_COLS (f) - 1, -1);
26700 }
26701 else
26702 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26703 width, 0, FRAME_COLS (f) - 1, -1);
26704
26705 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26706 row->truncated_on_right_p = saved_truncated;
26707 row->hash = row_hash (row);
26708 row->full_width_p = saved_width;
26709 row->reversed_p = saved_reversed;
26710 }
26711
26712
26713
26714
26715
26716
26717
26718
26719
26720
26721 static int
26722 redisplay_mode_lines (Lisp_Object window, bool force)
26723 {
26724 int nwindows = 0;
26725
26726 while (!NILP (window))
26727 {
26728 struct window *w = XWINDOW (window);
26729
26730 if (WINDOWP (w->contents))
26731 nwindows += redisplay_mode_lines (w->contents, force);
26732 else if (force
26733 || FRAME_GARBAGED_P (XFRAME (w->frame))
26734 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26735 {
26736 struct text_pos lpoint;
26737 struct buffer *old = current_buffer;
26738
26739
26740 SET_TEXT_POS (lpoint, PT, PT_BYTE);
26741 set_buffer_internal_1 (XBUFFER (w->contents));
26742
26743
26744
26745 if (!EQ (window, selected_window))
26746 {
26747 struct text_pos pt;
26748
26749 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
26750 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
26751 }
26752
26753
26754 clear_glyph_matrix (w->desired_matrix);
26755 if (display_mode_lines (w))
26756 ++nwindows;
26757
26758
26759 set_buffer_internal_1 (old);
26760 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
26761 }
26762
26763 window = w->next;
26764 }
26765
26766 return nwindows;
26767 }
26768
26769
26770
26771
26772
26773
26774 static int
26775 display_mode_lines (struct window *w)
26776 {
26777 Lisp_Object old_selected_window = selected_window;
26778 Lisp_Object new_frame = w->frame;
26779 specpdl_ref count = SPECPDL_INDEX ();
26780 int n = 0;
26781
26782 record_unwind_protect (restore_selected_window, selected_window);
26783 record_unwind_protect
26784 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
26785
26786 if (window_wants_mode_line (w))
26787 {
26788 Lisp_Object window;
26789 Lisp_Object default_help
26790 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
26791
26792
26793
26794 XSETWINDOW (window, w);
26795 if (FUNCTIONP (default_help))
26796 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
26797 else if (STRINGP (default_help))
26798 wset_mode_line_help_echo (w, default_help);
26799 else
26800 wset_mode_line_help_echo (w, Qnil);
26801 }
26802
26803 selected_frame = new_frame;
26804
26805
26806 XSETWINDOW (selected_window, w);
26807 XFRAME (new_frame)->selected_window = selected_window;
26808
26809
26810 line_number_displayed = false;
26811 w->column_number_displayed = -1;
26812
26813 if (window_wants_mode_line (w))
26814 {
26815 Lisp_Object window_mode_line_format
26816 = window_parameter (w, Qmode_line_format);
26817 struct window *sel_w = XWINDOW (old_selected_window);
26818
26819
26820 display_mode_line (w,
26821 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
26822 NILP (window_mode_line_format)
26823 ? BVAR (current_buffer, mode_line_format)
26824 : window_mode_line_format);
26825 ++n;
26826 }
26827
26828 if (window_wants_tab_line (w))
26829 {
26830 Lisp_Object window_tab_line_format
26831 = window_parameter (w, Qtab_line_format);
26832
26833 display_mode_line (w, TAB_LINE_FACE_ID,
26834 NILP (window_tab_line_format)
26835 ? BVAR (current_buffer, tab_line_format)
26836 : window_tab_line_format);
26837 ++n;
26838 }
26839
26840 if (window_wants_header_line (w))
26841 {
26842 Lisp_Object window_header_line_format
26843 = window_parameter (w, Qheader_line_format);
26844
26845 display_mode_line (w, HEADER_LINE_FACE_ID,
26846 NILP (window_header_line_format)
26847 ? BVAR (current_buffer, header_line_format)
26848 : window_header_line_format);
26849 ++n;
26850 }
26851
26852 unbind_to (count, Qnil);
26853
26854 if (n > 0)
26855 w->must_be_updated_p = true;
26856 return n;
26857 }
26858
26859
26860
26861
26862
26863
26864
26865
26866 static int
26867 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
26868 {
26869 struct it it;
26870 struct face *face;
26871 specpdl_ref count = SPECPDL_INDEX ();
26872
26873 init_iterator (&it, w, -1, -1, NULL, face_id);
26874
26875
26876 it.glyph_row->enabled_p = false;
26877 prepare_desired_row (w, it.glyph_row, true);
26878
26879 it.glyph_row->mode_line_p = true;
26880 if (face_id == TAB_LINE_FACE_ID)
26881 {
26882 it.glyph_row->tab_line_p = true;
26883 w->desired_matrix->tab_line_p = true;
26884 }
26885 else if (face_id == HEADER_LINE_FACE_ID)
26886 w->desired_matrix->header_line_p = true;
26887
26888
26889
26890
26891 it.paragraph_embedding = L2R;
26892
26893 record_unwind_protect (unwind_format_mode_line,
26894 format_mode_line_unwind_data (NULL, NULL,
26895 Qnil, false));
26896
26897
26898
26899
26900 push_kboard (FRAME_KBOARD (it.f));
26901 record_unwind_save_match_data ();
26902
26903 if (NILP (Vmode_line_compact)
26904 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
26905 {
26906 mode_line_target = MODE_LINE_DISPLAY;
26907 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
26908 }
26909 else
26910 {
26911 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
26912 if (EQ (Vmode_line_compact, Qlong)
26913 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
26914 {
26915
26916
26917 display_string (NULL, mode_string, Qnil,
26918 0, 0, &it, 0, 0, 0,
26919 STRING_MULTIBYTE (mode_string));
26920 }
26921 else
26922 {
26923
26924 ptrdiff_t i = 0, i_byte = 0, start = 0;
26925 int prev = 0;
26926
26927 while (i < SCHARS (mode_string))
26928 {
26929 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
26930 if (c == ' ' && prev == ' ')
26931 {
26932 display_string (NULL,
26933 Fsubstring (mode_string, make_fixnum (start),
26934 make_fixnum (i - 1)),
26935 Qnil, 0, 0, &it, 0, 0, 0,
26936 STRING_MULTIBYTE (mode_string));
26937
26938 while (c == ' ' && i < SCHARS (mode_string))
26939 c = fetch_string_char_advance (mode_string, &i, &i_byte);
26940 start = i - 1;
26941 }
26942 prev = c;
26943 }
26944
26945
26946 if (start < i)
26947 display_string (NULL,
26948 Fsubstring (mode_string, make_fixnum (start),
26949 make_fixnum (i)),
26950 Qnil, 0, 0, &it, 0, 0, 0,
26951 STRING_MULTIBYTE (mode_string));
26952 }
26953 }
26954 pop_kboard ();
26955
26956 unbind_to (count, Qnil);
26957
26958
26959 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
26960
26961 compute_line_metrics (&it);
26962 it.glyph_row->full_width_p = true;
26963 it.glyph_row->continued_p = false;
26964 it.glyph_row->truncated_on_left_p = false;
26965 it.glyph_row->truncated_on_right_p = false;
26966
26967
26968 face = FACE_FROM_ID (it.f, face_id);
26969 extend_face_to_end_of_line (&it);
26970 if (face->box != FACE_NO_BOX)
26971 {
26972 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26973 + it.glyph_row->used[TEXT_AREA] - 1);
26974 int box_thickness = face->box_vertical_line_width;
26975 last->right_box_line_p = true;
26976
26977
26978
26979
26980
26981
26982 if (box_thickness > 0)
26983 last->pixel_width += max (0, (box_thickness
26984 - (it.current_x - it.last_visible_x)));
26985 }
26986
26987 return it.glyph_row->height;
26988 }
26989
26990
26991
26992
26993 static Lisp_Object
26994 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
26995 {
26996 register Lisp_Object tail, prev;
26997 register Lisp_Object tem;
26998
26999 tail = list;
27000 prev = Qnil;
27001 while (CONSP (tail))
27002 {
27003 tem = XCAR (tail);
27004
27005 if (EQ (elt, tem))
27006 {
27007
27008 if (NILP (prev))
27009 list = XCDR (tail);
27010 else
27011 Fsetcdr (prev, XCDR (tail));
27012
27013
27014 Fsetcdr (tail, list);
27015 return tail;
27016 }
27017 else
27018 prev = tail;
27019 tail = XCDR (tail);
27020 maybe_quit ();
27021 }
27022
27023
27024 return list;
27025 }
27026
27027
27028
27029
27030
27031 static Lisp_Object
27032 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
27033 {
27034 eassert (nargs == 4);
27035 return Fset_text_properties (args[0], args[1], args[2], args[3]);
27036 }
27037
27038
27039
27040
27041
27042
27043
27044
27045
27046
27047
27048
27049
27050
27051
27052
27053
27054
27055
27056
27057
27058
27059
27060
27061
27062 static int
27063 display_mode_element (struct it *it, int depth, int field_width, int precision,
27064 Lisp_Object elt, Lisp_Object props, bool risky)
27065 {
27066 int n = 0, field, prec;
27067 bool literal = false;
27068
27069 tail_recurse:
27070 if (depth > 100)
27071 elt = build_string ("*too-deep*");
27072
27073 depth++;
27074
27075 switch (XTYPE (elt))
27076 {
27077 case Lisp_String:
27078 {
27079
27080 unsigned char c;
27081 ptrdiff_t offset = 0;
27082
27083 if (SCHARS (elt) > 0
27084 && (!NILP (props) || risky))
27085 {
27086 Lisp_Object oprops, aelt;
27087 oprops = Ftext_properties_at (make_fixnum (0), elt);
27088
27089
27090
27091
27092
27093 if (NILP (Fequal (props, oprops)) || risky)
27094 {
27095
27096
27097 if (! NILP (oprops) && !risky)
27098 {
27099 Lisp_Object tem;
27100
27101 oprops = Fcopy_sequence (oprops);
27102 tem = props;
27103 while (CONSP (tem) && CONSP (XCDR (tem)))
27104 {
27105 oprops = plist_put (oprops, XCAR (tem),
27106 XCAR (XCDR (tem)));
27107 tem = XCDR (XCDR (tem));
27108 }
27109 props = oprops;
27110 }
27111
27112 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27113 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27114 {
27115
27116
27117 elt = XCAR (aelt);
27118 mode_line_proptrans_alist
27119 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27120 }
27121 else
27122 {
27123 Lisp_Object tem;
27124
27125
27126
27127 if (! NILP (aelt))
27128 mode_line_proptrans_alist
27129 = Fdelq (aelt, mode_line_proptrans_alist);
27130
27131 elt = Fcopy_sequence (elt);
27132
27133
27134
27135 internal_condition_case_n (safe_set_text_properties,
27136 4,
27137 ((Lisp_Object [])
27138 {make_fixnum (0),
27139 Flength (elt),
27140 props,
27141 elt}),
27142 Qt, safe_eval_handler);
27143
27144 mode_line_proptrans_alist
27145 = Fcons (Fcons (elt, props),
27146 mode_line_proptrans_alist);
27147
27148
27149 tem = Fnthcdr (make_fixnum (50),
27150 mode_line_proptrans_alist);
27151 if (! NILP (tem))
27152 XSETCDR (tem, Qnil);
27153 }
27154 }
27155 }
27156
27157 offset = 0;
27158
27159 if (literal)
27160 {
27161 prec = precision - n;
27162 switch (mode_line_target)
27163 {
27164 case MODE_LINE_NOPROP:
27165 case MODE_LINE_TITLE:
27166 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27167 break;
27168 case MODE_LINE_STRING:
27169 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27170 break;
27171 case MODE_LINE_DISPLAY:
27172 n += display_string (NULL, elt, Qnil, 0, 0, it,
27173 0, prec, 0, STRING_MULTIBYTE (elt));
27174 break;
27175 }
27176
27177 break;
27178 }
27179
27180
27181
27182 while ((precision <= 0 || n < precision)
27183 && SREF (elt, offset) != 0
27184 && (mode_line_target != MODE_LINE_DISPLAY
27185 || it->current_x < it->last_visible_x))
27186 {
27187 ptrdiff_t last_offset = offset;
27188
27189
27190 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27191 ;
27192
27193 if (offset - 1 != last_offset)
27194 {
27195 ptrdiff_t nchars, nbytes;
27196
27197
27198
27199
27200 offset--;
27201
27202 prec = c_string_width (SDATA (elt) + last_offset,
27203 offset - last_offset, precision - n,
27204 &nchars, &nbytes);
27205
27206 switch (mode_line_target)
27207 {
27208 case MODE_LINE_NOPROP:
27209 case MODE_LINE_TITLE:
27210 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27211 break;
27212 case MODE_LINE_STRING:
27213 {
27214 ptrdiff_t bytepos = last_offset;
27215 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27216 ptrdiff_t endpos = (precision <= 0
27217 ? string_byte_to_char (elt, offset)
27218 : charpos + nchars);
27219 Lisp_Object mode_string
27220 = Fsubstring (elt, make_fixnum (charpos),
27221 make_fixnum (endpos));
27222 n += store_mode_line_string (NULL, mode_string, false,
27223 0, 0, Qnil);
27224 }
27225 break;
27226 case MODE_LINE_DISPLAY:
27227 {
27228 ptrdiff_t bytepos = last_offset;
27229 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27230
27231 if (precision <= 0)
27232 nchars = string_byte_to_char (elt, offset) - charpos;
27233 n += display_string (NULL, elt, Qnil, 0, charpos,
27234 it, 0, nchars, 0,
27235 STRING_MULTIBYTE (elt));
27236 }
27237 break;
27238 }
27239 }
27240 else
27241 {
27242 ptrdiff_t percent_position = offset;
27243
27244
27245
27246 field = 0;
27247 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27248 field = field * 10 + c - '0';
27249
27250
27251 if (field_width - n > 0 && field > field_width - n)
27252 field = field_width - n;
27253
27254
27255 prec = precision - n;
27256
27257 if (c == 'M')
27258 n += display_mode_element (it, depth, field, prec,
27259 Vglobal_mode_string, props,
27260 risky);
27261 else if (c != 0)
27262 {
27263 bool multibyte;
27264 ptrdiff_t bytepos, charpos;
27265 const char *spec;
27266 Lisp_Object string;
27267
27268 bytepos = percent_position;
27269 charpos = (STRING_MULTIBYTE (elt)
27270 ? string_byte_to_char (elt, bytepos)
27271 : bytepos);
27272 spec = decode_mode_spec (it->w, c, field, &string);
27273 eassert (NILP (string) || STRINGP (string));
27274 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27275
27276
27277 ptrdiff_t nbytes = strlen (spec);
27278 ptrdiff_t nchars, mb_nbytes;
27279 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27280 &nchars, &mb_nbytes);
27281 if (!(nbytes == nchars || nbytes != mb_nbytes))
27282 multibyte = true;
27283
27284 switch (mode_line_target)
27285 {
27286 case MODE_LINE_NOPROP:
27287 case MODE_LINE_TITLE:
27288 n += store_mode_line_noprop (spec, field, prec);
27289 break;
27290 case MODE_LINE_STRING:
27291 {
27292 Lisp_Object tem = build_string (spec);
27293 props = Ftext_properties_at (make_fixnum (charpos), elt);
27294
27295 n += store_mode_line_string (NULL, tem, false,
27296 field, prec, props);
27297 }
27298 break;
27299 case MODE_LINE_DISPLAY:
27300 {
27301 int nglyphs_before, nwritten;
27302
27303 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27304 nwritten = display_string (spec, string, elt,
27305 charpos, 0, it,
27306 field, prec, 0,
27307 multibyte);
27308
27309
27310
27311
27312 if (nwritten > 0)
27313 {
27314 struct glyph *glyph
27315 = (it->glyph_row->glyphs[TEXT_AREA]
27316 + nglyphs_before);
27317 int i;
27318
27319 for (i = 0; i < nwritten; ++i)
27320 {
27321 glyph[i].object = elt;
27322 glyph[i].charpos = charpos;
27323 }
27324
27325 n += nwritten;
27326 }
27327 }
27328 break;
27329 }
27330 }
27331 else
27332 break;
27333 }
27334 }
27335 }
27336 break;
27337
27338 case Lisp_Symbol:
27339
27340
27341
27342
27343 {
27344 register Lisp_Object tem;
27345
27346
27347
27348 if (NILP (Fget (elt, Qrisky_local_variable)))
27349 risky = true;
27350
27351 tem = Fboundp (elt);
27352 if (!NILP (tem))
27353 {
27354 tem = Fsymbol_value (elt);
27355
27356
27357 if (STRINGP (tem))
27358 literal = true;
27359
27360 if (!EQ (tem, elt))
27361 {
27362
27363 elt = tem;
27364 goto tail_recurse;
27365 }
27366 }
27367 }
27368 break;
27369
27370 case Lisp_Cons:
27371 {
27372 register Lisp_Object car, tem;
27373
27374
27375
27376
27377
27378
27379
27380
27381
27382
27383 car = XCAR (elt);
27384 if (EQ (car, QCeval))
27385 {
27386
27387
27388
27389 if (risky)
27390 break;
27391
27392 if (CONSP (XCDR (elt)))
27393 {
27394 Lisp_Object spec;
27395 spec = safe__eval (true, XCAR (XCDR (elt)));
27396
27397
27398
27399
27400
27401
27402 if (!FRAME_LIVE_P (it->f))
27403 signal_error (":eval deleted the frame being displayed", elt);
27404 n += display_mode_element (it, depth, field_width - n,
27405 precision - n, spec, props,
27406 risky);
27407 }
27408 }
27409 else if (EQ (car, QCpropertize))
27410 {
27411
27412
27413
27414 if (risky)
27415 break;
27416
27417 if (CONSP (XCDR (elt)))
27418 n += display_mode_element (it, depth, field_width - n,
27419 precision - n, XCAR (XCDR (elt)),
27420 XCDR (XCDR (elt)), risky);
27421 }
27422 else if (SYMBOLP (car))
27423 {
27424 tem = Fboundp (car);
27425 elt = XCDR (elt);
27426 if (!CONSP (elt))
27427 goto invalid;
27428
27429
27430 if (!NILP (tem))
27431 {
27432 tem = Fsymbol_value (car);
27433 if (!NILP (tem))
27434 {
27435 elt = XCAR (elt);
27436 goto tail_recurse;
27437 }
27438 }
27439
27440
27441
27442 elt = XCDR (elt);
27443 if (NILP (elt))
27444 break;
27445 else if (!CONSP (elt))
27446 goto invalid;
27447 elt = XCAR (elt);
27448 goto tail_recurse;
27449 }
27450 else if (FIXNUMP (car))
27451 {
27452 register int lim = XFIXNUM (car);
27453 elt = XCDR (elt);
27454 if (lim < 0)
27455 {
27456
27457 if (precision <= 0)
27458 precision = -lim;
27459 else
27460 precision = min (precision, -lim);
27461 }
27462 else if (lim > 0)
27463 {
27464
27465
27466 if (precision > 0)
27467 lim = min (precision, lim);
27468
27469
27470
27471
27472 field_width = max (lim, field_width);
27473 }
27474 goto tail_recurse;
27475 }
27476 else if (STRINGP (car) || CONSP (car))
27477 FOR_EACH_TAIL_SAFE (elt)
27478 {
27479 if (0 < precision && precision <= n)
27480 break;
27481 n += display_mode_element (it, depth,
27482
27483
27484 (! CONSP (XCDR (elt))
27485 ? field_width - n
27486 : 0),
27487 precision - n, XCAR (elt),
27488 props, risky);
27489 }
27490 }
27491 break;
27492
27493 default:
27494 invalid:
27495 elt = build_string ("*invalid*");
27496 goto tail_recurse;
27497 }
27498
27499
27500 if (field_width > 0 && n < field_width)
27501 {
27502 switch (mode_line_target)
27503 {
27504 case MODE_LINE_NOPROP:
27505 case MODE_LINE_TITLE:
27506 n += store_mode_line_noprop ("", field_width - n, 0);
27507 break;
27508 case MODE_LINE_STRING:
27509 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27510 Qnil);
27511 break;
27512 case MODE_LINE_DISPLAY:
27513 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27514 0, 0, 0);
27515 break;
27516 }
27517 }
27518
27519 return n;
27520 }
27521
27522
27523
27524
27525
27526
27527
27528
27529
27530
27531
27532
27533
27534
27535
27536
27537
27538
27539
27540
27541 static int
27542 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27543 bool copy_string,
27544 int field_width, int precision, Lisp_Object props)
27545 {
27546 ptrdiff_t len;
27547 int n = 0;
27548
27549 if (string != NULL)
27550 {
27551 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27552 lisp_string = make_string (string, len);
27553 if (NILP (props))
27554 props = mode_line_string_face_prop;
27555 else if (!NILP (mode_line_string_face))
27556 {
27557 Lisp_Object face = plist_get (props, Qface);
27558 props = Fcopy_sequence (props);
27559 if (NILP (face))
27560 face = mode_line_string_face;
27561 else
27562 face = list2 (face, mode_line_string_face);
27563 props = plist_put (props, Qface, face);
27564 }
27565 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27566 props, lisp_string);
27567 }
27568 else
27569 {
27570 len = SCHARS (lisp_string);
27571 if (precision > 0 && len > precision)
27572 {
27573 len = precision;
27574 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27575 precision = -1;
27576 }
27577 if (!NILP (mode_line_string_face))
27578 {
27579 Lisp_Object face;
27580 if (NILP (props))
27581 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27582 face = plist_get (props, Qface);
27583 if (NILP (face))
27584 face = mode_line_string_face;
27585 else
27586 face = list2 (face, mode_line_string_face);
27587 props = list2 (Qface, face);
27588 if (copy_string)
27589 lisp_string = Fcopy_sequence (lisp_string);
27590 }
27591 if (!NILP (props))
27592 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27593 props, lisp_string);
27594 }
27595
27596 if (len > 0)
27597 {
27598 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27599 n += len;
27600 }
27601
27602 if (field_width > len)
27603 {
27604 field_width -= len;
27605 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27606 Qnil);
27607 if (!NILP (props))
27608 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27609 props, lisp_string);
27610 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27611 n += field_width;
27612 }
27613
27614 return n;
27615 }
27616
27617
27618 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27619 1, 4, 0,
27620 doc:
27621
27622
27623
27624
27625
27626
27627
27628
27629
27630
27631
27632
27633
27634
27635
27636 )
27637 (Lisp_Object format, Lisp_Object face,
27638 Lisp_Object window, Lisp_Object buffer)
27639 {
27640 struct it it;
27641 int len;
27642 struct window *w;
27643 struct buffer *old_buffer = NULL;
27644 int face_id;
27645 bool no_props = FIXNUMP (face);
27646 specpdl_ref count = SPECPDL_INDEX ();
27647 Lisp_Object str;
27648 int string_start = 0;
27649
27650 w = decode_any_window (window);
27651 XSETWINDOW (window, w);
27652
27653 if (NILP (buffer))
27654 buffer = w->contents;
27655 CHECK_BUFFER (buffer);
27656 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
27657 error ("Attempt to format a mode line for a dead buffer");
27658
27659
27660
27661 if (NILP (format) || noninteractive)
27662 return empty_unibyte_string;
27663
27664 if (no_props)
27665 face = Qnil;
27666
27667 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27668 : EQ (face, Qt) ? (EQ (window, selected_window)
27669 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27670 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27671 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27672 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27673 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27674 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27675 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27676 : DEFAULT_FACE_ID;
27677
27678 old_buffer = current_buffer;
27679
27680
27681
27682 record_unwind_protect (unwind_format_mode_line,
27683 format_mode_line_unwind_data
27684 (XFRAME (WINDOW_FRAME (w)),
27685 old_buffer, selected_window, true));
27686 mode_line_proptrans_alist = Qnil;
27687
27688 Fselect_window (window, Qt);
27689 set_buffer_internal_1 (XBUFFER (buffer));
27690
27691 init_iterator (&it, w, -1, -1, NULL, face_id);
27692
27693 if (no_props)
27694 {
27695 mode_line_target = MODE_LINE_NOPROP;
27696 mode_line_string_face_prop = Qnil;
27697 mode_line_string_list = Qnil;
27698 string_start = MODE_LINE_NOPROP_LEN (0);
27699 }
27700 else
27701 {
27702 mode_line_target = MODE_LINE_STRING;
27703 mode_line_string_list = Qnil;
27704 mode_line_string_face = face;
27705 mode_line_string_face_prop
27706 = NILP (face) ? Qnil : list2 (Qface, face);
27707 }
27708
27709 push_kboard (FRAME_KBOARD (it.f));
27710 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27711 pop_kboard ();
27712
27713 if (no_props)
27714 {
27715 len = MODE_LINE_NOPROP_LEN (string_start);
27716 str = make_string (mode_line_noprop_buf + string_start, len);
27717 }
27718 else
27719 {
27720 mode_line_string_list = Fnreverse (mode_line_string_list);
27721 str = Fmapconcat (Qidentity, mode_line_string_list,
27722 empty_unibyte_string);
27723 }
27724
27725 return unbind_to (count, str);
27726 }
27727
27728
27729
27730
27731 static void
27732 pint2str (register char *buf, register int width, register ptrdiff_t d)
27733 {
27734 register char *p = buf;
27735
27736 if (d <= 0)
27737 *p++ = '0';
27738 else
27739 {
27740 while (d > 0)
27741 {
27742 *p++ = d % 10 + '0';
27743 d /= 10;
27744 }
27745 }
27746
27747 for (width -= (int) (p - buf); width > 0; --width)
27748 *p++ = ' ';
27749 *p-- = '\0';
27750 while (p > buf)
27751 {
27752 d = *buf;
27753 *buf++ = *p;
27754 *p-- = d;
27755 }
27756 }
27757
27758
27759
27760
27761
27762 static const char power_letter[] =
27763 {
27764 0,
27765 'k',
27766 'M',
27767 'G',
27768 'T',
27769 'P',
27770 'E',
27771 'Z',
27772 'Y'
27773 };
27774
27775 static void
27776 pint2hrstr (char *buf, int width, ptrdiff_t d)
27777 {
27778
27779
27780 ptrdiff_t quotient = d;
27781 int remainder = 0;
27782
27783 int tenths = -1;
27784 int exponent = 0;
27785
27786
27787 int length;
27788
27789 char * psuffix;
27790 char * p;
27791
27792 if (quotient >= 1000)
27793 {
27794
27795 do
27796 {
27797 remainder = quotient % 1000;
27798 quotient /= 1000;
27799 exponent++;
27800 }
27801 while (quotient >= 1000);
27802
27803
27804 if (quotient <= 9)
27805 {
27806 tenths = remainder / 100;
27807 if (remainder % 100 >= 50)
27808 {
27809 if (tenths < 9)
27810 tenths++;
27811 else
27812 {
27813 quotient++;
27814 if (quotient == 10)
27815 tenths = -1;
27816 else
27817 tenths = 0;
27818 }
27819 }
27820 }
27821 else
27822 if (remainder >= 500)
27823 {
27824 if (quotient < 999)
27825 quotient++;
27826 else
27827 {
27828 quotient = 1;
27829 exponent++;
27830 tenths = 0;
27831 }
27832 }
27833 }
27834
27835
27836 if (tenths == -1 && quotient <= 99)
27837 if (quotient <= 9)
27838 length = 1;
27839 else
27840 length = 2;
27841 else
27842 length = 3;
27843 p = psuffix = buf + max (width, length);
27844
27845
27846 *psuffix++ = power_letter[exponent];
27847 *psuffix = '\0';
27848
27849
27850 if (tenths >= 0)
27851 {
27852 *--p = '0' + tenths;
27853 *--p = '.';
27854 }
27855
27856
27857 do
27858 {
27859 int digit = quotient % 10;
27860 *--p = '0' + digit;
27861 }
27862 while ((quotient /= 10) != 0);
27863
27864
27865 while (buf < p)
27866 *--p = ' ';
27867 }
27868
27869
27870
27871
27872
27873 static unsigned char invalid_eol_type[] = "(*invalid*)";
27874
27875 static char *
27876 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
27877 {
27878 Lisp_Object val;
27879 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
27880 const unsigned char *eol_str;
27881 int eol_str_len;
27882
27883 Lisp_Object eoltype;
27884
27885 val = CODING_SYSTEM_SPEC (coding_system);
27886 eoltype = Qnil;
27887
27888 if (!VECTORP (val))
27889 {
27890 *buf++ = multibyte ? '-' : ' ';
27891 if (eol_flag)
27892 eoltype = eol_mnemonic_undecided;
27893
27894 }
27895 else
27896 {
27897 Lisp_Object attrs;
27898 Lisp_Object eolvalue;
27899
27900 attrs = AREF (val, 0);
27901 eolvalue = AREF (val, 2);
27902
27903 if (multibyte)
27904 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
27905 (unsigned char *) buf);
27906 else
27907 *buf++ = ' ';
27908
27909 if (eol_flag)
27910 {
27911
27912
27913 if (NILP (eolvalue))
27914 eoltype = eol_mnemonic_undecided;
27915 else if (VECTORP (eolvalue))
27916 eoltype = eol_mnemonic_undecided;
27917 else
27918 eoltype = (EQ (eolvalue, Qunix)
27919 ? eol_mnemonic_unix
27920 : EQ (eolvalue, Qdos)
27921 ? eol_mnemonic_dos : eol_mnemonic_mac);
27922 }
27923 }
27924
27925 if (eol_flag)
27926 {
27927
27928 if (STRINGP (eoltype))
27929 {
27930 eol_str = SDATA (eoltype);
27931 eol_str_len = SBYTES (eoltype);
27932 }
27933 else if (CHARACTERP (eoltype))
27934 {
27935 int c = XFIXNAT (eoltype);
27936 return buf + CHAR_STRING (c, (unsigned char *) buf);
27937 }
27938 else
27939 {
27940 eol_str = invalid_eol_type;
27941 eol_str_len = sizeof (invalid_eol_type) - 1;
27942 }
27943 memcpy (buf, eol_str, eol_str_len);
27944 buf += eol_str_len;
27945 }
27946
27947 return buf;
27948 }
27949
27950
27951
27952
27953 static int
27954 percent99 (ptrdiff_t n, ptrdiff_t d)
27955 {
27956 int percent = (d - 1 + 100.0 * n) / d;
27957 return min (percent, 99);
27958 }
27959
27960
27961
27962
27963
27964
27965
27966
27967
27968 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
27969
27970 static const char *
27971 decode_mode_spec (struct window *w, register int c, int field_width,
27972 Lisp_Object *string)
27973 {
27974 Lisp_Object obj;
27975 struct frame *f = XFRAME (WINDOW_FRAME (w));
27976 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
27977
27978
27979
27980
27981
27982 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
27983 struct buffer *b = current_buffer;
27984
27985 obj = Qnil;
27986 *string = Qnil;
27987
27988 switch (c)
27989 {
27990 case '*':
27991 if (!NILP (BVAR (b, read_only)))
27992 return "%";
27993 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
27994 return "*";
27995 return "-";
27996
27997 case '+':
27998
27999 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28000 return "*";
28001 if (!NILP (BVAR (b, read_only)))
28002 return "%";
28003 return "-";
28004
28005 case '&':
28006
28007 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28008 return "*";
28009 return "-";
28010
28011 case '%':
28012 return "%";
28013
28014 case '[':
28015 {
28016 int i;
28017 char *p;
28018
28019 if (command_loop_level > 5)
28020 return "[[[... ";
28021 p = decode_mode_spec_buf;
28022 for (i = 0; i < command_loop_level; i++)
28023 *p++ = '[';
28024 *p = 0;
28025 return decode_mode_spec_buf;
28026 }
28027
28028 case ']':
28029 {
28030 int i;
28031 char *p;
28032
28033 if (command_loop_level > 5)
28034 return " ...]]]";
28035 p = decode_mode_spec_buf;
28036 for (i = 0; i < command_loop_level; i++)
28037 *p++ = ']';
28038 *p = 0;
28039 return decode_mode_spec_buf;
28040 }
28041
28042 case '-':
28043 {
28044 register int i;
28045
28046
28047 if (mode_line_target == MODE_LINE_NOPROP
28048 || mode_line_target == MODE_LINE_STRING)
28049 return "--";
28050 if (field_width <= 0
28051 || field_width > sizeof (lots_of_dashes))
28052 {
28053 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28054 decode_mode_spec_buf[i] = '-';
28055 decode_mode_spec_buf[i] = '\0';
28056 return decode_mode_spec_buf;
28057 }
28058 else
28059 return lots_of_dashes;
28060 }
28061
28062 case 'b':
28063 obj = BVAR (b, name);
28064 break;
28065
28066 case 'c':
28067 case 'C':
28068
28069
28070
28071
28072
28073 if (mode_line_target == MODE_LINE_TITLE)
28074 return "";
28075 else
28076 {
28077 ptrdiff_t col = current_column ();
28078 int disp_col = (c == 'C') ? col + 1 : col;
28079 w->column_number_displayed = col;
28080 pint2str (decode_mode_spec_buf, width, disp_col);
28081 return decode_mode_spec_buf;
28082 }
28083
28084 case 'e':
28085 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28086 {
28087 if (NILP (Vmemory_full))
28088 return "";
28089 else
28090 return "!MEM FULL! ";
28091 }
28092 #else
28093 return "";
28094 #endif
28095
28096 case 'F':
28097
28098 if (!NILP (f->title))
28099 return SSDATA (f->title);
28100 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28101 return SSDATA (f->name);
28102 return "Emacs";
28103
28104 case 'f':
28105 obj = BVAR (b, filename);
28106 break;
28107
28108 case 'i':
28109 {
28110 ptrdiff_t size = ZV - BEGV;
28111 pint2str (decode_mode_spec_buf, width, size);
28112 return decode_mode_spec_buf;
28113 }
28114
28115 case 'I':
28116 {
28117 ptrdiff_t size = ZV - BEGV;
28118 pint2hrstr (decode_mode_spec_buf, width, size);
28119 return decode_mode_spec_buf;
28120 }
28121
28122 case 'l':
28123 {
28124 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28125 ptrdiff_t topline, nlines, height;
28126 ptrdiff_t junk;
28127
28128
28129 if (mode_line_target == MODE_LINE_TITLE)
28130 return "";
28131
28132 startpos = marker_position (w->start);
28133 startpos_byte = marker_byte_position (w->start);
28134 height = WINDOW_TOTAL_LINES (w);
28135
28136
28137
28138
28139
28140
28141
28142
28143 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28144 && startpos_byte <= BUF_ZV_BYTE (b)))
28145 {
28146 startpos = BUF_BEGV (b);
28147 startpos_byte = BUF_BEGV_BYTE (b);
28148 w->base_line_pos = 0;
28149 w->base_line_number = 0;
28150 }
28151
28152
28153
28154 if (w->base_line_pos == -1)
28155 goto no_value;
28156
28157
28158 if (FIXNUMP (Vline_number_display_limit)
28159 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28160 {
28161 w->base_line_pos = 0;
28162 w->base_line_number = 0;
28163 goto no_value;
28164 }
28165
28166 if (w->base_line_number > 0
28167 && w->base_line_pos > 0
28168 && w->base_line_pos <= startpos)
28169 {
28170 line = w->base_line_number;
28171 linepos = w->base_line_pos;
28172 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28173 }
28174 else
28175 {
28176 line = 1;
28177 linepos = BUF_BEGV (b);
28178 linepos_byte = BUF_BEGV_BYTE (b);
28179 }
28180
28181
28182 nlines = display_count_lines (linepos_byte,
28183 startpos_byte,
28184 startpos, &junk);
28185
28186 topline = nlines + line;
28187
28188
28189
28190
28191
28192 if (startpos == BUF_BEGV (b))
28193 {
28194 w->base_line_number = topline;
28195 w->base_line_pos = BUF_BEGV (b);
28196 }
28197 else if (nlines < height + 25 || nlines > height * 3 + 50
28198 || linepos == BUF_BEGV (b))
28199 {
28200 ptrdiff_t limit = BUF_BEGV (b);
28201 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28202 ptrdiff_t position;
28203 ptrdiff_t distance
28204 = (line_number_display_limit_width < 0 ? 0
28205 : INT_MULTIPLY_WRAPV (line_number_display_limit_width,
28206 height * 2 + 30,
28207 &distance)
28208 ? PTRDIFF_MAX : distance);
28209
28210 if (startpos - distance > limit)
28211 {
28212 limit = startpos - distance;
28213 limit_byte = CHAR_TO_BYTE (limit);
28214 }
28215
28216 nlines = display_count_lines (startpos_byte,
28217 limit_byte,
28218 - (height * 2 + 30),
28219 &position);
28220
28221
28222
28223 if (position == limit_byte && limit == startpos - distance)
28224 {
28225 w->base_line_pos = -1;
28226 w->base_line_number = 0;
28227 goto no_value;
28228 }
28229
28230 w->base_line_number = topline - nlines;
28231 w->base_line_pos = BYTE_TO_CHAR (position);
28232 }
28233
28234
28235 nlines = display_count_lines (startpos_byte,
28236 PT_BYTE, PT, &junk);
28237
28238
28239 line_number_displayed = true;
28240
28241
28242 pint2str (decode_mode_spec_buf, width, topline + nlines);
28243 return decode_mode_spec_buf;
28244 no_value:
28245 {
28246 char *p = decode_mode_spec_buf;
28247 int pad = width - 2;
28248 while (pad-- > 0)
28249 *p++ = ' ';
28250 *p++ = '?';
28251 *p++ = '?';
28252 *p = '\0';
28253 return decode_mode_spec_buf;
28254 }
28255 }
28256 break;
28257
28258 case 'm':
28259 obj = BVAR (b, mode_name);
28260 break;
28261
28262 case 'n':
28263 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28264 return " Narrow";
28265 break;
28266
28267
28268 case 'o':
28269 {
28270 ptrdiff_t toppos = marker_position (w->start);
28271 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28272 ptrdiff_t begv = BUF_BEGV (b);
28273 ptrdiff_t zv = BUF_ZV (b);
28274
28275 if (zv <= botpos)
28276 return toppos <= begv ? "All" : "Bottom";
28277 else if (toppos <= begv)
28278 return "Top";
28279 else
28280 {
28281 sprintf (decode_mode_spec_buf, "%2d%%",
28282 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28283 return decode_mode_spec_buf;
28284 }
28285 }
28286
28287
28288 case 'p':
28289 {
28290 ptrdiff_t pos = marker_position (w->start);
28291 ptrdiff_t begv = BUF_BEGV (b);
28292 ptrdiff_t zv = BUF_ZV (b);
28293
28294 if (w->window_end_pos <= BUF_Z (b) - zv)
28295 return pos <= begv ? "All" : "Bottom";
28296 else if (pos <= begv)
28297 return "Top";
28298 else
28299 {
28300 sprintf (decode_mode_spec_buf, "%2d%%",
28301 percent99 (pos - begv, zv - begv));
28302 return decode_mode_spec_buf;
28303 }
28304 }
28305
28306
28307 case 'P':
28308 {
28309 ptrdiff_t toppos = marker_position (w->start);
28310 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28311 ptrdiff_t begv = BUF_BEGV (b);
28312 ptrdiff_t zv = BUF_ZV (b);
28313
28314 if (zv <= botpos)
28315 return toppos <= begv ? "All" : "Bottom";
28316 else
28317 {
28318 sprintf (decode_mode_spec_buf,
28319 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28320 percent99 (botpos - begv, zv - begv));
28321 return decode_mode_spec_buf;
28322 }
28323 }
28324
28325
28326
28327 case 'q':
28328 {
28329 ptrdiff_t toppos = marker_position (w->start);
28330 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28331 ptrdiff_t begv = BUF_BEGV (b);
28332 ptrdiff_t zv = BUF_ZV (b);
28333 int top_perc, bot_perc;
28334
28335 if ((toppos <= begv) && (zv <= botpos))
28336 return "All ";
28337
28338 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28339 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28340
28341 if (top_perc == bot_perc)
28342 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28343 else
28344 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28345
28346 return decode_mode_spec_buf;
28347 }
28348
28349 case 's':
28350
28351 obj = Fget_buffer_process (Fcurrent_buffer ());
28352 if (NILP (obj))
28353 return "no process";
28354 #ifndef MSDOS
28355 obj = Fsymbol_name (Fprocess_status (obj));
28356 #endif
28357 break;
28358
28359 case '@':
28360 {
28361 specpdl_ref count = inhibit_garbage_collection ();
28362 Lisp_Object curdir = BVAR (current_buffer, directory);
28363 Lisp_Object val = Qnil;
28364
28365 if (STRINGP (curdir))
28366 val = safe_call1 (intern ("file-remote-p"), curdir);
28367
28368 val = unbind_to (count, val);
28369
28370 if (NILP (val))
28371 return "-";
28372 else
28373 return "@";
28374 }
28375
28376 case 'z':
28377
28378 case 'Z':
28379
28380 {
28381 bool eol_flag = (c == 'Z');
28382 char *p = decode_mode_spec_buf;
28383
28384 if (! FRAME_WINDOW_P (f))
28385 {
28386
28387
28388 p = decode_mode_spec_coding (CODING_ID_NAME
28389 (FRAME_KEYBOARD_CODING (f)->id),
28390 p, false);
28391 p = decode_mode_spec_coding (CODING_ID_NAME
28392 (FRAME_TERMINAL_CODING (f)->id),
28393 p, false);
28394 }
28395 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28396 p, eol_flag);
28397
28398 #if false
28399 #ifdef subprocesses
28400 obj = Fget_buffer_process (Fcurrent_buffer ());
28401 if (PROCESSP (obj))
28402 {
28403 p = decode_mode_spec_coding
28404 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28405 p = decode_mode_spec_coding
28406 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28407 }
28408 #endif
28409 #endif
28410 *p = 0;
28411 return decode_mode_spec_buf;
28412 }
28413 }
28414
28415 if (STRINGP (obj))
28416 {
28417 *string = obj;
28418 return SSDATA (obj);
28419 }
28420 else
28421 return "";
28422 }
28423
28424
28425
28426
28427 ptrdiff_t
28428 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28429 {
28430 ptrdiff_t ignored;
28431 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28432 }
28433
28434
28435
28436
28437
28438
28439
28440
28441
28442
28443
28444 static ptrdiff_t
28445 display_count_lines (ptrdiff_t start_byte,
28446 ptrdiff_t limit_byte, ptrdiff_t count,
28447 ptrdiff_t *byte_pos_ptr)
28448 {
28449 register unsigned char *cursor;
28450 unsigned char *base;
28451
28452 register ptrdiff_t ceiling;
28453 register unsigned char *ceiling_addr;
28454 ptrdiff_t orig_count = count;
28455
28456
28457
28458 bool selective_display
28459 = (!NILP (BVAR (current_buffer, selective_display))
28460 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28461
28462 if (count > 0)
28463 {
28464 while (start_byte < limit_byte)
28465 {
28466 ceiling = BUFFER_CEILING_OF (start_byte);
28467 ceiling = min (limit_byte - 1, ceiling);
28468 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28469 base = (cursor = BYTE_POS_ADDR (start_byte));
28470
28471 do
28472 {
28473 if (selective_display)
28474 {
28475 while (*cursor != '\n' && *cursor != 015
28476 && ++cursor != ceiling_addr)
28477 continue;
28478 if (cursor == ceiling_addr)
28479 break;
28480 }
28481 else
28482 {
28483 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28484 if (! cursor)
28485 break;
28486 }
28487
28488 cursor++;
28489
28490 if (--count == 0)
28491 {
28492 start_byte += cursor - base;
28493 *byte_pos_ptr = start_byte;
28494 return orig_count;
28495 }
28496 }
28497 while (cursor < ceiling_addr);
28498
28499 start_byte += ceiling_addr - base;
28500 }
28501 }
28502 else
28503 {
28504 while (start_byte > limit_byte)
28505 {
28506 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28507 ceiling = max (limit_byte, ceiling);
28508 ceiling_addr = BYTE_POS_ADDR (ceiling);
28509 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28510 while (true)
28511 {
28512 if (selective_display)
28513 {
28514 while (--cursor >= ceiling_addr
28515 && *cursor != '\n' && *cursor != 015)
28516 continue;
28517 if (cursor < ceiling_addr)
28518 break;
28519 }
28520 else
28521 {
28522 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28523 if (! cursor)
28524 break;
28525 }
28526
28527 if (++count == 0)
28528 {
28529 start_byte += cursor - base + 1;
28530 *byte_pos_ptr = start_byte;
28531
28532
28533 return - orig_count - 1;
28534 }
28535 }
28536 start_byte += ceiling_addr - base;
28537 }
28538 }
28539
28540 *byte_pos_ptr = limit_byte;
28541
28542 if (count < 0)
28543 return - orig_count + count;
28544 return orig_count - count;
28545
28546 }
28547
28548
28549
28550
28551
28552
28553
28554
28555
28556
28557
28558
28559
28560
28561
28562
28563
28564
28565
28566
28567
28568
28569
28570
28571
28572
28573
28574
28575
28576
28577
28578
28579
28580
28581
28582
28583
28584
28585
28586
28587
28588
28589
28590
28591
28592 static int
28593 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28594 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28595 int field_width, int precision, int max_x, int multibyte)
28596 {
28597 int hpos_at_start = it->hpos;
28598 int saved_face_id = it->face_id;
28599 struct glyph_row *row = it->glyph_row;
28600 ptrdiff_t it_charpos;
28601
28602
28603
28604 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28605 start, precision, field_width, multibyte);
28606
28607 if (string && STRINGP (lisp_string))
28608
28609
28610 it->stop_charpos = it->end_charpos;
28611
28612
28613
28614 if (STRINGP (face_string))
28615 {
28616 ptrdiff_t endptr;
28617 struct face *face;
28618
28619 it->face_id
28620 = face_at_string_position (it->w, face_string, face_string_pos,
28621 0, &endptr, it->base_face_id, false, 0);
28622 face = FACE_FROM_ID (it->f, it->face_id);
28623 it->face_box_p = face->box != FACE_NO_BOX;
28624
28625
28626
28627
28628 if (NILP (lisp_string))
28629 {
28630 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28631 face_string);
28632 if (!NILP (display))
28633 {
28634 Lisp_Object min_width = plist_get (display, Qmin_width);
28635 if (!NILP (min_width))
28636 display_min_width (it, 0, face_string, min_width);
28637 }
28638 }
28639 }
28640
28641
28642
28643 if (max_x <= 0)
28644 max_x = it->last_visible_x;
28645 else
28646 max_x = min (max_x, it->last_visible_x);
28647
28648
28649
28650 if (it->current_x < it->first_visible_x)
28651 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28652 MOVE_TO_POS | MOVE_TO_X);
28653
28654 row->ascent = it->max_ascent;
28655 row->height = it->max_ascent + it->max_descent;
28656 row->phys_ascent = it->max_phys_ascent;
28657 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28658 row->extra_line_spacing = it->max_extra_line_spacing;
28659
28660 if (STRINGP (it->string))
28661 it_charpos = IT_STRING_CHARPOS (*it);
28662 else
28663 it_charpos = IT_CHARPOS (*it);
28664
28665
28666
28667 while (it->current_x < max_x)
28668 {
28669 int x_before, x, n_glyphs_before, i, nglyphs;
28670
28671
28672 if (!get_next_display_element (it))
28673 break;
28674
28675
28676 x_before = it->current_x;
28677 n_glyphs_before = row->used[TEXT_AREA];
28678 PRODUCE_GLYPHS (it);
28679
28680 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28681 i = 0;
28682 x = x_before;
28683 while (i < nglyphs)
28684 {
28685 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28686
28687 if (it->line_wrap != TRUNCATE
28688 && x + glyph->pixel_width > max_x)
28689 {
28690
28691 if (CHAR_GLYPH_PADDING_P (*glyph))
28692 {
28693
28694 if (row->reversed_p)
28695 unproduce_glyphs (it, row->used[TEXT_AREA]
28696 - n_glyphs_before);
28697 row->used[TEXT_AREA] = n_glyphs_before;
28698 it->current_x = x_before;
28699 }
28700 else
28701 {
28702 if (row->reversed_p)
28703 unproduce_glyphs (it, row->used[TEXT_AREA]
28704 - (n_glyphs_before + i));
28705 row->used[TEXT_AREA] = n_glyphs_before + i;
28706 it->current_x = x;
28707 }
28708 break;
28709 }
28710 else if (x + glyph->pixel_width >= it->first_visible_x)
28711 {
28712
28713 ++it->hpos;
28714 if (x < it->first_visible_x)
28715 row->x = x - it->first_visible_x;
28716 }
28717 else
28718 {
28719
28720
28721 emacs_abort ();
28722 }
28723
28724 row->ascent = max (row->ascent, it->max_ascent);
28725 row->height = max (row->height, it->max_ascent + it->max_descent);
28726 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28727 row->phys_height = max (row->phys_height,
28728 it->max_phys_ascent + it->max_phys_descent);
28729 row->extra_line_spacing = max (row->extra_line_spacing,
28730 it->max_extra_line_spacing);
28731 x += glyph->pixel_width;
28732 ++i;
28733 }
28734
28735
28736 if (i < nglyphs)
28737 break;
28738
28739
28740 if (ITERATOR_AT_END_OF_LINE_P (it))
28741 {
28742 it->continuation_lines_width = 0;
28743 break;
28744 }
28745
28746 set_iterator_to_next (it, true);
28747 if (STRINGP (it->string))
28748 it_charpos = IT_STRING_CHARPOS (*it);
28749 else
28750 it_charpos = IT_CHARPOS (*it);
28751
28752
28753 if (it->line_wrap == TRUNCATE
28754 && it->current_x >= it->last_visible_x)
28755 {
28756
28757
28758 if (it_charpos < it->string_nchars)
28759 {
28760 if (!FRAME_WINDOW_P (it->f))
28761 {
28762 int ii, n;
28763
28764 if (it->current_x > it->last_visible_x)
28765 {
28766 if (!row->reversed_p)
28767 {
28768 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
28769 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28770 break;
28771 }
28772 else
28773 {
28774 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
28775 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28776 break;
28777 unproduce_glyphs (it, ii + 1);
28778 ii = row->used[TEXT_AREA] - (ii + 1);
28779 }
28780 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
28781 {
28782 row->used[TEXT_AREA] = ii;
28783 produce_special_glyphs (it, IT_TRUNCATION);
28784 }
28785 }
28786 produce_special_glyphs (it, IT_TRUNCATION);
28787 }
28788 row->truncated_on_right_p = true;
28789 }
28790 break;
28791 }
28792 }
28793
28794
28795 if (it->first_visible_x
28796 && it_charpos > 0)
28797 {
28798 if (!FRAME_WINDOW_P (it->f)
28799 || (row->reversed_p
28800 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
28801 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
28802 insert_left_trunc_glyphs (it);
28803 row->truncated_on_left_p = true;
28804 }
28805
28806 it->face_id = saved_face_id;
28807
28808
28809 return it->hpos - hpos_at_start;
28810 }
28811
28812
28813
28814
28815
28816
28817
28818
28819
28820
28821
28822 int
28823 invisible_prop (Lisp_Object propval, Lisp_Object list)
28824 {
28825 Lisp_Object tail, proptail;
28826
28827 for (tail = list; CONSP (tail); tail = XCDR (tail))
28828 {
28829 register Lisp_Object tem;
28830 tem = XCAR (tail);
28831 if (EQ (propval, tem))
28832 return 1;
28833 if (CONSP (tem) && EQ (propval, XCAR (tem)))
28834 return NILP (XCDR (tem)) ? 1 : 2;
28835 }
28836
28837 if (CONSP (propval))
28838 {
28839 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
28840 {
28841 Lisp_Object propelt;
28842 propelt = XCAR (proptail);
28843 for (tail = list; CONSP (tail); tail = XCDR (tail))
28844 {
28845 register Lisp_Object tem;
28846 tem = XCAR (tail);
28847 if (EQ (propelt, tem))
28848 return 1;
28849 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
28850 return NILP (XCDR (tem)) ? 1 : 2;
28851 }
28852 }
28853 }
28854
28855 return 0;
28856 }
28857
28858 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
28859 doc:
28860
28861
28862
28863
28864
28865
28866
28867
28868
28869
28870
28871 )
28872 (Lisp_Object pos)
28873 {
28874 Lisp_Object prop
28875 = (FIXNATP (pos) || MARKERP (pos)
28876 ? Fget_char_property (pos, Qinvisible, Qnil)
28877 : pos);
28878 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
28879 return (invis == 0 ? Qnil
28880 : invis == 1 ? Qt
28881 : make_fixnum (invis));
28882 }
28883
28884
28885
28886
28887
28888
28889
28890
28891
28892
28893
28894
28895
28896
28897
28898
28899
28900
28901
28902
28903
28904
28905
28906
28907
28908
28909
28910
28911
28912
28913
28914
28915
28916
28917
28918
28919
28920
28921
28922
28923
28924
28925
28926
28927
28928
28929
28930
28931
28932
28933
28934
28935
28936
28937
28938
28939
28940
28941
28942
28943
28944
28945
28946
28947
28948
28949
28950
28951
28952
28953
28954
28955
28956
28957
28958
28959
28960
28961
28962
28963
28964 static bool
28965 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
28966 struct font *font, bool width_p, int *align_to)
28967 {
28968
28969
28970
28971
28972 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
28973 double pixels;
28974
28975 # define OK_PIXELS(val) (*res = (val), true)
28976 # define OK_ALIGN_TO(val) (*align_to = (val), true)
28977
28978 if (NILP (prop))
28979 return OK_PIXELS (0);
28980
28981 eassert (FRAME_LIVE_P (it->f));
28982
28983 if (SYMBOLP (prop))
28984 {
28985 if (SCHARS (SYMBOL_NAME (prop)) == 2)
28986 {
28987 char *unit = SSDATA (SYMBOL_NAME (prop));
28988
28989
28990 if (unit[0] == 'i' && unit[1] == 'n')
28991 pixels = 1.0;
28992 else if (unit[0] == 'm' && unit[1] == 'm')
28993 pixels = 25.4;
28994 else if (unit[0] == 'c' && unit[1] == 'm')
28995 pixels = 2.54;
28996 else
28997 pixels = 0;
28998 if (pixels > 0)
28999 {
29000 double ppi = (width_p ? FRAME_RES_X (it->f)
29001 : FRAME_RES_Y (it->f));
29002
29003 if (ppi > 0)
29004 return OK_PIXELS (ppi / pixels);
29005 return false;
29006 }
29007 }
29008
29009 #ifdef HAVE_WINDOW_SYSTEM
29010
29011 if (EQ (prop, Qheight))
29012 return OK_PIXELS (font
29013 ? normal_char_height (font, -1)
29014 : FRAME_LINE_HEIGHT (it->f));
29015
29016 if (EQ (prop, Qwidth))
29017 return OK_PIXELS (font
29018 ? FONT_WIDTH (font)
29019 : FRAME_COLUMN_WIDTH (it->f));
29020 #else
29021 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
29022 return OK_PIXELS (1);
29023 #endif
29024
29025
29026 if (EQ (prop, Qtext))
29027 return OK_PIXELS (width_p
29028 ? (window_box_width (it->w, TEXT_AREA)
29029 - lnum_pixel_width)
29030 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
29031
29032
29033
29034
29035 if (align_to && *align_to < 0)
29036 {
29037 *res = 0;
29038
29039 if (EQ (prop, Qleft))
29040 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29041 + lnum_pixel_width);
29042
29043 if (EQ (prop, Qright))
29044 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
29045
29046 if (EQ (prop, Qcenter))
29047 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29048 + lnum_pixel_width
29049 + window_box_width (it->w, TEXT_AREA) / 2);
29050
29051 if (EQ (prop, Qleft_fringe))
29052 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29053 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29054 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29055
29056 if (EQ (prop, Qright_fringe))
29057 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29058 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29059 : window_box_right_offset (it->w, TEXT_AREA));
29060
29061 if (EQ (prop, Qleft_margin))
29062 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29063
29064 if (EQ (prop, Qright_margin))
29065 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29066
29067 if (EQ (prop, Qscroll_bar))
29068 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29069 ? 0
29070 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29071 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29072 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29073 : 0)));
29074 }
29075 else
29076 {
29077
29078 if (EQ (prop, Qleft_fringe))
29079 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29080 if (EQ (prop, Qright_fringe))
29081 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29082 if (EQ (prop, Qleft_margin))
29083 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29084 if (EQ (prop, Qright_margin))
29085 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29086 if (EQ (prop, Qscroll_bar))
29087 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29088 }
29089
29090 prop = buffer_local_value (prop, it->w->contents);
29091 if (BASE_EQ (prop, Qunbound))
29092 prop = Qnil;
29093 }
29094
29095 if (NUMBERP (prop))
29096 {
29097 int base_unit = (width_p
29098 ? FRAME_COLUMN_WIDTH (it->f)
29099 : FRAME_LINE_HEIGHT (it->f));
29100 if (width_p && align_to && *align_to < 0)
29101 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29102 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29103 }
29104
29105 if (CONSP (prop))
29106 {
29107 Lisp_Object car = XCAR (prop);
29108 Lisp_Object cdr = XCDR (prop);
29109
29110 if (SYMBOLP (car))
29111 {
29112 #ifdef HAVE_WINDOW_SYSTEM
29113
29114 if (FRAME_WINDOW_P (it->f)
29115 && valid_image_p (prop))
29116 {
29117 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29118 struct image *img = IMAGE_FROM_ID (it->f, id);
29119
29120 return OK_PIXELS (width_p ? img->width : img->height);
29121 }
29122
29123 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29124 {
29125
29126 return OK_PIXELS (100);
29127 }
29128 #endif
29129
29130
29131 if (EQ (car, Qplus) || EQ (car, Qminus))
29132 {
29133 bool first = true;
29134 double px;
29135
29136 pixels = 0;
29137 while (CONSP (cdr))
29138 {
29139 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29140 font, width_p, align_to))
29141 return false;
29142 if (first)
29143 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29144 else
29145 pixels += px;
29146 cdr = XCDR (cdr);
29147 }
29148 if (EQ (car, Qminus))
29149 pixels = -pixels;
29150 return OK_PIXELS (pixels);
29151 }
29152
29153 car = buffer_local_value (car, it->w->contents);
29154 if (BASE_EQ (car, Qunbound))
29155 car = Qnil;
29156 }
29157
29158
29159 if (NUMBERP (car))
29160 {
29161 double fact;
29162 int offset =
29163 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29164 pixels = XFLOATINT (car);
29165 if (NILP (cdr))
29166 return OK_PIXELS (pixels + offset);
29167 if (calc_pixel_width_or_height (&fact, it, cdr,
29168 font, width_p, align_to))
29169 return OK_PIXELS (pixels * fact + offset);
29170 return false;
29171 }
29172
29173 return false;
29174 }
29175
29176 return false;
29177 }
29178
29179 void
29180 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29181 {
29182 #ifdef HAVE_WINDOW_SYSTEM
29183 normal_char_ascent_descent (font, -1, ascent, descent);
29184 #else
29185 *ascent = 1;
29186 *descent = 0;
29187 #endif
29188 }
29189
29190
29191
29192
29193
29194
29195 #ifdef HAVE_WINDOW_SYSTEM
29196
29197 #ifdef GLYPH_DEBUG
29198
29199 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29200 void
29201 dump_glyph_string (struct glyph_string *s)
29202 {
29203 fputs ("glyph string\n", stderr);
29204 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29205 s->x, s->y, s->width, s->height);
29206 fprintf (stderr, " ybase = %d\n", s->ybase);
29207 fprintf (stderr, " hl = %u\n", s->hl);
29208 fprintf (stderr, " left overhang = %d, right = %d\n",
29209 s->left_overhang, s->right_overhang);
29210 fprintf (stderr, " nchars = %d\n", s->nchars);
29211 fprintf (stderr, " extends to end of line = %d\n",
29212 s->extends_to_end_of_line_p);
29213 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29214 fprintf (stderr, " bg width = %d\n", s->background_width);
29215 }
29216
29217 #endif
29218
29219
29220
29221
29222
29223
29224
29225
29226
29227 #ifdef HAVE_NTGUI
29228
29229
29230
29231
29232
29233 # define ALLOCATE_HDC(hdc, f) \
29234 Lisp_Object prev_quit = Vinhibit_quit; \
29235 Vinhibit_quit = Qt; \
29236 HDC hdc = get_frame_dc ((f))
29237 # define RELEASE_HDC(hdc, f) \
29238 release_frame_dc ((f), (hdc)); \
29239 Vinhibit_quit = prev_quit
29240 #else
29241 # define ALLOCATE_HDC(hdc, f)
29242 # define RELEASE_HDC(hdc, f)
29243 #endif
29244
29245 static void
29246 init_glyph_string (struct glyph_string *s,
29247 #ifdef HAVE_NTGUI
29248 HDC hdc,
29249 #endif
29250 unsigned *char2b, struct window *w, struct glyph_row *row,
29251 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29252 {
29253 memset (s, 0, sizeof *s);
29254 s->w = w;
29255 s->f = XFRAME (w->frame);
29256 #ifdef HAVE_NTGUI
29257 s->hdc = hdc;
29258 #endif
29259 s->char2b = char2b;
29260 s->hl = hl;
29261 s->row = row;
29262 s->area = area;
29263 s->first_glyph = row->glyphs[area] + start;
29264 s->height = row->height;
29265 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29266 s->ybase = s->y + row->ascent;
29267 }
29268
29269
29270
29271
29272
29273 static void
29274 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29275 struct glyph_string *h, struct glyph_string *t)
29276 {
29277 if (h)
29278 {
29279 if (*head)
29280 (*tail)->next = h;
29281 else
29282 *head = h;
29283 h->prev = *tail;
29284 *tail = t;
29285 }
29286 }
29287
29288
29289
29290
29291
29292
29293 static void
29294 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29295 struct glyph_string *h, struct glyph_string *t)
29296 {
29297 if (h)
29298 {
29299 if (*head)
29300 (*head)->prev = t;
29301 else
29302 *tail = t;
29303 t->next = *head;
29304 *head = h;
29305 }
29306 }
29307
29308
29309
29310
29311
29312 static void
29313 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29314 struct glyph_string *s)
29315 {
29316 s->next = s->prev = NULL;
29317 append_glyph_string_lists (head, tail, s, s);
29318 }
29319
29320
29321
29322
29323
29324
29325
29326
29327 static struct face *
29328 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29329 unsigned *char2b, bool display_p)
29330 {
29331 struct face *face = FACE_FROM_ID (f, face_id);
29332 unsigned code = 0;
29333
29334 if (face->font)
29335 {
29336 code = face->font->driver->encode_char (face->font, c);
29337
29338 if (code == FONT_INVALID_CODE)
29339 code = 0;
29340 }
29341
29342 *char2b = code & 0xFFFF;
29343
29344
29345 #ifdef HAVE_X_WINDOWS
29346 if (display_p)
29347 #endif
29348 {
29349 eassert (face != NULL);
29350 prepare_face_for_display (f, face);
29351 }
29352
29353 return face;
29354 }
29355
29356
29357
29358
29359
29360
29361 static struct face *
29362 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29363 unsigned *char2b)
29364 {
29365 struct face *face;
29366 unsigned code = 0;
29367
29368 eassert (glyph->type == CHAR_GLYPH);
29369 face = FACE_FROM_ID (f, glyph->face_id);
29370
29371
29372 prepare_face_for_display (f, face);
29373
29374 if (face->font)
29375 {
29376 if (CHAR_BYTE8_P (glyph->u.ch))
29377 code = CHAR_TO_BYTE8 (glyph->u.ch);
29378 else
29379 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29380
29381 if (code == FONT_INVALID_CODE)
29382 code = 0;
29383 }
29384
29385
29386 *char2b = code & 0xFFFF;
29387 return face;
29388 }
29389
29390
29391
29392
29393
29394 static bool
29395 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29396 {
29397 unsigned code;
29398
29399 if (CHAR_BYTE8_P (c))
29400 code = CHAR_TO_BYTE8 (c);
29401 else
29402 code = font->driver->encode_char (font, c);
29403
29404 if (code == FONT_INVALID_CODE)
29405 return false;
29406
29407
29408 *char2b = code & 0xFFFF;
29409 return true;
29410 }
29411
29412
29413
29414
29415
29416
29417
29418
29419
29420
29421
29422
29423 static int
29424 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29425 int overlaps)
29426 {
29427 int i;
29428
29429
29430
29431 struct face *face;
29432
29433 eassert (s);
29434
29435 s->for_overlaps = overlaps;
29436 s->face = NULL;
29437 s->font = NULL;
29438 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29439 {
29440 int c = COMPOSITION_GLYPH (s->cmp, i);
29441
29442
29443
29444 if (c != '\t')
29445 {
29446 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29447 -1, Qnil);
29448
29449 face = get_char_face_and_encoding (s->f, c, face_id,
29450 s->char2b + i, true);
29451 if (face)
29452 {
29453 if (! s->face)
29454 {
29455 s->face = face;
29456 s->font = s->face->font;
29457 }
29458 else if (s->face != face)
29459 break;
29460 }
29461 }
29462 ++s->nchars;
29463 }
29464 s->cmp_to = i;
29465
29466 if (s->face == NULL)
29467 {
29468 s->face = base_face->ascii_face;
29469 s->font = s->face->font;
29470 }
29471
29472 if (s->hl == DRAW_MOUSE_FACE
29473 || (s->hl == DRAW_CURSOR
29474 && MATRIX_ROW (s->w->current_matrix,
29475 s->w->phys_cursor.vpos)->mouse_face_p
29476 && cursor_in_mouse_face_p (s->w)))
29477 {
29478 int c = COMPOSITION_GLYPH (s->cmp, 0);
29479 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29480 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29481 if (!s->face)
29482 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29483
29484 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29485 prepare_face_for_display (s->f, s->face);
29486 }
29487
29488
29489
29490 s->width = s->first_glyph->pixel_width;
29491
29492
29493
29494
29495
29496 if (s->font == NULL)
29497 {
29498 s->font_not_found_p = true;
29499 s->font = FRAME_FONT (s->f);
29500 }
29501
29502
29503 s->ybase += s->first_glyph->voffset;
29504
29505 return s->cmp_to;
29506 }
29507
29508 static int
29509 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29510 int start, int end, int overlaps)
29511 {
29512 struct glyph *glyph, *last;
29513 int voffset;
29514 Lisp_Object lgstring;
29515 int i;
29516 bool glyph_not_available_p;
29517
29518 s->for_overlaps = overlaps;
29519 glyph = s->row->glyphs[s->area] + start;
29520 last = s->row->glyphs[s->area] + end;
29521 voffset = glyph->voffset;
29522 glyph_not_available_p = glyph->glyph_not_available_p;
29523 s->cmp_id = glyph->u.cmp.id;
29524 s->cmp_from = glyph->slice.cmp.from;
29525 s->cmp_to = glyph->slice.cmp.to + 1;
29526 if (s->hl == DRAW_MOUSE_FACE
29527 || (s->hl == DRAW_CURSOR
29528 && MATRIX_ROW (s->w->current_matrix,
29529 s->w->phys_cursor.vpos)->mouse_face_p
29530 && cursor_in_mouse_face_p (s->w)))
29531 {
29532 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29533 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29534 if (!s->face)
29535 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29536 prepare_face_for_display (s->f, s->face);
29537 }
29538 else
29539 s->face = FACE_FROM_ID (s->f, face_id);
29540 lgstring = composition_gstring_from_id (s->cmp_id);
29541 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29542
29543
29544 s->width = s->first_glyph->pixel_width;
29545 glyph++;
29546 while (glyph < last
29547 && glyph->u.cmp.automatic
29548 && glyph->u.cmp.id == s->cmp_id
29549 && glyph->face_id == face_id
29550 && s->cmp_to == glyph->slice.cmp.from
29551 && glyph->glyph_not_available_p == glyph_not_available_p)
29552 {
29553 s->width += glyph->pixel_width;
29554 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29555 }
29556
29557 for (i = s->cmp_from; i < s->cmp_to; i++)
29558 {
29559 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29560 unsigned code = LGLYPH_CODE (lglyph);
29561
29562
29563 s->char2b[i] = code & 0xFFFF;
29564 }
29565
29566
29567
29568
29569 if (glyph_not_available_p)
29570 s->font_not_found_p = true;
29571
29572
29573 s->ybase += voffset;
29574
29575 return glyph - s->row->glyphs[s->area];
29576 }
29577
29578
29579
29580
29581
29582
29583
29584 static int
29585 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29586 int start, int end, int overlaps)
29587 {
29588 struct glyph *glyph, *last;
29589 int voffset;
29590
29591 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29592 s->for_overlaps = overlaps;
29593 glyph = s->row->glyphs[s->area] + start;
29594 last = s->row->glyphs[s->area] + end;
29595 voffset = glyph->voffset;
29596 s->face = FACE_FROM_ID (s->f, face_id);
29597 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29598 if (s->hl == DRAW_MOUSE_FACE
29599 || (s->hl == DRAW_CURSOR
29600 && MATRIX_ROW (s->w->current_matrix,
29601 s->w->phys_cursor.vpos)->mouse_face_p
29602 && cursor_in_mouse_face_p (s->w)))
29603 {
29604 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29605 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29606 if (!s->face)
29607 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29608 prepare_face_for_display (s->f, s->face);
29609 }
29610 s->nchars = 1;
29611 s->width = glyph->pixel_width;
29612 glyph++;
29613 while (glyph < last
29614 && glyph->type == GLYPHLESS_GLYPH
29615 && glyph->voffset == voffset
29616 && glyph->face_id == face_id)
29617 {
29618 s->nchars++;
29619 s->width += glyph->pixel_width;
29620 glyph++;
29621 }
29622 s->ybase += voffset;
29623 return glyph - s->row->glyphs[s->area];
29624 }
29625
29626
29627
29628
29629
29630
29631
29632
29633
29634
29635
29636 static int
29637 fill_glyph_string (struct glyph_string *s, int face_id,
29638 int start, int end, int overlaps)
29639 {
29640 struct glyph *glyph, *last;
29641 int voffset;
29642 bool glyph_not_available_p;
29643
29644 eassert (s->f == XFRAME (s->w->frame));
29645 eassert (s->nchars == 0);
29646 eassert (start >= 0 && end > start);
29647
29648 s->for_overlaps = overlaps;
29649 glyph = s->row->glyphs[s->area] + start;
29650 last = s->row->glyphs[s->area] + end;
29651 voffset = glyph->voffset;
29652 s->padding_p = glyph->padding_p;
29653 glyph_not_available_p = glyph->glyph_not_available_p;
29654
29655 while (glyph < last
29656 && glyph->type == CHAR_GLYPH
29657 && glyph->voffset == voffset
29658
29659 && glyph->face_id == face_id
29660 && glyph->glyph_not_available_p == glyph_not_available_p)
29661 {
29662 s->face = get_glyph_face_and_encoding (s->f, glyph,
29663 s->char2b + s->nchars);
29664 ++s->nchars;
29665 eassert (s->nchars <= end - start);
29666 s->width += glyph->pixel_width;
29667 if (glyph++->padding_p != s->padding_p)
29668 break;
29669 }
29670
29671 s->font = s->face->font;
29672
29673 if (s->hl == DRAW_MOUSE_FACE
29674 || (s->hl == DRAW_CURSOR
29675 && MATRIX_ROW (s->w->current_matrix,
29676 s->w->phys_cursor.vpos)->mouse_face_p
29677 && cursor_in_mouse_face_p (s->w)))
29678 {
29679 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29680 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29681 if (!s->face)
29682 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29683 s->face
29684 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29685 s->first_glyph->u.ch, -1, Qnil));
29686 prepare_face_for_display (s->f, s->face);
29687 }
29688
29689
29690
29691
29692
29693 if (s->font == NULL || glyph_not_available_p)
29694 {
29695 s->font_not_found_p = true;
29696 s->font = FRAME_FONT (s->f);
29697 }
29698
29699
29700 s->ybase += voffset;
29701
29702 eassert (s->face && s->face->gc);
29703 return glyph - s->row->glyphs[s->area];
29704 }
29705
29706
29707
29708
29709 static void
29710 fill_image_glyph_string (struct glyph_string *s)
29711 {
29712 eassert (s->first_glyph->type == IMAGE_GLYPH);
29713 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29714 eassert (s->img);
29715 s->slice = s->first_glyph->slice.img;
29716 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29717 s->font = s->face->font;
29718 if (s->hl == DRAW_MOUSE_FACE
29719 || (s->hl == DRAW_CURSOR
29720 && MATRIX_ROW (s->w->current_matrix,
29721 s->w->phys_cursor.vpos)->mouse_face_p
29722 && cursor_in_mouse_face_p (s->w)))
29723 {
29724 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29725 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29726 if (!s->face)
29727 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29728 prepare_face_for_display (s->f, s->face);
29729 }
29730 s->width = s->first_glyph->pixel_width;
29731
29732
29733 s->ybase += s->first_glyph->voffset;
29734 }
29735
29736
29737 #ifdef HAVE_XWIDGETS
29738 static void
29739 fill_xwidget_glyph_string (struct glyph_string *s)
29740 {
29741 eassert (s->first_glyph->type == XWIDGET_GLYPH);
29742 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29743 s->font = s->face->font;
29744 if (s->hl == DRAW_MOUSE_FACE
29745 || (s->hl == DRAW_CURSOR
29746 && MATRIX_ROW (s->w->current_matrix,
29747 s->w->phys_cursor.vpos)->mouse_face_p
29748 && cursor_in_mouse_face_p (s->w)))
29749 {
29750 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29751 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29752 if (!s->face)
29753 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29754 prepare_face_for_display (s->f, s->face);
29755 }
29756 s->width = s->first_glyph->pixel_width;
29757 s->ybase += s->first_glyph->voffset;
29758 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
29759 }
29760 #endif
29761
29762
29763
29764
29765
29766
29767
29768 static int
29769 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
29770 {
29771 struct glyph *glyph, *last;
29772 int voffset, face_id;
29773
29774 eassert (s->first_glyph->type == STRETCH_GLYPH);
29775
29776 glyph = s->row->glyphs[s->area] + start;
29777 last = s->row->glyphs[s->area] + end;
29778 face_id = glyph->face_id;
29779 s->face = FACE_FROM_ID (s->f, face_id);
29780 s->font = s->face->font;
29781 if (s->hl == DRAW_MOUSE_FACE
29782 || (s->hl == DRAW_CURSOR
29783 && MATRIX_ROW (s->w->current_matrix,
29784 s->w->phys_cursor.vpos)->mouse_face_p
29785 && cursor_in_mouse_face_p (s->w)))
29786 {
29787 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29788 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29789 if (!s->face)
29790 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29791 prepare_face_for_display (s->f, s->face);
29792 }
29793 s->width = glyph->pixel_width;
29794 s->nchars = 1;
29795 voffset = glyph->voffset;
29796
29797 for (++glyph;
29798 (glyph < last
29799 && glyph->type == STRETCH_GLYPH
29800 && glyph->voffset == voffset
29801 && glyph->face_id == face_id);
29802 ++glyph)
29803 s->width += glyph->pixel_width;
29804
29805
29806 s->ybase += voffset;
29807
29808
29809
29810 eassert (s->face);
29811 return glyph - s->row->glyphs[s->area];
29812 }
29813
29814 static struct font_metrics *
29815 get_per_char_metric (struct font *font, const unsigned *char2b)
29816 {
29817 static struct font_metrics metrics;
29818
29819 if (! font)
29820 return NULL;
29821 if (*char2b == FONT_INVALID_CODE)
29822 return NULL;
29823
29824 font->driver->text_extents (font, char2b, 1, &metrics);
29825 return &metrics;
29826 }
29827
29828
29829
29830
29831
29832
29833
29834 static void
29835 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
29836 {
29837 *ascent = FONT_BASE (font);
29838 *descent = FONT_DESCENT (font);
29839
29840 if (FONT_TOO_HIGH (font))
29841 {
29842 unsigned char2b;
29843
29844
29845
29846 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
29847 {
29848 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
29849 eassume (pcm);
29850
29851 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
29852 {
29853
29854
29855
29856 *ascent = pcm->ascent + 1;
29857 *descent = pcm->descent + 1;
29858 }
29859 }
29860 }
29861 }
29862
29863
29864
29865
29866
29867
29868 static int
29869 normal_char_height (struct font *font, int c)
29870 {
29871 int ascent, descent;
29872
29873 normal_char_ascent_descent (font, c, &ascent, &descent);
29874
29875 return ascent + descent;
29876 }
29877
29878
29879
29880
29881
29882
29883 void
29884 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
29885 {
29886 *left = *right = 0;
29887
29888 if (glyph->type == CHAR_GLYPH)
29889 {
29890 unsigned char2b;
29891 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
29892 if (face->font)
29893 {
29894 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
29895 if (pcm)
29896 {
29897 if (pcm->rbearing > pcm->width)
29898 *right = pcm->rbearing - pcm->width;
29899 if (pcm->lbearing < 0)
29900 *left = -pcm->lbearing;
29901 }
29902 }
29903 }
29904 else if (glyph->type == COMPOSITE_GLYPH)
29905 {
29906 if (! glyph->u.cmp.automatic)
29907 {
29908 struct composition *cmp = composition_table[glyph->u.cmp.id];
29909
29910 if (cmp->rbearing > cmp->pixel_width)
29911 *right = cmp->rbearing - cmp->pixel_width;
29912 if (cmp->lbearing < 0)
29913 *left = - cmp->lbearing;
29914 }
29915 else
29916 {
29917 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
29918 struct font_metrics metrics;
29919
29920 composition_gstring_width (gstring, glyph->slice.cmp.from,
29921 glyph->slice.cmp.to + 1, &metrics);
29922 if (metrics.rbearing > metrics.width)
29923 *right = metrics.rbearing - metrics.width;
29924 if (metrics.lbearing < 0)
29925 *left = - metrics.lbearing;
29926 }
29927 }
29928 }
29929
29930
29931
29932
29933
29934
29935 static int
29936 left_overwritten (struct glyph_string *s)
29937 {
29938 int k;
29939
29940 if (s->left_overhang)
29941 {
29942 int x = 0, i;
29943 struct glyph *glyphs = s->row->glyphs[s->area];
29944 int first = s->first_glyph - glyphs;
29945
29946 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
29947 x -= glyphs[i].pixel_width;
29948
29949 k = i + 1;
29950 }
29951 else
29952 k = -1;
29953
29954 return k;
29955 }
29956
29957
29958
29959
29960
29961
29962 static int
29963 left_overwriting (struct glyph_string *s)
29964 {
29965 int i, k, x;
29966 struct glyph *glyphs = s->row->glyphs[s->area];
29967 int first = s->first_glyph - glyphs;
29968
29969 k = -1;
29970 x = 0;
29971 for (i = first - 1; i >= 0; --i)
29972 {
29973 int left, right;
29974 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
29975 if (x + right > 0)
29976 k = i;
29977 x -= glyphs[i].pixel_width;
29978 }
29979
29980 return k;
29981 }
29982
29983
29984
29985
29986
29987
29988 static int
29989 right_overwritten (struct glyph_string *s)
29990 {
29991 int k = -1;
29992
29993 if (s->right_overhang)
29994 {
29995 int x = 0, i;
29996 struct glyph *glyphs = s->row->glyphs[s->area];
29997 int first = (s->first_glyph - glyphs
29998 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
29999 int end = s->row->used[s->area];
30000
30001 for (i = first; i < end && s->right_overhang > x; ++i)
30002 x += glyphs[i].pixel_width;
30003
30004 k = i;
30005 }
30006
30007 return k;
30008 }
30009
30010
30011
30012
30013
30014
30015 static int
30016 right_overwriting (struct glyph_string *s)
30017 {
30018 int i, k, x;
30019 int end = s->row->used[s->area];
30020 struct glyph *glyphs = s->row->glyphs[s->area];
30021 int first = (s->first_glyph - glyphs
30022 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30023
30024 k = -1;
30025 x = 0;
30026 for (i = first; i < end; ++i)
30027 {
30028 int left, right;
30029 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30030 if (x - left < 0)
30031 k = i;
30032 x += glyphs[i].pixel_width;
30033 }
30034
30035 return k;
30036 }
30037
30038
30039
30040
30041
30042
30043
30044
30045
30046
30047
30048 static void
30049 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30050 {
30051
30052
30053
30054 if (start == s->row->used[s->area]
30055 && ((s->row->fill_line_p
30056 && (s->hl == DRAW_NORMAL_TEXT
30057 || s->hl == DRAW_IMAGE_RAISED
30058 || s->hl == DRAW_IMAGE_SUNKEN))
30059 || s->hl == DRAW_MOUSE_FACE))
30060 s->extends_to_end_of_line_p = true;
30061
30062
30063
30064
30065 if (s->extends_to_end_of_line_p)
30066 s->background_width = last_x - s->x + 1;
30067 else
30068 {
30069 s->background_width = s->width;
30070 #ifdef HAVE_WINDOW_SYSTEM
30071 if (FRAME_WINDOW_P (s->f)
30072 && s->hl == DRAW_CURSOR
30073 && MATRIX_ROW (s->w->current_matrix,
30074 s->w->phys_cursor.vpos)->mouse_face_p
30075 && cursor_in_mouse_face_p (s->w))
30076 {
30077
30078
30079
30080
30081 struct glyph *g = s->first_glyph;
30082 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30083 s->background_width +=
30084 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30085 regular_face, s->face);
30086
30087 s->width = s->background_width;
30088 }
30089 #endif
30090 }
30091 }
30092
30093
30094
30095
30096
30097 static struct glyph_string *
30098 glyph_string_containing_background_width (struct glyph_string *s)
30099 {
30100 if (s->cmp)
30101 while (s->cmp_from)
30102 s = s->prev;
30103
30104 return s;
30105 }
30106
30107
30108
30109
30110
30111
30112 static void
30113 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30114 {
30115 if (backward_p)
30116 {
30117 while (s)
30118 {
30119 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30120 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30121 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30122 x -= s->width;
30123 s->x = x;
30124 s = s->prev;
30125 }
30126 }
30127 else
30128 {
30129 while (s)
30130 {
30131 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30132 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30133 s->x = x;
30134 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30135 x += s->width;
30136 s = s->next;
30137 }
30138 }
30139 }
30140
30141
30142
30143
30144
30145
30146
30147
30148
30149 #ifdef HAVE_NTGUI
30150
30151
30152 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30153 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30154 #else
30155 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30156 init_glyph_string (s, char2b, w, row, area, start, hl)
30157 #endif
30158
30159
30160
30161
30162
30163
30164
30165
30166
30167
30168
30169 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30170 do \
30171 { \
30172 s = alloca (sizeof *s); \
30173 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30174 START = fill_stretch_glyph_string (s, START, END); \
30175 append_glyph_string (&HEAD, &TAIL, s); \
30176 s->x = (X); \
30177 } \
30178 while (false)
30179
30180
30181
30182
30183
30184
30185
30186
30187
30188
30189 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30190 do \
30191 { \
30192 s = alloca (sizeof *s); \
30193 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30194 fill_image_glyph_string (s); \
30195 append_glyph_string (&HEAD, &TAIL, s); \
30196 ++START; \
30197 s->x = (X); \
30198 } \
30199 while (false)
30200
30201 #ifndef HAVE_XWIDGETS
30202 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30203 eassume (false)
30204 #else
30205 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30206 do \
30207 { \
30208 s = alloca (sizeof *s); \
30209 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30210 fill_xwidget_glyph_string (s); \
30211 append_glyph_string (&(HEAD), &(TAIL), s); \
30212 ++(START); \
30213 s->x = (X); \
30214 } \
30215 while (false)
30216 #endif
30217
30218
30219
30220
30221
30222
30223
30224
30225
30226
30227 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30228 do \
30229 { \
30230 int face_id; \
30231 unsigned *char2b; \
30232 \
30233 face_id = (row)->glyphs[area][START].face_id; \
30234 \
30235 s = alloca (sizeof *s); \
30236 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30237 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30238 append_glyph_string (&HEAD, &TAIL, s); \
30239 s->x = (X); \
30240 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30241 } \
30242 while (false)
30243
30244
30245
30246
30247
30248
30249
30250
30251
30252
30253
30254 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30255 do { \
30256 int face_id = (row)->glyphs[area][START].face_id; \
30257 struct face *base_face = FACE_FROM_ID (f, face_id); \
30258 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30259 struct composition *cmp = composition_table[cmp_id]; \
30260 unsigned *char2b; \
30261 struct glyph_string *first_s = NULL; \
30262 int n; \
30263 \
30264 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30265 \
30266
30267 \
30268 for (n = 0; n < cmp->glyph_len;) \
30269 { \
30270 s = alloca (sizeof *s); \
30271 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30272 append_glyph_string (&(HEAD), &(TAIL), s); \
30273 s->cmp = cmp; \
30274 s->cmp_from = n; \
30275 s->x = (X); \
30276 if (n == 0) \
30277 first_s = s; \
30278 n = fill_composite_glyph_string (s, base_face, overlaps); \
30279 } \
30280 \
30281 ++START; \
30282 s = first_s; \
30283 } while (false)
30284
30285
30286
30287
30288
30289 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30290 do { \
30291 int face_id; \
30292 unsigned *char2b; \
30293 Lisp_Object gstring; \
30294 \
30295 face_id = (row)->glyphs[area][START].face_id; \
30296 gstring = (composition_gstring_from_id \
30297 ((row)->glyphs[area][START].u.cmp.id)); \
30298 s = alloca (sizeof *s); \
30299 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30300 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30301 append_glyph_string (&(HEAD), &(TAIL), s); \
30302 s->x = (X); \
30303 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30304 } while (false)
30305
30306
30307
30308
30309
30310
30311 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30312 do \
30313 { \
30314 int face_id; \
30315 \
30316 face_id = (row)->glyphs[area][START].face_id; \
30317 \
30318 s = alloca (sizeof *s); \
30319 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30320 append_glyph_string (&HEAD, &TAIL, s); \
30321 s->x = (X); \
30322 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30323 overlaps); \
30324 } \
30325 while (false)
30326
30327
30328
30329
30330
30331
30332
30333
30334
30335
30336
30337
30338 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30339 do \
30340 { \
30341 HEAD = TAIL = NULL; \
30342 while (START < END) \
30343 { \
30344 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30345 switch (first_glyph->type) \
30346 { \
30347 case CHAR_GLYPH: \
30348 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30349 HL, X, LAST_X); \
30350 break; \
30351 \
30352 case COMPOSITE_GLYPH: \
30353 if (first_glyph->u.cmp.automatic) \
30354 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30355 HL, X, LAST_X); \
30356 else \
30357 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30358 HL, X, LAST_X); \
30359 break; \
30360 \
30361 case STRETCH_GLYPH: \
30362 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30363 HL, X, LAST_X); \
30364 break; \
30365 \
30366 case IMAGE_GLYPH: \
30367 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30368 HL, X, LAST_X); \
30369 break;
30370
30371 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30372 case XWIDGET_GLYPH: \
30373 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30374 HL, X, LAST_X); \
30375 break;
30376
30377 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30378 case GLYPHLESS_GLYPH: \
30379 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30380 HL, X, LAST_X); \
30381 break; \
30382 \
30383 default: \
30384 emacs_abort (); \
30385 } \
30386 \
30387 if (s) \
30388 { \
30389 set_glyph_string_background_width (s, START, LAST_X); \
30390 (X) += s->width; \
30391 } \
30392 } \
30393 } while (false)
30394
30395
30396 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30397 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30398 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30399 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30400
30401
30402
30403
30404
30405
30406
30407
30408
30409
30410
30411
30412
30413
30414
30415
30416
30417
30418
30419
30420
30421
30422
30423
30424 static int
30425 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30426 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30427 enum draw_glyphs_face hl, int overlaps)
30428 {
30429 struct glyph_string *head, *tail;
30430 struct glyph_string *s;
30431 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30432 int i, j, x_reached, last_x, area_left = 0;
30433 struct frame *f = XFRAME (WINDOW_FRAME (w));
30434
30435 ALLOCATE_HDC (hdc, f);
30436
30437
30438 end = min (end, row->used[area]);
30439 start = clip_to_bounds (0, start, end);
30440
30441
30442
30443 if (row->full_width_p)
30444 {
30445
30446
30447 area_left = WINDOW_LEFT_EDGE_X (w);
30448 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30449 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30450 }
30451 else
30452 {
30453 area_left = window_box_left (w, area);
30454 last_x = area_left + window_box_width (w, area);
30455 }
30456 x += area_left;
30457
30458
30459
30460
30461
30462 i = start;
30463 USE_SAFE_ALLOCA;
30464 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30465 if (tail)
30466 {
30467 s = glyph_string_containing_background_width (tail);
30468 x_reached = s->x + s->background_width;
30469 }
30470 else
30471 x_reached = x;
30472
30473
30474
30475
30476 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30477 {
30478 struct glyph_string *h, *t;
30479 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30480 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30481 bool check_mouse_face = false;
30482 int dummy_x = 0;
30483
30484
30485
30486 if (area == TEXT_AREA && row->mouse_face_p
30487 && hlinfo->mouse_face_beg_row >= 0
30488 && hlinfo->mouse_face_end_row >= 0)
30489 {
30490 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30491
30492 if (row_vpos >= hlinfo->mouse_face_beg_row
30493 && row_vpos <= hlinfo->mouse_face_end_row)
30494 {
30495 check_mouse_face = true;
30496 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30497 ? hlinfo->mouse_face_beg_col : 0;
30498 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30499 ? hlinfo->mouse_face_end_col
30500 : row->used[TEXT_AREA];
30501 }
30502 }
30503
30504
30505 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30506 for (s = head; s; s = s->next)
30507 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30508
30509
30510
30511
30512
30513
30514 i = left_overwritten (head);
30515 if (i >= 0)
30516 {
30517 enum draw_glyphs_face overlap_hl;
30518
30519
30520
30521
30522
30523
30524
30525
30526 if (check_mouse_face
30527 && mouse_beg_col < start && mouse_end_col > i)
30528 overlap_hl = DRAW_MOUSE_FACE;
30529 else
30530 overlap_hl = DRAW_NORMAL_TEXT;
30531
30532 if (hl != overlap_hl)
30533 clip_head = head;
30534 j = i;
30535 BUILD_GLYPH_STRINGS (j, start, h, t,
30536 overlap_hl, dummy_x, last_x);
30537 start = i;
30538 compute_overhangs_and_x (t, head->x, true);
30539 prepend_glyph_string_lists (&head, &tail, h, t);
30540 if (clip_head == NULL)
30541 clip_head = head;
30542 }
30543
30544
30545
30546
30547
30548
30549
30550
30551 i = left_overwriting (head);
30552 if (i >= 0)
30553 {
30554 enum draw_glyphs_face overlap_hl;
30555
30556 if (check_mouse_face
30557 && mouse_beg_col < start && mouse_end_col > i)
30558 overlap_hl = DRAW_MOUSE_FACE;
30559 else
30560 overlap_hl = DRAW_NORMAL_TEXT;
30561
30562 if (hl == overlap_hl || clip_head == NULL)
30563 clip_head = head;
30564 BUILD_GLYPH_STRINGS (i, start, h, t,
30565 overlap_hl, dummy_x, last_x);
30566 for (s = h; s; s = s->next)
30567 s->background_filled_p = true;
30568 compute_overhangs_and_x (t, head->x, true);
30569 prepend_glyph_string_lists (&head, &tail, h, t);
30570 }
30571
30572
30573
30574
30575
30576 i = right_overwritten (tail);
30577 if (i >= 0)
30578 {
30579 enum draw_glyphs_face overlap_hl;
30580
30581 if (check_mouse_face
30582 && mouse_beg_col < i && mouse_end_col > end)
30583 overlap_hl = DRAW_MOUSE_FACE;
30584 else
30585 overlap_hl = DRAW_NORMAL_TEXT;
30586
30587 if (hl != overlap_hl)
30588 clip_tail = tail;
30589 BUILD_GLYPH_STRINGS (end, i, h, t,
30590 overlap_hl, x, last_x);
30591
30592
30593 compute_overhangs_and_x (h, tail->x + tail->width, false);
30594 append_glyph_string_lists (&head, &tail, h, t);
30595 if (clip_tail == NULL)
30596 clip_tail = tail;
30597 }
30598
30599
30600
30601
30602
30603
30604 i = right_overwriting (tail);
30605 if (i >= 0)
30606 {
30607 enum draw_glyphs_face overlap_hl;
30608 if (check_mouse_face
30609 && mouse_beg_col < i && mouse_end_col > end)
30610 overlap_hl = DRAW_MOUSE_FACE;
30611 else
30612 overlap_hl = DRAW_NORMAL_TEXT;
30613
30614 if (hl == overlap_hl || clip_tail == NULL)
30615 clip_tail = tail;
30616 i++;
30617 BUILD_GLYPH_STRINGS (end, i, h, t,
30618 overlap_hl, x, last_x);
30619 for (s = h; s; s = s->next)
30620 s->background_filled_p = true;
30621 compute_overhangs_and_x (h, tail->x + tail->width, false);
30622 append_glyph_string_lists (&head, &tail, h, t);
30623 }
30624 tail = glyph_string_containing_background_width (tail);
30625 if (clip_tail)
30626 clip_tail = glyph_string_containing_background_width (clip_tail);
30627 if (clip_head || clip_tail)
30628 for (s = head; s; s = s->next)
30629 {
30630 s->clip_head = clip_head;
30631 s->clip_tail = clip_tail;
30632 }
30633 }
30634
30635
30636 for (s = head; s; s = s->next)
30637 FRAME_RIF (f)->draw_glyph_string (s);
30638
30639
30640
30641 if (area == TEXT_AREA
30642 && !row->full_width_p
30643
30644
30645
30646 && !overlaps)
30647 {
30648 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30649 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30650 : (tail ? tail->x + tail->background_width : x));
30651 x0 -= area_left;
30652 x1 -= area_left;
30653
30654 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30655 row->y, MATRIX_ROW_BOTTOM_Y (row));
30656 }
30657
30658
30659
30660 if (row->full_width_p)
30661 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30662 else
30663 x_reached -= area_left;
30664
30665 RELEASE_HDC (hdc, f);
30666
30667 SAFE_FREE ();
30668 return x_reached;
30669 }
30670
30671
30672
30673
30674
30675
30676
30677
30678 struct font *
30679 font_for_underline_metrics (struct glyph_string *s)
30680 {
30681 struct glyph *g0 = s->row->glyphs[s->area], *g;
30682
30683 for (g = s->first_glyph - 1; g >= g0; g--)
30684 {
30685 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30686 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30687 break;
30688 }
30689
30690
30691 if (g == s->first_glyph - 1)
30692 return s->font;
30693 else
30694 {
30695
30696
30697 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30698 }
30699 }
30700
30701
30702
30703
30704 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30705 { \
30706 if (!it->f->fonts_changed \
30707 && (it->glyph_row->glyphs[area] \
30708 < it->glyph_row->glyphs[area + 1])) \
30709 { \
30710 it->w->ncols_scale_factor++; \
30711 it->f->fonts_changed = true; \
30712 } \
30713 }
30714
30715
30716
30717
30718 static void
30719 append_glyph (struct it *it)
30720 {
30721 struct glyph *glyph;
30722 enum glyph_row_area area = it->area;
30723
30724 eassert (it->glyph_row);
30725 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
30726
30727 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30728 if (glyph < it->glyph_row->glyphs[area + 1])
30729 {
30730
30731
30732 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30733 {
30734 struct glyph *g;
30735
30736
30737 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
30738 g[1] = *g;
30739 glyph = it->glyph_row->glyphs[area];
30740 }
30741 glyph->charpos = CHARPOS (it->position);
30742 glyph->object = it->object;
30743 if (it->pixel_width > 0)
30744 {
30745 eassert (it->pixel_width <= SHRT_MAX);
30746 glyph->pixel_width = it->pixel_width;
30747 glyph->padding_p = false;
30748 }
30749 else
30750 {
30751
30752
30753 glyph->pixel_width = 1;
30754 glyph->padding_p = true;
30755 }
30756 glyph->ascent = it->ascent;
30757 glyph->descent = it->descent;
30758 glyph->voffset = it->voffset;
30759 glyph->type = CHAR_GLYPH;
30760 glyph->avoid_cursor_p = it->avoid_cursor_p;
30761 glyph->multibyte_p = it->multibyte_p;
30762 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30763 {
30764
30765
30766 glyph->right_box_line_p = it->start_of_box_run_p;
30767 glyph->left_box_line_p = it->end_of_box_run_p;
30768 }
30769 else
30770 {
30771 glyph->left_box_line_p = it->start_of_box_run_p;
30772 glyph->right_box_line_p = it->end_of_box_run_p;
30773 }
30774 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30775 || it->phys_descent > it->descent);
30776 glyph->glyph_not_available_p = it->glyph_not_available_p;
30777 glyph->face_id = it->face_id;
30778 glyph->u.ch = it->char_to_display;
30779 glyph->slice.img = null_glyph_slice;
30780 glyph->font_type = FONT_TYPE_UNKNOWN;
30781 if (it->bidi_p)
30782 {
30783 glyph->resolved_level = it->bidi_it.resolved_level;
30784 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30785 glyph->bidi_type = it->bidi_it.type;
30786 }
30787 else
30788 {
30789 glyph->resolved_level = 0;
30790 glyph->bidi_type = UNKNOWN_BT;
30791 }
30792 ++it->glyph_row->used[area];
30793 }
30794 else
30795 IT_EXPAND_MATRIX_WIDTH (it, area);
30796 }
30797
30798
30799
30800
30801 static void
30802 append_composite_glyph (struct it *it)
30803 {
30804 struct glyph *glyph;
30805 enum glyph_row_area area = it->area;
30806
30807 eassert (it->glyph_row);
30808
30809 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30810 if (glyph < it->glyph_row->glyphs[area + 1])
30811 {
30812
30813
30814 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
30815 {
30816 struct glyph *g;
30817
30818
30819 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
30820 g[1] = *g;
30821 glyph = it->glyph_row->glyphs[it->area];
30822 }
30823 glyph->charpos = it->cmp_it.charpos;
30824 glyph->object = it->object;
30825 eassert (it->pixel_width <= SHRT_MAX);
30826 glyph->pixel_width = it->pixel_width;
30827 glyph->ascent = it->ascent;
30828 glyph->descent = it->descent;
30829 glyph->voffset = it->voffset;
30830 glyph->type = COMPOSITE_GLYPH;
30831 if (it->cmp_it.ch < 0)
30832 {
30833 glyph->u.cmp.automatic = false;
30834 glyph->u.cmp.id = it->cmp_it.id;
30835 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
30836 }
30837 else
30838 {
30839 glyph->u.cmp.automatic = true;
30840 glyph->u.cmp.id = it->cmp_it.id;
30841 glyph->slice.cmp.from = it->cmp_it.from;
30842 glyph->slice.cmp.to = it->cmp_it.to - 1;
30843 }
30844 glyph->avoid_cursor_p = it->avoid_cursor_p;
30845 glyph->multibyte_p = it->multibyte_p;
30846 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30847 {
30848
30849
30850 glyph->right_box_line_p = it->start_of_box_run_p;
30851 glyph->left_box_line_p = it->end_of_box_run_p;
30852 }
30853 else
30854 {
30855 glyph->left_box_line_p = it->start_of_box_run_p;
30856 glyph->right_box_line_p = it->end_of_box_run_p;
30857 }
30858 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30859 || it->phys_descent > it->descent);
30860 glyph->padding_p = false;
30861 glyph->glyph_not_available_p = it->glyph_not_available_p;
30862 glyph->face_id = it->face_id;
30863 glyph->font_type = FONT_TYPE_UNKNOWN;
30864 if (it->bidi_p)
30865 {
30866 glyph->resolved_level = it->bidi_it.resolved_level;
30867 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30868 glyph->bidi_type = it->bidi_it.type;
30869 }
30870 ++it->glyph_row->used[area];
30871 }
30872 else
30873 IT_EXPAND_MATRIX_WIDTH (it, area);
30874 }
30875
30876
30877
30878
30879
30880 static void
30881 take_vertical_position_into_account (struct it *it)
30882 {
30883 if (it->voffset)
30884 {
30885 if (it->voffset < 0)
30886
30887
30888 it->ascent -= it->voffset;
30889 else
30890
30891
30892 it->descent += it->voffset;
30893 }
30894 }
30895
30896
30897
30898
30899
30900
30901 static void
30902 produce_image_glyph (struct it *it)
30903 {
30904 struct image *img;
30905 struct face *face;
30906 int glyph_ascent, crop;
30907 struct glyph_slice slice;
30908
30909 eassert (it->what == IT_IMAGE);
30910
30911 face = FACE_FROM_ID (it->f, it->face_id);
30912
30913 prepare_face_for_display (it->f, face);
30914
30915 if (it->image_id < 0)
30916 {
30917
30918 it->ascent = it->phys_ascent = 0;
30919 it->descent = it->phys_descent = 0;
30920 it->pixel_width = 0;
30921 it->nglyphs = 0;
30922 return;
30923 }
30924
30925 img = IMAGE_FROM_ID (it->f, it->image_id);
30926
30927 prepare_image_for_display (it->f, img);
30928
30929 slice.x = slice.y = 0;
30930 slice.width = img->width;
30931 slice.height = img->height;
30932
30933 if (FIXNUMP (it->slice.x))
30934 slice.x = XFIXNUM (it->slice.x);
30935 else if (FLOATP (it->slice.x))
30936 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
30937
30938 if (FIXNUMP (it->slice.y))
30939 slice.y = XFIXNUM (it->slice.y);
30940 else if (FLOATP (it->slice.y))
30941 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
30942
30943 if (FIXNUMP (it->slice.width))
30944 slice.width = XFIXNUM (it->slice.width);
30945 else if (FLOATP (it->slice.width))
30946 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
30947
30948 if (FIXNUMP (it->slice.height))
30949 slice.height = XFIXNUM (it->slice.height);
30950 else if (FLOATP (it->slice.height))
30951 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
30952
30953 if (slice.x >= img->width)
30954 slice.x = img->width;
30955 if (slice.y >= img->height)
30956 slice.y = img->height;
30957 if (slice.x + slice.width >= img->width)
30958 slice.width = img->width - slice.x;
30959 if (slice.y + slice.height > img->height)
30960 slice.height = img->height - slice.y;
30961
30962 if (slice.width == 0 || slice.height == 0)
30963 return;
30964
30965 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
30966
30967 it->descent = slice.height - glyph_ascent;
30968 if (slice.y == 0)
30969 it->descent += img->vmargin;
30970 if (slice.y + slice.height == img->height)
30971 it->descent += img->vmargin;
30972 it->phys_descent = it->descent;
30973
30974 it->pixel_width = slice.width;
30975 if (slice.x == 0)
30976 it->pixel_width += img->hmargin;
30977 if (slice.x + slice.width == img->width)
30978 it->pixel_width += img->hmargin;
30979
30980
30981
30982 if (it->descent < 0)
30983 it->descent = 0;
30984
30985 it->nglyphs = 1;
30986
30987 if (face->box != FACE_NO_BOX)
30988 {
30989
30990
30991 if (face->box_horizontal_line_width > 0)
30992 {
30993 if (slice.y == 0)
30994 it->ascent += face->box_horizontal_line_width;
30995 if (slice.y + slice.height == img->height)
30996 it->descent += face->box_horizontal_line_width;
30997 }
30998
30999 if (face->box_vertical_line_width > 0)
31000 {
31001 if (it->start_of_box_run_p && slice.x == 0)
31002 it->pixel_width += face->box_vertical_line_width;
31003 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
31004 it->pixel_width += face->box_vertical_line_width;
31005 }
31006 }
31007
31008 take_vertical_position_into_account (it);
31009
31010
31011
31012 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
31013 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31014 {
31015 it->pixel_width -= crop;
31016 slice.width -= crop;
31017 }
31018
31019 if (it->glyph_row)
31020 {
31021 struct glyph *glyph;
31022 enum glyph_row_area area = it->area;
31023
31024 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31025 if (it->glyph_row->reversed_p)
31026 {
31027 struct glyph *g;
31028
31029
31030 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31031 g[1] = *g;
31032 glyph = it->glyph_row->glyphs[it->area];
31033 }
31034 if (glyph < it->glyph_row->glyphs[area + 1])
31035 {
31036 glyph->charpos = CHARPOS (it->position);
31037 glyph->object = it->object;
31038 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31039 glyph->ascent = glyph_ascent;
31040 glyph->descent = it->descent;
31041 glyph->voffset = it->voffset;
31042 glyph->type = IMAGE_GLYPH;
31043 glyph->avoid_cursor_p = it->avoid_cursor_p;
31044 glyph->multibyte_p = it->multibyte_p;
31045 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31046 {
31047
31048
31049 glyph->right_box_line_p = it->start_of_box_run_p;
31050 glyph->left_box_line_p = it->end_of_box_run_p;
31051 }
31052 else
31053 {
31054 glyph->left_box_line_p = it->start_of_box_run_p;
31055 glyph->right_box_line_p = it->end_of_box_run_p;
31056 }
31057 glyph->overlaps_vertically_p = false;
31058 glyph->padding_p = false;
31059 glyph->glyph_not_available_p = false;
31060 glyph->face_id = it->face_id;
31061 glyph->u.img_id = img->id;
31062 glyph->slice.img = slice;
31063 glyph->font_type = FONT_TYPE_UNKNOWN;
31064 if (it->bidi_p)
31065 {
31066 glyph->resolved_level = it->bidi_it.resolved_level;
31067 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31068 glyph->bidi_type = it->bidi_it.type;
31069 }
31070 ++it->glyph_row->used[area];
31071 }
31072 else
31073 IT_EXPAND_MATRIX_WIDTH (it, area);
31074 }
31075 }
31076
31077 static void
31078 produce_xwidget_glyph (struct it *it)
31079 {
31080 #ifdef HAVE_XWIDGETS
31081 struct xwidget *xw;
31082 int glyph_ascent, crop;
31083 eassert (it->what == IT_XWIDGET);
31084
31085 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31086
31087 prepare_face_for_display (it->f, face);
31088
31089 xw = it->xwidget;
31090 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31091 it->descent = xw->height/2;
31092 it->phys_descent = it->descent;
31093 it->pixel_width = xw->width;
31094
31095
31096 if (it->descent < 0)
31097 it->descent = 0;
31098
31099 it->nglyphs = 1;
31100
31101 if (face->box != FACE_NO_BOX)
31102 {
31103 if (face->box_horizontal_line_width > 0)
31104 {
31105 it->ascent += face->box_horizontal_line_width;
31106 it->descent += face->box_horizontal_line_width;
31107 }
31108
31109 if (face->box_vertical_line_width > 0)
31110 {
31111 if (it->start_of_box_run_p)
31112 it->pixel_width += face->box_vertical_line_width;
31113 it->pixel_width += face->box_vertical_line_width;
31114 }
31115 }
31116
31117 take_vertical_position_into_account (it);
31118
31119
31120
31121 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31122 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31123 it->pixel_width -= crop;
31124
31125 if (it->glyph_row)
31126 {
31127 enum glyph_row_area area = it->area;
31128 struct glyph *glyph
31129 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31130
31131 if (it->glyph_row->reversed_p)
31132 {
31133 struct glyph *g;
31134
31135
31136 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31137 g[1] = *g;
31138 glyph = it->glyph_row->glyphs[it->area];
31139 }
31140 if (glyph < it->glyph_row->glyphs[area + 1])
31141 {
31142 glyph->charpos = CHARPOS (it->position);
31143 glyph->object = it->object;
31144 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31145 glyph->ascent = glyph_ascent;
31146 glyph->descent = it->descent;
31147 glyph->voffset = it->voffset;
31148 glyph->type = XWIDGET_GLYPH;
31149 glyph->avoid_cursor_p = it->avoid_cursor_p;
31150 glyph->multibyte_p = it->multibyte_p;
31151 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31152 {
31153
31154
31155 glyph->right_box_line_p = it->start_of_box_run_p;
31156 glyph->left_box_line_p = it->end_of_box_run_p;
31157 }
31158 else
31159 {
31160 glyph->left_box_line_p = it->start_of_box_run_p;
31161 glyph->right_box_line_p = it->end_of_box_run_p;
31162 }
31163 glyph->overlaps_vertically_p = 0;
31164 glyph->padding_p = 0;
31165 glyph->glyph_not_available_p = 0;
31166 glyph->face_id = it->face_id;
31167 glyph->u.xwidget = it->xwidget->xwidget_id;
31168 glyph->font_type = FONT_TYPE_UNKNOWN;
31169 if (it->bidi_p)
31170 {
31171 glyph->resolved_level = it->bidi_it.resolved_level;
31172 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31173 glyph->bidi_type = it->bidi_it.type;
31174 }
31175 ++it->glyph_row->used[area];
31176 }
31177 else
31178 IT_EXPAND_MATRIX_WIDTH (it, area);
31179 }
31180 #endif
31181 }
31182
31183
31184
31185
31186
31187 static void
31188 append_stretch_glyph (struct it *it, Lisp_Object object,
31189 int width, int height, int ascent)
31190 {
31191 struct glyph *glyph;
31192 enum glyph_row_area area = it->area;
31193
31194 eassert (ascent >= 0 && ascent <= height);
31195
31196 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31197 if (glyph < it->glyph_row->glyphs[area + 1])
31198 {
31199
31200
31201 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31202 {
31203 struct glyph *g;
31204
31205
31206 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31207 g[1] = *g;
31208 glyph = it->glyph_row->glyphs[area];
31209
31210
31211
31212
31213
31214
31215
31216
31217
31218
31219
31220
31221
31222
31223
31224 if (it->current_x < it->first_visible_x)
31225 width -= it->first_visible_x - it->current_x;
31226 eassert (width > 0);
31227 }
31228 glyph->charpos = CHARPOS (it->position);
31229 glyph->object = object;
31230
31231
31232 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31233 glyph->ascent = ascent;
31234 glyph->descent = height - ascent;
31235 glyph->voffset = it->voffset;
31236 glyph->type = STRETCH_GLYPH;
31237 glyph->avoid_cursor_p = it->avoid_cursor_p;
31238 glyph->multibyte_p = it->multibyte_p;
31239 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31240 {
31241
31242
31243 glyph->right_box_line_p = it->start_of_box_run_p;
31244 glyph->left_box_line_p = it->end_of_box_run_p;
31245 }
31246 else
31247 {
31248 glyph->left_box_line_p = it->start_of_box_run_p;
31249 glyph->right_box_line_p = it->end_of_box_run_p;
31250 }
31251 glyph->overlaps_vertically_p = false;
31252 glyph->padding_p = false;
31253 glyph->glyph_not_available_p = false;
31254 glyph->face_id = it->face_id;
31255 glyph->u.stretch.ascent = ascent;
31256 glyph->u.stretch.height = height;
31257 glyph->slice.img = null_glyph_slice;
31258 glyph->font_type = FONT_TYPE_UNKNOWN;
31259 if (it->bidi_p)
31260 {
31261 glyph->resolved_level = it->bidi_it.resolved_level;
31262 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31263 glyph->bidi_type = it->bidi_it.type;
31264 }
31265 else
31266 {
31267 glyph->resolved_level = 0;
31268 glyph->bidi_type = UNKNOWN_BT;
31269 }
31270 ++it->glyph_row->used[area];
31271 }
31272 else
31273 IT_EXPAND_MATRIX_WIDTH (it, area);
31274 }
31275
31276 #endif
31277
31278
31279
31280
31281
31282
31283
31284
31285
31286
31287
31288
31289
31290
31291
31292
31293
31294
31295
31296
31297
31298
31299
31300
31301
31302
31303
31304
31305
31306
31307
31308
31309 void
31310 produce_stretch_glyph (struct it *it)
31311 {
31312
31313 Lisp_Object prop, plist;
31314 int width = 0, height = 0, align_to = -1;
31315 bool zero_width_ok_p = false;
31316 double tem;
31317 struct font *font = NULL;
31318
31319 #ifdef HAVE_WINDOW_SYSTEM
31320 int ascent = 0;
31321 bool zero_height_ok_p = false;
31322 struct face *face = NULL;
31323
31324 if (FRAME_WINDOW_P (it->f))
31325 {
31326 face = FACE_FROM_ID (it->f, it->face_id);
31327 font = face->font ? face->font : FRAME_FONT (it->f);
31328 prepare_face_for_display (it->f, face);
31329 }
31330 #endif
31331
31332
31333 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31334 plist = XCDR (it->object);
31335
31336
31337 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31338 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31339 {
31340
31341 zero_width_ok_p = true;
31342 width = (int)tem;
31343 }
31344 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31345 {
31346
31347
31348
31349 struct it it2;
31350 Lisp_Object object =
31351 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31352 unsigned char *p = (STRINGP (object)
31353 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31354 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31355 bool multibyte_p =
31356 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31357
31358 it2 = *it;
31359 if (multibyte_p)
31360 {
31361 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31362 #ifdef HAVE_WINDOW_SYSTEM
31363 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31364 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31365 IT_CHARPOS (*it),
31366 STRINGP (object)? object : Qnil);
31367 #endif
31368 }
31369 else
31370 {
31371 it2.c = it2.char_to_display = *p, it2.len = 1;
31372 if (! ASCII_CHAR_P (it2.c))
31373 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31374 }
31375
31376 it2.glyph_row = NULL;
31377 it2.what = IT_CHARACTER;
31378 PRODUCE_GLYPHS (&it2);
31379 width = NUMVAL (prop) * it2.pixel_width;
31380 }
31381 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31382 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31383 &align_to))
31384 {
31385 int x = it->current_x + it->continuation_lines_width;
31386 int x0 = x;
31387
31388 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31389 {
31390 x -= it->lnum_pixel_width;
31391
31392 if (x + it->stretch_adjust >= it->first_visible_x)
31393 x += it->stretch_adjust;
31394 }
31395
31396 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31397 align_to = (align_to < 0
31398 ? 0
31399 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31400 else if (align_to < 0)
31401 align_to = window_box_left_offset (it->w, TEXT_AREA);
31402 width = max (0, (int)tem + align_to - x);
31403
31404 int next_x = x + width;
31405 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31406 {
31407
31408
31409 if (x < it->first_visible_x)
31410 {
31411 next_x -= it->first_visible_x - x;
31412 it->stretch_adjust = it->first_visible_x - x;
31413 }
31414 else
31415 next_x -= it->stretch_adjust;
31416 }
31417 width = next_x - x0;
31418 zero_width_ok_p = true;
31419 }
31420 else
31421
31422 width = FRAME_COLUMN_WIDTH (it->f);
31423
31424 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31425 width = 1;
31426
31427 #ifdef HAVE_WINDOW_SYSTEM
31428
31429 if (FRAME_WINDOW_P (it->f))
31430 {
31431 int default_height = normal_char_height (font, ' ');
31432
31433 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31434 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31435 {
31436 height = (int)tem;
31437 zero_height_ok_p = true;
31438 }
31439 else if (prop = plist_get (plist, QCrelative_height),
31440 NUMVAL (prop) > 0)
31441 height = default_height * NUMVAL (prop);
31442 else
31443 height = default_height;
31444
31445 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31446 height = 1;
31447
31448
31449
31450
31451 if (prop = plist_get (plist, QCascent),
31452 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31453 ascent = height * NUMVAL (prop) / 100.0;
31454 else if (!NILP (prop)
31455 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31456 ascent = min (max (0, (int)tem), height);
31457 else
31458 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31459 }
31460 else
31461 #endif
31462 height = 1;
31463
31464 if (width > 0
31465 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31466 && it->current_x + width > it->last_visible_x)
31467 {
31468 width = it->last_visible_x - it->current_x;
31469 #ifdef HAVE_WINDOW_SYSTEM
31470
31471
31472 width -= FRAME_WINDOW_P (it->f);
31473 #endif
31474 }
31475
31476 if (width > 0 && height > 0 && it->glyph_row)
31477 {
31478 Lisp_Object o_object = it->object;
31479 Lisp_Object object =
31480 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31481 int n = width;
31482
31483 if (!STRINGP (object))
31484 object = it->w->contents;
31485 #ifdef HAVE_WINDOW_SYSTEM
31486 if (FRAME_WINDOW_P (it->f))
31487 append_stretch_glyph (it, object, width, height, ascent);
31488 else
31489 #endif
31490 {
31491 it->object = object;
31492 it->char_to_display = ' ';
31493 it->pixel_width = it->len = 1;
31494 while (n--)
31495 tty_append_glyph (it);
31496 it->object = o_object;
31497 }
31498 }
31499
31500 it->pixel_width = width;
31501 #ifdef HAVE_WINDOW_SYSTEM
31502 if (FRAME_WINDOW_P (it->f))
31503 {
31504 it->ascent = it->phys_ascent = ascent;
31505 it->descent = it->phys_descent = height - it->ascent;
31506 it->nglyphs = width > 0 && height > 0;
31507 take_vertical_position_into_account (it);
31508 }
31509 else
31510 #endif
31511 it->nglyphs = width;
31512 }
31513
31514
31515
31516
31517
31518
31519
31520 static void
31521 produce_special_glyphs (struct it *it, enum display_element_type what)
31522 {
31523 struct it temp_it;
31524 Lisp_Object gc;
31525 GLYPH glyph;
31526
31527 temp_it = *it;
31528 temp_it.object = Qnil;
31529 memset (&temp_it.current, 0, sizeof temp_it.current);
31530
31531 if (what == IT_CONTINUATION)
31532 {
31533
31534 if (it->bidi_it.paragraph_dir == R2L)
31535 SET_GLYPH_FROM_CHAR (glyph, '/');
31536 else
31537 SET_GLYPH_FROM_CHAR (glyph, '\\');
31538 if (it->dp
31539 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31540 {
31541
31542 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31543 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31544 }
31545 }
31546 else if (what == IT_TRUNCATION)
31547 {
31548
31549 SET_GLYPH_FROM_CHAR (glyph, '$');
31550 if (it->dp
31551 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31552 {
31553
31554 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31555 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31556 }
31557 }
31558 else
31559 emacs_abort ();
31560
31561 #ifdef HAVE_WINDOW_SYSTEM
31562
31563
31564
31565
31566
31567 if (FRAME_WINDOW_P (temp_it.f)
31568
31569
31570
31571 && temp_it.glyph_row
31572
31573
31574
31575 && temp_it.glyph_row->used[TEXT_AREA] > 0
31576 && (temp_it.glyph_row->reversed_p
31577 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31578 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31579 {
31580 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31581
31582 if (stretch_width > 0)
31583 {
31584 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31585 struct font *font =
31586 face->font ? face->font : FRAME_FONT (temp_it.f);
31587 int stretch_ascent =
31588 (((temp_it.ascent + temp_it.descent)
31589 * FONT_BASE (font)) / FONT_HEIGHT (font));
31590
31591 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31592 temp_it.ascent + temp_it.descent,
31593 stretch_ascent);
31594 }
31595 }
31596 #endif
31597
31598 temp_it.dp = NULL;
31599 temp_it.what = IT_CHARACTER;
31600 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31601 temp_it.face_id = GLYPH_FACE (glyph);
31602 temp_it.len = CHAR_BYTES (temp_it.c);
31603
31604 PRODUCE_GLYPHS (&temp_it);
31605 it->pixel_width = temp_it.pixel_width;
31606 it->nglyphs = temp_it.nglyphs;
31607 }
31608
31609 #ifdef HAVE_WINDOW_SYSTEM
31610
31611
31612
31613
31614
31615
31616
31617
31618
31619 static Lisp_Object
31620 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31621 int boff, bool override)
31622 {
31623 Lisp_Object face_name = Qnil;
31624 int ascent, descent, height;
31625
31626 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31627 return val;
31628
31629 if (CONSP (val))
31630 {
31631 face_name = XCAR (val);
31632 val = XCDR (val);
31633 if (!NUMBERP (val))
31634 val = make_fixnum (1);
31635 if (NILP (face_name))
31636 {
31637 height = it->ascent + it->descent;
31638 goto scale;
31639 }
31640 }
31641
31642 if (NILP (face_name))
31643 {
31644 font = FRAME_FONT (it->f);
31645 boff = FRAME_BASELINE_OFFSET (it->f);
31646 }
31647 else if (EQ (face_name, Qt))
31648 {
31649 override = false;
31650 }
31651 else
31652 {
31653 int face_id;
31654 struct face *face;
31655
31656 face_id = lookup_named_face (it->w, it->f, face_name, false);
31657 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31658 if (face == NULL || ((font = face->font) == NULL))
31659 return make_fixnum (-1);
31660 boff = font->baseline_offset;
31661 if (font->vertical_centering)
31662 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31663 }
31664
31665 normal_char_ascent_descent (font, -1, &ascent, &descent);
31666
31667 if (override)
31668 {
31669 it->override_ascent = ascent;
31670 it->override_descent = descent;
31671 it->override_boff = boff;
31672 }
31673
31674 height = ascent + descent;
31675
31676 scale:
31677
31678 if (FLOATP (val))
31679 height = (int)(XFLOAT_DATA (val) * height);
31680 else if (INTEGERP (val))
31681 {
31682 intmax_t v;
31683 if (integer_to_intmax (val, &v))
31684 height *= v;
31685 }
31686
31687 return make_fixnum (height);
31688 }
31689
31690
31691
31692
31693
31694
31695
31696
31697
31698
31699
31700
31701
31702
31703 static void
31704 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
31705 short upper_xoff, short upper_yoff,
31706 short lower_xoff, short lower_yoff)
31707 {
31708 struct glyph *glyph;
31709 enum glyph_row_area area = it->area;
31710
31711 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31712 if (glyph < it->glyph_row->glyphs[area + 1])
31713 {
31714
31715
31716 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31717 {
31718 struct glyph *g;
31719
31720
31721 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31722 g[1] = *g;
31723 glyph = it->glyph_row->glyphs[area];
31724 }
31725 glyph->charpos = CHARPOS (it->position);
31726 glyph->object = it->object;
31727 eassert (it->pixel_width <= SHRT_MAX);
31728 glyph->pixel_width = it->pixel_width;
31729 glyph->ascent = it->ascent;
31730 glyph->descent = it->descent;
31731 glyph->voffset = it->voffset;
31732 glyph->type = GLYPHLESS_GLYPH;
31733 glyph->u.glyphless.method = it->glyphless_method;
31734 glyph->u.glyphless.for_no_font = for_no_font;
31735 glyph->u.glyphless.len = len;
31736 glyph->u.glyphless.ch = it->c;
31737 glyph->slice.glyphless.upper_xoff = upper_xoff;
31738 glyph->slice.glyphless.upper_yoff = upper_yoff;
31739 glyph->slice.glyphless.lower_xoff = lower_xoff;
31740 glyph->slice.glyphless.lower_yoff = lower_yoff;
31741 glyph->avoid_cursor_p = it->avoid_cursor_p;
31742 glyph->multibyte_p = it->multibyte_p;
31743 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31744 {
31745
31746
31747 glyph->right_box_line_p = it->start_of_box_run_p;
31748 glyph->left_box_line_p = it->end_of_box_run_p;
31749 }
31750 else
31751 {
31752 glyph->left_box_line_p = it->start_of_box_run_p;
31753 glyph->right_box_line_p = it->end_of_box_run_p;
31754 }
31755 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31756 || it->phys_descent > it->descent);
31757 glyph->padding_p = false;
31758 glyph->glyph_not_available_p = false;
31759 glyph->face_id = face_id;
31760 glyph->font_type = FONT_TYPE_UNKNOWN;
31761 if (it->bidi_p)
31762 {
31763 glyph->resolved_level = it->bidi_it.resolved_level;
31764 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31765 glyph->bidi_type = it->bidi_it.type;
31766 }
31767 ++it->glyph_row->used[area];
31768 }
31769 else
31770 IT_EXPAND_MATRIX_WIDTH (it, area);
31771 }
31772
31773
31774
31775
31776
31777
31778
31779
31780
31781
31782
31783 static void
31784 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
31785 {
31786 int face_id;
31787 struct face *face;
31788 struct font *font;
31789 int base_width, base_height, width, height;
31790 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
31791 int len;
31792
31793
31794
31795
31796 face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
31797 if (face)
31798 face = face->ascii_face;
31799 font = (face && face->font) ? face->font : FRAME_FONT (it->f);
31800 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
31801 it->ascent += font->baseline_offset;
31802 it->descent -= font->baseline_offset;
31803 base_height = it->ascent + it->descent;
31804 base_width = font->average_width;
31805
31806 face_id = merge_glyphless_glyph_face (it);
31807
31808 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
31809 {
31810 it->pixel_width = THIN_SPACE_WIDTH;
31811 len = 0;
31812 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
31813 }
31814 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
31815 {
31816 width = CHARACTER_WIDTH (it->c);
31817 if (width == 0)
31818 width = 1;
31819 else if (width > 4)
31820 width = 4;
31821 it->pixel_width = base_width * width;
31822 len = 0;
31823 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
31824 }
31825 else
31826 {
31827 char buf[7];
31828 const char *str;
31829 unsigned int code[6];
31830 int upper_len;
31831 int ascent, descent;
31832 struct font_metrics metrics_upper, metrics_lower;
31833
31834 face = FACE_FROM_ID (it->f, face_id);
31835 font = face->font ? face->font : FRAME_FONT (it->f);
31836 prepare_face_for_display (it->f, face);
31837
31838 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
31839 {
31840 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
31841 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
31842 if (CONSP (acronym))
31843 acronym = XCAR (acronym);
31844 str = STRINGP (acronym) ? SSDATA (acronym) : "";
31845 }
31846 else
31847 {
31848 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
31849 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
31850 str = buf;
31851 }
31852 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
31853 code[len] = font->driver->encode_char (font, str[len]);
31854 upper_len = (len + 1) / 2;
31855 font->driver->text_extents (font, code, upper_len,
31856 &metrics_upper);
31857 font->driver->text_extents (font, code + upper_len, len - upper_len,
31858 &metrics_lower);
31859
31860
31861
31862
31863 width = max (metrics_upper.width, metrics_lower.width) + 4;
31864 upper_xoff = lower_xoff = 2;
31865 if (base_width >= width)
31866 {
31867
31868 it->pixel_width = base_width;
31869 lower_xoff = base_width - 2 - metrics_lower.width;
31870 }
31871 else
31872 {
31873
31874 it->pixel_width = width;
31875 if (metrics_upper.width >= metrics_lower.width)
31876 lower_xoff = (width - metrics_lower.width) / 2;
31877 else
31878 upper_xoff = (width - metrics_upper.width) / 2;
31879 }
31880
31881
31882
31883 height = (metrics_upper.ascent + metrics_upper.descent
31884 + metrics_lower.ascent + metrics_lower.descent) + 5;
31885
31886
31887
31888
31889
31890
31891
31892
31893 ascent = - (it->descent - (base_height + height + 1) / 2);
31894 descent = it->descent - (base_height - height) / 2;
31895 lower_yoff = descent - 2 - metrics_lower.descent;
31896 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
31897 - metrics_upper.descent);
31898
31899 if (height > base_height)
31900 {
31901 it->ascent = ascent;
31902 it->descent = descent;
31903 }
31904 }
31905
31906 it->phys_ascent = it->ascent;
31907 it->phys_descent = it->descent;
31908 if (it->glyph_row)
31909 append_glyphless_glyph (it, face_id, for_no_font, len,
31910 upper_xoff, upper_yoff,
31911 lower_xoff, lower_yoff);
31912 it->nglyphs = 1;
31913 take_vertical_position_into_account (it);
31914 }
31915
31916
31917
31918
31919
31920 #define IT_APPLY_FACE_BOX(it, face) \
31921 do { \
31922 if (face->box != FACE_NO_BOX) \
31923 { \
31924 int thick = face->box_horizontal_line_width; \
31925 if (thick > 0) \
31926 { \
31927 it->ascent += thick; \
31928 it->descent += thick; \
31929 } \
31930 \
31931 thick = face->box_vertical_line_width; \
31932 if (thick > 0) \
31933 { \
31934 if (it->start_of_box_run_p) \
31935 it->pixel_width += thick; \
31936 if (it->end_of_box_run_p) \
31937 it->pixel_width += thick; \
31938 } \
31939 } \
31940 } while (false)
31941
31942
31943
31944
31945
31946
31947 void
31948 gui_produce_glyphs (struct it *it)
31949 {
31950 int extra_line_spacing = it->extra_line_spacing;
31951
31952 it->glyph_not_available_p = false;
31953
31954 if (it->what == IT_CHARACTER)
31955 {
31956 unsigned char2b;
31957 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31958 struct font *font = face->font;
31959 struct font_metrics *pcm = NULL;
31960 int boff;
31961
31962 if (font == NULL)
31963 {
31964
31965
31966
31967 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
31968
31969 eassert (it->what == IT_GLYPHLESS);
31970 produce_glyphless_glyph (it, true,
31971 STRINGP (acronym) ? acronym : Qnil);
31972 goto done;
31973 }
31974
31975 boff = font->baseline_offset;
31976 if (font->vertical_centering)
31977 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31978
31979 if (it->char_to_display != '\n' && it->char_to_display != '\t')
31980 {
31981 it->nglyphs = 1;
31982
31983 if (it->override_ascent >= 0)
31984 {
31985 it->ascent = it->override_ascent;
31986 it->descent = it->override_descent;
31987 boff = it->override_boff;
31988 }
31989 else
31990 {
31991 it->ascent = FONT_BASE (font) + boff;
31992 it->descent = FONT_DESCENT (font) - boff;
31993 }
31994
31995 if (get_char_glyph_code (it->char_to_display, font, &char2b))
31996 {
31997 pcm = get_per_char_metric (font, &char2b);
31998 if (pcm->width == 0
31999 && pcm->rbearing == 0 && pcm->lbearing == 0)
32000 pcm = NULL;
32001 }
32002
32003 if (pcm)
32004 {
32005 it->phys_ascent = pcm->ascent + boff;
32006 it->phys_descent = pcm->descent - boff;
32007 it->pixel_width = pcm->width;
32008
32009
32010 if (it->override_ascent < 0)
32011 {
32012 if (FONT_TOO_HIGH (font))
32013 {
32014 it->ascent = it->phys_ascent;
32015 it->descent = it->phys_descent;
32016
32017
32018 if (it->ascent < 0)
32019 it->ascent = 0;
32020 if (it->descent < 0)
32021 it->descent = 0;
32022 }
32023 }
32024 }
32025 else
32026 {
32027 it->glyph_not_available_p = true;
32028 it->phys_ascent = it->ascent;
32029 it->phys_descent = it->descent;
32030 it->pixel_width = font->space_width;
32031 }
32032
32033 if (it->constrain_row_ascent_descent_p)
32034 {
32035 if (it->descent > it->max_descent)
32036 {
32037 it->ascent += it->descent - it->max_descent;
32038 it->descent = it->max_descent;
32039 }
32040 if (it->ascent > it->max_ascent)
32041 {
32042 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32043 it->ascent = it->max_ascent;
32044 }
32045 it->phys_ascent = min (it->phys_ascent, it->ascent);
32046 it->phys_descent = min (it->phys_descent, it->descent);
32047 extra_line_spacing = 0;
32048 }
32049
32050
32051
32052 bool stretched_p
32053 = it->char_to_display == ' ' && !NILP (it->space_width);
32054 if (stretched_p)
32055 it->pixel_width *= XFLOATINT (it->space_width);
32056
32057 IT_APPLY_FACE_BOX(it, face);
32058
32059
32060
32061 if (face->overline_p)
32062 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32063
32064 if (it->constrain_row_ascent_descent_p)
32065 {
32066 if (it->ascent > it->max_ascent)
32067 it->ascent = it->max_ascent;
32068 if (it->descent > it->max_descent)
32069 it->descent = it->max_descent;
32070 }
32071
32072 take_vertical_position_into_account (it);
32073
32074
32075 if (it->glyph_row)
32076 {
32077 if (stretched_p)
32078 {
32079
32080
32081 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32082 / FONT_HEIGHT (font));
32083 append_stretch_glyph (it, it->object, it->pixel_width,
32084 it->ascent + it->descent, ascent);
32085 }
32086 else
32087 append_glyph (it);
32088
32089
32090
32091
32092 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32093 it->glyph_row->contains_overlapping_glyphs_p = true;
32094 }
32095 if (! stretched_p && it->pixel_width == 0)
32096
32097
32098 it->pixel_width = 1;
32099 }
32100 else if (it->char_to_display == '\n')
32101 {
32102
32103
32104
32105
32106 Lisp_Object height;
32107 Lisp_Object total_height = Qnil;
32108
32109 it->override_ascent = -1;
32110 it->pixel_width = 0;
32111 it->nglyphs = 0;
32112
32113 height = get_it_property (it, Qline_height);
32114
32115 if (CONSP (height)
32116 && CONSP (XCDR (height))
32117 && NILP (XCDR (XCDR (height))))
32118 {
32119 total_height = XCAR (XCDR (height));
32120 height = XCAR (height);
32121 }
32122 height = calc_line_height_property (it, height, font, boff, true);
32123
32124 if (it->override_ascent >= 0)
32125 {
32126 it->ascent = it->override_ascent;
32127 it->descent = it->override_descent;
32128 boff = it->override_boff;
32129 }
32130 else
32131 {
32132 if (FONT_TOO_HIGH (font))
32133 {
32134 it->ascent = font->pixel_size + boff - 1;
32135 it->descent = -boff + 1;
32136 if (it->descent < 0)
32137 it->descent = 0;
32138 }
32139 else
32140 {
32141 it->ascent = FONT_BASE (font) + boff;
32142 it->descent = FONT_DESCENT (font) - boff;
32143 }
32144 }
32145
32146 if (EQ (height, Qt))
32147 {
32148 if (it->descent > it->max_descent)
32149 {
32150 it->ascent += it->descent - it->max_descent;
32151 it->descent = it->max_descent;
32152 }
32153 if (it->ascent > it->max_ascent)
32154 {
32155 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32156 it->ascent = it->max_ascent;
32157 }
32158 it->phys_ascent = min (it->phys_ascent, it->ascent);
32159 it->phys_descent = min (it->phys_descent, it->descent);
32160 it->constrain_row_ascent_descent_p = true;
32161 extra_line_spacing = 0;
32162 }
32163 else
32164 {
32165 Lisp_Object spacing;
32166
32167 it->phys_ascent = it->ascent;
32168 it->phys_descent = it->descent;
32169
32170 if ((it->max_ascent > 0 || it->max_descent > 0)
32171 && face->box != FACE_NO_BOX
32172 && face->box_horizontal_line_width > 0)
32173 {
32174 it->ascent += face->box_horizontal_line_width;
32175 it->descent += face->box_horizontal_line_width;
32176 }
32177 if (!NILP (height)
32178 && XFIXNUM (height) > it->ascent + it->descent)
32179 it->ascent = XFIXNUM (height) - it->descent;
32180
32181 if (!NILP (total_height))
32182 spacing = calc_line_height_property (it, total_height, font,
32183 boff, false);
32184 else
32185 {
32186 spacing = get_it_property (it, Qline_spacing);
32187 spacing = calc_line_height_property (it, spacing, font,
32188 boff, false);
32189 }
32190 if (FIXNUMP (spacing))
32191 {
32192 extra_line_spacing = XFIXNUM (spacing);
32193 if (!NILP (total_height))
32194 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32195 }
32196 }
32197 }
32198 else
32199 {
32200 if (font->space_width > 0)
32201 {
32202 int tab_width = it->tab_width * font->space_width;
32203 int x = it->current_x + it->continuation_lines_width;
32204 int x0 = x;
32205
32206 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32207 {
32208 x -= it->lnum_pixel_width;
32209
32210 if (x + it->stretch_adjust >= it->first_visible_x)
32211 x += it->stretch_adjust;
32212 }
32213
32214 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32215
32216
32217
32218
32219 if (next_tab_x - x < font->space_width)
32220 next_tab_x += tab_width;
32221 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32222 {
32223 next_tab_x += it->lnum_pixel_width;
32224
32225
32226 if (x < it->first_visible_x)
32227 {
32228 next_tab_x -= it->first_visible_x - x;
32229 it->stretch_adjust = it->first_visible_x - x;
32230 }
32231 else
32232 next_tab_x -= it->stretch_adjust;
32233 }
32234
32235 it->pixel_width = next_tab_x - x0;
32236 it->nglyphs = 1;
32237 if (FONT_TOO_HIGH (font))
32238 {
32239 if (get_char_glyph_code (' ', font, &char2b))
32240 {
32241 pcm = get_per_char_metric (font, &char2b);
32242 if (pcm->width == 0
32243 && pcm->rbearing == 0 && pcm->lbearing == 0)
32244 pcm = NULL;
32245 }
32246
32247 if (pcm)
32248 {
32249 it->ascent = pcm->ascent + boff;
32250 it->descent = pcm->descent - boff;
32251 }
32252 else
32253 {
32254 it->ascent = font->pixel_size + boff - 1;
32255 it->descent = -boff + 1;
32256 }
32257 if (it->ascent < 0)
32258 it->ascent = 0;
32259 if (it->descent < 0)
32260 it->descent = 0;
32261 }
32262 else
32263 {
32264 it->ascent = FONT_BASE (font) + boff;
32265 it->descent = FONT_DESCENT (font) - boff;
32266 }
32267 it->phys_ascent = it->ascent;
32268 it->phys_descent = it->descent;
32269
32270 if (it->glyph_row)
32271 {
32272 append_stretch_glyph (it, it->object, it->pixel_width,
32273 it->ascent + it->descent, it->ascent);
32274 }
32275 }
32276 else
32277 {
32278 it->pixel_width = 0;
32279 it->nglyphs = 1;
32280 }
32281 }
32282
32283 if (FONT_TOO_HIGH (font))
32284 {
32285 int font_ascent, font_descent;
32286
32287
32288
32289
32290
32291
32292
32293
32294 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32295 it->max_ascent = max (it->max_ascent, font_ascent);
32296 it->max_descent = max (it->max_descent, font_descent);
32297 }
32298
32299 if (it->ascent < 0)
32300 it->ascent = 0;
32301 if (it->descent < 0)
32302 it->descent = 0;
32303 }
32304 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32305 {
32306
32307
32308
32309
32310
32311
32312
32313
32314 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32315 int boff;
32316 struct composition *cmp = composition_table[it->cmp_it.id];
32317 int glyph_len = cmp->glyph_len;
32318 struct font *font = face->font;
32319
32320 it->nglyphs = 1;
32321
32322
32323
32324
32325
32326
32327
32328
32329 if (! cmp->font || cmp->font != font)
32330 {
32331
32332
32333
32334
32335 int font_ascent, font_descent, font_height;
32336
32337 int leftmost, rightmost, lowest, highest;
32338 int lbearing, rbearing;
32339 int i, width, ascent, descent;
32340 int c;
32341 unsigned char2b;
32342 struct font_metrics *pcm;
32343 ptrdiff_t pos;
32344
32345 eassume (0 < glyph_len);
32346 do
32347 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32348 while (c == '\t' && 0 < --glyph_len);
32349
32350 bool right_padded = glyph_len < cmp->glyph_len;
32351 for (i = 0; i < glyph_len; i++)
32352 {
32353 c = COMPOSITION_GLYPH (cmp, i);
32354 if (c != '\t')
32355 break;
32356 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32357 }
32358 bool left_padded = i > 0;
32359
32360 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32361 : IT_CHARPOS (*it));
32362
32363 bool font_not_found_p = font == NULL;
32364 if (font_not_found_p)
32365 {
32366 face = face->ascii_face;
32367 font = face->font;
32368 }
32369 boff = font->baseline_offset;
32370 if (font->vertical_centering)
32371 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32372 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32373 font_ascent += boff;
32374 font_descent -= boff;
32375 font_height = font_ascent + font_descent;
32376
32377 cmp->font = font;
32378
32379 pcm = NULL;
32380 if (! font_not_found_p)
32381 {
32382 get_char_face_and_encoding (it->f, c, it->face_id,
32383 &char2b, false);
32384 pcm = get_per_char_metric (font, &char2b);
32385 }
32386
32387
32388 if (pcm)
32389 {
32390 width = cmp->glyph_len > 0 ? pcm->width : 0;
32391 ascent = pcm->ascent;
32392 descent = pcm->descent;
32393 lbearing = pcm->lbearing;
32394 rbearing = pcm->rbearing;
32395 }
32396 else
32397 {
32398 width = cmp->glyph_len > 0 ? font->space_width : 0;
32399 ascent = FONT_BASE (font);
32400 descent = FONT_DESCENT (font);
32401 lbearing = 0;
32402 rbearing = width;
32403 }
32404
32405 rightmost = width;
32406 leftmost = 0;
32407 lowest = - descent + boff;
32408 highest = ascent + boff;
32409
32410 if (! font_not_found_p
32411 && font->default_ascent
32412 && CHAR_TABLE_P (Vuse_default_ascent)
32413 && !NILP (Faref (Vuse_default_ascent,
32414 make_fixnum (it->char_to_display))))
32415 highest = font->default_ascent + boff;
32416
32417
32418
32419
32420 cmp->offsets[i * 2] = 0;
32421 cmp->offsets[i * 2 + 1] = boff;
32422 cmp->lbearing = lbearing;
32423 cmp->rbearing = rbearing;
32424
32425
32426 for (i++; i < glyph_len; i++)
32427 {
32428 int left, right, btm, top;
32429 int ch = COMPOSITION_GLYPH (cmp, i);
32430 int face_id;
32431 struct face *this_face;
32432
32433 if (ch == '\t')
32434 ch = ' ';
32435 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32436 this_face = FACE_FROM_ID (it->f, face_id);
32437 font = this_face->font;
32438
32439 if (font == NULL)
32440 pcm = NULL;
32441 else
32442 {
32443 get_char_face_and_encoding (it->f, ch, face_id,
32444 &char2b, false);
32445 pcm = get_per_char_metric (font, &char2b);
32446 }
32447 if (! pcm)
32448 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32449 else
32450 {
32451 width = pcm->width;
32452 ascent = pcm->ascent;
32453 descent = pcm->descent;
32454 lbearing = pcm->lbearing;
32455 rbearing = pcm->rbearing;
32456 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32457 {
32458
32459
32460 left = (leftmost + rightmost - width) / 2;
32461 btm = - descent + boff;
32462 if (font->relative_compose
32463 && (! CHAR_TABLE_P (Vignore_relative_composition)
32464 || NILP (Faref (Vignore_relative_composition,
32465 make_fixnum (ch)))))
32466 {
32467
32468 if (- descent >= font->relative_compose)
32469
32470 btm = highest + 1;
32471 else if (ascent <= 0)
32472
32473 btm = lowest - 1 - ascent - descent;
32474 }
32475 }
32476 else
32477 {
32478
32479
32480
32481
32482
32483
32484
32485
32486
32487
32488
32489
32490
32491
32492
32493 int rule = COMPOSITION_RULE (cmp, i);
32494 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32495
32496 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32497 grefx = gref % 3, nrefx = nref % 3;
32498 grefy = gref / 3, nrefy = nref / 3;
32499 if (xoff)
32500 xoff = font_height * (xoff - 128) / 256;
32501 if (yoff)
32502 yoff = font_height * (yoff - 128) / 256;
32503
32504 left = (leftmost
32505 + grefx * (rightmost - leftmost) / 2
32506 - nrefx * width / 2
32507 + xoff);
32508
32509 btm = ((grefy == 0 ? highest
32510 : grefy == 1 ? 0
32511 : grefy == 2 ? lowest
32512 : (highest + lowest) / 2)
32513 - (nrefy == 0 ? ascent + descent
32514 : nrefy == 1 ? descent - boff
32515 : nrefy == 2 ? 0
32516 : (ascent + descent) / 2)
32517 + yoff);
32518 }
32519
32520 cmp->offsets[i * 2] = left;
32521 cmp->offsets[i * 2 + 1] = btm + descent;
32522
32523
32524 if (width > 0)
32525 {
32526 right = left + width;
32527 if (left < leftmost)
32528 leftmost = left;
32529 if (right > rightmost)
32530 rightmost = right;
32531 }
32532 top = btm + descent + ascent;
32533 if (top > highest)
32534 highest = top;
32535 if (btm < lowest)
32536 lowest = btm;
32537
32538 if (cmp->lbearing > left + lbearing)
32539 cmp->lbearing = left + lbearing;
32540 if (cmp->rbearing < left + rbearing)
32541 cmp->rbearing = left + rbearing;
32542 }
32543 }
32544
32545
32546
32547
32548 if (leftmost < 0)
32549 {
32550 for (i = 0; i < cmp->glyph_len; i++)
32551 cmp->offsets[i * 2] -= leftmost;
32552 rightmost -= leftmost;
32553 cmp->lbearing -= leftmost;
32554 cmp->rbearing -= leftmost;
32555 }
32556
32557 if (left_padded && cmp->lbearing < 0)
32558 {
32559 for (i = 0; i < cmp->glyph_len; i++)
32560 cmp->offsets[i * 2] -= cmp->lbearing;
32561 rightmost -= cmp->lbearing;
32562 cmp->rbearing -= cmp->lbearing;
32563 cmp->lbearing = 0;
32564 }
32565 if (right_padded && rightmost < cmp->rbearing)
32566 {
32567 rightmost = cmp->rbearing;
32568 }
32569
32570 cmp->pixel_width = rightmost;
32571 cmp->ascent = highest;
32572 cmp->descent = - lowest;
32573 if (cmp->ascent < font_ascent)
32574 cmp->ascent = font_ascent;
32575 if (cmp->descent < font_descent)
32576 cmp->descent = font_descent;
32577 }
32578
32579 if (it->glyph_row
32580 && (cmp->lbearing < 0
32581 || cmp->rbearing > cmp->pixel_width))
32582 it->glyph_row->contains_overlapping_glyphs_p = true;
32583
32584 it->pixel_width = cmp->pixel_width;
32585 it->ascent = it->phys_ascent = cmp->ascent;
32586 it->descent = it->phys_descent = cmp->descent;
32587 IT_APPLY_FACE_BOX(it, face);
32588
32589
32590
32591 if (face->overline_p)
32592 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32593
32594 take_vertical_position_into_account (it);
32595 if (it->ascent < 0)
32596 it->ascent = 0;
32597 if (it->descent < 0)
32598 it->descent = 0;
32599
32600 if (it->glyph_row && cmp->glyph_len > 0)
32601 append_composite_glyph (it);
32602 }
32603 else if (it->what == IT_COMPOSITION)
32604 {
32605
32606 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32607 Lisp_Object gstring;
32608 struct font_metrics metrics;
32609
32610 it->nglyphs = 1;
32611
32612 gstring = composition_gstring_from_id (it->cmp_it.id);
32613 it->pixel_width
32614 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32615 &metrics);
32616 if (it->pixel_width == 0)
32617 {
32618 it->glyph_not_available_p = true;
32619 it->phys_ascent = it->ascent;
32620 it->phys_descent = it->descent;
32621 it->pixel_width = face->font->space_width;
32622 }
32623 else
32624 {
32625 if (it->glyph_row
32626 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32627 it->glyph_row->contains_overlapping_glyphs_p = true;
32628 it->ascent = it->phys_ascent = metrics.ascent;
32629 it->descent = it->phys_descent = metrics.descent;
32630 }
32631 IT_APPLY_FACE_BOX(it, face);
32632
32633
32634
32635 if (face->overline_p)
32636 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32637 take_vertical_position_into_account (it);
32638 if (it->ascent < 0)
32639 it->ascent = 0;
32640 if (it->descent < 0)
32641 it->descent = 0;
32642
32643 if (it->glyph_row)
32644 append_composite_glyph (it);
32645 }
32646 else if (it->what == IT_GLYPHLESS)
32647 produce_glyphless_glyph (it, false, Qnil);
32648 else if (it->what == IT_IMAGE)
32649 produce_image_glyph (it);
32650 else if (it->what == IT_STRETCH)
32651 produce_stretch_glyph (it);
32652 else if (it->what == IT_XWIDGET)
32653 produce_xwidget_glyph (it);
32654
32655 done:
32656
32657
32658 eassert (it->ascent >= 0 && it->descent >= 0);
32659 if (it->area == TEXT_AREA)
32660 it->current_x += it->pixel_width;
32661
32662 if (extra_line_spacing > 0)
32663 {
32664 it->descent += extra_line_spacing;
32665 if (extra_line_spacing > it->max_extra_line_spacing)
32666 it->max_extra_line_spacing = extra_line_spacing;
32667 }
32668
32669 it->max_ascent = max (it->max_ascent, it->ascent);
32670 it->max_descent = max (it->max_descent, it->descent);
32671 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32672 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32673 }
32674
32675
32676
32677
32678
32679
32680 void
32681 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32682 struct glyph *start, enum glyph_row_area updated_area, int len)
32683 {
32684 int x, hpos, chpos = w->phys_cursor.hpos;
32685
32686 eassert (updated_row);
32687
32688
32689
32690 if (!updated_row->reversed_p && chpos < 0)
32691 chpos = 0;
32692 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
32693 chpos = updated_row->used[TEXT_AREA] - 1;
32694
32695 block_input ();
32696
32697
32698
32699 hpos = start - updated_row->glyphs[updated_area];
32700 x = draw_glyphs (w, w->output_cursor.x,
32701 updated_row, updated_area,
32702 hpos, hpos + len,
32703 DRAW_NORMAL_TEXT, 0);
32704
32705
32706 if (updated_area == TEXT_AREA
32707 && w->phys_cursor_on_p
32708 && w->phys_cursor.vpos == w->output_cursor.vpos
32709 && chpos >= hpos
32710 && chpos < hpos + len)
32711 w->phys_cursor_on_p = false;
32712
32713 unblock_input ();
32714
32715
32716 w->output_cursor.hpos += len;
32717 w->output_cursor.x = x;
32718 }
32719
32720
32721
32722
32723
32724 void
32725 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
32726 struct glyph *start, enum glyph_row_area updated_area, int len)
32727 {
32728 struct frame *f;
32729 int line_height, shift_by_width, shifted_region_width;
32730 struct glyph_row *row;
32731 struct glyph *glyph;
32732 int frame_x, frame_y;
32733 ptrdiff_t hpos;
32734
32735 eassert (updated_row);
32736 block_input ();
32737 f = XFRAME (WINDOW_FRAME (w));
32738
32739
32740 row = updated_row;
32741 line_height = row->height;
32742
32743
32744 shift_by_width = 0;
32745 for (glyph = start; glyph < start + len; ++glyph)
32746 shift_by_width += glyph->pixel_width;
32747
32748
32749 shifted_region_width = (window_box_width (w, updated_area)
32750 - w->output_cursor.x
32751 - shift_by_width);
32752
32753
32754 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
32755 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
32756
32757 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
32758 line_height, shift_by_width);
32759
32760
32761 hpos = start - row->glyphs[updated_area];
32762 draw_glyphs (w, w->output_cursor.x, row, updated_area,
32763 hpos, hpos + len,
32764 DRAW_NORMAL_TEXT, 0);
32765
32766
32767 w->output_cursor.hpos += len;
32768 w->output_cursor.x += shift_by_width;
32769 unblock_input ();
32770 }
32771
32772
32773
32774
32775
32776
32777
32778
32779
32780
32781 void
32782 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
32783 enum glyph_row_area updated_area, int to_x)
32784 {
32785 struct frame *f;
32786 int max_x, min_y, max_y;
32787 int from_x, from_y, to_y;
32788 struct face *face;
32789
32790 eassert (updated_row);
32791 f = XFRAME (w->frame);
32792 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
32793
32794 if (updated_row->full_width_p)
32795 max_x = (WINDOW_PIXEL_WIDTH (w)
32796 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
32797 else
32798 max_x = window_box_width (w, updated_area);
32799 max_y = window_text_bottom_y (w);
32800
32801
32802
32803 if (to_x == 0)
32804 return;
32805 else if (to_x < 0)
32806 to_x = max_x;
32807 else
32808 to_x = min (to_x, max_x);
32809
32810 to_y = min (max_y, w->output_cursor.y + updated_row->height);
32811
32812
32813 if (!updated_row->full_width_p)
32814 notice_overwritten_cursor (w, updated_area,
32815 w->output_cursor.x, -1,
32816 updated_row->y,
32817 MATRIX_ROW_BOTTOM_Y (updated_row));
32818
32819 from_x = w->output_cursor.x;
32820
32821
32822 if (updated_row->full_width_p)
32823 {
32824 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
32825 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
32826 }
32827 else
32828 {
32829 int area_left = window_box_left (w, updated_area);
32830 from_x += area_left;
32831 to_x += area_left;
32832 }
32833
32834 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
32835 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
32836 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
32837
32838
32839 if (to_x > from_x && to_y > from_y)
32840 {
32841 block_input ();
32842 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
32843 to_x - from_x, to_y - from_y);
32844
32845 if (face && !updated_row->stipple_p)
32846 updated_row->stipple_p = face->stipple;
32847 unblock_input ();
32848 }
32849 }
32850
32851 #endif
32852
32853
32854
32855
32856
32857
32858
32859
32860
32861
32862
32863 static enum text_cursor_kinds
32864 get_specified_cursor_type (Lisp_Object arg, int *width)
32865 {
32866 enum text_cursor_kinds type;
32867
32868 if (NILP (arg))
32869 return NO_CURSOR;
32870
32871 if (EQ (arg, Qbox))
32872 return FILLED_BOX_CURSOR;
32873
32874 if (EQ (arg, Qhollow))
32875 return HOLLOW_BOX_CURSOR;
32876
32877 if (EQ (arg, Qbar))
32878 {
32879 *width = 2;
32880 return BAR_CURSOR;
32881 }
32882
32883 if (EQ (arg, Qhbar))
32884 {
32885 *width = 2;
32886 return HBAR_CURSOR;
32887 }
32888
32889 if (CONSP (arg)
32890 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
32891 {
32892 *width = XFIXNUM (XCDR (arg));
32893
32894 if (EQ (XCAR (arg), Qbox))
32895 return FILLED_BOX_CURSOR;
32896 else if (EQ (XCAR (arg), Qbar))
32897 return BAR_CURSOR;
32898 else if (EQ (XCAR (arg), Qhbar))
32899 return HBAR_CURSOR;
32900 }
32901
32902
32903
32904
32905 type = HOLLOW_BOX_CURSOR;
32906
32907 return type;
32908 }
32909
32910
32911 void
32912 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
32913 {
32914 int width = 1;
32915 Lisp_Object tem;
32916
32917 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
32918 FRAME_CURSOR_WIDTH (f) = width;
32919
32920
32921
32922 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
32923 if (!NILP (tem))
32924 {
32925 FRAME_BLINK_OFF_CURSOR (f)
32926 = get_specified_cursor_type (XCDR (tem), &width);
32927 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
32928 }
32929 else
32930 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
32931
32932
32933 f->cursor_type_changed = true;
32934 }
32935
32936
32937 #ifdef HAVE_WINDOW_SYSTEM
32938
32939
32940
32941
32942
32943
32944
32945
32946
32947
32948
32949
32950 static enum text_cursor_kinds
32951 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
32952 bool *active_cursor)
32953 {
32954 struct frame *f = XFRAME (w->frame);
32955 struct buffer *b = XBUFFER (w->contents);
32956 int cursor_type = DEFAULT_CURSOR;
32957 Lisp_Object alt_cursor;
32958 bool non_selected = false;
32959
32960 *active_cursor = true;
32961
32962
32963 if (cursor_in_echo_area
32964 && FRAME_HAS_MINIBUF_P (f)
32965 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
32966 {
32967 if (w == XWINDOW (echo_area_window))
32968 {
32969 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
32970 {
32971 *width = FRAME_CURSOR_WIDTH (f);
32972 return FRAME_DESIRED_CURSOR (f);
32973 }
32974 else
32975 return get_specified_cursor_type (BVAR (b, cursor_type), width);
32976 }
32977
32978 *active_cursor = false;
32979 non_selected = true;
32980 }
32981
32982
32983 else if (w != XWINDOW (f->selected_window)
32984 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
32985 {
32986 *active_cursor = false;
32987
32988 if (MINI_WINDOW_P (w) &&
32989 (minibuf_level == 0
32990 || is_minibuffer (0, w->contents)))
32991 return NO_CURSOR;
32992
32993 non_selected = true;
32994 }
32995
32996
32997 if (NILP (BVAR (b, cursor_type)))
32998 return NO_CURSOR;
32999
33000
33001 if (EQ (BVAR (b, cursor_type), Qt))
33002 {
33003 cursor_type = FRAME_DESIRED_CURSOR (f);
33004 *width = FRAME_CURSOR_WIDTH (f);
33005 }
33006 else
33007 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
33008
33009
33010
33011 if (non_selected)
33012 {
33013 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
33014 if (!EQ (Qt, alt_cursor))
33015 return get_specified_cursor_type (alt_cursor, width);
33016
33017 if (cursor_type == FILLED_BOX_CURSOR)
33018 cursor_type = HOLLOW_BOX_CURSOR;
33019 else if (cursor_type == BAR_CURSOR && *width > 1)
33020 --*width;
33021 return cursor_type;
33022 }
33023
33024
33025 if (!w->cursor_off_p)
33026 {
33027 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
33028 return NO_CURSOR;
33029 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
33030 {
33031 if (cursor_type == FILLED_BOX_CURSOR)
33032 {
33033
33034
33035
33036
33037 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
33038 if (img != NULL && IMAGEP (img->spec))
33039 {
33040
33041
33042
33043
33044
33045
33046 if (!img->mask
33047 || (CONSP (BVAR (b, cursor_type))
33048 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33049 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33050 cursor_type = HOLLOW_BOX_CURSOR;
33051 }
33052 }
33053 else if (cursor_type != NO_CURSOR)
33054 {
33055
33056
33057
33058 cursor_type = HOLLOW_BOX_CURSOR;
33059 }
33060 }
33061 return cursor_type;
33062 }
33063
33064
33065
33066
33067 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33068 return get_specified_cursor_type (XCDR (alt_cursor), width);
33069
33070
33071 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33072 {
33073 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33074 return FRAME_BLINK_OFF_CURSOR (f);
33075 }
33076
33077 #if false
33078
33079
33080
33081
33082
33083
33084
33085
33086
33087
33088 if (cursor_type == FILLED_BOX_CURSOR)
33089 return HOLLOW_BOX_CURSOR;
33090
33091 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33092 {
33093 *width = 1;
33094 return cursor_type;
33095 }
33096 #endif
33097
33098 return NO_CURSOR;
33099 }
33100
33101
33102
33103
33104
33105
33106
33107
33108
33109 static void
33110 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33111 int x0, int x1, int y0, int y1)
33112 {
33113 int cx0, cx1, cy0, cy1;
33114 struct glyph_row *row;
33115
33116 if (!w->phys_cursor_on_p)
33117 return;
33118 if (area != TEXT_AREA)
33119 return;
33120
33121 if (w->phys_cursor.vpos < 0
33122 || w->phys_cursor.vpos >= w->current_matrix->nrows
33123 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33124 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33125 return;
33126
33127 if (row->cursor_in_fringe_p)
33128 {
33129 row->cursor_in_fringe_p = false;
33130 draw_fringe_bitmap (w, row, row->reversed_p);
33131 w->phys_cursor_on_p = false;
33132 return;
33133 }
33134
33135 cx0 = w->phys_cursor.x;
33136 cx1 = cx0 + w->phys_cursor_width;
33137 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33138 return;
33139
33140
33141
33142
33143
33144
33145
33146
33147
33148
33149
33150
33151
33152
33153
33154
33155
33156 cy0 = w->phys_cursor.y;
33157 cy1 = cy0 + w->phys_cursor_height;
33158 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33159 return;
33160
33161 w->phys_cursor_on_p = false;
33162 }
33163
33164 #endif
33165
33166
33167
33168
33169
33170
33171 #ifdef HAVE_WINDOW_SYSTEM
33172
33173
33174
33175
33176
33177 void
33178 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33179 enum glyph_row_area area, int overlaps)
33180 {
33181 int i, x;
33182
33183 block_input ();
33184
33185 x = 0;
33186 for (i = 0; i < row->used[area];)
33187 {
33188 if (row->glyphs[area][i].overlaps_vertically_p)
33189 {
33190 int start = i, start_x = x;
33191
33192 do
33193 {
33194 x += row->glyphs[area][i].pixel_width;
33195 ++i;
33196 }
33197 while (i < row->used[area]
33198 && row->glyphs[area][i].overlaps_vertically_p);
33199
33200 draw_glyphs (w, start_x, row, area,
33201 start, i,
33202 DRAW_NORMAL_TEXT, overlaps);
33203 }
33204 else
33205 {
33206 x += row->glyphs[area][i].pixel_width;
33207 ++i;
33208 }
33209 }
33210
33211 unblock_input ();
33212 }
33213
33214
33215
33216
33217
33218
33219 void
33220 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33221 enum draw_glyphs_face hl)
33222 {
33223
33224
33225
33226 if ((row->reversed_p
33227 ? (w->phys_cursor.hpos >= 0)
33228 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33229 {
33230 bool on_p = w->phys_cursor_on_p;
33231 int x1;
33232 int hpos = w->phys_cursor.hpos;
33233
33234
33235
33236
33237 if (!row->reversed_p && hpos < 0)
33238 hpos = 0;
33239 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33240 hpos = row->used[TEXT_AREA] - 1;
33241
33242 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33243 hl, 0);
33244 w->phys_cursor_on_p = on_p;
33245
33246 if (hl == DRAW_CURSOR)
33247 w->phys_cursor_width = x1 - w->phys_cursor.x;
33248
33249
33250
33251 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33252 {
33253 w->phys_cursor_width = x1 - w->phys_cursor.x;
33254
33255 if (row > w->current_matrix->rows
33256 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33257 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33258 OVERLAPS_ERASED_CURSOR);
33259
33260 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33261 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33262 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33263 OVERLAPS_ERASED_CURSOR);
33264 }
33265 }
33266 }
33267
33268
33269
33270
33271 void
33272 erase_phys_cursor (struct window *w)
33273 {
33274 struct frame *f = XFRAME (w->frame);
33275 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33276 int hpos = w->phys_cursor.hpos;
33277 int vpos = w->phys_cursor.vpos;
33278 bool mouse_face_here_p = false;
33279 struct glyph_matrix *active_glyphs = w->current_matrix;
33280 struct glyph_row *cursor_row;
33281 struct glyph *cursor_glyph;
33282 enum draw_glyphs_face hl;
33283
33284
33285
33286 if (w->phys_cursor_type == NO_CURSOR)
33287 goto mark_cursor_off;
33288
33289
33290
33291 if (vpos >= active_glyphs->nrows)
33292 goto mark_cursor_off;
33293
33294
33295
33296 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33297 if (!cursor_row->enabled_p)
33298 goto mark_cursor_off;
33299
33300
33301
33302 cursor_row->visible_height = min (cursor_row->visible_height,
33303 window_text_bottom_y (w) - cursor_row->y);
33304
33305
33306
33307
33308 if (cursor_row->visible_height <= 0)
33309 goto mark_cursor_off;
33310
33311
33312 if (cursor_row->cursor_in_fringe_p)
33313 {
33314 cursor_row->cursor_in_fringe_p = false;
33315 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33316 goto mark_cursor_off;
33317 }
33318
33319
33320
33321
33322
33323
33324 if ((cursor_row->reversed_p
33325 ? (w->phys_cursor.hpos < 0)
33326 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33327 goto mark_cursor_off;
33328
33329
33330
33331
33332 if (!cursor_row->reversed_p && hpos < 0)
33333 hpos = 0;
33334 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33335 hpos = cursor_row->used[TEXT_AREA] - 1;
33336
33337
33338
33339 if (! NILP (hlinfo->mouse_face_window)
33340 && coords_in_mouse_face_p (w, hpos, vpos)
33341
33342
33343
33344 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33345 mouse_face_here_p = true;
33346
33347 #ifdef HAVE_WINDOW_SYSTEM
33348
33349
33350
33351
33352 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33353 {
33354 w->phys_cursor_on_p = false;
33355 w->phys_cursor_type = NO_CURSOR;
33356 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33357 return;
33358 }
33359 #endif
33360
33361
33362 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33363 {
33364 int x, y;
33365 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33366 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33367 int width;
33368
33369 cursor_glyph = get_phys_cursor_glyph (w);
33370 if (cursor_glyph == NULL)
33371 goto mark_cursor_off;
33372
33373 width = cursor_glyph->pixel_width;
33374 x = w->phys_cursor.x;
33375 if (x < 0)
33376 {
33377 width += x;
33378 x = 0;
33379 }
33380 width = min (width, window_box_width (w, TEXT_AREA) - x);
33381 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33382 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33383
33384 if (width > 0)
33385 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33386 }
33387
33388
33389 if (mouse_face_here_p)
33390 hl = DRAW_MOUSE_FACE;
33391 else
33392 hl = DRAW_NORMAL_TEXT;
33393 draw_phys_cursor_glyph (w, cursor_row, hl);
33394
33395 mark_cursor_off:
33396 w->phys_cursor_on_p = false;
33397 w->phys_cursor_type = NO_CURSOR;
33398 }
33399
33400
33401
33402
33403
33404
33405 void
33406 display_and_set_cursor (struct window *w, bool on,
33407 int hpos, int vpos, int x, int y)
33408 {
33409 struct frame *f = XFRAME (w->frame);
33410 int new_cursor_type;
33411 int new_cursor_width UNINIT;
33412 bool active_cursor;
33413 struct glyph_row *glyph_row;
33414 struct glyph *glyph;
33415
33416
33417
33418
33419
33420 if (! FRAME_VISIBLE_P (f)
33421 || vpos >= w->current_matrix->nrows
33422 || hpos >= w->current_matrix->matrix_w)
33423 return;
33424
33425
33426 if (!on && !w->phys_cursor_on_p)
33427 return;
33428
33429 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33430
33431
33432 if (!glyph_row->enabled_p)
33433 {
33434 w->phys_cursor_on_p = false;
33435 return;
33436 }
33437
33438
33439
33440
33441
33442
33443
33444
33445
33446 if (FRAME_GARBAGED_P (f))
33447 {
33448 if (on)
33449 {
33450 w->phys_cursor.x = x;
33451 w->phys_cursor.y = glyph_row->y;
33452 w->phys_cursor.hpos = hpos;
33453 w->phys_cursor.vpos = vpos;
33454 }
33455 return;
33456 }
33457
33458 glyph = NULL;
33459 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33460 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33461
33462 eassert (input_blocked_p ());
33463
33464
33465 new_cursor_type = get_window_cursor_type (w, glyph,
33466 &new_cursor_width, &active_cursor);
33467
33468
33469
33470
33471 if (w->phys_cursor_on_p
33472 && (!on
33473 || w->phys_cursor.x != x
33474 || w->phys_cursor.y != y
33475
33476
33477
33478 || hpos < 0
33479 || new_cursor_type != w->phys_cursor_type
33480 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33481 && new_cursor_width != w->phys_cursor_width)))
33482 erase_phys_cursor (w);
33483
33484
33485
33486
33487
33488
33489 if (on)
33490 {
33491 w->phys_cursor_ascent = glyph_row->ascent;
33492 w->phys_cursor_height = glyph_row->height;
33493
33494
33495
33496 w->phys_cursor.x = x;
33497 w->phys_cursor.y = glyph_row->y;
33498 w->phys_cursor.hpos = hpos;
33499 w->phys_cursor.vpos = vpos;
33500 }
33501
33502 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33503 new_cursor_type, new_cursor_width,
33504 on, active_cursor);
33505 }
33506
33507
33508
33509
33510
33511 static void
33512 update_window_cursor (struct window *w, bool on)
33513 {
33514
33515
33516 if (w->current_matrix)
33517 {
33518 int hpos = w->phys_cursor.hpos;
33519 int vpos = w->phys_cursor.vpos;
33520 struct glyph_row *row;
33521
33522 if (vpos >= w->current_matrix->nrows
33523 || hpos >= w->current_matrix->matrix_w)
33524 return;
33525
33526 row = MATRIX_ROW (w->current_matrix, vpos);
33527
33528
33529
33530
33531 if (!row->reversed_p && hpos < 0)
33532 hpos = 0;
33533 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33534 hpos = row->used[TEXT_AREA] - 1;
33535
33536 block_input ();
33537 display_and_set_cursor (w, on, hpos, vpos,
33538 w->phys_cursor.x, w->phys_cursor.y);
33539 unblock_input ();
33540 }
33541 }
33542
33543
33544
33545
33546
33547 static void
33548 update_cursor_in_window_tree (struct window *w, bool on_p)
33549 {
33550 while (w)
33551 {
33552 if (WINDOWP (w->contents))
33553 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33554 else
33555 update_window_cursor (w, on_p);
33556
33557 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33558 }
33559 }
33560
33561
33562
33563
33564
33565
33566 void
33567 gui_update_cursor (struct frame *f, bool on_p)
33568 {
33569 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33570 }
33571
33572
33573
33574
33575
33576
33577
33578 void
33579 gui_clear_cursor (struct window *w)
33580 {
33581 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33582 update_window_cursor (w, false);
33583 }
33584
33585 #endif
33586
33587
33588
33589 static void
33590 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33591 int start_hpos, int end_hpos,
33592 enum draw_glyphs_face draw)
33593 {
33594 #ifdef HAVE_WINDOW_SYSTEM
33595 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33596 {
33597 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33598 return;
33599 }
33600 #endif
33601
33602 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33603 }
33604
33605
33606
33607 static void
33608 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33609 {
33610
33611
33612 if (!WINDOWP (hlinfo->mouse_face_window))
33613 return;
33614
33615 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33616 struct frame *f = XFRAME (WINDOW_FRAME (w));
33617
33618
33619 if (f != hlinfo->mouse_face_mouse_frame)
33620 return;
33621
33622 if (
33623
33624 w->current_matrix != NULL
33625
33626 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33627
33628
33629 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33630 {
33631 bool phys_cursor_on_p = w->phys_cursor_on_p;
33632 #ifdef HAVE_WINDOW_SYSTEM
33633 int mouse_off = 0;
33634 #endif
33635 struct glyph_row *row, *first, *last;
33636
33637 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33638 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33639
33640 for (row = first; row <= last && row->enabled_p; ++row)
33641 {
33642 int start_hpos, end_hpos, start_x;
33643
33644
33645 if (row == first)
33646 {
33647
33648
33649
33650
33651 if (!row->reversed_p)
33652 {
33653 start_hpos = hlinfo->mouse_face_beg_col;
33654 start_x = hlinfo->mouse_face_beg_x;
33655 }
33656 else if (row == last)
33657 {
33658 start_hpos = hlinfo->mouse_face_end_col;
33659 start_x = hlinfo->mouse_face_end_x;
33660 }
33661 else
33662 {
33663 start_hpos = 0;
33664 start_x = 0;
33665 }
33666 }
33667 else if (row->reversed_p && row == last)
33668 {
33669 start_hpos = hlinfo->mouse_face_end_col;
33670 start_x = hlinfo->mouse_face_end_x;
33671 }
33672 else
33673 {
33674 start_hpos = 0;
33675 start_x = 0;
33676 }
33677
33678 if (row == last)
33679 {
33680 if (!row->reversed_p)
33681 end_hpos = hlinfo->mouse_face_end_col;
33682 else if (row == first)
33683 end_hpos = hlinfo->mouse_face_beg_col;
33684 else
33685 {
33686 end_hpos = row->used[TEXT_AREA];
33687 if (draw == DRAW_NORMAL_TEXT)
33688 row->fill_line_p = true;
33689 }
33690 }
33691 else if (row->reversed_p && row == first)
33692 end_hpos = hlinfo->mouse_face_beg_col;
33693 else
33694 {
33695 end_hpos = row->used[TEXT_AREA];
33696 if (draw == DRAW_NORMAL_TEXT)
33697 row->fill_line_p = true;
33698 }
33699
33700 if (end_hpos > start_hpos)
33701 {
33702 draw_row_with_mouse_face (w, start_x, row,
33703 start_hpos, end_hpos, draw);
33704
33705 row->mouse_face_p
33706 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
33707 }
33708 #ifdef HAVE_WINDOW_SYSTEM
33709
33710 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
33711
33712
33713 && !w->pseudo_window_p
33714 && draw == DRAW_MOUSE_FACE)
33715 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
33716 #endif
33717 }
33718
33719
33720
33721 if (FRAME_WINDOW_P (f)
33722 && phys_cursor_on_p && !w->phys_cursor_on_p)
33723 {
33724 #ifdef HAVE_WINDOW_SYSTEM
33725 int hpos = w->phys_cursor.hpos;
33726 int old_phys_cursor_x = w->phys_cursor.x;
33727
33728
33729
33730
33731 if (!row->reversed_p && hpos < 0)
33732 hpos = 0;
33733 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33734 hpos = row->used[TEXT_AREA] - 1;
33735
33736 block_input ();
33737 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
33738 w->phys_cursor.x + mouse_off,
33739 w->phys_cursor.y);
33740
33741
33742 w->phys_cursor.x = old_phys_cursor_x;
33743 unblock_input ();
33744 #endif
33745 }
33746 }
33747
33748 #ifdef HAVE_WINDOW_SYSTEM
33749
33750 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
33751 {
33752 if (draw == DRAW_NORMAL_TEXT
33753 #ifndef HAVE_EXT_TOOL_BAR
33754 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
33755 #endif
33756 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
33757 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
33758 else
33759 if (draw == DRAW_MOUSE_FACE)
33760 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
33761 else
33762 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
33763 }
33764 #endif
33765 }
33766
33767
33768
33769
33770
33771
33772 bool
33773 clear_mouse_face (Mouse_HLInfo *hlinfo)
33774 {
33775 bool cleared
33776 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
33777 if (cleared)
33778 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
33779 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
33780 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
33781 hlinfo->mouse_face_window = Qnil;
33782 hlinfo->mouse_face_overlay = Qnil;
33783 return cleared;
33784 }
33785
33786
33787
33788 static bool
33789 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
33790 {
33791 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
33792
33793
33794 if (!(WINDOWP (hlinfo->mouse_face_window)
33795 && XWINDOW (hlinfo->mouse_face_window) == w))
33796 return false;
33797 if (vpos < hlinfo->mouse_face_beg_row
33798 || vpos > hlinfo->mouse_face_end_row)
33799 return false;
33800 if (vpos > hlinfo->mouse_face_beg_row
33801 && vpos < hlinfo->mouse_face_end_row)
33802 return true;
33803
33804 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
33805 {
33806 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
33807 {
33808 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
33809 return true;
33810 }
33811 else if ((vpos == hlinfo->mouse_face_beg_row
33812 && hpos >= hlinfo->mouse_face_beg_col)
33813 || (vpos == hlinfo->mouse_face_end_row
33814 && hpos < hlinfo->mouse_face_end_col))
33815 return true;
33816 }
33817 else
33818 {
33819 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
33820 {
33821 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
33822 return true;
33823 }
33824 else if ((vpos == hlinfo->mouse_face_beg_row
33825 && hpos <= hlinfo->mouse_face_beg_col)
33826 || (vpos == hlinfo->mouse_face_end_row
33827 && hpos > hlinfo->mouse_face_end_col))
33828 return true;
33829 }
33830 return false;
33831 }
33832
33833
33834
33835
33836
33837 bool
33838 cursor_in_mouse_face_p (struct window *w)
33839 {
33840 int vpos = w->phys_cursor.vpos;
33841
33842
33843
33844 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
33845 return false;
33846
33847 int hpos = w->phys_cursor.hpos;
33848 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
33849
33850
33851
33852
33853 if (!row->reversed_p && hpos < 0)
33854 hpos = 0;
33855 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33856 hpos = row->used[TEXT_AREA] - 1;
33857
33858 return coords_in_mouse_face_p (w, hpos, vpos);
33859 }
33860
33861
33862
33863
33864
33865
33866
33867
33868
33869 static void
33870 rows_from_pos_range (struct window *w,
33871 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
33872 Lisp_Object disp_string,
33873 struct glyph_row **start, struct glyph_row **end)
33874 {
33875 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
33876 int last_y = window_text_bottom_y (w);
33877 struct glyph_row *row;
33878
33879 *start = NULL;
33880 *end = NULL;
33881
33882 while (!first->enabled_p
33883 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
33884 first++;
33885
33886
33887 for (row = first;
33888 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
33889 row++)
33890 {
33891
33892
33893
33894 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
33895 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
33896
33897
33898
33899
33900 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
33901 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
33902 && !row->ends_at_zv_p
33903 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
33904 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
33905 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
33906 && !row->ends_at_zv_p
33907 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
33908 {
33909
33910
33911
33912
33913
33914
33915
33916
33917
33918
33919 struct glyph *g = row->glyphs[TEXT_AREA];
33920 struct glyph *e = g + row->used[TEXT_AREA];
33921
33922 while (g < e)
33923 {
33924 if (((BUFFERP (g->object) || NILP (g->object))
33925 && start_charpos <= g->charpos && g->charpos < end_charpos)
33926
33927
33928 || EQ (g->object, disp_string))
33929 *start = row;
33930 g++;
33931 }
33932 if (*start)
33933 break;
33934 }
33935 }
33936
33937
33938 if (!*start
33939
33940
33941 && !(row->enabled_p
33942 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
33943 row = first;
33944 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
33945 {
33946 struct glyph_row *next = row + 1;
33947 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
33948
33949 if (!next->enabled_p
33950 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
33951
33952
33953
33954 || (start_charpos < next_start
33955 && end_charpos < next_start)
33956 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
33957 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
33958 && !next->ends_at_zv_p
33959 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
33960 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
33961 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
33962 && !next->ends_at_zv_p
33963 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
33964 {
33965 *end = row;
33966 break;
33967 }
33968 else
33969 {
33970
33971
33972
33973 struct glyph *g = next->glyphs[TEXT_AREA];
33974 struct glyph *s = g;
33975 struct glyph *e = g + next->used[TEXT_AREA];
33976
33977 while (g < e)
33978 {
33979 if (((BUFFERP (g->object) || NILP (g->object))
33980 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
33981
33982
33983
33984
33985
33986 || (((!next->reversed_p && g == s)
33987 || (next->reversed_p && g == e - 1))
33988 && (g->charpos == end_charpos
33989
33990
33991 || (g->charpos == -1
33992 && !row->ends_at_zv_p
33993 && next_start == end_charpos)))))
33994
33995
33996 || EQ (g->object, disp_string))
33997 break;
33998 g++;
33999 }
34000 if (g == e)
34001 {
34002 *end = row;
34003 break;
34004 }
34005
34006
34007 else if (next->ends_at_zv_p)
34008 {
34009 *end = next;
34010 break;
34011 }
34012 }
34013 }
34014 }
34015
34016
34017
34018
34019
34020
34021
34022
34023
34024
34025 static void
34026 mouse_face_from_buffer_pos (Lisp_Object window,
34027 Mouse_HLInfo *hlinfo,
34028 ptrdiff_t mouse_charpos,
34029 ptrdiff_t start_charpos,
34030 ptrdiff_t end_charpos,
34031 Lisp_Object before_string,
34032 Lisp_Object after_string,
34033 Lisp_Object disp_string)
34034 {
34035 struct window *w = XWINDOW (window);
34036 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34037 struct glyph_row *r1, *r2;
34038 struct glyph *glyph, *end;
34039 ptrdiff_t ignore, pos;
34040 int x;
34041
34042 eassert (NILP (disp_string) || STRINGP (disp_string));
34043 eassert (NILP (before_string) || STRINGP (before_string));
34044 eassert (NILP (after_string) || STRINGP (after_string));
34045
34046
34047 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
34048 if (r1 == NULL)
34049 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34050
34051
34052 if (!NILP (before_string) || !NILP (disp_string))
34053 {
34054 struct glyph_row *prev;
34055 while ((prev = r1 - 1, prev >= first)
34056 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34057 && prev->used[TEXT_AREA] > 0)
34058 {
34059 struct glyph *beg = prev->glyphs[TEXT_AREA];
34060 glyph = beg + prev->used[TEXT_AREA];
34061 while (--glyph >= beg && NILP (glyph->object));
34062 if (glyph < beg
34063 || !(EQ (glyph->object, before_string)
34064 || EQ (glyph->object, disp_string)))
34065 break;
34066 r1 = prev;
34067 }
34068 }
34069 if (r2 == NULL)
34070 {
34071 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34072 hlinfo->mouse_face_past_end = true;
34073 }
34074 else if (!NILP (after_string))
34075 {
34076
34077 struct glyph_row *next;
34078 struct glyph_row *last
34079 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34080
34081 for (next = r2 + 1;
34082 next <= last
34083 && next->used[TEXT_AREA] > 0
34084 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34085 ++next)
34086 r2 = next;
34087 }
34088
34089
34090
34091
34092
34093 if (r1->y > r2->y)
34094 {
34095 struct glyph_row *tem = r2;
34096
34097 r2 = r1;
34098 r1 = tem;
34099 }
34100
34101 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34102 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34103
34104
34105
34106
34107
34108
34109
34110
34111
34112
34113
34114 if (!r1->reversed_p)
34115 {
34116
34117
34118 glyph = r1->glyphs[TEXT_AREA];
34119 end = glyph + r1->used[TEXT_AREA];
34120 x = r1->x;
34121
34122
34123 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34124 for (; glyph < end
34125 && NILP (glyph->object)
34126 && glyph->charpos < 0;
34127 ++glyph)
34128 x += glyph->pixel_width;
34129
34130
34131
34132
34133 for (; glyph < end
34134 && !NILP (glyph->object)
34135 && !EQ (glyph->object, disp_string)
34136 && !(BUFFERP (glyph->object)
34137 && (glyph->charpos >= start_charpos
34138 && glyph->charpos < end_charpos));
34139 ++glyph)
34140 {
34141
34142
34143
34144 if (EQ (glyph->object, before_string))
34145 {
34146 pos = string_buffer_position (before_string,
34147 start_charpos);
34148
34149
34150 if (!pos || (pos >= start_charpos && pos < end_charpos))
34151 break;
34152 }
34153 else if (EQ (glyph->object, after_string))
34154 {
34155 pos = string_buffer_position (after_string, end_charpos);
34156 if (!pos || (pos >= start_charpos && pos < end_charpos))
34157 break;
34158 }
34159 x += glyph->pixel_width;
34160 }
34161 hlinfo->mouse_face_beg_x = x;
34162 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34163 }
34164 else
34165 {
34166
34167
34168 struct glyph *g;
34169
34170 end = r1->glyphs[TEXT_AREA] - 1;
34171 glyph = end + r1->used[TEXT_AREA];
34172
34173
34174 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34175 for (; glyph > end
34176 && NILP (glyph->object)
34177 && glyph->charpos < 0;
34178 --glyph)
34179 ;
34180
34181
34182
34183
34184 for (; glyph > end
34185 && !NILP (glyph->object)
34186 && !EQ (glyph->object, disp_string)
34187 && !(BUFFERP (glyph->object)
34188 && (glyph->charpos >= start_charpos
34189 && glyph->charpos < end_charpos));
34190 --glyph)
34191 {
34192
34193
34194
34195 if (EQ (glyph->object, before_string))
34196 {
34197 pos = string_buffer_position (before_string, start_charpos);
34198
34199
34200 if (!pos || (pos >= start_charpos && pos < end_charpos))
34201 break;
34202 }
34203 else if (EQ (glyph->object, after_string))
34204 {
34205 pos = string_buffer_position (after_string, end_charpos);
34206 if (!pos || (pos >= start_charpos && pos < end_charpos))
34207 break;
34208 }
34209 }
34210
34211 glyph++;
34212 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34213 x += g->pixel_width;
34214 hlinfo->mouse_face_beg_x = x;
34215 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34216 }
34217
34218
34219
34220
34221 if (r2 != r1)
34222 {
34223 if (!r2->reversed_p)
34224 {
34225 glyph = r2->glyphs[TEXT_AREA];
34226 end = glyph + r2->used[TEXT_AREA];
34227 x = r2->x;
34228 }
34229 else
34230 {
34231 end = r2->glyphs[TEXT_AREA] - 1;
34232 glyph = end + r2->used[TEXT_AREA];
34233 }
34234 }
34235
34236 if (!r2->reversed_p)
34237 {
34238
34239
34240
34241 while (end > glyph
34242 && NILP ((end - 1)->object))
34243 --end;
34244
34245
34246
34247
34248 for (--end;
34249 end > glyph
34250 && !NILP (end->object)
34251 && !EQ (end->object, disp_string)
34252 && !(BUFFERP (end->object)
34253 && (end->charpos >= start_charpos
34254 && end->charpos < end_charpos));
34255 --end)
34256 {
34257
34258
34259
34260 if (EQ (end->object, before_string))
34261 {
34262 pos = string_buffer_position (before_string, start_charpos);
34263 if (!pos || (pos >= start_charpos && pos < end_charpos))
34264 break;
34265 }
34266 else if (EQ (end->object, after_string))
34267 {
34268 pos = string_buffer_position (after_string, end_charpos);
34269 if (!pos || (pos >= start_charpos && pos < end_charpos))
34270 break;
34271 }
34272 }
34273
34274 for (; glyph <= end; ++glyph)
34275 x += glyph->pixel_width;
34276
34277 hlinfo->mouse_face_end_x = x;
34278 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34279 }
34280 else
34281 {
34282
34283
34284
34285 x = r2->x;
34286 end++;
34287 while (end < glyph
34288 && NILP (end->object))
34289 {
34290 x += end->pixel_width;
34291 ++end;
34292 }
34293
34294
34295
34296
34297 for ( ;
34298 end < glyph
34299 && !NILP (end->object)
34300 && !EQ (end->object, disp_string)
34301 && !(BUFFERP (end->object)
34302 && (end->charpos >= start_charpos
34303 && end->charpos < end_charpos));
34304 ++end)
34305 {
34306
34307
34308
34309 if (EQ (end->object, before_string))
34310 {
34311 pos = string_buffer_position (before_string, start_charpos);
34312 if (!pos || (pos >= start_charpos && pos < end_charpos))
34313 break;
34314 }
34315 else if (EQ (end->object, after_string))
34316 {
34317 pos = string_buffer_position (after_string, end_charpos);
34318 if (!pos || (pos >= start_charpos && pos < end_charpos))
34319 break;
34320 }
34321 x += end->pixel_width;
34322 }
34323
34324
34325
34326
34327
34328 if (end == glyph
34329 && BUFFERP (end->object)
34330 && (end->charpos < start_charpos
34331 || end->charpos >= end_charpos))
34332 {
34333 x += end->pixel_width;
34334 ++end;
34335 }
34336 hlinfo->mouse_face_end_x = x;
34337 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34338 }
34339
34340 hlinfo->mouse_face_window = window;
34341 hlinfo->mouse_face_face_id
34342 = face_at_buffer_position (w, mouse_charpos, &ignore,
34343 mouse_charpos + 1,
34344 !hlinfo->mouse_face_hidden, -1, 0);
34345 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34346 }
34347
34348
34349
34350
34351
34352 #if false
34353
34354
34355
34356
34357
34358
34359
34360
34361
34362
34363
34364
34365
34366
34367
34368
34369 static bool
34370 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34371 int *hpos, int *vpos, int *x, int *y, bool right_p)
34372 {
34373 int yb = window_text_bottom_y (w);
34374 struct glyph_row *r;
34375 struct glyph *best_glyph = NULL;
34376 struct glyph_row *best_row = NULL;
34377 int best_x = 0;
34378
34379 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34380 r->enabled_p && r->y < yb;
34381 ++r)
34382 {
34383 struct glyph *g = r->glyphs[TEXT_AREA];
34384 struct glyph *e = g + r->used[TEXT_AREA];
34385 int gx;
34386
34387 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34388 if (EQ (g->object, object))
34389 {
34390 if (g->charpos == pos)
34391 {
34392 best_glyph = g;
34393 best_x = gx;
34394 best_row = r;
34395 goto found;
34396 }
34397 else if (best_glyph == NULL
34398 || ((eabs (g->charpos - pos)
34399 < eabs (best_glyph->charpos - pos))
34400 && (right_p
34401 ? g->charpos < pos
34402 : g->charpos > pos)))
34403 {
34404 best_glyph = g;
34405 best_x = gx;
34406 best_row = r;
34407 }
34408 }
34409 }
34410
34411 found:
34412
34413 if (best_glyph)
34414 {
34415 *x = best_x;
34416 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34417
34418 if (right_p)
34419 {
34420 *x += best_glyph->pixel_width;
34421 ++*hpos;
34422 }
34423
34424 *y = best_row->y;
34425 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34426 }
34427
34428 return best_glyph != NULL;
34429 }
34430 #endif
34431
34432
34433
34434
34435
34436
34437 static void
34438 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34439 Lisp_Object object,
34440 ptrdiff_t startpos, ptrdiff_t endpos)
34441 {
34442 int yb = window_text_bottom_y (w);
34443 struct glyph_row *r;
34444 struct glyph *g, *e;
34445 int gx;
34446 bool found = false;
34447
34448
34449
34450
34451 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34452 r->enabled_p && r->y < yb;
34453 ++r)
34454 {
34455 if (!r->reversed_p)
34456 {
34457 g = r->glyphs[TEXT_AREA];
34458 e = g + r->used[TEXT_AREA];
34459 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34460 if (EQ (g->object, object)
34461 && startpos <= g->charpos && g->charpos < endpos)
34462 {
34463 hlinfo->mouse_face_beg_row
34464 = MATRIX_ROW_VPOS (r, w->current_matrix);
34465 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34466 hlinfo->mouse_face_beg_x = gx;
34467 found = true;
34468 break;
34469 }
34470 }
34471 else
34472 {
34473 struct glyph *g1;
34474
34475 e = r->glyphs[TEXT_AREA];
34476 g = e + r->used[TEXT_AREA];
34477 for ( ; g > e; --g)
34478 if (EQ ((g-1)->object, object)
34479 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34480 {
34481 hlinfo->mouse_face_beg_row
34482 = MATRIX_ROW_VPOS (r, w->current_matrix);
34483 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34484 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34485 gx += g1->pixel_width;
34486 hlinfo->mouse_face_beg_x = gx;
34487 found = true;
34488 break;
34489 }
34490 }
34491 if (found)
34492 break;
34493 }
34494
34495 if (!found)
34496 return;
34497
34498
34499
34500 for (++r; r->enabled_p && r->y < yb; ++r)
34501 {
34502 g = r->glyphs[TEXT_AREA];
34503 e = g + r->used[TEXT_AREA];
34504 found = false;
34505 for ( ; g < e; ++g)
34506 if (EQ (g->object, object)
34507 && startpos <= g->charpos && g->charpos < endpos)
34508 {
34509 found = true;
34510 break;
34511 }
34512 if (!found)
34513 break;
34514 }
34515
34516
34517 r--;
34518
34519
34520 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34521
34522
34523
34524 if (!r->reversed_p)
34525 {
34526 g = r->glyphs[TEXT_AREA];
34527 e = g + r->used[TEXT_AREA];
34528 for ( ; e > g; --e)
34529 if (EQ ((e-1)->object, object)
34530 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34531 break;
34532 hlinfo->mouse_face_end_col = e - g;
34533
34534 for (gx = r->x; g < e; ++g)
34535 gx += g->pixel_width;
34536 hlinfo->mouse_face_end_x = gx;
34537 }
34538 else
34539 {
34540 e = r->glyphs[TEXT_AREA];
34541 g = e + r->used[TEXT_AREA];
34542 for (gx = r->x ; e < g; ++e)
34543 {
34544 if (EQ (e->object, object)
34545 && startpos <= e->charpos && e->charpos < endpos)
34546 break;
34547 gx += e->pixel_width;
34548 }
34549 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34550 hlinfo->mouse_face_end_x = gx;
34551 }
34552 }
34553
34554 #ifdef HAVE_WINDOW_SYSTEM
34555
34556
34557
34558 static bool
34559 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34560 {
34561 if (!CONSP (hot_spot))
34562 return false;
34563
34564 if (EQ (XCAR (hot_spot), Qrect))
34565 {
34566
34567 Lisp_Object rect = XCDR (hot_spot);
34568 Lisp_Object tem;
34569 if (!CONSP (rect))
34570 return false;
34571 if (!CONSP (XCAR (rect)))
34572 return false;
34573 if (!CONSP (XCDR (rect)))
34574 return false;
34575 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34576 return false;
34577 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34578 return false;
34579 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34580 return false;
34581 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34582 return false;
34583 return true;
34584 }
34585 else if (EQ (XCAR (hot_spot), Qcircle))
34586 {
34587
34588 Lisp_Object circ = XCDR (hot_spot);
34589 Lisp_Object lr, lx0, ly0;
34590 if (CONSP (circ)
34591 && CONSP (XCAR (circ))
34592 && (lr = XCDR (circ), NUMBERP (lr))
34593 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34594 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34595 {
34596 double r = XFLOATINT (lr);
34597 double dx = XFIXNUM (lx0) - x;
34598 double dy = XFIXNUM (ly0) - y;
34599 return (dx * dx + dy * dy <= r * r);
34600 }
34601 }
34602 else if (EQ (XCAR (hot_spot), Qpoly))
34603 {
34604
34605 if (VECTORP (XCDR (hot_spot)))
34606 {
34607 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34608 Lisp_Object *poly = v->contents;
34609 ptrdiff_t n = v->header.size;
34610 ptrdiff_t i;
34611 bool inside = false;
34612 Lisp_Object lx, ly;
34613 int x0, y0;
34614
34615
34616 if (n < 6 || n & 1)
34617 return false;
34618
34619
34620
34621
34622
34623 if ((lx = poly[n-2], !FIXNUMP (lx))
34624 || (ly = poly[n-1], !FIXNUMP (lx)))
34625 return false;
34626 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34627 for (i = 0; i < n; i += 2)
34628 {
34629 int x1 = x0, y1 = y0;
34630 if ((lx = poly[i], !FIXNUMP (lx))
34631 || (ly = poly[i+1], !FIXNUMP (ly)))
34632 return false;
34633 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34634
34635
34636 if (x0 >= x)
34637 {
34638 if (x1 >= x)
34639 continue;
34640 }
34641 else if (x1 < x)
34642 continue;
34643 if (y > y0 && y > y1)
34644 continue;
34645 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34646 inside = !inside;
34647 }
34648 return inside;
34649 }
34650 }
34651 return false;
34652 }
34653
34654 Lisp_Object
34655 find_hot_spot (Lisp_Object map, int x, int y)
34656 {
34657 while (CONSP (map))
34658 {
34659 if (CONSP (XCAR (map))
34660 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34661 return XCAR (map);
34662 map = XCDR (map);
34663 }
34664
34665 return Qnil;
34666 }
34667
34668 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34669 3, 3, 0,
34670 doc:
34671
34672
34673
34674
34675
34676
34677
34678
34679 )
34680 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
34681 {
34682 if (NILP (map))
34683 return Qnil;
34684
34685 CHECK_FIXNUM (x);
34686 CHECK_FIXNUM (y);
34687
34688 return find_hot_spot (map,
34689 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
34690 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
34691 }
34692 #endif
34693
34694
34695
34696 static void
34697 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
34698 {
34699 #ifdef HAVE_WINDOW_SYSTEM
34700 if (!FRAME_WINDOW_P (f))
34701 return;
34702
34703
34704 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
34705 || EQ (track_mouse, Qdrag_source))
34706 return;
34707
34708 if (!NILP (pointer))
34709 {
34710 if (EQ (pointer, Qarrow))
34711 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34712 else if (EQ (pointer, Qhand))
34713 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34714 else if (EQ (pointer, Qtext))
34715 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
34716 else if (EQ (pointer, intern ("hdrag")))
34717 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
34718 else if (EQ (pointer, intern ("nhdrag")))
34719 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34720 # ifdef HAVE_X_WINDOWS
34721 else if (EQ (pointer, intern ("vdrag")))
34722 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
34723 # endif
34724 else if (EQ (pointer, intern ("hourglass")))
34725 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
34726 else if (EQ (pointer, Qmodeline))
34727 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
34728 else
34729 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34730 }
34731
34732 if (cursor != No_Cursor)
34733 FRAME_RIF (f)->define_frame_cursor (f, cursor);
34734 #endif
34735 }
34736
34737
34738
34739
34740
34741
34742
34743 static void
34744 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
34745 enum window_part area)
34746 {
34747 struct window *w = XWINDOW (window);
34748 struct frame *f = XFRAME (w->frame);
34749 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
34750 Emacs_Cursor cursor = No_Cursor;
34751 Lisp_Object pointer = Qnil;
34752 int dx, dy, width, height;
34753 ptrdiff_t charpos;
34754 Lisp_Object string, object = Qnil;
34755 Lisp_Object pos UNINIT;
34756 Lisp_Object mouse_face;
34757 int original_x_pixel = x;
34758 struct glyph * glyph = NULL, * row_start_glyph = NULL;
34759 struct glyph_row *row UNINIT;
34760
34761 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
34762 {
34763 int x0;
34764 struct glyph *end;
34765
34766
34767
34768 string = mode_line_string (w, area, &x, &y, &charpos,
34769 &object, &dx, &dy, &width, &height);
34770
34771 row = (area == ON_MODE_LINE
34772 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
34773 : (area == ON_TAB_LINE
34774 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
34775 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
34776
34777
34778 if (row->mode_line_p && row->enabled_p)
34779 {
34780 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
34781 end = glyph + row->used[TEXT_AREA];
34782
34783 for (x0 = original_x_pixel;
34784 glyph < end && x0 >= glyph->pixel_width;
34785 ++glyph)
34786 x0 -= glyph->pixel_width;
34787
34788 if (glyph >= end)
34789 glyph = NULL;
34790 }
34791 }
34792 else
34793 {
34794 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
34795
34796
34797 string = marginal_area_string (w, area, &x, &y, &charpos,
34798 &object, &dx, &dy, &width, &height);
34799 }
34800
34801 Lisp_Object help = Qnil;
34802
34803 #ifdef HAVE_WINDOW_SYSTEM
34804 if (IMAGEP (object))
34805 {
34806 Lisp_Object image_map, hotspot;
34807 if ((image_map = plist_get (XCDR (object), QCmap),
34808 !NILP (image_map))
34809 && (hotspot = find_hot_spot (image_map, dx, dy),
34810 CONSP (hotspot))
34811 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
34812 {
34813 Lisp_Object plist;
34814
34815
34816
34817
34818 hotspot = XCDR (hotspot);
34819 if (CONSP (hotspot)
34820 && (plist = XCAR (hotspot), CONSP (plist)))
34821 {
34822 pointer = plist_get (plist, Qpointer);
34823 if (NILP (pointer))
34824 pointer = Qhand;
34825 help = plist_get (plist, Qhelp_echo);
34826 if (!NILP (help))
34827 {
34828 help_echo_string = help;
34829 XSETWINDOW (help_echo_window, w);
34830 help_echo_object = w->contents;
34831 help_echo_pos = charpos;
34832 }
34833 }
34834 }
34835 if (NILP (pointer))
34836 pointer = plist_get (XCDR (object), QCpointer);
34837 }
34838 #endif
34839
34840
34841
34842
34843 if (STRINGP (string))
34844 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
34845
34846
34847
34848
34849
34850 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
34851 || area == ON_TAB_LINE)
34852 {
34853
34854
34855 if (NILP (help))
34856 {
34857 if (STRINGP (string))
34858 help = Fget_text_property (pos, Qhelp_echo, string);
34859
34860 if (!NILP (help))
34861 {
34862 help_echo_string = help;
34863 XSETWINDOW (help_echo_window, w);
34864 help_echo_object = string;
34865 help_echo_pos = charpos;
34866 }
34867 else if (area == ON_MODE_LINE
34868 && !NILP (w->mode_line_help_echo))
34869 {
34870 help_echo_string = w->mode_line_help_echo;
34871 XSETWINDOW (help_echo_window, w);
34872 help_echo_object = Qnil;
34873 help_echo_pos = -1;
34874 }
34875 }
34876
34877 #ifdef HAVE_WINDOW_SYSTEM
34878
34879 if (FRAME_WINDOW_P (f))
34880 {
34881 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
34882 || minibuf_level
34883 || NILP (Vresize_mini_windows));
34884
34885 if (STRINGP (string))
34886 {
34887 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34888
34889 if (NILP (pointer))
34890 pointer = Fget_text_property (pos, Qpointer, string);
34891
34892
34893 if (NILP (pointer)
34894 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
34895 || area == ON_TAB_LINE))
34896 {
34897 Lisp_Object map;
34898
34899 map = Fget_text_property (pos, Qlocal_map, string);
34900 if (!KEYMAPP (map))
34901 map = Fget_text_property (pos, Qkeymap, string);
34902 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
34903 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34904 }
34905 }
34906 else if (draggable && area == ON_MODE_LINE)
34907 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34908 else if ((area == ON_MODE_LINE
34909 && WINDOW_BOTTOMMOST_P (w)
34910 && !FRAME_HAS_MINIBUF_P (f)
34911 && !NILP (Fframe_parameter
34912 (w->frame, Qdrag_with_mode_line)))
34913 || (((area == ON_HEADER_LINE
34914 && !NILP (Fframe_parameter
34915 (w->frame, Qdrag_with_header_line)))
34916 || (area == ON_TAB_LINE
34917 && !NILP (Fframe_parameter
34918 (w->frame, Qdrag_with_tab_line))))
34919 && WINDOW_TOPMOST_P (w)))
34920 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34921 else
34922 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34923 }
34924 #endif
34925 }
34926
34927
34928 bool mouse_face_shown = false;
34929
34930 if (STRINGP (string))
34931 {
34932 mouse_face = Fget_text_property (pos, Qmouse_face, string);
34933 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
34934 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
34935 || (area == ON_TAB_LINE))
34936 && glyph)
34937 {
34938 Lisp_Object b, e;
34939
34940 struct glyph * tmp_glyph;
34941
34942 int gpos;
34943 int gseq_length;
34944 int total_pixel_width;
34945 ptrdiff_t begpos, endpos, ignore;
34946
34947 int vpos, hpos;
34948
34949 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
34950 Qmouse_face, string, Qnil);
34951 if (NILP (b))
34952 begpos = 0;
34953 else
34954 begpos = XFIXNUM (b);
34955
34956 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
34957 if (NILP (e))
34958 endpos = SCHARS (string);
34959 else
34960 endpos = XFIXNUM (e);
34961
34962
34963
34964
34965
34966
34967
34968
34969
34970
34971
34972 tmp_glyph = row_start_glyph;
34973 while (tmp_glyph < glyph
34974 && (!(EQ (tmp_glyph->object, glyph->object)
34975 && begpos <= tmp_glyph->charpos
34976 && tmp_glyph->charpos < endpos)))
34977 tmp_glyph++;
34978 gpos = glyph - tmp_glyph;
34979
34980
34981
34982
34983
34984
34985 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
34986 tmp_glyph > glyph
34987 && (!(EQ (tmp_glyph->object, glyph->object)
34988 && begpos <= tmp_glyph->charpos
34989 && tmp_glyph->charpos < endpos));
34990 tmp_glyph--)
34991 ;
34992 gseq_length = gpos + (tmp_glyph - glyph) + 1;
34993
34994
34995
34996 total_pixel_width = 0;
34997 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
34998 total_pixel_width += tmp_glyph->pixel_width;
34999
35000
35001
35002
35003 hpos = x - gpos;
35004 vpos = (area == ON_MODE_LINE
35005 ? (w->current_matrix)->nrows - 1
35006 : (area == ON_TAB_LINE
35007 ? 0
35008 : (w->current_matrix->tab_line_p
35009 ? 1
35010 : 0)));
35011
35012
35013
35014 if ( EQ (window, hlinfo->mouse_face_window)
35015 && (!row->reversed_p
35016 ? (hlinfo->mouse_face_beg_col <= hpos
35017 && hpos < hlinfo->mouse_face_end_col)
35018
35019 : (hlinfo->mouse_face_end_col <= hpos
35020 && hpos < hlinfo->mouse_face_beg_col))
35021 && hlinfo->mouse_face_beg_row == vpos )
35022 return;
35023
35024 if (clear_mouse_face (hlinfo))
35025 cursor = No_Cursor;
35026
35027 if (!row->reversed_p)
35028 {
35029 hlinfo->mouse_face_beg_col = hpos;
35030 hlinfo->mouse_face_beg_x = original_x_pixel
35031 - (total_pixel_width + dx);
35032 hlinfo->mouse_face_end_col = hpos + gseq_length;
35033 hlinfo->mouse_face_end_x = 0;
35034 }
35035 else
35036 {
35037
35038
35039 hlinfo->mouse_face_end_col = hpos;
35040 hlinfo->mouse_face_end_x = original_x_pixel
35041 - (total_pixel_width + dx);
35042 hlinfo->mouse_face_beg_col = hpos + gseq_length;
35043 hlinfo->mouse_face_beg_x = 0;
35044 }
35045
35046 hlinfo->mouse_face_beg_row = vpos;
35047 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
35048 hlinfo->mouse_face_past_end = false;
35049 hlinfo->mouse_face_window = window;
35050
35051 hlinfo->mouse_face_face_id =
35052 face_at_string_position (w, string, charpos, 0, &ignore,
35053 glyph->face_id, true, 0);
35054
35055 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35056 mouse_face_shown = true;
35057
35058 if (NILP (pointer))
35059 pointer = Qhand;
35060 }
35061 }
35062
35063
35064
35065 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35066 || area == ON_TAB_LINE) && !mouse_face_shown)
35067 clear_mouse_face (hlinfo);
35068
35069 define_frame_cursor1 (f, cursor, pointer);
35070 }
35071
35072
35073
35074
35075
35076
35077
35078
35079
35080
35081 void
35082 note_mouse_highlight (struct frame *f, int x, int y)
35083 {
35084 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35085 enum window_part part = ON_NOTHING;
35086 Lisp_Object window;
35087 struct window *w;
35088 Emacs_Cursor cursor = No_Cursor;
35089 Lisp_Object pointer = Qnil;
35090 struct buffer *b;
35091
35092
35093 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS)
35094 if (popup_activated ())
35095 return;
35096 #endif
35097
35098 #if defined (HAVE_HAIKU)
35099 if (popup_activated_p)
35100 return;
35101 #endif
35102
35103 if (!f->glyphs_initialized_p
35104 || f->pointer_invisible)
35105 return;
35106
35107 hlinfo->mouse_face_mouse_x = x;
35108 hlinfo->mouse_face_mouse_y = y;
35109 hlinfo->mouse_face_mouse_frame = f;
35110
35111 if (hlinfo->mouse_face_defer)
35112 return;
35113
35114
35115 window = window_from_coordinates (f, x, y, &part, true, true);
35116
35117
35118 if (! EQ (window, hlinfo->mouse_face_window)
35119
35120 || (!NILP (hlinfo->mouse_face_window)
35121 && !NILP (window)
35122 && part != ON_TEXT
35123 && part != ON_MODE_LINE
35124 && part != ON_HEADER_LINE
35125 && part != ON_TAB_LINE))
35126 clear_mouse_face (hlinfo);
35127
35128
35129 help_echo_string = Qnil;
35130
35131
35132 if (!FRAME_WINDOW_P (f)
35133 && (y >= FRAME_MENU_BAR_LINES (f)
35134 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35135 {
35136 int prop_idx;
35137 bool ignore;
35138 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35139
35140 if (!NILP (caption))
35141 {
35142 help_echo_object = help_echo_window = Qnil;
35143 help_echo_pos = -1;
35144 help_echo_string = AREF (f->tab_bar_items,
35145 prop_idx * TAB_BAR_ITEM_NSLOTS
35146 + TAB_BAR_ITEM_HELP);
35147 if (NILP (help_echo_string))
35148 help_echo_string = caption;
35149 }
35150 }
35151
35152 #ifdef HAVE_WINDOW_SYSTEM
35153
35154
35155 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35156 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35157 {
35158 enum internal_border_part part = frame_internal_border_part (f, x, y);
35159
35160 switch (part)
35161 {
35162 case INTERNAL_BORDER_NONE:
35163 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35164
35165 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35166 break;
35167 case INTERNAL_BORDER_LEFT_EDGE:
35168 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35169 break;
35170 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35171 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35172 break;
35173 case INTERNAL_BORDER_TOP_EDGE:
35174 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35175 break;
35176 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35177 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35178 break;
35179 case INTERNAL_BORDER_RIGHT_EDGE:
35180 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35181 break;
35182 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35183 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35184 break;
35185 case INTERNAL_BORDER_BOTTOM_EDGE:
35186 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35187 break;
35188 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35189 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35190 break;
35191 default:
35192
35193 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35194 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35195 }
35196
35197 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35198 {
35199
35200 help_echo_string = build_string ("drag-mouse-1: resize frame");
35201 goto set_cursor;
35202 }
35203 }
35204 #endif
35205
35206
35207 if (!WINDOWP (window))
35208 return;
35209
35210
35211 w = XWINDOW (window);
35212 frame_to_window_pixel_xy (w, &x, &y);
35213
35214 #if defined (HAVE_WINDOW_SYSTEM)
35215
35216
35217 if (EQ (window, f->tab_bar_window))
35218 {
35219 note_tab_bar_highlight (f, x, y);
35220 if (tab_bar__dragging_in_progress)
35221 {
35222 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35223 goto set_cursor;
35224 }
35225 else
35226 return;
35227 }
35228 else
35229 {
35230
35231
35232
35233
35234 f->last_tab_bar_item = -1;
35235 }
35236 #endif
35237
35238 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35239
35240
35241 if (EQ (window, f->tool_bar_window))
35242 {
35243 note_tool_bar_highlight (f, x, y);
35244 return;
35245 }
35246 #endif
35247
35248
35249 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35250 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35251 {
35252 note_mode_line_or_margin_highlight (window, x, y, part);
35253
35254 #ifdef HAVE_WINDOW_SYSTEM
35255 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35256 {
35257 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35258
35259 goto set_cursor;
35260 }
35261 else
35262 #endif
35263 return;
35264 }
35265
35266 #ifdef HAVE_WINDOW_SYSTEM
35267 if (part == ON_VERTICAL_BORDER)
35268 {
35269 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35270 help_echo_string = build_string ("drag-mouse-1: resize");
35271 goto set_cursor;
35272 }
35273 else if (part == ON_RIGHT_DIVIDER)
35274 {
35275 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35276 help_echo_string = build_string ("drag-mouse-1: resize");
35277 goto set_cursor;
35278 }
35279 else if (part == ON_BOTTOM_DIVIDER)
35280 if (! WINDOW_BOTTOMMOST_P (w)
35281 || minibuf_level
35282 || NILP (Vresize_mini_windows))
35283 {
35284 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35285 help_echo_string = build_string ("drag-mouse-1: resize");
35286 goto set_cursor;
35287 }
35288 else
35289 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35290 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35291 || part == ON_VERTICAL_SCROLL_BAR
35292 || part == ON_HORIZONTAL_SCROLL_BAR)
35293 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35294 else
35295 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35296 #endif
35297
35298
35299
35300 b = XBUFFER (w->contents);
35301 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35302 {
35303 int hpos, vpos, dx, dy, area = LAST_AREA;
35304 ptrdiff_t pos;
35305 struct glyph *glyph;
35306 Lisp_Object object;
35307 Lisp_Object mouse_face = Qnil, position;
35308 Lisp_Object *overlay_vec = NULL;
35309 ptrdiff_t i, noverlays;
35310 struct buffer *obuf;
35311 ptrdiff_t obegv, ozv;
35312 bool same_region;
35313
35314
35315 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35316
35317 #ifdef HAVE_WINDOW_SYSTEM
35318
35319 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35320 {
35321 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35322 if (img != NULL && IMAGEP (img->spec))
35323 {
35324 Lisp_Object image_map, hotspot;
35325 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35326 !NILP (image_map))
35327 && (hotspot = find_hot_spot (image_map,
35328 glyph->slice.img.x + dx,
35329 glyph->slice.img.y + dy),
35330 CONSP (hotspot))
35331 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35332 {
35333 Lisp_Object plist;
35334
35335
35336
35337
35338
35339 hotspot = XCDR (hotspot);
35340 if (CONSP (hotspot)
35341 && (plist = XCAR (hotspot), CONSP (plist)))
35342 {
35343 pointer = plist_get (plist, Qpointer);
35344 if (NILP (pointer))
35345 pointer = Qhand;
35346 help_echo_string = plist_get (plist, Qhelp_echo);
35347 if (!NILP (help_echo_string))
35348 {
35349 help_echo_window = window;
35350 help_echo_object = glyph->object;
35351 help_echo_pos = glyph->charpos;
35352 }
35353 }
35354 }
35355 if (NILP (pointer))
35356 pointer = plist_get (XCDR (img->spec), QCpointer);
35357 }
35358 }
35359 #endif
35360
35361
35362 if (glyph == NULL
35363 || area != TEXT_AREA
35364 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35365
35366
35367
35368
35369
35370 || NILP (glyph->object)
35371
35372
35373
35374
35375 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35376 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35377 && glyph->type == STRETCH_GLYPH
35378 && glyph->avoid_cursor_p))
35379 {
35380 if (clear_mouse_face (hlinfo))
35381 cursor = No_Cursor;
35382 if (FRAME_WINDOW_P (f) && NILP (pointer))
35383 {
35384 #ifdef HAVE_WINDOW_SYSTEM
35385 if (area != TEXT_AREA)
35386 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35387 else
35388 pointer = Vvoid_text_area_pointer;
35389 #endif
35390 }
35391 goto set_cursor;
35392 }
35393
35394 pos = glyph->charpos;
35395 object = glyph->object;
35396 if (!STRINGP (object) && !BUFFERP (object))
35397 goto set_cursor;
35398
35399
35400 if (BUFFERP (object) && pos > BUF_Z (b))
35401 goto set_cursor;
35402
35403
35404
35405 obuf = current_buffer;
35406 current_buffer = b;
35407 obegv = BEGV;
35408 ozv = ZV;
35409 BEGV = BEG;
35410 ZV = Z;
35411
35412
35413 position = make_fixnum (pos);
35414
35415 USE_SAFE_ALLOCA;
35416
35417 if (BUFFERP (object))
35418 {
35419
35420 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35421
35422 noverlays = sort_overlays (overlay_vec, noverlays, w);
35423 }
35424 else
35425 noverlays = 0;
35426
35427 if (NILP (Vmouse_highlight))
35428 {
35429 clear_mouse_face (hlinfo);
35430 goto check_help_echo;
35431 }
35432
35433 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35434
35435 if (same_region)
35436 cursor = No_Cursor;
35437
35438
35439 if (! same_region
35440
35441
35442
35443
35444
35445 || (!hlinfo->mouse_face_hidden
35446 && OVERLAYP (hlinfo->mouse_face_overlay)
35447
35448 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35449 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35450 {
35451
35452 Lisp_Object overlay = Qnil;
35453 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35454 {
35455 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35456 if (!NILP (mouse_face))
35457 overlay = overlay_vec[i];
35458 }
35459
35460
35461
35462 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35463 goto check_help_echo;
35464
35465
35466 if (clear_mouse_face (hlinfo))
35467 cursor = No_Cursor;
35468
35469
35470 hlinfo->mouse_face_overlay = overlay;
35471
35472
35473 if (NILP (overlay))
35474 mouse_face = Fget_text_property (position, Qmouse_face, object);
35475
35476
35477
35478 if (!NILP (mouse_face) && STRINGP (object))
35479 {
35480
35481
35482 Lisp_Object s, e;
35483 ptrdiff_t ignore;
35484
35485 s = Fprevious_single_property_change
35486 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35487 e = Fnext_single_property_change
35488 (position, Qmouse_face, object, Qnil);
35489 if (NILP (s))
35490 s = make_fixnum (0);
35491 if (NILP (e))
35492 e = make_fixnum (SCHARS (object));
35493 mouse_face_from_string_pos (w, hlinfo, object,
35494 XFIXNUM (s), XFIXNUM (e));
35495 hlinfo->mouse_face_past_end = false;
35496 hlinfo->mouse_face_window = window;
35497 hlinfo->mouse_face_face_id
35498 = face_at_string_position (w, object, pos, 0, &ignore,
35499 glyph->face_id, true, 0);
35500 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35501 cursor = No_Cursor;
35502 }
35503 else
35504 {
35505
35506
35507 Lisp_Object buffer UNINIT;
35508 Lisp_Object disp_string UNINIT;
35509
35510 if (STRINGP (object))
35511 {
35512
35513
35514 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35515 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35516 pos = string_buffer_position (object, start);
35517 if (pos > 0)
35518 {
35519 mouse_face = get_char_property_and_overlay
35520 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35521 buffer = w->contents;
35522 disp_string = object;
35523 }
35524 }
35525 else
35526 {
35527 buffer = object;
35528 disp_string = Qnil;
35529 }
35530
35531 if (!NILP (mouse_face))
35532 {
35533 Lisp_Object before, after;
35534 Lisp_Object before_string, after_string;
35535
35536
35537
35538
35539
35540
35541
35542
35543
35544
35545 Lisp_Object lim1
35546 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35547 ? Fmarker_position (w->start)
35548 : Qnil;
35549 Lisp_Object lim2
35550 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35551 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35552 - w->window_end_pos)
35553 : Qnil;
35554
35555 if (NILP (overlay))
35556 {
35557
35558 before = Fprevious_single_property_change
35559 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35560 after = Fnext_single_property_change
35561 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35562 before_string = after_string = Qnil;
35563 }
35564 else
35565 {
35566
35567 before = Foverlay_start (overlay);
35568 after = Foverlay_end (overlay);
35569 before_string = Foverlay_get (overlay, Qbefore_string);
35570 after_string = Foverlay_get (overlay, Qafter_string);
35571
35572 if (!STRINGP (before_string)) before_string = Qnil;
35573 if (!STRINGP (after_string)) after_string = Qnil;
35574 }
35575
35576 mouse_face_from_buffer_pos (window, hlinfo, pos,
35577 NILP (before)
35578 ? 1
35579 : XFIXNAT (before),
35580 NILP (after)
35581 ? BUF_Z (XBUFFER (buffer))
35582 : XFIXNAT (after),
35583 before_string, after_string,
35584 disp_string);
35585 cursor = No_Cursor;
35586 }
35587 }
35588 }
35589
35590 check_help_echo:
35591
35592
35593 if (NILP (help_echo_string)) {
35594 Lisp_Object help, overlay;
35595
35596
35597 help = overlay = Qnil;
35598 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35599 {
35600 overlay = overlay_vec[i];
35601 help = Foverlay_get (overlay, Qhelp_echo);
35602 }
35603
35604 if (!NILP (help))
35605 {
35606 help_echo_string = help;
35607 help_echo_window = window;
35608 help_echo_object = overlay;
35609 help_echo_pos = pos;
35610 }
35611 else
35612 {
35613 Lisp_Object obj = glyph->object;
35614 ptrdiff_t charpos = glyph->charpos;
35615
35616
35617 if (STRINGP (obj)
35618 && charpos >= 0
35619 && charpos < SCHARS (obj))
35620 {
35621 help = Fget_text_property (make_fixnum (charpos),
35622 Qhelp_echo, obj);
35623 if (NILP (help))
35624 {
35625
35626
35627 struct glyph_row *r
35628 = MATRIX_ROW (w->current_matrix, vpos);
35629 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35630 ptrdiff_t p = string_buffer_position (obj, start);
35631 if (p > 0)
35632 {
35633 help = Fget_char_property (make_fixnum (p),
35634 Qhelp_echo, w->contents);
35635 if (!NILP (help))
35636 {
35637 charpos = p;
35638 obj = w->contents;
35639 }
35640 }
35641 }
35642 }
35643 else if (BUFFERP (obj)
35644 && charpos >= BEGV
35645 && charpos < ZV)
35646 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35647 obj);
35648
35649 if (!NILP (help))
35650 {
35651 help_echo_string = help;
35652 help_echo_window = window;
35653 help_echo_object = obj;
35654 help_echo_pos = charpos;
35655 }
35656 }
35657 }
35658
35659 #ifdef HAVE_WINDOW_SYSTEM
35660
35661 if (FRAME_WINDOW_P (f) && NILP (pointer))
35662 {
35663
35664 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35665 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35666
35667 if (NILP (pointer))
35668 {
35669 Lisp_Object obj = glyph->object;
35670 ptrdiff_t charpos = glyph->charpos;
35671
35672
35673 if (STRINGP (obj)
35674 && charpos >= 0
35675 && charpos < SCHARS (obj))
35676 {
35677 pointer = Fget_text_property (make_fixnum (charpos),
35678 Qpointer, obj);
35679 if (NILP (pointer))
35680 {
35681
35682
35683 struct glyph_row *r
35684 = MATRIX_ROW (w->current_matrix, vpos);
35685 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35686 ptrdiff_t p = string_buffer_position (obj, start);
35687 if (p > 0)
35688 pointer = Fget_char_property (make_fixnum (p),
35689 Qpointer, w->contents);
35690 }
35691 }
35692 else if (BUFFERP (obj)
35693 && charpos >= BEGV
35694 && charpos < ZV)
35695 pointer = Fget_text_property (make_fixnum (charpos),
35696 Qpointer, obj);
35697 }
35698 }
35699 #endif
35700
35701 BEGV = obegv;
35702 ZV = ozv;
35703 current_buffer = obuf;
35704 SAFE_FREE ();
35705 }
35706
35707 set_cursor:
35708 define_frame_cursor1 (f, cursor, pointer);
35709 }
35710
35711
35712
35713
35714
35715
35716
35717 void
35718 gui_clear_window_mouse_face (struct window *w)
35719 {
35720 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
35721 Lisp_Object window;
35722
35723 block_input ();
35724 XSETWINDOW (window, w);
35725 if (EQ (window, hlinfo->mouse_face_window))
35726 clear_mouse_face (hlinfo);
35727 unblock_input ();
35728 }
35729
35730
35731
35732
35733
35734
35735 void
35736 cancel_mouse_face (struct frame *f)
35737 {
35738 Lisp_Object window;
35739 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35740
35741 window = hlinfo->mouse_face_window;
35742 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
35743 reset_mouse_highlight (hlinfo);
35744 }
35745
35746
35747
35748
35749
35750
35751
35752 #ifdef HAVE_WINDOW_SYSTEM
35753
35754
35755
35756
35757 static void
35758 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
35759 enum glyph_row_area area)
35760 {
35761 struct glyph *first = row->glyphs[area];
35762 struct glyph *end = row->glyphs[area] + row->used[area];
35763 struct glyph *last;
35764 int first_x, start_x, x;
35765
35766 if (area == TEXT_AREA && row->fill_line_p)
35767
35768 draw_glyphs (w, row->x, row, area,
35769 0, row->used[area],
35770 DRAW_NORMAL_TEXT, 0);
35771 else
35772 {
35773
35774
35775
35776 start_x = window_box_left_offset (w, area);
35777 x = start_x;
35778 if (area == TEXT_AREA)
35779 x += row->x;
35780
35781
35782 while (first < end
35783 && x + first->pixel_width < r->x)
35784 {
35785 x += first->pixel_width;
35786 ++first;
35787 }
35788
35789
35790 last = first;
35791 first_x = x;
35792
35793
35794
35795 int r_end = r->x + r->width;
35796 while (last < end && x < r_end)
35797 {
35798 x += last->pixel_width;
35799 ++last;
35800 }
35801
35802
35803 if (last > first)
35804 draw_glyphs (w, first_x - start_x, row, area,
35805 first - row->glyphs[area], last - row->glyphs[area],
35806 DRAW_NORMAL_TEXT, 0);
35807 }
35808 }
35809
35810
35811
35812
35813
35814
35815 static bool
35816 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
35817 {
35818 eassert (row->enabled_p);
35819
35820 if (row->mode_line_p || w->pseudo_window_p)
35821 draw_glyphs (w, 0, row, TEXT_AREA,
35822 0, row->used[TEXT_AREA],
35823 DRAW_NORMAL_TEXT, 0);
35824 else
35825 {
35826 if (row->used[LEFT_MARGIN_AREA])
35827 expose_area (w, row, r, LEFT_MARGIN_AREA);
35828 if (row->used[TEXT_AREA])
35829 expose_area (w, row, r, TEXT_AREA);
35830 if (row->used[RIGHT_MARGIN_AREA])
35831 expose_area (w, row, r, RIGHT_MARGIN_AREA);
35832 draw_row_fringe_bitmaps (w, row);
35833 }
35834
35835 return row->mouse_face_p;
35836 }
35837
35838
35839
35840
35841
35842
35843
35844
35845
35846
35847 static void
35848 expose_overlaps (struct window *w,
35849 struct glyph_row *first_overlapping_row,
35850 struct glyph_row *last_overlapping_row,
35851 const Emacs_Rectangle *r)
35852 {
35853 struct glyph_row *row;
35854
35855 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
35856 if (row->overlapping_p)
35857 {
35858 eassert (row->enabled_p && !row->mode_line_p);
35859
35860 row->clip = r;
35861 if (row->used[LEFT_MARGIN_AREA])
35862 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
35863
35864 if (row->used[TEXT_AREA])
35865 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
35866
35867 if (row->used[RIGHT_MARGIN_AREA])
35868 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
35869 row->clip = NULL;
35870 }
35871 }
35872
35873
35874
35875
35876 static bool
35877 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
35878 {
35879 Emacs_Rectangle cr, result;
35880 struct glyph *cursor_glyph;
35881 struct glyph_row *row;
35882
35883 if (w->phys_cursor.vpos >= 0
35884 && w->phys_cursor.vpos < w->current_matrix->nrows
35885 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
35886 row->enabled_p)
35887 && row->cursor_in_fringe_p)
35888 {
35889
35890 cr.x = window_box_right_offset (w,
35891 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
35892 ? RIGHT_MARGIN_AREA
35893 : TEXT_AREA));
35894 cr.y = row->y;
35895 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
35896 cr.height = row->height;
35897 return gui_intersect_rectangles (&cr, r, &result);
35898 }
35899
35900 cursor_glyph = get_phys_cursor_glyph (w);
35901 if (cursor_glyph)
35902 {
35903
35904
35905 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
35906 cr.y = w->phys_cursor.y;
35907 cr.width = cursor_glyph->pixel_width;
35908 cr.height = w->phys_cursor_height;
35909
35910
35911 return gui_intersect_rectangles (&cr, r, &result);
35912 }
35913
35914 return false;
35915 }
35916
35917
35918
35919
35920
35921
35922 void
35923 gui_draw_vertical_border (struct window *w)
35924 {
35925 struct frame *f = XFRAME (WINDOW_FRAME (w));
35926
35927
35928
35929
35930
35931
35932
35933
35934
35935 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
35936 return;
35937
35938
35939
35940
35941 if (!WINDOW_RIGHTMOST_P (w)
35942 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
35943 {
35944 int x0, x1, y0, y1;
35945
35946 window_box_edges (w, &x0, &y0, &x1, &y1);
35947 y1 -= 1;
35948
35949 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
35950 x1 -= 1;
35951
35952 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
35953 }
35954
35955 if (!WINDOW_LEFTMOST_P (w)
35956 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
35957 {
35958 int x0, x1, y0, y1;
35959
35960 window_box_edges (w, &x0, &y0, &x1, &y1);
35961 y1 -= 1;
35962
35963 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
35964 x0 -= 1;
35965
35966 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
35967 }
35968 }
35969
35970
35971
35972
35973 void
35974 gui_draw_right_divider (struct window *w)
35975 {
35976 struct frame *f = WINDOW_XFRAME (w);
35977
35978 if (w->mini || w->pseudo_window_p)
35979 return;
35980 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
35981 {
35982 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
35983 int x1 = WINDOW_RIGHT_EDGE_X (w);
35984 int y0 = WINDOW_TOP_EDGE_Y (w);
35985 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
35986
35987
35988
35989 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
35990 && !NILP (w->parent)
35991 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
35992 && !NILP (w->next))
35993 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
35994
35995 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
35996 }
35997 }
35998
35999 static void
36000 gui_draw_bottom_divider (struct window *w)
36001 {
36002 struct frame *f = XFRAME (WINDOW_FRAME (w));
36003
36004 if (w->mini || w->pseudo_window_p)
36005 return;
36006 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36007 {
36008 int x0 = WINDOW_LEFT_EDGE_X (w);
36009 int x1 = WINDOW_RIGHT_EDGE_X (w);
36010 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36011 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36012 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
36013
36014
36015
36016 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
36017 && p
36018 && ((WINDOW_VERTICAL_COMBINATION_P (p)
36019 && !NILP (w->next))
36020 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
36021 && NILP (w->next)
36022 && !NILP (p->parent)
36023 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
36024 && !NILP (XWINDOW (p->parent)->next))))
36025 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
36026
36027 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36028 }
36029 }
36030
36031
36032
36033
36034
36035
36036 static bool
36037 expose_window (struct window *w, const Emacs_Rectangle *fr)
36038 {
36039 struct frame *f = XFRAME (w->frame);
36040 Emacs_Rectangle wr, r;
36041 bool mouse_face_overwritten_p = false;
36042
36043
36044
36045
36046
36047 if (w->current_matrix == NULL)
36048 return false;
36049
36050
36051
36052
36053 if (w->must_be_updated_p)
36054 {
36055 SET_FRAME_GARBAGED (f);
36056 return false;
36057 }
36058
36059
36060 wr.x = WINDOW_LEFT_EDGE_X (w);
36061 wr.y = WINDOW_TOP_EDGE_Y (w);
36062 wr.width = WINDOW_PIXEL_WIDTH (w);
36063 wr.height = WINDOW_PIXEL_HEIGHT (w);
36064
36065 if (gui_intersect_rectangles (fr, &wr, &r))
36066 {
36067 int yb = window_text_bottom_y (w);
36068 struct glyph_row *row;
36069 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36070
36071 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36072 r.x, r.y, r.width, r.height);
36073
36074
36075 r.x -= WINDOW_LEFT_EDGE_X (w);
36076 r.y -= WINDOW_TOP_EDGE_Y (w);
36077
36078
36079 bool cursor_cleared_p = (!w->pseudo_window_p
36080 && phys_cursor_in_rect_p (w, &r));
36081 if (cursor_cleared_p)
36082 gui_clear_cursor (w);
36083
36084
36085
36086
36087
36088
36089 bool phys_cursor_on_p = w->phys_cursor_on_p;
36090
36091
36092
36093
36094 int r_bottom = r.y + r.height;
36095
36096
36097
36098
36099
36100 bool buffer_changed = false;
36101 struct buffer *oldbuf = current_buffer;
36102 if (!w->pseudo_window_p)
36103 {
36104 set_buffer_internal_1 (XBUFFER (w->contents));
36105 buffer_changed = true;
36106 }
36107
36108
36109 first_overlapping_row = last_overlapping_row = NULL;
36110 for (row = w->current_matrix->rows;
36111 row->enabled_p;
36112 ++row)
36113 {
36114 int y0 = row->y;
36115 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36116
36117 if ((y0 >= r.y && y0 < r_bottom)
36118 || (y1 > r.y && y1 < r_bottom)
36119 || (r.y >= y0 && r.y < y1)
36120 || (r_bottom > y0 && r_bottom < y1))
36121 {
36122
36123
36124 if (row->overlapping_p && !row->mode_line_p)
36125 {
36126 if (first_overlapping_row == NULL)
36127 first_overlapping_row = row;
36128 last_overlapping_row = row;
36129 }
36130
36131 row->clip = fr;
36132 if (expose_line (w, row, &r))
36133 mouse_face_overwritten_p = true;
36134 row->clip = NULL;
36135 }
36136 else if (row->overlapping_p)
36137 {
36138
36139 if (y0 < r.y
36140 ? y0 + row->phys_height > r.y
36141 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36142 {
36143 if (first_overlapping_row == NULL)
36144 first_overlapping_row = row;
36145 last_overlapping_row = row;
36146 }
36147 }
36148
36149 if (y1 >= yb)
36150 break;
36151 }
36152
36153 if (buffer_changed)
36154 set_buffer_internal_1 (oldbuf);
36155
36156
36157 if (window_wants_mode_line (w)
36158 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36159 row->enabled_p)
36160 && row->y < r_bottom)
36161 {
36162 if (expose_line (w, row, &r))
36163 mouse_face_overwritten_p = true;
36164 }
36165
36166 if (!w->pseudo_window_p)
36167 {
36168
36169 if (first_overlapping_row)
36170 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36171 fr);
36172
36173
36174 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36175 gui_draw_right_divider (w);
36176 else
36177 gui_draw_vertical_border (w);
36178
36179 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36180 gui_draw_bottom_divider (w);
36181
36182
36183 if (cursor_cleared_p
36184 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36185 update_window_cursor (w, true);
36186 }
36187 }
36188
36189 return mouse_face_overwritten_p;
36190 }
36191
36192
36193
36194
36195
36196
36197
36198 static bool
36199 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36200 {
36201 struct frame *f = XFRAME (w->frame);
36202 bool mouse_face_overwritten_p = false;
36203
36204 while (w && !FRAME_GARBAGED_P (f))
36205 {
36206 mouse_face_overwritten_p
36207 |= (WINDOWP (w->contents)
36208 ? expose_window_tree (XWINDOW (w->contents), r)
36209 : expose_window (w, r));
36210
36211 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36212 }
36213
36214 return mouse_face_overwritten_p;
36215 }
36216
36217
36218
36219
36220
36221
36222
36223
36224 void
36225 expose_frame (struct frame *f, int x, int y, int w, int h)
36226 {
36227 Emacs_Rectangle r;
36228 bool mouse_face_overwritten_p = false;
36229
36230 if (FRAME_GARBAGED_P (f))
36231 {
36232 redisplay_trace ("expose_frame garbaged\n");
36233 return;
36234 }
36235
36236
36237
36238
36239 if (FRAME_FACE_CACHE (f) == NULL
36240 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36241 {
36242 redisplay_trace ("expose_frame no faces\n");
36243 return;
36244 }
36245
36246 if (w == 0 || h == 0)
36247 {
36248 r.x = r.y = 0;
36249 r.width = FRAME_TEXT_WIDTH (f);
36250 r.height = FRAME_TEXT_HEIGHT (f);
36251 }
36252 else
36253 {
36254 r.x = x;
36255 r.y = y;
36256 r.width = w;
36257 r.height = h;
36258 }
36259
36260 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36261 r.x, r.y, r.width, r.height);
36262 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36263
36264 if (WINDOWP (f->tab_bar_window))
36265 mouse_face_overwritten_p
36266 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36267
36268 #ifndef HAVE_EXT_TOOL_BAR
36269 if (WINDOWP (f->tool_bar_window))
36270 mouse_face_overwritten_p
36271 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36272 #endif
36273
36274 #ifdef HAVE_X_WINDOWS
36275 #ifndef MSDOS
36276 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
36277 if (WINDOWP (f->menu_bar_window))
36278 mouse_face_overwritten_p
36279 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36280 #endif
36281 #endif
36282 #endif
36283
36284
36285
36286
36287
36288
36289
36290
36291
36292
36293
36294
36295
36296
36297 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36298 {
36299 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36300 if (f == hlinfo->mouse_face_mouse_frame)
36301 {
36302 int mouse_x = hlinfo->mouse_face_mouse_x;
36303 int mouse_y = hlinfo->mouse_face_mouse_y;
36304 clear_mouse_face (hlinfo);
36305 note_mouse_highlight (f, mouse_x, mouse_y);
36306 }
36307 }
36308 }
36309
36310
36311
36312
36313
36314
36315
36316 bool
36317 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36318 Emacs_Rectangle *result)
36319 {
36320 const Emacs_Rectangle *left, *right;
36321 const Emacs_Rectangle *upper, *lower;
36322 bool intersection_p = false;
36323
36324
36325 if (r1->x < r2->x)
36326 left = r1, right = r2;
36327 else
36328 left = r2, right = r1;
36329
36330
36331
36332 if (right->x <= left->x + left->width)
36333 {
36334 result->x = right->x;
36335
36336
36337
36338 result->width = (min (left->x + left->width, right->x + right->width)
36339 - result->x);
36340
36341
36342 if (r1->y < r2->y)
36343 upper = r1, lower = r2;
36344 else
36345 upper = r2, lower = r1;
36346
36347
36348
36349 if (lower->y <= upper->y + upper->height)
36350 {
36351 result->y = lower->y;
36352
36353
36354
36355 result->height = (min (lower->y + lower->height,
36356 upper->y + upper->height)
36357 - result->y);
36358 intersection_p = true;
36359 }
36360 }
36361
36362 return intersection_p;
36363 }
36364
36365 #endif
36366
36367
36368
36369
36370
36371
36372 void
36373 syms_of_xdisp (void)
36374 {
36375 Vwith_echo_area_save_vector = Qnil;
36376 staticpro (&Vwith_echo_area_save_vector);
36377
36378 Vmessage_stack = Qnil;
36379 staticpro (&Vmessage_stack);
36380
36381
36382 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36383
36384 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36385
36386 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36387 scroll_minibuffer_conservatively,
36388 doc:
36389
36390 );
36391 scroll_minibuffer_conservatively = true;
36392
36393 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36394 doc:
36395
36396
36397
36398
36399
36400 );
36401 inhibit_message = false;
36402
36403 message_dolog_marker1 = Fmake_marker ();
36404 staticpro (&message_dolog_marker1);
36405 message_dolog_marker2 = Fmake_marker ();
36406 staticpro (&message_dolog_marker2);
36407 message_dolog_marker3 = Fmake_marker ();
36408 staticpro (&message_dolog_marker3);
36409
36410 defsubr (&Sset_buffer_redisplay);
36411 #ifdef GLYPH_DEBUG
36412 defsubr (&Sdump_frame_glyph_matrix);
36413 defsubr (&Sdump_glyph_matrix);
36414 defsubr (&Sdump_glyph_row);
36415 defsubr (&Sdump_tab_bar_row);
36416 defsubr (&Sdump_tool_bar_row);
36417 defsubr (&Strace_redisplay);
36418 defsubr (&Strace_to_stderr);
36419 #endif
36420 #ifdef HAVE_WINDOW_SYSTEM
36421 defsubr (&Stab_bar_height);
36422 defsubr (&Stool_bar_height);
36423 defsubr (&Slookup_image_map);
36424 #endif
36425 defsubr (&Sline_pixel_height);
36426 defsubr (&Sformat_mode_line);
36427 defsubr (&Sinvisible_p);
36428 defsubr (&Scurrent_bidi_paragraph_direction);
36429 defsubr (&Swindow_text_pixel_size);
36430 defsubr (&Sbuffer_text_pixel_size);
36431 defsubr (&Smove_point_visually);
36432 defsubr (&Sbidi_find_overridden_directionality);
36433 defsubr (&Sdisplay__line_is_continued_p);
36434 defsubr (&Sget_display_property);
36435 defsubr (&Slong_line_optimizations_p);
36436
36437 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36438 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36439 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36440 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36441 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36442 DEFSYM (Qeval, "eval");
36443 DEFSYM (QCdata, ":data");
36444
36445
36446 DEFSYM (Qdisplay, "display");
36447 DEFSYM (Qspace_width, "space-width");
36448 DEFSYM (Qraise, "raise");
36449 DEFSYM (Qslice, "slice");
36450 DEFSYM (Qspace, "space");
36451 DEFSYM (Qmargin, "margin");
36452 DEFSYM (Qpointer, "pointer");
36453 DEFSYM (Qleft_margin, "left-margin");
36454 DEFSYM (Qright_margin, "right-margin");
36455 DEFSYM (Qcenter, "center");
36456 DEFSYM (Qline_height, "line-height");
36457 DEFSYM (QCalign_to, ":align-to");
36458 DEFSYM (QCrelative_width, ":relative-width");
36459 DEFSYM (QCrelative_height, ":relative-height");
36460 DEFSYM (QCeval, ":eval");
36461 DEFSYM (QCpropertize, ":propertize");
36462 DEFSYM (QCfile, ":file");
36463 DEFSYM (Qfontified, "fontified");
36464 DEFSYM (Qfontification_functions, "fontification-functions");
36465 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36466 "long-line-optimizations-in-fontification-functions");
36467
36468
36469
36470 DEFSYM (Qdisable_eval, "disable-eval");
36471
36472
36473 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36474
36475
36476 DEFSYM (Qline_number, "line-number");
36477 DEFSYM (Qline_number_current_line, "line-number-current-line");
36478 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36479 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36480
36481 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36482
36483
36484 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36485
36486
36487 DEFSYM (Qescape_glyph, "escape-glyph");
36488
36489
36490
36491 DEFSYM (Qnobreak_space, "nobreak-space");
36492 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36493
36494
36495
36496 DEFSYM (Qimage, "image");
36497
36498
36499 DEFSYM (Qtext, "text");
36500 DEFSYM (Qboth, "both");
36501 DEFSYM (Qboth_horiz, "both-horiz");
36502 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36503
36504
36505 DEFSYM (QCmap, ":map");
36506 DEFSYM (QCpointer, ":pointer");
36507 DEFSYM (Qrect, "rect");
36508 DEFSYM (Qcircle, "circle");
36509 DEFSYM (Qpoly, "poly");
36510
36511 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36512
36513 DEFSYM (Qgrow_only, "grow-only");
36514 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36515 DEFSYM (Qposition, "position");
36516 DEFSYM (Qbuffer_position, "buffer-position");
36517 DEFSYM (Qobject, "object");
36518
36519
36520 DEFSYM (Qbar, "bar");
36521 DEFSYM (Qhbar, "hbar");
36522 DEFSYM (Qbox, "box");
36523 DEFSYM (Qhollow, "hollow");
36524
36525
36526 DEFSYM (Qhand, "hand");
36527 DEFSYM (Qarrow, "arrow");
36528
36529
36530 DEFSYM (Qdragging, "dragging");
36531 DEFSYM (Qdropping, "dropping");
36532 DEFSYM (Qdrag_source, "drag-source");
36533
36534 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36535 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36536 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36537
36538 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36539
36540 list_of_error = list1 (Qerror);
36541 staticpro (&list_of_error);
36542
36543
36544
36545
36546
36547 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36548 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36549
36550
36551
36552 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36553 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36554
36555 echo_buffer[0] = echo_buffer[1] = Qnil;
36556 staticpro (&echo_buffer[0]);
36557 staticpro (&echo_buffer[1]);
36558
36559 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36560 staticpro (&echo_area_buffer[0]);
36561 staticpro (&echo_area_buffer[1]);
36562
36563 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36564 doc:
36565
36566
36567
36568 );
36569 Vmessages_buffer_name = build_string ("*Messages*");
36570
36571 mode_line_proptrans_alist = Qnil;
36572 staticpro (&mode_line_proptrans_alist);
36573 mode_line_string_list = Qnil;
36574 staticpro (&mode_line_string_list);
36575 mode_line_string_face = Qnil;
36576 staticpro (&mode_line_string_face);
36577 mode_line_string_face_prop = Qnil;
36578 staticpro (&mode_line_string_face_prop);
36579 Vmode_line_unwind_vector = Qnil;
36580 staticpro (&Vmode_line_unwind_vector);
36581
36582 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36583
36584 help_echo_string = Qnil;
36585 staticpro (&help_echo_string);
36586 help_echo_object = Qnil;
36587 staticpro (&help_echo_object);
36588 help_echo_window = Qnil;
36589 staticpro (&help_echo_window);
36590 previous_help_echo_string = Qnil;
36591 staticpro (&previous_help_echo_string);
36592 help_echo_pos = -1;
36593
36594 DEFSYM (Qright_to_left, "right-to-left");
36595 DEFSYM (Qleft_to_right, "left-to-right");
36596 defsubr (&Sbidi_resolved_levels);
36597
36598 #ifdef HAVE_WINDOW_SYSTEM
36599 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36600 doc:
36601
36602 );
36603 x_stretch_cursor_p = 0;
36604 #endif
36605
36606 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36607 doc:
36608 );
36609 Vshow_trailing_whitespace = Qnil;
36610
36611 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36612 doc:
36613
36614
36615 );
36616 Vmode_line_compact = Qnil;
36617 DEFSYM (Qlong, "long");
36618
36619 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36620 doc:
36621
36622
36623
36624
36625
36626
36627
36628
36629
36630
36631
36632 );
36633 Vnobreak_char_display = Qt;
36634
36635 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
36636 doc:
36637
36638
36639
36640
36641
36642
36643
36644
36645
36646
36647
36648
36649
36650
36651
36652 );
36653 nobreak_char_ascii_display = false;
36654
36655 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
36656 doc:
36657
36658
36659 );
36660 Vvoid_text_area_pointer = Qarrow;
36661
36662 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
36663 doc:
36664 );
36665 Vinhibit_redisplay = Qnil;
36666
36667 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
36668 doc: );
36669 Vglobal_mode_string = Qnil;
36670
36671 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
36672 doc:
36673
36674 );
36675 Voverlay_arrow_position = Qnil;
36676
36677 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
36678 doc:
36679 );
36680 Voverlay_arrow_string = build_pure_c_string ("=>");
36681
36682 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
36683 doc:
36684
36685 );
36686 Voverlay_arrow_variable_list
36687 = list1 (intern_c_string ("overlay-arrow-position"));
36688
36689 DEFVAR_INT ("scroll-step", emacs_scroll_step,
36690 doc:
36691
36692
36693
36694 );
36695
36696 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
36697 doc:
36698
36699
36700
36701
36702
36703
36704
36705
36706
36707 );
36708 scroll_conservatively = 0;
36709
36710 DEFVAR_INT ("scroll-margin", scroll_margin,
36711 doc:
36712
36713 );
36714 scroll_margin = 0;
36715
36716 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
36717 doc:
36718
36719
36720
36721 );
36722 Vmaximum_scroll_margin = make_float (0.25);
36723
36724 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
36725 doc:
36726 );
36727 Vdisplay_pixels_per_inch = make_float (72.0);
36728
36729 #ifdef GLYPH_DEBUG
36730 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
36731 #endif
36732
36733 DEFVAR_LISP ("truncate-partial-width-windows",
36734 Vtruncate_partial_width_windows,
36735 doc:
36736
36737
36738
36739
36740
36741
36742
36743
36744
36745
36746
36747
36748
36749
36750
36751 );
36752 Vtruncate_partial_width_windows = make_fixnum (50);
36753
36754 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
36755
36756
36757
36758
36759
36760
36761
36762
36763
36764
36765
36766
36767
36768 );
36769 word_wrap_by_category = false;
36770
36771 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
36772 doc:
36773
36774 );
36775 Vline_number_display_limit = Qnil;
36776
36777 DEFVAR_INT ("line-number-display-limit-width",
36778 line_number_display_limit_width,
36779 doc:
36780
36781 );
36782 line_number_display_limit_width = 200;
36783
36784 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
36785 doc:
36786
36787 );
36788 highlight_nonselected_windows = false;
36789
36790 DEFVAR_BOOL ("multiple-frames", multiple_frames,
36791 doc:
36792
36793
36794 );
36795
36796 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
36797 doc:
36798
36799
36800
36801
36802 );
36803
36804 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
36805 doc:
36806
36807
36808
36809
36810
36811 );
36812
36813
36814 Lisp_Object icon_title_name_format
36815 = pure_list (empty_unibyte_string,
36816 build_pure_c_string ("%b - GNU Emacs at "),
36817 intern_c_string ("system-name"));
36818 Vicon_title_format
36819 = Vframe_title_format
36820 = pure_list (intern_c_string ("multiple-frames"),
36821 build_pure_c_string ("%b"),
36822 icon_title_name_format);
36823
36824 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
36825 doc:
36826
36827 );
36828 Vmessage_log_max = make_fixnum (1000);
36829
36830 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
36831 doc:
36832
36833
36834
36835
36836
36837
36838
36839
36840
36841
36842
36843
36844
36845 );
36846 Vwindow_scroll_functions = Qnil;
36847
36848 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
36849 doc:
36850
36851
36852
36853
36854
36855
36856
36857
36858
36859
36860
36861
36862
36863
36864
36865
36866
36867 );
36868 Vmouse_autoselect_window = Qnil;
36869
36870 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
36871 doc:
36872
36873
36874
36875
36876 );
36877 Vauto_resize_tab_bars = Qt;
36878
36879 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
36880 doc: );
36881 auto_raise_tab_bar_buttons_p = true;
36882
36883 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
36884 doc:
36885
36886
36887
36888
36889 );
36890 Vauto_resize_tool_bars = Qt;
36891
36892 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
36893 doc: );
36894 auto_raise_tool_bar_buttons_p = true;
36895
36896 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
36897 doc:
36898
36899
36900
36901
36902 );
36903 Vmake_cursor_line_fully_visible = Qt;
36904 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
36905
36906 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
36907 doc: );
36908 make_window_start_visible = false;
36909 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
36910 Fmake_variable_buffer_local (Qmake_window_start_visible);
36911
36912 DEFSYM (Qclose_tab, "close-tab");
36913 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
36914 doc:
36915
36916
36917
36918 );
36919 Vtab_bar_border = Qinternal_border_width;
36920
36921 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
36922 doc:
36923
36924
36925
36926 );
36927 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
36928
36929 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
36930 doc: );
36931 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
36932
36933 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
36934 doc:
36935
36936
36937
36938 );
36939 Vtool_bar_border = Qinternal_border_width;
36940
36941 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
36942 doc:
36943
36944
36945
36946 );
36947 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
36948
36949 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
36950 doc: );
36951 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
36952
36953 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
36954 doc:
36955
36956
36957
36958
36959
36960
36961
36962
36963 );
36964 Vtool_bar_style = Qnil;
36965
36966 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
36967 doc:
36968
36969 );
36970 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
36971
36972 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
36973 doc:
36974
36975
36976
36977
36978
36979
36980
36981
36982 );
36983 Vfontification_functions = Qnil;
36984 Fmake_variable_buffer_local (Qfontification_functions);
36985
36986 DEFVAR_BOOL ("unibyte-display-via-language-environment",
36987 unibyte_display_via_language_environment,
36988 doc:
36989
36990
36991
36992
36993
36994
36995 );
36996 unibyte_display_via_language_environment = false;
36997
36998 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
36999 doc:
37000
37001
37002
37003 );
37004 Vmax_mini_window_height = make_float (0.25);
37005
37006 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
37007 doc:
37008
37009
37010
37011
37012
37013
37014
37015
37016 );
37017
37018
37019
37020
37021
37022 Vresize_mini_windows = Qnil;
37023
37024 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
37025 doc:
37026
37027
37028
37029
37030
37031
37032
37033 );
37034 Vblink_cursor_alist = Qnil;
37035
37036 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
37037 doc:
37038
37039
37040
37041 );
37042 automatic_hscrolling = Qt;
37043 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
37044 DEFSYM (Qcurrent_line, "current-line");
37045
37046 DEFVAR_INT ("hscroll-margin", hscroll_margin,
37047 doc:
37048 );
37049 hscroll_margin = 5;
37050
37051 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37052 doc:
37053
37054
37055
37056
37057
37058
37059
37060
37061
37062
37063
37064
37065
37066 );
37067 Vhscroll_step = make_fixnum (0);
37068
37069 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37070 doc:
37071 );
37072 message_truncate_lines = false;
37073
37074 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37075 doc:
37076
37077
37078 );
37079 Vmenu_bar_update_hook = Qnil;
37080
37081 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37082 doc:
37083 );
37084 Vmenu_updating_frame = Qnil;
37085
37086 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37087 doc: );
37088 inhibit_menubar_update = false;
37089
37090 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37091 doc:
37092
37093
37094
37095
37096
37097
37098 );
37099 Vwrap_prefix = Qnil;
37100 DEFSYM (Qwrap_prefix, "wrap-prefix");
37101 Fmake_variable_buffer_local (Qwrap_prefix);
37102
37103 DEFVAR_LISP ("line-prefix", Vline_prefix,
37104 doc:
37105
37106
37107
37108
37109
37110
37111 );
37112 Vline_prefix = Qnil;
37113 DEFSYM (Qline_prefix, "line-prefix");
37114 Fmake_variable_buffer_local (Qline_prefix);
37115
37116 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37117 doc:
37118
37119
37120
37121
37122
37123
37124
37125
37126
37127
37128
37129
37130
37131
37132
37133
37134
37135
37136
37137
37138
37139
37140 );
37141 Vdisplay_line_numbers = Qnil;
37142 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37143 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37144 DEFSYM (Qrelative, "relative");
37145 DEFSYM (Qvisual, "visual");
37146
37147 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37148 doc:
37149
37150
37151
37152 );
37153 Vdisplay_line_numbers_width = Qnil;
37154 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37155 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37156
37157 DEFVAR_LISP ("display-line-numbers-current-absolute",
37158 Vdisplay_line_numbers_current_absolute,
37159 doc:
37160
37161 );
37162 Vdisplay_line_numbers_current_absolute = Qt;
37163
37164 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37165 doc: );
37166 display_line_numbers_widen = false;
37167 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37168 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37169
37170 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37171 doc:
37172
37173
37174 );
37175 display_line_numbers_offset = 0;
37176 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37177 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37178
37179 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37180 doc:
37181
37182
37183 );
37184 display_fill_column_indicator = false;
37185 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37186 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37187
37188 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37189 doc:
37190
37191
37192
37193 );
37194 Vdisplay_fill_column_indicator_column = Qt;
37195 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37196 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37197
37198 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37199 doc:
37200
37201
37202 );
37203 Vdisplay_fill_column_indicator_character = Qnil;
37204 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37205 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37206
37207 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37208 doc:
37209
37210
37211 );
37212 display_line_numbers_major_tick = 0;
37213
37214 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37215 doc:
37216
37217
37218 );
37219 display_line_numbers_minor_tick = 0;
37220
37221 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37222 doc: );
37223 inhibit_eval_during_redisplay = false;
37224
37225 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37226 doc: );
37227 inhibit_free_realized_faces = false;
37228
37229 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37230 doc:
37231
37232 );
37233 inhibit_bidi_mirroring = false;
37234
37235 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37236 doc:
37237
37238
37239
37240 );
37241 bidi_inhibit_bpa = false;
37242
37243 #ifdef GLYPH_DEBUG
37244 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37245 doc: );
37246 inhibit_try_window_id = false;
37247
37248 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37249 doc: );
37250 inhibit_try_window_reusing = false;
37251
37252 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37253 doc: );
37254 inhibit_try_cursor_movement = false;
37255 #endif
37256
37257 DEFVAR_INT ("overline-margin", overline_margin,
37258 doc:
37259
37260 );
37261 overline_margin = 2;
37262
37263 DEFVAR_INT ("underline-minimum-offset",
37264 underline_minimum_offset,
37265 doc:
37266
37267
37268
37269 );
37270 underline_minimum_offset = 1;
37271 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37272
37273 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37274 doc:
37275
37276 );
37277 display_hourglass_p = true;
37278
37279 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37280 doc: );
37281 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37282
37283 #ifdef HAVE_WINDOW_SYSTEM
37284 hourglass_atimer = NULL;
37285 hourglass_shown_p = false;
37286 #endif
37287
37288
37289 DEFSYM (Qglyphless_char, "glyphless-char");
37290
37291
37292 DEFSYM (Qhex_code, "hex-code");
37293 DEFSYM (Qempty_box, "empty-box");
37294 DEFSYM (Qthin_space, "thin-space");
37295 DEFSYM (Qzero_width, "zero-width");
37296
37297 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37298 doc:
37299
37300
37301 );
37302 Vpre_redisplay_function = intern ("ignore");
37303
37304
37305 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37306 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37307
37308 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37309 doc:
37310
37311
37312
37313
37314
37315
37316
37317
37318
37319
37320
37321
37322
37323
37324
37325
37326
37327
37328
37329
37330
37331
37332
37333 );
37334 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37335 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37336 Qempty_box);
37337
37338 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37339 doc: );
37340 Vdebug_on_message = Qnil;
37341
37342 DEFVAR_LISP ("set-message-function", Vset_message_function,
37343 doc:
37344
37345
37346
37347
37348
37349
37350
37351
37352
37353 );
37354 Vset_message_function = Qnil;
37355
37356 DEFSYM (Qdont_clear_message, "dont-clear-message");
37357 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37358 doc:
37359
37360
37361
37362
37363
37364
37365
37366
37367
37368
37369 );
37370 Vclear_message_function = Qnil;
37371
37372 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37373 doc:
37374 );
37375 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37376
37377 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37378 doc:
37379 );
37380 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37381
37382 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37383 doc: );
37384
37385
37386 redisplay__inhibit_bidi = true;
37387
37388 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37389 doc:
37390
37391 );
37392 display_raw_bytes_as_hex = false;
37393
37394 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37395 doc:
37396
37397 );
37398 mouse_fine_grained_tracking = false;
37399
37400 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37401 doc: );
37402 tab_bar__dragging_in_progress = false;
37403
37404 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37405 doc:
37406
37407
37408
37409 );
37410 redisplay_skip_initial_frame = true;
37411
37412 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37413 redisplay_skip_fontification_on_input,
37414 doc:
37415
37416
37417
37418
37419
37420
37421
37422 );
37423 redisplay_skip_fontification_on_input = false;
37424
37425 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37426 redisplay_adhoc_scroll_in_resize_mini_windows,
37427 doc:
37428
37429 );
37430
37431 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37432
37433 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37434 doc:
37435
37436 );
37437 composition_break_at_point = false;
37438
37439 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37440 doc:
37441
37442
37443
37444
37445
37446
37447
37448
37449
37450
37451
37452 );
37453 max_redisplay_ticks = 0;
37454 }
37455
37456
37457
37458
37459 void
37460 init_xdisp (void)
37461 {
37462 CHARPOS (this_line_start_pos) = 0;
37463
37464 echo_area_window = minibuf_window;
37465
37466 if (!noninteractive)
37467 {
37468 struct window *m = XWINDOW (minibuf_window);
37469 Lisp_Object frame = m->frame;
37470 struct frame *f = XFRAME (frame);
37471 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37472 struct window *r = XWINDOW (root);
37473 int i;
37474
37475 r->top_line = FRAME_TOP_MARGIN (f);
37476 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37477 r->total_cols = FRAME_COLS (f);
37478 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37479 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
37480 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37481
37482 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37483 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37484 m->total_cols = FRAME_COLS (f);
37485 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37486 m->total_lines = 1;
37487 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37488
37489 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37490 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37491 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37492
37493
37494 for (i = 0; i < 3; ++i)
37495 default_invis_vector[i] = make_fixnum ('.');
37496 }
37497
37498 {
37499
37500
37501 int size = 100;
37502 mode_line_noprop_buf = xmalloc (size);
37503 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37504 mode_line_noprop_ptr = mode_line_noprop_buf;
37505 mode_line_target = MODE_LINE_DISPLAY;
37506 }
37507
37508 help_echo_showing_p = false;
37509 }
37510
37511 #ifdef HAVE_WINDOW_SYSTEM
37512
37513
37514
37515
37516
37517 static void
37518 show_hourglass (struct atimer *timer)
37519 {
37520
37521
37522
37523 hourglass_atimer = NULL;
37524
37525 if (!hourglass_shown_p)
37526 {
37527 Lisp_Object tail, frame;
37528
37529 block_input ();
37530
37531 FOR_EACH_FRAME (tail, frame)
37532 {
37533 struct frame *f = XFRAME (frame);
37534
37535 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37536 && FRAME_RIF (f)->show_hourglass)
37537 FRAME_RIF (f)->show_hourglass (f);
37538 }
37539
37540 hourglass_shown_p = true;
37541 unblock_input ();
37542 }
37543 }
37544
37545
37546
37547 void
37548 start_hourglass (void)
37549 {
37550 struct timespec delay;
37551
37552 cancel_hourglass ();
37553
37554 if (FIXNUMP (Vhourglass_delay)
37555 && XFIXNUM (Vhourglass_delay) > 0)
37556 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37557 TYPE_MAXIMUM (time_t)),
37558 0);
37559 else if (FLOATP (Vhourglass_delay)
37560 && XFLOAT_DATA (Vhourglass_delay) > 0)
37561 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37562 else
37563 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37564
37565 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37566 show_hourglass, NULL);
37567 }
37568
37569
37570
37571
37572 void
37573 cancel_hourglass (void)
37574 {
37575 if (hourglass_atimer)
37576 {
37577 cancel_atimer (hourglass_atimer);
37578 hourglass_atimer = NULL;
37579 }
37580
37581 if (hourglass_shown_p)
37582 {
37583 Lisp_Object tail, frame;
37584
37585 block_input ();
37586
37587 FOR_EACH_FRAME (tail, frame)
37588 {
37589 struct frame *f = XFRAME (frame);
37590
37591 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37592 && FRAME_RIF (f)->hide_hourglass)
37593 FRAME_RIF (f)->hide_hourglass (f);
37594 #ifdef HAVE_NTGUI
37595
37596 else if (!FRAME_W32_P (f))
37597 w32_arrow_cursor ();
37598 #endif
37599 }
37600
37601 hourglass_shown_p = false;
37602 unblock_input ();
37603 }
37604 }
37605
37606
37607
37608
37609
37610
37611
37612
37613 static int
37614 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37615 struct window *w,
37616 struct face *original_face,
37617 struct face *mouse_face)
37618 {
37619 int sum = 0;
37620
37621 bool do_left_box_p = g->left_box_line_p;
37622 bool do_right_box_p = g->right_box_line_p;
37623
37624
37625
37626 if (g->type == IMAGE_GLYPH)
37627 {
37628 if (!row->reversed_p)
37629 {
37630 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37631 g->u.img_id);
37632 do_left_box_p = g->left_box_line_p &&
37633 g->slice.img.x == 0;
37634 do_right_box_p = g->right_box_line_p &&
37635 g->slice.img.x + g->slice.img.width == img->width;
37636 }
37637 else
37638 {
37639 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37640 g->u.img_id);
37641 do_left_box_p = g->left_box_line_p &&
37642 g->slice.img.x + g->slice.img.width == img->width;
37643 do_right_box_p = g->right_box_line_p &&
37644 g->slice.img.x == 0;
37645 }
37646 }
37647
37648
37649 if (do_left_box_p)
37650 sum -= max (0, original_face->box_vertical_line_width);
37651
37652
37653 if (do_right_box_p)
37654 sum -= max (0, original_face->box_vertical_line_width);
37655
37656 if (g->left_box_line_p)
37657 sum += max (0, mouse_face->box_vertical_line_width);
37658 if (g->right_box_line_p)
37659 sum += max (0, mouse_face->box_vertical_line_width);
37660
37661 return sum;
37662 }
37663
37664
37665
37666
37667
37668
37669
37670
37671
37672 static void
37673 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
37674 int *offset)
37675 {
37676 int sum = 0;
37677
37678 if (row->mode_line_p)
37679 return;
37680
37681 block_input ();
37682
37683 struct frame *f = WINDOW_XFRAME (w);
37684 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
37685 struct glyph *start, *end;
37686 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
37687 int hpos = w->phys_cursor.hpos;
37688 end = &row->glyphs[TEXT_AREA][hpos];
37689
37690 if (!row->reversed_p)
37691 {
37692 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37693 hlinfo->mouse_face_beg_row)
37694 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
37695 else
37696 start = row->glyphs[TEXT_AREA];
37697 }
37698 else
37699 {
37700 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37701 hlinfo->mouse_face_end_row)
37702 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
37703 else
37704 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
37705 }
37706
37707
37708
37709
37710 for ( ; row->reversed_p ? start > end : start < end;
37711 row->reversed_p ? --start : ++start)
37712 sum += adjust_glyph_width_for_mouse_face (start, row, w,
37713 FACE_FROM_ID (f, start->face_id),
37714 mouse_face);
37715
37716 if (row->reversed_p)
37717 sum = -sum;
37718
37719 *offset = sum;
37720
37721 unblock_input ();
37722 }
37723 #endif