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
- get_tab_bar_item_kbd
- 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
- pad_mode_line
- 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
- gui_union_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 (!ckd_mul (&icol, icol, char_width)
641 && !ckd_add (&icol, icol, it->lnum_pixel_width))
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 pad_mode_line (struct it *, bool);
1233 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
1234 static bool coords_in_mouse_face_p (struct window *, int, int);
1235 static void reset_box_start_end_flags (struct it *);
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249 int
1250 window_text_bottom_y (struct window *w)
1251 {
1252 int height = WINDOW_PIXEL_HEIGHT (w);
1253
1254 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1255
1256 if (window_wants_mode_line (w))
1257 height -= CURRENT_MODE_LINE_HEIGHT (w);
1258
1259 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1260
1261 return height;
1262 }
1263
1264
1265
1266
1267
1268 int
1269 window_box_width (struct window *w, enum glyph_row_area area)
1270 {
1271 int width = w->pixel_width;
1272
1273 if (!w->pseudo_window_p)
1274 {
1275 width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
1276 width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
1277
1278 if (area == TEXT_AREA)
1279 width -= (WINDOW_MARGINS_WIDTH (w)
1280 + WINDOW_FRINGES_WIDTH (w));
1281 else if (area == LEFT_MARGIN_AREA)
1282 width = WINDOW_LEFT_MARGIN_WIDTH (w);
1283 else if (area == RIGHT_MARGIN_AREA)
1284 width = WINDOW_RIGHT_MARGIN_WIDTH (w);
1285 }
1286
1287
1288
1289 return max (0, width);
1290 }
1291
1292
1293
1294
1295
1296 int
1297 window_box_height (struct window *w)
1298 {
1299 struct frame *f = XFRAME (w->frame);
1300 int height = WINDOW_PIXEL_HEIGHT (w);
1301
1302 eassert (height >= 0);
1303
1304 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1305 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1306
1307
1308
1309
1310
1311
1312
1313 if (window_wants_mode_line (w))
1314 {
1315 if (w->mode_line_height >= 0)
1316 height -= w->mode_line_height;
1317 else
1318 {
1319 struct glyph_row *ml_row
1320 = (w->current_matrix && w->current_matrix->rows
1321 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1322 : 0);
1323 if (ml_row && ml_row->mode_line_p)
1324 height -= ml_row->height;
1325 else
1326 height -= estimate_mode_line_height
1327 (f, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w));
1328 }
1329 }
1330
1331 if (window_wants_tab_line (w))
1332 {
1333 if (w->tab_line_height >= 0)
1334 height -= w->tab_line_height;
1335 else
1336 {
1337 struct glyph_row *tl_row
1338 = (w->current_matrix && w->current_matrix->rows
1339 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
1340 : 0);
1341 if (tl_row && tl_row->mode_line_p)
1342 height -= tl_row->height;
1343 else
1344 height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
1345 }
1346 }
1347
1348 if (window_wants_header_line (w))
1349 {
1350 if (w->header_line_height >= 0)
1351 height -= w->header_line_height;
1352 else
1353 {
1354 struct glyph_row *hl_row
1355 = (w->current_matrix && w->current_matrix->rows
1356 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1357 : 0);
1358 if (hl_row && hl_row->mode_line_p)
1359 height -= hl_row->height;
1360 else
1361 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1362 }
1363 }
1364
1365
1366
1367 return max (0, height);
1368 }
1369
1370
1371
1372
1373
1374 int
1375 window_box_left_offset (struct window *w, enum glyph_row_area area)
1376 {
1377 int x;
1378
1379 if (w->pseudo_window_p)
1380 return 0;
1381
1382 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1383
1384 if (area == TEXT_AREA)
1385 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1386 + window_box_width (w, LEFT_MARGIN_AREA));
1387 else if (area == RIGHT_MARGIN_AREA)
1388 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1389 + window_box_width (w, LEFT_MARGIN_AREA)
1390 + window_box_width (w, TEXT_AREA)
1391 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1392 ? 0
1393 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1394 else if (area == LEFT_MARGIN_AREA
1395 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1396 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1397
1398
1399 return min (x, w->pixel_width);
1400 }
1401
1402
1403
1404
1405
1406
1407 static int
1408 window_box_right_offset (struct window *w, enum glyph_row_area area)
1409 {
1410
1411 return min (window_box_left_offset (w, area) + window_box_width (w, area),
1412 w->pixel_width);
1413 }
1414
1415
1416
1417
1418
1419 int
1420 window_box_left (struct window *w, enum glyph_row_area area)
1421 {
1422 struct frame *f = XFRAME (w->frame);
1423 int x;
1424
1425 if (w->pseudo_window_p)
1426 return FRAME_INTERNAL_BORDER_WIDTH (f);
1427
1428 x = (WINDOW_LEFT_EDGE_X (w)
1429 + window_box_left_offset (w, area));
1430
1431 return x;
1432 }
1433
1434
1435
1436
1437
1438
1439 int
1440 window_box_right (struct window *w, enum glyph_row_area area)
1441 {
1442 return window_box_left (w, area) + window_box_width (w, area);
1443 }
1444
1445
1446
1447
1448
1449
1450
1451
1452 void
1453 window_box (struct window *w, enum glyph_row_area area, int *box_x,
1454 int *box_y, int *box_width, int *box_height)
1455 {
1456 if (box_width)
1457 *box_width = window_box_width (w, area);
1458 if (box_height)
1459 *box_height = window_box_height (w);
1460 if (box_x)
1461 *box_x = window_box_left (w, area);
1462 if (box_y)
1463 {
1464 *box_y = WINDOW_TOP_EDGE_Y (w);
1465 if (window_wants_tab_line (w))
1466 *box_y += CURRENT_TAB_LINE_HEIGHT (w);
1467 if (window_wants_header_line (w))
1468 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1469 }
1470 }
1471
1472 #ifdef HAVE_WINDOW_SYSTEM
1473
1474
1475
1476
1477
1478
1479
1480
1481 static void
1482 window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
1483 int *bottom_right_x, int *bottom_right_y)
1484 {
1485 window_box (w, ANY_AREA, top_left_x, top_left_y,
1486 bottom_right_x, bottom_right_y);
1487 *bottom_right_x += *top_left_x;
1488 *bottom_right_y += *top_left_y;
1489 }
1490
1491 #endif
1492
1493
1494
1495
1496
1497
1498
1499
1500 int
1501 line_bottom_y (struct it *it)
1502 {
1503 int line_height = it->max_ascent + it->max_descent;
1504 int line_top_y = it->current_y;
1505
1506 if (line_height == 0)
1507 {
1508 if (last_height)
1509 line_height = last_height;
1510 else if (IT_CHARPOS (*it) < ZV)
1511 {
1512 move_it_by_lines (it, 1);
1513 line_height = (it->max_ascent || it->max_descent
1514 ? it->max_ascent + it->max_descent
1515 : last_height);
1516 }
1517 else
1518 {
1519 struct glyph_row *row = it->glyph_row;
1520
1521
1522 it->glyph_row = NULL;
1523 it->what = IT_CHARACTER;
1524 it->c = ' ';
1525 it->len = 1;
1526 PRODUCE_GLYPHS (it);
1527 line_height = it->ascent + it->descent;
1528 it->glyph_row = row;
1529 }
1530 }
1531
1532 return line_top_y + line_height;
1533 }
1534
1535 DEFUN ("line-pixel-height", Fline_pixel_height,
1536 Sline_pixel_height, 0, 0, 0,
1537 doc:
1538
1539 )
1540 (void)
1541 {
1542 struct it it;
1543 struct text_pos pt;
1544 struct window *w = XWINDOW (selected_window);
1545 struct buffer *old_buffer = NULL;
1546 Lisp_Object result;
1547
1548 if (XBUFFER (w->contents) != current_buffer)
1549 {
1550 old_buffer = current_buffer;
1551 set_buffer_internal_1 (XBUFFER (w->contents));
1552 }
1553 SET_TEXT_POS (pt, PT, PT_BYTE);
1554 void *itdata = bidi_shelve_cache ();
1555 start_display (&it, w, pt);
1556
1557
1558
1559 move_it_by_lines (&it, 0);
1560 it.vpos = it.current_y = 0;
1561 last_height = 0;
1562 result = make_fixnum (line_bottom_y (&it));
1563 if (old_buffer)
1564 set_buffer_internal_1 (old_buffer);
1565
1566 bidi_unshelve_cache (itdata, false);
1567 return result;
1568 }
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584 int
1585 default_line_pixel_height (struct window *w)
1586 {
1587 struct frame *f = WINDOW_XFRAME (w);
1588 int height = FRAME_LINE_HEIGHT (f);
1589
1590 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1591 {
1592 struct buffer *b = XBUFFER (w->contents);
1593 Lisp_Object val = BVAR (b, extra_line_spacing);
1594
1595 if (NILP (val))
1596 val = BVAR (&buffer_defaults, extra_line_spacing);
1597 if (!NILP (val))
1598 {
1599 if (RANGED_FIXNUMP (0, val, INT_MAX))
1600 height += XFIXNAT (val);
1601 else if (FLOATP (val))
1602 {
1603 int addon = XFLOAT_DATA (val) * height + 0.5;
1604
1605 if (addon >= 0)
1606 height += addon;
1607 }
1608 }
1609 else
1610 height += f->extra_line_spacing;
1611 }
1612
1613 return height;
1614 }
1615
1616
1617
1618 static Lisp_Object
1619 string_from_display_spec (Lisp_Object spec)
1620 {
1621 if (VECTORP (spec))
1622 {
1623 for (ptrdiff_t i = 0; i < ASIZE (spec); i++)
1624 if (STRINGP (AREF (spec, i)))
1625 return AREF (spec, i);
1626 }
1627 else
1628 {
1629 for (; CONSP (spec); spec = XCDR (spec))
1630 if (STRINGP (XCAR (spec)))
1631 return XCAR (spec);
1632 }
1633 return spec;
1634 }
1635
1636
1637
1638
1639
1640 static int
1641 window_hscroll_limited (struct window *w, struct frame *f)
1642 {
1643 ptrdiff_t window_hscroll = w->hscroll;
1644 int window_text_width = window_box_width (w, TEXT_AREA);
1645 int colwidth = FRAME_COLUMN_WIDTH (f);
1646
1647 if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
1648 window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
1649
1650 return window_hscroll;
1651 }
1652
1653
1654
1655
1656
1657 static void
1658 reset_box_start_end_flags (struct it *it)
1659 {
1660
1661
1662 if (it->area == TEXT_AREA
1663
1664 && !(it->what == IT_IMAGE && it->image_id < 0))
1665 {
1666
1667
1668
1669
1670 if (it->face_box_p)
1671 it->start_of_box_run_p = false;
1672 it->end_of_box_run_p = false;
1673 }
1674 }
1675
1676
1677
1678
1679
1680
1681
1682 bool
1683 pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1684 int *rtop, int *rbot, int *rowh, int *vpos)
1685 {
1686 struct it it;
1687 void *itdata = bidi_shelve_cache ();
1688 struct text_pos top;
1689 bool visible_p = false;
1690 struct buffer *old_buffer = NULL;
1691 bool r2l = false;
1692
1693 if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
1694 return visible_p;
1695
1696 if (XBUFFER (w->contents) != current_buffer)
1697 {
1698 old_buffer = current_buffer;
1699 set_buffer_internal_1 (XBUFFER (w->contents));
1700 }
1701
1702 SET_TEXT_POS_FROM_MARKER (top, w->start);
1703
1704
1705
1706
1707 if (CHARPOS (top) > ZV || CHARPOS (top) < BEGV)
1708 SET_TEXT_POS (top, BEGV, BEGV_BYTE);
1709
1710
1711
1712 if (charpos >= 0 && CHARPOS (top) > charpos)
1713 return visible_p;
1714
1715
1716
1717
1718
1719
1720
1721
1722 int prev_mode_line_height = w->mode_line_height;
1723 int prev_header_line_height = w->header_line_height;
1724 int prev_tab_line_height = w->tab_line_height;
1725
1726 if (window_wants_mode_line (w))
1727 {
1728 Lisp_Object window_mode_line_format
1729 = window_parameter (w, Qmode_line_format);
1730
1731 w->mode_line_height
1732 = display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
1733 NILP (window_mode_line_format)
1734 ? BVAR (current_buffer, mode_line_format)
1735 : window_mode_line_format);
1736 }
1737
1738 if (window_wants_tab_line (w))
1739 {
1740 Lisp_Object window_tab_line_format
1741 = window_parameter (w, Qtab_line_format);
1742
1743 w->tab_line_height
1744 = display_mode_line (w, TAB_LINE_FACE_ID,
1745 NILP (window_tab_line_format)
1746 ? BVAR (current_buffer, tab_line_format)
1747 : window_tab_line_format);
1748 }
1749
1750 if (window_wants_header_line (w))
1751 {
1752 Lisp_Object window_header_line_format
1753 = window_parameter (w, Qheader_line_format);
1754
1755 w->header_line_height
1756 = display_mode_line (w, HEADER_LINE_FACE_ID,
1757 NILP (window_header_line_format)
1758 ? BVAR (current_buffer, header_line_format)
1759 : window_header_line_format);
1760 }
1761
1762 start_display (&it, w, top);
1763 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
1764 (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
1765
1766
1767
1768 if (!NILP (Vdisplay_line_numbers)
1769 && it.current_x >= it.first_visible_x
1770 && IT_CHARPOS (it) == charpos
1771 && !it.line_number_produced_p)
1772 {
1773
1774
1775
1776 if (!it.lnum_pixel_width)
1777 {
1778 struct it it2;
1779 void *it2data = NULL;
1780
1781 SAVE_IT (it2, it, it2data);
1782 move_it_by_lines (&it, 1);
1783 it2.lnum_pixel_width = it.lnum_pixel_width;
1784 RESTORE_IT (&it, &it2, it2data);
1785 }
1786 it.current_x += it.lnum_pixel_width;
1787 }
1788
1789 if (charpos >= 0
1790 && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
1791 && IT_CHARPOS (it) >= charpos)
1792
1793
1794
1795 || (it.bidi_p && it.bidi_it.scan_dir == -1
1796 && IT_CHARPOS (it) <= charpos)))
1797 {
1798
1799
1800
1801
1802
1803
1804 int top_x = it.current_x;
1805 int top_y = it.current_y;
1806 int window_top_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
1807 int bottom_y;
1808 struct it save_it;
1809 void *save_it_data = NULL;
1810
1811
1812 SAVE_IT (save_it, it, save_it_data);
1813 last_height = 0;
1814 bottom_y = line_bottom_y (&it);
1815 if (top_y < window_top_y)
1816 visible_p = bottom_y > window_top_y;
1817 else if (top_y < it.last_visible_y)
1818 visible_p = true;
1819 if (bottom_y >= it.last_visible_y
1820 && it.bidi_p && it.bidi_it.scan_dir == -1
1821 && IT_CHARPOS (it) < charpos)
1822 {
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833 int ten_more_lines = 10 * default_line_pixel_height (w);
1834
1835 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1836 MOVE_TO_POS | MOVE_TO_Y);
1837 if (it.current_y > top_y)
1838 visible_p = false;
1839
1840 }
1841 RESTORE_IT (&it, &save_it, save_it_data);
1842 if (visible_p)
1843 {
1844 if (it.method == GET_FROM_DISPLAY_VECTOR)
1845 {
1846
1847
1848 if (charpos < 2 || top.charpos >= charpos)
1849 top_x = it.glyph_row->x;
1850 else
1851 {
1852 struct it it2, it2_prev;
1853
1854
1855
1856
1857
1858
1859 start_display (&it2, w, top);
1860 it2.glyph_row = NULL;
1861 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
1862
1863
1864
1865
1866 if (IT_CHARPOS (it2) != charpos - 1)
1867 it2_prev = it2;
1868 else
1869 {
1870
1871
1872
1873 do {
1874 get_next_display_element (&it2);
1875 PRODUCE_GLYPHS (&it2);
1876 it2_prev = it2;
1877 set_iterator_to_next (&it2, true);
1878 } while (it2.method == GET_FROM_DISPLAY_VECTOR
1879 && IT_CHARPOS (it2) < charpos);
1880 }
1881 if (ITERATOR_AT_END_OF_LINE_P (&it2_prev)
1882 || it2_prev.current_x > it2_prev.last_visible_x)
1883 top_x = it.glyph_row->x;
1884 else
1885 {
1886 top_x = it2_prev.current_x;
1887 top_y = it2_prev.current_y;
1888 }
1889 }
1890 }
1891 else if (IT_CHARPOS (it) != charpos)
1892 {
1893 Lisp_Object cpos = make_fixnum (charpos);
1894 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1895 Lisp_Object string = string_from_display_spec (spec);
1896 struct text_pos tpos;
1897 bool newline_in_string
1898 = (STRINGP (string)
1899 && memchr (SDATA (string), '\n', SBYTES (string)));
1900
1901 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1902 bool replacing_spec_p
1903 = (!NILP (spec)
1904 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1905 charpos, FRAME_WINDOW_P (it.f)));
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922 if (replacing_spec_p)
1923 {
1924 Lisp_Object startpos, endpos;
1925 EMACS_INT start, end;
1926 struct it it3;
1927
1928
1929
1930 endpos =
1931 Fnext_single_char_property_change (cpos, Qdisplay,
1932 Qnil, Qnil);
1933 startpos =
1934 Fprevious_single_char_property_change (endpos, Qdisplay,
1935 Qnil, Qnil);
1936 start = XFIXNAT (startpos);
1937 end = XFIXNAT (endpos);
1938
1939
1940 start_display (&it3, w, top);
1941 if (start > CHARPOS (top))
1942 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
1943
1944
1945
1946
1947 if (it3.method == GET_FROM_BUFFER
1948 && (it3.c == '\n'
1949 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1950 move_it_by_lines (&it3, 1);
1951 else if (move_it_in_display_line_to (&it3, -1,
1952 it3.current_x
1953 + it3.pixel_width,
1954 MOVE_TO_X)
1955 == MOVE_LINE_CONTINUED)
1956 {
1957 move_it_by_lines (&it3, 1);
1958
1959
1960
1961 if (it3.line_wrap == WORD_WRAP)
1962 move_it_by_lines (&it3, -1);
1963 }
1964
1965
1966
1967 top_y = it3.current_y;
1968 if (it3.bidi_p)
1969 {
1970
1971
1972
1973
1974
1975 start_display (&it3, w, top);
1976 move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
1977 if (it3.current_y < top_y)
1978 top_y = it3.current_y;
1979 }
1980
1981
1982
1983 start_display (&it3, w, top);
1984 it3.glyph_row = NULL;
1985 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
1986
1987
1988
1989
1990
1991
1992
1993 bool it3_moved = false;
1994 int top_x_before_string = it3.current_x;
1995
1996
1997
1998
1999
2000 while (get_next_display_element (&it3))
2001 {
2002 if (!EQ (it3.object, string))
2003 top_x_before_string = it3.current_x;
2004 PRODUCE_GLYPHS (&it3);
2005 if ((it3.bidi_it.scan_dir == 1
2006 && IT_CHARPOS (it3) >= charpos)
2007 || (it3.bidi_it.scan_dir == -1
2008 && IT_CHARPOS (it3) <= charpos)
2009 || ITERATOR_AT_END_OF_LINE_P (&it3))
2010 break;
2011 it3_moved = true;
2012 set_iterator_to_next (&it3, false);
2013 }
2014 top_x = it3.current_x - it3.pixel_width;
2015
2016
2017
2018 if (!it3.line_number_produced_p)
2019 {
2020 if (it3.lnum_pixel_width > 0)
2021 {
2022 top_x += it3.lnum_pixel_width;
2023 top_x_before_string += it3.lnum_pixel_width;
2024 }
2025 else if (it.line_number_produced_p)
2026 {
2027 top_x += it.lnum_pixel_width;
2028 top_x_before_string += it3.lnum_pixel_width;
2029 }
2030 }
2031
2032
2033
2034
2035
2036
2037 if (it3_moved
2038 && newline_in_string
2039 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
2040 top_x = top_x_before_string;
2041 }
2042 }
2043
2044 *x = top_x;
2045
2046
2047
2048
2049 if (it.ascent == 0 && it.what == IT_IMAGE
2050 && it.method != GET_FROM_IMAGE
2051 && it.image_id < 0
2052 && it.max_ascent > 0)
2053 *y = max (top_y, window_top_y);
2054 else
2055 *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
2056 *rtop = max (0, window_top_y - top_y);
2057 *rbot = max (0, bottom_y - it.last_visible_y);
2058 *rowh = max (0, (min (bottom_y, it.last_visible_y)
2059 - max (top_y, window_top_y)));
2060 *vpos = it.vpos;
2061 if (it.bidi_it.paragraph_dir == R2L)
2062 r2l = true;
2063 }
2064 }
2065 else
2066 {
2067
2068
2069
2070 struct it it2;
2071 void *it2data = NULL;
2072
2073 SAVE_IT (it2, it, it2data);
2074 if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
2075 move_it_by_lines (&it, 1);
2076 if (charpos < IT_CHARPOS (it)
2077 || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
2078 {
2079 visible_p = true;
2080 RESTORE_IT (&it2, &it2, it2data);
2081 move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
2082 *x = it2.current_x;
2083 if (it2.ascent == 0 && it2.what == IT_IMAGE
2084 && it2.method != GET_FROM_IMAGE
2085 && it2.image_id < 0
2086 && it2.max_ascent > 0)
2087 *y = it2.current_y;
2088 else
2089 *y = it2.current_y + it2.max_ascent - it2.ascent;
2090 *rtop = max (0, -it2.current_y);
2091 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
2092 - it.last_visible_y));
2093 *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
2094 it.last_visible_y)
2095 - max (max (it2.current_y,
2096 WINDOW_TAB_LINE_HEIGHT (w)),
2097 WINDOW_HEADER_LINE_HEIGHT (w))));
2098 *vpos = it2.vpos;
2099 if (it2.bidi_it.paragraph_dir == R2L)
2100 r2l = true;
2101 }
2102 else
2103 bidi_unshelve_cache (it2data, true);
2104 }
2105 bidi_unshelve_cache (itdata, false);
2106
2107 if (old_buffer)
2108 set_buffer_internal_1 (old_buffer);
2109
2110 if (visible_p)
2111 {
2112 if (w->hscroll > 0)
2113 *x -=
2114 window_hscroll_limited (w, WINDOW_XFRAME (w))
2115 * WINDOW_FRAME_COLUMN_WIDTH (w);
2116
2117
2118
2119
2120
2121 if (r2l)
2122 *x = window_box_width (w, TEXT_AREA) - *x - 1;
2123 }
2124
2125 #if false
2126
2127 if (visible_p)
2128 fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
2129 charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
2130 else
2131 fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
2132 #endif
2133
2134
2135 w->mode_line_height = prev_mode_line_height;
2136 w->header_line_height = prev_header_line_height;
2137 w->tab_line_height = prev_tab_line_height;
2138
2139 return visible_p;
2140 }
2141
2142
2143
2144
2145
2146
2147
2148 static int
2149 check_char_and_length (const unsigned char *str, int *len)
2150 {
2151 int c = string_char_and_length (str, len);
2152 if (!CHAR_VALID_P (c))
2153
2154
2155
2156 c = '?';
2157
2158 return c;
2159 }
2160
2161
2162
2163
2164
2165
2166 static struct text_pos
2167 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
2168 {
2169 eassert (STRINGP (string) && nchars >= 0);
2170
2171 if (STRING_MULTIBYTE (string))
2172 {
2173 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
2174
2175 while (nchars--)
2176 {
2177 int len = BYTES_BY_CHAR_HEAD (*p);
2178 p += len;
2179 CHARPOS (pos) += 1;
2180 BYTEPOS (pos) += len;
2181 }
2182 }
2183 else
2184 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
2185
2186 return pos;
2187 }
2188
2189
2190
2191
2192
2193 static struct text_pos
2194 string_pos (ptrdiff_t charpos, Lisp_Object string)
2195 {
2196 struct text_pos pos;
2197 eassert (STRINGP (string));
2198 eassert (charpos >= 0);
2199 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
2200 return pos;
2201 }
2202
2203
2204
2205
2206
2207
2208 static struct text_pos
2209 c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
2210 {
2211 struct text_pos pos;
2212
2213 eassert (s != NULL);
2214 eassert (charpos >= 0);
2215
2216 if (multibyte_p)
2217 {
2218 SET_TEXT_POS (pos, 0, 0);
2219 while (charpos--)
2220 {
2221 int len = BYTES_BY_CHAR_HEAD (*s);
2222 s += len;
2223 CHARPOS (pos) += 1;
2224 BYTEPOS (pos) += len;
2225 }
2226 }
2227 else
2228 SET_TEXT_POS (pos, charpos, charpos);
2229
2230 return pos;
2231 }
2232
2233
2234
2235
2236
2237 static ptrdiff_t
2238 number_of_chars (const char *s, bool multibyte_p)
2239 {
2240 ptrdiff_t nchars;
2241
2242 if (multibyte_p)
2243 {
2244 ptrdiff_t rest = strlen (s);
2245 const unsigned char *p = (const unsigned char *) s;
2246
2247 for (nchars = 0; rest > 0; ++nchars)
2248 {
2249 int len = BYTES_BY_CHAR_HEAD (*p);
2250 rest -= len, p += len;
2251 }
2252 }
2253 else
2254 nchars = strlen (s);
2255
2256 return nchars;
2257 }
2258
2259
2260
2261
2262
2263
2264 static void
2265 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
2266 {
2267 eassert (STRINGP (string));
2268 eassert (CHARPOS (*newpos) >= CHARPOS (pos));
2269
2270 if (STRING_MULTIBYTE (string))
2271 *newpos = string_pos_nchars_ahead (pos, string,
2272 CHARPOS (*newpos) - CHARPOS (pos));
2273 else
2274 BYTEPOS (*newpos) = CHARPOS (*newpos);
2275 }
2276
2277
2278
2279
2280
2281 int
2282 estimate_mode_line_height (struct frame *f, enum face_id face_id)
2283 {
2284 #ifdef HAVE_WINDOW_SYSTEM
2285 if (FRAME_WINDOW_P (f))
2286 {
2287 int height = FONT_HEIGHT (FRAME_FONT (f));
2288
2289
2290
2291 if (FRAME_FACE_CACHE (f))
2292 {
2293 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2294 if (face)
2295 {
2296 if (face->font)
2297 height = normal_char_height (face->font, -1);
2298 if (face->box_horizontal_line_width > 0)
2299 height += 2 * face->box_horizontal_line_width;
2300 }
2301 }
2302
2303 return height;
2304 }
2305 #endif
2306
2307 return 1;
2308 }
2309
2310
2311
2312
2313
2314
2315 void
2316 pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2317 NativeRectangle *bounds, bool noclip)
2318 {
2319
2320 #ifdef HAVE_WINDOW_SYSTEM
2321 if (FRAME_WINDOW_P (f))
2322 {
2323
2324
2325 if (pix_x < 0)
2326 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
2327 if (pix_y < 0)
2328 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
2329
2330 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
2331 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
2332
2333 if (bounds)
2334 STORE_NATIVE_RECT (*bounds,
2335 FRAME_COL_TO_PIXEL_X (f, pix_x),
2336 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
2337 FRAME_COLUMN_WIDTH (f) - 1,
2338 FRAME_LINE_HEIGHT (f) - 1);
2339
2340
2341 if (!noclip)
2342 {
2343 if (pix_x < 0)
2344 pix_x = 0;
2345 else if (pix_x > FRAME_TOTAL_COLS (f))
2346 pix_x = FRAME_TOTAL_COLS (f);
2347
2348 if (pix_y < 0)
2349 pix_y = 0;
2350 else if (pix_y > FRAME_TOTAL_LINES (f))
2351 pix_y = FRAME_TOTAL_LINES (f);
2352 }
2353 }
2354 #endif
2355
2356 *x = pix_x;
2357 *y = pix_y;
2358 }
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369 struct glyph *
2370 x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2371 int *dx, int *dy, int *area)
2372 {
2373 struct glyph *glyph, *end;
2374 struct glyph_row *row = NULL;
2375 int x0, i;
2376
2377
2378 for (i = 0; i < w->current_matrix->nrows; ++i)
2379 {
2380 row = MATRIX_ROW (w->current_matrix, i);
2381 if (!row->enabled_p)
2382 return NULL;
2383 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
2384 break;
2385 }
2386
2387 *vpos = i;
2388 *hpos = 0;
2389
2390
2391 if (i == w->current_matrix->nrows)
2392 return NULL;
2393
2394
2395 if (w->pseudo_window_p)
2396 {
2397 *area = TEXT_AREA;
2398 x0 = 0;
2399 }
2400 else
2401 {
2402 if (x < window_box_left_offset (w, TEXT_AREA))
2403 {
2404 *area = LEFT_MARGIN_AREA;
2405 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
2406 }
2407 else if (x < window_box_right_offset (w, TEXT_AREA))
2408 {
2409 *area = TEXT_AREA;
2410 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
2411 }
2412 else
2413 {
2414 *area = RIGHT_MARGIN_AREA;
2415 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
2416 }
2417 }
2418
2419
2420 glyph = row->glyphs[*area];
2421 end = glyph + row->used[*area];
2422 x -= x0;
2423 while (glyph < end && x >= glyph->pixel_width)
2424 {
2425 x -= glyph->pixel_width;
2426 ++glyph;
2427 }
2428
2429 if (glyph == end)
2430 return NULL;
2431
2432 if (dx)
2433 {
2434 *dx = x;
2435 *dy = y - (row->y + row->ascent - glyph->ascent);
2436 }
2437
2438 *hpos = glyph - row->glyphs[*area];
2439 return glyph;
2440 }
2441
2442
2443
2444
2445 static void
2446 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
2447 {
2448 if (w->pseudo_window_p)
2449 {
2450
2451
2452 struct frame *f = XFRAME (w->frame);
2453 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
2454 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2455 }
2456 else
2457 {
2458 *x -= WINDOW_LEFT_EDGE_X (w);
2459 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2460 }
2461 }
2462
2463 #ifdef HAVE_WINDOW_SYSTEM
2464
2465
2466
2467
2468
2469 int
2470 get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int n)
2471 {
2472 Emacs_Rectangle r;
2473
2474 if (n <= 0)
2475 return 0;
2476
2477 if (s->row->full_width_p)
2478 {
2479
2480 r.x = WINDOW_LEFT_EDGE_X (s->w);
2481 if (s->row->mode_line_p)
2482 r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
2483 else
2484 r.width = WINDOW_PIXEL_WIDTH (s->w);
2485
2486
2487
2488 if (s->w->pseudo_window_p)
2489 r.height = s->row->visible_height;
2490 else
2491 r.height = s->height;
2492 }
2493 else
2494 {
2495
2496 r.x = window_box_left (s->w, s->area);
2497 r.width = window_box_width (s->w, s->area);
2498 r.height = s->row->visible_height;
2499 }
2500
2501 if (s->clip_head)
2502 if (r.x < s->clip_head->x)
2503 {
2504 if (r.width >= s->clip_head->x - r.x)
2505 r.width -= s->clip_head->x - r.x;
2506 else
2507 r.width = 0;
2508 r.x = s->clip_head->x;
2509 }
2510 if (s->clip_tail)
2511 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
2512 {
2513 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2514 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
2515 else
2516 r.width = 0;
2517 }
2518
2519
2520
2521
2522 if (s->for_overlaps)
2523 {
2524 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2525 r.height = window_text_bottom_y (s->w) - r.y;
2526
2527
2528
2529
2530
2531
2532 if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
2533 {
2534 Emacs_Rectangle rc, r_save = r;
2535
2536 rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
2537 rc.y = s->w->phys_cursor.y;
2538 rc.width = s->w->phys_cursor_width;
2539 rc.height = s->w->phys_cursor_height;
2540
2541 gui_intersect_rectangles (&r_save, &rc, &r);
2542 }
2543 }
2544 else
2545 {
2546
2547
2548
2549 if (!s->row->full_width_p
2550 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2551 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2552 else
2553 r.y = max (0, s->row->y);
2554 }
2555
2556 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
2557
2558
2559
2560 if (s->hl == DRAW_CURSOR)
2561 {
2562 struct glyph *glyph = s->first_glyph;
2563 int height, max_y;
2564
2565 if (s->x > r.x)
2566 {
2567 if (r.width >= s->x - r.x)
2568 r.width -= s->x - r.x;
2569 else
2570 r.width = 0;
2571 r.x = s->x;
2572 }
2573 r.width = min (r.width, glyph->pixel_width);
2574
2575
2576 height = min (glyph->ascent + glyph->descent,
2577 min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
2578 max_y = window_text_bottom_y (s->w) - height;
2579 max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
2580 if (s->ybase - glyph->ascent > max_y)
2581 {
2582 r.y = max_y;
2583 r.height = height;
2584 }
2585 else
2586 {
2587
2588 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2589 if (height < r.height)
2590 {
2591 max_y = r.y + r.height;
2592 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2593 r.height = min (max_y - r.y, height);
2594 }
2595 }
2596 }
2597
2598 if (s->row->clip)
2599 {
2600 Emacs_Rectangle r_save = r;
2601
2602 if (! gui_intersect_rectangles (&r_save, s->row->clip, &r))
2603 r.width = 0;
2604 }
2605
2606 if ((s->for_overlaps & OVERLAPS_BOTH) == 0
2607 || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
2608 {
2609 #ifdef CONVERT_FROM_EMACS_RECT
2610 CONVERT_FROM_EMACS_RECT (r, *rects);
2611 #else
2612 *rects = r;
2613 #endif
2614 return 1;
2615 }
2616 else
2617 {
2618
2619
2620
2621
2622 #ifdef CONVERT_FROM_EMACS_RECT
2623 Emacs_Rectangle rs[2];
2624 #else
2625 Emacs_Rectangle *rs = rects;
2626 #endif
2627 int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
2628
2629 if (s->for_overlaps & OVERLAPS_PRED)
2630 {
2631 rs[i] = r;
2632 if (r.y + r.height > row_y)
2633 {
2634 if (r.y < row_y)
2635 rs[i].height = row_y - r.y;
2636 else
2637 rs[i].height = 0;
2638 }
2639 i++;
2640 }
2641 if (s->for_overlaps & OVERLAPS_SUCC)
2642 {
2643 rs[i] = r;
2644 if (r.y < row_y + s->row->visible_height)
2645 {
2646 if (r.y + r.height > row_y + s->row->visible_height)
2647 {
2648 rs[i].y = row_y + s->row->visible_height;
2649 rs[i].height = r.y + r.height - rs[i].y;
2650 }
2651 else
2652 rs[i].height = 0;
2653 }
2654 i++;
2655 }
2656
2657 n = i;
2658 #ifdef CONVERT_FROM_EMACS_RECT
2659 for (i = 0; i < n; i++)
2660 CONVERT_FROM_EMACS_RECT (rs[i], rects[i]);
2661 #endif
2662 return n;
2663 }
2664 }
2665
2666
2667
2668
2669 void
2670 get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2671 {
2672 get_glyph_string_clip_rects (s, nr, 1);
2673 }
2674
2675
2676
2677
2678
2679
2680
2681 void
2682 get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2683 struct glyph *glyph, int *xp, int *yp, int *heightp)
2684 {
2685 struct frame *f = XFRAME (WINDOW_FRAME (w));
2686 int x, y, wd, h, h0, y0, ascent;
2687
2688
2689
2690
2691
2692 wd = glyph->pixel_width;
2693
2694 x = w->phys_cursor.x;
2695 if (x < 0)
2696 {
2697 wd += x;
2698 x = 0;
2699 }
2700
2701 if (glyph->type == STRETCH_GLYPH
2702 && !x_stretch_cursor_p)
2703 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2704 w->phys_cursor_width = wd;
2705
2706
2707
2708 y = w->phys_cursor.y;
2709 ascent = row->ascent;
2710
2711
2712
2713 if (!row->ends_at_zv_p && row->ascent < glyph->ascent)
2714 {
2715 y -= glyph->ascent - row->ascent;
2716 ascent = glyph->ascent;
2717 }
2718
2719
2720 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2721
2722 h = max (h0, ascent + glyph->descent);
2723
2724
2725 h = min (h, row->height);
2726 h0 = min (h0, ascent + glyph->descent);
2727
2728 y0 = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
2729 if (y < y0)
2730 {
2731 h = max (h - (y0 - y) + 1, h0);
2732 y = y0 - 1;
2733 }
2734 else
2735 {
2736 y0 = window_text_bottom_y (w) - h0;
2737 if (y > y0)
2738 {
2739 h += y - y0;
2740 y = y0;
2741 }
2742 }
2743
2744 *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
2745 *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2746 *heightp = h;
2747 }
2748
2749
2750
2751
2752
2753 void
2754 remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2755 {
2756 Lisp_Object window;
2757 struct window *w;
2758 struct glyph_row *r, *gr, *end_row;
2759 enum window_part part;
2760 enum glyph_row_area area;
2761 int x, y, width, height;
2762 int original_gx;
2763
2764 if (mouse_fine_grained_tracking)
2765 {
2766 STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
2767 return;
2768 }
2769
2770
2771
2772
2773 original_gx = gx;
2774
2775 if (window_resize_pixelwise)
2776 {
2777 width = height = 1;
2778 goto virtual_glyph;
2779 }
2780 else if (!f->glyphs_initialized_p
2781 || (window = window_from_coordinates (f, gx, gy, &part, false, false),
2782 NILP (window)))
2783 {
2784 width = FRAME_SMALLEST_CHAR_WIDTH (f);
2785 height = FRAME_SMALLEST_FONT_HEIGHT (f);
2786 goto virtual_glyph;
2787 }
2788
2789 w = XWINDOW (window);
2790 width = WINDOW_FRAME_COLUMN_WIDTH (w);
2791 height = WINDOW_FRAME_LINE_HEIGHT (w);
2792
2793 x = window_relative_x_coord (w, part, gx);
2794 y = gy - WINDOW_TOP_EDGE_Y (w);
2795
2796 r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
2797 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
2798
2799 if (w->pseudo_window_p)
2800 {
2801 area = TEXT_AREA;
2802 part = ON_MODE_LINE;
2803 goto text_glyph;
2804 }
2805
2806 switch (part)
2807 {
2808 case ON_LEFT_MARGIN:
2809 area = LEFT_MARGIN_AREA;
2810 goto text_glyph;
2811
2812 case ON_RIGHT_MARGIN:
2813 area = RIGHT_MARGIN_AREA;
2814 goto text_glyph;
2815
2816 case ON_TAB_LINE:
2817 case ON_HEADER_LINE:
2818 case ON_MODE_LINE:
2819 gr = (part == ON_TAB_LINE
2820 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
2821 : (part == ON_HEADER_LINE
2822 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
2823 : MATRIX_MODE_LINE_ROW (w->current_matrix)));
2824 gy = gr->y;
2825 area = TEXT_AREA;
2826 goto text_glyph_row_found;
2827
2828 case ON_TEXT:
2829 area = TEXT_AREA;
2830
2831 text_glyph:
2832 gr = 0; gy = 0;
2833 for (; r <= end_row && r->enabled_p; ++r)
2834 if (r->y + r->height > y)
2835 {
2836 gr = r; gy = r->y;
2837 break;
2838 }
2839
2840 text_glyph_row_found:
2841 if (gr && gy <= y)
2842 {
2843 struct glyph *g = gr->glyphs[area];
2844 struct glyph *end = g + gr->used[area];
2845
2846 height = gr->height;
2847 for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
2848 if (gx + g->pixel_width > x)
2849 break;
2850
2851 if (g < end)
2852 {
2853 if (g->type == IMAGE_GLYPH)
2854 {
2855
2856
2857 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
2858 return;
2859 }
2860 width = g->pixel_width;
2861 }
2862 else
2863 {
2864
2865 x -= gx;
2866 gx += (x / width) * width;
2867 }
2868
2869 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2870 && part != ON_TAB_LINE)
2871 {
2872 gx += window_box_left_offset (w, area);
2873
2874
2875 height = min (height,
2876 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2877 }
2878 }
2879 else
2880 {
2881
2882 gx = (x / width) * width;
2883 y -= gy;
2884 gy += (y / height) * height;
2885 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2886 && part != ON_TAB_LINE)
2887
2888 height = min (height,
2889 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2890 }
2891 break;
2892
2893 case ON_LEFT_FRINGE:
2894 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2895 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2896 : window_box_right_offset (w, LEFT_MARGIN_AREA));
2897 width = WINDOW_LEFT_FRINGE_WIDTH (w);
2898 goto row_glyph;
2899
2900 case ON_RIGHT_FRINGE:
2901 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2902 ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
2903 : window_box_right_offset (w, TEXT_AREA));
2904 if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
2905 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
2906 && !WINDOW_RIGHTMOST_P (w))
2907 if (gx < WINDOW_PIXEL_WIDTH (w) - width)
2908
2909
2910 width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
2911 else
2912 width = WINDOW_PIXEL_WIDTH (w) - gx;
2913 else
2914 width = WINDOW_RIGHT_FRINGE_WIDTH (w);
2915
2916 goto row_glyph;
2917
2918 case ON_VERTICAL_BORDER:
2919 gx = WINDOW_PIXEL_WIDTH (w) - width;
2920 goto row_glyph;
2921
2922 case ON_VERTICAL_SCROLL_BAR:
2923 gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
2924 ? 0
2925 : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
2926 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2927 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
2928 : 0)));
2929 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2930
2931 row_glyph:
2932 gr = 0, gy = 0;
2933 for (; r <= end_row && r->enabled_p; ++r)
2934 if (r->y + r->height > y)
2935 {
2936 gr = r; gy = r->y;
2937 break;
2938 }
2939
2940 if (gr && gy <= y)
2941 height = gr->height;
2942 else
2943 {
2944
2945 y -= gy;
2946 gy += (y / height) * height;
2947 }
2948 break;
2949
2950 case ON_RIGHT_DIVIDER:
2951 gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
2952 width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
2953 gy = 0;
2954
2955 height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2956 goto add_edge;
2957
2958 case ON_BOTTOM_DIVIDER:
2959 gx = 0;
2960 width = WINDOW_PIXEL_WIDTH (w);
2961 gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2962 height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2963 goto add_edge;
2964
2965 default:
2966 ;
2967 virtual_glyph:
2968
2969
2970
2971
2972
2973
2974 if (gx < 0)
2975 gx -= width - 1;
2976 if (gy < 0)
2977 gy -= height - 1;
2978
2979 gx = (gx / width) * width;
2980 gy = (gy / height) * height;
2981
2982 goto store_rect;
2983 }
2984
2985 add_edge:
2986 gx += WINDOW_LEFT_EDGE_X (w);
2987 gy += WINDOW_TOP_EDGE_Y (w);
2988
2989 store_rect:
2990 if (mouse_prefer_closest_glyph)
2991 {
2992 int half_width = width / 2;
2993 width = half_width;
2994
2995 int bisection = gx + half_width;
2996 if (original_gx > bisection)
2997 gx = bisection;
2998 }
2999 STORE_NATIVE_RECT (*rect, gx, gy, width, height);
3000
3001
3002 #if false && defined HAVE_X_WINDOWS
3003 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
3004 f->output_data.x->normal_gc,
3005 gx, gy, width, height);
3006 #endif
3007 }
3008
3009
3010 #endif
3011
3012 static void
3013 adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
3014 {
3015 eassert (w);
3016 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
3017 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
3018 w->window_end_vpos
3019 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
3020 }
3021
3022 static bool
3023 hscrolling_current_line_p (struct window *w)
3024 {
3025 return (!w->suspend_auto_hscroll
3026 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
3027 Qcurrent_line));
3028 }
3029
3030
3031
3032
3033
3034
3035
3036 static Lisp_Object
3037 safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
3038 {
3039 add_to_log ("Error during redisplay: %S signaled %S",
3040 Flist (nargs, args), arg);
3041 return Qnil;
3042 }
3043
3044
3045
3046
3047
3048 static Lisp_Object
3049 safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
3050 {
3051 Lisp_Object val;
3052
3053 if (inhibit_eval_during_redisplay)
3054 val = Qnil;
3055 else
3056 {
3057 ptrdiff_t i;
3058 specpdl_ref count = SPECPDL_INDEX ();
3059 Lisp_Object *args;
3060 USE_SAFE_ALLOCA;
3061 SAFE_ALLOCA_LISP (args, nargs);
3062
3063 args[0] = func;
3064 for (i = 1; i < nargs; i++)
3065 args[i] = va_arg (ap, Lisp_Object);
3066
3067 specbind (Qinhibit_redisplay, Qt);
3068 if (inhibit_quit)
3069 specbind (Qinhibit_quit, Qt);
3070
3071
3072 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
3073 safe_eval_handler);
3074 val = SAFE_FREE_UNBIND_TO (count, val);
3075 }
3076
3077 return val;
3078 }
3079
3080 Lisp_Object
3081 safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
3082 {
3083 Lisp_Object retval;
3084 va_list ap;
3085
3086 va_start (ap, func);
3087 retval = safe__call (false, nargs, func, ap);
3088 va_end (ap);
3089 return retval;
3090 }
3091
3092
3093
3094
3095 Lisp_Object
3096 safe_call1 (Lisp_Object fn, Lisp_Object arg)
3097 {
3098 return safe_call (2, fn, arg);
3099 }
3100
3101 static Lisp_Object
3102 safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
3103 {
3104 Lisp_Object retval;
3105 va_list ap;
3106
3107 va_start (ap, fn);
3108 retval = safe__call (inhibit_quit, 2, fn, ap);
3109 va_end (ap);
3110 return retval;
3111 }
3112
3113 Lisp_Object
3114 safe_eval (Lisp_Object sexpr)
3115 {
3116 return safe__call1 (false, Qeval, sexpr);
3117 }
3118
3119 static Lisp_Object
3120 safe__eval (bool inhibit_quit, Lisp_Object sexpr)
3121 {
3122 return safe__call1 (inhibit_quit, Qeval, sexpr);
3123 }
3124
3125
3126
3127
3128 Lisp_Object
3129 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
3130 {
3131 return safe_call (3, fn, arg1, arg2);
3132 }
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143 static void
3144 CHECK_IT (struct it *it)
3145 {
3146 #if false
3147 if (it->method == GET_FROM_STRING)
3148 {
3149 eassert (STRINGP (it->string));
3150 eassert (IT_STRING_CHARPOS (*it) >= 0);
3151 }
3152 else
3153 {
3154 eassert (IT_STRING_CHARPOS (*it) < 0);
3155 if (it->method == GET_FROM_BUFFER)
3156 {
3157
3158 eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
3159 }
3160 }
3161
3162 if (it->dpvec)
3163 eassert (it->current.dpvec_index >= 0);
3164 else
3165 eassert (it->current.dpvec_index < 0);
3166 #endif
3167 }
3168
3169
3170
3171
3172
3173 static void
3174 CHECK_WINDOW_END (struct window *w)
3175 {
3176 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3177 if (!MINI_WINDOW_P (w) && w->window_end_valid)
3178 {
3179 struct glyph_row *row;
3180 eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
3181 !row->enabled_p
3182 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
3183 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
3184 }
3185 #endif
3186 }
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211 void
3212 init_iterator (struct it *it, struct window *w,
3213 ptrdiff_t charpos, ptrdiff_t bytepos,
3214 struct glyph_row *row, enum face_id base_face_id)
3215 {
3216 enum face_id remapped_base_face_id = base_face_id;
3217 int body_width = 0, body_height = 0;
3218
3219
3220 eassert (w != NULL && it != NULL);
3221 eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
3222 && charpos <= ZV));
3223
3224
3225
3226
3227
3228 if (!inhibit_free_realized_faces)
3229 {
3230 if (face_change)
3231 {
3232 face_change = false;
3233 XFRAME (w->frame)->face_change = 0;
3234 free_all_realized_faces (Qnil);
3235 }
3236 else if (XFRAME (w->frame)->face_change)
3237 {
3238 XFRAME (w->frame)->face_change = 0;
3239 free_all_realized_faces (w->frame);
3240 }
3241 }
3242
3243
3244 if (! NILP (Vface_remapping_alist))
3245 remapped_base_face_id
3246 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
3247
3248
3249
3250 if (row == NULL)
3251 {
3252 if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
3253 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
3254 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
3255 else if (base_face_id == TAB_LINE_FACE_ID)
3256 row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
3257 else if (base_face_id == HEADER_LINE_FACE_ID)
3258 {
3259
3260 w->desired_matrix->tab_line_p = window_wants_tab_line (w);
3261 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
3262 }
3263 }
3264
3265
3266
3267 memclear (it, sizeof *it);
3268 it->current.overlay_string_index = -1;
3269 it->current.dpvec_index = -1;
3270 it->base_face_id = remapped_base_face_id;
3271 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3272 it->paragraph_embedding = L2R;
3273 it->bidi_it.w = w;
3274
3275
3276 XSETWINDOW (it->window, w);
3277 it->w = w;
3278 it->f = XFRAME (w->frame);
3279
3280 it->cmp_it.id = -1;
3281 it->cmp_it.parent_it = it;
3282
3283 if (max_redisplay_ticks > 0)
3284 update_redisplay_ticks (0, w);
3285
3286
3287 if (base_face_id == DEFAULT_FACE_ID
3288 && FRAME_WINDOW_P (it->f))
3289 {
3290 if (FIXNATP (BVAR (current_buffer, extra_line_spacing)))
3291 it->extra_line_spacing = XFIXNAT (BVAR (current_buffer, extra_line_spacing));
3292 else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
3293 it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
3294 * FRAME_LINE_HEIGHT (it->f));
3295 else if (it->f->extra_line_spacing > 0)
3296 it->extra_line_spacing = it->f->extra_line_spacing;
3297 }
3298
3299
3300
3301
3302
3303 if (FRAME_FACE_CACHE (it->f) == NULL)
3304 init_frame_faces (it->f);
3305 if (FRAME_FACE_CACHE (it->f)->used == 0)
3306 recompute_basic_faces (it->f);
3307
3308 it->override_ascent = -1;
3309
3310
3311 it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
3312
3313
3314
3315
3316 it->selective = (FIXNUMP (BVAR (current_buffer, selective_display))
3317 ? (clip_to_bounds
3318 (-1, XFIXNUM (BVAR (current_buffer, selective_display)),
3319 PTRDIFF_MAX))
3320 : (!NILP (BVAR (current_buffer, selective_display))
3321 ? -1 : 0));
3322 it->selective_display_ellipsis_p
3323 = !NILP (BVAR (current_buffer, selective_display_ellipses));
3324
3325
3326 it->dp = window_display_table (w);
3327
3328
3329 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
3330
3331 it->tab_width = SANE_TAB_WIDTH (current_buffer);
3332
3333
3334 if (TRUNCATE != 0)
3335 it->line_wrap = TRUNCATE;
3336 if (base_face_id == DEFAULT_FACE_ID
3337 && !it->w->hscroll
3338 && (WINDOW_FULL_WIDTH_P (it->w)
3339 || NILP (Vtruncate_partial_width_windows)
3340 || (FIXNUMP (Vtruncate_partial_width_windows)
3341
3342 && (XFIXNUM (Vtruncate_partial_width_windows)
3343 <= WINDOW_TOTAL_COLS (it->w))))
3344 && NILP (BVAR (current_buffer, truncate_lines)))
3345 it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
3346 ? WINDOW_WRAP : WORD_WRAP;
3347
3348
3349
3350
3351
3352
3353
3354 #ifdef HAVE_WINDOW_SYSTEM
3355 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3356 #endif
3357 {
3358 if (it->line_wrap == TRUNCATE)
3359 {
3360
3361 eassert (it->glyph_row == NULL);
3362 produce_special_glyphs (it, IT_TRUNCATION);
3363 it->truncation_pixel_width = it->pixel_width;
3364 }
3365 else
3366 {
3367
3368 eassert (it->glyph_row == NULL);
3369 produce_special_glyphs (it, IT_CONTINUATION);
3370 it->continuation_pixel_width = it->pixel_width;
3371 }
3372 }
3373
3374
3375
3376 it->pixel_width = it->ascent = it->descent = 0;
3377 it->phys_ascent = it->phys_descent = 0;
3378
3379
3380
3381
3382 it->glyph_row = row;
3383 it->area = TEXT_AREA;
3384
3385
3386
3387
3388
3389 if (base_face_id != DEFAULT_FACE_ID)
3390 {
3391
3392 it->first_visible_x = 0;
3393 it->last_visible_x =
3394 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3395 }
3396 else
3397 {
3398
3399
3400
3401
3402
3403
3404 if (hscrolling_current_line_p (w))
3405 {
3406 if (w->min_hscroll > 0)
3407 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
3408 else
3409 it->first_visible_x = 0;
3410 }
3411 else
3412 it->first_visible_x =
3413 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
3414
3415 body_width = window_box_width (w, TEXT_AREA);
3416 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3417 && body_width != w->old_body_pixel_width)
3418 FRAME_WINDOW_CHANGE (it->f) = true;
3419 it->last_visible_x = it->first_visible_x + body_width;
3420
3421
3422
3423
3424 if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
3425 {
3426 if (it->line_wrap == TRUNCATE)
3427 it->last_visible_x -= it->truncation_pixel_width;
3428 else
3429 it->last_visible_x -= it->continuation_pixel_width;
3430 }
3431
3432 it->tab_line_p = window_wants_tab_line (w);
3433 it->header_line_p = window_wants_header_line (w);
3434 body_height = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
3435 it->current_y = body_height + w->vscroll;
3436 }
3437
3438
3439 if (!FRAME_WINDOW_P (it->f)
3440 && !WINDOW_RIGHTMOST_P (it->w))
3441 it->last_visible_x -= 1;
3442
3443 it->last_visible_y = window_text_bottom_y (w);
3444 body_height += it->last_visible_y;
3445 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3446 && body_height != w->old_body_pixel_height)
3447 FRAME_WINDOW_CHANGE (it->f) = true;
3448
3449
3450
3451 if (base_face_id != DEFAULT_FACE_ID)
3452 {
3453 struct face *face;
3454
3455 it->face_id = remapped_base_face_id;
3456
3457
3458
3459 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3460 if (face && face->box != FACE_NO_BOX)
3461 {
3462 int box_thickness = face->box_vertical_line_width;
3463 it->face_box_p = true;
3464 it->start_of_box_run_p = true;
3465
3466
3467 if (box_thickness > 0)
3468 it->last_visible_x -= box_thickness;
3469 }
3470 }
3471
3472
3473
3474 if (charpos >= BUF_BEG (current_buffer))
3475 {
3476 it->stop_charpos = charpos;
3477 it->end_charpos = ZV;
3478 eassert (charpos == BYTE_TO_CHAR (bytepos));
3479 IT_CHARPOS (*it) = charpos;
3480 IT_BYTEPOS (*it) = bytepos;
3481
3482
3483
3484 it->face_id = it->base_face_id;
3485
3486 it->start = it->current;
3487
3488
3489
3490
3491
3492
3493
3494 it->bidi_p =
3495 !redisplay__inhibit_bidi
3496 && !NILP (BVAR (current_buffer, bidi_display_reordering))
3497 && it->multibyte_p;
3498
3499
3500
3501 if (it->bidi_p)
3502 {
3503
3504
3505
3506
3507 if (base_face_id == DEFAULT_FACE_ID
3508 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
3509 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
3510 {
3511 if (it->line_wrap == TRUNCATE)
3512 it->last_visible_x -= it->truncation_pixel_width;
3513 else
3514 it->last_visible_x -= it->continuation_pixel_width;
3515 }
3516
3517
3518 if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3519 Qleft_to_right))
3520 it->paragraph_embedding = L2R;
3521 else if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3522 Qright_to_left))
3523 it->paragraph_embedding = R2L;
3524 else
3525 it->paragraph_embedding = NEUTRAL_DIR;
3526 bidi_unshelve_cache (NULL, false);
3527 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
3528 &it->bidi_it);
3529 }
3530
3531
3532
3533 it->medium_narrowing_begv = 0;
3534
3535
3536 reseat (it, it->current.pos, true);
3537 }
3538
3539 CHECK_IT (it);
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
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628 static int
3629 get_narrowed_width (struct window *w)
3630 {
3631
3632
3633 int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
3634
3635
3636
3637 int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
3638 - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
3639 || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
3640 return fact * max (1, width);
3641 }
3642
3643 static int
3644 get_narrowed_len (struct window *w)
3645 {
3646 int height = window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS);
3647 return get_narrowed_width (w) * max (1, height);
3648 }
3649
3650 static ptrdiff_t
3651 get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
3652 {
3653 int len = get_narrowed_len (w);
3654 return max ((pos / len - 1) * len, BEGV);
3655 }
3656
3657 static ptrdiff_t
3658 get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
3659 {
3660 int len = get_narrowed_len (w);
3661 return min ((pos / len + 1) * len, ZV);
3662 }
3663
3664
3665
3666
3667
3668
3669 static ptrdiff_t
3670 get_nearby_bol_pos (ptrdiff_t pos)
3671 {
3672 ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = pos;
3673 int dist;
3674 for (dist = 500; dist <= 500000; dist *= 10)
3675 {
3676 pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
3677 start = pos - dist < BEGV ? BEGV : pos - dist;
3678 for (cur = start; cur < pos; cur = next)
3679 {
3680 next = find_newline1 (cur, CHAR_TO_BYTE (cur),
3681 pos, pos_bytepos,
3682 1, &found, NULL, false);
3683 if (found)
3684 bol = next;
3685 else
3686 break;
3687 }
3688 if (bol >= BEGV || start == BEGV)
3689 break;
3690 else
3691 pos = pos - dist < BEGV ? BEGV : pos - dist;
3692 }
3693 eassert (bol <= init_pos);
3694 return bol;
3695 }
3696
3697 ptrdiff_t
3698 get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
3699 {
3700 int len = get_narrowed_width (w);
3701 ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
3702 return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
3703 }
3704
3705 ptrdiff_t
3706 get_large_narrowing_begv (ptrdiff_t pos)
3707 {
3708 if (long_line_optimizations_region_size <= 0)
3709 return BEGV;
3710 int len = long_line_optimizations_region_size / 2;
3711 int begv = max (pos - len, BEGV);
3712 int limit = long_line_optimizations_bol_search_limit;
3713 while (limit > 0)
3714 {
3715 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3716 return begv;
3717 begv--;
3718 limit--;
3719 }
3720 return begv;
3721 }
3722
3723 ptrdiff_t
3724 get_large_narrowing_zv (ptrdiff_t pos)
3725 {
3726 if (long_line_optimizations_region_size <= 0)
3727 return ZV;
3728 int len = long_line_optimizations_region_size / 2;
3729 return min (pos + len, ZV);
3730 }
3731
3732 static void
3733 unwind_narrowed_begv (Lisp_Object point_min)
3734 {
3735 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3736 }
3737
3738
3739
3740
3741 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
3742 do { \
3743 if (IT->medium_narrowing_begv) \
3744 { \
3745 specpdl_ref count = SPECPDL_INDEX (); \
3746 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3747 SET_BUF_BEGV (current_buffer, BV); \
3748 DST = EXPR; \
3749 unbind_to (count, Qnil); \
3750 } \
3751 else \
3752 DST = EXPR; \
3753 } while (0)
3754
3755
3756
3757 void
3758 start_display (struct it *it, struct window *w, struct text_pos pos)
3759 {
3760 struct glyph_row *row;
3761 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
3762
3763 row = w->desired_matrix->rows + first_vpos;
3764 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3765 it->first_vpos = first_vpos;
3766
3767
3768
3769 if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
3770 {
3771 int first_y = it->current_y;
3772
3773
3774
3775 bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
3776 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
3777 if (!start_at_line_beg_p)
3778 {
3779 int new_x;
3780
3781 reseat_at_previous_visible_line_start (it);
3782 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
3783
3784 new_x = it->current_x + it->pixel_width;
3785
3786
3787
3788
3789
3790
3791
3792 if (it->current_x > 0
3793 && it->line_wrap != TRUNCATE
3794 && (
3795 new_x > it->last_visible_x
3796
3797
3798 || (new_x == it->last_visible_x
3799 && FRAME_WINDOW_P (it->f)
3800 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
3801 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
3802 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
3803 {
3804 if ((it->current.dpvec_index >= 0
3805 || it->current.overlay_string_index >= 0)
3806
3807
3808
3809
3810
3811 && it->c != '\n')
3812 {
3813 set_iterator_to_next (it, true);
3814 move_it_in_display_line_to (it, -1, -1, 0);
3815 }
3816
3817 it->continuation_lines_width += it->current_x;
3818 }
3819
3820
3821
3822
3823
3824 else if (it->current.dpvec_index >= 0)
3825 it->current.dpvec_index = 0;
3826
3827
3828
3829
3830 it->max_ascent = it->max_descent = 0;
3831 it->max_phys_ascent = it->max_phys_descent = 0;
3832
3833 it->current_y = first_y;
3834 it->vpos = 0;
3835 it->current_x = it->hpos = 0;
3836 }
3837 }
3838 }
3839
3840
3841
3842
3843
3844 static bool
3845 in_ellipses_for_invisible_text_p (struct display_pos *pos, struct window *w)
3846 {
3847 Lisp_Object prop, window;
3848 bool ellipses_p = false;
3849 ptrdiff_t charpos = CHARPOS (pos->pos);
3850
3851
3852
3853
3854
3855 if (pos->dpvec_index >= 0
3856 && pos->overlay_string_index < 0
3857 && CHARPOS (pos->string_pos) < 0
3858 && charpos > BEGV
3859 && (XSETWINDOW (window, w),
3860 prop = Fget_char_property (make_fixnum (charpos),
3861 Qinvisible, window),
3862 TEXT_PROP_MEANS_INVISIBLE (prop) == 0))
3863 {
3864 prop = Fget_char_property (make_fixnum (charpos - 1), Qinvisible,
3865 window);
3866 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
3867 }
3868
3869 return ellipses_p;
3870 }
3871
3872
3873
3874
3875
3876
3877
3878 static bool
3879 init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
3880 {
3881 ptrdiff_t charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3882 int i;
3883 bool overlay_strings_with_newlines = false;
3884
3885
3886
3887
3888
3889 if (in_ellipses_for_invisible_text_p (pos, w))
3890 {
3891 --charpos;
3892 bytepos = 0;
3893 }
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
3905
3906
3907
3908
3909 for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
3910 {
3911 const char *s = SSDATA (it->overlay_strings[i]);
3912 const char *e = s + SBYTES (it->overlay_strings[i]);
3913
3914 while (s < e && *s != '\n')
3915 ++s;
3916
3917 if (s < e)
3918 {
3919 overlay_strings_with_newlines = true;
3920 break;
3921 }
3922 }
3923
3924
3925
3926 if (pos->overlay_string_index >= 0)
3927 {
3928 int relative_index;
3929
3930
3931
3932
3933
3934 if (it->method == GET_FROM_IMAGE)
3935 pop_it (it);
3936
3937
3938
3939
3940 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
3941 {
3942 ptrdiff_t n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
3943 it->current.overlay_string_index = 0;
3944 while (n--)
3945 {
3946 load_overlay_strings (it, 0);
3947 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
3948 }
3949 }
3950
3951 it->current.overlay_string_index = pos->overlay_string_index;
3952 relative_index = (it->current.overlay_string_index
3953 % OVERLAY_STRING_CHUNK_SIZE);
3954 it->string = it->overlay_strings[relative_index];
3955 eassert (STRINGP (it->string));
3956 it->current.string_pos = pos->string_pos;
3957 it->method = GET_FROM_STRING;
3958 it->end_charpos = SCHARS (it->string);
3959
3960 if (it->bidi_p)
3961 {
3962 it->bidi_it.string.lstring = it->string;
3963 it->bidi_it.string.s = NULL;
3964 it->bidi_it.string.schars = SCHARS (it->string);
3965 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
3966 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
3967 it->bidi_it.string.unibyte = !it->multibyte_p;
3968 it->bidi_it.w = it->w;
3969 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3970 FRAME_WINDOW_P (it->f), &it->bidi_it);
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980 if (CHARPOS (pos->string_pos) == 0)
3981 {
3982 get_visually_first_element (it);
3983 if (IT_STRING_CHARPOS (*it) != 0)
3984 do {
3985
3986 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
3987 bidi_move_to_visually_next (&it->bidi_it);
3988 } while (it->bidi_it.charpos != 0);
3989 }
3990 eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
3991 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
3992 }
3993 }
3994
3995 if (CHARPOS (pos->string_pos) >= 0)
3996 {
3997
3998
3999
4000 it->current.string_pos = pos->string_pos;
4001 eassert (STRINGP (it->string));
4002 if (it->bidi_p)
4003 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
4004 FRAME_WINDOW_P (it->f), &it->bidi_it);
4005 }
4006
4007
4008
4009 if (pos->dpvec_index >= 0)
4010 {
4011 if (it->dpvec == NULL)
4012 get_next_display_element (it);
4013 eassert (it->dpvec && it->current.dpvec_index == 0);
4014 it->current.dpvec_index = pos->dpvec_index;
4015 }
4016
4017 CHECK_IT (it);
4018 return !overlay_strings_with_newlines;
4019 }
4020
4021
4022
4023
4024
4025 static void
4026 init_to_row_start (struct it *it, struct window *w, struct glyph_row *row)
4027 {
4028 init_from_display_pos (it, w, &row->start);
4029 it->start = row->start;
4030 it->continuation_lines_width = row->continuation_lines_width;
4031 CHECK_IT (it);
4032 }
4033
4034
4035
4036
4037
4038
4039
4040
4041 static bool
4042 init_to_row_end (struct it *it, struct window *w, struct glyph_row *row)
4043 {
4044 bool success = false;
4045
4046 if (init_from_display_pos (it, w, &row->end))
4047 {
4048 if (row->continued_p)
4049 it->continuation_lines_width
4050 = row->continuation_lines_width + row->pixel_width;
4051 CHECK_IT (it);
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061 if (get_next_display_element (it)
4062 && (it->bidi_it.scan_dir == -1 && it->cmp_it.id >= 0))
4063 success = false;
4064 else
4065 success = true;
4066 }
4067
4068 return success;
4069 }
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082 static void
4083 handle_stop (struct it *it)
4084 {
4085 enum prop_handled handled;
4086 bool handle_overlay_change_p;
4087 struct props *p;
4088
4089 it->dpvec = NULL;
4090 it->current.dpvec_index = -1;
4091 handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
4092 it->ellipsis_p = false;
4093
4094
4095 if (it->selective_display_ellipsis_p)
4096 it->saved_face_id = it->face_id;
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
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140 do
4141 {
4142 handled = HANDLED_NORMALLY;
4143
4144
4145 for (p = it_props; p->handler; ++p)
4146 {
4147 handled = p->handler (it);
4148
4149 if (handled == HANDLED_RECOMPUTE_PROPS)
4150 break;
4151 else if (handled == HANDLED_RETURN)
4152 {
4153
4154
4155 if (!handle_overlay_change_p
4156 || it->sp > 1
4157
4158
4159
4160
4161
4162
4163 || (it->current.overlay_string_index < 0
4164 && !get_overlay_strings_1 (it, 0, false)))
4165 {
4166 if (it->ellipsis_p)
4167 setup_for_ellipsis (it, 0);
4168
4169
4170
4171
4172
4173 if (STRINGP (it->string) && !SCHARS (it->string))
4174 pop_it (it);
4175 return;
4176 }
4177 else if (STRINGP (it->string) && !SCHARS (it->string))
4178 pop_it (it);
4179 else
4180 {
4181 it->string_from_display_prop_p = false;
4182 it->from_disp_prop_p = false;
4183 handle_overlay_change_p = false;
4184 }
4185 handled = HANDLED_RECOMPUTE_PROPS;
4186 break;
4187 }
4188 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
4189 handle_overlay_change_p = false;
4190 }
4191
4192 if (handled != HANDLED_RECOMPUTE_PROPS)
4193 {
4194
4195
4196 if (it->method == GET_FROM_DISPLAY_VECTOR)
4197 handle_overlay_change_p = false;
4198
4199
4200
4201
4202 if (handle_overlay_change_p)
4203 handled = handle_overlay_change (it);
4204 }
4205
4206 if (it->ellipsis_p)
4207 {
4208 setup_for_ellipsis (it, 0);
4209 break;
4210 }
4211 }
4212 while (handled == HANDLED_RECOMPUTE_PROPS);
4213
4214
4215 if (handled == HANDLED_NORMALLY)
4216 compute_stop_pos (it);
4217 }
4218
4219
4220
4221
4222
4223 static void
4224 compute_stop_pos (struct it *it)
4225 {
4226 register INTERVAL iv, next_iv;
4227 Lisp_Object object, limit, position;
4228 ptrdiff_t charpos, bytepos, cmp_limit_pos = -1;
4229
4230 if (STRINGP (it->string))
4231 {
4232
4233
4234 it->stop_charpos = it->end_charpos;
4235 object = it->string;
4236 limit = Qnil;
4237 charpos = IT_STRING_CHARPOS (*it);
4238 bytepos = IT_STRING_BYTEPOS (*it);
4239 }
4240 else
4241 {
4242 ptrdiff_t pos;
4243
4244
4245
4246 if (it->end_charpos > ZV)
4247 it->end_charpos = ZV;
4248 it->stop_charpos = it->end_charpos;
4249
4250
4251
4252
4253
4254 charpos = IT_CHARPOS (*it);
4255 bytepos = IT_BYTEPOS (*it);
4256 pos = next_overlay_change (charpos);
4257 if (pos < it->stop_charpos)
4258 it->stop_charpos = pos;
4259
4260 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
4261 && !NILP (Vauto_composition_mode)
4262 && composition_break_at_point
4263 && charpos < PT && PT < it->stop_charpos)
4264 it->stop_charpos = PT;
4265
4266
4267
4268 XSETBUFFER (object, current_buffer);
4269 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4270
4271
4272
4273
4274
4275
4276 if (!composition_break_at_point
4277 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
4278 && !NILP (Vauto_composition_mode))
4279 {
4280 ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
4281 bool found = false;
4282
4283 if (pos > ZV)
4284 pos = ZV;
4285 if (endpos > ZV)
4286 endpos = ZV;
4287 ptrdiff_t bpos = CHAR_TO_BYTE (pos);
4288 while (pos < endpos)
4289 {
4290 int ch = fetch_char_advance_no_check (&pos, &bpos);
4291 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\f')
4292 {
4293 found = true;
4294 break;
4295 }
4296 }
4297 if (found)
4298 {
4299 pos--;
4300 cmp_limit_pos = pos;
4301 }
4302 else if (it->stop_charpos < endpos)
4303 pos = it->stop_charpos;
4304 else
4305 {
4306
4307 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4308 }
4309 }
4310 limit = make_fixnum (pos);
4311 }
4312
4313
4314
4315 position = make_fixnum (charpos);
4316 iv = validate_interval_range (object, &position, &position, false);
4317 if (iv)
4318 {
4319 Lisp_Object values_here[LAST_PROP_IDX];
4320 struct props *p;
4321
4322
4323 for (p = it_props; p->handler; ++p)
4324 values_here[p->idx] = textget (iv->plist,
4325 builtin_lisp_symbol (p->name));
4326
4327
4328
4329 for (next_iv = next_interval (iv);
4330 (next_iv
4331 && (NILP (limit)
4332 || XFIXNAT (limit) > next_iv->position));
4333 next_iv = next_interval (next_iv))
4334 {
4335 for (p = it_props; p->handler; ++p)
4336 {
4337 Lisp_Object new_value = textget (next_iv->plist,
4338 builtin_lisp_symbol (p->name));
4339 if (!EQ (values_here[p->idx], new_value))
4340 break;
4341 }
4342
4343 if (p->handler)
4344 break;
4345 }
4346
4347 if (next_iv)
4348 {
4349 if (FIXNUMP (limit)
4350 && next_iv->position >= XFIXNAT (limit))
4351
4352 it->stop_charpos = min (XFIXNAT (limit), it->stop_charpos);
4353 else
4354
4355 it->stop_charpos = min (it->stop_charpos, next_iv->position);
4356 }
4357 }
4358
4359 if (it->cmp_it.id < 0
4360 && (STRINGP (it->string)
4361 || ((!it->bidi_p || it->bidi_it.scan_dir >= 0)
4362 && it->cmp_it.stop_pos <= IT_CHARPOS (*it))))
4363 {
4364 ptrdiff_t stoppos = it->end_charpos;
4365
4366
4367
4368
4369 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4370 stoppos = -1;
4371 else if (cmp_limit_pos > 0)
4372 stoppos = cmp_limit_pos;
4373
4374
4375
4376 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
4377 stoppos, it->string, false);
4378 }
4379
4380 eassert (STRINGP (it->string)
4381 || (it->stop_charpos >= BEGV
4382 && it->stop_charpos >= IT_CHARPOS (*it)));
4383 }
4384
4385
4386
4387
4388 #define MAX_DISP_SCAN 250
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402 ptrdiff_t
4403 compute_display_string_pos (struct text_pos *position,
4404 struct bidi_string_data *string,
4405 struct window *w,
4406 bool frame_window_p, int *disp_prop)
4407 {
4408
4409 Lisp_Object object, object1;
4410 Lisp_Object pos, spec, limpos;
4411 bool string_p = string && (STRINGP (string->lstring) || string->s);
4412 ptrdiff_t eob = string_p ? string->schars : ZV;
4413 ptrdiff_t begb = string_p ? 0 : BEGV;
4414 ptrdiff_t bufpos, charpos = CHARPOS (*position);
4415 ptrdiff_t lim =
4416 (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
4417 struct text_pos tpos;
4418 int rv = 0;
4419
4420 if (string && STRINGP (string->lstring))
4421 object1 = object = string->lstring;
4422 else if (w && !string_p)
4423 {
4424 XSETWINDOW (object, w);
4425 object1 = Qnil;
4426 }
4427 else
4428 object1 = object = Qnil;
4429
4430 *disp_prop = 1;
4431
4432 if (charpos >= eob
4433
4434
4435 || string->from_disp_str
4436
4437 || (string->s && !STRINGP (object)))
4438 {
4439 *disp_prop = 0;
4440 return eob;
4441 }
4442
4443
4444
4445 pos = make_fixnum (charpos);
4446 if (STRINGP (object))
4447 bufpos = string->bufpos;
4448 else
4449 bufpos = charpos;
4450 tpos = *position;
4451 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
4452 && (charpos <= begb
4453 || !EQ (Fget_char_property (make_fixnum (charpos - 1), Qdisplay,
4454 object),
4455 spec))
4456 && (rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos, bufpos,
4457 frame_window_p)))
4458 {
4459 if (rv == 2)
4460 *disp_prop = 2;
4461 return charpos;
4462 }
4463
4464
4465
4466 limpos = make_fixnum (lim);
4467 do {
4468 pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos);
4469 CHARPOS (tpos) = XFIXNAT (pos);
4470 if (CHARPOS (tpos) >= lim)
4471 {
4472 *disp_prop = 0;
4473 break;
4474 }
4475 if (STRINGP (object))
4476 BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
4477 else
4478 BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
4479 spec = Fget_char_property (pos, Qdisplay, object);
4480 if (!STRINGP (object))
4481 bufpos = CHARPOS (tpos);
4482 } while (NILP (spec)
4483 || !(rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos,
4484 bufpos, frame_window_p)));
4485 if (rv == 2)
4486 *disp_prop = 2;
4487
4488 return CHARPOS (tpos);
4489 }
4490
4491
4492
4493
4494
4495
4496 ptrdiff_t
4497 compute_display_string_end (ptrdiff_t charpos, struct bidi_string_data *string)
4498 {
4499
4500 Lisp_Object object =
4501 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
4502 Lisp_Object pos = make_fixnum (charpos);
4503 ptrdiff_t eob =
4504 (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
4505
4506 if (charpos >= eob || (string->s && !STRINGP (object)))
4507 return eob;
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523 if (NILP (Fget_char_property (pos, Qdisplay, object)))
4524 return -1;
4525
4526
4527
4528 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
4529
4530 return XFIXNAT (pos);
4531 }
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543 static enum prop_handled
4544 handle_fontified_prop (struct it *it)
4545 {
4546 Lisp_Object prop, pos;
4547 enum prop_handled handled = HANDLED_NORMALLY;
4548
4549 if (!NILP (Vmemory_full))
4550 return handled;
4551
4552
4553
4554
4555
4556 if (!STRINGP (it->string)
4557 && it->s == NULL
4558 && !NILP (Vfontification_functions)
4559 && !(input_was_pending && redisplay_skip_fontification_on_input)
4560 && !NILP (Vrun_hooks)
4561 && (pos = make_fixnum (IT_CHARPOS (*it)),
4562 prop = Fget_char_property (pos, Qfontified, Qnil),
4563
4564
4565 NILP (prop) && IT_CHARPOS (*it) < Z))
4566 {
4567 specpdl_ref count = SPECPDL_INDEX ();
4568 Lisp_Object val;
4569 struct buffer *obuf = current_buffer;
4570 ptrdiff_t begv = BEGV, zv = ZV;
4571 bool old_clip_changed = current_buffer->clip_changed;
4572 bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
4573
4574 val = Vfontification_functions;
4575 specbind (Qfontification_functions, Qnil);
4576
4577 eassert (it->end_charpos == ZV);
4578
4579 if (current_buffer->long_line_optimizations_p
4580 && long_line_optimizations_region_size > 0)
4581 {
4582 ptrdiff_t begv = it->large_narrowing_begv;
4583 ptrdiff_t zv = it->large_narrowing_zv;
4584 ptrdiff_t charpos = IT_CHARPOS (*it);
4585 if (charpos < begv || charpos > zv)
4586 {
4587 begv = get_large_narrowing_begv (charpos);
4588 zv = get_large_narrowing_zv (charpos);
4589 }
4590 if (begv != BEG || zv != Z)
4591 labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
4592 Qlong_line_optimizations_in_fontification_functions);
4593 }
4594
4595
4596
4597 it->f->inhibit_clear_image_cache = true;
4598
4599 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
4600 safe_call1 (val, pos);
4601 else
4602 {
4603 Lisp_Object fns, fn;
4604
4605 fns = Qnil;
4606
4607 for (; CONSP (val); val = XCDR (val))
4608 {
4609 fn = XCAR (val);
4610
4611 if (EQ (fn, Qt))
4612 {
4613
4614
4615
4616
4617
4618 for (fns = Fdefault_value (Qfontification_functions);
4619 CONSP (fns);
4620 fns = XCDR (fns))
4621 {
4622 fn = XCAR (fns);
4623 if (!EQ (fn, Qt))
4624 safe_call1 (fn, pos);
4625 }
4626 }
4627 else
4628 safe_call1 (fn, pos);
4629 }
4630 }
4631
4632 it->f->inhibit_clear_image_cache = saved_inhibit_flag;
4633 unbind_to (count, Qnil);
4634
4635
4636
4637
4638
4639
4640
4641
4642 if (obuf == current_buffer)
4643 {
4644 if (begv == BEGV && zv == ZV)
4645 current_buffer->clip_changed = old_clip_changed;
4646 }
4647
4648
4649 else if (BUFFER_LIVE_P (obuf))
4650 set_buffer_internal_1 (obuf);
4651
4652
4653
4654
4655
4656
4657 it->end_charpos = ZV;
4658
4659
4660
4661
4662 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
4663 handled = HANDLED_RECOMPUTE_PROPS;
4664 }
4665
4666 return handled;
4667 }
4668
4669
4670
4671
4672
4673
4674
4675 static int
4676 face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
4677 {
4678 ptrdiff_t next_stop;
4679
4680 if (!STRINGP (it->string))
4681 {
4682 return face_at_buffer_position (it->w,
4683 IT_CHARPOS (*it),
4684 &next_stop,
4685 (IT_CHARPOS (*it)
4686 + TEXT_PROP_DISTANCE_LIMIT),
4687 false, it->base_face_id,
4688 attr_filter);
4689 }
4690 else
4691 {
4692 int base_face_id;
4693 ptrdiff_t bufpos;
4694 int i;
4695 Lisp_Object from_overlay
4696 = (it->current.overlay_string_index >= 0
4697 ? it->string_overlays[it->current.overlay_string_index
4698 % OVERLAY_STRING_CHUNK_SIZE]
4699 : Qnil);
4700
4701
4702
4703
4704
4705
4706
4707 if (! NILP (from_overlay))
4708 for (i = it->sp - 1; i >= 0; i--)
4709 {
4710 if (it->stack[i].current.overlay_string_index >= 0)
4711 from_overlay
4712 = it->string_overlays[it->stack[i].current.overlay_string_index
4713 % OVERLAY_STRING_CHUNK_SIZE];
4714 else if (! NILP (it->stack[i].from_overlay))
4715 from_overlay = it->stack[i].from_overlay;
4716
4717 if (!NILP (from_overlay))
4718 break;
4719 }
4720
4721 if (! NILP (from_overlay))
4722 {
4723 bufpos = IT_CHARPOS (*it);
4724
4725
4726 base_face_id
4727 = face_for_overlay_string (it->w,
4728 IT_CHARPOS (*it),
4729 &next_stop,
4730 (IT_CHARPOS (*it)
4731 + TEXT_PROP_DISTANCE_LIMIT),
4732 false,
4733 from_overlay, attr_filter);
4734 }
4735 else
4736 {
4737 bufpos = 0;
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755 base_face_id = it->string_from_prefix_prop_p
4756 ? (!NILP (Vface_remapping_alist)
4757 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4758 : DEFAULT_FACE_ID)
4759 : underlying_face_id (it);
4760 }
4761
4762 return face_at_string_position (it->w,
4763 it->string,
4764 IT_STRING_CHARPOS (*it),
4765 bufpos,
4766 &next_stop,
4767 base_face_id, false,
4768 attr_filter);
4769 }
4770 }
4771
4772
4773
4774
4775 static enum prop_handled
4776 handle_face_prop (struct it *it)
4777 {
4778 specpdl_ref count = SPECPDL_INDEX ();
4779
4780
4781
4782 specbind (Qinhibit_quit, Qt);
4783 const int new_face_id = face_at_pos (it, 0);
4784 unbind_to (count, Qnil);
4785
4786
4787
4788
4789
4790
4791
4792
4793 if (new_face_id != it->face_id)
4794 {
4795 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
4796
4797
4798
4799 struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
4800
4801
4802
4803
4804 if (!STRINGP (it->string)
4805 && !old_face
4806 && IT_CHARPOS (*it) > BEG)
4807 {
4808 const int prev_face_id = face_before_it_pos (it);
4809
4810 old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
4811 }
4812
4813
4814
4815
4816 it->face_id = new_face_id;
4817
4818
4819 if (!(it->start_of_box_run_p && old_face && old_face->box))
4820 it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
4821 && (old_face == NULL || !old_face->box));
4822 it->face_box_p = new_face->box != FACE_NO_BOX;
4823 }
4824
4825 return HANDLED_NORMALLY;
4826 }
4827
4828
4829
4830
4831
4832
4833
4834 static int
4835 underlying_face_id (const struct it *it)
4836 {
4837 int face_id = it->base_face_id, i;
4838
4839 eassert (STRINGP (it->string));
4840
4841 for (i = it->sp - 1; i >= 0; --i)
4842 if (NILP (it->stack[i].string))
4843 face_id = it->stack[i].face_id;
4844
4845 return face_id;
4846 }
4847
4848
4849
4850
4851
4852
4853
4854 static int
4855 face_before_or_after_it_pos (struct it *it, bool before_p)
4856 {
4857 int face_id, limit;
4858 ptrdiff_t next_check_charpos;
4859 struct it it_copy;
4860 void *it_copy_data = NULL;
4861
4862 eassert (it->s == NULL);
4863
4864 if (STRINGP (it->string))
4865 {
4866 ptrdiff_t bufpos, charpos;
4867 int base_face_id;
4868
4869
4870
4871
4872
4873 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
4874 || (IT_STRING_CHARPOS (*it) == 0 && before_p)
4875 || it->current_x <= it->first_visible_x)
4876 return it->face_id;
4877
4878 if (!it->bidi_p)
4879 {
4880
4881
4882
4883 if (before_p)
4884 charpos = IT_STRING_CHARPOS (*it) - 1;
4885 else if (it->what == IT_COMPOSITION)
4886
4887
4888 charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars;
4889 else
4890 charpos = IT_STRING_CHARPOS (*it) + 1;
4891 }
4892 else
4893 {
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904 SAVE_IT (it_copy, *it, it_copy_data);
4905 IT_STRING_CHARPOS (it_copy) = 0;
4906 bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
4907 it_copy.bidi_it.scan_dir = 0;
4908
4909 do
4910 {
4911 charpos = it_copy.bidi_it.charpos;
4912 if (charpos >= SCHARS (it->string))
4913 break;
4914 bidi_move_to_visually_next (&it_copy.bidi_it);
4915 }
4916 while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
4917
4918 if (!before_p)
4919 {
4920
4921
4922
4923 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4924
4925
4926
4927 if (it_copy.bidi_it.first_elt)
4928 n++;
4929 while (n--)
4930 bidi_move_to_visually_next (&it_copy.bidi_it);
4931
4932 charpos = it_copy.bidi_it.charpos;
4933 }
4934
4935 RESTORE_IT (it, it, it_copy_data);
4936 }
4937 eassert (0 <= charpos && charpos <= SCHARS (it->string));
4938
4939 if (it->current.overlay_string_index >= 0)
4940 bufpos = IT_CHARPOS (*it);
4941 else
4942 bufpos = 0;
4943
4944 base_face_id = underlying_face_id (it);
4945
4946
4947 face_id = face_at_string_position (it->w, it->string, charpos,
4948 bufpos, &next_check_charpos,
4949 base_face_id, false, 0);
4950
4951
4952
4953
4954 if (STRING_MULTIBYTE (it->string))
4955 {
4956 struct text_pos pos1 = string_pos (charpos, it->string);
4957 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1);
4958 struct face *face = FACE_FROM_ID (it->f, face_id);
4959 int len, c = check_char_and_length (p, &len);
4960 face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string);
4961 }
4962 }
4963 else
4964 {
4965 struct text_pos pos;
4966
4967 if ((IT_CHARPOS (*it) >= ZV && !before_p)
4968 || (IT_CHARPOS (*it) <= BEGV && before_p))
4969 return it->face_id;
4970
4971 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
4972 pos = it->current.pos;
4973
4974 if (!it->bidi_p)
4975 {
4976 if (before_p)
4977 DEC_TEXT_POS (pos, it->multibyte_p);
4978 else
4979 {
4980 if (it->what == IT_COMPOSITION)
4981 {
4982
4983
4984 pos.charpos += it->cmp_it.nchars;
4985 pos.bytepos += it->len;
4986 }
4987 else
4988 INC_TEXT_POS (pos, it->multibyte_p);
4989 }
4990 }
4991 else
4992 {
4993 if (before_p)
4994 {
4995 int current_x;
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006 if (it->current_x <= it->first_visible_x)
5007 return it->face_id;
5008 SAVE_IT (it_copy, *it, it_copy_data);
5009
5010
5011
5012
5013
5014 current_x = it_copy.current_x;
5015 move_it_vertically_backward (&it_copy, 0);
5016 move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
5017 pos = it_copy.current.pos;
5018 RESTORE_IT (it, it, it_copy_data);
5019 }
5020 else
5021 {
5022
5023
5024
5025 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
5026
5027 it_copy = *it;
5028
5029
5030
5031 if (it->bidi_it.first_elt)
5032 n++;
5033 while (n--)
5034 bidi_move_to_visually_next (&it_copy.bidi_it);
5035
5036 SET_TEXT_POS (pos,
5037 it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
5038 }
5039 }
5040 eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
5041
5042
5043 face_id = face_at_buffer_position (it->w,
5044 CHARPOS (pos),
5045 &next_check_charpos,
5046 limit, false, -1, 0);
5047
5048
5049
5050
5051 if (it->multibyte_p)
5052 {
5053 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
5054 struct face *face = FACE_FROM_ID (it->f, face_id);
5055 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
5056 }
5057 }
5058
5059 return face_id;
5060 }
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071 static enum prop_handled
5072 handle_invisible_prop (struct it *it)
5073 {
5074 enum prop_handled handled = HANDLED_NORMALLY;
5075 int invis;
5076 Lisp_Object prop;
5077
5078 if (STRINGP (it->string))
5079 {
5080 Lisp_Object end_charpos, limit;
5081
5082
5083
5084
5085 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
5086 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5087 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5088
5089 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5090 {
5091
5092
5093 bool display_ellipsis_p = (invis == 2);
5094 ptrdiff_t len, endpos;
5095
5096 handled = HANDLED_RECOMPUTE_PROPS;
5097
5098
5099
5100 endpos = len = SCHARS (it->string);
5101 XSETINT (limit, len);
5102 do
5103 {
5104 end_charpos
5105 = Fnext_single_property_change (end_charpos, Qinvisible,
5106 it->string, limit);
5107
5108
5109 eassert (FIXNUMP (end_charpos));
5110 if (FIXNUMP (end_charpos))
5111 {
5112 endpos = XFIXNAT (end_charpos);
5113 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5114 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5115 if (invis == 2)
5116 display_ellipsis_p = true;
5117 }
5118 else
5119 endpos = len;
5120 }
5121 while (invis != 0 && endpos < len);
5122
5123 if (display_ellipsis_p)
5124 it->ellipsis_p = true;
5125
5126 if (endpos < len)
5127 {
5128
5129 struct text_pos old;
5130 ptrdiff_t oldpos;
5131
5132 old = it->current.string_pos;
5133 oldpos = CHARPOS (old);
5134 if (it->bidi_p)
5135 {
5136 if (it->bidi_it.first_elt
5137 && it->bidi_it.charpos < SCHARS (it->string))
5138 bidi_paragraph_init (it->paragraph_embedding,
5139 &it->bidi_it, true);
5140
5141 do
5142 {
5143 bidi_move_to_visually_next (&it->bidi_it);
5144 }
5145 while (oldpos <= it->bidi_it.charpos
5146 && it->bidi_it.charpos < endpos
5147 && it->bidi_it.charpos < it->bidi_it.string.schars);
5148
5149 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5150 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5151 if (IT_CHARPOS (*it) >= endpos)
5152 it->prev_stop = endpos;
5153 }
5154 else
5155 {
5156 IT_STRING_CHARPOS (*it) = endpos;
5157 compute_string_pos (&it->current.string_pos, old, it->string);
5158 }
5159 }
5160 else
5161 {
5162
5163
5164
5165 if (it->current.overlay_string_index >= 0
5166 && !display_ellipsis_p)
5167 {
5168 next_overlay_string (it);
5169
5170
5171 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5172 }
5173 else
5174 {
5175 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
5176 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5177 }
5178 }
5179 }
5180 }
5181 else
5182 {
5183 ptrdiff_t newpos, next_stop, start_charpos, tem;
5184 Lisp_Object pos, overlay;
5185
5186
5187 tem = start_charpos = IT_CHARPOS (*it);
5188 pos = make_fixnum (tem);
5189 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5190 &overlay);
5191 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5192
5193
5194 if (invis != 0 && start_charpos < it->end_charpos)
5195 {
5196
5197
5198 bool display_ellipsis_p = invis == 2;
5199
5200 handled = HANDLED_RECOMPUTE_PROPS;
5201
5202
5203
5204 do
5205 {
5206
5207
5208
5209
5210
5211 newpos = skip_invisible (tem, &next_stop, ZV, it->window);
5212
5213
5214
5215
5216 if (newpos == tem || newpos >= ZV)
5217 invis = 0;
5218 else
5219 {
5220
5221
5222
5223
5224
5225
5226 pos = make_fixnum (newpos);
5227 prop = Fget_char_property (pos, Qinvisible, it->window);
5228 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5229 }
5230
5231
5232
5233 if (invis != 0)
5234 tem = next_stop;
5235
5236
5237
5238 if (invis == 2)
5239 display_ellipsis_p = true;
5240 }
5241 while (invis != 0);
5242
5243
5244 if (it->bidi_p)
5245 {
5246 ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
5247 bool on_newline
5248 = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
5249 bool after_newline
5250 = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
5251
5252
5253
5254
5255
5256
5257
5258
5259 if (on_newline || after_newline)
5260 {
5261 struct text_pos tpos;
5262 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
5263
5264 SET_TEXT_POS (tpos, newpos, bpos);
5265 reseat_1 (it, tpos, false);
5266
5267
5268
5269
5270
5271 if (on_newline)
5272 {
5273 it->bidi_it.first_elt = false;
5274 it->bidi_it.paragraph_dir = pdir;
5275 it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
5276 it->bidi_it.nchars = 1;
5277 it->bidi_it.ch_len = 1;
5278 }
5279 }
5280 else
5281 {
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5293 {
5294
5295
5296
5297
5298
5299
5300
5301 bidi_paragraph_init (it->paragraph_embedding,
5302 &it->bidi_it, true);
5303 }
5304 do
5305 {
5306 bidi_move_to_visually_next (&it->bidi_it);
5307 }
5308 while (it->stop_charpos <= it->bidi_it.charpos
5309 && it->bidi_it.charpos < newpos);
5310 IT_CHARPOS (*it) = it->bidi_it.charpos;
5311 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5312
5313
5314
5315
5316 if (IT_CHARPOS (*it) >= newpos)
5317 it->prev_stop = newpos;
5318 }
5319 }
5320 else
5321 {
5322 IT_CHARPOS (*it) = newpos;
5323 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
5324 }
5325
5326 if (display_ellipsis_p)
5327 {
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340 if (!STRINGP (it->object))
5341 {
5342 it->position.charpos = newpos - 1;
5343 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5344 }
5345 }
5346
5347
5348
5349
5350
5351
5352
5353 if (NILP (overlay)
5354 && get_overlay_strings (it, it->stop_charpos))
5355 {
5356 handled = HANDLED_RECOMPUTE_PROPS;
5357 if (it->sp > 0)
5358 {
5359 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372 it->stack[it->sp - 1].stop_charpos
5373 = CHARPOS (it->stack[it->sp - 1].current.pos);
5374 }
5375 }
5376 else if (display_ellipsis_p)
5377 {
5378 it->ellipsis_p = true;
5379
5380
5381
5382 handled = HANDLED_RETURN;
5383 }
5384 }
5385 }
5386
5387 return handled;
5388 }
5389
5390
5391
5392
5393
5394 static void
5395 setup_for_ellipsis (struct it *it, int len)
5396 {
5397
5398
5399 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5400 {
5401 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5402 it->dpvec = v->contents;
5403 it->dpend = v->contents + v->header.size;
5404 }
5405 else
5406 {
5407
5408 it->dpvec = default_invis_vector;
5409 it->dpend = default_invis_vector + 3;
5410 }
5411
5412 it->dpvec_char_len = len;
5413 it->current.dpvec_index = 0;
5414 it->dpvec_face_id = -1;
5415
5416
5417
5418
5419
5420
5421
5422
5423 if (it->saved_face_id >= 0)
5424 it->face_id = it->saved_face_id;
5425
5426
5427
5428 if (it->method == GET_FROM_BUFFER)
5429 it->ignore_overlay_strings_at_pos_p = false;
5430
5431 it->method = GET_FROM_DISPLAY_VECTOR;
5432 it->ellipsis_p = true;
5433 }
5434
5435
5436 static Lisp_Object
5437 find_display_property (Lisp_Object disp, Lisp_Object prop)
5438 {
5439 if (NILP (disp))
5440 return Qnil;
5441
5442 if (VECTORP (disp))
5443 {
5444 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5445 {
5446 Lisp_Object elem = AREF (disp, i);
5447 if (CONSP (elem)
5448 && CONSP (XCDR (elem))
5449 && EQ (XCAR (elem), prop))
5450 return XCAR (XCDR (elem));
5451 }
5452 return Qnil;
5453 }
5454
5455 else if (CONSP (disp)
5456 && CONSP (XCAR (disp)))
5457 {
5458 while (!NILP (disp))
5459 {
5460 Lisp_Object elem = XCAR (disp);
5461 if (CONSP (elem)
5462 && CONSP (XCDR (elem))
5463 && EQ (XCAR (elem), prop))
5464 return XCAR (XCDR (elem));
5465
5466
5467
5468 if (CONSP (XCDR (disp)))
5469 disp = XCDR (disp);
5470 else
5471 disp = Qnil;
5472 }
5473 return Qnil;
5474 }
5475
5476 else if (CONSP (disp)
5477 && CONSP (XCDR (disp))
5478 && EQ (XCAR (disp), prop))
5479 return XCAR (XCDR (disp));
5480 else
5481 return Qnil;
5482 }
5483
5484 static Lisp_Object
5485 get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object)
5486 {
5487 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5488 Qdisplay, object),
5489 prop);
5490 }
5491
5492 static void
5493 display_min_width (struct it *it, ptrdiff_t bufpos,
5494 Lisp_Object object, Lisp_Object width_spec)
5495 {
5496
5497
5498 if (!NILP (it->min_width_property)
5499 && !EQ (width_spec, it->min_width_property))
5500 {
5501 if (!it->glyph_row)
5502 return;
5503
5504
5505
5506
5507
5508 if ((bufpos == 0
5509 && !EQ (it->min_width_property,
5510 get_display_property (0, Qmin_width, object)))
5511
5512
5513 || (bufpos > BEGV
5514 && EQ (it->min_width_property,
5515 get_display_property (bufpos - 1, Qmin_width, object))))
5516 {
5517 Lisp_Object w = Qnil;
5518 double width;
5519 #ifdef HAVE_WINDOW_SYSTEM
5520 if (FRAME_WINDOW_P (it->f))
5521 {
5522 struct font *font = NULL;
5523 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5524 font = face->font ? face->font : FRAME_FONT (it->f);
5525 calc_pixel_width_or_height (&width, it,
5526 XCAR (it->min_width_property),
5527 font, true, NULL);
5528 width -= it->current_x - it->min_width_start;
5529 w = list1 (make_int (width));
5530 }
5531 else
5532 #endif
5533 {
5534 calc_pixel_width_or_height (&width, it,
5535 XCAR (it->min_width_property),
5536 NULL, true, NULL);
5537 width -= (it->current_x - it->min_width_start) /
5538 FRAME_COLUMN_WIDTH (it->f);
5539 w = make_int (width);
5540 }
5541
5542
5543 it->object = list3 (Qspace, QCwidth, w);
5544 produce_stretch_glyph (it);
5545 if (it->area == TEXT_AREA)
5546 it->current_x += it->pixel_width;
5547 it->min_width_property = Qnil;
5548 }
5549 }
5550
5551
5552
5553
5554 if (CONSP (width_spec))
5555 {
5556 if (bufpos == BEGV
5557
5558 || (bufpos == 0
5559 && !EQ (it->min_width_property,
5560 get_display_property (0, Qmin_width, object)))
5561
5562 || (bufpos > BEGV
5563 && !EQ (width_spec,
5564 get_display_property (bufpos - 1, Qmin_width, object))))
5565 {
5566 it->min_width_property = width_spec;
5567 it->min_width_start = it->current_x;
5568 }
5569 }
5570 }
5571
5572 DEFUN ("get-display-property", Fget_display_property,
5573 Sget_display_property, 2, 4, 0,
5574 doc:
5575
5576
5577
5578
5579 )
5580 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5581 Lisp_Object properties)
5582 {
5583 if (NILP (properties))
5584 properties = Fget_text_property (position, Qdisplay, object);
5585 else
5586 CHECK_LIST (properties);
5587
5588 return find_display_property (properties, prop);
5589 }
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603 static enum prop_handled
5604 handle_display_prop (struct it *it)
5605 {
5606 Lisp_Object propval, object, overlay;
5607 struct text_pos *position;
5608 ptrdiff_t bufpos;
5609
5610 int display_replaced = 0;
5611
5612 if (STRINGP (it->string))
5613 {
5614 object = it->string;
5615 position = &it->current.string_pos;
5616 bufpos = CHARPOS (it->current.pos);
5617 }
5618 else
5619 {
5620 XSETWINDOW (object, it->w);
5621 position = &it->current.pos;
5622 bufpos = CHARPOS (*position);
5623 }
5624
5625
5626 it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
5627 it->space_width = Qnil;
5628 it->font_height = Qnil;
5629 it->voffset = 0;
5630
5631
5632
5633
5634 if (!it->string_from_display_prop_p)
5635 it->area = TEXT_AREA;
5636
5637 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5638 Qdisplay, object, &overlay);
5639
5640
5641 if (!STRINGP (it->string))
5642 object = it->w->contents;
5643
5644
5645 if (!NILP (it->min_width_property)
5646 && NILP (find_display_property (propval, Qmin_width)))
5647 display_min_width (it, bufpos, object, Qnil);
5648
5649 if (NILP (propval))
5650 return HANDLED_NORMALLY;
5651
5652
5653
5654 display_replaced = handle_display_spec (it, propval, object, overlay,
5655 position, bufpos,
5656 FRAME_WINDOW_P (it->f));
5657 return display_replaced != 0 ? HANDLED_RETURN : HANDLED_NORMALLY;
5658 }
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676 static int
5677 handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5678 Lisp_Object overlay, struct text_pos *position,
5679 ptrdiff_t bufpos, bool frame_window_p)
5680 {
5681 int replacing = 0;
5682 bool enable_eval = true;
5683
5684
5685 if (CONSP (spec) && EQ (XCAR (spec), Qdisable_eval))
5686 {
5687 enable_eval = false;
5688 spec = CONSP (XCDR (spec)) ? XCAR (XCDR (spec)) : Qnil;
5689 }
5690
5691 if (CONSP (spec)
5692
5693 && !EQ (XCAR (spec), Qimage)
5694 #ifdef HAVE_XWIDGETS
5695 && !EQ (XCAR (spec), Qxwidget)
5696 #endif
5697 && !EQ (XCAR (spec), Qspace)
5698 && !EQ (XCAR (spec), Qwhen)
5699 && !EQ (XCAR (spec), Qslice)
5700 && !EQ (XCAR (spec), Qspace_width)
5701 && !EQ (XCAR (spec), Qheight)
5702 && !EQ (XCAR (spec), Qraise)
5703
5704 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5705 && !EQ (XCAR (spec), Qleft_fringe)
5706 && !EQ (XCAR (spec), Qright_fringe)
5707 && !EQ (XCAR (spec), Qmin_width)
5708 && !NILP (XCAR (spec)))
5709 {
5710 for (; CONSP (spec); spec = XCDR (spec))
5711 {
5712 int rv = handle_single_display_spec (it, XCAR (spec), object,
5713 overlay, position, bufpos,
5714 replacing, frame_window_p,
5715 enable_eval);
5716 if (rv != 0)
5717 {
5718 replacing = rv;
5719
5720
5721 if (!it || STRINGP (object))
5722 break;
5723 }
5724 }
5725 }
5726 else if (VECTORP (spec))
5727 {
5728 ptrdiff_t i;
5729 for (i = 0; i < ASIZE (spec); ++i)
5730 {
5731 int rv = handle_single_display_spec (it, AREF (spec, i), object,
5732 overlay, position, bufpos,
5733 replacing, frame_window_p,
5734 enable_eval);
5735 if (rv != 0)
5736 {
5737 replacing = rv;
5738
5739
5740 if (!it || STRINGP (object))
5741 break;
5742 }
5743 }
5744 }
5745 else
5746 replacing = handle_single_display_spec (it, spec, object, overlay, position,
5747 bufpos, 0, frame_window_p,
5748 enable_eval);
5749 return replacing;
5750 }
5751
5752
5753
5754
5755 static struct text_pos
5756 display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
5757 {
5758 Lisp_Object end;
5759 struct text_pos end_pos;
5760
5761 end = Fnext_single_char_property_change (make_fixnum (CHARPOS (start_pos)),
5762 Qdisplay, object, Qnil);
5763 CHARPOS (end_pos) = XFIXNAT (end);
5764 if (STRINGP (object))
5765 compute_string_pos (&end_pos, start_pos, it->string);
5766 else
5767 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFIXNAT (end));
5768
5769 return end_pos;
5770 }
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798 static int
5799 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5800 Lisp_Object overlay, struct text_pos *position,
5801 ptrdiff_t bufpos, int display_replaced,
5802 bool frame_window_p, bool enable_eval_p)
5803 {
5804 Lisp_Object form;
5805 Lisp_Object location, value;
5806 struct text_pos start_pos = *position;
5807 void *itdata = NULL;
5808
5809
5810
5811 form = Qt;
5812 if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
5813 {
5814 spec = XCDR (spec);
5815 if (!CONSP (spec))
5816 return 0;
5817 form = XCAR (spec);
5818 spec = XCDR (spec);
5819 }
5820
5821 if (!NILP (form) && !EQ (form, Qt) && !enable_eval_p)
5822 form = Qnil;
5823 if (!NILP (form) && !EQ (form, Qt))
5824 {
5825 specpdl_ref count = SPECPDL_INDEX ();
5826
5827
5828
5829
5830
5831
5832 if (NILP (object))
5833 XSETBUFFER (object, current_buffer);
5834 specbind (Qobject, object);
5835 specbind (Qposition, make_fixnum (CHARPOS (*position)));
5836 specbind (Qbuffer_position, make_fixnum (bufpos));
5837
5838
5839 itdata = bidi_shelve_cache ();
5840 form = safe_eval (form);
5841 bidi_unshelve_cache (itdata, false);
5842 form = unbind_to (count, form);
5843 }
5844
5845 if (NILP (form))
5846 return 0;
5847
5848
5849 if (CONSP (spec)
5850 && EQ (XCAR (spec), Qheight)
5851 && CONSP (XCDR (spec)))
5852 {
5853 if (it)
5854 {
5855 if (!FRAME_WINDOW_P (it->f))
5856 return 0;
5857
5858 it->font_height = XCAR (XCDR (spec));
5859 if (!NILP (it->font_height))
5860 {
5861 int new_height = -1;
5862
5863 if (CONSP (it->font_height)
5864 && (EQ (XCAR (it->font_height), Qplus)
5865 || EQ (XCAR (it->font_height), Qminus))
5866 && CONSP (XCDR (it->font_height))
5867 && RANGED_FIXNUMP (0, XCAR (XCDR (it->font_height)), INT_MAX))
5868 {
5869
5870 int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
5871 if (EQ (XCAR (it->font_height), Qplus))
5872 steps = - steps;
5873 it->face_id = smaller_face (it->f, it->face_id, steps);
5874 }
5875 else if (FUNCTIONP (it->font_height) && enable_eval_p)
5876 {
5877
5878
5879 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5880 Lisp_Object height;
5881 itdata = bidi_shelve_cache ();
5882 height = safe_call1 (it->font_height,
5883 face->lface[LFACE_HEIGHT_INDEX]);
5884 bidi_unshelve_cache (itdata, false);
5885 if (NUMBERP (height))
5886 new_height = XFLOATINT (height);
5887 }
5888 else if (NUMBERP (it->font_height))
5889 {
5890
5891 struct face *f;
5892
5893 f = FACE_FROM_ID (it->f,
5894 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
5895 new_height = (XFLOATINT (it->font_height)
5896 * XFIXNUM (f->lface[LFACE_HEIGHT_INDEX]));
5897 }
5898 else if (enable_eval_p)
5899 {
5900
5901
5902 specpdl_ref count = SPECPDL_INDEX ();
5903 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5904
5905 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
5906 itdata = bidi_shelve_cache ();
5907 value = safe_eval (it->font_height);
5908 bidi_unshelve_cache (itdata, false);
5909 value = unbind_to (count, value);
5910
5911 if (NUMBERP (value))
5912 new_height = XFLOATINT (value);
5913 }
5914
5915 if (new_height > 0)
5916 it->face_id = face_with_height (it->f, it->face_id, new_height);
5917 }
5918 }
5919
5920 return 0;
5921 }
5922
5923
5924 if (CONSP (spec)
5925 && EQ (XCAR (spec), Qspace_width)
5926 && CONSP (XCDR (spec)))
5927 {
5928 if (it)
5929 {
5930 if (!FRAME_WINDOW_P (it->f))
5931 return 0;
5932
5933 value = XCAR (XCDR (spec));
5934 if (NUMBERP (value) && XFLOATINT (value) > 0)
5935 it->space_width = value;
5936 }
5937
5938 return 0;
5939 }
5940
5941
5942 if (CONSP (spec)
5943 && EQ (XCAR (spec), Qmin_width)
5944 && CONSP (XCDR (spec))
5945 && CONSP (XCAR (XCDR (spec))))
5946 {
5947 if (it)
5948 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5949 return 0;
5950 }
5951
5952
5953 if (CONSP (spec)
5954 && EQ (XCAR (spec), Qslice))
5955 {
5956 Lisp_Object tem;
5957
5958 if (it)
5959 {
5960 if (!FRAME_WINDOW_P (it->f))
5961 return 0;
5962
5963 if (tem = XCDR (spec), CONSP (tem))
5964 {
5965 it->slice.x = XCAR (tem);
5966 if (tem = XCDR (tem), CONSP (tem))
5967 {
5968 it->slice.y = XCAR (tem);
5969 if (tem = XCDR (tem), CONSP (tem))
5970 {
5971 it->slice.width = XCAR (tem);
5972 if (tem = XCDR (tem), CONSP (tem))
5973 it->slice.height = XCAR (tem);
5974 }
5975 }
5976 }
5977 }
5978
5979 return 0;
5980 }
5981
5982
5983 if (CONSP (spec)
5984 && EQ (XCAR (spec), Qraise)
5985 && CONSP (XCDR (spec)))
5986 {
5987 if (it)
5988 {
5989 if (!FRAME_WINDOW_P (it->f))
5990 return 0;
5991
5992 #ifdef HAVE_WINDOW_SYSTEM
5993 value = XCAR (XCDR (spec));
5994 if (NUMBERP (value))
5995 {
5996 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5997 it->voffset = - (XFLOATINT (value)
5998 * (normal_char_height (face->font, -1)));
5999 }
6000 #endif
6001 }
6002
6003 return 0;
6004 }
6005
6006
6007
6008 if (it && it->string_from_display_prop_p)
6009 return 0;
6010
6011
6012
6013 if (it)
6014 {
6015 start_pos = *position;
6016 *position = display_prop_end (it, object, start_pos);
6017
6018
6019
6020
6021
6022
6023
6024 if (!NILP (overlay))
6025 {
6026 ptrdiff_t ovendpos = OVERLAY_END (overlay);
6027
6028
6029
6030
6031
6032
6033
6034 ovendpos = clip_to_bounds (BEGV, ovendpos, ZV);
6035
6036 if (ovendpos > CHARPOS (*position))
6037 SET_TEXT_POS (*position, ovendpos, CHAR_TO_BYTE (ovendpos));
6038 }
6039 }
6040 value = Qnil;
6041
6042
6043
6044 if (it)
6045 it->stop_charpos = position->charpos;
6046
6047
6048
6049 if (CONSP (spec)
6050 && (EQ (XCAR (spec), Qleft_fringe)
6051 || EQ (XCAR (spec), Qright_fringe))
6052 && CONSP (XCDR (spec)))
6053 {
6054 if (it)
6055 {
6056 if (!FRAME_WINDOW_P (it->f))
6057
6058
6059 {
6060
6061
6062
6063
6064 if (it->bidi_p)
6065 {
6066 it->position = *position;
6067 iterate_out_of_display_property (it);
6068 *position = it->position;
6069 }
6070 return 1;
6071 }
6072 }
6073 else if (!frame_window_p)
6074 return 1;
6075
6076 #ifdef HAVE_WINDOW_SYSTEM
6077 value = XCAR (XCDR (spec));
6078 int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
6079 if (! fringe_bitmap)
6080
6081
6082 {
6083 if (it && it->bidi_p)
6084 {
6085 it->position = *position;
6086 iterate_out_of_display_property (it);
6087 *position = it->position;
6088 }
6089 return 1;
6090 }
6091
6092 if (it)
6093 {
6094 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
6095
6096 if (CONSP (XCDR (XCDR (spec))))
6097 {
6098 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
6099 int face_id2;
6100
6101
6102
6103 specpdl_ref count1 = SPECPDL_INDEX ();
6104 specbind (Qinhibit_quit, Qt);
6105 face_id2 = lookup_derived_face (it->w, it->f, face_name,
6106 FRINGE_FACE_ID, false);
6107 unbind_to (count1, Qnil);
6108 if (face_id2 >= 0)
6109 face_id = face_id2;
6110 }
6111
6112
6113
6114 push_it (it, position);
6115
6116 it->area = TEXT_AREA;
6117 it->what = IT_IMAGE;
6118 it->image_id = -1;
6119 it->position = start_pos;
6120 it->object = NILP (object) ? it->w->contents : object;
6121 it->method = GET_FROM_IMAGE;
6122 it->from_overlay = Qnil;
6123 it->face_id = face_id;
6124 it->from_disp_prop_p = true;
6125
6126
6127
6128
6129 *position = start_pos;
6130
6131 if (EQ (XCAR (spec), Qleft_fringe))
6132 {
6133 it->left_user_fringe_bitmap = fringe_bitmap;
6134 it->left_user_fringe_face_id = face_id;
6135 }
6136 else
6137 {
6138 it->right_user_fringe_bitmap = fringe_bitmap;
6139 it->right_user_fringe_face_id = face_id;
6140 }
6141 }
6142 #endif
6143 return 1;
6144 }
6145
6146
6147
6148
6149 location = Qunbound;
6150 if (CONSP (spec) && CONSP (XCAR (spec)))
6151 {
6152 Lisp_Object tem;
6153
6154 value = XCDR (spec);
6155 if (CONSP (value))
6156 value = XCAR (value);
6157
6158 tem = XCAR (spec);
6159 if (EQ (XCAR (tem), Qmargin)
6160 && (tem = XCDR (tem),
6161 tem = CONSP (tem) ? XCAR (tem) : Qnil,
6162 (NILP (tem)
6163 || EQ (tem, Qleft_margin)
6164 || EQ (tem, Qright_margin))))
6165 location = tem;
6166 }
6167
6168 if (BASE_EQ (location, Qunbound))
6169 {
6170 location = Qnil;
6171 value = spec;
6172 }
6173
6174
6175
6176
6177
6178
6179
6180
6181 bool valid_p = (STRINGP (value)
6182 #ifdef HAVE_WINDOW_SYSTEM
6183 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6184 && valid_image_p (value))
6185 #endif
6186 || (CONSP (value) && EQ (XCAR (value), Qspace))
6187 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6188 && valid_xwidget_spec_p (value)));
6189
6190 if (valid_p && display_replaced == 0)
6191 {
6192 int retval = 1;
6193
6194 if (!it)
6195 {
6196
6197
6198
6199 if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
6200 retval = 2;
6201 return retval;
6202 }
6203
6204
6205
6206 push_it (it, position);
6207 it->from_overlay = overlay;
6208 it->from_disp_prop_p = true;
6209
6210 if (NILP (location))
6211 it->area = TEXT_AREA;
6212 else if (EQ (location, Qleft_margin))
6213 it->area = LEFT_MARGIN_AREA;
6214 else
6215 it->area = RIGHT_MARGIN_AREA;
6216
6217 if (STRINGP (value))
6218 {
6219 it->string = value;
6220 it->multibyte_p = STRING_MULTIBYTE (it->string);
6221 it->current.overlay_string_index = -1;
6222 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6223 it->end_charpos = it->string_nchars = SCHARS (it->string);
6224 it->method = GET_FROM_STRING;
6225 it->stop_charpos = 0;
6226 it->prev_stop = 0;
6227 it->base_level_stop = 0;
6228 it->string_from_display_prop_p = true;
6229 it->cmp_it.id = -1;
6230
6231
6232
6233 if (BUFFERP (object))
6234 *position = start_pos;
6235
6236
6237
6238
6239 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6240 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6241 else
6242 it->paragraph_embedding = L2R;
6243
6244
6245 if (it->bidi_p)
6246 {
6247 it->bidi_it.string.lstring = it->string;
6248 it->bidi_it.string.s = NULL;
6249 it->bidi_it.string.schars = it->end_charpos;
6250 it->bidi_it.string.bufpos = bufpos;
6251 it->bidi_it.string.from_disp_str = true;
6252 it->bidi_it.string.unibyte = !it->multibyte_p;
6253 it->bidi_it.w = it->w;
6254 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6255 }
6256 }
6257 else if (CONSP (value) && EQ (XCAR (value), Qspace))
6258 {
6259 it->method = GET_FROM_STRETCH;
6260 it->object = value;
6261 *position = it->position = start_pos;
6262 retval = 1 + (it->area == TEXT_AREA);
6263 }
6264 else if (valid_xwidget_spec_p (value))
6265 {
6266 it->what = IT_XWIDGET;
6267 it->method = GET_FROM_XWIDGET;
6268 it->position = start_pos;
6269 it->object = NILP (object) ? it->w->contents : object;
6270 *position = start_pos;
6271 it->xwidget = lookup_xwidget (value);
6272 }
6273 #ifdef HAVE_WINDOW_SYSTEM
6274 else
6275 {
6276 specpdl_ref count = SPECPDL_INDEX ();
6277
6278 it->what = IT_IMAGE;
6279
6280
6281
6282 specbind (Qinhibit_quit, Qt);
6283 it->image_id = lookup_image (it->f, value, it->face_id);
6284 unbind_to (count, Qnil);
6285 it->position = start_pos;
6286 it->object = NILP (object) ? it->w->contents : object;
6287 it->method = GET_FROM_IMAGE;
6288
6289
6290
6291
6292 *position = start_pos;
6293 }
6294 #endif
6295
6296 return retval;
6297 }
6298
6299
6300
6301 *position = start_pos;
6302 return 0;
6303 }
6304
6305
6306
6307
6308
6309
6310 bool
6311 display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
6312 ptrdiff_t charpos, ptrdiff_t bytepos)
6313 {
6314 bool frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
6315 struct text_pos position;
6316
6317 SET_TEXT_POS (position, charpos, bytepos);
6318 return (handle_display_spec (NULL, prop, Qnil, overlay,
6319 &position, charpos, frame_window_p)
6320 != 0);
6321 }
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332 static bool
6333 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
6334 {
6335 if (EQ (string, prop))
6336 return true;
6337
6338
6339 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
6340 {
6341 prop = XCDR (prop);
6342 if (!CONSP (prop))
6343 return false;
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354 prop = XCDR (prop);
6355 }
6356
6357 if (CONSP (prop))
6358
6359 if (EQ (XCAR (prop), Qmargin))
6360 {
6361 prop = XCDR (prop);
6362 if (!CONSP (prop))
6363 return false;
6364
6365 prop = XCDR (prop);
6366 if (!CONSP (prop))
6367 return false;
6368 }
6369
6370 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
6371 }
6372
6373
6374
6375
6376 static bool
6377 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
6378 {
6379 if (CONSP (prop)
6380 && !EQ (XCAR (prop), Qwhen)
6381 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
6382 {
6383
6384 while (CONSP (prop))
6385 {
6386 if (single_display_spec_string_p (XCAR (prop), string))
6387 return true;
6388 prop = XCDR (prop);
6389 }
6390 }
6391 else if (VECTORP (prop))
6392 {
6393
6394 ptrdiff_t i;
6395 for (i = 0; i < ASIZE (prop); ++i)
6396 if (single_display_spec_string_p (AREF (prop, i), string))
6397 return true;
6398 }
6399 else
6400 return single_display_spec_string_p (prop, string);
6401
6402 return false;
6403 }
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415 static ptrdiff_t
6416 string_buffer_position_lim (Lisp_Object string,
6417 ptrdiff_t from, ptrdiff_t to, bool back_p)
6418 {
6419 Lisp_Object limit, prop, pos;
6420 bool found = false;
6421
6422 pos = make_fixnum (max (from, BEGV));
6423
6424 if (!back_p)
6425 {
6426 limit = make_fixnum (min (to, ZV));
6427 while (!found && !EQ (pos, limit))
6428 {
6429 prop = Fget_char_property (pos, Qdisplay, Qnil);
6430 if (!NILP (prop) && display_prop_string_p (prop, string))
6431 found = true;
6432 else
6433 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
6434 limit);
6435 }
6436 }
6437 else
6438 {
6439 limit = make_fixnum (max (to, BEGV));
6440 while (!found && !EQ (pos, limit))
6441 {
6442 prop = Fget_char_property (pos, Qdisplay, Qnil);
6443 if (!NILP (prop) && display_prop_string_p (prop, string))
6444 found = true;
6445 else
6446 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
6447 limit);
6448 }
6449 }
6450
6451 return found ? XFIXNUM (pos) : 0;
6452 }
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463 static ptrdiff_t
6464 string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6465 {
6466 const int MAX_DISTANCE = 1000;
6467 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6468 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6469 forward_limit, false);
6470
6471 if (!found)
6472 {
6473 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6474 found = string_buffer_position_lim (string, around_charpos,
6475 backward_limit, true);
6476 }
6477 return found;
6478 }
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489 static enum prop_handled
6490 handle_composition_prop (struct it *it)
6491 {
6492 Lisp_Object prop, string;
6493 ptrdiff_t pos, pos_byte, start, end;
6494
6495 if (STRINGP (it->string))
6496 {
6497 unsigned char *s;
6498
6499 pos = IT_STRING_CHARPOS (*it);
6500 pos_byte = IT_STRING_BYTEPOS (*it);
6501 string = it->string;
6502 s = SDATA (string) + pos_byte;
6503 if (STRING_MULTIBYTE (string))
6504 it->c = STRING_CHAR (s);
6505 else
6506 it->c = *s;
6507 }
6508 else
6509 {
6510 pos = IT_CHARPOS (*it);
6511 pos_byte = IT_BYTEPOS (*it);
6512 string = Qnil;
6513 it->c = FETCH_CHAR (pos_byte);
6514 }
6515
6516
6517
6518
6519 if (find_composition (pos, -1, &start, &end, &prop, string)
6520 && composition_valid_p (start, end, prop)
6521 && (STRINGP (it->string) || (PT <= start || PT >= end)))
6522 {
6523 if (start < pos)
6524
6525
6526
6527 return HANDLED_NORMALLY;
6528 if (start != pos)
6529 {
6530 if (STRINGP (it->string))
6531 pos_byte = string_char_to_byte (it->string, start);
6532 else
6533 pos_byte = CHAR_TO_BYTE (start);
6534 }
6535 it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
6536 prop, string);
6537
6538 if (it->cmp_it.id >= 0)
6539 {
6540 it->cmp_it.ch = -1;
6541 it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
6542 it->cmp_it.nglyphs = -1;
6543 }
6544 }
6545
6546 return HANDLED_NORMALLY;
6547 }
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558 struct overlay_entry
6559 {
6560 Lisp_Object overlay;
6561 Lisp_Object string;
6562 EMACS_INT priority;
6563 bool after_string_p;
6564 };
6565
6566
6567
6568
6569
6570 static enum prop_handled
6571 handle_overlay_change (struct it *it)
6572 {
6573 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
6574 return HANDLED_RECOMPUTE_PROPS;
6575 else
6576 return HANDLED_NORMALLY;
6577 }
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587 static void
6588 next_overlay_string (struct it *it)
6589 {
6590 ++it->current.overlay_string_index;
6591 if (it->current.overlay_string_index == it->n_overlay_strings)
6592 {
6593
6594
6595
6596
6597 it->ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
6598 pop_it (it);
6599 eassert (it->sp > 0
6600 || (NILP (it->string)
6601 && it->method == GET_FROM_BUFFER
6602 && it->stop_charpos >= BEGV
6603 && it->stop_charpos <= it->end_charpos));
6604 it->current.overlay_string_index = -1;
6605 it->n_overlay_strings = 0;
6606
6607
6608
6609
6610 if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
6611 pop_it (it);
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621 if (it->overlay_strings_charpos == IT_CHARPOS (*it))
6622 it->ignore_overlay_strings_at_pos_p = true;
6623
6624
6625
6626
6627 if (NILP (it->string)
6628 && IT_CHARPOS (*it) >= it->end_charpos
6629 && it->overlay_strings_charpos >= it->end_charpos)
6630 it->overlay_strings_at_end_processed_p = true;
6631
6632
6633
6634
6635
6636
6637
6638 it->overlay_strings_charpos = -1;
6639 }
6640 else
6641 {
6642
6643
6644
6645
6646
6647
6648 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
6649
6650 if (it->current.overlay_string_index && i == 0)
6651 load_overlay_strings (it, it->overlay_strings_charpos);
6652
6653
6654
6655 it->string = it->overlay_strings[i];
6656 it->multibyte_p = STRING_MULTIBYTE (it->string);
6657 SET_TEXT_POS (it->current.string_pos, 0, 0);
6658 it->method = GET_FROM_STRING;
6659 it->stop_charpos = 0;
6660 it->end_charpos = SCHARS (it->string);
6661 if (it->cmp_it.stop_pos >= 0)
6662 it->cmp_it.stop_pos = 0;
6663 it->prev_stop = 0;
6664 it->base_level_stop = 0;
6665
6666
6667 if (it->bidi_p)
6668 {
6669 it->bidi_it.string.lstring = it->string;
6670 it->bidi_it.string.s = NULL;
6671 it->bidi_it.string.schars = SCHARS (it->string);
6672 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
6673 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6674 it->bidi_it.string.unibyte = !it->multibyte_p;
6675 it->bidi_it.w = it->w;
6676 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6677 }
6678 }
6679
6680 CHECK_IT (it);
6681 }
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700 static int
6701 compare_overlay_entries (const void *e1, const void *e2)
6702 {
6703 struct overlay_entry const *entry1 = e1;
6704 struct overlay_entry const *entry2 = e2;
6705 int result;
6706
6707 if (entry1->after_string_p != entry2->after_string_p)
6708 {
6709
6710
6711 if (EQ (entry1->overlay, entry2->overlay))
6712 result = entry1->after_string_p ? 1 : -1;
6713 else
6714 result = entry1->after_string_p ? -1 : 1;
6715 }
6716 else if (entry1->priority != entry2->priority)
6717 {
6718 if (entry1->after_string_p)
6719
6720 result = entry2->priority < entry1->priority ? -1 : 1;
6721 else
6722
6723 result = entry1->priority < entry2->priority ? -1 : 1;
6724 }
6725 else
6726 result = 0;
6727
6728 return result;
6729 }
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756 static void
6757 load_overlay_strings (struct it *it, ptrdiff_t charpos)
6758 {
6759 ptrdiff_t n = 0;
6760 struct overlay_entry entriesbuf[20];
6761 ptrdiff_t size = ARRAYELTS (entriesbuf);
6762 struct overlay_entry *entries = entriesbuf;
6763 struct itree_node *node;
6764
6765 USE_SAFE_ALLOCA;
6766
6767 if (charpos <= 0)
6768 charpos = IT_CHARPOS (*it);
6769
6770
6771
6772
6773
6774 #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
6775 do \
6776 { \
6777 Lisp_Object priority; \
6778 \
6779 if (n == size) \
6780 { \
6781 struct overlay_entry *old = entries; \
6782 SAFE_NALLOCA (entries, 2, size); \
6783 memcpy (entries, old, size * sizeof *entries); \
6784 size *= 2; \
6785 } \
6786 \
6787 entries[n].string = (STRING); \
6788 entries[n].overlay = (OVERLAY); \
6789 priority = Foverlay_get ((OVERLAY), Qpriority); \
6790 entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
6791 entries[n].after_string_p = (AFTER_P); \
6792 ++n; \
6793 } \
6794 while (false)
6795
6796
6797
6798 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6799 {
6800 Lisp_Object overlay = node->data;
6801 eassert (OVERLAYP (overlay));
6802 ptrdiff_t start = node->begin;
6803 ptrdiff_t end = node->end;
6804
6805
6806
6807 if (end != charpos && start != charpos)
6808 continue;
6809
6810
6811 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6812 if (WINDOWP (window) && XWINDOW (window) != it->w)
6813 continue;
6814
6815
6816
6817
6818 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6819 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6820
6821
6822 Lisp_Object str;
6823 if ((start == charpos || (end == charpos && invis != 0))
6824 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6825 && SCHARS (str))
6826 RECORD_OVERLAY_STRING (overlay, str, false);
6827
6828
6829 if ((end == charpos || (start == charpos && invis != 0))
6830 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6831 && SCHARS (str))
6832 RECORD_OVERLAY_STRING (overlay, str, true);
6833 }
6834
6835 #undef RECORD_OVERLAY_STRING
6836
6837
6838 if (n > 1)
6839 qsort (entries, n, sizeof *entries, compare_overlay_entries);
6840
6841
6842 it->n_overlay_strings = n;
6843 it->overlay_strings_charpos = charpos;
6844
6845
6846
6847
6848 ptrdiff_t j = it->current.overlay_string_index;
6849 for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++)
6850 {
6851 it->overlay_strings[i] = entries[j].string;
6852 it->string_overlays[i] = entries[j].overlay;
6853 }
6854
6855 CHECK_IT (it);
6856 SAFE_FREE ();
6857 }
6858
6859
6860
6861
6862
6863
6864 static bool
6865 get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, bool compute_stop_p)
6866 {
6867
6868
6869
6870
6871
6872
6873
6874 it->current.overlay_string_index = 0;
6875 load_overlay_strings (it, charpos);
6876
6877
6878
6879
6880 if (it->n_overlay_strings)
6881 {
6882
6883
6884
6885 if (compute_stop_p)
6886 compute_stop_pos (it);
6887 eassert (it->face_id >= 0);
6888
6889
6890
6891 eassert (!compute_stop_p || it->sp == 0);
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901 if (!(!it->bidi_p
6902 && STRINGP (it->string) && !SCHARS (it->string)))
6903 push_it (it, NULL);
6904
6905
6906
6907 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6908 it->string = it->overlay_strings[0];
6909 it->from_overlay = Qnil;
6910 it->stop_charpos = 0;
6911 eassert (STRINGP (it->string));
6912 it->end_charpos = SCHARS (it->string);
6913 it->prev_stop = 0;
6914 it->base_level_stop = 0;
6915 it->multibyte_p = STRING_MULTIBYTE (it->string);
6916 it->method = GET_FROM_STRING;
6917 it->from_disp_prop_p = 0;
6918 it->cmp_it.id = -1;
6919
6920
6921
6922 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6923 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6924 else
6925 it->paragraph_embedding = L2R;
6926
6927
6928 if (it->bidi_p)
6929 {
6930 ptrdiff_t pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
6931
6932 it->bidi_it.string.lstring = it->string;
6933 it->bidi_it.string.s = NULL;
6934 it->bidi_it.string.schars = SCHARS (it->string);
6935 it->bidi_it.string.bufpos = pos;
6936 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6937 it->bidi_it.string.unibyte = !it->multibyte_p;
6938 it->bidi_it.w = it->w;
6939 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6940 }
6941 return true;
6942 }
6943
6944 it->current.overlay_string_index = -1;
6945 return false;
6946 }
6947
6948 static bool
6949 get_overlay_strings (struct it *it, ptrdiff_t charpos)
6950 {
6951 it->string = Qnil;
6952 it->method = GET_FROM_BUFFER;
6953
6954 get_overlay_strings_1 (it, charpos, true);
6955
6956 CHECK_IT (it);
6957
6958
6959 return STRINGP (it->string);
6960 }
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974 static void
6975 push_it (struct it *it, struct text_pos *position)
6976 {
6977 struct iterator_stack_entry *p;
6978
6979 eassert (it->sp < IT_STACK_SIZE);
6980 p = it->stack + it->sp;
6981
6982 p->stop_charpos = it->stop_charpos;
6983 p->prev_stop = it->prev_stop;
6984 p->base_level_stop = it->base_level_stop;
6985 p->cmp_it = it->cmp_it;
6986 eassert (it->face_id >= 0);
6987 p->face_id = it->face_id;
6988 p->string = it->string;
6989 p->method = it->method;
6990 p->from_overlay = it->from_overlay;
6991 switch (p->method)
6992 {
6993 case GET_FROM_IMAGE:
6994 p->u.image.object = it->object;
6995 p->u.image.image_id = it->image_id;
6996 p->u.image.slice = it->slice;
6997 break;
6998 case GET_FROM_STRETCH:
6999 p->u.stretch.object = it->object;
7000 break;
7001 case GET_FROM_XWIDGET:
7002 p->u.xwidget.object = it->object;
7003 break;
7004 case GET_FROM_BUFFER:
7005 case GET_FROM_DISPLAY_VECTOR:
7006 case GET_FROM_STRING:
7007 case GET_FROM_C_STRING:
7008 break;
7009 default:
7010 emacs_abort ();
7011 }
7012 p->position = position ? *position : it->position;
7013 p->current = it->current;
7014 p->end_charpos = it->end_charpos;
7015 p->string_nchars = it->string_nchars;
7016 p->area = it->area;
7017 p->multibyte_p = it->multibyte_p;
7018 p->avoid_cursor_p = it->avoid_cursor_p;
7019 p->space_width = it->space_width;
7020 p->font_height = it->font_height;
7021 p->voffset = it->voffset;
7022 p->string_from_display_prop_p = it->string_from_display_prop_p;
7023 p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
7024 p->display_ellipsis_p = false;
7025 p->line_wrap = it->line_wrap;
7026 p->bidi_p = it->bidi_p;
7027 p->paragraph_embedding = it->paragraph_embedding;
7028 p->from_disp_prop_p = it->from_disp_prop_p;
7029 ++it->sp;
7030
7031
7032 if (it->bidi_p)
7033 bidi_push_it (&it->bidi_it);
7034 }
7035
7036 static void
7037 iterate_out_of_display_property (struct it *it)
7038 {
7039 bool buffer_p = !STRINGP (it->string);
7040 ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
7041 ptrdiff_t bob = (buffer_p ? BEGV : 0);
7042
7043 eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
7044
7045
7046
7047
7048 if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
7049 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
7050
7051 while (it->bidi_it.charpos >= bob
7052 && it->prev_stop <= it->bidi_it.charpos
7053 && it->bidi_it.charpos < CHARPOS (it->position)
7054 && it->bidi_it.charpos < eob)
7055 bidi_move_to_visually_next (&it->bidi_it);
7056
7057
7058 if (it->bidi_it.charpos > CHARPOS (it->position))
7059 it->prev_stop = CHARPOS (it->position);
7060
7061
7062 if (it->bidi_it.charpos != CHARPOS (it->position))
7063 SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
7064 if (buffer_p)
7065 it->current.pos = it->position;
7066 else
7067 it->current.string_pos = it->position;
7068 }
7069
7070
7071
7072
7073
7074 static void
7075 restore_face_box_flags (struct it *it, int prev_face_id)
7076 {
7077 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
7078
7079 if (face)
7080 {
7081 struct face *prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
7082
7083 if (!(it->start_of_box_run_p && prev_face && prev_face->box))
7084 it->start_of_box_run_p = (face->box != FACE_NO_BOX
7085 && (prev_face == NULL
7086 || prev_face->box == FACE_NO_BOX));
7087 it->face_box_p = face->box != FACE_NO_BOX;
7088 }
7089 }
7090
7091
7092
7093
7094
7095
7096
7097 static void
7098 pop_it (struct it *it)
7099 {
7100 struct iterator_stack_entry *p;
7101 bool from_display_prop = it->from_disp_prop_p;
7102 ptrdiff_t prev_pos = IT_CHARPOS (*it);
7103 int prev_face_id = it->face_id;
7104
7105 eassert (it->sp > 0);
7106 --it->sp;
7107 p = it->stack + it->sp;
7108 it->stop_charpos = p->stop_charpos;
7109 it->prev_stop = p->prev_stop;
7110 it->base_level_stop = p->base_level_stop;
7111 it->cmp_it = p->cmp_it;
7112 it->face_id = p->face_id;
7113 it->current = p->current;
7114 it->position = p->position;
7115 it->string = p->string;
7116 it->from_overlay = p->from_overlay;
7117 if (NILP (it->string))
7118 SET_TEXT_POS (it->current.string_pos, -1, -1);
7119 it->method = p->method;
7120 switch (it->method)
7121 {
7122 case GET_FROM_IMAGE:
7123 it->image_id = p->u.image.image_id;
7124 it->object = p->u.image.object;
7125 it->slice = p->u.image.slice;
7126 break;
7127 case GET_FROM_XWIDGET:
7128 it->object = p->u.xwidget.object;
7129 break;
7130 case GET_FROM_STRETCH:
7131 it->object = p->u.stretch.object;
7132 break;
7133 case GET_FROM_BUFFER:
7134 {
7135 restore_face_box_flags (it, prev_face_id);
7136 it->object = it->w->contents;
7137 }
7138 break;
7139 case GET_FROM_STRING:
7140 {
7141 restore_face_box_flags (it, prev_face_id);
7142 it->object = it->string;
7143 }
7144 break;
7145 case GET_FROM_DISPLAY_VECTOR:
7146 if (it->s)
7147 it->method = GET_FROM_C_STRING;
7148 else if (STRINGP (it->string))
7149 it->method = GET_FROM_STRING;
7150 else
7151 {
7152 it->method = GET_FROM_BUFFER;
7153 it->object = it->w->contents;
7154 }
7155 break;
7156 case GET_FROM_C_STRING:
7157 break;
7158 default:
7159 emacs_abort ();
7160 }
7161 it->end_charpos = p->end_charpos;
7162 it->string_nchars = p->string_nchars;
7163 it->area = p->area;
7164 it->multibyte_p = p->multibyte_p;
7165 it->avoid_cursor_p = p->avoid_cursor_p;
7166 it->space_width = p->space_width;
7167 it->font_height = p->font_height;
7168 it->voffset = p->voffset;
7169 it->string_from_display_prop_p = p->string_from_display_prop_p;
7170 it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
7171 it->line_wrap = p->line_wrap;
7172 it->bidi_p = p->bidi_p;
7173 it->paragraph_embedding = p->paragraph_embedding;
7174 it->from_disp_prop_p = p->from_disp_prop_p;
7175 if (it->bidi_p)
7176 {
7177 bidi_pop_it (&it->bidi_it);
7178
7179
7180
7181
7182
7183
7184
7185 if (from_display_prop
7186 && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
7187 iterate_out_of_display_property (it);
7188
7189 eassert ((BUFFERP (it->object)
7190 && IT_CHARPOS (*it) == it->bidi_it.charpos
7191 && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
7192 || (STRINGP (it->object)
7193 && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
7194 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
7195 || (CONSP (it->object) && it->method == GET_FROM_STRETCH)
7196
7197
7198
7199
7200
7201
7202 || it->sp > 0);
7203 }
7204
7205
7206
7207 if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
7208 it->ignore_overlay_strings_at_pos_p = false;
7209 }
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219 static void
7220 back_to_previous_line_start (struct it *it)
7221 {
7222 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
7223
7224 dec_both (&cp, &bp);
7225 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7226 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
7227 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
7228 }
7229
7230
7231
7232
7233
7234 static bool
7235 strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7236 {
7237 struct itree_node *node;
7238
7239 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7240 {
7241 Lisp_Object overlay = node->data;
7242 eassert (OVERLAYP (overlay));
7243
7244
7245 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7246 if (WINDOWP (window) && XWINDOW (window) != w)
7247 continue;
7248
7249 ptrdiff_t ostart = node->begin;
7250 ptrdiff_t oend = node->end;
7251
7252
7253 if (!((startpos < oend && ostart < endpos)
7254 || (ostart == oend
7255 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7256 continue;
7257
7258 Lisp_Object str;
7259 str = Foverlay_get (overlay, Qbefore_string);
7260 if (STRINGP (str) && SCHARS (str)
7261 && memchr (SDATA (str), '\n', SBYTES (str)))
7262 return true;
7263 str = Foverlay_get (overlay, Qafter_string);
7264 if (STRINGP (str) && SCHARS (str)
7265 && memchr (SDATA (str), '\n', SBYTES (str)))
7266 return true;
7267 }
7268
7269
7270 Lisp_Object cpos = make_fixnum (startpos);
7271 Lisp_Object limpos = make_fixnum (endpos);
7272
7273 while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos),
7274 !(NILP (cpos) || XFIXNAT (cpos) >= endpos)))
7275 {
7276 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
7277 Lisp_Object string = string_from_display_spec (spec);
7278 if (STRINGP (string)
7279 && memchr (SDATA (string), '\n', SBYTES (string)))
7280 return true;
7281 }
7282
7283 return false;
7284 }
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308 static bool
7309 forward_to_next_line_start (struct it *it, bool *skipped_p,
7310 struct bidi_it *bidi_it_prev)
7311 {
7312 ptrdiff_t old_selective;
7313 bool newline_found_p = false;
7314 int n;
7315 const int MAX_NEWLINE_DISTANCE = 500;
7316
7317
7318
7319 if (it->what == IT_CHARACTER
7320 && it->c == '\n'
7321 && CHARPOS (it->position) == IT_CHARPOS (*it))
7322 {
7323 if (it->bidi_p && bidi_it_prev)
7324 *bidi_it_prev = it->bidi_it;
7325 set_iterator_to_next (it, false);
7326 it->c = 0;
7327 return true;
7328 }
7329
7330
7331
7332
7333
7334 old_selective = it->selective;
7335 it->selective = 0;
7336
7337
7338
7339
7340 for (n = 0;
7341 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
7342 n += !STRINGP (it->string))
7343 {
7344 if (!get_next_display_element (it))
7345 return false;
7346 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
7347 if (newline_found_p && it->bidi_p && bidi_it_prev)
7348 *bidi_it_prev = it->bidi_it;
7349 set_iterator_to_next (it, false);
7350 }
7351
7352
7353
7354 if (!newline_found_p)
7355 {
7356 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
7357 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
7358 1, &bytepos);
7359 eassert (!STRINGP (it->string));
7360
7361
7362
7363
7364 bool no_strings_with_newlines = it->stop_charpos >= limit;
7365
7366 if (!no_strings_with_newlines)
7367 {
7368 if (!(current_buffer->long_line_optimizations_p
7369 && it->line_wrap == TRUNCATE))
7370 {
7371
7372
7373 Lisp_Object pos =
7374 Fnext_single_property_change (make_fixnum (start),
7375 Qdisplay, Qnil,
7376 make_fixnum (limit));
7377 no_strings_with_newlines =
7378 (NILP (pos) || XFIXNAT (pos) == limit)
7379 && next_overlay_change (start) == ZV;
7380 }
7381 else
7382 {
7383
7384
7385
7386
7387 no_strings_with_newlines =
7388 !strings_with_newlines (start, limit, it->w);
7389 }
7390 }
7391
7392
7393
7394
7395 if (no_strings_with_newlines)
7396 {
7397 if (!it->bidi_p || !bidi_it_prev)
7398 {
7399
7400 IT_CHARPOS (*it) = limit;
7401 IT_BYTEPOS (*it) = bytepos;
7402 }
7403 else
7404 {
7405
7406
7407
7408 struct bidi_it bprev;
7409
7410
7411
7412
7413 if (it->bidi_it.disp_pos < limit)
7414 {
7415 it->bidi_it.disp_pos = limit;
7416 it->bidi_it.disp_prop = 0;
7417 }
7418 do {
7419 bprev = it->bidi_it;
7420 bidi_move_to_visually_next (&it->bidi_it);
7421 } while (it->bidi_it.charpos != limit);
7422 IT_CHARPOS (*it) = limit;
7423 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7424 if (bidi_it_prev)
7425 *bidi_it_prev = bprev;
7426 }
7427 *skipped_p = newline_found_p = true;
7428 }
7429 else
7430 {
7431
7432 while (!newline_found_p)
7433 {
7434 if (!get_next_display_element (it))
7435 break;
7436 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
7437 if (newline_found_p && it->bidi_p && bidi_it_prev)
7438 *bidi_it_prev = it->bidi_it;
7439 set_iterator_to_next (it, false);
7440 }
7441 }
7442 }
7443
7444 it->selective = old_selective;
7445 return newline_found_p;
7446 }
7447
7448
7449
7450
7451
7452
7453
7454 static void
7455 back_to_previous_visible_line_start (struct it *it)
7456 {
7457 while (IT_CHARPOS (*it) > BEGV)
7458 {
7459 back_to_previous_line_start (it);
7460
7461 if (IT_CHARPOS (*it) <= BEGV)
7462 break;
7463
7464
7465
7466 if (it->selective > 0
7467 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7468 it->selective))
7469 continue;
7470
7471
7472 {
7473 Lisp_Object prop;
7474 prop = Fget_char_property (make_fixnum (IT_CHARPOS (*it) - 1),
7475 Qinvisible, it->window);
7476 if (TEXT_PROP_MEANS_INVISIBLE (prop) != 0)
7477 continue;
7478 }
7479
7480 if (IT_CHARPOS (*it) <= BEGV)
7481 break;
7482
7483 {
7484 struct it it2;
7485 void *it2data = NULL;
7486 ptrdiff_t pos;
7487 ptrdiff_t beg, end;
7488 Lisp_Object val, overlay;
7489
7490 SAVE_IT (it2, *it, it2data);
7491
7492
7493 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
7494 && beg < IT_CHARPOS (*it))
7495 goto replaced;
7496
7497
7498
7499 pos = --IT_CHARPOS (it2);
7500 --IT_BYTEPOS (it2);
7501 it2.sp = 0;
7502 bidi_unshelve_cache (NULL, false);
7503 it2.string_from_display_prop_p = false;
7504 it2.from_disp_prop_p = false;
7505 if (handle_display_prop (&it2) == HANDLED_RETURN
7506 && !NILP (val = get_char_property_and_overlay
7507 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7508 && (OVERLAYP (overlay)
7509 ? (beg = OVERLAY_START (overlay))
7510 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7511 {
7512 RESTORE_IT (it, it, it2data);
7513 goto replaced;
7514 }
7515
7516
7517 RESTORE_IT (it, it, it2data);
7518 break;
7519
7520 replaced:
7521 if (beg < BEGV)
7522 beg = BEGV;
7523 IT_CHARPOS (*it) = beg;
7524 IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
7525 }
7526 }
7527
7528 it->continuation_lines_width = 0;
7529
7530 eassert (IT_CHARPOS (*it) >= BEGV);
7531 eassert (it->medium_narrowing_begv > 0
7532 || IT_CHARPOS (*it) == BEGV
7533 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7534 CHECK_IT (it);
7535 }
7536
7537
7538
7539
7540
7541
7542
7543 void
7544 reseat_at_previous_visible_line_start (struct it *it)
7545 {
7546 back_to_previous_visible_line_start (it);
7547 reseat (it, it->current.pos, true);
7548 CHECK_IT (it);
7549 }
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559 static void
7560 reseat_at_next_visible_line_start (struct it *it, bool on_newline_p)
7561 {
7562 bool skipped_p = false;
7563 struct bidi_it bidi_it_prev;
7564 bool newline_found_p
7565 = forward_to_next_line_start (it, &skipped_p,
7566 on_newline_p ? &bidi_it_prev : NULL);
7567
7568
7569
7570 if (it->selective > 0)
7571 while (IT_CHARPOS (*it) < ZV
7572 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7573 it->selective))
7574 {
7575 eassert (IT_BYTEPOS (*it) == BEGV
7576 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7577 newline_found_p =
7578 forward_to_next_line_start (it, &skipped_p,
7579 on_newline_p ? &bidi_it_prev : NULL);
7580 }
7581
7582
7583 if (on_newline_p && newline_found_p)
7584 {
7585 if (STRINGP (it->string))
7586 {
7587 if (IT_STRING_CHARPOS (*it) > 0)
7588 {
7589 if (!it->bidi_p)
7590 {
7591 --IT_STRING_CHARPOS (*it);
7592 --IT_STRING_BYTEPOS (*it);
7593 }
7594 else
7595 {
7596
7597
7598
7599 it->bidi_it = bidi_it_prev;
7600 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
7601 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
7602 }
7603 }
7604 }
7605 else if (IT_CHARPOS (*it) > BEGV)
7606 {
7607 if (!it->bidi_p)
7608 {
7609 --IT_CHARPOS (*it);
7610 --IT_BYTEPOS (*it);
7611 }
7612 else
7613 {
7614
7615
7616 it->bidi_it = bidi_it_prev;
7617 IT_CHARPOS (*it) = it->bidi_it.charpos;
7618 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7619 }
7620 reseat (it, it->current.pos, false);
7621 }
7622 }
7623 else if (skipped_p)
7624 reseat (it, it->current.pos, false);
7625
7626 CHECK_IT (it);
7627 }
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640 static void
7641 reseat (struct it *it, struct text_pos pos, bool force_p)
7642 {
7643 ptrdiff_t original_pos = IT_CHARPOS (*it);
7644
7645 reseat_1 (it, pos, false);
7646
7647 if (current_buffer->long_line_optimizations_p)
7648 {
7649 if (!it->medium_narrowing_begv)
7650 {
7651 it->medium_narrowing_begv
7652 = get_medium_narrowing_begv (it->w, window_point (it->w));
7653 it->medium_narrowing_zv
7654 = get_medium_narrowing_zv (it->w, window_point (it->w));
7655 it->large_narrowing_begv
7656 = get_large_narrowing_begv (window_point (it->w));
7657 it->large_narrowing_zv
7658 = get_large_narrowing_zv (window_point (it->w));
7659 }
7660 else if ((pos.charpos < it->medium_narrowing_begv
7661 || pos.charpos > it->medium_narrowing_zv)
7662 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7663 {
7664 it->medium_narrowing_begv
7665 = get_medium_narrowing_begv (it->w, pos.charpos);
7666 it->medium_narrowing_zv
7667 = get_medium_narrowing_zv (it->w, pos.charpos);
7668 it->large_narrowing_begv
7669 = get_large_narrowing_begv (window_point (it->w));
7670 it->large_narrowing_zv
7671 = get_large_narrowing_zv (window_point (it->w));
7672 }
7673 }
7674
7675
7676
7677 if (force_p
7678 || CHARPOS (pos) > it->stop_charpos
7679 || CHARPOS (pos) < original_pos)
7680 {
7681 if (it->bidi_p)
7682 {
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693 if (CHARPOS (pos) != it->prev_stop)
7694 it->prev_stop = CHARPOS (pos);
7695 if (CHARPOS (pos) < it->base_level_stop)
7696 it->base_level_stop = 0;
7697 handle_stop (it);
7698 }
7699 else
7700 {
7701 handle_stop (it);
7702 it->prev_stop = it->base_level_stop = 0;
7703 }
7704
7705 }
7706
7707 CHECK_IT (it);
7708 }
7709
7710
7711
7712
7713
7714 static void
7715 reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7716 {
7717
7718 eassert (it->s == NULL);
7719
7720
7721 eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
7722
7723 it->current.pos = it->position = pos;
7724 it->end_charpos = ZV;
7725 it->dpvec = NULL;
7726 it->current.dpvec_index = -1;
7727 it->current.overlay_string_index = -1;
7728 IT_STRING_CHARPOS (*it) = -1;
7729 IT_STRING_BYTEPOS (*it) = -1;
7730 it->string = Qnil;
7731 it->method = GET_FROM_BUFFER;
7732 it->object = it->w->contents;
7733 it->area = TEXT_AREA;
7734 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
7735 it->sp = 0;
7736 it->string_from_display_prop_p = false;
7737 it->string_from_prefix_prop_p = false;
7738
7739 it->from_disp_prop_p = false;
7740 it->face_before_selective_p = false;
7741 if (it->bidi_p)
7742 {
7743 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7744 &it->bidi_it);
7745 bidi_unshelve_cache (NULL, false);
7746 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7747 it->bidi_it.string.s = NULL;
7748 it->bidi_it.string.lstring = Qnil;
7749 it->bidi_it.string.bufpos = 0;
7750 it->bidi_it.string.from_disp_str = false;
7751 it->bidi_it.string.unibyte = false;
7752 it->bidi_it.w = it->w;
7753 }
7754
7755 if (set_stop_p)
7756 {
7757 it->stop_charpos = CHARPOS (pos);
7758 it->base_level_stop = CHARPOS (pos);
7759 }
7760
7761 it->cmp_it.id = -1;
7762 it->min_width_property = Qnil;
7763 }
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784 static void
7785 reseat_to_string (struct it *it, const char *s, Lisp_Object string,
7786 ptrdiff_t charpos, ptrdiff_t precision, int field_width,
7787 int multibyte)
7788 {
7789
7790 it->stop_charpos = -1;
7791
7792
7793 memset (&it->current, 0, sizeof it->current);
7794 it->current.overlay_string_index = -1;
7795 it->current.dpvec_index = -1;
7796 eassert (charpos >= 0);
7797
7798
7799
7800 if (multibyte >= 0)
7801 it->multibyte_p = multibyte > 0;
7802
7803
7804
7805
7806
7807 it->bidi_p =
7808 !redisplay__inhibit_bidi
7809 && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
7810
7811 if (s == NULL)
7812 {
7813 eassert (STRINGP (string));
7814 it->string = string;
7815 it->s = NULL;
7816 it->end_charpos = it->string_nchars = SCHARS (string);
7817 it->method = GET_FROM_STRING;
7818 it->current.string_pos = string_pos (charpos, string);
7819
7820 if (it->bidi_p)
7821 {
7822 it->bidi_it.string.lstring = string;
7823 it->bidi_it.string.s = NULL;
7824 it->bidi_it.string.schars = it->end_charpos;
7825 it->bidi_it.string.bufpos = 0;
7826 it->bidi_it.string.from_disp_str = false;
7827 it->bidi_it.string.unibyte = !it->multibyte_p;
7828 it->bidi_it.w = it->w;
7829 bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
7830 FRAME_WINDOW_P (it->f), &it->bidi_it);
7831 }
7832 }
7833 else
7834 {
7835 it->s = (const unsigned char *) s;
7836 it->string = Qnil;
7837
7838
7839
7840 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
7841 if (it->multibyte_p)
7842 {
7843 it->current.pos = c_string_pos (charpos, s, true);
7844 it->end_charpos = it->string_nchars = number_of_chars (s, true);
7845 }
7846 else
7847 {
7848 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
7849 it->end_charpos = it->string_nchars = strlen (s);
7850 }
7851
7852 if (it->bidi_p)
7853 {
7854 it->bidi_it.string.lstring = Qnil;
7855 it->bidi_it.string.s = (const unsigned char *) s;
7856 it->bidi_it.string.schars = it->end_charpos;
7857 it->bidi_it.string.bufpos = 0;
7858 it->bidi_it.string.from_disp_str = false;
7859 it->bidi_it.string.unibyte = !it->multibyte_p;
7860 it->bidi_it.w = it->w;
7861 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7862 &it->bidi_it);
7863 }
7864 it->method = GET_FROM_C_STRING;
7865 }
7866
7867
7868
7869 if (precision > 0 && it->end_charpos - charpos > precision)
7870 {
7871 it->end_charpos = it->string_nchars = charpos + precision;
7872 if (it->bidi_p)
7873 it->bidi_it.string.schars = it->end_charpos;
7874 }
7875
7876
7877
7878
7879
7880 if (field_width < 0)
7881 field_width = DISP_INFINITY;
7882
7883
7884
7885 if (field_width > it->end_charpos - charpos)
7886 it->end_charpos = charpos + field_width;
7887
7888
7889 if (DISP_TABLE_P (Vstandard_display_table))
7890 it->dp = XCHAR_TABLE (Vstandard_display_table);
7891
7892 it->stop_charpos = charpos;
7893 it->prev_stop = charpos;
7894 it->base_level_stop = 0;
7895 if (it->bidi_p)
7896 {
7897 it->bidi_it.first_elt = true;
7898 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7899 it->bidi_it.disp_pos = -1;
7900 }
7901 if (s == NULL && it->multibyte_p)
7902 {
7903 ptrdiff_t endpos = SCHARS (it->string);
7904 if (endpos > it->end_charpos)
7905 endpos = it->end_charpos;
7906 composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
7907 it->string, true);
7908 }
7909 CHECK_IT (it);
7910 }
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920 typedef bool (*next_element_function) (struct it *);
7921
7922 static next_element_function const get_next_element[NUM_IT_METHODS] =
7923 {
7924 next_element_from_buffer,
7925 next_element_from_display_vector,
7926 next_element_from_string,
7927 next_element_from_c_string,
7928 next_element_from_image,
7929 next_element_from_stretch,
7930 next_element_from_xwidget,
7931 };
7932
7933 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944 #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS) \
7945 ((IT)->cmp_it.id >= 0 \
7946 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
7947 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
7948 END_CHARPOS, (IT)->w, \
7949 (IT)->bidi_p \
7950 ? (IT)->bidi_it.resolved_level \
7951 : -1, \
7952 FACE_FROM_ID_OR_NULL ((IT)->f, \
7953 (IT)->face_id), \
7954 (IT)->string)))
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964 Lisp_Object
7965 lookup_glyphless_char_display (int c, struct it *it)
7966 {
7967 Lisp_Object glyphless_method = Qnil;
7968
7969 if (CHAR_TABLE_P (Vglyphless_char_display)
7970 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
7971 {
7972 if (c >= 0)
7973 glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
7974 else
7975 glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
7976
7977 if (CONSP (glyphless_method))
7978 glyphless_method = FRAME_WINDOW_P (it->f)
7979 ? XCAR (glyphless_method)
7980 : XCDR (glyphless_method);
7981 }
7982
7983 retry:
7984 if (NILP (glyphless_method))
7985 {
7986 if (c >= 0)
7987
7988 return Qnil;
7989
7990 glyphless_method = Qempty_box;
7991 }
7992 if (EQ (glyphless_method, Qzero_width))
7993 {
7994 if (c >= 0)
7995 return glyphless_method;
7996
7997 glyphless_method = Qempty_box;
7998 }
7999 if (EQ (glyphless_method, Qthin_space))
8000 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
8001 else if (EQ (glyphless_method, Qempty_box))
8002 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
8003 else if (EQ (glyphless_method, Qhex_code))
8004 it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
8005 else if (STRINGP (glyphless_method))
8006 it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
8007 else
8008 {
8009
8010 glyphless_method = Qnil;
8011 goto retry;
8012 }
8013 it->what = IT_GLYPHLESS;
8014 return glyphless_method;
8015 }
8016
8017
8018
8019 static struct frame *last_escape_glyph_frame = NULL;
8020 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8021 static int last_escape_glyph_merged_face_id = 0;
8022
8023 static int
8024 merge_escape_glyph_face (struct it *it)
8025 {
8026 int face_id;
8027
8028 if (it->f == last_escape_glyph_frame
8029 && it->face_id == last_escape_glyph_face_id)
8030 face_id = last_escape_glyph_merged_face_id;
8031 else
8032 {
8033
8034 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
8035 last_escape_glyph_frame = it->f;
8036 last_escape_glyph_face_id = it->face_id;
8037 last_escape_glyph_merged_face_id = face_id;
8038 }
8039 return face_id;
8040 }
8041
8042
8043
8044 static struct frame *last_glyphless_glyph_frame = NULL;
8045 static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8046 static int last_glyphless_glyph_merged_face_id = 0;
8047
8048 int
8049 merge_glyphless_glyph_face (struct it *it)
8050 {
8051 int face_id;
8052
8053 if (it->f == last_glyphless_glyph_frame
8054 && it->face_id == last_glyphless_glyph_face_id)
8055 face_id = last_glyphless_glyph_merged_face_id;
8056 else
8057 {
8058
8059 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
8060 last_glyphless_glyph_frame = it->f;
8061 last_glyphless_glyph_face_id = it->face_id;
8062 last_glyphless_glyph_merged_face_id = face_id;
8063 }
8064 return face_id;
8065 }
8066
8067
8068
8069
8070 void
8071 forget_escape_and_glyphless_faces (void)
8072 {
8073 last_escape_glyph_frame = NULL;
8074 last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8075 last_glyphless_glyph_frame = NULL;
8076 last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8077 }
8078
8079
8080
8081
8082
8083 static bool
8084 get_next_display_element (struct it *it)
8085 {
8086
8087
8088
8089
8090 bool success_p;
8091
8092 get_next:
8093 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
8094
8095 if (it->what == IT_CHARACTER)
8096 {
8097
8098
8099
8100
8101
8102 if (it->bidi_p && it->bidi_it.type == STRONG_R
8103 && !inhibit_bidi_mirroring)
8104 it->c = bidi_mirror_char (it->c);
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114 if (success_p && it->dpvec == NULL)
8115 {
8116 Lisp_Object dv;
8117 struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
8118 bool nonascii_space_p = false;
8119 bool nonascii_hyphen_p = false;
8120 int c = it->c;
8121
8122 if (! it->multibyte_p && ! ASCII_CHAR_P (c))
8123 {
8124 eassert (SINGLE_BYTE_CHAR_P (c));
8125 if (unibyte_display_via_language_environment)
8126 {
8127 c = DECODE_CHAR (unibyte, c);
8128 if (c < 0)
8129 c = BYTE8_TO_CHAR (it->c);
8130 }
8131 else
8132 c = BYTE8_TO_CHAR (it->c);
8133 }
8134
8135 if (it->dp
8136 && (dv = DISP_CHAR_VECTOR (it->dp, c),
8137 VECTORP (dv)))
8138 {
8139 struct Lisp_Vector *v = XVECTOR (dv);
8140
8141
8142
8143
8144 if (v->header.size)
8145 {
8146 it->dpvec_char_len = it->len;
8147 it->dpvec = v->contents;
8148 it->dpend = v->contents + v->header.size;
8149 it->current.dpvec_index = 0;
8150 it->dpvec_face_id = -1;
8151 it->saved_face_id = it->face_id;
8152 it->method = GET_FROM_DISPLAY_VECTOR;
8153 it->ellipsis_p = false;
8154 }
8155 else
8156 {
8157 set_iterator_to_next (it, false);
8158 }
8159 goto get_next;
8160 }
8161
8162 if (! NILP (lookup_glyphless_char_display (c, it)))
8163 {
8164 if (it->what == IT_GLYPHLESS)
8165 goto done;
8166
8167 set_iterator_to_next (it, false);
8168 goto get_next;
8169 }
8170
8171
8172
8173 if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
8174 {
8175 if (blankp (c))
8176 nonascii_space_p = true;
8177 else if (c == SOFT_HYPHEN || c == HYPHEN
8178 || c == NON_BREAKING_HYPHEN)
8179 nonascii_hyphen_p = true;
8180 }
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193 if (((c < ' ' || c == 127)
8194 ? (it->area != TEXT_AREA
8195
8196 || (c != '\t'
8197 && it->glyph_row
8198 && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
8199 || (c != '\n' && c != '\t'))
8200 : (nonascii_space_p
8201 || nonascii_hyphen_p
8202 || CHAR_BYTE8_P (c)
8203 || ! CHAR_PRINTABLE_P (c))))
8204 {
8205
8206
8207
8208
8209
8210
8211 Lisp_Object gc;
8212 int ctl_len;
8213 int face_id;
8214 int lface_id = 0;
8215 int escape_glyph;
8216
8217
8218
8219 if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
8220 {
8221 int g;
8222
8223 g = '^';
8224
8225 if (it->dp
8226 && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8227 {
8228 g = GLYPH_CODE_CHAR (gc);
8229 lface_id = GLYPH_CODE_FACE (gc);
8230 }
8231
8232 face_id = (lface_id
8233 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8234 : merge_escape_glyph_face (it));
8235
8236 XSETINT (it->ctl_chars[0], g);
8237 XSETINT (it->ctl_chars[1], c ^ 0100);
8238 ctl_len = 2;
8239 goto display_control;
8240 }
8241
8242
8243
8244
8245 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
8246 {
8247
8248 face_id = merge_faces (it->w, Qnobreak_space, 0,
8249 it->face_id);
8250 XSETINT (it->ctl_chars[0],
8251 nobreak_char_ascii_display ? ' ' : it->c);
8252 ctl_len = 1;
8253 goto display_control;
8254 }
8255
8256
8257
8258
8259 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
8260 {
8261
8262 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
8263 it->face_id);
8264 XSETINT (it->ctl_chars[0],
8265 nobreak_char_ascii_display ? '-' : it->c);
8266 ctl_len = 1;
8267 goto display_control;
8268 }
8269
8270
8271
8272
8273 escape_glyph = '\\';
8274
8275 if (it->dp
8276 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8277 {
8278 escape_glyph = GLYPH_CODE_CHAR (gc);
8279 lface_id = GLYPH_CODE_FACE (gc);
8280 }
8281
8282 face_id = (lface_id
8283 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8284 : merge_escape_glyph_face (it));
8285
8286
8287
8288 if (nonascii_space_p || nonascii_hyphen_p)
8289 {
8290 XSETINT (it->ctl_chars[0], escape_glyph);
8291 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
8292 ctl_len = 2;
8293 goto display_control;
8294 }
8295
8296 {
8297 char str[10];
8298 int len, i;
8299
8300 if (CHAR_BYTE8_P (c))
8301
8302 c = CHAR_TO_BYTE8 (c);
8303 const char *format_string = display_raw_bytes_as_hex
8304 ? "x%02x"
8305 : "%03o";
8306 len = sprintf (str, format_string, c + 0u);
8307
8308 XSETINT (it->ctl_chars[0], escape_glyph);
8309 for (i = 0; i < len; i++)
8310 XSETINT (it->ctl_chars[i + 1], str[i]);
8311 ctl_len = len + 1;
8312 }
8313
8314 display_control:
8315
8316 it->dpvec_char_len = it->len;
8317 it->dpvec = it->ctl_chars;
8318 it->dpend = it->dpvec + ctl_len;
8319 it->current.dpvec_index = 0;
8320 it->dpvec_face_id = face_id;
8321 it->saved_face_id = it->face_id;
8322 it->method = GET_FROM_DISPLAY_VECTOR;
8323 it->ellipsis_p = false;
8324 goto get_next;
8325 }
8326 it->char_to_display = c;
8327 }
8328 else if (success_p)
8329 {
8330 it->char_to_display = it->c;
8331 }
8332 }
8333
8334 #ifdef HAVE_WINDOW_SYSTEM
8335
8336
8337 if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
8338 && it->multibyte_p
8339 && success_p
8340 && FRAME_WINDOW_P (it->f))
8341 {
8342 struct face *face = FACE_FROM_ID (it->f, it->face_id);
8343
8344 if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8345 {
8346
8347 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8348
8349 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8350 }
8351 else
8352 {
8353 ptrdiff_t pos = (it->s ? -1
8354 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8355 : IT_CHARPOS (*it));
8356 int c;
8357
8358 if (it->what == IT_CHARACTER)
8359 c = it->char_to_display;
8360 else
8361 {
8362 struct composition *cmp = composition_table[it->cmp_it.id];
8363 int i;
8364
8365 c = ' ';
8366 for (i = 0; i < cmp->glyph_len; i++)
8367
8368
8369 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8370 break;
8371 }
8372 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8373 }
8374 }
8375 #endif
8376
8377 done:
8378
8379
8380 if (it->face_box_p
8381 && it->s == NULL)
8382 {
8383 if (it->method == GET_FROM_STRING && it->sp)
8384 {
8385 int face_id = underlying_face_id (it);
8386 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8387
8388 if (face)
8389 {
8390 if (face->box == FACE_NO_BOX)
8391 {
8392
8393
8394 int string_face_id = face_after_it_pos (it);
8395 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8396 it->end_of_box_run_p = true;
8397 }
8398
8399
8400
8401 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8402
8403
8404
8405 || (it->what == IT_COMPOSITION
8406 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8407 >= SCHARS (it->string))))
8408
8409
8410 && ((it->current.overlay_string_index >= 0
8411 && (it->current.overlay_string_index
8412 == it->n_overlay_strings - 1))
8413
8414 || it->from_disp_prop_p))
8415 {
8416 ptrdiff_t ignore;
8417 int next_face_id;
8418 bool text_from_string = false;
8419
8420
8421 struct text_pos pos = it->current.pos;
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433 if (it->from_disp_prop_p)
8434 {
8435 int stackp = it->sp - 1;
8436
8437
8438 while (stackp >= 0
8439 && STRINGP ((it->stack + stackp)->string))
8440 stackp--;
8441 if (stackp < 0)
8442 {
8443
8444
8445
8446
8447
8448
8449 text_from_string = true;
8450 pos = it->stack[it->sp - 1].position;
8451 }
8452 else
8453 pos = (it->stack + stackp)->position;
8454 }
8455 else
8456 INC_TEXT_POS (pos, it->multibyte_p);
8457
8458 if (text_from_string)
8459 {
8460 Lisp_Object base_string = it->stack[it->sp - 1].string;
8461
8462 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8463 it->end_of_box_run_p = true;
8464 else
8465 {
8466 next_face_id
8467 = face_at_string_position (it->w, base_string,
8468 CHARPOS (pos), 0,
8469 &ignore, face_id,
8470 false, 0);
8471 if (FACE_FROM_ID (it->f, next_face_id)->box
8472 == FACE_NO_BOX)
8473 it->end_of_box_run_p = true;
8474 }
8475 }
8476 else if (CHARPOS (pos) >= ZV)
8477 it->end_of_box_run_p = true;
8478 else
8479 {
8480 next_face_id =
8481 face_at_buffer_position (it->w, CHARPOS (pos),
8482 &ignore,
8483 CHARPOS (pos)
8484 + TEXT_PROP_DISTANCE_LIMIT,
8485 false, -1, 0);
8486 if (FACE_FROM_ID (it->f, next_face_id)->box
8487 == FACE_NO_BOX)
8488 it->end_of_box_run_p = true;
8489 }
8490 }
8491 }
8492 }
8493
8494
8495 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8496 {
8497 int face_id = face_after_it_pos (it);
8498 if (face_id != it->face_id
8499 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8500 it->end_of_box_run_p = true;
8501 }
8502 }
8503
8504
8505
8506
8507
8508 if (!success_p && it->sp > 0)
8509 {
8510 set_iterator_to_next (it, false);
8511 success_p = get_next_display_element (it);
8512 }
8513
8514
8515 return success_p;
8516 }
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534 void
8535 set_iterator_to_next (struct it *it, bool reseat_p)
8536 {
8537
8538 if (max_redisplay_ticks > 0)
8539 update_redisplay_ticks (1, it->w);
8540
8541 switch (it->method)
8542 {
8543 case GET_FROM_BUFFER:
8544
8545
8546
8547 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8548 reseat_at_next_visible_line_start (it, false);
8549 else if (it->cmp_it.id >= 0)
8550 {
8551
8552 if (! it->bidi_p)
8553 {
8554 IT_CHARPOS (*it) += it->cmp_it.nchars;
8555 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8556 }
8557 else
8558 {
8559 int i;
8560
8561
8562
8563
8564 for (i = 0; i < it->cmp_it.nchars; i++)
8565 bidi_move_to_visually_next (&it->bidi_it);
8566 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8567 IT_CHARPOS (*it) = it->bidi_it.charpos;
8568 }
8569
8570 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8571 && it->cmp_it.to < it->cmp_it.nglyphs)
8572 {
8573
8574
8575 it->cmp_it.from = it->cmp_it.to;
8576 }
8577 else if ((it->bidi_p && it->cmp_it.reversed_p)
8578 && it->cmp_it.from > 0)
8579 {
8580
8581
8582 it->cmp_it.to = it->cmp_it.from;
8583 }
8584 else
8585 {
8586
8587
8588 ptrdiff_t stop = it->end_charpos;
8589
8590 if (it->bidi_it.scan_dir < 0)
8591
8592
8593 stop = -1;
8594 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8595 IT_BYTEPOS (*it), stop, Qnil, true);
8596 }
8597 }
8598 else
8599 {
8600 eassert (it->len != 0);
8601
8602 if (!it->bidi_p)
8603 {
8604 IT_BYTEPOS (*it) += it->len;
8605 IT_CHARPOS (*it) += 1;
8606 }
8607 else
8608 {
8609 int prev_scan_dir = it->bidi_it.scan_dir;
8610
8611
8612 if (it->bidi_it.new_paragraph)
8613 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8614 false);
8615 bidi_move_to_visually_next (&it->bidi_it);
8616 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8617 IT_CHARPOS (*it) = it->bidi_it.charpos;
8618 if (prev_scan_dir != it->bidi_it.scan_dir)
8619 {
8620
8621
8622 ptrdiff_t stop = it->end_charpos;
8623 if (it->bidi_it.scan_dir < 0)
8624 stop = -1;
8625 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8626 IT_BYTEPOS (*it), stop, Qnil,
8627 true);
8628 }
8629 }
8630 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8631 }
8632 break;
8633
8634 case GET_FROM_C_STRING:
8635
8636 if (!it->bidi_p
8637
8638
8639
8640
8641 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8642 {
8643 IT_BYTEPOS (*it) += it->len;
8644 IT_CHARPOS (*it) += 1;
8645 }
8646 else
8647 {
8648 bidi_move_to_visually_next (&it->bidi_it);
8649 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8650 IT_CHARPOS (*it) = it->bidi_it.charpos;
8651 }
8652 break;
8653
8654 case GET_FROM_DISPLAY_VECTOR:
8655
8656
8657
8658
8659 ++it->current.dpvec_index;
8660
8661
8662
8663 it->face_id = it->saved_face_id;
8664
8665 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8666 {
8667 bool recheck_faces = it->ellipsis_p;
8668
8669 if (it->s)
8670 it->method = GET_FROM_C_STRING;
8671 else if (STRINGP (it->string))
8672 it->method = GET_FROM_STRING;
8673 else
8674 {
8675 it->method = GET_FROM_BUFFER;
8676 it->object = it->w->contents;
8677 }
8678
8679 it->dpvec = NULL;
8680 it->current.dpvec_index = -1;
8681
8682
8683 if (it->dpvec_char_len < 0)
8684 reseat_at_next_visible_line_start (it, true);
8685 else if (it->dpvec_char_len > 0)
8686 {
8687 it->len = it->dpvec_char_len;
8688 set_iterator_to_next (it, reseat_p);
8689 }
8690
8691
8692 if (recheck_faces)
8693 {
8694 if (it->method == GET_FROM_STRING)
8695 it->stop_charpos = IT_STRING_CHARPOS (*it);
8696 else
8697 it->stop_charpos = IT_CHARPOS (*it);
8698 }
8699 }
8700 break;
8701
8702 case GET_FROM_STRING:
8703
8704 eassert (it->s == NULL && STRINGP (it->string));
8705
8706
8707
8708
8709
8710 if (it->current.overlay_string_index >= 0)
8711 {
8712
8713
8714
8715 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8716 goto consider_string_end;
8717 }
8718 else
8719 {
8720
8721
8722 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8723 goto consider_string_end;
8724 }
8725 if (it->cmp_it.id >= 0)
8726 {
8727
8728
8729
8730 if (! it->bidi_p)
8731 {
8732 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8733 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8734 }
8735 else
8736 {
8737 int i;
8738
8739 for (i = 0; i < it->cmp_it.nchars; i++)
8740 bidi_move_to_visually_next (&it->bidi_it);
8741 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8742 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8743 }
8744
8745
8746
8747 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8748 && (it->cmp_it.to < it->cmp_it.nglyphs))
8749 {
8750
8751
8752 it->cmp_it.from = it->cmp_it.to;
8753 }
8754 else if ((it->bidi_p && it->cmp_it.reversed_p)
8755 && it->cmp_it.from > 0)
8756 {
8757
8758
8759 it->cmp_it.to = it->cmp_it.from;
8760 }
8761 else
8762 {
8763
8764
8765
8766
8767
8768
8769 ptrdiff_t stop = SCHARS (it->string);
8770
8771 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8772 stop = -1;
8773 else if (it->end_charpos < stop)
8774 {
8775
8776
8777
8778 stop = it->end_charpos;
8779 }
8780 composition_compute_stop_pos (&it->cmp_it,
8781 IT_STRING_CHARPOS (*it),
8782 IT_STRING_BYTEPOS (*it), stop,
8783 it->string, true);
8784 }
8785 }
8786 else
8787 {
8788 if (!it->bidi_p
8789
8790
8791
8792
8793
8794 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8795 {
8796 IT_STRING_BYTEPOS (*it) += it->len;
8797 IT_STRING_CHARPOS (*it) += 1;
8798 }
8799 else
8800 {
8801 int prev_scan_dir = it->bidi_it.scan_dir;
8802
8803 bidi_move_to_visually_next (&it->bidi_it);
8804 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8805 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8806
8807
8808 if (prev_scan_dir != it->bidi_it.scan_dir)
8809 {
8810 ptrdiff_t stop = SCHARS (it->string);
8811
8812 if (it->bidi_it.scan_dir < 0)
8813 stop = -1;
8814 else if (it->end_charpos < stop)
8815 stop = it->end_charpos;
8816
8817 composition_compute_stop_pos (&it->cmp_it,
8818 IT_STRING_CHARPOS (*it),
8819 IT_STRING_BYTEPOS (*it), stop,
8820 it->string, true);
8821 }
8822 }
8823 }
8824
8825 consider_string_end:
8826
8827 if (it->current.overlay_string_index >= 0)
8828 {
8829
8830
8831 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8832 {
8833 it->ellipsis_p = false;
8834 next_overlay_string (it);
8835 if (it->ellipsis_p)
8836 setup_for_ellipsis (it, 0);
8837 }
8838 }
8839 else
8840 {
8841
8842
8843
8844
8845 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8846 && it->sp > 0)
8847 {
8848 pop_it (it);
8849 if (it->method == GET_FROM_STRING)
8850 goto consider_string_end;
8851 }
8852 }
8853 break;
8854
8855 case GET_FROM_IMAGE:
8856 case GET_FROM_STRETCH:
8857 case GET_FROM_XWIDGET:
8858
8859
8860
8861
8862 eassert (it->sp > 0);
8863 pop_it (it);
8864 if (it->method == GET_FROM_STRING)
8865 goto consider_string_end;
8866 break;
8867
8868 default:
8869
8870 emacs_abort ();
8871 }
8872
8873 eassert (it->method != GET_FROM_STRING
8874 || (STRINGP (it->string)
8875 && IT_STRING_CHARPOS (*it) >= 0));
8876 }
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887 static bool
8888 next_element_from_display_vector (struct it *it)
8889 {
8890 Lisp_Object gc;
8891 int prev_face_id = it->face_id;
8892 int next_face_id;
8893
8894
8895 eassert (it->dpvec && it->current.dpvec_index >= 0);
8896
8897 it->face_id = it->saved_face_id;
8898
8899
8900
8901 if (it->dpend - it->dpvec > 0
8902 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8903 {
8904 struct face *this_face, *prev_face, *next_face;
8905
8906 it->c = GLYPH_CODE_CHAR (gc);
8907 it->len = CHAR_BYTES (it->c);
8908
8909
8910
8911
8912 if (it->dpvec_face_id >= 0)
8913 it->face_id = it->dpvec_face_id;
8914 else
8915 {
8916 int lface_id = GLYPH_CODE_FACE (gc);
8917 if (lface_id > 0)
8918 it->face_id = merge_faces (it->w, Qt, lface_id,
8919 it->saved_face_id);
8920 }
8921
8922
8923
8924
8925 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8926 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8927
8928
8929 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8930 && (!prev_face
8931 || prev_face->box == FACE_NO_BOX));
8932
8933
8934
8935
8936 next_face_id = it->saved_face_id;
8937 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8938 {
8939 if (it->dpvec_face_id >= 0)
8940 next_face_id = it->dpvec_face_id;
8941 else
8942 {
8943 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8944 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8945
8946 if (lface_id > 0)
8947 next_face_id = merge_faces (it->w, Qt, lface_id,
8948 it->saved_face_id);
8949 }
8950 }
8951 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8952 if (this_face && this_face->box != FACE_NO_BOX
8953 && (!next_face || next_face->box == FACE_NO_BOX))
8954 it->end_of_box_run_p = true;
8955 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8956 }
8957 else
8958
8959 it->c = ' ', it->len = 1;
8960
8961
8962
8963
8964 it->what = IT_CHARACTER;
8965 return true;
8966 }
8967
8968
8969
8970 static void
8971 get_visually_first_element (struct it *it)
8972 {
8973 bool string_p = STRINGP (it->string) || it->s;
8974 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8975 ptrdiff_t bob;
8976 ptrdiff_t obegv = BEGV;
8977
8978 SET_WITH_NARROWED_BEGV (it, bob,
8979 string_p ? 0 :
8980 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8981 it->medium_narrowing_begv);
8982
8983 if (STRINGP (it->string))
8984 {
8985 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8986 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8987 }
8988 else
8989 {
8990 it->bidi_it.charpos = IT_CHARPOS (*it);
8991 it->bidi_it.bytepos = IT_BYTEPOS (*it);
8992 }
8993
8994 if (it->bidi_it.charpos == eob)
8995 {
8996
8997
8998
8999 it->bidi_it.first_elt = false;
9000 }
9001 else if (it->bidi_it.charpos == bob
9002 || (!string_p
9003 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
9004 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
9005 {
9006
9007
9008 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
9009 bidi_move_to_visually_next (&it->bidi_it);
9010 }
9011 else
9012 {
9013 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
9014
9015
9016
9017
9018 if (string_p)
9019 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
9020 else
9021 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
9022 find_newline_no_quit (IT_CHARPOS (*it),
9023 IT_BYTEPOS (*it), -1,
9024 &it->bidi_it.bytepos),
9025 it->medium_narrowing_begv);
9026 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
9027 do
9028 {
9029
9030
9031 bidi_move_to_visually_next (&it->bidi_it);
9032 }
9033 while (it->bidi_it.bytepos != orig_bytepos
9034 && it->bidi_it.charpos < eob);
9035 }
9036
9037
9038 if (STRINGP (it->string))
9039 {
9040 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
9041 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
9042 }
9043 else
9044 {
9045 IT_CHARPOS (*it) = it->bidi_it.charpos;
9046 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
9047 }
9048
9049 if (STRINGP (it->string) || !it->s)
9050 {
9051 ptrdiff_t stop, charpos, bytepos;
9052
9053 if (STRINGP (it->string))
9054 {
9055 eassert (!it->s);
9056 stop = SCHARS (it->string);
9057 if (stop > it->end_charpos)
9058 stop = it->end_charpos;
9059 charpos = IT_STRING_CHARPOS (*it);
9060 bytepos = IT_STRING_BYTEPOS (*it);
9061 }
9062 else
9063 {
9064 stop = it->end_charpos;
9065 charpos = IT_CHARPOS (*it);
9066 bytepos = IT_BYTEPOS (*it);
9067 }
9068 if (it->bidi_it.scan_dir < 0)
9069 stop = -1;
9070 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9071 it->string, true);
9072 }
9073 }
9074
9075
9076
9077
9078
9079
9080 static bool
9081 next_element_from_string (struct it *it)
9082 {
9083 struct text_pos position;
9084
9085 eassert (STRINGP (it->string));
9086 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9087 eassert (IT_STRING_CHARPOS (*it) >= 0);
9088 position = it->current.string_pos;
9089
9090
9091
9092
9093
9094 if (it->bidi_p && it->bidi_it.first_elt)
9095 {
9096 get_visually_first_element (it);
9097 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9098 }
9099
9100
9101 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9102 {
9103 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9104 {
9105 if (!(!it->bidi_p
9106 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9107 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9108 {
9109
9110
9111
9112
9113
9114
9115 handle_stop_backwards (it, it->stop_charpos);
9116 return GET_NEXT_DISPLAY_ELEMENT (it);
9117 }
9118 else
9119 {
9120 if (it->bidi_p)
9121 {
9122
9123
9124 it->prev_stop = it->stop_charpos;
9125
9126
9127
9128 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9129 it->base_level_stop = it->stop_charpos;
9130 }
9131 handle_stop (it);
9132
9133
9134
9135 return GET_NEXT_DISPLAY_ELEMENT (it);
9136 }
9137 }
9138 else if (it->bidi_p
9139
9140
9141
9142 && IT_STRING_CHARPOS (*it) < it->prev_stop
9143
9144
9145
9146
9147 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9148 {
9149
9150
9151
9152
9153 if (it->base_level_stop <= 0
9154 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9155 it->base_level_stop = 0;
9156 handle_stop_backwards (it, it->base_level_stop);
9157 return GET_NEXT_DISPLAY_ELEMENT (it);
9158 }
9159 }
9160
9161 if (it->current.overlay_string_index >= 0)
9162 {
9163
9164
9165
9166 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9167 {
9168 it->what = IT_EOB;
9169 return false;
9170 }
9171 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9172 IT_STRING_BYTEPOS (*it),
9173 it->bidi_it.scan_dir < 0
9174 ? -1
9175 : SCHARS (it->string))
9176 && next_element_from_composition (it))
9177 {
9178 return true;
9179 }
9180 else if (STRING_MULTIBYTE (it->string))
9181 {
9182 const unsigned char *s = (SDATA (it->string)
9183 + IT_STRING_BYTEPOS (*it));
9184 it->c = check_char_and_length (s, &it->len);
9185 }
9186 else
9187 {
9188 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9189 it->len = 1;
9190 }
9191 }
9192 else
9193 {
9194
9195
9196
9197
9198 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9199 {
9200 it->what = IT_EOB;
9201 return false;
9202 }
9203 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9204 {
9205
9206 it->c = ' ', it->len = 1;
9207 CHARPOS (position) = BYTEPOS (position) = -1;
9208 }
9209 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9210 IT_STRING_BYTEPOS (*it),
9211 it->bidi_it.scan_dir < 0
9212 ? -1
9213 : it->string_nchars)
9214 && next_element_from_composition (it))
9215 {
9216 return true;
9217 }
9218 else if (STRING_MULTIBYTE (it->string))
9219 {
9220 const unsigned char *s = (SDATA (it->string)
9221 + IT_STRING_BYTEPOS (*it));
9222 it->c = check_char_and_length (s, &it->len);
9223 }
9224 else
9225 {
9226 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9227 it->len = 1;
9228 }
9229 }
9230
9231
9232 it->what = IT_CHARACTER;
9233 it->object = it->string;
9234 it->position = position;
9235 return true;
9236 }
9237
9238
9239
9240
9241
9242
9243
9244
9245
9246 static bool
9247 next_element_from_c_string (struct it *it)
9248 {
9249 bool success_p = true;
9250
9251 eassert (it->s);
9252 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9253 it->what = IT_CHARACTER;
9254 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9255 it->object = make_fixnum (0);
9256
9257
9258
9259
9260
9261 if (it->bidi_p && it->bidi_it.first_elt)
9262 get_visually_first_element (it);
9263
9264
9265
9266
9267 if (IT_CHARPOS (*it) >= it->end_charpos)
9268 {
9269
9270 it->what = IT_EOB;
9271 success_p = false;
9272 }
9273 else if (IT_CHARPOS (*it) >= it->string_nchars)
9274 {
9275
9276 it->c = ' ', it->len = 1;
9277 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9278 }
9279 else if (it->multibyte_p)
9280 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9281 else
9282 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9283
9284 return success_p;
9285 }
9286
9287
9288
9289
9290
9291
9292
9293 static bool
9294 next_element_from_ellipsis (struct it *it)
9295 {
9296 if (it->selective_display_ellipsis_p)
9297 setup_for_ellipsis (it, it->len);
9298 else
9299 {
9300
9301
9302
9303
9304 it->saved_face_id = it->face_id;
9305 it->method = GET_FROM_BUFFER;
9306 it->object = it->w->contents;
9307 reseat_at_next_visible_line_start (it, true);
9308 it->face_before_selective_p = true;
9309 }
9310
9311 return GET_NEXT_DISPLAY_ELEMENT (it);
9312 }
9313
9314
9315
9316
9317
9318
9319
9320 static bool
9321 next_element_from_image (struct it *it)
9322 {
9323 it->what = IT_IMAGE;
9324 return true;
9325 }
9326
9327 static bool
9328 next_element_from_xwidget (struct it *it)
9329 {
9330 it->what = IT_XWIDGET;
9331 return true;
9332 }
9333
9334
9335
9336
9337
9338
9339 static bool
9340 next_element_from_stretch (struct it *it)
9341 {
9342 it->what = IT_STRETCH;
9343 return true;
9344 }
9345
9346
9347
9348
9349
9350
9351 static void
9352 compute_stop_pos_backwards (struct it *it)
9353 {
9354 const int SCAN_BACK_LIMIT = 1000;
9355 struct text_pos pos;
9356 struct display_pos save_current = it->current;
9357 struct text_pos save_position = it->position;
9358 ptrdiff_t charpos = IT_CHARPOS (*it);
9359 ptrdiff_t where_we_are = charpos;
9360 ptrdiff_t save_stop_pos = it->stop_charpos;
9361 ptrdiff_t save_end_pos = it->end_charpos;
9362
9363 eassert (NILP (it->string) && !it->s);
9364 eassert (it->bidi_p);
9365 it->bidi_p = false;
9366 do
9367 {
9368 it->end_charpos = min (charpos + 1, ZV);
9369 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9370 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9371 reseat_1 (it, pos, false);
9372 compute_stop_pos (it);
9373
9374 if (it->stop_charpos <= charpos)
9375 emacs_abort ();
9376 }
9377 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9378
9379 if (it->stop_charpos <= where_we_are)
9380 it->prev_stop = it->stop_charpos;
9381 else
9382 it->prev_stop = BEGV;
9383 it->bidi_p = true;
9384 it->current = save_current;
9385 it->position = save_position;
9386 it->stop_charpos = save_stop_pos;
9387 it->end_charpos = save_end_pos;
9388 }
9389
9390
9391
9392
9393
9394
9395
9396
9397
9398 static void
9399 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9400 {
9401 bool bufp = !STRINGP (it->string);
9402 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9403 struct display_pos save_current = it->current;
9404 struct text_pos save_position = it->position;
9405 struct composition_it save_cmp_it = it->cmp_it;
9406 struct text_pos pos1;
9407 ptrdiff_t next_stop;
9408
9409
9410 eassert (it->bidi_p);
9411 it->bidi_p = false;
9412 do
9413 {
9414 it->prev_stop = charpos;
9415 if (bufp)
9416 {
9417 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9418 reseat_1 (it, pos1, false);
9419 }
9420 else
9421 it->current.string_pos = string_pos (charpos, it->string);
9422 compute_stop_pos (it);
9423
9424 if (it->stop_charpos <= it->prev_stop)
9425 emacs_abort ();
9426 charpos = it->stop_charpos;
9427 }
9428 while (charpos <= where_we_are);
9429
9430 it->bidi_p = true;
9431 it->current = save_current;
9432 it->position = save_position;
9433 it->cmp_it = save_cmp_it;
9434 next_stop = it->stop_charpos;
9435 it->stop_charpos = it->prev_stop;
9436 handle_stop (it);
9437 it->stop_charpos = next_stop;
9438 }
9439
9440
9441
9442
9443
9444
9445 static bool
9446 next_element_from_buffer (struct it *it)
9447 {
9448 bool success_p = true;
9449
9450 eassert (IT_CHARPOS (*it) >= BEGV);
9451 eassert (NILP (it->string) && !it->s);
9452 eassert (!it->bidi_p
9453 || (NILP (it->bidi_it.string.lstring)
9454 && it->bidi_it.string.s == NULL));
9455
9456
9457
9458
9459
9460 if (it->bidi_p && it->bidi_it.first_elt)
9461 {
9462 get_visually_first_element (it);
9463 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9464 }
9465
9466 if (IT_CHARPOS (*it) >= it->stop_charpos)
9467 {
9468 if (IT_CHARPOS (*it) >= it->end_charpos)
9469 {
9470 bool overlay_strings_follow_p;
9471
9472
9473
9474 if (it->overlay_strings_at_end_processed_p)
9475 overlay_strings_follow_p = false;
9476 else
9477 {
9478 it->overlay_strings_at_end_processed_p = true;
9479 overlay_strings_follow_p = get_overlay_strings (it, 0);
9480 }
9481
9482 if (overlay_strings_follow_p)
9483 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9484 else
9485 {
9486 it->what = IT_EOB;
9487 it->position = it->current.pos;
9488 success_p = false;
9489 }
9490 }
9491 else if (!(!it->bidi_p
9492 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9493 || IT_CHARPOS (*it) == it->stop_charpos))
9494 {
9495
9496
9497
9498
9499
9500
9501 handle_stop_backwards (it, it->stop_charpos);
9502 it->ignore_overlay_strings_at_pos_p = false;
9503 return GET_NEXT_DISPLAY_ELEMENT (it);
9504 }
9505 else
9506 {
9507 if (it->bidi_p)
9508 {
9509
9510
9511 it->prev_stop = it->stop_charpos;
9512
9513
9514
9515 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9516 it->base_level_stop = it->stop_charpos;
9517 }
9518 handle_stop (it);
9519 it->ignore_overlay_strings_at_pos_p = false;
9520 return GET_NEXT_DISPLAY_ELEMENT (it);
9521 }
9522 }
9523 else if (it->bidi_p
9524
9525
9526
9527 && IT_CHARPOS (*it) < it->prev_stop
9528
9529
9530
9531
9532 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9533 {
9534 if (it->base_level_stop <= 0
9535 || IT_CHARPOS (*it) < it->base_level_stop)
9536 {
9537
9538
9539
9540
9541 it->base_level_stop = BEGV;
9542 compute_stop_pos_backwards (it);
9543 handle_stop_backwards (it, it->prev_stop);
9544 }
9545 else
9546 handle_stop_backwards (it, it->base_level_stop);
9547 it->ignore_overlay_strings_at_pos_p = false;
9548 return GET_NEXT_DISPLAY_ELEMENT (it);
9549 }
9550 else
9551 {
9552
9553
9554 unsigned char *p;
9555 ptrdiff_t stop;
9556
9557
9558
9559 it->ignore_overlay_strings_at_pos_p = false;
9560
9561 if (composition_break_at_point
9562 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9563 && !NILP (Vauto_composition_mode))
9564 {
9565
9566 if (it->bidi_it.scan_dir < 0)
9567 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9568 else
9569 stop = (IT_CHARPOS (*it) < PT
9570 && PT < it->end_charpos) ? PT : it->end_charpos;
9571 }
9572 else
9573 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9574 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9575 stop)
9576 && next_element_from_composition (it))
9577 {
9578 return true;
9579 }
9580
9581
9582 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9583 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9584 it->c = string_char_and_length (p, &it->len);
9585 else
9586 it->c = *p, it->len = 1;
9587
9588
9589 it->what = IT_CHARACTER;
9590 it->object = it->w->contents;
9591 it->position = it->current.pos;
9592
9593
9594
9595 if (it->selective)
9596 {
9597 if (it->c == '\n')
9598 {
9599
9600
9601 if (it->selective > 0
9602 && IT_CHARPOS (*it) + 1 < ZV
9603 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9604 IT_BYTEPOS (*it) + 1,
9605 it->selective))
9606 {
9607 success_p = next_element_from_ellipsis (it);
9608 it->dpvec_char_len = -1;
9609 }
9610 }
9611 else if (it->c == '\r' && it->selective == -1)
9612 {
9613
9614
9615
9616 success_p = next_element_from_ellipsis (it);
9617 it->dpvec_char_len = -1;
9618 }
9619 }
9620 }
9621
9622
9623 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9624 return success_p;
9625 }
9626
9627
9628
9629
9630
9631
9632
9633 static bool
9634 next_element_from_composition (struct it *it)
9635 {
9636 it->what = IT_COMPOSITION;
9637 it->len = it->cmp_it.nbytes;
9638 if (STRINGP (it->string))
9639 {
9640 if (it->c < 0)
9641 {
9642 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9643 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9644 return false;
9645 }
9646 it->position = it->current.string_pos;
9647 it->object = it->string;
9648 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9649 IT_STRING_BYTEPOS (*it), it->string);
9650 }
9651 else
9652 {
9653 if (it->c < 0)
9654 {
9655 IT_CHARPOS (*it) += it->cmp_it.nchars;
9656 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9657 if (it->bidi_p)
9658 {
9659 if (it->bidi_it.new_paragraph)
9660 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9661 false);
9662
9663
9664 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9665 bidi_move_to_visually_next (&it->bidi_it);
9666 }
9667 return false;
9668 }
9669 it->position = it->current.pos;
9670 it->object = it->w->contents;
9671 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9672 IT_BYTEPOS (*it), Qnil);
9673 }
9674 return true;
9675 }
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9687 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716
9717
9718
9719
9720
9721
9722
9723 static enum move_it_result
9724 move_it_in_display_line_to (struct it *it,
9725 ptrdiff_t to_charpos, int to_x,
9726 enum move_operation_enum op)
9727 {
9728 enum move_it_result result = MOVE_UNDEFINED;
9729 struct glyph_row *saved_glyph_row;
9730 struct it wrap_it, atpos_it, atx_it, ppos_it;
9731 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9732 void *ppos_data = NULL;
9733 bool may_wrap = false;
9734 enum it_method prev_method = it->method;
9735 ptrdiff_t closest_pos UNINIT;
9736 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9737 bool saw_smaller_pos = prev_pos < to_charpos;
9738 bool line_number_pending = false;
9739
9740
9741 saved_glyph_row = it->glyph_row;
9742 it->glyph_row = NULL;
9743
9744
9745
9746
9747
9748
9749 wrap_it.sp = -1;
9750 atpos_it.sp = -1;
9751 atx_it.sp = -1;
9752
9753
9754
9755
9756
9757
9758
9759
9760 if (it->bidi_p)
9761 {
9762 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9763 {
9764 SAVE_IT (ppos_it, *it, ppos_data);
9765 closest_pos = IT_CHARPOS (*it);
9766 }
9767 else
9768 closest_pos = ZV;
9769 }
9770
9771 #define BUFFER_POS_REACHED_P() \
9772 ((op & MOVE_TO_POS) != 0 \
9773 && BUFFERP (it->object) \
9774 && (IT_CHARPOS (*it) == to_charpos \
9775 || ((!it->bidi_p \
9776 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9777 && IT_CHARPOS (*it) > to_charpos) \
9778 || (it->what == IT_COMPOSITION \
9779 && ((IT_CHARPOS (*it) > to_charpos \
9780 && to_charpos >= it->cmp_it.charpos) \
9781 || (IT_CHARPOS (*it) < to_charpos \
9782 && to_charpos <= it->cmp_it.charpos)))) \
9783 && (it->method == GET_FROM_BUFFER \
9784 || (it->method == GET_FROM_DISPLAY_VECTOR \
9785 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9786
9787 if (it->hpos == 0)
9788 {
9789
9790
9791
9792
9793 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9794 && should_produce_line_number (it))
9795 {
9796 if (it->current_x == it->first_visible_x)
9797 maybe_produce_line_number (it);
9798 else
9799 line_number_pending = true;
9800 }
9801
9802 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9803 handle_line_prefix (it);
9804 }
9805
9806 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9807 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9808
9809 while (true)
9810 {
9811 int x, i, ascent = 0, descent = 0;
9812
9813
9814 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9815 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9816 (IT)->max_descent = descent)
9817
9818
9819
9820 if ((op & MOVE_TO_POS) != 0
9821 && BUFFERP (it->object)
9822 && it->method == GET_FROM_BUFFER
9823 && (((!it->bidi_p
9824
9825
9826
9827
9828 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9829 && IT_CHARPOS (*it) > to_charpos)
9830 || (it->bidi_p
9831 && (prev_method == GET_FROM_IMAGE
9832 || prev_method == GET_FROM_STRETCH
9833 || prev_method == GET_FROM_STRING)
9834
9835 && ((prev_pos < to_charpos
9836 && IT_CHARPOS (*it) >= to_charpos)
9837
9838 || (prev_pos > to_charpos
9839 && IT_CHARPOS (*it) <= to_charpos)))))
9840 {
9841 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9842 {
9843 result = MOVE_POS_MATCH_OR_ZV;
9844 break;
9845 }
9846 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9847
9848
9849
9850 SAVE_IT (atpos_it, *it, atpos_data);
9851 }
9852
9853
9854
9855
9856
9857 if (!get_next_display_element (it))
9858 {
9859 result = MOVE_POS_MATCH_OR_ZV;
9860 break;
9861 }
9862
9863 if (it->line_wrap == TRUNCATE)
9864 {
9865
9866
9867
9868
9869
9870
9871 if (BUFFER_POS_REACHED_P ()
9872 && (it->pixel_width > 0
9873 || IT_CHARPOS (*it) > to_charpos
9874 || it->area != TEXT_AREA))
9875 {
9876 result = MOVE_POS_MATCH_OR_ZV;
9877 break;
9878 }
9879 }
9880 else
9881 {
9882 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9883 {
9884 bool next_may_wrap = may_wrap;
9885
9886 if (char_can_wrap_after (it))
9887 next_may_wrap = true;
9888 else
9889 next_may_wrap = false;
9890
9891 if (may_wrap && char_can_wrap_before (it))
9892 {
9893
9894
9895
9896
9897
9898 if (atpos_it.sp >= 0)
9899 {
9900 RESTORE_IT (it, &atpos_it, atpos_data);
9901 result = MOVE_POS_MATCH_OR_ZV;
9902 goto done;
9903 }
9904 if (atx_it.sp >= 0)
9905 {
9906 RESTORE_IT (it, &atx_it, atx_data);
9907 result = MOVE_X_REACHED;
9908 goto done;
9909 }
9910
9911 SAVE_IT (wrap_it, *it, wrap_data);
9912 }
9913
9914 may_wrap = next_may_wrap;
9915 }
9916 }
9917
9918
9919
9920 ascent = it->max_ascent;
9921 descent = it->max_descent;
9922
9923
9924
9925
9926
9927 x = it->current_x;
9928
9929 PRODUCE_GLYPHS (it);
9930
9931 if (it->area != TEXT_AREA)
9932 {
9933 prev_method = it->method;
9934 if (it->method == GET_FROM_BUFFER)
9935 prev_pos = IT_CHARPOS (*it);
9936 set_iterator_to_next (it, true);
9937 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9938 SET_TEXT_POS (this_line_min_pos,
9939 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9940 if (it->bidi_p
9941 && (op & MOVE_TO_POS)
9942 && IT_CHARPOS (*it) > to_charpos
9943 && IT_CHARPOS (*it) < closest_pos)
9944 closest_pos = IT_CHARPOS (*it);
9945 continue;
9946 }
9947
9948
9949
9950
9951
9952
9953
9954
9955
9956
9957
9958
9959
9960
9961
9962
9963
9964
9965
9966 if (it->nglyphs)
9967 {
9968
9969
9970 int single_glyph_width = it->pixel_width / it->nglyphs;
9971 int new_x;
9972 int x_before_this_char = x;
9973 int hpos_before_this_char = it->hpos;
9974
9975 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9976 {
9977 new_x = x + single_glyph_width;
9978
9979
9980 if ((op & MOVE_TO_X) && new_x > to_x)
9981 {
9982 if (BUFFER_POS_REACHED_P ())
9983 {
9984 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9985 goto buffer_pos_reached;
9986 if (atpos_it.sp < 0)
9987 {
9988 SAVE_IT (atpos_it, *it, atpos_data);
9989 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9990 }
9991 }
9992 else
9993 {
9994 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9995 {
9996 it->current_x = x;
9997 result = MOVE_X_REACHED;
9998 break;
9999 }
10000 if (atx_it.sp < 0)
10001 {
10002 SAVE_IT (atx_it, *it, atx_data);
10003 IT_RESET_X_ASCENT_DESCENT (&atx_it);
10004 }
10005 }
10006 }
10007
10008 if (
10009 it->line_wrap != TRUNCATE
10010 && (
10011 new_x > it->last_visible_x
10012
10013
10014 || (new_x == it->last_visible_x
10015 && FRAME_WINDOW_P (it->f)
10016 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10017 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10018 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
10019 {
10020 bool moved_forward = false;
10021
10022 if (
10023
10024 it->hpos == 0
10025 || (new_x == it->last_visible_x
10026 && FRAME_WINDOW_P (it->f)))
10027 {
10028 ++it->hpos;
10029 it->current_x = new_x;
10030
10031
10032
10033 if (i == it->nglyphs - 1)
10034 {
10035
10036
10037
10038 if (BUFFER_POS_REACHED_P ())
10039 {
10040 bool can_wrap = true;
10041
10042
10043
10044
10045
10046 if (it->line_wrap == WORD_WRAP
10047 && wrap_it.sp >= 0
10048 && may_wrap
10049 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10050 {
10051 struct it tem_it;
10052 void *tem_data = NULL;
10053
10054 SAVE_IT (tem_it, *it, tem_data);
10055 set_iterator_to_next (it, true);
10056 if (get_next_display_element (it)
10057 && !char_can_wrap_before (it))
10058 can_wrap = false;
10059 RESTORE_IT (it, &tem_it, tem_data);
10060 }
10061 if (it->line_wrap != WORD_WRAP
10062 || wrap_it.sp < 0
10063
10064
10065
10066
10067
10068
10069
10070 || (may_wrap && can_wrap
10071 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10072 {
10073 it->hpos = hpos_before_this_char;
10074 it->current_x = x_before_this_char;
10075 result = MOVE_POS_MATCH_OR_ZV;
10076 break;
10077 }
10078 if (it->line_wrap == WORD_WRAP
10079 && atpos_it.sp < 0)
10080 {
10081 SAVE_IT (atpos_it, *it, atpos_data);
10082 atpos_it.current_x = x_before_this_char;
10083 atpos_it.hpos = hpos_before_this_char;
10084 }
10085 }
10086
10087 prev_method = it->method;
10088 if (it->method == GET_FROM_BUFFER)
10089 prev_pos = IT_CHARPOS (*it);
10090 set_iterator_to_next (it, true);
10091 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10092 SET_TEXT_POS (this_line_min_pos,
10093 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10094
10095
10096
10097
10098
10099
10100
10101 if (!FRAME_WINDOW_P (it->f)
10102 || ((it->bidi_p
10103 && it->bidi_it.paragraph_dir == R2L)
10104 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10105 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10106 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10107 {
10108 if (!get_next_display_element (it))
10109 {
10110 result = MOVE_POS_MATCH_OR_ZV;
10111 break;
10112 }
10113 moved_forward = true;
10114 if (BUFFER_POS_REACHED_P ())
10115 {
10116 if (ITERATOR_AT_END_OF_LINE_P (it))
10117 result = MOVE_POS_MATCH_OR_ZV;
10118 else
10119 result = MOVE_LINE_CONTINUED;
10120 break;
10121 }
10122 if (ITERATOR_AT_END_OF_LINE_P (it)
10123 && (it->line_wrap != WORD_WRAP
10124 || wrap_it.sp < 0
10125 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10126 {
10127 result = MOVE_NEWLINE_OR_CR;
10128 break;
10129 }
10130 }
10131 }
10132 }
10133 else
10134 IT_RESET_X_ASCENT_DESCENT (it);
10135
10136
10137
10138
10139
10140
10141 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10142
10143
10144
10145
10146
10147 && (!moved_forward || char_can_wrap_before (it)))
10148 {
10149
10150
10151 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10152 && atx_it.sp >= 0)
10153 {
10154 RESTORE_IT (it, &atx_it, atx_data);
10155 atpos_it.sp = -1;
10156 atx_it.sp = -1;
10157 result = MOVE_X_REACHED;
10158 break;
10159 }
10160 }
10161 else if (wrap_it.sp >= 0)
10162 {
10163 RESTORE_IT (it, &wrap_it, wrap_data);
10164 atpos_it.sp = -1;
10165 atx_it.sp = -1;
10166 }
10167
10168 move_trace ("move_it_in: continued at %td\n",
10169 IT_CHARPOS (*it));
10170 result = MOVE_LINE_CONTINUED;
10171 break;
10172 }
10173
10174 if (BUFFER_POS_REACHED_P ())
10175 {
10176 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10177 goto buffer_pos_reached;
10178 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10179 {
10180 SAVE_IT (atpos_it, *it, atpos_data);
10181 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10182 }
10183 }
10184
10185 if (new_x > it->first_visible_x)
10186 {
10187
10188
10189 if (line_number_pending)
10190 {
10191 line_number_pending = false;
10192 it->current_x = it->first_visible_x;
10193 maybe_produce_line_number (it);
10194 it->current_x += new_x - it->first_visible_x;
10195 }
10196
10197
10198 ++it->hpos;
10199 }
10200 }
10201
10202 if (result != MOVE_UNDEFINED)
10203 break;
10204 }
10205 else if (BUFFER_POS_REACHED_P ())
10206 {
10207 buffer_pos_reached:
10208 IT_RESET_X_ASCENT_DESCENT (it);
10209 result = MOVE_POS_MATCH_OR_ZV;
10210 break;
10211 }
10212 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10213 {
10214
10215
10216
10217
10218 eassert (it->nglyphs == 0);
10219 result = MOVE_X_REACHED;
10220 break;
10221 }
10222
10223
10224 if (ITERATOR_AT_END_OF_LINE_P (it))
10225 {
10226
10227
10228
10229
10230 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10231 {
10232 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10233 {
10234 if (closest_pos < ZV)
10235 {
10236 RESTORE_IT (it, &ppos_it, ppos_data);
10237
10238
10239 if (closest_pos != to_charpos)
10240 move_it_in_display_line_to (it, closest_pos, -1,
10241 MOVE_TO_POS);
10242 result = MOVE_POS_MATCH_OR_ZV;
10243 }
10244 else
10245 goto buffer_pos_reached;
10246 }
10247 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10248 && IT_CHARPOS (*it) > to_charpos)
10249 goto buffer_pos_reached;
10250 else
10251 result = MOVE_NEWLINE_OR_CR;
10252 }
10253 else
10254 result = MOVE_NEWLINE_OR_CR;
10255
10256
10257
10258
10259 if (it->line_wrap == TRUNCATE
10260 && it->current_x <= it->first_visible_x
10261 && result == MOVE_NEWLINE_OR_CR
10262 && it->char_to_display == '\n')
10263 {
10264 it->max_ascent = it->ascent;
10265 it->max_descent = it->descent;
10266 }
10267
10268
10269
10270 if (result == MOVE_NEWLINE_OR_CR)
10271 it->constrain_row_ascent_descent_p = false;
10272 break;
10273 }
10274
10275 prev_method = it->method;
10276 if (it->method == GET_FROM_BUFFER)
10277 prev_pos = IT_CHARPOS (*it);
10278
10279
10280
10281
10282
10283
10284
10285
10286
10287 bool overwide_wrap_prefix =
10288 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10289 && it->sp > 0 && it->method == GET_FROM_STRETCH
10290 && it->current_x >= it->last_visible_x
10291 && it->continuation_lines_width > 0
10292 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10293
10294
10295 if (!overwide_wrap_prefix)
10296 set_iterator_to_next (it, true);
10297 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10298 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10299 if (IT_CHARPOS (*it) < to_charpos)
10300 saw_smaller_pos = true;
10301 if (it->bidi_p
10302 && (op & MOVE_TO_POS)
10303 && IT_CHARPOS (*it) >= to_charpos
10304 && IT_CHARPOS (*it) < closest_pos)
10305 closest_pos = IT_CHARPOS (*it);
10306
10307
10308
10309 if (it->line_wrap == TRUNCATE
10310 && it->current_x >= it->last_visible_x)
10311 {
10312 if (!FRAME_WINDOW_P (it->f)
10313 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10314 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10315 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10316 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10317 {
10318 bool at_eob_p = false;
10319
10320 if ((at_eob_p = !get_next_display_element (it))
10321 || BUFFER_POS_REACHED_P ()
10322
10323
10324
10325
10326 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10327 && !saw_smaller_pos
10328 && IT_CHARPOS (*it) > to_charpos))
10329 {
10330 if (it->bidi_p
10331 && !BUFFER_POS_REACHED_P ()
10332 && !at_eob_p && 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 if (ITERATOR_AT_END_OF_LINE_P (it))
10343 {
10344 result = MOVE_NEWLINE_OR_CR;
10345 break;
10346 }
10347 }
10348 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10349 && !saw_smaller_pos
10350 && IT_CHARPOS (*it) > to_charpos)
10351 {
10352 if (closest_pos < ZV)
10353 {
10354 RESTORE_IT (it, &ppos_it, ppos_data);
10355 if (closest_pos != to_charpos)
10356 move_it_in_display_line_to (it, closest_pos, -1,
10357 MOVE_TO_POS);
10358 }
10359 result = MOVE_POS_MATCH_OR_ZV;
10360 break;
10361 }
10362 result = MOVE_LINE_TRUNCATED;
10363 break;
10364 }
10365 #undef IT_RESET_X_ASCENT_DESCENT
10366 }
10367
10368 #undef BUFFER_POS_REACHED_P
10369
10370
10371
10372
10373
10374
10375 if (result == MOVE_LINE_CONTINUED
10376 && it->line_wrap == WORD_WRAP
10377 && wrap_it.sp >= 0
10378 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10379 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10380 RESTORE_IT (it, &wrap_it, wrap_data);
10381 else if (atpos_it.sp >= 0)
10382 RESTORE_IT (it, &atpos_it, atpos_data);
10383 else if (atx_it.sp >= 0)
10384 RESTORE_IT (it, &atx_it, atx_data);
10385
10386 done:
10387
10388 if (atpos_data)
10389 bidi_unshelve_cache (atpos_data, true);
10390 if (atx_data)
10391 bidi_unshelve_cache (atx_data, true);
10392 if (wrap_data)
10393 bidi_unshelve_cache (wrap_data, true);
10394 if (ppos_data)
10395 bidi_unshelve_cache (ppos_data, true);
10396
10397
10398
10399 it->glyph_row = saved_glyph_row;
10400 return result;
10401 }
10402
10403
10404 void
10405 move_it_in_display_line (struct it *it,
10406 ptrdiff_t to_charpos, int to_x,
10407 enum move_operation_enum op)
10408 {
10409 if (it->line_wrap == WORD_WRAP
10410 && (op & MOVE_TO_X))
10411 {
10412 struct it save_it;
10413 void *save_data = NULL;
10414 int skip;
10415
10416 SAVE_IT (save_it, *it, save_data);
10417 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10418
10419
10420
10421
10422 if (skip == MOVE_LINE_CONTINUED)
10423 {
10424 int prev_x = max (it->current_x - 1, 0);
10425 RESTORE_IT (it, &save_it, save_data);
10426 move_it_in_display_line_to
10427 (it, -1, prev_x, MOVE_TO_X);
10428 }
10429 else
10430 bidi_unshelve_cache (save_data, true);
10431 }
10432 else
10433 move_it_in_display_line_to (it, to_charpos, to_x, op);
10434 }
10435
10436
10437
10438
10439
10440
10441
10442
10443
10444
10445
10446
10447
10448
10449
10450
10451 int
10452 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10453 {
10454 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10455 int line_height, line_start_x = 0, reached = 0;
10456 int max_current_x = 0;
10457 void *backup_data = NULL;
10458 ptrdiff_t orig_charpos = -1;
10459 enum it_method orig_method = NUM_IT_METHODS;
10460
10461 for (;;)
10462 {
10463 orig_charpos = IT_CHARPOS (*it);
10464 orig_method = it->method;
10465 if (op & MOVE_TO_VPOS)
10466 {
10467
10468
10469 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10470 {
10471 if (it->vpos == to_vpos)
10472 {
10473 reached = 1;
10474 break;
10475 }
10476 else
10477 skip = move_it_in_display_line_to (it, -1, -1, 0);
10478 }
10479 else
10480 {
10481
10482
10483 if (it->vpos == to_vpos)
10484 {
10485 reached = 2;
10486 break;
10487 }
10488
10489 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10490
10491 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10492 {
10493 reached = 3;
10494 break;
10495 }
10496 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10497 {
10498
10499 skip = move_it_in_display_line_to (it, to_charpos,
10500 -1, MOVE_TO_POS);
10501 if (skip == MOVE_POS_MATCH_OR_ZV)
10502 {
10503 reached = 4;
10504 break;
10505 }
10506 }
10507 }
10508 }
10509 else if (op & MOVE_TO_Y)
10510 {
10511 struct it it_backup;
10512
10513 if (it->line_wrap == WORD_WRAP)
10514 SAVE_IT (it_backup, *it, backup_data);
10515
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528 skip = move_it_in_display_line_to
10529 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10530 (MOVE_TO_X | (op & MOVE_TO_POS)));
10531
10532
10533 if (skip == MOVE_POS_MATCH_OR_ZV)
10534 reached = 5;
10535 else if (skip == MOVE_X_REACHED)
10536 {
10537
10538
10539
10540
10541 line_height = it->max_ascent + it->max_descent;
10542 if (to_y >= it->current_y
10543 && to_y < it->current_y + line_height)
10544 {
10545 reached = 6;
10546 break;
10547 }
10548 SAVE_IT (it_backup, *it, backup_data);
10549 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10550 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10551 op & MOVE_TO_POS);
10552 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10553 line_height = it->max_ascent + it->max_descent;
10554 move_trace ("move_it: line_height = %d\n", line_height);
10555
10556 if (to_y >= it->current_y
10557 && to_y < it->current_y + line_height)
10558 {
10559
10560
10561
10562
10563
10564
10565
10566
10567 int max_ascent = it->max_ascent;
10568 int max_descent = it->max_descent;
10569
10570 RESTORE_IT (it, &it_backup, backup_data);
10571 it->max_ascent = max_ascent;
10572 it->max_descent = max_descent;
10573 reached = 6;
10574 }
10575 else
10576 {
10577 skip = skip2;
10578 if (skip == MOVE_POS_MATCH_OR_ZV)
10579 {
10580 reached = 7;
10581
10582
10583
10584
10585
10586
10587
10588 if (to_charpos > 0
10589 && IT_CHARPOS (*it) != to_charpos
10590 && ((IT_CHARPOS (it_backup) > to_charpos)
10591 == (IT_CHARPOS (*it) > to_charpos)))
10592 {
10593 int max_ascent = it->max_ascent;
10594 int max_descent = it->max_descent;
10595
10596 RESTORE_IT (it, &it_backup, backup_data);
10597 it->max_ascent = max_ascent;
10598 it->max_descent = max_descent;
10599 }
10600 }
10601 }
10602 }
10603 else
10604 {
10605
10606 line_height = it->max_ascent + it->max_descent;
10607 move_trace ("move_it: line_height = %d\n", line_height);
10608
10609 if (to_y >= it->current_y
10610 && to_y < it->current_y + line_height)
10611 {
10612 if (to_y > it->current_y)
10613 max_current_x = max (it->current_x, max_current_x);
10614
10615
10616
10617
10618
10619 if (skip == MOVE_LINE_CONTINUED
10620 && it->line_wrap == WORD_WRAP)
10621 {
10622 int prev_x = max (it->current_x - 1, 0);
10623 RESTORE_IT (it, &it_backup, backup_data);
10624 skip = move_it_in_display_line_to
10625 (it, -1, prev_x, MOVE_TO_X);
10626 }
10627
10628 reached = 6;
10629 }
10630 }
10631
10632 if (reached)
10633 {
10634 max_current_x = max (it->current_x, max_current_x);
10635 break;
10636 }
10637 }
10638 else if (BUFFERP (it->object)
10639 && (it->method == GET_FROM_BUFFER
10640 || it->method == GET_FROM_STRETCH)
10641 && IT_CHARPOS (*it) >= to_charpos
10642
10643
10644
10645
10646
10647 && !(it->bidi_p
10648 && it->bidi_it.scan_dir == -1))
10649 skip = MOVE_POS_MATCH_OR_ZV;
10650 else
10651 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10652
10653 switch (skip)
10654 {
10655 case MOVE_POS_MATCH_OR_ZV:
10656 max_current_x = max (it->current_x, max_current_x);
10657 reached = 8;
10658 goto out;
10659
10660 case MOVE_NEWLINE_OR_CR:
10661 max_current_x = max (it->current_x, max_current_x);
10662 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10663 it->override_ascent = -1;
10664 set_iterator_to_next (it, true);
10665 it->continuation_lines_width = 0;
10666 break;
10667
10668 case MOVE_LINE_TRUNCATED:
10669 max_current_x = it->last_visible_x;
10670 it->continuation_lines_width = 0;
10671 reseat_at_next_visible_line_start (it, false);
10672 if ((op & MOVE_TO_POS) != 0
10673 && (IT_CHARPOS (*it) > to_charpos
10674 || (IT_CHARPOS (*it) == to_charpos
10675
10676
10677 && to_charpos == ZV
10678 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10679
10680
10681
10682 && (it->sp == 0
10683 || (STRINGP (it->string)
10684 && (it->current.overlay_string_index < 0
10685 || (it->current.overlay_string_index >= 0
10686 && it->current.overlay_string_index
10687 >= it->n_overlay_strings - 1))
10688 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10689 {
10690 reached = 9;
10691 goto out;
10692 }
10693 break;
10694
10695 case MOVE_LINE_CONTINUED:
10696 max_current_x = it->last_visible_x;
10697
10698
10699
10700
10701 if (it->c == '\t')
10702 {
10703 it->continuation_lines_width += it->last_visible_x;
10704
10705
10706
10707 if (it->current_x != it->last_visible_x
10708 && (op & MOVE_TO_VPOS)
10709 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10710 {
10711 line_start_x = it->current_x + it->pixel_width
10712 - it->last_visible_x;
10713 if (FRAME_WINDOW_P (it->f))
10714 {
10715 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10716 struct font *face_font = face->font;
10717
10718
10719
10720
10721
10722
10723
10724 eassert (face_font);
10725 if (face_font)
10726 {
10727 if (line_start_x < face_font->space_width)
10728 line_start_x
10729 += it->tab_width * face_font->space_width;
10730 }
10731 }
10732 set_iterator_to_next (it, false);
10733 }
10734 }
10735 else
10736 {
10737
10738
10739
10740
10741
10742
10743
10744
10745 if (IT_CHARPOS (*it) == orig_charpos
10746 && it->method == orig_method
10747 && orig_method == GET_FROM_BUFFER)
10748 set_iterator_to_next (it, false);
10749 it->continuation_lines_width += it->current_x;
10750 }
10751 break;
10752
10753 default:
10754 emacs_abort ();
10755 }
10756
10757
10758 it->current_x = line_start_x;
10759 line_start_x = 0;
10760 it->hpos = 0;
10761 it->line_number_produced_p = false;
10762 it->current_y += it->max_ascent + it->max_descent;
10763 ++it->vpos;
10764 last_height = it->max_ascent + it->max_descent;
10765 it->max_ascent = it->max_descent = 0;
10766 }
10767
10768 out:
10769
10770
10771
10772
10773
10774
10775 if (!FRAME_WINDOW_P (it->f)
10776 && op & MOVE_TO_POS
10777 && IT_CHARPOS (*it) == to_charpos
10778 && it->what == IT_CHARACTER
10779 && it->nglyphs > 1
10780 && it->line_wrap == WINDOW_WRAP
10781 && it->current_x == it->last_visible_x - 1
10782 && it->c != '\n'
10783 && it->c != '\t'
10784 && it->w->window_end_valid
10785 && it->vpos < it->w->window_end_vpos)
10786 {
10787 it->continuation_lines_width += it->current_x;
10788 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10789 it->current_y += it->max_ascent + it->max_descent;
10790 ++it->vpos;
10791 last_height = it->max_ascent + it->max_descent;
10792 }
10793
10794 if (backup_data)
10795 bidi_unshelve_cache (backup_data, true);
10796
10797 move_trace ("move_it_to: reached %d\n", reached);
10798
10799 return max_current_x;
10800 }
10801
10802
10803
10804
10805
10806
10807
10808
10809
10810
10811
10812 void
10813 move_it_vertically_backward (struct it *it, int dy)
10814 {
10815 int nlines, h;
10816 struct it it2, it3;
10817 void *it2data = NULL, *it3data = NULL;
10818 ptrdiff_t start_pos;
10819 int nchars_per_row
10820 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10821 ptrdiff_t pos_limit;
10822
10823 move_further_back:
10824 eassert (dy >= 0);
10825
10826 start_pos = IT_CHARPOS (*it);
10827
10828
10829 nlines = max (1, dy / default_line_pixel_height (it->w));
10830 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10831 pos_limit = BEGV;
10832 else
10833 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10834
10835
10836
10837
10838 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10839 back_to_previous_visible_line_start (it);
10840
10841
10842
10843
10844
10845 reseat_1 (it, it->current.pos, true);
10846
10847
10848 it->current_x = it->hpos = 0;
10849
10850 it->continuation_lines_width = 0;
10851
10852
10853
10854
10855
10856 SAVE_IT (it2, *it, it2data);
10857 it2.max_ascent = it2.max_descent = 0;
10858 do
10859 {
10860 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10861 MOVE_TO_POS | MOVE_TO_VPOS);
10862 }
10863 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10864
10865
10866
10867
10868
10869
10870 || (it2.method == GET_FROM_STRING
10871 && IT_CHARPOS (it2) == start_pos
10872 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10873 eassert (IT_CHARPOS (*it) >= BEGV);
10874 SAVE_IT (it3, it2, it3data);
10875
10876 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10877 eassert (IT_CHARPOS (*it) >= BEGV);
10878
10879
10880 h = it2.current_y - it->current_y;
10881
10882 nlines = it2.vpos - it->vpos;
10883
10884
10885
10886 it->vpos -= nlines;
10887 it->current_y -= h;
10888
10889 if (dy == 0)
10890 {
10891
10892
10893
10894 RESTORE_IT (it, it, it2data);
10895 if (nlines > 0)
10896 move_it_by_lines (it, nlines);
10897
10898
10899
10900
10901
10902
10903 if (it->bidi_p
10904 && !it->continuation_lines_width
10905 && !STRINGP (it->string)
10906 && IT_CHARPOS (*it) > BEGV
10907 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10908 {
10909 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10910
10911 dec_both (&cp, &bp);
10912 SET_WITH_NARROWED_BEGV (it, cp,
10913 find_newline_no_quit (cp, bp, -1, NULL),
10914 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10915 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10916 }
10917 bidi_unshelve_cache (it3data, true);
10918 }
10919 else
10920 {
10921
10922
10923 int target_y = it->current_y + h - dy;
10924 int y0 = it3.current_y;
10925 int y1;
10926 int line_height;
10927
10928 RESTORE_IT (&it3, &it3, it3data);
10929 y1 = line_bottom_y (&it3);
10930 line_height = y1 - y0;
10931 RESTORE_IT (it, it, it2data);
10932
10933
10934 if (target_y < it->current_y
10935
10936
10937
10938
10939 && (it->current_y - target_y
10940 > min (window_box_height (it->w), line_height * 2 / 3))
10941 && IT_CHARPOS (*it) > BEGV)
10942 {
10943 move_trace (" not far enough -> move_vert %d\n",
10944 target_y - it->current_y);
10945 dy = it->current_y - target_y;
10946 goto move_further_back;
10947 }
10948 else if (target_y >= it->current_y + line_height
10949 && IT_CHARPOS (*it) < ZV)
10950 {
10951
10952
10953
10954
10955
10956
10957
10958
10959 if (!FRAME_WINDOW_P (it->f))
10960 move_it_vertically (it, target_y - it->current_y);
10961 else
10962 {
10963 struct text_pos last_pos;
10964 int last_y, last_vpos;
10965 do
10966 {
10967 last_pos = it->current.pos;
10968 last_y = it->current_y;
10969 last_vpos = it->vpos;
10970 move_it_by_lines (it, 1);
10971 }
10972 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10973 if (it->current_y > target_y)
10974 {
10975 reseat (it, last_pos, true);
10976 it->current_y = last_y;
10977 it->vpos = last_vpos;
10978 }
10979 }
10980 }
10981 }
10982 }
10983
10984
10985
10986
10987
10988
10989 void
10990 move_it_vertically (struct it *it, int dy)
10991 {
10992 if (dy <= 0)
10993 move_it_vertically_backward (it, -dy);
10994 else
10995 {
10996 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
10997 move_it_to (it, ZV, -1, it->current_y + dy, -1,
10998 MOVE_TO_POS | MOVE_TO_Y);
10999 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
11000
11001
11002
11003 if (IT_CHARPOS (*it) == ZV
11004 && ZV > BEGV
11005 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
11006 move_it_by_lines (it, 0);
11007 }
11008 }
11009
11010
11011
11012
11013 void
11014 move_it_past_eol (struct it *it)
11015 {
11016 enum move_it_result rc;
11017
11018 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
11019 if (rc == MOVE_NEWLINE_OR_CR)
11020 set_iterator_to_next (it, false);
11021 }
11022
11023
11024
11025
11026
11027
11028
11029
11030
11031
11032 void
11033 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
11034 {
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044
11045
11046
11047
11048
11049
11050
11051
11052 if (dvpos == 0)
11053 {
11054
11055 move_it_vertically_backward (it, 0);
11056
11057 last_height = 0;
11058 }
11059 else if (dvpos > 0)
11060 {
11061 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
11062 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11063 {
11064
11065
11066
11067
11068
11069
11070
11071
11072
11073
11074 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11075 -1, -1, -1, MOVE_TO_POS);
11076 }
11077 }
11078 else
11079 {
11080 struct it it2;
11081 void *it2data = NULL;
11082 ptrdiff_t start_charpos, orig_charpos, i;
11083 int nchars_per_row
11084 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11085 bool hit_pos_limit = false;
11086 ptrdiff_t pos_limit;
11087
11088
11089
11090
11091 dvpos += it->vpos;
11092 orig_charpos = IT_CHARPOS (*it);
11093 move_it_vertically_backward (it, 0);
11094 dvpos -= it->vpos;
11095
11096
11097
11098 start_charpos = IT_CHARPOS (*it);
11099 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11100 pos_limit = BEGV;
11101 else
11102 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11103
11104 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11105 back_to_previous_visible_line_start (it);
11106 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11107 hit_pos_limit = true;
11108 reseat (it, it->current.pos, true);
11109
11110
11111 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11112 {
11113
11114 dvpos += it->vpos;
11115 move_it_vertically_backward (it, 0);
11116 dvpos -= it->vpos;
11117 if (IT_POS_VALID_AFTER_MOVE_P (it))
11118 break;
11119
11120
11121 back_to_previous_visible_line_start (it);
11122 reseat (it, it->current.pos, true);
11123 dvpos--;
11124 }
11125
11126 it->current_x = it->hpos = 0;
11127
11128
11129
11130 SAVE_IT (it2, *it, it2data);
11131 it2.vpos = it2.current_y = 0;
11132 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11133 it->vpos -= it2.vpos;
11134 it->current_y -= it2.current_y;
11135 it->current_x = it->hpos = 0;
11136
11137
11138 if (it2.vpos > -dvpos)
11139 {
11140 int delta = it2.vpos + dvpos;
11141
11142 RESTORE_IT (&it2, &it2, it2data);
11143 SAVE_IT (it2, *it, it2data);
11144 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11145
11146
11147 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11148 RESTORE_IT (it, &it2, it2data);
11149 else
11150 bidi_unshelve_cache (it2data, true);
11151 }
11152 else if (hit_pos_limit && pos_limit > BEGV
11153 && dvpos < 0 && it2.vpos < -dvpos)
11154 {
11155
11156
11157
11158
11159
11160
11161
11162
11163 dvpos += it2.vpos;
11164 RESTORE_IT (it, it, it2data);
11165 for (i = -dvpos; i > 0; --i)
11166 {
11167 back_to_previous_visible_line_start (it);
11168 it->vpos--;
11169 }
11170 reseat_1 (it, it->current.pos, true);
11171 }
11172 else
11173 RESTORE_IT (it, it, it2data);
11174 }
11175 }
11176
11177 int
11178 partial_line_height (struct it *it_origin)
11179 {
11180
11181
11182
11183
11184
11185 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11186 && it_origin->line_wrap == TRUNCATE)
11187 return 0;
11188
11189 int partial_height;
11190 void *it_data = NULL;
11191 struct it it;
11192 SAVE_IT (it, *it_origin, it_data);
11193 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11194 MOVE_TO_POS | MOVE_TO_Y);
11195 if (it.what == IT_EOB)
11196 {
11197 int vis_height = it.last_visible_y - it.current_y;
11198 int height = it.ascent + it.descent;
11199 partial_height = (vis_height < height) ? vis_height : 0;
11200 }
11201 else
11202 {
11203 int last_line_y = it.current_y;
11204 move_it_by_lines (&it, 1);
11205 partial_height = (it.current_y > it.last_visible_y)
11206 ? it.last_visible_y - last_line_y : 0;
11207 }
11208 RESTORE_IT (&it, &it, it_data);
11209 return partial_height;
11210 }
11211
11212
11213
11214
11215
11216
11217
11218
11219
11220
11221
11222
11223 static enum move_it_result
11224 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11225 {
11226 ptrdiff_t nl_bytepos;
11227 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11228 1, &nl_bytepos);
11229 struct text_pos new_pos;
11230 enum move_it_result move_result;
11231
11232 if (nl_pos - IT_CHARPOS (*it) > nchars)
11233 {
11234 SET_TEXT_POS (new_pos,
11235 IT_CHARPOS (*it) + nchars,
11236 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11237 move_result = MOVE_X_REACHED;
11238 }
11239 else
11240 {
11241 if (nl_bytepos < ZV_BYTE
11242 || (nl_bytepos > BEGV_BYTE
11243 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11244 {
11245 nl_pos--;
11246 nl_bytepos--;
11247 move_result = MOVE_NEWLINE_OR_CR;
11248 }
11249 else
11250 move_result = MOVE_POS_MATCH_OR_ZV;
11251 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11252 }
11253 reseat (it, new_pos, false);
11254 return move_result;
11255 }
11256
11257
11258
11259 bool
11260 in_display_vector_p (struct it *it)
11261 {
11262 return (it->method == GET_FROM_DISPLAY_VECTOR
11263 && it->current.dpvec_index > 0
11264 && it->dpvec + it->current.dpvec_index != it->dpend);
11265 }
11266
11267
11268
11269
11270
11271 static Lisp_Object
11272 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11273 Lisp_Object x_limit, Lisp_Object y_limit,
11274 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11275 {
11276 struct window *w = decode_live_window (window);
11277 struct it it;
11278 ptrdiff_t start, end, bpos;
11279 struct text_pos startp;
11280 void *itdata = NULL;
11281 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11282
11283 if (NILP (from))
11284 {
11285 start = BEGV;
11286 bpos = BEGV_BYTE;
11287 }
11288 else if (EQ (from, Qt))
11289 {
11290 start = BEGV;
11291 bpos = BEGV_BYTE;
11292 while (bpos < ZV_BYTE)
11293 {
11294 c = FETCH_BYTE (bpos);
11295 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11296 break;
11297 inc_both (&start, &bpos);
11298 }
11299 while (bpos > BEGV_BYTE)
11300 {
11301 dec_both (&start, &bpos);
11302 c = FETCH_BYTE (bpos);
11303 if (!(c == ' ' || c == '\t'))
11304 break;
11305 }
11306 }
11307 else if (CONSP (from))
11308 {
11309 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11310 bpos = CHAR_TO_BYTE (start);
11311 CHECK_FIXNUM (XCDR (from));
11312 vertical_offset = XFIXNUM (XCDR (from));
11313 }
11314 else
11315 {
11316 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11317 bpos = CHAR_TO_BYTE (start);
11318 }
11319
11320 SET_TEXT_POS (startp, start, bpos);
11321
11322 if (NILP (to))
11323 end = ZV;
11324 else if (EQ (to, Qt))
11325 {
11326 end = ZV;
11327 bpos = ZV_BYTE;
11328 while (bpos > BEGV_BYTE)
11329 {
11330 dec_both (&end, &bpos);
11331 c = FETCH_BYTE (bpos);
11332 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11333 {
11334 inc_both (&end, &bpos);
11335 break;
11336 }
11337 }
11338 while (bpos < ZV_BYTE)
11339 {
11340 c = fetch_char_advance (&end, &bpos);
11341 if (!(c == ' ' || c == '\t'))
11342 break;
11343 }
11344 }
11345 else
11346 end = clip_to_bounds (start, fix_position (to), ZV);
11347
11348 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11349 max_x = XFIXNUM (x_limit);
11350 else if (!NILP (x_limit))
11351 max_x = INT_MAX;
11352
11353 if (NILP (y_limit))
11354 max_y = INT_MAX;
11355 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11356 max_y = XFIXNUM (y_limit);
11357
11358 itdata = bidi_shelve_cache ();
11359
11360 start_display (&it, w, startp);
11361
11362 int start_y = it.current_y;
11363
11364
11365
11366
11367
11368
11369
11370 it.bidi_p = false;
11371
11372 int start_x;
11373 if (vertical_offset != 0)
11374 {
11375 int last_y;
11376 it.current_y = 0;
11377
11378 move_it_by_lines (&it, 0);
11379
11380
11381
11382
11383
11384 if (vertical_offset < 0)
11385 {
11386 while (it.current_y > vertical_offset)
11387 {
11388 last_y = it.current_y;
11389 move_it_vertically_backward (&it,
11390 (abs (vertical_offset)
11391 + it.current_y));
11392
11393 if (it.current_y == last_y)
11394 break;
11395 }
11396 }
11397 else
11398 {
11399 move_it_vertically (&it, vertical_offset);
11400 }
11401
11402 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11403 + WINDOW_HEADER_LINE_HEIGHT (w));
11404 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11405 start_y = it.current_y;
11406 start_x = it.current_x;
11407 }
11408 else
11409 {
11410
11411
11412
11413 reseat_at_previous_visible_line_start (&it);
11414 it.current_x = it.hpos = 0;
11415 if (IT_CHARPOS (it) != start)
11416 {
11417 void *it1data = NULL;
11418 struct it it1;
11419
11420 SAVE_IT (it1, it, it1data);
11421 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11422
11423
11424
11425
11426
11427 if (IT_CHARPOS (it) > start && start > BEGV)
11428 {
11429 ptrdiff_t it1pos = IT_CHARPOS (it1);
11430 int it1_x = it1.current_x;
11431
11432 RESTORE_IT (&it, &it1, it1data);
11433
11434
11435
11436
11437
11438 if (start - 1 > it1pos)
11439 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11440 else
11441 move_it_in_display_line (&it, start, it1_x + 1,
11442 MOVE_TO_POS | MOVE_TO_X);
11443 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11444 start_x = it.current_x;
11445
11446
11447
11448 if (IT_CHARPOS (it) == start - 1)
11449 start_x += it.pixel_width;
11450 }
11451 else
11452 {
11453 start_x = it.current_x;
11454 bidi_unshelve_cache (it1data, true);
11455 }
11456 }
11457 else
11458 start_x = it.current_x;
11459 }
11460
11461
11462 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11463 int to_x = -1;
11464 it.current_y = start_y;
11465
11466
11467 if (FETCH_BYTE (start) == '\n')
11468 it.current_x = 0;
11469 if (!NILP (x_limit))
11470 {
11471 it.last_visible_x = max_x;
11472
11473
11474
11475 move_op |= MOVE_TO_X;
11476 to_x = INT_MAX;
11477 }
11478
11479 void *it2data = NULL;
11480 struct it it2;
11481 SAVE_IT (it2, it, it2data);
11482
11483 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11484
11485
11486
11487
11488
11489 if (IT_CHARPOS (it) > end)
11490 {
11491 end--;
11492 RESTORE_IT (&it, &it2, it2data);
11493 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11494
11495
11496
11497 if (IT_CHARPOS (it) == end)
11498 {
11499 x += it.pixel_width;
11500
11501
11502 if (!NILP (ignore_line_at_end))
11503 doff = (max (it.max_ascent, it.ascent)
11504 + max (it.max_descent, it.descent));
11505 else
11506 {
11507 it.max_ascent = max (it.max_ascent, it.ascent);
11508 it.max_descent = max (it.max_descent, it.descent);
11509 }
11510 }
11511 }
11512 else
11513 bidi_unshelve_cache (it2data, true);
11514
11515 if (!NILP (x_limit))
11516 {
11517
11518 if (x > max_x)
11519 x = max_x;
11520 }
11521
11522
11523
11524
11525 if (it.current_y > start_y)
11526 start_x = 0;
11527
11528
11529
11530 if (!NILP (ignore_line_at_end))
11531 y = (it.current_y + doff
11532 - WINDOW_TAB_LINE_HEIGHT (w)
11533 - WINDOW_HEADER_LINE_HEIGHT (w));
11534 else
11535 y = (it.current_y + it.max_ascent + it.max_descent + doff
11536 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11537
11538
11539 if (y > max_y)
11540 y = max_y;
11541
11542 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11543 && window_wants_tab_line (w))
11544
11545 {
11546 Lisp_Object window_tab_line_format
11547 = window_parameter (w, Qtab_line_format);
11548
11549 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11550 NILP (window_tab_line_format)
11551 ? BVAR (current_buffer, tab_line_format)
11552 : window_tab_line_format);
11553 }
11554
11555 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11556 && window_wants_header_line (w))
11557 {
11558 Lisp_Object window_header_line_format
11559 = window_parameter (w, Qheader_line_format);
11560
11561 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11562 NILP (window_header_line_format)
11563 ? BVAR (current_buffer, header_line_format)
11564 : window_header_line_format);
11565 }
11566
11567 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11568 && window_wants_mode_line (w))
11569 {
11570 Lisp_Object window_mode_line_format
11571 = window_parameter (w, Qmode_line_format);
11572
11573 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11574 NILP (window_mode_line_format)
11575 ? BVAR (current_buffer, mode_line_format)
11576 : window_mode_line_format);
11577 }
11578
11579 bidi_unshelve_cache (itdata, false);
11580
11581 return (!vertical_offset
11582 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11583 : list3i (x - start_x, y, start));
11584 }
11585
11586 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11587 doc:
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
11624
11625
11626
11627
11628
11629
11630
11631
11632
11633
11634
11635
11636
11637
11638
11639
11640
11641
11642 )
11643 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11644 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11645 {
11646 struct window *w = decode_live_window (window);
11647 struct buffer *b = XBUFFER (w->contents);
11648 struct buffer *old_b = NULL;
11649 Lisp_Object value;
11650
11651 if (b != current_buffer)
11652 {
11653 old_b = current_buffer;
11654 set_buffer_internal_1 (b);
11655 }
11656
11657 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11658 ignore_line_at_end);
11659
11660 if (old_b)
11661 set_buffer_internal_1 (old_b);
11662
11663 return value;
11664 }
11665
11666 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11667 doc:
11668
11669
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680 )
11681 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11682 Lisp_Object y_limit)
11683 {
11684 struct window *w = decode_live_window (window);
11685 struct buffer *b = (NILP (buffer_or_name)
11686 ? current_buffer
11687 : XBUFFER (Fget_buffer (buffer_or_name)));
11688 Lisp_Object buffer, value;
11689 specpdl_ref count = SPECPDL_INDEX ();
11690
11691 XSETBUFFER (buffer, b);
11692
11693
11694
11695
11696 record_unwind_protect (unwind_with_echo_area_buffer,
11697 with_echo_area_buffer_unwind_data (w));
11698
11699 set_buffer_internal_1 (b);
11700
11701 ptrdiff_t base_line_pos = w->base_line_pos;
11702 int end_valid = w->window_end_valid;
11703 if (!EQ (buffer, w->contents))
11704 {
11705 wset_buffer (w, buffer);
11706 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11707 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11708 }
11709
11710 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11711 Qnil);
11712
11713 unbind_to (count, Qnil);
11714
11715
11716
11717 w->base_line_pos = base_line_pos;
11718 w->window_end_valid = end_valid;
11719
11720 return value;
11721 }
11722
11723
11724 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11725 Sdisplay__line_is_continued_p, 0, 0, 0,
11726 doc: )
11727 (void)
11728 {
11729 struct buffer *oldb = current_buffer;
11730 struct window *w = XWINDOW (selected_window);
11731 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11732
11733 set_buffer_internal_1 (XBUFFER (w->contents));
11734
11735 if (PT < ZV)
11736 {
11737 struct text_pos startpos;
11738 struct it it;
11739 void *itdata;
11740
11741
11742 Lisp_Object opoint = Fpoint_marker ();
11743
11744
11745
11746 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11747 SET_TEXT_POS (startpos, PT, PT_BYTE);
11748 itdata = bidi_shelve_cache ();
11749 start_display (&it, w, startpos);
11750
11751 if (it.line_wrap != TRUNCATE)
11752 {
11753 it.glyph_row = NULL;
11754 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11755 }
11756 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11757 bidi_unshelve_cache (itdata, false);
11758 }
11759 set_buffer_internal_1 (oldb);
11760
11761 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11762 }
11763
11764
11765
11766
11767
11768
11769
11770
11771 static ptrdiff_t
11772 format_nargs (char const *format)
11773 {
11774 ptrdiff_t nargs = 0;
11775 for (char const *p = format; (p = strchr (p, '%')); p++)
11776 if (p[1] == '%')
11777 p++;
11778 else
11779 nargs++;
11780 return nargs;
11781 }
11782
11783
11784
11785
11786 void
11787 add_to_log (const char *format, ...)
11788 {
11789 va_list ap;
11790 va_start (ap, format);
11791 vadd_to_log (format, ap);
11792 va_end (ap);
11793 }
11794
11795 void
11796 vadd_to_log (char const *format, va_list ap)
11797 {
11798 ptrdiff_t form_nargs = format_nargs (format);
11799 ptrdiff_t nargs = 1 + form_nargs;
11800 Lisp_Object args[10];
11801 eassert (nargs <= ARRAYELTS (args));
11802 AUTO_STRING (args0, format);
11803 args[0] = args0;
11804 for (ptrdiff_t i = 1; i <= nargs; i++)
11805 args[i] = va_arg (ap, Lisp_Object);
11806 Lisp_Object msg = Qnil;
11807 msg = Fformat_message (nargs, args);
11808
11809 ptrdiff_t len = SBYTES (msg) + 1;
11810 USE_SAFE_ALLOCA;
11811 char *buffer = SAFE_ALLOCA (len);
11812 memcpy (buffer, SDATA (msg), len);
11813
11814 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11815 SAFE_FREE ();
11816 }
11817
11818
11819
11820
11821 void
11822 message_log_maybe_newline (void)
11823 {
11824 if (message_log_need_newline)
11825 message_dolog ("", 0, true, false);
11826 }
11827
11828
11829
11830
11831
11832
11833
11834
11835
11836
11837
11838 void
11839 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11840 {
11841 const unsigned char *msg = (const unsigned char *) m;
11842
11843 if (!NILP (Vmemory_full))
11844 return;
11845
11846 if (!NILP (Vmessage_log_max))
11847 {
11848 struct buffer *oldbuf;
11849 Lisp_Object oldpoint, oldbegv, oldzv;
11850 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11851 ptrdiff_t point_at_end = 0;
11852 ptrdiff_t zv_at_end = 0;
11853 Lisp_Object old_deactivate_mark;
11854
11855 old_deactivate_mark = Vdeactivate_mark;
11856 oldbuf = current_buffer;
11857
11858
11859
11860 if (! STRINGP (Vmessages_buffer_name))
11861 Vmessages_buffer_name = build_string ("*Messages*");
11862
11863
11864 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11865 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11866 if (newbuffer
11867 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11868 call0 (intern ("messages-buffer-mode"));
11869
11870 bset_undo_list (current_buffer, Qt);
11871 bset_cache_long_scans (current_buffer, Qnil);
11872
11873 oldpoint = message_dolog_marker1;
11874 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11875 oldbegv = message_dolog_marker2;
11876 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11877 oldzv = message_dolog_marker3;
11878 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11879
11880 if (PT == Z)
11881 point_at_end = 1;
11882 if (ZV == Z)
11883 zv_at_end = 1;
11884
11885 BEGV = BEG;
11886 BEGV_BYTE = BEG_BYTE;
11887 ZV = Z;
11888 ZV_BYTE = Z_BYTE;
11889 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11890
11891
11892
11893 if (multibyte
11894 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11895 {
11896
11897
11898 for (ptrdiff_t i = 0; i < nbytes; )
11899 {
11900 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11901 char work = CHAR_TO_BYTE8 (c);
11902 insert_1_both (&work, 1, 1, true, false, false);
11903 i += char_bytes;
11904 }
11905 }
11906 else if (! multibyte
11907 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11908 {
11909
11910
11911 for (ptrdiff_t i = 0; i < nbytes; i++)
11912 {
11913 int c = make_char_multibyte (msg[i]);
11914 unsigned char str[MAX_MULTIBYTE_LENGTH];
11915 int char_bytes = CHAR_STRING (c, str);
11916 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11917 }
11918 }
11919 else if (nbytes)
11920 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11921 true, false, false);
11922
11923 if (nlflag)
11924 {
11925 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11926 intmax_t dups;
11927
11928
11929
11930
11931
11932 specpdl_ref count = SPECPDL_INDEX ();
11933 specbind (Qinhibit_modification_hooks, Qt);
11934
11935 insert_1_both ("\n", 1, 1, true, false, false);
11936
11937 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11938 this_bol = PT;
11939 this_bol_byte = PT_BYTE;
11940
11941
11942
11943 if (this_bol > BEG)
11944 {
11945 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11946 prev_bol = PT;
11947 prev_bol_byte = PT_BYTE;
11948
11949 dups = message_log_check_duplicate (prev_bol_byte,
11950 this_bol_byte);
11951 if (dups)
11952 {
11953 del_range_both (prev_bol, prev_bol_byte,
11954 this_bol, this_bol_byte, false);
11955 if (dups > 1)
11956 {
11957 char dupstr[sizeof " [ times]"
11958 + INT_STRLEN_BOUND (dups)];
11959
11960
11961
11962 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11963 dups);
11964 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11965 insert_1_both (dupstr, duplen, duplen,
11966 true, false, true);
11967 }
11968 }
11969 }
11970
11971
11972
11973
11974
11975 if (FIXNATP (Vmessage_log_max))
11976 {
11977 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11978 -XFIXNAT (Vmessage_log_max) - 1, false);
11979 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11980 }
11981
11982 unbind_to (count, Qnil);
11983 }
11984 BEGV = marker_position (oldbegv);
11985 BEGV_BYTE = marker_byte_position (oldbegv);
11986
11987 if (zv_at_end)
11988 {
11989 ZV = Z;
11990 ZV_BYTE = Z_BYTE;
11991 }
11992 else
11993 {
11994 ZV = marker_position (oldzv);
11995 ZV_BYTE = marker_byte_position (oldzv);
11996 }
11997
11998 if (point_at_end)
11999 TEMP_SET_PT_BOTH (Z, Z_BYTE);
12000 else
12001
12002
12003 TEMP_SET_PT_BOTH (marker_position (oldpoint),
12004 marker_byte_position (oldpoint));
12005
12006 unchain_marker (XMARKER (oldpoint));
12007 unchain_marker (XMARKER (oldbegv));
12008 unchain_marker (XMARKER (oldzv));
12009
12010
12011
12012
12013
12014
12015
12016 windows_or_buffers_changed = old_windows_or_buffers_changed;
12017 bset_redisplay (current_buffer);
12018
12019 set_buffer_internal (oldbuf);
12020
12021 message_log_need_newline = !nlflag;
12022 Vdeactivate_mark = old_deactivate_mark;
12023 }
12024 }
12025
12026
12027
12028
12029
12030
12031
12032
12033 static intmax_t
12034 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
12035 {
12036 ptrdiff_t i;
12037 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
12038 bool seen_dots = false;
12039 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
12040 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
12041
12042 for (i = 0; i < len; i++)
12043 {
12044 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
12045 seen_dots = true;
12046 if (p1[i] != p2[i])
12047 return seen_dots;
12048 }
12049 p1 += len;
12050 if (*p1 == '\n')
12051 return 2;
12052 if (*p1++ == ' ' && *p1++ == '[')
12053 {
12054 char *pend;
12055 intmax_t n = strtoimax ((char *) p1, &pend, 10);
12056 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
12057 return n + 1;
12058 }
12059 return 0;
12060 }
12061
12062
12063
12064
12065
12066
12067
12068
12069
12070 void
12071 message3 (Lisp_Object m)
12072 {
12073 clear_message (true, true);
12074 cancel_echoing ();
12075
12076
12077 message_log_maybe_newline ();
12078 if (STRINGP (m))
12079 {
12080 ptrdiff_t nbytes = SBYTES (m);
12081 bool multibyte = STRING_MULTIBYTE (m);
12082 char *buffer;
12083 USE_SAFE_ALLOCA;
12084 SAFE_ALLOCA_STRING (buffer, m);
12085 message_dolog (buffer, nbytes, true, multibyte);
12086 SAFE_FREE ();
12087 }
12088 if (! inhibit_message)
12089 message3_nolog (m);
12090 }
12091
12092
12093
12094 static void
12095 message_to_stderr (Lisp_Object m)
12096 {
12097 if (noninteractive_need_newline)
12098 {
12099 noninteractive_need_newline = false;
12100 errputc ('\n');
12101 }
12102 if (STRINGP (m))
12103 {
12104 Lisp_Object coding_system = Vlocale_coding_system;
12105 Lisp_Object s;
12106
12107 if (!NILP (Vcoding_system_for_write))
12108 coding_system = Vcoding_system_for_write;
12109 if (!NILP (coding_system))
12110 s = code_convert_string_norecord (m, coding_system, true);
12111 else
12112 s = m;
12113
12114 errwrite (SDATA (s), SBYTES (s));
12115 }
12116 if (STRINGP (m) || !cursor_in_echo_area)
12117 errputc ('\n');
12118 }
12119
12120
12121
12122
12123
12124
12125 void
12126 message3_nolog (Lisp_Object m)
12127 {
12128 struct frame *sf = SELECTED_FRAME ();
12129
12130 if (FRAME_INITIAL_P (sf))
12131 message_to_stderr (m);
12132
12133
12134
12135 else if (INTERACTIVE && sf->glyphs_initialized_p)
12136 {
12137
12138
12139 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12140 Lisp_Object frame = XWINDOW (mini_window)->frame;
12141 struct frame *f = XFRAME (frame);
12142
12143 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12144 Fmake_frame_visible (frame);
12145
12146 if (STRINGP (m) && SCHARS (m) > 0)
12147 {
12148 set_message (m);
12149 if (minibuffer_auto_raise)
12150 Fraise_frame (frame);
12151
12152
12153 echo_message_buffer = Qnil;
12154 }
12155 else
12156 clear_message (true, true);
12157
12158 do_pending_window_change (false);
12159 echo_area_display (true);
12160 do_pending_window_change (false);
12161 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12162 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12163 }
12164 }
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175 void
12176 message1 (const char *m)
12177 {
12178 message3 (m ? build_unibyte_string (m) : Qnil);
12179 }
12180
12181
12182
12183
12184 void
12185 message1_nolog (const char *m)
12186 {
12187 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12188 }
12189
12190
12191
12192
12193 void
12194 message_with_string (const char *m, Lisp_Object string, bool log)
12195 {
12196 CHECK_STRING (string);
12197
12198 bool need_message;
12199 if (noninteractive)
12200 need_message = !!m;
12201 else if (!INTERACTIVE)
12202 need_message = false;
12203 else
12204 {
12205
12206
12207
12208 Lisp_Object mini_window;
12209 struct frame *f, *sf = SELECTED_FRAME ();
12210
12211
12212
12213 mini_window = FRAME_MINIBUF_WINDOW (sf);
12214 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12215
12216
12217
12218
12219 need_message = f->glyphs_initialized_p;
12220 }
12221
12222 if (need_message)
12223 {
12224 AUTO_STRING (fmt, m);
12225 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12226
12227 if (noninteractive)
12228 message_to_stderr (msg);
12229 else
12230 {
12231 if (log)
12232 message3 (msg);
12233 else
12234 message3_nolog (msg);
12235
12236
12237
12238 message_buf_print = false;
12239 }
12240 }
12241 }
12242
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12255 vmessage (const char *m, va_list ap)
12256 {
12257 if (noninteractive)
12258 {
12259 if (m)
12260 {
12261 if (noninteractive_need_newline)
12262 putc ('\n', stderr);
12263 noninteractive_need_newline = false;
12264 vfprintf (stderr, m, ap);
12265 if (!cursor_in_echo_area)
12266 putc ('\n', stderr);
12267 fflush (stderr);
12268 }
12269 }
12270 else if (INTERACTIVE)
12271 {
12272
12273
12274
12275 Lisp_Object mini_window;
12276 struct frame *f, *sf = SELECTED_FRAME ();
12277
12278
12279
12280 mini_window = FRAME_MINIBUF_WINDOW (sf);
12281 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12282
12283
12284
12285
12286 if (f->glyphs_initialized_p)
12287 {
12288 if (m)
12289 {
12290 ptrdiff_t len;
12291 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12292 USE_SAFE_ALLOCA;
12293 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12294
12295 len = doprnt (message_buf, maxsize, m, 0, ap);
12296
12297 message3 (make_string (message_buf, len));
12298 SAFE_FREE ();
12299 }
12300 else
12301 message1 (0);
12302
12303
12304
12305 message_buf_print = false;
12306 }
12307 }
12308 }
12309
12310
12311 void
12312 message (const char *m, ...)
12313 {
12314 va_list ap;
12315 va_start (ap, m);
12316 vmessage (m, ap);
12317 va_end (ap);
12318 }
12319
12320
12321
12322
12323
12324
12325 void
12326 update_echo_area (void)
12327 {
12328 if (!NILP (echo_area_buffer[0]))
12329 {
12330 Lisp_Object string;
12331 string = Fcurrent_message ();
12332 message3 (string);
12333 }
12334 }
12335
12336
12337
12338
12339
12340 static void
12341 ensure_echo_area_buffers (void)
12342 {
12343 for (int i = 0; i < 2; i++)
12344 if (!BUFFERP (echo_buffer[i])
12345 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12346 {
12347 Lisp_Object old_buffer = echo_buffer[i];
12348 static char const name_fmt[] = " *Echo Area %d*";
12349 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12350 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12351 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12352 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12353
12354
12355
12356
12357 for (int j = 0; j < 2; j++)
12358 if (EQ (old_buffer, echo_area_buffer[j]))
12359 echo_area_buffer[j] = echo_buffer[i];
12360 }
12361 }
12362
12363
12364
12365
12366
12367
12368
12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380 static bool
12381 with_echo_area_buffer (struct window *w, int which,
12382 bool (*fn) (void *, Lisp_Object),
12383 void *a1, Lisp_Object a2)
12384 {
12385 Lisp_Object buffer;
12386 bool this_one, the_other, clear_buffer_p, rc;
12387 specpdl_ref count = SPECPDL_INDEX ();
12388
12389
12390 ensure_echo_area_buffers ();
12391
12392 clear_buffer_p = false;
12393
12394 if (which == 0)
12395 this_one = false, the_other = true;
12396 else if (which > 0)
12397 this_one = true, the_other = false;
12398 else
12399 {
12400 this_one = false, the_other = true;
12401 clear_buffer_p = true;
12402
12403
12404
12405 if (!NILP (echo_area_buffer[this_one])
12406 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12407 echo_area_buffer[this_one] = Qnil;
12408 }
12409
12410
12411
12412 if (NILP (echo_area_buffer[this_one]))
12413 {
12414 echo_area_buffer[this_one]
12415 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12416 ? echo_buffer[the_other]
12417 : echo_buffer[this_one]);
12418 clear_buffer_p = true;
12419 }
12420
12421 buffer = echo_area_buffer[this_one];
12422
12423
12424
12425 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12426 cancel_echoing ();
12427
12428 record_unwind_protect (unwind_with_echo_area_buffer,
12429 with_echo_area_buffer_unwind_data (w));
12430
12431
12432
12433
12434
12435
12436
12437
12438 set_buffer_internal_1 (XBUFFER (buffer));
12439 if (w)
12440 {
12441 wset_buffer (w, buffer);
12442 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12443 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12444 }
12445
12446 bset_undo_list (current_buffer, Qt);
12447 bset_read_only (current_buffer, Qnil);
12448 specbind (Qinhibit_read_only, Qt);
12449 specbind (Qinhibit_modification_hooks, Qt);
12450
12451 if (clear_buffer_p && Z > BEG)
12452 del_range (BEG, Z);
12453
12454 eassert (BEGV >= BEG);
12455 eassert (ZV <= Z && ZV >= BEGV);
12456
12457 rc = fn (a1, a2);
12458
12459 eassert (BEGV >= BEG);
12460 eassert (ZV <= Z && ZV >= BEGV);
12461
12462 unbind_to (count, Qnil);
12463 return rc;
12464 }
12465
12466
12467
12468
12469
12470 static Lisp_Object
12471 with_echo_area_buffer_unwind_data (struct window *w)
12472 {
12473 int i = 0;
12474 Lisp_Object vector, tmp;
12475
12476
12477
12478 vector = Vwith_echo_area_save_vector;
12479 Vwith_echo_area_save_vector = Qnil;
12480
12481 if (NILP (vector))
12482 vector = make_nil_vector (11);
12483
12484 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12485 ASET (vector, i, Vdeactivate_mark); ++i;
12486 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12487
12488 if (w)
12489 {
12490 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12491 ASET (vector, i, w->contents); ++i;
12492 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12493 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12494 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12495 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12496 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12497 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12498 }
12499 else
12500 {
12501 int end = i + 8;
12502 for (; i < end; ++i)
12503 ASET (vector, i, Qnil);
12504 }
12505
12506 eassert (i == ASIZE (vector));
12507 return vector;
12508 }
12509
12510
12511
12512
12513
12514 static void
12515 unwind_with_echo_area_buffer (Lisp_Object vector)
12516 {
12517 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12518 Vdeactivate_mark = AREF (vector, 1);
12519 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12520
12521 if (WINDOWP (AREF (vector, 3)))
12522 {
12523 struct window *w;
12524 Lisp_Object buffer;
12525
12526 w = XWINDOW (AREF (vector, 3));
12527 buffer = AREF (vector, 4);
12528
12529 wset_buffer (w, buffer);
12530 set_marker_restricted_both (w->pointm, buffer,
12531 XFIXNAT (AREF (vector, 5)),
12532 XFIXNAT (AREF (vector, 6)));
12533 set_marker_restricted_both (w->old_pointm, buffer,
12534 XFIXNAT (AREF (vector, 7)),
12535 XFIXNAT (AREF (vector, 8)));
12536 set_marker_restricted_both (w->start, buffer,
12537 XFIXNAT (AREF (vector, 9)),
12538 XFIXNAT (AREF (vector, 10)));
12539 }
12540
12541 Vwith_echo_area_save_vector = vector;
12542 }
12543
12544
12545
12546
12547
12548 void
12549 setup_echo_area_for_printing (bool multibyte_p)
12550 {
12551
12552 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12553 Fkill_emacs (Qnil, Qnil);
12554
12555 ensure_echo_area_buffers ();
12556
12557 if (!message_buf_print)
12558 {
12559
12560
12561 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12562 echo_area_buffer[0] = echo_buffer[1];
12563 else
12564 echo_area_buffer[0] = echo_buffer[0];
12565
12566
12567 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12568 bset_truncate_lines (current_buffer, Qnil);
12569
12570 if (Z > BEG)
12571 {
12572 specpdl_ref count = SPECPDL_INDEX ();
12573 specbind (Qinhibit_read_only, Qt);
12574
12575 del_range (BEG, Z);
12576 unbind_to (count, Qnil);
12577 }
12578 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12579
12580
12581
12582
12583
12584
12585
12586 if (unibyte_display_via_language_environment
12587 && !multibyte_p
12588 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12589 Fset_buffer_multibyte (Qnil);
12590 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12591 Fset_buffer_multibyte (Qt);
12592
12593
12594 if (minibuffer_auto_raise)
12595 {
12596 struct frame *sf = SELECTED_FRAME ();
12597 Lisp_Object mini_window;
12598 mini_window = FRAME_MINIBUF_WINDOW (sf);
12599 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12600 }
12601
12602 message_log_maybe_newline ();
12603 message_buf_print = true;
12604 }
12605 else
12606 {
12607 if (NILP (echo_area_buffer[0]))
12608 {
12609 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12610 echo_area_buffer[0] = echo_buffer[1];
12611 else
12612 echo_area_buffer[0] = echo_buffer[0];
12613 }
12614
12615 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12616 {
12617
12618 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12619 bset_truncate_lines (current_buffer, Qnil);
12620 }
12621 }
12622 }
12623
12624
12625
12626
12627
12628
12629
12630 static bool
12631 display_echo_area (struct window *w)
12632 {
12633 bool no_message_p, window_height_changed_p;
12634
12635
12636
12637
12638
12639
12640 specpdl_ref count = inhibit_garbage_collection ();
12641
12642
12643
12644
12645
12646 bool i = display_last_displayed_message_p;
12647
12648
12649
12650 no_message_p = NILP (echo_area_buffer[i]);
12651
12652 window_height_changed_p
12653 = with_echo_area_buffer (w, display_last_displayed_message_p,
12654 display_echo_area_1, w, Qnil);
12655
12656 if (no_message_p)
12657 echo_area_buffer[i] = Qnil;
12658
12659 unbind_to (count, Qnil);
12660 return window_height_changed_p;
12661 }
12662
12663
12664
12665
12666
12667
12668
12669
12670 static bool
12671 display_echo_area_1 (void *a1, Lisp_Object a2)
12672 {
12673 struct window *w = a1;
12674 Lisp_Object window;
12675 struct text_pos start;
12676
12677
12678
12679
12680 forget_escape_and_glyphless_faces ();
12681
12682
12683
12684
12685 bool window_height_changed_p = resize_mini_window (w, false);
12686
12687
12688 SET_TEXT_POS_FROM_MARKER (start, w->start);
12689
12690
12691 clear_glyph_matrix (w->desired_matrix);
12692 XSETWINDOW (window, w);
12693 void *itdata = bidi_shelve_cache ();
12694 try_window (window, start, 0);
12695 bidi_unshelve_cache (itdata, false);
12696
12697 return window_height_changed_p;
12698 }
12699
12700
12701
12702
12703
12704
12705 void
12706 resize_echo_area_exactly (void)
12707 {
12708 if (BUFFERP (echo_area_buffer[0])
12709 && WINDOWP (echo_area_window))
12710 {
12711 struct window *w = XWINDOW (echo_area_window);
12712 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12713 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12714 w, resize_exactly);
12715 if (resized_p)
12716 {
12717 windows_or_buffers_changed = 42;
12718 update_mode_lines = 30;
12719 redisplay_internal ();
12720 }
12721 }
12722 }
12723
12724
12725
12726
12727
12728
12729
12730
12731 static bool
12732 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12733 {
12734 return resize_mini_window (a1, !NILP (exactly));
12735 }
12736
12737
12738
12739
12740
12741
12742
12743
12744
12745
12746
12747
12748
12749 bool
12750 resize_mini_window (struct window *w, bool exact_p)
12751 {
12752 struct frame *f = XFRAME (w->frame);
12753 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12754
12755 eassert (MINI_WINDOW_P (w));
12756
12757
12758
12759
12760
12761
12762
12763 if (!NILP (Vinhibit_redisplay))
12764 return false;
12765
12766
12767 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12768 set_marker_both (w->start, w->contents,
12769 BUF_BEGV (XBUFFER (w->contents)),
12770 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12771
12772
12773 if ((NILP (Vresize_mini_windows)
12774 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12775 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12776 return false;
12777
12778 if (FRAME_MINIBUF_ONLY_P (f))
12779 {
12780 if (!NILP (resize_mini_frames))
12781 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12782 }
12783 else
12784 {
12785 struct it it;
12786 int unit = FRAME_LINE_HEIGHT (f);
12787 int height, max_height;
12788 struct text_pos start;
12789 struct buffer *old_current_buffer = NULL;
12790 int windows_height = FRAME_INNER_HEIGHT (f);
12791
12792 if (current_buffer != XBUFFER (w->contents))
12793 {
12794 old_current_buffer = current_buffer;
12795 set_buffer_internal (XBUFFER (w->contents));
12796 }
12797
12798 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12799
12800
12801 if (FLOATP (Vmax_mini_window_height))
12802 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12803 else if (FIXNUMP (Vmax_mini_window_height))
12804 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12805 else
12806 max_height = windows_height / 4;
12807
12808
12809 max_height = clip_to_bounds (unit, max_height, windows_height);
12810
12811
12812 last_height = 0;
12813 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12814
12815
12816 if (it.max_ascent == 0 && it.max_descent == 0)
12817 {
12818 height = it.current_y;
12819
12820
12821
12822
12823
12824 if (!(it.line_wrap == TRUNCATE
12825 && it.current_x <= it.first_visible_x
12826 && ZV_BYTE > 1
12827 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12828 height += last_height;
12829 }
12830 else
12831 height = it.current_y + it.max_ascent + it.max_descent;
12832 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12833
12834
12835 if (height > max_height)
12836 {
12837 height = (max_height / unit) * unit;
12838 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12839 {
12840 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12841 move_it_vertically_backward (&it, height - unit);
12842
12843
12844
12845
12846
12847
12848
12849
12850
12851 move_it_by_lines (&it, 0);
12852 start = it.current.pos;
12853
12854
12855 w->start_at_line_beg = false;
12856 SET_MARKER_FROM_TEXT_POS (w->start, start);
12857 }
12858 }
12859 else
12860 {
12861 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12862 SET_MARKER_FROM_TEXT_POS (w->start, start);
12863 }
12864
12865 if (EQ (Vresize_mini_windows, Qgrow_only))
12866 {
12867
12868
12869 if (height > old_height)
12870 grow_mini_window (w, height - old_height);
12871 else if (height < old_height && (exact_p || BEGV == ZV))
12872 shrink_mini_window (w);
12873 }
12874 else if (height != old_height)
12875
12876 grow_mini_window (w, height - old_height);
12877
12878 if (old_current_buffer)
12879 set_buffer_internal (old_current_buffer);
12880 }
12881
12882 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12883 }
12884
12885
12886
12887
12888
12889 Lisp_Object
12890 current_message (void)
12891 {
12892 Lisp_Object msg;
12893
12894 if (!BUFFERP (echo_area_buffer[0]))
12895 msg = Qnil;
12896 else
12897 {
12898 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12899 if (NILP (msg))
12900 echo_area_buffer[0] = Qnil;
12901 }
12902
12903 return msg;
12904 }
12905
12906
12907 static bool
12908 current_message_1 (void *a1, Lisp_Object a2)
12909 {
12910 Lisp_Object *msg = a1;
12911
12912 if (Z > BEG)
12913 *msg = make_buffer_string (BEG, Z, true);
12914 else
12915 *msg = Qnil;
12916 return false;
12917 }
12918
12919
12920
12921
12922
12923
12924
12925 bool
12926 push_message (void)
12927 {
12928 Lisp_Object msg = current_message ();
12929 Vmessage_stack = Fcons (msg, Vmessage_stack);
12930 return STRINGP (msg);
12931 }
12932
12933
12934
12935
12936 void
12937 restore_message (void)
12938 {
12939 eassert (CONSP (Vmessage_stack));
12940 message3_nolog (XCAR (Vmessage_stack));
12941 }
12942
12943
12944
12945
12946 void
12947 pop_message_unwind (void)
12948 {
12949
12950 eassert (CONSP (Vmessage_stack));
12951 Vmessage_stack = XCDR (Vmessage_stack);
12952 }
12953
12954
12955
12956
12957
12958
12959 void
12960 check_message_stack (void)
12961 {
12962 if (!NILP (Vmessage_stack))
12963 emacs_abort ();
12964 }
12965
12966 void
12967 clear_message_stack (void)
12968 {
12969 Vmessage_stack = Qnil;
12970 }
12971
12972
12973
12974
12975 void
12976 truncate_echo_area (ptrdiff_t nchars)
12977 {
12978 if (nchars == 0)
12979 echo_area_buffer[0] = Qnil;
12980 else if (!noninteractive
12981 && INTERACTIVE
12982 && !NILP (echo_area_buffer[0]))
12983 {
12984 struct frame *sf = SELECTED_FRAME ();
12985
12986
12987
12988 if (sf->glyphs_initialized_p)
12989 with_echo_area_buffer (0, 0, truncate_message_1,
12990 (void *) (intptr_t) nchars, Qnil);
12991 }
12992 }
12993
12994
12995
12996
12997
12998 static bool
12999 truncate_message_1 (void *a1, Lisp_Object a2)
13000 {
13001 intptr_t nchars = (intptr_t) a1;
13002 if (BEG + nchars < Z)
13003 del_range (BEG + nchars, Z);
13004 if (Z == BEG)
13005 echo_area_buffer[0] = Qnil;
13006 return false;
13007 }
13008
13009 extern intptr_t garbage_collection_inhibited;
13010
13011
13012
13013 static void
13014 set_message (Lisp_Object string)
13015 {
13016 Lisp_Object message = Qnil;
13017
13018 eassert (STRINGP (string));
13019
13020 if (FUNCTIONP (Vset_message_function)
13021
13022
13023
13024 && !garbage_collection_inhibited)
13025 {
13026 specpdl_ref count = SPECPDL_INDEX ();
13027 specbind (Qinhibit_quit, Qt);
13028 message = safe_call1 (Vset_message_function, string);
13029 unbind_to (count, Qnil);
13030
13031 if (STRINGP (message))
13032 {
13033 string = message;
13034 message = Qnil;
13035 }
13036 }
13037
13038 if (NILP (message))
13039 {
13040 message_enable_multibyte = STRING_MULTIBYTE (string);
13041
13042 with_echo_area_buffer (0, -1, set_message_1, 0, string);
13043 message_buf_print = false;
13044 help_echo_showing_p = false;
13045 }
13046
13047 if (STRINGP (Vdebug_on_message)
13048 && STRINGP (string)
13049 && fast_string_match (Vdebug_on_message, string) >= 0)
13050 call_debugger (list2 (Qerror, string));
13051 }
13052
13053
13054
13055
13056
13057
13058 static bool
13059 set_message_1 (void *a1, Lisp_Object string)
13060 {
13061 eassert (STRINGP (string));
13062
13063
13064
13065
13066
13067
13068 if (!message_enable_multibyte
13069 && unibyte_display_via_language_environment
13070 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13071 Fset_buffer_multibyte (Qnil);
13072 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13073 Fset_buffer_multibyte (Qt);
13074
13075 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13076 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13077 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13078
13079
13080 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13081
13082
13083
13084
13085 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13086
13087 return false;
13088 }
13089
13090
13091
13092
13093
13094 void
13095 clear_message (bool current_p, bool last_displayed_p)
13096 {
13097 Lisp_Object preserve = Qnil;
13098
13099 if (current_p)
13100 {
13101 if (FUNCTIONP (Vclear_message_function)
13102
13103 && !garbage_collection_inhibited)
13104 {
13105 specpdl_ref count = SPECPDL_INDEX ();
13106 specbind (Qinhibit_quit, Qt);
13107 preserve = safe_call (1, Vclear_message_function);
13108 unbind_to (count, Qnil);
13109 }
13110
13111 if (!EQ (preserve, Qdont_clear_message))
13112 {
13113 echo_area_buffer[0] = Qnil;
13114 message_cleared_p = true;
13115 }
13116 }
13117
13118 if (last_displayed_p)
13119 echo_area_buffer[1] = Qnil;
13120
13121 message_buf_print = false;
13122 }
13123
13124
13125
13126
13127
13128
13129
13130
13131
13132
13133 static void
13134 clear_garbaged_frames (void)
13135 {
13136 if (frame_garbaged)
13137 {
13138 Lisp_Object tail, frame;
13139 struct frame *sf = SELECTED_FRAME ();
13140
13141 FOR_EACH_FRAME (tail, frame)
13142 {
13143 struct frame *f = XFRAME (frame);
13144
13145 if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
13146 {
13147 if (f->resized_p
13148
13149
13150
13151
13152
13153 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13154 redraw_frame (f);
13155 else
13156 clear_current_matrices (f);
13157
13158 #ifdef HAVE_WINDOW_SYSTEM
13159 if (FRAME_WINDOW_P (f)
13160 && FRAME_RIF (f)->clear_under_internal_border)
13161 FRAME_RIF (f)->clear_under_internal_border (f);
13162 #endif
13163 fset_redisplay (f);
13164 f->garbaged = false;
13165 f->resized_p = false;
13166 }
13167 }
13168
13169 frame_garbaged = false;
13170 }
13171 }
13172
13173
13174
13175
13176
13177 static void
13178 echo_area_display (bool update_frame_p)
13179 {
13180 Lisp_Object mini_window;
13181 struct window *w;
13182 struct frame *f;
13183 bool window_height_changed_p = false;
13184 struct frame *sf = SELECTED_FRAME ();
13185
13186 mini_window = FRAME_MINIBUF_WINDOW (sf);
13187 if (NILP (mini_window))
13188 return;
13189
13190 w = XWINDOW (mini_window);
13191 f = XFRAME (WINDOW_FRAME (w));
13192
13193
13194 if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
13195 return;
13196
13197 #ifdef HAVE_WINDOW_SYSTEM
13198
13199
13200
13201 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13202 return;
13203 #endif
13204
13205
13206 clear_garbaged_frames ();
13207
13208 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13209 {
13210 echo_area_window = mini_window;
13211 window_height_changed_p = display_echo_area (w);
13212 w->must_be_updated_p = true;
13213
13214
13215
13216
13217
13218 if (update_frame_p && !redisplaying_p)
13219 {
13220 int n = 0;
13221
13222
13223
13224
13225
13226
13227 if (!display_completed)
13228 {
13229 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13230
13231 #ifdef HAVE_WINDOW_SYSTEM
13232 if (FRAME_WINDOW_P (f)
13233 && FRAME_RIF (f)->clear_under_internal_border)
13234 FRAME_RIF (f)->clear_under_internal_border (f);
13235 #endif
13236 }
13237
13238 if (window_height_changed_p
13239
13240
13241 && !NILP (Vrun_hooks))
13242 {
13243
13244
13245
13246 specpdl_ref count = SPECPDL_INDEX ();
13247 specbind (Qredisplay_dont_pause, Qt);
13248 fset_redisplay (f);
13249 redisplay_internal ();
13250 unbind_to (count, Qnil);
13251 }
13252 else if (FRAME_WINDOW_P (f) && n == 0)
13253 {
13254
13255
13256
13257 update_single_window (w);
13258 flush_frame (f);
13259 }
13260 else
13261 update_frame (f, true, true);
13262
13263
13264
13265
13266 if (cursor_in_echo_area)
13267 wset_redisplay (XWINDOW (mini_window));
13268 }
13269 }
13270 else if (!EQ (mini_window, selected_window))
13271 wset_redisplay (XWINDOW (mini_window));
13272
13273
13274 echo_area_buffer[1] = echo_area_buffer[0];
13275
13276 echo_message_buffer = Qnil;
13277
13278
13279
13280
13281 if (EQ (mini_window, selected_window))
13282 CHARPOS (this_line_start_pos) = 0;
13283
13284 if (window_height_changed_p)
13285 {
13286 fset_redisplay (f);
13287
13288
13289
13290
13291
13292 clear_garbaged_frames ();
13293 }
13294 }
13295
13296
13297
13298 static bool
13299 window_buffer_changed (struct window *w)
13300 {
13301 struct buffer *b = XBUFFER (w->contents);
13302
13303 eassert (BUFFER_LIVE_P (b));
13304
13305 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13306 }
13307
13308
13309
13310 static bool
13311 mode_line_update_needed (struct window *w)
13312 {
13313 return (w->column_number_displayed != -1
13314 && !(PT == w->last_point && !window_outdated (w))
13315 && (w->column_number_displayed != current_column ()));
13316 }
13317
13318
13319
13320
13321 static bool
13322 window_frozen_p (struct window *w)
13323 {
13324 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13325 {
13326 Lisp_Object window;
13327
13328 XSETWINDOW (window, w);
13329 if (MINI_WINDOW_P (w))
13330 return false;
13331 else if (EQ (window, selected_window))
13332 return false;
13333 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13334 && EQ (window, Vminibuf_scroll_window))
13335
13336 return false;
13337 else
13338 return true;
13339 }
13340 return false;
13341 }
13342
13343
13344
13345
13346
13347
13348
13349
13350
13351 static char *mode_line_noprop_buf;
13352
13353
13354
13355 static char *mode_line_noprop_buf_end;
13356 static char *mode_line_noprop_ptr;
13357
13358 #define MODE_LINE_NOPROP_LEN(start) \
13359 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13360
13361 static enum {
13362 MODE_LINE_DISPLAY = 0,
13363 MODE_LINE_TITLE,
13364 MODE_LINE_NOPROP,
13365 MODE_LINE_STRING
13366 } mode_line_target;
13367
13368
13369
13370 static Lisp_Object mode_line_proptrans_alist;
13371
13372
13373 static Lisp_Object mode_line_string_list;
13374
13375
13376 static Lisp_Object mode_line_string_face;
13377 static Lisp_Object mode_line_string_face_prop;
13378
13379
13380
13381
13382 static Lisp_Object Vmode_line_unwind_vector;
13383
13384 static Lisp_Object
13385 format_mode_line_unwind_data (struct frame *target_frame,
13386 struct buffer *obuf,
13387 Lisp_Object owin,
13388 bool save_proptrans)
13389 {
13390 Lisp_Object vector, tmp;
13391
13392
13393
13394 vector = Vmode_line_unwind_vector;
13395 Vmode_line_unwind_vector = Qnil;
13396
13397 if (NILP (vector))
13398 vector = make_nil_vector (12);
13399
13400 ASET (vector, 0, make_fixnum (mode_line_target));
13401 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13402 ASET (vector, 2, mode_line_string_list);
13403 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13404 ASET (vector, 4, mode_line_string_face);
13405 ASET (vector, 5, mode_line_string_face_prop);
13406
13407 if (obuf)
13408 XSETBUFFER (tmp, obuf);
13409 else
13410 tmp = Qnil;
13411 ASET (vector, 6, tmp);
13412 ASET (vector, 7, owin);
13413 if (target_frame)
13414 {
13415 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13416 struct buffer *b = XBUFFER (buffer);
13417 struct buffer *cb = current_buffer;
13418
13419
13420
13421
13422 ASET (vector, 8, target_frame->selected_window);
13423 if (FRAME_TERMCAP_P (target_frame))
13424 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13425
13426
13427
13428
13429 ASET (vector, 10, buffer);
13430 current_buffer = b;
13431 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13432 current_buffer = cb;
13433 }
13434
13435 return vector;
13436 }
13437
13438 static void
13439 unwind_format_mode_line (Lisp_Object vector)
13440 {
13441 Lisp_Object old_window = AREF (vector, 7);
13442 Lisp_Object target_frame_window = AREF (vector, 8);
13443 Lisp_Object old_top_frame = AREF (vector, 9);
13444
13445 mode_line_target = XFIXNUM (AREF (vector, 0));
13446 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13447 mode_line_string_list = AREF (vector, 2);
13448 if (! EQ (AREF (vector, 3), Qt))
13449 mode_line_proptrans_alist = AREF (vector, 3);
13450 mode_line_string_face = AREF (vector, 4);
13451 mode_line_string_face_prop = AREF (vector, 5);
13452
13453
13454 if (WINDOW_LIVE_P (old_window))
13455 {
13456
13457
13458
13459 if (WINDOW_LIVE_P (target_frame_window))
13460 {
13461 Lisp_Object frame
13462 = WINDOW_FRAME (XWINDOW (target_frame_window));
13463
13464 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13465 Fselect_window (target_frame_window, Qt);
13466
13467 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13468
13469
13470 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13471 Fselect_frame (old_top_frame, Qt);
13472 }
13473
13474 Fselect_window (old_window, Qt);
13475
13476
13477
13478
13479 if (WINDOW_LIVE_P (target_frame_window))
13480 {
13481 Lisp_Object buffer = AREF (vector, 10);
13482
13483 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13484 {
13485 struct buffer *cb = current_buffer;
13486
13487 current_buffer = XBUFFER (buffer);
13488 set_point_from_marker (AREF (vector, 11));
13489 ASET (vector, 11, Qnil);
13490 current_buffer = cb;
13491 }
13492 }
13493 }
13494
13495 if (!NILP (AREF (vector, 6)))
13496 {
13497 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13498 ASET (vector, 6, Qnil);
13499 }
13500
13501 Vmode_line_unwind_vector = vector;
13502 }
13503
13504
13505
13506
13507
13508 static void
13509 store_mode_line_noprop_char (char c)
13510 {
13511
13512
13513 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13514 {
13515 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13516 ptrdiff_t size = len;
13517 mode_line_noprop_buf =
13518 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13519 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13520 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13521 }
13522
13523 *mode_line_noprop_ptr++ = c;
13524 }
13525
13526
13527
13528
13529
13530
13531
13532
13533
13534
13535 static int
13536 store_mode_line_noprop (const char *string, int field_width, int precision)
13537 {
13538 const unsigned char *str = (const unsigned char *) string;
13539 int n = 0;
13540 ptrdiff_t dummy, nbytes;
13541
13542
13543 nbytes = strlen (string);
13544 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13545 while (nbytes--)
13546 store_mode_line_noprop_char (*str++);
13547
13548
13549 while (field_width > 0
13550 && n < field_width)
13551 {
13552 store_mode_line_noprop_char (' ');
13553 ++n;
13554 }
13555
13556 return n;
13557 }
13558
13559
13560
13561
13562
13563 #ifdef HAVE_WINDOW_SYSTEM
13564
13565
13566
13567
13568
13569 void
13570 gui_consider_frame_title (Lisp_Object frame)
13571 {
13572 struct frame *f = XFRAME (frame);
13573 Lisp_Object format_data;
13574
13575 if ((FRAME_WINDOW_P (f)
13576 || FRAME_MINIBUF_ONLY_P (f)
13577 || f->explicit_name)
13578 && !FRAME_TOOLTIP_P (f))
13579 {
13580
13581 Lisp_Object tail, other_frame, fmt;
13582 ptrdiff_t title_start;
13583 char *title;
13584 ptrdiff_t len;
13585 struct it it;
13586 specpdl_ref count = SPECPDL_INDEX ();
13587
13588 FOR_EACH_FRAME (tail, other_frame)
13589 {
13590 struct frame *tf = XFRAME (other_frame);
13591
13592 if (tf != f
13593 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13594 && !FRAME_MINIBUF_ONLY_P (tf)
13595 && !FRAME_PARENT_FRAME (tf)
13596 && !FRAME_TOOLTIP_P (tf)
13597 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13598 break;
13599 }
13600
13601
13602 multiple_frames = CONSP (tail);
13603
13604
13605
13606
13607
13608
13609
13610
13611
13612
13613
13614
13615 specbind (Qinhibit_redisplay, Qt);
13616
13617
13618
13619
13620
13621
13622
13623
13624 format_data = format_mode_line_unwind_data (f, current_buffer,
13625 selected_window,
13626 false);
13627 record_unwind_protect (unwind_format_mode_line, format_data);
13628
13629 Fselect_window (f->selected_window, Qt);
13630 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13631 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13632 ? Vicon_title_format : Vframe_title_format);
13633
13634 mode_line_target = MODE_LINE_TITLE;
13635 title_start = MODE_LINE_NOPROP_LEN (0);
13636 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13637 NULL, DEFAULT_FACE_ID);
13638 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13639 len = MODE_LINE_NOPROP_LEN (title_start);
13640 title = mode_line_noprop_buf + title_start;
13641
13642
13643 ptrdiff_t nchars = 0;
13644 len = str_as_multibyte ((unsigned char *) title,
13645 mode_line_noprop_buf_end - title,
13646 len, &nchars);
13647 unbind_to (count, Qnil);
13648
13649
13650
13651
13652
13653
13654 if ((! STRINGP (f->name)
13655 || SBYTES (f->name) != len
13656 || memcmp (title, SDATA (f->name), len) != 0)
13657 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13658 {
13659 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13660 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13661 }
13662 }
13663 }
13664
13665 #endif
13666
13667
13668
13669
13670
13671
13672
13673 #define REDISPLAY_SOME_P() \
13674 ((windows_or_buffers_changed == 0 \
13675 || windows_or_buffers_changed == REDISPLAY_SOME) \
13676 && (update_mode_lines == 0 \
13677 || update_mode_lines == REDISPLAY_SOME))
13678
13679 static bool
13680 needs_no_redisplay (struct window *w)
13681 {
13682 struct buffer *buffer = XBUFFER (w->contents);
13683 struct frame *f = XFRAME (w->frame);
13684 return (REDISPLAY_SOME_P ()
13685 && !w->redisplay
13686 && !w->update_mode_line
13687 && !f->face_change
13688 && !f->redisplay
13689 && !buffer->text->redisplay
13690 && window_point (w) == w->last_point);
13691 }
13692
13693
13694
13695
13696 static void
13697 prepare_menu_bars (void)
13698 {
13699 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13700 bool some_windows = REDISPLAY_SOME_P ();
13701
13702 if (FUNCTIONP (Vpre_redisplay_function))
13703 {
13704 Lisp_Object windows = all_windows ? Qt : Qnil;
13705 if (all_windows && some_windows)
13706 {
13707 Lisp_Object ws = window_list ();
13708 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13709 {
13710 Lisp_Object this = XCAR (ws);
13711 struct window *w = XWINDOW (this);
13712
13713
13714 if (!needs_no_redisplay (w))
13715 windows = Fcons (this, windows);
13716 }
13717 }
13718 safe__call1 (true, Vpre_redisplay_function, windows);
13719 }
13720
13721
13722
13723
13724 #ifdef HAVE_WINDOW_SYSTEM
13725 if (all_windows)
13726 {
13727 Lisp_Object tail, frame;
13728
13729 FOR_EACH_FRAME (tail, frame)
13730 {
13731 struct frame *f = XFRAME (frame);
13732 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13733 if (some_windows
13734 && !f->redisplay
13735 && !w->redisplay
13736 && !XBUFFER (w->contents)->text->redisplay)
13737 continue;
13738
13739 if (!FRAME_TOOLTIP_P (f)
13740 && (FRAME_ICONIFIED_P (f)
13741 || FRAME_VISIBLE_P (f) == 1
13742
13743
13744
13745
13746
13747
13748
13749
13750
13751 || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
13752 gui_consider_frame_title (frame);
13753 }
13754 }
13755 #endif
13756
13757
13758
13759
13760 if (all_windows)
13761 {
13762 Lisp_Object tail, frame;
13763 specpdl_ref count = SPECPDL_INDEX ();
13764
13765
13766 bool menu_bar_hooks_run = false;
13767
13768 record_unwind_save_match_data ();
13769
13770 FOR_EACH_FRAME (tail, frame)
13771 {
13772 struct frame *f = XFRAME (frame);
13773 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13774
13775
13776 if (FRAME_TOOLTIP_P (f))
13777 continue;
13778
13779 if (some_windows
13780 && !f->redisplay
13781 && !w->redisplay
13782 && !XBUFFER (w->contents)->text->redisplay)
13783 continue;
13784
13785 if (!FRAME_PARENT_FRAME (f))
13786 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13787
13788 update_tab_bar (f, false);
13789 #ifdef HAVE_WINDOW_SYSTEM
13790 update_tool_bar (f, false);
13791 #endif
13792 }
13793
13794 unbind_to (count, Qnil);
13795 }
13796 else
13797 {
13798 struct frame *sf = SELECTED_FRAME ();
13799
13800 if (!FRAME_PARENT_FRAME (sf))
13801 update_menu_bar (sf, true, false);
13802
13803 update_tab_bar (sf, true);
13804 #ifdef HAVE_WINDOW_SYSTEM
13805 update_tool_bar (sf, true);
13806 #endif
13807 }
13808 }
13809
13810
13811
13812
13813
13814
13815
13816
13817
13818
13819
13820
13821
13822 static bool
13823 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13824 {
13825 Lisp_Object window;
13826 struct window *w;
13827
13828
13829
13830
13831 if (inhibit_menubar_update)
13832 return hooks_run;
13833
13834 window = FRAME_SELECTED_WINDOW (f);
13835 w = XWINDOW (window);
13836
13837 if (FRAME_WINDOW_P (f)
13838 ?
13839 #ifdef HAVE_EXT_MENU_BAR
13840 FRAME_EXTERNAL_MENU_BAR (f)
13841 #else
13842 FRAME_MENU_BAR_LINES (f) > 0
13843 #endif
13844 : FRAME_MENU_BAR_LINES (f) > 0)
13845 {
13846
13847
13848
13849
13850
13851
13852
13853 if (windows_or_buffers_changed
13854
13855
13856 || update_mode_lines
13857 || window_buffer_changed (w))
13858 {
13859 struct buffer *prev = current_buffer;
13860 specpdl_ref count = SPECPDL_INDEX ();
13861
13862 specbind (Qinhibit_menubar_update, Qt);
13863
13864 set_buffer_internal_1 (XBUFFER (w->contents));
13865 if (save_match_data)
13866 record_unwind_save_match_data ();
13867 if (NILP (Voverriding_local_map_menu_flag))
13868 {
13869 specbind (Qoverriding_terminal_local_map, Qnil);
13870 specbind (Qoverriding_local_map, Qnil);
13871 }
13872
13873 if (!hooks_run)
13874 {
13875
13876 safe_run_hooks (Qactivate_menubar_hook);
13877
13878
13879
13880 safe_run_hooks (Qmenu_bar_update_hook);
13881
13882 hooks_run = true;
13883 }
13884
13885 XSETFRAME (Vmenu_updating_frame, f);
13886 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13887
13888
13889 #ifdef HAVE_EXT_MENU_BAR
13890 if (FRAME_WINDOW_P (f))
13891 {
13892 #if defined (HAVE_NS)
13893
13894
13895 if (f == SELECTED_FRAME ())
13896 #endif
13897 set_frame_menubar (f, false);
13898 }
13899 else
13900
13901
13902 w->update_mode_line = true;
13903 #else
13904
13905
13906 w->update_mode_line = true;
13907 #endif
13908
13909 unbind_to (count, Qnil);
13910 set_buffer_internal_1 (prev);
13911 }
13912 }
13913
13914 return hooks_run;
13915 }
13916
13917
13918
13919
13920
13921
13922
13923
13924
13925
13926
13927
13928 static void
13929 restore_selected_window (Lisp_Object window)
13930 {
13931 if (WINDOW_LIVE_P (window))
13932
13933
13934 {
13935 selected_window = window;
13936 selected_frame = XWINDOW (window)->frame;
13937 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13938 }
13939 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13940
13941
13942 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13943 else
13944
13945
13946
13947 {
13948 Lisp_Object tail;
13949 Lisp_Object frame UNINIT;
13950
13951 FOR_EACH_FRAME (tail, frame)
13952 {
13953 struct frame *f = XFRAME (frame);
13954
13955 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13956 {
13957 selected_frame = frame;
13958 selected_window = FRAME_SELECTED_WINDOW (f);
13959
13960 return;
13961 }
13962 }
13963
13964
13965 emacs_abort ();
13966 }
13967 }
13968
13969
13970 static void
13971 restore_frame_selected_window (Lisp_Object window)
13972 {
13973 if (WINDOW_LIVE_P (window))
13974
13975
13976
13977 {
13978 Lisp_Object frame = XWINDOW (window)->frame;
13979
13980 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13981 if (EQ (frame, selected_frame))
13982 selected_window = window;
13983 }
13984 }
13985
13986
13987
13988
13989
13990
13991 static void
13992 update_tab_bar (struct frame *f, bool save_match_data)
13993 {
13994 bool do_update = false;
13995
13996 #ifdef HAVE_WINDOW_SYSTEM
13997 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
13998 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
13999 do_update = true;
14000 }
14001 else
14002 #endif
14003 if (FRAME_TAB_BAR_LINES (f) > 0)
14004 do_update = true;
14005
14006 if (do_update)
14007 {
14008 Lisp_Object window;
14009 struct window *w;
14010
14011 window = FRAME_SELECTED_WINDOW (f);
14012 w = XWINDOW (window);
14013
14014
14015
14016
14017
14018
14019
14020
14021 if (windows_or_buffers_changed
14022 || w->update_mode_line
14023 || update_mode_lines
14024 || window_buffer_changed (w))
14025 {
14026 struct buffer *prev = current_buffer;
14027 specpdl_ref count = SPECPDL_INDEX ();
14028 Lisp_Object new_tab_bar;
14029 int new_n_tab_bar;
14030
14031
14032
14033
14034 set_buffer_internal_1 (XBUFFER (w->contents));
14035
14036
14037 if (save_match_data)
14038 record_unwind_save_match_data ();
14039
14040
14041 if (NILP (Voverriding_local_map_menu_flag))
14042 {
14043 specbind (Qoverriding_terminal_local_map, Qnil);
14044 specbind (Qoverriding_local_map, Qnil);
14045 }
14046
14047
14048
14049
14050
14051 eassert (EQ (selected_window,
14052
14053
14054 XFRAME (selected_frame)->selected_window));
14055 #ifdef HAVE_WINDOW_SYSTEM
14056 Lisp_Object frame;
14057 record_unwind_protect (restore_selected_window, selected_window);
14058 XSETFRAME (frame, f);
14059 selected_frame = frame;
14060 selected_window = FRAME_SELECTED_WINDOW (f);
14061 #endif
14062
14063
14064 new_tab_bar
14065 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
14066 &new_n_tab_bar);
14067
14068
14069 if (new_n_tab_bar != f->n_tab_bar_items
14070 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14071 {
14072
14073
14074
14075 block_input ();
14076 fset_tab_bar_items (f, new_tab_bar);
14077 f->n_tab_bar_items = new_n_tab_bar;
14078 w->update_mode_line = true;
14079 unblock_input ();
14080 }
14081
14082 unbind_to (count, Qnil);
14083 set_buffer_internal_1 (prev);
14084 }
14085 }
14086 }
14087
14088
14089
14090
14091
14092
14093
14094
14095
14096
14097
14098 static void
14099 display_tab_bar (struct window *w)
14100 {
14101 struct frame *f = XFRAME (WINDOW_FRAME (w));
14102 struct it it;
14103 Lisp_Object items;
14104 int i;
14105
14106
14107 #ifdef HAVE_NTGUI
14108 if (FRAME_W32_P (f))
14109 return;
14110 #endif
14111 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14112 if (FRAME_X_P (f))
14113 return;
14114 #endif
14115
14116 #ifdef HAVE_NS
14117 if (FRAME_NS_P (f))
14118 return;
14119 #endif
14120
14121 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14122 eassert (!FRAME_WINDOW_P (f));
14123 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14124 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14125 TAB_BAR_FACE_ID);
14126 it.first_visible_x = 0;
14127 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14128 #elif defined (HAVE_X_WINDOWS)
14129 if (FRAME_WINDOW_P (f))
14130 {
14131
14132
14133 struct window *tab_w;
14134 tab_w = XWINDOW (f->tab_bar_window);
14135 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14136 TAB_BAR_FACE_ID);
14137 it.first_visible_x = 0;
14138 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14139 }
14140 else
14141 #endif
14142 {
14143
14144
14145 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14146 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14147 TAB_BAR_FACE_ID);
14148 it.first_visible_x = 0;
14149 it.last_visible_x = FRAME_COLS (f);
14150 }
14151
14152
14153
14154
14155 it.paragraph_embedding = L2R;
14156
14157
14158 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14159 {
14160 struct glyph_row *row = it.glyph_row + i;
14161 clear_glyph_row (row);
14162 row->enabled_p = true;
14163 row->full_width_p = true;
14164 row->reversed_p = false;
14165 }
14166
14167
14168 items = it.f->tab_bar_items;
14169 int j;
14170 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14171 {
14172 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14173
14174
14175 if (NILP (string))
14176 break;
14177
14178 if (it.current_x < it.last_visible_x)
14179 display_string (NULL, string, Qnil, 0, 0, &it,
14180 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14181 }
14182
14183
14184 if (it.current_x < it.last_visible_x)
14185 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14186
14187
14188 compute_line_metrics (&it);
14189 }
14190
14191 #ifdef HAVE_WINDOW_SYSTEM
14192
14193
14194
14195
14196
14197 static void
14198 build_desired_tab_bar_string (struct frame *f)
14199 {
14200 int i;
14201 Lisp_Object caption;
14202
14203 caption = Qnil;
14204
14205
14206 fset_desired_tab_bar_string (f, build_string (""));
14207
14208
14209
14210
14211 for (i = 0; i < f->n_tab_bar_items; ++i)
14212 {
14213 #define PROP(IDX) \
14214 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14215
14216 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14217
14218
14219
14220
14221
14222 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14223
14224 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14225 props, caption);
14226
14227 f->desired_tab_bar_string =
14228 concat2 (f->desired_tab_bar_string, caption);
14229
14230 #undef PROP
14231 }
14232 }
14233
14234
14235
14236
14237
14238
14239
14240
14241
14242
14243
14244
14245
14246
14247 static void
14248 display_tab_bar_line (struct it *it, int height)
14249 {
14250 struct glyph_row *row = it->glyph_row;
14251 int max_x = it->last_visible_x;
14252 struct glyph *last;
14253
14254
14255 clear_glyph_row (row);
14256 row->enabled_p = true;
14257 row->y = it->current_y;
14258
14259
14260
14261 it->start_of_box_run_p = true;
14262
14263 bool enough = false;
14264 while (it->current_x < max_x)
14265 {
14266 int x, n_glyphs_before, i, nglyphs;
14267 struct it it_before;
14268
14269
14270 if (!get_next_display_element (it))
14271 {
14272
14273 if (height < 0 && !it->hpos)
14274 return;
14275 break;
14276 }
14277
14278
14279 n_glyphs_before = row->used[TEXT_AREA];
14280 it_before = *it;
14281
14282 PRODUCE_GLYPHS (it);
14283
14284 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14285 i = 0;
14286 x = it_before.current_x;
14287 while (i < nglyphs)
14288 {
14289 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14290
14291 if (x + glyph->pixel_width > max_x)
14292 {
14293
14294 row->used[TEXT_AREA] = n_glyphs_before;
14295 *it = it_before;
14296
14297
14298
14299 if (n_glyphs_before == 0
14300 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14301 break;
14302 goto out;
14303 }
14304
14305 ++it->hpos;
14306 x += glyph->pixel_width;
14307 ++i;
14308 }
14309
14310 enough = ITERATOR_AT_END_OF_LINE_P (it);
14311 set_iterator_to_next (it, true);
14312
14313
14314 if (enough)
14315 break;
14316 }
14317
14318 out:;
14319
14320 row->displays_text_p = row->used[TEXT_AREA] != 0;
14321
14322
14323
14324
14325
14326
14327
14328 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14329 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14330 it->face_id = DEFAULT_FACE_ID;
14331
14332 extend_face_to_end_of_line (it);
14333 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14334 last->right_box_line_p = true;
14335 if (last == row->glyphs[TEXT_AREA])
14336 last->left_box_line_p = true;
14337
14338
14339 if ((height -= it->max_ascent + it->max_descent) > 0)
14340 {
14341
14342 height %= FRAME_LINE_HEIGHT (it->f);
14343 it->max_ascent += height / 2;
14344 it->max_descent += (height + 1) / 2;
14345 }
14346
14347 compute_line_metrics (it);
14348
14349
14350 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14351 {
14352 row->height = row->phys_height = it->last_visible_y - row->y;
14353 row->visible_height = row->height;
14354 row->ascent = row->phys_ascent = 0;
14355 row->extra_line_spacing = 0;
14356 }
14357
14358 row->full_width_p = true;
14359 row->continued_p = false;
14360 row->truncated_on_left_p = false;
14361 row->truncated_on_right_p = false;
14362
14363 it->current_x = it->hpos = 0;
14364 it->current_y += row->height;
14365 ++it->vpos;
14366 ++it->glyph_row;
14367 }
14368
14369
14370
14371
14372
14373 static int
14374 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14375 {
14376 struct window *w = XWINDOW (f->tab_bar_window);
14377 struct it it;
14378
14379
14380
14381 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14382
14383
14384
14385 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14386 temp_row->reversed_p = false;
14387 it.first_visible_x = 0;
14388 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14389 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14390 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14391 it.paragraph_embedding = L2R;
14392
14393 clear_glyph_row (temp_row);
14394 while (!ITERATOR_AT_END_P (&it))
14395 {
14396 it.glyph_row = temp_row;
14397 display_tab_bar_line (&it, -1);
14398 }
14399 clear_glyph_row (temp_row);
14400
14401
14402 if (n_rows)
14403 *n_rows = it.vpos > 0 ? it.vpos : -1;
14404
14405 if (pixelwise)
14406 return it.current_y;
14407 else
14408 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14409 }
14410
14411 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14412 0, 2, 0,
14413 doc:
14414
14415 )
14416 (Lisp_Object frame, Lisp_Object pixelwise)
14417 {
14418 int height = 0;
14419
14420 struct frame *f = decode_any_frame (frame);
14421
14422 if (WINDOWP (f->tab_bar_window)
14423 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14424 {
14425 update_tab_bar (f, true);
14426 if (f->n_tab_bar_items)
14427 {
14428 build_desired_tab_bar_string (f);
14429 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14430 }
14431 }
14432
14433 return make_fixnum (height);
14434 }
14435
14436
14437
14438
14439 static bool
14440 redisplay_tab_bar (struct frame *f)
14441 {
14442 struct window *w;
14443 struct it it;
14444 struct glyph_row *row;
14445
14446 f->tab_bar_redisplayed = true;
14447
14448
14449
14450
14451
14452 if (!WINDOWP (f->tab_bar_window)
14453 || (w = XWINDOW (f->tab_bar_window),
14454 WINDOW_TOTAL_LINES (w) == 0))
14455 {
14456
14457
14458
14459
14460
14461 f->tab_bar_resized = true;
14462
14463 return false;
14464 }
14465
14466
14467 build_desired_tab_bar_string (f);
14468
14469 int new_nrows;
14470 int new_height = tab_bar_height (f, &new_nrows, true);
14471
14472 if (f->n_tab_bar_rows == 0)
14473 {
14474 f->n_tab_bar_rows = new_nrows;
14475 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14476 frame_default_tab_bar_height = new_height;
14477 }
14478
14479
14480
14481 if (new_nrows > f->n_tab_bar_rows
14482 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14483 && !f->minimize_tab_bar_window_p
14484 && new_height > WINDOW_PIXEL_HEIGHT (w))
14485 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14486 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14487 {
14488 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14489 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14490 if (new_nrows != f->n_tab_bar_rows)
14491 f->n_tab_bar_rows = new_nrows;
14492 clear_glyph_matrix (w->desired_matrix);
14493 f->fonts_changed = true;
14494 return true;
14495 }
14496
14497
14498 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14499 it.first_visible_x = 0;
14500 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14501 row = it.glyph_row;
14502 row->reversed_p = false;
14503 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14504 STRING_MULTIBYTE (f->desired_tab_bar_string));
14505
14506
14507
14508
14509
14510
14511
14512 it.paragraph_embedding = L2R;
14513
14514
14515
14516 if (f->n_tab_bar_rows > 0)
14517 {
14518 int border, rows, height, extra;
14519
14520 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14521 border = XFIXNUM (Vtab_bar_border);
14522 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14523 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14524 else if (EQ (Vtab_bar_border, Qborder_width))
14525 border = f->border_width;
14526 else
14527 border = 0;
14528 if (border < 0)
14529 border = 0;
14530
14531 rows = f->n_tab_bar_rows;
14532 height = max (1, (it.last_visible_y - border) / rows);
14533 extra = it.last_visible_y - border - height * rows;
14534
14535 while (it.current_y < it.last_visible_y)
14536 {
14537 int h = 0;
14538 if (extra > 0 && rows-- > 0)
14539 {
14540 h = (extra + rows - 1) / rows;
14541 extra -= h;
14542 }
14543 display_tab_bar_line (&it, height + h);
14544 }
14545 }
14546 else
14547 {
14548 while (it.current_y < it.last_visible_y)
14549 display_tab_bar_line (&it, 0);
14550 }
14551
14552
14553
14554 w->desired_matrix->no_scrolling_p = true;
14555 w->must_be_updated_p = true;
14556
14557 if (!NILP (Vauto_resize_tab_bars))
14558 {
14559 bool change_height_p = false;
14560
14561
14562
14563 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14564 change_height_p = true;
14565
14566
14567
14568
14569
14570 row = it.glyph_row - 1;
14571
14572
14573
14574
14575 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14576 && row->height >= FRAME_LINE_HEIGHT (f))
14577 change_height_p = true;
14578
14579
14580
14581 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14582 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14583 change_height_p = true;
14584
14585
14586
14587 if (change_height_p)
14588 {
14589 int nrows;
14590 int new_height = tab_bar_height (f, &nrows, true);
14591
14592 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14593 && !f->minimize_tab_bar_window_p)
14594 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14595 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14596 f->minimize_tab_bar_window_p = false;
14597
14598 if (change_height_p)
14599 {
14600 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14601 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14602 frame_default_tab_bar_height = new_height;
14603 clear_glyph_matrix (w->desired_matrix);
14604 f->n_tab_bar_rows = nrows;
14605 f->fonts_changed = true;
14606
14607 return true;
14608 }
14609 }
14610 }
14611
14612 f->minimize_tab_bar_window_p = false;
14613 return false;
14614 }
14615
14616
14617
14618
14619
14620
14621
14622 static bool
14623 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14624 int *prop_idx, bool *close_p)
14625 {
14626 Lisp_Object prop;
14627 ptrdiff_t charpos;
14628
14629
14630
14631
14632 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14633 charpos = max (0, charpos);
14634
14635
14636
14637
14638 prop = Fget_text_property (make_fixnum (charpos),
14639 Qmenu_item, f->current_tab_bar_string);
14640 if (! FIXNUMP (prop))
14641 return false;
14642
14643 *prop_idx = XFIXNUM (prop);
14644
14645 if (close_p)
14646 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14647 Qclose_tab,
14648 f->current_tab_bar_string));
14649
14650 return true;
14651 }
14652
14653
14654
14655
14656
14657
14658
14659
14660
14661
14662
14663
14664
14665
14666
14667
14668
14669
14670
14671
14672
14673 static int
14674 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14675 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14676 {
14677 struct window *w = XWINDOW (f->tab_bar_window);
14678 int area;
14679
14680
14681 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14682 if (*glyph == NULL)
14683 return -1;
14684
14685
14686
14687 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14688 return -1;
14689
14690 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14691 }
14692
14693
14694
14695
14696
14697
14698
14699 int
14700 get_tab_bar_item_kbd (struct frame *f, int x, int y, int *prop_idx,
14701 bool *close_p)
14702 {
14703 struct window *w;
14704 int area, vpos, hpos;
14705 struct glyph *glyph;
14706
14707 w = XWINDOW (f->tab_bar_window);
14708
14709
14710 frame_to_window_pixel_xy (w, &x, &y);
14711
14712
14713 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, 0,
14714 0, &area);
14715 if (glyph == NULL)
14716 return -1;
14717
14718
14719
14720 if (!tab_bar_item_info (f, glyph, prop_idx, close_p))
14721 return -1;
14722
14723 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14724 }
14725
14726
14727
14728
14729
14730
14731
14732 Lisp_Object
14733 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14734 int modifiers)
14735 {
14736 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14737 struct window *w = XWINDOW (f->tab_bar_window);
14738 int hpos, vpos, prop_idx;
14739 bool close_p;
14740 struct glyph *glyph;
14741 Lisp_Object enabled_p;
14742 int ts;
14743
14744 frame_to_window_pixel_xy (w, &x, &y);
14745 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14746 if (ts == -1)
14747 return Fcons (Qtab_bar, Qnil);
14748
14749
14750 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14751 if (NILP (enabled_p))
14752 return Qnil;
14753
14754 if (down_p)
14755 {
14756
14757 if (!NILP (Vmouse_highlight))
14758 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14759 f->last_tab_bar_item = prop_idx;
14760 }
14761 else
14762 {
14763
14764 if (!NILP (Vmouse_highlight))
14765 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14766 f->last_tab_bar_item = -1;
14767 }
14768
14769 Lisp_Object caption =
14770 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14771
14772 AUTO_LIST2 (props, Qmenu_item,
14773 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14774 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14775 close_p ? Qt : Qnil));
14776
14777 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14778 props, caption);
14779
14780 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14781 }
14782
14783
14784
14785
14786
14787
14788 static void
14789 note_tab_bar_highlight (struct frame *f, int x, int y)
14790 {
14791 Lisp_Object window = f->tab_bar_window;
14792 struct window *w = XWINDOW (window);
14793 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14794 int hpos, vpos;
14795 struct glyph *glyph;
14796 struct glyph_row *row;
14797 int i;
14798 Lisp_Object enabled_p;
14799 int prop_idx;
14800 bool close_p;
14801 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14802 int rc;
14803
14804
14805
14806 if (x <= 0 || y <= 0)
14807 {
14808 clear_mouse_face (hlinfo);
14809 return;
14810 }
14811
14812 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14813 if (rc < 0)
14814 {
14815
14816 clear_mouse_face (hlinfo);
14817 return;
14818 }
14819 else if (rc == 0)
14820
14821 goto set_help_echo;
14822
14823 clear_mouse_face (hlinfo);
14824
14825 bool mouse_down_p = false;
14826
14827
14828
14829
14830
14831 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14832 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14833 && f == dpyinfo->last_mouse_frame);
14834
14835 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14836 && f->last_tab_bar_item != -1)
14837 return;
14838 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14839
14840
14841 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14842 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14843 {
14844
14845
14846 row = MATRIX_ROW (w->current_matrix, vpos);
14847 for (i = x = 0; i < hpos; ++i)
14848 x += row->glyphs[TEXT_AREA][i].pixel_width;
14849
14850
14851 hlinfo->mouse_face_beg_col = hpos;
14852 hlinfo->mouse_face_beg_row = vpos;
14853 hlinfo->mouse_face_beg_x = x;
14854 hlinfo->mouse_face_past_end = false;
14855
14856 hlinfo->mouse_face_end_col = hpos + 1;
14857 hlinfo->mouse_face_end_row = vpos;
14858 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14859 hlinfo->mouse_face_window = window;
14860 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14861
14862
14863 show_mouse_face (hlinfo, draw);
14864 }
14865
14866 set_help_echo:
14867
14868
14869
14870 help_echo_object = help_echo_window = Qnil;
14871 help_echo_pos = -1;
14872 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14873 if (NILP (help_echo_string))
14874 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14875 }
14876
14877 #endif
14878
14879
14880 static Lisp_Object
14881 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14882 {
14883 ptrdiff_t clen = 0;
14884
14885 for (int i = 0; i < f->n_tab_bar_items; i++)
14886 {
14887 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14888 + TAB_BAR_ITEM_CAPTION));
14889 if (NILP (caption))
14890 return Qnil;
14891 clen += SCHARS (caption);
14892 if (x < clen)
14893 {
14894 *prop_idx = i;
14895 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14896 - (clen - x)),
14897 Qclose_tab,
14898 caption));
14899 return caption;
14900 }
14901 }
14902 return Qnil;
14903 }
14904
14905
14906
14907
14908
14909
14910 Lisp_Object
14911 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14912 struct input_event *event)
14913 {
14914
14915 if (y < FRAME_MENU_BAR_LINES (f)
14916 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14917 return Qnil;
14918
14919
14920 int prop_idx;
14921 bool close_p;
14922 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14923
14924 if (NILP (caption))
14925 return Qnil;
14926
14927 if (NILP (AREF (f->tab_bar_items,
14928 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14929 return Qnil;
14930
14931 if (down_p)
14932 f->last_tab_bar_item = prop_idx;
14933 else
14934 f->last_tab_bar_item = -1;
14935
14936 caption = Fcopy_sequence (caption);
14937
14938 AUTO_LIST2 (props, Qmenu_item,
14939 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14940 + TAB_BAR_ITEM_KEY),
14941 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14942 + TAB_BAR_ITEM_BINDING),
14943 close_p ? Qt : Qnil));
14944
14945 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14946 props, caption);
14947
14948 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14949 }
14950
14951
14952
14953
14954
14955
14956
14957 #ifdef HAVE_WINDOW_SYSTEM
14958
14959
14960
14961
14962
14963
14964 static void
14965 update_tool_bar (struct frame *f, bool save_match_data)
14966 {
14967 #ifdef HAVE_EXT_TOOL_BAR
14968 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14969 #else
14970 bool do_update = (WINDOWP (f->tool_bar_window)
14971 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14972 #endif
14973
14974 if (do_update)
14975 {
14976 Lisp_Object window;
14977 struct window *w;
14978
14979 window = FRAME_SELECTED_WINDOW (f);
14980 w = XWINDOW (window);
14981
14982
14983
14984
14985
14986
14987
14988
14989 if (windows_or_buffers_changed
14990 || w->update_mode_line
14991 || update_mode_lines
14992 || window_buffer_changed (w))
14993 {
14994 struct buffer *prev = current_buffer;
14995 specpdl_ref count = SPECPDL_INDEX ();
14996 Lisp_Object frame, new_tool_bar;
14997 int new_n_tool_bar;
14998
14999
15000
15001
15002 set_buffer_internal_1 (XBUFFER (w->contents));
15003
15004
15005 if (save_match_data)
15006 record_unwind_save_match_data ();
15007
15008
15009 if (NILP (Voverriding_local_map_menu_flag))
15010 {
15011 specbind (Qoverriding_terminal_local_map, Qnil);
15012 specbind (Qoverriding_local_map, Qnil);
15013 }
15014
15015
15016
15017
15018
15019 eassert (EQ (selected_window,
15020
15021
15022 XFRAME (selected_frame)->selected_window));
15023 record_unwind_protect (restore_selected_window, selected_window);
15024 XSETFRAME (frame, f);
15025 selected_frame = frame;
15026 selected_window = FRAME_SELECTED_WINDOW (f);
15027
15028
15029 new_tool_bar
15030 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
15031 &new_n_tool_bar);
15032
15033
15034 if (new_n_tool_bar != f->n_tool_bar_items
15035 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
15036 {
15037
15038
15039
15040 block_input ();
15041 fset_tool_bar_items (f, new_tool_bar);
15042 f->n_tool_bar_items = new_n_tool_bar;
15043 w->update_mode_line = true;
15044 unblock_input ();
15045 }
15046
15047 unbind_to (count, Qnil);
15048 set_buffer_internal_1 (prev);
15049 }
15050 }
15051 }
15052
15053 #ifndef HAVE_EXT_TOOL_BAR
15054
15055
15056
15057
15058
15059
15060
15061
15062 static void
15063 build_desired_tool_bar_string (struct frame *f)
15064 {
15065 int i, size, size_needed;
15066 Lisp_Object image, plist;
15067
15068 image = plist = Qnil;
15069
15070
15071
15072
15073
15074 size = (STRINGP (f->desired_tool_bar_string)
15075 ? SCHARS (f->desired_tool_bar_string)
15076 : 0);
15077
15078
15079 size_needed = f->n_tool_bar_items;
15080
15081
15082
15083 if (size < size_needed || NILP (f->desired_tool_bar_string))
15084
15085
15086 fset_desired_tool_bar_string (f, make_uninit_string (size_needed));
15087 else
15088 {
15089 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
15090 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
15091 props, f->desired_tool_bar_string);
15092 }
15093
15094 f->tool_bar_wraps_p = false;
15095
15096
15097
15098
15099 for (i = 0; i < f->n_tool_bar_items; ++i)
15100 {
15101 #define PROP(IDX) \
15102 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
15103
15104 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
15105 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
15106 int hmargin, vmargin, relief, idx, end;
15107
15108 if (!NILP (PROP (TOOL_BAR_ITEM_WRAP)))
15109 {
15110
15111
15112 SSET (f->desired_tool_bar_string, i, '\n');
15113
15114
15115
15116 f->tool_bar_wraps_p = true;
15117 continue;
15118 }
15119
15120
15121 SSET (f->desired_tool_bar_string, i, ' ');
15122
15123
15124
15125 image = PROP (TOOL_BAR_ITEM_IMAGES);
15126 if (VECTORP (image))
15127 {
15128 if (enabled_p)
15129 idx = (selected_p
15130 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
15131 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
15132 else
15133 idx = (selected_p
15134 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15135 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15136
15137 eassert (ASIZE (image) >= idx);
15138 image = AREF (image, idx);
15139 }
15140 else
15141 idx = -1;
15142
15143
15144 if (!valid_image_p (image))
15145 continue;
15146
15147
15148 plist = Fcopy_sequence (XCDR (image));
15149
15150
15151 relief = (tool_bar_button_relief >= 0
15152 ? min (tool_bar_button_relief,
15153 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15154 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15155 hmargin = vmargin = relief;
15156
15157 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15158 INT_MAX - max (hmargin, vmargin)))
15159 {
15160 hmargin += XFIXNAT (Vtool_bar_button_margin);
15161 vmargin += XFIXNAT (Vtool_bar_button_margin);
15162 }
15163 else if (CONSP (Vtool_bar_button_margin))
15164 {
15165 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15166 INT_MAX - hmargin))
15167 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15168
15169 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15170 INT_MAX - vmargin))
15171 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15172 }
15173
15174 if (auto_raise_tool_bar_buttons_p)
15175 {
15176
15177
15178 if (selected_p)
15179 {
15180 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15181 hmargin -= relief;
15182 vmargin -= relief;
15183 }
15184 }
15185 else
15186 {
15187
15188
15189
15190 plist = plist_put (plist, QCrelief,
15191 (selected_p
15192 ? make_fixnum (-relief)
15193 : make_fixnum (relief)));
15194 hmargin -= relief;
15195 vmargin -= relief;
15196 }
15197
15198
15199 if (hmargin || vmargin)
15200 {
15201 if (hmargin == vmargin)
15202 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15203 else
15204 plist = plist_put (plist, QCmargin,
15205 Fcons (make_fixnum (hmargin),
15206 make_fixnum (vmargin)));
15207 }
15208
15209
15210
15211
15212 if (!enabled_p && idx < 0)
15213 plist = plist_put (plist, QCconversion, Qdisabled);
15214
15215
15216
15217
15218
15219 image = Fcons (Qimage, plist);
15220 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15221 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15222
15223
15224
15225
15226 if (i + 1 == f->n_tool_bar_items)
15227 end = SCHARS (f->desired_tool_bar_string);
15228 else
15229 end = i + 1;
15230 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15231 props, f->desired_tool_bar_string);
15232 #undef PROP
15233 }
15234
15235
15236
15237
15238
15239
15240
15241 for (; i < size; ++i)
15242
15243 SSET (f->desired_tool_bar_string, i, ' ');
15244 }
15245
15246
15247
15248
15249
15250
15251
15252
15253
15254
15255
15256
15257
15258
15259
15260
15261
15262 static void
15263 display_tool_bar_line (struct it *it, int height)
15264 {
15265 struct glyph_row *row = it->glyph_row;
15266 int max_x = it->last_visible_x;
15267 struct glyph *last;
15268
15269
15270 clear_glyph_row (row);
15271 row->enabled_p = true;
15272 row->y = it->current_y;
15273
15274
15275
15276 it->start_of_box_run_p = true;
15277
15278 while (it->current_x < max_x)
15279 {
15280 int x, n_glyphs_before, i, nglyphs;
15281 struct it it_before;
15282
15283
15284 if (!get_next_display_element (it))
15285 {
15286
15287 if (height < 0 && !it->hpos)
15288 return;
15289 break;
15290 }
15291
15292
15293 n_glyphs_before = row->used[TEXT_AREA];
15294 it_before = *it;
15295
15296 PRODUCE_GLYPHS (it);
15297
15298 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15299 i = 0;
15300 x = it_before.current_x;
15301 while (i < nglyphs)
15302 {
15303 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15304
15305 if (x + glyph->pixel_width > max_x)
15306 {
15307
15308 row->used[TEXT_AREA] = n_glyphs_before;
15309 *it = it_before;
15310
15311
15312
15313 if (n_glyphs_before == 0
15314 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15315 break;
15316 goto out;
15317 }
15318
15319 ++it->hpos;
15320 x += glyph->pixel_width;
15321 ++i;
15322 }
15323
15324
15325
15326
15327
15328
15329 if (ITERATOR_AT_END_OF_LINE_P (it))
15330 {
15331 reseat_at_next_visible_line_start (it, false);
15332 break;
15333 }
15334
15335 if (ITERATOR_AT_END_P (it))
15336 break;
15337
15338 set_iterator_to_next (it, true);
15339 }
15340
15341 out:;
15342
15343 row->displays_text_p = row->used[TEXT_AREA] != 0;
15344
15345
15346
15347
15348
15349
15350
15351 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15352 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15353 it->face_id = DEFAULT_FACE_ID;
15354
15355 extend_face_to_end_of_line (it);
15356 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15357 last->right_box_line_p = true;
15358 if (last == row->glyphs[TEXT_AREA])
15359 last->left_box_line_p = true;
15360
15361
15362 if (height != -1
15363 && (height -= it->max_ascent + it->max_descent) > 0)
15364 {
15365
15366 height %= FRAME_LINE_HEIGHT (it->f);
15367 it->max_ascent += height / 2;
15368 it->max_descent += (height + 1) / 2;
15369 }
15370
15371 compute_line_metrics (it);
15372
15373
15374 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15375 {
15376 row->height = row->phys_height = it->last_visible_y - row->y;
15377 row->visible_height = row->height;
15378 row->ascent = row->phys_ascent = 0;
15379 row->extra_line_spacing = 0;
15380 }
15381
15382 row->full_width_p = true;
15383 row->continued_p = false;
15384 row->truncated_on_left_p = false;
15385 row->truncated_on_right_p = false;
15386
15387 it->current_x = it->hpos = 0;
15388 it->current_y += row->height;
15389 ++it->vpos;
15390 ++it->glyph_row;
15391 }
15392
15393
15394
15395
15396
15397
15398 static int
15399 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15400 {
15401 struct window *w = XWINDOW (f->tool_bar_window);
15402 struct it it;
15403
15404
15405
15406 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15407
15408
15409
15410 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15411 temp_row->reversed_p = false;
15412 it.first_visible_x = 0;
15413 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15414 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15415 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15416 it.paragraph_embedding = L2R;
15417
15418 while (!ITERATOR_AT_END_P (&it))
15419 {
15420 clear_glyph_row (temp_row);
15421 it.glyph_row = temp_row;
15422 display_tool_bar_line (&it, -1);
15423 }
15424 clear_glyph_row (temp_row);
15425
15426
15427 if (n_rows)
15428 *n_rows = it.vpos > 0 ? it.vpos : -1;
15429
15430 if (pixelwise)
15431 return it.current_y;
15432 else
15433 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15434 }
15435
15436 #endif
15437
15438 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15439 0, 2, 0,
15440 doc:
15441
15442 )
15443 (Lisp_Object frame, Lisp_Object pixelwise)
15444 {
15445 int height = 0;
15446
15447 #ifndef HAVE_EXT_TOOL_BAR
15448 struct frame *f = decode_any_frame (frame);
15449
15450 if (WINDOWP (f->tool_bar_window)
15451 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15452 {
15453 update_tool_bar (f, true);
15454 if (f->n_tool_bar_items)
15455 {
15456 build_desired_tool_bar_string (f);
15457 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15458 }
15459 }
15460 #endif
15461
15462 return make_fixnum (height);
15463 }
15464
15465 #ifndef HAVE_EXT_TOOL_BAR
15466
15467
15468
15469 static bool
15470 redisplay_tool_bar (struct frame *f)
15471 {
15472 struct window *w;
15473 struct it it;
15474 struct glyph_row *row;
15475 bool change_height_p;
15476
15477 change_height_p = false;
15478 f->tool_bar_redisplayed = true;
15479
15480
15481
15482
15483
15484 if (!WINDOWP (f->tool_bar_window)
15485 || (w = XWINDOW (f->tool_bar_window),
15486 WINDOW_TOTAL_LINES (w) == 0))
15487 {
15488
15489
15490
15491
15492
15493 f->tool_bar_resized = true;
15494
15495 return false;
15496 }
15497
15498
15499 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15500 it.first_visible_x = 0;
15501 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15502 row = it.glyph_row;
15503 row->reversed_p = false;
15504
15505
15506 build_desired_tool_bar_string (f);
15507 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15508 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15509
15510
15511
15512
15513
15514
15515
15516 it.paragraph_embedding = L2R;
15517
15518 if (f->n_tool_bar_rows == 0)
15519 {
15520 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15521
15522 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15523 {
15524 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15525 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15526 frame_default_tool_bar_height = new_height;
15527
15528 clear_glyph_matrix (w->desired_matrix);
15529 f->fonts_changed = true;
15530
15531
15532
15533
15534
15535
15536
15537 resize_frame_windows (f, FRAME_INNER_HEIGHT (f), false);
15538
15539 return true;
15540 }
15541 }
15542
15543
15544
15545 if (f->n_tool_bar_rows > 0)
15546 {
15547 int border, rows, height, extra;
15548
15549 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15550 border = XFIXNUM (Vtool_bar_border);
15551 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15552 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15553 else if (EQ (Vtool_bar_border, Qborder_width))
15554 border = f->border_width;
15555 else
15556 border = 0;
15557 if (border < 0)
15558 border = 0;
15559
15560 rows = f->n_tool_bar_rows;
15561
15562 if (f->tool_bar_wraps_p)
15563 {
15564
15565
15566
15567 while (!ITERATOR_AT_END_P (&it))
15568 display_tool_bar_line (&it, -1);
15569
15570
15571
15572
15573
15574
15575 if (it.current_y != it.last_visible_y)
15576 change_height_p = true;
15577 }
15578 else
15579 {
15580 height = max (1, (it.last_visible_y - border) / rows);
15581 extra = it.last_visible_y - border - height * rows;
15582
15583 while (it.current_y < it.last_visible_y)
15584 {
15585 int h = 0;
15586 if (extra > 0 && rows-- > 0)
15587 {
15588 h = (extra + rows - 1) / rows;
15589 extra -= h;
15590 }
15591
15592 display_tool_bar_line (&it, height + h);
15593 }
15594 }
15595 }
15596 else
15597 {
15598 while (it.current_y < it.last_visible_y)
15599 display_tool_bar_line (&it, 0);
15600 }
15601
15602
15603
15604 w->desired_matrix->no_scrolling_p = true;
15605 w->must_be_updated_p = true;
15606
15607 if (!NILP (Vauto_resize_tool_bars))
15608 {
15609
15610
15611 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15612 change_height_p = true;
15613
15614
15615
15616
15617
15618 row = it.glyph_row - 1;
15619
15620
15621
15622
15623 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15624 && row->height >= FRAME_LINE_HEIGHT (f))
15625 change_height_p = true;
15626
15627
15628
15629 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15630 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15631 change_height_p = true;
15632
15633
15634
15635 if (change_height_p)
15636 {
15637 int nrows;
15638 int new_height = tool_bar_height (f, &nrows, true);
15639
15640 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15641 && !f->minimize_tool_bar_window_p)
15642 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15643 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15644 f->minimize_tool_bar_window_p = false;
15645
15646 if (change_height_p)
15647 {
15648 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15649 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15650 frame_default_tool_bar_height = new_height;
15651 clear_glyph_matrix (w->desired_matrix);
15652 f->n_tool_bar_rows = nrows;
15653 f->fonts_changed = true;
15654
15655 return true;
15656 }
15657 }
15658 }
15659
15660 f->minimize_tool_bar_window_p = false;
15661
15662 return false;
15663 }
15664
15665
15666
15667
15668
15669
15670 static bool
15671 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15672 {
15673 Lisp_Object prop;
15674 ptrdiff_t charpos;
15675
15676
15677
15678
15679 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15680 charpos = max (0, charpos);
15681
15682
15683
15684
15685 prop = Fget_text_property (make_fixnum (charpos),
15686 Qmenu_item, f->current_tool_bar_string);
15687 if (! FIXNUMP (prop))
15688 return false;
15689 *prop_idx = XFIXNUM (prop);
15690 return true;
15691 }
15692
15693
15694
15695
15696
15697
15698
15699
15700
15701
15702
15703
15704 static int
15705 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15706 int *hpos, int *vpos, int *prop_idx)
15707 {
15708 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15709 struct window *w = XWINDOW (f->tool_bar_window);
15710 int area;
15711
15712
15713 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15714 if (*glyph == NULL)
15715 return -1;
15716
15717
15718
15719 if (!tool_bar_item_info (f, *glyph, prop_idx))
15720 return -1;
15721
15722
15723 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15724 && *vpos >= hlinfo->mouse_face_beg_row
15725 && *vpos <= hlinfo->mouse_face_end_row
15726 && (*vpos > hlinfo->mouse_face_beg_row
15727 || *hpos >= hlinfo->mouse_face_beg_col)
15728 && (*vpos < hlinfo->mouse_face_end_row
15729 || *hpos < hlinfo->mouse_face_end_col
15730 || hlinfo->mouse_face_past_end))
15731 return 0;
15732
15733 return 1;
15734 }
15735
15736
15737
15738
15739
15740
15741
15742
15743 void
15744 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15745 int modifiers, Lisp_Object device)
15746 {
15747 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15748 struct window *w = XWINDOW (f->tool_bar_window);
15749 int hpos, vpos, prop_idx;
15750 struct glyph *glyph;
15751 Lisp_Object enabled_p;
15752 int ts;
15753
15754
15755
15756
15757
15758
15759
15760
15761 frame_to_window_pixel_xy (w, &x, &y);
15762 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15763 if (ts == -1
15764 || (ts != 0 && !NILP (Vmouse_highlight)))
15765 return;
15766
15767
15768
15769
15770 if (NILP (Vmouse_highlight) && !down_p)
15771 prop_idx = f->last_tool_bar_item;
15772
15773
15774 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15775 if (NILP (enabled_p))
15776 return;
15777
15778 if (down_p)
15779 {
15780
15781 if (!NILP (Vmouse_highlight))
15782 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15783 f->last_tool_bar_item = prop_idx;
15784 }
15785 else
15786 {
15787 Lisp_Object key, frame;
15788 struct input_event event;
15789 EVENT_INIT (event);
15790
15791
15792 if (!NILP (Vmouse_highlight))
15793 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15794
15795 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15796
15797 XSETFRAME (frame, f);
15798 event.kind = TOOL_BAR_EVENT;
15799 event.frame_or_window = frame;
15800 event.arg = key;
15801 event.modifiers = modifiers;
15802 event.device = device;
15803 kbd_buffer_store_event (&event);
15804 f->last_tool_bar_item = -1;
15805 }
15806 }
15807
15808 void
15809 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15810 int modifiers)
15811 {
15812 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15813 }
15814
15815
15816
15817
15818
15819 static void
15820 note_tool_bar_highlight (struct frame *f, int x, int y)
15821 {
15822 Lisp_Object window = f->tool_bar_window;
15823 struct window *w = XWINDOW (window);
15824 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15825 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15826 int hpos, vpos;
15827 struct glyph *glyph;
15828 struct glyph_row *row;
15829 int i;
15830 Lisp_Object enabled_p;
15831 int prop_idx;
15832 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15833 bool mouse_down_p;
15834 int rc;
15835
15836
15837
15838 if (x <= 0 || y <= 0)
15839 {
15840 clear_mouse_face (hlinfo);
15841 return;
15842 }
15843
15844 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15845 if (rc < 0)
15846 {
15847
15848 clear_mouse_face (hlinfo);
15849 return;
15850 }
15851 else if (rc == 0)
15852
15853 goto set_help_echo;
15854
15855 clear_mouse_face (hlinfo);
15856
15857
15858 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15859 && f == dpyinfo->last_mouse_frame);
15860
15861 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15862 return;
15863
15864 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15865
15866
15867 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15868 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15869 {
15870
15871
15872 row = MATRIX_ROW (w->current_matrix, vpos);
15873 for (i = x = 0; i < hpos; ++i)
15874 x += row->glyphs[TEXT_AREA][i].pixel_width;
15875
15876
15877 hlinfo->mouse_face_beg_col = hpos;
15878 hlinfo->mouse_face_beg_row = vpos;
15879 hlinfo->mouse_face_beg_x = x;
15880 hlinfo->mouse_face_past_end = false;
15881
15882 hlinfo->mouse_face_end_col = hpos + 1;
15883 hlinfo->mouse_face_end_row = vpos;
15884 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15885 hlinfo->mouse_face_window = window;
15886 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15887
15888
15889 show_mouse_face (hlinfo, draw);
15890 }
15891
15892 set_help_echo:
15893
15894
15895
15896 help_echo_object = help_echo_window = Qnil;
15897 help_echo_pos = -1;
15898 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15899 if (NILP (help_echo_string))
15900 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15901 }
15902
15903 #endif
15904
15905 #endif
15906
15907
15908
15909
15910
15911
15912
15913
15914
15915
15916
15917
15918
15919 static bool
15920 hscroll_window_tree (Lisp_Object window)
15921 {
15922 bool hscrolled_p = false;
15923 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15924 int hscroll_step_abs = 0;
15925 double hscroll_step_rel = 0;
15926
15927 if (hscroll_relative_p)
15928 {
15929 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15930 if (hscroll_step_rel < 0)
15931 {
15932 hscroll_relative_p = false;
15933 hscroll_step_abs = 0;
15934 }
15935 }
15936 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15937 {
15938 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15939 if (hscroll_step_abs < 0)
15940 hscroll_step_abs = 0;
15941 }
15942 else
15943 hscroll_step_abs = 0;
15944
15945 while (WINDOWP (window))
15946 {
15947 struct window *w = XWINDOW (window);
15948
15949 if (WINDOWP (w->contents))
15950 hscrolled_p |= hscroll_window_tree (w->contents);
15951 else if (w->cursor.vpos >= 0
15952
15953
15954
15955
15956
15957
15958 && !(w == XWINDOW (echo_area_window)
15959 && !NILP (echo_area_buffer[0])))
15960 {
15961 int h_margin;
15962 int text_area_width;
15963 struct glyph_row *cursor_row;
15964 struct glyph_row *bottom_row;
15965
15966 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15967 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15968 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15969 else
15970 cursor_row = bottom_row - 1;
15971
15972 if (!cursor_row->enabled_p)
15973 {
15974 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15975 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15976 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15977 else
15978 cursor_row = bottom_row - 1;
15979 }
15980 bool row_r2l_p = cursor_row->reversed_p;
15981 bool hscl = hscrolling_current_line_p (w);
15982 int x_offset = 0;
15983
15984
15985 if (!NILP (Vdisplay_line_numbers))
15986 {
15987 struct glyph *g;
15988 if (!row_r2l_p)
15989 {
15990 for (g = cursor_row->glyphs[TEXT_AREA];
15991 g < cursor_row->glyphs[TEXT_AREA]
15992 + cursor_row->used[TEXT_AREA];
15993 g++)
15994 {
15995 if (!(NILP (g->object) && g->charpos < 0))
15996 break;
15997 x_offset += g->pixel_width;
15998 }
15999 }
16000 else
16001 {
16002 for (g = cursor_row->glyphs[TEXT_AREA]
16003 + cursor_row->used[TEXT_AREA];
16004 g > cursor_row->glyphs[TEXT_AREA];
16005 g--)
16006 {
16007 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
16008 break;
16009 x_offset += (g - 1)->pixel_width;
16010 }
16011 }
16012 }
16013 if (cursor_row->truncated_on_left_p)
16014 {
16015
16016 struct frame *f = XFRAME (WINDOW_FRAME (w));
16017 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
16018 }
16019
16020 text_area_width = window_box_width (w, TEXT_AREA);
16021
16022
16023 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
16024 * WINDOW_FRAME_COLUMN_WIDTH (w));
16025
16026
16027
16028 if (w->suspend_auto_hscroll
16029 && NILP (Fequal (Fwindow_point (window),
16030 Fwindow_old_point (window))))
16031 {
16032 w->suspend_auto_hscroll = false;
16033
16034
16035
16036
16037 if (w->min_hscroll == 0 && w->hscroll > 0
16038 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
16039 Qcurrent_line))
16040 SET_FRAME_GARBAGED (XFRAME (w->frame));
16041 }
16042
16043
16044 Fset_marker (w->old_pointm,
16045 ((w == XWINDOW (selected_window))
16046 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
16047 : Fmarker_position (w->pointm)),
16048 w->contents);
16049
16050 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
16051 && !w->suspend_auto_hscroll
16052
16053
16054
16055
16056
16057
16058 && (CHARPOS (cursor_row->start.pos)
16059 >= BUF_BEG (XBUFFER (w->contents)))
16060
16061
16062
16063
16064 && ((!row_r2l_p
16065 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
16066 || (cursor_row->enabled_p
16067 && cursor_row->truncated_on_right_p
16068 && (w->cursor.x >= text_area_width - h_margin))))
16069
16070
16071
16072
16073
16074
16075 || (row_r2l_p
16076 && ((cursor_row->enabled_p
16077
16078
16079
16080 && cursor_row->truncated_on_right_p
16081 && w->cursor.x <= h_margin)
16082 || (w->hscroll
16083 && (w->cursor.x >= (text_area_width - h_margin
16084 - x_offset)))))
16085
16086
16087
16088
16089
16090 || (hscl
16091 && w->hscroll != w->min_hscroll
16092 && !cursor_row->truncated_on_left_p)))
16093 {
16094 struct it it;
16095 ptrdiff_t hscroll;
16096 struct buffer *saved_current_buffer;
16097 ptrdiff_t pt;
16098 int wanted_x;
16099
16100
16101 saved_current_buffer = current_buffer;
16102 current_buffer = XBUFFER (w->contents);
16103
16104 if (w == XWINDOW (selected_window))
16105 pt = PT;
16106 else
16107 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
16108
16109
16110
16111 init_to_row_start (&it, w, cursor_row);
16112 if (hscl)
16113 it.first_visible_x = window_hscroll_limited (w, it.f)
16114 * FRAME_COLUMN_WIDTH (it.f);
16115 it.last_visible_x = DISP_INFINITY;
16116
16117 ptrdiff_t nchars = pt - IT_CHARPOS (it);
16118 if (current_buffer->long_line_optimizations_p
16119 && nchars > large_hscroll_threshold)
16120 {
16121
16122
16123
16124
16125 fast_move_it_horizontally (&it, nchars);
16126 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
16127 }
16128 else
16129 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
16130
16131
16132
16133
16134
16135
16136 if (it.method == GET_FROM_STRING && pt > 1)
16137 {
16138 init_to_row_start (&it, w, cursor_row);
16139 if (hscl)
16140 it.first_visible_x = (window_hscroll_limited (w, it.f)
16141 * FRAME_COLUMN_WIDTH (it.f));
16142 if (current_buffer->long_line_optimizations_p
16143 && nchars > large_hscroll_threshold)
16144 {
16145 fast_move_it_horizontally (&it, nchars - 1);
16146 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
16147 }
16148 else
16149 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
16150 }
16151 current_buffer = saved_current_buffer;
16152
16153
16154 if (!hscroll_relative_p && hscroll_step_abs == 0)
16155 hscroll = max (0, (it.current_x
16156 - (ITERATOR_AT_END_OF_LINE_P (&it)
16157 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
16158 : (text_area_width / 2))))
16159 / FRAME_COLUMN_WIDTH (it.f);
16160 else if ((!row_r2l_p
16161 && w->cursor.x >= text_area_width - h_margin)
16162 || (row_r2l_p && w->cursor.x <= h_margin))
16163 {
16164 if (hscroll_relative_p)
16165 wanted_x = text_area_width * (1 - hscroll_step_rel)
16166 - h_margin;
16167 else
16168 wanted_x = text_area_width
16169 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16170 - h_margin;
16171 hscroll
16172 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16173 }
16174 else
16175 {
16176 if (hscroll_relative_p)
16177 wanted_x =
16178 text_area_width * hscroll_step_rel + h_margin + x_offset;
16179 else
16180 wanted_x =
16181 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16182 + h_margin + x_offset;
16183 hscroll
16184 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16185 }
16186 hscroll = max (hscroll, w->min_hscroll);
16187
16188
16189
16190
16191 if (w->hscroll != hscroll
16192
16193
16194
16195
16196 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16197 {
16198 struct buffer *b = XBUFFER (w->contents);
16199 b->prevent_redisplay_optimizations_p = true;
16200 w->hscroll = hscroll;
16201 hscrolled_p = true;
16202 }
16203 }
16204 }
16205
16206 window = w->next;
16207 }
16208
16209
16210 return hscrolled_p;
16211 }
16212
16213
16214
16215
16216
16217
16218
16219
16220 static bool
16221 hscroll_windows (Lisp_Object window)
16222 {
16223 bool hscrolled_p = hscroll_window_tree (window);
16224 if (hscrolled_p)
16225 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16226 return hscrolled_p;
16227 }
16228
16229
16230
16231
16232
16233
16234
16235
16236
16237
16238 #ifdef GLYPH_DEBUG
16239
16240
16241
16242 static int debug_first_unchanged_at_end_vpos;
16243 static int debug_last_unchanged_at_beg_vpos;
16244
16245
16246
16247 static int debug_dvpos, debug_dy;
16248
16249
16250
16251 static ptrdiff_t debug_delta, debug_delta_bytes;
16252
16253
16254
16255
16256 static ptrdiff_t debug_end_vpos;
16257
16258
16259
16260
16261
16262 static void debug_method_add (struct window *, char const *, ...)
16263 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16264
16265 static void
16266 debug_method_add (struct window *w, char const *fmt, ...)
16267 {
16268 void *ptr = w;
16269 char *method = w->desired_matrix->method;
16270 int len = strlen (method);
16271 int size = sizeof w->desired_matrix->method;
16272 int remaining = size - len - 1;
16273 va_list ap;
16274
16275 if (len && remaining)
16276 {
16277 method[len] = '|';
16278 --remaining, ++len;
16279 }
16280
16281 va_start (ap, fmt);
16282 vsnprintf (method + len, remaining + 1, fmt, ap);
16283 va_end (ap);
16284
16285 if (trace_redisplay_p)
16286 fprintf (stderr, "%p (%s): %s\n",
16287 ptr,
16288 ((BUFFERP (w->contents)
16289 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16290 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16291 : "no buffer"),
16292 method + len);
16293 }
16294
16295 #endif
16296
16297
16298
16299
16300
16301
16302
16303 static bool
16304 text_outside_line_unchanged_p (struct window *w,
16305 ptrdiff_t start, ptrdiff_t end)
16306 {
16307 bool unchanged_p = true;
16308
16309
16310 if (window_outdated (w))
16311 {
16312
16313 if (GPT < start || Z - GPT < end)
16314 unchanged_p = false;
16315
16316
16317 if (unchanged_p
16318 && (BEG_UNCHANGED < start - 1
16319 || END_UNCHANGED < end))
16320 unchanged_p = false;
16321
16322
16323
16324 if (unchanged_p
16325 && FIXNUMP (BVAR (current_buffer, selective_display))
16326 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16327 && (BEG_UNCHANGED < start || GPT <= start))
16328 unchanged_p = false;
16329
16330
16331
16332
16333
16334
16335
16336
16337 if (unchanged_p)
16338 {
16339 if (BEG + BEG_UNCHANGED == start
16340 && overlay_touches_p (start))
16341 unchanged_p = false;
16342 if (END_UNCHANGED == end
16343 && overlay_touches_p (Z - end))
16344 unchanged_p = false;
16345 }
16346
16347
16348
16349
16350
16351
16352
16353
16354 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16355 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16356 unchanged_p = false;
16357 }
16358
16359 return unchanged_p;
16360 }
16361
16362
16363
16364
16365
16366
16367
16368
16369
16370 void
16371 redisplay (void)
16372 {
16373 redisplay_internal ();
16374 }
16375
16376
16377 static Lisp_Object
16378 overlay_arrow_string_or_property (Lisp_Object var)
16379 {
16380 Lisp_Object val;
16381
16382 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16383 return val;
16384
16385 return Voverlay_arrow_string;
16386 }
16387
16388
16389 static bool
16390 overlay_arrow_in_current_buffer_p (void)
16391 {
16392 Lisp_Object vlist;
16393
16394 for (vlist = Voverlay_arrow_variable_list;
16395 CONSP (vlist);
16396 vlist = XCDR (vlist))
16397 {
16398 Lisp_Object var = XCAR (vlist);
16399 Lisp_Object val;
16400
16401 if (!SYMBOLP (var))
16402 continue;
16403 val = find_symbol_value (var);
16404 if (MARKERP (val)
16405 && current_buffer == XMARKER (val)->buffer)
16406 return true;
16407 }
16408 return false;
16409 }
16410
16411
16412
16413
16414
16415
16416
16417 static bool
16418 overlay_arrows_changed_p (bool set_redisplay)
16419 {
16420 Lisp_Object vlist;
16421 bool changed = false;
16422
16423 for (vlist = Voverlay_arrow_variable_list;
16424 CONSP (vlist);
16425 vlist = XCDR (vlist))
16426 {
16427 Lisp_Object var = XCAR (vlist);
16428 Lisp_Object val, pstr;
16429
16430 if (!SYMBOLP (var))
16431 continue;
16432 val = find_symbol_value (var);
16433 if (!MARKERP (val))
16434 continue;
16435 if (! EQ (Fmarker_position (val),
16436
16437
16438 Fget (var, Qlast_arrow_position))
16439 || ! (pstr = overlay_arrow_string_or_property (var),
16440 EQ (pstr, Fget (var, Qlast_arrow_string))))
16441 {
16442 struct buffer *buf = XMARKER (val)->buffer;
16443
16444 if (set_redisplay)
16445 {
16446 if (buf)
16447 bset_redisplay (buf);
16448 changed = true;
16449 }
16450 else
16451 return true;
16452 }
16453 }
16454 return changed;
16455 }
16456
16457
16458
16459 static void
16460 update_overlay_arrows (int up_to_date)
16461 {
16462 Lisp_Object vlist;
16463
16464 for (vlist = Voverlay_arrow_variable_list;
16465 CONSP (vlist);
16466 vlist = XCDR (vlist))
16467 {
16468 Lisp_Object var = XCAR (vlist);
16469
16470 if (!SYMBOLP (var))
16471 continue;
16472
16473 if (up_to_date > 0)
16474 {
16475 Lisp_Object val = find_symbol_value (var);
16476 if (!MARKERP (val))
16477 continue;
16478 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16479 Fput (var, Qlast_arrow_string,
16480 overlay_arrow_string_or_property (var));
16481 }
16482 else if (up_to_date < 0
16483 || !NILP (Fget (var, Qlast_arrow_position)))
16484 {
16485 Fput (var, Qlast_arrow_position, Qt);
16486 Fput (var, Qlast_arrow_string, Qt);
16487 }
16488 }
16489 }
16490
16491
16492
16493
16494
16495
16496 static Lisp_Object
16497 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16498 {
16499 Lisp_Object vlist;
16500
16501 for (vlist = Voverlay_arrow_variable_list;
16502 CONSP (vlist);
16503 vlist = XCDR (vlist))
16504 {
16505 Lisp_Object var = XCAR (vlist);
16506 Lisp_Object val;
16507
16508 if (!SYMBOLP (var))
16509 continue;
16510
16511 val = find_symbol_value (var);
16512
16513 if (MARKERP (val)
16514 && current_buffer == XMARKER (val)->buffer
16515 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16516 {
16517 if (FRAME_WINDOW_P (it->f)
16518
16519
16520 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16521 {
16522 #ifdef HAVE_WINDOW_SYSTEM
16523 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16524 {
16525 int fringe_bitmap = lookup_fringe_bitmap (val);
16526 if (fringe_bitmap != 0)
16527 return make_fixnum (fringe_bitmap);
16528 }
16529 #endif
16530 return make_fixnum (-1);
16531 }
16532 return overlay_arrow_string_or_property (var);
16533 }
16534 }
16535
16536 return Qnil;
16537 }
16538
16539
16540
16541
16542
16543 static bool
16544 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16545 struct buffer *buf, ptrdiff_t pt)
16546 {
16547 ptrdiff_t start, end;
16548 Lisp_Object prop;
16549 Lisp_Object buffer;
16550
16551 XSETBUFFER (buffer, buf);
16552
16553
16554 if (prev_buf == buf)
16555 {
16556 if (prev_pt == pt)
16557
16558 return false;
16559
16560 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16561 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16562 && composition_valid_p (start, end, prop)
16563 && start < prev_pt && end > prev_pt)
16564
16565
16566 return (pt <= start || pt >= end);
16567 }
16568
16569
16570 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16571 && find_composition (pt, -1, &start, &end, &prop, buffer)
16572 && composition_valid_p (start, end, prop)
16573 && start < pt && end > pt);
16574 }
16575
16576
16577
16578 static void
16579 reconsider_clip_changes (struct window *w)
16580 {
16581 struct buffer *b = XBUFFER (w->contents);
16582
16583 if (b->clip_changed
16584 && w->window_end_valid
16585 && w->current_matrix->buffer == b
16586 && w->current_matrix->zv == BUF_ZV (b)
16587 && w->current_matrix->begv == BUF_BEGV (b))
16588 b->clip_changed = false;
16589
16590
16591
16592
16593
16594 if (!b->clip_changed && w->window_end_valid)
16595 {
16596 ptrdiff_t pt = (w == XWINDOW (selected_window)
16597 ? PT : marker_position (w->pointm));
16598
16599 if ((w->current_matrix->buffer != b || pt != w->last_point)
16600 && check_point_in_composition (w->current_matrix->buffer,
16601 w->last_point, b, pt))
16602 b->clip_changed = true;
16603 }
16604 }
16605
16606 static void
16607 propagate_buffer_redisplay (void)
16608 {
16609
16610
16611
16612
16613
16614
16615
16616
16617
16618 Lisp_Object ws = window_list ();
16619 for (; CONSP (ws); ws = XCDR (ws))
16620 {
16621 struct window *thisw = XWINDOW (XCAR (ws));
16622 struct buffer *thisb = XBUFFER (thisw->contents);
16623 if (thisb->text->redisplay)
16624 thisw->redisplay = true;
16625 }
16626 }
16627
16628 #define STOP_POLLING \
16629 do { if (! polling_stopped_here) stop_polling (); \
16630 polling_stopped_here = true; } while (false)
16631
16632 #define RESUME_POLLING \
16633 do { if (polling_stopped_here) start_polling (); \
16634 polling_stopped_here = false; } while (false)
16635
16636
16637
16638
16639 static void
16640 redisplay_internal (void)
16641 {
16642 struct window *w = XWINDOW (selected_window);
16643 struct window *sw;
16644 struct frame *fr;
16645 bool pending;
16646 bool must_finish = false, match_p;
16647 struct text_pos tlbufpos, tlendpos;
16648 int number_of_visible_frames;
16649 struct frame *sf;
16650 bool polling_stopped_here = false;
16651 Lisp_Object tail, frame;
16652
16653
16654
16655
16656 enum { MAX_HSCROLL_RETRIES = 16 };
16657 int hscroll_retries = 0;
16658
16659
16660
16661
16662
16663
16664 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16665 int garbaged_frame_retries = 0;
16666
16667
16668
16669
16670 bool consider_all_windows_p;
16671
16672
16673 bool update_miniwindow_p = false;
16674
16675 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16676
16677
16678
16679
16680 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16681 && redisplay_skip_initial_frame)
16682 || !NILP (Vinhibit_redisplay))
16683 return;
16684
16685
16686
16687
16688 fr = XFRAME (w->frame);
16689 sf = SELECTED_FRAME ();
16690
16691 if (!fr->glyphs_initialized_p)
16692 return;
16693
16694 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16695 if (popup_activated ())
16696 return;
16697 #endif
16698
16699 #if defined (HAVE_HAIKU)
16700 if (popup_activated_p)
16701 return;
16702 #endif
16703
16704
16705 if (redisplaying_p)
16706 return;
16707
16708
16709
16710 specpdl_ref count = SPECPDL_INDEX ();
16711 record_unwind_protect_void (unwind_redisplay);
16712 redisplaying_p = true;
16713 block_buffer_flips ();
16714 specbind (Qinhibit_free_realized_faces, Qnil);
16715
16716
16717 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16718
16719 FOR_EACH_FRAME (tail, frame)
16720 XFRAME (frame)->already_hscrolled_p = false;
16721
16722 reset_outermost_restrictions ();
16723
16724 retry:
16725
16726 sw = w;
16727
16728 pending = false;
16729 forget_escape_and_glyphless_faces ();
16730
16731 inhibit_free_realized_faces = false;
16732
16733
16734
16735
16736 if (face_change)
16737 windows_or_buffers_changed = 47;
16738
16739 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16740 && FRAME_TTY (sf)->previous_frame != sf)
16741 {
16742
16743
16744
16745 SET_FRAME_GARBAGED (sf);
16746 #if !defined DOS_NT && !defined HAVE_ANDROID
16747 set_tty_color_mode (FRAME_TTY (sf), sf);
16748 #endif
16749 FRAME_TTY (sf)->previous_frame = sf;
16750 }
16751
16752
16753
16754
16755 number_of_visible_frames = 0;
16756
16757 FOR_EACH_FRAME (tail, frame)
16758 {
16759 struct frame *f = XFRAME (frame);
16760
16761 if (FRAME_REDISPLAY_P (f))
16762 {
16763 ++number_of_visible_frames;
16764
16765 if (f->fonts_changed)
16766 {
16767 adjust_frame_glyphs (f);
16768
16769
16770
16771
16772
16773
16774 SET_FRAME_GARBAGED (f);
16775 f->fonts_changed = false;
16776 }
16777
16778
16779 if (f != sf && f->cursor_type_changed)
16780 fset_redisplay (f);
16781 }
16782 clear_desired_matrices (f);
16783 }
16784
16785
16786 do_pending_window_change (true);
16787
16788
16789 clear_garbaged_frames ();
16790
16791
16792 if (NILP (Vmemory_full))
16793 prepare_menu_bars ();
16794
16795
16796
16797
16798
16799 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16800 sw = w;
16801
16802 reconsider_clip_changes (w);
16803
16804
16805 match_p = XBUFFER (w->contents) == current_buffer;
16806 if (match_p)
16807 {
16808
16809 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16810 w->update_mode_line = true;
16811
16812 if (mode_line_update_needed (w))
16813 w->update_mode_line = true;
16814
16815
16816
16817
16818 if (current_buffer->clip_changed)
16819 bset_update_mode_line (current_buffer);
16820 }
16821
16822
16823
16824
16825
16826
16827 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16828 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16829 || (message_cleared_p
16830 && minibuf_level == 0
16831
16832
16833 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16834 {
16835 echo_area_display (false);
16836
16837 if (message_cleared_p)
16838 update_miniwindow_p = true;
16839
16840 must_finish = true;
16841
16842
16843
16844
16845
16846 if (!display_last_displayed_message_p)
16847 message_cleared_p = false;
16848 }
16849 else if (EQ (selected_window, minibuf_window)
16850 && (current_buffer->clip_changed || window_outdated (w))
16851 && resize_mini_window (w, false))
16852 {
16853
16854
16855 must_finish = true;
16856
16857
16858
16859
16860 clear_garbaged_frames ();
16861 }
16862
16863 if (!NILP (Vrun_hooks))
16864 run_window_change_functions ();
16865
16866 if (windows_or_buffers_changed && !update_mode_lines)
16867
16868
16869
16870 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16871 ? REDISPLAY_SOME : 32);
16872
16873
16874
16875
16876
16877 overlay_arrows_changed_p (true);
16878
16879 consider_all_windows_p = (update_mode_lines
16880 || windows_or_buffers_changed);
16881
16882 #define AINC(a,i) \
16883 { \
16884 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16885 if (FIXNUMP (entry)) \
16886 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16887 }
16888
16889 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16890 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16891
16892
16893
16894
16895
16896 tlbufpos = this_line_start_pos;
16897 tlendpos = this_line_end_pos;
16898 if (!consider_all_windows_p
16899 && CHARPOS (tlbufpos) > 0
16900 && !w->update_mode_line
16901 && !current_buffer->clip_changed
16902 && !current_buffer->prevent_redisplay_optimizations_p
16903 && FRAME_REDISPLAY_P (XFRAME (w->frame))
16904 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16905 && !XFRAME (w->frame)->cursor_type_changed
16906 && !XFRAME (w->frame)->face_change
16907
16908 && this_line_buffer == current_buffer
16909 && match_p
16910 && !w->force_start
16911 && !w->optional_new_start
16912
16913 && PT >= CHARPOS (tlbufpos)
16914 && PT <= Z - CHARPOS (tlendpos)
16915
16916
16917
16918
16919
16920
16921 && (NILP (Vdisplay_line_numbers)
16922 || EQ (Vdisplay_line_numbers, Qvisual))
16923
16924
16925 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16926 CHARPOS (tlendpos)))
16927 {
16928 if (CHARPOS (tlbufpos) > BEGV
16929 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16930 && (CHARPOS (tlbufpos) == ZV
16931 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16932
16933 goto cancel;
16934 else if (window_outdated (w) || MINI_WINDOW_P (w))
16935 {
16936
16937
16938
16939
16940
16941
16942
16943
16944
16945
16946
16947
16948
16949
16950
16951 struct it it;
16952 int line_height_before = this_line_pixel_height;
16953
16954
16955
16956 start_display (&it, w, tlbufpos);
16957
16958
16959 if (it.current_x != this_line_start_x)
16960 goto cancel;
16961
16962
16963
16964
16965 if (it.sp > 1
16966 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16967 goto cancel;
16968 redisplay_trace ("trying display optimization 1\n");
16969 w->cursor.vpos = -1;
16970 overlay_arrow_seen = false;
16971 it.vpos = this_line_vpos;
16972 it.current_y = this_line_y;
16973 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16974 display_line (&it, -1);
16975
16976
16977
16978 if (w->cursor.vpos >= 0
16979
16980
16981 && CHARPOS (this_line_start_pos)
16982
16983 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16984
16985
16986 && this_line_pixel_height == line_height_before
16987
16988
16989
16990
16991 && !hscrolling_current_line_p (w))
16992 {
16993
16994
16995 if (it.current_y < it.last_visible_y)
16996 {
16997 struct glyph_row *row
16998 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
16999 ptrdiff_t delta, delta_bytes;
17000
17001
17002
17003
17004
17005
17006 delta = (Z
17007 - CHARPOS (tlendpos)
17008 - MATRIX_ROW_START_CHARPOS (row));
17009 delta_bytes = (Z_BYTE
17010 - BYTEPOS (tlendpos)
17011 - MATRIX_ROW_START_BYTEPOS (row));
17012
17013 increment_matrix_positions (w->current_matrix,
17014 this_line_vpos + 1,
17015 w->current_matrix->nrows,
17016 delta, delta_bytes);
17017 }
17018
17019
17020
17021
17022 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
17023 {
17024 if (w->window_end_vpos < this_line_vpos)
17025 w->window_end_vpos = this_line_vpos;
17026 }
17027 else if (w->window_end_vpos == this_line_vpos
17028 && this_line_vpos > 0)
17029 w->window_end_vpos = this_line_vpos - 1;
17030 w->window_end_valid = false;
17031
17032
17033 w->desired_matrix->no_scrolling_p = true;
17034
17035 #ifdef GLYPH_DEBUG
17036 *w->desired_matrix->method = 0;
17037 debug_method_add (w, "optimization 1");
17038 #endif
17039 #ifdef HAVE_WINDOW_SYSTEM
17040 update_window_fringes (w, false);
17041 #endif
17042 goto update;
17043 }
17044 else
17045 goto cancel;
17046 }
17047 else if (
17048 PT == w->last_point
17049
17050
17051
17052
17053 && 0 <= w->cursor.vpos
17054 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
17055 {
17056 if (!must_finish)
17057 {
17058 do_pending_window_change (true);
17059
17060 if (WINDOWP (selected_window)
17061 && (w = XWINDOW (selected_window)) != sw)
17062 goto retry;
17063
17064
17065
17066 if (w->cursor_off_p == w->last_cursor_off_p)
17067 goto end_of_redisplay;
17068 }
17069 goto update;
17070 }
17071
17072
17073 else if (NILP (Vshow_trailing_whitespace)
17074 && !cursor_in_echo_area
17075 && !composition_break_at_point)
17076 {
17077 struct it it;
17078 struct glyph_row *row;
17079
17080
17081
17082
17083 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
17084 NULL, DEFAULT_FACE_ID);
17085 it.current_x = this_line_start_x;
17086 it.current_y = this_line_y;
17087 it.vpos = this_line_vpos;
17088
17089 if (current_buffer->long_line_optimizations_p
17090 && it.line_wrap == TRUNCATE
17091 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
17092 {
17093
17094
17095
17096 reseat_at_next_visible_line_start (&it, false);
17097 if (IT_CHARPOS (it) <= PT)
17098 it.vpos = this_line_vpos + 1;
17099 }
17100 else
17101 {
17102
17103
17104 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
17105 }
17106
17107 if (it.vpos == this_line_vpos
17108 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
17109 row->enabled_p))
17110 {
17111 eassert (this_line_vpos == it.vpos);
17112 eassert (this_line_y == it.current_y);
17113 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
17114 if (cursor_row_fully_visible_p (w, false, true, false))
17115 {
17116 #ifdef GLYPH_DEBUG
17117 *w->desired_matrix->method = 0;
17118 debug_method_add (w, "optimization 3");
17119 #endif
17120 goto update;
17121 }
17122 else
17123 goto cancel;
17124 }
17125 else
17126 goto cancel;
17127 }
17128
17129 cancel:
17130
17131 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
17132 }
17133
17134 CHARPOS (this_line_start_pos) = 0;
17135 ++clear_face_cache_count;
17136 #ifdef HAVE_WINDOW_SYSTEM
17137 ++clear_image_cache_count;
17138 #endif
17139
17140
17141
17142
17143
17144
17145 if (consider_all_windows_p)
17146 {
17147 FOR_EACH_FRAME (tail, frame)
17148 XFRAME (frame)->updated_p = false;
17149
17150 propagate_buffer_redisplay ();
17151
17152 FOR_EACH_FRAME (tail, frame)
17153 {
17154 struct frame *f = XFRAME (frame);
17155
17156
17157
17158 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
17159 && !EQ (FRAME_TTY (f)->top_frame, frame))
17160 continue;
17161
17162 retry_frame:
17163 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
17164 {
17165 bool gcscrollbars
17166
17167 = f->redisplay || !REDISPLAY_SOME_P ();
17168 bool f_redisplay_flag = f->redisplay;
17169
17170
17171
17172
17173 if (!FRAME_LIVE_P (f))
17174 continue;
17175
17176
17177
17178 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
17179 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
17180
17181 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17182 {
17183
17184
17185
17186
17187
17188
17189
17190 f->inhibit_clear_image_cache = true;
17191 redisplay_windows (FRAME_ROOT_WINDOW (f));
17192 }
17193
17194
17195 else if (!REDISPLAY_SOME_P ())
17196 f->redisplay = true;
17197
17198
17199 if (!FRAME_LIVE_P (f))
17200 continue;
17201
17202
17203
17204 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17205 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17206
17207 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17208 {
17209
17210 if (f->fonts_changed)
17211 {
17212 adjust_frame_glyphs (f);
17213
17214
17215
17216 SET_FRAME_GARBAGED (f);
17217 f->fonts_changed = false;
17218 goto retry_frame;
17219 }
17220
17221
17222 if (!f->already_hscrolled_p)
17223 {
17224 f->already_hscrolled_p = true;
17225 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17226 && hscroll_windows (f->root_window))
17227 {
17228 hscroll_retries++;
17229 goto retry_frame;
17230 }
17231 }
17232
17233
17234
17235
17236
17237
17238
17239
17240
17241
17242
17243
17244 if (!f_redisplay_flag && f->redisplay)
17245 goto retry_frame;
17246
17247
17248
17249
17250
17251
17252
17253
17254
17255 if (FRAME_GARBAGED_P (f)
17256 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17257 goto retry;
17258
17259 #ifdef HAVE_WINDOW_SYSTEM
17260 if (FRAME_WINDOW_P (f)
17261 && FRAME_RIF (f)->clear_under_internal_border)
17262 FRAME_RIF (f)->clear_under_internal_border (f);
17263 #endif
17264
17265
17266
17267 if (interrupt_input)
17268 unrequest_sigio ();
17269 STOP_POLLING;
17270
17271 pending |= update_frame (f, false, false);
17272
17273
17274
17275
17276
17277
17278
17279 if (FRAME_GARBAGED_P (f))
17280 {
17281 fset_redisplay (f);
17282 f->garbaged = false;
17283 goto retry_frame;
17284 }
17285 f->cursor_type_changed = false;
17286 f->updated_p = true;
17287 f->inhibit_clear_image_cache = false;
17288 }
17289 }
17290 }
17291
17292 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17293
17294 if (!pending)
17295 {
17296
17297
17298
17299 FOR_EACH_FRAME (tail, frame)
17300 {
17301 struct frame *f = XFRAME (frame);
17302 if (f->updated_p)
17303 {
17304 f->redisplay = false;
17305 f->garbaged = false;
17306 mark_window_display_accurate (f->root_window, true);
17307 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17308 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17309 }
17310 }
17311 }
17312 }
17313 else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17314 {
17315 sf->inhibit_clear_image_cache = true;
17316 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17317
17318
17319 internal_condition_case_1 (redisplay_window_1, selected_window,
17320 list_of_error,
17321 redisplay_window_error);
17322 if (update_miniwindow_p)
17323 {
17324 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17325
17326 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17327 internal_condition_case_1 (redisplay_window_1, mini_window,
17328 list_of_error,
17329 redisplay_window_error);
17330 }
17331
17332
17333
17334 update:
17335
17336
17337
17338 if (sf->fonts_changed || sf->redisplay)
17339 {
17340 if (sf->redisplay)
17341 {
17342
17343
17344
17345
17346
17347
17348 windows_or_buffers_changed = 50;
17349 }
17350 goto retry;
17351 }
17352
17353
17354
17355 inhibit_free_realized_faces = true;
17356
17357
17358
17359
17360 if (interrupt_input)
17361 unrequest_sigio ();
17362 STOP_POLLING;
17363
17364 if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17365 {
17366 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17367 && hscroll_windows (selected_window))
17368 {
17369 hscroll_retries++;
17370 goto retry;
17371 }
17372
17373 XWINDOW (selected_window)->must_be_updated_p = true;
17374 pending = update_frame (sf, false, false);
17375 sf->cursor_type_changed = false;
17376 sf->inhibit_clear_image_cache = false;
17377 }
17378
17379
17380
17381
17382
17383
17384 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17385 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17386
17387 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17388 {
17389 XWINDOW (mini_window)->must_be_updated_p = true;
17390 pending |= update_frame (mini_frame, false, false);
17391 mini_frame->cursor_type_changed = false;
17392 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17393 && hscroll_windows (mini_window))
17394 {
17395 hscroll_retries++;
17396 goto retry;
17397 }
17398 }
17399 }
17400
17401
17402
17403 if (pending)
17404 {
17405
17406
17407
17408 CHARPOS (this_line_start_pos) = 0;
17409
17410
17411 update_overlay_arrows (0);
17412
17413
17414
17415 if (!WINDOW_FULL_WIDTH_P (w)
17416 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17417 update_mode_lines = 36;
17418 }
17419 else
17420 {
17421 if (!consider_all_windows_p)
17422 {
17423
17424
17425 if (XBUFFER (w->contents)->text->redisplay
17426 && buffer_window_count (XBUFFER (w->contents)) > 1)
17427
17428
17429 propagate_buffer_redisplay ();
17430 mark_window_display_accurate_1 (w, true);
17431
17432
17433 update_overlay_arrows (1);
17434
17435 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17436 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17437 }
17438
17439 update_mode_lines = 0;
17440 windows_or_buffers_changed = 0;
17441 }
17442
17443
17444
17445
17446
17447 if (interrupt_input)
17448 request_sigio ();
17449 RESUME_POLLING;
17450
17451
17452
17453
17454
17455
17456
17457 if (!pending)
17458 {
17459 int new_count = 0;
17460
17461 FOR_EACH_FRAME (tail, frame)
17462 {
17463 if (FRAME_REDISPLAY_P (XFRAME (frame)))
17464 new_count++;
17465 }
17466
17467 if (new_count != number_of_visible_frames)
17468 windows_or_buffers_changed = 52;
17469 }
17470
17471
17472 do_pending_window_change (true);
17473
17474
17475
17476 if ((windows_or_buffers_changed && !pending)
17477 || (WINDOWP (selected_window)
17478 && (w = XWINDOW (selected_window)) != sw))
17479 goto retry;
17480
17481
17482
17483
17484
17485
17486
17487 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17488 {
17489 clear_face_cache (false);
17490 clear_face_cache_count = 0;
17491 }
17492
17493 #ifdef HAVE_WINDOW_SYSTEM
17494 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17495 {
17496 clear_image_caches (Qnil);
17497 clear_image_cache_count = 0;
17498 }
17499 #endif
17500
17501 end_of_redisplay:
17502 #ifdef HAVE_NS
17503 ns_set_doc_edited ();
17504 #endif
17505 if (interrupt_input && interrupts_deferred)
17506 request_sigio ();
17507
17508
17509
17510 if (max_redisplay_ticks > 0)
17511 update_redisplay_ticks (0, NULL);
17512
17513 unbind_to (count, Qnil);
17514 RESUME_POLLING;
17515 }
17516
17517 static void
17518 unwind_redisplay_preserve_echo_area (void)
17519 {
17520 unblock_buffer_flips ();
17521 }
17522
17523
17524
17525
17526
17527
17528
17529
17530
17531
17532
17533
17534 void
17535 redisplay_preserve_echo_area (int from_where)
17536 {
17537 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17538
17539 block_input ();
17540 specpdl_ref count = SPECPDL_INDEX ();
17541 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17542 block_buffer_flips ();
17543 unblock_input ();
17544
17545 if (!NILP (echo_area_buffer[1]))
17546 {
17547
17548
17549 display_last_displayed_message_p = true;
17550 redisplay_internal ();
17551 display_last_displayed_message_p = false;
17552 }
17553 else
17554 redisplay_internal ();
17555
17556 flush_frame (SELECTED_FRAME ());
17557 unbind_to (count, Qnil);
17558 }
17559
17560
17561
17562
17563 static void
17564 unwind_redisplay (void)
17565 {
17566 redisplaying_p = false;
17567 unblock_buffer_flips ();
17568 }
17569
17570
17571
17572 void
17573 unwind_display_working_on_window (void)
17574 {
17575 display_working_on_window_p = false;
17576 }
17577
17578
17579
17580
17581
17582
17583 static void
17584 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17585 {
17586 struct buffer *b = XBUFFER (w->contents);
17587 #ifdef HAVE_TEXT_CONVERSION
17588 ptrdiff_t prev_point, prev_mark;
17589 #endif
17590
17591 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17592 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17593 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17594
17595 if (accurate_p)
17596 {
17597 b->clip_changed = false;
17598 b->prevent_redisplay_optimizations_p = false;
17599 eassert (buffer_window_count (b) > 0);
17600
17601
17602
17603 b->text->redisplay = false;
17604
17605 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17606 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17607 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17608 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17609
17610 w->current_matrix->buffer = b;
17611 w->current_matrix->begv = BUF_BEGV (b);
17612 w->current_matrix->zv = BUF_ZV (b);
17613 w->current_matrix->header_line_p = window_wants_header_line (w);
17614 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17615
17616 w->last_cursor_vpos = w->cursor.vpos;
17617 w->last_cursor_off_p = w->cursor_off_p;
17618
17619 #ifdef HAVE_TEXT_CONVERSION
17620 prev_point = w->last_point;
17621 prev_mark = w->last_mark;
17622 #endif
17623
17624 if (w == XWINDOW (selected_window))
17625 w->last_point = BUF_PT (b);
17626 else
17627 w->last_point = marker_position (w->pointm);
17628
17629
17630
17631
17632
17633 if (XMARKER (BVAR (b, mark))->buffer == b
17634 && !NILP (BVAR (b, mark_active)))
17635 w->last_mark = marker_position (BVAR (b, mark));
17636 else
17637 w->last_mark = -1;
17638
17639 #ifdef HAVE_TEXT_CONVERSION
17640
17641 w->ephemeral_last_point = w->last_point;
17642
17643
17644
17645
17646
17647
17648
17649
17650
17651
17652
17653
17654
17655
17656
17657 if ((prev_point != w->last_point
17658 || prev_mark != w->last_mark)
17659 && FRAME_WINDOW_P (WINDOW_XFRAME (w))
17660 && w == XWINDOW (WINDOW_XFRAME (w)->selected_window))
17661 report_point_change (WINDOW_XFRAME (w), w, b);
17662 #endif
17663
17664 struct glyph_row *row;
17665
17666 if (w->window_end_vpos < w->current_matrix->nrows
17667 && ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
17668 !row->enabled_p
17669 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
17670 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0)))
17671 w->window_end_valid = true;
17672 w->update_mode_line = false;
17673 w->preserve_vscroll_p = false;
17674 }
17675
17676 w->redisplay = !accurate_p;
17677 }
17678
17679
17680
17681
17682
17683
17684
17685 void
17686 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17687 {
17688 struct window *w;
17689
17690 for (; !NILP (window); window = w->next)
17691 {
17692 w = XWINDOW (window);
17693 if (WINDOWP (w->contents))
17694 mark_window_display_accurate (w->contents, accurate_p);
17695 else
17696 mark_window_display_accurate_1 (w, accurate_p);
17697 }
17698
17699 if (accurate_p)
17700 update_overlay_arrows (1);
17701 else
17702
17703
17704
17705 update_overlay_arrows (-1);
17706 }
17707
17708
17709
17710
17711
17712
17713
17714 Lisp_Object
17715 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17716 {
17717 Lisp_Object val;
17718
17719 if (ASCII_CHAR_P (c))
17720 {
17721 val = dp->ascii;
17722 if (SUB_CHAR_TABLE_P (val))
17723 val = XSUB_CHAR_TABLE (val)->contents[c];
17724 }
17725 else
17726 {
17727 Lisp_Object table;
17728
17729 XSETCHAR_TABLE (table, dp);
17730 val = char_table_ref (table, c);
17731 }
17732 if (NILP (val))
17733 val = dp->defalt;
17734 return val;
17735 }
17736
17737 static int buffer_flip_blocked_depth;
17738
17739 static void
17740 block_buffer_flips (void)
17741 {
17742 eassert (buffer_flip_blocked_depth >= 0);
17743 buffer_flip_blocked_depth++;
17744 }
17745
17746 static void
17747 unblock_buffer_flips (void)
17748 {
17749 eassert (buffer_flip_blocked_depth > 0);
17750 if (--buffer_flip_blocked_depth == 0)
17751 {
17752 Lisp_Object tail, frame;
17753 block_input ();
17754 FOR_EACH_FRAME (tail, frame)
17755 {
17756 struct frame *f = XFRAME (frame);
17757 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17758 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17759 }
17760 unblock_input ();
17761 }
17762 }
17763
17764 bool
17765 buffer_flipping_blocked_p (void)
17766 {
17767 return buffer_flip_blocked_depth > 0;
17768 }
17769
17770
17771
17772
17773
17774
17775
17776
17777 static void
17778 redisplay_windows (Lisp_Object window)
17779 {
17780 while (!NILP (window))
17781 {
17782 struct window *w = XWINDOW (window);
17783
17784 if (WINDOWP (w->contents))
17785 redisplay_windows (w->contents);
17786 else if (BUFFERP (w->contents))
17787 {
17788 displayed_buffer = XBUFFER (w->contents);
17789
17790
17791 internal_condition_case_1 (redisplay_window_0, window,
17792 list_of_error,
17793 redisplay_window_error);
17794 }
17795
17796 window = w->next;
17797 }
17798 }
17799
17800 static Lisp_Object
17801 redisplay_window_error (Lisp_Object error_data)
17802 {
17803 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17804
17805
17806
17807 if (max_redisplay_ticks > 0
17808 && CONSP (error_data)
17809 && EQ (XCAR (error_data), Qerror)
17810 && CONSP (XCDR (error_data))
17811 && STRINGP (XCAR (XCDR (error_data))))
17812 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17813 XCAR (XCDR (error_data))),
17814 Vdelayed_warnings_list);
17815 return Qnil;
17816 }
17817
17818 static Lisp_Object
17819 redisplay_window_0 (Lisp_Object window)
17820 {
17821 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17822 redisplay_window (window, false);
17823 return Qnil;
17824 }
17825
17826 static Lisp_Object
17827 redisplay_window_1 (Lisp_Object window)
17828 {
17829 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17830 redisplay_window (window, true);
17831 return Qnil;
17832 }
17833
17834
17835
17836
17837
17838
17839
17840
17841
17842
17843
17844
17845
17846
17847
17848
17849
17850
17851
17852 void
17853 update_redisplay_ticks (int ticks, struct window *w)
17854 {
17855
17856 static struct window *cwindow;
17857 static EMACS_INT window_ticks;
17858
17859
17860
17861
17862 if (!ticks && w != cwindow)
17863 {
17864 cwindow = w;
17865 window_ticks = 0;
17866 }
17867
17868
17869 if ((!w && !redisplaying_p && !display_working_on_window_p)
17870
17871
17872 || (w && MINI_WINDOW_P (w)))
17873 return;
17874
17875 if (ticks > 0)
17876 window_ticks += ticks;
17877 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17878 {
17879
17880
17881
17882 Lisp_Object contents = w ? w->contents : Qnil;
17883 char *bufname =
17884 NILP (contents)
17885 ? SSDATA (BVAR (current_buffer, name))
17886 : (BUFFERP (contents)
17887 ? SSDATA (BVAR (XBUFFER (contents), name))
17888 : (char *) "<unknown>");
17889
17890 windows_or_buffers_changed = 177;
17891
17892
17893
17894 if (w && w->desired_matrix)
17895 w->desired_matrix->no_scrolling_p = true;
17896 error ("Window showing buffer %s takes too long to redisplay", bufname);
17897 }
17898 }
17899
17900
17901
17902
17903
17904
17905
17906
17907
17908
17909 static bool
17910 set_cursor_from_row (struct window *w, struct glyph_row *row,
17911 struct glyph_matrix *matrix,
17912 ptrdiff_t delta, ptrdiff_t delta_bytes,
17913 int dy, int dvpos)
17914 {
17915 struct glyph *glyph = row->glyphs[TEXT_AREA];
17916 struct glyph *end = glyph + row->used[TEXT_AREA];
17917 struct glyph *cursor = NULL;
17918
17919 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17920 int x = row->x;
17921 ptrdiff_t pt_old = PT - delta;
17922 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17923 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17924 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17925
17926
17927 struct glyph *glyphs_end = end;
17928
17929
17930 bool match_with_avoid_cursor = false;
17931
17932
17933 bool string_seen = false;
17934
17935
17936 ptrdiff_t bpos_max = pos_before;
17937 ptrdiff_t bpos_min = pos_after;
17938
17939
17940 ptrdiff_t bpos_covered = 0;
17941
17942
17943 bool string_from_text_prop = false;
17944
17945
17946
17947
17948 eassert (!row->mode_line_p);
17949 if (row->mode_line_p)
17950 return false;
17951
17952
17953
17954
17955 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17956 {
17957 if (!row->reversed_p)
17958 {
17959 while (glyph < end
17960 && NILP (glyph->object)
17961 && glyph->charpos < 0)
17962 {
17963 x += glyph->pixel_width;
17964 ++glyph;
17965 }
17966 while (end > glyph
17967 && NILP ((end - 1)->object)
17968
17969
17970 && (end - 1)->charpos <= 0)
17971 --end;
17972 glyph_before = glyph - 1;
17973 glyph_after = end;
17974 }
17975 else
17976 {
17977 struct glyph *g;
17978
17979
17980
17981 glyphs_end = end = glyph - 1;
17982 glyph += row->used[TEXT_AREA] - 1;
17983
17984 while (glyph > end + 1
17985 && NILP (glyph->object)
17986 && glyph->charpos < 0)
17987 --glyph;
17988 if (NILP (glyph->object) && glyph->charpos < 0)
17989 --glyph;
17990
17991
17992 for (x = 0, g = end + 1; g < glyph; g++)
17993 x += g->pixel_width;
17994 while (end < glyph
17995 && NILP ((end + 1)->object)
17996 && (end + 1)->charpos <= 0)
17997 ++end;
17998 glyph_before = glyph + 1;
17999 glyph_after = end;
18000 }
18001 }
18002 else if (row->reversed_p)
18003 {
18004
18005
18006
18007 cursor = end - 1;
18008
18009
18010
18011 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
18012 && !WINDOW_RIGHTMOST_P (w)
18013 && cursor == row->glyphs[LAST_AREA] - 1)
18014 cursor--;
18015 x = -1;
18016 }
18017
18018
18019
18020
18021
18022 if (!row->reversed_p)
18023 while (
18024 glyph < end
18025
18026 && !NILP (glyph->object))
18027 {
18028 if (BUFFERP (glyph->object))
18029 {
18030 ptrdiff_t dpos = glyph->charpos - pt_old;
18031
18032 if (glyph->charpos > bpos_max)
18033 bpos_max = glyph->charpos;
18034 if (glyph->charpos < bpos_min)
18035 bpos_min = glyph->charpos;
18036 if (!glyph->avoid_cursor_p)
18037 {
18038
18039
18040 if (dpos == 0)
18041 {
18042 match_with_avoid_cursor = false;
18043 break;
18044 }
18045
18046
18047 if (0 > dpos && dpos > pos_before - pt_old)
18048 {
18049 pos_before = glyph->charpos;
18050 glyph_before = glyph;
18051 }
18052 else if (0 < dpos && dpos < pos_after - pt_old)
18053 {
18054 pos_after = glyph->charpos;
18055 glyph_after = glyph;
18056 }
18057 }
18058 else if (dpos == 0)
18059 match_with_avoid_cursor = true;
18060 }
18061 else if (STRINGP (glyph->object))
18062 {
18063 Lisp_Object chprop;
18064 ptrdiff_t glyph_pos = glyph->charpos;
18065
18066 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18067 glyph->object);
18068 if (!NILP (chprop))
18069 {
18070
18071
18072
18073
18074
18075
18076
18077
18078
18079
18080 ptrdiff_t prop_pos =
18081 string_buffer_position_lim (glyph->object, pos_before,
18082 pos_after, false);
18083
18084 if (prop_pos >= pos_before)
18085 bpos_max = prop_pos;
18086 }
18087 if (FIXNUMP (chprop))
18088 {
18089 bpos_covered = bpos_max + XFIXNUM (chprop);
18090
18091
18092
18093
18094
18095
18096
18097
18098
18099
18100
18101 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18102 {
18103 cursor = glyph;
18104 break;
18105 }
18106 }
18107
18108 string_seen = true;
18109 }
18110 x += glyph->pixel_width;
18111 ++glyph;
18112 }
18113 else if (glyph > end)
18114 while (!NILP (glyph->object))
18115 {
18116 if (BUFFERP (glyph->object))
18117 {
18118 ptrdiff_t dpos = glyph->charpos - pt_old;
18119
18120 if (glyph->charpos > bpos_max)
18121 bpos_max = glyph->charpos;
18122 if (glyph->charpos < bpos_min)
18123 bpos_min = glyph->charpos;
18124 if (!glyph->avoid_cursor_p)
18125 {
18126 if (dpos == 0)
18127 {
18128 match_with_avoid_cursor = false;
18129 break;
18130 }
18131 if (0 > dpos && dpos > pos_before - pt_old)
18132 {
18133 pos_before = glyph->charpos;
18134 glyph_before = glyph;
18135 }
18136 else if (0 < dpos && dpos < pos_after - pt_old)
18137 {
18138 pos_after = glyph->charpos;
18139 glyph_after = glyph;
18140 }
18141 }
18142 else if (dpos == 0)
18143 match_with_avoid_cursor = true;
18144 }
18145 else if (STRINGP (glyph->object))
18146 {
18147 Lisp_Object chprop;
18148 ptrdiff_t glyph_pos = glyph->charpos;
18149
18150 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18151 glyph->object);
18152 if (!NILP (chprop))
18153 {
18154 ptrdiff_t prop_pos =
18155 string_buffer_position_lim (glyph->object, pos_before,
18156 pos_after, false);
18157
18158 if (prop_pos >= pos_before)
18159 bpos_max = prop_pos;
18160 }
18161 if (FIXNUMP (chprop))
18162 {
18163 bpos_covered = bpos_max + XFIXNUM (chprop);
18164
18165
18166
18167 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18168 {
18169 cursor = glyph;
18170 break;
18171 }
18172 }
18173 string_seen = true;
18174 }
18175 --glyph;
18176 if (glyph == glyphs_end)
18177 {
18178 x--;
18179 break;
18180 }
18181 x -= glyph->pixel_width;
18182 }
18183
18184
18185
18186
18187 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18188 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
18189 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
18190 {
18191
18192
18193
18194
18195
18196 bool empty_line_p =
18197 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18198 && NILP (glyph->object) && glyph->charpos > 0
18199
18200
18201
18202
18203 && !(row->continued_p || row->truncated_on_right_p));
18204
18205 if (row->ends_in_ellipsis_p && pos_after == last_pos)
18206 {
18207 ptrdiff_t ellipsis_pos;
18208
18209
18210 if (!row->reversed_p)
18211 {
18212 ellipsis_pos = (glyph - 1)->charpos;
18213 while (glyph > row->glyphs[TEXT_AREA]
18214 && (glyph - 1)->charpos == ellipsis_pos)
18215 glyph--, x -= glyph->pixel_width;
18216
18217
18218
18219 x += glyph->pixel_width;
18220 glyph++;
18221 }
18222 else
18223 {
18224 ellipsis_pos = (glyph + 1)->charpos;
18225 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18226 && (glyph + 1)->charpos == ellipsis_pos)
18227 glyph++, x += glyph->pixel_width;
18228 x -= glyph->pixel_width;
18229 glyph--;
18230 }
18231 }
18232 else if (match_with_avoid_cursor)
18233 {
18234 cursor = glyph_after;
18235 x = -1;
18236 }
18237 else if (string_seen)
18238 {
18239 int incr = row->reversed_p ? -1 : +1;
18240
18241
18242
18243
18244
18245
18246 struct glyph *start, *stop;
18247 ptrdiff_t pos = pos_before;
18248
18249 x = -1;
18250
18251
18252
18253
18254
18255
18256 if (row->ends_in_newline_from_string_p)
18257 {
18258 glyph_after = end;
18259 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18260 }
18261
18262
18263
18264
18265
18266
18267
18268
18269
18270 if (!row->reversed_p)
18271 {
18272 start = min (glyph_before, glyph_after);
18273 stop = max (glyph_before, glyph_after);
18274 }
18275 else
18276 {
18277 start = max (glyph_before, glyph_after);
18278 stop = min (glyph_before, glyph_after);
18279 }
18280 for (glyph = start + incr;
18281 row->reversed_p ? glyph > stop : glyph < stop; )
18282 {
18283
18284
18285
18286
18287 if (STRINGP (glyph->object))
18288 {
18289 Lisp_Object str;
18290 ptrdiff_t tem;
18291
18292
18293 ptrdiff_t lim = pos_after
18294 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18295
18296 string_from_text_prop = false;
18297 str = glyph->object;
18298 tem = string_buffer_position_lim (str, pos, lim, false);
18299 if (tem == 0
18300 || pos <= tem)
18301 {
18302
18303
18304
18305
18306
18307
18308
18309
18310
18311
18312 if (tem == 0
18313 || tem == pt_old
18314 || (tem - pt_old > 0 && tem < pos_after))
18315 {
18316
18317
18318
18319
18320
18321
18322 ptrdiff_t strpos = glyph->charpos;
18323
18324 if (tem)
18325 {
18326 cursor = glyph;
18327 string_from_text_prop = true;
18328 }
18329 for ( ;
18330 (row->reversed_p ? glyph > stop : glyph < stop)
18331 && EQ (glyph->object, str);
18332 glyph += incr)
18333 {
18334 Lisp_Object cprop;
18335 ptrdiff_t gpos = glyph->charpos;
18336
18337 cprop = Fget_char_property (make_fixnum (gpos),
18338 Qcursor,
18339 glyph->object);
18340 if (!NILP (cprop))
18341 {
18342 cursor = glyph;
18343 break;
18344 }
18345 if (tem && glyph->charpos < strpos)
18346 {
18347 strpos = glyph->charpos;
18348 cursor = glyph;
18349 }
18350 }
18351
18352 if (tem == pt_old
18353 || (tem - pt_old > 0 && tem < pos_after))
18354 goto compute_x;
18355 }
18356 if (tem)
18357 pos = tem + 1;
18358 }
18359
18360
18361 while ((row->reversed_p ? glyph > stop : glyph < stop)
18362 && EQ (glyph->object, str))
18363 glyph += incr;
18364 }
18365 else
18366 glyph += incr;
18367 }
18368
18369
18370
18371 if (cursor == NULL
18372 && (row->reversed_p ? glyph <= end : glyph >= end)
18373 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18374 && STRINGP (end->object)
18375 && row->continued_p)
18376 return false;
18377 }
18378
18379
18380
18381
18382
18383 else if (row->truncated_on_left_p && pt_old < bpos_min)
18384 {
18385 cursor = glyph_before;
18386 x = -1;
18387 }
18388 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18389
18390 || (!empty_line_p
18391 && (row->reversed_p
18392 ? glyph_after > glyphs_end
18393 : glyph_after < glyphs_end)))
18394 {
18395 cursor = glyph_after;
18396 x = -1;
18397 }
18398 }
18399
18400 compute_x:
18401 if (cursor != NULL)
18402 glyph = cursor;
18403 else if (glyph == glyphs_end
18404 && pos_before == pos_after
18405 && STRINGP ((row->reversed_p
18406 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18407 : row->glyphs[TEXT_AREA])->object))
18408 {
18409
18410
18411
18412
18413 glyph =
18414 row->reversed_p
18415 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18416 : row->glyphs[TEXT_AREA];
18417 }
18418 if (x < 0)
18419 {
18420 struct glyph *g;
18421
18422
18423 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18424 {
18425 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18426 emacs_abort ();
18427 x += g->pixel_width;
18428 }
18429 }
18430
18431
18432
18433
18434
18435
18436 if (
18437 w->cursor.vpos >= 0
18438
18439 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18440
18441
18442
18443
18444
18445 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18446 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18447 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18448 {
18449 struct glyph *g1
18450 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18451
18452
18453 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18454 return false;
18455
18456
18457 if (
18458 w->cursor.hpos >= 0
18459 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18460 && ((BUFFERP (g1->object)
18461 && (g1->charpos == pt_old
18462 || (BUFFERP (glyph->object)
18463 && eabs (g1->charpos - pt_old)
18464 < eabs (glyph->charpos - pt_old))))
18465
18466
18467 || (STRINGP (g1->object)
18468 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18469 Qcursor, g1->object))
18470
18471
18472
18473 || (EQ (g1->object, glyph->object)
18474 && string_from_text_prop)
18475
18476
18477 || (NILP (glyph->object)
18478 && glyph->charpos != pt_old)))))
18479 return false;
18480
18481 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18482
18483
18484
18485 || (!row->continued_p
18486 && NILP (glyph->object)
18487 && glyph->charpos == 0
18488 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18489
18490
18491
18492
18493
18494 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18495 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18496 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18497 return false;
18498 }
18499 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18500 w->cursor.x = x;
18501 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18502 w->cursor.y = row->y + dy;
18503
18504 if (w == XWINDOW (selected_window))
18505 {
18506 if (!row->continued_p
18507 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18508 && row->x == 0)
18509 {
18510 this_line_buffer = XBUFFER (w->contents);
18511
18512 CHARPOS (this_line_start_pos)
18513 = MATRIX_ROW_START_CHARPOS (row) + delta;
18514 BYTEPOS (this_line_start_pos)
18515 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18516
18517 CHARPOS (this_line_end_pos)
18518 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18519 BYTEPOS (this_line_end_pos)
18520 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18521
18522 this_line_y = w->cursor.y;
18523 this_line_pixel_height = row->height;
18524 this_line_vpos = w->cursor.vpos;
18525 this_line_start_x = row->x;
18526 }
18527 else
18528 CHARPOS (this_line_start_pos) = 0;
18529 }
18530
18531 return true;
18532 }
18533
18534
18535
18536
18537
18538
18539
18540 static struct text_pos
18541 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18542 {
18543 struct window *w = XWINDOW (window);
18544 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18545
18546 eassert (current_buffer == XBUFFER (w->contents));
18547
18548 if (!NILP (Vwindow_scroll_functions))
18549 {
18550 specpdl_ref count = SPECPDL_INDEX ();
18551 specbind (Qinhibit_quit, Qt);
18552 safe_run_hooks_2
18553 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18554 unbind_to (count, Qnil);
18555 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18556
18557 set_buffer_internal (XBUFFER (w->contents));
18558 }
18559
18560 return startp;
18561 }
18562
18563
18564
18565
18566
18567
18568
18569
18570
18571
18572
18573
18574
18575
18576
18577
18578
18579
18580
18581
18582
18583
18584 static bool
18585 cursor_row_fully_visible_p (struct window *w, bool force_p,
18586 bool current_matrix_p,
18587 bool just_test_user_preference_p)
18588 {
18589 struct glyph_matrix *matrix;
18590 struct glyph_row *row;
18591 int window_height;
18592 Lisp_Object mclfv_p =
18593 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18594
18595
18596 if (BASE_EQ (mclfv_p, Qunbound))
18597 mclfv_p = Vmake_cursor_line_fully_visible;
18598
18599
18600 if (FUNCTIONP (mclfv_p))
18601 {
18602 Lisp_Object window;
18603 XSETWINDOW (window, w);
18604
18605
18606 Lisp_Object val = safe_call1 (mclfv_p, window);
18607 if (NILP (val))
18608 return true;
18609 else if (just_test_user_preference_p)
18610 return false;
18611 }
18612 else if (NILP (mclfv_p))
18613 return true;
18614 else if (just_test_user_preference_p)
18615 return false;
18616
18617
18618
18619 if (w->cursor.vpos < 0)
18620 return true;
18621
18622 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18623 row = MATRIX_ROW (matrix, w->cursor.vpos);
18624
18625
18626 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18627 return true;
18628
18629
18630
18631 window_height = window_box_height (w);
18632 if (row->height >= window_height)
18633 {
18634 if (!force_p || MINI_WINDOW_P (w)
18635 || w->vscroll || w->cursor.vpos == 0)
18636 return true;
18637 }
18638 return false;
18639 }
18640
18641
18642
18643
18644
18645
18646
18647
18648
18649
18650
18651
18652
18653
18654
18655
18656
18657
18658
18659
18660 enum
18661 {
18662 SCROLLING_SUCCESS = 1,
18663 SCROLLING_FAILED = 0,
18664 SCROLLING_NEED_LARGER_MATRICES = -1
18665 };
18666
18667
18668
18669
18670
18671 #define SCROLL_LIMIT 100
18672
18673 static int
18674 try_scrolling (Lisp_Object window, bool just_this_one_p,
18675 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18676 bool temp_scroll_step, bool last_line_misfit)
18677 {
18678 struct window *w = XWINDOW (window);
18679 struct text_pos pos, startp;
18680 struct it it;
18681 int this_scroll_margin, scroll_max, rc, height;
18682 int dy = 0, amount_to_scroll = 0;
18683 bool scroll_down_p = false;
18684 int extra_scroll_margin_lines = last_line_misfit;
18685 Lisp_Object aggressive;
18686
18687 int scroll_limit = SCROLL_LIMIT;
18688 int frame_line_height = default_line_pixel_height (w);
18689
18690 #ifdef GLYPH_DEBUG
18691 debug_method_add (w, "try_scrolling");
18692 #endif
18693
18694 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18695
18696 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18697
18698
18699
18700
18701
18702 if (arg_scroll_conservatively > scroll_limit)
18703 {
18704 arg_scroll_conservatively = scroll_limit + 1;
18705 scroll_max = scroll_limit * frame_line_height;
18706 }
18707 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18708
18709
18710 {
18711 intmax_t scroll_lines_max
18712 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18713 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18714 scroll_max = scroll_lines * frame_line_height;
18715 }
18716 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18717 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18718
18719
18720 scroll_max = 10 * frame_line_height;
18721 else
18722 scroll_max = 0;
18723
18724 too_near_end:
18725
18726
18727 if (PT > CHARPOS (startp))
18728 {
18729 int scroll_margin_y;
18730
18731
18732
18733 start_display (&it, w, startp);
18734 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18735 - this_scroll_margin
18736 - frame_line_height * extra_scroll_margin_lines;
18737 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18738 (MOVE_TO_POS | MOVE_TO_Y));
18739
18740 if (PT > CHARPOS (it.current.pos))
18741 {
18742 int y0 = line_bottom_y (&it);
18743
18744
18745
18746
18747
18748 int slack = max (scroll_max, 10 * frame_line_height);
18749 int y_to_move = it.last_visible_y + slack;
18750
18751
18752
18753
18754
18755 move_it_to (&it, PT, -1, y_to_move,
18756 -1, MOVE_TO_POS | MOVE_TO_Y);
18757 dy = line_bottom_y (&it) - y0;
18758
18759 if (dy > scroll_max)
18760 return SCROLLING_FAILED;
18761
18762 if (dy > 0)
18763 scroll_down_p = true;
18764 }
18765 else if (PT == IT_CHARPOS (it)
18766 && IT_CHARPOS (it) < ZV
18767 && it.method == GET_FROM_STRING
18768 && arg_scroll_conservatively > scroll_limit
18769 && it.current_x == 0)
18770 {
18771 enum move_it_result skip;
18772 int y1 = it.current_y;
18773 int vpos;
18774
18775
18776
18777
18778
18779
18780
18781 do {
18782 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18783 if (skip != MOVE_NEWLINE_OR_CR
18784 || IT_CHARPOS (it) != PT
18785 || it.method == GET_FROM_BUFFER)
18786 break;
18787 vpos = it.vpos;
18788 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18789 } while (it.vpos > vpos);
18790
18791 dy = it.current_y - y1;
18792
18793 if (dy > scroll_max)
18794 return SCROLLING_FAILED;
18795
18796 if (dy > 0)
18797 scroll_down_p = true;
18798 }
18799 }
18800
18801 if (scroll_down_p)
18802 {
18803
18804
18805
18806
18807 if (arg_scroll_conservatively)
18808 amount_to_scroll
18809 = min (max (dy, frame_line_height),
18810 frame_line_height * arg_scroll_conservatively);
18811 else if (scroll_step || temp_scroll_step)
18812 amount_to_scroll = scroll_max;
18813 else
18814 {
18815 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18816 height = WINDOW_BOX_TEXT_HEIGHT (w);
18817 if (NUMBERP (aggressive))
18818 {
18819 double float_amount = XFLOATINT (aggressive) * height;
18820 int aggressive_scroll = float_amount;
18821 if (aggressive_scroll == 0 && float_amount > 0)
18822 aggressive_scroll = 1;
18823
18824
18825
18826
18827
18828
18829 if (aggressive_scroll + 2 * this_scroll_margin > height)
18830 aggressive_scroll = height - 2 * this_scroll_margin;
18831 amount_to_scroll = dy + aggressive_scroll;
18832 }
18833 }
18834
18835 if (amount_to_scroll <= 0)
18836 return SCROLLING_FAILED;
18837
18838 start_display (&it, w, startp);
18839 if (arg_scroll_conservatively <= scroll_limit)
18840 move_it_vertically (&it, amount_to_scroll);
18841 else
18842 {
18843
18844
18845
18846
18847
18848
18849 struct it it1;
18850 void *it1data = NULL;
18851
18852
18853 int start_y;
18854
18855 SAVE_IT (it1, it, it1data);
18856 start_y = line_bottom_y (&it1);
18857 do {
18858 RESTORE_IT (&it, &it, it1data);
18859 move_it_by_lines (&it, 1);
18860 SAVE_IT (it1, it, it1data);
18861 } while (IT_CHARPOS (it) < ZV
18862 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18863 bidi_unshelve_cache (it1data, true);
18864 }
18865
18866
18867 if (IT_CHARPOS (it) == CHARPOS (startp))
18868 move_it_by_lines (&it, 1);
18869 startp = it.current.pos;
18870 }
18871 else
18872 {
18873 struct text_pos scroll_margin_pos = startp;
18874 int y_offset = 0;
18875
18876
18877
18878 if (this_scroll_margin)
18879 {
18880 int y_start;
18881
18882 start_display (&it, w, startp);
18883 y_start = it.current_y;
18884 move_it_vertically (&it, this_scroll_margin);
18885 scroll_margin_pos = it.current.pos;
18886
18887
18888
18889 if (IT_CHARPOS (it) == ZV
18890 && it.current_y - y_start < this_scroll_margin)
18891 y_offset = this_scroll_margin - (it.current_y - y_start);
18892 }
18893
18894 if (PT < CHARPOS (scroll_margin_pos))
18895 {
18896
18897
18898 int y0, y_to_move;
18899
18900
18901
18902
18903
18904
18905 SET_TEXT_POS (pos, PT, PT_BYTE);
18906 start_display (&it, w, pos);
18907 y0 = it.current_y;
18908 y_to_move = max (it.last_visible_y,
18909 max (scroll_max, 10 * frame_line_height));
18910 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18911 y_to_move, -1,
18912 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18913 dy = it.current_y - y0;
18914 if (dy > scroll_max
18915 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18916 return SCROLLING_FAILED;
18917
18918
18919 dy += y_offset;
18920
18921
18922 start_display (&it, w, startp);
18923
18924 if (arg_scroll_conservatively)
18925 amount_to_scroll
18926 = min (max (dy, frame_line_height),
18927 frame_line_height * arg_scroll_conservatively);
18928 else if (scroll_step || temp_scroll_step)
18929 amount_to_scroll = scroll_max;
18930 else
18931 {
18932 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18933 height = WINDOW_BOX_TEXT_HEIGHT (w);
18934 if (NUMBERP (aggressive))
18935 {
18936 double float_amount = XFLOATINT (aggressive) * height;
18937 int aggressive_scroll = float_amount;
18938 if (aggressive_scroll == 0 && float_amount > 0)
18939 aggressive_scroll = 1;
18940
18941
18942
18943
18944 if (aggressive_scroll + 2 * this_scroll_margin > height)
18945 aggressive_scroll = height - 2 * this_scroll_margin;
18946 amount_to_scroll = dy + aggressive_scroll;
18947 }
18948 }
18949
18950 if (amount_to_scroll <= 0)
18951 return SCROLLING_FAILED;
18952
18953 move_it_vertically_backward (&it, amount_to_scroll);
18954 startp = it.current.pos;
18955 }
18956 }
18957
18958
18959 startp = run_window_scroll_functions (window, startp);
18960
18961
18962
18963 if (!try_window (window, startp, 0))
18964 rc = SCROLLING_NEED_LARGER_MATRICES;
18965 else if (w->cursor.vpos < 0)
18966 {
18967 clear_glyph_matrix (w->desired_matrix);
18968 rc = SCROLLING_FAILED;
18969 }
18970 else
18971 {
18972
18973 if (!just_this_one_p
18974 || current_buffer->clip_changed
18975 || BEG_UNCHANGED < CHARPOS (startp))
18976 w->base_line_number = 0;
18977
18978
18979
18980 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18981 false, false)
18982
18983
18984
18985 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18986 {
18987 clear_glyph_matrix (w->desired_matrix);
18988 ++extra_scroll_margin_lines;
18989 goto too_near_end;
18990 }
18991 rc = SCROLLING_SUCCESS;
18992 }
18993
18994 return rc;
18995 }
18996
18997
18998
18999
19000
19001
19002
19003
19004
19005
19006
19007
19008 static bool
19009 compute_window_start_on_continuation_line (struct window *w)
19010 {
19011 struct text_pos pos, start_pos, pos_before_pt;
19012 bool window_start_changed_p = false;
19013
19014 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19015
19016
19017
19018
19019 if (CHARPOS (start_pos) > BEGV
19020 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
19021 {
19022 struct it it;
19023 struct glyph_row *row;
19024
19025
19026 if (CHARPOS (start_pos) < BEGV)
19027 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
19028 else if (CHARPOS (start_pos) > ZV)
19029 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
19030
19031
19032
19033 row = w->desired_matrix->rows + window_wants_tab_line (w)
19034 + window_wants_header_line (w);
19035 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
19036 row, DEFAULT_FACE_ID);
19037 reseat_at_previous_visible_line_start (&it);
19038
19039
19040
19041
19042
19043
19044
19045 if (IT_CHARPOS (it) <= PT
19046 && (CHARPOS (start_pos) - IT_CHARPOS (it)
19047
19048 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
19049 {
19050 int min_distance, distance;
19051
19052
19053
19054
19055
19056
19057
19058 pos_before_pt = pos = it.current.pos;
19059 min_distance = DISP_INFINITY;
19060 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
19061 distance < min_distance)
19062 {
19063 min_distance = distance;
19064 if (CHARPOS (pos) <= PT)
19065 pos_before_pt = pos;
19066 pos = it.current.pos;
19067 if (it.line_wrap == WORD_WRAP)
19068 {
19069
19070
19071
19072
19073
19074
19075
19076
19077
19078 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
19079 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19080 move_it_to (&it, ZV, 0,
19081 it.current_y + it.max_ascent + it.max_descent, -1,
19082 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19083 }
19084 else
19085 move_it_by_lines (&it, 1);
19086 }
19087
19088
19089
19090
19091
19092 if (CHARPOS (pos) > PT)
19093 pos = pos_before_pt;
19094
19095
19096 SET_MARKER_FROM_TEXT_POS (w->start, pos);
19097 window_start_changed_p = true;
19098 }
19099 }
19100
19101 return window_start_changed_p;
19102 }
19103
19104
19105
19106
19107
19108
19109
19110
19111
19112
19113
19114
19115
19116
19117
19118
19119
19120 enum
19121 {
19122 CURSOR_MOVEMENT_SUCCESS,
19123 CURSOR_MOVEMENT_CANNOT_BE_USED,
19124 CURSOR_MOVEMENT_MUST_SCROLL,
19125 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
19126 };
19127
19128 static int
19129 try_cursor_movement (Lisp_Object window, struct text_pos startp,
19130 bool *scroll_step)
19131 {
19132 struct window *w = XWINDOW (window);
19133 struct frame *f = XFRAME (w->frame);
19134 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
19135
19136 #ifdef GLYPH_DEBUG
19137 if (inhibit_try_cursor_movement)
19138 return rc;
19139 #endif
19140
19141
19142
19143
19144 eassert (w->last_point > 0);
19145
19146
19147
19148 eassert (!w->window_end_valid
19149 || w->window_end_vpos < w->current_matrix->nrows);
19150
19151
19152
19153 if (
19154 PT >= CHARPOS (startp)
19155
19156 && !current_buffer->clip_changed
19157
19158
19159
19160
19161 && !update_mode_lines
19162 && !windows_or_buffers_changed
19163 && !f->cursor_type_changed
19164 && NILP (Vshow_trailing_whitespace)
19165
19166
19167 && !EQ (Vdisplay_line_numbers, Qrelative)
19168 && !EQ (Vdisplay_line_numbers, Qvisual)
19169
19170
19171
19172 && !(!NILP (Vdisplay_line_numbers)
19173 && NILP (Finternal_lisp_face_equal_p (Qline_number,
19174 Qline_number_current_line,
19175 w->frame)))
19176
19177
19178
19179
19180
19181
19182 && !EQ (window, minibuf_window)
19183
19184
19185
19186 && !overlay_arrow_in_current_buffer_p ())
19187 {
19188 int this_scroll_margin, top_scroll_margin;
19189 struct glyph_row *row = NULL;
19190
19191 #ifdef GLYPH_DEBUG
19192 debug_method_add (w, "cursor movement");
19193 #endif
19194
19195 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
19196
19197 top_scroll_margin = this_scroll_margin;
19198 if (window_wants_tab_line (w))
19199 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
19200 if (window_wants_header_line (w))
19201 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
19202
19203
19204
19205 if (w->last_cursor_vpos < 0
19206 || w->last_cursor_vpos >= w->current_matrix->nrows)
19207 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19208 else
19209 {
19210 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
19211
19212 if (row->tab_line_p)
19213 ++row;
19214 if (row->mode_line_p)
19215 ++row;
19216 if (!row->enabled_p)
19217 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19218 }
19219
19220 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
19221 {
19222 bool scroll_p = false, must_scroll = false;
19223 int last_y = window_text_bottom_y (w) - this_scroll_margin;
19224
19225 if (PT > w->last_point)
19226 {
19227
19228 while (MATRIX_ROW_END_CHARPOS (row) < PT
19229 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19230 {
19231 eassert (row->enabled_p);
19232 ++row;
19233 }
19234
19235
19236
19237
19238 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19239 && MATRIX_ROW_END_CHARPOS (row) == PT
19240 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
19241 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19242 && !cursor_row_p (row))
19243 ++row;
19244
19245
19246
19247
19248
19249 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19250 || PT > MATRIX_ROW_END_CHARPOS (row)
19251
19252
19253 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19254 && PT == MATRIX_ROW_END_CHARPOS (row)
19255 && !row->ends_at_zv_p
19256 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19257 scroll_p = true;
19258 }
19259 else if (PT < w->last_point)
19260 {
19261
19262
19263 struct glyph_row *row0 = row;
19264
19265 while (!row->mode_line_p
19266 && (MATRIX_ROW_START_CHARPOS (row) > PT
19267 || (MATRIX_ROW_START_CHARPOS (row) == PT
19268 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19269 || (
19270 row > w->current_matrix->rows
19271 && (row-1)->ends_in_newline_from_string_p))))
19272 && (row->y > top_scroll_margin
19273 || CHARPOS (startp) == BEGV))
19274 {
19275 eassert (row->enabled_p);
19276 --row;
19277 }
19278
19279
19280
19281
19282
19283 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19284 && PT <= MATRIX_ROW_END_CHARPOS (row))
19285 && row0->continued_p)
19286 {
19287 row = row0;
19288 while (MATRIX_ROW_START_CHARPOS (row) > PT
19289 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19290 {
19291 eassert (row->enabled_p);
19292 ++row;
19293 }
19294 }
19295
19296
19297
19298
19299
19300
19301 if (row < w->current_matrix->rows
19302 || row->mode_line_p)
19303 {
19304 row = w->current_matrix->rows;
19305
19306 if (row->tab_line_p)
19307 ++row;
19308 if (row->mode_line_p)
19309 ++row;
19310 }
19311
19312
19313
19314 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19315 && MATRIX_ROW_END_CHARPOS (row) == PT
19316 && !cursor_row_p (row))
19317 ++row;
19318
19319
19320
19321 if ((row->y < top_scroll_margin
19322 && CHARPOS (startp) != BEGV)
19323 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19324 || PT > MATRIX_ROW_END_CHARPOS (row)
19325 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19326 && PT == MATRIX_ROW_END_CHARPOS (row)
19327 && !row->ends_at_zv_p
19328 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19329 scroll_p = true;
19330 }
19331 else
19332 {
19333
19334
19335 rc = CURSOR_MOVEMENT_SUCCESS;
19336 }
19337
19338 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19339 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19340
19341
19342 || (MATRIX_ROW_END_CHARPOS (row-1)
19343 == MATRIX_ROW_START_CHARPOS (row))))
19344 || PT > MATRIX_ROW_END_CHARPOS (row))
19345 {
19346
19347 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19348 must_scroll = true;
19349 }
19350 else if (rc != CURSOR_MOVEMENT_SUCCESS
19351 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19352 {
19353 struct glyph_row *row1;
19354
19355
19356
19357
19358
19359
19360
19361
19362
19363
19364
19365 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19366 MATRIX_ROW_CONTINUATION_LINE_P (row);
19367 --row)
19368 {
19369
19370
19371
19372 if (row <= row1)
19373 {
19374 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19375 break;
19376 }
19377 eassert (row->enabled_p);
19378 }
19379 }
19380 if (must_scroll)
19381 ;
19382 else if (rc != CURSOR_MOVEMENT_SUCCESS
19383 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19384
19385
19386
19387 && !row->mode_line_p
19388 && !cursor_row_fully_visible_p (w, true, true, true))
19389 {
19390 if (PT == MATRIX_ROW_END_CHARPOS (row)
19391 && !row->ends_at_zv_p
19392 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19393 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19394 else if (row->height > window_box_height (w))
19395 {
19396
19397
19398
19399
19400 *scroll_step = true;
19401 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19402 }
19403 else
19404 {
19405 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19406 if (!cursor_row_fully_visible_p (w, false, true, false))
19407 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19408 else
19409 rc = CURSOR_MOVEMENT_SUCCESS;
19410 }
19411 }
19412 else if (scroll_p)
19413 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19414 else if (rc != CURSOR_MOVEMENT_SUCCESS
19415 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19416 {
19417
19418
19419
19420
19421
19422
19423
19424 bool rv = false;
19425 bool pt_invis = false;
19426 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19427 Qinvisible,
19428 Qnil, NULL);
19429
19430 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19431 pt_invis = true;
19432
19433 do
19434 {
19435 bool at_zv_p = false, exact_match_p = false;
19436
19437
19438
19439
19440
19441 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19442 && PT <= MATRIX_ROW_END_CHARPOS (row)
19443 && cursor_row_p (row))
19444 rv |= set_cursor_from_row (w, row, w->current_matrix,
19445 0, 0, 0, 0);
19446
19447
19448
19449 if (rv)
19450 {
19451 at_zv_p = MATRIX_ROW (w->current_matrix,
19452 w->cursor.vpos)->ends_at_zv_p;
19453 if (!at_zv_p
19454 && w->cursor.hpos >= 0
19455 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19456 w->cursor.vpos))
19457 {
19458 struct glyph_row *candidate =
19459 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19460 struct glyph *g =
19461 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19462 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19463
19464 exact_match_p =
19465 (BUFFERP (g->object) && g->charpos == PT)
19466 || (NILP (g->object)
19467 && (g->charpos == PT
19468 || (g->charpos == 0 && endpos - 1 == PT)));
19469
19470
19471
19472
19473 if (!exact_match_p && pt_invis)
19474 exact_match_p = true;
19475 }
19476 if (at_zv_p || exact_match_p)
19477 {
19478 rc = CURSOR_MOVEMENT_SUCCESS;
19479 break;
19480 }
19481 }
19482 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19483 break;
19484 ++row;
19485 }
19486 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19487 || row->continued_p)
19488 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19489 || (MATRIX_ROW_START_CHARPOS (row) == PT
19490 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19491
19492
19493
19494 if (rc != CURSOR_MOVEMENT_SUCCESS
19495 && !(rv
19496 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19497 && !row->continued_p))
19498 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19499 else if (rv)
19500 rc = CURSOR_MOVEMENT_SUCCESS;
19501 }
19502 else
19503 {
19504 do
19505 {
19506 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19507 {
19508 rc = CURSOR_MOVEMENT_SUCCESS;
19509 break;
19510 }
19511 ++row;
19512 }
19513 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19514 && MATRIX_ROW_START_CHARPOS (row) == PT
19515 && cursor_row_p (row));
19516 }
19517 }
19518 }
19519
19520 return rc;
19521 }
19522
19523
19524 void
19525 set_vertical_scroll_bar (struct window *w)
19526 {
19527 ptrdiff_t start, end, whole;
19528
19529
19530
19531
19532
19533
19534
19535
19536 if (!MINI_WINDOW_P (w)
19537 || (w == XWINDOW (minibuf_window)
19538 && NILP (echo_area_buffer[0])))
19539 {
19540 struct buffer *buf = XBUFFER (w->contents);
19541
19542 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19543 start = marker_position (w->start) - BUF_BEGV (buf);
19544 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19545
19546
19547
19548
19549 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19550 {
19551 struct it it;
19552 struct text_pos start_pos;
19553 struct buffer *obuf = current_buffer;
19554
19555
19556
19557 set_buffer_internal_1 (XBUFFER (w->contents));
19558 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19559 start_display (&it, w, start_pos);
19560 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19561 MOVE_TO_X | MOVE_TO_Y);
19562 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19563 set_buffer_internal_1 (obuf);
19564 }
19565
19566 if (end < start)
19567 end = start;
19568 if (whole < (end - start))
19569 whole = end - start;
19570 }
19571 else
19572 start = end = whole = 0;
19573
19574
19575 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19576 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19577 (w, end - start, whole, start);
19578 }
19579
19580
19581 void
19582 set_horizontal_scroll_bar (struct window *w)
19583 {
19584 int start, end, whole, portion;
19585
19586 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19587 {
19588 struct buffer *b = XBUFFER (w->contents);
19589 struct buffer *old_buffer = NULL;
19590 struct it it;
19591 struct text_pos startp;
19592
19593 if (b != current_buffer)
19594 {
19595 old_buffer = current_buffer;
19596 set_buffer_internal (b);
19597 }
19598
19599 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19600 start_display (&it, w, startp);
19601 it.last_visible_x = INT_MAX;
19602 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19603 MOVE_TO_X | MOVE_TO_Y);
19604
19605
19606
19607
19608 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19609 end = start + window_box_width (w, TEXT_AREA);
19610 portion = end - start;
19611
19612
19613
19614
19615 whole = max (whole, end);
19616
19617 if (it.bidi_p)
19618 {
19619 Lisp_Object pdir;
19620
19621 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19622 if (EQ (pdir, Qright_to_left))
19623 {
19624 start = whole - end;
19625 end = start + portion;
19626 }
19627 }
19628
19629 if (old_buffer)
19630 set_buffer_internal (old_buffer);
19631 }
19632 else
19633 start = end = whole = portion = 0;
19634
19635 w->hscroll_whole = whole;
19636
19637
19638 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19639 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19640 (w, portion, whole, start);
19641 }
19642
19643
19644
19645 static bool
19646 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19647 {
19648 if (!make_window_start_visible)
19649 return true;
19650
19651 struct window *w = XWINDOW (window);
19652 struct frame *f = XFRAME (w->frame);
19653 Lisp_Object startpos = make_fixnum (startp);
19654 Lisp_Object invprop, disp_spec;
19655 struct text_pos ignored;
19656
19657
19658 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19659 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19660 return false;
19661
19662
19663 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19664 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19665 FRAME_WINDOW_P (f)) > 0)
19666 return false;
19667
19668 return true;
19669 }
19670
19671 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19672 0, 0, 0,
19673 doc:
19674
19675 )
19676 (void)
19677 {
19678 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19679 }
19680
19681
19682
19683
19684
19685
19686
19687
19688
19689
19690
19691
19692
19693
19694
19695
19696
19697
19698
19699
19700
19701
19702
19703
19704
19705
19706
19707
19708
19709
19710
19711
19712
19713
19714
19715
19716
19717
19718
19719
19720
19721
19722
19723
19724
19725
19726
19727
19728
19729
19730
19731 static void
19732 redisplay_window (Lisp_Object window, bool just_this_one_p)
19733 {
19734 struct window *w = XWINDOW (window);
19735 struct frame *f = XFRAME (w->frame);
19736 struct buffer *buffer = XBUFFER (w->contents);
19737 struct buffer *old = current_buffer;
19738 struct text_pos lpoint, opoint, startp;
19739 bool update_mode_line;
19740 int tem;
19741 struct it it;
19742
19743 bool current_matrix_up_to_date_p = false;
19744 bool used_current_matrix_p = false;
19745
19746
19747 bool buffer_unchanged_p = false;
19748 bool temp_scroll_step = false;
19749 specpdl_ref count = SPECPDL_INDEX ();
19750 int rc;
19751 int centering_position = -1;
19752 bool last_line_misfit = false;
19753 ptrdiff_t beg_unchanged, end_unchanged;
19754 int frame_line_height, margin;
19755 bool use_desired_matrix;
19756 void *itdata = NULL;
19757
19758 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19759 opoint = lpoint;
19760
19761 #ifdef GLYPH_DEBUG
19762 *w->desired_matrix->method = 0;
19763 #endif
19764
19765 if (!just_this_one_p && needs_no_redisplay (w))
19766 return;
19767
19768
19769 eassert (XMARKER (w->start)->buffer == buffer);
19770 eassert (XMARKER (w->pointm)->buffer == buffer);
19771
19772 reconsider_clip_changes (w);
19773 frame_line_height = default_line_pixel_height (w);
19774 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19775
19776
19777
19778 update_mode_line = (w->update_mode_line
19779 || update_mode_lines
19780 || buffer->clip_changed
19781 || buffer->prevent_redisplay_optimizations_p);
19782
19783 if (!just_this_one_p)
19784
19785
19786 w->must_be_updated_p = true;
19787
19788 if (MINI_WINDOW_P (w))
19789 {
19790 if (w == XWINDOW (echo_area_window)
19791 && !NILP (echo_area_buffer[0]))
19792 {
19793 if (update_mode_line)
19794
19795
19796 goto finish_menu_bars;
19797 else
19798
19799 goto finish_scroll_bars;
19800 }
19801 else if ((w != XWINDOW (minibuf_window)
19802 || minibuf_level == 0)
19803
19804 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19805
19806
19807 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19808 {
19809
19810
19811 int yb = window_text_bottom_y (w);
19812 struct glyph_row *row;
19813 int y;
19814
19815 for (y = 0, row = w->desired_matrix->rows;
19816 y < yb;
19817 y += row->height, ++row)
19818 blank_row (w, row, y);
19819 goto finish_scroll_bars;
19820 }
19821 else if (minibuf_level >= 1)
19822 {
19823
19824
19825
19826 resize_mini_window (w, false);
19827 }
19828
19829 clear_glyph_matrix (w->desired_matrix);
19830 }
19831
19832
19833
19834
19835
19836 set_buffer_internal_1 (XBUFFER (w->contents));
19837
19838 current_matrix_up_to_date_p
19839 = (w->window_end_valid
19840 && !current_buffer->clip_changed
19841 && !current_buffer->prevent_redisplay_optimizations_p
19842 && !window_outdated (w)
19843 && !composition_break_at_point
19844 && !hscrolling_current_line_p (w));
19845
19846 beg_unchanged = BEG_UNCHANGED;
19847 end_unchanged = END_UNCHANGED;
19848
19849 SET_TEXT_POS (opoint, PT, PT_BYTE);
19850
19851 specbind (Qinhibit_point_motion_hooks, Qt);
19852
19853 buffer_unchanged_p
19854 = (w->window_end_valid
19855 && !current_buffer->clip_changed
19856 && !window_outdated (w));
19857
19858
19859
19860 if (windows_or_buffers_changed)
19861 {
19862
19863
19864 if (XMARKER (w->start)->buffer == current_buffer)
19865 compute_window_start_on_continuation_line (w);
19866
19867 w->window_end_valid = false;
19868
19869
19870 current_matrix_up_to_date_p = false;
19871 }
19872
19873
19874 CHECK_WINDOW_END (w);
19875 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19876 emacs_abort ();
19877 if (BYTEPOS (opoint) < CHARPOS (opoint))
19878 emacs_abort ();
19879
19880 if (mode_line_update_needed (w))
19881 update_mode_line = true;
19882
19883
19884
19885 if (!EQ (window, selected_window))
19886 {
19887 ptrdiff_t new_pt = marker_position (w->pointm);
19888 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19889
19890 if (new_pt < BEGV)
19891 {
19892 new_pt = BEGV;
19893 new_pt_byte = BEGV_BYTE;
19894 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19895 }
19896 else if (new_pt > (ZV - 1))
19897 {
19898 new_pt = ZV;
19899 new_pt_byte = ZV_BYTE;
19900 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19901 }
19902
19903
19904 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19905 }
19906
19907
19908
19909
19910
19911
19912 if (current_buffer->width_run_cache
19913 || (current_buffer->base_buffer
19914 && current_buffer->base_buffer->width_run_cache))
19915 {
19916 struct Lisp_Char_Table *disptab = buffer_display_table ();
19917
19918 if (! disptab_matches_widthtab
19919 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19920 {
19921 struct buffer *buf = current_buffer;
19922
19923 if (buf->base_buffer)
19924 buf = buf->base_buffer;
19925 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19926 recompute_width_table (current_buffer, disptab);
19927 }
19928 }
19929
19930
19931 if (!NILP (Vlong_line_threshold)
19932 && !current_buffer->long_line_optimizations_p
19933 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19934 || current_buffer->clip_changed))
19935 {
19936 ptrdiff_t cur, next, found, max = 0, threshold;
19937 threshold = XFIXNUM (Vlong_line_threshold);
19938 for (cur = BEGV; cur < ZV; cur = next)
19939 {
19940 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19941 &found, NULL, true);
19942 if (next - cur > max) max = next - cur;
19943 if (!found || max > threshold) break;
19944 }
19945 if (max > threshold)
19946 current_buffer->long_line_optimizations_p = true;
19947 }
19948
19949
19950 if (XMARKER (w->start)->buffer != current_buffer)
19951 goto recenter;
19952
19953 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19954
19955
19956
19957 if ((w->optional_new_start || window_frozen_p (w))
19958 && CHARPOS (startp) >= BEGV
19959 && CHARPOS (startp) <= ZV)
19960 {
19961 ptrdiff_t it_charpos;
19962
19963 w->optional_new_start = false;
19964 if (!w->force_start)
19965 {
19966 start_display (&it, w, startp);
19967 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19968 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19969
19970
19971 it_charpos = IT_CHARPOS (it);
19972
19973
19974
19975
19976
19977 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19978 {
19979 if (it_charpos == PT)
19980 w->force_start = true;
19981
19982 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19983 w->force_start = true;
19984 #ifdef GLYPH_DEBUG
19985 if (w->force_start)
19986 {
19987 if (window_frozen_p (w))
19988 debug_method_add (w, "set force_start from frozen window start");
19989 else
19990 debug_method_add (w, "set force_start from optional_new_start");
19991 }
19992 #endif
19993 }
19994 }
19995 }
19996
19997 force_start:
19998
19999
20000
20001 if (w->force_start)
20002 {
20003
20004 int new_vpos = -1;
20005
20006 w->force_start = false;
20007
20008
20009
20010
20011 if (!w->preserve_vscroll_p || !window_frozen_p (w))
20012 w->vscroll = 0;
20013
20014 w->preserve_vscroll_p = false;
20015 w->window_end_valid = false;
20016
20017
20018 if (!buffer_unchanged_p)
20019 w->base_line_number = 0;
20020
20021
20022
20023
20024
20025
20026
20027
20028 if (!update_mode_line
20029 || ! NILP (Vwindow_scroll_functions))
20030 {
20031 update_mode_line = true;
20032 w->update_mode_line = true;
20033 startp = run_window_scroll_functions (window, startp);
20034 }
20035
20036 if (CHARPOS (startp) < BEGV)
20037 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
20038 else if (CHARPOS (startp) > ZV)
20039 SET_TEXT_POS (startp, ZV, ZV_BYTE);
20040
20041
20042
20043 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20044 goto ignore_start;
20045
20046
20047
20048
20049
20050
20051 clear_glyph_matrix (w->desired_matrix);
20052 if (!try_window (window, startp, 0))
20053 {
20054 w->force_start = true;
20055 clear_glyph_matrix (w->desired_matrix);
20056 goto need_larger_matrices;
20057 }
20058
20059 if (w->cursor.vpos < 0)
20060 {
20061
20062
20063
20064
20065
20066 struct glyph_row *r = NULL;
20067 Lisp_Object invprop =
20068 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20069 Qnil, NULL);
20070
20071 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
20072 {
20073 ptrdiff_t alt_pt;
20074 Lisp_Object invprop_end =
20075 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20076 Qnil, Qnil);
20077
20078 if (FIXNATP (invprop_end))
20079 alt_pt = XFIXNAT (invprop_end);
20080 else
20081 alt_pt = ZV;
20082 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
20083 NULL, 0);
20084 }
20085 if (r)
20086 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
20087 else
20088 new_vpos = window_box_height (w) / 2;
20089 }
20090
20091 if (!cursor_row_fully_visible_p (w, false, false, false))
20092 {
20093
20094
20095 new_vpos = window_box_height (w);
20096
20097
20098
20099
20100
20101
20102 if (new_vpos >= w->cursor.y)
20103 {
20104 w->cursor.vpos = -1;
20105 clear_glyph_matrix (w->desired_matrix);
20106 goto try_to_scroll;
20107 }
20108 }
20109 else if (w->cursor.vpos >= 0)
20110 {
20111
20112
20113
20114 int pixel_margin = margin * frame_line_height;
20115 bool tab_line = window_wants_tab_line (w);
20116 bool header_line = window_wants_header_line (w);
20117
20118
20119
20120
20121
20122 if (w->cursor.vpos < margin + tab_line + header_line)
20123 {
20124 w->cursor.vpos = -1;
20125 clear_glyph_matrix (w->desired_matrix);
20126 goto try_to_scroll;
20127 }
20128 else
20129 {
20130 int window_height = window_box_height (w);
20131
20132 if (tab_line)
20133 window_height += CURRENT_TAB_LINE_HEIGHT (w);
20134 if (header_line)
20135 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
20136 if (w->cursor.y >= window_height - pixel_margin)
20137 {
20138 w->cursor.vpos = -1;
20139 clear_glyph_matrix (w->desired_matrix);
20140 goto try_to_scroll;
20141 }
20142 }
20143 }
20144
20145
20146
20147 if (new_vpos >= 0)
20148 {
20149 struct glyph_row *row;
20150
20151 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
20152 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
20153 && !row->ends_at_zv_p)
20154 ++row;
20155
20156 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
20157 MATRIX_ROW_START_BYTEPOS (row));
20158
20159 if (w != XWINDOW (selected_window))
20160 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
20161 else if (current_buffer == old)
20162 SET_TEXT_POS (lpoint, PT, PT_BYTE);
20163
20164 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
20165
20166
20167
20168
20169
20170
20171
20172 w->redisplay = false;
20173 XBUFFER (w->contents)->text->redisplay = false;
20174 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
20175
20176 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
20177 || ((EQ (Vdisplay_line_numbers, Qrelative)
20178 || EQ (Vdisplay_line_numbers, Qvisual))
20179 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
20180 {
20181
20182
20183
20184
20185 clear_glyph_matrix (w->desired_matrix);
20186 if (!try_window (window, startp, 0))
20187 goto need_larger_matrices;
20188 }
20189 }
20190 if (w->cursor.vpos < 0
20191 || !cursor_row_fully_visible_p (w, false, false, false))
20192 {
20193 clear_glyph_matrix (w->desired_matrix);
20194 goto try_to_scroll;
20195 }
20196
20197 #ifdef GLYPH_DEBUG
20198 debug_method_add (w, "forced window start");
20199 #endif
20200 goto done;
20201 }
20202
20203 ignore_start:
20204
20205
20206
20207
20208 if (current_matrix_up_to_date_p
20209 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
20210 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
20211 {
20212 switch (rc)
20213 {
20214 case CURSOR_MOVEMENT_SUCCESS:
20215 used_current_matrix_p = true;
20216 goto done;
20217
20218 case CURSOR_MOVEMENT_MUST_SCROLL:
20219 goto try_to_scroll;
20220
20221 default:
20222 emacs_abort ();
20223 }
20224 }
20225
20226
20227
20228 else if (w->start_at_line_beg
20229 && ((CHARPOS (startp) > BEGV
20230 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
20231 || (CHARPOS (startp) >= BEGV
20232 && CHARPOS (startp) <= ZV
20233 && !window_start_acceptable_p (window, CHARPOS (startp)))))
20234 {
20235 #ifdef GLYPH_DEBUG
20236 debug_method_add (w, "recenter 1");
20237 #endif
20238 goto recenter;
20239 }
20240
20241
20242
20243
20244 else if ((tem = try_window_id (w)) != 0)
20245 {
20246 #ifdef GLYPH_DEBUG
20247 debug_method_add (w, "try_window_id %d", tem);
20248 #endif
20249
20250 if (f->fonts_changed)
20251 goto need_larger_matrices;
20252 if (tem > 0)
20253 goto done;
20254
20255
20256
20257 }
20258 else if (CHARPOS (startp) >= BEGV
20259 && CHARPOS (startp) <= ZV
20260 && PT >= CHARPOS (startp)
20261 && (CHARPOS (startp) < ZV
20262
20263 || CHARPOS (startp) == BEGV
20264 || !window_outdated (w)))
20265 {
20266 int d1, d2, d5, d6;
20267 int rtop, rbot;
20268
20269
20270
20271
20272
20273
20274
20275
20276
20277
20278 if (!w->start_at_line_beg
20279 && NILP (track_mouse)
20280 && CHARPOS (startp) > BEGV
20281 && CHARPOS (startp) > BEG + beg_unchanged
20282 && CHARPOS (startp) <= Z - end_unchanged
20283
20284
20285
20286
20287
20288 && XMARKER (w->start)->buffer == current_buffer
20289 && compute_window_start_on_continuation_line (w)
20290
20291
20292
20293
20294
20295
20296 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20297
20298
20299 && (rtop != 0) == (rbot != 0))
20300 {
20301 w->force_start = true;
20302 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20303 #ifdef GLYPH_DEBUG
20304 debug_method_add (w, "recomputed window start in continuation line");
20305 #endif
20306 goto force_start;
20307 }
20308
20309
20310
20311
20312 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20313 {
20314 #ifdef GLYPH_DEBUG
20315 debug_method_add (w, "recenter 2");
20316 #endif
20317 goto recenter;
20318 }
20319
20320 #ifdef GLYPH_DEBUG
20321 debug_method_add (w, "same window start");
20322 #endif
20323
20324
20325
20326 if (!current_matrix_up_to_date_p
20327
20328
20329
20330 || !NILP (Vwindow_scroll_functions)
20331 || MINI_WINDOW_P (w)
20332 || !(used_current_matrix_p
20333 = try_window_reusing_current_matrix (w)))
20334 {
20335 IF_DEBUG (debug_method_add (w, "1"));
20336 clear_glyph_matrix (w->desired_matrix);
20337 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20338
20339
20340
20341 goto try_to_scroll;
20342 }
20343
20344 if (f->fonts_changed)
20345 goto need_larger_matrices;
20346
20347 if (w->cursor.vpos >= 0)
20348 {
20349 if (!just_this_one_p
20350 || current_buffer->clip_changed
20351 || BEG_UNCHANGED < CHARPOS (startp))
20352
20353 w->base_line_number = 0;
20354
20355 if (!cursor_row_fully_visible_p (w, true, false, false))
20356 {
20357 clear_glyph_matrix (w->desired_matrix);
20358 last_line_misfit = true;
20359 }
20360
20361 else
20362 goto done;
20363 }
20364 else
20365 clear_glyph_matrix (w->desired_matrix);
20366 }
20367
20368 try_to_scroll:
20369
20370
20371 if (!update_mode_line)
20372 {
20373 update_mode_line = true;
20374 w->update_mode_line = true;
20375 }
20376
20377
20378 if ((0 < scroll_conservatively
20379
20380
20381
20382
20383 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20384 || 0 < emacs_scroll_step
20385 || temp_scroll_step
20386 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20387 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20388 && CHARPOS (startp) >= BEGV
20389 && CHARPOS (startp) <= ZV)
20390 {
20391
20392
20393 int ss = try_scrolling (window, just_this_one_p,
20394 ((scroll_minibuffer_conservatively
20395 && MINI_WINDOW_P (w))
20396 ? SCROLL_LIMIT + 1
20397 : scroll_conservatively),
20398 emacs_scroll_step,
20399 temp_scroll_step, last_line_misfit);
20400 switch (ss)
20401 {
20402 case SCROLLING_SUCCESS:
20403 goto done;
20404
20405 case SCROLLING_NEED_LARGER_MATRICES:
20406 goto need_larger_matrices;
20407
20408 case SCROLLING_FAILED:
20409 break;
20410
20411 default:
20412 emacs_abort ();
20413 }
20414 }
20415
20416
20417
20418
20419 recenter:
20420
20421 #ifdef GLYPH_DEBUG
20422 debug_method_add (w, "recenter");
20423 #endif
20424
20425
20426 if (!buffer_unchanged_p)
20427 w->base_line_number = 0;
20428
20429
20430 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20431 it.current_y = it.last_visible_y;
20432 if (centering_position < 0)
20433 {
20434 ptrdiff_t margin_pos = CHARPOS (startp);
20435 Lisp_Object aggressive;
20436 bool scrolling_up;
20437
20438
20439
20440 if (margin
20441
20442
20443
20444
20445
20446
20447 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20448 {
20449 struct it it1;
20450 void *it1data = NULL;
20451
20452 SAVE_IT (it1, it, it1data);
20453 start_display (&it1, w, startp);
20454 move_it_vertically (&it1, margin * frame_line_height);
20455 margin_pos = IT_CHARPOS (it1);
20456 RESTORE_IT (&it, &it, it1data);
20457 }
20458 scrolling_up = PT > margin_pos;
20459 aggressive =
20460 scrolling_up
20461 ? BVAR (current_buffer, scroll_up_aggressively)
20462 : BVAR (current_buffer, scroll_down_aggressively);
20463
20464 if (!MINI_WINDOW_P (w)
20465 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20466 {
20467 int pt_offset = 0;
20468
20469
20470
20471 if (!scroll_conservatively && NUMBERP (aggressive))
20472 {
20473 double float_amount = XFLOATINT (aggressive);
20474
20475 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20476 if (pt_offset == 0 && float_amount > 0)
20477 pt_offset = 1;
20478 if (pt_offset && margin > 0)
20479 margin -= 1;
20480 }
20481
20482
20483
20484 if (scrolling_up)
20485 {
20486 centering_position = it.last_visible_y;
20487 if (pt_offset)
20488 centering_position -= pt_offset;
20489 centering_position -=
20490 (frame_line_height * (1 + margin + last_line_misfit)
20491 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20492
20493
20494 if (centering_position < margin * frame_line_height)
20495 centering_position = margin * frame_line_height;
20496 }
20497 else
20498 centering_position = margin * frame_line_height + pt_offset;
20499 }
20500 else
20501
20502
20503 centering_position = window_box_height (w) / 2;
20504 }
20505 if (current_buffer->long_line_optimizations_p
20506 && it.line_wrap == TRUNCATE)
20507 {
20508
20509
20510
20511 int nlines = centering_position / frame_line_height;
20512
20513 while (nlines-- && IT_CHARPOS (it) > BEGV)
20514 back_to_previous_visible_line_start (&it);
20515 reseat_1 (&it, it.current.pos, true);
20516 }
20517 else
20518 move_it_vertically_backward (&it, centering_position);
20519
20520 eassert (IT_CHARPOS (it) >= BEGV);
20521
20522
20523
20524
20525
20526
20527 if (it.current_y <= 0)
20528 {
20529 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20530 move_it_vertically_backward (&it, 0);
20531 it.current_y = 0;
20532 }
20533
20534 it.current_x = it.hpos = 0;
20535
20536
20537
20538
20539 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20540
20541
20542 startp = run_window_scroll_functions (window, it.current.pos);
20543
20544
20545
20546
20547 itdata = bidi_shelve_cache ();
20548
20549
20550 use_desired_matrix = false;
20551 if (!current_matrix_up_to_date_p
20552 || windows_or_buffers_changed
20553 || f->cursor_type_changed
20554
20555
20556 || !NILP (Vwindow_scroll_functions)
20557 || !just_this_one_p
20558 || MINI_WINDOW_P (w)
20559 || !(used_current_matrix_p
20560 = try_window_reusing_current_matrix (w)))
20561 use_desired_matrix = (try_window (window, startp, 0) == 1);
20562
20563 bidi_unshelve_cache (itdata, false);
20564
20565
20566
20567
20568 if (f->fonts_changed)
20569 goto need_larger_matrices;
20570
20571
20572
20573
20574
20575
20576 if (w->cursor.vpos < 0)
20577 {
20578 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20579 {
20580 clear_glyph_matrix (w->desired_matrix);
20581 move_it_by_lines (&it, 1);
20582 try_window (window, it.current.pos, 0);
20583 }
20584 else if (PT < IT_CHARPOS (it))
20585 {
20586 clear_glyph_matrix (w->desired_matrix);
20587 move_it_by_lines (&it, -1);
20588 try_window (window, it.current.pos, 0);
20589 }
20590 else if (scroll_conservatively > SCROLL_LIMIT
20591 && (it.method == GET_FROM_STRING
20592 || overlay_touches_p (IT_CHARPOS (it)))
20593 && IT_CHARPOS (it) < ZV)
20594 {
20595
20596
20597
20598
20599
20600
20601
20602
20603 ptrdiff_t pos0 = IT_CHARPOS (it);
20604
20605 clear_glyph_matrix (w->desired_matrix);
20606 do {
20607 move_it_by_lines (&it, 1);
20608 } while (IT_CHARPOS (it) == pos0);
20609 try_window (window, it.current.pos, 0);
20610 }
20611 else
20612 {
20613
20614 }
20615 }
20616
20617
20618
20619
20620
20621
20622 if (w->cursor.vpos < 0)
20623 {
20624
20625
20626
20627
20628 struct glyph_matrix *matrix =
20629 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20630
20631 struct glyph_row *row =
20632 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20633
20634
20635
20636
20637
20638
20639
20640 if (!row)
20641 {
20642 Lisp_Object val =
20643 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20644 Qnil, NULL);
20645
20646 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20647 {
20648 ptrdiff_t alt_pos;
20649 Lisp_Object invis_end =
20650 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20651 Qnil, Qnil);
20652
20653 if (FIXNATP (invis_end))
20654 alt_pos = XFIXNAT (invis_end);
20655 else
20656 alt_pos = ZV;
20657 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20658 }
20659 }
20660
20661
20662
20663 if (!row)
20664 {
20665 row = matrix->rows;
20666
20667 if (row->tab_line_p)
20668 ++row;
20669 if (row->mode_line_p)
20670 ++row;
20671 }
20672 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20673 }
20674
20675 if (!cursor_row_fully_visible_p (w, false, false, false))
20676 {
20677
20678 if (w->vscroll)
20679 {
20680 w->vscroll = 0;
20681 clear_glyph_matrix (w->desired_matrix);
20682 goto recenter;
20683 }
20684
20685
20686
20687
20688
20689 if (scroll_conservatively > SCROLL_LIMIT)
20690 {
20691 int window_total_lines
20692 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20693 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20694
20695 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20696 clear_glyph_matrix (w->desired_matrix);
20697 if (1 == try_window (window, it.current.pos,
20698 TRY_WINDOW_CHECK_MARGINS))
20699 goto done;
20700 }
20701
20702
20703
20704
20705 if (centering_position == 0)
20706 goto done;
20707
20708 clear_glyph_matrix (w->desired_matrix);
20709 centering_position = 0;
20710 goto recenter;
20711 }
20712
20713 done:
20714
20715 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20716 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20717 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20718
20719
20720 if ((update_mode_line
20721
20722
20723
20724
20725 || (!just_this_one_p
20726 && !FRAME_WINDOW_P (f)
20727 && !WINDOW_FULL_WIDTH_P (w))
20728
20729 || w->base_line_pos > 0
20730
20731 || (w->column_number_displayed != -1
20732 && (w->column_number_displayed != current_column ())))
20733
20734 && (window_wants_mode_line (w)
20735 || window_wants_header_line (w)
20736 || window_wants_tab_line (w)))
20737 {
20738 specpdl_ref count1 = SPECPDL_INDEX ();
20739
20740 specbind (Qinhibit_quit, Qt);
20741 display_mode_lines (w);
20742 unbind_to (count1, Qnil);
20743
20744
20745
20746 if (window_wants_mode_line (w)
20747 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20748 {
20749 f->fonts_changed = true;
20750 w->mode_line_height = -1;
20751 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20752 = DESIRED_MODE_LINE_HEIGHT (w);
20753 }
20754
20755
20756
20757 if (window_wants_tab_line (w)
20758 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20759 {
20760 f->fonts_changed = true;
20761 w->tab_line_height = -1;
20762 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20763 = DESIRED_TAB_LINE_HEIGHT (w);
20764 }
20765
20766
20767
20768 if (window_wants_header_line (w)
20769 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20770 {
20771 f->fonts_changed = true;
20772 w->header_line_height = -1;
20773 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20774 = DESIRED_HEADER_LINE_HEIGHT (w);
20775 }
20776
20777 if (f->fonts_changed)
20778 goto need_larger_matrices;
20779 }
20780
20781 if (!line_number_displayed && w->base_line_pos != -1)
20782 {
20783 w->base_line_pos = 0;
20784 w->base_line_number = 0;
20785 }
20786
20787 finish_menu_bars:
20788
20789
20790
20791 if (update_mode_line
20792 && EQ (FRAME_SELECTED_WINDOW (f), window))
20793 {
20794 bool redisplay_menu_p;
20795
20796 if (FRAME_WINDOW_P (f))
20797 {
20798 #ifdef HAVE_EXT_MENU_BAR
20799 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20800 #else
20801 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20802 #endif
20803 }
20804 else
20805 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20806
20807 if (redisplay_menu_p)
20808 display_menu_bar (w);
20809
20810 #ifdef HAVE_WINDOW_SYSTEM
20811 if (FRAME_WINDOW_P (f))
20812 {
20813 if (WINDOWP (f->tab_bar_window)
20814 && (FRAME_TAB_BAR_LINES (f) > 0
20815 || !NILP (Vauto_resize_tab_bars))
20816 && redisplay_tab_bar (f))
20817 ignore_mouse_drag_p = true;
20818
20819 #ifdef HAVE_EXT_TOOL_BAR
20820 if (FRAME_EXTERNAL_TOOL_BAR (f))
20821 update_frame_tool_bar (f);
20822 #else
20823 if (WINDOWP (f->tool_bar_window)
20824 && (FRAME_TOOL_BAR_LINES (f) > 0
20825 || !NILP (Vauto_resize_tool_bars))
20826 && redisplay_tool_bar (f))
20827 ignore_mouse_drag_p = true;
20828 #endif
20829 }
20830 else
20831 {
20832 if ((FRAME_TAB_BAR_LINES (f) > 0))
20833 display_tab_bar (w);
20834 }
20835
20836 gui_consider_frame_title (w->frame);
20837 #else
20838 if ((FRAME_TAB_BAR_LINES (f) > 0))
20839 display_tab_bar (w);
20840 #endif
20841 }
20842
20843 #ifdef HAVE_WINDOW_SYSTEM
20844 if (FRAME_WINDOW_P (f)
20845 && update_window_fringes (w, (just_this_one_p
20846 || (!used_current_matrix_p && !overlay_arrow_seen)
20847 || w->pseudo_window_p)))
20848 {
20849 update_begin (f);
20850 block_input ();
20851 if (draw_window_fringes (w, true))
20852 {
20853 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20854 gui_draw_right_divider (w);
20855 else
20856 gui_draw_vertical_border (w);
20857 }
20858 unblock_input ();
20859 update_end (f);
20860 }
20861
20862 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20863 gui_draw_bottom_divider (w);
20864 #endif
20865
20866
20867
20868
20869
20870 need_larger_matrices:
20871 ;
20872 finish_scroll_bars:
20873
20874 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20875 {
20876 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20877
20878 set_vertical_scroll_bar (w);
20879
20880 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20881
20882 set_horizontal_scroll_bar (w);
20883
20884
20885
20886 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20887 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20888 }
20889
20890
20891
20892
20893 if (CHARPOS (opoint) < BEGV)
20894 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20895 else if (CHARPOS (opoint) > ZV)
20896 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20897 else
20898 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20899
20900 set_buffer_internal_1 (old);
20901
20902
20903 if (CHARPOS (lpoint) <= ZV)
20904 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20905
20906 unbind_to (count, Qnil);
20907 }
20908
20909
20910
20911
20912
20913
20914
20915
20916
20917
20918
20919
20920
20921
20922
20923
20924
20925
20926
20927
20928 int
20929 try_window (Lisp_Object window, struct text_pos pos, int flags)
20930 {
20931 struct window *w = XWINDOW (window);
20932 struct it it;
20933 struct glyph_row *last_text_row = NULL;
20934 struct frame *f = XFRAME (w->frame);
20935 int cursor_vpos = w->cursor.vpos;
20936
20937
20938 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20939
20940
20941 w->cursor.vpos = -1;
20942 overlay_arrow_seen = false;
20943
20944
20945 start_display (&it, w, pos);
20946 it.glyph_row->reversed_p = false;
20947
20948
20949 while (it.current_y < it.last_visible_y)
20950 {
20951 int last_row_scale = it.w->nrows_scale_factor;
20952 int last_col_scale = it.w->ncols_scale_factor;
20953 if (display_line (&it, cursor_vpos))
20954 last_text_row = it.glyph_row - 1;
20955 if (f->fonts_changed
20956 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20957
20958
20959 && last_row_scale == it.w->nrows_scale_factor
20960 && last_col_scale == it.w->ncols_scale_factor))
20961 return 0;
20962 }
20963
20964
20965
20966 ptrdiff_t it_charpos = IT_CHARPOS (it);
20967
20968
20969
20970
20971 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20972 && w->vscroll == 0
20973 && !MINI_WINDOW_P (w))
20974 {
20975 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20976 int bot_scroll_margin = top_scroll_margin;
20977 if (window_wants_header_line (w))
20978 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20979 if (window_wants_tab_line (w))
20980 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20981 start_display (&it, w, pos);
20982
20983 if ((w->cursor.y >= 0
20984 && w->cursor.y < top_scroll_margin
20985 && CHARPOS (pos) > BEGV)
20986
20987
20988
20989
20990 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20991 - bot_scroll_margin - 1))
20992 {
20993 w->cursor.vpos = -1;
20994 clear_glyph_matrix (w->desired_matrix);
20995 return -1;
20996 }
20997 }
20998
20999
21000 if (w->window_end_pos <= 0 && Z != it_charpos)
21001 w->update_mode_line = true;
21002
21003
21004
21005
21006 if (last_text_row)
21007 {
21008 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
21009 adjust_window_ends (w, last_text_row, false);
21010 eassert
21011 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
21012 w->window_end_vpos)));
21013 }
21014 else
21015 {
21016 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21017 w->window_end_pos = Z - ZV;
21018 w->window_end_vpos = 0;
21019 }
21020
21021
21022 w->window_end_valid = false;
21023 return 1;
21024 }
21025
21026
21027
21028
21029
21030
21031
21032
21033
21034
21035
21036
21037 static bool
21038 try_window_reusing_current_matrix (struct window *w)
21039 {
21040 struct frame *f = XFRAME (w->frame);
21041 struct glyph_row *bottom_row;
21042 struct it it;
21043 struct run run;
21044 struct text_pos start, new_start;
21045 int nrows_scrolled, i;
21046 struct glyph_row *last_text_row;
21047 struct glyph_row *last_reused_text_row;
21048 struct glyph_row *start_row;
21049 int start_vpos, min_y, max_y;
21050
21051 #ifdef GLYPH_DEBUG
21052 if (inhibit_try_window_reusing)
21053 return false;
21054 #endif
21055
21056 if (
21057 !FRAME_WINDOW_P (f)
21058
21059
21060 || windows_or_buffers_changed
21061 || f->cursor_type_changed
21062
21063
21064
21065 || overlay_arrow_in_current_buffer_p ())
21066 return false;
21067
21068
21069 if (!NILP (Vshow_trailing_whitespace))
21070 return false;
21071
21072
21073 if (window_wants_tab_line (w)
21074 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
21075 return false;
21076
21077
21078 if (window_wants_header_line (w)
21079 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
21080 return false;
21081
21082
21083
21084 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21085 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
21086 return false;
21087
21088
21089 clear_glyph_matrix (w->desired_matrix);
21090
21091
21092
21093
21094 if (!NILP (Vdisplay_line_numbers))
21095 return false;
21096
21097
21098
21099
21100 #ifdef HAVE_NTGUI
21101 if (w32_use_visible_system_caret)
21102 return false;
21103 #endif
21104
21105
21106
21107 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
21108 start = start_row->minpos;
21109 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21110
21111 if (CHARPOS (new_start) <= CHARPOS (start))
21112 {
21113
21114
21115
21116
21117 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
21118 return false;
21119
21120 IF_DEBUG (debug_method_add (w, "twu1"));
21121
21122
21123
21124
21125
21126 start_display (&it, w, new_start);
21127 w->cursor.vpos = -1;
21128 last_text_row = last_reused_text_row = NULL;
21129
21130 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21131 {
21132
21133
21134
21135
21136 while (IT_CHARPOS (it) > CHARPOS (start))
21137 {
21138
21139 start_row++;
21140 start = start_row->minpos;
21141
21142 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
21143 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
21144 || CHARPOS (start) == ZV)
21145 {
21146 clear_glyph_matrix (w->desired_matrix);
21147 return false;
21148 }
21149
21150 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21151 }
21152
21153
21154 if (IT_CHARPOS (it) == CHARPOS (start)
21155
21156
21157
21158
21159
21160 && it.current.dpvec_index < 0)
21161 break;
21162
21163 it.glyph_row->reversed_p = false;
21164 if (display_line (&it, -1))
21165 last_text_row = it.glyph_row - 1;
21166
21167 }
21168
21169
21170
21171
21172 if (it.current_y < it.last_visible_y)
21173 {
21174 struct glyph_row *row;
21175
21176
21177 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
21178
21179
21180 if (w->cursor.vpos < 0)
21181 {
21182 int dy = it.current_y - start_row->y;
21183
21184 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21185 row = row_containing_pos (w, PT, row, NULL, dy);
21186 if (row)
21187 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
21188 dy, nrows_scrolled);
21189 else
21190 {
21191 clear_glyph_matrix (w->desired_matrix);
21192 return false;
21193 }
21194 }
21195
21196
21197
21198
21199
21200
21201
21202 run.current_y = start_row->y;
21203 run.desired_y = it.current_y;
21204 run.height = it.last_visible_y - it.current_y;
21205
21206 if (run.height > 0 && run.current_y != run.desired_y)
21207 {
21208 #ifdef HAVE_WINDOW_SYSTEM
21209 update_begin (f);
21210 gui_update_window_begin (w);
21211 FRAME_RIF (f)->clear_window_mouse_face (w);
21212 FRAME_RIF (f)->scroll_run_hook (w, &run);
21213 gui_update_window_end (w, false, false);
21214 update_end (f);
21215 #endif
21216 }
21217
21218
21219 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21220 rotate_matrix (w->current_matrix,
21221 start_vpos,
21222 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21223 nrows_scrolled);
21224
21225
21226 for (i = 0; i < nrows_scrolled; ++i)
21227 (start_row + i)->enabled_p = false;
21228
21229
21230 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21231 max_y = it.last_visible_y;
21232 for (row = start_row + nrows_scrolled;
21233 row < bottom_row;
21234 ++row)
21235 {
21236 row->y = it.current_y;
21237 row->visible_height = row->height;
21238
21239 if (row->y < min_y)
21240 row->visible_height -= min_y - row->y;
21241 if (row->y + row->height > max_y)
21242 row->visible_height -= row->y + row->height - max_y;
21243 if (row->fringe_bitmap_periodic_p)
21244 row->redraw_fringe_bitmaps_p = true;
21245
21246 it.current_y += row->height;
21247
21248 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21249 last_reused_text_row = row;
21250 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21251 break;
21252 }
21253
21254
21255
21256 for (++row; row < bottom_row; ++row)
21257 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21258 }
21259
21260
21261
21262
21263
21264 if (last_reused_text_row)
21265 adjust_window_ends (w, last_reused_text_row, true);
21266 else if (last_text_row)
21267 adjust_window_ends (w, last_text_row, false);
21268 else
21269 {
21270
21271 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21272 w->window_end_pos = Z - ZV;
21273 w->window_end_vpos = 0;
21274 }
21275 w->window_end_valid = false;
21276
21277
21278 w->desired_matrix->no_scrolling_p = true;
21279
21280 #ifdef GLYPH_DEBUG
21281 debug_method_add (w, "try_window_reusing_current_matrix 1");
21282 #endif
21283 return true;
21284 }
21285 else if (CHARPOS (new_start) > CHARPOS (start))
21286 {
21287 struct glyph_row *pt_row, *row;
21288 struct glyph_row *first_reusable_row;
21289 struct glyph_row *first_row_to_display;
21290 int dy;
21291 int yb = window_text_bottom_y (w);
21292
21293
21294
21295 first_reusable_row = start_row;
21296 while (first_reusable_row->enabled_p
21297 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21298 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21299 < CHARPOS (new_start)))
21300 ++first_reusable_row;
21301
21302
21303 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21304 || !first_reusable_row->enabled_p
21305 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21306 != CHARPOS (new_start)))
21307 return false;
21308
21309
21310
21311
21312
21313 pt_row = NULL;
21314 for (first_row_to_display = first_reusable_row;
21315 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21316 ++first_row_to_display)
21317 {
21318 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21319 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21320 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21321 && first_row_to_display->ends_at_zv_p
21322 && pt_row == NULL)))
21323 pt_row = first_row_to_display;
21324 }
21325
21326 if (first_row_to_display->y >= yb)
21327 return false;
21328
21329
21330 init_to_row_start (&it, w, first_row_to_display);
21331
21332 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21333 - start_vpos);
21334 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21335 - nrows_scrolled);
21336 it.current_y = (first_row_to_display->y - first_reusable_row->y
21337 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21338
21339
21340
21341
21342 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21343 if (pt_row == NULL)
21344 w->cursor.vpos = -1;
21345 last_text_row = NULL;
21346 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21347 if (display_line (&it, w->cursor.vpos))
21348 last_text_row = it.glyph_row - 1;
21349
21350
21351
21352 if (pt_row)
21353 {
21354 w->cursor.vpos -= nrows_scrolled;
21355 w->cursor.y -= first_reusable_row->y - start_row->y;
21356 }
21357
21358
21359
21360
21361
21362 if (w->cursor.vpos < 0)
21363 {
21364 clear_glyph_matrix (w->desired_matrix);
21365 return false;
21366 }
21367
21368
21369 run.current_y = first_reusable_row->y;
21370 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21371 run.height = it.last_visible_y - run.current_y;
21372 dy = run.current_y - run.desired_y;
21373
21374 if (run.height)
21375 {
21376 #ifdef HAVE_WINDOW_SYSTEM
21377 update_begin (f);
21378 gui_update_window_begin (w);
21379 FRAME_RIF (f)->clear_window_mouse_face (w);
21380 FRAME_RIF (f)->scroll_run_hook (w, &run);
21381 gui_update_window_end (w, false, false);
21382 update_end (f);
21383 #endif
21384 }
21385
21386
21387 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21388 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21389 max_y = it.last_visible_y;
21390 for (row = first_reusable_row; row < first_row_to_display; ++row)
21391 {
21392 row->y -= dy;
21393 row->visible_height = row->height;
21394 if (row->y < min_y)
21395 row->visible_height -= min_y - row->y;
21396 if (row->y + row->height > max_y)
21397 row->visible_height -= row->y + row->height - max_y;
21398 if (row->fringe_bitmap_periodic_p)
21399 row->redraw_fringe_bitmaps_p = true;
21400 }
21401
21402
21403 eassert (nrows_scrolled > 0);
21404 rotate_matrix (w->current_matrix,
21405 start_vpos,
21406 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21407 -nrows_scrolled);
21408
21409
21410 for (row -= nrows_scrolled; row < bottom_row; ++row)
21411 row->enabled_p = false;
21412
21413
21414
21415 if (pt_row)
21416 {
21417 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21418 row < bottom_row
21419 && PT >= MATRIX_ROW_END_CHARPOS (row)
21420 && !row->ends_at_zv_p;
21421 row++)
21422 {
21423 w->cursor.vpos++;
21424 w->cursor.y = row->y;
21425 }
21426 if (row < bottom_row)
21427 {
21428
21429
21430
21431
21432 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21433 {
21434 if (!set_cursor_from_row (w, row, w->current_matrix,
21435 0, 0, 0, 0))
21436 {
21437 clear_glyph_matrix (w->desired_matrix);
21438 return false;
21439 }
21440 }
21441 else
21442 {
21443 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21444 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21445
21446 for (; glyph < end
21447 && (!BUFFERP (glyph->object)
21448 || glyph->charpos < PT);
21449 glyph++)
21450 {
21451 w->cursor.hpos++;
21452 w->cursor.x += glyph->pixel_width;
21453 }
21454 }
21455 }
21456 }
21457
21458
21459
21460
21461 if (last_text_row)
21462 adjust_window_ends (w, last_text_row, false);
21463 else
21464 w->window_end_vpos -= nrows_scrolled;
21465
21466 w->window_end_valid = false;
21467 w->desired_matrix->no_scrolling_p = true;
21468
21469 #ifdef GLYPH_DEBUG
21470 debug_method_add (w, "try_window_reusing_current_matrix 2");
21471 #endif
21472 return true;
21473 }
21474
21475 return false;
21476 }
21477
21478
21479
21480
21481
21482
21483
21484 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21485 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21486 ptrdiff_t *, ptrdiff_t *);
21487 static struct glyph_row *
21488 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21489 struct glyph_row *);
21490
21491
21492
21493
21494
21495
21496
21497 static struct glyph_row *
21498 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21499 struct glyph_row *start)
21500 {
21501 struct glyph_row *row, *row_found;
21502
21503
21504
21505
21506 row_found = NULL;
21507 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21508 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21509 {
21510 eassert (row->enabled_p);
21511 row_found = row;
21512 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21513 break;
21514 ++row;
21515 }
21516
21517 return row_found;
21518 }
21519
21520
21521
21522
21523
21524
21525
21526
21527
21528
21529
21530
21531 static struct glyph_row *
21532 find_last_unchanged_at_beg_row (struct window *w)
21533 {
21534 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21535 struct glyph_row *row;
21536 struct glyph_row *row_found = NULL;
21537 int yb = window_text_bottom_y (w);
21538
21539
21540 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21541 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21542 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21543 ++row)
21544 {
21545 if (
21546
21547 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21548
21549
21550 && !row->ends_at_zv_p
21551
21552
21553
21554 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21555 && (row->continued_p
21556 || row->exact_window_width_line_p))
21557
21558
21559
21560
21561
21562
21563
21564 && CHARPOS (row->end.pos) <= ZV)
21565 row_found = row;
21566
21567
21568 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21569 break;
21570 }
21571
21572 return row_found;
21573 }
21574
21575
21576
21577
21578
21579
21580
21581
21582
21583
21584
21585
21586
21587
21588 static struct glyph_row *
21589 find_first_unchanged_at_end_row (struct window *w,
21590 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21591 {
21592 struct glyph_row *row;
21593 struct glyph_row *row_found = NULL;
21594
21595 *delta = *delta_bytes = 0;
21596
21597
21598
21599 eassert (w->window_end_valid);
21600
21601
21602
21603
21604 if (w->window_end_pos >= END_UNCHANGED)
21605 return NULL;
21606
21607
21608 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21609
21610
21611 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21612 {
21613
21614
21615
21616
21617
21618 ptrdiff_t Z_old =
21619 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21620 ptrdiff_t Z_BYTE_old =
21621 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21622 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21623 struct glyph_row *first_text_row
21624 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21625
21626 *delta = Z - Z_old;
21627 *delta_bytes = Z_BYTE - Z_BYTE_old;
21628
21629
21630
21631
21632
21633
21634
21635 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21636 last_unchanged_pos_old = last_unchanged_pos - *delta;
21637
21638
21639
21640 for (; row > first_text_row; --row)
21641 {
21642
21643
21644 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21645 break;
21646
21647 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21648 row_found = row;
21649 }
21650 }
21651
21652 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21653
21654 return row_found;
21655 }
21656
21657
21658
21659
21660
21661
21662
21663
21664 static void
21665 sync_frame_with_window_matrix_rows (struct window *w)
21666 {
21667 struct frame *f = XFRAME (w->frame);
21668 struct glyph_row *window_row, *window_row_end, *frame_row;
21669
21670
21671
21672 eassert (BUFFERP (w->contents));
21673 eassert (WINDOW_FULL_WIDTH_P (w));
21674 eassert (!FRAME_WINDOW_P (f));
21675
21676
21677
21678
21679
21680 window_row = w->current_matrix->rows;
21681 window_row_end = window_row + w->current_matrix->nrows;
21682 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21683 while (window_row < window_row_end)
21684 {
21685 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21686 struct glyph *end = window_row->glyphs[LAST_AREA];
21687
21688 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21689 frame_row->glyphs[TEXT_AREA] = start;
21690 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21691 frame_row->glyphs[LAST_AREA] = end;
21692
21693
21694
21695 if (!window_row->enabled_p)
21696 frame_row->enabled_p = false;
21697
21698 ++window_row, ++frame_row;
21699 }
21700 }
21701
21702
21703
21704
21705
21706
21707
21708 struct glyph_row *
21709 row_containing_pos (struct window *w, ptrdiff_t charpos,
21710 struct glyph_row *start, struct glyph_row *end, int dy)
21711 {
21712 struct glyph_row *row = start;
21713 struct glyph_row *best_row = NULL;
21714 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21715 int last_y;
21716
21717
21718 if (row->tab_line_p)
21719 ++row;
21720 if (row->mode_line_p)
21721 ++row;
21722
21723 if ((end && row >= end) || !row->enabled_p)
21724 return NULL;
21725
21726 last_y = window_text_bottom_y (w) - dy;
21727
21728 while (true)
21729 {
21730
21731 if ((end && row >= end) || !row->enabled_p)
21732 return NULL;
21733
21734
21735
21736 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21737 return NULL;
21738
21739
21740 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21741 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21742
21743
21744
21745
21746 && !row_for_charpos_p (row, charpos)))
21747 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21748 {
21749 struct glyph *g;
21750
21751 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21752 || (!best_row && !row->continued_p))
21753 return row;
21754
21755
21756
21757
21758 for (g = row->glyphs[TEXT_AREA];
21759 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21760 g++)
21761 {
21762 if (!STRINGP (g->object))
21763 {
21764 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21765 {
21766 mindif = eabs (g->charpos - charpos);
21767 best_row = row;
21768
21769 if (mindif == 0)
21770 return best_row;
21771 }
21772 }
21773 }
21774 }
21775 else if (best_row && !row->continued_p)
21776 return best_row;
21777 ++row;
21778 }
21779 }
21780
21781
21782
21783
21784
21785
21786
21787
21788
21789
21790
21791
21792
21793
21794
21795
21796
21797
21798
21799
21800
21801
21802
21803
21804
21805
21806
21807
21808
21809
21810
21811
21812
21813
21814
21815
21816
21817
21818
21819
21820
21821
21822
21823
21824 static int
21825 try_window_id (struct window *w)
21826 {
21827 struct frame *f = XFRAME (w->frame);
21828 struct glyph_matrix *current_matrix = w->current_matrix;
21829 struct glyph_matrix *desired_matrix = w->desired_matrix;
21830 struct glyph_row *last_unchanged_at_beg_row;
21831 struct glyph_row *first_unchanged_at_end_row;
21832 struct glyph_row *row;
21833 struct glyph_row *bottom_row;
21834 int bottom_vpos;
21835 struct it it;
21836 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21837 int dvpos, dy;
21838 struct text_pos start_pos;
21839 struct run run;
21840 int first_unchanged_at_end_vpos = 0;
21841 struct glyph_row *last_text_row, *last_text_row_at_end;
21842 struct text_pos start;
21843 ptrdiff_t first_changed_charpos, last_changed_charpos;
21844
21845 #ifdef GLYPH_DEBUG
21846 if (inhibit_try_window_id)
21847 return 0;
21848 #endif
21849
21850
21851 #if false
21852 #define GIVE_UP(X) \
21853 do { \
21854 redisplay_trace ("try_window_id give up %d\n", X); \
21855 return 0; \
21856 } while (false)
21857 #else
21858 #define GIVE_UP(X) return 0
21859 #endif
21860
21861 SET_TEXT_POS_FROM_MARKER (start, w->start);
21862
21863
21864
21865 if (MINI_WINDOW_P (w))
21866 GIVE_UP (1);
21867
21868
21869 if (windows_or_buffers_changed || f->cursor_type_changed)
21870 GIVE_UP (2);
21871
21872
21873
21874
21875 if (w->last_overlay_modified != OVERLAY_MODIFF)
21876 GIVE_UP (200);
21877
21878
21879
21880
21881
21882 if (current_buffer->clip_changed
21883 || current_buffer->prevent_redisplay_optimizations_p)
21884 GIVE_UP (3);
21885
21886
21887 if (!FRAME_WINDOW_P (f)
21888 && (!FRAME_LINE_INS_DEL_OK (f)
21889 || !WINDOW_FULL_WIDTH_P (w)))
21890 GIVE_UP (4);
21891
21892
21893 if (PT < CHARPOS (start))
21894 GIVE_UP (5);
21895
21896
21897 if (w->last_modified == 0)
21898 GIVE_UP (6);
21899
21900
21901 if (w->hscroll != 0)
21902 GIVE_UP (7);
21903
21904
21905 if (!w->window_end_valid)
21906 GIVE_UP (8);
21907
21908
21909 if (!NILP (Vshow_trailing_whitespace))
21910 GIVE_UP (11);
21911
21912
21913
21914 if (overlay_arrows_changed_p (false))
21915 GIVE_UP (12);
21916
21917
21918
21919
21920
21921 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21922 GIVE_UP (21);
21923
21924
21925
21926
21927
21928
21929
21930
21931
21932 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21933 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21934 GIVE_UP (22);
21935
21936
21937
21938 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21939 GIVE_UP (23);
21940
21941
21942
21943 if (EQ (Vdisplay_line_numbers, Qrelative)
21944 || EQ (Vdisplay_line_numbers, Qvisual)
21945 || (!NILP (Vdisplay_line_numbers)
21946 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21947 Qline_number_current_line,
21948 w->frame))))
21949 GIVE_UP (24);
21950
21951
21952
21953
21954 if (composition_break_at_point)
21955 GIVE_UP (27);
21956
21957
21958
21959
21960
21961 if (MODIFF > SAVE_MODIFF
21962
21963 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21964 {
21965 if (GPT - BEG < BEG_UNCHANGED)
21966 BEG_UNCHANGED = GPT - BEG;
21967 if (Z - GPT < END_UNCHANGED)
21968 END_UNCHANGED = Z - GPT;
21969 }
21970
21971
21972 first_changed_charpos = BEG + BEG_UNCHANGED;
21973 last_changed_charpos = Z - END_UNCHANGED;
21974
21975
21976
21977
21978
21979
21980 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21981 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21982 && ((last_changed_charpos < CHARPOS (start)
21983 && CHARPOS (start) == BEGV)
21984 || (last_changed_charpos < CHARPOS (start) - 1
21985 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21986 {
21987 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21988 struct glyph_row *r0;
21989
21990
21991
21992 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21993 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21994 Z_delta = Z - Z_old;
21995 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
21996
21997
21998
21999
22000 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
22001 GIVE_UP (13);
22002
22003
22004
22005
22006 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
22007 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
22008 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
22009
22010 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
22011 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
22012 {
22013
22014 if (Z_delta || Z_delta_bytes)
22015 {
22016 struct glyph_row *r1
22017 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22018 increment_matrix_positions (w->current_matrix,
22019 MATRIX_ROW_VPOS (r0, current_matrix),
22020 MATRIX_ROW_VPOS (r1, current_matrix),
22021 Z_delta, Z_delta_bytes);
22022 }
22023
22024
22025 row = row_containing_pos (w, PT, r0, NULL, 0);
22026 if (row)
22027 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
22028 return 1;
22029 }
22030 }
22031
22032
22033
22034
22035
22036 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
22037
22038
22039 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
22040 || first_changed_charpos == last_changed_charpos))
22041 {
22042 struct glyph_row *r0;
22043
22044
22045
22046
22047 if (PT >= MATRIX_ROW_END_CHARPOS (row))
22048 GIVE_UP (14);
22049
22050
22051
22052
22053 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
22054 if (TEXT_POS_EQUAL_P (start, r0->minpos)
22055
22056 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
22057 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
22058 {
22059
22060
22061 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22062 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22063
22064
22065 row = row_containing_pos (w, PT, r0, NULL, 0);
22066 if (row)
22067 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
22068 return 2;
22069 }
22070 }
22071
22072
22073
22074
22075
22076
22077
22078
22079 if (CHARPOS (start) >= first_changed_charpos
22080 && CHARPOS (start) <= last_changed_charpos)
22081 GIVE_UP (15);
22082
22083
22084
22085
22086
22087 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
22088 if (!TEXT_POS_EQUAL_P (start, row->minpos))
22089 GIVE_UP (16);
22090
22091
22092
22093 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
22094 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
22095 GIVE_UP (20);
22096
22097
22098
22099
22100
22101 #ifdef HAVE_NTGUI
22102 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
22103 GIVE_UP (25);
22104 #endif
22105
22106
22107
22108
22109
22110
22111
22112 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
22113 if (last_unchanged_at_beg_row)
22114 {
22115
22116
22117
22118
22119 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
22120 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
22121 && last_unchanged_at_beg_row > w->current_matrix->rows)
22122 --last_unchanged_at_beg_row;
22123
22124 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
22125 GIVE_UP (17);
22126
22127 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
22128 GIVE_UP (18);
22129
22130
22131
22132 if (it.sp > 1
22133 && it.method == GET_FROM_IMAGE && it.image_id == -1)
22134 GIVE_UP (26);
22135 start_pos = it.current.pos;
22136
22137
22138
22139
22140 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
22141 current_matrix);
22142 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22143 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
22144
22145 eassert (it.hpos == 0 && it.current_x == 0);
22146 }
22147 else
22148 {
22149
22150
22151 start_display (&it, w, start);
22152 it.vpos = it.first_vpos;
22153 start_pos = it.current.pos;
22154 }
22155
22156
22157
22158
22159
22160
22161
22162 first_unchanged_at_end_row
22163 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
22164 IF_DEBUG (debug_delta = delta);
22165 IF_DEBUG (debug_delta_bytes = delta_bytes);
22166
22167
22168
22169
22170
22171
22172 stop_pos = 0;
22173 if (first_unchanged_at_end_row)
22174 {
22175 eassert (last_unchanged_at_beg_row == NULL
22176 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
22177
22178
22179
22180
22181
22182 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
22183 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22184 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22185 < it.last_visible_y))
22186 ++first_unchanged_at_end_row;
22187
22188 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22189 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22190 >= it.last_visible_y))
22191 first_unchanged_at_end_row = NULL;
22192 else
22193 {
22194 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
22195 + delta);
22196 first_unchanged_at_end_vpos
22197 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
22198 eassert (stop_pos >= Z - END_UNCHANGED);
22199 }
22200 }
22201 else if (last_unchanged_at_beg_row == NULL)
22202 GIVE_UP (19);
22203
22204
22205 #ifdef GLYPH_DEBUG
22206
22207
22208
22209
22210 eassert (first_unchanged_at_end_row == NULL
22211 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22212
22213 debug_last_unchanged_at_beg_vpos
22214 = (last_unchanged_at_beg_row
22215 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
22216 : -1);
22217 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
22218
22219 #endif
22220
22221
22222
22223
22224
22225 w->cursor.vpos = -1;
22226 last_text_row = NULL;
22227 overlay_arrow_seen = false;
22228 if (it.current_y < it.last_visible_y
22229 && !f->fonts_changed
22230 && (first_unchanged_at_end_row == NULL
22231 || IT_CHARPOS (it) < stop_pos))
22232 it.glyph_row->reversed_p = false;
22233 while (it.current_y < it.last_visible_y
22234 && !f->fonts_changed
22235 && (first_unchanged_at_end_row == NULL
22236 || IT_CHARPOS (it) < stop_pos))
22237 {
22238 if (display_line (&it, -1))
22239 last_text_row = it.glyph_row - 1;
22240 }
22241
22242 if (f->fonts_changed)
22243 return -1;
22244
22245
22246
22247
22248
22249
22250
22251
22252
22253
22254
22255 if (!w->window_end_valid)
22256 {
22257 clear_glyph_matrix (w->desired_matrix);
22258 return -1;
22259 }
22260
22261
22262
22263
22264 if (first_unchanged_at_end_row
22265
22266
22267 && it.current_y < it.last_visible_y)
22268 {
22269 dvpos = (it.vpos
22270 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22271 current_matrix));
22272 dy = it.current_y - first_unchanged_at_end_row->y;
22273 run.current_y = first_unchanged_at_end_row->y;
22274 run.desired_y = run.current_y + dy;
22275 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22276 }
22277 else
22278 {
22279 delta = delta_bytes = dvpos = dy
22280 = run.current_y = run.desired_y = run.height = 0;
22281 first_unchanged_at_end_row = NULL;
22282 }
22283 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22284
22285
22286
22287
22288
22289
22290
22291
22292
22293
22294 if (w->cursor.vpos < 0)
22295 {
22296
22297 if (PT < CHARPOS (start_pos)
22298 && last_unchanged_at_beg_row)
22299 {
22300 row = row_containing_pos (w, PT,
22301 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22302 last_unchanged_at_beg_row + 1, 0);
22303 if (row)
22304 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22305 }
22306
22307
22308 else if (first_unchanged_at_end_row)
22309 {
22310 row = row_containing_pos (w, PT - delta,
22311 first_unchanged_at_end_row, NULL, 0);
22312 if (row)
22313 set_cursor_from_row (w, row, w->current_matrix, delta,
22314 delta_bytes, dy, dvpos);
22315 }
22316
22317
22318 if (w->cursor.vpos < 0)
22319 {
22320 clear_glyph_matrix (w->desired_matrix);
22321 return -1;
22322 }
22323 }
22324
22325
22326 {
22327 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22328 int bot_scroll_margin = top_scroll_margin;
22329 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22330
22331 if (window_wants_header_line (w))
22332 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22333 if (window_wants_tab_line (w))
22334 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22335
22336 if ((w->cursor.y < top_scroll_margin
22337 && CHARPOS (start) > BEGV)
22338
22339
22340 || (w->cursor.y
22341 + (cursor_row_fully_visible_p (w, false, true, true)
22342 ? 1
22343 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22344 {
22345 w->cursor.vpos = -1;
22346 clear_glyph_matrix (w->desired_matrix);
22347 return -1;
22348 }
22349 }
22350
22351
22352
22353
22354 if (dy && run.height)
22355 {
22356 update_begin (f);
22357
22358 if (FRAME_WINDOW_P (f))
22359 {
22360 #ifdef HAVE_WINDOW_SYSTEM
22361 gui_update_window_begin (w);
22362 FRAME_RIF (f)->clear_window_mouse_face (w);
22363 FRAME_RIF (f)->scroll_run_hook (w, &run);
22364 gui_update_window_end (w, false, false);
22365 #endif
22366 }
22367 else
22368 {
22369
22370
22371 int from_vpos
22372 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22373 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22374 int end = (WINDOW_TOP_EDGE_LINE (w)
22375 + window_wants_tab_line (w)
22376 + window_wants_header_line (w)
22377 + window_internal_height (w));
22378
22379 gui_clear_window_mouse_face (w);
22380
22381
22382 if (dvpos > 0)
22383 {
22384
22385
22386 set_terminal_window (f, end);
22387
22388
22389
22390 if (!FRAME_SCROLL_REGION_OK (f))
22391 ins_del_lines (f, end - dvpos, -dvpos);
22392
22393
22394
22395 ins_del_lines (f, from, dvpos);
22396 }
22397 else if (dvpos < 0)
22398 {
22399
22400
22401 set_terminal_window (f, end);
22402
22403
22404
22405
22406
22407 ins_del_lines (f, from + dvpos, dvpos);
22408
22409
22410
22411 if (!FRAME_SCROLL_REGION_OK (f))
22412 ins_del_lines (f, end + dvpos, -dvpos);
22413 }
22414
22415 set_terminal_window (f, 0);
22416 }
22417
22418 update_end (f);
22419 }
22420
22421
22422
22423
22424 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22425 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22426 if (dvpos < 0)
22427 {
22428 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22429 bottom_vpos, dvpos);
22430 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22431 bottom_vpos);
22432 }
22433 else if (dvpos > 0)
22434 {
22435 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22436 bottom_vpos, dvpos);
22437 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22438 first_unchanged_at_end_vpos + dvpos);
22439 }
22440
22441
22442
22443 if (!FRAME_WINDOW_P (f))
22444 sync_frame_with_window_matrix_rows (w);
22445
22446
22447 if (delta || delta_bytes)
22448 increment_matrix_positions (current_matrix,
22449 first_unchanged_at_end_vpos + dvpos,
22450 bottom_vpos, delta, delta_bytes);
22451
22452
22453 if (dy)
22454 shift_glyph_matrix (w, current_matrix,
22455 first_unchanged_at_end_vpos + dvpos,
22456 bottom_vpos, dy);
22457
22458 if (first_unchanged_at_end_row)
22459 {
22460 first_unchanged_at_end_row += dvpos;
22461 if (first_unchanged_at_end_row->y >= it.last_visible_y
22462 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22463 first_unchanged_at_end_row = NULL;
22464 }
22465
22466
22467
22468 last_text_row_at_end = NULL;
22469 if (dy < 0)
22470 {
22471
22472
22473
22474
22475
22476 int last_vpos = w->window_end_vpos + dvpos;
22477 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22478
22479
22480 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22481
22482
22483
22484
22485 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22486 {
22487 init_to_row_start (&it, w, last_row);
22488 it.vpos = last_vpos;
22489 it.current_y = last_row->y;
22490 }
22491 else
22492 {
22493 init_to_row_end (&it, w, last_row);
22494 it.vpos = 1 + last_vpos;
22495 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22496 ++last_row;
22497 }
22498
22499
22500
22501 it.continuation_lines_width = last_row->continuation_lines_width;
22502 it.hpos = it.current_x = 0;
22503
22504
22505 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22506 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22507 {
22508
22509
22510
22511
22512 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22513 if (display_line (&it, w->cursor.vpos))
22514 last_text_row_at_end = it.glyph_row - 1;
22515 }
22516 }
22517
22518
22519 if (first_unchanged_at_end_row && !last_text_row_at_end)
22520 {
22521
22522
22523
22524
22525 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22526 row = find_last_row_displaying_text (w->current_matrix, &it,
22527 first_unchanged_at_end_row);
22528 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22529 adjust_window_ends (w, row, true);
22530 eassert (w->window_end_bytepos >= 0);
22531 IF_DEBUG (debug_method_add (w, "A"));
22532 }
22533 else if (last_text_row_at_end)
22534 {
22535 adjust_window_ends (w, last_text_row_at_end, false);
22536 eassert (w->window_end_bytepos >= 0);
22537 IF_DEBUG (debug_method_add (w, "B"));
22538 }
22539 else if (last_text_row)
22540 {
22541
22542
22543
22544 adjust_window_ends (w, last_text_row, false);
22545 eassert (w->window_end_bytepos >= 0);
22546 }
22547 else if (first_unchanged_at_end_row == NULL
22548 && last_text_row == NULL
22549 && last_text_row_at_end == NULL)
22550 {
22551
22552
22553 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22554 int vpos = w->window_end_vpos;
22555 struct glyph_row *current_row = current_matrix->rows + vpos;
22556 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22557
22558 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22559 {
22560 eassert (first_vpos <= vpos);
22561 if (desired_row->enabled_p)
22562 {
22563 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22564 row = desired_row;
22565 }
22566 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22567 row = current_row;
22568 }
22569
22570 w->window_end_vpos = vpos + 1;
22571 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22572 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22573 eassert (w->window_end_bytepos >= 0);
22574 IF_DEBUG (debug_method_add (w, "C"));
22575 }
22576 else
22577 emacs_abort ();
22578
22579 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22580 debug_end_vpos = w->window_end_vpos));
22581
22582
22583 w->window_end_valid = false;
22584 w->desired_matrix->no_scrolling_p = true;
22585 return 3;
22586
22587 #undef GIVE_UP
22588 }
22589
22590
22591
22592
22593
22594
22595
22596 #ifdef GLYPH_DEBUG
22597
22598 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22599 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22600 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22601
22602
22603
22604
22605
22606
22607
22608
22609 void
22610 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22611 {
22612 int i;
22613 for (i = 0; i < matrix->nrows; ++i)
22614 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22615 }
22616
22617
22618
22619
22620
22621 void
22622 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22623 {
22624 if (glyph->type == CHAR_GLYPH
22625 || glyph->type == GLYPHLESS_GLYPH)
22626 {
22627 fprintf (stderr,
22628 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22629 glyph - row->glyphs[TEXT_AREA],
22630 (glyph->type == CHAR_GLYPH
22631 ? 'C'
22632 : 'G'),
22633 glyph->charpos,
22634 (BUFFERP (glyph->object)
22635 ? 'B'
22636 : (STRINGP (glyph->object)
22637 ? 'S'
22638 : (NILP (glyph->object)
22639 ? '0'
22640 : '-'))),
22641 glyph->pixel_width,
22642 glyph->u.ch,
22643 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22644 ? (int) glyph->u.ch
22645 : '.'),
22646 glyph->face_id,
22647 glyph->left_box_line_p,
22648 glyph->right_box_line_p);
22649 }
22650 else if (glyph->type == STRETCH_GLYPH)
22651 {
22652 fprintf (stderr,
22653 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22654 glyph - row->glyphs[TEXT_AREA],
22655 'S',
22656 glyph->charpos,
22657 (BUFFERP (glyph->object)
22658 ? 'B'
22659 : (STRINGP (glyph->object)
22660 ? 'S'
22661 : (NILP (glyph->object)
22662 ? '0'
22663 : '-'))),
22664 glyph->pixel_width,
22665 0u,
22666 ' ',
22667 glyph->face_id,
22668 glyph->left_box_line_p,
22669 glyph->right_box_line_p);
22670 }
22671 else if (glyph->type == IMAGE_GLYPH)
22672 {
22673 fprintf (stderr,
22674 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22675 glyph - row->glyphs[TEXT_AREA],
22676 'I',
22677 glyph->charpos,
22678 (BUFFERP (glyph->object)
22679 ? 'B'
22680 : (STRINGP (glyph->object)
22681 ? 'S'
22682 : (NILP (glyph->object)
22683 ? '0'
22684 : '-'))),
22685 glyph->pixel_width,
22686 (unsigned int) glyph->u.img_id,
22687 '.',
22688 glyph->face_id,
22689 glyph->left_box_line_p,
22690 glyph->right_box_line_p);
22691 }
22692 else if (glyph->type == COMPOSITE_GLYPH)
22693 {
22694 fprintf (stderr,
22695 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22696 glyph - row->glyphs[TEXT_AREA],
22697 '+',
22698 glyph->charpos,
22699 (BUFFERP (glyph->object)
22700 ? 'B'
22701 : (STRINGP (glyph->object)
22702 ? 'S'
22703 : (NILP (glyph->object)
22704 ? '0'
22705 : '-'))),
22706 glyph->pixel_width,
22707 (unsigned int) glyph->u.cmp.id);
22708 if (glyph->u.cmp.automatic)
22709 fprintf (stderr,
22710 "[%d-%d]",
22711 glyph->slice.cmp.from, glyph->slice.cmp.to);
22712 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22713 glyph->face_id,
22714 glyph->left_box_line_p,
22715 glyph->right_box_line_p);
22716 }
22717 else if (glyph->type == XWIDGET_GLYPH)
22718 {
22719 #ifndef HAVE_XWIDGETS
22720 eassume (false);
22721 #else
22722 fprintf (stderr,
22723 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22724 glyph - row->glyphs[TEXT_AREA],
22725 'X',
22726 glyph->charpos,
22727 (BUFFERP (glyph->object)
22728 ? 'B'
22729 : (STRINGP (glyph->object)
22730 ? 'S'
22731 : '-')),
22732 glyph->pixel_width,
22733 glyph->u.xwidget,
22734 '.',
22735 glyph->face_id,
22736 glyph->left_box_line_p,
22737 glyph->right_box_line_p);
22738 #endif
22739 }
22740 }
22741
22742
22743
22744
22745
22746
22747
22748 void
22749 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22750 {
22751 if (glyphs != 1)
22752 {
22753 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22754 "==============================================================================\n"),
22755 stderr);
22756 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22757 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22758 vpos,
22759 MATRIX_ROW_START_CHARPOS (row),
22760 MATRIX_ROW_END_CHARPOS (row),
22761 row->used[TEXT_AREA],
22762 row->contains_overlapping_glyphs_p,
22763 row->enabled_p,
22764 row->truncated_on_left_p,
22765 row->truncated_on_right_p,
22766 row->continued_p,
22767 MATRIX_ROW_CONTINUATION_LINE_P (row),
22768 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22769 row->ends_at_zv_p,
22770 row->fill_line_p,
22771 row->ends_in_middle_of_char_p,
22772 row->starts_in_middle_of_char_p,
22773 row->mouse_face_p,
22774 row->x,
22775 row->y,
22776 row->pixel_width,
22777 row->height,
22778 row->visible_height,
22779 row->ascent,
22780 row->phys_ascent);
22781
22782 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22783 row->end.overlay_string_index,
22784 row->continuation_lines_width);
22785 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22786 CHARPOS (row->start.string_pos),
22787 CHARPOS (row->end.string_pos));
22788 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22789 row->end.dpvec_index);
22790 }
22791
22792 if (glyphs > 1)
22793 {
22794 int area;
22795
22796 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22797 {
22798 struct glyph *glyph = row->glyphs[area];
22799 struct glyph *glyph_end = glyph + row->used[area];
22800
22801
22802 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22803 ++glyph_end;
22804
22805 if (glyph < glyph_end)
22806 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22807 stderr);
22808
22809 for (; glyph < glyph_end; ++glyph)
22810 dump_glyph (row, glyph, area);
22811 }
22812 }
22813 else if (glyphs == 1)
22814 {
22815 int area;
22816 char s[SHRT_MAX + 4];
22817
22818 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22819 {
22820 int i;
22821
22822 for (i = 0; i < row->used[area]; ++i)
22823 {
22824 struct glyph *glyph = row->glyphs[area] + i;
22825 if (i == row->used[area] - 1
22826 && area == TEXT_AREA
22827 && NILP (glyph->object)
22828 && glyph->type == CHAR_GLYPH
22829 && glyph->u.ch == ' ')
22830 {
22831 strcpy (&s[i], "[\\n]");
22832 i += 4;
22833 }
22834 else if (glyph->type == CHAR_GLYPH
22835 && glyph->u.ch < 0x80
22836 && glyph->u.ch >= ' ')
22837 s[i] = glyph->u.ch;
22838 else
22839 s[i] = '.';
22840 }
22841
22842 s[i] = '\0';
22843 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22844 }
22845 }
22846 }
22847
22848
22849 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22850 Sdump_glyph_matrix, 0, 1, "p",
22851 doc:
22852
22853
22854
22855
22856
22857 )
22858 (Lisp_Object glyphs)
22859 {
22860 struct window *w = XWINDOW (selected_window);
22861 struct buffer *buffer = XBUFFER (w->contents);
22862
22863 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22864 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22865 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22866 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22867 fputs ("=============================================\n", stderr);
22868 dump_glyph_matrix (w->current_matrix,
22869 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22870 return Qnil;
22871 }
22872
22873
22874 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22875 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22876 )
22877 (void)
22878 {
22879 struct frame *f = XFRAME (selected_frame);
22880
22881 if (f->current_matrix)
22882 dump_glyph_matrix (f->current_matrix, 1);
22883 else
22884 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22885 return Qnil;
22886 }
22887
22888
22889 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22890 doc:
22891
22892
22893
22894
22895 )
22896 (Lisp_Object row, Lisp_Object glyphs)
22897 {
22898 struct glyph_matrix *matrix;
22899 EMACS_INT vpos;
22900
22901 if (NILP (row))
22902 {
22903 int d1, d2, d3, d4, d5, ypos;
22904 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22905 &d1, &d2, &d3, &d4, &d5, &ypos);
22906 if (visible_p)
22907 vpos = ypos;
22908 else
22909 vpos = 0;
22910 }
22911 else
22912 {
22913 CHECK_FIXNUM (row);
22914 vpos = XFIXNUM (row);
22915 }
22916 matrix = XWINDOW (selected_window)->current_matrix;
22917 if (vpos >= 0 && vpos < matrix->nrows)
22918 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22919 vpos,
22920 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22921 return Qnil;
22922 }
22923
22924
22925 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22926 doc:
22927
22928
22929
22930
22931
22932
22933 )
22934 (Lisp_Object row, Lisp_Object glyphs)
22935 {
22936 #if defined (HAVE_WINDOW_SYSTEM)
22937 struct frame *sf = SELECTED_FRAME ();
22938 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22939 ? XWINDOW (sf->tab_bar_window)->current_matrix
22940 : sf->current_matrix;
22941 EMACS_INT vpos;
22942
22943 if (NILP (row))
22944 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22945 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22946 else
22947 {
22948 CHECK_FIXNUM (row);
22949 vpos = XFIXNUM (row);
22950 }
22951 if (vpos >= 0 && vpos < m->nrows)
22952 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22953 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22954 #endif
22955 return Qnil;
22956 }
22957
22958 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22959 doc:
22960
22961
22962
22963
22964
22965
22966 )
22967 (Lisp_Object row, Lisp_Object glyphs)
22968 {
22969 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22970 struct frame *sf = SELECTED_FRAME ();
22971 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22972 EMACS_INT vpos;
22973
22974 if (NILP (row))
22975 vpos = 0;
22976 else
22977 {
22978 CHECK_FIXNUM (row);
22979 vpos = XFIXNUM (row);
22980 }
22981 if (vpos >= 0 && vpos < m->nrows)
22982 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22983 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22984 #endif
22985 return Qnil;
22986 }
22987
22988
22989 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22990 doc:
22991 )
22992 (Lisp_Object arg)
22993 {
22994 if (NILP (arg))
22995 trace_redisplay_p = !trace_redisplay_p;
22996 else
22997 {
22998 arg = Fprefix_numeric_value (arg);
22999 trace_redisplay_p = XFIXNUM (arg) > 0;
23000 }
23001
23002 return Qnil;
23003 }
23004
23005
23006 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
23007 doc:
23008 )
23009 (ptrdiff_t nargs, Lisp_Object *args)
23010 {
23011 Lisp_Object s = Fformat (nargs, args);
23012 fwrite (SDATA (s), 1, SBYTES (s), stderr);
23013 return Qnil;
23014 }
23015
23016 #endif
23017
23018
23019
23020
23021
23022
23023
23024
23025
23026
23027
23028 static struct glyph_row *
23029 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
23030 {
23031 struct frame *f = XFRAME (WINDOW_FRAME (w));
23032 struct buffer *buffer = XBUFFER (w->contents);
23033 struct buffer *old = current_buffer;
23034 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
23035 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
23036 const unsigned char *arrow_end = arrow_string + arrow_len;
23037 const unsigned char *p;
23038 struct it it;
23039 bool multibyte_p;
23040 int n_glyphs_before;
23041
23042 set_buffer_temp (buffer);
23043 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
23044 scratch_glyph_row.reversed_p = false;
23045 it.glyph_row->used[TEXT_AREA] = 0;
23046 SET_TEXT_POS (it.position, 0, 0);
23047
23048 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
23049 p = arrow_string;
23050 while (p < arrow_end)
23051 {
23052 Lisp_Object face, ilisp;
23053
23054
23055 if (multibyte_p)
23056 it.c = it.char_to_display = check_char_and_length (p, &it.len);
23057 else
23058 {
23059 it.c = it.char_to_display = *p, it.len = 1;
23060 if (! ASCII_CHAR_P (it.c))
23061 it.char_to_display = BYTE8_TO_CHAR (it.c);
23062 }
23063 p += it.len;
23064
23065
23066 ilisp = make_fixnum (char_num++);
23067 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
23068 it.face_id = compute_char_face (f, it.char_to_display, face);
23069
23070
23071 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
23072 SET_TEXT_POS (it.position, -1, -1);
23073 PRODUCE_GLYPHS (&it);
23074
23075
23076
23077 if (it.current_x > it.last_visible_x)
23078 {
23079 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
23080 break;
23081 }
23082 }
23083
23084 set_buffer_temp (old);
23085 return it.glyph_row;
23086 }
23087
23088
23089
23090
23091
23092 static void
23093 insert_left_trunc_glyphs (struct it *it)
23094 {
23095 struct it truncate_it;
23096 struct glyph *from, *end, *to, *toend;
23097
23098 eassert (!FRAME_WINDOW_P (it->f)
23099 || (!it->glyph_row->reversed_p
23100 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23101 || (it->glyph_row->reversed_p
23102 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
23103
23104
23105 truncate_it = *it;
23106 truncate_it.current_x = 0;
23107 truncate_it.face_id = DEFAULT_FACE_ID;
23108 truncate_it.glyph_row = &scratch_glyph_row;
23109 truncate_it.area = TEXT_AREA;
23110 truncate_it.glyph_row->used[TEXT_AREA] = 0;
23111 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
23112 truncate_it.object = Qnil;
23113 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
23114
23115
23116 if (!it->glyph_row->reversed_p)
23117 {
23118 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23119
23120 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23121 end = from + tused;
23122 to = it->glyph_row->glyphs[TEXT_AREA];
23123 toend = to + it->glyph_row->used[TEXT_AREA];
23124 if (FRAME_WINDOW_P (it->f))
23125 {
23126
23127
23128
23129
23130
23131
23132
23133 int w = 0;
23134 struct glyph *g = to;
23135 short used;
23136
23137
23138
23139
23140
23141
23142 it->glyph_row->x = 0;
23143 while (g < toend && w < it->truncation_pixel_width)
23144 {
23145 w += g->pixel_width;
23146 ++g;
23147 }
23148 if (g - to - tused > 0)
23149 {
23150 memmove (to + tused, g, (toend - g) * sizeof(*g));
23151 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
23152 }
23153 used = it->glyph_row->used[TEXT_AREA];
23154 if (it->glyph_row->truncated_on_right_p
23155 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
23156 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
23157 == STRETCH_GLYPH)
23158 {
23159 int extra = w - it->truncation_pixel_width;
23160
23161 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
23162 }
23163 }
23164
23165 while (from < end)
23166 *to++ = *from++;
23167
23168
23169 if (!FRAME_WINDOW_P (it->f))
23170 {
23171 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
23172 {
23173 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23174 while (from < end)
23175 *to++ = *from++;
23176 }
23177 }
23178
23179 if (to > toend)
23180 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
23181 }
23182 else
23183 {
23184 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23185
23186
23187
23188 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
23189 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23190 toend = it->glyph_row->glyphs[TEXT_AREA];
23191 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
23192 if (FRAME_WINDOW_P (it->f))
23193 {
23194 int w = 0;
23195 struct glyph *g = to;
23196
23197 while (g >= toend && w < it->truncation_pixel_width)
23198 {
23199 w += g->pixel_width;
23200 --g;
23201 }
23202 if (to - g - tused > 0)
23203 to = g + tused;
23204 if (it->glyph_row->truncated_on_right_p
23205 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
23206 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
23207 {
23208 int extra = w - it->truncation_pixel_width;
23209
23210 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
23211 }
23212 }
23213
23214 while (from >= end && to >= toend)
23215 *to-- = *from--;
23216 if (!FRAME_WINDOW_P (it->f))
23217 {
23218 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
23219 {
23220 from =
23221 truncate_it.glyph_row->glyphs[TEXT_AREA]
23222 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23223 while (from >= end && to >= toend)
23224 *to-- = *from--;
23225 }
23226 }
23227 if (from >= end)
23228 {
23229
23230
23231 int move_by = from - end + 1;
23232 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
23233 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
23234
23235 for ( ; g >= g0; g--)
23236 g[move_by] = *g;
23237 while (from >= end)
23238 *to-- = *from--;
23239 it->glyph_row->used[TEXT_AREA] += move_by;
23240 }
23241 }
23242 }
23243
23244
23245 unsigned
23246 row_hash (struct glyph_row *row)
23247 {
23248 int area, k;
23249 unsigned hashval = 0;
23250
23251 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23252 for (k = 0; k < row->used[area]; ++k)
23253 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23254 + row->glyphs[area][k].u.val
23255 + row->glyphs[area][k].face_id
23256 + row->glyphs[area][k].padding_p
23257 + (row->glyphs[area][k].type << 2));
23258
23259 return hashval;
23260 }
23261
23262
23263
23264
23265
23266
23267
23268
23269
23270
23271
23272
23273
23274
23275
23276
23277
23278
23279 static void
23280 compute_line_metrics (struct it *it)
23281 {
23282 struct glyph_row *row = it->glyph_row;
23283
23284 if (FRAME_WINDOW_P (it->f))
23285 {
23286 int i, min_y, max_y;
23287
23288
23289
23290
23291 if (row->height == 0)
23292 {
23293 if (it->max_ascent + it->max_descent == 0)
23294 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23295 row->ascent = it->max_ascent;
23296 row->height = it->max_ascent + it->max_descent;
23297 row->phys_ascent = it->max_phys_ascent;
23298 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23299 row->extra_line_spacing = it->max_extra_line_spacing;
23300 }
23301
23302
23303 row->pixel_width = row->x;
23304 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23305 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23306
23307 eassert (row->pixel_width >= 0);
23308 eassert (row->ascent >= 0 && row->height > 0);
23309
23310 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23311 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23312
23313
23314
23315
23316 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23317 && row->phys_ascent > row->ascent)
23318 {
23319 row->height += row->phys_ascent - row->ascent;
23320 row->ascent = row->phys_ascent;
23321 }
23322
23323
23324 row->visible_height = row->height;
23325
23326 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23327 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23328
23329 if (row->y < min_y)
23330 row->visible_height -= min_y - row->y;
23331 if (row->y + row->height > max_y)
23332 row->visible_height -= row->y + row->height - max_y;
23333 }
23334 else
23335 {
23336 row->pixel_width = row->used[TEXT_AREA];
23337 if (row->continued_p)
23338 row->pixel_width -= it->continuation_pixel_width;
23339 else if (row->truncated_on_right_p)
23340 row->pixel_width -= it->truncation_pixel_width;
23341 row->ascent = row->phys_ascent = 0;
23342 row->height = row->phys_height = row->visible_height = 1;
23343 row->extra_line_spacing = 0;
23344 }
23345
23346
23347 row->hash = row_hash (row);
23348
23349 it->max_ascent = it->max_descent = 0;
23350 it->max_phys_ascent = it->max_phys_descent = 0;
23351 }
23352
23353
23354 static void
23355 clear_position (struct it *it)
23356 {
23357 it->position.charpos = 0;
23358 it->position.bytepos = 0;
23359 }
23360
23361
23362
23363
23364
23365
23366
23367
23368
23369
23370
23371
23372
23373 static bool
23374 append_space_for_newline (struct it *it, bool default_face_p)
23375 {
23376 int n = it->glyph_row->used[TEXT_AREA];
23377
23378 if (it->glyph_row->glyphs[TEXT_AREA] + n
23379 < it->glyph_row->glyphs[1 + TEXT_AREA])
23380 {
23381
23382
23383
23384
23385 enum display_element_type saved_what = it->what;
23386 int saved_c = it->c, saved_len = it->len;
23387 int saved_char_to_display = it->char_to_display;
23388 int saved_x = it->current_x;
23389 const int saved_face_id = it->face_id;
23390 bool saved_box_end = it->end_of_box_run_p;
23391 struct text_pos saved_pos = it->position;
23392 Lisp_Object saved_object = it->object;
23393 struct face *face;
23394
23395 it->what = IT_CHARACTER;
23396 clear_position (it);
23397 it->object = Qnil;
23398 it->len = 1;
23399
23400 int char_width = 1;
23401
23402 if (default_face_p
23403 #ifdef HAVE_WINDOW_SYSTEM
23404 || FRAME_WINDOW_P (it->f)
23405 #endif
23406 )
23407 {
23408 const int local_default_face_id =
23409 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23410
23411 #ifdef HAVE_WINDOW_SYSTEM
23412 if (FRAME_WINDOW_P (it->f))
23413 {
23414 struct face *default_face
23415 = FACE_FROM_ID (it->f, local_default_face_id);
23416 struct font *font = (default_face->font
23417 ? default_face->font
23418 : FRAME_FONT (it->f));
23419 char_width = (font->average_width
23420 ? font->average_width
23421 : font->space_width);
23422 }
23423 #endif
23424 if (default_face_p)
23425 it->face_id = local_default_face_id;
23426 }
23427
23428
23429
23430
23431 const int indicator_column =
23432 fill_column_indicator_column (it, char_width);
23433 int saved_end_of_box_run = it->end_of_box_run_p;
23434 bool should_keep_end_of_box_run = false;
23435
23436 if (it->current_x == indicator_column)
23437 {
23438 it->c = it->char_to_display
23439 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23440 it->face_id
23441 = merge_faces (it->w, Qfill_column_indicator,
23442 0, saved_face_id);
23443 face = FACE_FROM_ID (it->f, it->face_id);
23444 }
23445 else
23446 {
23447 it->c = it->char_to_display = ' ';
23448
23449
23450
23451 face = FACE_FROM_ID (it->f, it->face_id);
23452 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23453
23454
23455
23456
23457 if (!(it->glyph_row->reversed_p
23458
23459
23460
23461 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23462 should_keep_end_of_box_run = true;
23463 }
23464 PRODUCE_GLYPHS (it);
23465
23466
23467 if (should_keep_end_of_box_run)
23468 it->end_of_box_run_p = saved_end_of_box_run;
23469 #ifdef HAVE_WINDOW_SYSTEM
23470 if (FRAME_WINDOW_P (it->f))
23471 {
23472
23473
23474
23475 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23476 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23477 if (n == 0)
23478 {
23479 Lisp_Object height, total_height;
23480 int extra_line_spacing = it->extra_line_spacing;
23481 int boff = font->baseline_offset;
23482
23483 if (font->vertical_centering)
23484 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23485
23486 it->object = saved_object;
23487 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23488
23489
23490 height = get_it_property (it, Qline_height);
23491 if (CONSP (height)
23492 && CONSP (XCDR (height))
23493 && NILP (XCDR (XCDR (height))))
23494 {
23495 total_height = XCAR (XCDR (height));
23496 height = XCAR (height);
23497 }
23498 else
23499 total_height = Qnil;
23500 height = calc_line_height_property (it, height, font, boff, true);
23501
23502 if (it->override_ascent >= 0)
23503 {
23504 it->ascent = it->override_ascent;
23505 it->descent = it->override_descent;
23506 boff = it->override_boff;
23507 }
23508 if (EQ (height, Qt))
23509 extra_line_spacing = 0;
23510 else
23511 {
23512 Lisp_Object spacing;
23513
23514 it->phys_ascent = it->ascent;
23515 it->phys_descent = it->descent;
23516 if (!NILP (height)
23517 && XFIXNUM (height) > it->ascent + it->descent)
23518 it->ascent = XFIXNUM (height) - it->descent;
23519
23520 if (!NILP (total_height))
23521 spacing = calc_line_height_property (it, total_height, font,
23522 boff, false);
23523 else
23524 {
23525 spacing = get_it_property (it, Qline_spacing);
23526 spacing = calc_line_height_property (it, spacing, font,
23527 boff, false);
23528 }
23529 if (FIXNUMP (spacing))
23530 {
23531 extra_line_spacing = XFIXNUM (spacing);
23532 if (!NILP (total_height))
23533 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23534 }
23535 }
23536 if (extra_line_spacing > 0)
23537 {
23538 it->descent += extra_line_spacing;
23539 if (extra_line_spacing > it->max_extra_line_spacing)
23540 it->max_extra_line_spacing = extra_line_spacing;
23541 }
23542 it->max_ascent = it->ascent;
23543 it->max_descent = it->descent;
23544
23545 it->glyph_row->height = 0;
23546 }
23547
23548 g->ascent = it->max_ascent;
23549 g->descent = it->max_descent;
23550 }
23551 #endif
23552 it->override_ascent = -1;
23553 it->constrain_row_ascent_descent_p = false;
23554 it->current_x = saved_x;
23555 it->object = saved_object;
23556 it->position = saved_pos;
23557 it->what = saved_what;
23558 it->face_id = saved_face_id;
23559 it->len = saved_len;
23560 it->c = saved_c;
23561 it->char_to_display = saved_char_to_display;
23562 it->end_of_box_run_p = saved_box_end;
23563 return true;
23564 }
23565
23566 return false;
23567 }
23568
23569
23570
23571
23572
23573
23574
23575
23576
23577 static void
23578 extend_face_to_end_of_line (struct it *it)
23579 {
23580 struct frame *f = it->f;
23581
23582
23583
23584
23585
23586
23587 if ((it->current_x >= it->last_visible_x
23588 + (!FRAME_WINDOW_P (f)
23589 && it->glyph_row->reversed_p
23590 && !it->glyph_row->continued_p))
23591
23592
23593 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23594 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23595 return;
23596
23597 specpdl_ref count = SPECPDL_INDEX ();
23598
23599
23600
23601
23602 specbind (Qinhibit_quit, Qt);
23603
23604 struct face *default_face =
23605 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23606 if (!default_face)
23607 return;
23608
23609 const int extend_face_id =
23610 (it->face_id == default_face->id || it->s != NULL)
23611 ? it->face_id
23612 : (it->glyph_row->ends_at_zv_p
23613 ? default_face->id
23614 : face_at_pos (it, LFACE_EXTEND_INDEX));
23615 unbind_to (count, Qnil);
23616
23617
23618
23619
23620 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23621 ? it->saved_face_id
23622 : extend_face_id));
23623
23624 if (FRAME_WINDOW_P (f)
23625 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23626 && face->box == FACE_NO_BOX
23627 && face->underline == FACE_NO_UNDERLINE
23628 && !face->overline_p
23629 && !face->strike_through_p
23630 && face->background == FRAME_BACKGROUND_PIXEL (f)
23631 #ifdef HAVE_WINDOW_SYSTEM
23632 && !face->stipple
23633 #endif
23634 && !it->glyph_row->reversed_p
23635 && !display_fill_column_indicator)
23636 return;
23637
23638
23639
23640 it->glyph_row->fill_line_p = true;
23641
23642 const int orig_face_id = it->face_id;
23643
23644
23645
23646
23647
23648 if (!ASCII_CHAR_P (it->c))
23649 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23650
23651
23652 #ifdef HAVE_WINDOW_SYSTEM
23653 if (FRAME_WINDOW_P (f))
23654 {
23655
23656
23657 if (it->glyph_row->used[TEXT_AREA] == 0)
23658 {
23659 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23660 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23661 it->glyph_row->used[TEXT_AREA] = 1;
23662 }
23663
23664
23665 if (!(it->glyph_row->mode_line_p
23666 || (WINDOWP (f->tab_bar_window)
23667 && it->w == XWINDOW (f->tab_bar_window))
23668 #ifndef HAVE_EXT_TOOL_BAR
23669 || (WINDOWP (f->tool_bar_window)
23670 && it->w == XWINDOW (f->tool_bar_window))
23671 #endif
23672 ))
23673 {
23674 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23675 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23676 {
23677 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23678 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23679 default_face->id;
23680 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23681 }
23682 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23683 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23684 {
23685 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23686 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23687 default_face->id;
23688 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23689 }
23690
23691 struct font *font = (default_face->font
23692 ? default_face->font
23693 : FRAME_FONT (f));
23694
23695 const int char_width = (font->average_width
23696 ? font->average_width
23697 : font->space_width);
23698
23699 const int indicator_column =
23700 fill_column_indicator_column (it, char_width);
23701
23702 const char saved_char = it->char_to_display;
23703 const struct text_pos saved_pos = it->position;
23704 const bool saved_avoid_cursor = it->avoid_cursor_p;
23705 const bool saved_box_start = it->start_of_box_run_p;
23706 Lisp_Object save_object = it->object;
23707 const int saved_face_id = it->face_id;
23708
23709 it->face_id = extend_face_id;
23710 it->avoid_cursor_p = true;
23711 it->object = Qnil;
23712
23713 const int stretch_height = it->ascent + it->descent;
23714 const int stretch_ascent =
23715 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23716
23717 if (indicator_column >= 0
23718 && indicator_column > it->current_x
23719 && indicator_column < it->last_visible_x)
23720 {
23721
23722
23723
23724
23725 const int stretch_width =
23726 indicator_column - it->current_x - char_width;
23727
23728 clear_position (it);
23729
23730
23731
23732 if (stretch_width > 0)
23733 {
23734 append_stretch_glyph (it, Qnil, stretch_width,
23735 stretch_height, stretch_ascent);
23736 }
23737
23738
23739
23740 if (it->current_x < indicator_column)
23741 {
23742 const int save_face_id = it->face_id;
23743 const int save_ascent = it->ascent;
23744 const int save_descent = it->descent;
23745 it->char_to_display
23746 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23747 it->face_id
23748 = merge_faces (it->w, Qfill_column_indicator,
23749 0, extend_face_id);
23750 PRODUCE_GLYPHS (it);
23751 it->face_id = save_face_id;
23752 it->ascent = save_ascent;
23753 it->descent = save_descent;
23754 }
23755 }
23756
23757
23758
23759 if (!it->glyph_row->reversed_p)
23760 {
23761 const int stretch_width = it->last_visible_x - it->current_x;
23762
23763 if (stretch_width > 0)
23764 {
23765 clear_position (it);
23766 append_stretch_glyph (it, Qnil, stretch_width,
23767 stretch_height, stretch_ascent);
23768 }
23769 }
23770
23771 it->char_to_display = saved_char;
23772 it->position = saved_pos;
23773 it->avoid_cursor_p = saved_avoid_cursor;
23774 it->start_of_box_run_p = saved_box_start;
23775 it->object = save_object;
23776 it->face_id = saved_face_id;
23777 }
23778 if (it->glyph_row->reversed_p)
23779 {
23780
23781
23782
23783
23784
23785 struct font *font = face->font ? face->font : FRAME_FONT (f);
23786 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23787 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23788 struct glyph *g;
23789 int row_width, stretch_ascent, stretch_width;
23790 struct text_pos saved_pos;
23791 int saved_face_id;
23792 bool saved_avoid_cursor, saved_box_start;
23793
23794 for (row_width = 0, g = row_start; g < row_end; g++)
23795 row_width += g->pixel_width;
23796
23797
23798
23799
23800 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23801 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23802 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23803 stretch_width = window_box_width (it->w, TEXT_AREA);
23804 else
23805 stretch_width = it->last_visible_x - it->first_visible_x;
23806 stretch_width -= row_width;
23807
23808 if (stretch_width > 0)
23809 {
23810 stretch_ascent =
23811 (((it->ascent + it->descent)
23812 * FONT_BASE (font)) / FONT_HEIGHT (font));
23813 saved_pos = it->position;
23814 clear_position (it);
23815 saved_avoid_cursor = it->avoid_cursor_p;
23816 it->avoid_cursor_p = true;
23817 saved_face_id = it->face_id;
23818 saved_box_start = it->start_of_box_run_p;
23819
23820
23821
23822 it->face_id = (it->glyph_row->ends_at_zv_p ?
23823 default_face->id : face->id);
23824
23825 it->start_of_box_run_p = false;
23826 append_stretch_glyph (it, Qnil, stretch_width,
23827 it->ascent + it->descent, stretch_ascent);
23828 it->position = saved_pos;
23829 it->avoid_cursor_p = saved_avoid_cursor;
23830 it->face_id = saved_face_id;
23831 it->start_of_box_run_p = saved_box_start;
23832 }
23833
23834
23835
23836
23837 if (stretch_width < 0)
23838 it->glyph_row->x = stretch_width;
23839 }
23840 it->face_id = orig_face_id;
23841 }
23842 else
23843 #endif
23844 {
23845
23846 int saved_x = it->current_x;
23847 struct text_pos saved_pos = it->position;
23848 Lisp_Object saved_object = it->object;;
23849 enum display_element_type saved_what = it->what;
23850
23851 it->what = IT_CHARACTER;
23852 clear_position (it);
23853 it->object = Qnil;
23854 it->c = it->char_to_display = ' ';
23855 it->len = 1;
23856
23857 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23858 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23859 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23860 && !it->glyph_row->mode_line_p
23861 && face->background != FRAME_BACKGROUND_PIXEL (f))
23862 {
23863 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23864 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23865
23866 for (it->current_x = 0; g < e; g++)
23867 it->current_x += g->pixel_width;
23868
23869 it->area = LEFT_MARGIN_AREA;
23870 it->face_id = default_face->id;
23871 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23872 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23873 && g < it->glyph_row->glyphs[TEXT_AREA])
23874 {
23875 PRODUCE_GLYPHS (it);
23876
23877
23878 it->current_x += it->pixel_width;
23879 g++;
23880 }
23881
23882 it->current_x = saved_x;
23883 it->area = TEXT_AREA;
23884 }
23885
23886
23887
23888
23889 it->face_id = (it->glyph_row->ends_at_zv_p ?
23890 default_face->id : face->id);
23891
23892
23893
23894
23895
23896 it->current_x = it->glyph_row->used[TEXT_AREA];
23897
23898
23899
23900
23901
23902
23903
23904
23905 const int indicator_column =
23906 fill_column_indicator_column (it, 1) - it->first_visible_x;
23907
23908
23909 while (it->current_x <= it->last_visible_x)
23910 {
23911 if (it->current_x != indicator_column)
23912 PRODUCE_GLYPHS (it);
23913 else
23914 {
23915 int saved_face_id = it->face_id;
23916 it->face_id
23917 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23918 it->c = it->char_to_display
23919 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23920
23921 PRODUCE_GLYPHS (it);
23922
23923 it->face_id = saved_face_id;
23924 it->c = it->char_to_display = ' ';
23925 }
23926 }
23927
23928 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23929 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23930 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23931 && !it->glyph_row->mode_line_p
23932 && face->background != FRAME_BACKGROUND_PIXEL (f))
23933 {
23934 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23935 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23936
23937 for ( ; g < e; g++)
23938 it->current_x += g->pixel_width;
23939
23940 it->area = RIGHT_MARGIN_AREA;
23941 it->face_id = default_face->id;
23942 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23943 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23944 && g < it->glyph_row->glyphs[LAST_AREA])
23945 {
23946 PRODUCE_GLYPHS (it);
23947 it->current_x += it->pixel_width;
23948 g++;
23949 }
23950
23951 it->area = TEXT_AREA;
23952 }
23953
23954
23955
23956 it->current_x = saved_x;
23957 it->object = saved_object;
23958 it->position = saved_pos;
23959 it->what = saved_what;
23960 it->face_id = orig_face_id;
23961 }
23962 }
23963
23964
23965
23966
23967
23968 static bool
23969 trailing_whitespace_p (ptrdiff_t charpos)
23970 {
23971 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23972 int c = 0;
23973
23974 while (bytepos < ZV_BYTE
23975 && (c = FETCH_BYTE (bytepos),
23976 c == ' ' || c == '\t'))
23977 ++bytepos;
23978
23979 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23980 {
23981 if (bytepos != PT_BYTE)
23982 return true;
23983 }
23984 return false;
23985 }
23986
23987
23988
23989
23990 static void
23991 highlight_trailing_whitespace (struct it *it)
23992 {
23993 struct glyph_row *row = it->glyph_row;
23994 int used = row->used[TEXT_AREA];
23995
23996 if (used)
23997 {
23998 struct glyph *start = row->glyphs[TEXT_AREA];
23999 struct glyph *glyph = start + used - 1;
24000
24001 if (row->reversed_p)
24002 {
24003
24004
24005 glyph = start;
24006 start = row->glyphs[TEXT_AREA] + used - 1;
24007 }
24008
24009
24010
24011
24012
24013 if (!row->reversed_p)
24014 {
24015 while (glyph >= start
24016 && (glyph->type == CHAR_GLYPH
24017 || glyph->type == STRETCH_GLYPH)
24018 && NILP (glyph->object))
24019 --glyph;
24020 }
24021 else
24022 {
24023 while (glyph <= start
24024 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
24025 && NILP (glyph->object))
24026 ++glyph;
24027 }
24028
24029
24030
24031
24032 if ((row->reversed_p ? glyph <= start : glyph >= start)
24033 && BUFFERP (glyph->object)
24034 && (glyph->type == STRETCH_GLYPH
24035 || (glyph->type == CHAR_GLYPH
24036 && glyph->u.ch == ' '))
24037 && trailing_whitespace_p (glyph->charpos))
24038 {
24039 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
24040 if (face_id < 0)
24041 return;
24042
24043 if (!row->reversed_p)
24044 {
24045 while (glyph >= start
24046 && BUFFERP (glyph->object)
24047 && (glyph->type == STRETCH_GLYPH
24048 || (glyph->type == CHAR_GLYPH
24049 && glyph->u.ch == ' ')))
24050 (glyph--)->face_id = face_id;
24051 }
24052 else
24053 {
24054 while (glyph <= start
24055 && BUFFERP (glyph->object)
24056 && (glyph->type == STRETCH_GLYPH
24057 || (glyph->type == CHAR_GLYPH
24058 && glyph->u.ch == ' ')))
24059 (glyph++)->face_id = face_id;
24060 }
24061 }
24062 }
24063 }
24064
24065
24066
24067
24068
24069 static bool
24070 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
24071 {
24072 bool result = true;
24073
24074 if (charpos == CHARPOS (row->end.pos)
24075 || charpos == MATRIX_ROW_END_CHARPOS (row))
24076 {
24077
24078
24079
24080
24081
24082
24083
24084
24085 if (CHARPOS (row->end.string_pos) >= 0)
24086 {
24087 if (row->continued_p)
24088 result = true;
24089 else
24090 {
24091
24092 struct glyph *beg = row->glyphs[TEXT_AREA];
24093 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
24094 struct glyph *glyph;
24095
24096 result = false;
24097 for (glyph = end; glyph >= beg; --glyph)
24098 if (STRINGP (glyph->object))
24099 {
24100 Lisp_Object prop
24101 = Fget_char_property (make_fixnum (charpos),
24102 Qdisplay, Qnil);
24103 result =
24104 (!NILP (prop)
24105 && display_prop_string_p (prop, glyph->object));
24106
24107
24108
24109 if (!result)
24110 {
24111 Lisp_Object s = glyph->object;
24112
24113 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
24114 {
24115 ptrdiff_t gpos = glyph->charpos;
24116
24117 if (!NILP (Fget_char_property (make_fixnum (gpos),
24118 Qcursor, s)))
24119 {
24120 result = true;
24121 break;
24122 }
24123 }
24124 }
24125 break;
24126 }
24127 }
24128 }
24129 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
24130 {
24131
24132
24133
24134
24135 if (!row->ends_in_ellipsis_p)
24136 result = row->continued_p;
24137 else
24138
24139
24140
24141
24142 result = false;
24143 }
24144
24145
24146 else
24147 result = row->ends_at_zv_p;
24148 }
24149
24150 return result;
24151 }
24152
24153
24154
24155
24156 static bool
24157 cursor_row_p (struct glyph_row *row)
24158 {
24159 return row_for_charpos_p (row, PT);
24160 }
24161
24162
24163
24164
24165
24166
24167
24168
24169 static bool
24170 push_prefix_prop (struct it *it, Lisp_Object prop)
24171 {
24172 struct text_pos pos =
24173 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
24174
24175 eassert (it->method == GET_FROM_BUFFER
24176 || it->method == GET_FROM_DISPLAY_VECTOR
24177 || it->method == GET_FROM_STRING
24178 || it->method == GET_FROM_IMAGE);
24179
24180
24181
24182
24183
24184 push_it (it, &pos);
24185
24186 if (STRINGP (prop))
24187 {
24188 if (SCHARS (prop) == 0)
24189 {
24190 pop_it (it);
24191 return false;
24192 }
24193
24194 it->string = prop;
24195 it->string_from_prefix_prop_p = true;
24196 it->multibyte_p = STRING_MULTIBYTE (it->string);
24197 it->current.overlay_string_index = -1;
24198 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
24199 it->end_charpos = it->string_nchars = SCHARS (it->string);
24200 it->method = GET_FROM_STRING;
24201 it->stop_charpos = 0;
24202 it->prev_stop = 0;
24203 it->base_level_stop = 0;
24204 it->cmp_it.id = -1;
24205
24206
24207
24208 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
24209 it->paragraph_embedding = it->bidi_it.paragraph_dir;
24210 else
24211 it->paragraph_embedding = L2R;
24212
24213
24214 if (it->bidi_p)
24215 {
24216 it->bidi_it.string.lstring = it->string;
24217 it->bidi_it.string.s = NULL;
24218 it->bidi_it.string.schars = it->end_charpos;
24219 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
24220 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
24221 it->bidi_it.string.unibyte = !it->multibyte_p;
24222 it->bidi_it.w = it->w;
24223 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
24224 }
24225 }
24226 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
24227 {
24228 it->method = GET_FROM_STRETCH;
24229 it->object = prop;
24230 }
24231 #ifdef HAVE_WINDOW_SYSTEM
24232 else if (IMAGEP (prop))
24233 {
24234 it->what = IT_IMAGE;
24235 it->image_id = lookup_image (it->f, prop, it->face_id);
24236 it->method = GET_FROM_IMAGE;
24237 }
24238 #endif
24239 else
24240 {
24241 pop_it (it);
24242 return false;
24243 }
24244
24245 return true;
24246 }
24247
24248
24249
24250 static Lisp_Object
24251 get_it_property (struct it *it, Lisp_Object prop)
24252 {
24253 Lisp_Object position, object = it->object;
24254
24255 if (STRINGP (object))
24256 position = make_fixnum (IT_STRING_CHARPOS (*it));
24257 else if (BUFFERP (object))
24258 {
24259 position = make_fixnum (IT_CHARPOS (*it));
24260 object = it->window;
24261 }
24262 else
24263 return Qnil;
24264
24265 return Fget_char_property (position, prop, object);
24266 }
24267
24268
24269
24270
24271 static Lisp_Object
24272 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24273 {
24274 Lisp_Object prefix = get_it_property (it, prop);
24275
24276
24277
24278 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24279 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24280 it->w->contents);
24281 return prefix;
24282 }
24283
24284
24285
24286 static void
24287 handle_line_prefix (struct it *it)
24288 {
24289 Lisp_Object prefix;
24290
24291 if (it->continuation_lines_width > 0)
24292 {
24293 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24294 if (NILP (prefix))
24295 prefix = Vwrap_prefix;
24296 }
24297 else
24298 {
24299 prefix = get_line_prefix_it_property (it, Qline_prefix);
24300 if (NILP (prefix))
24301 prefix = Vline_prefix;
24302 }
24303 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24304 {
24305
24306
24307
24308 it->line_wrap = TRUNCATE;
24309 it->avoid_cursor_p = true;
24310 }
24311 }
24312
24313
24314
24315
24316
24317
24318
24319 static void
24320 unproduce_glyphs (struct it *it, int n)
24321 {
24322 struct glyph *glyph, *end;
24323
24324 eassert (it->glyph_row);
24325 eassert (it->glyph_row->reversed_p);
24326 eassert (it->area == TEXT_AREA);
24327 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24328
24329 if (n > it->glyph_row->used[TEXT_AREA])
24330 n = it->glyph_row->used[TEXT_AREA];
24331 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24332 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24333 for ( ; glyph < end; glyph++)
24334 glyph[-n] = *glyph;
24335 }
24336
24337
24338
24339 static void
24340 find_row_edges (struct it *it, struct glyph_row *row,
24341 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24342 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24343 {
24344
24345
24346
24347
24348
24349 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24350 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24351 else
24352
24353
24354
24355 row->minpos = row->start.pos;
24356 if (max_pos <= 0)
24357 {
24358 max_pos = CHARPOS (it->current.pos);
24359 max_bpos = BYTEPOS (it->current.pos);
24360 }
24361
24362
24363
24364
24365
24366
24367
24368
24369
24370
24371
24372
24373
24374
24375
24376
24377
24378 if (row->ends_at_zv_p)
24379 row->maxpos = it->current.pos;
24380 else if (row->used[TEXT_AREA])
24381 {
24382 bool seen_this_string = false;
24383 struct glyph_row *r1 = row - 1;
24384
24385
24386 if (STRINGP (it->object)
24387
24388 && row > it->w->desired_matrix->rows
24389
24390 && !r1->mode_line_p
24391
24392 && r1->ends_in_newline_from_string_p)
24393 {
24394 struct glyph *start, *end;
24395
24396
24397
24398
24399
24400 if (!r1->reversed_p)
24401 {
24402 start = r1->glyphs[TEXT_AREA];
24403 end = start + r1->used[TEXT_AREA];
24404
24405 while (end > start
24406 && NILP ((end - 1)->object)
24407 && (end - 1)->charpos <= 0)
24408 --end;
24409 if (end > start)
24410 {
24411 if (EQ ((end - 1)->object, it->object))
24412 seen_this_string = true;
24413 }
24414 else
24415
24416
24417
24418
24419
24420 seen_this_string = true;
24421 }
24422 else
24423 {
24424 end = r1->glyphs[TEXT_AREA] - 1;
24425 start = end + r1->used[TEXT_AREA];
24426 while (end < start
24427 && NILP ((end + 1)->object)
24428 && (end + 1)->charpos <= 0)
24429 ++end;
24430 if (end < start)
24431 {
24432 if (EQ ((end + 1)->object, it->object))
24433 seen_this_string = true;
24434 }
24435 else
24436 seen_this_string = true;
24437 }
24438 }
24439
24440
24441
24442 if (row->ends_in_newline_from_string_p && !seen_this_string)
24443 {
24444
24445
24446
24447
24448
24449
24450
24451
24452 if (CHARPOS (row->end.pos) > max_pos)
24453 inc_both (&max_pos, &max_bpos);
24454 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24455 }
24456 else if (CHARPOS (it->eol_pos) > 0)
24457 SET_TEXT_POS (row->maxpos,
24458 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24459 else if (row->continued_p)
24460 {
24461
24462
24463
24464
24465
24466
24467 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24468 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24469 else
24470 {
24471 inc_both (&max_pos, &max_bpos);
24472 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24473 }
24474 }
24475 else if (row->truncated_on_right_p)
24476
24477
24478
24479 row->maxpos = it->current.pos;
24480 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24481
24482 row->maxpos = row->minpos;
24483 else
24484 emacs_abort ();
24485 }
24486 else
24487 row->maxpos = it->current.pos;
24488 }
24489
24490
24491
24492 static ptrdiff_t
24493 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24494 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24495 {
24496 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24497 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24498
24499 ptrdiff_t val;
24500 specpdl_ref pdl_count = SPECPDL_INDEX ();
24501 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24502 labeled_restrictions_remove_in_current_buffer ();
24503 Fwiden ();
24504 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24505 unbind_to (pdl_count, Qnil);
24506 return val;
24507 }
24508
24509
24510
24511 static ptrdiff_t
24512 display_count_lines_visually (struct it *it)
24513 {
24514 struct it tem_it;
24515 ptrdiff_t to;
24516 struct text_pos from;
24517
24518
24519
24520
24521
24522
24523 if (it->lnum_bytepos > 0)
24524 return it->lnum + 1;
24525 else
24526 {
24527 specpdl_ref count = SPECPDL_INDEX ();
24528
24529 if (IT_CHARPOS (*it) <= PT)
24530 {
24531 from = it->current.pos;
24532 to = PT;
24533 }
24534 else
24535 {
24536 SET_TEXT_POS (from, PT, PT_BYTE);
24537 to = IT_CHARPOS (*it);
24538 }
24539
24540
24541
24542 specbind (Qdisplay_line_numbers, Qrelative);
24543 start_display (&tem_it, it->w, from);
24544
24545
24546
24547
24548 move_it_to (&tem_it, to, -1,
24549 tem_it.last_visible_y
24550 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24551 -1, MOVE_TO_POS | MOVE_TO_Y);
24552 unbind_to (count, Qnil);
24553 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24554 }
24555 }
24556
24557
24558
24559
24560 static void
24561 maybe_produce_line_number (struct it *it)
24562 {
24563 ptrdiff_t last_line = it->lnum;
24564 ptrdiff_t start_from, bytepos;
24565 ptrdiff_t this_line;
24566 bool first_time = false;
24567 ptrdiff_t beg_byte;
24568 ptrdiff_t z_byte;
24569 bool line_numbers_wide;
24570 void *itdata = bidi_shelve_cache ();
24571
24572 if (display_line_numbers_offset
24573 && !display_line_numbers_widen
24574 && !EQ (Vdisplay_line_numbers, Qvisual)
24575 && !EQ (Vdisplay_line_numbers, Qrelative))
24576 line_numbers_wide = true;
24577 else
24578 line_numbers_wide = display_line_numbers_widen;
24579
24580 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24581 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24582
24583 if (EQ (Vdisplay_line_numbers, Qvisual))
24584 this_line = display_count_lines_visually (it);
24585 else
24586 {
24587 if (!last_line)
24588 {
24589
24590 if (it->w->base_line_number > 0
24591 && it->w->base_line_pos > 0
24592 && it->w->base_line_pos <= IT_CHARPOS (*it)
24593
24594
24595
24596
24597 && !(line_numbers_wide
24598 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24599 && !current_buffer->clip_changed)
24600 {
24601 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24602 last_line = it->w->base_line_number - 1;
24603 }
24604 else
24605 start_from = beg_byte;
24606 if (!it->lnum_bytepos)
24607 first_time = true;
24608 }
24609 else
24610 start_from = it->lnum_bytepos;
24611
24612
24613
24614
24615 if (!(beg_byte <= start_from && start_from <= z_byte))
24616 {
24617 last_line = 0;
24618 start_from = beg_byte;
24619 }
24620
24621 this_line =
24622 last_line + display_count_lines_logically (start_from,
24623 IT_BYTEPOS (*it),
24624 IT_CHARPOS (*it), &bytepos);
24625 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24626 eassert (bytepos == IT_BYTEPOS (*it));
24627 }
24628
24629
24630 if (this_line != last_line || !it->lnum_bytepos)
24631 {
24632 it->lnum = this_line;
24633 it->lnum_bytepos = IT_BYTEPOS (*it);
24634 }
24635
24636
24637 struct it tem_it;
24638 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24639 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24640 ptrdiff_t lnum_offset = -1;
24641 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24642 int current_lnum_face_id
24643 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24644
24645
24646 bool save_free_realized_faces = inhibit_free_realized_faces;
24647 inhibit_free_realized_faces = true;
24648
24649 if ((EQ (Vdisplay_line_numbers, Qrelative)
24650 || EQ (Vdisplay_line_numbers, Qvisual)
24651 || lnum_face_id != current_lnum_face_id)
24652 && !it->pt_lnum)
24653 {
24654 ptrdiff_t ignored;
24655 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24656 it->pt_lnum =
24657 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24658 PT, &ignored);
24659 else
24660 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24661 &ignored);
24662 }
24663
24664 if (!it->lnum_width)
24665 {
24666 if (FIXNATP (Vdisplay_line_numbers_width))
24667 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24668
24669
24670
24671 ptrdiff_t max_lnum;
24672
24673 if (NILP (Vdisplay_line_numbers_current_absolute)
24674 && (EQ (Vdisplay_line_numbers, Qrelative)
24675 || EQ (Vdisplay_line_numbers, Qvisual)))
24676
24677
24678 max_lnum = it->w->desired_matrix->nrows - 2;
24679 else if (EQ (Vdisplay_line_numbers, Qvisual))
24680 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24681 else
24682 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24683 max_lnum = max (1, max_lnum);
24684 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24685 eassert (it->lnum_width > 0);
24686 }
24687 if (EQ (Vdisplay_line_numbers, Qrelative))
24688 lnum_offset = it->pt_lnum;
24689 else if (EQ (Vdisplay_line_numbers, Qvisual))
24690 lnum_offset = 0;
24691 else if (display_line_numbers_offset)
24692 lnum_offset -= display_line_numbers_offset;
24693
24694
24695
24696 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24697 if ((EQ (Vdisplay_line_numbers, Qrelative)
24698 || EQ (Vdisplay_line_numbers, Qvisual))
24699 && lnum_to_display == 0
24700 && !NILP (Vdisplay_line_numbers_current_absolute))
24701 lnum_to_display = it->pt_lnum + 1;
24702
24703
24704
24705
24706
24707 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24708 strcat (lnum_buf, " ");
24709
24710
24711 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24712
24713 DEFAULT_FACE_ID);
24714 scratch_glyph_row.reversed_p = false;
24715 scratch_glyph_row.used[TEXT_AREA] = 0;
24716 SET_TEXT_POS (tem_it.position, 0, 0);
24717 tem_it.avoid_cursor_p = true;
24718 tem_it.bidi_p = true;
24719 tem_it.bidi_it.type = WEAK_EN;
24720
24721
24722
24723 tem_it.bidi_it.resolved_level = 2;
24724
24725
24726
24727 int width_limit =
24728 tem_it.last_visible_x - tem_it.first_visible_x
24729 - 3 * FRAME_COLUMN_WIDTH (it->f);
24730
24731 tem_it.face_id = lnum_face_id;
24732
24733
24734 if (lnum_face_id != current_lnum_face_id
24735 && (EQ (Vdisplay_line_numbers, Qvisual)
24736 ? this_line == 0
24737 : this_line == it->pt_lnum)
24738 && it->what != IT_EOB)
24739 tem_it.face_id = current_lnum_face_id;
24740 else if (!beyond_zv)
24741 {
24742 if (display_line_numbers_major_tick > 0
24743 && (lnum_to_display % display_line_numbers_major_tick == 0))
24744 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24745 0, DEFAULT_FACE_ID);
24746 else if (display_line_numbers_minor_tick > 0
24747 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24748 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24749 0, DEFAULT_FACE_ID);
24750 }
24751
24752
24753 for (const char *p = lnum_buf; *p; p++)
24754 {
24755
24756
24757 if (beyond_zv
24758
24759 || (!EQ (Vdisplay_line_numbers, Qvisual)
24760 && (it->continuation_lines_width > 0
24761 || (this_line == last_line && !first_time))))
24762 tem_it.c = tem_it.char_to_display = ' ';
24763 else
24764 tem_it.c = tem_it.char_to_display = *p;
24765 tem_it.len = 1;
24766
24767 SET_TEXT_POS (tem_it.position, -1, -1);
24768 PRODUCE_GLYPHS (&tem_it);
24769
24770
24771
24772 if (tem_it.current_x >= width_limit)
24773 {
24774 it->lnum_width = 0;
24775 it->lnum_pixel_width = 0;
24776 bidi_unshelve_cache (itdata, false);
24777 inhibit_free_realized_faces = save_free_realized_faces;
24778 return;
24779 }
24780 }
24781
24782 inhibit_free_realized_faces = save_free_realized_faces;
24783
24784
24785 it->lnum_pixel_width = tem_it.current_x;
24786
24787 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24788 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24789 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24790 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24791
24792 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24793
24794 for ( ; g < e; g++)
24795 {
24796 it->current_x += g->pixel_width;
24797
24798
24799
24800 if (it->current_x > it->first_visible_x)
24801 it->hpos++;
24802 if (p)
24803 {
24804 *p++ = *g;
24805 (*u)++;
24806 }
24807 }
24808
24809
24810
24811
24812 if (!beyond_zv)
24813 {
24814 if (it->glyph_row)
24815 {
24816 struct glyph_row *row = it->glyph_row;
24817
24818 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24819 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24820 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24821 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24822 tem_it.max_phys_descent);
24823 }
24824 else
24825 {
24826 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24827 it->max_descent = max (it->max_descent, tem_it.max_descent);
24828 it->max_phys_ascent = max (it->max_phys_ascent,
24829 tem_it.max_phys_ascent);
24830 it->max_phys_descent = max (it->max_phys_descent,
24831 tem_it.max_phys_descent);
24832 }
24833 }
24834
24835 it->line_number_produced_p = true;
24836
24837 bidi_unshelve_cache (itdata, false);
24838 }
24839
24840
24841
24842 static bool
24843 should_produce_line_number (struct it *it)
24844 {
24845 if (NILP (Vdisplay_line_numbers))
24846 return false;
24847
24848
24849 if (MINI_WINDOW_P (it->w))
24850 return false;
24851
24852 #ifdef HAVE_WINDOW_SYSTEM
24853
24854 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24855 return false;
24856 #endif
24857
24858
24859
24860
24861
24862 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24863 Qdisplay_line_numbers_disable,
24864 it->window);
24865
24866
24867
24868 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24869 val = disable_line_numbers_overlay_at_eob ();
24870 return NILP (val) ? true : false;
24871 }
24872
24873
24874
24875
24876
24877 static bool
24878 row_text_area_empty (struct glyph_row *row)
24879 {
24880 if (!row->reversed_p)
24881 {
24882 for (struct glyph *g = row->glyphs[TEXT_AREA];
24883 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24884 g++)
24885 if (!NILP (g->object) || g->charpos > 0)
24886 return false;
24887 }
24888 else
24889 {
24890 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24891 g > row->glyphs[TEXT_AREA];
24892 g--)
24893 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24894 return false;
24895 }
24896
24897 return true;
24898 }
24899
24900
24901
24902
24903
24904
24905
24906
24907 static bool
24908 display_line (struct it *it, int cursor_vpos)
24909 {
24910 struct glyph_row *row = it->glyph_row;
24911 Lisp_Object overlay_arrow_string;
24912 struct it wrap_it;
24913 void *wrap_data = NULL;
24914 bool may_wrap = false;
24915 int wrap_x UNINIT;
24916 int wrap_row_used = -1;
24917 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24918 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24919 int wrap_row_extra_line_spacing UNINIT;
24920 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24921 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24922 int cvpos;
24923 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24924 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24925 bool pending_handle_line_prefix = false;
24926 int tab_line = window_wants_tab_line (it->w);
24927 int header_line = window_wants_header_line (it->w);
24928 bool hscroll_this_line = (cursor_vpos >= 0
24929 && it->vpos == cursor_vpos - tab_line - header_line
24930 && hscrolling_current_line_p (it->w));
24931 int first_visible_x = it->first_visible_x;
24932 int last_visible_x = it->last_visible_x;
24933 int x_incr = 0;
24934
24935
24936 eassert (it->hpos == 0 && it->current_x == 0);
24937
24938 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24939 >= it->w->desired_matrix->nrows)
24940 {
24941 it->w->nrows_scale_factor++;
24942 it->f->fonts_changed = true;
24943 return false;
24944 }
24945
24946
24947 prepare_desired_row (it->w, row, false);
24948
24949 row->y = it->current_y;
24950 row->start = it->start;
24951 row->continuation_lines_width = it->continuation_lines_width;
24952 row->displays_text_p = true;
24953 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24954 it->starts_in_middle_of_char_p = false;
24955 it->stretch_adjust = 0;
24956 it->line_number_produced_p = false;
24957
24958
24959
24960
24961 if (hscroll_this_line)
24962 x_incr =
24963 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24964 * FRAME_COLUMN_WIDTH (it->f);
24965
24966 bool line_number_needed = should_produce_line_number (it);
24967
24968
24969
24970
24971 if (it->current_x < it->first_visible_x + x_incr)
24972 {
24973 enum move_it_result move_result;
24974
24975 this_line_min_pos = row->start.pos;
24976 if (hscroll_this_line)
24977 {
24978 it->first_visible_x += x_incr;
24979 it->last_visible_x += x_incr;
24980 }
24981 if (current_buffer->long_line_optimizations_p
24982 && it->line_wrap == TRUNCATE
24983 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24984 {
24985
24986
24987
24988
24989 ptrdiff_t chars_to_skip =
24990 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24991 move_result = fast_move_it_horizontally (it, chars_to_skip);
24992
24993 if (move_result == MOVE_X_REACHED)
24994 it->current_x = it->first_visible_x;
24995 else
24996 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24997 }
24998 else
24999 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
25000 MOVE_TO_POS | MOVE_TO_X);
25001
25002
25003
25004
25005
25006
25007 if (it->current_x < it->first_visible_x
25008 && (move_result == MOVE_NEWLINE_OR_CR
25009 || move_result == MOVE_POS_MATCH_OR_ZV))
25010 it->current_x = it->first_visible_x;
25011
25012
25013
25014 it->line_number_produced_p = false;
25015
25016
25017
25018
25019
25020
25021
25022
25023 min_pos = CHARPOS (this_line_min_pos);
25024 min_bpos = BYTEPOS (this_line_min_pos);
25025
25026
25027 if (line_number_needed)
25028 maybe_produce_line_number (it);
25029 }
25030 else if (it->area == TEXT_AREA)
25031 {
25032
25033 if (line_number_needed)
25034 maybe_produce_line_number (it);
25035
25036
25037
25038 handle_line_prefix (it);
25039 }
25040 else
25041 {
25042
25043
25044
25045
25046
25047
25048
25049 pending_handle_line_prefix = true;
25050 }
25051
25052
25053
25054 row->ascent = it->max_ascent;
25055 row->height = it->max_ascent + it->max_descent;
25056 row->phys_ascent = it->max_phys_ascent;
25057 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
25058 row->extra_line_spacing = it->max_extra_line_spacing;
25059
25060
25061 #define RECORD_MAX_MIN_POS(IT) \
25062 do \
25063 { \
25064 bool composition_p \
25065 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
25066 ptrdiff_t current_pos = \
25067 composition_p ? (IT)->cmp_it.charpos \
25068 : IT_CHARPOS (*(IT)); \
25069 ptrdiff_t current_bpos = \
25070 composition_p ? CHAR_TO_BYTE (current_pos) \
25071 : IT_BYTEPOS (*(IT)); \
25072 if (current_pos < min_pos) \
25073 { \
25074 min_pos = current_pos; \
25075 min_bpos = current_bpos; \
25076 } \
25077 if (IT_CHARPOS (*it) > max_pos) \
25078 { \
25079 max_pos = IT_CHARPOS (*it); \
25080 max_bpos = IT_BYTEPOS (*it); \
25081 } \
25082 } \
25083 while (false)
25084
25085
25086
25087 while (true)
25088 {
25089 int n_glyphs_before, hpos_before, x_before;
25090 int x, nglyphs;
25091 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
25092
25093
25094
25095 if (!get_next_display_element (it))
25096 {
25097 bool row_has_glyphs = false;
25098
25099
25100
25101
25102 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25103 row->exact_window_width_line_p = true;
25104 else if ((append_space_for_newline (it, true)
25105 && row->used[TEXT_AREA] == 1)
25106 || row->used[TEXT_AREA] == 0
25107 || (row_has_glyphs = row_text_area_empty (row)))
25108 {
25109 row->glyphs[TEXT_AREA]->charpos = -1;
25110
25111
25112 if (!row_has_glyphs)
25113 row->displays_text_p = false;
25114
25115 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
25116 && (!MINI_WINDOW_P (it->w)))
25117 row->indicate_empty_line_p = true;
25118 }
25119
25120 it->continuation_lines_width = 0;
25121
25122
25123
25124
25125 it->font_height = Qnil;
25126 it->voffset = 0;
25127 row->ends_at_zv_p = true;
25128
25129
25130
25131
25132
25133
25134
25135
25136 if (row->reversed_p
25137 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
25138 != DEFAULT_FACE_ID)
25139 extend_face_to_end_of_line (it);
25140 break;
25141 }
25142
25143
25144
25145 n_glyphs_before = row->used[TEXT_AREA];
25146 x = it->current_x;
25147
25148
25149
25150 if (it->line_wrap != TRUNCATE)
25151 {
25152 ascent = it->max_ascent;
25153 descent = it->max_descent;
25154 phys_ascent = it->max_phys_ascent;
25155 phys_descent = it->max_phys_descent;
25156
25157 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
25158 {
25159 bool next_may_wrap = may_wrap;
25160
25161 if (char_can_wrap_after (it))
25162 next_may_wrap = true;
25163 else
25164 next_may_wrap = false;
25165
25166 if (may_wrap && char_can_wrap_before (it))
25167 {
25168 SAVE_IT (wrap_it, *it, wrap_data);
25169 wrap_x = x;
25170 wrap_row_used = row->used[TEXT_AREA];
25171 wrap_row_ascent = row->ascent;
25172 wrap_row_height = row->height;
25173 wrap_row_phys_ascent = row->phys_ascent;
25174 wrap_row_phys_height = row->phys_height;
25175 wrap_row_extra_line_spacing = row->extra_line_spacing;
25176 wrap_row_min_pos = min_pos;
25177 wrap_row_min_bpos = min_bpos;
25178 wrap_row_max_pos = max_pos;
25179 wrap_row_max_bpos = max_bpos;
25180 }
25181
25182 may_wrap = next_may_wrap;
25183 }
25184 }
25185
25186 PRODUCE_GLYPHS (it);
25187
25188
25189
25190 if (it->area != TEXT_AREA)
25191 {
25192 row->ascent = max (row->ascent, it->max_ascent);
25193 row->height = max (row->height, it->max_ascent + it->max_descent);
25194 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25195 row->phys_height = max (row->phys_height,
25196 it->max_phys_ascent + it->max_phys_descent);
25197 row->extra_line_spacing = max (row->extra_line_spacing,
25198 it->max_extra_line_spacing);
25199 set_iterator_to_next (it, true);
25200
25201
25202
25203 if (it->area == TEXT_AREA && pending_handle_line_prefix)
25204 {
25205
25206 if (line_number_needed)
25207 maybe_produce_line_number (it);
25208
25209 pending_handle_line_prefix = false;
25210 handle_line_prefix (it);
25211 }
25212 continue;
25213 }
25214
25215
25216
25217
25218
25219
25220
25221
25222
25223
25224 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
25225 hpos_before = it->hpos;
25226 x_before = x;
25227
25228 if (
25229 nglyphs > 0
25230
25231 && it->current_x < it->last_visible_x)
25232 {
25233 it->hpos += nglyphs;
25234 row->ascent = max (row->ascent, it->max_ascent);
25235 row->height = max (row->height, it->max_ascent + it->max_descent);
25236 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25237 row->phys_height = max (row->phys_height,
25238 it->max_phys_ascent + it->max_phys_descent);
25239 row->extra_line_spacing = max (row->extra_line_spacing,
25240 it->max_extra_line_spacing);
25241 if (it->current_x - it->pixel_width < it->first_visible_x
25242
25243
25244
25245 && !line_number_needed
25246
25247
25248
25249
25250 && !row->reversed_p)
25251 row->x = x - it->first_visible_x;
25252
25253
25254 if (it->bidi_p)
25255 RECORD_MAX_MIN_POS (it);
25256 }
25257 else
25258 {
25259 int i, new_x;
25260 struct glyph *glyph;
25261
25262 for (i = 0; i < nglyphs; ++i, x = new_x)
25263 {
25264
25265
25266
25267 if (!row->reversed_p)
25268 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25269 else
25270 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25271 new_x = x + glyph->pixel_width;
25272
25273 if (
25274 it->line_wrap != TRUNCATE
25275 && (
25276 new_x > it->last_visible_x
25277
25278 || (new_x == it->last_visible_x
25279 && FRAME_WINDOW_P (it->f)
25280 && (row->reversed_p
25281 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25282 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25283 {
25284
25285
25286 if (it->hpos == 0
25287 || (new_x == it->last_visible_x
25288 && FRAME_WINDOW_P (it->f)
25289 && (row->reversed_p
25290 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25291 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25292 {
25293
25294
25295
25296
25297 row->continued_p = true;
25298 it->current_x = new_x;
25299 it->continuation_lines_width += new_x;
25300 ++it->hpos;
25301 if (i == nglyphs - 1)
25302 {
25303
25304
25305 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25306 && wrap_row_used > 0
25307
25308
25309
25310
25311
25312
25313
25314
25315
25316
25317 && (!may_wrap || !char_can_wrap_before (it)))
25318 goto back_to_wrap;
25319
25320
25321
25322
25323 if (it->bidi_p)
25324 RECORD_MAX_MIN_POS (it);
25325 set_iterator_to_next (it, true);
25326 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25327 {
25328 if (!get_next_display_element (it))
25329 {
25330 row->exact_window_width_line_p = true;
25331 it->continuation_lines_width = 0;
25332 it->font_height = Qnil;
25333 it->voffset = 0;
25334 row->continued_p = false;
25335 row->ends_at_zv_p = true;
25336 }
25337 else if (ITERATOR_AT_END_OF_LINE_P (it))
25338 {
25339 row->continued_p = false;
25340 row->exact_window_width_line_p = true;
25341 }
25342
25343
25344 else if (wrap_row_used > 0
25345
25346
25347
25348
25349
25350
25351
25352
25353
25354 && (!may_wrap || !char_can_wrap_before (it)))
25355 goto back_to_wrap;
25356
25357 }
25358 }
25359 else if (it->bidi_p)
25360 RECORD_MAX_MIN_POS (it);
25361 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25362 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25363 extend_face_to_end_of_line (it);
25364 }
25365 else if (CHAR_GLYPH_PADDING_P (*glyph)
25366 && !FRAME_WINDOW_P (it->f))
25367 {
25368
25369
25370
25371 if (row->reversed_p)
25372 unproduce_glyphs (it, row->used[TEXT_AREA]
25373 - n_glyphs_before);
25374 row->used[TEXT_AREA] = n_glyphs_before;
25375
25376
25377
25378 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25379 < row->glyphs[1 + TEXT_AREA])
25380 produce_special_glyphs (it, IT_CONTINUATION);
25381
25382 row->continued_p = true;
25383 it->current_x = x_before;
25384 it->continuation_lines_width += x_before;
25385
25386
25387
25388 it->max_ascent = ascent;
25389 it->max_descent = descent;
25390 it->max_phys_ascent = phys_ascent;
25391 it->max_phys_descent = phys_descent;
25392 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25393 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25394 extend_face_to_end_of_line (it);
25395 }
25396 else if (wrap_row_used > 0)
25397 {
25398 back_to_wrap:
25399 if (row->reversed_p)
25400 unproduce_glyphs (it,
25401 row->used[TEXT_AREA] - wrap_row_used);
25402 RESTORE_IT (it, &wrap_it, wrap_data);
25403 it->continuation_lines_width += wrap_x;
25404 row->used[TEXT_AREA] = wrap_row_used;
25405 row->ascent = wrap_row_ascent;
25406 row->height = wrap_row_height;
25407 row->phys_ascent = wrap_row_phys_ascent;
25408 row->phys_height = wrap_row_phys_height;
25409 row->extra_line_spacing = wrap_row_extra_line_spacing;
25410 min_pos = wrap_row_min_pos;
25411 min_bpos = wrap_row_min_bpos;
25412 max_pos = wrap_row_max_pos;
25413 max_bpos = wrap_row_max_bpos;
25414 row->continued_p = true;
25415 row->ends_at_zv_p = false;
25416 row->exact_window_width_line_p = false;
25417
25418
25419
25420 extend_face_to_end_of_line (it);
25421 }
25422 else if ((it->what == IT_CHARACTER
25423 || it->what == IT_STRETCH
25424 || it->what == IT_COMPOSITION)
25425 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25426 {
25427
25428
25429
25430
25431
25432 if ((row->reversed_p
25433 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25434 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25435 produce_special_glyphs (it, IT_CONTINUATION);
25436 it->continuation_lines_width += it->last_visible_x;
25437 row->ends_in_middle_of_char_p = true;
25438 row->continued_p = true;
25439 glyph->pixel_width = it->last_visible_x - x;
25440 it->starts_in_middle_of_char_p = true;
25441 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25442 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25443 extend_face_to_end_of_line (it);
25444 }
25445 else
25446 {
25447
25448
25449
25450 if (row->reversed_p)
25451 unproduce_glyphs (it, row->used[TEXT_AREA]
25452 - (n_glyphs_before + i));
25453 row->used[TEXT_AREA] = n_glyphs_before + i;
25454
25455
25456 it->current_x = x_before;
25457 it->continuation_lines_width += x;
25458 if (!FRAME_WINDOW_P (it->f)
25459 || (row->reversed_p
25460 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25461 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25462 produce_special_glyphs (it, IT_CONTINUATION);
25463 row->continued_p = true;
25464
25465 extend_face_to_end_of_line (it);
25466
25467 if (nglyphs > 1 && i > 0)
25468 {
25469 row->ends_in_middle_of_char_p = true;
25470 it->starts_in_middle_of_char_p = true;
25471 }
25472
25473
25474
25475 it->max_ascent = ascent;
25476 it->max_descent = descent;
25477 it->max_phys_ascent = phys_ascent;
25478 it->max_phys_descent = phys_descent;
25479 }
25480
25481 break;
25482 }
25483 else if (new_x > it->first_visible_x)
25484 {
25485
25486 ++it->hpos;
25487
25488
25489
25490
25491 if (it->bidi_p)
25492 RECORD_MAX_MIN_POS (it);
25493
25494 if (x < it->first_visible_x && !row->reversed_p
25495 && !line_number_needed)
25496
25497
25498
25499
25500
25501
25502 row->x = x - it->first_visible_x;
25503
25504
25505
25506
25507
25508
25509 if (row->reversed_p
25510 && new_x > it->last_visible_x
25511 && !line_number_needed
25512 && !(it->line_wrap == TRUNCATE
25513 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25514 {
25515 eassert (FRAME_WINDOW_P (it->f));
25516 row->x = it->last_visible_x - new_x;
25517 }
25518 }
25519 else
25520 {
25521
25522
25523
25524
25525
25526 eassert (it->first_visible_x <= it->last_visible_x);
25527 }
25528 }
25529
25530
25531 if (it->bidi_p && nglyphs == 0)
25532 RECORD_MAX_MIN_POS (it);
25533
25534 row->ascent = max (row->ascent, it->max_ascent);
25535 row->height = max (row->height, it->max_ascent + it->max_descent);
25536 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25537 row->phys_height = max (row->phys_height,
25538 it->max_phys_ascent + it->max_phys_descent);
25539 row->extra_line_spacing = max (row->extra_line_spacing,
25540 it->max_extra_line_spacing);
25541
25542
25543 if (row->continued_p || row->ends_at_zv_p)
25544 break;
25545 }
25546
25547 at_end_of_line:
25548
25549
25550
25551 if (ITERATOR_AT_END_OF_LINE_P (it))
25552 {
25553 int used_before = row->used[TEXT_AREA];
25554
25555 row->ends_in_newline_from_string_p = STRINGP (it->object);
25556
25557
25558
25559 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25560 append_space_for_newline (it, false);
25561
25562
25563 extend_face_to_end_of_line (it);
25564
25565
25566 if (used_before == 0)
25567 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25568
25569
25570
25571 it->eol_pos = it->current.pos;
25572
25573
25574 set_iterator_to_next (it, true);
25575 it->continuation_lines_width = 0;
25576 break;
25577 }
25578
25579
25580
25581
25582
25583
25584
25585
25586 bool overwide_wrap_prefix =
25587 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25588 && it->sp > 0 && it->method == GET_FROM_STRETCH
25589 && it->current_x >= it->last_visible_x
25590 && it->continuation_lines_width > 0
25591 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25592
25593
25594
25595 if (!overwide_wrap_prefix)
25596 set_iterator_to_next (it, true);
25597
25598
25599
25600 if (it->line_wrap == TRUNCATE
25601 && ((FRAME_WINDOW_P (it->f)
25602
25603
25604
25605
25606 && ((row->reversed_p
25607 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25608 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25609 || it->what == IT_IMAGE))
25610 ? (it->current_x >= it->last_visible_x)
25611 : (it->current_x > it->last_visible_x)))
25612 {
25613
25614 if (!FRAME_WINDOW_P (it->f)
25615 || (row->reversed_p
25616 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25617 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25618 {
25619 int i, n;
25620
25621 if (!row->reversed_p)
25622 {
25623 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25624 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25625 break;
25626 }
25627 else
25628 {
25629 for (i = 0; i < row->used[TEXT_AREA]; i++)
25630 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25631 break;
25632
25633
25634
25635
25636
25637 unproduce_glyphs (it, i + 1);
25638
25639 i = row->used[TEXT_AREA] - (i + 1);
25640 }
25641
25642
25643
25644
25645 if (it->current_x > it->last_visible_x)
25646 {
25647 it->current_x = x_before;
25648 if (!FRAME_WINDOW_P (it->f))
25649 {
25650 for (n = row->used[TEXT_AREA]; i < n; ++i)
25651 {
25652 row->used[TEXT_AREA] = i;
25653 produce_special_glyphs (it, IT_TRUNCATION);
25654 }
25655 }
25656 else
25657 {
25658 row->used[TEXT_AREA] = i;
25659 produce_special_glyphs (it, IT_TRUNCATION);
25660 }
25661 it->hpos = hpos_before;
25662 }
25663 }
25664 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25665 {
25666
25667 if (!get_next_display_element (it))
25668 {
25669 it->continuation_lines_width = 0;
25670 it->font_height = Qnil;
25671 it->voffset = 0;
25672 row->ends_at_zv_p = true;
25673 row->exact_window_width_line_p = true;
25674 break;
25675 }
25676 if (ITERATOR_AT_END_OF_LINE_P (it))
25677 {
25678 row->exact_window_width_line_p = true;
25679 goto at_end_of_line;
25680 }
25681 it->current_x = x_before;
25682 it->hpos = hpos_before;
25683 }
25684
25685 row->truncated_on_right_p = true;
25686 it->continuation_lines_width = 0;
25687 reseat_at_next_visible_line_start (it, false);
25688
25689
25690
25691
25692 if (IT_BYTEPOS (*it) > BEG_BYTE)
25693 row->ends_at_zv_p =
25694 IT_BYTEPOS (*it) >= ZV_BYTE
25695 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25696 else
25697 row->ends_at_zv_p = false;
25698 break;
25699 }
25700 }
25701
25702 if (wrap_data)
25703 bidi_unshelve_cache (wrap_data, true);
25704
25705
25706
25707 if (it->first_visible_x
25708 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25709 {
25710 if (!FRAME_WINDOW_P (it->f)
25711 || (((row->reversed_p
25712 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25713 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25714
25715
25716 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25717 insert_left_trunc_glyphs (it);
25718 row->truncated_on_left_p = true;
25719 }
25720
25721
25722
25723
25724
25725
25726 row->end = it->current;
25727 if (!it->bidi_p)
25728 {
25729 row->minpos = row->start.pos;
25730 row->maxpos = row->end.pos;
25731 }
25732 else
25733 {
25734
25735
25736
25737
25738 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25739 }
25740
25741
25742
25743
25744
25745 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25746 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25747 !NILP (overlay_arrow_string)))
25748 {
25749
25750 if (STRINGP (overlay_arrow_string))
25751 {
25752 struct glyph_row *arrow_row
25753 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25754 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25755 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25756 struct glyph *p = row->glyphs[TEXT_AREA];
25757 struct glyph *p2, *end;
25758
25759
25760 while (glyph < arrow_end)
25761 *p++ = *glyph++;
25762
25763
25764 p2 = p;
25765 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25766 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25767 ++p2;
25768 if (p2 > p)
25769 {
25770 while (p2 < end)
25771 *p++ = *p2++;
25772 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25773 }
25774 }
25775 else
25776 {
25777 eassert (FIXNUMP (overlay_arrow_string));
25778 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25779 }
25780 overlay_arrow_seen = true;
25781 }
25782
25783
25784 if (!NILP (Vshow_trailing_whitespace))
25785 highlight_trailing_whitespace (it);
25786
25787
25788 compute_line_metrics (it);
25789
25790
25791
25792
25793
25794
25795
25796 row->ends_in_ellipsis_p
25797 = (it->method == GET_FROM_DISPLAY_VECTOR
25798 && it->ellipsis_p);
25799
25800
25801 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25802 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25803 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25804 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25805
25806 it->left_user_fringe_bitmap = 0;
25807 it->left_user_fringe_face_id = 0;
25808 it->right_user_fringe_bitmap = 0;
25809 it->right_user_fringe_face_id = 0;
25810
25811
25812
25813
25814
25815
25816 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25817 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25818 row->redraw_fringe_bitmaps_p = true;
25819
25820
25821 cvpos = it->w->cursor.vpos;
25822 if ((cvpos < 0
25823
25824
25825
25826
25827
25828
25829
25830
25831 || (it->bidi_p
25832 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25833 && PT >= MATRIX_ROW_START_CHARPOS (row)
25834 && PT <= MATRIX_ROW_END_CHARPOS (row)
25835 && cursor_row_p (row))
25836 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25837
25838
25839
25840
25841
25842 it->current_x = it->hpos = 0;
25843 it->current_y += row->height;
25844
25845
25846 if (hscroll_this_line)
25847 {
25848 it->first_visible_x = first_visible_x;
25849 it->last_visible_x = last_visible_x;
25850 }
25851 SET_TEXT_POS (it->eol_pos, 0, 0);
25852 ++it->vpos;
25853 ++it->glyph_row;
25854
25855
25856
25857
25858 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25859 it->glyph_row->reversed_p = row->reversed_p;
25860 it->start = row->end;
25861 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25862
25863 #undef RECORD_MAX_MIN_POS
25864 }
25865
25866 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25867 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25868 doc:
25869
25870
25871
25872
25873
25874
25875
25876
25877 )
25878 (Lisp_Object buffer)
25879 {
25880 struct buffer *buf = current_buffer;
25881 struct buffer *old = buf;
25882
25883 if (! NILP (buffer))
25884 {
25885 CHECK_BUFFER (buffer);
25886 buf = XBUFFER (buffer);
25887 }
25888
25889 if (NILP (BVAR (buf, bidi_display_reordering))
25890 || NILP (BVAR (buf, enable_multibyte_characters))
25891
25892
25893 || redisplay__inhibit_bidi)
25894 return Qleft_to_right;
25895 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25896 return BVAR (buf, bidi_paragraph_direction);
25897 else
25898 {
25899
25900
25901
25902 struct bidi_it itb;
25903 ptrdiff_t pos = BUF_PT (buf);
25904 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25905 int c;
25906 void *itb_data = bidi_shelve_cache ();
25907
25908 set_buffer_temp (buf);
25909
25910
25911
25912
25913
25914 if (pos >= ZV && pos > BEGV)
25915 dec_both (&pos, &bytepos);
25916 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25917 if (fast_looking_at (trailing_white_space,
25918 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25919 {
25920 while ((c = FETCH_BYTE (bytepos)) == '\n'
25921 || c == ' ' || c == '\t' || c == '\f')
25922 {
25923 if (bytepos <= BEGV_BYTE)
25924 break;
25925 bytepos--;
25926 pos--;
25927 }
25928 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25929 bytepos--;
25930 }
25931 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25932 itb.paragraph_dir = NEUTRAL_DIR;
25933 itb.string.s = NULL;
25934 itb.string.lstring = Qnil;
25935 itb.string.bufpos = 0;
25936 itb.string.from_disp_str = false;
25937 itb.string.unibyte = false;
25938
25939
25940
25941 itb.w = NULL;
25942 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25943 bidi_unshelve_cache (itb_data, false);
25944 set_buffer_temp (old);
25945 switch (itb.paragraph_dir)
25946 {
25947 case L2R:
25948 return Qleft_to_right;
25949 break;
25950 case R2L:
25951 return Qright_to_left;
25952 break;
25953 default:
25954 emacs_abort ();
25955 }
25956 }
25957 }
25958
25959 DEFUN ("bidi-find-overridden-directionality",
25960 Fbidi_find_overridden_directionality,
25961 Sbidi_find_overridden_directionality, 3, 4, 0,
25962 doc:
25963
25964
25965
25966
25967
25968
25969
25970
25971
25972
25973
25974
25975
25976
25977
25978
25979
25980
25981
25982
25983
25984
25985
25986
25987
25988
25989
25990
25991
25992
25993
25994
25995
25996
25997
25998
25999 )
26000 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
26001 {
26002 struct buffer *buf = current_buffer;
26003 struct buffer *old = buf;
26004 struct window *w = NULL;
26005 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
26006 struct bidi_it itb;
26007 ptrdiff_t from_pos, to_pos, from_bpos;
26008 void *itb_data;
26009
26010 if (!NILP (object))
26011 {
26012 if (BUFFERP (object))
26013 buf = XBUFFER (object);
26014 else if (WINDOWP (object))
26015 {
26016 w = decode_live_window (object);
26017 buf = XBUFFER (w->contents);
26018 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
26019 }
26020 else
26021 CHECK_STRING (object);
26022 }
26023
26024 if (STRINGP (object))
26025 {
26026
26027
26028 if (!STRING_MULTIBYTE (object)
26029
26030
26031
26032 || redisplay__inhibit_bidi)
26033 return Qnil;
26034
26035 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
26036 if (from_pos >= SCHARS (object))
26037 return Qnil;
26038
26039
26040 itb_data = bidi_shelve_cache ();
26041 itb.paragraph_dir = NEUTRAL_DIR;
26042 itb.string.lstring = object;
26043 itb.string.s = NULL;
26044 itb.string.schars = SCHARS (object);
26045 itb.string.bufpos = 0;
26046 itb.string.from_disp_str = false;
26047 itb.string.unibyte = false;
26048 itb.w = w;
26049 bidi_init_it (0, 0, frame_window_p, &itb);
26050 }
26051 else
26052 {
26053
26054
26055 if (NILP (BVAR (buf, bidi_display_reordering))
26056 || NILP (BVAR (buf, enable_multibyte_characters))
26057
26058
26059
26060 || redisplay__inhibit_bidi)
26061 return Qnil;
26062
26063 set_buffer_temp (buf);
26064 validate_region (&from, &to);
26065 from_pos = XFIXNUM (from);
26066 to_pos = XFIXNUM (to);
26067 if (from_pos >= ZV)
26068 return Qnil;
26069
26070
26071 itb_data = bidi_shelve_cache ();
26072 from_bpos = CHAR_TO_BYTE (from_pos);
26073 if (from_pos == BEGV)
26074 {
26075 itb.charpos = BEGV;
26076 itb.bytepos = BEGV_BYTE;
26077 }
26078 else if (FETCH_BYTE (from_bpos - 1) == '\n')
26079 {
26080 itb.charpos = from_pos;
26081 itb.bytepos = from_bpos;
26082 }
26083 else
26084 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
26085 -1, &itb.bytepos);
26086 itb.paragraph_dir = NEUTRAL_DIR;
26087 itb.string.s = NULL;
26088 itb.string.lstring = Qnil;
26089 itb.string.bufpos = 0;
26090 itb.string.from_disp_str = false;
26091 itb.string.unibyte = false;
26092 itb.w = w;
26093 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
26094 }
26095
26096 ptrdiff_t found;
26097 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
26098 do {
26099 bidi_paragraph_init (bdir, &itb, false);
26100 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
26101 ;
26102 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
26103
26104 bidi_unshelve_cache (itb_data, false);
26105 set_buffer_temp (old);
26106
26107 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
26108 }
26109
26110 DEFUN ("move-point-visually", Fmove_point_visually,
26111 Smove_point_visually, 1, 1, 0,
26112 doc:
26113
26114
26115
26116 )
26117 (Lisp_Object direction)
26118 {
26119 struct window *w = XWINDOW (selected_window);
26120 struct buffer *b = XBUFFER (w->contents);
26121 struct glyph_row *row;
26122 int dir;
26123 Lisp_Object paragraph_dir;
26124
26125 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
26126 (!(ROW)->continued_p \
26127 && NILP ((GLYPH)->object) \
26128 && (GLYPH)->type == CHAR_GLYPH \
26129 && (GLYPH)->u.ch == ' ' \
26130 && (GLYPH)->charpos >= 0 \
26131 && !(GLYPH)->avoid_cursor_p)
26132
26133 CHECK_FIXNUM (direction);
26134 dir = XFIXNUM (direction);
26135 if (dir > 0)
26136 dir = 1;
26137 else
26138 dir = -1;
26139
26140
26141
26142
26143 if (w->window_end_valid
26144 && !windows_or_buffers_changed
26145 && b
26146 && !b->clip_changed
26147 && !b->prevent_redisplay_optimizations_p
26148 && !window_outdated (w)
26149
26150
26151
26152 && w->last_point == BUF_PT (b)
26153 && w->cursor.vpos >= 0
26154 && w->cursor.vpos < w->current_matrix->nrows
26155 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
26156 {
26157 struct glyph *g = row->glyphs[TEXT_AREA];
26158 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
26159 struct glyph *gpt = g + w->cursor.hpos;
26160
26161 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
26162 {
26163 if (BUFFERP (g->object) && g->charpos != PT)
26164 {
26165 SET_PT (g->charpos);
26166 w->cursor.vpos = -1;
26167 return make_fixnum (PT);
26168 }
26169 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
26170 {
26171 ptrdiff_t new_pos;
26172
26173 if (BUFFERP (gpt->object))
26174 {
26175 new_pos = PT;
26176 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
26177 new_pos += (row->reversed_p ? -dir : dir);
26178 else
26179 new_pos -= (row->reversed_p ? -dir : dir);
26180 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
26181
26182
26183 if (new_pos == PT)
26184 break;
26185 }
26186 else if (BUFFERP (g->object))
26187 new_pos = g->charpos;
26188 else
26189 break;
26190 SET_PT (new_pos);
26191 w->cursor.vpos = -1;
26192 return make_fixnum (PT);
26193 }
26194 else if (ROW_GLYPH_NEWLINE_P (row, g))
26195 {
26196
26197
26198
26199 if (g->charpos > 0)
26200 SET_PT (g->charpos);
26201 else if (row->ends_at_zv_p && PT != ZV)
26202 SET_PT (ZV);
26203 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
26204 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26205 else
26206 break;
26207 w->cursor.vpos = -1;
26208 return make_fixnum (PT);
26209 }
26210 }
26211 if (g == e || NILP (g->object))
26212 {
26213 if (row->truncated_on_left_p || row->truncated_on_right_p)
26214 goto simulate_display;
26215 if (!row->reversed_p)
26216 row += dir;
26217 else
26218 row -= dir;
26219 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
26220 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
26221 goto simulate_display;
26222
26223 if (dir > 0)
26224 {
26225 if (row->reversed_p && !row->continued_p)
26226 {
26227 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26228 w->cursor.vpos = -1;
26229 return make_fixnum (PT);
26230 }
26231 g = row->glyphs[TEXT_AREA];
26232 e = g + row->used[TEXT_AREA];
26233 for ( ; g < e; g++)
26234 {
26235 if (BUFFERP (g->object)
26236
26237
26238
26239 || ROW_GLYPH_NEWLINE_P (row, g)
26240
26241
26242 || (row->ends_at_zv_p
26243 && !row->reversed_p
26244 && NILP (g->object)
26245 && g->type == CHAR_GLYPH
26246 && g->u.ch == ' '))
26247 {
26248 if (g->charpos > 0)
26249 SET_PT (g->charpos);
26250 else if (!row->reversed_p
26251 && row->ends_at_zv_p
26252 && PT != ZV)
26253 SET_PT (ZV);
26254 else
26255 continue;
26256 w->cursor.vpos = -1;
26257 return make_fixnum (PT);
26258 }
26259 }
26260 }
26261 else
26262 {
26263 if (!row->reversed_p && !row->continued_p)
26264 {
26265 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26266 w->cursor.vpos = -1;
26267 return make_fixnum (PT);
26268 }
26269 e = row->glyphs[TEXT_AREA];
26270 g = e + row->used[TEXT_AREA] - 1;
26271 for ( ; g >= e; g--)
26272 {
26273 if (BUFFERP (g->object)
26274 || (ROW_GLYPH_NEWLINE_P (row, g)
26275 && g->charpos > 0)
26276
26277
26278
26279 || g->type == STRETCH_GLYPH
26280 || (row->ends_at_zv_p
26281 && row->reversed_p
26282 && NILP (g->object)
26283 && g->type == CHAR_GLYPH
26284 && g->u.ch == ' '))
26285 {
26286 if (g->charpos > 0)
26287 SET_PT (g->charpos);
26288 else if (row->reversed_p
26289 && row->ends_at_zv_p
26290 && PT != ZV)
26291 SET_PT (ZV);
26292 else
26293 continue;
26294 w->cursor.vpos = -1;
26295 return make_fixnum (PT);
26296 }
26297 }
26298 }
26299 }
26300 }
26301
26302 simulate_display:
26303
26304
26305
26306
26307 if (b)
26308 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26309 else
26310 paragraph_dir = Qleft_to_right;
26311 if (EQ (paragraph_dir, Qright_to_left))
26312 dir = -dir;
26313 if (PT <= BEGV && dir < 0)
26314 xsignal0 (Qbeginning_of_buffer);
26315 else if (PT >= ZV && dir > 0)
26316 xsignal0 (Qend_of_buffer);
26317 else
26318 {
26319 struct text_pos pt;
26320 struct it it;
26321 int pt_x, target_x, pixel_width, pt_vpos;
26322 bool at_eol_p;
26323 bool overshoot_expected = false;
26324 bool target_is_eol_p = false;
26325 void *itdata = bidi_shelve_cache ();
26326
26327
26328 SET_TEXT_POS (pt, PT, PT_BYTE);
26329 start_display (&it, w, pt);
26330
26331
26332
26333
26334
26335
26336 if (it.line_wrap == TRUNCATE)
26337 it.last_visible_x = DISP_INFINITY;
26338
26339 if (it.cmp_it.id < 0
26340 && it.method == GET_FROM_STRING
26341 && it.area == TEXT_AREA
26342 && it.string_from_display_prop_p
26343 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26344 overshoot_expected = true;
26345
26346
26347
26348
26349
26350 reseat:
26351 reseat_at_previous_visible_line_start (&it);
26352 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26353 if (IT_CHARPOS (it) != PT)
26354 {
26355 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26356 -1, -1, -1, MOVE_TO_POS);
26357
26358
26359
26360 if (it.method == GET_FROM_DISPLAY_VECTOR
26361 && it.current.dpvec_index > 0
26362 && !overshoot_expected)
26363 {
26364 overshoot_expected = true;
26365 goto reseat;
26366 }
26367 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26368 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26369 }
26370 pt_x = it.current_x;
26371 pt_vpos = it.vpos;
26372 if (dir > 0 || overshoot_expected)
26373 {
26374 struct glyph_row *row = it.glyph_row;
26375
26376
26377
26378
26379 if (pt_x == 0)
26380 get_next_display_element (&it);
26381 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26382 it.glyph_row = NULL;
26383 PRODUCE_GLYPHS (&it);
26384 it.glyph_row = row;
26385
26386
26387
26388 it.current_x = pt_x;
26389 }
26390 else
26391 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26392 pixel_width = it.pixel_width;
26393 if (overshoot_expected && at_eol_p)
26394 pixel_width = 0;
26395 else if (pixel_width <= 0)
26396 pixel_width = 1;
26397
26398
26399
26400
26401 if (overshoot_expected)
26402 {
26403 if (it.bidi_p)
26404 pt_x += pixel_width * it.bidi_it.scan_dir;
26405 else
26406 pt_x += pixel_width;
26407 }
26408
26409
26410
26411
26412
26413
26414
26415 if (dir > 0)
26416 target_x = pt_x + pixel_width;
26417 else
26418 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26419
26420
26421
26422
26423
26424 if (dir < 0)
26425 {
26426 if (pt_x > 0)
26427 {
26428 start_display (&it, w, pt);
26429 if (it.line_wrap == TRUNCATE)
26430 it.last_visible_x = DISP_INFINITY;
26431 reseat_at_previous_visible_line_start (&it);
26432 it.current_x = it.current_y = it.hpos = 0;
26433 if (pt_vpos != 0)
26434 move_it_by_lines (&it, pt_vpos);
26435 }
26436 else
26437 {
26438 move_it_by_lines (&it, -1);
26439 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26440 target_is_eol_p = true;
26441
26442
26443
26444
26445
26446
26447
26448
26449
26450
26451 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26452 {
26453 void *it_data = NULL;
26454 struct it it2;
26455
26456 SAVE_IT (it2, it, it_data);
26457 move_it_in_display_line_to (&it, ZV, target_x,
26458 MOVE_TO_POS | MOVE_TO_X);
26459
26460
26461 if (it.current_x != target_x)
26462 target_x = it.current_x - 1;
26463 RESTORE_IT (&it, &it2, it_data);
26464 }
26465 }
26466 }
26467 else
26468 {
26469 if (at_eol_p
26470 || (target_x >= it.last_visible_x
26471 && it.line_wrap != TRUNCATE))
26472 {
26473 if (pt_x > 0)
26474 move_it_by_lines (&it, 0);
26475 move_it_by_lines (&it, 1);
26476 target_x = 0;
26477 }
26478 }
26479
26480
26481
26482
26483
26484
26485
26486 if (FRAME_WINDOW_P (it.f) && dir < 0)
26487 {
26488 struct text_pos new_pos;
26489 enum move_it_result rc = MOVE_X_REACHED;
26490
26491 if (it.current_x == 0)
26492 get_next_display_element (&it);
26493 if (it.what == IT_COMPOSITION)
26494 {
26495 new_pos.charpos = it.cmp_it.charpos;
26496 new_pos.bytepos = -1;
26497 }
26498 else
26499 new_pos = it.current.pos;
26500
26501 while (it.current_x + it.pixel_width <= target_x
26502 && (rc == MOVE_X_REACHED
26503
26504
26505
26506 || (it.line_wrap == WORD_WRAP
26507 && rc == MOVE_POS_MATCH_OR_ZV)))
26508 {
26509 int new_x = it.current_x + it.pixel_width;
26510
26511
26512
26513
26514
26515
26516
26517 if (it.what == IT_COMPOSITION)
26518 {
26519 new_pos.charpos = it.cmp_it.charpos;
26520 new_pos.bytepos = -1;
26521 }
26522 else
26523 new_pos = it.current.pos;
26524 if (new_x == it.current_x)
26525 new_x++;
26526 rc = move_it_in_display_line_to (&it, ZV, new_x,
26527 MOVE_TO_POS | MOVE_TO_X);
26528 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26529 break;
26530 }
26531
26532
26533 if (new_pos.bytepos == -1)
26534 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26535 it.current.pos = new_pos;
26536 }
26537 else if (it.current_x != target_x)
26538 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26539
26540
26541
26542 if (dir > 0)
26543 {
26544 while (IT_CHARPOS (it) == PT)
26545 {
26546 set_iterator_to_next (&it, false);
26547 if (!get_next_display_element (&it))
26548 break;
26549 }
26550 }
26551
26552
26553 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26554 bidi_unshelve_cache (itdata, false);
26555 }
26556
26557 return make_fixnum (PT);
26558
26559 #undef ROW_GLYPH_NEWLINE_P
26560 }
26561
26562 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26563 Sbidi_resolved_levels, 0, 1, 0,
26564 doc:
26565
26566
26567
26568
26569
26570
26571
26572
26573
26574
26575
26576
26577
26578
26579
26580
26581
26582
26583
26584
26585
26586
26587
26588
26589
26590 )
26591 (Lisp_Object vpos)
26592 {
26593 struct window *w = XWINDOW (selected_window);
26594 struct buffer *b = XBUFFER (w->contents);
26595 int nrow;
26596 struct glyph_row *row;
26597
26598 if (NILP (vpos))
26599 {
26600 int d1, d2, d3, d4, d5;
26601
26602 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26603 }
26604 else
26605 {
26606 CHECK_FIXNUM (vpos);
26607 nrow = XFIXNUM (vpos);
26608 }
26609
26610
26611 if (w->window_end_valid
26612 && !windows_or_buffers_changed
26613 && b
26614 && !b->clip_changed
26615 && !b->prevent_redisplay_optimizations_p
26616 && !window_outdated (w)
26617 && nrow >= 0
26618 && nrow < w->current_matrix->nrows
26619 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26620 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26621 {
26622 struct glyph *g, *e, *g1;
26623 int nglyphs, i;
26624 Lisp_Object levels;
26625
26626 if (!row->reversed_p)
26627 {
26628 g = g1 = row->glyphs[TEXT_AREA];
26629 e = g + row->used[TEXT_AREA];
26630
26631
26632
26633 while (g < e
26634 && NILP (g->object)
26635 && g->charpos < 0)
26636 g++;
26637 g1 = g;
26638
26639
26640 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26641 nglyphs++;
26642
26643
26644 levels = make_uninit_vector (nglyphs);
26645 for (i = 0; g1 < g; i++, g1++)
26646 ASET (levels, i, make_fixnum (g1->resolved_level));
26647 }
26648 else
26649 {
26650 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26651 e = row->glyphs[TEXT_AREA] - 1;
26652 while (g > e
26653 && NILP (g->object)
26654 && g->charpos < 0)
26655 g--;
26656 g1 = g;
26657 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26658 nglyphs++;
26659 levels = make_uninit_vector (nglyphs);
26660 for (i = 0; g1 > g; i++, g1--)
26661 ASET (levels, i, make_fixnum (g1->resolved_level));
26662 }
26663 return levels;
26664 }
26665 else
26666 return Qnil;
26667 }
26668
26669
26670
26671
26672
26673
26674
26675
26676
26677
26678
26679
26680
26681
26682
26683
26684
26685 static void
26686 display_menu_bar (struct window *w)
26687 {
26688 struct frame *f = XFRAME (WINDOW_FRAME (w));
26689 struct it it;
26690 Lisp_Object items;
26691 int i;
26692
26693
26694 #ifdef HAVE_NTGUI
26695 if (FRAME_W32_P (f))
26696 return;
26697 #endif
26698 #if defined (HAVE_PGTK)
26699 if (FRAME_PGTK_P (f))
26700 return;
26701 #endif
26702
26703 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26704 if (FRAME_X_P (f))
26705 return;
26706 #endif
26707
26708 #ifdef HAVE_NS
26709 if (FRAME_NS_P (f))
26710 return;
26711 #endif
26712
26713 #ifdef HAVE_HAIKU
26714 if (FRAME_HAIKU_P (f))
26715 return;
26716 #endif
26717
26718 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26719 eassert (!FRAME_WINDOW_P (f));
26720 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26721 it.first_visible_x = 0;
26722 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26723 #elif defined (HAVE_X_WINDOWS) || defined (HAVE_ANDROID)
26724 struct window *menu_window = NULL;
26725 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
26726
26727 if (FRAME_WINDOW_P (f))
26728 {
26729
26730
26731 menu_window = XWINDOW (f->menu_bar_window);
26732 init_iterator (&it, menu_window, -1, -1,
26733 menu_window->desired_matrix->rows,
26734 MENU_FACE_ID);
26735 }
26736 else
26737 #endif
26738 {
26739
26740
26741 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26742 MENU_FACE_ID);
26743 it.first_visible_x = 0;
26744 it.last_visible_x = FRAME_COLS (f);
26745 }
26746
26747
26748
26749
26750 it.paragraph_embedding = L2R;
26751
26752
26753 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26754 {
26755 struct glyph_row *row = it.glyph_row + i;
26756 clear_glyph_row (row);
26757 row->enabled_p = true;
26758 row->full_width_p = true;
26759 row->reversed_p = false;
26760 }
26761
26762
26763 items = FRAME_MENU_BAR_ITEMS (it.f);
26764 for (i = 0; i < ASIZE (items); i += 4)
26765 {
26766 Lisp_Object string;
26767
26768
26769 string = AREF (items, i + 1);
26770 if (NILP (string))
26771 break;
26772
26773
26774 ASET (items, i + 3, make_fixnum (it.hpos));
26775
26776
26777 if (it.current_x < it.last_visible_x)
26778 display_string (NULL, string, Qnil, 0, 0, &it,
26779 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26780 }
26781
26782
26783 if (it.current_x < it.last_visible_x)
26784 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26785
26786
26787 compute_line_metrics (&it);
26788 it.glyph_row->full_width_p = true;
26789 it.glyph_row->continued_p = false;
26790 it.glyph_row->truncated_on_left_p = false;
26791 it.glyph_row->truncated_on_right_p = false;
26792
26793
26794
26795
26796
26797 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
26798
26799 extend_face_to_end_of_line (&it);
26800 if (face->box != FACE_NO_BOX)
26801 {
26802 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26803 + it.glyph_row->used[TEXT_AREA] - 1);
26804 int box_thickness = face->box_vertical_line_width;
26805 last->right_box_line_p = true;
26806
26807
26808
26809
26810
26811
26812 if (box_thickness > 0)
26813 last->pixel_width += max (0, (box_thickness
26814 - (it.current_x - it.last_visible_x)));
26815 }
26816
26817
26818
26819 if (FRAME_WINDOW_P (it.f) && menu_window)
26820 {
26821 struct glyph_row *row;
26822 int delta_height;
26823
26824 row = it.glyph_row;
26825 delta_height
26826 = ((row->y + row->height)
26827 - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
26828
26829 if (delta_height != 0)
26830 {
26831 FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
26832 adjust_frame_size (it.f, -1, -1, 3, false, Qmenu_bar_lines);
26833 }
26834 }
26835 #endif
26836 }
26837
26838
26839
26840
26841 #ifndef HAVE_ANDROID
26842
26843
26844 static void
26845 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26846 {
26847 struct glyph *pointers[1 + LAST_AREA];
26848 int to_used = to->used[TEXT_AREA];
26849
26850
26851 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26852
26853
26854 *to = *from;
26855
26856
26857 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26858
26859
26860 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26861 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26862
26863
26864
26865 if (to_used > from->used[TEXT_AREA])
26866 fill_up_frame_row_with_spaces (to, to_used);
26867 }
26868
26869
26870
26871
26872
26873
26874
26875
26876
26877
26878
26879
26880
26881
26882
26883
26884
26885
26886
26887
26888
26889
26890 void
26891 display_tty_menu_item (const char *item_text, int width, int face_id,
26892 int x, int y, bool submenu)
26893 {
26894 struct it it;
26895 struct frame *f = SELECTED_FRAME ();
26896 struct window *w = XWINDOW (f->selected_window);
26897 struct glyph_row *row;
26898 size_t item_len = strlen (item_text);
26899
26900 eassert (FRAME_TERMCAP_P (f));
26901
26902
26903
26904
26905
26906
26907 if (y >= f->desired_matrix->nrows)
26908 return;
26909
26910 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26911 it.first_visible_x = 0;
26912 it.last_visible_x = FRAME_COLS (f) - 1;
26913 row = it.glyph_row;
26914
26915 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26916 bool saved_width = row->full_width_p;
26917 row->full_width_p = true;
26918 bool saved_reversed = row->reversed_p;
26919 row->reversed_p = false;
26920 row->enabled_p = true;
26921
26922
26923
26924 eassert (x < f->desired_matrix->matrix_w);
26925 it.current_x = it.hpos = x;
26926 it.current_y = it.vpos = y;
26927 int saved_used = row->used[TEXT_AREA];
26928 bool saved_truncated = row->truncated_on_right_p;
26929 row->used[TEXT_AREA] = x;
26930 it.face_id = face_id;
26931 it.line_wrap = TRUNCATE;
26932
26933
26934
26935
26936
26937
26938 it.paragraph_embedding = L2R;
26939
26940
26941 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26942 width--;
26943
26944 if (submenu)
26945 {
26946 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26947 item_len, 0, FRAME_COLS (f) - 1, -1);
26948 width -= item_len;
26949
26950 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26951 FRAME_COLS (f) - 1, -1);
26952 }
26953 else
26954 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26955 width, 0, FRAME_COLS (f) - 1, -1);
26956
26957 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26958 row->truncated_on_right_p = saved_truncated;
26959 row->hash = row_hash (row);
26960 row->full_width_p = saved_width;
26961 row->reversed_p = saved_reversed;
26962 }
26963
26964 #endif
26965
26966
26967
26968
26969
26970
26971
26972
26973
26974
26975
26976 static int
26977 redisplay_mode_lines (Lisp_Object window, bool force)
26978 {
26979 int nwindows = 0;
26980
26981 while (!NILP (window))
26982 {
26983 struct window *w = XWINDOW (window);
26984
26985 if (WINDOWP (w->contents))
26986 nwindows += redisplay_mode_lines (w->contents, force);
26987 else if (force
26988 || FRAME_GARBAGED_P (XFRAME (w->frame))
26989 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26990 {
26991 struct text_pos lpoint;
26992 struct buffer *old = current_buffer;
26993
26994
26995 SET_TEXT_POS (lpoint, PT, PT_BYTE);
26996 set_buffer_internal_1 (XBUFFER (w->contents));
26997
26998
26999
27000 if (!EQ (window, selected_window))
27001 {
27002 struct text_pos pt;
27003
27004 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
27005 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
27006 }
27007
27008
27009 clear_glyph_matrix (w->desired_matrix);
27010 if (display_mode_lines (w))
27011 ++nwindows;
27012
27013
27014 set_buffer_internal_1 (old);
27015 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
27016 }
27017
27018 window = w->next;
27019 }
27020
27021 return nwindows;
27022 }
27023
27024
27025
27026
27027
27028
27029 static int
27030 display_mode_lines (struct window *w)
27031 {
27032 Lisp_Object old_selected_window = selected_window;
27033 Lisp_Object new_frame = w->frame;
27034 specpdl_ref count = SPECPDL_INDEX ();
27035 int n = 0;
27036
27037 record_unwind_protect (restore_selected_window, selected_window);
27038 record_unwind_protect
27039 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
27040
27041 if (window_wants_mode_line (w))
27042 {
27043 Lisp_Object window;
27044 Lisp_Object default_help
27045 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
27046
27047
27048
27049 XSETWINDOW (window, w);
27050 if (FUNCTIONP (default_help))
27051 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
27052 else if (STRINGP (default_help))
27053 wset_mode_line_help_echo (w, default_help);
27054 else
27055 wset_mode_line_help_echo (w, Qnil);
27056 }
27057
27058 selected_frame = new_frame;
27059
27060
27061 XSETWINDOW (selected_window, w);
27062 XFRAME (new_frame)->selected_window = selected_window;
27063
27064
27065 line_number_displayed = false;
27066 w->column_number_displayed = -1;
27067
27068 if (window_wants_mode_line (w))
27069 {
27070 Lisp_Object window_mode_line_format
27071 = window_parameter (w, Qmode_line_format);
27072 struct window *sel_w = XWINDOW (old_selected_window);
27073
27074
27075 display_mode_line (w,
27076 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
27077 NILP (window_mode_line_format)
27078 ? BVAR (current_buffer, mode_line_format)
27079 : window_mode_line_format);
27080 ++n;
27081 }
27082
27083 if (window_wants_tab_line (w))
27084 {
27085 Lisp_Object window_tab_line_format
27086 = window_parameter (w, Qtab_line_format);
27087
27088 display_mode_line (w, TAB_LINE_FACE_ID,
27089 NILP (window_tab_line_format)
27090 ? BVAR (current_buffer, tab_line_format)
27091 : window_tab_line_format);
27092 ++n;
27093 }
27094
27095 if (window_wants_header_line (w))
27096 {
27097 Lisp_Object window_header_line_format
27098 = window_parameter (w, Qheader_line_format);
27099
27100 display_mode_line (w, HEADER_LINE_FACE_ID,
27101 NILP (window_header_line_format)
27102 ? BVAR (current_buffer, header_line_format)
27103 : window_header_line_format);
27104 ++n;
27105 }
27106
27107 unbind_to (count, Qnil);
27108
27109 if (n > 0)
27110 w->must_be_updated_p = true;
27111 return n;
27112 }
27113
27114
27115
27116
27117
27118
27119
27120
27121 static int
27122 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
27123 {
27124 struct it it;
27125 struct face *face;
27126 specpdl_ref count = SPECPDL_INDEX ();
27127
27128 init_iterator (&it, w, -1, -1, NULL, face_id);
27129
27130
27131 it.glyph_row->enabled_p = false;
27132 prepare_desired_row (w, it.glyph_row, true);
27133
27134 it.glyph_row->mode_line_p = true;
27135 if (face_id == TAB_LINE_FACE_ID)
27136 {
27137 it.glyph_row->tab_line_p = true;
27138 w->desired_matrix->tab_line_p = true;
27139 }
27140 else if (face_id == HEADER_LINE_FACE_ID)
27141 w->desired_matrix->header_line_p = true;
27142
27143
27144
27145
27146 it.paragraph_embedding = L2R;
27147
27148 record_unwind_protect (unwind_format_mode_line,
27149 format_mode_line_unwind_data (NULL, NULL,
27150 Qnil, false));
27151
27152
27153
27154
27155 push_kboard (FRAME_KBOARD (it.f));
27156 record_unwind_save_match_data ();
27157
27158 if (NILP (Vmode_line_compact)
27159 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
27160 {
27161 mode_line_target = MODE_LINE_DISPLAY;
27162 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27163 }
27164 else
27165 {
27166 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
27167 if (EQ (Vmode_line_compact, Qlong)
27168 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
27169 {
27170
27171
27172 display_string (NULL, mode_string, Qnil,
27173 0, 0, &it, 0, 0, 0,
27174 STRING_MULTIBYTE (mode_string));
27175 }
27176 else
27177 {
27178
27179 ptrdiff_t i = 0, i_byte = 0, start = 0;
27180 int prev = 0;
27181
27182 while (i < SCHARS (mode_string))
27183 {
27184 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
27185 if (c == ' ' && prev == ' ')
27186 {
27187 display_string (NULL,
27188 Fsubstring (mode_string, make_fixnum (start),
27189 make_fixnum (i - 1)),
27190 Qnil, 0, 0, &it, 0, 0, 0,
27191 STRING_MULTIBYTE (mode_string));
27192
27193 while (c == ' ' && i < SCHARS (mode_string))
27194 c = fetch_string_char_advance (mode_string, &i, &i_byte);
27195 start = i - 1;
27196 }
27197 prev = c;
27198 }
27199
27200
27201 if (start < i)
27202 display_string (NULL,
27203 Fsubstring (mode_string, make_fixnum (start),
27204 make_fixnum (i)),
27205 Qnil, 0, 0, &it, 0, 0, 0,
27206 STRING_MULTIBYTE (mode_string));
27207 }
27208 }
27209 pop_kboard ();
27210
27211 unbind_to (count, Qnil);
27212
27213
27214 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
27215
27216 compute_line_metrics (&it);
27217 it.glyph_row->full_width_p = true;
27218 it.glyph_row->continued_p = false;
27219 it.glyph_row->truncated_on_left_p = false;
27220 it.glyph_row->truncated_on_right_p = false;
27221
27222
27223 face = FACE_FROM_ID (it.f, face_id);
27224 extend_face_to_end_of_line (&it);
27225 if (face->box != FACE_NO_BOX)
27226 {
27227 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
27228 + it.glyph_row->used[TEXT_AREA] - 1);
27229 int box_thickness = face->box_vertical_line_width;
27230 last->right_box_line_p = true;
27231
27232
27233
27234
27235
27236
27237 if (box_thickness > 0)
27238 last->pixel_width += max (0, (box_thickness
27239 - (it.current_x - it.last_visible_x)));
27240 }
27241
27242 return it.glyph_row->height;
27243 }
27244
27245
27246
27247
27248 static Lisp_Object
27249 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
27250 {
27251 register Lisp_Object tail, prev;
27252 register Lisp_Object tem;
27253
27254 tail = list;
27255 prev = Qnil;
27256 while (CONSP (tail))
27257 {
27258 tem = XCAR (tail);
27259
27260 if (EQ (elt, tem))
27261 {
27262
27263 if (NILP (prev))
27264 list = XCDR (tail);
27265 else
27266 Fsetcdr (prev, XCDR (tail));
27267
27268
27269 Fsetcdr (tail, list);
27270 return tail;
27271 }
27272 else
27273 prev = tail;
27274 tail = XCDR (tail);
27275 maybe_quit ();
27276 }
27277
27278
27279 return list;
27280 }
27281
27282
27283
27284
27285
27286 static Lisp_Object
27287 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
27288 {
27289 eassert (nargs == 4);
27290 return Fset_text_properties (args[0], args[1], args[2], args[3]);
27291 }
27292
27293
27294
27295
27296
27297
27298
27299
27300
27301
27302
27303
27304
27305
27306
27307
27308
27309
27310
27311
27312
27313
27314
27315
27316
27317 static int
27318 display_mode_element (struct it *it, int depth, int field_width, int precision,
27319 Lisp_Object elt, Lisp_Object props, bool risky)
27320 {
27321 int n = 0, field, prec;
27322 bool literal = false;
27323
27324 tail_recurse:
27325 if (depth > 100)
27326 elt = build_string ("*too-deep*");
27327
27328 depth++;
27329
27330 switch (XTYPE (elt))
27331 {
27332 case Lisp_String:
27333 {
27334
27335 unsigned char c;
27336 ptrdiff_t offset = 0;
27337
27338 if (SCHARS (elt) > 0
27339 && (!NILP (props) || risky))
27340 {
27341 Lisp_Object oprops, aelt;
27342 oprops = Ftext_properties_at (make_fixnum (0), elt);
27343
27344
27345
27346
27347
27348 if (NILP (Fequal (props, oprops)) || risky)
27349 {
27350
27351
27352 if (! NILP (oprops) && !risky)
27353 {
27354 Lisp_Object tem;
27355
27356 oprops = Fcopy_sequence (oprops);
27357 tem = props;
27358 while (CONSP (tem) && CONSP (XCDR (tem)))
27359 {
27360 oprops = plist_put (oprops, XCAR (tem),
27361 XCAR (XCDR (tem)));
27362 tem = XCDR (XCDR (tem));
27363 }
27364 props = oprops;
27365 }
27366
27367 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27368 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27369 {
27370
27371
27372 elt = XCAR (aelt);
27373 mode_line_proptrans_alist
27374 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27375 }
27376 else
27377 {
27378 Lisp_Object tem;
27379
27380
27381
27382 if (! NILP (aelt))
27383 mode_line_proptrans_alist
27384 = Fdelq (aelt, mode_line_proptrans_alist);
27385
27386 elt = Fcopy_sequence (elt);
27387
27388
27389
27390 internal_condition_case_n (safe_set_text_properties,
27391 4,
27392 ((Lisp_Object [])
27393 {make_fixnum (0),
27394 Flength (elt),
27395 props,
27396 elt}),
27397 Qt, safe_eval_handler);
27398
27399 mode_line_proptrans_alist
27400 = Fcons (Fcons (elt, props),
27401 mode_line_proptrans_alist);
27402
27403
27404 tem = Fnthcdr (make_fixnum (50),
27405 mode_line_proptrans_alist);
27406 if (! NILP (tem))
27407 XSETCDR (tem, Qnil);
27408 }
27409 }
27410 }
27411
27412 offset = 0;
27413
27414 if (literal)
27415 {
27416 prec = precision - n;
27417 switch (mode_line_target)
27418 {
27419 case MODE_LINE_NOPROP:
27420 case MODE_LINE_TITLE:
27421 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27422 break;
27423 case MODE_LINE_STRING:
27424 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27425 break;
27426 case MODE_LINE_DISPLAY:
27427 n += display_string (NULL, elt, Qnil, 0, 0, it,
27428 0, prec, 0, STRING_MULTIBYTE (elt));
27429 break;
27430 }
27431
27432 break;
27433 }
27434
27435
27436
27437 while ((precision <= 0 || n < precision)
27438 && SREF (elt, offset) != 0
27439 && (mode_line_target != MODE_LINE_DISPLAY
27440 || it->current_x < it->last_visible_x))
27441 {
27442 ptrdiff_t last_offset = offset;
27443
27444
27445 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27446 ;
27447
27448 if (offset - 1 != last_offset)
27449 {
27450 ptrdiff_t nchars, nbytes;
27451
27452
27453
27454
27455 offset--;
27456
27457 prec = c_string_width (SDATA (elt) + last_offset,
27458 offset - last_offset, precision - n,
27459 &nchars, &nbytes);
27460
27461 switch (mode_line_target)
27462 {
27463 case MODE_LINE_NOPROP:
27464 case MODE_LINE_TITLE:
27465 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27466 break;
27467 case MODE_LINE_STRING:
27468 {
27469 ptrdiff_t bytepos = last_offset;
27470 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27471 ptrdiff_t endpos = (precision <= 0
27472 ? string_byte_to_char (elt, offset)
27473 : charpos + nchars);
27474 Lisp_Object mode_string
27475 = Fsubstring (elt, make_fixnum (charpos),
27476 make_fixnum (endpos));
27477 n += store_mode_line_string (NULL, mode_string, false,
27478 0, 0, Qnil);
27479 }
27480 break;
27481 case MODE_LINE_DISPLAY:
27482 {
27483 ptrdiff_t bytepos = last_offset;
27484 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27485
27486 if (precision <= 0)
27487 nchars = string_byte_to_char (elt, offset) - charpos;
27488 n += display_string (NULL, elt, Qnil, 0, charpos,
27489 it, 0, nchars, 0,
27490 STRING_MULTIBYTE (elt));
27491 }
27492 break;
27493 }
27494 }
27495 else
27496 {
27497 ptrdiff_t percent_position = offset;
27498
27499
27500
27501 field = 0;
27502 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27503 field = field * 10 + c - '0';
27504
27505
27506 if (field_width - n > 0 && field > field_width - n)
27507 field = field_width - n;
27508
27509
27510 prec = precision - n;
27511
27512 if (c == 'M')
27513 n += display_mode_element (it, depth, field, prec,
27514 Vglobal_mode_string, props,
27515 risky);
27516 else if (c != 0)
27517 {
27518 bool multibyte;
27519 ptrdiff_t bytepos, charpos;
27520 const char *spec;
27521 Lisp_Object string;
27522
27523 bytepos = percent_position;
27524 charpos = (STRING_MULTIBYTE (elt)
27525 ? string_byte_to_char (elt, bytepos)
27526 : bytepos);
27527 spec = decode_mode_spec (it->w, c, field, &string);
27528 eassert (NILP (string) || STRINGP (string));
27529 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27530
27531
27532 ptrdiff_t nbytes = strlen (spec);
27533 ptrdiff_t nchars, mb_nbytes;
27534 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27535 &nchars, &mb_nbytes);
27536 if (!(nbytes == nchars || nbytes != mb_nbytes))
27537 multibyte = true;
27538
27539 switch (mode_line_target)
27540 {
27541 case MODE_LINE_NOPROP:
27542 case MODE_LINE_TITLE:
27543 n += store_mode_line_noprop (spec, field, prec);
27544 break;
27545 case MODE_LINE_STRING:
27546 {
27547 Lisp_Object tem = build_string (spec);
27548 props = Ftext_properties_at (make_fixnum (charpos), elt);
27549
27550 n += store_mode_line_string (NULL, tem, false,
27551 field, prec, props);
27552 }
27553 break;
27554 case MODE_LINE_DISPLAY:
27555 {
27556 int nglyphs_before, nwritten;
27557
27558 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27559 nwritten = display_string (spec, string, elt,
27560 charpos, 0, it,
27561 field, prec, 0,
27562 multibyte);
27563
27564
27565
27566
27567 if (nwritten > 0)
27568 {
27569 struct glyph *glyph
27570 = (it->glyph_row->glyphs[TEXT_AREA]
27571 + nglyphs_before);
27572 int i;
27573
27574 for (i = 0; i < nwritten; ++i)
27575 {
27576 glyph[i].object = elt;
27577 glyph[i].charpos = charpos;
27578 }
27579
27580 n += nwritten;
27581 }
27582 }
27583 break;
27584 }
27585 }
27586 else
27587 break;
27588 }
27589 }
27590 }
27591 break;
27592
27593 case Lisp_Symbol:
27594
27595
27596
27597
27598 {
27599 register Lisp_Object tem;
27600
27601
27602
27603 if (NILP (Fget (elt, Qrisky_local_variable)))
27604 risky = true;
27605
27606 tem = Fboundp (elt);
27607 if (!NILP (tem))
27608 {
27609 tem = Fsymbol_value (elt);
27610
27611
27612 if (STRINGP (tem))
27613 literal = true;
27614
27615 if (!EQ (tem, elt))
27616 {
27617
27618 elt = tem;
27619 goto tail_recurse;
27620 }
27621 }
27622 }
27623 break;
27624
27625 case Lisp_Cons:
27626 {
27627 register Lisp_Object car, tem;
27628
27629
27630
27631
27632
27633
27634
27635
27636
27637
27638 car = XCAR (elt);
27639 if (EQ (car, QCeval))
27640 {
27641
27642
27643
27644 if (risky)
27645 break;
27646
27647 if (CONSP (XCDR (elt)))
27648 {
27649 Lisp_Object spec;
27650 spec = safe__eval (true, XCAR (XCDR (elt)));
27651
27652
27653
27654
27655
27656
27657 if (!FRAME_LIVE_P (it->f))
27658 signal_error (":eval deleted the frame being displayed", elt);
27659 n += display_mode_element (it, depth, field_width - n,
27660 precision - n, spec, props,
27661 risky);
27662 }
27663 }
27664 else if (EQ (car, QCpropertize))
27665 {
27666
27667
27668
27669 if (risky)
27670 break;
27671
27672 if (CONSP (XCDR (elt)))
27673 n += display_mode_element (it, depth, field_width - n,
27674 precision - n, XCAR (XCDR (elt)),
27675 XCDR (XCDR (elt)), risky);
27676 }
27677 else if (SYMBOLP (car))
27678 {
27679 tem = Fboundp (car);
27680 elt = XCDR (elt);
27681 if (!CONSP (elt))
27682 goto invalid;
27683
27684
27685 if (!NILP (tem))
27686 {
27687 tem = Fsymbol_value (car);
27688 if (!NILP (tem))
27689 {
27690 elt = XCAR (elt);
27691 goto tail_recurse;
27692 }
27693 }
27694
27695
27696
27697 elt = XCDR (elt);
27698 if (NILP (elt))
27699 break;
27700 else if (!CONSP (elt))
27701 goto invalid;
27702 elt = XCAR (elt);
27703 goto tail_recurse;
27704 }
27705 else if (FIXNUMP (car))
27706 {
27707 register int lim = XFIXNUM (car);
27708 elt = XCDR (elt);
27709 if (lim < 0)
27710 {
27711
27712 if (precision <= 0)
27713 precision = -lim;
27714 else
27715 precision = min (precision, -lim);
27716 }
27717 else if (lim > 0)
27718 {
27719
27720
27721 if (precision > 0)
27722 lim = min (precision, lim);
27723
27724
27725
27726
27727 field_width = max (lim, field_width);
27728 }
27729 goto tail_recurse;
27730 }
27731 else if (STRINGP (car) || CONSP (car))
27732 FOR_EACH_TAIL_SAFE (elt)
27733 {
27734 if (0 < precision && precision <= n)
27735 break;
27736 n += display_mode_element (it, depth,
27737
27738
27739 (! CONSP (XCDR (elt))
27740 ? field_width - n
27741 : 0),
27742 precision - n, XCAR (elt),
27743 props, risky);
27744 }
27745 }
27746 break;
27747
27748 default:
27749 invalid:
27750 elt = build_string ("*invalid*");
27751 goto tail_recurse;
27752 }
27753
27754
27755 if (field_width > 0 && n < field_width)
27756 {
27757 switch (mode_line_target)
27758 {
27759 case MODE_LINE_NOPROP:
27760 case MODE_LINE_TITLE:
27761 n += store_mode_line_noprop ("", field_width - n, 0);
27762 break;
27763 case MODE_LINE_STRING:
27764 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27765 Qnil);
27766 break;
27767 case MODE_LINE_DISPLAY:
27768 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27769 0, 0, 0);
27770 break;
27771 }
27772 }
27773
27774 return n;
27775 }
27776
27777
27778
27779
27780
27781
27782
27783
27784
27785
27786
27787
27788
27789
27790
27791
27792
27793
27794
27795
27796 static int
27797 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27798 bool copy_string,
27799 int field_width, int precision, Lisp_Object props)
27800 {
27801 ptrdiff_t len;
27802 int n = 0;
27803
27804 if (string != NULL)
27805 {
27806 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27807 lisp_string = make_string (string, len);
27808 if (NILP (props))
27809 props = mode_line_string_face_prop;
27810 else if (!NILP (mode_line_string_face))
27811 {
27812 Lisp_Object face = plist_get (props, Qface);
27813 props = Fcopy_sequence (props);
27814 if (NILP (face))
27815 face = mode_line_string_face;
27816 else
27817 face = list2 (face, mode_line_string_face);
27818 props = plist_put (props, Qface, face);
27819 }
27820 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27821 props, lisp_string);
27822 }
27823 else
27824 {
27825 len = SCHARS (lisp_string);
27826 if (precision > 0 && len > precision)
27827 {
27828 len = precision;
27829 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27830 precision = -1;
27831 }
27832 if (!NILP (mode_line_string_face))
27833 {
27834 Lisp_Object face;
27835 if (NILP (props))
27836 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27837 face = plist_get (props, Qface);
27838 if (NILP (face))
27839 face = mode_line_string_face;
27840 else
27841 face = list2 (face, mode_line_string_face);
27842 props = list2 (Qface, face);
27843 if (copy_string)
27844 lisp_string = Fcopy_sequence (lisp_string);
27845 }
27846 if (!NILP (props))
27847 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27848 props, lisp_string);
27849 }
27850
27851 if (len > 0)
27852 {
27853 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27854 n += len;
27855 }
27856
27857 if (field_width > len)
27858 {
27859 field_width -= len;
27860 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27861 Qnil);
27862 if (!NILP (props))
27863 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27864 props, lisp_string);
27865 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27866 n += field_width;
27867 }
27868
27869 return n;
27870 }
27871
27872
27873 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27874 1, 4, 0,
27875 doc:
27876
27877
27878
27879
27880
27881
27882
27883
27884
27885
27886
27887
27888
27889
27890
27891 )
27892 (Lisp_Object format, Lisp_Object face,
27893 Lisp_Object window, Lisp_Object buffer)
27894 {
27895 struct it it;
27896 int len;
27897 struct window *w;
27898 struct buffer *old_buffer = NULL;
27899 int face_id;
27900 bool no_props = FIXNUMP (face);
27901 specpdl_ref count = SPECPDL_INDEX ();
27902 Lisp_Object str;
27903 int string_start = 0;
27904
27905 w = decode_any_window (window);
27906 XSETWINDOW (window, w);
27907
27908 if (NILP (buffer))
27909 buffer = w->contents;
27910 CHECK_BUFFER (buffer);
27911
27912
27913
27914 if (NILP (format) || noninteractive)
27915 return empty_unibyte_string;
27916
27917 if (no_props)
27918 face = Qnil;
27919
27920 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27921 : EQ (face, Qt) ? (EQ (window, selected_window)
27922 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27923 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27924 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27925 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27926 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27927 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27928 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27929 : DEFAULT_FACE_ID;
27930
27931 old_buffer = current_buffer;
27932
27933
27934
27935 record_unwind_protect (unwind_format_mode_line,
27936 format_mode_line_unwind_data
27937 (XFRAME (WINDOW_FRAME (w)),
27938 old_buffer, selected_window, true));
27939 mode_line_proptrans_alist = Qnil;
27940
27941 Fselect_window (window, Qt);
27942 set_buffer_internal_1 (XBUFFER (buffer));
27943
27944 init_iterator (&it, w, -1, -1, NULL, face_id);
27945
27946 if (no_props)
27947 {
27948 mode_line_target = MODE_LINE_NOPROP;
27949 mode_line_string_face_prop = Qnil;
27950 mode_line_string_list = Qnil;
27951 string_start = MODE_LINE_NOPROP_LEN (0);
27952 }
27953 else
27954 {
27955 mode_line_target = MODE_LINE_STRING;
27956 mode_line_string_list = Qnil;
27957 mode_line_string_face = face;
27958 mode_line_string_face_prop
27959 = NILP (face) ? Qnil : list2 (Qface, face);
27960 }
27961
27962 push_kboard (FRAME_KBOARD (it.f));
27963 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27964 pop_kboard ();
27965
27966 if (no_props)
27967 {
27968 len = MODE_LINE_NOPROP_LEN (string_start);
27969 str = make_string (mode_line_noprop_buf + string_start, len);
27970 }
27971 else
27972 {
27973 mode_line_string_list = Fnreverse (mode_line_string_list);
27974 str = Fmapconcat (Qidentity, mode_line_string_list,
27975 empty_unibyte_string);
27976 }
27977
27978 return unbind_to (count, str);
27979 }
27980
27981
27982
27983
27984 static void
27985 pint2str (register char *buf, register int width, register ptrdiff_t d)
27986 {
27987 register char *p = buf;
27988
27989 if (d <= 0)
27990 *p++ = '0';
27991 else
27992 {
27993 while (d > 0)
27994 {
27995 *p++ = d % 10 + '0';
27996 d /= 10;
27997 }
27998 }
27999
28000 for (width -= (int) (p - buf); width > 0; --width)
28001 *p++ = ' ';
28002 *p-- = '\0';
28003 while (p > buf)
28004 {
28005 d = *buf;
28006 *buf++ = *p;
28007 *p-- = d;
28008 }
28009 }
28010
28011
28012
28013
28014
28015 static const char power_letter[] =
28016 {
28017 0,
28018 'k',
28019 'M',
28020 'G',
28021 'T',
28022 'P',
28023 'E',
28024 'Z',
28025 'Y',
28026 'R',
28027 'Q'
28028 };
28029
28030 static void
28031 pint2hrstr (char *buf, int width, ptrdiff_t d)
28032 {
28033
28034
28035 ptrdiff_t quotient = d;
28036 int remainder = 0;
28037
28038 int tenths = -1;
28039 int exponent = 0;
28040
28041
28042 int length;
28043
28044 char * psuffix;
28045 char * p;
28046
28047 if (quotient >= 1000)
28048 {
28049
28050 do
28051 {
28052 remainder = quotient % 1000;
28053 quotient /= 1000;
28054 exponent++;
28055 }
28056 while (quotient >= 1000);
28057
28058
28059 if (quotient <= 9)
28060 {
28061 tenths = remainder / 100;
28062 if (remainder % 100 >= 50)
28063 {
28064 if (tenths < 9)
28065 tenths++;
28066 else
28067 {
28068 quotient++;
28069 if (quotient == 10)
28070 tenths = -1;
28071 else
28072 tenths = 0;
28073 }
28074 }
28075 }
28076 else
28077 if (remainder >= 500)
28078 {
28079 if (quotient < 999)
28080 quotient++;
28081 else
28082 {
28083 quotient = 1;
28084 exponent++;
28085 tenths = 0;
28086 }
28087 }
28088 }
28089
28090
28091 if (tenths == -1 && quotient <= 99)
28092 if (quotient <= 9)
28093 length = 1;
28094 else
28095 length = 2;
28096 else
28097 length = 3;
28098 p = psuffix = buf + max (width, length);
28099
28100
28101 *psuffix++ = power_letter[exponent];
28102 *psuffix = '\0';
28103
28104
28105 if (tenths >= 0)
28106 {
28107 *--p = '0' + tenths;
28108 *--p = '.';
28109 }
28110
28111
28112 do
28113 {
28114 int digit = quotient % 10;
28115 *--p = '0' + digit;
28116 }
28117 while ((quotient /= 10) != 0);
28118
28119
28120 while (buf < p)
28121 *--p = ' ';
28122 }
28123
28124
28125
28126
28127
28128 static unsigned char invalid_eol_type[] = "(*invalid*)";
28129
28130 static char *
28131 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
28132 {
28133 Lisp_Object val;
28134 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
28135 const unsigned char *eol_str;
28136 int eol_str_len;
28137
28138 Lisp_Object eoltype;
28139
28140 val = CODING_SYSTEM_SPEC (coding_system);
28141 eoltype = Qnil;
28142
28143 if (!VECTORP (val))
28144 {
28145 *buf++ = multibyte ? '-' : ' ';
28146 if (eol_flag)
28147 eoltype = eol_mnemonic_undecided;
28148
28149 }
28150 else
28151 {
28152 Lisp_Object attrs;
28153 Lisp_Object eolvalue;
28154
28155 attrs = AREF (val, 0);
28156 eolvalue = AREF (val, 2);
28157
28158 if (multibyte)
28159 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
28160 (unsigned char *) buf);
28161 else
28162 *buf++ = ' ';
28163
28164 if (eol_flag)
28165 {
28166
28167
28168 if (NILP (eolvalue))
28169 eoltype = eol_mnemonic_undecided;
28170 else if (VECTORP (eolvalue))
28171 eoltype = eol_mnemonic_undecided;
28172 else
28173 eoltype = (EQ (eolvalue, Qunix)
28174 ? eol_mnemonic_unix
28175 : EQ (eolvalue, Qdos)
28176 ? eol_mnemonic_dos : eol_mnemonic_mac);
28177 }
28178 }
28179
28180 if (eol_flag)
28181 {
28182
28183 if (STRINGP (eoltype))
28184 {
28185 eol_str = SDATA (eoltype);
28186 eol_str_len = SBYTES (eoltype);
28187 }
28188 else if (CHARACTERP (eoltype))
28189 {
28190 int c = XFIXNAT (eoltype);
28191 return buf + CHAR_STRING (c, (unsigned char *) buf);
28192 }
28193 else
28194 {
28195 eol_str = invalid_eol_type;
28196 eol_str_len = sizeof (invalid_eol_type) - 1;
28197 }
28198 memcpy (buf, eol_str, eol_str_len);
28199 buf += eol_str_len;
28200 }
28201
28202 return buf;
28203 }
28204
28205
28206
28207
28208 static int
28209 percent99 (ptrdiff_t n, ptrdiff_t d)
28210 {
28211 int percent = (d - 1 + 100.0 * n) / d;
28212 return min (percent, 99);
28213 }
28214
28215
28216
28217
28218
28219
28220
28221
28222
28223 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
28224
28225 static const char *
28226 decode_mode_spec (struct window *w, register int c, int field_width,
28227 Lisp_Object *string)
28228 {
28229 Lisp_Object obj;
28230 struct frame *f = XFRAME (WINDOW_FRAME (w));
28231 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
28232
28233
28234
28235
28236
28237 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
28238 struct buffer *b = current_buffer;
28239
28240 obj = Qnil;
28241 *string = Qnil;
28242
28243 switch (c)
28244 {
28245 case '*':
28246 if (!NILP (BVAR (b, read_only)))
28247 return "%";
28248 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28249 return "*";
28250 return "-";
28251
28252 case '+':
28253
28254 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28255 return "*";
28256 if (!NILP (BVAR (b, read_only)))
28257 return "%";
28258 return "-";
28259
28260 case '&':
28261
28262 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28263 return "*";
28264 return "-";
28265
28266 case '%':
28267 return "%";
28268
28269 case '[':
28270 {
28271 int i;
28272 char *p;
28273
28274 if (command_loop_level > 5)
28275 return "[[[... ";
28276 p = decode_mode_spec_buf;
28277 for (i = 0; i < command_loop_level; i++)
28278 *p++ = '[';
28279 *p = 0;
28280 return decode_mode_spec_buf;
28281 }
28282
28283 case ']':
28284 {
28285 int i;
28286 char *p;
28287
28288 if (command_loop_level > 5)
28289 return " ...]]]";
28290 p = decode_mode_spec_buf;
28291 for (i = 0; i < command_loop_level; i++)
28292 *p++ = ']';
28293 *p = 0;
28294 return decode_mode_spec_buf;
28295 }
28296
28297 case '-':
28298 {
28299 register int i;
28300
28301
28302 if (mode_line_target == MODE_LINE_NOPROP
28303 || mode_line_target == MODE_LINE_STRING)
28304 return "--";
28305 if (field_width <= 0
28306 || field_width > sizeof (lots_of_dashes))
28307 {
28308 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28309 decode_mode_spec_buf[i] = '-';
28310 decode_mode_spec_buf[i] = '\0';
28311 return decode_mode_spec_buf;
28312 }
28313 else
28314 return lots_of_dashes;
28315 }
28316
28317 case 'b':
28318 obj = BVAR (b, name);
28319 break;
28320
28321 case 'c':
28322 case 'C':
28323
28324
28325
28326
28327
28328 if (mode_line_target == MODE_LINE_TITLE)
28329 return "";
28330 else
28331 {
28332 ptrdiff_t col = current_column ();
28333 int disp_col = (c == 'C') ? col + 1 : col;
28334 w->column_number_displayed = col;
28335 pint2str (decode_mode_spec_buf, width, disp_col);
28336 return decode_mode_spec_buf;
28337 }
28338
28339 case 'e':
28340 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28341 {
28342 if (NILP (Vmemory_full))
28343 return "";
28344 else
28345 return "!MEM FULL! ";
28346 }
28347 #else
28348 return "";
28349 #endif
28350
28351 case 'F':
28352
28353 if (!NILP (f->title))
28354 return SSDATA (f->title);
28355 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28356 return SSDATA (f->name);
28357 return "Emacs";
28358
28359 case 'f':
28360 obj = BVAR (b, filename);
28361 break;
28362
28363 case 'i':
28364 {
28365 ptrdiff_t size = ZV - BEGV;
28366 pint2str (decode_mode_spec_buf, width, size);
28367 return decode_mode_spec_buf;
28368 }
28369
28370 case 'I':
28371 {
28372 ptrdiff_t size = ZV - BEGV;
28373 pint2hrstr (decode_mode_spec_buf, width, size);
28374 return decode_mode_spec_buf;
28375 }
28376
28377 case 'l':
28378 {
28379 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28380 ptrdiff_t topline, nlines, height;
28381 ptrdiff_t junk;
28382
28383
28384 if (mode_line_target == MODE_LINE_TITLE)
28385 return "";
28386
28387 startpos = marker_position (w->start);
28388 startpos_byte = marker_byte_position (w->start);
28389 height = WINDOW_TOTAL_LINES (w);
28390
28391
28392
28393
28394
28395
28396
28397
28398 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28399 && startpos_byte <= BUF_ZV_BYTE (b)))
28400 {
28401 startpos = BUF_BEGV (b);
28402 startpos_byte = BUF_BEGV_BYTE (b);
28403 w->base_line_pos = 0;
28404 w->base_line_number = 0;
28405 }
28406
28407
28408
28409 if (w->base_line_pos == -1)
28410 goto no_value;
28411
28412
28413 if (FIXNUMP (Vline_number_display_limit)
28414 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28415 {
28416 w->base_line_pos = 0;
28417 w->base_line_number = 0;
28418 goto no_value;
28419 }
28420
28421 if (w->base_line_number > 0
28422 && w->base_line_pos > 0
28423 && w->base_line_pos <= startpos)
28424 {
28425 line = w->base_line_number;
28426 linepos = w->base_line_pos;
28427 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28428 }
28429 else
28430 {
28431 line = 1;
28432 linepos = BUF_BEGV (b);
28433 linepos_byte = BUF_BEGV_BYTE (b);
28434 }
28435
28436
28437 nlines = display_count_lines (linepos_byte,
28438 startpos_byte,
28439 startpos, &junk);
28440
28441 topline = nlines + line;
28442
28443
28444
28445
28446
28447 if (startpos == BUF_BEGV (b))
28448 {
28449 w->base_line_number = topline;
28450 w->base_line_pos = BUF_BEGV (b);
28451 }
28452 else if (nlines < height + 25 || nlines > height * 3 + 50
28453 || linepos == BUF_BEGV (b))
28454 {
28455 ptrdiff_t limit = BUF_BEGV (b);
28456 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28457 ptrdiff_t position;
28458 ptrdiff_t distance
28459 = (line_number_display_limit_width < 0 ? 0
28460 : ckd_mul (&distance, line_number_display_limit_width,
28461 height * 2 + 30)
28462 ? PTRDIFF_MAX : distance);
28463
28464 if (startpos - distance > limit)
28465 {
28466 limit = startpos - distance;
28467 limit_byte = CHAR_TO_BYTE (limit);
28468 }
28469
28470 nlines = display_count_lines (startpos_byte,
28471 limit_byte,
28472 - (height * 2 + 30),
28473 &position);
28474
28475
28476
28477 if (position == limit_byte && limit == startpos - distance)
28478 {
28479 w->base_line_pos = -1;
28480 w->base_line_number = 0;
28481 goto no_value;
28482 }
28483
28484 w->base_line_number = topline - nlines;
28485 w->base_line_pos = BYTE_TO_CHAR (position);
28486 }
28487
28488
28489 nlines = display_count_lines (startpos_byte,
28490 PT_BYTE, PT, &junk);
28491
28492
28493 line_number_displayed = true;
28494
28495
28496 pint2str (decode_mode_spec_buf, width, topline + nlines);
28497 return decode_mode_spec_buf;
28498 no_value:
28499 {
28500 char *p = decode_mode_spec_buf;
28501 int pad = width - 2;
28502 while (pad-- > 0)
28503 *p++ = ' ';
28504 *p++ = '?';
28505 *p++ = '?';
28506 *p = '\0';
28507 return decode_mode_spec_buf;
28508 }
28509 }
28510 break;
28511
28512 case 'm':
28513 obj = BVAR (b, mode_name);
28514 break;
28515
28516 case 'n':
28517 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28518 return " Narrow";
28519 break;
28520
28521
28522 case 'o':
28523 {
28524 ptrdiff_t toppos = marker_position (w->start);
28525 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28526 ptrdiff_t begv = BUF_BEGV (b);
28527 ptrdiff_t zv = BUF_ZV (b);
28528
28529 if (zv <= botpos)
28530 return toppos <= begv ? "All" : "Bottom";
28531 else if (toppos <= begv)
28532 return "Top";
28533 else
28534 {
28535 sprintf (decode_mode_spec_buf, "%2d%%",
28536 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28537 return decode_mode_spec_buf;
28538 }
28539 }
28540
28541
28542 case 'p':
28543 {
28544 ptrdiff_t pos = marker_position (w->start);
28545 ptrdiff_t begv = BUF_BEGV (b);
28546 ptrdiff_t zv = BUF_ZV (b);
28547
28548 if (w->window_end_pos <= BUF_Z (b) - zv)
28549 return pos <= begv ? "All" : "Bottom";
28550 else if (pos <= begv)
28551 return "Top";
28552 else
28553 {
28554 sprintf (decode_mode_spec_buf, "%2d%%",
28555 percent99 (pos - begv, zv - begv));
28556 return decode_mode_spec_buf;
28557 }
28558 }
28559
28560
28561 case 'P':
28562 {
28563 ptrdiff_t toppos = marker_position (w->start);
28564 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28565 ptrdiff_t begv = BUF_BEGV (b);
28566 ptrdiff_t zv = BUF_ZV (b);
28567
28568 if (zv <= botpos)
28569 return toppos <= begv ? "All" : "Bottom";
28570 else
28571 {
28572 sprintf (decode_mode_spec_buf,
28573 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28574 percent99 (botpos - begv, zv - begv));
28575 return decode_mode_spec_buf;
28576 }
28577 }
28578
28579
28580
28581 case 'q':
28582 {
28583 ptrdiff_t toppos = marker_position (w->start);
28584 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28585 ptrdiff_t begv = BUF_BEGV (b);
28586 ptrdiff_t zv = BUF_ZV (b);
28587 int top_perc, bot_perc;
28588
28589 if ((toppos <= begv) && (zv <= botpos))
28590 return "All ";
28591
28592 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28593 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28594
28595 if (top_perc == bot_perc)
28596 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28597 else
28598 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28599
28600 return decode_mode_spec_buf;
28601 }
28602
28603 case 's':
28604
28605 obj = Fget_buffer_process (Fcurrent_buffer ());
28606 if (NILP (obj))
28607 return "no process";
28608 #ifndef MSDOS
28609 obj = Fsymbol_name (Fprocess_status (obj));
28610 #endif
28611 break;
28612
28613 case '@':
28614 {
28615 specpdl_ref count = inhibit_garbage_collection ();
28616 Lisp_Object curdir = BVAR (current_buffer, directory);
28617 Lisp_Object val = Qnil;
28618
28619 if (STRINGP (curdir))
28620 val = safe_call1 (intern ("file-remote-p"), curdir);
28621
28622 val = unbind_to (count, val);
28623
28624 if (NILP (val))
28625 return "-";
28626 else
28627 return "@";
28628 }
28629
28630 case 'z':
28631
28632 case 'Z':
28633
28634 {
28635 bool eol_flag = (c == 'Z');
28636 char *p = decode_mode_spec_buf;
28637
28638 if (! FRAME_WINDOW_P (f))
28639 {
28640
28641
28642 p = decode_mode_spec_coding (CODING_ID_NAME
28643 (FRAME_KEYBOARD_CODING (f)->id),
28644 p, false);
28645 p = decode_mode_spec_coding (CODING_ID_NAME
28646 (FRAME_TERMINAL_CODING (f)->id),
28647 p, false);
28648 }
28649 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28650 p, eol_flag);
28651
28652 #if false
28653 #ifdef subprocesses
28654 obj = Fget_buffer_process (Fcurrent_buffer ());
28655 if (PROCESSP (obj))
28656 {
28657 p = decode_mode_spec_coding
28658 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28659 p = decode_mode_spec_coding
28660 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28661 }
28662 #endif
28663 #endif
28664 *p = 0;
28665 return decode_mode_spec_buf;
28666 }
28667 }
28668
28669 if (STRINGP (obj))
28670 {
28671 *string = obj;
28672 return SSDATA (obj);
28673 }
28674 else
28675 return "";
28676 }
28677
28678
28679
28680
28681 ptrdiff_t
28682 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28683 {
28684 ptrdiff_t ignored;
28685 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28686 }
28687
28688
28689
28690
28691
28692
28693
28694
28695
28696
28697
28698 static ptrdiff_t
28699 display_count_lines (ptrdiff_t start_byte,
28700 ptrdiff_t limit_byte, ptrdiff_t count,
28701 ptrdiff_t *byte_pos_ptr)
28702 {
28703 register unsigned char *cursor;
28704 unsigned char *base;
28705
28706 register ptrdiff_t ceiling;
28707 register unsigned char *ceiling_addr;
28708 ptrdiff_t orig_count = count;
28709
28710
28711
28712 bool selective_display
28713 = (!NILP (BVAR (current_buffer, selective_display))
28714 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28715
28716 if (count > 0)
28717 {
28718 while (start_byte < limit_byte)
28719 {
28720 ceiling = BUFFER_CEILING_OF (start_byte);
28721 ceiling = min (limit_byte - 1, ceiling);
28722 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28723 base = (cursor = BYTE_POS_ADDR (start_byte));
28724
28725 do
28726 {
28727 if (selective_display)
28728 {
28729 while (*cursor != '\n' && *cursor != 015
28730 && ++cursor != ceiling_addr)
28731 continue;
28732 if (cursor == ceiling_addr)
28733 break;
28734 }
28735 else
28736 {
28737 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28738 if (! cursor)
28739 break;
28740 }
28741
28742 cursor++;
28743
28744 if (--count == 0)
28745 {
28746 start_byte += cursor - base;
28747 *byte_pos_ptr = start_byte;
28748 return orig_count;
28749 }
28750 }
28751 while (cursor < ceiling_addr);
28752
28753 start_byte += ceiling_addr - base;
28754 }
28755 }
28756 else
28757 {
28758 while (start_byte > limit_byte)
28759 {
28760 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28761 ceiling = max (limit_byte, ceiling);
28762 ceiling_addr = BYTE_POS_ADDR (ceiling);
28763 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28764 while (true)
28765 {
28766 if (selective_display)
28767 {
28768 while (--cursor >= ceiling_addr
28769 && *cursor != '\n' && *cursor != 015)
28770 continue;
28771 if (cursor < ceiling_addr)
28772 break;
28773 }
28774 else
28775 {
28776 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28777 if (! cursor)
28778 break;
28779 }
28780
28781 if (++count == 0)
28782 {
28783 start_byte += cursor - base + 1;
28784 *byte_pos_ptr = start_byte;
28785
28786
28787 return - orig_count - 1;
28788 }
28789 }
28790 start_byte += ceiling_addr - base;
28791 }
28792 }
28793
28794 *byte_pos_ptr = limit_byte;
28795
28796 if (count < 0)
28797 return - orig_count + count;
28798 return orig_count - count;
28799
28800 }
28801
28802
28803
28804
28805
28806
28807
28808
28809
28810
28811
28812
28813
28814
28815
28816
28817
28818
28819
28820
28821
28822
28823
28824
28825
28826
28827
28828
28829
28830
28831
28832
28833
28834
28835
28836
28837
28838
28839
28840
28841
28842
28843
28844
28845
28846 static int
28847 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28848 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28849 int field_width, int precision, int max_x, int multibyte)
28850 {
28851 int hpos_at_start = it->hpos;
28852 int saved_face_id = it->face_id;
28853 struct glyph_row *row = it->glyph_row;
28854 ptrdiff_t it_charpos;
28855
28856
28857
28858 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28859 start, precision, field_width, multibyte);
28860
28861 if (string && STRINGP (lisp_string))
28862
28863
28864 it->stop_charpos = it->end_charpos;
28865
28866
28867
28868 if (STRINGP (face_string))
28869 {
28870 ptrdiff_t endptr;
28871 struct face *face;
28872
28873 it->face_id
28874 = face_at_string_position (it->w, face_string, face_string_pos,
28875 0, &endptr, it->base_face_id, false, 0);
28876 face = FACE_FROM_ID (it->f, it->face_id);
28877 it->face_box_p = face->box != FACE_NO_BOX;
28878
28879
28880
28881
28882 if (NILP (lisp_string))
28883 {
28884 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28885 face_string);
28886 if (!NILP (display))
28887 {
28888 Lisp_Object min_width = plist_get (display, Qmin_width);
28889 if (!NILP (min_width))
28890 display_min_width (it, 0, face_string, min_width);
28891 }
28892 }
28893 }
28894
28895
28896
28897 if (max_x <= 0)
28898 max_x = it->last_visible_x;
28899 else
28900 max_x = min (max_x, it->last_visible_x);
28901
28902
28903
28904 if (it->current_x < it->first_visible_x)
28905 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28906 MOVE_TO_POS | MOVE_TO_X);
28907
28908 row->ascent = it->max_ascent;
28909 row->height = it->max_ascent + it->max_descent;
28910 row->phys_ascent = it->max_phys_ascent;
28911 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28912 row->extra_line_spacing = it->max_extra_line_spacing;
28913
28914 if (STRINGP (it->string))
28915 it_charpos = IT_STRING_CHARPOS (*it);
28916 else
28917 it_charpos = IT_CHARPOS (*it);
28918
28919
28920
28921 while (it->current_x < max_x)
28922 {
28923 int x_before, x, n_glyphs_before, i, nglyphs;
28924
28925
28926 if (!get_next_display_element (it))
28927 break;
28928
28929
28930 x_before = it->current_x;
28931 n_glyphs_before = row->used[TEXT_AREA];
28932 PRODUCE_GLYPHS (it);
28933
28934 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28935 i = 0;
28936 x = x_before;
28937 while (i < nglyphs)
28938 {
28939 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28940
28941 if (it->line_wrap != TRUNCATE
28942 && x + glyph->pixel_width > max_x)
28943 {
28944
28945 if (CHAR_GLYPH_PADDING_P (*glyph))
28946 {
28947
28948 if (row->reversed_p)
28949 unproduce_glyphs (it, row->used[TEXT_AREA]
28950 - n_glyphs_before);
28951 row->used[TEXT_AREA] = n_glyphs_before;
28952 it->current_x = x_before;
28953 }
28954 else
28955 {
28956 if (row->reversed_p)
28957 unproduce_glyphs (it, row->used[TEXT_AREA]
28958 - (n_glyphs_before + i));
28959 row->used[TEXT_AREA] = n_glyphs_before + i;
28960 it->current_x = x;
28961 }
28962 break;
28963 }
28964 else if (x + glyph->pixel_width >= it->first_visible_x)
28965 {
28966
28967 ++it->hpos;
28968 if (x < it->first_visible_x)
28969 row->x = x - it->first_visible_x;
28970 }
28971 else
28972 {
28973
28974
28975 emacs_abort ();
28976 }
28977
28978 row->ascent = max (row->ascent, it->max_ascent);
28979 row->height = max (row->height, it->max_ascent + it->max_descent);
28980 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28981 row->phys_height = max (row->phys_height,
28982 it->max_phys_ascent + it->max_phys_descent);
28983 row->extra_line_spacing = max (row->extra_line_spacing,
28984 it->max_extra_line_spacing);
28985 x += glyph->pixel_width;
28986 ++i;
28987 }
28988
28989
28990 if (i < nglyphs)
28991 break;
28992
28993
28994 if (ITERATOR_AT_END_OF_LINE_P (it))
28995 {
28996 it->continuation_lines_width = 0;
28997 break;
28998 }
28999
29000 set_iterator_to_next (it, true);
29001 if (STRINGP (it->string))
29002 it_charpos = IT_STRING_CHARPOS (*it);
29003 else
29004 it_charpos = IT_CHARPOS (*it);
29005
29006
29007 if (it->line_wrap == TRUNCATE
29008 && it->current_x >= it->last_visible_x)
29009 {
29010
29011
29012
29013
29014
29015
29016 if (it_charpos <= it->string_nchars)
29017 {
29018 if (!FRAME_WINDOW_P (it->f))
29019 {
29020 int ii, n;
29021
29022 if (it->current_x > it->last_visible_x)
29023 {
29024
29025
29026 bool mode_line_p = false;
29027
29028
29029
29030 if (row->mode_line_p)
29031 {
29032 struct window *w = it->w;
29033 if (row == MATRIX_MODE_LINE_ROW (w->desired_matrix))
29034 mode_line_p = true;
29035 }
29036 if (!row->reversed_p)
29037 {
29038 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
29039 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
29040 break;
29041 }
29042 else
29043 {
29044 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
29045 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
29046 break;
29047 unproduce_glyphs (it, ii + 1);
29048 ii = row->used[TEXT_AREA] - (ii + 1);
29049 }
29050 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
29051 {
29052 row->used[TEXT_AREA] = ii;
29053 if (row->mode_line_p)
29054 pad_mode_line (it, mode_line_p);
29055 else
29056 produce_special_glyphs (it, IT_TRUNCATION);
29057 }
29058 }
29059 produce_special_glyphs (it, IT_TRUNCATION);
29060 }
29061 row->truncated_on_right_p = true;
29062 }
29063 break;
29064 }
29065 }
29066
29067
29068 if (it->first_visible_x
29069 && it_charpos > 0)
29070 {
29071 if (!FRAME_WINDOW_P (it->f)
29072 || (row->reversed_p
29073 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29074 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
29075 insert_left_trunc_glyphs (it);
29076 row->truncated_on_left_p = true;
29077 }
29078
29079 it->face_id = saved_face_id;
29080
29081
29082 return it->hpos - hpos_at_start;
29083 }
29084
29085
29086
29087
29088
29089
29090
29091
29092
29093
29094
29095 int
29096 invisible_prop (Lisp_Object propval, Lisp_Object list)
29097 {
29098 Lisp_Object tail, proptail;
29099
29100 for (tail = list; CONSP (tail); tail = XCDR (tail))
29101 {
29102 register Lisp_Object tem;
29103 tem = XCAR (tail);
29104 if (EQ (propval, tem))
29105 return 1;
29106 if (CONSP (tem) && EQ (propval, XCAR (tem)))
29107 return NILP (XCDR (tem)) ? 1 : 2;
29108 }
29109
29110 if (CONSP (propval))
29111 {
29112 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
29113 {
29114 Lisp_Object propelt;
29115 propelt = XCAR (proptail);
29116 for (tail = list; CONSP (tail); tail = XCDR (tail))
29117 {
29118 register Lisp_Object tem;
29119 tem = XCAR (tail);
29120 if (EQ (propelt, tem))
29121 return 1;
29122 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
29123 return NILP (XCDR (tem)) ? 1 : 2;
29124 }
29125 }
29126 }
29127
29128 return 0;
29129 }
29130
29131 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
29132 doc:
29133
29134
29135
29136
29137
29138
29139
29140
29141
29142
29143
29144 )
29145 (Lisp_Object pos)
29146 {
29147 Lisp_Object prop
29148 = (FIXNATP (pos) || MARKERP (pos)
29149 ? Fget_char_property (pos, Qinvisible, Qnil)
29150 : pos);
29151 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
29152 return (invis == 0 ? Qnil
29153 : invis == 1 ? Qt
29154 : make_fixnum (invis));
29155 }
29156
29157
29158
29159
29160
29161
29162
29163
29164
29165
29166
29167
29168
29169
29170
29171
29172
29173
29174
29175
29176
29177
29178
29179
29180
29181
29182
29183
29184
29185
29186
29187
29188
29189
29190
29191
29192
29193
29194
29195
29196
29197
29198
29199
29200
29201
29202
29203
29204
29205
29206
29207
29208
29209
29210
29211
29212
29213
29214
29215
29216
29217
29218
29219
29220
29221
29222
29223
29224
29225
29226
29227
29228
29229
29230
29231
29232
29233
29234
29235
29236
29237 static bool
29238 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
29239 struct font *font, bool width_p, int *align_to)
29240 {
29241
29242
29243
29244
29245 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
29246 double pixels;
29247
29248 # define OK_PIXELS(val) (*res = (val), true)
29249 # define OK_ALIGN_TO(val) (*align_to = (val), true)
29250
29251 if (NILP (prop))
29252 return OK_PIXELS (0);
29253
29254 eassert (FRAME_LIVE_P (it->f));
29255
29256 if (SYMBOLP (prop))
29257 {
29258 if (SCHARS (SYMBOL_NAME (prop)) == 2)
29259 {
29260 char *unit = SSDATA (SYMBOL_NAME (prop));
29261
29262
29263 if (unit[0] == 'i' && unit[1] == 'n')
29264 pixels = 1.0;
29265 else if (unit[0] == 'm' && unit[1] == 'm')
29266 pixels = 25.4;
29267 else if (unit[0] == 'c' && unit[1] == 'm')
29268 pixels = 2.54;
29269 else
29270 pixels = 0;
29271 if (pixels > 0)
29272 {
29273 double ppi = (width_p ? FRAME_RES_X (it->f)
29274 : FRAME_RES_Y (it->f));
29275
29276 if (ppi > 0)
29277 return OK_PIXELS (ppi / pixels);
29278 return false;
29279 }
29280 }
29281
29282 #ifdef HAVE_WINDOW_SYSTEM
29283
29284 if (EQ (prop, Qheight))
29285 return OK_PIXELS (font
29286 ? normal_char_height (font, -1)
29287 : FRAME_LINE_HEIGHT (it->f));
29288
29289 if (EQ (prop, Qwidth))
29290 return OK_PIXELS (font
29291 ? (font->average_width
29292 ? font->average_width
29293 : font->space_width)
29294 : FRAME_COLUMN_WIDTH (it->f));
29295 #else
29296 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
29297 return OK_PIXELS (1);
29298 #endif
29299
29300
29301 if (EQ (prop, Qtext))
29302 return OK_PIXELS (width_p
29303 ? (window_box_width (it->w, TEXT_AREA)
29304 - lnum_pixel_width)
29305 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
29306
29307
29308
29309
29310 if (align_to && *align_to < 0)
29311 {
29312 *res = 0;
29313
29314 if (EQ (prop, Qleft))
29315 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29316 + lnum_pixel_width);
29317
29318 if (EQ (prop, Qright))
29319 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
29320
29321 if (EQ (prop, Qcenter))
29322 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29323 + lnum_pixel_width
29324 + window_box_width (it->w, TEXT_AREA) / 2);
29325
29326 if (EQ (prop, Qleft_fringe))
29327 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29328 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29329 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29330
29331 if (EQ (prop, Qright_fringe))
29332 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29333 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29334 : window_box_right_offset (it->w, TEXT_AREA));
29335
29336 if (EQ (prop, Qleft_margin))
29337 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29338
29339 if (EQ (prop, Qright_margin))
29340 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29341
29342 if (EQ (prop, Qscroll_bar))
29343 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29344 ? 0
29345 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29346 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29347 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29348 : 0)));
29349 }
29350 else
29351 {
29352
29353 if (EQ (prop, Qleft_fringe))
29354 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29355 if (EQ (prop, Qright_fringe))
29356 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29357 if (EQ (prop, Qleft_margin))
29358 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29359 if (EQ (prop, Qright_margin))
29360 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29361 if (EQ (prop, Qscroll_bar))
29362 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29363 }
29364
29365 prop = buffer_local_value (prop, it->w->contents);
29366 if (BASE_EQ (prop, Qunbound))
29367 prop = Qnil;
29368 }
29369
29370 if (NUMBERP (prop))
29371 {
29372 int base_unit = (width_p
29373 ? FRAME_COLUMN_WIDTH (it->f)
29374 : FRAME_LINE_HEIGHT (it->f));
29375 if (width_p && align_to && *align_to < 0)
29376 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29377 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29378 }
29379
29380 if (CONSP (prop))
29381 {
29382 Lisp_Object car = XCAR (prop);
29383 Lisp_Object cdr = XCDR (prop);
29384
29385 if (SYMBOLP (car))
29386 {
29387 #ifdef HAVE_WINDOW_SYSTEM
29388
29389 if (FRAME_WINDOW_P (it->f)
29390 && valid_image_p (prop))
29391 {
29392 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29393 struct image *img = IMAGE_FROM_ID (it->f, id);
29394
29395 return OK_PIXELS (width_p ? img->width : img->height);
29396 }
29397
29398 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29399 {
29400
29401 return OK_PIXELS (100);
29402 }
29403 #endif
29404
29405
29406 if (EQ (car, Qplus) || EQ (car, Qminus))
29407 {
29408 bool first = true;
29409 double px;
29410
29411 pixels = 0;
29412 while (CONSP (cdr))
29413 {
29414 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29415 font, width_p, align_to))
29416 return false;
29417 if (first)
29418 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29419 else
29420 pixels += px;
29421 cdr = XCDR (cdr);
29422 }
29423 if (EQ (car, Qminus))
29424 pixels = -pixels;
29425 return OK_PIXELS (pixels);
29426 }
29427
29428 car = buffer_local_value (car, it->w->contents);
29429 if (BASE_EQ (car, Qunbound))
29430 car = Qnil;
29431 }
29432
29433
29434 if (NUMBERP (car))
29435 {
29436 double fact;
29437 int offset =
29438 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29439 pixels = XFLOATINT (car);
29440 if (NILP (cdr))
29441 return OK_PIXELS (pixels + offset);
29442 if (calc_pixel_width_or_height (&fact, it, cdr,
29443 font, width_p, align_to))
29444 return OK_PIXELS (pixels * fact + offset);
29445 return false;
29446 }
29447
29448 return false;
29449 }
29450
29451 return false;
29452 }
29453
29454 void
29455 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29456 {
29457 #ifdef HAVE_WINDOW_SYSTEM
29458 normal_char_ascent_descent (font, -1, ascent, descent);
29459 #else
29460 *ascent = 1;
29461 *descent = 0;
29462 #endif
29463 }
29464
29465
29466
29467
29468
29469
29470 #ifdef HAVE_WINDOW_SYSTEM
29471
29472 #ifdef GLYPH_DEBUG
29473
29474 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29475 void
29476 dump_glyph_string (struct glyph_string *s)
29477 {
29478 fputs ("glyph string\n", stderr);
29479 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29480 s->x, s->y, s->width, s->height);
29481 fprintf (stderr, " ybase = %d\n", s->ybase);
29482 fprintf (stderr, " hl = %u\n", s->hl);
29483 fprintf (stderr, " left overhang = %d, right = %d\n",
29484 s->left_overhang, s->right_overhang);
29485 fprintf (stderr, " nchars = %d\n", s->nchars);
29486 fprintf (stderr, " extends to end of line = %d\n",
29487 s->extends_to_end_of_line_p);
29488 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29489 fprintf (stderr, " bg width = %d\n", s->background_width);
29490 }
29491
29492 #endif
29493
29494
29495
29496
29497
29498
29499
29500
29501
29502 #ifdef HAVE_NTGUI
29503
29504
29505
29506
29507
29508 # define ALLOCATE_HDC(hdc, f) \
29509 Lisp_Object prev_quit = Vinhibit_quit; \
29510 Vinhibit_quit = Qt; \
29511 HDC hdc = get_frame_dc ((f))
29512 # define RELEASE_HDC(hdc, f) \
29513 release_frame_dc ((f), (hdc)); \
29514 Vinhibit_quit = prev_quit
29515 #else
29516 # define ALLOCATE_HDC(hdc, f)
29517 # define RELEASE_HDC(hdc, f)
29518 #endif
29519
29520 static void
29521 init_glyph_string (struct glyph_string *s,
29522 #ifdef HAVE_NTGUI
29523 HDC hdc,
29524 #endif
29525 unsigned *char2b, struct window *w, struct glyph_row *row,
29526 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29527 {
29528 memset (s, 0, sizeof *s);
29529 s->w = w;
29530 s->f = XFRAME (w->frame);
29531 #ifdef HAVE_NTGUI
29532 s->hdc = hdc;
29533 #endif
29534 s->char2b = char2b;
29535 s->hl = hl;
29536 s->row = row;
29537 s->area = area;
29538 s->first_glyph = row->glyphs[area] + start;
29539 s->height = row->height;
29540 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29541 s->ybase = s->y + row->ascent;
29542 }
29543
29544
29545
29546
29547
29548 static void
29549 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29550 struct glyph_string *h, struct glyph_string *t)
29551 {
29552 if (h)
29553 {
29554 if (*head)
29555 (*tail)->next = h;
29556 else
29557 *head = h;
29558 h->prev = *tail;
29559 *tail = t;
29560 }
29561 }
29562
29563
29564
29565
29566
29567
29568 static void
29569 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29570 struct glyph_string *h, struct glyph_string *t)
29571 {
29572 if (h)
29573 {
29574 if (*head)
29575 (*head)->prev = t;
29576 else
29577 *tail = t;
29578 t->next = *head;
29579 *head = h;
29580 }
29581 }
29582
29583
29584
29585
29586
29587 static void
29588 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29589 struct glyph_string *s)
29590 {
29591 s->next = s->prev = NULL;
29592 append_glyph_string_lists (head, tail, s, s);
29593 }
29594
29595
29596
29597
29598
29599
29600
29601
29602 static struct face *
29603 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29604 unsigned *char2b, bool display_p)
29605 {
29606 struct face *face = FACE_FROM_ID (f, face_id);
29607 unsigned code = 0;
29608
29609 if (face->font)
29610 {
29611 code = face->font->driver->encode_char (face->font, c);
29612
29613 if (code == FONT_INVALID_CODE)
29614 code = 0;
29615 }
29616
29617 *char2b = code & 0xFFFF;
29618
29619
29620 #ifdef HAVE_X_WINDOWS
29621 if (display_p)
29622 #endif
29623 {
29624 eassert (face != NULL);
29625 prepare_face_for_display (f, face);
29626 }
29627
29628 return face;
29629 }
29630
29631
29632
29633
29634
29635
29636 static struct face *
29637 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29638 unsigned *char2b)
29639 {
29640 struct face *face;
29641 unsigned code = 0;
29642
29643 eassert (glyph->type == CHAR_GLYPH);
29644 face = FACE_FROM_ID (f, glyph->face_id);
29645
29646
29647 prepare_face_for_display (f, face);
29648
29649 if (face->font)
29650 {
29651 if (CHAR_BYTE8_P (glyph->u.ch))
29652 code = CHAR_TO_BYTE8 (glyph->u.ch);
29653 else
29654 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29655
29656 if (code == FONT_INVALID_CODE)
29657 code = 0;
29658 }
29659
29660
29661 *char2b = code & 0xFFFF;
29662 return face;
29663 }
29664
29665
29666
29667
29668
29669 static bool
29670 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29671 {
29672 unsigned code;
29673
29674 if (CHAR_BYTE8_P (c))
29675 code = CHAR_TO_BYTE8 (c);
29676 else
29677 code = font->driver->encode_char (font, c);
29678
29679 if (code == FONT_INVALID_CODE)
29680 return false;
29681
29682
29683 *char2b = code & 0xFFFF;
29684 return true;
29685 }
29686
29687
29688
29689
29690
29691
29692
29693
29694
29695
29696
29697
29698 static int
29699 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29700 int overlaps)
29701 {
29702 int i;
29703
29704
29705
29706 struct face *face;
29707
29708 eassert (s);
29709
29710 s->for_overlaps = overlaps;
29711 s->face = NULL;
29712 s->font = NULL;
29713 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29714 {
29715 int c = COMPOSITION_GLYPH (s->cmp, i);
29716
29717
29718
29719 if (c != '\t')
29720 {
29721 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29722 -1, Qnil);
29723
29724 face = get_char_face_and_encoding (s->f, c, face_id,
29725 s->char2b + i, true);
29726 if (face)
29727 {
29728 if (! s->face)
29729 {
29730 s->face = face;
29731 s->font = s->face->font;
29732 }
29733 else if (s->face != face)
29734 break;
29735 }
29736 }
29737 ++s->nchars;
29738 }
29739 s->cmp_to = i;
29740
29741 if (s->face == NULL)
29742 {
29743 s->face = base_face->ascii_face;
29744 s->font = s->face->font;
29745 }
29746
29747 if (s->hl == DRAW_MOUSE_FACE
29748 || (s->hl == DRAW_CURSOR
29749 && MATRIX_ROW (s->w->current_matrix,
29750 s->w->phys_cursor.vpos)->mouse_face_p
29751 && cursor_in_mouse_face_p (s->w)))
29752 {
29753 int c = COMPOSITION_GLYPH (s->cmp, 0);
29754 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29755 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29756 if (!s->face)
29757 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29758
29759 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29760 prepare_face_for_display (s->f, s->face);
29761 }
29762
29763
29764
29765 s->width = s->first_glyph->pixel_width;
29766
29767
29768
29769
29770
29771 if (s->font == NULL)
29772 {
29773 s->font_not_found_p = true;
29774 s->font = FRAME_FONT (s->f);
29775 }
29776
29777
29778 s->ybase += s->first_glyph->voffset;
29779
29780 return s->cmp_to;
29781 }
29782
29783 static int
29784 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29785 int start, int end, int overlaps)
29786 {
29787 struct glyph *glyph, *last;
29788 int voffset;
29789 Lisp_Object lgstring;
29790 int i;
29791 bool glyph_not_available_p;
29792
29793 s->for_overlaps = overlaps;
29794 glyph = s->row->glyphs[s->area] + start;
29795 last = s->row->glyphs[s->area] + end;
29796 voffset = glyph->voffset;
29797 glyph_not_available_p = glyph->glyph_not_available_p;
29798 s->cmp_id = glyph->u.cmp.id;
29799 s->cmp_from = glyph->slice.cmp.from;
29800 s->cmp_to = glyph->slice.cmp.to + 1;
29801 if (s->hl == DRAW_MOUSE_FACE
29802 || (s->hl == DRAW_CURSOR
29803 && MATRIX_ROW (s->w->current_matrix,
29804 s->w->phys_cursor.vpos)->mouse_face_p
29805 && cursor_in_mouse_face_p (s->w)))
29806 {
29807 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29808 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29809 if (!s->face)
29810 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29811 prepare_face_for_display (s->f, s->face);
29812 }
29813 else
29814 s->face = FACE_FROM_ID (s->f, face_id);
29815 lgstring = composition_gstring_from_id (s->cmp_id);
29816 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29817
29818
29819 s->width = s->first_glyph->pixel_width;
29820 glyph++;
29821 while (glyph < last
29822 && glyph->u.cmp.automatic
29823 && glyph->u.cmp.id == s->cmp_id
29824 && glyph->face_id == face_id
29825 && s->cmp_to == glyph->slice.cmp.from
29826 && glyph->glyph_not_available_p == glyph_not_available_p)
29827 {
29828 s->width += glyph->pixel_width;
29829 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29830 }
29831
29832 for (i = s->cmp_from; i < s->cmp_to; i++)
29833 {
29834 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29835 unsigned code = LGLYPH_CODE (lglyph);
29836
29837
29838 s->char2b[i] = code & 0xFFFF;
29839 }
29840
29841
29842
29843
29844 if (glyph_not_available_p)
29845 s->font_not_found_p = true;
29846
29847
29848 s->ybase += voffset;
29849
29850 return glyph - s->row->glyphs[s->area];
29851 }
29852
29853
29854
29855
29856
29857
29858
29859 static int
29860 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29861 int start, int end, int overlaps)
29862 {
29863 struct glyph *glyph, *last;
29864 int voffset;
29865
29866 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29867 s->for_overlaps = overlaps;
29868 glyph = s->row->glyphs[s->area] + start;
29869 last = s->row->glyphs[s->area] + end;
29870 voffset = glyph->voffset;
29871 s->face = FACE_FROM_ID (s->f, face_id);
29872 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29873 if (s->hl == DRAW_MOUSE_FACE
29874 || (s->hl == DRAW_CURSOR
29875 && MATRIX_ROW (s->w->current_matrix,
29876 s->w->phys_cursor.vpos)->mouse_face_p
29877 && cursor_in_mouse_face_p (s->w)))
29878 {
29879 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29880 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29881 if (!s->face)
29882 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29883 prepare_face_for_display (s->f, s->face);
29884 }
29885 s->nchars = 1;
29886 s->width = glyph->pixel_width;
29887 glyph++;
29888 while (glyph < last
29889 && glyph->type == GLYPHLESS_GLYPH
29890 && glyph->voffset == voffset
29891 && glyph->face_id == face_id)
29892 {
29893 s->nchars++;
29894 s->width += glyph->pixel_width;
29895 glyph++;
29896 }
29897 s->ybase += voffset;
29898 return glyph - s->row->glyphs[s->area];
29899 }
29900
29901
29902
29903
29904
29905
29906
29907
29908
29909
29910
29911 static int
29912 fill_glyph_string (struct glyph_string *s, int face_id,
29913 int start, int end, int overlaps)
29914 {
29915 struct glyph *glyph, *last;
29916 int voffset;
29917 bool glyph_not_available_p;
29918
29919 eassert (s->f == XFRAME (s->w->frame));
29920 eassert (s->nchars == 0);
29921 eassert (start >= 0 && end > start);
29922
29923 s->for_overlaps = overlaps;
29924 glyph = s->row->glyphs[s->area] + start;
29925 last = s->row->glyphs[s->area] + end;
29926 voffset = glyph->voffset;
29927 s->padding_p = glyph->padding_p;
29928 glyph_not_available_p = glyph->glyph_not_available_p;
29929
29930 while (glyph < last
29931 && glyph->type == CHAR_GLYPH
29932 && glyph->voffset == voffset
29933
29934 && glyph->face_id == face_id
29935 && glyph->glyph_not_available_p == glyph_not_available_p)
29936 {
29937 s->face = get_glyph_face_and_encoding (s->f, glyph,
29938 s->char2b + s->nchars);
29939 ++s->nchars;
29940 eassert (s->nchars <= end - start);
29941 s->width += glyph->pixel_width;
29942 if (glyph++->padding_p != s->padding_p)
29943 break;
29944 }
29945
29946 s->font = s->face->font;
29947
29948 if (s->hl == DRAW_MOUSE_FACE
29949 || (s->hl == DRAW_CURSOR
29950 && MATRIX_ROW (s->w->current_matrix,
29951 s->w->phys_cursor.vpos)->mouse_face_p
29952 && cursor_in_mouse_face_p (s->w)))
29953 {
29954 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29955 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29956 if (!s->face)
29957 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29958 s->face
29959 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29960 s->first_glyph->u.ch, -1, Qnil));
29961 prepare_face_for_display (s->f, s->face);
29962 }
29963
29964
29965
29966
29967
29968 if (s->font == NULL || glyph_not_available_p)
29969 {
29970 s->font_not_found_p = true;
29971 s->font = FRAME_FONT (s->f);
29972 }
29973
29974
29975 s->ybase += voffset;
29976
29977 eassert (s->face && s->face->gc);
29978 return glyph - s->row->glyphs[s->area];
29979 }
29980
29981
29982
29983
29984 static void
29985 fill_image_glyph_string (struct glyph_string *s)
29986 {
29987 eassert (s->first_glyph->type == IMAGE_GLYPH);
29988 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29989 eassert (s->img);
29990 s->slice = s->first_glyph->slice.img;
29991 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29992 s->font = s->face->font;
29993 if (s->hl == DRAW_MOUSE_FACE
29994 || (s->hl == DRAW_CURSOR
29995 && MATRIX_ROW (s->w->current_matrix,
29996 s->w->phys_cursor.vpos)->mouse_face_p
29997 && cursor_in_mouse_face_p (s->w)))
29998 {
29999 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
30000 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
30001 if (!s->face)
30002 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30003 prepare_face_for_display (s->f, s->face);
30004 }
30005 s->width = s->first_glyph->pixel_width;
30006
30007
30008 s->ybase += s->first_glyph->voffset;
30009 }
30010
30011
30012 #ifdef HAVE_XWIDGETS
30013 static void
30014 fill_xwidget_glyph_string (struct glyph_string *s)
30015 {
30016 eassert (s->first_glyph->type == XWIDGET_GLYPH);
30017 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
30018 s->font = s->face->font;
30019 if (s->hl == DRAW_MOUSE_FACE
30020 || (s->hl == DRAW_CURSOR
30021 && MATRIX_ROW (s->w->current_matrix,
30022 s->w->phys_cursor.vpos)->mouse_face_p
30023 && cursor_in_mouse_face_p (s->w)))
30024 {
30025 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
30026 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
30027 if (!s->face)
30028 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30029 prepare_face_for_display (s->f, s->face);
30030 }
30031 s->width = s->first_glyph->pixel_width;
30032 s->ybase += s->first_glyph->voffset;
30033 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
30034 }
30035 #endif
30036
30037
30038
30039
30040
30041
30042
30043 static int
30044 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
30045 {
30046 struct glyph *glyph, *last;
30047 int voffset, face_id;
30048
30049 eassert (s->first_glyph->type == STRETCH_GLYPH);
30050
30051 glyph = s->row->glyphs[s->area] + start;
30052 last = s->row->glyphs[s->area] + end;
30053 face_id = glyph->face_id;
30054 s->face = FACE_FROM_ID (s->f, face_id);
30055 s->font = s->face->font;
30056 if (s->hl == DRAW_MOUSE_FACE
30057 || (s->hl == DRAW_CURSOR
30058 && MATRIX_ROW (s->w->current_matrix,
30059 s->w->phys_cursor.vpos)->mouse_face_p
30060 && cursor_in_mouse_face_p (s->w)))
30061 {
30062 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
30063 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
30064 if (!s->face)
30065 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30066 prepare_face_for_display (s->f, s->face);
30067 }
30068 s->width = glyph->pixel_width;
30069 s->nchars = 1;
30070 voffset = glyph->voffset;
30071
30072 for (++glyph;
30073 (glyph < last
30074 && glyph->type == STRETCH_GLYPH
30075 && glyph->voffset == voffset
30076 && glyph->face_id == face_id);
30077 ++glyph)
30078 s->width += glyph->pixel_width;
30079
30080
30081 s->ybase += voffset;
30082
30083
30084
30085 eassert (s->face);
30086 return glyph - s->row->glyphs[s->area];
30087 }
30088
30089 static struct font_metrics *
30090 get_per_char_metric (struct font *font, const unsigned *char2b)
30091 {
30092 static struct font_metrics metrics;
30093
30094 if (! font)
30095 return NULL;
30096 if (*char2b == FONT_INVALID_CODE)
30097 return NULL;
30098
30099 font->driver->text_extents (font, char2b, 1, &metrics);
30100 return &metrics;
30101 }
30102
30103
30104
30105
30106
30107
30108
30109 static void
30110 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
30111 {
30112 *ascent = FONT_BASE (font);
30113 *descent = FONT_DESCENT (font);
30114
30115 if (FONT_TOO_HIGH (font))
30116 {
30117 unsigned char2b;
30118
30119
30120
30121 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
30122 {
30123 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
30124 eassume (pcm);
30125
30126 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
30127 {
30128
30129
30130
30131 *ascent = pcm->ascent + 1;
30132 *descent = pcm->descent + 1;
30133 }
30134 }
30135 }
30136 }
30137
30138
30139
30140
30141
30142
30143 static int
30144 normal_char_height (struct font *font, int c)
30145 {
30146 int ascent, descent;
30147
30148 normal_char_ascent_descent (font, c, &ascent, &descent);
30149
30150 return ascent + descent;
30151 }
30152
30153
30154
30155
30156
30157
30158 void
30159 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
30160 {
30161 *left = *right = 0;
30162
30163 if (glyph->type == CHAR_GLYPH)
30164 {
30165 unsigned char2b;
30166 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
30167 if (face->font)
30168 {
30169 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
30170 if (pcm)
30171 {
30172 if (pcm->rbearing > pcm->width)
30173 *right = pcm->rbearing - pcm->width;
30174 if (pcm->lbearing < 0)
30175 *left = -pcm->lbearing;
30176 }
30177 }
30178 }
30179 else if (glyph->type == COMPOSITE_GLYPH)
30180 {
30181 if (! glyph->u.cmp.automatic)
30182 {
30183 struct composition *cmp = composition_table[glyph->u.cmp.id];
30184
30185 if (cmp->rbearing > cmp->pixel_width)
30186 *right = cmp->rbearing - cmp->pixel_width;
30187 if (cmp->lbearing < 0)
30188 *left = - cmp->lbearing;
30189 }
30190 else
30191 {
30192 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
30193 struct font_metrics metrics;
30194
30195 composition_gstring_width (gstring, glyph->slice.cmp.from,
30196 glyph->slice.cmp.to + 1, &metrics);
30197 if (metrics.rbearing > metrics.width)
30198 *right = metrics.rbearing - metrics.width;
30199 if (metrics.lbearing < 0)
30200 *left = - metrics.lbearing;
30201 }
30202 }
30203 }
30204
30205
30206
30207
30208
30209
30210 static int
30211 left_overwritten (struct glyph_string *s)
30212 {
30213 int k;
30214
30215 if (s->left_overhang)
30216 {
30217 int x = 0, i;
30218 struct glyph *glyphs = s->row->glyphs[s->area];
30219 int first = s->first_glyph - glyphs;
30220
30221 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
30222 x -= glyphs[i].pixel_width;
30223
30224 k = i + 1;
30225 }
30226 else
30227 k = -1;
30228
30229 return k;
30230 }
30231
30232
30233
30234
30235
30236
30237 static int
30238 left_overwriting (struct glyph_string *s)
30239 {
30240 int i, k, x;
30241 struct glyph *glyphs = s->row->glyphs[s->area];
30242 int first = s->first_glyph - glyphs;
30243
30244 k = -1;
30245 x = 0;
30246 for (i = first - 1; i >= 0; --i)
30247 {
30248 int left, right;
30249 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30250 if (x + right > 0)
30251 k = i;
30252 x -= glyphs[i].pixel_width;
30253 }
30254
30255 return k;
30256 }
30257
30258
30259
30260
30261
30262
30263 static int
30264 right_overwritten (struct glyph_string *s)
30265 {
30266 int k = -1;
30267
30268 if (s->right_overhang)
30269 {
30270 int x = 0, i;
30271 struct glyph *glyphs = s->row->glyphs[s->area];
30272 int first = (s->first_glyph - glyphs
30273 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30274 int end = s->row->used[s->area];
30275
30276 for (i = first; i < end && s->right_overhang > x; ++i)
30277 x += glyphs[i].pixel_width;
30278
30279 k = i;
30280 }
30281
30282 return k;
30283 }
30284
30285
30286
30287
30288
30289
30290 static int
30291 right_overwriting (struct glyph_string *s)
30292 {
30293 int i, k, x;
30294 int end = s->row->used[s->area];
30295 struct glyph *glyphs = s->row->glyphs[s->area];
30296 int first = (s->first_glyph - glyphs
30297 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30298
30299 k = -1;
30300 x = 0;
30301 for (i = first; i < end; ++i)
30302 {
30303 int left, right;
30304 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30305 if (x - left < 0)
30306 k = i;
30307 x += glyphs[i].pixel_width;
30308 }
30309
30310 return k;
30311 }
30312
30313
30314
30315
30316
30317
30318
30319
30320
30321
30322
30323 static void
30324 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30325 {
30326
30327
30328
30329 if (start == s->row->used[s->area]
30330 && ((s->row->fill_line_p
30331 && (s->hl == DRAW_NORMAL_TEXT
30332 || s->hl == DRAW_IMAGE_RAISED
30333 || s->hl == DRAW_IMAGE_SUNKEN))
30334 || s->hl == DRAW_MOUSE_FACE))
30335 s->extends_to_end_of_line_p = true;
30336
30337
30338
30339
30340 if (s->extends_to_end_of_line_p)
30341 s->background_width = last_x - s->x + 1;
30342 else
30343 {
30344 s->background_width = s->width;
30345 #ifdef HAVE_WINDOW_SYSTEM
30346 if (FRAME_WINDOW_P (s->f)
30347 && s->hl == DRAW_CURSOR
30348 && MATRIX_ROW (s->w->current_matrix,
30349 s->w->phys_cursor.vpos)->mouse_face_p
30350 && cursor_in_mouse_face_p (s->w))
30351 {
30352
30353
30354
30355
30356 struct glyph *g = s->first_glyph;
30357 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30358 s->background_width +=
30359 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30360 regular_face, s->face);
30361
30362 s->width = s->background_width;
30363 }
30364 #endif
30365 }
30366 }
30367
30368
30369
30370
30371
30372 static struct glyph_string *
30373 glyph_string_containing_background_width (struct glyph_string *s)
30374 {
30375 if (s->cmp)
30376 while (s->cmp_from)
30377 s = s->prev;
30378
30379 return s;
30380 }
30381
30382
30383
30384
30385
30386
30387 static void
30388 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30389 {
30390 if (backward_p)
30391 {
30392 while (s)
30393 {
30394 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30395 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30396 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30397 x -= s->width;
30398 s->x = x;
30399 s = s->prev;
30400 }
30401 }
30402 else
30403 {
30404 while (s)
30405 {
30406 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30407 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30408 s->x = x;
30409 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30410 x += s->width;
30411 s = s->next;
30412 }
30413 }
30414 }
30415
30416
30417
30418
30419
30420
30421
30422
30423
30424 #ifdef HAVE_NTGUI
30425
30426
30427 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30428 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30429 #else
30430 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30431 init_glyph_string (s, char2b, w, row, area, start, hl)
30432 #endif
30433
30434
30435
30436
30437
30438
30439
30440
30441
30442
30443
30444 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30445 do \
30446 { \
30447 s = alloca (sizeof *s); \
30448 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30449 START = fill_stretch_glyph_string (s, START, END); \
30450 append_glyph_string (&HEAD, &TAIL, s); \
30451 s->x = (X); \
30452 } \
30453 while (false)
30454
30455
30456
30457
30458
30459
30460
30461
30462
30463
30464 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30465 do \
30466 { \
30467 s = alloca (sizeof *s); \
30468 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30469 fill_image_glyph_string (s); \
30470 append_glyph_string (&HEAD, &TAIL, s); \
30471 ++START; \
30472 s->x = (X); \
30473 } \
30474 while (false)
30475
30476 #ifndef HAVE_XWIDGETS
30477 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30478 eassume (false)
30479 #else
30480 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30481 do \
30482 { \
30483 s = alloca (sizeof *s); \
30484 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30485 fill_xwidget_glyph_string (s); \
30486 append_glyph_string (&(HEAD), &(TAIL), s); \
30487 ++(START); \
30488 s->x = (X); \
30489 } \
30490 while (false)
30491 #endif
30492
30493
30494
30495
30496
30497
30498
30499
30500
30501
30502 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30503 do \
30504 { \
30505 int face_id; \
30506 unsigned *char2b; \
30507 \
30508 face_id = (row)->glyphs[area][START].face_id; \
30509 \
30510 s = alloca (sizeof *s); \
30511 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30512 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30513 append_glyph_string (&HEAD, &TAIL, s); \
30514 s->x = (X); \
30515 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30516 } \
30517 while (false)
30518
30519
30520
30521
30522
30523
30524
30525
30526
30527
30528
30529 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30530 do { \
30531 int face_id = (row)->glyphs[area][START].face_id; \
30532 struct face *base_face = FACE_FROM_ID (f, face_id); \
30533 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30534 struct composition *cmp = composition_table[cmp_id]; \
30535 unsigned *char2b; \
30536 struct glyph_string *first_s = NULL; \
30537 int n; \
30538 \
30539 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30540 \
30541
30542 \
30543 for (n = 0; n < cmp->glyph_len;) \
30544 { \
30545 s = alloca (sizeof *s); \
30546 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30547 append_glyph_string (&(HEAD), &(TAIL), s); \
30548 s->cmp = cmp; \
30549 s->cmp_from = n; \
30550 s->x = (X); \
30551 if (n == 0) \
30552 first_s = s; \
30553 n = fill_composite_glyph_string (s, base_face, overlaps); \
30554 } \
30555 \
30556 ++START; \
30557 s = first_s; \
30558 } while (false)
30559
30560
30561
30562
30563
30564 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30565 do { \
30566 int face_id; \
30567 unsigned *char2b; \
30568 Lisp_Object gstring; \
30569 \
30570 face_id = (row)->glyphs[area][START].face_id; \
30571 gstring = (composition_gstring_from_id \
30572 ((row)->glyphs[area][START].u.cmp.id)); \
30573 s = alloca (sizeof *s); \
30574 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30575 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30576 append_glyph_string (&(HEAD), &(TAIL), s); \
30577 s->x = (X); \
30578 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30579 } while (false)
30580
30581
30582
30583
30584
30585
30586 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30587 do \
30588 { \
30589 int face_id; \
30590 \
30591 face_id = (row)->glyphs[area][START].face_id; \
30592 \
30593 s = alloca (sizeof *s); \
30594 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30595 append_glyph_string (&HEAD, &TAIL, s); \
30596 s->x = (X); \
30597 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30598 overlaps); \
30599 } \
30600 while (false)
30601
30602
30603
30604
30605
30606
30607
30608
30609
30610
30611
30612
30613 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30614 do \
30615 { \
30616 HEAD = TAIL = NULL; \
30617 while (START < END) \
30618 { \
30619 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30620 switch (first_glyph->type) \
30621 { \
30622 case CHAR_GLYPH: \
30623 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30624 HL, X, LAST_X); \
30625 break; \
30626 \
30627 case COMPOSITE_GLYPH: \
30628 if (first_glyph->u.cmp.automatic) \
30629 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30630 HL, X, LAST_X); \
30631 else \
30632 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30633 HL, X, LAST_X); \
30634 break; \
30635 \
30636 case STRETCH_GLYPH: \
30637 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30638 HL, X, LAST_X); \
30639 break; \
30640 \
30641 case IMAGE_GLYPH: \
30642 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30643 HL, X, LAST_X); \
30644 break;
30645
30646 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30647 case XWIDGET_GLYPH: \
30648 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30649 HL, X, LAST_X); \
30650 break;
30651
30652 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30653 case GLYPHLESS_GLYPH: \
30654 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30655 HL, X, LAST_X); \
30656 break; \
30657 \
30658 default: \
30659 emacs_abort (); \
30660 } \
30661 \
30662 if (s) \
30663 { \
30664 set_glyph_string_background_width (s, START, LAST_X); \
30665 (X) += s->width; \
30666 } \
30667 } \
30668 } while (false)
30669
30670
30671 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30672 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30673 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30674 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30675
30676
30677
30678
30679
30680
30681
30682
30683
30684
30685
30686
30687
30688
30689
30690
30691
30692
30693
30694
30695
30696
30697
30698
30699 static int
30700 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30701 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30702 enum draw_glyphs_face hl, int overlaps)
30703 {
30704 struct glyph_string *head, *tail;
30705 struct glyph_string *s;
30706 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30707 int i, j, x_reached, last_x, area_left = 0;
30708 struct frame *f = XFRAME (WINDOW_FRAME (w));
30709
30710 ALLOCATE_HDC (hdc, f);
30711
30712
30713 end = min (end, row->used[area]);
30714 start = clip_to_bounds (0, start, end);
30715
30716
30717
30718 if (row->full_width_p)
30719 {
30720
30721
30722 area_left = WINDOW_LEFT_EDGE_X (w);
30723 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30724 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30725 }
30726 else
30727 {
30728 area_left = window_box_left (w, area);
30729 last_x = area_left + window_box_width (w, area);
30730 }
30731 x += area_left;
30732
30733
30734
30735
30736
30737 i = start;
30738 USE_SAFE_ALLOCA;
30739 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30740 if (tail)
30741 {
30742 s = glyph_string_containing_background_width (tail);
30743 x_reached = s->x + s->background_width;
30744 }
30745 else
30746 x_reached = x;
30747
30748
30749
30750
30751 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30752 {
30753 struct glyph_string *h, *t;
30754 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30755 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30756 bool check_mouse_face = false;
30757 int dummy_x = 0;
30758
30759
30760
30761 if (area == TEXT_AREA && row->mouse_face_p
30762 && hlinfo->mouse_face_beg_row >= 0
30763 && hlinfo->mouse_face_end_row >= 0)
30764 {
30765 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30766
30767 if (row_vpos >= hlinfo->mouse_face_beg_row
30768 && row_vpos <= hlinfo->mouse_face_end_row)
30769 {
30770 check_mouse_face = true;
30771 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30772 ? hlinfo->mouse_face_beg_col : 0;
30773 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30774 ? hlinfo->mouse_face_end_col
30775 : row->used[TEXT_AREA];
30776 }
30777 }
30778
30779
30780 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30781 for (s = head; s; s = s->next)
30782 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30783
30784
30785
30786
30787
30788
30789 i = left_overwritten (head);
30790 if (i >= 0)
30791 {
30792 enum draw_glyphs_face overlap_hl;
30793
30794
30795
30796
30797
30798
30799
30800
30801 if (check_mouse_face
30802 && mouse_beg_col < start && mouse_end_col > i)
30803 overlap_hl = DRAW_MOUSE_FACE;
30804 else
30805 overlap_hl = DRAW_NORMAL_TEXT;
30806
30807 if (hl != overlap_hl)
30808 clip_head = head;
30809 j = i;
30810 BUILD_GLYPH_STRINGS (j, start, h, t,
30811 overlap_hl, dummy_x, last_x);
30812 start = i;
30813 compute_overhangs_and_x (t, head->x, true);
30814 prepend_glyph_string_lists (&head, &tail, h, t);
30815 if (clip_head == NULL)
30816 clip_head = head;
30817 }
30818
30819
30820
30821
30822
30823
30824
30825
30826 i = left_overwriting (head);
30827 if (i >= 0)
30828 {
30829 enum draw_glyphs_face overlap_hl;
30830
30831 if (check_mouse_face
30832 && mouse_beg_col < start && mouse_end_col > i)
30833 overlap_hl = DRAW_MOUSE_FACE;
30834 else
30835 overlap_hl = DRAW_NORMAL_TEXT;
30836
30837 if (hl == overlap_hl || clip_head == NULL)
30838 clip_head = head;
30839 BUILD_GLYPH_STRINGS (i, start, h, t,
30840 overlap_hl, dummy_x, last_x);
30841 for (s = h; s; s = s->next)
30842 s->background_filled_p = true;
30843 compute_overhangs_and_x (t, head->x, true);
30844 prepend_glyph_string_lists (&head, &tail, h, t);
30845 }
30846
30847
30848
30849
30850
30851 i = right_overwritten (tail);
30852 if (i >= 0)
30853 {
30854 enum draw_glyphs_face overlap_hl;
30855
30856 if (check_mouse_face
30857 && mouse_beg_col < i && mouse_end_col > end)
30858 overlap_hl = DRAW_MOUSE_FACE;
30859 else
30860 overlap_hl = DRAW_NORMAL_TEXT;
30861
30862 if (hl != overlap_hl)
30863 clip_tail = tail;
30864 BUILD_GLYPH_STRINGS (end, i, h, t,
30865 overlap_hl, x, last_x);
30866
30867
30868 compute_overhangs_and_x (h, tail->x + tail->width, false);
30869 append_glyph_string_lists (&head, &tail, h, t);
30870 if (clip_tail == NULL)
30871 clip_tail = tail;
30872 }
30873
30874
30875
30876
30877
30878
30879 i = right_overwriting (tail);
30880 if (i >= 0)
30881 {
30882 enum draw_glyphs_face overlap_hl;
30883 if (check_mouse_face
30884 && mouse_beg_col < i && mouse_end_col > end)
30885 overlap_hl = DRAW_MOUSE_FACE;
30886 else
30887 overlap_hl = DRAW_NORMAL_TEXT;
30888
30889 if (hl == overlap_hl || clip_tail == NULL)
30890 clip_tail = tail;
30891 i++;
30892 BUILD_GLYPH_STRINGS (end, i, h, t,
30893 overlap_hl, x, last_x);
30894 for (s = h; s; s = s->next)
30895 s->background_filled_p = true;
30896 compute_overhangs_and_x (h, tail->x + tail->width, false);
30897 append_glyph_string_lists (&head, &tail, h, t);
30898 }
30899 tail = glyph_string_containing_background_width (tail);
30900 if (clip_tail)
30901 clip_tail = glyph_string_containing_background_width (clip_tail);
30902 if (clip_head || clip_tail)
30903 for (s = head; s; s = s->next)
30904 {
30905 s->clip_head = clip_head;
30906 s->clip_tail = clip_tail;
30907 }
30908 }
30909
30910
30911 for (s = head; s; s = s->next)
30912 FRAME_RIF (f)->draw_glyph_string (s);
30913
30914
30915
30916 if (area == TEXT_AREA
30917 && !row->full_width_p
30918
30919
30920
30921 && !overlaps)
30922 {
30923 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30924 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30925 : (tail ? tail->x + tail->background_width : x));
30926 x0 -= area_left;
30927 x1 -= area_left;
30928
30929 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30930 row->y, MATRIX_ROW_BOTTOM_Y (row));
30931 }
30932
30933
30934
30935 if (row->full_width_p)
30936 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30937 else
30938 x_reached -= area_left;
30939
30940 RELEASE_HDC (hdc, f);
30941
30942 SAFE_FREE ();
30943 return x_reached;
30944 }
30945
30946
30947
30948
30949
30950
30951
30952
30953 struct font *
30954 font_for_underline_metrics (struct glyph_string *s)
30955 {
30956 struct glyph *g0 = s->row->glyphs[s->area], *g;
30957
30958 for (g = s->first_glyph - 1; g >= g0; g--)
30959 {
30960 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30961 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30962 break;
30963 }
30964
30965
30966 if (g == s->first_glyph - 1)
30967 return s->font;
30968 else
30969 {
30970
30971
30972 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30973 }
30974 }
30975
30976
30977
30978
30979 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30980 { \
30981 if (!it->f->fonts_changed \
30982 && (it->glyph_row->glyphs[area] \
30983 < it->glyph_row->glyphs[area + 1])) \
30984 { \
30985 it->w->ncols_scale_factor++; \
30986 it->f->fonts_changed = true; \
30987 } \
30988 }
30989
30990
30991
30992
30993 static void
30994 append_glyph (struct it *it)
30995 {
30996 struct glyph *glyph;
30997 enum glyph_row_area area = it->area;
30998
30999 eassert (it->glyph_row);
31000 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
31001
31002 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31003 if (glyph < it->glyph_row->glyphs[area + 1])
31004 {
31005
31006
31007 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31008 {
31009 struct glyph *g;
31010
31011
31012 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31013 g[1] = *g;
31014 glyph = it->glyph_row->glyphs[area];
31015 }
31016 glyph->charpos = CHARPOS (it->position);
31017 glyph->object = it->object;
31018 if (it->pixel_width > 0)
31019 {
31020 eassert (it->pixel_width <= SHRT_MAX);
31021 glyph->pixel_width = it->pixel_width;
31022 glyph->padding_p = false;
31023 }
31024 else
31025 {
31026
31027
31028 glyph->pixel_width = 1;
31029 glyph->padding_p = true;
31030 }
31031 glyph->ascent = it->ascent;
31032 glyph->descent = it->descent;
31033 glyph->voffset = it->voffset;
31034 glyph->type = CHAR_GLYPH;
31035 glyph->avoid_cursor_p = it->avoid_cursor_p;
31036 glyph->multibyte_p = it->multibyte_p;
31037 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31038 {
31039
31040
31041 glyph->right_box_line_p = it->start_of_box_run_p;
31042 glyph->left_box_line_p = it->end_of_box_run_p;
31043 }
31044 else
31045 {
31046 glyph->left_box_line_p = it->start_of_box_run_p;
31047 glyph->right_box_line_p = it->end_of_box_run_p;
31048 }
31049 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31050 || it->phys_descent > it->descent);
31051 glyph->glyph_not_available_p = it->glyph_not_available_p;
31052 glyph->face_id = it->face_id;
31053 glyph->u.ch = it->char_to_display;
31054 glyph->slice.img = null_glyph_slice;
31055 glyph->font_type = FONT_TYPE_UNKNOWN;
31056 if (it->bidi_p)
31057 {
31058 glyph->resolved_level = it->bidi_it.resolved_level;
31059 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31060 glyph->bidi_type = it->bidi_it.type;
31061 }
31062 else
31063 {
31064 glyph->resolved_level = 0;
31065 glyph->bidi_type = UNKNOWN_BT;
31066 }
31067 ++it->glyph_row->used[area];
31068 }
31069 else
31070 IT_EXPAND_MATRIX_WIDTH (it, area);
31071 }
31072
31073
31074
31075
31076 static void
31077 append_composite_glyph (struct it *it)
31078 {
31079 struct glyph *glyph;
31080 enum glyph_row_area area = it->area;
31081
31082 eassert (it->glyph_row);
31083
31084 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31085 if (glyph < it->glyph_row->glyphs[area + 1])
31086 {
31087
31088
31089 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
31090 {
31091 struct glyph *g;
31092
31093
31094 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31095 g[1] = *g;
31096 glyph = it->glyph_row->glyphs[it->area];
31097 }
31098 glyph->charpos = it->cmp_it.charpos;
31099 glyph->object = it->object;
31100 eassert (it->pixel_width <= SHRT_MAX);
31101 glyph->pixel_width = it->pixel_width;
31102 glyph->ascent = it->ascent;
31103 glyph->descent = it->descent;
31104 glyph->voffset = it->voffset;
31105 glyph->type = COMPOSITE_GLYPH;
31106 if (it->cmp_it.ch < 0)
31107 {
31108 glyph->u.cmp.automatic = false;
31109 glyph->u.cmp.id = it->cmp_it.id;
31110 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
31111 }
31112 else
31113 {
31114 glyph->u.cmp.automatic = true;
31115 glyph->u.cmp.id = it->cmp_it.id;
31116 glyph->slice.cmp.from = it->cmp_it.from;
31117 glyph->slice.cmp.to = it->cmp_it.to - 1;
31118 }
31119 glyph->avoid_cursor_p = it->avoid_cursor_p;
31120 glyph->multibyte_p = it->multibyte_p;
31121 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31122 {
31123
31124
31125 glyph->right_box_line_p = it->start_of_box_run_p;
31126 glyph->left_box_line_p = it->end_of_box_run_p;
31127 }
31128 else
31129 {
31130 glyph->left_box_line_p = it->start_of_box_run_p;
31131 glyph->right_box_line_p = it->end_of_box_run_p;
31132 }
31133 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31134 || it->phys_descent > it->descent);
31135 glyph->padding_p = false;
31136 glyph->glyph_not_available_p = it->glyph_not_available_p;
31137 glyph->face_id = it->face_id;
31138 glyph->font_type = FONT_TYPE_UNKNOWN;
31139 if (it->bidi_p)
31140 {
31141 glyph->resolved_level = it->bidi_it.resolved_level;
31142 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31143 glyph->bidi_type = it->bidi_it.type;
31144 }
31145 ++it->glyph_row->used[area];
31146 }
31147 else
31148 IT_EXPAND_MATRIX_WIDTH (it, area);
31149 }
31150
31151
31152
31153
31154
31155 static void
31156 take_vertical_position_into_account (struct it *it)
31157 {
31158 if (it->voffset)
31159 {
31160 if (it->voffset < 0)
31161
31162
31163 it->ascent -= it->voffset;
31164 else
31165
31166
31167 it->descent += it->voffset;
31168 }
31169 }
31170
31171
31172
31173
31174
31175
31176 static void
31177 produce_image_glyph (struct it *it)
31178 {
31179 struct image *img;
31180 struct face *face;
31181 int glyph_ascent, crop;
31182 struct glyph_slice slice;
31183
31184 eassert (it->what == IT_IMAGE);
31185
31186 face = FACE_FROM_ID (it->f, it->face_id);
31187
31188 prepare_face_for_display (it->f, face);
31189
31190 if (it->image_id < 0)
31191 {
31192
31193 it->ascent = it->phys_ascent = 0;
31194 it->descent = it->phys_descent = 0;
31195 it->pixel_width = 0;
31196 it->nglyphs = 0;
31197 return;
31198 }
31199
31200 img = IMAGE_FROM_ID (it->f, it->image_id);
31201
31202 prepare_image_for_display (it->f, img);
31203
31204 slice.x = slice.y = 0;
31205 slice.width = img->width;
31206 slice.height = img->height;
31207
31208 if (FIXNUMP (it->slice.x))
31209 slice.x = XFIXNUM (it->slice.x);
31210 else if (FLOATP (it->slice.x))
31211 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
31212
31213 if (FIXNUMP (it->slice.y))
31214 slice.y = XFIXNUM (it->slice.y);
31215 else if (FLOATP (it->slice.y))
31216 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
31217
31218 if (FIXNUMP (it->slice.width))
31219 slice.width = XFIXNUM (it->slice.width);
31220 else if (FLOATP (it->slice.width))
31221 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
31222
31223 if (FIXNUMP (it->slice.height))
31224 slice.height = XFIXNUM (it->slice.height);
31225 else if (FLOATP (it->slice.height))
31226 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
31227
31228 if (slice.x >= img->width)
31229 slice.x = img->width;
31230 if (slice.y >= img->height)
31231 slice.y = img->height;
31232 if (slice.x + slice.width >= img->width)
31233 slice.width = img->width - slice.x;
31234 if (slice.y + slice.height > img->height)
31235 slice.height = img->height - slice.y;
31236
31237 if (slice.width == 0 || slice.height == 0)
31238 return;
31239
31240 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
31241
31242 it->descent = slice.height - glyph_ascent;
31243 if (slice.y == 0)
31244 it->descent += img->vmargin;
31245 if (slice.y + slice.height == img->height)
31246 it->descent += img->vmargin;
31247 it->phys_descent = it->descent;
31248
31249 it->pixel_width = slice.width;
31250 if (slice.x == 0)
31251 it->pixel_width += img->hmargin;
31252 if (slice.x + slice.width == img->width)
31253 it->pixel_width += img->hmargin;
31254
31255
31256
31257 if (it->descent < 0)
31258 it->descent = 0;
31259
31260 it->nglyphs = 1;
31261
31262 if (face->box != FACE_NO_BOX)
31263 {
31264
31265
31266 if (face->box_horizontal_line_width > 0)
31267 {
31268 if (slice.y == 0)
31269 it->ascent += face->box_horizontal_line_width;
31270 if (slice.y + slice.height == img->height)
31271 it->descent += face->box_horizontal_line_width;
31272 }
31273
31274 if (face->box_vertical_line_width > 0)
31275 {
31276 if (it->start_of_box_run_p && slice.x == 0)
31277 it->pixel_width += face->box_vertical_line_width;
31278 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
31279 it->pixel_width += face->box_vertical_line_width;
31280 }
31281 }
31282
31283 take_vertical_position_into_account (it);
31284
31285
31286
31287 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
31288 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31289 {
31290 it->pixel_width -= crop;
31291 slice.width -= crop;
31292 }
31293
31294 if (it->glyph_row)
31295 {
31296 struct glyph *glyph;
31297 enum glyph_row_area area = it->area;
31298
31299 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31300 if (it->glyph_row->reversed_p)
31301 {
31302 struct glyph *g;
31303
31304
31305 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31306 g[1] = *g;
31307 glyph = it->glyph_row->glyphs[it->area];
31308 }
31309 if (glyph < it->glyph_row->glyphs[area + 1])
31310 {
31311 glyph->charpos = CHARPOS (it->position);
31312 glyph->object = it->object;
31313 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31314 glyph->ascent = glyph_ascent;
31315 glyph->descent = it->descent;
31316 glyph->voffset = it->voffset;
31317 glyph->type = IMAGE_GLYPH;
31318 glyph->avoid_cursor_p = it->avoid_cursor_p;
31319 glyph->multibyte_p = it->multibyte_p;
31320 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31321 {
31322
31323
31324 glyph->right_box_line_p = it->start_of_box_run_p;
31325 glyph->left_box_line_p = it->end_of_box_run_p;
31326 }
31327 else
31328 {
31329 glyph->left_box_line_p = it->start_of_box_run_p;
31330 glyph->right_box_line_p = it->end_of_box_run_p;
31331 }
31332 glyph->overlaps_vertically_p = false;
31333 glyph->padding_p = false;
31334 glyph->glyph_not_available_p = false;
31335 glyph->face_id = it->face_id;
31336 glyph->u.img_id = img->id;
31337 glyph->slice.img = slice;
31338 glyph->font_type = FONT_TYPE_UNKNOWN;
31339 if (it->bidi_p)
31340 {
31341 glyph->resolved_level = it->bidi_it.resolved_level;
31342 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31343 glyph->bidi_type = it->bidi_it.type;
31344 }
31345 ++it->glyph_row->used[area];
31346 }
31347 else
31348 IT_EXPAND_MATRIX_WIDTH (it, area);
31349 }
31350 }
31351
31352 static void
31353 produce_xwidget_glyph (struct it *it)
31354 {
31355 #ifdef HAVE_XWIDGETS
31356 struct xwidget *xw;
31357 int glyph_ascent, crop;
31358 eassert (it->what == IT_XWIDGET);
31359
31360 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31361
31362 prepare_face_for_display (it->f, face);
31363
31364 xw = it->xwidget;
31365 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31366 it->descent = xw->height/2;
31367 it->phys_descent = it->descent;
31368 it->pixel_width = xw->width;
31369
31370
31371 if (it->descent < 0)
31372 it->descent = 0;
31373
31374 it->nglyphs = 1;
31375
31376 if (face->box != FACE_NO_BOX)
31377 {
31378 if (face->box_horizontal_line_width > 0)
31379 {
31380 it->ascent += face->box_horizontal_line_width;
31381 it->descent += face->box_horizontal_line_width;
31382 }
31383
31384 if (face->box_vertical_line_width > 0)
31385 {
31386 if (it->start_of_box_run_p)
31387 it->pixel_width += face->box_vertical_line_width;
31388 it->pixel_width += face->box_vertical_line_width;
31389 }
31390 }
31391
31392 take_vertical_position_into_account (it);
31393
31394
31395
31396 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31397 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31398 it->pixel_width -= crop;
31399
31400 if (it->glyph_row)
31401 {
31402 enum glyph_row_area area = it->area;
31403 struct glyph *glyph
31404 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31405
31406 if (it->glyph_row->reversed_p)
31407 {
31408 struct glyph *g;
31409
31410
31411 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31412 g[1] = *g;
31413 glyph = it->glyph_row->glyphs[it->area];
31414 }
31415 if (glyph < it->glyph_row->glyphs[area + 1])
31416 {
31417 glyph->charpos = CHARPOS (it->position);
31418 glyph->object = it->object;
31419 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31420 glyph->ascent = glyph_ascent;
31421 glyph->descent = it->descent;
31422 glyph->voffset = it->voffset;
31423 glyph->type = XWIDGET_GLYPH;
31424 glyph->avoid_cursor_p = it->avoid_cursor_p;
31425 glyph->multibyte_p = it->multibyte_p;
31426 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31427 {
31428
31429
31430 glyph->right_box_line_p = it->start_of_box_run_p;
31431 glyph->left_box_line_p = it->end_of_box_run_p;
31432 }
31433 else
31434 {
31435 glyph->left_box_line_p = it->start_of_box_run_p;
31436 glyph->right_box_line_p = it->end_of_box_run_p;
31437 }
31438 glyph->overlaps_vertically_p = 0;
31439 glyph->padding_p = 0;
31440 glyph->glyph_not_available_p = 0;
31441 glyph->face_id = it->face_id;
31442 glyph->u.xwidget = it->xwidget->xwidget_id;
31443 glyph->font_type = FONT_TYPE_UNKNOWN;
31444 if (it->bidi_p)
31445 {
31446 glyph->resolved_level = it->bidi_it.resolved_level;
31447 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31448 glyph->bidi_type = it->bidi_it.type;
31449 }
31450 ++it->glyph_row->used[area];
31451 }
31452 else
31453 IT_EXPAND_MATRIX_WIDTH (it, area);
31454 }
31455 #endif
31456 }
31457
31458
31459
31460
31461
31462 static void
31463 append_stretch_glyph (struct it *it, Lisp_Object object,
31464 int width, int height, int ascent)
31465 {
31466 struct glyph *glyph;
31467 enum glyph_row_area area = it->area;
31468
31469 eassert (ascent >= 0 && ascent <= height);
31470
31471 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31472 if (glyph < it->glyph_row->glyphs[area + 1])
31473 {
31474
31475
31476 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31477 {
31478 struct glyph *g;
31479
31480
31481 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31482 g[1] = *g;
31483 glyph = it->glyph_row->glyphs[area];
31484
31485
31486
31487
31488
31489
31490
31491
31492
31493
31494
31495
31496
31497
31498
31499 if (it->current_x < it->first_visible_x)
31500 width -= it->first_visible_x - it->current_x;
31501 eassert (width > 0);
31502 }
31503 glyph->charpos = CHARPOS (it->position);
31504 glyph->object = object;
31505
31506
31507 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31508 glyph->ascent = ascent;
31509 glyph->descent = height - ascent;
31510 glyph->voffset = it->voffset;
31511 glyph->type = STRETCH_GLYPH;
31512 glyph->avoid_cursor_p = it->avoid_cursor_p;
31513 glyph->multibyte_p = it->multibyte_p;
31514 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31515 {
31516
31517
31518 glyph->right_box_line_p = it->start_of_box_run_p;
31519 glyph->left_box_line_p = it->end_of_box_run_p;
31520 }
31521 else
31522 {
31523 glyph->left_box_line_p = it->start_of_box_run_p;
31524 glyph->right_box_line_p = it->end_of_box_run_p;
31525 }
31526 glyph->overlaps_vertically_p = false;
31527 glyph->padding_p = false;
31528 glyph->glyph_not_available_p = false;
31529 glyph->face_id = it->face_id;
31530 glyph->u.stretch.ascent = ascent;
31531 glyph->u.stretch.height = height;
31532 glyph->slice.img = null_glyph_slice;
31533 glyph->font_type = FONT_TYPE_UNKNOWN;
31534 if (it->bidi_p)
31535 {
31536 glyph->resolved_level = it->bidi_it.resolved_level;
31537 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31538 glyph->bidi_type = it->bidi_it.type;
31539 }
31540 else
31541 {
31542 glyph->resolved_level = 0;
31543 glyph->bidi_type = UNKNOWN_BT;
31544 }
31545 ++it->glyph_row->used[area];
31546 }
31547 else
31548 IT_EXPAND_MATRIX_WIDTH (it, area);
31549 }
31550
31551 #endif
31552
31553
31554
31555
31556
31557
31558
31559
31560
31561
31562
31563
31564
31565
31566
31567
31568
31569
31570
31571
31572
31573
31574
31575
31576
31577
31578
31579
31580
31581
31582
31583
31584 void
31585 produce_stretch_glyph (struct it *it)
31586 {
31587
31588 Lisp_Object prop, plist;
31589 int width = 0, height = 0, align_to = -1;
31590 bool zero_width_ok_p = false;
31591 double tem;
31592 struct font *font = NULL;
31593
31594 #ifdef HAVE_WINDOW_SYSTEM
31595 int ascent = 0;
31596 bool zero_height_ok_p = false;
31597 struct face *face = NULL;
31598
31599 if (FRAME_WINDOW_P (it->f))
31600 {
31601 face = FACE_FROM_ID (it->f, it->face_id);
31602 font = face->font ? face->font : FRAME_FONT (it->f);
31603 prepare_face_for_display (it->f, face);
31604 }
31605 #endif
31606
31607
31608 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31609 plist = XCDR (it->object);
31610
31611
31612 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31613 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31614 {
31615
31616 zero_width_ok_p = true;
31617 width = (int)tem;
31618 }
31619 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31620 {
31621
31622
31623
31624 struct it it2;
31625 Lisp_Object object =
31626 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31627 unsigned char *p = (STRINGP (object)
31628 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31629 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31630 bool multibyte_p =
31631 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31632
31633 it2 = *it;
31634 if (multibyte_p)
31635 {
31636 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31637 #ifdef HAVE_WINDOW_SYSTEM
31638 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31639 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31640 IT_CHARPOS (*it),
31641 STRINGP (object)? object : Qnil);
31642 #endif
31643 }
31644 else
31645 {
31646 it2.c = it2.char_to_display = *p, it2.len = 1;
31647 if (! ASCII_CHAR_P (it2.c))
31648 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31649 }
31650
31651 it2.glyph_row = NULL;
31652 it2.what = IT_CHARACTER;
31653 PRODUCE_GLYPHS (&it2);
31654 width = NUMVAL (prop) * it2.pixel_width;
31655 }
31656 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31657 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31658 &align_to))
31659 {
31660 int x = it->current_x + it->continuation_lines_width;
31661 int x0 = x;
31662
31663 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31664 {
31665 x -= it->lnum_pixel_width;
31666
31667 if (x + it->stretch_adjust >= it->first_visible_x)
31668 x += it->stretch_adjust;
31669 }
31670
31671 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31672 align_to = (align_to < 0
31673 ? 0
31674 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31675 else if (align_to < 0)
31676 align_to = window_box_left_offset (it->w, TEXT_AREA);
31677 width = max (0, (int)tem + align_to - x);
31678
31679 int next_x = x + width;
31680 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31681 {
31682
31683
31684 if (x < it->first_visible_x)
31685 {
31686 next_x -= it->first_visible_x - x;
31687 it->stretch_adjust = it->first_visible_x - x;
31688 }
31689 else
31690 next_x -= it->stretch_adjust;
31691 }
31692 width = next_x - x0;
31693 zero_width_ok_p = true;
31694 }
31695 else
31696
31697 width = FRAME_COLUMN_WIDTH (it->f);
31698
31699 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31700 width = 1;
31701
31702 #ifdef HAVE_WINDOW_SYSTEM
31703
31704 if (FRAME_WINDOW_P (it->f))
31705 {
31706 int default_height = normal_char_height (font, ' ');
31707
31708 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31709 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31710 {
31711 height = (int)tem;
31712 zero_height_ok_p = true;
31713 }
31714 else if (prop = plist_get (plist, QCrelative_height),
31715 NUMVAL (prop) > 0)
31716 height = default_height * NUMVAL (prop);
31717 else
31718 height = default_height;
31719
31720 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31721 height = 1;
31722
31723
31724
31725
31726 if (prop = plist_get (plist, QCascent),
31727 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31728 ascent = height * NUMVAL (prop) / 100.0;
31729 else if (!NILP (prop)
31730 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31731 ascent = min (max (0, (int)tem), height);
31732 else
31733 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31734 }
31735 else
31736 #endif
31737 height = 1;
31738
31739 if (width > 0
31740 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31741 && it->current_x + width > it->last_visible_x)
31742 {
31743 width = it->last_visible_x - it->current_x;
31744 #ifdef HAVE_WINDOW_SYSTEM
31745
31746
31747 width -= FRAME_WINDOW_P (it->f);
31748 #endif
31749 }
31750
31751 if (width > 0 && height > 0 && it->glyph_row)
31752 {
31753 Lisp_Object o_object = it->object;
31754 Lisp_Object object =
31755 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31756 int n = width;
31757
31758 if (!STRINGP (object))
31759 object = it->w->contents;
31760 #ifdef HAVE_WINDOW_SYSTEM
31761 if (FRAME_WINDOW_P (it->f))
31762 append_stretch_glyph (it, object, width, height, ascent);
31763 else
31764 #endif
31765 {
31766 it->object = object;
31767 it->char_to_display = ' ';
31768 it->pixel_width = it->len = 1;
31769 while (n--)
31770 tty_append_glyph (it);
31771 it->object = o_object;
31772 }
31773 }
31774
31775 it->pixel_width = width;
31776 #ifdef HAVE_WINDOW_SYSTEM
31777 if (FRAME_WINDOW_P (it->f))
31778 {
31779 it->ascent = it->phys_ascent = ascent;
31780 it->descent = it->phys_descent = height - it->ascent;
31781 it->nglyphs = width > 0 && height > 0;
31782 take_vertical_position_into_account (it);
31783 }
31784 else
31785 #endif
31786 it->nglyphs = width;
31787 }
31788
31789
31790
31791
31792
31793
31794
31795 static void
31796 produce_special_glyphs (struct it *it, enum display_element_type what)
31797 {
31798 struct it temp_it;
31799 Lisp_Object gc;
31800 GLYPH glyph;
31801
31802 temp_it = *it;
31803 temp_it.object = Qnil;
31804 memset (&temp_it.current, 0, sizeof temp_it.current);
31805
31806 if (what == IT_CONTINUATION)
31807 {
31808
31809 if (it->bidi_it.paragraph_dir == R2L)
31810 SET_GLYPH_FROM_CHAR (glyph, '/');
31811 else
31812 SET_GLYPH_FROM_CHAR (glyph, '\\');
31813 if (it->dp
31814 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31815 {
31816
31817 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31818 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31819 }
31820 }
31821 else if (what == IT_TRUNCATION)
31822 {
31823
31824 SET_GLYPH_FROM_CHAR (glyph, '$');
31825 if (it->dp
31826 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31827 {
31828
31829 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31830 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31831 }
31832 }
31833 else
31834 emacs_abort ();
31835
31836 #ifdef HAVE_WINDOW_SYSTEM
31837
31838
31839
31840
31841
31842 if (FRAME_WINDOW_P (temp_it.f)
31843
31844
31845
31846 && temp_it.glyph_row
31847
31848
31849
31850 && temp_it.glyph_row->used[TEXT_AREA] > 0
31851 && (temp_it.glyph_row->reversed_p
31852 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31853 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31854 {
31855 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31856
31857 if (stretch_width > 0)
31858 {
31859 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31860 struct font *font =
31861 face->font ? face->font : FRAME_FONT (temp_it.f);
31862 int stretch_ascent =
31863 (((temp_it.ascent + temp_it.descent)
31864 * FONT_BASE (font)) / FONT_HEIGHT (font));
31865
31866 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31867 temp_it.ascent + temp_it.descent,
31868 stretch_ascent);
31869 }
31870 }
31871 #endif
31872
31873 temp_it.dp = NULL;
31874 temp_it.what = IT_CHARACTER;
31875 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31876 temp_it.face_id = GLYPH_FACE (glyph);
31877 temp_it.len = CHAR_BYTES (temp_it.c);
31878
31879 PRODUCE_GLYPHS (&temp_it);
31880 it->pixel_width = temp_it.pixel_width;
31881 it->nglyphs = temp_it.nglyphs;
31882 }
31883
31884
31885
31886
31887
31888
31889
31890
31891
31892 static void
31893 pad_mode_line (struct it *it, bool mode_line_p)
31894 {
31895 struct it temp_it;
31896 GLYPH glyph;
31897
31898 eassert (!FRAME_WINDOW_P (it->f));
31899 temp_it = *it;
31900 temp_it.object = Qnil;
31901 memset (&temp_it.current, 0, sizeof temp_it.current);
31902
31903 SET_GLYPH (glyph, mode_line_p ? '-' : ' ', it->base_face_id);
31904
31905 temp_it.dp = NULL;
31906 temp_it.what = IT_CHARACTER;
31907 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31908 temp_it.face_id = GLYPH_FACE (glyph);
31909 temp_it.len = CHAR_BYTES (temp_it.c);
31910
31911 PRODUCE_GLYPHS (&temp_it);
31912 it->pixel_width = temp_it.pixel_width;
31913 it->nglyphs = temp_it.nglyphs;
31914 }
31915
31916 #ifdef HAVE_WINDOW_SYSTEM
31917
31918
31919
31920
31921
31922
31923
31924
31925
31926 static Lisp_Object
31927 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31928 int boff, bool override)
31929 {
31930 Lisp_Object face_name = Qnil;
31931 int ascent, descent, height;
31932
31933 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31934 return val;
31935
31936 if (CONSP (val))
31937 {
31938 face_name = XCAR (val);
31939 val = XCDR (val);
31940 if (!NUMBERP (val))
31941 val = make_fixnum (1);
31942 if (NILP (face_name))
31943 {
31944 height = it->ascent + it->descent;
31945 goto scale;
31946 }
31947 }
31948
31949 if (NILP (face_name))
31950 {
31951 font = FRAME_FONT (it->f);
31952 boff = FRAME_BASELINE_OFFSET (it->f);
31953 }
31954 else if (EQ (face_name, Qt))
31955 {
31956 override = false;
31957 }
31958 else
31959 {
31960 int face_id;
31961 struct face *face;
31962
31963 face_id = lookup_named_face (it->w, it->f, face_name, false);
31964 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31965 if (face == NULL || ((font = face->font) == NULL))
31966 return make_fixnum (-1);
31967 boff = font->baseline_offset;
31968 if (font->vertical_centering)
31969 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31970 }
31971
31972 normal_char_ascent_descent (font, -1, &ascent, &descent);
31973
31974 if (override)
31975 {
31976 it->override_ascent = ascent;
31977 it->override_descent = descent;
31978 it->override_boff = boff;
31979 }
31980
31981 height = ascent + descent;
31982
31983 scale:
31984
31985 if (FLOATP (val))
31986 height = (int)(XFLOAT_DATA (val) * height);
31987 else if (INTEGERP (val))
31988 {
31989 intmax_t v;
31990 if (integer_to_intmax (val, &v))
31991 height *= v;
31992 }
31993
31994 return make_fixnum (height);
31995 }
31996
31997
31998
31999
32000
32001
32002
32003
32004
32005
32006
32007
32008
32009
32010 static void
32011 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
32012 short upper_xoff, short upper_yoff,
32013 short lower_xoff, short lower_yoff)
32014 {
32015 struct glyph *glyph;
32016 enum glyph_row_area area = it->area;
32017
32018 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
32019 if (glyph < it->glyph_row->glyphs[area + 1])
32020 {
32021
32022
32023 if (it->glyph_row->reversed_p && area == TEXT_AREA)
32024 {
32025 struct glyph *g;
32026
32027
32028 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
32029 g[1] = *g;
32030 glyph = it->glyph_row->glyphs[area];
32031 }
32032 glyph->charpos = CHARPOS (it->position);
32033 glyph->object = it->object;
32034 eassert (it->pixel_width <= SHRT_MAX);
32035 glyph->pixel_width = it->pixel_width;
32036 glyph->ascent = it->ascent;
32037 glyph->descent = it->descent;
32038 glyph->voffset = it->voffset;
32039 glyph->type = GLYPHLESS_GLYPH;
32040 glyph->u.glyphless.method = it->glyphless_method;
32041 glyph->u.glyphless.for_no_font = for_no_font;
32042 glyph->u.glyphless.len = len;
32043 glyph->u.glyphless.ch = it->c;
32044 glyph->slice.glyphless.upper_xoff = upper_xoff;
32045 glyph->slice.glyphless.upper_yoff = upper_yoff;
32046 glyph->slice.glyphless.lower_xoff = lower_xoff;
32047 glyph->slice.glyphless.lower_yoff = lower_yoff;
32048 glyph->avoid_cursor_p = it->avoid_cursor_p;
32049 glyph->multibyte_p = it->multibyte_p;
32050 if (it->glyph_row->reversed_p && area == TEXT_AREA)
32051 {
32052
32053
32054 glyph->right_box_line_p = it->start_of_box_run_p;
32055 glyph->left_box_line_p = it->end_of_box_run_p;
32056 }
32057 else
32058 {
32059 glyph->left_box_line_p = it->start_of_box_run_p;
32060 glyph->right_box_line_p = it->end_of_box_run_p;
32061 }
32062 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
32063 || it->phys_descent > it->descent);
32064 glyph->padding_p = false;
32065 glyph->glyph_not_available_p = false;
32066 glyph->face_id = face_id;
32067 glyph->font_type = FONT_TYPE_UNKNOWN;
32068 if (it->bidi_p)
32069 {
32070 glyph->resolved_level = it->bidi_it.resolved_level;
32071 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
32072 glyph->bidi_type = it->bidi_it.type;
32073 }
32074 ++it->glyph_row->used[area];
32075 }
32076 else
32077 IT_EXPAND_MATRIX_WIDTH (it, area);
32078 }
32079
32080
32081
32082
32083
32084
32085
32086
32087
32088
32089
32090 static void
32091 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
32092 {
32093 int face_id;
32094 struct face *face;
32095 struct font *font;
32096 int base_width, base_height, width, height;
32097 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
32098 int len;
32099
32100
32101
32102 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
32103 font = face->font ? face->font : FRAME_FONT (it->f);
32104 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
32105 it->ascent += font->baseline_offset;
32106 it->descent -= font->baseline_offset;
32107 base_height = it->ascent + it->descent;
32108 base_width = font->average_width;
32109
32110 face_id = merge_glyphless_glyph_face (it);
32111
32112 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
32113 {
32114 it->pixel_width = THIN_SPACE_WIDTH;
32115 len = 0;
32116 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32117 }
32118 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
32119 {
32120 width = CHARACTER_WIDTH (it->c);
32121 if (width == 0)
32122 width = 1;
32123 else if (width > 4)
32124 width = 4;
32125 it->pixel_width = base_width * width;
32126 len = 0;
32127 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32128 }
32129 else
32130 {
32131 char buf[7];
32132 const char *str;
32133 unsigned int code[6];
32134 int upper_len;
32135 int ascent, descent;
32136 struct font_metrics metrics_upper, metrics_lower;
32137
32138 face = FACE_FROM_ID (it->f, face_id);
32139 font = face->font ? face->font : FRAME_FONT (it->f);
32140 prepare_face_for_display (it->f, face);
32141
32142 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
32143 {
32144 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
32145 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
32146 if (CONSP (acronym))
32147 acronym = XCAR (acronym);
32148 str = STRINGP (acronym) ? SSDATA (acronym) : "";
32149 }
32150 else
32151 {
32152 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
32153 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
32154 str = buf;
32155 }
32156 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
32157 code[len] = font->driver->encode_char (font, str[len]);
32158 upper_len = (len + 1) / 2;
32159 font->driver->text_extents (font, code, upper_len,
32160 &metrics_upper);
32161 font->driver->text_extents (font, code + upper_len, len - upper_len,
32162 &metrics_lower);
32163
32164
32165
32166
32167 width = max (metrics_upper.width, metrics_lower.width) + 4;
32168 upper_xoff = lower_xoff = 2;
32169 if (base_width >= width)
32170 {
32171
32172 it->pixel_width = base_width;
32173 lower_xoff = base_width - 2 - metrics_lower.width;
32174 }
32175 else
32176 {
32177
32178 it->pixel_width = width;
32179 if (metrics_upper.width >= metrics_lower.width)
32180 lower_xoff = (width - metrics_lower.width) / 2;
32181 else
32182 upper_xoff = (width - metrics_upper.width) / 2;
32183 }
32184
32185
32186
32187 height = (metrics_upper.ascent + metrics_upper.descent
32188 + metrics_lower.ascent + metrics_lower.descent) + 5;
32189
32190
32191
32192
32193
32194
32195
32196
32197 ascent = - (it->descent - (base_height + height + 1) / 2);
32198 descent = it->descent - (base_height - height) / 2;
32199 lower_yoff = descent - 2 - metrics_lower.descent;
32200 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
32201 - metrics_upper.descent);
32202
32203 if (height > base_height)
32204 {
32205 it->ascent = ascent;
32206 it->descent = descent;
32207 }
32208 }
32209
32210 it->phys_ascent = it->ascent;
32211 it->phys_descent = it->descent;
32212 if (it->glyph_row)
32213 append_glyphless_glyph (it, face_id, for_no_font, len,
32214 upper_xoff, upper_yoff,
32215 lower_xoff, lower_yoff);
32216 it->nglyphs = 1;
32217 take_vertical_position_into_account (it);
32218 }
32219
32220
32221
32222
32223
32224 #define IT_APPLY_FACE_BOX(it, face) \
32225 do { \
32226 if (face->box != FACE_NO_BOX) \
32227 { \
32228 int thick = face->box_horizontal_line_width; \
32229 if (thick > 0) \
32230 { \
32231 it->ascent += thick; \
32232 it->descent += thick; \
32233 } \
32234 \
32235 thick = face->box_vertical_line_width; \
32236 if (thick > 0) \
32237 { \
32238 if (it->start_of_box_run_p) \
32239 it->pixel_width += thick; \
32240 if (it->end_of_box_run_p) \
32241 it->pixel_width += thick; \
32242 } \
32243 } \
32244 } while (false)
32245
32246
32247
32248
32249
32250
32251 void
32252 gui_produce_glyphs (struct it *it)
32253 {
32254 int extra_line_spacing = it->extra_line_spacing;
32255
32256 it->glyph_not_available_p = false;
32257
32258 if (it->what == IT_CHARACTER)
32259 {
32260 unsigned char2b;
32261 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32262 struct font *font = face->font;
32263 struct font_metrics *pcm = NULL;
32264 int boff;
32265
32266 if (font == NULL)
32267 {
32268
32269
32270
32271 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
32272
32273 eassert (it->what == IT_GLYPHLESS);
32274 produce_glyphless_glyph (it, true,
32275 STRINGP (acronym) ? acronym : Qnil);
32276 goto done;
32277 }
32278
32279 boff = font->baseline_offset;
32280 if (font->vertical_centering)
32281 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32282
32283 if (it->char_to_display != '\n' && it->char_to_display != '\t')
32284 {
32285 it->nglyphs = 1;
32286
32287 if (it->override_ascent >= 0)
32288 {
32289 it->ascent = it->override_ascent;
32290 it->descent = it->override_descent;
32291 boff = it->override_boff;
32292 }
32293 else
32294 {
32295 it->ascent = FONT_BASE (font) + boff;
32296 it->descent = FONT_DESCENT (font) - boff;
32297 }
32298
32299 if (get_char_glyph_code (it->char_to_display, font, &char2b))
32300 {
32301 pcm = get_per_char_metric (font, &char2b);
32302 if (pcm->width == 0
32303 && pcm->rbearing == 0 && pcm->lbearing == 0)
32304 pcm = NULL;
32305 }
32306
32307 if (pcm)
32308 {
32309 it->phys_ascent = pcm->ascent + boff;
32310 it->phys_descent = pcm->descent - boff;
32311 it->pixel_width = pcm->width;
32312
32313
32314 if (it->override_ascent < 0)
32315 {
32316 if (FONT_TOO_HIGH (font))
32317 {
32318 it->ascent = it->phys_ascent;
32319 it->descent = it->phys_descent;
32320
32321
32322 if (it->ascent < 0)
32323 it->ascent = 0;
32324 if (it->descent < 0)
32325 it->descent = 0;
32326 }
32327 }
32328 }
32329 else
32330 {
32331 it->glyph_not_available_p = true;
32332 it->phys_ascent = it->ascent;
32333 it->phys_descent = it->descent;
32334 it->pixel_width = font->space_width;
32335 }
32336
32337 if (it->constrain_row_ascent_descent_p)
32338 {
32339 if (it->descent > it->max_descent)
32340 {
32341 it->ascent += it->descent - it->max_descent;
32342 it->descent = it->max_descent;
32343 }
32344 if (it->ascent > it->max_ascent)
32345 {
32346 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32347 it->ascent = it->max_ascent;
32348 }
32349 it->phys_ascent = min (it->phys_ascent, it->ascent);
32350 it->phys_descent = min (it->phys_descent, it->descent);
32351 extra_line_spacing = 0;
32352 }
32353
32354
32355
32356 bool stretched_p
32357 = it->char_to_display == ' ' && !NILP (it->space_width);
32358 if (stretched_p)
32359 it->pixel_width *= XFLOATINT (it->space_width);
32360
32361 IT_APPLY_FACE_BOX(it, face);
32362
32363
32364
32365 if (face->overline_p)
32366 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32367
32368 if (it->constrain_row_ascent_descent_p)
32369 {
32370 if (it->ascent > it->max_ascent)
32371 it->ascent = it->max_ascent;
32372 if (it->descent > it->max_descent)
32373 it->descent = it->max_descent;
32374 }
32375
32376 take_vertical_position_into_account (it);
32377
32378
32379 if (it->glyph_row)
32380 {
32381 if (stretched_p)
32382 {
32383
32384
32385 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32386 / FONT_HEIGHT (font));
32387 append_stretch_glyph (it, it->object, it->pixel_width,
32388 it->ascent + it->descent, ascent);
32389 }
32390 else
32391 append_glyph (it);
32392
32393
32394
32395
32396 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32397 it->glyph_row->contains_overlapping_glyphs_p = true;
32398 }
32399 if (! stretched_p && it->pixel_width == 0)
32400
32401
32402 it->pixel_width = 1;
32403 }
32404 else if (it->char_to_display == '\n')
32405 {
32406
32407
32408
32409
32410 Lisp_Object height;
32411 Lisp_Object total_height = Qnil;
32412
32413 it->override_ascent = -1;
32414 it->pixel_width = 0;
32415 it->nglyphs = 0;
32416
32417 height = get_it_property (it, Qline_height);
32418
32419 if (CONSP (height)
32420 && CONSP (XCDR (height))
32421 && NILP (XCDR (XCDR (height))))
32422 {
32423 total_height = XCAR (XCDR (height));
32424 height = XCAR (height);
32425 }
32426 height = calc_line_height_property (it, height, font, boff, true);
32427
32428 if (it->override_ascent >= 0)
32429 {
32430 it->ascent = it->override_ascent;
32431 it->descent = it->override_descent;
32432 boff = it->override_boff;
32433 }
32434 else
32435 {
32436 if (FONT_TOO_HIGH (font))
32437 {
32438 it->ascent = font->pixel_size + boff - 1;
32439 it->descent = -boff + 1;
32440 if (it->descent < 0)
32441 it->descent = 0;
32442 }
32443 else
32444 {
32445 it->ascent = FONT_BASE (font) + boff;
32446 it->descent = FONT_DESCENT (font) - boff;
32447 }
32448 }
32449
32450 if (EQ (height, Qt))
32451 {
32452 if (it->descent > it->max_descent)
32453 {
32454 it->ascent += it->descent - it->max_descent;
32455 it->descent = it->max_descent;
32456 }
32457 if (it->ascent > it->max_ascent)
32458 {
32459 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32460 it->ascent = it->max_ascent;
32461 }
32462 it->phys_ascent = min (it->phys_ascent, it->ascent);
32463 it->phys_descent = min (it->phys_descent, it->descent);
32464 it->constrain_row_ascent_descent_p = true;
32465 extra_line_spacing = 0;
32466 }
32467 else
32468 {
32469 Lisp_Object spacing;
32470
32471 it->phys_ascent = it->ascent;
32472 it->phys_descent = it->descent;
32473
32474 if ((it->max_ascent > 0 || it->max_descent > 0)
32475 && face->box != FACE_NO_BOX
32476 && face->box_horizontal_line_width > 0)
32477 {
32478 it->ascent += face->box_horizontal_line_width;
32479 it->descent += face->box_horizontal_line_width;
32480 }
32481 if (!NILP (height)
32482 && XFIXNUM (height) > it->ascent + it->descent)
32483 it->ascent = XFIXNUM (height) - it->descent;
32484
32485 if (!NILP (total_height))
32486 spacing = calc_line_height_property (it, total_height, font,
32487 boff, false);
32488 else
32489 {
32490 spacing = get_it_property (it, Qline_spacing);
32491 spacing = calc_line_height_property (it, spacing, font,
32492 boff, false);
32493 }
32494 if (FIXNUMP (spacing))
32495 {
32496 extra_line_spacing = XFIXNUM (spacing);
32497 if (!NILP (total_height))
32498 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32499 }
32500 }
32501 }
32502 else
32503 {
32504 if (font->space_width > 0)
32505 {
32506 int tab_width = it->tab_width * font->space_width;
32507 int x = it->current_x + it->continuation_lines_width;
32508 int x0 = x;
32509
32510 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32511 {
32512 x -= it->lnum_pixel_width;
32513
32514 if (x + it->stretch_adjust >= it->first_visible_x)
32515 x += it->stretch_adjust;
32516 }
32517
32518 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32519
32520
32521
32522
32523 if (next_tab_x - x < font->space_width)
32524 next_tab_x += tab_width;
32525 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32526 {
32527 next_tab_x += it->lnum_pixel_width;
32528
32529
32530 if (x < it->first_visible_x)
32531 {
32532 next_tab_x -= it->first_visible_x - x;
32533 it->stretch_adjust = it->first_visible_x - x;
32534 }
32535 else
32536 next_tab_x -= it->stretch_adjust;
32537 }
32538
32539 it->pixel_width = next_tab_x - x0;
32540 it->nglyphs = 1;
32541 if (FONT_TOO_HIGH (font))
32542 {
32543 if (get_char_glyph_code (' ', font, &char2b))
32544 {
32545 pcm = get_per_char_metric (font, &char2b);
32546 if (pcm->width == 0
32547 && pcm->rbearing == 0 && pcm->lbearing == 0)
32548 pcm = NULL;
32549 }
32550
32551 if (pcm)
32552 {
32553 it->ascent = pcm->ascent + boff;
32554 it->descent = pcm->descent - boff;
32555 }
32556 else
32557 {
32558 it->ascent = font->pixel_size + boff - 1;
32559 it->descent = -boff + 1;
32560 }
32561 if (it->ascent < 0)
32562 it->ascent = 0;
32563 if (it->descent < 0)
32564 it->descent = 0;
32565 }
32566 else
32567 {
32568 it->ascent = FONT_BASE (font) + boff;
32569 it->descent = FONT_DESCENT (font) - boff;
32570 }
32571 it->phys_ascent = it->ascent;
32572 it->phys_descent = it->descent;
32573
32574 if (it->glyph_row)
32575 {
32576 append_stretch_glyph (it, it->object, it->pixel_width,
32577 it->ascent + it->descent, it->ascent);
32578 }
32579 }
32580 else
32581 {
32582 it->pixel_width = 0;
32583 it->nglyphs = 1;
32584 }
32585 }
32586
32587 if (FONT_TOO_HIGH (font))
32588 {
32589 int font_ascent, font_descent;
32590
32591
32592
32593
32594
32595
32596
32597
32598 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32599 it->max_ascent = max (it->max_ascent, font_ascent);
32600 it->max_descent = max (it->max_descent, font_descent);
32601 }
32602
32603 if (it->ascent < 0)
32604 it->ascent = 0;
32605 if (it->descent < 0)
32606 it->descent = 0;
32607 }
32608 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32609 {
32610
32611
32612
32613
32614
32615
32616
32617
32618 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32619 int boff;
32620 struct composition *cmp = composition_table[it->cmp_it.id];
32621 int glyph_len = cmp->glyph_len;
32622 struct font *font = face->font;
32623
32624 it->nglyphs = 1;
32625
32626
32627
32628
32629
32630
32631
32632
32633 if (! cmp->font || cmp->font != font)
32634 {
32635
32636
32637
32638
32639 int font_ascent, font_descent, font_height;
32640
32641 int leftmost, rightmost, lowest, highest;
32642 int lbearing, rbearing;
32643 int i, width, ascent, descent;
32644 int c;
32645 unsigned char2b;
32646 struct font_metrics *pcm;
32647 ptrdiff_t pos;
32648
32649 eassume (0 < glyph_len);
32650 do
32651 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32652 while (c == '\t' && 0 < --glyph_len);
32653
32654 bool right_padded = glyph_len < cmp->glyph_len;
32655 for (i = 0; i < glyph_len; i++)
32656 {
32657 c = COMPOSITION_GLYPH (cmp, i);
32658 if (c != '\t')
32659 break;
32660 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32661 }
32662 bool left_padded = i > 0;
32663
32664 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32665 : IT_CHARPOS (*it));
32666
32667 bool font_not_found_p = font == NULL;
32668 if (font_not_found_p)
32669 {
32670 face = face->ascii_face;
32671 font = face->font;
32672 }
32673 boff = font->baseline_offset;
32674 if (font->vertical_centering)
32675 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32676 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32677 font_ascent += boff;
32678 font_descent -= boff;
32679 font_height = font_ascent + font_descent;
32680
32681 cmp->font = font;
32682
32683 pcm = NULL;
32684 if (! font_not_found_p)
32685 {
32686 get_char_face_and_encoding (it->f, c, it->face_id,
32687 &char2b, false);
32688 pcm = get_per_char_metric (font, &char2b);
32689 }
32690
32691
32692 if (pcm)
32693 {
32694 width = cmp->glyph_len > 0 ? pcm->width : 0;
32695 ascent = pcm->ascent;
32696 descent = pcm->descent;
32697 lbearing = pcm->lbearing;
32698 rbearing = pcm->rbearing;
32699 }
32700 else
32701 {
32702 width = cmp->glyph_len > 0 ? font->space_width : 0;
32703 ascent = FONT_BASE (font);
32704 descent = FONT_DESCENT (font);
32705 lbearing = 0;
32706 rbearing = width;
32707 }
32708
32709 rightmost = width;
32710 leftmost = 0;
32711 lowest = - descent + boff;
32712 highest = ascent + boff;
32713
32714 if (! font_not_found_p
32715 && font->default_ascent
32716 && CHAR_TABLE_P (Vuse_default_ascent)
32717 && !NILP (Faref (Vuse_default_ascent,
32718 make_fixnum (it->char_to_display))))
32719 highest = font->default_ascent + boff;
32720
32721
32722
32723
32724 cmp->offsets[i * 2] = 0;
32725 cmp->offsets[i * 2 + 1] = boff;
32726 cmp->lbearing = lbearing;
32727 cmp->rbearing = rbearing;
32728
32729
32730 for (i++; i < glyph_len; i++)
32731 {
32732 int left, right, btm, top;
32733 int ch = COMPOSITION_GLYPH (cmp, i);
32734 int face_id;
32735 struct face *this_face;
32736
32737 if (ch == '\t')
32738 ch = ' ';
32739 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32740 this_face = FACE_FROM_ID (it->f, face_id);
32741 font = this_face->font;
32742
32743 if (font == NULL)
32744 pcm = NULL;
32745 else
32746 {
32747 get_char_face_and_encoding (it->f, ch, face_id,
32748 &char2b, false);
32749 pcm = get_per_char_metric (font, &char2b);
32750 }
32751 if (! pcm)
32752 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32753 else
32754 {
32755 width = pcm->width;
32756 ascent = pcm->ascent;
32757 descent = pcm->descent;
32758 lbearing = pcm->lbearing;
32759 rbearing = pcm->rbearing;
32760 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32761 {
32762
32763
32764 left = (leftmost + rightmost - width) / 2;
32765 btm = - descent + boff;
32766 if (font->relative_compose
32767 && (! CHAR_TABLE_P (Vignore_relative_composition)
32768 || NILP (Faref (Vignore_relative_composition,
32769 make_fixnum (ch)))))
32770 {
32771
32772 if (- descent >= font->relative_compose)
32773
32774 btm = highest + 1;
32775 else if (ascent <= 0)
32776
32777 btm = lowest - 1 - ascent - descent;
32778 }
32779 }
32780 else
32781 {
32782
32783
32784
32785
32786
32787
32788
32789
32790
32791
32792
32793
32794
32795
32796
32797 int rule = COMPOSITION_RULE (cmp, i);
32798 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32799
32800 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32801 grefx = gref % 3, nrefx = nref % 3;
32802 grefy = gref / 3, nrefy = nref / 3;
32803 if (xoff)
32804 xoff = font_height * (xoff - 128) / 256;
32805 if (yoff)
32806 yoff = font_height * (yoff - 128) / 256;
32807
32808 left = (leftmost
32809 + grefx * (rightmost - leftmost) / 2
32810 - nrefx * width / 2
32811 + xoff);
32812
32813 btm = ((grefy == 0 ? highest
32814 : grefy == 1 ? 0
32815 : grefy == 2 ? lowest
32816 : (highest + lowest) / 2)
32817 - (nrefy == 0 ? ascent + descent
32818 : nrefy == 1 ? descent - boff
32819 : nrefy == 2 ? 0
32820 : (ascent + descent) / 2)
32821 + yoff);
32822 }
32823
32824 cmp->offsets[i * 2] = left;
32825 cmp->offsets[i * 2 + 1] = btm + descent;
32826
32827
32828 if (width > 0)
32829 {
32830 right = left + width;
32831 if (left < leftmost)
32832 leftmost = left;
32833 if (right > rightmost)
32834 rightmost = right;
32835 }
32836 top = btm + descent + ascent;
32837 if (top > highest)
32838 highest = top;
32839 if (btm < lowest)
32840 lowest = btm;
32841
32842 if (cmp->lbearing > left + lbearing)
32843 cmp->lbearing = left + lbearing;
32844 if (cmp->rbearing < left + rbearing)
32845 cmp->rbearing = left + rbearing;
32846 }
32847 }
32848
32849
32850
32851
32852 if (leftmost < 0)
32853 {
32854 for (i = 0; i < cmp->glyph_len; i++)
32855 cmp->offsets[i * 2] -= leftmost;
32856 rightmost -= leftmost;
32857 cmp->lbearing -= leftmost;
32858 cmp->rbearing -= leftmost;
32859 }
32860
32861 if (left_padded && cmp->lbearing < 0)
32862 {
32863 for (i = 0; i < cmp->glyph_len; i++)
32864 cmp->offsets[i * 2] -= cmp->lbearing;
32865 rightmost -= cmp->lbearing;
32866 cmp->rbearing -= cmp->lbearing;
32867 cmp->lbearing = 0;
32868 }
32869 if (right_padded && rightmost < cmp->rbearing)
32870 {
32871 rightmost = cmp->rbearing;
32872 }
32873
32874 cmp->pixel_width = rightmost;
32875 cmp->ascent = highest;
32876 cmp->descent = - lowest;
32877 if (cmp->ascent < font_ascent)
32878 cmp->ascent = font_ascent;
32879 if (cmp->descent < font_descent)
32880 cmp->descent = font_descent;
32881 }
32882
32883 if (it->glyph_row
32884 && (cmp->lbearing < 0
32885 || cmp->rbearing > cmp->pixel_width))
32886 it->glyph_row->contains_overlapping_glyphs_p = true;
32887
32888 it->pixel_width = cmp->pixel_width;
32889 it->ascent = it->phys_ascent = cmp->ascent;
32890 it->descent = it->phys_descent = cmp->descent;
32891 IT_APPLY_FACE_BOX(it, face);
32892
32893
32894
32895 if (face->overline_p)
32896 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32897
32898 take_vertical_position_into_account (it);
32899 if (it->ascent < 0)
32900 it->ascent = 0;
32901 if (it->descent < 0)
32902 it->descent = 0;
32903
32904 if (it->glyph_row && cmp->glyph_len > 0)
32905 append_composite_glyph (it);
32906 }
32907 else if (it->what == IT_COMPOSITION)
32908 {
32909
32910 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32911 Lisp_Object gstring;
32912 struct font_metrics metrics;
32913
32914 it->nglyphs = 1;
32915
32916 gstring = composition_gstring_from_id (it->cmp_it.id);
32917 it->pixel_width
32918 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32919 &metrics);
32920 if (it->pixel_width == 0)
32921 {
32922 it->glyph_not_available_p = true;
32923 it->phys_ascent = it->ascent;
32924 it->phys_descent = it->descent;
32925 it->pixel_width = face->font->space_width;
32926 }
32927 else
32928 {
32929 if (it->glyph_row
32930 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32931 it->glyph_row->contains_overlapping_glyphs_p = true;
32932 it->ascent = it->phys_ascent = metrics.ascent;
32933 it->descent = it->phys_descent = metrics.descent;
32934 }
32935 IT_APPLY_FACE_BOX(it, face);
32936
32937
32938
32939 if (face->overline_p)
32940 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32941 take_vertical_position_into_account (it);
32942 if (it->ascent < 0)
32943 it->ascent = 0;
32944 if (it->descent < 0)
32945 it->descent = 0;
32946
32947 if (it->glyph_row)
32948 append_composite_glyph (it);
32949 }
32950 else if (it->what == IT_GLYPHLESS)
32951 produce_glyphless_glyph (it, false, Qnil);
32952 else if (it->what == IT_IMAGE)
32953 produce_image_glyph (it);
32954 else if (it->what == IT_STRETCH)
32955 produce_stretch_glyph (it);
32956 else if (it->what == IT_XWIDGET)
32957 produce_xwidget_glyph (it);
32958
32959 done:
32960
32961
32962 eassert (it->ascent >= 0 && it->descent >= 0);
32963 if (it->area == TEXT_AREA)
32964 it->current_x += it->pixel_width;
32965
32966 if (extra_line_spacing > 0)
32967 {
32968 it->descent += extra_line_spacing;
32969 if (extra_line_spacing > it->max_extra_line_spacing)
32970 it->max_extra_line_spacing = extra_line_spacing;
32971 }
32972
32973 it->max_ascent = max (it->max_ascent, it->ascent);
32974 it->max_descent = max (it->max_descent, it->descent);
32975 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32976 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32977 }
32978
32979
32980
32981
32982
32983
32984 void
32985 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32986 struct glyph *start, enum glyph_row_area updated_area, int len)
32987 {
32988 int x, hpos, chpos = w->phys_cursor.hpos;
32989
32990 eassert (updated_row);
32991
32992
32993
32994 if (!updated_row->reversed_p && chpos < 0)
32995 chpos = 0;
32996 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
32997 chpos = updated_row->used[TEXT_AREA] - 1;
32998
32999 block_input ();
33000
33001
33002
33003 hpos = start - updated_row->glyphs[updated_area];
33004 x = draw_glyphs (w, w->output_cursor.x,
33005 updated_row, updated_area,
33006 hpos, hpos + len,
33007 DRAW_NORMAL_TEXT, 0);
33008
33009
33010 if (updated_area == TEXT_AREA
33011 && w->phys_cursor_on_p
33012 && w->phys_cursor.vpos == w->output_cursor.vpos
33013 && chpos >= hpos
33014 && chpos < hpos + len)
33015 w->phys_cursor_on_p = false;
33016
33017 unblock_input ();
33018
33019
33020 w->output_cursor.hpos += len;
33021 w->output_cursor.x = x;
33022 }
33023
33024
33025
33026
33027
33028 void
33029 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
33030 struct glyph *start, enum glyph_row_area updated_area, int len)
33031 {
33032 struct frame *f;
33033 int line_height, shift_by_width, shifted_region_width;
33034 struct glyph_row *row;
33035 struct glyph *glyph;
33036 int frame_x, frame_y;
33037 ptrdiff_t hpos;
33038
33039 eassert (updated_row);
33040 block_input ();
33041 f = XFRAME (WINDOW_FRAME (w));
33042
33043
33044 row = updated_row;
33045 line_height = row->height;
33046
33047
33048 shift_by_width = 0;
33049 for (glyph = start; glyph < start + len; ++glyph)
33050 shift_by_width += glyph->pixel_width;
33051
33052
33053 shifted_region_width = (window_box_width (w, updated_area)
33054 - w->output_cursor.x
33055 - shift_by_width);
33056
33057
33058 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
33059 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
33060
33061 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
33062 line_height, shift_by_width);
33063
33064
33065 hpos = start - row->glyphs[updated_area];
33066 draw_glyphs (w, w->output_cursor.x, row, updated_area,
33067 hpos, hpos + len,
33068 DRAW_NORMAL_TEXT, 0);
33069
33070
33071 w->output_cursor.hpos += len;
33072 w->output_cursor.x += shift_by_width;
33073 unblock_input ();
33074 }
33075
33076
33077
33078
33079
33080
33081
33082
33083
33084
33085 void
33086 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
33087 enum glyph_row_area updated_area, int to_x)
33088 {
33089 struct frame *f;
33090 int max_x, min_y, max_y;
33091 int from_x, from_y, to_y;
33092 struct face *face;
33093
33094 eassert (updated_row);
33095 f = XFRAME (w->frame);
33096 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
33097
33098 if (updated_row->full_width_p)
33099 max_x = (WINDOW_PIXEL_WIDTH (w)
33100 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
33101 else
33102 max_x = window_box_width (w, updated_area);
33103 max_y = window_text_bottom_y (w);
33104
33105
33106
33107 if (to_x == 0)
33108 return;
33109 else if (to_x < 0)
33110 to_x = max_x;
33111 else
33112 to_x = min (to_x, max_x);
33113
33114 to_y = min (max_y, w->output_cursor.y + updated_row->height);
33115
33116
33117 if (!updated_row->full_width_p)
33118 notice_overwritten_cursor (w, updated_area,
33119 w->output_cursor.x, -1,
33120 updated_row->y,
33121 MATRIX_ROW_BOTTOM_Y (updated_row));
33122
33123 from_x = w->output_cursor.x;
33124
33125
33126 if (updated_row->full_width_p)
33127 {
33128 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
33129 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
33130 }
33131 else
33132 {
33133 int area_left = window_box_left (w, updated_area);
33134 from_x += area_left;
33135 to_x += area_left;
33136 }
33137
33138 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
33139 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
33140 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
33141
33142
33143 if (to_x > from_x && to_y > from_y)
33144 {
33145 block_input ();
33146 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
33147 to_x - from_x, to_y - from_y);
33148
33149 if (face && !updated_row->stipple_p)
33150 updated_row->stipple_p = face->stipple;
33151 unblock_input ();
33152 }
33153 }
33154
33155 #endif
33156
33157
33158
33159
33160
33161
33162
33163
33164
33165
33166
33167 static enum text_cursor_kinds
33168 get_specified_cursor_type (Lisp_Object arg, int *width)
33169 {
33170 enum text_cursor_kinds type;
33171
33172 if (NILP (arg))
33173 return NO_CURSOR;
33174
33175 if (EQ (arg, Qbox))
33176 return FILLED_BOX_CURSOR;
33177
33178 if (EQ (arg, Qhollow))
33179 return HOLLOW_BOX_CURSOR;
33180
33181 if (EQ (arg, Qbar))
33182 {
33183 *width = 2;
33184 return BAR_CURSOR;
33185 }
33186
33187 if (EQ (arg, Qhbar))
33188 {
33189 *width = 2;
33190 return HBAR_CURSOR;
33191 }
33192
33193 if (CONSP (arg)
33194 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
33195 {
33196 *width = XFIXNUM (XCDR (arg));
33197
33198 if (EQ (XCAR (arg), Qbox))
33199 return FILLED_BOX_CURSOR;
33200 else if (EQ (XCAR (arg), Qbar))
33201 return BAR_CURSOR;
33202 else if (EQ (XCAR (arg), Qhbar))
33203 return HBAR_CURSOR;
33204 }
33205
33206
33207
33208
33209 type = HOLLOW_BOX_CURSOR;
33210
33211 return type;
33212 }
33213
33214
33215 void
33216 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
33217 {
33218 int width = 1;
33219 Lisp_Object tem;
33220
33221 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
33222 FRAME_CURSOR_WIDTH (f) = width;
33223
33224
33225
33226 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
33227 if (!NILP (tem))
33228 {
33229 FRAME_BLINK_OFF_CURSOR (f)
33230 = get_specified_cursor_type (XCDR (tem), &width);
33231 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
33232 }
33233 else
33234 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
33235
33236
33237 f->cursor_type_changed = true;
33238 }
33239
33240
33241 #ifdef HAVE_WINDOW_SYSTEM
33242
33243
33244
33245
33246
33247
33248
33249
33250
33251
33252
33253
33254 static enum text_cursor_kinds
33255 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
33256 bool *active_cursor)
33257 {
33258 struct frame *f = XFRAME (w->frame);
33259 struct buffer *b = XBUFFER (w->contents);
33260 int cursor_type = DEFAULT_CURSOR;
33261 Lisp_Object alt_cursor;
33262 bool non_selected = false;
33263
33264 *active_cursor = true;
33265
33266
33267 if (cursor_in_echo_area
33268 && FRAME_HAS_MINIBUF_P (f)
33269 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
33270 {
33271 if (w == XWINDOW (echo_area_window))
33272 {
33273 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
33274 {
33275 *width = FRAME_CURSOR_WIDTH (f);
33276 return FRAME_DESIRED_CURSOR (f);
33277 }
33278 else
33279 return get_specified_cursor_type (BVAR (b, cursor_type), width);
33280 }
33281
33282 *active_cursor = false;
33283 non_selected = true;
33284 }
33285
33286
33287 else if (w != XWINDOW (f->selected_window)
33288 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
33289 {
33290 *active_cursor = false;
33291
33292 if (MINI_WINDOW_P (w) &&
33293 (minibuf_level == 0
33294 || is_minibuffer (0, w->contents)))
33295 return NO_CURSOR;
33296
33297 non_selected = true;
33298 }
33299
33300
33301 if (NILP (BVAR (b, cursor_type)))
33302 return NO_CURSOR;
33303
33304
33305 if (EQ (BVAR (b, cursor_type), Qt))
33306 {
33307 cursor_type = FRAME_DESIRED_CURSOR (f);
33308 *width = FRAME_CURSOR_WIDTH (f);
33309 }
33310 else
33311 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
33312
33313
33314
33315 if (non_selected)
33316 {
33317 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
33318 if (!EQ (Qt, alt_cursor))
33319 return get_specified_cursor_type (alt_cursor, width);
33320
33321 if (cursor_type == FILLED_BOX_CURSOR)
33322 cursor_type = HOLLOW_BOX_CURSOR;
33323 else if (cursor_type == BAR_CURSOR && *width > 1)
33324 --*width;
33325 return cursor_type;
33326 }
33327
33328
33329 if (!w->cursor_off_p)
33330 {
33331 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
33332 return NO_CURSOR;
33333 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
33334 {
33335 if (cursor_type == FILLED_BOX_CURSOR)
33336 {
33337
33338
33339
33340
33341 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
33342 if (img != NULL && IMAGEP (img->spec))
33343 {
33344
33345
33346
33347
33348
33349
33350 if (!img->mask
33351 || (CONSP (BVAR (b, cursor_type))
33352 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33353 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33354 cursor_type = HOLLOW_BOX_CURSOR;
33355 }
33356 }
33357 else if (cursor_type != NO_CURSOR)
33358 {
33359
33360
33361
33362 cursor_type = HOLLOW_BOX_CURSOR;
33363 }
33364 }
33365 return cursor_type;
33366 }
33367
33368
33369
33370
33371 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33372 return get_specified_cursor_type (XCDR (alt_cursor), width);
33373
33374
33375 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33376 {
33377 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33378 return FRAME_BLINK_OFF_CURSOR (f);
33379 }
33380
33381 #if false
33382
33383
33384
33385
33386
33387
33388
33389
33390
33391
33392 if (cursor_type == FILLED_BOX_CURSOR)
33393 return HOLLOW_BOX_CURSOR;
33394
33395 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33396 {
33397 *width = 1;
33398 return cursor_type;
33399 }
33400 #endif
33401
33402 return NO_CURSOR;
33403 }
33404
33405
33406
33407
33408
33409
33410
33411
33412
33413 static void
33414 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33415 int x0, int x1, int y0, int y1)
33416 {
33417 int cx0, cx1, cy0, cy1;
33418 struct glyph_row *row;
33419
33420 if (!w->phys_cursor_on_p)
33421 return;
33422 if (area != TEXT_AREA)
33423 return;
33424
33425 if (w->phys_cursor.vpos < 0
33426 || w->phys_cursor.vpos >= w->current_matrix->nrows
33427 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33428 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33429 return;
33430
33431 if (row->cursor_in_fringe_p)
33432 {
33433 row->cursor_in_fringe_p = false;
33434 draw_fringe_bitmap (w, row, row->reversed_p);
33435 w->phys_cursor_on_p = false;
33436 return;
33437 }
33438
33439 cx0 = w->phys_cursor.x;
33440 cx1 = cx0 + w->phys_cursor_width;
33441 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33442 return;
33443
33444
33445
33446
33447
33448
33449
33450
33451
33452
33453
33454
33455
33456
33457
33458
33459
33460 cy0 = w->phys_cursor.y;
33461 cy1 = cy0 + w->phys_cursor_height;
33462 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33463 return;
33464
33465 w->phys_cursor_on_p = false;
33466 }
33467
33468 #endif
33469
33470
33471
33472
33473
33474
33475 #ifdef HAVE_WINDOW_SYSTEM
33476
33477
33478
33479
33480
33481 void
33482 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33483 enum glyph_row_area area, int overlaps)
33484 {
33485 int i, x;
33486
33487 block_input ();
33488
33489 x = 0;
33490 for (i = 0; i < row->used[area];)
33491 {
33492 if (row->glyphs[area][i].overlaps_vertically_p)
33493 {
33494 int start = i, start_x = x;
33495
33496 do
33497 {
33498 x += row->glyphs[area][i].pixel_width;
33499 ++i;
33500 }
33501 while (i < row->used[area]
33502 && row->glyphs[area][i].overlaps_vertically_p);
33503
33504 draw_glyphs (w, start_x, row, area,
33505 start, i,
33506 DRAW_NORMAL_TEXT, overlaps);
33507 }
33508 else
33509 {
33510 x += row->glyphs[area][i].pixel_width;
33511 ++i;
33512 }
33513 }
33514
33515 unblock_input ();
33516 }
33517
33518
33519
33520
33521
33522
33523 void
33524 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33525 enum draw_glyphs_face hl)
33526 {
33527
33528
33529
33530 if ((row->reversed_p
33531 ? (w->phys_cursor.hpos >= 0)
33532 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33533 {
33534 bool on_p = w->phys_cursor_on_p;
33535 int x1;
33536 int hpos = w->phys_cursor.hpos;
33537
33538
33539
33540
33541 if (!row->reversed_p && hpos < 0)
33542 hpos = 0;
33543 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33544 hpos = row->used[TEXT_AREA] - 1;
33545
33546 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33547 hl, 0);
33548 w->phys_cursor_on_p = on_p;
33549
33550 if (hl == DRAW_CURSOR)
33551 w->phys_cursor_width = x1 - w->phys_cursor.x;
33552
33553
33554
33555 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33556 {
33557 w->phys_cursor_width = x1 - w->phys_cursor.x;
33558
33559 if (row > w->current_matrix->rows
33560 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33561 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33562 OVERLAPS_ERASED_CURSOR);
33563
33564 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33565 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33566 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33567 OVERLAPS_ERASED_CURSOR);
33568 }
33569 }
33570 }
33571
33572
33573
33574
33575 void
33576 erase_phys_cursor (struct window *w)
33577 {
33578 struct frame *f = XFRAME (w->frame);
33579 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33580 int hpos = w->phys_cursor.hpos;
33581 int vpos = w->phys_cursor.vpos;
33582 bool mouse_face_here_p = false;
33583 struct glyph_matrix *active_glyphs = w->current_matrix;
33584 struct glyph_row *cursor_row;
33585 struct glyph *cursor_glyph;
33586 enum draw_glyphs_face hl;
33587
33588
33589
33590 if (w->phys_cursor_type == NO_CURSOR)
33591 goto mark_cursor_off;
33592
33593
33594
33595 if (vpos >= active_glyphs->nrows)
33596 goto mark_cursor_off;
33597
33598
33599
33600 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33601 if (!cursor_row->enabled_p)
33602 goto mark_cursor_off;
33603
33604
33605
33606 cursor_row->visible_height = min (cursor_row->visible_height,
33607 window_text_bottom_y (w) - cursor_row->y);
33608
33609
33610
33611
33612 if (cursor_row->visible_height <= 0)
33613 goto mark_cursor_off;
33614
33615
33616 if (cursor_row->cursor_in_fringe_p)
33617 {
33618 cursor_row->cursor_in_fringe_p = false;
33619 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33620 goto mark_cursor_off;
33621 }
33622
33623
33624
33625
33626
33627
33628 if ((cursor_row->reversed_p
33629 ? (w->phys_cursor.hpos < 0)
33630 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33631 goto mark_cursor_off;
33632
33633
33634
33635
33636 if (!cursor_row->reversed_p && hpos < 0)
33637 hpos = 0;
33638 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33639 hpos = cursor_row->used[TEXT_AREA] - 1;
33640
33641
33642
33643 if (! NILP (hlinfo->mouse_face_window)
33644 && coords_in_mouse_face_p (w, hpos, vpos)
33645
33646
33647
33648 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33649 mouse_face_here_p = true;
33650
33651 #ifdef HAVE_WINDOW_SYSTEM
33652
33653
33654
33655
33656 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33657 {
33658 w->phys_cursor_on_p = false;
33659 w->phys_cursor_type = NO_CURSOR;
33660 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33661 return;
33662 }
33663 #endif
33664
33665
33666 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33667 {
33668 int x, y;
33669 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33670 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33671 int width;
33672
33673 cursor_glyph = get_phys_cursor_glyph (w);
33674 if (cursor_glyph == NULL)
33675 goto mark_cursor_off;
33676
33677 width = cursor_glyph->pixel_width;
33678 x = w->phys_cursor.x;
33679 if (x < 0)
33680 {
33681 width += x;
33682 x = 0;
33683 }
33684 width = min (width, window_box_width (w, TEXT_AREA) - x);
33685 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33686 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33687
33688 if (width > 0)
33689 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33690 }
33691
33692
33693 if (mouse_face_here_p)
33694 hl = DRAW_MOUSE_FACE;
33695 else
33696 hl = DRAW_NORMAL_TEXT;
33697 draw_phys_cursor_glyph (w, cursor_row, hl);
33698
33699 mark_cursor_off:
33700 w->phys_cursor_on_p = false;
33701 w->phys_cursor_type = NO_CURSOR;
33702 }
33703
33704
33705
33706
33707
33708
33709 void
33710 display_and_set_cursor (struct window *w, bool on,
33711 int hpos, int vpos, int x, int y)
33712 {
33713 struct frame *f = XFRAME (w->frame);
33714 int new_cursor_type;
33715 int new_cursor_width UNINIT;
33716 bool active_cursor;
33717 struct glyph_row *glyph_row;
33718 struct glyph *glyph;
33719
33720
33721
33722
33723
33724 if (! FRAME_REDISPLAY_P (f)
33725 || vpos >= w->current_matrix->nrows
33726 || hpos >= w->current_matrix->matrix_w)
33727 return;
33728
33729
33730 if (!on && !w->phys_cursor_on_p)
33731 return;
33732
33733 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33734
33735
33736 if (!glyph_row->enabled_p)
33737 {
33738 w->phys_cursor_on_p = false;
33739 return;
33740 }
33741
33742
33743
33744
33745
33746
33747
33748
33749
33750 if (FRAME_GARBAGED_P (f))
33751 {
33752 if (on)
33753 {
33754 w->phys_cursor.x = x;
33755 w->phys_cursor.y = glyph_row->y;
33756 w->phys_cursor.hpos = hpos;
33757 w->phys_cursor.vpos = vpos;
33758 }
33759 return;
33760 }
33761
33762 glyph = NULL;
33763 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33764 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33765
33766 eassert (input_blocked_p ());
33767
33768
33769 new_cursor_type = get_window_cursor_type (w, glyph,
33770 &new_cursor_width, &active_cursor);
33771
33772
33773
33774
33775 if (w->phys_cursor_on_p
33776 && (!on
33777 || w->phys_cursor.x != x
33778 || w->phys_cursor.y != y
33779
33780
33781
33782 || hpos < 0
33783 || new_cursor_type != w->phys_cursor_type
33784 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33785 && new_cursor_width != w->phys_cursor_width)))
33786 erase_phys_cursor (w);
33787
33788
33789
33790
33791
33792
33793 if (on)
33794 {
33795 w->phys_cursor_ascent = glyph_row->ascent;
33796 w->phys_cursor_height = glyph_row->height;
33797
33798
33799
33800 w->phys_cursor.x = x;
33801 w->phys_cursor.y = glyph_row->y;
33802 w->phys_cursor.hpos = hpos;
33803 w->phys_cursor.vpos = vpos;
33804 }
33805
33806 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33807 new_cursor_type, new_cursor_width,
33808 on, active_cursor);
33809 }
33810
33811
33812
33813
33814
33815 static void
33816 update_window_cursor (struct window *w, bool on)
33817 {
33818
33819
33820 if (w->current_matrix)
33821 {
33822 int hpos = w->phys_cursor.hpos;
33823 int vpos = w->phys_cursor.vpos;
33824 struct glyph_row *row;
33825
33826 if (vpos >= w->current_matrix->nrows
33827 || hpos >= w->current_matrix->matrix_w)
33828 return;
33829
33830 row = MATRIX_ROW (w->current_matrix, vpos);
33831
33832
33833
33834
33835 if (!row->reversed_p && hpos < 0)
33836 hpos = 0;
33837 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33838 hpos = row->used[TEXT_AREA] - 1;
33839
33840 block_input ();
33841 display_and_set_cursor (w, on, hpos, vpos,
33842 w->phys_cursor.x, w->phys_cursor.y);
33843 unblock_input ();
33844 }
33845 }
33846
33847
33848
33849
33850
33851 static void
33852 update_cursor_in_window_tree (struct window *w, bool on_p)
33853 {
33854 while (w)
33855 {
33856 if (WINDOWP (w->contents))
33857 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33858 else
33859 update_window_cursor (w, on_p);
33860
33861 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33862 }
33863 }
33864
33865
33866
33867
33868
33869
33870 void
33871 gui_update_cursor (struct frame *f, bool on_p)
33872 {
33873 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33874 }
33875
33876
33877
33878
33879
33880
33881
33882 void
33883 gui_clear_cursor (struct window *w)
33884 {
33885 if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33886 update_window_cursor (w, false);
33887 }
33888
33889 #endif
33890
33891
33892
33893 static void
33894 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33895 int start_hpos, int end_hpos,
33896 enum draw_glyphs_face draw)
33897 {
33898 #ifdef HAVE_WINDOW_SYSTEM
33899 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33900 {
33901 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33902 return;
33903 }
33904 #endif
33905
33906 #ifndef HAVE_ANDROID
33907 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33908 #endif
33909 }
33910
33911
33912
33913 static void
33914 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33915 {
33916
33917
33918 if (!WINDOWP (hlinfo->mouse_face_window))
33919 return;
33920
33921 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33922 struct frame *f = XFRAME (WINDOW_FRAME (w));
33923
33924
33925 if (f != hlinfo->mouse_face_mouse_frame)
33926 return;
33927
33928 if (
33929
33930 w->current_matrix != NULL
33931
33932 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33933
33934
33935 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33936 {
33937 bool phys_cursor_on_p = w->phys_cursor_on_p;
33938 #ifdef HAVE_WINDOW_SYSTEM
33939 int mouse_off = 0;
33940 #endif
33941 struct glyph_row *row, *first, *last;
33942
33943 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33944 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33945
33946 for (row = first; row <= last && row->enabled_p; ++row)
33947 {
33948 int start_hpos, end_hpos, start_x;
33949
33950
33951 if (row == first)
33952 {
33953
33954
33955
33956
33957 if (!row->reversed_p)
33958 {
33959 start_hpos = hlinfo->mouse_face_beg_col;
33960 start_x = hlinfo->mouse_face_beg_x;
33961 }
33962 else if (row == last)
33963 {
33964 start_hpos = hlinfo->mouse_face_end_col;
33965 start_x = hlinfo->mouse_face_end_x;
33966 }
33967 else
33968 {
33969 start_hpos = 0;
33970 start_x = 0;
33971 }
33972 }
33973 else if (row->reversed_p && row == last)
33974 {
33975 start_hpos = hlinfo->mouse_face_end_col;
33976 start_x = hlinfo->mouse_face_end_x;
33977 }
33978 else
33979 {
33980 start_hpos = 0;
33981 start_x = 0;
33982 }
33983
33984 if (row == last)
33985 {
33986 if (!row->reversed_p)
33987 end_hpos = hlinfo->mouse_face_end_col;
33988 else if (row == first)
33989 end_hpos = hlinfo->mouse_face_beg_col;
33990 else
33991 {
33992 end_hpos = row->used[TEXT_AREA];
33993 if (draw == DRAW_NORMAL_TEXT)
33994 row->fill_line_p = true;
33995 }
33996 }
33997 else if (row->reversed_p && row == first)
33998 end_hpos = hlinfo->mouse_face_beg_col;
33999 else
34000 {
34001 end_hpos = row->used[TEXT_AREA];
34002 if (draw == DRAW_NORMAL_TEXT)
34003 row->fill_line_p = true;
34004 }
34005
34006 if (end_hpos > start_hpos)
34007 {
34008 draw_row_with_mouse_face (w, start_x, row,
34009 start_hpos, end_hpos, draw);
34010
34011 row->mouse_face_p
34012 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
34013 }
34014 #ifdef HAVE_WINDOW_SYSTEM
34015
34016 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
34017
34018
34019 && !w->pseudo_window_p
34020 && draw == DRAW_MOUSE_FACE)
34021 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
34022 #endif
34023 }
34024
34025
34026
34027 if (FRAME_WINDOW_P (f)
34028 && phys_cursor_on_p && !w->phys_cursor_on_p)
34029 {
34030 #ifdef HAVE_WINDOW_SYSTEM
34031 int hpos = w->phys_cursor.hpos;
34032 int old_phys_cursor_x = w->phys_cursor.x;
34033
34034
34035
34036
34037 if (!row->reversed_p && hpos < 0)
34038 hpos = 0;
34039 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
34040 hpos = row->used[TEXT_AREA] - 1;
34041
34042 block_input ();
34043 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
34044 w->phys_cursor.x + mouse_off,
34045 w->phys_cursor.y);
34046
34047
34048 w->phys_cursor.x = old_phys_cursor_x;
34049 unblock_input ();
34050 #endif
34051 }
34052 }
34053
34054 #ifdef HAVE_WINDOW_SYSTEM
34055
34056 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
34057 {
34058 if (draw == DRAW_NORMAL_TEXT
34059 #ifndef HAVE_EXT_TOOL_BAR
34060 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
34061 #endif
34062 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
34063 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
34064 else
34065 if (draw == DRAW_MOUSE_FACE)
34066 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
34067 else
34068 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
34069 }
34070 #endif
34071 }
34072
34073
34074
34075
34076
34077
34078 bool
34079 clear_mouse_face (Mouse_HLInfo *hlinfo)
34080 {
34081 bool cleared
34082 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
34083 if (cleared)
34084 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
34085 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
34086 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
34087 hlinfo->mouse_face_window = Qnil;
34088 hlinfo->mouse_face_overlay = Qnil;
34089 return cleared;
34090 }
34091
34092
34093
34094 static bool
34095 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
34096 {
34097 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
34098
34099
34100 if (!(WINDOWP (hlinfo->mouse_face_window)
34101 && XWINDOW (hlinfo->mouse_face_window) == w))
34102 return false;
34103 if (vpos < hlinfo->mouse_face_beg_row
34104 || vpos > hlinfo->mouse_face_end_row)
34105 return false;
34106 if (vpos > hlinfo->mouse_face_beg_row
34107 && vpos < hlinfo->mouse_face_end_row)
34108 return true;
34109
34110 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
34111 {
34112 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34113 {
34114 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
34115 return true;
34116 }
34117 else if ((vpos == hlinfo->mouse_face_beg_row
34118 && hpos >= hlinfo->mouse_face_beg_col)
34119 || (vpos == hlinfo->mouse_face_end_row
34120 && hpos < hlinfo->mouse_face_end_col))
34121 return true;
34122 }
34123 else
34124 {
34125 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34126 {
34127 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
34128 return true;
34129 }
34130 else if ((vpos == hlinfo->mouse_face_beg_row
34131 && hpos <= hlinfo->mouse_face_beg_col)
34132 || (vpos == hlinfo->mouse_face_end_row
34133 && hpos > hlinfo->mouse_face_end_col))
34134 return true;
34135 }
34136 return false;
34137 }
34138
34139
34140
34141
34142
34143 bool
34144 cursor_in_mouse_face_p (struct window *w)
34145 {
34146 int vpos = w->phys_cursor.vpos;
34147
34148
34149
34150 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
34151 return false;
34152
34153 int hpos = w->phys_cursor.hpos;
34154 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
34155
34156
34157
34158
34159 if (!row->reversed_p && hpos < 0)
34160 hpos = 0;
34161 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
34162 hpos = row->used[TEXT_AREA] - 1;
34163
34164 return coords_in_mouse_face_p (w, hpos, vpos);
34165 }
34166
34167
34168
34169
34170
34171
34172
34173
34174
34175 static void
34176 rows_from_pos_range (struct window *w,
34177 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
34178 Lisp_Object disp_string,
34179 struct glyph_row **start, struct glyph_row **end)
34180 {
34181 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34182 int last_y = window_text_bottom_y (w);
34183 struct glyph_row *row;
34184
34185 *start = NULL;
34186 *end = NULL;
34187
34188 while (!first->enabled_p
34189 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
34190 first++;
34191
34192
34193 for (row = first;
34194 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
34195 row++)
34196 {
34197
34198
34199
34200 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
34201 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
34202
34203
34204
34205
34206 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
34207 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
34208 && !row->ends_at_zv_p
34209 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
34210 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
34211 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
34212 && !row->ends_at_zv_p
34213 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
34214 {
34215
34216
34217
34218
34219
34220
34221
34222
34223
34224
34225 struct glyph *g = row->glyphs[TEXT_AREA];
34226 struct glyph *e = g + row->used[TEXT_AREA];
34227
34228 while (g < e)
34229 {
34230 if (((BUFFERP (g->object) || NILP (g->object))
34231 && start_charpos <= g->charpos && g->charpos < end_charpos)
34232
34233
34234 || EQ (g->object, disp_string))
34235 *start = row;
34236 g++;
34237 }
34238 if (*start)
34239 break;
34240 }
34241 }
34242
34243
34244 if (!*start
34245
34246
34247 && !(row->enabled_p
34248 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
34249 row = first;
34250 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
34251 {
34252 struct glyph_row *next = row + 1;
34253 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
34254
34255 if (!next->enabled_p
34256 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
34257
34258
34259
34260 || (start_charpos < next_start
34261 && end_charpos < next_start)
34262 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
34263 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
34264 && !next->ends_at_zv_p
34265 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
34266 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
34267 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
34268 && !next->ends_at_zv_p
34269 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
34270 {
34271 *end = row;
34272 break;
34273 }
34274 else
34275 {
34276
34277
34278
34279 struct glyph *g = next->glyphs[TEXT_AREA];
34280 struct glyph *s = g;
34281 struct glyph *e = g + next->used[TEXT_AREA];
34282
34283 while (g < e)
34284 {
34285 if (((BUFFERP (g->object) || NILP (g->object))
34286 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
34287
34288
34289
34290
34291
34292 || (((!next->reversed_p && g == s)
34293 || (next->reversed_p && g == e - 1))
34294 && (g->charpos == end_charpos
34295
34296
34297 || (g->charpos == -1
34298 && !row->ends_at_zv_p
34299 && next_start == end_charpos)))))
34300
34301
34302 || EQ (g->object, disp_string))
34303 break;
34304 g++;
34305 }
34306 if (g == e)
34307 {
34308 *end = row;
34309 break;
34310 }
34311
34312
34313 else if (next->ends_at_zv_p)
34314 {
34315 *end = next;
34316 break;
34317 }
34318 }
34319 }
34320 }
34321
34322
34323
34324
34325
34326
34327
34328
34329
34330
34331 static void
34332 mouse_face_from_buffer_pos (Lisp_Object window,
34333 Mouse_HLInfo *hlinfo,
34334 ptrdiff_t mouse_charpos,
34335 ptrdiff_t start_charpos,
34336 ptrdiff_t end_charpos,
34337 Lisp_Object before_string,
34338 Lisp_Object after_string,
34339 Lisp_Object disp_string)
34340 {
34341 struct window *w = XWINDOW (window);
34342 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34343 struct glyph_row *r1, *r2;
34344 struct glyph *glyph, *end;
34345 ptrdiff_t ignore, pos;
34346 int x;
34347
34348 eassert (NILP (disp_string) || STRINGP (disp_string));
34349 eassert (NILP (before_string) || STRINGP (before_string));
34350 eassert (NILP (after_string) || STRINGP (after_string));
34351
34352
34353 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
34354 if (r1 == NULL)
34355 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34356
34357
34358 if (!NILP (before_string) || !NILP (disp_string))
34359 {
34360 struct glyph_row *prev;
34361 while ((prev = r1 - 1, prev >= first)
34362 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34363 && prev->used[TEXT_AREA] > 0)
34364 {
34365 struct glyph *beg = prev->glyphs[TEXT_AREA];
34366 glyph = beg + prev->used[TEXT_AREA];
34367 while (--glyph >= beg && NILP (glyph->object));
34368 if (glyph < beg
34369 || !(EQ (glyph->object, before_string)
34370 || EQ (glyph->object, disp_string)))
34371 break;
34372 r1 = prev;
34373 }
34374 }
34375 if (r2 == NULL)
34376 {
34377 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34378 hlinfo->mouse_face_past_end = true;
34379 }
34380 else if (!NILP (after_string))
34381 {
34382
34383 struct glyph_row *next;
34384 struct glyph_row *last
34385 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34386
34387 for (next = r2 + 1;
34388 next <= last
34389 && next->used[TEXT_AREA] > 0
34390 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34391 ++next)
34392 r2 = next;
34393 }
34394
34395
34396
34397
34398
34399 if (r1->y > r2->y)
34400 {
34401 struct glyph_row *tem = r2;
34402
34403 r2 = r1;
34404 r1 = tem;
34405 }
34406
34407 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34408 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34409
34410
34411
34412
34413
34414
34415
34416
34417
34418
34419
34420 if (!r1->reversed_p)
34421 {
34422
34423
34424 glyph = r1->glyphs[TEXT_AREA];
34425 end = glyph + r1->used[TEXT_AREA];
34426 x = r1->x;
34427
34428
34429 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34430 for (; glyph < end
34431 && NILP (glyph->object)
34432 && glyph->charpos < 0;
34433 ++glyph)
34434 x += glyph->pixel_width;
34435
34436
34437
34438
34439 for (; glyph < end
34440 && !NILP (glyph->object)
34441 && !EQ (glyph->object, disp_string)
34442 && !(BUFFERP (glyph->object)
34443 && (glyph->charpos >= start_charpos
34444 && glyph->charpos < end_charpos));
34445 ++glyph)
34446 {
34447
34448
34449
34450 if (EQ (glyph->object, before_string))
34451 {
34452 pos = string_buffer_position (before_string,
34453 start_charpos);
34454
34455
34456 if (!pos || (pos >= start_charpos && pos < end_charpos))
34457 break;
34458 }
34459 else if (EQ (glyph->object, after_string))
34460 {
34461 pos = string_buffer_position (after_string, end_charpos);
34462 if (!pos || (pos >= start_charpos && pos < end_charpos))
34463 break;
34464 }
34465 x += glyph->pixel_width;
34466 }
34467 hlinfo->mouse_face_beg_x = x;
34468 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34469 }
34470 else
34471 {
34472
34473
34474 struct glyph *g;
34475
34476 end = r1->glyphs[TEXT_AREA] - 1;
34477 glyph = end + r1->used[TEXT_AREA];
34478
34479
34480 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34481 for (; glyph > end
34482 && NILP (glyph->object)
34483 && glyph->charpos < 0;
34484 --glyph)
34485 ;
34486
34487
34488
34489
34490 for (; glyph > end
34491 && !NILP (glyph->object)
34492 && !EQ (glyph->object, disp_string)
34493 && !(BUFFERP (glyph->object)
34494 && (glyph->charpos >= start_charpos
34495 && glyph->charpos < end_charpos));
34496 --glyph)
34497 {
34498
34499
34500
34501 if (EQ (glyph->object, before_string))
34502 {
34503 pos = string_buffer_position (before_string, start_charpos);
34504
34505
34506 if (!pos || (pos >= start_charpos && pos < end_charpos))
34507 break;
34508 }
34509 else if (EQ (glyph->object, after_string))
34510 {
34511 pos = string_buffer_position (after_string, end_charpos);
34512 if (!pos || (pos >= start_charpos && pos < end_charpos))
34513 break;
34514 }
34515 }
34516
34517 glyph++;
34518 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34519 x += g->pixel_width;
34520 hlinfo->mouse_face_beg_x = x;
34521 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34522 }
34523
34524
34525
34526
34527 if (r2 != r1)
34528 {
34529 if (!r2->reversed_p)
34530 {
34531 glyph = r2->glyphs[TEXT_AREA];
34532 end = glyph + r2->used[TEXT_AREA];
34533 x = r2->x;
34534 }
34535 else
34536 {
34537 end = r2->glyphs[TEXT_AREA] - 1;
34538 glyph = end + r2->used[TEXT_AREA];
34539 }
34540 }
34541
34542 if (!r2->reversed_p)
34543 {
34544
34545
34546
34547 while (end > glyph
34548 && NILP ((end - 1)->object))
34549 --end;
34550
34551
34552
34553
34554 for (--end;
34555 end > glyph
34556 && !NILP (end->object)
34557 && !EQ (end->object, disp_string)
34558 && !(BUFFERP (end->object)
34559 && (end->charpos >= start_charpos
34560 && end->charpos < end_charpos));
34561 --end)
34562 {
34563
34564
34565
34566 if (EQ (end->object, before_string))
34567 {
34568 pos = string_buffer_position (before_string, start_charpos);
34569 if (!pos || (pos >= start_charpos && pos < end_charpos))
34570 break;
34571 }
34572 else if (EQ (end->object, after_string))
34573 {
34574 pos = string_buffer_position (after_string, end_charpos);
34575 if (!pos || (pos >= start_charpos && pos < end_charpos))
34576 break;
34577 }
34578 }
34579
34580 for (; glyph <= end; ++glyph)
34581 x += glyph->pixel_width;
34582
34583 hlinfo->mouse_face_end_x = x;
34584 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34585 }
34586 else
34587 {
34588
34589
34590
34591 x = r2->x;
34592 end++;
34593 while (end < glyph
34594 && NILP (end->object))
34595 {
34596 x += end->pixel_width;
34597 ++end;
34598 }
34599
34600
34601
34602
34603 for ( ;
34604 end < glyph
34605 && !NILP (end->object)
34606 && !EQ (end->object, disp_string)
34607 && !(BUFFERP (end->object)
34608 && (end->charpos >= start_charpos
34609 && end->charpos < end_charpos));
34610 ++end)
34611 {
34612
34613
34614
34615 if (EQ (end->object, before_string))
34616 {
34617 pos = string_buffer_position (before_string, start_charpos);
34618 if (!pos || (pos >= start_charpos && pos < end_charpos))
34619 break;
34620 }
34621 else if (EQ (end->object, after_string))
34622 {
34623 pos = string_buffer_position (after_string, end_charpos);
34624 if (!pos || (pos >= start_charpos && pos < end_charpos))
34625 break;
34626 }
34627 x += end->pixel_width;
34628 }
34629
34630
34631
34632
34633
34634 if (end == glyph
34635 && BUFFERP (end->object)
34636 && (end->charpos < start_charpos
34637 || end->charpos >= end_charpos))
34638 {
34639 x += end->pixel_width;
34640 ++end;
34641 }
34642 hlinfo->mouse_face_end_x = x;
34643 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34644 }
34645
34646 hlinfo->mouse_face_window = window;
34647 hlinfo->mouse_face_face_id
34648 = face_at_buffer_position (w, mouse_charpos, &ignore,
34649 mouse_charpos + 1,
34650 !hlinfo->mouse_face_hidden, -1, 0);
34651 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34652 }
34653
34654
34655
34656
34657
34658 #if false
34659
34660
34661
34662
34663
34664
34665
34666
34667
34668
34669
34670
34671
34672
34673
34674
34675 static bool
34676 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34677 int *hpos, int *vpos, int *x, int *y, bool right_p)
34678 {
34679 int yb = window_text_bottom_y (w);
34680 struct glyph_row *r;
34681 struct glyph *best_glyph = NULL;
34682 struct glyph_row *best_row = NULL;
34683 int best_x = 0;
34684
34685 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34686 r->enabled_p && r->y < yb;
34687 ++r)
34688 {
34689 struct glyph *g = r->glyphs[TEXT_AREA];
34690 struct glyph *e = g + r->used[TEXT_AREA];
34691 int gx;
34692
34693 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34694 if (EQ (g->object, object))
34695 {
34696 if (g->charpos == pos)
34697 {
34698 best_glyph = g;
34699 best_x = gx;
34700 best_row = r;
34701 goto found;
34702 }
34703 else if (best_glyph == NULL
34704 || ((eabs (g->charpos - pos)
34705 < eabs (best_glyph->charpos - pos))
34706 && (right_p
34707 ? g->charpos < pos
34708 : g->charpos > pos)))
34709 {
34710 best_glyph = g;
34711 best_x = gx;
34712 best_row = r;
34713 }
34714 }
34715 }
34716
34717 found:
34718
34719 if (best_glyph)
34720 {
34721 *x = best_x;
34722 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34723
34724 if (right_p)
34725 {
34726 *x += best_glyph->pixel_width;
34727 ++*hpos;
34728 }
34729
34730 *y = best_row->y;
34731 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34732 }
34733
34734 return best_glyph != NULL;
34735 }
34736 #endif
34737
34738
34739
34740
34741
34742
34743 static void
34744 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34745 Lisp_Object object,
34746 ptrdiff_t startpos, ptrdiff_t endpos)
34747 {
34748 int yb = window_text_bottom_y (w);
34749 struct glyph_row *r;
34750 struct glyph *g, *e;
34751 int gx;
34752 bool found = false;
34753
34754
34755
34756
34757 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34758 r->enabled_p && r->y < yb;
34759 ++r)
34760 {
34761 if (!r->reversed_p)
34762 {
34763 g = r->glyphs[TEXT_AREA];
34764 e = g + r->used[TEXT_AREA];
34765 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34766 if (EQ (g->object, object)
34767 && startpos <= g->charpos && g->charpos < endpos)
34768 {
34769 hlinfo->mouse_face_beg_row
34770 = MATRIX_ROW_VPOS (r, w->current_matrix);
34771 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34772 hlinfo->mouse_face_beg_x = gx;
34773 found = true;
34774 break;
34775 }
34776 }
34777 else
34778 {
34779 struct glyph *g1;
34780
34781 e = r->glyphs[TEXT_AREA];
34782 g = e + r->used[TEXT_AREA];
34783 for ( ; g > e; --g)
34784 if (EQ ((g-1)->object, object)
34785 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34786 {
34787 hlinfo->mouse_face_beg_row
34788 = MATRIX_ROW_VPOS (r, w->current_matrix);
34789 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34790 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34791 gx += g1->pixel_width;
34792 hlinfo->mouse_face_beg_x = gx;
34793 found = true;
34794 break;
34795 }
34796 }
34797 if (found)
34798 break;
34799 }
34800
34801 if (!found)
34802 return;
34803
34804
34805
34806 for (++r; r->enabled_p && r->y < yb; ++r)
34807 {
34808 g = r->glyphs[TEXT_AREA];
34809 e = g + r->used[TEXT_AREA];
34810 found = false;
34811 for ( ; g < e; ++g)
34812 if (EQ (g->object, object)
34813 && startpos <= g->charpos && g->charpos < endpos)
34814 {
34815 found = true;
34816 break;
34817 }
34818 if (!found)
34819 break;
34820 }
34821
34822
34823 r--;
34824
34825
34826 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34827
34828
34829
34830 if (!r->reversed_p)
34831 {
34832 g = r->glyphs[TEXT_AREA];
34833 e = g + r->used[TEXT_AREA];
34834 for ( ; e > g; --e)
34835 if (EQ ((e-1)->object, object)
34836 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34837 break;
34838 hlinfo->mouse_face_end_col = e - g;
34839
34840 for (gx = r->x; g < e; ++g)
34841 gx += g->pixel_width;
34842 hlinfo->mouse_face_end_x = gx;
34843 }
34844 else
34845 {
34846 e = r->glyphs[TEXT_AREA];
34847 g = e + r->used[TEXT_AREA];
34848 for (gx = r->x ; e < g; ++e)
34849 {
34850 if (EQ (e->object, object)
34851 && startpos <= e->charpos && e->charpos < endpos)
34852 break;
34853 gx += e->pixel_width;
34854 }
34855 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34856 hlinfo->mouse_face_end_x = gx;
34857 }
34858 }
34859
34860 #ifdef HAVE_WINDOW_SYSTEM
34861
34862
34863
34864 static bool
34865 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34866 {
34867 if (!CONSP (hot_spot))
34868 return false;
34869
34870 if (EQ (XCAR (hot_spot), Qrect))
34871 {
34872
34873 Lisp_Object rect = XCDR (hot_spot);
34874 Lisp_Object tem;
34875 if (!CONSP (rect))
34876 return false;
34877 if (!CONSP (XCAR (rect)))
34878 return false;
34879 if (!CONSP (XCDR (rect)))
34880 return false;
34881 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34882 return false;
34883 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34884 return false;
34885 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34886 return false;
34887 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34888 return false;
34889 return true;
34890 }
34891 else if (EQ (XCAR (hot_spot), Qcircle))
34892 {
34893
34894 Lisp_Object circ = XCDR (hot_spot);
34895 Lisp_Object lr, lx0, ly0;
34896 if (CONSP (circ)
34897 && CONSP (XCAR (circ))
34898 && (lr = XCDR (circ), NUMBERP (lr))
34899 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34900 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34901 {
34902 double r = XFLOATINT (lr);
34903 double dx = XFIXNUM (lx0) - x;
34904 double dy = XFIXNUM (ly0) - y;
34905 return (dx * dx + dy * dy <= r * r);
34906 }
34907 }
34908 else if (EQ (XCAR (hot_spot), Qpoly))
34909 {
34910
34911 if (VECTORP (XCDR (hot_spot)))
34912 {
34913 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34914 Lisp_Object *poly = v->contents;
34915 ptrdiff_t n = v->header.size;
34916 ptrdiff_t i;
34917 bool inside = false;
34918 Lisp_Object lx, ly;
34919 int x0, y0;
34920
34921
34922 if (n < 6 || n & 1)
34923 return false;
34924
34925
34926
34927
34928
34929 if ((lx = poly[n-2], !FIXNUMP (lx))
34930 || (ly = poly[n-1], !FIXNUMP (lx)))
34931 return false;
34932 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34933 for (i = 0; i < n; i += 2)
34934 {
34935 int x1 = x0, y1 = y0;
34936 if ((lx = poly[i], !FIXNUMP (lx))
34937 || (ly = poly[i+1], !FIXNUMP (ly)))
34938 return false;
34939 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34940
34941
34942 if (x0 >= x)
34943 {
34944 if (x1 >= x)
34945 continue;
34946 }
34947 else if (x1 < x)
34948 continue;
34949 if (y > y0 && y > y1)
34950 continue;
34951 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34952 inside = !inside;
34953 }
34954 return inside;
34955 }
34956 }
34957 return false;
34958 }
34959
34960 Lisp_Object
34961 find_hot_spot (Lisp_Object map, int x, int y)
34962 {
34963 while (CONSP (map))
34964 {
34965 if (CONSP (XCAR (map))
34966 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34967 return XCAR (map);
34968 map = XCDR (map);
34969 }
34970
34971 return Qnil;
34972 }
34973
34974 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34975 3, 3, 0,
34976 doc:
34977
34978
34979
34980
34981
34982
34983
34984
34985 )
34986 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
34987 {
34988 if (NILP (map))
34989 return Qnil;
34990
34991 CHECK_FIXNUM (x);
34992 CHECK_FIXNUM (y);
34993
34994 return find_hot_spot (map,
34995 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
34996 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
34997 }
34998 #endif
34999
35000
35001
35002 static void
35003 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
35004 {
35005 #ifdef HAVE_WINDOW_SYSTEM
35006 if (!FRAME_WINDOW_P (f))
35007 return;
35008
35009
35010 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
35011 || EQ (track_mouse, Qdrag_source))
35012 return;
35013
35014 if (!NILP (pointer))
35015 {
35016 if (EQ (pointer, Qarrow))
35017 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35018 else if (EQ (pointer, Qhand))
35019 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35020 else if (EQ (pointer, Qtext))
35021 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35022 else if (EQ (pointer, intern ("hdrag")))
35023 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35024 else if (EQ (pointer, intern ("nhdrag")))
35025 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35026 # ifdef HAVE_X_WINDOWS
35027 else if (EQ (pointer, intern ("vdrag")))
35028 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
35029 # endif
35030 else if (EQ (pointer, intern ("hourglass")))
35031 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
35032 else if (EQ (pointer, Qmodeline))
35033 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
35034 else
35035 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35036 }
35037
35038 if (cursor != No_Cursor)
35039 FRAME_RIF (f)->define_frame_cursor (f, cursor);
35040 #endif
35041 }
35042
35043
35044
35045
35046
35047
35048
35049 static void
35050 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
35051 enum window_part area)
35052 {
35053 struct window *w = XWINDOW (window);
35054 struct frame *f = XFRAME (w->frame);
35055 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35056 Emacs_Cursor cursor = No_Cursor;
35057 Lisp_Object pointer = Qnil;
35058 int dx, dy, width, height;
35059 ptrdiff_t charpos;
35060 Lisp_Object string, object = Qnil;
35061 Lisp_Object pos UNINIT;
35062 Lisp_Object mouse_face;
35063 int original_x_pixel = x;
35064 struct glyph * glyph = NULL, * row_start_glyph = NULL;
35065 struct glyph_row *row UNINIT;
35066
35067 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
35068 {
35069 int x0;
35070 struct glyph *end;
35071
35072
35073
35074 string = mode_line_string (w, area, &x, &y, &charpos,
35075 &object, &dx, &dy, &width, &height);
35076
35077 row = (area == ON_MODE_LINE
35078 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
35079 : (area == ON_TAB_LINE
35080 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
35081 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
35082
35083
35084 if (row->mode_line_p && row->enabled_p)
35085 {
35086 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
35087 end = glyph + row->used[TEXT_AREA];
35088
35089 for (x0 = original_x_pixel;
35090 glyph < end && x0 >= glyph->pixel_width;
35091 ++glyph)
35092 x0 -= glyph->pixel_width;
35093
35094 if (glyph >= end)
35095 glyph = NULL;
35096 }
35097 }
35098 else
35099 {
35100 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
35101
35102
35103 string = marginal_area_string (w, area, &x, &y, &charpos,
35104 &object, &dx, &dy, &width, &height);
35105 }
35106
35107 Lisp_Object help = Qnil;
35108
35109 #ifdef HAVE_WINDOW_SYSTEM
35110 if (IMAGEP (object))
35111 {
35112 Lisp_Object image_map, hotspot;
35113 if ((image_map = plist_get (XCDR (object), QCmap),
35114 !NILP (image_map))
35115 && (hotspot = find_hot_spot (image_map, dx, dy),
35116 CONSP (hotspot))
35117 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35118 {
35119 Lisp_Object plist;
35120
35121
35122
35123
35124 hotspot = XCDR (hotspot);
35125 if (CONSP (hotspot)
35126 && (plist = XCAR (hotspot), CONSP (plist)))
35127 {
35128 pointer = plist_get (plist, Qpointer);
35129 if (NILP (pointer))
35130 pointer = Qhand;
35131 help = plist_get (plist, Qhelp_echo);
35132 if (!NILP (help))
35133 {
35134 help_echo_string = help;
35135 XSETWINDOW (help_echo_window, w);
35136 help_echo_object = w->contents;
35137 help_echo_pos = charpos;
35138 }
35139 }
35140 }
35141 if (NILP (pointer))
35142 pointer = plist_get (XCDR (object), QCpointer);
35143 }
35144 #endif
35145
35146
35147
35148
35149 if (STRINGP (string))
35150 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
35151
35152
35153
35154
35155
35156 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
35157 || area == ON_TAB_LINE)
35158 {
35159
35160
35161 if (NILP (help))
35162 {
35163 if (STRINGP (string))
35164 help = Fget_text_property (pos, Qhelp_echo, string);
35165
35166 if (!NILP (help))
35167 {
35168 help_echo_string = help;
35169 XSETWINDOW (help_echo_window, w);
35170 help_echo_object = string;
35171 help_echo_pos = charpos;
35172 }
35173 else if (area == ON_MODE_LINE
35174 && !NILP (w->mode_line_help_echo))
35175 {
35176 help_echo_string = w->mode_line_help_echo;
35177 XSETWINDOW (help_echo_window, w);
35178 help_echo_object = Qnil;
35179 help_echo_pos = -1;
35180 }
35181 }
35182
35183 #ifdef HAVE_WINDOW_SYSTEM
35184
35185 if (FRAME_WINDOW_P (f))
35186 {
35187 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
35188 || minibuf_level
35189 || NILP (Vresize_mini_windows));
35190
35191 if (STRINGP (string))
35192 {
35193 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35194
35195 if (NILP (pointer))
35196 pointer = Fget_text_property (pos, Qpointer, string);
35197
35198
35199 if (NILP (pointer)
35200 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
35201 || area == ON_TAB_LINE))
35202 {
35203 Lisp_Object map;
35204
35205 map = Fget_text_property (pos, Qlocal_map, string);
35206 if (!KEYMAPP (map))
35207 map = Fget_text_property (pos, Qkeymap, string);
35208 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
35209 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35210 }
35211 }
35212 else if (draggable && area == ON_MODE_LINE)
35213 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35214 else if ((area == ON_MODE_LINE
35215 && WINDOW_BOTTOMMOST_P (w)
35216 && !FRAME_HAS_MINIBUF_P (f)
35217 && !NILP (Fframe_parameter
35218 (w->frame, Qdrag_with_mode_line)))
35219 || (((area == ON_HEADER_LINE
35220 && !NILP (Fframe_parameter
35221 (w->frame, Qdrag_with_header_line)))
35222 || (area == ON_TAB_LINE
35223 && !NILP (Fframe_parameter
35224 (w->frame, Qdrag_with_tab_line))))
35225 && WINDOW_TOPMOST_P (w)))
35226 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35227 else
35228 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35229 }
35230 #endif
35231 }
35232
35233
35234 bool mouse_face_shown = false;
35235
35236 if (STRINGP (string))
35237 {
35238 mouse_face = Fget_text_property (pos, Qmouse_face, string);
35239 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
35240 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
35241 || (area == ON_TAB_LINE))
35242 && glyph)
35243 {
35244 Lisp_Object b, e;
35245
35246 struct glyph * tmp_glyph;
35247
35248 int gpos;
35249 int gseq_length;
35250 int total_pixel_width;
35251 ptrdiff_t begpos, endpos, ignore;
35252
35253 int vpos, hpos;
35254
35255 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
35256 Qmouse_face, string, Qnil);
35257 if (NILP (b))
35258 begpos = 0;
35259 else
35260 begpos = XFIXNUM (b);
35261
35262 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
35263 if (NILP (e))
35264 endpos = SCHARS (string);
35265 else
35266 endpos = XFIXNUM (e);
35267
35268
35269
35270
35271
35272
35273
35274
35275
35276
35277
35278 tmp_glyph = row_start_glyph;
35279 while (tmp_glyph < glyph
35280 && (!(EQ (tmp_glyph->object, glyph->object)
35281 && begpos <= tmp_glyph->charpos
35282 && tmp_glyph->charpos < endpos)))
35283 tmp_glyph++;
35284 gpos = glyph - tmp_glyph;
35285
35286
35287
35288
35289
35290
35291 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
35292 tmp_glyph > glyph
35293 && (!(EQ (tmp_glyph->object, glyph->object)
35294 && begpos <= tmp_glyph->charpos
35295 && tmp_glyph->charpos < endpos));
35296 tmp_glyph--)
35297 ;
35298 gseq_length = gpos + (tmp_glyph - glyph) + 1;
35299
35300
35301
35302 total_pixel_width = 0;
35303 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
35304 total_pixel_width += tmp_glyph->pixel_width;
35305
35306
35307
35308
35309 hpos = x - gpos;
35310 vpos = (area == ON_MODE_LINE
35311 ? (w->current_matrix)->nrows - 1
35312 : (area == ON_TAB_LINE
35313 ? 0
35314 : (w->current_matrix->tab_line_p
35315 ? 1
35316 : 0)));
35317
35318
35319
35320 if ( EQ (window, hlinfo->mouse_face_window)
35321 && (!row->reversed_p
35322 ? (hlinfo->mouse_face_beg_col <= hpos
35323 && hpos < hlinfo->mouse_face_end_col)
35324
35325 : (hlinfo->mouse_face_end_col <= hpos
35326 && hpos < hlinfo->mouse_face_beg_col))
35327 && hlinfo->mouse_face_beg_row == vpos )
35328 return;
35329
35330 if (clear_mouse_face (hlinfo))
35331 cursor = No_Cursor;
35332
35333 if (!row->reversed_p)
35334 {
35335 hlinfo->mouse_face_beg_col = hpos;
35336 hlinfo->mouse_face_beg_x = original_x_pixel
35337 - (total_pixel_width + dx);
35338 hlinfo->mouse_face_end_col = hpos + gseq_length;
35339 hlinfo->mouse_face_end_x = 0;
35340 }
35341 else
35342 {
35343
35344
35345 hlinfo->mouse_face_end_col = hpos;
35346 hlinfo->mouse_face_end_x = original_x_pixel
35347 - (total_pixel_width + dx);
35348 hlinfo->mouse_face_beg_col = hpos + gseq_length;
35349 hlinfo->mouse_face_beg_x = 0;
35350 }
35351
35352 hlinfo->mouse_face_beg_row = vpos;
35353 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
35354 hlinfo->mouse_face_past_end = false;
35355 hlinfo->mouse_face_window = window;
35356
35357 hlinfo->mouse_face_face_id =
35358 face_at_string_position (w, string, charpos, 0, &ignore,
35359 glyph->face_id, true, 0);
35360
35361 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35362 mouse_face_shown = true;
35363
35364 if (NILP (pointer))
35365 pointer = Qhand;
35366 }
35367 }
35368
35369
35370
35371 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35372 || area == ON_TAB_LINE) && !mouse_face_shown)
35373 clear_mouse_face (hlinfo);
35374
35375 define_frame_cursor1 (f, cursor, pointer);
35376 }
35377
35378
35379
35380
35381
35382
35383
35384
35385
35386
35387 void
35388 note_mouse_highlight (struct frame *f, int x, int y)
35389 {
35390 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35391 enum window_part part = ON_NOTHING;
35392 Lisp_Object window;
35393 struct window *w;
35394 Emacs_Cursor cursor = No_Cursor;
35395 Lisp_Object pointer = Qnil;
35396 struct buffer *b;
35397
35398
35399 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS) \
35400 || defined (HAVE_ANDROID)
35401 if (popup_activated ())
35402 return;
35403 #endif
35404
35405 #if defined (HAVE_HAIKU)
35406 if (popup_activated_p)
35407 return;
35408 #endif
35409
35410 if (!f->glyphs_initialized_p
35411 || f->pointer_invisible)
35412 return;
35413
35414 hlinfo->mouse_face_mouse_x = x;
35415 hlinfo->mouse_face_mouse_y = y;
35416 hlinfo->mouse_face_mouse_frame = f;
35417
35418 if (hlinfo->mouse_face_defer)
35419 return;
35420
35421
35422 window = window_from_coordinates (f, x, y, &part, true, true);
35423
35424
35425 if (! EQ (window, hlinfo->mouse_face_window)
35426
35427 || (!NILP (hlinfo->mouse_face_window)
35428 && !NILP (window)
35429 && part != ON_TEXT
35430 && part != ON_MODE_LINE
35431 && part != ON_HEADER_LINE
35432 && part != ON_TAB_LINE))
35433 clear_mouse_face (hlinfo);
35434
35435
35436 help_echo_string = Qnil;
35437
35438
35439 if (!FRAME_WINDOW_P (f)
35440 && (y >= FRAME_MENU_BAR_LINES (f)
35441 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35442 {
35443 int prop_idx;
35444 bool ignore;
35445 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35446
35447 if (!NILP (caption))
35448 {
35449 help_echo_object = help_echo_window = Qnil;
35450 help_echo_pos = -1;
35451 help_echo_string = AREF (f->tab_bar_items,
35452 prop_idx * TAB_BAR_ITEM_NSLOTS
35453 + TAB_BAR_ITEM_HELP);
35454 if (NILP (help_echo_string))
35455 help_echo_string = caption;
35456 }
35457 }
35458
35459 #ifdef HAVE_WINDOW_SYSTEM
35460
35461
35462 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35463 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35464 {
35465 enum internal_border_part part = frame_internal_border_part (f, x, y);
35466
35467 switch (part)
35468 {
35469 case INTERNAL_BORDER_NONE:
35470 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35471
35472 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35473 break;
35474 case INTERNAL_BORDER_LEFT_EDGE:
35475 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35476 break;
35477 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35478 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35479 break;
35480 case INTERNAL_BORDER_TOP_EDGE:
35481 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35482 break;
35483 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35484 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35485 break;
35486 case INTERNAL_BORDER_RIGHT_EDGE:
35487 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35488 break;
35489 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35490 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35491 break;
35492 case INTERNAL_BORDER_BOTTOM_EDGE:
35493 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35494 break;
35495 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35496 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35497 break;
35498 default:
35499
35500 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35501 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35502 }
35503
35504 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35505 {
35506
35507 help_echo_string = build_string ("drag-mouse-1: resize frame");
35508 goto set_cursor;
35509 }
35510 }
35511 #endif
35512
35513
35514 if (!WINDOWP (window))
35515 return;
35516
35517
35518 w = XWINDOW (window);
35519 frame_to_window_pixel_xy (w, &x, &y);
35520
35521 #if defined (HAVE_WINDOW_SYSTEM)
35522
35523
35524 if (EQ (window, f->tab_bar_window))
35525 {
35526 note_tab_bar_highlight (f, x, y);
35527 if (tab_bar__dragging_in_progress)
35528 {
35529 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35530 goto set_cursor;
35531 }
35532 else
35533 return;
35534 }
35535 else
35536 {
35537
35538
35539
35540
35541 f->last_tab_bar_item = -1;
35542 }
35543 #endif
35544
35545 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35546
35547
35548 if (EQ (window, f->tool_bar_window))
35549 {
35550 note_tool_bar_highlight (f, x, y);
35551 return;
35552 }
35553 #endif
35554
35555
35556 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35557 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35558 {
35559 note_mode_line_or_margin_highlight (window, x, y, part);
35560
35561 #ifdef HAVE_WINDOW_SYSTEM
35562 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35563 {
35564 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35565
35566 goto set_cursor;
35567 }
35568 else
35569 #endif
35570 return;
35571 }
35572
35573 #ifdef HAVE_WINDOW_SYSTEM
35574 if (part == ON_VERTICAL_BORDER)
35575 {
35576 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35577 help_echo_string = build_string ("drag-mouse-1: resize");
35578 goto set_cursor;
35579 }
35580 else if (part == ON_RIGHT_DIVIDER)
35581 {
35582 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35583 help_echo_string = build_string ("drag-mouse-1: resize");
35584 goto set_cursor;
35585 }
35586 else if (part == ON_BOTTOM_DIVIDER)
35587 if (! WINDOW_BOTTOMMOST_P (w)
35588 || minibuf_level
35589 || NILP (Vresize_mini_windows))
35590 {
35591 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35592 help_echo_string = build_string ("drag-mouse-1: resize");
35593 goto set_cursor;
35594 }
35595 else
35596 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35597 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35598 || part == ON_VERTICAL_SCROLL_BAR
35599 || part == ON_HORIZONTAL_SCROLL_BAR)
35600 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35601 else
35602 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35603 #endif
35604
35605
35606
35607 b = XBUFFER (w->contents);
35608 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35609 {
35610 int hpos, vpos, dx, dy, area = LAST_AREA;
35611 ptrdiff_t pos;
35612 struct glyph *glyph;
35613 Lisp_Object object;
35614 Lisp_Object mouse_face = Qnil, position;
35615 Lisp_Object *overlay_vec = NULL;
35616 ptrdiff_t i, noverlays;
35617 struct buffer *obuf;
35618 ptrdiff_t obegv, ozv;
35619 bool same_region;
35620
35621
35622 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35623
35624 #ifdef HAVE_WINDOW_SYSTEM
35625
35626 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35627 {
35628 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35629 if (img != NULL && IMAGEP (img->spec))
35630 {
35631 Lisp_Object image_map, hotspot;
35632 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35633 !NILP (image_map))
35634 && (hotspot = find_hot_spot (image_map,
35635 glyph->slice.img.x + dx,
35636 glyph->slice.img.y + dy),
35637 CONSP (hotspot))
35638 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35639 {
35640 Lisp_Object plist;
35641
35642
35643
35644
35645
35646 hotspot = XCDR (hotspot);
35647 if (CONSP (hotspot)
35648 && (plist = XCAR (hotspot), CONSP (plist)))
35649 {
35650 pointer = plist_get (plist, Qpointer);
35651 if (NILP (pointer))
35652 pointer = Qhand;
35653 help_echo_string = plist_get (plist, Qhelp_echo);
35654 if (!NILP (help_echo_string))
35655 {
35656 help_echo_window = window;
35657 help_echo_object = glyph->object;
35658 help_echo_pos = glyph->charpos;
35659 }
35660 }
35661 }
35662 if (NILP (pointer))
35663 pointer = plist_get (XCDR (img->spec), QCpointer);
35664 }
35665 }
35666 #endif
35667
35668
35669 if (glyph == NULL
35670 || area != TEXT_AREA
35671 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35672
35673
35674
35675
35676
35677 || NILP (glyph->object)
35678
35679
35680
35681
35682 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35683 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35684 && glyph->type == STRETCH_GLYPH
35685 && glyph->avoid_cursor_p))
35686 {
35687 if (clear_mouse_face (hlinfo))
35688 cursor = No_Cursor;
35689 if (FRAME_WINDOW_P (f) && NILP (pointer))
35690 {
35691 #ifdef HAVE_WINDOW_SYSTEM
35692 if (area != TEXT_AREA)
35693 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35694 else
35695 pointer = Vvoid_text_area_pointer;
35696 #endif
35697 }
35698 goto set_cursor;
35699 }
35700
35701 pos = glyph->charpos;
35702 object = glyph->object;
35703 if (!STRINGP (object) && !BUFFERP (object))
35704 goto set_cursor;
35705
35706
35707 if (BUFFERP (object) && pos > BUF_Z (b))
35708 goto set_cursor;
35709
35710
35711
35712 obuf = current_buffer;
35713 current_buffer = b;
35714 obegv = BEGV;
35715 ozv = ZV;
35716 BEGV = BEG;
35717 ZV = Z;
35718
35719
35720 position = make_fixnum (pos);
35721
35722 USE_SAFE_ALLOCA;
35723
35724 if (BUFFERP (object))
35725 {
35726
35727 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35728
35729 noverlays = sort_overlays (overlay_vec, noverlays, w);
35730 }
35731 else
35732 noverlays = 0;
35733
35734 if (NILP (Vmouse_highlight))
35735 {
35736 clear_mouse_face (hlinfo);
35737 goto check_help_echo;
35738 }
35739
35740 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35741
35742 if (same_region)
35743 cursor = No_Cursor;
35744
35745
35746 if (! same_region
35747
35748
35749
35750
35751
35752 || (!hlinfo->mouse_face_hidden
35753 && OVERLAYP (hlinfo->mouse_face_overlay)
35754
35755 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35756 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35757 {
35758
35759 Lisp_Object overlay = Qnil;
35760 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35761 {
35762 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35763 if (!NILP (mouse_face))
35764 overlay = overlay_vec[i];
35765 }
35766
35767
35768
35769 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35770 goto check_help_echo;
35771
35772
35773 if (clear_mouse_face (hlinfo))
35774 cursor = No_Cursor;
35775
35776
35777 hlinfo->mouse_face_overlay = overlay;
35778
35779
35780 if (NILP (overlay))
35781 mouse_face = Fget_text_property (position, Qmouse_face, object);
35782
35783
35784
35785 if (!NILP (mouse_face) && STRINGP (object))
35786 {
35787
35788
35789 Lisp_Object s, e;
35790 ptrdiff_t ignore;
35791
35792 s = Fprevious_single_property_change
35793 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35794 e = Fnext_single_property_change
35795 (position, Qmouse_face, object, Qnil);
35796 if (NILP (s))
35797 s = make_fixnum (0);
35798 if (NILP (e))
35799 e = make_fixnum (SCHARS (object));
35800 mouse_face_from_string_pos (w, hlinfo, object,
35801 XFIXNUM (s), XFIXNUM (e));
35802 hlinfo->mouse_face_past_end = false;
35803 hlinfo->mouse_face_window = window;
35804 hlinfo->mouse_face_face_id
35805 = face_at_string_position (w, object, pos, 0, &ignore,
35806 glyph->face_id, true, 0);
35807 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35808 cursor = No_Cursor;
35809 }
35810 else
35811 {
35812
35813
35814 Lisp_Object buffer UNINIT;
35815 Lisp_Object disp_string UNINIT;
35816
35817 if (STRINGP (object))
35818 {
35819
35820
35821 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35822 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35823 pos = string_buffer_position (object, start);
35824 if (pos > 0)
35825 {
35826 mouse_face = get_char_property_and_overlay
35827 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35828 buffer = w->contents;
35829 disp_string = object;
35830 }
35831 }
35832 else
35833 {
35834 buffer = object;
35835 disp_string = Qnil;
35836 }
35837
35838 if (!NILP (mouse_face))
35839 {
35840 Lisp_Object before, after;
35841 Lisp_Object before_string, after_string;
35842
35843
35844
35845
35846
35847
35848
35849
35850
35851
35852 Lisp_Object lim1
35853 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35854 ? Fmarker_position (w->start)
35855 : Qnil;
35856 Lisp_Object lim2
35857 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35858 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35859 - w->window_end_pos)
35860 : Qnil;
35861
35862 if (NILP (overlay))
35863 {
35864
35865 before = Fprevious_single_property_change
35866 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35867 after = Fnext_single_property_change
35868 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35869 before_string = after_string = Qnil;
35870 }
35871 else
35872 {
35873
35874 before = Foverlay_start (overlay);
35875 after = Foverlay_end (overlay);
35876 before_string = Foverlay_get (overlay, Qbefore_string);
35877 after_string = Foverlay_get (overlay, Qafter_string);
35878
35879 if (!STRINGP (before_string)) before_string = Qnil;
35880 if (!STRINGP (after_string)) after_string = Qnil;
35881 }
35882
35883 mouse_face_from_buffer_pos (window, hlinfo, pos,
35884 NILP (before)
35885 ? 1
35886 : XFIXNAT (before),
35887 NILP (after)
35888 ? BUF_Z (XBUFFER (buffer))
35889 : XFIXNAT (after),
35890 before_string, after_string,
35891 disp_string);
35892 cursor = No_Cursor;
35893 }
35894 }
35895 }
35896
35897 check_help_echo:
35898
35899
35900 if (NILP (help_echo_string)) {
35901 Lisp_Object help, overlay;
35902
35903
35904 help = overlay = Qnil;
35905 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35906 {
35907 overlay = overlay_vec[i];
35908 help = Foverlay_get (overlay, Qhelp_echo);
35909 }
35910
35911 if (!NILP (help))
35912 {
35913 help_echo_string = help;
35914 help_echo_window = window;
35915 help_echo_object = overlay;
35916 help_echo_pos = pos;
35917 }
35918 else
35919 {
35920 Lisp_Object obj = glyph->object;
35921 ptrdiff_t charpos = glyph->charpos;
35922
35923
35924 if (STRINGP (obj)
35925 && charpos >= 0
35926 && charpos < SCHARS (obj))
35927 {
35928 help = Fget_text_property (make_fixnum (charpos),
35929 Qhelp_echo, obj);
35930 if (NILP (help))
35931 {
35932
35933
35934 struct glyph_row *r
35935 = MATRIX_ROW (w->current_matrix, vpos);
35936 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35937 ptrdiff_t p = string_buffer_position (obj, start);
35938 if (p > 0)
35939 {
35940 help = Fget_char_property (make_fixnum (p),
35941 Qhelp_echo, w->contents);
35942 if (!NILP (help))
35943 {
35944 charpos = p;
35945 obj = w->contents;
35946 }
35947 }
35948 }
35949 }
35950 else if (BUFFERP (obj)
35951 && charpos >= BEGV
35952 && charpos < ZV)
35953 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35954 obj);
35955
35956 if (!NILP (help))
35957 {
35958 help_echo_string = help;
35959 help_echo_window = window;
35960 help_echo_object = obj;
35961 help_echo_pos = charpos;
35962 }
35963 }
35964 }
35965
35966 #ifdef HAVE_WINDOW_SYSTEM
35967
35968 if (FRAME_WINDOW_P (f) && NILP (pointer))
35969 {
35970
35971 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35972 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35973
35974 if (NILP (pointer))
35975 {
35976 Lisp_Object obj = glyph->object;
35977 ptrdiff_t charpos = glyph->charpos;
35978
35979
35980 if (STRINGP (obj)
35981 && charpos >= 0
35982 && charpos < SCHARS (obj))
35983 {
35984 pointer = Fget_text_property (make_fixnum (charpos),
35985 Qpointer, obj);
35986 if (NILP (pointer))
35987 {
35988
35989
35990 struct glyph_row *r
35991 = MATRIX_ROW (w->current_matrix, vpos);
35992 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35993 ptrdiff_t p = string_buffer_position (obj, start);
35994 if (p > 0)
35995 pointer = Fget_char_property (make_fixnum (p),
35996 Qpointer, w->contents);
35997 }
35998 }
35999 else if (BUFFERP (obj)
36000 && charpos >= BEGV
36001 && charpos < ZV)
36002 pointer = Fget_text_property (make_fixnum (charpos),
36003 Qpointer, obj);
36004 }
36005 }
36006 #endif
36007
36008 BEGV = obegv;
36009 ZV = ozv;
36010 current_buffer = obuf;
36011 SAFE_FREE ();
36012 }
36013
36014 set_cursor:
36015 define_frame_cursor1 (f, cursor, pointer);
36016 }
36017
36018
36019
36020
36021
36022
36023
36024 void
36025 gui_clear_window_mouse_face (struct window *w)
36026 {
36027 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
36028 Lisp_Object window;
36029
36030 block_input ();
36031 XSETWINDOW (window, w);
36032 if (EQ (window, hlinfo->mouse_face_window))
36033 clear_mouse_face (hlinfo);
36034 unblock_input ();
36035 }
36036
36037
36038
36039
36040
36041
36042 void
36043 cancel_mouse_face (struct frame *f)
36044 {
36045 Lisp_Object window;
36046 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36047
36048 window = hlinfo->mouse_face_window;
36049 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
36050 reset_mouse_highlight (hlinfo);
36051 }
36052
36053
36054
36055
36056
36057
36058
36059 #ifdef HAVE_WINDOW_SYSTEM
36060
36061
36062
36063
36064 static void
36065 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
36066 enum glyph_row_area area)
36067 {
36068 struct glyph *first = row->glyphs[area];
36069 struct glyph *end = row->glyphs[area] + row->used[area];
36070 struct glyph *last;
36071 int first_x, start_x, x;
36072
36073 if (area == TEXT_AREA && row->fill_line_p)
36074
36075 draw_glyphs (w, row->x, row, area,
36076 0, row->used[area],
36077 DRAW_NORMAL_TEXT, 0);
36078 else
36079 {
36080
36081
36082
36083 start_x = window_box_left_offset (w, area);
36084 x = start_x;
36085 if (area == TEXT_AREA)
36086 x += row->x;
36087
36088
36089 while (first < end
36090 && x + first->pixel_width < r->x)
36091 {
36092 x += first->pixel_width;
36093 ++first;
36094 }
36095
36096
36097 last = first;
36098 first_x = x;
36099
36100
36101
36102 int r_end = r->x + r->width;
36103 while (last < end && x < r_end)
36104 {
36105 x += last->pixel_width;
36106 ++last;
36107 }
36108
36109
36110 if (last > first)
36111 draw_glyphs (w, first_x - start_x, row, area,
36112 first - row->glyphs[area], last - row->glyphs[area],
36113 DRAW_NORMAL_TEXT, 0);
36114 }
36115 }
36116
36117
36118
36119
36120
36121
36122 static bool
36123 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
36124 {
36125 eassert (row->enabled_p);
36126
36127 if (row->mode_line_p || w->pseudo_window_p)
36128 draw_glyphs (w, 0, row, TEXT_AREA,
36129 0, row->used[TEXT_AREA],
36130 DRAW_NORMAL_TEXT, 0);
36131 else
36132 {
36133 if (row->used[LEFT_MARGIN_AREA])
36134 expose_area (w, row, r, LEFT_MARGIN_AREA);
36135 if (row->used[TEXT_AREA])
36136 expose_area (w, row, r, TEXT_AREA);
36137 if (row->used[RIGHT_MARGIN_AREA])
36138 expose_area (w, row, r, RIGHT_MARGIN_AREA);
36139 draw_row_fringe_bitmaps (w, row);
36140 }
36141
36142 return row->mouse_face_p;
36143 }
36144
36145
36146
36147
36148
36149
36150
36151
36152
36153
36154 static void
36155 expose_overlaps (struct window *w,
36156 struct glyph_row *first_overlapping_row,
36157 struct glyph_row *last_overlapping_row,
36158 const Emacs_Rectangle *r)
36159 {
36160 struct glyph_row *row;
36161
36162 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
36163 if (row->overlapping_p)
36164 {
36165 eassert (row->enabled_p && !row->mode_line_p);
36166
36167 row->clip = r;
36168 if (row->used[LEFT_MARGIN_AREA])
36169 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
36170
36171 if (row->used[TEXT_AREA])
36172 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
36173
36174 if (row->used[RIGHT_MARGIN_AREA])
36175 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
36176 row->clip = NULL;
36177 }
36178 }
36179
36180
36181
36182
36183 static bool
36184 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
36185 {
36186 Emacs_Rectangle cr, result;
36187 struct glyph *cursor_glyph;
36188 struct glyph_row *row;
36189
36190 if (w->phys_cursor.vpos >= 0
36191 && w->phys_cursor.vpos < w->current_matrix->nrows
36192 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
36193 row->enabled_p)
36194 && row->cursor_in_fringe_p)
36195 {
36196
36197 cr.x = window_box_right_offset (w,
36198 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
36199 ? RIGHT_MARGIN_AREA
36200 : TEXT_AREA));
36201 cr.y = row->y;
36202 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
36203 cr.height = row->height;
36204 return gui_intersect_rectangles (&cr, r, &result);
36205 }
36206
36207 cursor_glyph = get_phys_cursor_glyph (w);
36208 if (cursor_glyph)
36209 {
36210
36211
36212 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
36213 cr.y = w->phys_cursor.y;
36214 cr.width = cursor_glyph->pixel_width;
36215 cr.height = w->phys_cursor_height;
36216
36217
36218 return gui_intersect_rectangles (&cr, r, &result);
36219 }
36220
36221 return false;
36222 }
36223
36224
36225
36226
36227
36228
36229 void
36230 gui_draw_vertical_border (struct window *w)
36231 {
36232 struct frame *f = XFRAME (WINDOW_FRAME (w));
36233
36234
36235
36236
36237
36238
36239
36240
36241
36242 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
36243 return;
36244
36245
36246
36247
36248 if (!WINDOW_RIGHTMOST_P (w)
36249 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
36250 {
36251 int x0, x1, y0, y1;
36252
36253 window_box_edges (w, &x0, &y0, &x1, &y1);
36254 y1 -= 1;
36255
36256 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36257 x1 -= 1;
36258
36259 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
36260 }
36261
36262 if (!WINDOW_LEFTMOST_P (w)
36263 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
36264 {
36265 int x0, x1, y0, y1;
36266
36267 window_box_edges (w, &x0, &y0, &x1, &y1);
36268 y1 -= 1;
36269
36270 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36271 x0 -= 1;
36272
36273 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
36274 }
36275 }
36276
36277
36278
36279
36280 void
36281 gui_draw_right_divider (struct window *w)
36282 {
36283 struct frame *f = WINDOW_XFRAME (w);
36284
36285 if (w->mini || w->pseudo_window_p)
36286 return;
36287 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36288 {
36289 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
36290 int x1 = WINDOW_RIGHT_EDGE_X (w);
36291 int y0 = WINDOW_TOP_EDGE_Y (w);
36292 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36293
36294
36295
36296 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
36297 && !NILP (w->parent)
36298 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
36299 && !NILP (w->next))
36300 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36301
36302 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36303 }
36304 }
36305
36306 static void
36307 gui_draw_bottom_divider (struct window *w)
36308 {
36309 struct frame *f = XFRAME (WINDOW_FRAME (w));
36310
36311 if (w->mini || w->pseudo_window_p)
36312 return;
36313 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36314 {
36315 int x0 = WINDOW_LEFT_EDGE_X (w);
36316 int x1 = WINDOW_RIGHT_EDGE_X (w);
36317 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36318 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36319 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
36320
36321
36322
36323 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
36324 && p
36325 && ((WINDOW_VERTICAL_COMBINATION_P (p)
36326 && !NILP (w->next))
36327 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
36328 && NILP (w->next)
36329 && !NILP (p->parent)
36330 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
36331 && !NILP (XWINDOW (p->parent)->next))))
36332 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
36333
36334 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36335 }
36336 }
36337
36338
36339
36340
36341
36342
36343 static bool
36344 expose_window (struct window *w, const Emacs_Rectangle *fr)
36345 {
36346 struct frame *f = XFRAME (w->frame);
36347 Emacs_Rectangle wr, r;
36348 bool mouse_face_overwritten_p = false;
36349
36350
36351
36352
36353
36354 if (w->current_matrix == NULL)
36355 return false;
36356
36357
36358
36359
36360 if (w->must_be_updated_p)
36361 {
36362 SET_FRAME_GARBAGED (f);
36363 return false;
36364 }
36365
36366
36367 wr.x = WINDOW_LEFT_EDGE_X (w);
36368 wr.y = WINDOW_TOP_EDGE_Y (w);
36369 wr.width = WINDOW_PIXEL_WIDTH (w);
36370 wr.height = WINDOW_PIXEL_HEIGHT (w);
36371
36372 if (gui_intersect_rectangles (fr, &wr, &r))
36373 {
36374 int yb = window_text_bottom_y (w);
36375 struct glyph_row *row;
36376 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36377
36378 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36379 r.x, r.y, r.width, r.height);
36380
36381
36382 r.x -= WINDOW_LEFT_EDGE_X (w);
36383 r.y -= WINDOW_TOP_EDGE_Y (w);
36384
36385
36386 bool cursor_cleared_p = (!w->pseudo_window_p
36387 && phys_cursor_in_rect_p (w, &r));
36388 if (cursor_cleared_p)
36389 gui_clear_cursor (w);
36390
36391
36392
36393
36394
36395
36396 bool phys_cursor_on_p = w->phys_cursor_on_p;
36397
36398
36399
36400
36401 int r_bottom = r.y + r.height;
36402
36403
36404
36405
36406
36407 bool buffer_changed = false;
36408 struct buffer *oldbuf = current_buffer;
36409 if (!w->pseudo_window_p)
36410 {
36411 set_buffer_internal_1 (XBUFFER (w->contents));
36412 buffer_changed = true;
36413 }
36414
36415
36416 first_overlapping_row = last_overlapping_row = NULL;
36417 for (row = w->current_matrix->rows;
36418 row->enabled_p;
36419 ++row)
36420 {
36421 int y0 = row->y;
36422 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36423
36424 if ((y0 >= r.y && y0 < r_bottom)
36425 || (y1 > r.y && y1 < r_bottom)
36426 || (r.y >= y0 && r.y < y1)
36427 || (r_bottom > y0 && r_bottom < y1))
36428 {
36429
36430
36431 if (row->overlapping_p && !row->mode_line_p)
36432 {
36433 if (first_overlapping_row == NULL)
36434 first_overlapping_row = row;
36435 last_overlapping_row = row;
36436 }
36437
36438 row->clip = fr;
36439 if (expose_line (w, row, &r))
36440 mouse_face_overwritten_p = true;
36441 row->clip = NULL;
36442 }
36443 else if (row->overlapping_p)
36444 {
36445
36446 if (y0 < r.y
36447 ? y0 + row->phys_height > r.y
36448 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36449 {
36450 if (first_overlapping_row == NULL)
36451 first_overlapping_row = row;
36452 last_overlapping_row = row;
36453 }
36454 }
36455
36456 if (y1 >= yb)
36457 break;
36458 }
36459
36460 if (buffer_changed)
36461 set_buffer_internal_1 (oldbuf);
36462
36463
36464 if (window_wants_mode_line (w)
36465 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36466 row->enabled_p)
36467 && row->y < r_bottom)
36468 {
36469 if (expose_line (w, row, &r))
36470 mouse_face_overwritten_p = true;
36471 }
36472
36473 if (!w->pseudo_window_p)
36474 {
36475
36476 if (first_overlapping_row)
36477 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36478 fr);
36479
36480
36481 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36482 gui_draw_right_divider (w);
36483 else
36484 gui_draw_vertical_border (w);
36485
36486 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36487 gui_draw_bottom_divider (w);
36488
36489
36490 if (cursor_cleared_p
36491 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36492 update_window_cursor (w, true);
36493 }
36494 }
36495
36496 return mouse_face_overwritten_p;
36497 }
36498
36499
36500
36501
36502
36503
36504
36505 static bool
36506 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36507 {
36508 struct frame *f = XFRAME (w->frame);
36509 bool mouse_face_overwritten_p = false;
36510
36511 while (w && !FRAME_GARBAGED_P (f))
36512 {
36513 mouse_face_overwritten_p
36514 |= (WINDOWP (w->contents)
36515 ? expose_window_tree (XWINDOW (w->contents), r)
36516 : expose_window (w, r));
36517
36518 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36519 }
36520
36521 return mouse_face_overwritten_p;
36522 }
36523
36524
36525
36526
36527
36528
36529
36530
36531 void
36532 expose_frame (struct frame *f, int x, int y, int w, int h)
36533 {
36534 Emacs_Rectangle r;
36535 bool mouse_face_overwritten_p = false;
36536
36537 if (FRAME_GARBAGED_P (f))
36538 {
36539 redisplay_trace ("expose_frame garbaged\n");
36540 return;
36541 }
36542
36543
36544
36545
36546 if (FRAME_FACE_CACHE (f) == NULL
36547 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36548 {
36549 redisplay_trace ("expose_frame no faces\n");
36550 return;
36551 }
36552
36553 if (w == 0 || h == 0)
36554 {
36555 r.x = r.y = 0;
36556 r.width = FRAME_TEXT_WIDTH (f);
36557 r.height = FRAME_TEXT_HEIGHT (f);
36558 }
36559 else
36560 {
36561 r.x = x;
36562 r.y = y;
36563 r.width = w;
36564 r.height = h;
36565 }
36566
36567 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36568 r.x, r.y, r.width, r.height);
36569 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36570
36571 if (WINDOWP (f->tab_bar_window))
36572 mouse_face_overwritten_p
36573 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36574
36575 #ifndef HAVE_EXT_TOOL_BAR
36576 if (WINDOWP (f->tool_bar_window))
36577 mouse_face_overwritten_p
36578 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36579 #endif
36580
36581 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
36582 if (WINDOWP (f->menu_bar_window))
36583 mouse_face_overwritten_p
36584 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36585 #endif
36586
36587
36588
36589
36590
36591
36592
36593
36594
36595
36596
36597
36598
36599
36600 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36601 {
36602 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36603 if (f == hlinfo->mouse_face_mouse_frame)
36604 {
36605 int mouse_x = hlinfo->mouse_face_mouse_x;
36606 int mouse_y = hlinfo->mouse_face_mouse_y;
36607 clear_mouse_face (hlinfo);
36608 note_mouse_highlight (f, mouse_x, mouse_y);
36609 }
36610 }
36611 }
36612
36613
36614
36615
36616
36617
36618
36619 bool
36620 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36621 Emacs_Rectangle *result)
36622 {
36623 const Emacs_Rectangle *left, *right;
36624 const Emacs_Rectangle *upper, *lower;
36625 bool intersection_p = false;
36626
36627
36628 if (r1->x < r2->x)
36629 left = r1, right = r2;
36630 else
36631 left = r2, right = r1;
36632
36633
36634
36635 if (right->x <= left->x + left->width)
36636 {
36637 result->x = right->x;
36638
36639
36640
36641 result->width = (min (left->x + left->width, right->x + right->width)
36642 - result->x);
36643
36644
36645 if (r1->y < r2->y)
36646 upper = r1, lower = r2;
36647 else
36648 upper = r2, lower = r1;
36649
36650
36651
36652 if (lower->y <= upper->y + upper->height)
36653 {
36654 result->y = lower->y;
36655
36656
36657
36658 result->height = (min (lower->y + lower->height,
36659 upper->y + upper->height)
36660 - result->y);
36661 intersection_p = true;
36662 }
36663 }
36664
36665 return intersection_p;
36666 }
36667
36668
36669
36670
36671
36672
36673 void
36674 gui_union_rectangles (const Emacs_Rectangle *a, const Emacs_Rectangle *b,
36675 Emacs_Rectangle *result)
36676 {
36677 struct gui_box a_box, b_box, result_box;
36678
36679
36680
36681 if (!a->width || !a->height)
36682 {
36683 *result = *b;
36684 return;
36685 }
36686 else if (!b->width || !b->height)
36687 {
36688 *result = *a;
36689 return;
36690 }
36691
36692
36693 a_box.x1 = a->x;
36694 a_box.y1 = a->y;
36695 a_box.x2 = a->x + a->width;
36696 a_box.y2 = a->y + a->height;
36697
36698 b_box.x1 = b->x;
36699 b_box.y1 = b->y;
36700 b_box.x2 = b->x + b->width;
36701 b_box.y2 = b->y + b->height;
36702
36703
36704 result_box.x1 = min (a_box.x1, b_box.x1);
36705 result_box.y1 = min (a_box.y1, b_box.y1);
36706 result_box.x2 = max (a_box.x2, b_box.x2);
36707 result_box.y2 = max (a_box.y2, b_box.y2);
36708
36709
36710
36711 result->x = result_box.x1;
36712 result->y = result_box.y1;
36713 result->width = result_box.x2 - result_box.x1;
36714 result->height = result_box.y2 - result_box.y1;
36715 }
36716
36717 #endif
36718
36719
36720
36721
36722
36723
36724 void
36725 syms_of_xdisp (void)
36726 {
36727 Vwith_echo_area_save_vector = Qnil;
36728 staticpro (&Vwith_echo_area_save_vector);
36729
36730 Vmessage_stack = Qnil;
36731 staticpro (&Vmessage_stack);
36732
36733
36734 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36735
36736 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36737
36738 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36739 scroll_minibuffer_conservatively,
36740 doc:
36741
36742 );
36743 scroll_minibuffer_conservatively = true;
36744
36745 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36746 doc:
36747
36748
36749
36750
36751
36752 );
36753 inhibit_message = false;
36754
36755 message_dolog_marker1 = Fmake_marker ();
36756 staticpro (&message_dolog_marker1);
36757 message_dolog_marker2 = Fmake_marker ();
36758 staticpro (&message_dolog_marker2);
36759 message_dolog_marker3 = Fmake_marker ();
36760 staticpro (&message_dolog_marker3);
36761
36762 defsubr (&Sset_buffer_redisplay);
36763 #ifdef GLYPH_DEBUG
36764 defsubr (&Sdump_frame_glyph_matrix);
36765 defsubr (&Sdump_glyph_matrix);
36766 defsubr (&Sdump_glyph_row);
36767 defsubr (&Sdump_tab_bar_row);
36768 defsubr (&Sdump_tool_bar_row);
36769 defsubr (&Strace_redisplay);
36770 defsubr (&Strace_to_stderr);
36771 #endif
36772 #ifdef HAVE_WINDOW_SYSTEM
36773 defsubr (&Stab_bar_height);
36774 defsubr (&Stool_bar_height);
36775 defsubr (&Slookup_image_map);
36776 #endif
36777 defsubr (&Sline_pixel_height);
36778 defsubr (&Sformat_mode_line);
36779 defsubr (&Sinvisible_p);
36780 defsubr (&Scurrent_bidi_paragraph_direction);
36781 defsubr (&Swindow_text_pixel_size);
36782 defsubr (&Sbuffer_text_pixel_size);
36783 defsubr (&Smove_point_visually);
36784 defsubr (&Sbidi_find_overridden_directionality);
36785 defsubr (&Sdisplay__line_is_continued_p);
36786 defsubr (&Sget_display_property);
36787 defsubr (&Slong_line_optimizations_p);
36788
36789 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36790 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36791 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36792 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36793 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36794 DEFSYM (Qeval, "eval");
36795 DEFSYM (QCdata, ":data");
36796
36797
36798 DEFSYM (Qdisplay, "display");
36799 DEFSYM (Qspace_width, "space-width");
36800 DEFSYM (Qraise, "raise");
36801 DEFSYM (Qslice, "slice");
36802 DEFSYM (Qspace, "space");
36803 DEFSYM (Qmargin, "margin");
36804 DEFSYM (Qpointer, "pointer");
36805 DEFSYM (Qleft_margin, "left-margin");
36806 DEFSYM (Qright_margin, "right-margin");
36807 DEFSYM (Qcenter, "center");
36808 DEFSYM (Qline_height, "line-height");
36809 DEFSYM (QCalign_to, ":align-to");
36810 DEFSYM (QCrelative_width, ":relative-width");
36811 DEFSYM (QCrelative_height, ":relative-height");
36812 DEFSYM (QCeval, ":eval");
36813 DEFSYM (QCpropertize, ":propertize");
36814 DEFSYM (QCfile, ":file");
36815 DEFSYM (Qfontified, "fontified");
36816 DEFSYM (Qfontification_functions, "fontification-functions");
36817 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36818 "long-line-optimizations-in-fontification-functions");
36819
36820
36821
36822 DEFSYM (Qdisable_eval, "disable-eval");
36823
36824
36825 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36826
36827
36828 DEFSYM (Qline_number, "line-number");
36829 DEFSYM (Qline_number_current_line, "line-number-current-line");
36830 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36831 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36832
36833 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36834
36835
36836 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36837
36838
36839 DEFSYM (Qescape_glyph, "escape-glyph");
36840
36841
36842
36843 DEFSYM (Qnobreak_space, "nobreak-space");
36844 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36845
36846
36847
36848 DEFSYM (Qimage, "image");
36849
36850
36851 DEFSYM (Qtext, "text");
36852 DEFSYM (Qboth, "both");
36853 DEFSYM (Qboth_horiz, "both-horiz");
36854 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36855
36856
36857 DEFSYM (QCmap, ":map");
36858 DEFSYM (QCpointer, ":pointer");
36859 DEFSYM (Qrect, "rect");
36860 DEFSYM (Qcircle, "circle");
36861 DEFSYM (Qpoly, "poly");
36862
36863 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36864
36865 DEFSYM (Qgrow_only, "grow-only");
36866 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36867 DEFSYM (Qposition, "position");
36868 DEFSYM (Qbuffer_position, "buffer-position");
36869 DEFSYM (Qobject, "object");
36870
36871
36872 DEFSYM (Qbar, "bar");
36873 DEFSYM (Qhbar, "hbar");
36874 DEFSYM (Qbox, "box");
36875 DEFSYM (Qhollow, "hollow");
36876
36877
36878 DEFSYM (Qhand, "hand");
36879 DEFSYM (Qarrow, "arrow");
36880
36881
36882 DEFSYM (Qdragging, "dragging");
36883 DEFSYM (Qdropping, "dropping");
36884 DEFSYM (Qdrag_source, "drag-source");
36885
36886 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36887 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36888 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36889
36890 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36891
36892 list_of_error = list1 (Qerror);
36893 staticpro (&list_of_error);
36894
36895
36896
36897
36898
36899 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36900 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36901
36902
36903
36904 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36905 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36906
36907 echo_buffer[0] = echo_buffer[1] = Qnil;
36908 staticpro (&echo_buffer[0]);
36909 staticpro (&echo_buffer[1]);
36910
36911 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36912 staticpro (&echo_area_buffer[0]);
36913 staticpro (&echo_area_buffer[1]);
36914
36915 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36916 doc:
36917
36918
36919
36920 );
36921 Vmessages_buffer_name = build_string ("*Messages*");
36922
36923 mode_line_proptrans_alist = Qnil;
36924 staticpro (&mode_line_proptrans_alist);
36925 mode_line_string_list = Qnil;
36926 staticpro (&mode_line_string_list);
36927 mode_line_string_face = Qnil;
36928 staticpro (&mode_line_string_face);
36929 mode_line_string_face_prop = Qnil;
36930 staticpro (&mode_line_string_face_prop);
36931 Vmode_line_unwind_vector = Qnil;
36932 staticpro (&Vmode_line_unwind_vector);
36933
36934 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36935
36936 help_echo_string = Qnil;
36937 staticpro (&help_echo_string);
36938 help_echo_object = Qnil;
36939 staticpro (&help_echo_object);
36940 help_echo_window = Qnil;
36941 staticpro (&help_echo_window);
36942 previous_help_echo_string = Qnil;
36943 staticpro (&previous_help_echo_string);
36944 help_echo_pos = -1;
36945
36946 DEFSYM (Qright_to_left, "right-to-left");
36947 DEFSYM (Qleft_to_right, "left-to-right");
36948 defsubr (&Sbidi_resolved_levels);
36949
36950 #ifdef HAVE_WINDOW_SYSTEM
36951 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36952 doc:
36953
36954 );
36955 x_stretch_cursor_p = 0;
36956 #endif
36957
36958 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36959 doc:
36960 );
36961 Vshow_trailing_whitespace = Qnil;
36962
36963 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36964 doc:
36965
36966
36967 );
36968 Vmode_line_compact = Qnil;
36969 DEFSYM (Qlong, "long");
36970
36971 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36972 doc:
36973
36974
36975
36976
36977
36978
36979
36980
36981
36982
36983
36984 );
36985 Vnobreak_char_display = Qt;
36986
36987 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
36988 doc:
36989
36990
36991
36992
36993
36994
36995
36996
36997
36998
36999
37000
37001
37002
37003
37004 );
37005 nobreak_char_ascii_display = false;
37006
37007 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
37008 doc:
37009
37010
37011 );
37012 Vvoid_text_area_pointer = Qarrow;
37013
37014 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
37015 doc:
37016 );
37017 Vinhibit_redisplay = Qnil;
37018
37019 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
37020 doc: );
37021 Vglobal_mode_string = Qnil;
37022
37023 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
37024 doc:
37025
37026 );
37027 Voverlay_arrow_position = Qnil;
37028
37029 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
37030 doc:
37031 );
37032 Voverlay_arrow_string = build_pure_c_string ("=>");
37033
37034 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
37035 doc:
37036
37037 );
37038 Voverlay_arrow_variable_list
37039 = list1 (intern_c_string ("overlay-arrow-position"));
37040
37041 DEFVAR_INT ("scroll-step", emacs_scroll_step,
37042 doc:
37043
37044
37045
37046 );
37047
37048 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
37049 doc:
37050
37051
37052
37053
37054
37055
37056
37057
37058
37059 );
37060 scroll_conservatively = 0;
37061
37062 DEFVAR_INT ("scroll-margin", scroll_margin,
37063 doc:
37064
37065 );
37066 scroll_margin = 0;
37067
37068 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
37069 doc:
37070
37071
37072
37073 );
37074 Vmaximum_scroll_margin = make_float (0.25);
37075
37076 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
37077 doc:
37078 );
37079 Vdisplay_pixels_per_inch = make_float (72.0);
37080
37081 #ifdef GLYPH_DEBUG
37082 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
37083 #endif
37084
37085 DEFVAR_LISP ("truncate-partial-width-windows",
37086 Vtruncate_partial_width_windows,
37087 doc:
37088
37089
37090
37091
37092
37093
37094
37095
37096
37097
37098
37099
37100
37101
37102
37103 );
37104 Vtruncate_partial_width_windows = make_fixnum (50);
37105
37106 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
37107
37108
37109
37110
37111
37112
37113
37114
37115
37116
37117
37118
37119
37120 );
37121 word_wrap_by_category = false;
37122
37123 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
37124 doc:
37125
37126 );
37127 Vline_number_display_limit = Qnil;
37128
37129 DEFVAR_INT ("line-number-display-limit-width",
37130 line_number_display_limit_width,
37131 doc:
37132
37133 );
37134 line_number_display_limit_width = 200;
37135
37136 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
37137 doc:
37138
37139 );
37140 highlight_nonselected_windows = false;
37141
37142 DEFVAR_BOOL ("multiple-frames", multiple_frames,
37143 doc:
37144
37145
37146 );
37147
37148 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
37149 doc:
37150
37151
37152
37153
37154 );
37155
37156 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
37157 doc:
37158
37159
37160
37161
37162
37163 );
37164
37165
37166 Lisp_Object icon_title_name_format
37167 = pure_list (empty_unibyte_string,
37168 build_pure_c_string ("%b - GNU Emacs at "),
37169 intern_c_string ("system-name"));
37170 Vicon_title_format
37171 = Vframe_title_format
37172 = pure_list (intern_c_string ("multiple-frames"),
37173 build_pure_c_string ("%b"),
37174 icon_title_name_format);
37175
37176 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
37177 doc:
37178
37179 );
37180 Vmessage_log_max = make_fixnum (1000);
37181
37182 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
37183 doc:
37184
37185
37186
37187
37188
37189
37190
37191
37192
37193
37194
37195
37196
37197 );
37198 Vwindow_scroll_functions = Qnil;
37199
37200 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
37201 doc:
37202
37203
37204
37205
37206
37207
37208
37209
37210
37211
37212
37213
37214
37215
37216
37217
37218
37219 );
37220 Vmouse_autoselect_window = Qnil;
37221
37222 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
37223 doc:
37224
37225
37226
37227
37228 );
37229 Vauto_resize_tab_bars = Qt;
37230
37231 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
37232 doc: );
37233 auto_raise_tab_bar_buttons_p = true;
37234
37235 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
37236 doc:
37237
37238
37239
37240
37241 );
37242 Vauto_resize_tool_bars = Qt;
37243
37244 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
37245 doc: );
37246 auto_raise_tool_bar_buttons_p = true;
37247
37248 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
37249 doc:
37250
37251
37252
37253
37254 );
37255 Vmake_cursor_line_fully_visible = Qt;
37256 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
37257
37258 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
37259 doc: );
37260 make_window_start_visible = false;
37261 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
37262 Fmake_variable_buffer_local (Qmake_window_start_visible);
37263
37264 DEFSYM (Qclose_tab, "close-tab");
37265 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
37266 doc:
37267
37268
37269
37270 );
37271 Vtab_bar_border = Qinternal_border_width;
37272
37273 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
37274 doc:
37275
37276
37277
37278 );
37279 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
37280
37281 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
37282 doc: );
37283 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
37284
37285 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
37286 doc:
37287
37288
37289
37290 );
37291 Vtool_bar_border = Qinternal_border_width;
37292
37293 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
37294 doc:
37295
37296
37297
37298 );
37299 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
37300
37301 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
37302 doc: );
37303 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
37304
37305 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
37306 doc:
37307
37308
37309
37310
37311
37312
37313
37314
37315 );
37316 Vtool_bar_style = Qnil;
37317
37318 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
37319 doc:
37320
37321 );
37322 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
37323
37324 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
37325 doc:
37326
37327
37328
37329
37330
37331
37332
37333
37334 );
37335 Vfontification_functions = Qnil;
37336 Fmake_variable_buffer_local (Qfontification_functions);
37337
37338 DEFVAR_BOOL ("unibyte-display-via-language-environment",
37339 unibyte_display_via_language_environment,
37340 doc:
37341
37342
37343
37344
37345
37346
37347 );
37348 unibyte_display_via_language_environment = false;
37349
37350 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
37351 doc:
37352
37353
37354
37355 );
37356 Vmax_mini_window_height = make_float (0.25);
37357
37358 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
37359 doc:
37360
37361
37362
37363
37364
37365
37366
37367
37368 );
37369
37370
37371
37372
37373
37374 Vresize_mini_windows = Qnil;
37375
37376 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
37377 doc:
37378
37379
37380
37381
37382
37383
37384
37385 );
37386 Vblink_cursor_alist = Qnil;
37387
37388 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
37389 doc:
37390
37391
37392
37393 );
37394 automatic_hscrolling = Qt;
37395 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
37396 DEFSYM (Qcurrent_line, "current-line");
37397
37398 DEFVAR_INT ("hscroll-margin", hscroll_margin,
37399 doc:
37400 );
37401 hscroll_margin = 5;
37402
37403 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37404 doc:
37405
37406
37407
37408
37409
37410
37411
37412
37413
37414
37415
37416
37417
37418 );
37419 Vhscroll_step = make_fixnum (0);
37420
37421 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37422 doc:
37423 );
37424 message_truncate_lines = false;
37425
37426 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37427 doc:
37428
37429
37430 );
37431 Vmenu_bar_update_hook = Qnil;
37432
37433 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37434 doc:
37435 );
37436 Vmenu_updating_frame = Qnil;
37437
37438 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37439 doc: );
37440 inhibit_menubar_update = false;
37441
37442 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37443 doc:
37444
37445
37446
37447
37448
37449
37450 );
37451 Vwrap_prefix = Qnil;
37452 DEFSYM (Qwrap_prefix, "wrap-prefix");
37453 Fmake_variable_buffer_local (Qwrap_prefix);
37454
37455 DEFVAR_LISP ("line-prefix", Vline_prefix,
37456 doc:
37457
37458
37459
37460
37461
37462
37463 );
37464 Vline_prefix = Qnil;
37465 DEFSYM (Qline_prefix, "line-prefix");
37466 Fmake_variable_buffer_local (Qline_prefix);
37467
37468 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37469 doc:
37470
37471
37472
37473
37474
37475
37476
37477
37478
37479
37480
37481
37482
37483
37484
37485
37486
37487
37488
37489
37490
37491
37492 );
37493 Vdisplay_line_numbers = Qnil;
37494 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37495 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37496 DEFSYM (Qrelative, "relative");
37497 DEFSYM (Qvisual, "visual");
37498
37499 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37500 doc:
37501
37502
37503
37504 );
37505 Vdisplay_line_numbers_width = Qnil;
37506 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37507 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37508
37509 DEFVAR_LISP ("display-line-numbers-current-absolute",
37510 Vdisplay_line_numbers_current_absolute,
37511 doc:
37512
37513 );
37514 Vdisplay_line_numbers_current_absolute = Qt;
37515
37516 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37517 doc: );
37518 display_line_numbers_widen = false;
37519 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37520 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37521
37522 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37523 doc:
37524
37525
37526 );
37527 display_line_numbers_offset = 0;
37528 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37529 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37530
37531 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37532 doc:
37533
37534
37535 );
37536 display_fill_column_indicator = false;
37537 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37538 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37539
37540 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37541 doc:
37542
37543
37544
37545 );
37546 Vdisplay_fill_column_indicator_column = Qt;
37547 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37548 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37549
37550 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37551 doc:
37552
37553
37554 );
37555 Vdisplay_fill_column_indicator_character = Qnil;
37556 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37557 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37558
37559 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37560 doc:
37561
37562
37563 );
37564 display_line_numbers_major_tick = 0;
37565
37566 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37567 doc:
37568
37569
37570 );
37571 display_line_numbers_minor_tick = 0;
37572
37573 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37574 doc: );
37575 inhibit_eval_during_redisplay = false;
37576
37577 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37578 doc: );
37579 inhibit_free_realized_faces = false;
37580
37581 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37582 doc:
37583
37584 );
37585 inhibit_bidi_mirroring = false;
37586
37587 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37588 doc:
37589
37590
37591
37592 );
37593 bidi_inhibit_bpa = false;
37594
37595 #ifdef GLYPH_DEBUG
37596 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37597 doc: );
37598 inhibit_try_window_id = false;
37599
37600 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37601 doc: );
37602 inhibit_try_window_reusing = false;
37603
37604 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37605 doc: );
37606 inhibit_try_cursor_movement = false;
37607 #endif
37608
37609 DEFVAR_INT ("overline-margin", overline_margin,
37610 doc:
37611
37612 );
37613 overline_margin = 2;
37614
37615 DEFVAR_INT ("underline-minimum-offset",
37616 underline_minimum_offset,
37617 doc:
37618
37619
37620
37621 );
37622 underline_minimum_offset = 1;
37623 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37624
37625 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37626 doc:
37627
37628 );
37629 display_hourglass_p = true;
37630
37631 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37632 doc: );
37633 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37634
37635 #ifdef HAVE_WINDOW_SYSTEM
37636 hourglass_atimer = NULL;
37637 hourglass_shown_p = false;
37638 #endif
37639
37640
37641 DEFSYM (Qglyphless_char, "glyphless-char");
37642
37643
37644 DEFSYM (Qhex_code, "hex-code");
37645 DEFSYM (Qempty_box, "empty-box");
37646 DEFSYM (Qthin_space, "thin-space");
37647 DEFSYM (Qzero_width, "zero-width");
37648
37649 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37650 doc:
37651
37652
37653 );
37654 Vpre_redisplay_function = intern ("ignore");
37655
37656
37657 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37658 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37659
37660 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37661 doc:
37662
37663
37664
37665
37666
37667
37668
37669
37670
37671
37672
37673
37674
37675
37676
37677
37678
37679
37680
37681
37682
37683
37684
37685 );
37686 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37687 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37688 Qempty_box);
37689
37690 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37691 doc: );
37692 Vdebug_on_message = Qnil;
37693
37694 DEFVAR_LISP ("set-message-function", Vset_message_function,
37695 doc:
37696
37697
37698
37699
37700
37701
37702
37703
37704
37705 );
37706 Vset_message_function = Qnil;
37707
37708 DEFSYM (Qdont_clear_message, "dont-clear-message");
37709 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37710 doc:
37711
37712
37713
37714
37715
37716
37717
37718
37719
37720
37721 );
37722 Vclear_message_function = Qnil;
37723
37724 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37725 doc:
37726 );
37727 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37728
37729 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37730 doc:
37731 );
37732 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37733
37734 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37735 doc: );
37736
37737
37738 redisplay__inhibit_bidi = true;
37739
37740 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37741 doc:
37742
37743 );
37744 display_raw_bytes_as_hex = false;
37745
37746 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37747 doc:
37748
37749
37750
37751
37752 );
37753 mouse_fine_grained_tracking = false;
37754
37755 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37756 doc: );
37757 tab_bar__dragging_in_progress = false;
37758
37759 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37760 doc:
37761
37762
37763
37764 );
37765 redisplay_skip_initial_frame = true;
37766
37767 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37768 redisplay_skip_fontification_on_input,
37769 doc:
37770
37771
37772
37773
37774
37775
37776
37777 );
37778 redisplay_skip_fontification_on_input = false;
37779
37780 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37781 redisplay_adhoc_scroll_in_resize_mini_windows,
37782 doc:
37783
37784 );
37785
37786 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37787
37788 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37789 doc:
37790
37791 );
37792 composition_break_at_point = false;
37793
37794 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37795 doc:
37796
37797
37798
37799
37800
37801
37802
37803
37804
37805
37806
37807 );
37808 max_redisplay_ticks = 0;
37809 }
37810
37811
37812
37813
37814 void
37815 init_xdisp (void)
37816 {
37817 CHARPOS (this_line_start_pos) = 0;
37818
37819 echo_area_window = minibuf_window;
37820
37821 if (!noninteractive)
37822 {
37823 struct window *m = XWINDOW (minibuf_window);
37824 Lisp_Object frame = m->frame;
37825 struct frame *f = XFRAME (frame);
37826 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37827 struct window *r = XWINDOW (root);
37828 int i;
37829
37830 r->top_line = FRAME_TOP_MARGIN (f);
37831 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37832 r->total_cols = FRAME_COLS (f);
37833 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37834 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_MARGINS (f);
37835 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37836
37837 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37838 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37839 m->total_cols = FRAME_COLS (f);
37840 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37841 m->total_lines = 1;
37842 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37843
37844 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37845 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37846 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37847
37848
37849 for (i = 0; i < 3; ++i)
37850 default_invis_vector[i] = make_fixnum ('.');
37851 }
37852
37853 {
37854
37855
37856 int size = 100;
37857 mode_line_noprop_buf = xmalloc (size);
37858 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37859 mode_line_noprop_ptr = mode_line_noprop_buf;
37860 mode_line_target = MODE_LINE_DISPLAY;
37861 }
37862
37863 help_echo_showing_p = false;
37864 }
37865
37866 #ifdef HAVE_WINDOW_SYSTEM
37867
37868
37869
37870
37871
37872 static void
37873 show_hourglass (struct atimer *timer)
37874 {
37875
37876
37877
37878 hourglass_atimer = NULL;
37879
37880 if (!hourglass_shown_p)
37881 {
37882 Lisp_Object tail, frame;
37883
37884 block_input ();
37885
37886 FOR_EACH_FRAME (tail, frame)
37887 {
37888 struct frame *f = XFRAME (frame);
37889
37890 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37891 && FRAME_RIF (f)->show_hourglass)
37892 FRAME_RIF (f)->show_hourglass (f);
37893 }
37894
37895 hourglass_shown_p = true;
37896 unblock_input ();
37897 }
37898 }
37899
37900
37901
37902 void
37903 start_hourglass (void)
37904 {
37905 struct timespec delay;
37906
37907 cancel_hourglass ();
37908
37909 if (FIXNUMP (Vhourglass_delay)
37910 && XFIXNUM (Vhourglass_delay) > 0)
37911 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37912 TYPE_MAXIMUM (time_t)),
37913 0);
37914 else if (FLOATP (Vhourglass_delay)
37915 && XFLOAT_DATA (Vhourglass_delay) > 0)
37916 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37917 else
37918 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37919
37920 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37921 show_hourglass, NULL);
37922 }
37923
37924
37925
37926
37927 void
37928 cancel_hourglass (void)
37929 {
37930 if (hourglass_atimer)
37931 {
37932 cancel_atimer (hourglass_atimer);
37933 hourglass_atimer = NULL;
37934 }
37935
37936 if (hourglass_shown_p)
37937 {
37938 Lisp_Object tail, frame;
37939
37940 block_input ();
37941
37942 FOR_EACH_FRAME (tail, frame)
37943 {
37944 struct frame *f = XFRAME (frame);
37945
37946 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37947 && FRAME_RIF (f)->hide_hourglass)
37948 FRAME_RIF (f)->hide_hourglass (f);
37949 #ifdef HAVE_NTGUI
37950
37951 else if (!FRAME_W32_P (f))
37952 w32_arrow_cursor ();
37953 #endif
37954 }
37955
37956 hourglass_shown_p = false;
37957 unblock_input ();
37958 }
37959 }
37960
37961
37962
37963
37964
37965
37966
37967
37968 static int
37969 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37970 struct window *w,
37971 struct face *original_face,
37972 struct face *mouse_face)
37973 {
37974 int sum = 0;
37975
37976 bool do_left_box_p = g->left_box_line_p;
37977 bool do_right_box_p = g->right_box_line_p;
37978
37979
37980
37981 if (g->type == IMAGE_GLYPH)
37982 {
37983 if (!row->reversed_p)
37984 {
37985 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37986 g->u.img_id);
37987 do_left_box_p = g->left_box_line_p &&
37988 g->slice.img.x == 0;
37989 do_right_box_p = g->right_box_line_p &&
37990 g->slice.img.x + g->slice.img.width == img->width;
37991 }
37992 else
37993 {
37994 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37995 g->u.img_id);
37996 do_left_box_p = g->left_box_line_p &&
37997 g->slice.img.x + g->slice.img.width == img->width;
37998 do_right_box_p = g->right_box_line_p &&
37999 g->slice.img.x == 0;
38000 }
38001 }
38002
38003
38004 if (do_left_box_p)
38005 sum -= max (0, original_face->box_vertical_line_width);
38006
38007
38008 if (do_right_box_p)
38009 sum -= max (0, original_face->box_vertical_line_width);
38010
38011 if (g->left_box_line_p)
38012 sum += max (0, mouse_face->box_vertical_line_width);
38013 if (g->right_box_line_p)
38014 sum += max (0, mouse_face->box_vertical_line_width);
38015
38016 return sum;
38017 }
38018
38019
38020
38021
38022
38023
38024
38025
38026
38027 static void
38028 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
38029 int *offset)
38030 {
38031 int sum = 0;
38032
38033 if (row->mode_line_p)
38034 return;
38035
38036 block_input ();
38037
38038 struct frame *f = WINDOW_XFRAME (w);
38039 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
38040 struct glyph *start, *end;
38041 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
38042 int hpos = w->phys_cursor.hpos;
38043 end = &row->glyphs[TEXT_AREA][hpos];
38044
38045 if (!row->reversed_p)
38046 {
38047 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
38048 hlinfo->mouse_face_beg_row)
38049 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
38050 else
38051 start = row->glyphs[TEXT_AREA];
38052 }
38053 else
38054 {
38055 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
38056 hlinfo->mouse_face_end_row)
38057 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
38058 else
38059 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
38060 }
38061
38062
38063
38064
38065 for ( ; row->reversed_p ? start > end : start < end;
38066 row->reversed_p ? --start : ++start)
38067 sum += adjust_glyph_width_for_mouse_face (start, row, w,
38068 FACE_FROM_ID (f, start->face_id),
38069 mouse_face);
38070
38071 if (row->reversed_p)
38072 sum = -sum;
38073
38074 *offset = sum;
38075
38076 unblock_input ();
38077 }
38078 #endif