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_OR_NULL (it->f, it->face_id);
8343
8344
8345
8346
8347 if (!face)
8348 {
8349 it->what = IT_GLYPHLESS;
8350 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
8351 }
8352 else if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8353 {
8354
8355 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8356
8357 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8358 }
8359 else
8360 {
8361 ptrdiff_t pos = (it->s ? -1
8362 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8363 : IT_CHARPOS (*it));
8364 int c;
8365
8366 if (it->what == IT_CHARACTER)
8367 c = it->char_to_display;
8368 else
8369 {
8370 struct composition *cmp = composition_table[it->cmp_it.id];
8371 int i;
8372
8373 c = ' ';
8374 for (i = 0; i < cmp->glyph_len; i++)
8375
8376
8377 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8378 break;
8379 }
8380 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8381 }
8382 }
8383 #endif
8384
8385 done:
8386
8387
8388 if (it->face_box_p
8389 && it->s == NULL)
8390 {
8391 if (it->method == GET_FROM_STRING && it->sp)
8392 {
8393 int face_id = underlying_face_id (it);
8394 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8395
8396 if (face)
8397 {
8398 if (face->box == FACE_NO_BOX)
8399 {
8400
8401
8402 int string_face_id = face_after_it_pos (it);
8403 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8404 it->end_of_box_run_p = true;
8405 }
8406
8407
8408
8409 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8410
8411
8412
8413 || (it->what == IT_COMPOSITION
8414 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8415 >= SCHARS (it->string))))
8416
8417
8418 && ((it->current.overlay_string_index >= 0
8419 && (it->current.overlay_string_index
8420 == it->n_overlay_strings - 1))
8421
8422 || it->from_disp_prop_p))
8423 {
8424 ptrdiff_t ignore;
8425 int next_face_id;
8426 bool text_from_string = false;
8427
8428
8429 struct text_pos pos = it->current.pos;
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441 if (it->from_disp_prop_p)
8442 {
8443 int stackp = it->sp - 1;
8444
8445
8446 while (stackp >= 0
8447 && STRINGP ((it->stack + stackp)->string))
8448 stackp--;
8449 if (stackp < 0)
8450 {
8451
8452
8453
8454
8455
8456
8457 text_from_string = true;
8458 pos = it->stack[it->sp - 1].position;
8459 }
8460 else
8461 pos = (it->stack + stackp)->position;
8462 }
8463 else
8464 INC_TEXT_POS (pos, it->multibyte_p);
8465
8466 if (text_from_string)
8467 {
8468 Lisp_Object base_string = it->stack[it->sp - 1].string;
8469
8470 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8471 it->end_of_box_run_p = true;
8472 else
8473 {
8474 next_face_id
8475 = face_at_string_position (it->w, base_string,
8476 CHARPOS (pos), 0,
8477 &ignore, face_id,
8478 false, 0);
8479 if (FACE_FROM_ID (it->f, next_face_id)->box
8480 == FACE_NO_BOX)
8481 it->end_of_box_run_p = true;
8482 }
8483 }
8484 else if (CHARPOS (pos) >= ZV)
8485 it->end_of_box_run_p = true;
8486 else
8487 {
8488 next_face_id =
8489 face_at_buffer_position (it->w, CHARPOS (pos),
8490 &ignore,
8491 CHARPOS (pos)
8492 + TEXT_PROP_DISTANCE_LIMIT,
8493 false, -1, 0);
8494 if (FACE_FROM_ID (it->f, next_face_id)->box
8495 == FACE_NO_BOX)
8496 it->end_of_box_run_p = true;
8497 }
8498 }
8499 }
8500 }
8501
8502
8503 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8504 {
8505 int face_id = face_after_it_pos (it);
8506 if (face_id != it->face_id
8507 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8508 it->end_of_box_run_p = true;
8509 }
8510 }
8511
8512
8513
8514
8515
8516 if (!success_p && it->sp > 0)
8517 {
8518 set_iterator_to_next (it, false);
8519 success_p = get_next_display_element (it);
8520 }
8521
8522
8523 return success_p;
8524 }
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542 void
8543 set_iterator_to_next (struct it *it, bool reseat_p)
8544 {
8545
8546 if (max_redisplay_ticks > 0)
8547 update_redisplay_ticks (1, it->w);
8548
8549 switch (it->method)
8550 {
8551 case GET_FROM_BUFFER:
8552
8553
8554
8555 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8556 reseat_at_next_visible_line_start (it, false);
8557 else if (it->cmp_it.id >= 0)
8558 {
8559
8560 if (! it->bidi_p)
8561 {
8562 IT_CHARPOS (*it) += it->cmp_it.nchars;
8563 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8564 }
8565 else
8566 {
8567 int i;
8568
8569
8570
8571
8572 for (i = 0; i < it->cmp_it.nchars; i++)
8573 bidi_move_to_visually_next (&it->bidi_it);
8574 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8575 IT_CHARPOS (*it) = it->bidi_it.charpos;
8576 }
8577
8578 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8579 && it->cmp_it.to < it->cmp_it.nglyphs)
8580 {
8581
8582
8583 it->cmp_it.from = it->cmp_it.to;
8584 }
8585 else if ((it->bidi_p && it->cmp_it.reversed_p)
8586 && it->cmp_it.from > 0)
8587 {
8588
8589
8590 it->cmp_it.to = it->cmp_it.from;
8591 }
8592 else
8593 {
8594
8595
8596 ptrdiff_t stop = it->end_charpos;
8597
8598 if (it->bidi_it.scan_dir < 0)
8599
8600
8601 stop = -1;
8602 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8603 IT_BYTEPOS (*it), stop, Qnil, true);
8604 }
8605 }
8606 else
8607 {
8608 eassert (it->len != 0);
8609
8610 if (!it->bidi_p)
8611 {
8612 IT_BYTEPOS (*it) += it->len;
8613 IT_CHARPOS (*it) += 1;
8614 }
8615 else
8616 {
8617 int prev_scan_dir = it->bidi_it.scan_dir;
8618
8619
8620 if (it->bidi_it.new_paragraph)
8621 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8622 false);
8623 bidi_move_to_visually_next (&it->bidi_it);
8624 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8625 IT_CHARPOS (*it) = it->bidi_it.charpos;
8626 if (prev_scan_dir != it->bidi_it.scan_dir)
8627 {
8628
8629
8630 ptrdiff_t stop = it->end_charpos;
8631 if (it->bidi_it.scan_dir < 0)
8632 stop = -1;
8633 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8634 IT_BYTEPOS (*it), stop, Qnil,
8635 true);
8636 }
8637 }
8638 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8639 }
8640 break;
8641
8642 case GET_FROM_C_STRING:
8643
8644 if (!it->bidi_p
8645
8646
8647
8648
8649 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8650 {
8651 IT_BYTEPOS (*it) += it->len;
8652 IT_CHARPOS (*it) += 1;
8653 }
8654 else
8655 {
8656 bidi_move_to_visually_next (&it->bidi_it);
8657 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8658 IT_CHARPOS (*it) = it->bidi_it.charpos;
8659 }
8660 break;
8661
8662 case GET_FROM_DISPLAY_VECTOR:
8663
8664
8665
8666
8667 ++it->current.dpvec_index;
8668
8669
8670
8671 it->face_id = it->saved_face_id;
8672
8673 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8674 {
8675 bool recheck_faces = it->ellipsis_p;
8676
8677 if (it->s)
8678 it->method = GET_FROM_C_STRING;
8679 else if (STRINGP (it->string))
8680 it->method = GET_FROM_STRING;
8681 else
8682 {
8683 it->method = GET_FROM_BUFFER;
8684 it->object = it->w->contents;
8685 }
8686
8687 it->dpvec = NULL;
8688 it->current.dpvec_index = -1;
8689
8690
8691 if (it->dpvec_char_len < 0)
8692 reseat_at_next_visible_line_start (it, true);
8693 else if (it->dpvec_char_len > 0)
8694 {
8695 it->len = it->dpvec_char_len;
8696 set_iterator_to_next (it, reseat_p);
8697 }
8698
8699
8700 if (recheck_faces)
8701 {
8702 if (it->method == GET_FROM_STRING)
8703 it->stop_charpos = IT_STRING_CHARPOS (*it);
8704 else
8705 it->stop_charpos = IT_CHARPOS (*it);
8706 }
8707 }
8708 break;
8709
8710 case GET_FROM_STRING:
8711
8712 eassert (it->s == NULL && STRINGP (it->string));
8713
8714
8715
8716
8717
8718 if (it->current.overlay_string_index >= 0)
8719 {
8720
8721
8722
8723 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8724 goto consider_string_end;
8725 }
8726 else
8727 {
8728
8729
8730 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8731 goto consider_string_end;
8732 }
8733 if (it->cmp_it.id >= 0)
8734 {
8735
8736
8737
8738 if (! it->bidi_p)
8739 {
8740 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8741 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8742 }
8743 else
8744 {
8745 int i;
8746
8747 for (i = 0; i < it->cmp_it.nchars; i++)
8748 bidi_move_to_visually_next (&it->bidi_it);
8749 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8750 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8751 }
8752
8753
8754
8755 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8756 && (it->cmp_it.to < it->cmp_it.nglyphs))
8757 {
8758
8759
8760 it->cmp_it.from = it->cmp_it.to;
8761 }
8762 else if ((it->bidi_p && it->cmp_it.reversed_p)
8763 && it->cmp_it.from > 0)
8764 {
8765
8766
8767 it->cmp_it.to = it->cmp_it.from;
8768 }
8769 else
8770 {
8771
8772
8773
8774
8775
8776
8777 ptrdiff_t stop = SCHARS (it->string);
8778
8779 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8780 stop = -1;
8781 else if (it->end_charpos < stop)
8782 {
8783
8784
8785
8786 stop = it->end_charpos;
8787 }
8788 composition_compute_stop_pos (&it->cmp_it,
8789 IT_STRING_CHARPOS (*it),
8790 IT_STRING_BYTEPOS (*it), stop,
8791 it->string, true);
8792 }
8793 }
8794 else
8795 {
8796 if (!it->bidi_p
8797
8798
8799
8800
8801
8802 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8803 {
8804 IT_STRING_BYTEPOS (*it) += it->len;
8805 IT_STRING_CHARPOS (*it) += 1;
8806 }
8807 else
8808 {
8809 int prev_scan_dir = it->bidi_it.scan_dir;
8810
8811 bidi_move_to_visually_next (&it->bidi_it);
8812 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8813 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8814
8815
8816 if (prev_scan_dir != it->bidi_it.scan_dir)
8817 {
8818 ptrdiff_t stop = SCHARS (it->string);
8819
8820 if (it->bidi_it.scan_dir < 0)
8821 stop = -1;
8822 else if (it->end_charpos < stop)
8823 stop = it->end_charpos;
8824
8825 composition_compute_stop_pos (&it->cmp_it,
8826 IT_STRING_CHARPOS (*it),
8827 IT_STRING_BYTEPOS (*it), stop,
8828 it->string, true);
8829 }
8830 }
8831 }
8832
8833 consider_string_end:
8834
8835 if (it->current.overlay_string_index >= 0)
8836 {
8837
8838
8839 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8840 {
8841 it->ellipsis_p = false;
8842 next_overlay_string (it);
8843 if (it->ellipsis_p)
8844 setup_for_ellipsis (it, 0);
8845 }
8846 }
8847 else
8848 {
8849
8850
8851
8852
8853 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8854 && it->sp > 0)
8855 {
8856 pop_it (it);
8857 if (it->method == GET_FROM_STRING)
8858 goto consider_string_end;
8859 }
8860 }
8861 break;
8862
8863 case GET_FROM_IMAGE:
8864 case GET_FROM_STRETCH:
8865 case GET_FROM_XWIDGET:
8866
8867
8868
8869
8870 eassert (it->sp > 0);
8871 pop_it (it);
8872 if (it->method == GET_FROM_STRING)
8873 goto consider_string_end;
8874 break;
8875
8876 default:
8877
8878 emacs_abort ();
8879 }
8880
8881 eassert (it->method != GET_FROM_STRING
8882 || (STRINGP (it->string)
8883 && IT_STRING_CHARPOS (*it) >= 0));
8884 }
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895 static bool
8896 next_element_from_display_vector (struct it *it)
8897 {
8898 Lisp_Object gc;
8899 int prev_face_id = it->face_id;
8900 int next_face_id;
8901
8902
8903 eassert (it->dpvec && it->current.dpvec_index >= 0);
8904
8905 it->face_id = it->saved_face_id;
8906
8907
8908
8909 if (it->dpend - it->dpvec > 0
8910 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8911 {
8912 struct face *this_face, *prev_face, *next_face;
8913
8914 it->c = GLYPH_CODE_CHAR (gc);
8915 it->len = CHAR_BYTES (it->c);
8916
8917
8918
8919
8920 if (it->dpvec_face_id >= 0)
8921 it->face_id = it->dpvec_face_id;
8922 else
8923 {
8924 int lface_id = GLYPH_CODE_FACE (gc);
8925 if (lface_id > 0)
8926 it->face_id = merge_faces (it->w, Qt, lface_id,
8927 it->saved_face_id);
8928 }
8929
8930
8931
8932
8933 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8934 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8935
8936
8937 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8938 && (!prev_face
8939 || prev_face->box == FACE_NO_BOX));
8940
8941
8942
8943
8944 next_face_id = it->saved_face_id;
8945 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8946 {
8947 if (it->dpvec_face_id >= 0)
8948 next_face_id = it->dpvec_face_id;
8949 else
8950 {
8951 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8952 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8953
8954 if (lface_id > 0)
8955 next_face_id = merge_faces (it->w, Qt, lface_id,
8956 it->saved_face_id);
8957 }
8958 }
8959 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8960 if (this_face && this_face->box != FACE_NO_BOX
8961 && (!next_face || next_face->box == FACE_NO_BOX))
8962 it->end_of_box_run_p = true;
8963 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8964 }
8965 else
8966
8967 it->c = ' ', it->len = 1;
8968
8969
8970
8971
8972 it->what = IT_CHARACTER;
8973 return true;
8974 }
8975
8976
8977
8978 static void
8979 get_visually_first_element (struct it *it)
8980 {
8981 bool string_p = STRINGP (it->string) || it->s;
8982 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8983 ptrdiff_t bob;
8984 ptrdiff_t obegv = BEGV;
8985
8986 SET_WITH_NARROWED_BEGV (it, bob,
8987 string_p ? 0 :
8988 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8989 it->medium_narrowing_begv);
8990
8991 if (STRINGP (it->string))
8992 {
8993 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8994 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8995 }
8996 else
8997 {
8998 it->bidi_it.charpos = IT_CHARPOS (*it);
8999 it->bidi_it.bytepos = IT_BYTEPOS (*it);
9000 }
9001
9002 if (it->bidi_it.charpos == eob)
9003 {
9004
9005
9006
9007 it->bidi_it.first_elt = false;
9008 }
9009 else if (it->bidi_it.charpos == bob
9010 || (!string_p
9011 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
9012 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
9013 {
9014
9015
9016 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
9017 bidi_move_to_visually_next (&it->bidi_it);
9018 }
9019 else
9020 {
9021 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
9022
9023
9024
9025
9026 if (string_p)
9027 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
9028 else
9029 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
9030 find_newline_no_quit (IT_CHARPOS (*it),
9031 IT_BYTEPOS (*it), -1,
9032 &it->bidi_it.bytepos),
9033 it->medium_narrowing_begv);
9034 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
9035 do
9036 {
9037
9038
9039 bidi_move_to_visually_next (&it->bidi_it);
9040 }
9041 while (it->bidi_it.bytepos != orig_bytepos
9042 && it->bidi_it.charpos < eob);
9043 }
9044
9045
9046 if (STRINGP (it->string))
9047 {
9048 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
9049 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
9050 }
9051 else
9052 {
9053 IT_CHARPOS (*it) = it->bidi_it.charpos;
9054 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
9055 }
9056
9057 if (STRINGP (it->string) || !it->s)
9058 {
9059 ptrdiff_t stop, charpos, bytepos;
9060
9061 if (STRINGP (it->string))
9062 {
9063 eassert (!it->s);
9064 stop = SCHARS (it->string);
9065 if (stop > it->end_charpos)
9066 stop = it->end_charpos;
9067 charpos = IT_STRING_CHARPOS (*it);
9068 bytepos = IT_STRING_BYTEPOS (*it);
9069 }
9070 else
9071 {
9072 stop = it->end_charpos;
9073 charpos = IT_CHARPOS (*it);
9074 bytepos = IT_BYTEPOS (*it);
9075 }
9076 if (it->bidi_it.scan_dir < 0)
9077 stop = -1;
9078 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9079 it->string, true);
9080 }
9081 }
9082
9083
9084
9085
9086
9087
9088 static bool
9089 next_element_from_string (struct it *it)
9090 {
9091 struct text_pos position;
9092
9093 eassert (STRINGP (it->string));
9094 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9095 eassert (IT_STRING_CHARPOS (*it) >= 0);
9096 position = it->current.string_pos;
9097
9098
9099
9100
9101
9102 if (it->bidi_p && it->bidi_it.first_elt)
9103 {
9104 get_visually_first_element (it);
9105 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9106 }
9107
9108
9109 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9110 {
9111 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9112 {
9113 if (!(!it->bidi_p
9114 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9115 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9116 {
9117
9118
9119
9120
9121
9122
9123 handle_stop_backwards (it, it->stop_charpos);
9124 return GET_NEXT_DISPLAY_ELEMENT (it);
9125 }
9126 else
9127 {
9128 if (it->bidi_p)
9129 {
9130
9131
9132 it->prev_stop = it->stop_charpos;
9133
9134
9135
9136 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9137 it->base_level_stop = it->stop_charpos;
9138 }
9139 handle_stop (it);
9140
9141
9142
9143 return GET_NEXT_DISPLAY_ELEMENT (it);
9144 }
9145 }
9146 else if (it->bidi_p
9147
9148
9149
9150 && IT_STRING_CHARPOS (*it) < it->prev_stop
9151
9152
9153
9154
9155 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9156 {
9157
9158
9159
9160
9161 if (it->base_level_stop <= 0
9162 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9163 it->base_level_stop = 0;
9164 handle_stop_backwards (it, it->base_level_stop);
9165 return GET_NEXT_DISPLAY_ELEMENT (it);
9166 }
9167 }
9168
9169 if (it->current.overlay_string_index >= 0)
9170 {
9171
9172
9173
9174 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9175 {
9176 it->what = IT_EOB;
9177 return false;
9178 }
9179 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9180 IT_STRING_BYTEPOS (*it),
9181 it->bidi_it.scan_dir < 0
9182 ? -1
9183 : SCHARS (it->string))
9184 && next_element_from_composition (it))
9185 {
9186 return true;
9187 }
9188 else if (STRING_MULTIBYTE (it->string))
9189 {
9190 const unsigned char *s = (SDATA (it->string)
9191 + IT_STRING_BYTEPOS (*it));
9192 it->c = check_char_and_length (s, &it->len);
9193 }
9194 else
9195 {
9196 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9197 it->len = 1;
9198 }
9199 }
9200 else
9201 {
9202
9203
9204
9205
9206 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9207 {
9208 it->what = IT_EOB;
9209 return false;
9210 }
9211 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9212 {
9213
9214 it->c = ' ', it->len = 1;
9215 CHARPOS (position) = BYTEPOS (position) = -1;
9216 }
9217 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9218 IT_STRING_BYTEPOS (*it),
9219 it->bidi_it.scan_dir < 0
9220 ? -1
9221 : it->string_nchars)
9222 && next_element_from_composition (it))
9223 {
9224 return true;
9225 }
9226 else if (STRING_MULTIBYTE (it->string))
9227 {
9228 const unsigned char *s = (SDATA (it->string)
9229 + IT_STRING_BYTEPOS (*it));
9230 it->c = check_char_and_length (s, &it->len);
9231 }
9232 else
9233 {
9234 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9235 it->len = 1;
9236 }
9237 }
9238
9239
9240 it->what = IT_CHARACTER;
9241 it->object = it->string;
9242 it->position = position;
9243 return true;
9244 }
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254 static bool
9255 next_element_from_c_string (struct it *it)
9256 {
9257 bool success_p = true;
9258
9259 eassert (it->s);
9260 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9261 it->what = IT_CHARACTER;
9262 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9263 it->object = make_fixnum (0);
9264
9265
9266
9267
9268
9269 if (it->bidi_p && it->bidi_it.first_elt)
9270 get_visually_first_element (it);
9271
9272
9273
9274
9275 if (IT_CHARPOS (*it) >= it->end_charpos)
9276 {
9277
9278 it->what = IT_EOB;
9279 success_p = false;
9280 }
9281 else if (IT_CHARPOS (*it) >= it->string_nchars)
9282 {
9283
9284 it->c = ' ', it->len = 1;
9285 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9286 }
9287 else if (it->multibyte_p)
9288 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9289 else
9290 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9291
9292 return success_p;
9293 }
9294
9295
9296
9297
9298
9299
9300
9301 static bool
9302 next_element_from_ellipsis (struct it *it)
9303 {
9304 if (it->selective_display_ellipsis_p)
9305 setup_for_ellipsis (it, it->len);
9306 else
9307 {
9308
9309
9310
9311
9312 it->saved_face_id = it->face_id;
9313 it->method = GET_FROM_BUFFER;
9314 it->object = it->w->contents;
9315 reseat_at_next_visible_line_start (it, true);
9316 it->face_before_selective_p = true;
9317 }
9318
9319 return GET_NEXT_DISPLAY_ELEMENT (it);
9320 }
9321
9322
9323
9324
9325
9326
9327
9328 static bool
9329 next_element_from_image (struct it *it)
9330 {
9331 it->what = IT_IMAGE;
9332 return true;
9333 }
9334
9335 static bool
9336 next_element_from_xwidget (struct it *it)
9337 {
9338 it->what = IT_XWIDGET;
9339 return true;
9340 }
9341
9342
9343
9344
9345
9346
9347 static bool
9348 next_element_from_stretch (struct it *it)
9349 {
9350 it->what = IT_STRETCH;
9351 return true;
9352 }
9353
9354
9355
9356
9357
9358
9359 static void
9360 compute_stop_pos_backwards (struct it *it)
9361 {
9362 const int SCAN_BACK_LIMIT = 1000;
9363 struct text_pos pos;
9364 struct display_pos save_current = it->current;
9365 struct text_pos save_position = it->position;
9366 ptrdiff_t charpos = IT_CHARPOS (*it);
9367 ptrdiff_t where_we_are = charpos;
9368 ptrdiff_t save_stop_pos = it->stop_charpos;
9369 ptrdiff_t save_end_pos = it->end_charpos;
9370
9371 eassert (NILP (it->string) && !it->s);
9372 eassert (it->bidi_p);
9373 it->bidi_p = false;
9374 do
9375 {
9376 it->end_charpos = min (charpos + 1, ZV);
9377 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9378 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9379 reseat_1 (it, pos, false);
9380 compute_stop_pos (it);
9381
9382 if (it->stop_charpos <= charpos)
9383 emacs_abort ();
9384 }
9385 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9386
9387 if (it->stop_charpos <= where_we_are)
9388 it->prev_stop = it->stop_charpos;
9389 else
9390 it->prev_stop = BEGV;
9391 it->bidi_p = true;
9392 it->current = save_current;
9393 it->position = save_position;
9394 it->stop_charpos = save_stop_pos;
9395 it->end_charpos = save_end_pos;
9396 }
9397
9398
9399
9400
9401
9402
9403
9404
9405
9406 static void
9407 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9408 {
9409 bool bufp = !STRINGP (it->string);
9410 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9411 struct display_pos save_current = it->current;
9412 struct text_pos save_position = it->position;
9413 struct composition_it save_cmp_it = it->cmp_it;
9414 struct text_pos pos1;
9415 ptrdiff_t next_stop;
9416
9417
9418 eassert (it->bidi_p);
9419 it->bidi_p = false;
9420 do
9421 {
9422 it->prev_stop = charpos;
9423 if (bufp)
9424 {
9425 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9426 reseat_1 (it, pos1, false);
9427 }
9428 else
9429 it->current.string_pos = string_pos (charpos, it->string);
9430 compute_stop_pos (it);
9431
9432 if (it->stop_charpos <= it->prev_stop)
9433 emacs_abort ();
9434 charpos = it->stop_charpos;
9435 }
9436 while (charpos <= where_we_are);
9437
9438 it->bidi_p = true;
9439 it->current = save_current;
9440 it->position = save_position;
9441 it->cmp_it = save_cmp_it;
9442 next_stop = it->stop_charpos;
9443 it->stop_charpos = it->prev_stop;
9444 handle_stop (it);
9445 it->stop_charpos = next_stop;
9446 }
9447
9448
9449
9450
9451
9452
9453 static bool
9454 next_element_from_buffer (struct it *it)
9455 {
9456 bool success_p = true;
9457
9458 eassert (IT_CHARPOS (*it) >= BEGV);
9459 eassert (NILP (it->string) && !it->s);
9460 eassert (!it->bidi_p
9461 || (NILP (it->bidi_it.string.lstring)
9462 && it->bidi_it.string.s == NULL));
9463
9464
9465
9466
9467
9468 if (it->bidi_p && it->bidi_it.first_elt)
9469 {
9470 get_visually_first_element (it);
9471 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9472 }
9473
9474 if (IT_CHARPOS (*it) >= it->stop_charpos)
9475 {
9476 if (IT_CHARPOS (*it) >= it->end_charpos)
9477 {
9478 bool overlay_strings_follow_p;
9479
9480
9481
9482 if (it->overlay_strings_at_end_processed_p)
9483 overlay_strings_follow_p = false;
9484 else
9485 {
9486 it->overlay_strings_at_end_processed_p = true;
9487 overlay_strings_follow_p = get_overlay_strings (it, 0);
9488 }
9489
9490 if (overlay_strings_follow_p)
9491 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9492 else
9493 {
9494 it->what = IT_EOB;
9495 it->position = it->current.pos;
9496 success_p = false;
9497 }
9498 }
9499 else if (!(!it->bidi_p
9500 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9501 || IT_CHARPOS (*it) == it->stop_charpos))
9502 {
9503
9504
9505
9506
9507
9508
9509 handle_stop_backwards (it, it->stop_charpos);
9510 it->ignore_overlay_strings_at_pos_p = false;
9511 return GET_NEXT_DISPLAY_ELEMENT (it);
9512 }
9513 else
9514 {
9515 if (it->bidi_p)
9516 {
9517
9518
9519 it->prev_stop = it->stop_charpos;
9520
9521
9522
9523 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9524 it->base_level_stop = it->stop_charpos;
9525 }
9526 handle_stop (it);
9527 it->ignore_overlay_strings_at_pos_p = false;
9528 return GET_NEXT_DISPLAY_ELEMENT (it);
9529 }
9530 }
9531 else if (it->bidi_p
9532
9533
9534
9535 && IT_CHARPOS (*it) < it->prev_stop
9536
9537
9538
9539
9540 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9541 {
9542 if (it->base_level_stop <= 0
9543 || IT_CHARPOS (*it) < it->base_level_stop)
9544 {
9545
9546
9547
9548
9549 it->base_level_stop = BEGV;
9550 compute_stop_pos_backwards (it);
9551 handle_stop_backwards (it, it->prev_stop);
9552 }
9553 else
9554 handle_stop_backwards (it, it->base_level_stop);
9555 it->ignore_overlay_strings_at_pos_p = false;
9556 return GET_NEXT_DISPLAY_ELEMENT (it);
9557 }
9558 else
9559 {
9560
9561
9562 unsigned char *p;
9563 ptrdiff_t stop;
9564
9565
9566
9567 it->ignore_overlay_strings_at_pos_p = false;
9568
9569 if (composition_break_at_point
9570 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9571 && !NILP (Vauto_composition_mode))
9572 {
9573
9574 if (it->bidi_it.scan_dir < 0)
9575 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9576 else
9577 stop = (IT_CHARPOS (*it) < PT
9578 && PT < it->end_charpos) ? PT : it->end_charpos;
9579 }
9580 else
9581 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9582 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9583 stop)
9584 && next_element_from_composition (it))
9585 {
9586 return true;
9587 }
9588
9589
9590 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9591 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9592 it->c = string_char_and_length (p, &it->len);
9593 else
9594 it->c = *p, it->len = 1;
9595
9596
9597 it->what = IT_CHARACTER;
9598 it->object = it->w->contents;
9599 it->position = it->current.pos;
9600
9601
9602
9603 if (it->selective)
9604 {
9605 if (it->c == '\n')
9606 {
9607
9608
9609 if (it->selective > 0
9610 && IT_CHARPOS (*it) + 1 < ZV
9611 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9612 IT_BYTEPOS (*it) + 1,
9613 it->selective))
9614 {
9615 success_p = next_element_from_ellipsis (it);
9616 it->dpvec_char_len = -1;
9617 }
9618 }
9619 else if (it->c == '\r' && it->selective == -1)
9620 {
9621
9622
9623
9624 success_p = next_element_from_ellipsis (it);
9625 it->dpvec_char_len = -1;
9626 }
9627 }
9628 }
9629
9630
9631 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9632 return success_p;
9633 }
9634
9635
9636
9637
9638
9639
9640
9641 static bool
9642 next_element_from_composition (struct it *it)
9643 {
9644 it->what = IT_COMPOSITION;
9645 it->len = it->cmp_it.nbytes;
9646 if (STRINGP (it->string))
9647 {
9648 if (it->c < 0)
9649 {
9650 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9651 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9652 return false;
9653 }
9654 it->position = it->current.string_pos;
9655 it->object = it->string;
9656 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9657 IT_STRING_BYTEPOS (*it), it->string);
9658 }
9659 else
9660 {
9661 if (it->c < 0)
9662 {
9663 IT_CHARPOS (*it) += it->cmp_it.nchars;
9664 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9665 if (it->bidi_p)
9666 {
9667 if (it->bidi_it.new_paragraph)
9668 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9669 false);
9670
9671
9672 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9673 bidi_move_to_visually_next (&it->bidi_it);
9674 }
9675 return false;
9676 }
9677 it->position = it->current.pos;
9678 it->object = it->w->contents;
9679 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9680 IT_BYTEPOS (*it), Qnil);
9681 }
9682 return true;
9683 }
9684
9685
9686
9687
9688
9689
9690
9691
9692
9693
9694 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9695 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
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
9724
9725
9726
9727
9728
9729
9730
9731 static enum move_it_result
9732 move_it_in_display_line_to (struct it *it,
9733 ptrdiff_t to_charpos, int to_x,
9734 enum move_operation_enum op)
9735 {
9736 enum move_it_result result = MOVE_UNDEFINED;
9737 struct glyph_row *saved_glyph_row;
9738 struct it wrap_it, atpos_it, atx_it, ppos_it;
9739 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9740 void *ppos_data = NULL;
9741 bool may_wrap = false;
9742 enum it_method prev_method = it->method;
9743 ptrdiff_t closest_pos UNINIT;
9744 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9745 bool saw_smaller_pos = prev_pos < to_charpos;
9746 bool line_number_pending = false;
9747
9748
9749 saved_glyph_row = it->glyph_row;
9750 it->glyph_row = NULL;
9751
9752
9753
9754
9755
9756
9757 wrap_it.sp = -1;
9758 atpos_it.sp = -1;
9759 atx_it.sp = -1;
9760
9761
9762
9763
9764
9765
9766
9767
9768 if (it->bidi_p)
9769 {
9770 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9771 {
9772 SAVE_IT (ppos_it, *it, ppos_data);
9773 closest_pos = IT_CHARPOS (*it);
9774 }
9775 else
9776 closest_pos = ZV;
9777 }
9778
9779 #define BUFFER_POS_REACHED_P() \
9780 ((op & MOVE_TO_POS) != 0 \
9781 && BUFFERP (it->object) \
9782 && (IT_CHARPOS (*it) == to_charpos \
9783 || ((!it->bidi_p \
9784 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9785 && IT_CHARPOS (*it) > to_charpos) \
9786 || (it->what == IT_COMPOSITION \
9787 && ((IT_CHARPOS (*it) > to_charpos \
9788 && to_charpos >= it->cmp_it.charpos) \
9789 || (IT_CHARPOS (*it) < to_charpos \
9790 && to_charpos <= it->cmp_it.charpos)))) \
9791 && (it->method == GET_FROM_BUFFER \
9792 || (it->method == GET_FROM_DISPLAY_VECTOR \
9793 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9794
9795 if (it->hpos == 0)
9796 {
9797
9798
9799
9800
9801 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9802 && should_produce_line_number (it))
9803 {
9804 if (it->current_x == it->first_visible_x)
9805 maybe_produce_line_number (it);
9806 else
9807 line_number_pending = true;
9808 }
9809
9810 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9811 handle_line_prefix (it);
9812 }
9813
9814 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9815 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9816
9817 while (true)
9818 {
9819 int x, i, ascent = 0, descent = 0;
9820
9821
9822 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9823 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9824 (IT)->max_descent = descent)
9825
9826
9827
9828 if ((op & MOVE_TO_POS) != 0
9829 && BUFFERP (it->object)
9830 && it->method == GET_FROM_BUFFER
9831 && (((!it->bidi_p
9832
9833
9834
9835
9836 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9837 && IT_CHARPOS (*it) > to_charpos)
9838 || (it->bidi_p
9839 && (prev_method == GET_FROM_IMAGE
9840 || prev_method == GET_FROM_STRETCH
9841 || prev_method == GET_FROM_STRING)
9842
9843 && ((prev_pos < to_charpos
9844 && IT_CHARPOS (*it) >= to_charpos)
9845
9846 || (prev_pos > to_charpos
9847 && IT_CHARPOS (*it) <= to_charpos)))))
9848 {
9849 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9850 {
9851 result = MOVE_POS_MATCH_OR_ZV;
9852 break;
9853 }
9854 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9855
9856
9857
9858 SAVE_IT (atpos_it, *it, atpos_data);
9859 }
9860
9861
9862
9863
9864
9865 if (!get_next_display_element (it))
9866 {
9867 result = MOVE_POS_MATCH_OR_ZV;
9868 break;
9869 }
9870
9871 if (it->line_wrap == TRUNCATE)
9872 {
9873
9874
9875
9876
9877
9878
9879 if (BUFFER_POS_REACHED_P ()
9880 && (it->pixel_width > 0
9881 || IT_CHARPOS (*it) > to_charpos
9882 || it->area != TEXT_AREA))
9883 {
9884 result = MOVE_POS_MATCH_OR_ZV;
9885 break;
9886 }
9887 }
9888 else
9889 {
9890 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9891 {
9892 bool next_may_wrap = may_wrap;
9893
9894 if (char_can_wrap_after (it))
9895 next_may_wrap = true;
9896 else
9897 next_may_wrap = false;
9898
9899 if (may_wrap && char_can_wrap_before (it))
9900 {
9901
9902
9903
9904
9905
9906 if (atpos_it.sp >= 0)
9907 {
9908 RESTORE_IT (it, &atpos_it, atpos_data);
9909 result = MOVE_POS_MATCH_OR_ZV;
9910 goto done;
9911 }
9912 if (atx_it.sp >= 0)
9913 {
9914 RESTORE_IT (it, &atx_it, atx_data);
9915 result = MOVE_X_REACHED;
9916 goto done;
9917 }
9918
9919 SAVE_IT (wrap_it, *it, wrap_data);
9920 }
9921
9922 may_wrap = next_may_wrap;
9923 }
9924 }
9925
9926
9927
9928 ascent = it->max_ascent;
9929 descent = it->max_descent;
9930
9931
9932
9933
9934
9935 x = it->current_x;
9936
9937 PRODUCE_GLYPHS (it);
9938
9939 if (it->area != TEXT_AREA)
9940 {
9941 prev_method = it->method;
9942 if (it->method == GET_FROM_BUFFER)
9943 prev_pos = IT_CHARPOS (*it);
9944 set_iterator_to_next (it, true);
9945 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9946 SET_TEXT_POS (this_line_min_pos,
9947 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9948 if (it->bidi_p
9949 && (op & MOVE_TO_POS)
9950 && IT_CHARPOS (*it) > to_charpos
9951 && IT_CHARPOS (*it) < closest_pos)
9952 closest_pos = IT_CHARPOS (*it);
9953 continue;
9954 }
9955
9956
9957
9958
9959
9960
9961
9962
9963
9964
9965
9966
9967
9968
9969
9970
9971
9972
9973
9974 if (it->nglyphs)
9975 {
9976
9977
9978 int single_glyph_width = it->pixel_width / it->nglyphs;
9979 int new_x;
9980 int x_before_this_char = x;
9981 int hpos_before_this_char = it->hpos;
9982
9983 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9984 {
9985 new_x = x + single_glyph_width;
9986
9987
9988 if ((op & MOVE_TO_X) && new_x > to_x)
9989 {
9990 if (BUFFER_POS_REACHED_P ())
9991 {
9992 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9993 goto buffer_pos_reached;
9994 if (atpos_it.sp < 0)
9995 {
9996 SAVE_IT (atpos_it, *it, atpos_data);
9997 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9998 }
9999 }
10000 else
10001 {
10002 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10003 {
10004 it->current_x = x;
10005 result = MOVE_X_REACHED;
10006 break;
10007 }
10008 if (atx_it.sp < 0)
10009 {
10010 SAVE_IT (atx_it, *it, atx_data);
10011 IT_RESET_X_ASCENT_DESCENT (&atx_it);
10012 }
10013 }
10014 }
10015
10016 if (
10017 it->line_wrap != TRUNCATE
10018 && (
10019 new_x > it->last_visible_x
10020
10021
10022 || (new_x == it->last_visible_x
10023 && FRAME_WINDOW_P (it->f)
10024 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10025 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10026 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
10027 {
10028 bool moved_forward = false;
10029
10030 if (
10031
10032 it->hpos == 0
10033 || (new_x == it->last_visible_x
10034 && FRAME_WINDOW_P (it->f)))
10035 {
10036 ++it->hpos;
10037 it->current_x = new_x;
10038
10039
10040
10041 if (i == it->nglyphs - 1)
10042 {
10043
10044
10045
10046 if (BUFFER_POS_REACHED_P ())
10047 {
10048 bool can_wrap = true;
10049
10050
10051
10052
10053
10054 if (it->line_wrap == WORD_WRAP
10055 && wrap_it.sp >= 0
10056 && may_wrap
10057 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10058 {
10059 struct it tem_it;
10060 void *tem_data = NULL;
10061
10062 SAVE_IT (tem_it, *it, tem_data);
10063 set_iterator_to_next (it, true);
10064 if (get_next_display_element (it)
10065 && !char_can_wrap_before (it))
10066 can_wrap = false;
10067 RESTORE_IT (it, &tem_it, tem_data);
10068 }
10069 if (it->line_wrap != WORD_WRAP
10070 || wrap_it.sp < 0
10071
10072
10073
10074
10075
10076
10077
10078 || (may_wrap && can_wrap
10079 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10080 {
10081 it->hpos = hpos_before_this_char;
10082 it->current_x = x_before_this_char;
10083 result = MOVE_POS_MATCH_OR_ZV;
10084 break;
10085 }
10086 if (it->line_wrap == WORD_WRAP
10087 && atpos_it.sp < 0)
10088 {
10089 SAVE_IT (atpos_it, *it, atpos_data);
10090 atpos_it.current_x = x_before_this_char;
10091 atpos_it.hpos = hpos_before_this_char;
10092 }
10093 }
10094
10095 prev_method = it->method;
10096 if (it->method == GET_FROM_BUFFER)
10097 prev_pos = IT_CHARPOS (*it);
10098 set_iterator_to_next (it, true);
10099 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10100 SET_TEXT_POS (this_line_min_pos,
10101 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10102
10103
10104
10105
10106
10107
10108
10109 if (!FRAME_WINDOW_P (it->f)
10110 || ((it->bidi_p
10111 && it->bidi_it.paragraph_dir == R2L)
10112 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10113 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10114 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10115 {
10116 if (!get_next_display_element (it))
10117 {
10118 result = MOVE_POS_MATCH_OR_ZV;
10119 break;
10120 }
10121 moved_forward = true;
10122 if (BUFFER_POS_REACHED_P ())
10123 {
10124 if (ITERATOR_AT_END_OF_LINE_P (it))
10125 result = MOVE_POS_MATCH_OR_ZV;
10126 else
10127 result = MOVE_LINE_CONTINUED;
10128 break;
10129 }
10130 if (ITERATOR_AT_END_OF_LINE_P (it)
10131 && (it->line_wrap != WORD_WRAP
10132 || wrap_it.sp < 0
10133 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10134 {
10135 result = MOVE_NEWLINE_OR_CR;
10136 break;
10137 }
10138 }
10139 }
10140 }
10141 else
10142 IT_RESET_X_ASCENT_DESCENT (it);
10143
10144
10145
10146
10147
10148
10149 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10150
10151
10152
10153
10154
10155 && (!moved_forward || char_can_wrap_before (it)))
10156 {
10157
10158
10159 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10160 && atx_it.sp >= 0)
10161 {
10162 RESTORE_IT (it, &atx_it, atx_data);
10163 atpos_it.sp = -1;
10164 atx_it.sp = -1;
10165 result = MOVE_X_REACHED;
10166 break;
10167 }
10168 }
10169 else if (wrap_it.sp >= 0)
10170 {
10171 RESTORE_IT (it, &wrap_it, wrap_data);
10172 atpos_it.sp = -1;
10173 atx_it.sp = -1;
10174 }
10175
10176 move_trace ("move_it_in: continued at %td\n",
10177 IT_CHARPOS (*it));
10178 result = MOVE_LINE_CONTINUED;
10179 break;
10180 }
10181
10182 if (BUFFER_POS_REACHED_P ())
10183 {
10184 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10185 goto buffer_pos_reached;
10186 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10187 {
10188 SAVE_IT (atpos_it, *it, atpos_data);
10189 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10190 }
10191 }
10192
10193 if (new_x > it->first_visible_x)
10194 {
10195
10196
10197 if (line_number_pending)
10198 {
10199 line_number_pending = false;
10200 it->current_x = it->first_visible_x;
10201 maybe_produce_line_number (it);
10202 it->current_x += new_x - it->first_visible_x;
10203 }
10204
10205
10206 ++it->hpos;
10207 }
10208 }
10209
10210 if (result != MOVE_UNDEFINED)
10211 break;
10212 }
10213 else if (BUFFER_POS_REACHED_P ())
10214 {
10215 buffer_pos_reached:
10216 IT_RESET_X_ASCENT_DESCENT (it);
10217 result = MOVE_POS_MATCH_OR_ZV;
10218 break;
10219 }
10220 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10221 {
10222
10223
10224
10225
10226 eassert (it->nglyphs == 0);
10227 result = MOVE_X_REACHED;
10228 break;
10229 }
10230
10231
10232 if (ITERATOR_AT_END_OF_LINE_P (it))
10233 {
10234
10235
10236
10237
10238 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10239 {
10240 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10241 {
10242 if (closest_pos < ZV)
10243 {
10244 RESTORE_IT (it, &ppos_it, ppos_data);
10245
10246
10247 if (closest_pos != to_charpos)
10248 move_it_in_display_line_to (it, closest_pos, -1,
10249 MOVE_TO_POS);
10250 result = MOVE_POS_MATCH_OR_ZV;
10251 }
10252 else
10253 goto buffer_pos_reached;
10254 }
10255 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10256 && IT_CHARPOS (*it) > to_charpos)
10257 goto buffer_pos_reached;
10258 else
10259 result = MOVE_NEWLINE_OR_CR;
10260 }
10261 else
10262 result = MOVE_NEWLINE_OR_CR;
10263
10264
10265
10266
10267 if (it->line_wrap == TRUNCATE
10268 && it->current_x <= it->first_visible_x
10269 && result == MOVE_NEWLINE_OR_CR
10270 && it->char_to_display == '\n')
10271 {
10272 it->max_ascent = it->ascent;
10273 it->max_descent = it->descent;
10274 }
10275
10276
10277
10278 if (result == MOVE_NEWLINE_OR_CR)
10279 it->constrain_row_ascent_descent_p = false;
10280 break;
10281 }
10282
10283 prev_method = it->method;
10284 if (it->method == GET_FROM_BUFFER)
10285 prev_pos = IT_CHARPOS (*it);
10286
10287
10288
10289
10290
10291
10292
10293
10294
10295 bool overwide_wrap_prefix =
10296 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10297 && it->sp > 0 && it->method == GET_FROM_STRETCH
10298 && it->current_x >= it->last_visible_x
10299 && it->continuation_lines_width > 0
10300 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10301
10302
10303 if (!overwide_wrap_prefix)
10304 set_iterator_to_next (it, true);
10305 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10306 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10307 if (IT_CHARPOS (*it) < to_charpos)
10308 saw_smaller_pos = true;
10309 if (it->bidi_p
10310 && (op & MOVE_TO_POS)
10311 && IT_CHARPOS (*it) >= to_charpos
10312 && IT_CHARPOS (*it) < closest_pos)
10313 closest_pos = IT_CHARPOS (*it);
10314
10315
10316
10317 if (it->line_wrap == TRUNCATE
10318 && it->current_x >= it->last_visible_x)
10319 {
10320 if (!FRAME_WINDOW_P (it->f)
10321 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10322 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10323 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10324 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10325 {
10326 bool at_eob_p = false;
10327
10328 if ((at_eob_p = !get_next_display_element (it))
10329 || BUFFER_POS_REACHED_P ()
10330
10331
10332
10333
10334 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10335 && !saw_smaller_pos
10336 && IT_CHARPOS (*it) > to_charpos))
10337 {
10338 if (it->bidi_p
10339 && !BUFFER_POS_REACHED_P ()
10340 && !at_eob_p && closest_pos < ZV)
10341 {
10342 RESTORE_IT (it, &ppos_it, ppos_data);
10343 if (closest_pos != to_charpos)
10344 move_it_in_display_line_to (it, closest_pos, -1,
10345 MOVE_TO_POS);
10346 }
10347 result = MOVE_POS_MATCH_OR_ZV;
10348 break;
10349 }
10350 if (ITERATOR_AT_END_OF_LINE_P (it))
10351 {
10352 result = MOVE_NEWLINE_OR_CR;
10353 break;
10354 }
10355 }
10356 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10357 && !saw_smaller_pos
10358 && IT_CHARPOS (*it) > to_charpos)
10359 {
10360 if (closest_pos < ZV)
10361 {
10362 RESTORE_IT (it, &ppos_it, ppos_data);
10363 if (closest_pos != to_charpos)
10364 move_it_in_display_line_to (it, closest_pos, -1,
10365 MOVE_TO_POS);
10366 }
10367 result = MOVE_POS_MATCH_OR_ZV;
10368 break;
10369 }
10370 result = MOVE_LINE_TRUNCATED;
10371 break;
10372 }
10373 #undef IT_RESET_X_ASCENT_DESCENT
10374 }
10375
10376 #undef BUFFER_POS_REACHED_P
10377
10378
10379
10380
10381
10382
10383 if (result == MOVE_LINE_CONTINUED
10384 && it->line_wrap == WORD_WRAP
10385 && wrap_it.sp >= 0
10386 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10387 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10388 RESTORE_IT (it, &wrap_it, wrap_data);
10389 else if (atpos_it.sp >= 0)
10390 RESTORE_IT (it, &atpos_it, atpos_data);
10391 else if (atx_it.sp >= 0)
10392 RESTORE_IT (it, &atx_it, atx_data);
10393
10394 done:
10395
10396 if (atpos_data)
10397 bidi_unshelve_cache (atpos_data, true);
10398 if (atx_data)
10399 bidi_unshelve_cache (atx_data, true);
10400 if (wrap_data)
10401 bidi_unshelve_cache (wrap_data, true);
10402 if (ppos_data)
10403 bidi_unshelve_cache (ppos_data, true);
10404
10405
10406
10407 it->glyph_row = saved_glyph_row;
10408 return result;
10409 }
10410
10411
10412 void
10413 move_it_in_display_line (struct it *it,
10414 ptrdiff_t to_charpos, int to_x,
10415 enum move_operation_enum op)
10416 {
10417 if (it->line_wrap == WORD_WRAP
10418 && (op & MOVE_TO_X))
10419 {
10420 struct it save_it;
10421 void *save_data = NULL;
10422 int skip;
10423
10424 SAVE_IT (save_it, *it, save_data);
10425 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10426
10427
10428
10429
10430 if (skip == MOVE_LINE_CONTINUED)
10431 {
10432 int prev_x = max (it->current_x - 1, 0);
10433 RESTORE_IT (it, &save_it, save_data);
10434 move_it_in_display_line_to
10435 (it, -1, prev_x, MOVE_TO_X);
10436 }
10437 else
10438 bidi_unshelve_cache (save_data, true);
10439 }
10440 else
10441 move_it_in_display_line_to (it, to_charpos, to_x, op);
10442 }
10443
10444
10445
10446
10447
10448
10449
10450
10451
10452
10453
10454
10455
10456
10457
10458
10459 int
10460 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10461 {
10462 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10463 int line_height, line_start_x = 0, reached = 0;
10464 int max_current_x = 0;
10465 void *backup_data = NULL;
10466 ptrdiff_t orig_charpos = -1;
10467 enum it_method orig_method = NUM_IT_METHODS;
10468
10469 for (;;)
10470 {
10471 orig_charpos = IT_CHARPOS (*it);
10472 orig_method = it->method;
10473 if (op & MOVE_TO_VPOS)
10474 {
10475
10476
10477 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10478 {
10479 if (it->vpos == to_vpos)
10480 {
10481 reached = 1;
10482 break;
10483 }
10484 else
10485 skip = move_it_in_display_line_to (it, -1, -1, 0);
10486 }
10487 else
10488 {
10489
10490
10491 if (it->vpos == to_vpos)
10492 {
10493 reached = 2;
10494 break;
10495 }
10496
10497 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10498
10499 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10500 {
10501 reached = 3;
10502 break;
10503 }
10504 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10505 {
10506
10507 skip = move_it_in_display_line_to (it, to_charpos,
10508 -1, MOVE_TO_POS);
10509 if (skip == MOVE_POS_MATCH_OR_ZV)
10510 {
10511 reached = 4;
10512 break;
10513 }
10514 }
10515 }
10516 }
10517 else if (op & MOVE_TO_Y)
10518 {
10519 struct it it_backup;
10520
10521 if (it->line_wrap == WORD_WRAP)
10522 SAVE_IT (it_backup, *it, backup_data);
10523
10524
10525
10526
10527
10528
10529
10530
10531
10532
10533
10534
10535
10536 skip = move_it_in_display_line_to
10537 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10538 (MOVE_TO_X | (op & MOVE_TO_POS)));
10539
10540
10541 if (skip == MOVE_POS_MATCH_OR_ZV)
10542 reached = 5;
10543 else if (skip == MOVE_X_REACHED)
10544 {
10545
10546
10547
10548
10549 line_height = it->max_ascent + it->max_descent;
10550 if (to_y >= it->current_y
10551 && to_y < it->current_y + line_height)
10552 {
10553 reached = 6;
10554 break;
10555 }
10556 SAVE_IT (it_backup, *it, backup_data);
10557 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10558 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10559 op & MOVE_TO_POS);
10560 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10561 line_height = it->max_ascent + it->max_descent;
10562 move_trace ("move_it: line_height = %d\n", line_height);
10563
10564 if (to_y >= it->current_y
10565 && to_y < it->current_y + line_height)
10566 {
10567
10568
10569
10570
10571
10572
10573
10574
10575 int max_ascent = it->max_ascent;
10576 int max_descent = it->max_descent;
10577
10578 RESTORE_IT (it, &it_backup, backup_data);
10579 it->max_ascent = max_ascent;
10580 it->max_descent = max_descent;
10581 reached = 6;
10582 }
10583 else
10584 {
10585 skip = skip2;
10586 if (skip == MOVE_POS_MATCH_OR_ZV)
10587 {
10588 reached = 7;
10589
10590
10591
10592
10593
10594
10595
10596 if (to_charpos > 0
10597 && IT_CHARPOS (*it) != to_charpos
10598 && ((IT_CHARPOS (it_backup) > to_charpos)
10599 == (IT_CHARPOS (*it) > to_charpos)))
10600 {
10601 int max_ascent = it->max_ascent;
10602 int max_descent = it->max_descent;
10603
10604 RESTORE_IT (it, &it_backup, backup_data);
10605 it->max_ascent = max_ascent;
10606 it->max_descent = max_descent;
10607 }
10608 }
10609 }
10610 }
10611 else
10612 {
10613
10614 line_height = it->max_ascent + it->max_descent;
10615 move_trace ("move_it: line_height = %d\n", line_height);
10616
10617 if (to_y >= it->current_y
10618 && to_y < it->current_y + line_height)
10619 {
10620 if (to_y > it->current_y)
10621 max_current_x = max (it->current_x, max_current_x);
10622
10623
10624
10625
10626
10627 if (skip == MOVE_LINE_CONTINUED
10628 && it->line_wrap == WORD_WRAP)
10629 {
10630 int prev_x = max (it->current_x - 1, 0);
10631 RESTORE_IT (it, &it_backup, backup_data);
10632 skip = move_it_in_display_line_to
10633 (it, -1, prev_x, MOVE_TO_X);
10634 }
10635
10636 reached = 6;
10637 }
10638 }
10639
10640 if (reached)
10641 {
10642 max_current_x = max (it->current_x, max_current_x);
10643 break;
10644 }
10645 }
10646 else if (BUFFERP (it->object)
10647 && (it->method == GET_FROM_BUFFER
10648 || it->method == GET_FROM_STRETCH)
10649 && IT_CHARPOS (*it) >= to_charpos
10650
10651
10652
10653
10654
10655 && !(it->bidi_p
10656 && it->bidi_it.scan_dir == -1))
10657 skip = MOVE_POS_MATCH_OR_ZV;
10658 else
10659 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10660
10661 switch (skip)
10662 {
10663 case MOVE_POS_MATCH_OR_ZV:
10664 max_current_x = max (it->current_x, max_current_x);
10665 reached = 8;
10666 goto out;
10667
10668 case MOVE_NEWLINE_OR_CR:
10669 max_current_x = max (it->current_x, max_current_x);
10670 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10671 it->override_ascent = -1;
10672 set_iterator_to_next (it, true);
10673 it->continuation_lines_width = 0;
10674 break;
10675
10676 case MOVE_LINE_TRUNCATED:
10677 max_current_x = it->last_visible_x;
10678 it->continuation_lines_width = 0;
10679 reseat_at_next_visible_line_start (it, false);
10680 if ((op & MOVE_TO_POS) != 0
10681 && (IT_CHARPOS (*it) > to_charpos
10682 || (IT_CHARPOS (*it) == to_charpos
10683
10684
10685 && to_charpos == ZV
10686 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10687
10688
10689
10690 && (it->sp == 0
10691 || (STRINGP (it->string)
10692 && (it->current.overlay_string_index < 0
10693 || (it->current.overlay_string_index >= 0
10694 && it->current.overlay_string_index
10695 >= it->n_overlay_strings - 1))
10696 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10697 {
10698 reached = 9;
10699 goto out;
10700 }
10701 break;
10702
10703 case MOVE_LINE_CONTINUED:
10704 max_current_x = it->last_visible_x;
10705
10706
10707
10708
10709 if (it->c == '\t')
10710 {
10711 it->continuation_lines_width += it->last_visible_x;
10712
10713
10714
10715 if (it->current_x != it->last_visible_x
10716 && (op & MOVE_TO_VPOS)
10717 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10718 {
10719 line_start_x = it->current_x + it->pixel_width
10720 - it->last_visible_x;
10721 if (FRAME_WINDOW_P (it->f))
10722 {
10723 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10724 struct font *face_font = face->font;
10725
10726
10727
10728
10729
10730
10731
10732 eassert (face_font);
10733 if (face_font)
10734 {
10735 if (line_start_x < face_font->space_width)
10736 line_start_x
10737 += it->tab_width * face_font->space_width;
10738 }
10739 }
10740 set_iterator_to_next (it, false);
10741 }
10742 }
10743 else
10744 {
10745
10746
10747
10748
10749
10750
10751
10752
10753 if (IT_CHARPOS (*it) == orig_charpos
10754 && it->method == orig_method
10755 && orig_method == GET_FROM_BUFFER)
10756 set_iterator_to_next (it, false);
10757 it->continuation_lines_width += it->current_x;
10758 }
10759 break;
10760
10761 default:
10762 emacs_abort ();
10763 }
10764
10765
10766 it->current_x = line_start_x;
10767 line_start_x = 0;
10768 it->hpos = 0;
10769 it->line_number_produced_p = false;
10770 it->current_y += it->max_ascent + it->max_descent;
10771 ++it->vpos;
10772 last_height = it->max_ascent + it->max_descent;
10773 it->max_ascent = it->max_descent = 0;
10774 }
10775
10776 out:
10777
10778
10779
10780
10781
10782
10783 if (!FRAME_WINDOW_P (it->f)
10784 && op & MOVE_TO_POS
10785 && IT_CHARPOS (*it) == to_charpos
10786 && it->what == IT_CHARACTER
10787 && it->nglyphs > 1
10788 && it->line_wrap == WINDOW_WRAP
10789 && it->current_x == it->last_visible_x - 1
10790 && it->c != '\n'
10791 && it->c != '\t'
10792 && it->w->window_end_valid
10793 && it->vpos < it->w->window_end_vpos)
10794 {
10795 it->continuation_lines_width += it->current_x;
10796 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10797 it->current_y += it->max_ascent + it->max_descent;
10798 ++it->vpos;
10799 last_height = it->max_ascent + it->max_descent;
10800 }
10801
10802 if (backup_data)
10803 bidi_unshelve_cache (backup_data, true);
10804
10805 move_trace ("move_it_to: reached %d\n", reached);
10806
10807 return max_current_x;
10808 }
10809
10810
10811
10812
10813
10814
10815
10816
10817
10818
10819
10820 void
10821 move_it_vertically_backward (struct it *it, int dy)
10822 {
10823 int nlines, h;
10824 struct it it2, it3;
10825 void *it2data = NULL, *it3data = NULL;
10826 ptrdiff_t start_pos;
10827 int nchars_per_row
10828 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10829 ptrdiff_t pos_limit;
10830
10831 move_further_back:
10832 eassert (dy >= 0);
10833
10834 start_pos = IT_CHARPOS (*it);
10835
10836
10837 nlines = max (1, dy / default_line_pixel_height (it->w));
10838 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10839 pos_limit = BEGV;
10840 else
10841 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10842
10843
10844
10845
10846 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10847 back_to_previous_visible_line_start (it);
10848
10849
10850
10851
10852
10853 reseat_1 (it, it->current.pos, true);
10854
10855
10856 it->current_x = it->hpos = 0;
10857
10858 it->continuation_lines_width = 0;
10859
10860
10861
10862
10863
10864 SAVE_IT (it2, *it, it2data);
10865 it2.max_ascent = it2.max_descent = 0;
10866 do
10867 {
10868 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10869 MOVE_TO_POS | MOVE_TO_VPOS);
10870 }
10871 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10872
10873
10874
10875
10876
10877
10878 || (it2.method == GET_FROM_STRING
10879 && IT_CHARPOS (it2) == start_pos
10880 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10881 eassert (IT_CHARPOS (*it) >= BEGV);
10882 SAVE_IT (it3, it2, it3data);
10883
10884 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10885 eassert (IT_CHARPOS (*it) >= BEGV);
10886
10887
10888 h = it2.current_y - it->current_y;
10889
10890 nlines = it2.vpos - it->vpos;
10891
10892
10893
10894 it->vpos -= nlines;
10895 it->current_y -= h;
10896
10897 if (dy == 0)
10898 {
10899
10900
10901
10902 RESTORE_IT (it, it, it2data);
10903 if (nlines > 0)
10904 move_it_by_lines (it, nlines);
10905
10906
10907
10908
10909
10910
10911 if (it->bidi_p
10912 && !it->continuation_lines_width
10913 && !STRINGP (it->string)
10914 && IT_CHARPOS (*it) > BEGV
10915 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10916 {
10917 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10918
10919 dec_both (&cp, &bp);
10920 SET_WITH_NARROWED_BEGV (it, cp,
10921 find_newline_no_quit (cp, bp, -1, NULL),
10922 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10923 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10924 }
10925 bidi_unshelve_cache (it3data, true);
10926 }
10927 else
10928 {
10929
10930
10931 int target_y = it->current_y + h - dy;
10932 int y0 = it3.current_y;
10933 int y1;
10934 int line_height;
10935
10936 RESTORE_IT (&it3, &it3, it3data);
10937 y1 = line_bottom_y (&it3);
10938 line_height = y1 - y0;
10939 RESTORE_IT (it, it, it2data);
10940
10941
10942 if (target_y < it->current_y
10943
10944
10945
10946
10947 && (it->current_y - target_y
10948 > min (window_box_height (it->w), line_height * 2 / 3))
10949 && IT_CHARPOS (*it) > BEGV)
10950 {
10951 move_trace (" not far enough -> move_vert %d\n",
10952 target_y - it->current_y);
10953 dy = it->current_y - target_y;
10954 goto move_further_back;
10955 }
10956 else if (target_y >= it->current_y + line_height
10957 && IT_CHARPOS (*it) < ZV)
10958 {
10959
10960
10961
10962
10963
10964
10965
10966
10967 if (!FRAME_WINDOW_P (it->f))
10968 move_it_vertically (it, target_y - it->current_y);
10969 else
10970 {
10971 struct text_pos last_pos;
10972 int last_y, last_vpos;
10973 do
10974 {
10975 last_pos = it->current.pos;
10976 last_y = it->current_y;
10977 last_vpos = it->vpos;
10978 move_it_by_lines (it, 1);
10979 }
10980 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10981 if (it->current_y > target_y)
10982 {
10983 reseat (it, last_pos, true);
10984 it->current_y = last_y;
10985 it->vpos = last_vpos;
10986 }
10987 }
10988 }
10989 }
10990 }
10991
10992
10993
10994
10995
10996
10997 void
10998 move_it_vertically (struct it *it, int dy)
10999 {
11000 if (dy <= 0)
11001 move_it_vertically_backward (it, -dy);
11002 else
11003 {
11004 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
11005 move_it_to (it, ZV, -1, it->current_y + dy, -1,
11006 MOVE_TO_POS | MOVE_TO_Y);
11007 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
11008
11009
11010
11011 if (IT_CHARPOS (*it) == ZV
11012 && ZV > BEGV
11013 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
11014 move_it_by_lines (it, 0);
11015 }
11016 }
11017
11018
11019
11020
11021 void
11022 move_it_past_eol (struct it *it)
11023 {
11024 enum move_it_result rc;
11025
11026 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
11027 if (rc == MOVE_NEWLINE_OR_CR)
11028 set_iterator_to_next (it, false);
11029 }
11030
11031
11032
11033
11034
11035
11036
11037
11038
11039
11040 void
11041 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
11042 {
11043
11044
11045
11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
11056
11057
11058
11059
11060 if (dvpos == 0)
11061 {
11062
11063 move_it_vertically_backward (it, 0);
11064
11065 last_height = 0;
11066 }
11067 else if (dvpos > 0)
11068 {
11069 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
11070 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11071 {
11072
11073
11074
11075
11076
11077
11078
11079
11080
11081
11082 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11083 -1, -1, -1, MOVE_TO_POS);
11084 }
11085 }
11086 else
11087 {
11088 struct it it2;
11089 void *it2data = NULL;
11090 ptrdiff_t start_charpos, orig_charpos, i;
11091 int nchars_per_row
11092 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11093 bool hit_pos_limit = false;
11094 ptrdiff_t pos_limit;
11095
11096
11097
11098
11099 dvpos += it->vpos;
11100 orig_charpos = IT_CHARPOS (*it);
11101 move_it_vertically_backward (it, 0);
11102 dvpos -= it->vpos;
11103
11104
11105
11106 start_charpos = IT_CHARPOS (*it);
11107 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11108 pos_limit = BEGV;
11109 else
11110 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11111
11112 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11113 back_to_previous_visible_line_start (it);
11114 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11115 hit_pos_limit = true;
11116 reseat (it, it->current.pos, true);
11117
11118
11119 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11120 {
11121
11122 dvpos += it->vpos;
11123 move_it_vertically_backward (it, 0);
11124 dvpos -= it->vpos;
11125 if (IT_POS_VALID_AFTER_MOVE_P (it))
11126 break;
11127
11128
11129 back_to_previous_visible_line_start (it);
11130 reseat (it, it->current.pos, true);
11131 dvpos--;
11132 }
11133
11134 it->current_x = it->hpos = 0;
11135
11136
11137
11138 SAVE_IT (it2, *it, it2data);
11139 it2.vpos = it2.current_y = 0;
11140 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11141 it->vpos -= it2.vpos;
11142 it->current_y -= it2.current_y;
11143 it->current_x = it->hpos = 0;
11144
11145
11146 if (it2.vpos > -dvpos)
11147 {
11148 int delta = it2.vpos + dvpos;
11149
11150 RESTORE_IT (&it2, &it2, it2data);
11151 SAVE_IT (it2, *it, it2data);
11152 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11153
11154
11155 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11156 RESTORE_IT (it, &it2, it2data);
11157 else
11158 bidi_unshelve_cache (it2data, true);
11159 }
11160 else if (hit_pos_limit && pos_limit > BEGV
11161 && dvpos < 0 && it2.vpos < -dvpos)
11162 {
11163
11164
11165
11166
11167
11168
11169
11170
11171 dvpos += it2.vpos;
11172 RESTORE_IT (it, it, it2data);
11173 for (i = -dvpos; i > 0; --i)
11174 {
11175 back_to_previous_visible_line_start (it);
11176 it->vpos--;
11177 }
11178 reseat_1 (it, it->current.pos, true);
11179 }
11180 else
11181 RESTORE_IT (it, it, it2data);
11182 }
11183 }
11184
11185 int
11186 partial_line_height (struct it *it_origin)
11187 {
11188
11189
11190
11191
11192
11193 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11194 && it_origin->line_wrap == TRUNCATE)
11195 return 0;
11196
11197 int partial_height;
11198 void *it_data = NULL;
11199 struct it it;
11200 SAVE_IT (it, *it_origin, it_data);
11201 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11202 MOVE_TO_POS | MOVE_TO_Y);
11203 if (it.what == IT_EOB)
11204 {
11205 int vis_height = it.last_visible_y - it.current_y;
11206 int height = it.ascent + it.descent;
11207 partial_height = (vis_height < height) ? vis_height : 0;
11208 }
11209 else
11210 {
11211 int last_line_y = it.current_y;
11212 move_it_by_lines (&it, 1);
11213 partial_height = (it.current_y > it.last_visible_y)
11214 ? it.last_visible_y - last_line_y : 0;
11215 }
11216 RESTORE_IT (&it, &it, it_data);
11217 return partial_height;
11218 }
11219
11220
11221
11222
11223
11224
11225
11226
11227
11228
11229
11230
11231 static enum move_it_result
11232 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11233 {
11234 ptrdiff_t nl_bytepos;
11235 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11236 1, &nl_bytepos);
11237 struct text_pos new_pos;
11238 enum move_it_result move_result;
11239
11240 if (nl_pos - IT_CHARPOS (*it) > nchars)
11241 {
11242 SET_TEXT_POS (new_pos,
11243 IT_CHARPOS (*it) + nchars,
11244 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11245 move_result = MOVE_X_REACHED;
11246 }
11247 else
11248 {
11249 if (nl_bytepos < ZV_BYTE
11250 || (nl_bytepos > BEGV_BYTE
11251 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11252 {
11253 nl_pos--;
11254 nl_bytepos--;
11255 move_result = MOVE_NEWLINE_OR_CR;
11256 }
11257 else
11258 move_result = MOVE_POS_MATCH_OR_ZV;
11259 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11260 }
11261 reseat (it, new_pos, false);
11262 return move_result;
11263 }
11264
11265
11266
11267 bool
11268 in_display_vector_p (struct it *it)
11269 {
11270 return (it->method == GET_FROM_DISPLAY_VECTOR
11271 && it->current.dpvec_index > 0
11272 && it->dpvec + it->current.dpvec_index != it->dpend);
11273 }
11274
11275
11276
11277
11278
11279 static Lisp_Object
11280 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11281 Lisp_Object x_limit, Lisp_Object y_limit,
11282 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11283 {
11284 struct window *w = decode_live_window (window);
11285 struct it it;
11286 ptrdiff_t start, end, bpos;
11287 struct text_pos startp;
11288 void *itdata = NULL;
11289 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11290
11291 if (NILP (from))
11292 {
11293 start = BEGV;
11294 bpos = BEGV_BYTE;
11295 }
11296 else if (EQ (from, Qt))
11297 {
11298 start = BEGV;
11299 bpos = BEGV_BYTE;
11300 while (bpos < ZV_BYTE)
11301 {
11302 c = FETCH_BYTE (bpos);
11303 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11304 break;
11305 inc_both (&start, &bpos);
11306 }
11307 while (bpos > BEGV_BYTE)
11308 {
11309 dec_both (&start, &bpos);
11310 c = FETCH_BYTE (bpos);
11311 if (!(c == ' ' || c == '\t'))
11312 break;
11313 }
11314 }
11315 else if (CONSP (from))
11316 {
11317 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11318 bpos = CHAR_TO_BYTE (start);
11319 CHECK_FIXNUM (XCDR (from));
11320 vertical_offset = XFIXNUM (XCDR (from));
11321 }
11322 else
11323 {
11324 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11325 bpos = CHAR_TO_BYTE (start);
11326 }
11327
11328 SET_TEXT_POS (startp, start, bpos);
11329
11330 if (NILP (to))
11331 end = ZV;
11332 else if (EQ (to, Qt))
11333 {
11334 end = ZV;
11335 bpos = ZV_BYTE;
11336 while (bpos > BEGV_BYTE)
11337 {
11338 dec_both (&end, &bpos);
11339 c = FETCH_BYTE (bpos);
11340 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11341 {
11342 inc_both (&end, &bpos);
11343 break;
11344 }
11345 }
11346 while (bpos < ZV_BYTE)
11347 {
11348 c = fetch_char_advance (&end, &bpos);
11349 if (!(c == ' ' || c == '\t'))
11350 break;
11351 }
11352 }
11353 else
11354 end = clip_to_bounds (start, fix_position (to), ZV);
11355
11356 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11357 max_x = XFIXNUM (x_limit);
11358 else if (!NILP (x_limit))
11359 max_x = INT_MAX;
11360
11361 if (NILP (y_limit))
11362 max_y = INT_MAX;
11363 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11364 max_y = XFIXNUM (y_limit);
11365
11366 itdata = bidi_shelve_cache ();
11367
11368 start_display (&it, w, startp);
11369
11370 int start_y = it.current_y;
11371
11372
11373
11374
11375
11376
11377
11378 it.bidi_p = false;
11379
11380 int start_x;
11381 if (vertical_offset != 0)
11382 {
11383 int last_y;
11384 it.current_y = 0;
11385
11386 move_it_by_lines (&it, 0);
11387
11388
11389
11390
11391
11392 if (vertical_offset < 0)
11393 {
11394 while (it.current_y > vertical_offset)
11395 {
11396 last_y = it.current_y;
11397 move_it_vertically_backward (&it,
11398 (abs (vertical_offset)
11399 + it.current_y));
11400
11401 if (it.current_y == last_y)
11402 break;
11403 }
11404 }
11405 else
11406 {
11407 move_it_vertically (&it, vertical_offset);
11408 }
11409
11410 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11411 + WINDOW_HEADER_LINE_HEIGHT (w));
11412 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11413 start_y = it.current_y;
11414 start_x = it.current_x;
11415 }
11416 else
11417 {
11418
11419
11420
11421 reseat_at_previous_visible_line_start (&it);
11422 it.current_x = it.hpos = 0;
11423 if (IT_CHARPOS (it) != start)
11424 {
11425 void *it1data = NULL;
11426 struct it it1;
11427
11428 SAVE_IT (it1, it, it1data);
11429 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11430
11431
11432
11433
11434
11435 if (IT_CHARPOS (it) > start && start > BEGV)
11436 {
11437 ptrdiff_t it1pos = IT_CHARPOS (it1);
11438 int it1_x = it1.current_x;
11439
11440 RESTORE_IT (&it, &it1, it1data);
11441
11442
11443
11444
11445
11446 if (start - 1 > it1pos)
11447 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11448 else
11449 move_it_in_display_line (&it, start, it1_x + 1,
11450 MOVE_TO_POS | MOVE_TO_X);
11451 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11452 start_x = it.current_x;
11453
11454
11455
11456 if (IT_CHARPOS (it) == start - 1)
11457 start_x += it.pixel_width;
11458 }
11459 else
11460 {
11461 start_x = it.current_x;
11462 bidi_unshelve_cache (it1data, true);
11463 }
11464 }
11465 else
11466 start_x = it.current_x;
11467 }
11468
11469
11470 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11471 int to_x = -1;
11472 it.current_y = start_y;
11473
11474
11475 if (FETCH_BYTE (start) == '\n')
11476 it.current_x = 0;
11477 if (!NILP (x_limit))
11478 {
11479 it.last_visible_x = max_x;
11480
11481
11482
11483 move_op |= MOVE_TO_X;
11484 to_x = INT_MAX;
11485 }
11486
11487 void *it2data = NULL;
11488 struct it it2;
11489 SAVE_IT (it2, it, it2data);
11490
11491 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11492
11493
11494
11495
11496
11497 if (IT_CHARPOS (it) > end)
11498 {
11499 end--;
11500 RESTORE_IT (&it, &it2, it2data);
11501 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11502
11503
11504
11505 if (IT_CHARPOS (it) == end)
11506 {
11507 x += it.pixel_width;
11508
11509
11510 if (!NILP (ignore_line_at_end))
11511 doff = (max (it.max_ascent, it.ascent)
11512 + max (it.max_descent, it.descent));
11513 else
11514 {
11515 it.max_ascent = max (it.max_ascent, it.ascent);
11516 it.max_descent = max (it.max_descent, it.descent);
11517 }
11518 }
11519 }
11520 else
11521 bidi_unshelve_cache (it2data, true);
11522
11523 if (!NILP (x_limit))
11524 {
11525
11526 if (x > max_x)
11527 x = max_x;
11528 }
11529
11530
11531
11532
11533 if (it.current_y > start_y)
11534 start_x = 0;
11535
11536
11537
11538 if (!NILP (ignore_line_at_end))
11539 y = (it.current_y + doff
11540 - WINDOW_TAB_LINE_HEIGHT (w)
11541 - WINDOW_HEADER_LINE_HEIGHT (w));
11542 else
11543 y = (it.current_y + it.max_ascent + it.max_descent + doff
11544 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11545
11546
11547 if (y > max_y)
11548 y = max_y;
11549
11550 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11551 && window_wants_tab_line (w))
11552
11553 {
11554 Lisp_Object window_tab_line_format
11555 = window_parameter (w, Qtab_line_format);
11556
11557 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11558 NILP (window_tab_line_format)
11559 ? BVAR (current_buffer, tab_line_format)
11560 : window_tab_line_format);
11561 }
11562
11563 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11564 && window_wants_header_line (w))
11565 {
11566 Lisp_Object window_header_line_format
11567 = window_parameter (w, Qheader_line_format);
11568
11569 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11570 NILP (window_header_line_format)
11571 ? BVAR (current_buffer, header_line_format)
11572 : window_header_line_format);
11573 }
11574
11575 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11576 && window_wants_mode_line (w))
11577 {
11578 Lisp_Object window_mode_line_format
11579 = window_parameter (w, Qmode_line_format);
11580
11581 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11582 NILP (window_mode_line_format)
11583 ? BVAR (current_buffer, mode_line_format)
11584 : window_mode_line_format);
11585 }
11586
11587 bidi_unshelve_cache (itdata, false);
11588
11589 return (!vertical_offset
11590 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11591 : list3i (x - start_x, y, start));
11592 }
11593
11594 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11595 doc:
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
11644
11645
11646
11647
11648
11649
11650 )
11651 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11652 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11653 {
11654 struct window *w = decode_live_window (window);
11655 struct buffer *b = XBUFFER (w->contents);
11656 struct buffer *old_b = NULL;
11657 Lisp_Object value;
11658
11659 if (b != current_buffer)
11660 {
11661 old_b = current_buffer;
11662 set_buffer_internal_1 (b);
11663 }
11664
11665 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11666 ignore_line_at_end);
11667
11668 if (old_b)
11669 set_buffer_internal_1 (old_b);
11670
11671 return value;
11672 }
11673
11674 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11675 doc:
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688 )
11689 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11690 Lisp_Object y_limit)
11691 {
11692 struct window *w = decode_live_window (window);
11693 struct buffer *b = (NILP (buffer_or_name)
11694 ? current_buffer
11695 : XBUFFER (Fget_buffer (buffer_or_name)));
11696 Lisp_Object buffer, value;
11697 specpdl_ref count = SPECPDL_INDEX ();
11698
11699 XSETBUFFER (buffer, b);
11700
11701
11702
11703
11704 record_unwind_protect (unwind_with_echo_area_buffer,
11705 with_echo_area_buffer_unwind_data (w));
11706
11707 set_buffer_internal_1 (b);
11708
11709 ptrdiff_t base_line_pos = w->base_line_pos;
11710 int end_valid = w->window_end_valid;
11711 if (!EQ (buffer, w->contents))
11712 {
11713 wset_buffer (w, buffer);
11714 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11715 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11716 }
11717
11718 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11719 Qnil);
11720
11721 unbind_to (count, Qnil);
11722
11723
11724
11725 w->base_line_pos = base_line_pos;
11726 w->window_end_valid = end_valid;
11727
11728 return value;
11729 }
11730
11731
11732 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11733 Sdisplay__line_is_continued_p, 0, 0, 0,
11734 doc: )
11735 (void)
11736 {
11737 struct buffer *oldb = current_buffer;
11738 struct window *w = XWINDOW (selected_window);
11739 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11740
11741 set_buffer_internal_1 (XBUFFER (w->contents));
11742
11743 if (PT < ZV)
11744 {
11745 struct text_pos startpos;
11746 struct it it;
11747 void *itdata;
11748
11749
11750 Lisp_Object opoint = Fpoint_marker ();
11751
11752
11753
11754 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11755 SET_TEXT_POS (startpos, PT, PT_BYTE);
11756 itdata = bidi_shelve_cache ();
11757 start_display (&it, w, startpos);
11758
11759 if (it.line_wrap != TRUNCATE)
11760 {
11761 it.glyph_row = NULL;
11762 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11763 }
11764 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11765 bidi_unshelve_cache (itdata, false);
11766 }
11767 set_buffer_internal_1 (oldb);
11768
11769 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11770 }
11771
11772
11773
11774
11775
11776
11777
11778
11779 static ptrdiff_t
11780 format_nargs (char const *format)
11781 {
11782 ptrdiff_t nargs = 0;
11783 for (char const *p = format; (p = strchr (p, '%')); p++)
11784 if (p[1] == '%')
11785 p++;
11786 else
11787 nargs++;
11788 return nargs;
11789 }
11790
11791
11792
11793
11794 void
11795 add_to_log (const char *format, ...)
11796 {
11797 va_list ap;
11798 va_start (ap, format);
11799 vadd_to_log (format, ap);
11800 va_end (ap);
11801 }
11802
11803 void
11804 vadd_to_log (char const *format, va_list ap)
11805 {
11806 ptrdiff_t form_nargs = format_nargs (format);
11807 ptrdiff_t nargs = 1 + form_nargs;
11808 Lisp_Object args[10];
11809 eassert (nargs <= ARRAYELTS (args));
11810 AUTO_STRING (args0, format);
11811 args[0] = args0;
11812 for (ptrdiff_t i = 1; i <= nargs; i++)
11813 args[i] = va_arg (ap, Lisp_Object);
11814 Lisp_Object msg = Qnil;
11815 msg = Fformat_message (nargs, args);
11816
11817 ptrdiff_t len = SBYTES (msg) + 1;
11818 USE_SAFE_ALLOCA;
11819 char *buffer = SAFE_ALLOCA (len);
11820 memcpy (buffer, SDATA (msg), len);
11821
11822 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11823 SAFE_FREE ();
11824 }
11825
11826
11827
11828
11829 void
11830 message_log_maybe_newline (void)
11831 {
11832 if (message_log_need_newline)
11833 message_dolog ("", 0, true, false);
11834 }
11835
11836
11837
11838
11839
11840
11841
11842
11843
11844
11845
11846 void
11847 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11848 {
11849 const unsigned char *msg = (const unsigned char *) m;
11850
11851 if (!NILP (Vmemory_full))
11852 return;
11853
11854 if (!NILP (Vmessage_log_max))
11855 {
11856 struct buffer *oldbuf;
11857 Lisp_Object oldpoint, oldbegv, oldzv;
11858 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11859 ptrdiff_t point_at_end = 0;
11860 ptrdiff_t zv_at_end = 0;
11861 Lisp_Object old_deactivate_mark;
11862
11863 old_deactivate_mark = Vdeactivate_mark;
11864 oldbuf = current_buffer;
11865
11866
11867
11868 if (! STRINGP (Vmessages_buffer_name))
11869 Vmessages_buffer_name = build_string ("*Messages*");
11870
11871
11872 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11873 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11874 if (newbuffer
11875 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11876 call0 (intern ("messages-buffer-mode"));
11877
11878 bset_undo_list (current_buffer, Qt);
11879 bset_cache_long_scans (current_buffer, Qnil);
11880
11881 oldpoint = message_dolog_marker1;
11882 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11883 oldbegv = message_dolog_marker2;
11884 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11885 oldzv = message_dolog_marker3;
11886 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11887
11888 if (PT == Z)
11889 point_at_end = 1;
11890 if (ZV == Z)
11891 zv_at_end = 1;
11892
11893 BEGV = BEG;
11894 BEGV_BYTE = BEG_BYTE;
11895 ZV = Z;
11896 ZV_BYTE = Z_BYTE;
11897 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11898
11899
11900
11901 if (multibyte
11902 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11903 {
11904
11905
11906 for (ptrdiff_t i = 0; i < nbytes; )
11907 {
11908 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11909 char work = CHAR_TO_BYTE8 (c);
11910 insert_1_both (&work, 1, 1, true, false, false);
11911 i += char_bytes;
11912 }
11913 }
11914 else if (! multibyte
11915 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11916 {
11917
11918
11919 for (ptrdiff_t i = 0; i < nbytes; i++)
11920 {
11921 int c = make_char_multibyte (msg[i]);
11922 unsigned char str[MAX_MULTIBYTE_LENGTH];
11923 int char_bytes = CHAR_STRING (c, str);
11924 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11925 }
11926 }
11927 else if (nbytes)
11928 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11929 true, false, false);
11930
11931 if (nlflag)
11932 {
11933 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11934 intmax_t dups;
11935
11936
11937
11938
11939
11940 specpdl_ref count = SPECPDL_INDEX ();
11941 specbind (Qinhibit_modification_hooks, Qt);
11942
11943 insert_1_both ("\n", 1, 1, true, false, false);
11944
11945 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11946 this_bol = PT;
11947 this_bol_byte = PT_BYTE;
11948
11949
11950
11951 if (this_bol > BEG)
11952 {
11953 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11954 prev_bol = PT;
11955 prev_bol_byte = PT_BYTE;
11956
11957 dups = message_log_check_duplicate (prev_bol_byte,
11958 this_bol_byte);
11959 if (dups)
11960 {
11961 del_range_both (prev_bol, prev_bol_byte,
11962 this_bol, this_bol_byte, false);
11963 if (dups > 1)
11964 {
11965 char dupstr[sizeof " [ times]"
11966 + INT_STRLEN_BOUND (dups)];
11967
11968
11969
11970 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11971 dups);
11972 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11973 insert_1_both (dupstr, duplen, duplen,
11974 true, false, true);
11975 }
11976 }
11977 }
11978
11979
11980
11981
11982
11983 if (FIXNATP (Vmessage_log_max))
11984 {
11985 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11986 -XFIXNAT (Vmessage_log_max) - 1, false);
11987 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11988 }
11989
11990 unbind_to (count, Qnil);
11991 }
11992 BEGV = marker_position (oldbegv);
11993 BEGV_BYTE = marker_byte_position (oldbegv);
11994
11995 if (zv_at_end)
11996 {
11997 ZV = Z;
11998 ZV_BYTE = Z_BYTE;
11999 }
12000 else
12001 {
12002 ZV = marker_position (oldzv);
12003 ZV_BYTE = marker_byte_position (oldzv);
12004 }
12005
12006 if (point_at_end)
12007 TEMP_SET_PT_BOTH (Z, Z_BYTE);
12008 else
12009
12010
12011 TEMP_SET_PT_BOTH (marker_position (oldpoint),
12012 marker_byte_position (oldpoint));
12013
12014 unchain_marker (XMARKER (oldpoint));
12015 unchain_marker (XMARKER (oldbegv));
12016 unchain_marker (XMARKER (oldzv));
12017
12018
12019
12020
12021
12022
12023
12024 windows_or_buffers_changed = old_windows_or_buffers_changed;
12025 bset_redisplay (current_buffer);
12026
12027 set_buffer_internal (oldbuf);
12028
12029 message_log_need_newline = !nlflag;
12030 Vdeactivate_mark = old_deactivate_mark;
12031 }
12032 }
12033
12034
12035
12036
12037
12038
12039
12040
12041 static intmax_t
12042 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
12043 {
12044 ptrdiff_t i;
12045 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
12046 bool seen_dots = false;
12047 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
12048 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
12049
12050 for (i = 0; i < len; i++)
12051 {
12052 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
12053 seen_dots = true;
12054 if (p1[i] != p2[i])
12055 return seen_dots;
12056 }
12057 p1 += len;
12058 if (*p1 == '\n')
12059 return 2;
12060 if (*p1++ == ' ' && *p1++ == '[')
12061 {
12062 char *pend;
12063 intmax_t n = strtoimax ((char *) p1, &pend, 10);
12064 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
12065 return n + 1;
12066 }
12067 return 0;
12068 }
12069
12070
12071
12072
12073
12074
12075
12076
12077
12078 void
12079 message3 (Lisp_Object m)
12080 {
12081 clear_message (true, true);
12082 cancel_echoing ();
12083
12084
12085 message_log_maybe_newline ();
12086 if (STRINGP (m))
12087 {
12088 ptrdiff_t nbytes = SBYTES (m);
12089 bool multibyte = STRING_MULTIBYTE (m);
12090 char *buffer;
12091 USE_SAFE_ALLOCA;
12092 SAFE_ALLOCA_STRING (buffer, m);
12093 message_dolog (buffer, nbytes, true, multibyte);
12094 SAFE_FREE ();
12095 }
12096 if (! inhibit_message)
12097 message3_nolog (m);
12098 }
12099
12100
12101
12102 static void
12103 message_to_stderr (Lisp_Object m)
12104 {
12105 if (noninteractive_need_newline)
12106 {
12107 noninteractive_need_newline = false;
12108 errputc ('\n');
12109 }
12110 if (STRINGP (m))
12111 {
12112 Lisp_Object coding_system = Vlocale_coding_system;
12113 Lisp_Object s;
12114
12115 if (!NILP (Vcoding_system_for_write))
12116 coding_system = Vcoding_system_for_write;
12117 if (!NILP (coding_system))
12118 s = code_convert_string_norecord (m, coding_system, true);
12119 else
12120 s = m;
12121
12122 errwrite (SDATA (s), SBYTES (s));
12123 }
12124 if (STRINGP (m) || !cursor_in_echo_area)
12125 errputc ('\n');
12126 }
12127
12128
12129
12130
12131
12132
12133 void
12134 message3_nolog (Lisp_Object m)
12135 {
12136 struct frame *sf = SELECTED_FRAME ();
12137
12138 if (FRAME_INITIAL_P (sf))
12139 message_to_stderr (m);
12140
12141
12142
12143 else if (INTERACTIVE && sf->glyphs_initialized_p)
12144 {
12145
12146
12147 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12148 Lisp_Object frame = XWINDOW (mini_window)->frame;
12149 struct frame *f = XFRAME (frame);
12150
12151 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12152 Fmake_frame_visible (frame);
12153
12154 if (STRINGP (m) && SCHARS (m) > 0)
12155 {
12156 set_message (m);
12157 if (minibuffer_auto_raise)
12158 Fraise_frame (frame);
12159
12160
12161 echo_message_buffer = Qnil;
12162 }
12163 else
12164 clear_message (true, true);
12165
12166 do_pending_window_change (false);
12167 echo_area_display (true);
12168 do_pending_window_change (false);
12169 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12170 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12171 }
12172 }
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183 void
12184 message1 (const char *m)
12185 {
12186 message3 (m ? build_unibyte_string (m) : Qnil);
12187 }
12188
12189
12190
12191
12192 void
12193 message1_nolog (const char *m)
12194 {
12195 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12196 }
12197
12198
12199
12200
12201 void
12202 message_with_string (const char *m, Lisp_Object string, bool log)
12203 {
12204 CHECK_STRING (string);
12205
12206 bool need_message;
12207 if (noninteractive)
12208 need_message = !!m;
12209 else if (!INTERACTIVE)
12210 need_message = false;
12211 else
12212 {
12213
12214
12215
12216 Lisp_Object mini_window;
12217 struct frame *f, *sf = SELECTED_FRAME ();
12218
12219
12220
12221 mini_window = FRAME_MINIBUF_WINDOW (sf);
12222 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12223
12224
12225
12226
12227 need_message = f->glyphs_initialized_p;
12228 }
12229
12230 if (need_message)
12231 {
12232 AUTO_STRING (fmt, m);
12233 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12234
12235 if (noninteractive)
12236 message_to_stderr (msg);
12237 else
12238 {
12239 if (log)
12240 message3 (msg);
12241 else
12242 message3_nolog (msg);
12243
12244
12245
12246 message_buf_print = false;
12247 }
12248 }
12249 }
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259
12260
12261
12262 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12263 vmessage (const char *m, va_list ap)
12264 {
12265 if (noninteractive)
12266 {
12267 if (m)
12268 {
12269 if (noninteractive_need_newline)
12270 putc ('\n', stderr);
12271 noninteractive_need_newline = false;
12272 vfprintf (stderr, m, ap);
12273 if (!cursor_in_echo_area)
12274 putc ('\n', stderr);
12275 fflush (stderr);
12276 }
12277 }
12278 else if (INTERACTIVE)
12279 {
12280
12281
12282
12283 Lisp_Object mini_window;
12284 struct frame *f, *sf = SELECTED_FRAME ();
12285
12286
12287
12288 mini_window = FRAME_MINIBUF_WINDOW (sf);
12289 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12290
12291
12292
12293
12294 if (f->glyphs_initialized_p)
12295 {
12296 if (m)
12297 {
12298 ptrdiff_t len;
12299 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12300 USE_SAFE_ALLOCA;
12301 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12302
12303 len = doprnt (message_buf, maxsize, m, 0, ap);
12304
12305 message3 (make_string (message_buf, len));
12306 SAFE_FREE ();
12307 }
12308 else
12309 message1 (0);
12310
12311
12312
12313 message_buf_print = false;
12314 }
12315 }
12316 }
12317
12318
12319 void
12320 message (const char *m, ...)
12321 {
12322 va_list ap;
12323 va_start (ap, m);
12324 vmessage (m, ap);
12325 va_end (ap);
12326 }
12327
12328
12329
12330
12331
12332
12333 void
12334 update_echo_area (void)
12335 {
12336 if (!NILP (echo_area_buffer[0]))
12337 {
12338 Lisp_Object string;
12339 string = Fcurrent_message ();
12340 message3 (string);
12341 }
12342 }
12343
12344
12345
12346
12347
12348 static void
12349 ensure_echo_area_buffers (void)
12350 {
12351 for (int i = 0; i < 2; i++)
12352 if (!BUFFERP (echo_buffer[i])
12353 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12354 {
12355 Lisp_Object old_buffer = echo_buffer[i];
12356 static char const name_fmt[] = " *Echo Area %d*";
12357 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12358 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12359 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12360 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12361
12362
12363
12364
12365 for (int j = 0; j < 2; j++)
12366 if (EQ (old_buffer, echo_area_buffer[j]))
12367 echo_area_buffer[j] = echo_buffer[i];
12368 }
12369 }
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388 static bool
12389 with_echo_area_buffer (struct window *w, int which,
12390 bool (*fn) (void *, Lisp_Object),
12391 void *a1, Lisp_Object a2)
12392 {
12393 Lisp_Object buffer;
12394 bool this_one, the_other, clear_buffer_p, rc;
12395 specpdl_ref count = SPECPDL_INDEX ();
12396
12397
12398 ensure_echo_area_buffers ();
12399
12400 clear_buffer_p = false;
12401
12402 if (which == 0)
12403 this_one = false, the_other = true;
12404 else if (which > 0)
12405 this_one = true, the_other = false;
12406 else
12407 {
12408 this_one = false, the_other = true;
12409 clear_buffer_p = true;
12410
12411
12412
12413 if (!NILP (echo_area_buffer[this_one])
12414 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12415 echo_area_buffer[this_one] = Qnil;
12416 }
12417
12418
12419
12420 if (NILP (echo_area_buffer[this_one]))
12421 {
12422 echo_area_buffer[this_one]
12423 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12424 ? echo_buffer[the_other]
12425 : echo_buffer[this_one]);
12426 clear_buffer_p = true;
12427 }
12428
12429 buffer = echo_area_buffer[this_one];
12430
12431
12432
12433 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12434 cancel_echoing ();
12435
12436 record_unwind_protect (unwind_with_echo_area_buffer,
12437 with_echo_area_buffer_unwind_data (w));
12438
12439
12440
12441
12442
12443
12444
12445
12446 set_buffer_internal_1 (XBUFFER (buffer));
12447 if (w)
12448 {
12449 wset_buffer (w, buffer);
12450 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12451 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12452 }
12453
12454 bset_undo_list (current_buffer, Qt);
12455 bset_read_only (current_buffer, Qnil);
12456 specbind (Qinhibit_read_only, Qt);
12457 specbind (Qinhibit_modification_hooks, Qt);
12458
12459 if (clear_buffer_p && Z > BEG)
12460 del_range (BEG, Z);
12461
12462 eassert (BEGV >= BEG);
12463 eassert (ZV <= Z && ZV >= BEGV);
12464
12465 rc = fn (a1, a2);
12466
12467 eassert (BEGV >= BEG);
12468 eassert (ZV <= Z && ZV >= BEGV);
12469
12470 unbind_to (count, Qnil);
12471 return rc;
12472 }
12473
12474
12475
12476
12477
12478 static Lisp_Object
12479 with_echo_area_buffer_unwind_data (struct window *w)
12480 {
12481 int i = 0;
12482 Lisp_Object vector, tmp;
12483
12484
12485
12486 vector = Vwith_echo_area_save_vector;
12487 Vwith_echo_area_save_vector = Qnil;
12488
12489 if (NILP (vector))
12490 vector = make_nil_vector (11);
12491
12492 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12493 ASET (vector, i, Vdeactivate_mark); ++i;
12494 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12495
12496 if (w)
12497 {
12498 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12499 ASET (vector, i, w->contents); ++i;
12500 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12501 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12502 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12503 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12504 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12505 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12506 }
12507 else
12508 {
12509 int end = i + 8;
12510 for (; i < end; ++i)
12511 ASET (vector, i, Qnil);
12512 }
12513
12514 eassert (i == ASIZE (vector));
12515 return vector;
12516 }
12517
12518
12519
12520
12521
12522 static void
12523 unwind_with_echo_area_buffer (Lisp_Object vector)
12524 {
12525 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12526 Vdeactivate_mark = AREF (vector, 1);
12527 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12528
12529 if (WINDOWP (AREF (vector, 3)))
12530 {
12531 struct window *w;
12532 Lisp_Object buffer;
12533
12534 w = XWINDOW (AREF (vector, 3));
12535 buffer = AREF (vector, 4);
12536
12537 wset_buffer (w, buffer);
12538 set_marker_restricted_both (w->pointm, buffer,
12539 XFIXNAT (AREF (vector, 5)),
12540 XFIXNAT (AREF (vector, 6)));
12541 set_marker_restricted_both (w->old_pointm, buffer,
12542 XFIXNAT (AREF (vector, 7)),
12543 XFIXNAT (AREF (vector, 8)));
12544 set_marker_restricted_both (w->start, buffer,
12545 XFIXNAT (AREF (vector, 9)),
12546 XFIXNAT (AREF (vector, 10)));
12547 }
12548
12549 Vwith_echo_area_save_vector = vector;
12550 }
12551
12552
12553
12554
12555
12556 void
12557 setup_echo_area_for_printing (bool multibyte_p)
12558 {
12559
12560 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12561 Fkill_emacs (Qnil, Qnil);
12562
12563 ensure_echo_area_buffers ();
12564
12565 if (!message_buf_print)
12566 {
12567
12568
12569 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12570 echo_area_buffer[0] = echo_buffer[1];
12571 else
12572 echo_area_buffer[0] = echo_buffer[0];
12573
12574
12575 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12576 bset_truncate_lines (current_buffer, Qnil);
12577
12578 if (Z > BEG)
12579 {
12580 specpdl_ref count = SPECPDL_INDEX ();
12581 specbind (Qinhibit_read_only, Qt);
12582
12583 del_range (BEG, Z);
12584 unbind_to (count, Qnil);
12585 }
12586 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12587
12588
12589
12590
12591
12592
12593
12594 if (unibyte_display_via_language_environment
12595 && !multibyte_p
12596 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12597 Fset_buffer_multibyte (Qnil);
12598 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12599 Fset_buffer_multibyte (Qt);
12600
12601
12602 if (minibuffer_auto_raise)
12603 {
12604 struct frame *sf = SELECTED_FRAME ();
12605 Lisp_Object mini_window;
12606 mini_window = FRAME_MINIBUF_WINDOW (sf);
12607 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12608 }
12609
12610 message_log_maybe_newline ();
12611 message_buf_print = true;
12612 }
12613 else
12614 {
12615 if (NILP (echo_area_buffer[0]))
12616 {
12617 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12618 echo_area_buffer[0] = echo_buffer[1];
12619 else
12620 echo_area_buffer[0] = echo_buffer[0];
12621 }
12622
12623 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12624 {
12625
12626 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12627 bset_truncate_lines (current_buffer, Qnil);
12628 }
12629 }
12630 }
12631
12632
12633
12634
12635
12636
12637
12638 static bool
12639 display_echo_area (struct window *w)
12640 {
12641 bool no_message_p, window_height_changed_p;
12642
12643
12644
12645
12646
12647
12648 specpdl_ref count = inhibit_garbage_collection ();
12649
12650
12651
12652
12653
12654 bool i = display_last_displayed_message_p;
12655
12656
12657
12658 no_message_p = NILP (echo_area_buffer[i]);
12659
12660 window_height_changed_p
12661 = with_echo_area_buffer (w, display_last_displayed_message_p,
12662 display_echo_area_1, w, Qnil);
12663
12664 if (no_message_p)
12665 echo_area_buffer[i] = Qnil;
12666
12667 unbind_to (count, Qnil);
12668 return window_height_changed_p;
12669 }
12670
12671
12672
12673
12674
12675
12676
12677
12678 static bool
12679 display_echo_area_1 (void *a1, Lisp_Object a2)
12680 {
12681 struct window *w = a1;
12682 Lisp_Object window;
12683 struct text_pos start;
12684
12685
12686
12687
12688 forget_escape_and_glyphless_faces ();
12689
12690
12691
12692
12693 bool window_height_changed_p = resize_mini_window (w, false);
12694
12695
12696 SET_TEXT_POS_FROM_MARKER (start, w->start);
12697
12698
12699 clear_glyph_matrix (w->desired_matrix);
12700 XSETWINDOW (window, w);
12701 void *itdata = bidi_shelve_cache ();
12702 try_window (window, start, 0);
12703 bidi_unshelve_cache (itdata, false);
12704
12705 return window_height_changed_p;
12706 }
12707
12708
12709
12710
12711
12712
12713 void
12714 resize_echo_area_exactly (void)
12715 {
12716 if (BUFFERP (echo_area_buffer[0])
12717 && WINDOWP (echo_area_window))
12718 {
12719 struct window *w = XWINDOW (echo_area_window);
12720 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12721 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12722 w, resize_exactly);
12723 if (resized_p)
12724 {
12725 windows_or_buffers_changed = 42;
12726 update_mode_lines = 30;
12727 redisplay_internal ();
12728 }
12729 }
12730 }
12731
12732
12733
12734
12735
12736
12737
12738
12739 static bool
12740 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12741 {
12742 return resize_mini_window (a1, !NILP (exactly));
12743 }
12744
12745
12746
12747
12748
12749
12750
12751
12752
12753
12754
12755
12756
12757 bool
12758 resize_mini_window (struct window *w, bool exact_p)
12759 {
12760 struct frame *f = XFRAME (w->frame);
12761 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12762
12763 eassert (MINI_WINDOW_P (w));
12764
12765
12766
12767
12768
12769
12770
12771 if (!NILP (Vinhibit_redisplay))
12772 return false;
12773
12774
12775 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12776 set_marker_both (w->start, w->contents,
12777 BUF_BEGV (XBUFFER (w->contents)),
12778 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12779
12780
12781 if ((NILP (Vresize_mini_windows)
12782 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12783 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12784 return false;
12785
12786 if (FRAME_MINIBUF_ONLY_P (f))
12787 {
12788 if (!NILP (resize_mini_frames))
12789 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12790 }
12791 else
12792 {
12793 struct it it;
12794 int unit = FRAME_LINE_HEIGHT (f);
12795 int height, max_height;
12796 struct text_pos start;
12797 struct buffer *old_current_buffer = NULL;
12798 int windows_height = FRAME_INNER_HEIGHT (f);
12799
12800 if (current_buffer != XBUFFER (w->contents))
12801 {
12802 old_current_buffer = current_buffer;
12803 set_buffer_internal (XBUFFER (w->contents));
12804 }
12805
12806 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12807
12808
12809 if (FLOATP (Vmax_mini_window_height))
12810 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12811 else if (FIXNUMP (Vmax_mini_window_height))
12812 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12813 else
12814 max_height = windows_height / 4;
12815
12816
12817 max_height = clip_to_bounds (unit, max_height, windows_height);
12818
12819
12820 last_height = 0;
12821 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12822
12823
12824 if (it.max_ascent == 0 && it.max_descent == 0)
12825 {
12826 height = it.current_y;
12827
12828
12829
12830
12831
12832 if (!(it.line_wrap == TRUNCATE
12833 && it.current_x <= it.first_visible_x
12834 && ZV_BYTE > 1
12835 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12836 height += last_height;
12837 }
12838 else
12839 height = it.current_y + it.max_ascent + it.max_descent;
12840 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12841
12842
12843 if (height > max_height)
12844 {
12845 height = (max_height / unit) * unit;
12846 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12847 {
12848 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12849 move_it_vertically_backward (&it, height - unit);
12850
12851
12852
12853
12854
12855
12856
12857
12858
12859 move_it_by_lines (&it, 0);
12860 start = it.current.pos;
12861
12862
12863 w->start_at_line_beg = false;
12864 SET_MARKER_FROM_TEXT_POS (w->start, start);
12865 }
12866 }
12867 else
12868 {
12869 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12870 SET_MARKER_FROM_TEXT_POS (w->start, start);
12871 }
12872
12873 if (EQ (Vresize_mini_windows, Qgrow_only))
12874 {
12875
12876
12877 if (height > old_height)
12878 grow_mini_window (w, height - old_height);
12879 else if (height < old_height && (exact_p || BEGV == ZV))
12880 shrink_mini_window (w);
12881 }
12882 else if (height != old_height)
12883
12884 grow_mini_window (w, height - old_height);
12885
12886 if (old_current_buffer)
12887 set_buffer_internal (old_current_buffer);
12888 }
12889
12890 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12891 }
12892
12893
12894
12895
12896
12897 Lisp_Object
12898 current_message (void)
12899 {
12900 Lisp_Object msg;
12901
12902 if (!BUFFERP (echo_area_buffer[0]))
12903 msg = Qnil;
12904 else
12905 {
12906 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12907 if (NILP (msg))
12908 echo_area_buffer[0] = Qnil;
12909 }
12910
12911 return msg;
12912 }
12913
12914
12915 static bool
12916 current_message_1 (void *a1, Lisp_Object a2)
12917 {
12918 Lisp_Object *msg = a1;
12919
12920 if (Z > BEG)
12921 *msg = make_buffer_string (BEG, Z, true);
12922 else
12923 *msg = Qnil;
12924 return false;
12925 }
12926
12927
12928
12929
12930
12931
12932
12933 bool
12934 push_message (void)
12935 {
12936 Lisp_Object msg = current_message ();
12937 Vmessage_stack = Fcons (msg, Vmessage_stack);
12938 return STRINGP (msg);
12939 }
12940
12941
12942
12943
12944 void
12945 restore_message (void)
12946 {
12947 eassert (CONSP (Vmessage_stack));
12948 message3_nolog (XCAR (Vmessage_stack));
12949 }
12950
12951
12952
12953
12954 void
12955 pop_message_unwind (void)
12956 {
12957
12958 eassert (CONSP (Vmessage_stack));
12959 Vmessage_stack = XCDR (Vmessage_stack);
12960 }
12961
12962
12963
12964
12965
12966
12967 void
12968 check_message_stack (void)
12969 {
12970 if (!NILP (Vmessage_stack))
12971 emacs_abort ();
12972 }
12973
12974 void
12975 clear_message_stack (void)
12976 {
12977 Vmessage_stack = Qnil;
12978 }
12979
12980
12981
12982
12983 void
12984 truncate_echo_area (ptrdiff_t nchars)
12985 {
12986 if (nchars == 0)
12987 echo_area_buffer[0] = Qnil;
12988 else if (!noninteractive
12989 && INTERACTIVE
12990 && !NILP (echo_area_buffer[0]))
12991 {
12992 struct frame *sf = SELECTED_FRAME ();
12993
12994
12995
12996 if (sf->glyphs_initialized_p)
12997 with_echo_area_buffer (0, 0, truncate_message_1,
12998 (void *) (intptr_t) nchars, Qnil);
12999 }
13000 }
13001
13002
13003
13004
13005
13006 static bool
13007 truncate_message_1 (void *a1, Lisp_Object a2)
13008 {
13009 intptr_t nchars = (intptr_t) a1;
13010 if (BEG + nchars < Z)
13011 del_range (BEG + nchars, Z);
13012 if (Z == BEG)
13013 echo_area_buffer[0] = Qnil;
13014 return false;
13015 }
13016
13017 extern intptr_t garbage_collection_inhibited;
13018
13019
13020
13021 static void
13022 set_message (Lisp_Object string)
13023 {
13024 Lisp_Object message = Qnil;
13025
13026 eassert (STRINGP (string));
13027
13028 if (FUNCTIONP (Vset_message_function)
13029
13030
13031
13032 && !garbage_collection_inhibited)
13033 {
13034 specpdl_ref count = SPECPDL_INDEX ();
13035 specbind (Qinhibit_quit, Qt);
13036 message = safe_call1 (Vset_message_function, string);
13037 unbind_to (count, Qnil);
13038
13039 if (STRINGP (message))
13040 {
13041 string = message;
13042 message = Qnil;
13043 }
13044 }
13045
13046 if (NILP (message))
13047 {
13048 message_enable_multibyte = STRING_MULTIBYTE (string);
13049
13050 with_echo_area_buffer (0, -1, set_message_1, 0, string);
13051 message_buf_print = false;
13052 help_echo_showing_p = false;
13053 }
13054
13055 if (STRINGP (Vdebug_on_message)
13056 && STRINGP (string)
13057 && fast_string_match (Vdebug_on_message, string) >= 0)
13058 call_debugger (list2 (Qerror, string));
13059 }
13060
13061
13062
13063
13064
13065
13066 static bool
13067 set_message_1 (void *a1, Lisp_Object string)
13068 {
13069 eassert (STRINGP (string));
13070
13071
13072
13073
13074
13075
13076 if (!message_enable_multibyte
13077 && unibyte_display_via_language_environment
13078 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13079 Fset_buffer_multibyte (Qnil);
13080 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13081 Fset_buffer_multibyte (Qt);
13082
13083 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13084 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13085 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13086
13087
13088 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13089
13090
13091
13092
13093 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13094
13095 return false;
13096 }
13097
13098
13099
13100
13101
13102 void
13103 clear_message (bool current_p, bool last_displayed_p)
13104 {
13105 Lisp_Object preserve = Qnil;
13106
13107 if (current_p)
13108 {
13109 if (FUNCTIONP (Vclear_message_function)
13110
13111 && !garbage_collection_inhibited)
13112 {
13113 specpdl_ref count = SPECPDL_INDEX ();
13114 specbind (Qinhibit_quit, Qt);
13115 preserve = safe_call (1, Vclear_message_function);
13116 unbind_to (count, Qnil);
13117 }
13118
13119 if (!EQ (preserve, Qdont_clear_message))
13120 {
13121 echo_area_buffer[0] = Qnil;
13122 message_cleared_p = true;
13123 }
13124 }
13125
13126 if (last_displayed_p)
13127 echo_area_buffer[1] = Qnil;
13128
13129 message_buf_print = false;
13130 }
13131
13132
13133
13134
13135
13136
13137
13138
13139
13140
13141 static void
13142 clear_garbaged_frames (void)
13143 {
13144 if (frame_garbaged)
13145 {
13146 Lisp_Object tail, frame;
13147 struct frame *sf = SELECTED_FRAME ();
13148
13149 FOR_EACH_FRAME (tail, frame)
13150 {
13151 struct frame *f = XFRAME (frame);
13152
13153 if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
13154 {
13155 if (f->resized_p
13156
13157
13158
13159
13160
13161 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13162 redraw_frame (f);
13163 else
13164 clear_current_matrices (f);
13165
13166 #ifdef HAVE_WINDOW_SYSTEM
13167 if (FRAME_WINDOW_P (f)
13168 && FRAME_RIF (f)->clear_under_internal_border)
13169 FRAME_RIF (f)->clear_under_internal_border (f);
13170 #endif
13171 fset_redisplay (f);
13172 f->garbaged = false;
13173 f->resized_p = false;
13174 }
13175 }
13176
13177 frame_garbaged = false;
13178 }
13179 }
13180
13181
13182
13183
13184
13185 static void
13186 echo_area_display (bool update_frame_p)
13187 {
13188 Lisp_Object mini_window;
13189 struct window *w;
13190 struct frame *f;
13191 bool window_height_changed_p = false;
13192 struct frame *sf = SELECTED_FRAME ();
13193
13194 mini_window = FRAME_MINIBUF_WINDOW (sf);
13195 if (NILP (mini_window))
13196 return;
13197
13198 w = XWINDOW (mini_window);
13199 f = XFRAME (WINDOW_FRAME (w));
13200
13201
13202 if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
13203 return;
13204
13205 #ifdef HAVE_WINDOW_SYSTEM
13206
13207
13208
13209 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13210 return;
13211 #endif
13212
13213
13214 clear_garbaged_frames ();
13215
13216 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13217 {
13218 echo_area_window = mini_window;
13219 window_height_changed_p = display_echo_area (w);
13220 w->must_be_updated_p = true;
13221
13222
13223
13224
13225
13226 if (update_frame_p && !redisplaying_p)
13227 {
13228 int n = 0;
13229
13230
13231
13232
13233
13234
13235 if (!display_completed)
13236 {
13237 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13238
13239 #ifdef HAVE_WINDOW_SYSTEM
13240 if (FRAME_WINDOW_P (f)
13241 && FRAME_RIF (f)->clear_under_internal_border)
13242 FRAME_RIF (f)->clear_under_internal_border (f);
13243 #endif
13244 }
13245
13246 if (window_height_changed_p
13247
13248
13249 && !NILP (Vrun_hooks))
13250 {
13251
13252
13253
13254 specpdl_ref count = SPECPDL_INDEX ();
13255 specbind (Qredisplay_dont_pause, Qt);
13256 fset_redisplay (f);
13257 redisplay_internal ();
13258 unbind_to (count, Qnil);
13259 }
13260 else if (FRAME_WINDOW_P (f) && n == 0)
13261 {
13262
13263
13264
13265 update_single_window (w);
13266 flush_frame (f);
13267 }
13268 else
13269 update_frame (f, true, true);
13270
13271
13272
13273
13274 if (cursor_in_echo_area)
13275 wset_redisplay (XWINDOW (mini_window));
13276 }
13277 }
13278 else if (!EQ (mini_window, selected_window))
13279 wset_redisplay (XWINDOW (mini_window));
13280
13281
13282 echo_area_buffer[1] = echo_area_buffer[0];
13283
13284 echo_message_buffer = Qnil;
13285
13286
13287
13288
13289 if (EQ (mini_window, selected_window))
13290 CHARPOS (this_line_start_pos) = 0;
13291
13292 if (window_height_changed_p)
13293 {
13294 fset_redisplay (f);
13295
13296
13297
13298
13299
13300 clear_garbaged_frames ();
13301 }
13302 }
13303
13304
13305
13306 static bool
13307 window_buffer_changed (struct window *w)
13308 {
13309 struct buffer *b = XBUFFER (w->contents);
13310
13311 eassert (BUFFER_LIVE_P (b));
13312
13313 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13314 }
13315
13316
13317
13318 static bool
13319 mode_line_update_needed (struct window *w)
13320 {
13321 return (w->column_number_displayed != -1
13322 && !(PT == w->last_point && !window_outdated (w))
13323 && (w->column_number_displayed != current_column ()));
13324 }
13325
13326
13327
13328
13329 static bool
13330 window_frozen_p (struct window *w)
13331 {
13332 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13333 {
13334 Lisp_Object window;
13335
13336 XSETWINDOW (window, w);
13337 if (MINI_WINDOW_P (w))
13338 return false;
13339 else if (EQ (window, selected_window))
13340 return false;
13341 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13342 && EQ (window, Vminibuf_scroll_window))
13343
13344 return false;
13345 else
13346 return true;
13347 }
13348 return false;
13349 }
13350
13351
13352
13353
13354
13355
13356
13357
13358
13359 static char *mode_line_noprop_buf;
13360
13361
13362
13363 static char *mode_line_noprop_buf_end;
13364 static char *mode_line_noprop_ptr;
13365
13366 #define MODE_LINE_NOPROP_LEN(start) \
13367 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13368
13369 static enum {
13370 MODE_LINE_DISPLAY = 0,
13371 MODE_LINE_TITLE,
13372 MODE_LINE_NOPROP,
13373 MODE_LINE_STRING
13374 } mode_line_target;
13375
13376
13377
13378 static Lisp_Object mode_line_proptrans_alist;
13379
13380
13381 static Lisp_Object mode_line_string_list;
13382
13383
13384 static Lisp_Object mode_line_string_face;
13385 static Lisp_Object mode_line_string_face_prop;
13386
13387
13388
13389
13390 static Lisp_Object Vmode_line_unwind_vector;
13391
13392 static Lisp_Object
13393 format_mode_line_unwind_data (struct frame *target_frame,
13394 struct buffer *obuf,
13395 Lisp_Object owin,
13396 bool save_proptrans)
13397 {
13398 Lisp_Object vector, tmp;
13399
13400
13401
13402 vector = Vmode_line_unwind_vector;
13403 Vmode_line_unwind_vector = Qnil;
13404
13405 if (NILP (vector))
13406 vector = make_nil_vector (12);
13407
13408 ASET (vector, 0, make_fixnum (mode_line_target));
13409 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13410 ASET (vector, 2, mode_line_string_list);
13411 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13412 ASET (vector, 4, mode_line_string_face);
13413 ASET (vector, 5, mode_line_string_face_prop);
13414
13415 if (obuf)
13416 XSETBUFFER (tmp, obuf);
13417 else
13418 tmp = Qnil;
13419 ASET (vector, 6, tmp);
13420 ASET (vector, 7, owin);
13421 if (target_frame)
13422 {
13423 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13424 struct buffer *b = XBUFFER (buffer);
13425 struct buffer *cb = current_buffer;
13426
13427
13428
13429
13430 ASET (vector, 8, target_frame->selected_window);
13431 if (FRAME_TERMCAP_P (target_frame))
13432 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13433
13434
13435
13436
13437 ASET (vector, 10, buffer);
13438 current_buffer = b;
13439 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13440 current_buffer = cb;
13441 }
13442
13443 return vector;
13444 }
13445
13446 static void
13447 unwind_format_mode_line (Lisp_Object vector)
13448 {
13449 Lisp_Object old_window = AREF (vector, 7);
13450 Lisp_Object target_frame_window = AREF (vector, 8);
13451 Lisp_Object old_top_frame = AREF (vector, 9);
13452
13453 mode_line_target = XFIXNUM (AREF (vector, 0));
13454 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13455 mode_line_string_list = AREF (vector, 2);
13456 if (! EQ (AREF (vector, 3), Qt))
13457 mode_line_proptrans_alist = AREF (vector, 3);
13458 mode_line_string_face = AREF (vector, 4);
13459 mode_line_string_face_prop = AREF (vector, 5);
13460
13461
13462 if (WINDOW_LIVE_P (old_window))
13463 {
13464
13465
13466
13467 if (WINDOW_LIVE_P (target_frame_window))
13468 {
13469 Lisp_Object frame
13470 = WINDOW_FRAME (XWINDOW (target_frame_window));
13471
13472 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13473 Fselect_window (target_frame_window, Qt);
13474
13475 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13476
13477
13478 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13479 Fselect_frame (old_top_frame, Qt);
13480 }
13481
13482 Fselect_window (old_window, Qt);
13483
13484
13485
13486
13487 if (WINDOW_LIVE_P (target_frame_window))
13488 {
13489 Lisp_Object buffer = AREF (vector, 10);
13490
13491 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13492 {
13493 struct buffer *cb = current_buffer;
13494
13495 current_buffer = XBUFFER (buffer);
13496 set_point_from_marker (AREF (vector, 11));
13497 ASET (vector, 11, Qnil);
13498 current_buffer = cb;
13499 }
13500 }
13501 }
13502
13503 if (!NILP (AREF (vector, 6)))
13504 {
13505 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13506 ASET (vector, 6, Qnil);
13507 }
13508
13509 Vmode_line_unwind_vector = vector;
13510 }
13511
13512
13513
13514
13515
13516 static void
13517 store_mode_line_noprop_char (char c)
13518 {
13519
13520
13521 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13522 {
13523 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13524 ptrdiff_t size = len;
13525 mode_line_noprop_buf =
13526 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13527 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13528 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13529 }
13530
13531 *mode_line_noprop_ptr++ = c;
13532 }
13533
13534
13535
13536
13537
13538
13539
13540
13541
13542
13543 static int
13544 store_mode_line_noprop (const char *string, int field_width, int precision)
13545 {
13546 const unsigned char *str = (const unsigned char *) string;
13547 int n = 0;
13548 ptrdiff_t dummy, nbytes;
13549
13550
13551 nbytes = strlen (string);
13552 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13553 while (nbytes--)
13554 store_mode_line_noprop_char (*str++);
13555
13556
13557 while (field_width > 0
13558 && n < field_width)
13559 {
13560 store_mode_line_noprop_char (' ');
13561 ++n;
13562 }
13563
13564 return n;
13565 }
13566
13567
13568
13569
13570
13571 #ifdef HAVE_WINDOW_SYSTEM
13572
13573
13574
13575
13576
13577 void
13578 gui_consider_frame_title (Lisp_Object frame)
13579 {
13580 struct frame *f = XFRAME (frame);
13581 Lisp_Object format_data;
13582
13583 if ((FRAME_WINDOW_P (f)
13584 || FRAME_MINIBUF_ONLY_P (f)
13585 || f->explicit_name)
13586 && !FRAME_TOOLTIP_P (f))
13587 {
13588
13589 Lisp_Object tail, other_frame, fmt;
13590 ptrdiff_t title_start;
13591 char *title;
13592 ptrdiff_t len;
13593 struct it it;
13594 specpdl_ref count = SPECPDL_INDEX ();
13595
13596 FOR_EACH_FRAME (tail, other_frame)
13597 {
13598 struct frame *tf = XFRAME (other_frame);
13599
13600 if (tf != f
13601 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13602 && !FRAME_MINIBUF_ONLY_P (tf)
13603 && !FRAME_PARENT_FRAME (tf)
13604 && !FRAME_TOOLTIP_P (tf)
13605 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13606 break;
13607 }
13608
13609
13610 multiple_frames = CONSP (tail);
13611
13612
13613
13614
13615
13616
13617
13618
13619
13620
13621
13622
13623 specbind (Qinhibit_redisplay, Qt);
13624
13625
13626
13627
13628
13629
13630
13631
13632 format_data = format_mode_line_unwind_data (f, current_buffer,
13633 selected_window,
13634 false);
13635 record_unwind_protect (unwind_format_mode_line, format_data);
13636
13637 Fselect_window (f->selected_window, Qt);
13638 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13639 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13640 ? Vicon_title_format : Vframe_title_format);
13641
13642 mode_line_target = MODE_LINE_TITLE;
13643 title_start = MODE_LINE_NOPROP_LEN (0);
13644 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13645 NULL, DEFAULT_FACE_ID);
13646 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13647 len = MODE_LINE_NOPROP_LEN (title_start);
13648 title = mode_line_noprop_buf + title_start;
13649
13650
13651 ptrdiff_t nchars = 0;
13652 len = str_as_multibyte ((unsigned char *) title,
13653 mode_line_noprop_buf_end - title,
13654 len, &nchars);
13655 unbind_to (count, Qnil);
13656
13657
13658
13659
13660
13661
13662 if ((! STRINGP (f->name)
13663 || SBYTES (f->name) != len
13664 || memcmp (title, SDATA (f->name), len) != 0)
13665 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13666 {
13667 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13668 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13669 }
13670 }
13671 }
13672
13673 #endif
13674
13675
13676
13677
13678
13679
13680
13681 #define REDISPLAY_SOME_P() \
13682 ((windows_or_buffers_changed == 0 \
13683 || windows_or_buffers_changed == REDISPLAY_SOME) \
13684 && (update_mode_lines == 0 \
13685 || update_mode_lines == REDISPLAY_SOME))
13686
13687 static bool
13688 needs_no_redisplay (struct window *w)
13689 {
13690 struct buffer *buffer = XBUFFER (w->contents);
13691 struct frame *f = XFRAME (w->frame);
13692 return (REDISPLAY_SOME_P ()
13693 && !w->redisplay
13694 && !w->update_mode_line
13695 && !f->face_change
13696 && !f->redisplay
13697 && !buffer->text->redisplay
13698 && window_point (w) == w->last_point);
13699 }
13700
13701
13702
13703
13704 static void
13705 prepare_menu_bars (void)
13706 {
13707 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13708 bool some_windows = REDISPLAY_SOME_P ();
13709
13710 if (FUNCTIONP (Vpre_redisplay_function))
13711 {
13712 Lisp_Object windows = all_windows ? Qt : Qnil;
13713 if (all_windows && some_windows)
13714 {
13715 Lisp_Object ws = window_list ();
13716 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13717 {
13718 Lisp_Object this = XCAR (ws);
13719 struct window *w = XWINDOW (this);
13720
13721
13722 if (!needs_no_redisplay (w))
13723 windows = Fcons (this, windows);
13724 }
13725 }
13726 safe__call1 (true, Vpre_redisplay_function, windows);
13727 }
13728
13729
13730
13731
13732 #ifdef HAVE_WINDOW_SYSTEM
13733 if (all_windows)
13734 {
13735 Lisp_Object tail, frame;
13736
13737 FOR_EACH_FRAME (tail, frame)
13738 {
13739 struct frame *f = XFRAME (frame);
13740 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13741 if (some_windows
13742 && !f->redisplay
13743 && !w->redisplay
13744 && !XBUFFER (w->contents)->text->redisplay)
13745 continue;
13746
13747 if (!FRAME_TOOLTIP_P (f)
13748 && (FRAME_ICONIFIED_P (f)
13749 || FRAME_VISIBLE_P (f) == 1
13750
13751
13752
13753
13754
13755
13756
13757
13758
13759 || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
13760 gui_consider_frame_title (frame);
13761 }
13762 }
13763 #endif
13764
13765
13766
13767
13768 if (all_windows)
13769 {
13770 Lisp_Object tail, frame;
13771 specpdl_ref count = SPECPDL_INDEX ();
13772
13773
13774 bool menu_bar_hooks_run = false;
13775
13776 record_unwind_save_match_data ();
13777
13778 FOR_EACH_FRAME (tail, frame)
13779 {
13780 struct frame *f = XFRAME (frame);
13781 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13782
13783
13784 if (FRAME_TOOLTIP_P (f))
13785 continue;
13786
13787 if (some_windows
13788 && !f->redisplay
13789 && !w->redisplay
13790 && !XBUFFER (w->contents)->text->redisplay)
13791 continue;
13792
13793 if (!FRAME_PARENT_FRAME (f))
13794 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13795
13796 update_tab_bar (f, false);
13797 #ifdef HAVE_WINDOW_SYSTEM
13798 update_tool_bar (f, false);
13799 #endif
13800 }
13801
13802 unbind_to (count, Qnil);
13803 }
13804 else
13805 {
13806 struct frame *sf = SELECTED_FRAME ();
13807
13808 if (!FRAME_PARENT_FRAME (sf))
13809 update_menu_bar (sf, true, false);
13810
13811 update_tab_bar (sf, true);
13812 #ifdef HAVE_WINDOW_SYSTEM
13813 update_tool_bar (sf, true);
13814 #endif
13815 }
13816 }
13817
13818
13819
13820
13821
13822
13823
13824
13825
13826
13827
13828
13829
13830 static bool
13831 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13832 {
13833 Lisp_Object window;
13834 struct window *w;
13835
13836
13837
13838
13839 if (inhibit_menubar_update)
13840 return hooks_run;
13841
13842 window = FRAME_SELECTED_WINDOW (f);
13843 w = XWINDOW (window);
13844
13845 if (FRAME_WINDOW_P (f)
13846 ?
13847 #ifdef HAVE_EXT_MENU_BAR
13848 FRAME_EXTERNAL_MENU_BAR (f)
13849 #else
13850 FRAME_MENU_BAR_LINES (f) > 0
13851 #endif
13852 : FRAME_MENU_BAR_LINES (f) > 0)
13853 {
13854
13855
13856
13857
13858
13859
13860
13861 if (windows_or_buffers_changed
13862
13863
13864 || update_mode_lines
13865 || window_buffer_changed (w))
13866 {
13867 struct buffer *prev = current_buffer;
13868 specpdl_ref count = SPECPDL_INDEX ();
13869
13870 specbind (Qinhibit_menubar_update, Qt);
13871
13872 set_buffer_internal_1 (XBUFFER (w->contents));
13873 if (save_match_data)
13874 record_unwind_save_match_data ();
13875 if (NILP (Voverriding_local_map_menu_flag))
13876 {
13877 specbind (Qoverriding_terminal_local_map, Qnil);
13878 specbind (Qoverriding_local_map, Qnil);
13879 }
13880
13881 if (!hooks_run)
13882 {
13883
13884 safe_run_hooks (Qactivate_menubar_hook);
13885
13886
13887
13888 safe_run_hooks (Qmenu_bar_update_hook);
13889
13890 hooks_run = true;
13891 }
13892
13893 XSETFRAME (Vmenu_updating_frame, f);
13894 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13895
13896
13897 #ifdef HAVE_EXT_MENU_BAR
13898 if (FRAME_WINDOW_P (f))
13899 {
13900 #if defined (HAVE_NS)
13901
13902
13903 if (f == SELECTED_FRAME ())
13904 #endif
13905 set_frame_menubar (f, false);
13906 }
13907 else
13908
13909
13910 w->update_mode_line = true;
13911 #else
13912
13913
13914 w->update_mode_line = true;
13915 #endif
13916
13917 unbind_to (count, Qnil);
13918 set_buffer_internal_1 (prev);
13919 }
13920 }
13921
13922 return hooks_run;
13923 }
13924
13925
13926
13927
13928
13929
13930
13931
13932
13933
13934
13935
13936 static void
13937 restore_selected_window (Lisp_Object window)
13938 {
13939 if (WINDOW_LIVE_P (window))
13940
13941
13942 {
13943 selected_window = window;
13944 selected_frame = XWINDOW (window)->frame;
13945 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13946 }
13947 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13948
13949
13950 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13951 else
13952
13953
13954
13955 {
13956 Lisp_Object tail;
13957 Lisp_Object frame UNINIT;
13958
13959 FOR_EACH_FRAME (tail, frame)
13960 {
13961 struct frame *f = XFRAME (frame);
13962
13963 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13964 {
13965 selected_frame = frame;
13966 selected_window = FRAME_SELECTED_WINDOW (f);
13967
13968 return;
13969 }
13970 }
13971
13972
13973 emacs_abort ();
13974 }
13975 }
13976
13977
13978 static void
13979 restore_frame_selected_window (Lisp_Object window)
13980 {
13981 if (WINDOW_LIVE_P (window))
13982
13983
13984
13985 {
13986 Lisp_Object frame = XWINDOW (window)->frame;
13987
13988 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13989 if (EQ (frame, selected_frame))
13990 selected_window = window;
13991 }
13992 }
13993
13994
13995
13996
13997
13998
13999 static void
14000 update_tab_bar (struct frame *f, bool save_match_data)
14001 {
14002 bool do_update = false;
14003
14004 #ifdef HAVE_WINDOW_SYSTEM
14005 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
14006 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
14007 do_update = true;
14008 }
14009 else
14010 #endif
14011 if (FRAME_TAB_BAR_LINES (f) > 0)
14012 do_update = true;
14013
14014 if (do_update)
14015 {
14016 Lisp_Object window;
14017 struct window *w;
14018
14019 window = FRAME_SELECTED_WINDOW (f);
14020 w = XWINDOW (window);
14021
14022
14023
14024
14025
14026
14027
14028
14029 if (windows_or_buffers_changed
14030 || w->update_mode_line
14031 || update_mode_lines
14032 || window_buffer_changed (w))
14033 {
14034 struct buffer *prev = current_buffer;
14035 specpdl_ref count = SPECPDL_INDEX ();
14036 Lisp_Object new_tab_bar;
14037 int new_n_tab_bar;
14038
14039
14040
14041
14042 set_buffer_internal_1 (XBUFFER (w->contents));
14043
14044
14045 if (save_match_data)
14046 record_unwind_save_match_data ();
14047
14048
14049 if (NILP (Voverriding_local_map_menu_flag))
14050 {
14051 specbind (Qoverriding_terminal_local_map, Qnil);
14052 specbind (Qoverriding_local_map, Qnil);
14053 }
14054
14055
14056
14057
14058
14059 eassert (EQ (selected_window,
14060
14061
14062 XFRAME (selected_frame)->selected_window));
14063 #ifdef HAVE_WINDOW_SYSTEM
14064 Lisp_Object frame;
14065 record_unwind_protect (restore_selected_window, selected_window);
14066 XSETFRAME (frame, f);
14067 selected_frame = frame;
14068 selected_window = FRAME_SELECTED_WINDOW (f);
14069 #endif
14070
14071
14072 new_tab_bar
14073 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
14074 &new_n_tab_bar);
14075
14076
14077 if (new_n_tab_bar != f->n_tab_bar_items
14078 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14079 {
14080
14081
14082
14083 block_input ();
14084 fset_tab_bar_items (f, new_tab_bar);
14085 f->n_tab_bar_items = new_n_tab_bar;
14086 w->update_mode_line = true;
14087 unblock_input ();
14088 }
14089
14090 unbind_to (count, Qnil);
14091 set_buffer_internal_1 (prev);
14092 }
14093 }
14094 }
14095
14096
14097
14098
14099
14100
14101
14102
14103
14104
14105
14106 static void
14107 display_tab_bar (struct window *w)
14108 {
14109 struct frame *f = XFRAME (WINDOW_FRAME (w));
14110 struct it it;
14111 Lisp_Object items;
14112 int i;
14113
14114
14115 #ifdef HAVE_NTGUI
14116 if (FRAME_W32_P (f))
14117 return;
14118 #endif
14119 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14120 if (FRAME_X_P (f))
14121 return;
14122 #endif
14123
14124 #ifdef HAVE_NS
14125 if (FRAME_NS_P (f))
14126 return;
14127 #endif
14128
14129 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14130 eassert (!FRAME_WINDOW_P (f));
14131 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14132 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14133 TAB_BAR_FACE_ID);
14134 it.first_visible_x = 0;
14135 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14136 #elif defined (HAVE_X_WINDOWS)
14137 if (FRAME_WINDOW_P (f))
14138 {
14139
14140
14141 struct window *tab_w;
14142 tab_w = XWINDOW (f->tab_bar_window);
14143 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14144 TAB_BAR_FACE_ID);
14145 it.first_visible_x = 0;
14146 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14147 }
14148 else
14149 #endif
14150 {
14151
14152
14153 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14154 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14155 TAB_BAR_FACE_ID);
14156 it.first_visible_x = 0;
14157 it.last_visible_x = FRAME_COLS (f);
14158 }
14159
14160
14161
14162
14163 it.paragraph_embedding = L2R;
14164
14165
14166 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14167 {
14168 struct glyph_row *row = it.glyph_row + i;
14169 clear_glyph_row (row);
14170 row->enabled_p = true;
14171 row->full_width_p = true;
14172 row->reversed_p = false;
14173 }
14174
14175
14176 items = it.f->tab_bar_items;
14177 int j;
14178 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14179 {
14180 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14181
14182
14183 if (NILP (string))
14184 break;
14185
14186 if (it.current_x < it.last_visible_x)
14187 display_string (NULL, string, Qnil, 0, 0, &it,
14188 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14189 }
14190
14191
14192 if (it.current_x < it.last_visible_x)
14193 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14194
14195
14196 compute_line_metrics (&it);
14197 }
14198
14199 #ifdef HAVE_WINDOW_SYSTEM
14200
14201
14202
14203
14204
14205 static void
14206 build_desired_tab_bar_string (struct frame *f)
14207 {
14208 int i;
14209 Lisp_Object caption;
14210
14211 caption = Qnil;
14212
14213
14214 fset_desired_tab_bar_string (f, build_string (""));
14215
14216
14217
14218
14219 for (i = 0; i < f->n_tab_bar_items; ++i)
14220 {
14221 #define PROP(IDX) \
14222 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14223
14224 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14225
14226
14227
14228
14229
14230 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14231
14232 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14233 props, caption);
14234
14235 f->desired_tab_bar_string =
14236 concat2 (f->desired_tab_bar_string, caption);
14237
14238 #undef PROP
14239 }
14240 }
14241
14242
14243
14244
14245
14246
14247
14248
14249
14250
14251
14252
14253
14254
14255 static void
14256 display_tab_bar_line (struct it *it, int height)
14257 {
14258 struct glyph_row *row = it->glyph_row;
14259 int max_x = it->last_visible_x;
14260 struct glyph *last;
14261
14262
14263 clear_glyph_row (row);
14264 row->enabled_p = true;
14265 row->y = it->current_y;
14266
14267
14268
14269 it->start_of_box_run_p = true;
14270
14271 bool enough = false;
14272 while (it->current_x < max_x)
14273 {
14274 int x, n_glyphs_before, i, nglyphs;
14275 struct it it_before;
14276
14277
14278 if (!get_next_display_element (it))
14279 {
14280
14281 if (height < 0 && !it->hpos)
14282 return;
14283 break;
14284 }
14285
14286
14287 n_glyphs_before = row->used[TEXT_AREA];
14288 it_before = *it;
14289
14290 PRODUCE_GLYPHS (it);
14291
14292 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14293 i = 0;
14294 x = it_before.current_x;
14295 while (i < nglyphs)
14296 {
14297 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14298
14299 if (x + glyph->pixel_width > max_x)
14300 {
14301
14302 row->used[TEXT_AREA] = n_glyphs_before;
14303 *it = it_before;
14304
14305
14306
14307 if (n_glyphs_before == 0
14308 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14309 break;
14310 goto out;
14311 }
14312
14313 ++it->hpos;
14314 x += glyph->pixel_width;
14315 ++i;
14316 }
14317
14318 enough = ITERATOR_AT_END_OF_LINE_P (it);
14319 set_iterator_to_next (it, true);
14320
14321
14322 if (enough)
14323 break;
14324 }
14325
14326 out:;
14327
14328 row->displays_text_p = row->used[TEXT_AREA] != 0;
14329
14330
14331
14332
14333
14334
14335
14336 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14337 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14338 it->face_id = DEFAULT_FACE_ID;
14339
14340 extend_face_to_end_of_line (it);
14341 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14342 last->right_box_line_p = true;
14343 if (last == row->glyphs[TEXT_AREA])
14344 last->left_box_line_p = true;
14345
14346
14347 if ((height -= it->max_ascent + it->max_descent) > 0)
14348 {
14349
14350 height %= FRAME_LINE_HEIGHT (it->f);
14351 it->max_ascent += height / 2;
14352 it->max_descent += (height + 1) / 2;
14353 }
14354
14355 compute_line_metrics (it);
14356
14357
14358 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14359 {
14360 row->height = row->phys_height = it->last_visible_y - row->y;
14361 row->visible_height = row->height;
14362 row->ascent = row->phys_ascent = 0;
14363 row->extra_line_spacing = 0;
14364 }
14365
14366 row->full_width_p = true;
14367 row->continued_p = false;
14368 row->truncated_on_left_p = false;
14369 row->truncated_on_right_p = false;
14370
14371 it->current_x = it->hpos = 0;
14372 it->current_y += row->height;
14373 ++it->vpos;
14374 ++it->glyph_row;
14375 }
14376
14377
14378
14379
14380
14381 static int
14382 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14383 {
14384 struct window *w = XWINDOW (f->tab_bar_window);
14385 struct it it;
14386
14387
14388
14389 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14390
14391
14392
14393 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14394 temp_row->reversed_p = false;
14395 it.first_visible_x = 0;
14396 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14397 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14398 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14399 it.paragraph_embedding = L2R;
14400
14401 clear_glyph_row (temp_row);
14402 while (!ITERATOR_AT_END_P (&it))
14403 {
14404 it.glyph_row = temp_row;
14405 display_tab_bar_line (&it, -1);
14406 }
14407 clear_glyph_row (temp_row);
14408
14409
14410 if (n_rows)
14411 *n_rows = it.vpos > 0 ? it.vpos : -1;
14412
14413 if (pixelwise)
14414 return it.current_y;
14415 else
14416 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14417 }
14418
14419 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14420 0, 2, 0,
14421 doc:
14422
14423 )
14424 (Lisp_Object frame, Lisp_Object pixelwise)
14425 {
14426 int height = 0;
14427
14428 struct frame *f = decode_any_frame (frame);
14429
14430 if (WINDOWP (f->tab_bar_window)
14431 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14432 {
14433 update_tab_bar (f, true);
14434 if (f->n_tab_bar_items)
14435 {
14436 build_desired_tab_bar_string (f);
14437 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14438 }
14439 }
14440
14441 return make_fixnum (height);
14442 }
14443
14444
14445
14446
14447 static bool
14448 redisplay_tab_bar (struct frame *f)
14449 {
14450 struct window *w;
14451 struct it it;
14452 struct glyph_row *row;
14453
14454 f->tab_bar_redisplayed = true;
14455
14456
14457
14458
14459
14460 if (!WINDOWP (f->tab_bar_window)
14461 || (w = XWINDOW (f->tab_bar_window),
14462 WINDOW_TOTAL_LINES (w) == 0))
14463 {
14464
14465
14466
14467
14468
14469 f->tab_bar_resized = true;
14470
14471 return false;
14472 }
14473
14474
14475 build_desired_tab_bar_string (f);
14476
14477 int new_nrows;
14478 int new_height = tab_bar_height (f, &new_nrows, true);
14479
14480 if (f->n_tab_bar_rows == 0)
14481 {
14482 f->n_tab_bar_rows = new_nrows;
14483 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14484 frame_default_tab_bar_height = new_height;
14485 }
14486
14487
14488
14489 if (new_nrows > f->n_tab_bar_rows
14490 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14491 && !f->minimize_tab_bar_window_p
14492 && new_height > WINDOW_PIXEL_HEIGHT (w))
14493 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14494 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14495 {
14496 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14497 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14498 if (new_nrows != f->n_tab_bar_rows)
14499 f->n_tab_bar_rows = new_nrows;
14500 clear_glyph_matrix (w->desired_matrix);
14501 f->fonts_changed = true;
14502 return true;
14503 }
14504
14505
14506 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14507 it.first_visible_x = 0;
14508 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14509 row = it.glyph_row;
14510 row->reversed_p = false;
14511 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14512 STRING_MULTIBYTE (f->desired_tab_bar_string));
14513
14514
14515
14516
14517
14518
14519
14520 it.paragraph_embedding = L2R;
14521
14522
14523
14524 if (f->n_tab_bar_rows > 0)
14525 {
14526 int border, rows, height, extra;
14527
14528 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14529 border = XFIXNUM (Vtab_bar_border);
14530 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14531 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14532 else if (EQ (Vtab_bar_border, Qborder_width))
14533 border = f->border_width;
14534 else
14535 border = 0;
14536 if (border < 0)
14537 border = 0;
14538
14539 rows = f->n_tab_bar_rows;
14540 height = max (1, (it.last_visible_y - border) / rows);
14541 extra = it.last_visible_y - border - height * rows;
14542
14543 while (it.current_y < it.last_visible_y)
14544 {
14545 int h = 0;
14546 if (extra > 0 && rows-- > 0)
14547 {
14548 h = (extra + rows - 1) / rows;
14549 extra -= h;
14550 }
14551 display_tab_bar_line (&it, height + h);
14552 }
14553 }
14554 else
14555 {
14556 while (it.current_y < it.last_visible_y)
14557 display_tab_bar_line (&it, 0);
14558 }
14559
14560
14561
14562 w->desired_matrix->no_scrolling_p = true;
14563 w->must_be_updated_p = true;
14564
14565 if (!NILP (Vauto_resize_tab_bars))
14566 {
14567 bool change_height_p = false;
14568
14569
14570
14571 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14572 change_height_p = true;
14573
14574
14575
14576
14577
14578 row = it.glyph_row - 1;
14579
14580
14581
14582
14583 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14584 && row->height >= FRAME_LINE_HEIGHT (f))
14585 change_height_p = true;
14586
14587
14588
14589 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14590 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14591 change_height_p = true;
14592
14593
14594
14595 if (change_height_p)
14596 {
14597 int nrows;
14598 int new_height = tab_bar_height (f, &nrows, true);
14599
14600 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14601 && !f->minimize_tab_bar_window_p)
14602 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14603 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14604 f->minimize_tab_bar_window_p = false;
14605
14606 if (change_height_p)
14607 {
14608 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14609 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14610 frame_default_tab_bar_height = new_height;
14611 clear_glyph_matrix (w->desired_matrix);
14612 f->n_tab_bar_rows = nrows;
14613 f->fonts_changed = true;
14614
14615 return true;
14616 }
14617 }
14618 }
14619
14620 f->minimize_tab_bar_window_p = false;
14621 return false;
14622 }
14623
14624
14625
14626
14627
14628
14629
14630 static bool
14631 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14632 int *prop_idx, bool *close_p)
14633 {
14634 Lisp_Object prop;
14635 ptrdiff_t charpos;
14636
14637
14638
14639
14640 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14641 charpos = max (0, charpos);
14642
14643
14644
14645
14646 prop = Fget_text_property (make_fixnum (charpos),
14647 Qmenu_item, f->current_tab_bar_string);
14648 if (! FIXNUMP (prop))
14649 return false;
14650
14651 *prop_idx = XFIXNUM (prop);
14652
14653 if (close_p)
14654 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14655 Qclose_tab,
14656 f->current_tab_bar_string));
14657
14658 return true;
14659 }
14660
14661
14662
14663
14664
14665
14666
14667
14668
14669
14670
14671
14672
14673
14674
14675
14676
14677
14678
14679
14680
14681 static int
14682 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14683 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14684 {
14685 struct window *w = XWINDOW (f->tab_bar_window);
14686 int area;
14687
14688
14689 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14690 if (*glyph == NULL)
14691 return -1;
14692
14693
14694
14695 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14696 return -1;
14697
14698 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14699 }
14700
14701
14702
14703
14704
14705
14706
14707 int
14708 get_tab_bar_item_kbd (struct frame *f, int x, int y, int *prop_idx,
14709 bool *close_p)
14710 {
14711 struct window *w;
14712 int area, vpos, hpos;
14713 struct glyph *glyph;
14714
14715 w = XWINDOW (f->tab_bar_window);
14716
14717
14718 frame_to_window_pixel_xy (w, &x, &y);
14719
14720
14721 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, 0,
14722 0, &area);
14723 if (glyph == NULL)
14724 return -1;
14725
14726
14727
14728 if (!tab_bar_item_info (f, glyph, prop_idx, close_p))
14729 return -1;
14730
14731 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14732 }
14733
14734
14735
14736
14737
14738
14739
14740 Lisp_Object
14741 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14742 int modifiers)
14743 {
14744 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14745 struct window *w = XWINDOW (f->tab_bar_window);
14746 int hpos, vpos, prop_idx;
14747 bool close_p;
14748 struct glyph *glyph;
14749 Lisp_Object enabled_p;
14750 int ts;
14751
14752 frame_to_window_pixel_xy (w, &x, &y);
14753 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14754 if (ts == -1)
14755 return Fcons (Qtab_bar, Qnil);
14756
14757
14758 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14759 if (NILP (enabled_p))
14760 return Qnil;
14761
14762 if (down_p)
14763 {
14764
14765 if (!NILP (Vmouse_highlight))
14766 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14767 f->last_tab_bar_item = prop_idx;
14768 }
14769 else
14770 {
14771
14772 if (!NILP (Vmouse_highlight))
14773 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14774 f->last_tab_bar_item = -1;
14775 }
14776
14777 Lisp_Object caption =
14778 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14779
14780 AUTO_LIST2 (props, Qmenu_item,
14781 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14782 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14783 close_p ? Qt : Qnil));
14784
14785 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14786 props, caption);
14787
14788 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14789 }
14790
14791
14792
14793
14794
14795
14796 static void
14797 note_tab_bar_highlight (struct frame *f, int x, int y)
14798 {
14799 Lisp_Object window = f->tab_bar_window;
14800 struct window *w = XWINDOW (window);
14801 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14802 int hpos, vpos;
14803 struct glyph *glyph;
14804 struct glyph_row *row;
14805 int i;
14806 Lisp_Object enabled_p;
14807 int prop_idx;
14808 bool close_p;
14809 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14810 int rc;
14811
14812
14813
14814 if (x <= 0 || y <= 0)
14815 {
14816 clear_mouse_face (hlinfo);
14817 return;
14818 }
14819
14820 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14821 if (rc < 0)
14822 {
14823
14824 clear_mouse_face (hlinfo);
14825 return;
14826 }
14827 else if (rc == 0)
14828
14829 goto set_help_echo;
14830
14831 clear_mouse_face (hlinfo);
14832
14833 bool mouse_down_p = false;
14834
14835
14836
14837
14838
14839 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14840 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14841 && f == dpyinfo->last_mouse_frame);
14842
14843 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14844 && f->last_tab_bar_item != -1)
14845 return;
14846 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14847
14848
14849 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14850 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14851 {
14852
14853
14854 row = MATRIX_ROW (w->current_matrix, vpos);
14855 for (i = x = 0; i < hpos; ++i)
14856 x += row->glyphs[TEXT_AREA][i].pixel_width;
14857
14858
14859 hlinfo->mouse_face_beg_col = hpos;
14860 hlinfo->mouse_face_beg_row = vpos;
14861 hlinfo->mouse_face_beg_x = x;
14862 hlinfo->mouse_face_past_end = false;
14863
14864 hlinfo->mouse_face_end_col = hpos + 1;
14865 hlinfo->mouse_face_end_row = vpos;
14866 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14867 hlinfo->mouse_face_window = window;
14868 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14869
14870
14871 show_mouse_face (hlinfo, draw);
14872 }
14873
14874 set_help_echo:
14875
14876
14877
14878 help_echo_object = help_echo_window = Qnil;
14879 help_echo_pos = -1;
14880 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14881 if (NILP (help_echo_string))
14882 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14883 }
14884
14885 #endif
14886
14887
14888 static Lisp_Object
14889 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14890 {
14891 ptrdiff_t clen = 0;
14892
14893 for (int i = 0; i < f->n_tab_bar_items; i++)
14894 {
14895 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14896 + TAB_BAR_ITEM_CAPTION));
14897 if (NILP (caption))
14898 return Qnil;
14899 clen += SCHARS (caption);
14900 if (x < clen)
14901 {
14902 *prop_idx = i;
14903 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14904 - (clen - x)),
14905 Qclose_tab,
14906 caption));
14907 return caption;
14908 }
14909 }
14910 return Qnil;
14911 }
14912
14913
14914
14915
14916
14917
14918 Lisp_Object
14919 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14920 struct input_event *event)
14921 {
14922
14923 if (y < FRAME_MENU_BAR_LINES (f)
14924 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14925 return Qnil;
14926
14927
14928 int prop_idx;
14929 bool close_p;
14930 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14931
14932 if (NILP (caption))
14933 return Qnil;
14934
14935 if (NILP (AREF (f->tab_bar_items,
14936 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14937 return Qnil;
14938
14939 if (down_p)
14940 f->last_tab_bar_item = prop_idx;
14941 else
14942 f->last_tab_bar_item = -1;
14943
14944 caption = Fcopy_sequence (caption);
14945
14946 AUTO_LIST2 (props, Qmenu_item,
14947 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14948 + TAB_BAR_ITEM_KEY),
14949 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14950 + TAB_BAR_ITEM_BINDING),
14951 close_p ? Qt : Qnil));
14952
14953 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14954 props, caption);
14955
14956 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14957 }
14958
14959
14960
14961
14962
14963
14964
14965 #ifdef HAVE_WINDOW_SYSTEM
14966
14967
14968
14969
14970
14971
14972 static void
14973 update_tool_bar (struct frame *f, bool save_match_data)
14974 {
14975 #ifdef HAVE_EXT_TOOL_BAR
14976 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14977 #else
14978 bool do_update = (WINDOWP (f->tool_bar_window)
14979 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14980 #endif
14981
14982 if (do_update)
14983 {
14984 Lisp_Object window;
14985 struct window *w;
14986
14987 window = FRAME_SELECTED_WINDOW (f);
14988 w = XWINDOW (window);
14989
14990
14991
14992
14993
14994
14995
14996
14997 if (windows_or_buffers_changed
14998 || w->update_mode_line
14999 || update_mode_lines
15000 || window_buffer_changed (w))
15001 {
15002 struct buffer *prev = current_buffer;
15003 specpdl_ref count = SPECPDL_INDEX ();
15004 Lisp_Object frame, new_tool_bar;
15005 int new_n_tool_bar;
15006
15007
15008
15009
15010 set_buffer_internal_1 (XBUFFER (w->contents));
15011
15012
15013 if (save_match_data)
15014 record_unwind_save_match_data ();
15015
15016
15017 if (NILP (Voverriding_local_map_menu_flag))
15018 {
15019 specbind (Qoverriding_terminal_local_map, Qnil);
15020 specbind (Qoverriding_local_map, Qnil);
15021 }
15022
15023
15024
15025
15026
15027 eassert (EQ (selected_window,
15028
15029
15030 XFRAME (selected_frame)->selected_window));
15031 record_unwind_protect (restore_selected_window, selected_window);
15032 XSETFRAME (frame, f);
15033 selected_frame = frame;
15034 selected_window = FRAME_SELECTED_WINDOW (f);
15035
15036
15037 new_tool_bar
15038 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
15039 &new_n_tool_bar);
15040
15041
15042 if (new_n_tool_bar != f->n_tool_bar_items
15043 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
15044 {
15045
15046
15047
15048 block_input ();
15049 fset_tool_bar_items (f, new_tool_bar);
15050 f->n_tool_bar_items = new_n_tool_bar;
15051 w->update_mode_line = true;
15052 unblock_input ();
15053 }
15054
15055 unbind_to (count, Qnil);
15056 set_buffer_internal_1 (prev);
15057 }
15058 }
15059 }
15060
15061 #ifndef HAVE_EXT_TOOL_BAR
15062
15063
15064
15065
15066
15067
15068
15069
15070 static void
15071 build_desired_tool_bar_string (struct frame *f)
15072 {
15073 int i, size, size_needed;
15074 Lisp_Object image, plist;
15075
15076 image = plist = Qnil;
15077
15078
15079
15080
15081
15082 size = (STRINGP (f->desired_tool_bar_string)
15083 ? SCHARS (f->desired_tool_bar_string)
15084 : 0);
15085
15086
15087 size_needed = f->n_tool_bar_items;
15088
15089
15090
15091 if (size < size_needed || NILP (f->desired_tool_bar_string))
15092
15093
15094 fset_desired_tool_bar_string (f, make_uninit_string (size_needed));
15095 else
15096 {
15097 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
15098 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
15099 props, f->desired_tool_bar_string);
15100 }
15101
15102 f->tool_bar_wraps_p = false;
15103
15104
15105
15106
15107 for (i = 0; i < f->n_tool_bar_items; ++i)
15108 {
15109 #define PROP(IDX) \
15110 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
15111
15112 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
15113 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
15114 int hmargin, vmargin, relief, idx, end;
15115
15116 if (!NILP (PROP (TOOL_BAR_ITEM_WRAP)))
15117 {
15118
15119
15120 SSET (f->desired_tool_bar_string, i, '\n');
15121
15122
15123
15124 f->tool_bar_wraps_p = true;
15125 continue;
15126 }
15127
15128
15129 SSET (f->desired_tool_bar_string, i, ' ');
15130
15131
15132
15133 image = PROP (TOOL_BAR_ITEM_IMAGES);
15134 if (VECTORP (image))
15135 {
15136 if (enabled_p)
15137 idx = (selected_p
15138 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
15139 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
15140 else
15141 idx = (selected_p
15142 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15143 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15144
15145 eassert (ASIZE (image) >= idx);
15146 image = AREF (image, idx);
15147 }
15148 else
15149 idx = -1;
15150
15151
15152 if (!valid_image_p (image))
15153 continue;
15154
15155
15156 plist = Fcopy_sequence (XCDR (image));
15157
15158
15159 relief = (tool_bar_button_relief >= 0
15160 ? min (tool_bar_button_relief,
15161 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15162 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15163 hmargin = vmargin = relief;
15164
15165 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15166 INT_MAX - max (hmargin, vmargin)))
15167 {
15168 hmargin += XFIXNAT (Vtool_bar_button_margin);
15169 vmargin += XFIXNAT (Vtool_bar_button_margin);
15170 }
15171 else if (CONSP (Vtool_bar_button_margin))
15172 {
15173 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15174 INT_MAX - hmargin))
15175 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15176
15177 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15178 INT_MAX - vmargin))
15179 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15180 }
15181
15182 if (auto_raise_tool_bar_buttons_p)
15183 {
15184
15185
15186 if (selected_p)
15187 {
15188 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15189 hmargin -= relief;
15190 vmargin -= relief;
15191 }
15192 }
15193 else
15194 {
15195
15196
15197
15198 plist = plist_put (plist, QCrelief,
15199 (selected_p
15200 ? make_fixnum (-relief)
15201 : make_fixnum (relief)));
15202 hmargin -= relief;
15203 vmargin -= relief;
15204 }
15205
15206
15207 if (hmargin || vmargin)
15208 {
15209 if (hmargin == vmargin)
15210 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15211 else
15212 plist = plist_put (plist, QCmargin,
15213 Fcons (make_fixnum (hmargin),
15214 make_fixnum (vmargin)));
15215 }
15216
15217
15218
15219
15220 if (!enabled_p && idx < 0)
15221 plist = plist_put (plist, QCconversion, Qdisabled);
15222
15223
15224
15225
15226
15227 image = Fcons (Qimage, plist);
15228 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15229 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15230
15231
15232
15233
15234 if (i + 1 == f->n_tool_bar_items)
15235 end = SCHARS (f->desired_tool_bar_string);
15236 else
15237 end = i + 1;
15238 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15239 props, f->desired_tool_bar_string);
15240 #undef PROP
15241 }
15242
15243
15244
15245
15246
15247
15248
15249 for (; i < size; ++i)
15250
15251 SSET (f->desired_tool_bar_string, i, ' ');
15252 }
15253
15254
15255
15256
15257
15258
15259
15260
15261
15262
15263
15264
15265
15266
15267
15268
15269
15270 static void
15271 display_tool_bar_line (struct it *it, int height)
15272 {
15273 struct glyph_row *row = it->glyph_row;
15274 int max_x = it->last_visible_x;
15275 struct glyph *last;
15276
15277
15278 clear_glyph_row (row);
15279 row->enabled_p = true;
15280 row->y = it->current_y;
15281
15282
15283
15284 it->start_of_box_run_p = true;
15285
15286 while (it->current_x < max_x)
15287 {
15288 int x, n_glyphs_before, i, nglyphs;
15289 struct it it_before;
15290
15291
15292 if (!get_next_display_element (it))
15293 {
15294
15295 if (height < 0 && !it->hpos)
15296 return;
15297 break;
15298 }
15299
15300
15301 n_glyphs_before = row->used[TEXT_AREA];
15302 it_before = *it;
15303
15304 PRODUCE_GLYPHS (it);
15305
15306 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15307 i = 0;
15308 x = it_before.current_x;
15309 while (i < nglyphs)
15310 {
15311 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15312
15313 if (x + glyph->pixel_width > max_x)
15314 {
15315
15316 row->used[TEXT_AREA] = n_glyphs_before;
15317 *it = it_before;
15318
15319
15320
15321 if (n_glyphs_before == 0
15322 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15323 break;
15324 goto out;
15325 }
15326
15327 ++it->hpos;
15328 x += glyph->pixel_width;
15329 ++i;
15330 }
15331
15332
15333
15334
15335
15336
15337 if (ITERATOR_AT_END_OF_LINE_P (it))
15338 {
15339 reseat_at_next_visible_line_start (it, false);
15340 break;
15341 }
15342
15343 if (ITERATOR_AT_END_P (it))
15344 break;
15345
15346 set_iterator_to_next (it, true);
15347 }
15348
15349 out:;
15350
15351 row->displays_text_p = row->used[TEXT_AREA] != 0;
15352
15353
15354
15355
15356
15357
15358
15359 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15360 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15361 it->face_id = DEFAULT_FACE_ID;
15362
15363 extend_face_to_end_of_line (it);
15364 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15365 last->right_box_line_p = true;
15366 if (last == row->glyphs[TEXT_AREA])
15367 last->left_box_line_p = true;
15368
15369
15370 if (height != -1
15371 && (height -= it->max_ascent + it->max_descent) > 0)
15372 {
15373
15374 height %= FRAME_LINE_HEIGHT (it->f);
15375 it->max_ascent += height / 2;
15376 it->max_descent += (height + 1) / 2;
15377 }
15378
15379 compute_line_metrics (it);
15380
15381
15382 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15383 {
15384 row->height = row->phys_height = it->last_visible_y - row->y;
15385 row->visible_height = row->height;
15386 row->ascent = row->phys_ascent = 0;
15387 row->extra_line_spacing = 0;
15388 }
15389
15390 row->full_width_p = true;
15391 row->continued_p = false;
15392 row->truncated_on_left_p = false;
15393 row->truncated_on_right_p = false;
15394
15395 it->current_x = it->hpos = 0;
15396 it->current_y += row->height;
15397 ++it->vpos;
15398 ++it->glyph_row;
15399 }
15400
15401
15402
15403
15404
15405
15406 static int
15407 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15408 {
15409 struct window *w = XWINDOW (f->tool_bar_window);
15410 struct it it;
15411
15412
15413
15414 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15415
15416
15417
15418 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15419 temp_row->reversed_p = false;
15420 it.first_visible_x = 0;
15421 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15422 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15423 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15424 it.paragraph_embedding = L2R;
15425
15426 while (!ITERATOR_AT_END_P (&it))
15427 {
15428 clear_glyph_row (temp_row);
15429 it.glyph_row = temp_row;
15430 display_tool_bar_line (&it, -1);
15431 }
15432 clear_glyph_row (temp_row);
15433
15434
15435 if (n_rows)
15436 *n_rows = it.vpos > 0 ? it.vpos : -1;
15437
15438 if (pixelwise)
15439 return it.current_y;
15440 else
15441 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15442 }
15443
15444 #endif
15445
15446 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15447 0, 2, 0,
15448 doc:
15449
15450 )
15451 (Lisp_Object frame, Lisp_Object pixelwise)
15452 {
15453 int height = 0;
15454
15455 #ifndef HAVE_EXT_TOOL_BAR
15456 struct frame *f = decode_any_frame (frame);
15457
15458 if (WINDOWP (f->tool_bar_window)
15459 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15460 {
15461 update_tool_bar (f, true);
15462 if (f->n_tool_bar_items)
15463 {
15464 build_desired_tool_bar_string (f);
15465 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15466 }
15467 }
15468 #endif
15469
15470 return make_fixnum (height);
15471 }
15472
15473 #ifndef HAVE_EXT_TOOL_BAR
15474
15475
15476
15477 static bool
15478 redisplay_tool_bar (struct frame *f)
15479 {
15480 struct window *w;
15481 struct it it;
15482 struct glyph_row *row;
15483 bool change_height_p;
15484
15485 change_height_p = false;
15486 f->tool_bar_redisplayed = true;
15487
15488
15489
15490
15491
15492 if (!WINDOWP (f->tool_bar_window)
15493 || (w = XWINDOW (f->tool_bar_window),
15494 WINDOW_TOTAL_LINES (w) == 0))
15495 {
15496
15497
15498
15499
15500
15501 f->tool_bar_resized = true;
15502
15503 return false;
15504 }
15505
15506
15507 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15508 it.first_visible_x = 0;
15509 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15510 row = it.glyph_row;
15511 row->reversed_p = false;
15512
15513
15514 build_desired_tool_bar_string (f);
15515 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15516 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15517
15518
15519
15520
15521
15522
15523
15524 it.paragraph_embedding = L2R;
15525
15526 if (f->n_tool_bar_rows == 0)
15527 {
15528 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15529
15530 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15531 {
15532 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15533 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15534 frame_default_tool_bar_height = new_height;
15535
15536 clear_glyph_matrix (w->desired_matrix);
15537 f->fonts_changed = true;
15538
15539
15540
15541
15542
15543
15544
15545 resize_frame_windows (f, FRAME_INNER_HEIGHT (f), false);
15546
15547 return true;
15548 }
15549 }
15550
15551
15552
15553 if (f->n_tool_bar_rows > 0)
15554 {
15555 int border, rows, height, extra;
15556
15557 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15558 border = XFIXNUM (Vtool_bar_border);
15559 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15560 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15561 else if (EQ (Vtool_bar_border, Qborder_width))
15562 border = f->border_width;
15563 else
15564 border = 0;
15565 if (border < 0)
15566 border = 0;
15567
15568 rows = f->n_tool_bar_rows;
15569
15570 if (f->tool_bar_wraps_p)
15571 {
15572
15573
15574
15575 while (!ITERATOR_AT_END_P (&it))
15576 display_tool_bar_line (&it, -1);
15577
15578
15579
15580
15581
15582
15583 if (it.current_y != it.last_visible_y)
15584 change_height_p = true;
15585 }
15586 else
15587 {
15588 height = max (1, (it.last_visible_y - border) / rows);
15589 extra = it.last_visible_y - border - height * rows;
15590
15591 while (it.current_y < it.last_visible_y)
15592 {
15593 int h = 0;
15594 if (extra > 0 && rows-- > 0)
15595 {
15596 h = (extra + rows - 1) / rows;
15597 extra -= h;
15598 }
15599
15600 display_tool_bar_line (&it, height + h);
15601 }
15602 }
15603 }
15604 else
15605 {
15606 while (it.current_y < it.last_visible_y)
15607 display_tool_bar_line (&it, 0);
15608 }
15609
15610
15611
15612 w->desired_matrix->no_scrolling_p = true;
15613 w->must_be_updated_p = true;
15614
15615 if (!NILP (Vauto_resize_tool_bars))
15616 {
15617
15618
15619 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15620 change_height_p = true;
15621
15622
15623
15624
15625
15626 row = it.glyph_row - 1;
15627
15628
15629
15630
15631 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15632 && row->height >= FRAME_LINE_HEIGHT (f))
15633 change_height_p = true;
15634
15635
15636
15637 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15638 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15639 change_height_p = true;
15640
15641
15642
15643 if (change_height_p)
15644 {
15645 int nrows;
15646 int new_height = tool_bar_height (f, &nrows, true);
15647
15648 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15649 && !f->minimize_tool_bar_window_p)
15650 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15651 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15652 f->minimize_tool_bar_window_p = false;
15653
15654 if (change_height_p)
15655 {
15656 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15657 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15658 frame_default_tool_bar_height = new_height;
15659 clear_glyph_matrix (w->desired_matrix);
15660 f->n_tool_bar_rows = nrows;
15661 f->fonts_changed = true;
15662
15663 return true;
15664 }
15665 }
15666 }
15667
15668 f->minimize_tool_bar_window_p = false;
15669
15670 return false;
15671 }
15672
15673
15674
15675
15676
15677
15678 static bool
15679 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15680 {
15681 Lisp_Object prop;
15682 ptrdiff_t charpos;
15683
15684
15685
15686
15687 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15688 charpos = max (0, charpos);
15689
15690
15691
15692
15693 prop = Fget_text_property (make_fixnum (charpos),
15694 Qmenu_item, f->current_tool_bar_string);
15695 if (! FIXNUMP (prop))
15696 return false;
15697 *prop_idx = XFIXNUM (prop);
15698 return true;
15699 }
15700
15701
15702
15703
15704
15705
15706
15707
15708
15709
15710
15711
15712 static int
15713 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15714 int *hpos, int *vpos, int *prop_idx)
15715 {
15716 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15717 struct window *w = XWINDOW (f->tool_bar_window);
15718 int area;
15719
15720
15721 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15722 if (*glyph == NULL)
15723 return -1;
15724
15725
15726
15727 if (!tool_bar_item_info (f, *glyph, prop_idx))
15728 return -1;
15729
15730
15731 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15732 && *vpos >= hlinfo->mouse_face_beg_row
15733 && *vpos <= hlinfo->mouse_face_end_row
15734 && (*vpos > hlinfo->mouse_face_beg_row
15735 || *hpos >= hlinfo->mouse_face_beg_col)
15736 && (*vpos < hlinfo->mouse_face_end_row
15737 || *hpos < hlinfo->mouse_face_end_col
15738 || hlinfo->mouse_face_past_end))
15739 return 0;
15740
15741 return 1;
15742 }
15743
15744
15745
15746
15747
15748
15749
15750
15751 void
15752 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15753 int modifiers, Lisp_Object device)
15754 {
15755 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15756 struct window *w = XWINDOW (f->tool_bar_window);
15757 int hpos, vpos, prop_idx;
15758 struct glyph *glyph;
15759 Lisp_Object enabled_p;
15760 int ts;
15761
15762
15763
15764
15765
15766
15767
15768
15769 frame_to_window_pixel_xy (w, &x, &y);
15770 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15771 if (ts == -1
15772 || (ts != 0 && !NILP (Vmouse_highlight)))
15773 return;
15774
15775
15776
15777
15778 if (NILP (Vmouse_highlight) && !down_p)
15779 prop_idx = f->last_tool_bar_item;
15780
15781
15782 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15783 if (NILP (enabled_p))
15784 return;
15785
15786 if (down_p)
15787 {
15788
15789 if (!NILP (Vmouse_highlight))
15790 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15791 f->last_tool_bar_item = prop_idx;
15792 }
15793 else
15794 {
15795 Lisp_Object key, frame;
15796 struct input_event event;
15797 EVENT_INIT (event);
15798
15799
15800 if (!NILP (Vmouse_highlight))
15801 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15802
15803 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15804
15805 XSETFRAME (frame, f);
15806 event.kind = TOOL_BAR_EVENT;
15807 event.frame_or_window = frame;
15808 event.arg = key;
15809 event.modifiers = modifiers;
15810 event.device = device;
15811 kbd_buffer_store_event (&event);
15812 f->last_tool_bar_item = -1;
15813 }
15814 }
15815
15816 void
15817 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15818 int modifiers)
15819 {
15820 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15821 }
15822
15823
15824
15825
15826
15827 static void
15828 note_tool_bar_highlight (struct frame *f, int x, int y)
15829 {
15830 Lisp_Object window = f->tool_bar_window;
15831 struct window *w = XWINDOW (window);
15832 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15833 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15834 int hpos, vpos;
15835 struct glyph *glyph;
15836 struct glyph_row *row;
15837 int i;
15838 Lisp_Object enabled_p;
15839 int prop_idx;
15840 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15841 bool mouse_down_p;
15842 int rc;
15843
15844
15845
15846 if (x <= 0 || y <= 0)
15847 {
15848 clear_mouse_face (hlinfo);
15849 return;
15850 }
15851
15852 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15853 if (rc < 0)
15854 {
15855
15856 clear_mouse_face (hlinfo);
15857 return;
15858 }
15859 else if (rc == 0)
15860
15861 goto set_help_echo;
15862
15863 clear_mouse_face (hlinfo);
15864
15865
15866 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15867 && f == dpyinfo->last_mouse_frame);
15868
15869 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15870 return;
15871
15872 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15873
15874
15875 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15876 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15877 {
15878
15879
15880 row = MATRIX_ROW (w->current_matrix, vpos);
15881 for (i = x = 0; i < hpos; ++i)
15882 x += row->glyphs[TEXT_AREA][i].pixel_width;
15883
15884
15885 hlinfo->mouse_face_beg_col = hpos;
15886 hlinfo->mouse_face_beg_row = vpos;
15887 hlinfo->mouse_face_beg_x = x;
15888 hlinfo->mouse_face_past_end = false;
15889
15890 hlinfo->mouse_face_end_col = hpos + 1;
15891 hlinfo->mouse_face_end_row = vpos;
15892 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15893 hlinfo->mouse_face_window = window;
15894 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15895
15896
15897 show_mouse_face (hlinfo, draw);
15898 }
15899
15900 set_help_echo:
15901
15902
15903
15904 help_echo_object = help_echo_window = Qnil;
15905 help_echo_pos = -1;
15906 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15907 if (NILP (help_echo_string))
15908 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15909 }
15910
15911 #endif
15912
15913 #endif
15914
15915
15916
15917
15918
15919
15920
15921
15922
15923
15924
15925
15926
15927 static bool
15928 hscroll_window_tree (Lisp_Object window)
15929 {
15930 bool hscrolled_p = false;
15931 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15932 int hscroll_step_abs = 0;
15933 double hscroll_step_rel = 0;
15934
15935 if (hscroll_relative_p)
15936 {
15937 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15938 if (hscroll_step_rel < 0)
15939 {
15940 hscroll_relative_p = false;
15941 hscroll_step_abs = 0;
15942 }
15943 }
15944 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15945 {
15946 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15947 if (hscroll_step_abs < 0)
15948 hscroll_step_abs = 0;
15949 }
15950 else
15951 hscroll_step_abs = 0;
15952
15953 while (WINDOWP (window))
15954 {
15955 struct window *w = XWINDOW (window);
15956
15957 if (WINDOWP (w->contents))
15958 hscrolled_p |= hscroll_window_tree (w->contents);
15959 else if (w->cursor.vpos >= 0
15960
15961
15962
15963
15964
15965
15966 && !(w == XWINDOW (echo_area_window)
15967 && !NILP (echo_area_buffer[0])))
15968 {
15969 int h_margin;
15970 int text_area_width;
15971 struct glyph_row *cursor_row;
15972 struct glyph_row *bottom_row;
15973
15974 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15975 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15976 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15977 else
15978 cursor_row = bottom_row - 1;
15979
15980 if (!cursor_row->enabled_p)
15981 {
15982 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15983 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15984 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15985 else
15986 cursor_row = bottom_row - 1;
15987 }
15988 bool row_r2l_p = cursor_row->reversed_p;
15989 bool hscl = hscrolling_current_line_p (w);
15990 int x_offset = 0;
15991
15992
15993 if (!NILP (Vdisplay_line_numbers))
15994 {
15995 struct glyph *g;
15996 if (!row_r2l_p)
15997 {
15998 for (g = cursor_row->glyphs[TEXT_AREA];
15999 g < cursor_row->glyphs[TEXT_AREA]
16000 + cursor_row->used[TEXT_AREA];
16001 g++)
16002 {
16003 if (!(NILP (g->object) && g->charpos < 0))
16004 break;
16005 x_offset += g->pixel_width;
16006 }
16007 }
16008 else
16009 {
16010 for (g = cursor_row->glyphs[TEXT_AREA]
16011 + cursor_row->used[TEXT_AREA];
16012 g > cursor_row->glyphs[TEXT_AREA];
16013 g--)
16014 {
16015 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
16016 break;
16017 x_offset += (g - 1)->pixel_width;
16018 }
16019 }
16020 }
16021 if (cursor_row->truncated_on_left_p)
16022 {
16023
16024 struct frame *f = XFRAME (WINDOW_FRAME (w));
16025 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
16026 }
16027
16028 text_area_width = window_box_width (w, TEXT_AREA);
16029
16030
16031 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
16032 * WINDOW_FRAME_COLUMN_WIDTH (w));
16033
16034
16035
16036 if (w->suspend_auto_hscroll
16037 && NILP (Fequal (Fwindow_point (window),
16038 Fwindow_old_point (window))))
16039 {
16040 w->suspend_auto_hscroll = false;
16041
16042
16043
16044
16045 if (w->min_hscroll == 0 && w->hscroll > 0
16046 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
16047 Qcurrent_line))
16048 SET_FRAME_GARBAGED (XFRAME (w->frame));
16049 }
16050
16051
16052 Fset_marker (w->old_pointm,
16053 ((w == XWINDOW (selected_window))
16054 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
16055 : Fmarker_position (w->pointm)),
16056 w->contents);
16057
16058 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
16059 && !w->suspend_auto_hscroll
16060
16061
16062
16063
16064
16065
16066 && (CHARPOS (cursor_row->start.pos)
16067 >= BUF_BEG (XBUFFER (w->contents)))
16068
16069
16070
16071
16072 && ((!row_r2l_p
16073 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
16074 || (cursor_row->enabled_p
16075 && cursor_row->truncated_on_right_p
16076 && (w->cursor.x >= text_area_width - h_margin))))
16077
16078
16079
16080
16081
16082
16083 || (row_r2l_p
16084 && ((cursor_row->enabled_p
16085
16086
16087
16088 && cursor_row->truncated_on_right_p
16089 && w->cursor.x <= h_margin)
16090 || (w->hscroll
16091 && (w->cursor.x >= (text_area_width - h_margin
16092 - x_offset)))))
16093
16094
16095
16096
16097
16098 || (hscl
16099 && w->hscroll != w->min_hscroll
16100 && !cursor_row->truncated_on_left_p)))
16101 {
16102 struct it it;
16103 ptrdiff_t hscroll;
16104 struct buffer *saved_current_buffer;
16105 ptrdiff_t pt;
16106 int wanted_x;
16107
16108
16109 saved_current_buffer = current_buffer;
16110 current_buffer = XBUFFER (w->contents);
16111
16112 if (w == XWINDOW (selected_window))
16113 pt = PT;
16114 else
16115 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
16116
16117
16118
16119 init_to_row_start (&it, w, cursor_row);
16120 if (hscl)
16121 it.first_visible_x = window_hscroll_limited (w, it.f)
16122 * FRAME_COLUMN_WIDTH (it.f);
16123 it.last_visible_x = DISP_INFINITY;
16124
16125 ptrdiff_t nchars = pt - IT_CHARPOS (it);
16126 if (current_buffer->long_line_optimizations_p
16127 && nchars > large_hscroll_threshold)
16128 {
16129
16130
16131
16132
16133 fast_move_it_horizontally (&it, nchars);
16134 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
16135 }
16136 else
16137 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
16138
16139
16140
16141
16142
16143
16144 if (it.method == GET_FROM_STRING && pt > 1)
16145 {
16146 init_to_row_start (&it, w, cursor_row);
16147 if (hscl)
16148 it.first_visible_x = (window_hscroll_limited (w, it.f)
16149 * FRAME_COLUMN_WIDTH (it.f));
16150 if (current_buffer->long_line_optimizations_p
16151 && nchars > large_hscroll_threshold)
16152 {
16153 fast_move_it_horizontally (&it, nchars - 1);
16154 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
16155 }
16156 else
16157 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
16158 }
16159 current_buffer = saved_current_buffer;
16160
16161
16162 if (!hscroll_relative_p && hscroll_step_abs == 0)
16163 hscroll = max (0, (it.current_x
16164 - (ITERATOR_AT_END_OF_LINE_P (&it)
16165 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
16166 : (text_area_width / 2))))
16167 / FRAME_COLUMN_WIDTH (it.f);
16168 else if ((!row_r2l_p
16169 && w->cursor.x >= text_area_width - h_margin)
16170 || (row_r2l_p && w->cursor.x <= h_margin))
16171 {
16172 if (hscroll_relative_p)
16173 wanted_x = text_area_width * (1 - hscroll_step_rel)
16174 - h_margin;
16175 else
16176 wanted_x = text_area_width
16177 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16178 - h_margin;
16179 hscroll
16180 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16181 }
16182 else
16183 {
16184 if (hscroll_relative_p)
16185 wanted_x =
16186 text_area_width * hscroll_step_rel + h_margin + x_offset;
16187 else
16188 wanted_x =
16189 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16190 + h_margin + x_offset;
16191 hscroll
16192 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16193 }
16194 hscroll = max (hscroll, w->min_hscroll);
16195
16196
16197
16198
16199 if (w->hscroll != hscroll
16200
16201
16202
16203
16204 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16205 {
16206 struct buffer *b = XBUFFER (w->contents);
16207 b->prevent_redisplay_optimizations_p = true;
16208 w->hscroll = hscroll;
16209 hscrolled_p = true;
16210 }
16211 }
16212 }
16213
16214 window = w->next;
16215 }
16216
16217
16218 return hscrolled_p;
16219 }
16220
16221
16222
16223
16224
16225
16226
16227
16228 static bool
16229 hscroll_windows (Lisp_Object window)
16230 {
16231 bool hscrolled_p = hscroll_window_tree (window);
16232 if (hscrolled_p)
16233 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16234 return hscrolled_p;
16235 }
16236
16237
16238
16239
16240
16241
16242
16243
16244
16245
16246 #ifdef GLYPH_DEBUG
16247
16248
16249
16250 static int debug_first_unchanged_at_end_vpos;
16251 static int debug_last_unchanged_at_beg_vpos;
16252
16253
16254
16255 static int debug_dvpos, debug_dy;
16256
16257
16258
16259 static ptrdiff_t debug_delta, debug_delta_bytes;
16260
16261
16262
16263
16264 static ptrdiff_t debug_end_vpos;
16265
16266
16267
16268
16269
16270 static void debug_method_add (struct window *, char const *, ...)
16271 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16272
16273 static void
16274 debug_method_add (struct window *w, char const *fmt, ...)
16275 {
16276 void *ptr = w;
16277 char *method = w->desired_matrix->method;
16278 int len = strlen (method);
16279 int size = sizeof w->desired_matrix->method;
16280 int remaining = size - len - 1;
16281 va_list ap;
16282
16283 if (len && remaining)
16284 {
16285 method[len] = '|';
16286 --remaining, ++len;
16287 }
16288
16289 va_start (ap, fmt);
16290 vsnprintf (method + len, remaining + 1, fmt, ap);
16291 va_end (ap);
16292
16293 if (trace_redisplay_p)
16294 fprintf (stderr, "%p (%s): %s\n",
16295 ptr,
16296 ((BUFFERP (w->contents)
16297 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16298 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16299 : "no buffer"),
16300 method + len);
16301 }
16302
16303 #endif
16304
16305
16306
16307
16308
16309
16310
16311 static bool
16312 text_outside_line_unchanged_p (struct window *w,
16313 ptrdiff_t start, ptrdiff_t end)
16314 {
16315 bool unchanged_p = true;
16316
16317
16318 if (window_outdated (w))
16319 {
16320
16321 if (GPT < start || Z - GPT < end)
16322 unchanged_p = false;
16323
16324
16325 if (unchanged_p
16326 && (BEG_UNCHANGED < start - 1
16327 || END_UNCHANGED < end))
16328 unchanged_p = false;
16329
16330
16331
16332 if (unchanged_p
16333 && FIXNUMP (BVAR (current_buffer, selective_display))
16334 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16335 && (BEG_UNCHANGED < start || GPT <= start))
16336 unchanged_p = false;
16337
16338
16339
16340
16341
16342
16343
16344
16345 if (unchanged_p)
16346 {
16347 if (BEG + BEG_UNCHANGED == start
16348 && overlay_touches_p (start))
16349 unchanged_p = false;
16350 if (END_UNCHANGED == end
16351 && overlay_touches_p (Z - end))
16352 unchanged_p = false;
16353 }
16354
16355
16356
16357
16358
16359
16360
16361
16362 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16363 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16364 unchanged_p = false;
16365 }
16366
16367 return unchanged_p;
16368 }
16369
16370
16371
16372
16373
16374
16375
16376
16377
16378 void
16379 redisplay (void)
16380 {
16381 redisplay_internal ();
16382 }
16383
16384
16385 static Lisp_Object
16386 overlay_arrow_string_or_property (Lisp_Object var)
16387 {
16388 Lisp_Object val;
16389
16390 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16391 return val;
16392
16393 return Voverlay_arrow_string;
16394 }
16395
16396
16397 static bool
16398 overlay_arrow_in_current_buffer_p (void)
16399 {
16400 Lisp_Object vlist;
16401
16402 for (vlist = Voverlay_arrow_variable_list;
16403 CONSP (vlist);
16404 vlist = XCDR (vlist))
16405 {
16406 Lisp_Object var = XCAR (vlist);
16407 Lisp_Object val;
16408
16409 if (!SYMBOLP (var))
16410 continue;
16411 val = find_symbol_value (var);
16412 if (MARKERP (val)
16413 && current_buffer == XMARKER (val)->buffer)
16414 return true;
16415 }
16416 return false;
16417 }
16418
16419
16420
16421
16422
16423
16424
16425 static bool
16426 overlay_arrows_changed_p (bool set_redisplay)
16427 {
16428 Lisp_Object vlist;
16429 bool changed = false;
16430
16431 for (vlist = Voverlay_arrow_variable_list;
16432 CONSP (vlist);
16433 vlist = XCDR (vlist))
16434 {
16435 Lisp_Object var = XCAR (vlist);
16436 Lisp_Object val, pstr;
16437
16438 if (!SYMBOLP (var))
16439 continue;
16440 val = find_symbol_value (var);
16441 if (!MARKERP (val))
16442 continue;
16443 if (! EQ (Fmarker_position (val),
16444
16445
16446 Fget (var, Qlast_arrow_position))
16447 || ! (pstr = overlay_arrow_string_or_property (var),
16448 EQ (pstr, Fget (var, Qlast_arrow_string))))
16449 {
16450 struct buffer *buf = XMARKER (val)->buffer;
16451
16452 if (set_redisplay)
16453 {
16454 if (buf)
16455 bset_redisplay (buf);
16456 changed = true;
16457 }
16458 else
16459 return true;
16460 }
16461 }
16462 return changed;
16463 }
16464
16465
16466
16467 static void
16468 update_overlay_arrows (int up_to_date)
16469 {
16470 Lisp_Object vlist;
16471
16472 for (vlist = Voverlay_arrow_variable_list;
16473 CONSP (vlist);
16474 vlist = XCDR (vlist))
16475 {
16476 Lisp_Object var = XCAR (vlist);
16477
16478 if (!SYMBOLP (var))
16479 continue;
16480
16481 if (up_to_date > 0)
16482 {
16483 Lisp_Object val = find_symbol_value (var);
16484 if (!MARKERP (val))
16485 continue;
16486 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16487 Fput (var, Qlast_arrow_string,
16488 overlay_arrow_string_or_property (var));
16489 }
16490 else if (up_to_date < 0
16491 || !NILP (Fget (var, Qlast_arrow_position)))
16492 {
16493 Fput (var, Qlast_arrow_position, Qt);
16494 Fput (var, Qlast_arrow_string, Qt);
16495 }
16496 }
16497 }
16498
16499
16500
16501
16502
16503
16504 static Lisp_Object
16505 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16506 {
16507 Lisp_Object vlist;
16508
16509 for (vlist = Voverlay_arrow_variable_list;
16510 CONSP (vlist);
16511 vlist = XCDR (vlist))
16512 {
16513 Lisp_Object var = XCAR (vlist);
16514 Lisp_Object val;
16515
16516 if (!SYMBOLP (var))
16517 continue;
16518
16519 val = find_symbol_value (var);
16520
16521 if (MARKERP (val)
16522 && current_buffer == XMARKER (val)->buffer
16523 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16524 {
16525 if (FRAME_WINDOW_P (it->f)
16526
16527
16528 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16529 {
16530 #ifdef HAVE_WINDOW_SYSTEM
16531 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16532 {
16533 int fringe_bitmap = lookup_fringe_bitmap (val);
16534 if (fringe_bitmap != 0)
16535 return make_fixnum (fringe_bitmap);
16536 }
16537 #endif
16538 return make_fixnum (-1);
16539 }
16540 return overlay_arrow_string_or_property (var);
16541 }
16542 }
16543
16544 return Qnil;
16545 }
16546
16547
16548
16549
16550
16551 static bool
16552 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16553 struct buffer *buf, ptrdiff_t pt)
16554 {
16555 ptrdiff_t start, end;
16556 Lisp_Object prop;
16557 Lisp_Object buffer;
16558
16559 XSETBUFFER (buffer, buf);
16560
16561
16562 if (prev_buf == buf)
16563 {
16564 if (prev_pt == pt)
16565
16566 return false;
16567
16568 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16569 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16570 && composition_valid_p (start, end, prop)
16571 && start < prev_pt && end > prev_pt)
16572
16573
16574 return (pt <= start || pt >= end);
16575 }
16576
16577
16578 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16579 && find_composition (pt, -1, &start, &end, &prop, buffer)
16580 && composition_valid_p (start, end, prop)
16581 && start < pt && end > pt);
16582 }
16583
16584
16585
16586 static void
16587 reconsider_clip_changes (struct window *w)
16588 {
16589 struct buffer *b = XBUFFER (w->contents);
16590
16591 if (b->clip_changed
16592 && w->window_end_valid
16593 && w->current_matrix->buffer == b
16594 && w->current_matrix->zv == BUF_ZV (b)
16595 && w->current_matrix->begv == BUF_BEGV (b))
16596 b->clip_changed = false;
16597
16598
16599
16600
16601
16602 if (!b->clip_changed && w->window_end_valid)
16603 {
16604 ptrdiff_t pt = (w == XWINDOW (selected_window)
16605 ? PT : marker_position (w->pointm));
16606
16607 if ((w->current_matrix->buffer != b || pt != w->last_point)
16608 && check_point_in_composition (w->current_matrix->buffer,
16609 w->last_point, b, pt))
16610 b->clip_changed = true;
16611 }
16612 }
16613
16614 static void
16615 propagate_buffer_redisplay (void)
16616 {
16617
16618
16619
16620
16621
16622
16623
16624
16625
16626 Lisp_Object ws = window_list ();
16627 for (; CONSP (ws); ws = XCDR (ws))
16628 {
16629 struct window *thisw = XWINDOW (XCAR (ws));
16630 struct buffer *thisb = XBUFFER (thisw->contents);
16631 if (thisb->text->redisplay)
16632 thisw->redisplay = true;
16633 }
16634 }
16635
16636 #define STOP_POLLING \
16637 do { if (! polling_stopped_here) stop_polling (); \
16638 polling_stopped_here = true; } while (false)
16639
16640 #define RESUME_POLLING \
16641 do { if (polling_stopped_here) start_polling (); \
16642 polling_stopped_here = false; } while (false)
16643
16644
16645
16646
16647 static void
16648 redisplay_internal (void)
16649 {
16650 struct window *w = XWINDOW (selected_window);
16651 struct window *sw;
16652 struct frame *fr;
16653 bool pending;
16654 bool must_finish = false, match_p;
16655 struct text_pos tlbufpos, tlendpos;
16656 int number_of_visible_frames;
16657 struct frame *sf;
16658 bool polling_stopped_here = false;
16659 Lisp_Object tail, frame;
16660
16661
16662
16663
16664 enum { MAX_HSCROLL_RETRIES = 16 };
16665 int hscroll_retries = 0;
16666
16667
16668
16669
16670
16671
16672 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16673 int garbaged_frame_retries = 0;
16674
16675
16676
16677
16678 bool consider_all_windows_p;
16679
16680
16681 bool update_miniwindow_p = false;
16682
16683 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16684
16685
16686
16687
16688 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16689 && redisplay_skip_initial_frame)
16690 || !NILP (Vinhibit_redisplay))
16691 return;
16692
16693
16694
16695
16696 fr = XFRAME (w->frame);
16697 sf = SELECTED_FRAME ();
16698
16699 if (!fr->glyphs_initialized_p)
16700 return;
16701
16702 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16703 if (popup_activated ())
16704 return;
16705 #endif
16706
16707 #if defined (HAVE_HAIKU)
16708 if (popup_activated_p)
16709 return;
16710 #endif
16711
16712
16713 if (redisplaying_p)
16714 return;
16715
16716
16717
16718 specpdl_ref count = SPECPDL_INDEX ();
16719 record_unwind_protect_void (unwind_redisplay);
16720 redisplaying_p = true;
16721 block_buffer_flips ();
16722 specbind (Qinhibit_free_realized_faces, Qnil);
16723
16724
16725 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16726
16727 FOR_EACH_FRAME (tail, frame)
16728 XFRAME (frame)->already_hscrolled_p = false;
16729
16730 reset_outermost_restrictions ();
16731
16732 retry:
16733
16734 sw = w;
16735
16736 pending = false;
16737 forget_escape_and_glyphless_faces ();
16738
16739 inhibit_free_realized_faces = false;
16740
16741
16742
16743
16744 if (face_change)
16745 windows_or_buffers_changed = 47;
16746
16747 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16748 && FRAME_TTY (sf)->previous_frame != sf)
16749 {
16750
16751
16752
16753 SET_FRAME_GARBAGED (sf);
16754 #if !defined DOS_NT && !defined HAVE_ANDROID
16755 set_tty_color_mode (FRAME_TTY (sf), sf);
16756 #endif
16757 FRAME_TTY (sf)->previous_frame = sf;
16758 }
16759
16760
16761
16762
16763 number_of_visible_frames = 0;
16764
16765 FOR_EACH_FRAME (tail, frame)
16766 {
16767 struct frame *f = XFRAME (frame);
16768
16769 if (FRAME_REDISPLAY_P (f))
16770 {
16771 ++number_of_visible_frames;
16772
16773 if (f->fonts_changed)
16774 {
16775 adjust_frame_glyphs (f);
16776
16777
16778
16779
16780
16781
16782 SET_FRAME_GARBAGED (f);
16783 f->fonts_changed = false;
16784 }
16785
16786
16787 if (f != sf && f->cursor_type_changed)
16788 fset_redisplay (f);
16789 }
16790 clear_desired_matrices (f);
16791 }
16792
16793
16794 do_pending_window_change (true);
16795
16796
16797 clear_garbaged_frames ();
16798
16799
16800 if (NILP (Vmemory_full))
16801 prepare_menu_bars ();
16802
16803
16804
16805
16806
16807 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16808 sw = w;
16809
16810 reconsider_clip_changes (w);
16811
16812
16813 match_p = XBUFFER (w->contents) == current_buffer;
16814 if (match_p)
16815 {
16816
16817 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16818 w->update_mode_line = true;
16819
16820 if (mode_line_update_needed (w))
16821 w->update_mode_line = true;
16822
16823
16824
16825
16826 if (current_buffer->clip_changed)
16827 bset_update_mode_line (current_buffer);
16828 }
16829
16830
16831
16832
16833
16834
16835 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16836 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16837 || (message_cleared_p
16838 && minibuf_level == 0
16839
16840
16841 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16842 {
16843 echo_area_display (false);
16844
16845 if (message_cleared_p)
16846 update_miniwindow_p = true;
16847
16848 must_finish = true;
16849
16850
16851
16852
16853
16854 if (!display_last_displayed_message_p)
16855 message_cleared_p = false;
16856 }
16857 else if (EQ (selected_window, minibuf_window)
16858 && (current_buffer->clip_changed || window_outdated (w))
16859 && resize_mini_window (w, false))
16860 {
16861
16862
16863 must_finish = true;
16864
16865
16866
16867
16868 clear_garbaged_frames ();
16869 }
16870
16871 if (!NILP (Vrun_hooks))
16872 run_window_change_functions ();
16873
16874 if (windows_or_buffers_changed && !update_mode_lines)
16875
16876
16877
16878 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16879 ? REDISPLAY_SOME : 32);
16880
16881
16882
16883
16884
16885 overlay_arrows_changed_p (true);
16886
16887 consider_all_windows_p = (update_mode_lines
16888 || windows_or_buffers_changed);
16889
16890 #define AINC(a,i) \
16891 { \
16892 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16893 if (FIXNUMP (entry)) \
16894 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16895 }
16896
16897 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16898 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16899
16900
16901
16902
16903
16904 tlbufpos = this_line_start_pos;
16905 tlendpos = this_line_end_pos;
16906 if (!consider_all_windows_p
16907 && CHARPOS (tlbufpos) > 0
16908 && !w->update_mode_line
16909 && !current_buffer->clip_changed
16910 && !current_buffer->prevent_redisplay_optimizations_p
16911 && FRAME_REDISPLAY_P (XFRAME (w->frame))
16912 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16913 && !XFRAME (w->frame)->cursor_type_changed
16914 && !XFRAME (w->frame)->face_change
16915
16916 && this_line_buffer == current_buffer
16917 && match_p
16918 && !w->force_start
16919 && !w->optional_new_start
16920
16921 && PT >= CHARPOS (tlbufpos)
16922 && PT <= Z - CHARPOS (tlendpos)
16923
16924
16925
16926
16927
16928
16929 && (NILP (Vdisplay_line_numbers)
16930 || EQ (Vdisplay_line_numbers, Qvisual))
16931
16932
16933 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16934 CHARPOS (tlendpos)))
16935 {
16936 if (CHARPOS (tlbufpos) > BEGV
16937 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16938 && (CHARPOS (tlbufpos) == ZV
16939 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16940
16941 goto cancel;
16942 else if (window_outdated (w) || MINI_WINDOW_P (w))
16943 {
16944
16945
16946
16947
16948
16949
16950
16951
16952
16953
16954
16955
16956
16957
16958
16959 struct it it;
16960 int line_height_before = this_line_pixel_height;
16961
16962
16963
16964 start_display (&it, w, tlbufpos);
16965
16966
16967 if (it.current_x != this_line_start_x)
16968 goto cancel;
16969
16970
16971
16972
16973 if (it.sp > 1
16974 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16975 goto cancel;
16976 redisplay_trace ("trying display optimization 1\n");
16977 w->cursor.vpos = -1;
16978 overlay_arrow_seen = false;
16979 it.vpos = this_line_vpos;
16980 it.current_y = this_line_y;
16981 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16982 display_line (&it, -1);
16983
16984
16985
16986 if (w->cursor.vpos >= 0
16987
16988
16989 && CHARPOS (this_line_start_pos)
16990
16991 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16992
16993
16994 && this_line_pixel_height == line_height_before
16995
16996
16997
16998
16999 && !hscrolling_current_line_p (w))
17000 {
17001
17002
17003 if (it.current_y < it.last_visible_y)
17004 {
17005 struct glyph_row *row
17006 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
17007 ptrdiff_t delta, delta_bytes;
17008
17009
17010
17011
17012
17013
17014 delta = (Z
17015 - CHARPOS (tlendpos)
17016 - MATRIX_ROW_START_CHARPOS (row));
17017 delta_bytes = (Z_BYTE
17018 - BYTEPOS (tlendpos)
17019 - MATRIX_ROW_START_BYTEPOS (row));
17020
17021 increment_matrix_positions (w->current_matrix,
17022 this_line_vpos + 1,
17023 w->current_matrix->nrows,
17024 delta, delta_bytes);
17025 }
17026
17027
17028
17029
17030 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
17031 {
17032 if (w->window_end_vpos < this_line_vpos)
17033 w->window_end_vpos = this_line_vpos;
17034 }
17035 else if (w->window_end_vpos == this_line_vpos
17036 && this_line_vpos > 0)
17037 w->window_end_vpos = this_line_vpos - 1;
17038 w->window_end_valid = false;
17039
17040
17041 w->desired_matrix->no_scrolling_p = true;
17042
17043 #ifdef GLYPH_DEBUG
17044 *w->desired_matrix->method = 0;
17045 debug_method_add (w, "optimization 1");
17046 #endif
17047 #ifdef HAVE_WINDOW_SYSTEM
17048 update_window_fringes (w, false);
17049 #endif
17050 goto update;
17051 }
17052 else
17053 goto cancel;
17054 }
17055 else if (
17056 PT == w->last_point
17057
17058
17059
17060
17061 && 0 <= w->cursor.vpos
17062 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
17063 {
17064 if (!must_finish)
17065 {
17066 do_pending_window_change (true);
17067
17068 if (WINDOWP (selected_window)
17069 && (w = XWINDOW (selected_window)) != sw)
17070 goto retry;
17071
17072
17073
17074 if (w->cursor_off_p == w->last_cursor_off_p)
17075 goto end_of_redisplay;
17076 }
17077 goto update;
17078 }
17079
17080
17081 else if (NILP (Vshow_trailing_whitespace)
17082 && !cursor_in_echo_area
17083 && !composition_break_at_point)
17084 {
17085 struct it it;
17086 struct glyph_row *row;
17087
17088
17089
17090
17091 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
17092 NULL, DEFAULT_FACE_ID);
17093 it.current_x = this_line_start_x;
17094 it.current_y = this_line_y;
17095 it.vpos = this_line_vpos;
17096
17097 if (current_buffer->long_line_optimizations_p
17098 && it.line_wrap == TRUNCATE
17099 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
17100 {
17101
17102
17103
17104 reseat_at_next_visible_line_start (&it, false);
17105 if (IT_CHARPOS (it) <= PT)
17106 it.vpos = this_line_vpos + 1;
17107 }
17108 else
17109 {
17110
17111
17112 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
17113 }
17114
17115 if (it.vpos == this_line_vpos
17116 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
17117 row->enabled_p))
17118 {
17119 eassert (this_line_vpos == it.vpos);
17120 eassert (this_line_y == it.current_y);
17121 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
17122 if (cursor_row_fully_visible_p (w, false, true, false))
17123 {
17124 #ifdef GLYPH_DEBUG
17125 *w->desired_matrix->method = 0;
17126 debug_method_add (w, "optimization 3");
17127 #endif
17128 goto update;
17129 }
17130 else
17131 goto cancel;
17132 }
17133 else
17134 goto cancel;
17135 }
17136
17137 cancel:
17138
17139 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
17140 }
17141
17142 CHARPOS (this_line_start_pos) = 0;
17143 ++clear_face_cache_count;
17144 #ifdef HAVE_WINDOW_SYSTEM
17145 ++clear_image_cache_count;
17146 #endif
17147
17148
17149
17150
17151
17152
17153 if (consider_all_windows_p)
17154 {
17155 FOR_EACH_FRAME (tail, frame)
17156 XFRAME (frame)->updated_p = false;
17157
17158 propagate_buffer_redisplay ();
17159
17160 FOR_EACH_FRAME (tail, frame)
17161 {
17162 struct frame *f = XFRAME (frame);
17163
17164
17165
17166 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
17167 && !EQ (FRAME_TTY (f)->top_frame, frame))
17168 continue;
17169
17170 retry_frame:
17171 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
17172 {
17173 bool gcscrollbars
17174
17175 = f->redisplay || !REDISPLAY_SOME_P ();
17176 bool f_redisplay_flag = f->redisplay;
17177
17178
17179
17180
17181 if (!FRAME_LIVE_P (f))
17182 continue;
17183
17184
17185
17186 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
17187 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
17188
17189 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17190 {
17191
17192
17193
17194
17195
17196
17197
17198 f->inhibit_clear_image_cache = true;
17199 redisplay_windows (FRAME_ROOT_WINDOW (f));
17200 }
17201
17202
17203 else if (!REDISPLAY_SOME_P ())
17204 f->redisplay = true;
17205
17206
17207 if (!FRAME_LIVE_P (f))
17208 continue;
17209
17210
17211
17212 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17213 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17214
17215 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17216 {
17217
17218 if (f->fonts_changed)
17219 {
17220 adjust_frame_glyphs (f);
17221
17222
17223
17224 SET_FRAME_GARBAGED (f);
17225 f->fonts_changed = false;
17226 goto retry_frame;
17227 }
17228
17229
17230 if (!f->already_hscrolled_p)
17231 {
17232 f->already_hscrolled_p = true;
17233 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17234 && hscroll_windows (f->root_window))
17235 {
17236 hscroll_retries++;
17237 goto retry_frame;
17238 }
17239 }
17240
17241
17242
17243
17244
17245
17246
17247
17248
17249
17250
17251
17252 if (!f_redisplay_flag && f->redisplay)
17253 goto retry_frame;
17254
17255
17256
17257
17258
17259
17260
17261
17262
17263 if (FRAME_GARBAGED_P (f)
17264 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17265 goto retry;
17266
17267 #ifdef HAVE_WINDOW_SYSTEM
17268 if (FRAME_WINDOW_P (f)
17269 && FRAME_RIF (f)->clear_under_internal_border)
17270 FRAME_RIF (f)->clear_under_internal_border (f);
17271 #endif
17272
17273
17274
17275 if (interrupt_input)
17276 unrequest_sigio ();
17277 STOP_POLLING;
17278
17279 pending |= update_frame (f, false, false);
17280
17281
17282
17283
17284
17285
17286
17287 if (FRAME_GARBAGED_P (f))
17288 {
17289 fset_redisplay (f);
17290 f->garbaged = false;
17291 goto retry_frame;
17292 }
17293 f->cursor_type_changed = false;
17294 f->updated_p = true;
17295 f->inhibit_clear_image_cache = false;
17296 }
17297 }
17298 }
17299
17300 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17301
17302 if (!pending)
17303 {
17304
17305
17306
17307 FOR_EACH_FRAME (tail, frame)
17308 {
17309 struct frame *f = XFRAME (frame);
17310 if (f->updated_p)
17311 {
17312 f->redisplay = false;
17313 f->garbaged = false;
17314 mark_window_display_accurate (f->root_window, true);
17315 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17316 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17317 }
17318 }
17319 }
17320 }
17321 else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17322 {
17323 sf->inhibit_clear_image_cache = true;
17324 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17325
17326
17327 internal_condition_case_1 (redisplay_window_1, selected_window,
17328 list_of_error,
17329 redisplay_window_error);
17330 if (update_miniwindow_p)
17331 {
17332 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17333
17334 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17335 internal_condition_case_1 (redisplay_window_1, mini_window,
17336 list_of_error,
17337 redisplay_window_error);
17338 }
17339
17340
17341
17342 update:
17343
17344
17345
17346 if (sf->fonts_changed || sf->redisplay)
17347 {
17348 if (sf->redisplay)
17349 {
17350
17351
17352
17353
17354
17355
17356 windows_or_buffers_changed = 50;
17357 }
17358 goto retry;
17359 }
17360
17361
17362
17363 inhibit_free_realized_faces = true;
17364
17365
17366
17367
17368 if (interrupt_input)
17369 unrequest_sigio ();
17370 STOP_POLLING;
17371
17372 if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17373 {
17374 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17375 && hscroll_windows (selected_window))
17376 {
17377 hscroll_retries++;
17378 goto retry;
17379 }
17380
17381 XWINDOW (selected_window)->must_be_updated_p = true;
17382 pending = update_frame (sf, false, false);
17383 sf->cursor_type_changed = false;
17384 sf->inhibit_clear_image_cache = false;
17385 }
17386
17387
17388
17389
17390
17391
17392 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17393 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17394
17395 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17396 {
17397 XWINDOW (mini_window)->must_be_updated_p = true;
17398 pending |= update_frame (mini_frame, false, false);
17399 mini_frame->cursor_type_changed = false;
17400 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17401 && hscroll_windows (mini_window))
17402 {
17403 hscroll_retries++;
17404 goto retry;
17405 }
17406 }
17407 }
17408
17409
17410
17411 if (pending)
17412 {
17413
17414
17415
17416 CHARPOS (this_line_start_pos) = 0;
17417
17418
17419 update_overlay_arrows (0);
17420
17421
17422
17423 if (!WINDOW_FULL_WIDTH_P (w)
17424 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17425 update_mode_lines = 36;
17426 }
17427 else
17428 {
17429 if (!consider_all_windows_p)
17430 {
17431
17432
17433 if (XBUFFER (w->contents)->text->redisplay
17434 && buffer_window_count (XBUFFER (w->contents)) > 1)
17435
17436
17437 propagate_buffer_redisplay ();
17438 mark_window_display_accurate_1 (w, true);
17439
17440
17441 update_overlay_arrows (1);
17442
17443 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17444 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17445 }
17446
17447 update_mode_lines = 0;
17448 windows_or_buffers_changed = 0;
17449 }
17450
17451
17452
17453
17454
17455 if (interrupt_input)
17456 request_sigio ();
17457 RESUME_POLLING;
17458
17459
17460
17461
17462
17463
17464
17465 if (!pending)
17466 {
17467 int new_count = 0;
17468
17469 FOR_EACH_FRAME (tail, frame)
17470 {
17471 if (FRAME_REDISPLAY_P (XFRAME (frame)))
17472 new_count++;
17473 }
17474
17475 if (new_count != number_of_visible_frames)
17476 windows_or_buffers_changed = 52;
17477 }
17478
17479
17480 do_pending_window_change (true);
17481
17482
17483
17484 if ((windows_or_buffers_changed && !pending)
17485 || (WINDOWP (selected_window)
17486 && (w = XWINDOW (selected_window)) != sw))
17487 goto retry;
17488
17489
17490
17491
17492
17493
17494
17495 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17496 {
17497 clear_face_cache (false);
17498 clear_face_cache_count = 0;
17499 }
17500
17501 #ifdef HAVE_WINDOW_SYSTEM
17502 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17503 {
17504 clear_image_caches (Qnil);
17505 clear_image_cache_count = 0;
17506 }
17507 #endif
17508
17509 end_of_redisplay:
17510 #ifdef HAVE_NS
17511 ns_set_doc_edited ();
17512 #endif
17513 if (interrupt_input && interrupts_deferred)
17514 request_sigio ();
17515
17516
17517
17518 if (max_redisplay_ticks > 0)
17519 update_redisplay_ticks (0, NULL);
17520
17521 unbind_to (count, Qnil);
17522 RESUME_POLLING;
17523 }
17524
17525 static void
17526 unwind_redisplay_preserve_echo_area (void)
17527 {
17528 unblock_buffer_flips ();
17529 }
17530
17531
17532
17533
17534
17535
17536
17537
17538
17539
17540
17541
17542 void
17543 redisplay_preserve_echo_area (int from_where)
17544 {
17545 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17546
17547 block_input ();
17548 specpdl_ref count = SPECPDL_INDEX ();
17549 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17550 block_buffer_flips ();
17551 unblock_input ();
17552
17553 if (!NILP (echo_area_buffer[1]))
17554 {
17555
17556
17557 display_last_displayed_message_p = true;
17558 redisplay_internal ();
17559 display_last_displayed_message_p = false;
17560 }
17561 else
17562 redisplay_internal ();
17563
17564 flush_frame (SELECTED_FRAME ());
17565 unbind_to (count, Qnil);
17566 }
17567
17568
17569
17570
17571 static void
17572 unwind_redisplay (void)
17573 {
17574 redisplaying_p = false;
17575 unblock_buffer_flips ();
17576 }
17577
17578
17579
17580 void
17581 unwind_display_working_on_window (void)
17582 {
17583 display_working_on_window_p = false;
17584 }
17585
17586
17587
17588
17589
17590
17591 static void
17592 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17593 {
17594 struct buffer *b = XBUFFER (w->contents);
17595 #ifdef HAVE_TEXT_CONVERSION
17596 ptrdiff_t prev_point, prev_mark;
17597 #endif
17598
17599 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17600 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17601 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17602
17603 if (accurate_p)
17604 {
17605 b->clip_changed = false;
17606 b->prevent_redisplay_optimizations_p = false;
17607 eassert (buffer_window_count (b) > 0);
17608
17609
17610
17611 b->text->redisplay = false;
17612
17613 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17614 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17615 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17616 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17617
17618 w->current_matrix->buffer = b;
17619 w->current_matrix->begv = BUF_BEGV (b);
17620 w->current_matrix->zv = BUF_ZV (b);
17621 w->current_matrix->header_line_p = window_wants_header_line (w);
17622 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17623
17624 w->last_cursor_vpos = w->cursor.vpos;
17625 w->last_cursor_off_p = w->cursor_off_p;
17626
17627 #ifdef HAVE_TEXT_CONVERSION
17628 prev_point = w->last_point;
17629 prev_mark = w->last_mark;
17630 #endif
17631
17632 if (w == XWINDOW (selected_window))
17633 w->last_point = BUF_PT (b);
17634 else
17635 w->last_point = marker_position (w->pointm);
17636
17637
17638
17639
17640
17641 if (XMARKER (BVAR (b, mark))->buffer == b
17642 && !NILP (BVAR (b, mark_active)))
17643 w->last_mark = marker_position (BVAR (b, mark));
17644 else
17645 w->last_mark = -1;
17646
17647 #ifdef HAVE_TEXT_CONVERSION
17648
17649 w->ephemeral_last_point = w->last_point;
17650
17651
17652
17653
17654
17655
17656
17657
17658
17659
17660
17661
17662
17663
17664
17665 if ((prev_point != w->last_point
17666 || prev_mark != w->last_mark)
17667 && FRAME_WINDOW_P (WINDOW_XFRAME (w))
17668 && w == XWINDOW (WINDOW_XFRAME (w)->selected_window))
17669 report_point_change (WINDOW_XFRAME (w), w, b);
17670 #endif
17671
17672 struct glyph_row *row;
17673
17674 if (w->window_end_vpos < w->current_matrix->nrows
17675 && ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
17676 !row->enabled_p
17677 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
17678 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0)))
17679 w->window_end_valid = true;
17680 w->update_mode_line = false;
17681 w->preserve_vscroll_p = false;
17682 }
17683
17684 w->redisplay = !accurate_p;
17685 }
17686
17687
17688
17689
17690
17691
17692
17693 void
17694 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17695 {
17696 struct window *w;
17697
17698 for (; !NILP (window); window = w->next)
17699 {
17700 w = XWINDOW (window);
17701 if (WINDOWP (w->contents))
17702 mark_window_display_accurate (w->contents, accurate_p);
17703 else
17704 mark_window_display_accurate_1 (w, accurate_p);
17705 }
17706
17707 if (accurate_p)
17708 update_overlay_arrows (1);
17709 else
17710
17711
17712
17713 update_overlay_arrows (-1);
17714 }
17715
17716
17717
17718
17719
17720
17721
17722 Lisp_Object
17723 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17724 {
17725 Lisp_Object val;
17726
17727 if (ASCII_CHAR_P (c))
17728 {
17729 val = dp->ascii;
17730 if (SUB_CHAR_TABLE_P (val))
17731 val = XSUB_CHAR_TABLE (val)->contents[c];
17732 }
17733 else
17734 {
17735 Lisp_Object table;
17736
17737 XSETCHAR_TABLE (table, dp);
17738 val = char_table_ref (table, c);
17739 }
17740 if (NILP (val))
17741 val = dp->defalt;
17742 return val;
17743 }
17744
17745 static int buffer_flip_blocked_depth;
17746
17747 static void
17748 block_buffer_flips (void)
17749 {
17750 eassert (buffer_flip_blocked_depth >= 0);
17751 buffer_flip_blocked_depth++;
17752 }
17753
17754 static void
17755 unblock_buffer_flips (void)
17756 {
17757 eassert (buffer_flip_blocked_depth > 0);
17758 if (--buffer_flip_blocked_depth == 0)
17759 {
17760 Lisp_Object tail, frame;
17761 block_input ();
17762 FOR_EACH_FRAME (tail, frame)
17763 {
17764 struct frame *f = XFRAME (frame);
17765 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17766 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17767 }
17768 unblock_input ();
17769 }
17770 }
17771
17772 bool
17773 buffer_flipping_blocked_p (void)
17774 {
17775 return buffer_flip_blocked_depth > 0;
17776 }
17777
17778
17779
17780
17781
17782
17783
17784
17785 static void
17786 redisplay_windows (Lisp_Object window)
17787 {
17788 while (!NILP (window))
17789 {
17790 struct window *w = XWINDOW (window);
17791
17792 if (WINDOWP (w->contents))
17793 redisplay_windows (w->contents);
17794 else if (BUFFERP (w->contents))
17795 {
17796 displayed_buffer = XBUFFER (w->contents);
17797
17798
17799 internal_condition_case_1 (redisplay_window_0, window,
17800 list_of_error,
17801 redisplay_window_error);
17802 }
17803
17804 window = w->next;
17805 }
17806 }
17807
17808 static Lisp_Object
17809 redisplay_window_error (Lisp_Object error_data)
17810 {
17811 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17812
17813
17814
17815 if (max_redisplay_ticks > 0
17816 && CONSP (error_data)
17817 && EQ (XCAR (error_data), Qerror)
17818 && CONSP (XCDR (error_data))
17819 && STRINGP (XCAR (XCDR (error_data))))
17820 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17821 XCAR (XCDR (error_data))),
17822 Vdelayed_warnings_list);
17823 return Qnil;
17824 }
17825
17826 static Lisp_Object
17827 redisplay_window_0 (Lisp_Object window)
17828 {
17829 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17830 redisplay_window (window, false);
17831 return Qnil;
17832 }
17833
17834 static Lisp_Object
17835 redisplay_window_1 (Lisp_Object window)
17836 {
17837 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17838 redisplay_window (window, true);
17839 return Qnil;
17840 }
17841
17842
17843
17844
17845
17846
17847
17848
17849
17850
17851
17852
17853
17854
17855
17856
17857
17858
17859
17860 void
17861 update_redisplay_ticks (int ticks, struct window *w)
17862 {
17863
17864 static struct window *cwindow;
17865 static EMACS_INT window_ticks;
17866
17867
17868
17869
17870 if (!ticks && w != cwindow)
17871 {
17872 cwindow = w;
17873 window_ticks = 0;
17874 }
17875
17876
17877 if ((!w && !redisplaying_p && !display_working_on_window_p)
17878
17879
17880 || (w && MINI_WINDOW_P (w)))
17881 return;
17882
17883 if (ticks > 0)
17884 window_ticks += ticks;
17885 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17886 {
17887
17888
17889
17890 Lisp_Object contents = w ? w->contents : Qnil;
17891 char *bufname =
17892 NILP (contents)
17893 ? SSDATA (BVAR (current_buffer, name))
17894 : (BUFFERP (contents)
17895 ? SSDATA (BVAR (XBUFFER (contents), name))
17896 : (char *) "<unknown>");
17897
17898 windows_or_buffers_changed = 177;
17899
17900
17901
17902 if (w && w->desired_matrix)
17903 w->desired_matrix->no_scrolling_p = true;
17904 error ("Window showing buffer %s takes too long to redisplay", bufname);
17905 }
17906 }
17907
17908
17909
17910
17911
17912
17913
17914
17915
17916
17917 static bool
17918 set_cursor_from_row (struct window *w, struct glyph_row *row,
17919 struct glyph_matrix *matrix,
17920 ptrdiff_t delta, ptrdiff_t delta_bytes,
17921 int dy, int dvpos)
17922 {
17923 struct glyph *glyph = row->glyphs[TEXT_AREA];
17924 struct glyph *end = glyph + row->used[TEXT_AREA];
17925 struct glyph *cursor = NULL;
17926
17927 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17928 int x = row->x;
17929 ptrdiff_t pt_old = PT - delta;
17930 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17931 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17932 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17933
17934
17935 struct glyph *glyphs_end = end;
17936
17937
17938 bool match_with_avoid_cursor = false;
17939
17940
17941 bool string_seen = false;
17942
17943
17944 ptrdiff_t bpos_max = pos_before;
17945 ptrdiff_t bpos_min = pos_after;
17946
17947
17948 ptrdiff_t bpos_covered = 0;
17949
17950
17951 bool string_from_text_prop = false;
17952
17953
17954
17955
17956 eassert (!row->mode_line_p);
17957 if (row->mode_line_p)
17958 return false;
17959
17960
17961
17962
17963 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17964 {
17965 if (!row->reversed_p)
17966 {
17967 while (glyph < end
17968 && NILP (glyph->object)
17969 && glyph->charpos < 0)
17970 {
17971 x += glyph->pixel_width;
17972 ++glyph;
17973 }
17974 while (end > glyph
17975 && NILP ((end - 1)->object)
17976
17977
17978 && (end - 1)->charpos <= 0)
17979 --end;
17980 glyph_before = glyph - 1;
17981 glyph_after = end;
17982 }
17983 else
17984 {
17985 struct glyph *g;
17986
17987
17988
17989 glyphs_end = end = glyph - 1;
17990 glyph += row->used[TEXT_AREA] - 1;
17991
17992 while (glyph > end + 1
17993 && NILP (glyph->object)
17994 && glyph->charpos < 0)
17995 --glyph;
17996 if (NILP (glyph->object) && glyph->charpos < 0)
17997 --glyph;
17998
17999
18000 for (x = 0, g = end + 1; g < glyph; g++)
18001 x += g->pixel_width;
18002 while (end < glyph
18003 && NILP ((end + 1)->object)
18004 && (end + 1)->charpos <= 0)
18005 ++end;
18006 glyph_before = glyph + 1;
18007 glyph_after = end;
18008 }
18009 }
18010 else if (row->reversed_p)
18011 {
18012
18013
18014
18015 cursor = end - 1;
18016
18017
18018
18019 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
18020 && !WINDOW_RIGHTMOST_P (w)
18021 && cursor == row->glyphs[LAST_AREA] - 1)
18022 cursor--;
18023 x = -1;
18024 }
18025
18026
18027
18028
18029
18030 if (!row->reversed_p)
18031 while (
18032 glyph < end
18033
18034 && !NILP (glyph->object))
18035 {
18036 if (BUFFERP (glyph->object))
18037 {
18038 ptrdiff_t dpos = glyph->charpos - pt_old;
18039
18040 if (glyph->charpos > bpos_max)
18041 bpos_max = glyph->charpos;
18042 if (glyph->charpos < bpos_min)
18043 bpos_min = glyph->charpos;
18044 if (!glyph->avoid_cursor_p)
18045 {
18046
18047
18048 if (dpos == 0)
18049 {
18050 match_with_avoid_cursor = false;
18051 break;
18052 }
18053
18054
18055 if (0 > dpos && dpos > pos_before - pt_old)
18056 {
18057 pos_before = glyph->charpos;
18058 glyph_before = glyph;
18059 }
18060 else if (0 < dpos && dpos < pos_after - pt_old)
18061 {
18062 pos_after = glyph->charpos;
18063 glyph_after = glyph;
18064 }
18065 }
18066 else if (dpos == 0)
18067 match_with_avoid_cursor = true;
18068 }
18069 else if (STRINGP (glyph->object))
18070 {
18071 Lisp_Object chprop;
18072 ptrdiff_t glyph_pos = glyph->charpos;
18073
18074 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18075 glyph->object);
18076 if (!NILP (chprop))
18077 {
18078
18079
18080
18081
18082
18083
18084
18085
18086
18087
18088 ptrdiff_t prop_pos =
18089 string_buffer_position_lim (glyph->object, pos_before,
18090 pos_after, false);
18091
18092 if (prop_pos >= pos_before)
18093 bpos_max = prop_pos;
18094 }
18095 if (FIXNUMP (chprop))
18096 {
18097 bpos_covered = bpos_max + XFIXNUM (chprop);
18098
18099
18100
18101
18102
18103
18104
18105
18106
18107
18108
18109 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18110 {
18111 cursor = glyph;
18112 break;
18113 }
18114 }
18115
18116 string_seen = true;
18117 }
18118 x += glyph->pixel_width;
18119 ++glyph;
18120 }
18121 else if (glyph > end)
18122 while (!NILP (glyph->object))
18123 {
18124 if (BUFFERP (glyph->object))
18125 {
18126 ptrdiff_t dpos = glyph->charpos - pt_old;
18127
18128 if (glyph->charpos > bpos_max)
18129 bpos_max = glyph->charpos;
18130 if (glyph->charpos < bpos_min)
18131 bpos_min = glyph->charpos;
18132 if (!glyph->avoid_cursor_p)
18133 {
18134 if (dpos == 0)
18135 {
18136 match_with_avoid_cursor = false;
18137 break;
18138 }
18139 if (0 > dpos && dpos > pos_before - pt_old)
18140 {
18141 pos_before = glyph->charpos;
18142 glyph_before = glyph;
18143 }
18144 else if (0 < dpos && dpos < pos_after - pt_old)
18145 {
18146 pos_after = glyph->charpos;
18147 glyph_after = glyph;
18148 }
18149 }
18150 else if (dpos == 0)
18151 match_with_avoid_cursor = true;
18152 }
18153 else if (STRINGP (glyph->object))
18154 {
18155 Lisp_Object chprop;
18156 ptrdiff_t glyph_pos = glyph->charpos;
18157
18158 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18159 glyph->object);
18160 if (!NILP (chprop))
18161 {
18162 ptrdiff_t prop_pos =
18163 string_buffer_position_lim (glyph->object, pos_before,
18164 pos_after, false);
18165
18166 if (prop_pos >= pos_before)
18167 bpos_max = prop_pos;
18168 }
18169 if (FIXNUMP (chprop))
18170 {
18171 bpos_covered = bpos_max + XFIXNUM (chprop);
18172
18173
18174
18175 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18176 {
18177 cursor = glyph;
18178 break;
18179 }
18180 }
18181 string_seen = true;
18182 }
18183 --glyph;
18184 if (glyph == glyphs_end)
18185 {
18186 x--;
18187 break;
18188 }
18189 x -= glyph->pixel_width;
18190 }
18191
18192
18193
18194
18195 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18196 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
18197 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
18198 {
18199
18200
18201
18202
18203
18204 bool empty_line_p =
18205 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18206 && NILP (glyph->object) && glyph->charpos > 0
18207
18208
18209
18210
18211 && !(row->continued_p || row->truncated_on_right_p));
18212
18213 if (row->ends_in_ellipsis_p && pos_after == last_pos)
18214 {
18215 ptrdiff_t ellipsis_pos;
18216
18217
18218 if (!row->reversed_p)
18219 {
18220 ellipsis_pos = (glyph - 1)->charpos;
18221 while (glyph > row->glyphs[TEXT_AREA]
18222 && (glyph - 1)->charpos == ellipsis_pos)
18223 glyph--, x -= glyph->pixel_width;
18224
18225
18226
18227 x += glyph->pixel_width;
18228 glyph++;
18229 }
18230 else
18231 {
18232 ellipsis_pos = (glyph + 1)->charpos;
18233 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18234 && (glyph + 1)->charpos == ellipsis_pos)
18235 glyph++, x += glyph->pixel_width;
18236 x -= glyph->pixel_width;
18237 glyph--;
18238 }
18239 }
18240 else if (match_with_avoid_cursor)
18241 {
18242 cursor = glyph_after;
18243 x = -1;
18244 }
18245 else if (string_seen)
18246 {
18247 int incr = row->reversed_p ? -1 : +1;
18248
18249
18250
18251
18252
18253
18254 struct glyph *start, *stop;
18255 ptrdiff_t pos = pos_before;
18256
18257 x = -1;
18258
18259
18260
18261
18262
18263
18264 if (row->ends_in_newline_from_string_p)
18265 {
18266 glyph_after = end;
18267 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18268 }
18269
18270
18271
18272
18273
18274
18275
18276
18277
18278 if (!row->reversed_p)
18279 {
18280 start = min (glyph_before, glyph_after);
18281 stop = max (glyph_before, glyph_after);
18282 }
18283 else
18284 {
18285 start = max (glyph_before, glyph_after);
18286 stop = min (glyph_before, glyph_after);
18287 }
18288 for (glyph = start + incr;
18289 row->reversed_p ? glyph > stop : glyph < stop; )
18290 {
18291
18292
18293
18294
18295 if (STRINGP (glyph->object))
18296 {
18297 Lisp_Object str;
18298 ptrdiff_t tem;
18299
18300
18301 ptrdiff_t lim = pos_after
18302 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18303
18304 string_from_text_prop = false;
18305 str = glyph->object;
18306 tem = string_buffer_position_lim (str, pos, lim, false);
18307 if (tem == 0
18308 || pos <= tem)
18309 {
18310
18311
18312
18313
18314
18315
18316
18317
18318
18319
18320 if (tem == 0
18321 || tem == pt_old
18322 || (tem - pt_old > 0 && tem < pos_after))
18323 {
18324
18325
18326
18327
18328
18329
18330 ptrdiff_t strpos = glyph->charpos;
18331
18332 if (tem)
18333 {
18334 cursor = glyph;
18335 string_from_text_prop = true;
18336 }
18337 for ( ;
18338 (row->reversed_p ? glyph > stop : glyph < stop)
18339 && EQ (glyph->object, str);
18340 glyph += incr)
18341 {
18342 Lisp_Object cprop;
18343 ptrdiff_t gpos = glyph->charpos;
18344
18345 cprop = Fget_char_property (make_fixnum (gpos),
18346 Qcursor,
18347 glyph->object);
18348 if (!NILP (cprop))
18349 {
18350 cursor = glyph;
18351 break;
18352 }
18353 if (tem && glyph->charpos < strpos)
18354 {
18355 strpos = glyph->charpos;
18356 cursor = glyph;
18357 }
18358 }
18359
18360 if (tem == pt_old
18361 || (tem - pt_old > 0 && tem < pos_after))
18362 goto compute_x;
18363 }
18364 if (tem)
18365 pos = tem + 1;
18366 }
18367
18368
18369 while ((row->reversed_p ? glyph > stop : glyph < stop)
18370 && EQ (glyph->object, str))
18371 glyph += incr;
18372 }
18373 else
18374 glyph += incr;
18375 }
18376
18377
18378
18379 if (cursor == NULL
18380 && (row->reversed_p ? glyph <= end : glyph >= end)
18381 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18382 && STRINGP (end->object)
18383 && row->continued_p)
18384 return false;
18385 }
18386
18387
18388
18389
18390
18391 else if (row->truncated_on_left_p && pt_old < bpos_min)
18392 {
18393 cursor = glyph_before;
18394 x = -1;
18395 }
18396 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18397
18398 || (!empty_line_p
18399 && (row->reversed_p
18400 ? glyph_after > glyphs_end
18401 : glyph_after < glyphs_end)))
18402 {
18403 cursor = glyph_after;
18404 x = -1;
18405 }
18406 }
18407
18408 compute_x:
18409 if (cursor != NULL)
18410 glyph = cursor;
18411 else if (glyph == glyphs_end
18412 && pos_before == pos_after
18413 && STRINGP ((row->reversed_p
18414 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18415 : row->glyphs[TEXT_AREA])->object))
18416 {
18417
18418
18419
18420
18421 glyph =
18422 row->reversed_p
18423 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18424 : row->glyphs[TEXT_AREA];
18425 }
18426 if (x < 0)
18427 {
18428 struct glyph *g;
18429
18430
18431 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18432 {
18433 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18434 emacs_abort ();
18435 x += g->pixel_width;
18436 }
18437 }
18438
18439
18440
18441
18442
18443
18444 if (
18445 w->cursor.vpos >= 0
18446
18447 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18448
18449
18450
18451
18452
18453 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18454 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18455 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18456 {
18457 struct glyph *g1
18458 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18459
18460
18461 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18462 return false;
18463
18464
18465 if (
18466 w->cursor.hpos >= 0
18467 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18468 && ((BUFFERP (g1->object)
18469 && (g1->charpos == pt_old
18470 || (BUFFERP (glyph->object)
18471 && eabs (g1->charpos - pt_old)
18472 < eabs (glyph->charpos - pt_old))))
18473
18474
18475 || (STRINGP (g1->object)
18476 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18477 Qcursor, g1->object))
18478
18479
18480
18481 || (EQ (g1->object, glyph->object)
18482 && string_from_text_prop)
18483
18484
18485 || (NILP (glyph->object)
18486 && glyph->charpos != pt_old)))))
18487 return false;
18488
18489 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18490
18491
18492
18493 || (!row->continued_p
18494 && NILP (glyph->object)
18495 && glyph->charpos == 0
18496 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18497
18498
18499
18500
18501
18502 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18503 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18504 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18505 return false;
18506 }
18507 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18508 w->cursor.x = x;
18509 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18510 w->cursor.y = row->y + dy;
18511
18512 if (w == XWINDOW (selected_window))
18513 {
18514 if (!row->continued_p
18515 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18516 && row->x == 0)
18517 {
18518 this_line_buffer = XBUFFER (w->contents);
18519
18520 CHARPOS (this_line_start_pos)
18521 = MATRIX_ROW_START_CHARPOS (row) + delta;
18522 BYTEPOS (this_line_start_pos)
18523 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18524
18525 CHARPOS (this_line_end_pos)
18526 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18527 BYTEPOS (this_line_end_pos)
18528 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18529
18530 this_line_y = w->cursor.y;
18531 this_line_pixel_height = row->height;
18532 this_line_vpos = w->cursor.vpos;
18533 this_line_start_x = row->x;
18534 }
18535 else
18536 CHARPOS (this_line_start_pos) = 0;
18537 }
18538
18539 return true;
18540 }
18541
18542
18543
18544
18545
18546
18547
18548 static struct text_pos
18549 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18550 {
18551 struct window *w = XWINDOW (window);
18552 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18553
18554 eassert (current_buffer == XBUFFER (w->contents));
18555
18556 if (!NILP (Vwindow_scroll_functions))
18557 {
18558 specpdl_ref count = SPECPDL_INDEX ();
18559 specbind (Qinhibit_quit, Qt);
18560 safe_run_hooks_2
18561 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18562 unbind_to (count, Qnil);
18563 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18564
18565 set_buffer_internal (XBUFFER (w->contents));
18566 }
18567
18568 return startp;
18569 }
18570
18571
18572
18573
18574
18575
18576
18577
18578
18579
18580
18581
18582
18583
18584
18585
18586
18587
18588
18589
18590
18591
18592 static bool
18593 cursor_row_fully_visible_p (struct window *w, bool force_p,
18594 bool current_matrix_p,
18595 bool just_test_user_preference_p)
18596 {
18597 struct glyph_matrix *matrix;
18598 struct glyph_row *row;
18599 int window_height;
18600 Lisp_Object mclfv_p =
18601 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18602
18603
18604 if (BASE_EQ (mclfv_p, Qunbound))
18605 mclfv_p = Vmake_cursor_line_fully_visible;
18606
18607
18608 if (FUNCTIONP (mclfv_p))
18609 {
18610 Lisp_Object window;
18611 XSETWINDOW (window, w);
18612
18613
18614 Lisp_Object val = safe_call1 (mclfv_p, window);
18615 if (NILP (val))
18616 return true;
18617 else if (just_test_user_preference_p)
18618 return false;
18619 }
18620 else if (NILP (mclfv_p))
18621 return true;
18622 else if (just_test_user_preference_p)
18623 return false;
18624
18625
18626
18627 if (w->cursor.vpos < 0)
18628 return true;
18629
18630 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18631 row = MATRIX_ROW (matrix, w->cursor.vpos);
18632
18633
18634 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18635 return true;
18636
18637
18638
18639 window_height = window_box_height (w);
18640 if (row->height >= window_height)
18641 {
18642 if (!force_p || MINI_WINDOW_P (w)
18643 || w->vscroll || w->cursor.vpos == 0)
18644 return true;
18645 }
18646 return false;
18647 }
18648
18649
18650
18651
18652
18653
18654
18655
18656
18657
18658
18659
18660
18661
18662
18663
18664
18665
18666
18667
18668 enum
18669 {
18670 SCROLLING_SUCCESS = 1,
18671 SCROLLING_FAILED = 0,
18672 SCROLLING_NEED_LARGER_MATRICES = -1
18673 };
18674
18675
18676
18677
18678
18679 #define SCROLL_LIMIT 100
18680
18681 static int
18682 try_scrolling (Lisp_Object window, bool just_this_one_p,
18683 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18684 bool temp_scroll_step, bool last_line_misfit)
18685 {
18686 struct window *w = XWINDOW (window);
18687 struct text_pos pos, startp;
18688 struct it it;
18689 int this_scroll_margin, scroll_max, rc, height;
18690 int dy = 0, amount_to_scroll = 0;
18691 bool scroll_down_p = false;
18692 int extra_scroll_margin_lines = last_line_misfit;
18693 Lisp_Object aggressive;
18694
18695 int scroll_limit = SCROLL_LIMIT;
18696 int frame_line_height = default_line_pixel_height (w);
18697
18698 #ifdef GLYPH_DEBUG
18699 debug_method_add (w, "try_scrolling");
18700 #endif
18701
18702 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18703
18704 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18705
18706
18707
18708
18709
18710 if (arg_scroll_conservatively > scroll_limit)
18711 {
18712 arg_scroll_conservatively = scroll_limit + 1;
18713 scroll_max = scroll_limit * frame_line_height;
18714 }
18715 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18716
18717
18718 {
18719 intmax_t scroll_lines_max
18720 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18721 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18722 scroll_max = scroll_lines * frame_line_height;
18723 }
18724 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18725 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18726
18727
18728 scroll_max = 10 * frame_line_height;
18729 else
18730 scroll_max = 0;
18731
18732 too_near_end:
18733
18734
18735 if (PT > CHARPOS (startp))
18736 {
18737 int scroll_margin_y;
18738
18739
18740
18741 start_display (&it, w, startp);
18742 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18743 - this_scroll_margin
18744 - frame_line_height * extra_scroll_margin_lines;
18745 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18746 (MOVE_TO_POS | MOVE_TO_Y));
18747
18748 if (PT > CHARPOS (it.current.pos))
18749 {
18750 int y0 = line_bottom_y (&it);
18751
18752
18753
18754
18755
18756 int slack = max (scroll_max, 10 * frame_line_height);
18757 int y_to_move = it.last_visible_y + slack;
18758
18759
18760
18761
18762
18763 move_it_to (&it, PT, -1, y_to_move,
18764 -1, MOVE_TO_POS | MOVE_TO_Y);
18765 dy = line_bottom_y (&it) - y0;
18766
18767 if (dy > scroll_max)
18768 return SCROLLING_FAILED;
18769
18770 if (dy > 0)
18771 scroll_down_p = true;
18772 }
18773 else if (PT == IT_CHARPOS (it)
18774 && IT_CHARPOS (it) < ZV
18775 && it.method == GET_FROM_STRING
18776 && arg_scroll_conservatively > scroll_limit
18777 && it.current_x == 0)
18778 {
18779 enum move_it_result skip;
18780 int y1 = it.current_y;
18781 int vpos;
18782
18783
18784
18785
18786
18787
18788
18789 do {
18790 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18791 if (skip != MOVE_NEWLINE_OR_CR
18792 || IT_CHARPOS (it) != PT
18793 || it.method == GET_FROM_BUFFER)
18794 break;
18795 vpos = it.vpos;
18796 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18797 } while (it.vpos > vpos);
18798
18799 dy = it.current_y - y1;
18800
18801 if (dy > scroll_max)
18802 return SCROLLING_FAILED;
18803
18804 if (dy > 0)
18805 scroll_down_p = true;
18806 }
18807 }
18808
18809 if (scroll_down_p)
18810 {
18811
18812
18813
18814
18815 if (arg_scroll_conservatively)
18816 amount_to_scroll
18817 = min (max (dy, frame_line_height),
18818 frame_line_height * arg_scroll_conservatively);
18819 else if (scroll_step || temp_scroll_step)
18820 amount_to_scroll = scroll_max;
18821 else
18822 {
18823 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18824 height = WINDOW_BOX_TEXT_HEIGHT (w);
18825 if (NUMBERP (aggressive))
18826 {
18827 double float_amount = XFLOATINT (aggressive) * height;
18828 int aggressive_scroll = float_amount;
18829 if (aggressive_scroll == 0 && float_amount > 0)
18830 aggressive_scroll = 1;
18831
18832
18833
18834
18835
18836
18837 if (aggressive_scroll + 2 * this_scroll_margin > height)
18838 aggressive_scroll = height - 2 * this_scroll_margin;
18839 amount_to_scroll = dy + aggressive_scroll;
18840 }
18841 }
18842
18843 if (amount_to_scroll <= 0)
18844 return SCROLLING_FAILED;
18845
18846 start_display (&it, w, startp);
18847 if (arg_scroll_conservatively <= scroll_limit)
18848 move_it_vertically (&it, amount_to_scroll);
18849 else
18850 {
18851
18852
18853
18854
18855
18856
18857 struct it it1;
18858 void *it1data = NULL;
18859
18860
18861 int start_y;
18862
18863 SAVE_IT (it1, it, it1data);
18864 start_y = line_bottom_y (&it1);
18865 do {
18866 RESTORE_IT (&it, &it, it1data);
18867 move_it_by_lines (&it, 1);
18868 SAVE_IT (it1, it, it1data);
18869 } while (IT_CHARPOS (it) < ZV
18870 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18871 bidi_unshelve_cache (it1data, true);
18872 }
18873
18874
18875 if (IT_CHARPOS (it) == CHARPOS (startp))
18876 move_it_by_lines (&it, 1);
18877 startp = it.current.pos;
18878 }
18879 else
18880 {
18881 struct text_pos scroll_margin_pos = startp;
18882 int y_offset = 0;
18883
18884
18885
18886 if (this_scroll_margin)
18887 {
18888 int y_start;
18889
18890 start_display (&it, w, startp);
18891 y_start = it.current_y;
18892 move_it_vertically (&it, this_scroll_margin);
18893 scroll_margin_pos = it.current.pos;
18894
18895
18896
18897 if (IT_CHARPOS (it) == ZV
18898 && it.current_y - y_start < this_scroll_margin)
18899 y_offset = this_scroll_margin - (it.current_y - y_start);
18900 }
18901
18902 if (PT < CHARPOS (scroll_margin_pos))
18903 {
18904
18905
18906 int y0, y_to_move;
18907
18908
18909
18910
18911
18912
18913 SET_TEXT_POS (pos, PT, PT_BYTE);
18914 start_display (&it, w, pos);
18915 y0 = it.current_y;
18916 y_to_move = max (it.last_visible_y,
18917 max (scroll_max, 10 * frame_line_height));
18918 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18919 y_to_move, -1,
18920 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18921 dy = it.current_y - y0;
18922 if (dy > scroll_max
18923 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18924 return SCROLLING_FAILED;
18925
18926
18927 dy += y_offset;
18928
18929
18930 start_display (&it, w, startp);
18931
18932 if (arg_scroll_conservatively)
18933 amount_to_scroll
18934 = min (max (dy, frame_line_height),
18935 frame_line_height * arg_scroll_conservatively);
18936 else if (scroll_step || temp_scroll_step)
18937 amount_to_scroll = scroll_max;
18938 else
18939 {
18940 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18941 height = WINDOW_BOX_TEXT_HEIGHT (w);
18942 if (NUMBERP (aggressive))
18943 {
18944 double float_amount = XFLOATINT (aggressive) * height;
18945 int aggressive_scroll = float_amount;
18946 if (aggressive_scroll == 0 && float_amount > 0)
18947 aggressive_scroll = 1;
18948
18949
18950
18951
18952 if (aggressive_scroll + 2 * this_scroll_margin > height)
18953 aggressive_scroll = height - 2 * this_scroll_margin;
18954 amount_to_scroll = dy + aggressive_scroll;
18955 }
18956 }
18957
18958 if (amount_to_scroll <= 0)
18959 return SCROLLING_FAILED;
18960
18961 move_it_vertically_backward (&it, amount_to_scroll);
18962 startp = it.current.pos;
18963 }
18964 }
18965
18966
18967 startp = run_window_scroll_functions (window, startp);
18968
18969
18970
18971 if (!try_window (window, startp, 0))
18972 rc = SCROLLING_NEED_LARGER_MATRICES;
18973 else if (w->cursor.vpos < 0)
18974 {
18975 clear_glyph_matrix (w->desired_matrix);
18976 rc = SCROLLING_FAILED;
18977 }
18978 else
18979 {
18980
18981 if (!just_this_one_p
18982 || current_buffer->clip_changed
18983 || BEG_UNCHANGED < CHARPOS (startp))
18984 w->base_line_number = 0;
18985
18986
18987
18988 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18989 false, false)
18990
18991
18992
18993 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18994 {
18995 clear_glyph_matrix (w->desired_matrix);
18996 ++extra_scroll_margin_lines;
18997 goto too_near_end;
18998 }
18999 rc = SCROLLING_SUCCESS;
19000 }
19001
19002 return rc;
19003 }
19004
19005
19006
19007
19008
19009
19010
19011
19012
19013
19014
19015
19016 static bool
19017 compute_window_start_on_continuation_line (struct window *w)
19018 {
19019 struct text_pos pos, start_pos, pos_before_pt;
19020 bool window_start_changed_p = false;
19021
19022 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19023
19024
19025
19026
19027 if (CHARPOS (start_pos) > BEGV
19028 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
19029 {
19030 struct it it;
19031 struct glyph_row *row;
19032
19033
19034 if (CHARPOS (start_pos) < BEGV)
19035 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
19036 else if (CHARPOS (start_pos) > ZV)
19037 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
19038
19039
19040
19041 row = w->desired_matrix->rows + window_wants_tab_line (w)
19042 + window_wants_header_line (w);
19043 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
19044 row, DEFAULT_FACE_ID);
19045 reseat_at_previous_visible_line_start (&it);
19046
19047
19048
19049
19050
19051
19052
19053 if (IT_CHARPOS (it) <= PT
19054 && (CHARPOS (start_pos) - IT_CHARPOS (it)
19055
19056 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
19057 {
19058 int min_distance, distance;
19059
19060
19061
19062
19063
19064
19065
19066 pos_before_pt = pos = it.current.pos;
19067 min_distance = DISP_INFINITY;
19068 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
19069 distance < min_distance)
19070 {
19071 min_distance = distance;
19072 if (CHARPOS (pos) <= PT)
19073 pos_before_pt = pos;
19074 pos = it.current.pos;
19075 if (it.line_wrap == WORD_WRAP)
19076 {
19077
19078
19079
19080
19081
19082
19083
19084
19085
19086 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
19087 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19088 move_it_to (&it, ZV, 0,
19089 it.current_y + it.max_ascent + it.max_descent, -1,
19090 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19091 }
19092 else
19093 move_it_by_lines (&it, 1);
19094 }
19095
19096
19097
19098
19099
19100 if (CHARPOS (pos) > PT)
19101 pos = pos_before_pt;
19102
19103
19104 SET_MARKER_FROM_TEXT_POS (w->start, pos);
19105 window_start_changed_p = true;
19106 }
19107 }
19108
19109 return window_start_changed_p;
19110 }
19111
19112
19113
19114
19115
19116
19117
19118
19119
19120
19121
19122
19123
19124
19125
19126
19127
19128 enum
19129 {
19130 CURSOR_MOVEMENT_SUCCESS,
19131 CURSOR_MOVEMENT_CANNOT_BE_USED,
19132 CURSOR_MOVEMENT_MUST_SCROLL,
19133 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
19134 };
19135
19136 static int
19137 try_cursor_movement (Lisp_Object window, struct text_pos startp,
19138 bool *scroll_step)
19139 {
19140 struct window *w = XWINDOW (window);
19141 struct frame *f = XFRAME (w->frame);
19142 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
19143
19144 #ifdef GLYPH_DEBUG
19145 if (inhibit_try_cursor_movement)
19146 return rc;
19147 #endif
19148
19149
19150
19151
19152 eassert (w->last_point > 0);
19153
19154
19155
19156 eassert (!w->window_end_valid
19157 || w->window_end_vpos < w->current_matrix->nrows);
19158
19159
19160
19161 if (
19162 PT >= CHARPOS (startp)
19163
19164 && !current_buffer->clip_changed
19165
19166
19167
19168
19169 && !update_mode_lines
19170 && !windows_or_buffers_changed
19171 && !f->cursor_type_changed
19172 && NILP (Vshow_trailing_whitespace)
19173
19174
19175 && !EQ (Vdisplay_line_numbers, Qrelative)
19176 && !EQ (Vdisplay_line_numbers, Qvisual)
19177
19178
19179
19180 && !(!NILP (Vdisplay_line_numbers)
19181 && NILP (Finternal_lisp_face_equal_p (Qline_number,
19182 Qline_number_current_line,
19183 w->frame)))
19184
19185
19186
19187
19188
19189
19190 && !EQ (window, minibuf_window)
19191
19192
19193
19194 && !overlay_arrow_in_current_buffer_p ())
19195 {
19196 int this_scroll_margin, top_scroll_margin;
19197 struct glyph_row *row = NULL;
19198
19199 #ifdef GLYPH_DEBUG
19200 debug_method_add (w, "cursor movement");
19201 #endif
19202
19203 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
19204
19205 top_scroll_margin = this_scroll_margin;
19206 if (window_wants_tab_line (w))
19207 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
19208 if (window_wants_header_line (w))
19209 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
19210
19211
19212
19213 if (w->last_cursor_vpos < 0
19214 || w->last_cursor_vpos >= w->current_matrix->nrows)
19215 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19216 else
19217 {
19218 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
19219
19220 if (row->tab_line_p)
19221 ++row;
19222 if (row->mode_line_p)
19223 ++row;
19224 if (!row->enabled_p)
19225 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19226 }
19227
19228 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
19229 {
19230 bool scroll_p = false, must_scroll = false;
19231 int last_y = window_text_bottom_y (w) - this_scroll_margin;
19232
19233 if (PT > w->last_point)
19234 {
19235
19236 while (MATRIX_ROW_END_CHARPOS (row) < PT
19237 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19238 {
19239 eassert (row->enabled_p);
19240 ++row;
19241 }
19242
19243
19244
19245
19246 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19247 && MATRIX_ROW_END_CHARPOS (row) == PT
19248 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
19249 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19250 && !cursor_row_p (row))
19251 ++row;
19252
19253
19254
19255
19256
19257 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19258 || PT > MATRIX_ROW_END_CHARPOS (row)
19259
19260
19261 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19262 && PT == MATRIX_ROW_END_CHARPOS (row)
19263 && !row->ends_at_zv_p
19264 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19265 scroll_p = true;
19266 }
19267 else if (PT < w->last_point)
19268 {
19269
19270
19271 struct glyph_row *row0 = row;
19272
19273 while (!row->mode_line_p
19274 && (MATRIX_ROW_START_CHARPOS (row) > PT
19275 || (MATRIX_ROW_START_CHARPOS (row) == PT
19276 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19277 || (
19278 row > w->current_matrix->rows
19279 && (row-1)->ends_in_newline_from_string_p))))
19280 && (row->y > top_scroll_margin
19281 || CHARPOS (startp) == BEGV))
19282 {
19283 eassert (row->enabled_p);
19284 --row;
19285 }
19286
19287
19288
19289
19290
19291 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19292 && PT <= MATRIX_ROW_END_CHARPOS (row))
19293 && row0->continued_p)
19294 {
19295 row = row0;
19296 while (MATRIX_ROW_START_CHARPOS (row) > PT
19297 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19298 {
19299 eassert (row->enabled_p);
19300 ++row;
19301 }
19302 }
19303
19304
19305
19306
19307
19308
19309 if (row < w->current_matrix->rows
19310 || row->mode_line_p)
19311 {
19312 row = w->current_matrix->rows;
19313
19314 if (row->tab_line_p)
19315 ++row;
19316 if (row->mode_line_p)
19317 ++row;
19318 }
19319
19320
19321
19322 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19323 && MATRIX_ROW_END_CHARPOS (row) == PT
19324 && !cursor_row_p (row))
19325 ++row;
19326
19327
19328
19329 if ((row->y < top_scroll_margin
19330 && CHARPOS (startp) != BEGV)
19331 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19332 || PT > MATRIX_ROW_END_CHARPOS (row)
19333 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19334 && PT == MATRIX_ROW_END_CHARPOS (row)
19335 && !row->ends_at_zv_p
19336 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19337 scroll_p = true;
19338 }
19339 else
19340 {
19341
19342
19343 rc = CURSOR_MOVEMENT_SUCCESS;
19344 }
19345
19346 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19347 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19348
19349
19350 || (MATRIX_ROW_END_CHARPOS (row-1)
19351 == MATRIX_ROW_START_CHARPOS (row))))
19352 || PT > MATRIX_ROW_END_CHARPOS (row))
19353 {
19354
19355 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19356 must_scroll = true;
19357 }
19358 else if (rc != CURSOR_MOVEMENT_SUCCESS
19359 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19360 {
19361 struct glyph_row *row1;
19362
19363
19364
19365
19366
19367
19368
19369
19370
19371
19372
19373 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19374 MATRIX_ROW_CONTINUATION_LINE_P (row);
19375 --row)
19376 {
19377
19378
19379
19380 if (row <= row1)
19381 {
19382 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19383 break;
19384 }
19385 eassert (row->enabled_p);
19386 }
19387 }
19388 if (must_scroll)
19389 ;
19390 else if (rc != CURSOR_MOVEMENT_SUCCESS
19391 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19392
19393
19394
19395 && !row->mode_line_p
19396 && !cursor_row_fully_visible_p (w, true, true, true))
19397 {
19398 if (PT == MATRIX_ROW_END_CHARPOS (row)
19399 && !row->ends_at_zv_p
19400 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19401 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19402 else if (row->height > window_box_height (w))
19403 {
19404
19405
19406
19407
19408 *scroll_step = true;
19409 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19410 }
19411 else
19412 {
19413 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19414 if (!cursor_row_fully_visible_p (w, false, true, false))
19415 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19416 else
19417 rc = CURSOR_MOVEMENT_SUCCESS;
19418 }
19419 }
19420 else if (scroll_p)
19421 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19422 else if (rc != CURSOR_MOVEMENT_SUCCESS
19423 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19424 {
19425
19426
19427
19428
19429
19430
19431
19432 bool rv = false;
19433 bool pt_invis = false;
19434 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19435 Qinvisible,
19436 Qnil, NULL);
19437
19438 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19439 pt_invis = true;
19440
19441 do
19442 {
19443 bool at_zv_p = false, exact_match_p = false;
19444
19445
19446
19447
19448
19449 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19450 && PT <= MATRIX_ROW_END_CHARPOS (row)
19451 && cursor_row_p (row))
19452 rv |= set_cursor_from_row (w, row, w->current_matrix,
19453 0, 0, 0, 0);
19454
19455
19456
19457 if (rv)
19458 {
19459 at_zv_p = MATRIX_ROW (w->current_matrix,
19460 w->cursor.vpos)->ends_at_zv_p;
19461 if (!at_zv_p
19462 && w->cursor.hpos >= 0
19463 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19464 w->cursor.vpos))
19465 {
19466 struct glyph_row *candidate =
19467 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19468 struct glyph *g =
19469 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19470 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19471
19472 exact_match_p =
19473 (BUFFERP (g->object) && g->charpos == PT)
19474 || (NILP (g->object)
19475 && (g->charpos == PT
19476 || (g->charpos == 0 && endpos - 1 == PT)));
19477
19478
19479
19480
19481 if (!exact_match_p && pt_invis)
19482 exact_match_p = true;
19483 }
19484 if (at_zv_p || exact_match_p)
19485 {
19486 rc = CURSOR_MOVEMENT_SUCCESS;
19487 break;
19488 }
19489 }
19490 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19491 break;
19492 ++row;
19493 }
19494 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19495 || row->continued_p)
19496 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19497 || (MATRIX_ROW_START_CHARPOS (row) == PT
19498 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19499
19500
19501
19502 if (rc != CURSOR_MOVEMENT_SUCCESS
19503 && !(rv
19504 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19505 && !row->continued_p))
19506 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19507 else if (rv)
19508 rc = CURSOR_MOVEMENT_SUCCESS;
19509 }
19510 else
19511 {
19512 do
19513 {
19514 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19515 {
19516 rc = CURSOR_MOVEMENT_SUCCESS;
19517 break;
19518 }
19519 ++row;
19520 }
19521 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19522 && MATRIX_ROW_START_CHARPOS (row) == PT
19523 && cursor_row_p (row));
19524 }
19525 }
19526 }
19527
19528 return rc;
19529 }
19530
19531
19532 void
19533 set_vertical_scroll_bar (struct window *w)
19534 {
19535 ptrdiff_t start, end, whole;
19536
19537
19538
19539
19540
19541
19542
19543
19544 if (!MINI_WINDOW_P (w)
19545 || (w == XWINDOW (minibuf_window)
19546 && NILP (echo_area_buffer[0])))
19547 {
19548 struct buffer *buf = XBUFFER (w->contents);
19549
19550 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19551 start = marker_position (w->start) - BUF_BEGV (buf);
19552 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19553
19554
19555
19556
19557 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19558 {
19559 struct it it;
19560 struct text_pos start_pos;
19561 struct buffer *obuf = current_buffer;
19562
19563
19564
19565 set_buffer_internal_1 (XBUFFER (w->contents));
19566 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19567 start_display (&it, w, start_pos);
19568 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19569 MOVE_TO_X | MOVE_TO_Y);
19570 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19571 set_buffer_internal_1 (obuf);
19572 }
19573
19574 if (end < start)
19575 end = start;
19576 if (whole < (end - start))
19577 whole = end - start;
19578 }
19579 else
19580 start = end = whole = 0;
19581
19582
19583 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19584 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19585 (w, end - start, whole, start);
19586 }
19587
19588
19589 void
19590 set_horizontal_scroll_bar (struct window *w)
19591 {
19592 int start, end, whole, portion;
19593
19594 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19595 {
19596 struct buffer *b = XBUFFER (w->contents);
19597 struct buffer *old_buffer = NULL;
19598 struct it it;
19599 struct text_pos startp;
19600
19601 if (b != current_buffer)
19602 {
19603 old_buffer = current_buffer;
19604 set_buffer_internal (b);
19605 }
19606
19607 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19608 start_display (&it, w, startp);
19609 it.last_visible_x = INT_MAX;
19610 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19611 MOVE_TO_X | MOVE_TO_Y);
19612
19613
19614
19615
19616 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19617 end = start + window_box_width (w, TEXT_AREA);
19618 portion = end - start;
19619
19620
19621
19622
19623 whole = max (whole, end);
19624
19625 if (it.bidi_p)
19626 {
19627 Lisp_Object pdir;
19628
19629 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19630 if (EQ (pdir, Qright_to_left))
19631 {
19632 start = whole - end;
19633 end = start + portion;
19634 }
19635 }
19636
19637 if (old_buffer)
19638 set_buffer_internal (old_buffer);
19639 }
19640 else
19641 start = end = whole = portion = 0;
19642
19643 w->hscroll_whole = whole;
19644
19645
19646 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19647 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19648 (w, portion, whole, start);
19649 }
19650
19651
19652
19653 static bool
19654 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19655 {
19656 if (!make_window_start_visible)
19657 return true;
19658
19659 struct window *w = XWINDOW (window);
19660 struct frame *f = XFRAME (w->frame);
19661 Lisp_Object startpos = make_fixnum (startp);
19662 Lisp_Object invprop, disp_spec;
19663 struct text_pos ignored;
19664
19665
19666 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19667 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19668 return false;
19669
19670
19671 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19672 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19673 FRAME_WINDOW_P (f)) > 0)
19674 return false;
19675
19676 return true;
19677 }
19678
19679 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19680 0, 0, 0,
19681 doc:
19682
19683 )
19684 (void)
19685 {
19686 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
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
19732
19733
19734
19735
19736
19737
19738
19739 static void
19740 redisplay_window (Lisp_Object window, bool just_this_one_p)
19741 {
19742 struct window *w = XWINDOW (window);
19743 struct frame *f = XFRAME (w->frame);
19744 struct buffer *buffer = XBUFFER (w->contents);
19745 struct buffer *old = current_buffer;
19746 struct text_pos lpoint, opoint, startp;
19747 bool update_mode_line;
19748 int tem;
19749 struct it it;
19750
19751 bool current_matrix_up_to_date_p = false;
19752 bool used_current_matrix_p = false;
19753
19754
19755 bool buffer_unchanged_p = false;
19756 bool temp_scroll_step = false;
19757 specpdl_ref count = SPECPDL_INDEX ();
19758 int rc;
19759 int centering_position = -1;
19760 bool last_line_misfit = false;
19761 ptrdiff_t beg_unchanged, end_unchanged;
19762 int frame_line_height, margin;
19763 bool use_desired_matrix;
19764 void *itdata = NULL;
19765
19766 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19767 opoint = lpoint;
19768
19769 #ifdef GLYPH_DEBUG
19770 *w->desired_matrix->method = 0;
19771 #endif
19772
19773 if (!just_this_one_p && needs_no_redisplay (w))
19774 return;
19775
19776
19777 eassert (XMARKER (w->start)->buffer == buffer);
19778 eassert (XMARKER (w->pointm)->buffer == buffer);
19779
19780 reconsider_clip_changes (w);
19781 frame_line_height = default_line_pixel_height (w);
19782 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19783
19784
19785
19786 update_mode_line = (w->update_mode_line
19787 || update_mode_lines
19788 || buffer->clip_changed
19789 || buffer->prevent_redisplay_optimizations_p);
19790
19791 if (!just_this_one_p)
19792
19793
19794 w->must_be_updated_p = true;
19795
19796 if (MINI_WINDOW_P (w))
19797 {
19798 if (w == XWINDOW (echo_area_window)
19799 && !NILP (echo_area_buffer[0]))
19800 {
19801 if (update_mode_line)
19802
19803
19804 goto finish_menu_bars;
19805 else
19806
19807 goto finish_scroll_bars;
19808 }
19809 else if ((w != XWINDOW (minibuf_window)
19810 || minibuf_level == 0)
19811
19812 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19813
19814
19815 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19816 {
19817
19818
19819 int yb = window_text_bottom_y (w);
19820 struct glyph_row *row;
19821 int y;
19822
19823 for (y = 0, row = w->desired_matrix->rows;
19824 y < yb;
19825 y += row->height, ++row)
19826 blank_row (w, row, y);
19827 goto finish_scroll_bars;
19828 }
19829 else if (minibuf_level >= 1)
19830 {
19831
19832
19833
19834 resize_mini_window (w, false);
19835 }
19836
19837 clear_glyph_matrix (w->desired_matrix);
19838 }
19839
19840
19841
19842
19843
19844 set_buffer_internal_1 (XBUFFER (w->contents));
19845
19846 current_matrix_up_to_date_p
19847 = (w->window_end_valid
19848 && !current_buffer->clip_changed
19849 && !current_buffer->prevent_redisplay_optimizations_p
19850 && !window_outdated (w)
19851 && !composition_break_at_point
19852 && !hscrolling_current_line_p (w));
19853
19854 beg_unchanged = BEG_UNCHANGED;
19855 end_unchanged = END_UNCHANGED;
19856
19857 SET_TEXT_POS (opoint, PT, PT_BYTE);
19858
19859 specbind (Qinhibit_point_motion_hooks, Qt);
19860
19861 buffer_unchanged_p
19862 = (w->window_end_valid
19863 && !current_buffer->clip_changed
19864 && !window_outdated (w));
19865
19866
19867
19868 if (windows_or_buffers_changed)
19869 {
19870
19871
19872 if (XMARKER (w->start)->buffer == current_buffer)
19873 compute_window_start_on_continuation_line (w);
19874
19875 w->window_end_valid = false;
19876
19877
19878 current_matrix_up_to_date_p = false;
19879 }
19880
19881
19882 CHECK_WINDOW_END (w);
19883 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19884 emacs_abort ();
19885 if (BYTEPOS (opoint) < CHARPOS (opoint))
19886 emacs_abort ();
19887
19888 if (mode_line_update_needed (w))
19889 update_mode_line = true;
19890
19891
19892
19893 if (!EQ (window, selected_window))
19894 {
19895 ptrdiff_t new_pt = marker_position (w->pointm);
19896 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19897
19898 if (new_pt < BEGV)
19899 {
19900 new_pt = BEGV;
19901 new_pt_byte = BEGV_BYTE;
19902 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19903 }
19904 else if (new_pt > (ZV - 1))
19905 {
19906 new_pt = ZV;
19907 new_pt_byte = ZV_BYTE;
19908 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19909 }
19910
19911
19912 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19913 }
19914
19915
19916
19917
19918
19919
19920 if (current_buffer->width_run_cache
19921 || (current_buffer->base_buffer
19922 && current_buffer->base_buffer->width_run_cache))
19923 {
19924 struct Lisp_Char_Table *disptab = buffer_display_table ();
19925
19926 if (! disptab_matches_widthtab
19927 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19928 {
19929 struct buffer *buf = current_buffer;
19930
19931 if (buf->base_buffer)
19932 buf = buf->base_buffer;
19933 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19934 recompute_width_table (current_buffer, disptab);
19935 }
19936 }
19937
19938
19939 if (!NILP (Vlong_line_threshold)
19940 && !current_buffer->long_line_optimizations_p
19941 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19942 || current_buffer->clip_changed))
19943 {
19944 ptrdiff_t cur, next, found, max = 0, threshold;
19945 threshold = XFIXNUM (Vlong_line_threshold);
19946 for (cur = BEGV; cur < ZV; cur = next)
19947 {
19948 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19949 &found, NULL, true);
19950 if (next - cur > max) max = next - cur;
19951 if (!found || max > threshold) break;
19952 }
19953 if (max > threshold)
19954 current_buffer->long_line_optimizations_p = true;
19955 }
19956
19957
19958 if (XMARKER (w->start)->buffer != current_buffer)
19959 goto recenter;
19960
19961 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19962
19963
19964
19965 if ((w->optional_new_start || window_frozen_p (w))
19966 && CHARPOS (startp) >= BEGV
19967 && CHARPOS (startp) <= ZV)
19968 {
19969 ptrdiff_t it_charpos;
19970
19971 w->optional_new_start = false;
19972 if (!w->force_start)
19973 {
19974 start_display (&it, w, startp);
19975 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19976 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19977
19978
19979 it_charpos = IT_CHARPOS (it);
19980
19981
19982
19983
19984
19985 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19986 {
19987 if (it_charpos == PT)
19988 w->force_start = true;
19989
19990 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19991 w->force_start = true;
19992 #ifdef GLYPH_DEBUG
19993 if (w->force_start)
19994 {
19995 if (window_frozen_p (w))
19996 debug_method_add (w, "set force_start from frozen window start");
19997 else
19998 debug_method_add (w, "set force_start from optional_new_start");
19999 }
20000 #endif
20001 }
20002 }
20003 }
20004
20005 force_start:
20006
20007
20008
20009 if (w->force_start)
20010 {
20011
20012 int new_vpos = -1;
20013
20014 w->force_start = false;
20015
20016
20017
20018
20019 if (!w->preserve_vscroll_p || !window_frozen_p (w))
20020 w->vscroll = 0;
20021
20022 w->preserve_vscroll_p = false;
20023 w->window_end_valid = false;
20024
20025
20026 if (!buffer_unchanged_p)
20027 w->base_line_number = 0;
20028
20029
20030
20031
20032
20033
20034
20035
20036 if (!update_mode_line
20037 || ! NILP (Vwindow_scroll_functions))
20038 {
20039 update_mode_line = true;
20040 w->update_mode_line = true;
20041 startp = run_window_scroll_functions (window, startp);
20042 }
20043
20044 if (CHARPOS (startp) < BEGV)
20045 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
20046 else if (CHARPOS (startp) > ZV)
20047 SET_TEXT_POS (startp, ZV, ZV_BYTE);
20048
20049
20050
20051 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20052 goto ignore_start;
20053
20054
20055
20056
20057
20058
20059 clear_glyph_matrix (w->desired_matrix);
20060 if (!try_window (window, startp, 0))
20061 {
20062 w->force_start = true;
20063 clear_glyph_matrix (w->desired_matrix);
20064 goto need_larger_matrices;
20065 }
20066
20067 if (w->cursor.vpos < 0)
20068 {
20069
20070
20071
20072
20073
20074 struct glyph_row *r = NULL;
20075 Lisp_Object invprop =
20076 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20077 Qnil, NULL);
20078
20079 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
20080 {
20081 ptrdiff_t alt_pt;
20082 Lisp_Object invprop_end =
20083 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20084 Qnil, Qnil);
20085
20086 if (FIXNATP (invprop_end))
20087 alt_pt = XFIXNAT (invprop_end);
20088 else
20089 alt_pt = ZV;
20090 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
20091 NULL, 0);
20092 }
20093 if (r)
20094 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
20095 else
20096 new_vpos = window_box_height (w) / 2;
20097 }
20098
20099 if (!cursor_row_fully_visible_p (w, false, false, false))
20100 {
20101
20102
20103 new_vpos = window_box_height (w);
20104
20105
20106
20107
20108
20109
20110 if (new_vpos >= w->cursor.y)
20111 {
20112 w->cursor.vpos = -1;
20113 clear_glyph_matrix (w->desired_matrix);
20114 goto try_to_scroll;
20115 }
20116 }
20117 else if (w->cursor.vpos >= 0)
20118 {
20119
20120
20121
20122 int pixel_margin = margin * frame_line_height;
20123 bool tab_line = window_wants_tab_line (w);
20124 bool header_line = window_wants_header_line (w);
20125
20126
20127
20128
20129
20130 if (w->cursor.vpos < margin + tab_line + header_line)
20131 {
20132 w->cursor.vpos = -1;
20133 clear_glyph_matrix (w->desired_matrix);
20134 goto try_to_scroll;
20135 }
20136 else
20137 {
20138 int window_height = window_box_height (w);
20139
20140 if (tab_line)
20141 window_height += CURRENT_TAB_LINE_HEIGHT (w);
20142 if (header_line)
20143 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
20144 if (w->cursor.y >= window_height - pixel_margin)
20145 {
20146 w->cursor.vpos = -1;
20147 clear_glyph_matrix (w->desired_matrix);
20148 goto try_to_scroll;
20149 }
20150 }
20151 }
20152
20153
20154
20155 if (new_vpos >= 0)
20156 {
20157 struct glyph_row *row;
20158
20159 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
20160 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
20161 && !row->ends_at_zv_p)
20162 ++row;
20163
20164 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
20165 MATRIX_ROW_START_BYTEPOS (row));
20166
20167 if (w != XWINDOW (selected_window))
20168 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
20169 else if (current_buffer == old)
20170 SET_TEXT_POS (lpoint, PT, PT_BYTE);
20171
20172 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
20173
20174
20175
20176
20177
20178
20179
20180 w->redisplay = false;
20181 XBUFFER (w->contents)->text->redisplay = false;
20182 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
20183
20184 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
20185 || ((EQ (Vdisplay_line_numbers, Qrelative)
20186 || EQ (Vdisplay_line_numbers, Qvisual))
20187 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
20188 {
20189
20190
20191
20192
20193 clear_glyph_matrix (w->desired_matrix);
20194 if (!try_window (window, startp, 0))
20195 goto need_larger_matrices;
20196 }
20197 }
20198 if (w->cursor.vpos < 0
20199 || !cursor_row_fully_visible_p (w, false, false, false))
20200 {
20201 clear_glyph_matrix (w->desired_matrix);
20202 goto try_to_scroll;
20203 }
20204
20205 #ifdef GLYPH_DEBUG
20206 debug_method_add (w, "forced window start");
20207 #endif
20208 goto done;
20209 }
20210
20211 ignore_start:
20212
20213
20214
20215
20216 if (current_matrix_up_to_date_p
20217 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
20218 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
20219 {
20220 switch (rc)
20221 {
20222 case CURSOR_MOVEMENT_SUCCESS:
20223 used_current_matrix_p = true;
20224 goto done;
20225
20226 case CURSOR_MOVEMENT_MUST_SCROLL:
20227 goto try_to_scroll;
20228
20229 default:
20230 emacs_abort ();
20231 }
20232 }
20233
20234
20235
20236 else if (w->start_at_line_beg
20237 && ((CHARPOS (startp) > BEGV
20238 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
20239 || (CHARPOS (startp) >= BEGV
20240 && CHARPOS (startp) <= ZV
20241 && !window_start_acceptable_p (window, CHARPOS (startp)))))
20242 {
20243 #ifdef GLYPH_DEBUG
20244 debug_method_add (w, "recenter 1");
20245 #endif
20246 goto recenter;
20247 }
20248
20249
20250
20251
20252 else if ((tem = try_window_id (w)) != 0)
20253 {
20254 #ifdef GLYPH_DEBUG
20255 debug_method_add (w, "try_window_id %d", tem);
20256 #endif
20257
20258 if (f->fonts_changed)
20259 goto need_larger_matrices;
20260 if (tem > 0)
20261 goto done;
20262
20263
20264
20265 }
20266 else if (CHARPOS (startp) >= BEGV
20267 && CHARPOS (startp) <= ZV
20268 && PT >= CHARPOS (startp)
20269 && (CHARPOS (startp) < ZV
20270
20271 || CHARPOS (startp) == BEGV
20272 || !window_outdated (w)))
20273 {
20274 int d1, d2, d5, d6;
20275 int rtop, rbot;
20276
20277
20278
20279
20280
20281
20282
20283
20284
20285
20286 if (!w->start_at_line_beg
20287 && NILP (track_mouse)
20288 && CHARPOS (startp) > BEGV
20289 && CHARPOS (startp) > BEG + beg_unchanged
20290 && CHARPOS (startp) <= Z - end_unchanged
20291
20292
20293
20294
20295
20296 && XMARKER (w->start)->buffer == current_buffer
20297 && compute_window_start_on_continuation_line (w)
20298
20299
20300
20301
20302
20303
20304 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20305
20306
20307 && (rtop != 0) == (rbot != 0))
20308 {
20309 w->force_start = true;
20310 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20311 #ifdef GLYPH_DEBUG
20312 debug_method_add (w, "recomputed window start in continuation line");
20313 #endif
20314 goto force_start;
20315 }
20316
20317
20318
20319
20320 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20321 {
20322 #ifdef GLYPH_DEBUG
20323 debug_method_add (w, "recenter 2");
20324 #endif
20325 goto recenter;
20326 }
20327
20328 #ifdef GLYPH_DEBUG
20329 debug_method_add (w, "same window start");
20330 #endif
20331
20332
20333
20334 if (!current_matrix_up_to_date_p
20335
20336
20337
20338 || !NILP (Vwindow_scroll_functions)
20339 || MINI_WINDOW_P (w)
20340 || !(used_current_matrix_p
20341 = try_window_reusing_current_matrix (w)))
20342 {
20343 IF_DEBUG (debug_method_add (w, "1"));
20344 clear_glyph_matrix (w->desired_matrix);
20345 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20346
20347
20348
20349 goto try_to_scroll;
20350 }
20351
20352 if (f->fonts_changed)
20353 goto need_larger_matrices;
20354
20355 if (w->cursor.vpos >= 0)
20356 {
20357 if (!just_this_one_p
20358 || current_buffer->clip_changed
20359 || BEG_UNCHANGED < CHARPOS (startp))
20360
20361 w->base_line_number = 0;
20362
20363 if (!cursor_row_fully_visible_p (w, true, false, false))
20364 {
20365 clear_glyph_matrix (w->desired_matrix);
20366 last_line_misfit = true;
20367 }
20368
20369 else
20370 goto done;
20371 }
20372 else
20373 clear_glyph_matrix (w->desired_matrix);
20374 }
20375
20376 try_to_scroll:
20377
20378
20379 if (!update_mode_line)
20380 {
20381 update_mode_line = true;
20382 w->update_mode_line = true;
20383 }
20384
20385
20386 if ((0 < scroll_conservatively
20387
20388
20389
20390
20391 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20392 || 0 < emacs_scroll_step
20393 || temp_scroll_step
20394 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20395 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20396 && CHARPOS (startp) >= BEGV
20397 && CHARPOS (startp) <= ZV)
20398 {
20399
20400
20401 int ss = try_scrolling (window, just_this_one_p,
20402 ((scroll_minibuffer_conservatively
20403 && MINI_WINDOW_P (w))
20404 ? SCROLL_LIMIT + 1
20405 : scroll_conservatively),
20406 emacs_scroll_step,
20407 temp_scroll_step, last_line_misfit);
20408 switch (ss)
20409 {
20410 case SCROLLING_SUCCESS:
20411 goto done;
20412
20413 case SCROLLING_NEED_LARGER_MATRICES:
20414 goto need_larger_matrices;
20415
20416 case SCROLLING_FAILED:
20417 break;
20418
20419 default:
20420 emacs_abort ();
20421 }
20422 }
20423
20424
20425
20426
20427 recenter:
20428
20429 #ifdef GLYPH_DEBUG
20430 debug_method_add (w, "recenter");
20431 #endif
20432
20433
20434 if (!buffer_unchanged_p)
20435 w->base_line_number = 0;
20436
20437
20438 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20439 it.current_y = it.last_visible_y;
20440 if (centering_position < 0)
20441 {
20442 ptrdiff_t margin_pos = CHARPOS (startp);
20443 Lisp_Object aggressive;
20444 bool scrolling_up;
20445
20446
20447
20448 if (margin
20449
20450
20451
20452
20453
20454
20455 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20456 {
20457 struct it it1;
20458 void *it1data = NULL;
20459
20460 SAVE_IT (it1, it, it1data);
20461 start_display (&it1, w, startp);
20462 move_it_vertically (&it1, margin * frame_line_height);
20463 margin_pos = IT_CHARPOS (it1);
20464 RESTORE_IT (&it, &it, it1data);
20465 }
20466 scrolling_up = PT > margin_pos;
20467 aggressive =
20468 scrolling_up
20469 ? BVAR (current_buffer, scroll_up_aggressively)
20470 : BVAR (current_buffer, scroll_down_aggressively);
20471
20472 if (!MINI_WINDOW_P (w)
20473 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20474 {
20475 int pt_offset = 0;
20476
20477
20478
20479 if (!scroll_conservatively && NUMBERP (aggressive))
20480 {
20481 double float_amount = XFLOATINT (aggressive);
20482
20483 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20484 if (pt_offset == 0 && float_amount > 0)
20485 pt_offset = 1;
20486 if (pt_offset && margin > 0)
20487 margin -= 1;
20488 }
20489
20490
20491
20492 if (scrolling_up)
20493 {
20494 centering_position = it.last_visible_y;
20495 if (pt_offset)
20496 centering_position -= pt_offset;
20497 centering_position -=
20498 (frame_line_height * (1 + margin + last_line_misfit)
20499 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20500
20501
20502 if (centering_position < margin * frame_line_height)
20503 centering_position = margin * frame_line_height;
20504 }
20505 else
20506 centering_position = margin * frame_line_height + pt_offset;
20507 }
20508 else
20509
20510
20511 centering_position = window_box_height (w) / 2;
20512 }
20513 if (current_buffer->long_line_optimizations_p
20514 && it.line_wrap == TRUNCATE)
20515 {
20516
20517
20518
20519 int nlines = centering_position / frame_line_height;
20520
20521 while (nlines-- && IT_CHARPOS (it) > BEGV)
20522 back_to_previous_visible_line_start (&it);
20523 reseat_1 (&it, it.current.pos, true);
20524 }
20525 else
20526 move_it_vertically_backward (&it, centering_position);
20527
20528 eassert (IT_CHARPOS (it) >= BEGV);
20529
20530
20531
20532
20533
20534
20535 if (it.current_y <= 0)
20536 {
20537 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20538 move_it_vertically_backward (&it, 0);
20539 it.current_y = 0;
20540 }
20541
20542 it.current_x = it.hpos = 0;
20543
20544
20545
20546
20547 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20548
20549
20550 startp = run_window_scroll_functions (window, it.current.pos);
20551
20552
20553
20554
20555 itdata = bidi_shelve_cache ();
20556
20557
20558 use_desired_matrix = false;
20559 if (!current_matrix_up_to_date_p
20560 || windows_or_buffers_changed
20561 || f->cursor_type_changed
20562
20563
20564 || !NILP (Vwindow_scroll_functions)
20565 || !just_this_one_p
20566 || MINI_WINDOW_P (w)
20567 || !(used_current_matrix_p
20568 = try_window_reusing_current_matrix (w)))
20569 use_desired_matrix = (try_window (window, startp, 0) == 1);
20570
20571 bidi_unshelve_cache (itdata, false);
20572
20573
20574
20575
20576 if (f->fonts_changed)
20577 goto need_larger_matrices;
20578
20579
20580
20581
20582
20583
20584 if (w->cursor.vpos < 0)
20585 {
20586 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20587 {
20588 clear_glyph_matrix (w->desired_matrix);
20589 move_it_by_lines (&it, 1);
20590 try_window (window, it.current.pos, 0);
20591 }
20592 else if (PT < IT_CHARPOS (it))
20593 {
20594 clear_glyph_matrix (w->desired_matrix);
20595 move_it_by_lines (&it, -1);
20596 try_window (window, it.current.pos, 0);
20597 }
20598 else if (scroll_conservatively > SCROLL_LIMIT
20599 && (it.method == GET_FROM_STRING
20600 || overlay_touches_p (IT_CHARPOS (it)))
20601 && IT_CHARPOS (it) < ZV)
20602 {
20603
20604
20605
20606
20607
20608
20609
20610
20611 ptrdiff_t pos0 = IT_CHARPOS (it);
20612
20613 clear_glyph_matrix (w->desired_matrix);
20614 do {
20615 move_it_by_lines (&it, 1);
20616 } while (IT_CHARPOS (it) == pos0);
20617 try_window (window, it.current.pos, 0);
20618 }
20619 else
20620 {
20621
20622 }
20623 }
20624
20625
20626
20627
20628
20629
20630 if (w->cursor.vpos < 0)
20631 {
20632
20633
20634
20635
20636 struct glyph_matrix *matrix =
20637 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20638
20639 struct glyph_row *row =
20640 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20641
20642
20643
20644
20645
20646
20647
20648 if (!row)
20649 {
20650 Lisp_Object val =
20651 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20652 Qnil, NULL);
20653
20654 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20655 {
20656 ptrdiff_t alt_pos;
20657 Lisp_Object invis_end =
20658 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20659 Qnil, Qnil);
20660
20661 if (FIXNATP (invis_end))
20662 alt_pos = XFIXNAT (invis_end);
20663 else
20664 alt_pos = ZV;
20665 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20666 }
20667 }
20668
20669
20670
20671 if (!row)
20672 {
20673 row = matrix->rows;
20674
20675 if (row->tab_line_p)
20676 ++row;
20677 if (row->mode_line_p)
20678 ++row;
20679 }
20680 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20681 }
20682
20683 if (!cursor_row_fully_visible_p (w, false, false, false))
20684 {
20685
20686 if (w->vscroll)
20687 {
20688 w->vscroll = 0;
20689 clear_glyph_matrix (w->desired_matrix);
20690 goto recenter;
20691 }
20692
20693
20694
20695
20696
20697 if (scroll_conservatively > SCROLL_LIMIT)
20698 {
20699 int window_total_lines
20700 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20701 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20702
20703 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20704 clear_glyph_matrix (w->desired_matrix);
20705 if (1 == try_window (window, it.current.pos,
20706 TRY_WINDOW_CHECK_MARGINS))
20707 goto done;
20708 }
20709
20710
20711
20712
20713 if (centering_position == 0)
20714 goto done;
20715
20716 clear_glyph_matrix (w->desired_matrix);
20717 centering_position = 0;
20718 goto recenter;
20719 }
20720
20721 done:
20722
20723 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20724 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20725 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20726
20727
20728 if ((update_mode_line
20729
20730
20731
20732
20733 || (!just_this_one_p
20734 && !FRAME_WINDOW_P (f)
20735 && !WINDOW_FULL_WIDTH_P (w))
20736
20737 || w->base_line_pos > 0
20738
20739 || (w->column_number_displayed != -1
20740 && (w->column_number_displayed != current_column ())))
20741
20742 && (window_wants_mode_line (w)
20743 || window_wants_header_line (w)
20744 || window_wants_tab_line (w)))
20745 {
20746 specpdl_ref count1 = SPECPDL_INDEX ();
20747
20748 specbind (Qinhibit_quit, Qt);
20749 display_mode_lines (w);
20750 unbind_to (count1, Qnil);
20751
20752
20753
20754 if (window_wants_mode_line (w)
20755 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20756 {
20757 f->fonts_changed = true;
20758 w->mode_line_height = -1;
20759 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20760 = DESIRED_MODE_LINE_HEIGHT (w);
20761 }
20762
20763
20764
20765 if (window_wants_tab_line (w)
20766 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20767 {
20768 f->fonts_changed = true;
20769 w->tab_line_height = -1;
20770 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20771 = DESIRED_TAB_LINE_HEIGHT (w);
20772 }
20773
20774
20775
20776 if (window_wants_header_line (w)
20777 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20778 {
20779 f->fonts_changed = true;
20780 w->header_line_height = -1;
20781 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20782 = DESIRED_HEADER_LINE_HEIGHT (w);
20783 }
20784
20785 if (f->fonts_changed)
20786 goto need_larger_matrices;
20787 }
20788
20789 if (!line_number_displayed && w->base_line_pos != -1)
20790 {
20791 w->base_line_pos = 0;
20792 w->base_line_number = 0;
20793 }
20794
20795 finish_menu_bars:
20796
20797
20798
20799 if (update_mode_line
20800 && EQ (FRAME_SELECTED_WINDOW (f), window))
20801 {
20802 bool redisplay_menu_p;
20803
20804 if (FRAME_WINDOW_P (f))
20805 {
20806 #ifdef HAVE_EXT_MENU_BAR
20807 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20808 #else
20809 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20810 #endif
20811 }
20812 else
20813 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20814
20815 if (redisplay_menu_p)
20816 display_menu_bar (w);
20817
20818 #ifdef HAVE_WINDOW_SYSTEM
20819 if (FRAME_WINDOW_P (f))
20820 {
20821 if (WINDOWP (f->tab_bar_window)
20822 && (FRAME_TAB_BAR_LINES (f) > 0
20823 || !NILP (Vauto_resize_tab_bars))
20824 && redisplay_tab_bar (f))
20825 ignore_mouse_drag_p = true;
20826
20827 #ifdef HAVE_EXT_TOOL_BAR
20828 if (FRAME_EXTERNAL_TOOL_BAR (f))
20829 update_frame_tool_bar (f);
20830 #else
20831 if (WINDOWP (f->tool_bar_window)
20832 && (FRAME_TOOL_BAR_LINES (f) > 0
20833 || !NILP (Vauto_resize_tool_bars))
20834 && redisplay_tool_bar (f))
20835 ignore_mouse_drag_p = true;
20836 #endif
20837 }
20838 else
20839 {
20840 if ((FRAME_TAB_BAR_LINES (f) > 0))
20841 display_tab_bar (w);
20842 }
20843
20844 gui_consider_frame_title (w->frame);
20845 #else
20846 if ((FRAME_TAB_BAR_LINES (f) > 0))
20847 display_tab_bar (w);
20848 #endif
20849 }
20850
20851 #ifdef HAVE_WINDOW_SYSTEM
20852 if (FRAME_WINDOW_P (f)
20853 && update_window_fringes (w, (just_this_one_p
20854 || (!used_current_matrix_p && !overlay_arrow_seen)
20855 || w->pseudo_window_p)))
20856 {
20857 update_begin (f);
20858 block_input ();
20859 if (draw_window_fringes (w, true))
20860 {
20861 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20862 gui_draw_right_divider (w);
20863 else
20864 gui_draw_vertical_border (w);
20865 }
20866 unblock_input ();
20867 update_end (f);
20868 }
20869
20870 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20871 gui_draw_bottom_divider (w);
20872 #endif
20873
20874
20875
20876
20877
20878 need_larger_matrices:
20879 ;
20880 finish_scroll_bars:
20881
20882 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20883 {
20884 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20885
20886 set_vertical_scroll_bar (w);
20887
20888 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20889
20890 set_horizontal_scroll_bar (w);
20891
20892
20893
20894 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20895 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20896 }
20897
20898
20899
20900
20901 if (CHARPOS (opoint) < BEGV)
20902 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20903 else if (CHARPOS (opoint) > ZV)
20904 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20905 else
20906 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20907
20908 set_buffer_internal_1 (old);
20909
20910
20911 if (CHARPOS (lpoint) <= ZV)
20912 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20913
20914 unbind_to (count, Qnil);
20915 }
20916
20917
20918
20919
20920
20921
20922
20923
20924
20925
20926
20927
20928
20929
20930
20931
20932
20933
20934
20935
20936 int
20937 try_window (Lisp_Object window, struct text_pos pos, int flags)
20938 {
20939 struct window *w = XWINDOW (window);
20940 struct it it;
20941 struct glyph_row *last_text_row = NULL;
20942 struct frame *f = XFRAME (w->frame);
20943 int cursor_vpos = w->cursor.vpos;
20944
20945
20946 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20947
20948
20949 w->cursor.vpos = -1;
20950 overlay_arrow_seen = false;
20951
20952
20953 start_display (&it, w, pos);
20954 it.glyph_row->reversed_p = false;
20955
20956
20957 while (it.current_y < it.last_visible_y)
20958 {
20959 int last_row_scale = it.w->nrows_scale_factor;
20960 int last_col_scale = it.w->ncols_scale_factor;
20961 if (display_line (&it, cursor_vpos))
20962 last_text_row = it.glyph_row - 1;
20963 if (f->fonts_changed
20964 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20965
20966
20967 && last_row_scale == it.w->nrows_scale_factor
20968 && last_col_scale == it.w->ncols_scale_factor))
20969 return 0;
20970 }
20971
20972
20973
20974 ptrdiff_t it_charpos = IT_CHARPOS (it);
20975
20976
20977
20978
20979 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20980 && w->vscroll == 0
20981 && !MINI_WINDOW_P (w))
20982 {
20983 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20984 int bot_scroll_margin = top_scroll_margin;
20985 if (window_wants_header_line (w))
20986 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20987 if (window_wants_tab_line (w))
20988 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20989 start_display (&it, w, pos);
20990
20991 if ((w->cursor.y >= 0
20992 && w->cursor.y < top_scroll_margin
20993 && CHARPOS (pos) > BEGV)
20994
20995
20996
20997
20998 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20999 - bot_scroll_margin - 1))
21000 {
21001 w->cursor.vpos = -1;
21002 clear_glyph_matrix (w->desired_matrix);
21003 return -1;
21004 }
21005 }
21006
21007
21008 if (w->window_end_pos <= 0 && Z != it_charpos)
21009 w->update_mode_line = true;
21010
21011
21012
21013
21014 if (last_text_row)
21015 {
21016 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
21017 adjust_window_ends (w, last_text_row, false);
21018 eassert
21019 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
21020 w->window_end_vpos)));
21021 }
21022 else
21023 {
21024 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21025 w->window_end_pos = Z - ZV;
21026 w->window_end_vpos = 0;
21027 }
21028
21029
21030 w->window_end_valid = false;
21031 return 1;
21032 }
21033
21034
21035
21036
21037
21038
21039
21040
21041
21042
21043
21044
21045 static bool
21046 try_window_reusing_current_matrix (struct window *w)
21047 {
21048 struct frame *f = XFRAME (w->frame);
21049 struct glyph_row *bottom_row;
21050 struct it it;
21051 struct run run;
21052 struct text_pos start, new_start;
21053 int nrows_scrolled, i;
21054 struct glyph_row *last_text_row;
21055 struct glyph_row *last_reused_text_row;
21056 struct glyph_row *start_row;
21057 int start_vpos, min_y, max_y;
21058
21059 #ifdef GLYPH_DEBUG
21060 if (inhibit_try_window_reusing)
21061 return false;
21062 #endif
21063
21064 if (
21065 !FRAME_WINDOW_P (f)
21066
21067
21068 || windows_or_buffers_changed
21069 || f->cursor_type_changed
21070
21071
21072
21073 || overlay_arrow_in_current_buffer_p ())
21074 return false;
21075
21076
21077 if (!NILP (Vshow_trailing_whitespace))
21078 return false;
21079
21080
21081 if (window_wants_tab_line (w)
21082 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
21083 return false;
21084
21085
21086 if (window_wants_header_line (w)
21087 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
21088 return false;
21089
21090
21091
21092 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21093 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
21094 return false;
21095
21096
21097 clear_glyph_matrix (w->desired_matrix);
21098
21099
21100
21101
21102 if (!NILP (Vdisplay_line_numbers))
21103 return false;
21104
21105
21106
21107
21108 #ifdef HAVE_NTGUI
21109 if (w32_use_visible_system_caret)
21110 return false;
21111 #endif
21112
21113
21114
21115 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
21116 start = start_row->minpos;
21117 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21118
21119 if (CHARPOS (new_start) <= CHARPOS (start))
21120 {
21121
21122
21123
21124
21125 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
21126 return false;
21127
21128 IF_DEBUG (debug_method_add (w, "twu1"));
21129
21130
21131
21132
21133
21134 start_display (&it, w, new_start);
21135 w->cursor.vpos = -1;
21136 last_text_row = last_reused_text_row = NULL;
21137
21138 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21139 {
21140
21141
21142
21143
21144 while (IT_CHARPOS (it) > CHARPOS (start))
21145 {
21146
21147 start_row++;
21148 start = start_row->minpos;
21149
21150 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
21151 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
21152 || CHARPOS (start) == ZV)
21153 {
21154 clear_glyph_matrix (w->desired_matrix);
21155 return false;
21156 }
21157
21158 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21159 }
21160
21161
21162 if (IT_CHARPOS (it) == CHARPOS (start)
21163
21164
21165
21166
21167
21168 && it.current.dpvec_index < 0)
21169 break;
21170
21171 it.glyph_row->reversed_p = false;
21172 if (display_line (&it, -1))
21173 last_text_row = it.glyph_row - 1;
21174
21175 }
21176
21177
21178
21179
21180 if (it.current_y < it.last_visible_y)
21181 {
21182 struct glyph_row *row;
21183
21184
21185 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
21186
21187
21188 if (w->cursor.vpos < 0)
21189 {
21190 int dy = it.current_y - start_row->y;
21191
21192 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21193 row = row_containing_pos (w, PT, row, NULL, dy);
21194 if (row)
21195 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
21196 dy, nrows_scrolled);
21197 else
21198 {
21199 clear_glyph_matrix (w->desired_matrix);
21200 return false;
21201 }
21202 }
21203
21204
21205
21206
21207
21208
21209
21210 run.current_y = start_row->y;
21211 run.desired_y = it.current_y;
21212 run.height = it.last_visible_y - it.current_y;
21213
21214 if (run.height > 0 && run.current_y != run.desired_y)
21215 {
21216 #ifdef HAVE_WINDOW_SYSTEM
21217 update_begin (f);
21218 gui_update_window_begin (w);
21219 FRAME_RIF (f)->clear_window_mouse_face (w);
21220 FRAME_RIF (f)->scroll_run_hook (w, &run);
21221 gui_update_window_end (w, false, false);
21222 update_end (f);
21223 #endif
21224 }
21225
21226
21227 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21228 rotate_matrix (w->current_matrix,
21229 start_vpos,
21230 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21231 nrows_scrolled);
21232
21233
21234 for (i = 0; i < nrows_scrolled; ++i)
21235 (start_row + i)->enabled_p = false;
21236
21237
21238 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21239 max_y = it.last_visible_y;
21240 for (row = start_row + nrows_scrolled;
21241 row < bottom_row;
21242 ++row)
21243 {
21244 row->y = it.current_y;
21245 row->visible_height = row->height;
21246
21247 if (row->y < min_y)
21248 row->visible_height -= min_y - row->y;
21249 if (row->y + row->height > max_y)
21250 row->visible_height -= row->y + row->height - max_y;
21251 if (row->fringe_bitmap_periodic_p)
21252 row->redraw_fringe_bitmaps_p = true;
21253
21254 it.current_y += row->height;
21255
21256 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21257 last_reused_text_row = row;
21258 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21259 break;
21260 }
21261
21262
21263
21264 for (++row; row < bottom_row; ++row)
21265 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21266 }
21267
21268
21269
21270
21271
21272 if (last_reused_text_row)
21273 adjust_window_ends (w, last_reused_text_row, true);
21274 else if (last_text_row)
21275 adjust_window_ends (w, last_text_row, false);
21276 else
21277 {
21278
21279 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21280 w->window_end_pos = Z - ZV;
21281 w->window_end_vpos = 0;
21282 }
21283 w->window_end_valid = false;
21284
21285
21286 w->desired_matrix->no_scrolling_p = true;
21287
21288 #ifdef GLYPH_DEBUG
21289 debug_method_add (w, "try_window_reusing_current_matrix 1");
21290 #endif
21291 return true;
21292 }
21293 else if (CHARPOS (new_start) > CHARPOS (start))
21294 {
21295 struct glyph_row *pt_row, *row;
21296 struct glyph_row *first_reusable_row;
21297 struct glyph_row *first_row_to_display;
21298 int dy;
21299 int yb = window_text_bottom_y (w);
21300
21301
21302
21303 first_reusable_row = start_row;
21304 while (first_reusable_row->enabled_p
21305 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21306 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21307 < CHARPOS (new_start)))
21308 ++first_reusable_row;
21309
21310
21311 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21312 || !first_reusable_row->enabled_p
21313 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21314 != CHARPOS (new_start)))
21315 return false;
21316
21317
21318
21319
21320
21321 pt_row = NULL;
21322 for (first_row_to_display = first_reusable_row;
21323 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21324 ++first_row_to_display)
21325 {
21326 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21327 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21328 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21329 && first_row_to_display->ends_at_zv_p
21330 && pt_row == NULL)))
21331 pt_row = first_row_to_display;
21332 }
21333
21334 if (first_row_to_display->y >= yb)
21335 return false;
21336
21337
21338 init_to_row_start (&it, w, first_row_to_display);
21339
21340 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21341 - start_vpos);
21342 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21343 - nrows_scrolled);
21344 it.current_y = (first_row_to_display->y - first_reusable_row->y
21345 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21346
21347
21348
21349
21350 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21351 if (pt_row == NULL)
21352 w->cursor.vpos = -1;
21353 last_text_row = NULL;
21354 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21355 if (display_line (&it, w->cursor.vpos))
21356 last_text_row = it.glyph_row - 1;
21357
21358
21359
21360 if (pt_row)
21361 {
21362 w->cursor.vpos -= nrows_scrolled;
21363 w->cursor.y -= first_reusable_row->y - start_row->y;
21364 }
21365
21366
21367
21368
21369
21370 if (w->cursor.vpos < 0)
21371 {
21372 clear_glyph_matrix (w->desired_matrix);
21373 return false;
21374 }
21375
21376
21377 run.current_y = first_reusable_row->y;
21378 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21379 run.height = it.last_visible_y - run.current_y;
21380 dy = run.current_y - run.desired_y;
21381
21382 if (run.height)
21383 {
21384 #ifdef HAVE_WINDOW_SYSTEM
21385 update_begin (f);
21386 gui_update_window_begin (w);
21387 FRAME_RIF (f)->clear_window_mouse_face (w);
21388 FRAME_RIF (f)->scroll_run_hook (w, &run);
21389 gui_update_window_end (w, false, false);
21390 update_end (f);
21391 #endif
21392 }
21393
21394
21395 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21396 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21397 max_y = it.last_visible_y;
21398 for (row = first_reusable_row; row < first_row_to_display; ++row)
21399 {
21400 row->y -= dy;
21401 row->visible_height = row->height;
21402 if (row->y < min_y)
21403 row->visible_height -= min_y - row->y;
21404 if (row->y + row->height > max_y)
21405 row->visible_height -= row->y + row->height - max_y;
21406 if (row->fringe_bitmap_periodic_p)
21407 row->redraw_fringe_bitmaps_p = true;
21408 }
21409
21410
21411 eassert (nrows_scrolled > 0);
21412 rotate_matrix (w->current_matrix,
21413 start_vpos,
21414 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21415 -nrows_scrolled);
21416
21417
21418 for (row -= nrows_scrolled; row < bottom_row; ++row)
21419 row->enabled_p = false;
21420
21421
21422
21423 if (pt_row)
21424 {
21425 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21426 row < bottom_row
21427 && PT >= MATRIX_ROW_END_CHARPOS (row)
21428 && !row->ends_at_zv_p;
21429 row++)
21430 {
21431 w->cursor.vpos++;
21432 w->cursor.y = row->y;
21433 }
21434 if (row < bottom_row)
21435 {
21436
21437
21438
21439
21440 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21441 {
21442 if (!set_cursor_from_row (w, row, w->current_matrix,
21443 0, 0, 0, 0))
21444 {
21445 clear_glyph_matrix (w->desired_matrix);
21446 return false;
21447 }
21448 }
21449 else
21450 {
21451 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21452 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21453
21454 for (; glyph < end
21455 && (!BUFFERP (glyph->object)
21456 || glyph->charpos < PT);
21457 glyph++)
21458 {
21459 w->cursor.hpos++;
21460 w->cursor.x += glyph->pixel_width;
21461 }
21462 }
21463 }
21464 }
21465
21466
21467
21468
21469 if (last_text_row)
21470 adjust_window_ends (w, last_text_row, false);
21471 else
21472 w->window_end_vpos -= nrows_scrolled;
21473
21474 w->window_end_valid = false;
21475 w->desired_matrix->no_scrolling_p = true;
21476
21477 #ifdef GLYPH_DEBUG
21478 debug_method_add (w, "try_window_reusing_current_matrix 2");
21479 #endif
21480 return true;
21481 }
21482
21483 return false;
21484 }
21485
21486
21487
21488
21489
21490
21491
21492 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21493 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21494 ptrdiff_t *, ptrdiff_t *);
21495 static struct glyph_row *
21496 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21497 struct glyph_row *);
21498
21499
21500
21501
21502
21503
21504
21505 static struct glyph_row *
21506 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21507 struct glyph_row *start)
21508 {
21509 struct glyph_row *row, *row_found;
21510
21511
21512
21513
21514 row_found = NULL;
21515 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21516 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21517 {
21518 eassert (row->enabled_p);
21519 row_found = row;
21520 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21521 break;
21522 ++row;
21523 }
21524
21525 return row_found;
21526 }
21527
21528
21529
21530
21531
21532
21533
21534
21535
21536
21537
21538
21539 static struct glyph_row *
21540 find_last_unchanged_at_beg_row (struct window *w)
21541 {
21542 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21543 struct glyph_row *row;
21544 struct glyph_row *row_found = NULL;
21545 int yb = window_text_bottom_y (w);
21546
21547
21548 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21549 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21550 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21551 ++row)
21552 {
21553 if (
21554
21555 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21556
21557
21558 && !row->ends_at_zv_p
21559
21560
21561
21562 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21563 && (row->continued_p
21564 || row->exact_window_width_line_p))
21565
21566
21567
21568
21569
21570
21571
21572 && CHARPOS (row->end.pos) <= ZV)
21573 row_found = row;
21574
21575
21576 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21577 break;
21578 }
21579
21580 return row_found;
21581 }
21582
21583
21584
21585
21586
21587
21588
21589
21590
21591
21592
21593
21594
21595
21596 static struct glyph_row *
21597 find_first_unchanged_at_end_row (struct window *w,
21598 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21599 {
21600 struct glyph_row *row;
21601 struct glyph_row *row_found = NULL;
21602
21603 *delta = *delta_bytes = 0;
21604
21605
21606
21607 eassert (w->window_end_valid);
21608
21609
21610
21611
21612 if (w->window_end_pos >= END_UNCHANGED)
21613 return NULL;
21614
21615
21616 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21617
21618
21619 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21620 {
21621
21622
21623
21624
21625
21626 ptrdiff_t Z_old =
21627 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21628 ptrdiff_t Z_BYTE_old =
21629 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21630 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21631 struct glyph_row *first_text_row
21632 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21633
21634 *delta = Z - Z_old;
21635 *delta_bytes = Z_BYTE - Z_BYTE_old;
21636
21637
21638
21639
21640
21641
21642
21643 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21644 last_unchanged_pos_old = last_unchanged_pos - *delta;
21645
21646
21647
21648 for (; row > first_text_row; --row)
21649 {
21650
21651
21652 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21653 break;
21654
21655 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21656 row_found = row;
21657 }
21658 }
21659
21660 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21661
21662 return row_found;
21663 }
21664
21665
21666
21667
21668
21669
21670
21671
21672 static void
21673 sync_frame_with_window_matrix_rows (struct window *w)
21674 {
21675 struct frame *f = XFRAME (w->frame);
21676 struct glyph_row *window_row, *window_row_end, *frame_row;
21677
21678
21679
21680 eassert (BUFFERP (w->contents));
21681 eassert (WINDOW_FULL_WIDTH_P (w));
21682 eassert (!FRAME_WINDOW_P (f));
21683
21684
21685
21686
21687
21688 window_row = w->current_matrix->rows;
21689 window_row_end = window_row + w->current_matrix->nrows;
21690 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21691 while (window_row < window_row_end)
21692 {
21693 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21694 struct glyph *end = window_row->glyphs[LAST_AREA];
21695
21696 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21697 frame_row->glyphs[TEXT_AREA] = start;
21698 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21699 frame_row->glyphs[LAST_AREA] = end;
21700
21701
21702
21703 if (!window_row->enabled_p)
21704 frame_row->enabled_p = false;
21705
21706 ++window_row, ++frame_row;
21707 }
21708 }
21709
21710
21711
21712
21713
21714
21715
21716 struct glyph_row *
21717 row_containing_pos (struct window *w, ptrdiff_t charpos,
21718 struct glyph_row *start, struct glyph_row *end, int dy)
21719 {
21720 struct glyph_row *row = start;
21721 struct glyph_row *best_row = NULL;
21722 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21723 int last_y;
21724
21725
21726 if (row->tab_line_p)
21727 ++row;
21728 if (row->mode_line_p)
21729 ++row;
21730
21731 if ((end && row >= end) || !row->enabled_p)
21732 return NULL;
21733
21734 last_y = window_text_bottom_y (w) - dy;
21735
21736 while (true)
21737 {
21738
21739 if ((end && row >= end) || !row->enabled_p)
21740 return NULL;
21741
21742
21743
21744 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21745 return NULL;
21746
21747
21748 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21749 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21750
21751
21752
21753
21754 && !row_for_charpos_p (row, charpos)))
21755 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21756 {
21757 struct glyph *g;
21758
21759 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21760 || (!best_row && !row->continued_p))
21761 return row;
21762
21763
21764
21765
21766 for (g = row->glyphs[TEXT_AREA];
21767 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21768 g++)
21769 {
21770 if (!STRINGP (g->object))
21771 {
21772 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21773 {
21774 mindif = eabs (g->charpos - charpos);
21775 best_row = row;
21776
21777 if (mindif == 0)
21778 return best_row;
21779 }
21780 }
21781 }
21782 }
21783 else if (best_row && !row->continued_p)
21784 return best_row;
21785 ++row;
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
21825
21826
21827
21828
21829
21830
21831
21832 static int
21833 try_window_id (struct window *w)
21834 {
21835 struct frame *f = XFRAME (w->frame);
21836 struct glyph_matrix *current_matrix = w->current_matrix;
21837 struct glyph_matrix *desired_matrix = w->desired_matrix;
21838 struct glyph_row *last_unchanged_at_beg_row;
21839 struct glyph_row *first_unchanged_at_end_row;
21840 struct glyph_row *row;
21841 struct glyph_row *bottom_row;
21842 int bottom_vpos;
21843 struct it it;
21844 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21845 int dvpos, dy;
21846 struct text_pos start_pos;
21847 struct run run;
21848 int first_unchanged_at_end_vpos = 0;
21849 struct glyph_row *last_text_row, *last_text_row_at_end;
21850 struct text_pos start;
21851 ptrdiff_t first_changed_charpos, last_changed_charpos;
21852
21853 #ifdef GLYPH_DEBUG
21854 if (inhibit_try_window_id)
21855 return 0;
21856 #endif
21857
21858
21859 #if false
21860 #define GIVE_UP(X) \
21861 do { \
21862 redisplay_trace ("try_window_id give up %d\n", X); \
21863 return 0; \
21864 } while (false)
21865 #else
21866 #define GIVE_UP(X) return 0
21867 #endif
21868
21869 SET_TEXT_POS_FROM_MARKER (start, w->start);
21870
21871
21872
21873 if (MINI_WINDOW_P (w))
21874 GIVE_UP (1);
21875
21876
21877 if (windows_or_buffers_changed || f->cursor_type_changed)
21878 GIVE_UP (2);
21879
21880
21881
21882
21883 if (w->last_overlay_modified != OVERLAY_MODIFF)
21884 GIVE_UP (200);
21885
21886
21887
21888
21889
21890 if (current_buffer->clip_changed
21891 || current_buffer->prevent_redisplay_optimizations_p)
21892 GIVE_UP (3);
21893
21894
21895 if (!FRAME_WINDOW_P (f)
21896 && (!FRAME_LINE_INS_DEL_OK (f)
21897 || !WINDOW_FULL_WIDTH_P (w)))
21898 GIVE_UP (4);
21899
21900
21901 if (PT < CHARPOS (start))
21902 GIVE_UP (5);
21903
21904
21905 if (w->last_modified == 0)
21906 GIVE_UP (6);
21907
21908
21909 if (w->hscroll != 0)
21910 GIVE_UP (7);
21911
21912
21913 if (!w->window_end_valid)
21914 GIVE_UP (8);
21915
21916
21917 if (!NILP (Vshow_trailing_whitespace))
21918 GIVE_UP (11);
21919
21920
21921
21922 if (overlay_arrows_changed_p (false))
21923 GIVE_UP (12);
21924
21925
21926
21927
21928
21929 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21930 GIVE_UP (21);
21931
21932
21933
21934
21935
21936
21937
21938
21939
21940 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21941 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21942 GIVE_UP (22);
21943
21944
21945
21946 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21947 GIVE_UP (23);
21948
21949
21950
21951 if (EQ (Vdisplay_line_numbers, Qrelative)
21952 || EQ (Vdisplay_line_numbers, Qvisual)
21953 || (!NILP (Vdisplay_line_numbers)
21954 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21955 Qline_number_current_line,
21956 w->frame))))
21957 GIVE_UP (24);
21958
21959
21960
21961
21962 if (composition_break_at_point)
21963 GIVE_UP (27);
21964
21965
21966
21967
21968
21969 if (MODIFF > SAVE_MODIFF
21970
21971 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21972 {
21973 if (GPT - BEG < BEG_UNCHANGED)
21974 BEG_UNCHANGED = GPT - BEG;
21975 if (Z - GPT < END_UNCHANGED)
21976 END_UNCHANGED = Z - GPT;
21977 }
21978
21979
21980 first_changed_charpos = BEG + BEG_UNCHANGED;
21981 last_changed_charpos = Z - END_UNCHANGED;
21982
21983
21984
21985
21986
21987
21988 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21989 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21990 && ((last_changed_charpos < CHARPOS (start)
21991 && CHARPOS (start) == BEGV)
21992 || (last_changed_charpos < CHARPOS (start) - 1
21993 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21994 {
21995 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21996 struct glyph_row *r0;
21997
21998
21999
22000 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
22001 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
22002 Z_delta = Z - Z_old;
22003 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
22004
22005
22006
22007
22008 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
22009 GIVE_UP (13);
22010
22011
22012
22013
22014 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
22015 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
22016 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
22017
22018 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
22019 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
22020 {
22021
22022 if (Z_delta || Z_delta_bytes)
22023 {
22024 struct glyph_row *r1
22025 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22026 increment_matrix_positions (w->current_matrix,
22027 MATRIX_ROW_VPOS (r0, current_matrix),
22028 MATRIX_ROW_VPOS (r1, current_matrix),
22029 Z_delta, Z_delta_bytes);
22030 }
22031
22032
22033 row = row_containing_pos (w, PT, r0, NULL, 0);
22034 if (row)
22035 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
22036 return 1;
22037 }
22038 }
22039
22040
22041
22042
22043
22044 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
22045
22046
22047 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
22048 || first_changed_charpos == last_changed_charpos))
22049 {
22050 struct glyph_row *r0;
22051
22052
22053
22054
22055 if (PT >= MATRIX_ROW_END_CHARPOS (row))
22056 GIVE_UP (14);
22057
22058
22059
22060
22061 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
22062 if (TEXT_POS_EQUAL_P (start, r0->minpos)
22063
22064 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
22065 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
22066 {
22067
22068
22069 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22070 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22071
22072
22073 row = row_containing_pos (w, PT, r0, NULL, 0);
22074 if (row)
22075 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
22076 return 2;
22077 }
22078 }
22079
22080
22081
22082
22083
22084
22085
22086
22087 if (CHARPOS (start) >= first_changed_charpos
22088 && CHARPOS (start) <= last_changed_charpos)
22089 GIVE_UP (15);
22090
22091
22092
22093
22094
22095 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
22096 if (!TEXT_POS_EQUAL_P (start, row->minpos))
22097 GIVE_UP (16);
22098
22099
22100
22101 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
22102 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
22103 GIVE_UP (20);
22104
22105
22106
22107
22108
22109 #ifdef HAVE_NTGUI
22110 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
22111 GIVE_UP (25);
22112 #endif
22113
22114
22115
22116
22117
22118
22119
22120 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
22121 if (last_unchanged_at_beg_row)
22122 {
22123
22124
22125
22126
22127 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
22128 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
22129 && last_unchanged_at_beg_row > w->current_matrix->rows)
22130 --last_unchanged_at_beg_row;
22131
22132 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
22133 GIVE_UP (17);
22134
22135 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
22136 GIVE_UP (18);
22137
22138
22139
22140 if (it.sp > 1
22141 && it.method == GET_FROM_IMAGE && it.image_id == -1)
22142 GIVE_UP (26);
22143 start_pos = it.current.pos;
22144
22145
22146
22147
22148 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
22149 current_matrix);
22150 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22151 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
22152
22153 eassert (it.hpos == 0 && it.current_x == 0);
22154 }
22155 else
22156 {
22157
22158
22159 start_display (&it, w, start);
22160 it.vpos = it.first_vpos;
22161 start_pos = it.current.pos;
22162 }
22163
22164
22165
22166
22167
22168
22169
22170 first_unchanged_at_end_row
22171 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
22172 IF_DEBUG (debug_delta = delta);
22173 IF_DEBUG (debug_delta_bytes = delta_bytes);
22174
22175
22176
22177
22178
22179
22180 stop_pos = 0;
22181 if (first_unchanged_at_end_row)
22182 {
22183 eassert (last_unchanged_at_beg_row == NULL
22184 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
22185
22186
22187
22188
22189
22190 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
22191 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22192 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22193 < it.last_visible_y))
22194 ++first_unchanged_at_end_row;
22195
22196 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22197 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22198 >= it.last_visible_y))
22199 first_unchanged_at_end_row = NULL;
22200 else
22201 {
22202 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
22203 + delta);
22204 first_unchanged_at_end_vpos
22205 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
22206 eassert (stop_pos >= Z - END_UNCHANGED);
22207 }
22208 }
22209 else if (last_unchanged_at_beg_row == NULL)
22210 GIVE_UP (19);
22211
22212
22213 #ifdef GLYPH_DEBUG
22214
22215
22216
22217
22218 eassert (first_unchanged_at_end_row == NULL
22219 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22220
22221 debug_last_unchanged_at_beg_vpos
22222 = (last_unchanged_at_beg_row
22223 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
22224 : -1);
22225 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
22226
22227 #endif
22228
22229
22230
22231
22232
22233 w->cursor.vpos = -1;
22234 last_text_row = NULL;
22235 overlay_arrow_seen = false;
22236 if (it.current_y < it.last_visible_y
22237 && !f->fonts_changed
22238 && (first_unchanged_at_end_row == NULL
22239 || IT_CHARPOS (it) < stop_pos))
22240 it.glyph_row->reversed_p = false;
22241 while (it.current_y < it.last_visible_y
22242 && !f->fonts_changed
22243 && (first_unchanged_at_end_row == NULL
22244 || IT_CHARPOS (it) < stop_pos))
22245 {
22246 if (display_line (&it, -1))
22247 last_text_row = it.glyph_row - 1;
22248 }
22249
22250 if (f->fonts_changed)
22251 return -1;
22252
22253
22254
22255
22256
22257
22258
22259
22260
22261
22262
22263 if (!w->window_end_valid)
22264 {
22265 clear_glyph_matrix (w->desired_matrix);
22266 return -1;
22267 }
22268
22269
22270
22271
22272 if (first_unchanged_at_end_row
22273
22274
22275 && it.current_y < it.last_visible_y)
22276 {
22277 dvpos = (it.vpos
22278 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22279 current_matrix));
22280 dy = it.current_y - first_unchanged_at_end_row->y;
22281 run.current_y = first_unchanged_at_end_row->y;
22282 run.desired_y = run.current_y + dy;
22283 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22284 }
22285 else
22286 {
22287 delta = delta_bytes = dvpos = dy
22288 = run.current_y = run.desired_y = run.height = 0;
22289 first_unchanged_at_end_row = NULL;
22290 }
22291 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22292
22293
22294
22295
22296
22297
22298
22299
22300
22301
22302 if (w->cursor.vpos < 0)
22303 {
22304
22305 if (PT < CHARPOS (start_pos)
22306 && last_unchanged_at_beg_row)
22307 {
22308 row = row_containing_pos (w, PT,
22309 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22310 last_unchanged_at_beg_row + 1, 0);
22311 if (row)
22312 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22313 }
22314
22315
22316 else if (first_unchanged_at_end_row)
22317 {
22318 row = row_containing_pos (w, PT - delta,
22319 first_unchanged_at_end_row, NULL, 0);
22320 if (row)
22321 set_cursor_from_row (w, row, w->current_matrix, delta,
22322 delta_bytes, dy, dvpos);
22323 }
22324
22325
22326 if (w->cursor.vpos < 0)
22327 {
22328 clear_glyph_matrix (w->desired_matrix);
22329 return -1;
22330 }
22331 }
22332
22333
22334 {
22335 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22336 int bot_scroll_margin = top_scroll_margin;
22337 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22338
22339 if (window_wants_header_line (w))
22340 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22341 if (window_wants_tab_line (w))
22342 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22343
22344 if ((w->cursor.y < top_scroll_margin
22345 && CHARPOS (start) > BEGV)
22346
22347
22348 || (w->cursor.y
22349 + (cursor_row_fully_visible_p (w, false, true, true)
22350 ? 1
22351 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22352 {
22353 w->cursor.vpos = -1;
22354 clear_glyph_matrix (w->desired_matrix);
22355 return -1;
22356 }
22357 }
22358
22359
22360
22361
22362 if (dy && run.height)
22363 {
22364 update_begin (f);
22365
22366 if (FRAME_WINDOW_P (f))
22367 {
22368 #ifdef HAVE_WINDOW_SYSTEM
22369 gui_update_window_begin (w);
22370 FRAME_RIF (f)->clear_window_mouse_face (w);
22371 FRAME_RIF (f)->scroll_run_hook (w, &run);
22372 gui_update_window_end (w, false, false);
22373 #endif
22374 }
22375 else
22376 {
22377
22378
22379 int from_vpos
22380 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22381 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22382 int end = (WINDOW_TOP_EDGE_LINE (w)
22383 + window_wants_tab_line (w)
22384 + window_wants_header_line (w)
22385 + window_internal_height (w));
22386
22387 gui_clear_window_mouse_face (w);
22388
22389
22390 if (dvpos > 0)
22391 {
22392
22393
22394 set_terminal_window (f, end);
22395
22396
22397
22398 if (!FRAME_SCROLL_REGION_OK (f))
22399 ins_del_lines (f, end - dvpos, -dvpos);
22400
22401
22402
22403 ins_del_lines (f, from, dvpos);
22404 }
22405 else if (dvpos < 0)
22406 {
22407
22408
22409 set_terminal_window (f, end);
22410
22411
22412
22413
22414
22415 ins_del_lines (f, from + dvpos, dvpos);
22416
22417
22418
22419 if (!FRAME_SCROLL_REGION_OK (f))
22420 ins_del_lines (f, end + dvpos, -dvpos);
22421 }
22422
22423 set_terminal_window (f, 0);
22424 }
22425
22426 update_end (f);
22427 }
22428
22429
22430
22431
22432 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22433 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22434 if (dvpos < 0)
22435 {
22436 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22437 bottom_vpos, dvpos);
22438 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22439 bottom_vpos);
22440 }
22441 else if (dvpos > 0)
22442 {
22443 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22444 bottom_vpos, dvpos);
22445 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22446 first_unchanged_at_end_vpos + dvpos);
22447 }
22448
22449
22450
22451 if (!FRAME_WINDOW_P (f))
22452 sync_frame_with_window_matrix_rows (w);
22453
22454
22455 if (delta || delta_bytes)
22456 increment_matrix_positions (current_matrix,
22457 first_unchanged_at_end_vpos + dvpos,
22458 bottom_vpos, delta, delta_bytes);
22459
22460
22461 if (dy)
22462 shift_glyph_matrix (w, current_matrix,
22463 first_unchanged_at_end_vpos + dvpos,
22464 bottom_vpos, dy);
22465
22466 if (first_unchanged_at_end_row)
22467 {
22468 first_unchanged_at_end_row += dvpos;
22469 if (first_unchanged_at_end_row->y >= it.last_visible_y
22470 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22471 first_unchanged_at_end_row = NULL;
22472 }
22473
22474
22475
22476 last_text_row_at_end = NULL;
22477 if (dy < 0)
22478 {
22479
22480
22481
22482
22483
22484 int last_vpos = w->window_end_vpos + dvpos;
22485 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22486
22487
22488 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22489
22490
22491
22492
22493 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22494 {
22495 init_to_row_start (&it, w, last_row);
22496 it.vpos = last_vpos;
22497 it.current_y = last_row->y;
22498 }
22499 else
22500 {
22501 init_to_row_end (&it, w, last_row);
22502 it.vpos = 1 + last_vpos;
22503 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22504 ++last_row;
22505 }
22506
22507
22508
22509 it.continuation_lines_width = last_row->continuation_lines_width;
22510 it.hpos = it.current_x = 0;
22511
22512
22513 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22514 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22515 {
22516
22517
22518
22519
22520 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22521 if (display_line (&it, w->cursor.vpos))
22522 last_text_row_at_end = it.glyph_row - 1;
22523 }
22524 }
22525
22526
22527 if (first_unchanged_at_end_row && !last_text_row_at_end)
22528 {
22529
22530
22531
22532
22533 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22534 row = find_last_row_displaying_text (w->current_matrix, &it,
22535 first_unchanged_at_end_row);
22536 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22537 adjust_window_ends (w, row, true);
22538 eassert (w->window_end_bytepos >= 0);
22539 IF_DEBUG (debug_method_add (w, "A"));
22540 }
22541 else if (last_text_row_at_end)
22542 {
22543 adjust_window_ends (w, last_text_row_at_end, false);
22544 eassert (w->window_end_bytepos >= 0);
22545 IF_DEBUG (debug_method_add (w, "B"));
22546 }
22547 else if (last_text_row)
22548 {
22549
22550
22551
22552 adjust_window_ends (w, last_text_row, false);
22553 eassert (w->window_end_bytepos >= 0);
22554 }
22555 else if (first_unchanged_at_end_row == NULL
22556 && last_text_row == NULL
22557 && last_text_row_at_end == NULL)
22558 {
22559
22560
22561 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22562 int vpos = w->window_end_vpos;
22563 struct glyph_row *current_row = current_matrix->rows + vpos;
22564 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22565
22566 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22567 {
22568 eassert (first_vpos <= vpos);
22569 if (desired_row->enabled_p)
22570 {
22571 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22572 row = desired_row;
22573 }
22574 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22575 row = current_row;
22576 }
22577
22578 w->window_end_vpos = vpos + 1;
22579 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22580 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22581 eassert (w->window_end_bytepos >= 0);
22582 IF_DEBUG (debug_method_add (w, "C"));
22583 }
22584 else
22585 emacs_abort ();
22586
22587 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22588 debug_end_vpos = w->window_end_vpos));
22589
22590
22591 w->window_end_valid = false;
22592 w->desired_matrix->no_scrolling_p = true;
22593 return 3;
22594
22595 #undef GIVE_UP
22596 }
22597
22598
22599
22600
22601
22602
22603
22604 #ifdef GLYPH_DEBUG
22605
22606 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22607 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22608 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22609
22610
22611
22612
22613
22614
22615
22616
22617 void
22618 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22619 {
22620 int i;
22621 for (i = 0; i < matrix->nrows; ++i)
22622 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22623 }
22624
22625
22626
22627
22628
22629 void
22630 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22631 {
22632 if (glyph->type == CHAR_GLYPH
22633 || glyph->type == GLYPHLESS_GLYPH)
22634 {
22635 fprintf (stderr,
22636 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22637 glyph - row->glyphs[TEXT_AREA],
22638 (glyph->type == CHAR_GLYPH
22639 ? 'C'
22640 : 'G'),
22641 glyph->charpos,
22642 (BUFFERP (glyph->object)
22643 ? 'B'
22644 : (STRINGP (glyph->object)
22645 ? 'S'
22646 : (NILP (glyph->object)
22647 ? '0'
22648 : '-'))),
22649 glyph->pixel_width,
22650 glyph->u.ch,
22651 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22652 ? (int) glyph->u.ch
22653 : '.'),
22654 glyph->face_id,
22655 glyph->left_box_line_p,
22656 glyph->right_box_line_p);
22657 }
22658 else if (glyph->type == STRETCH_GLYPH)
22659 {
22660 fprintf (stderr,
22661 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22662 glyph - row->glyphs[TEXT_AREA],
22663 'S',
22664 glyph->charpos,
22665 (BUFFERP (glyph->object)
22666 ? 'B'
22667 : (STRINGP (glyph->object)
22668 ? 'S'
22669 : (NILP (glyph->object)
22670 ? '0'
22671 : '-'))),
22672 glyph->pixel_width,
22673 0u,
22674 ' ',
22675 glyph->face_id,
22676 glyph->left_box_line_p,
22677 glyph->right_box_line_p);
22678 }
22679 else if (glyph->type == IMAGE_GLYPH)
22680 {
22681 fprintf (stderr,
22682 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22683 glyph - row->glyphs[TEXT_AREA],
22684 'I',
22685 glyph->charpos,
22686 (BUFFERP (glyph->object)
22687 ? 'B'
22688 : (STRINGP (glyph->object)
22689 ? 'S'
22690 : (NILP (glyph->object)
22691 ? '0'
22692 : '-'))),
22693 glyph->pixel_width,
22694 (unsigned int) glyph->u.img_id,
22695 '.',
22696 glyph->face_id,
22697 glyph->left_box_line_p,
22698 glyph->right_box_line_p);
22699 }
22700 else if (glyph->type == COMPOSITE_GLYPH)
22701 {
22702 fprintf (stderr,
22703 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22704 glyph - row->glyphs[TEXT_AREA],
22705 '+',
22706 glyph->charpos,
22707 (BUFFERP (glyph->object)
22708 ? 'B'
22709 : (STRINGP (glyph->object)
22710 ? 'S'
22711 : (NILP (glyph->object)
22712 ? '0'
22713 : '-'))),
22714 glyph->pixel_width,
22715 (unsigned int) glyph->u.cmp.id);
22716 if (glyph->u.cmp.automatic)
22717 fprintf (stderr,
22718 "[%d-%d]",
22719 glyph->slice.cmp.from, glyph->slice.cmp.to);
22720 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22721 glyph->face_id,
22722 glyph->left_box_line_p,
22723 glyph->right_box_line_p);
22724 }
22725 else if (glyph->type == XWIDGET_GLYPH)
22726 {
22727 #ifndef HAVE_XWIDGETS
22728 eassume (false);
22729 #else
22730 fprintf (stderr,
22731 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22732 glyph - row->glyphs[TEXT_AREA],
22733 'X',
22734 glyph->charpos,
22735 (BUFFERP (glyph->object)
22736 ? 'B'
22737 : (STRINGP (glyph->object)
22738 ? 'S'
22739 : '-')),
22740 glyph->pixel_width,
22741 glyph->u.xwidget,
22742 '.',
22743 glyph->face_id,
22744 glyph->left_box_line_p,
22745 glyph->right_box_line_p);
22746 #endif
22747 }
22748 }
22749
22750
22751
22752
22753
22754
22755
22756 void
22757 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22758 {
22759 if (glyphs != 1)
22760 {
22761 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22762 "==============================================================================\n"),
22763 stderr);
22764 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22765 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22766 vpos,
22767 MATRIX_ROW_START_CHARPOS (row),
22768 MATRIX_ROW_END_CHARPOS (row),
22769 row->used[TEXT_AREA],
22770 row->contains_overlapping_glyphs_p,
22771 row->enabled_p,
22772 row->truncated_on_left_p,
22773 row->truncated_on_right_p,
22774 row->continued_p,
22775 MATRIX_ROW_CONTINUATION_LINE_P (row),
22776 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22777 row->ends_at_zv_p,
22778 row->fill_line_p,
22779 row->ends_in_middle_of_char_p,
22780 row->starts_in_middle_of_char_p,
22781 row->mouse_face_p,
22782 row->x,
22783 row->y,
22784 row->pixel_width,
22785 row->height,
22786 row->visible_height,
22787 row->ascent,
22788 row->phys_ascent);
22789
22790 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22791 row->end.overlay_string_index,
22792 row->continuation_lines_width);
22793 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22794 CHARPOS (row->start.string_pos),
22795 CHARPOS (row->end.string_pos));
22796 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22797 row->end.dpvec_index);
22798 }
22799
22800 if (glyphs > 1)
22801 {
22802 int area;
22803
22804 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22805 {
22806 struct glyph *glyph = row->glyphs[area];
22807 struct glyph *glyph_end = glyph + row->used[area];
22808
22809
22810 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22811 ++glyph_end;
22812
22813 if (glyph < glyph_end)
22814 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22815 stderr);
22816
22817 for (; glyph < glyph_end; ++glyph)
22818 dump_glyph (row, glyph, area);
22819 }
22820 }
22821 else if (glyphs == 1)
22822 {
22823 int area;
22824 char s[SHRT_MAX + 4];
22825
22826 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22827 {
22828 int i;
22829
22830 for (i = 0; i < row->used[area]; ++i)
22831 {
22832 struct glyph *glyph = row->glyphs[area] + i;
22833 if (i == row->used[area] - 1
22834 && area == TEXT_AREA
22835 && NILP (glyph->object)
22836 && glyph->type == CHAR_GLYPH
22837 && glyph->u.ch == ' ')
22838 {
22839 strcpy (&s[i], "[\\n]");
22840 i += 4;
22841 }
22842 else if (glyph->type == CHAR_GLYPH
22843 && glyph->u.ch < 0x80
22844 && glyph->u.ch >= ' ')
22845 s[i] = glyph->u.ch;
22846 else
22847 s[i] = '.';
22848 }
22849
22850 s[i] = '\0';
22851 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22852 }
22853 }
22854 }
22855
22856
22857 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22858 Sdump_glyph_matrix, 0, 1, "p",
22859 doc:
22860
22861
22862
22863
22864
22865 )
22866 (Lisp_Object glyphs)
22867 {
22868 struct window *w = XWINDOW (selected_window);
22869 struct buffer *buffer = XBUFFER (w->contents);
22870
22871 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22872 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22873 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22874 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22875 fputs ("=============================================\n", stderr);
22876 dump_glyph_matrix (w->current_matrix,
22877 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22878 return Qnil;
22879 }
22880
22881
22882 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22883 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22884 )
22885 (void)
22886 {
22887 struct frame *f = XFRAME (selected_frame);
22888
22889 if (f->current_matrix)
22890 dump_glyph_matrix (f->current_matrix, 1);
22891 else
22892 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22893 return Qnil;
22894 }
22895
22896
22897 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22898 doc:
22899
22900
22901
22902
22903 )
22904 (Lisp_Object row, Lisp_Object glyphs)
22905 {
22906 struct glyph_matrix *matrix;
22907 EMACS_INT vpos;
22908
22909 if (NILP (row))
22910 {
22911 int d1, d2, d3, d4, d5, ypos;
22912 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22913 &d1, &d2, &d3, &d4, &d5, &ypos);
22914 if (visible_p)
22915 vpos = ypos;
22916 else
22917 vpos = 0;
22918 }
22919 else
22920 {
22921 CHECK_FIXNUM (row);
22922 vpos = XFIXNUM (row);
22923 }
22924 matrix = XWINDOW (selected_window)->current_matrix;
22925 if (vpos >= 0 && vpos < matrix->nrows)
22926 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22927 vpos,
22928 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22929 return Qnil;
22930 }
22931
22932
22933 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22934 doc:
22935
22936
22937
22938
22939
22940
22941 )
22942 (Lisp_Object row, Lisp_Object glyphs)
22943 {
22944 #if defined (HAVE_WINDOW_SYSTEM)
22945 struct frame *sf = SELECTED_FRAME ();
22946 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22947 ? XWINDOW (sf->tab_bar_window)->current_matrix
22948 : sf->current_matrix;
22949 EMACS_INT vpos;
22950
22951 if (NILP (row))
22952 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22953 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22954 else
22955 {
22956 CHECK_FIXNUM (row);
22957 vpos = XFIXNUM (row);
22958 }
22959 if (vpos >= 0 && vpos < m->nrows)
22960 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22961 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22962 #endif
22963 return Qnil;
22964 }
22965
22966 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22967 doc:
22968
22969
22970
22971
22972
22973
22974 )
22975 (Lisp_Object row, Lisp_Object glyphs)
22976 {
22977 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22978 struct frame *sf = SELECTED_FRAME ();
22979 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22980 EMACS_INT vpos;
22981
22982 if (NILP (row))
22983 vpos = 0;
22984 else
22985 {
22986 CHECK_FIXNUM (row);
22987 vpos = XFIXNUM (row);
22988 }
22989 if (vpos >= 0 && vpos < m->nrows)
22990 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22991 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22992 #endif
22993 return Qnil;
22994 }
22995
22996
22997 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22998 doc:
22999 )
23000 (Lisp_Object arg)
23001 {
23002 if (NILP (arg))
23003 trace_redisplay_p = !trace_redisplay_p;
23004 else
23005 {
23006 arg = Fprefix_numeric_value (arg);
23007 trace_redisplay_p = XFIXNUM (arg) > 0;
23008 }
23009
23010 return Qnil;
23011 }
23012
23013
23014 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
23015 doc:
23016 )
23017 (ptrdiff_t nargs, Lisp_Object *args)
23018 {
23019 Lisp_Object s = Fformat (nargs, args);
23020 fwrite (SDATA (s), 1, SBYTES (s), stderr);
23021 return Qnil;
23022 }
23023
23024 #endif
23025
23026
23027
23028
23029
23030
23031
23032
23033
23034
23035
23036 static struct glyph_row *
23037 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
23038 {
23039 struct frame *f = XFRAME (WINDOW_FRAME (w));
23040 struct buffer *buffer = XBUFFER (w->contents);
23041 struct buffer *old = current_buffer;
23042 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
23043 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
23044 const unsigned char *arrow_end = arrow_string + arrow_len;
23045 const unsigned char *p;
23046 struct it it;
23047 bool multibyte_p;
23048 int n_glyphs_before;
23049
23050 set_buffer_temp (buffer);
23051 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
23052 scratch_glyph_row.reversed_p = false;
23053 it.glyph_row->used[TEXT_AREA] = 0;
23054 SET_TEXT_POS (it.position, 0, 0);
23055
23056 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
23057 p = arrow_string;
23058 while (p < arrow_end)
23059 {
23060 Lisp_Object face, ilisp;
23061
23062
23063 if (multibyte_p)
23064 it.c = it.char_to_display = check_char_and_length (p, &it.len);
23065 else
23066 {
23067 it.c = it.char_to_display = *p, it.len = 1;
23068 if (! ASCII_CHAR_P (it.c))
23069 it.char_to_display = BYTE8_TO_CHAR (it.c);
23070 }
23071 p += it.len;
23072
23073
23074 ilisp = make_fixnum (char_num++);
23075 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
23076 it.face_id = compute_char_face (f, it.char_to_display, face);
23077
23078
23079 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
23080 SET_TEXT_POS (it.position, -1, -1);
23081 PRODUCE_GLYPHS (&it);
23082
23083
23084
23085 if (it.current_x > it.last_visible_x)
23086 {
23087 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
23088 break;
23089 }
23090 }
23091
23092 set_buffer_temp (old);
23093 return it.glyph_row;
23094 }
23095
23096
23097
23098
23099
23100 static void
23101 insert_left_trunc_glyphs (struct it *it)
23102 {
23103 struct it truncate_it;
23104 struct glyph *from, *end, *to, *toend;
23105
23106 eassert (!FRAME_WINDOW_P (it->f)
23107 || (!it->glyph_row->reversed_p
23108 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23109 || (it->glyph_row->reversed_p
23110 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
23111
23112
23113 truncate_it = *it;
23114 truncate_it.current_x = 0;
23115 truncate_it.face_id = DEFAULT_FACE_ID;
23116 truncate_it.glyph_row = &scratch_glyph_row;
23117 truncate_it.area = TEXT_AREA;
23118 truncate_it.glyph_row->used[TEXT_AREA] = 0;
23119 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
23120 truncate_it.object = Qnil;
23121 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
23122
23123
23124 if (!it->glyph_row->reversed_p)
23125 {
23126 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23127
23128 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23129 end = from + tused;
23130 to = it->glyph_row->glyphs[TEXT_AREA];
23131 toend = to + it->glyph_row->used[TEXT_AREA];
23132 if (FRAME_WINDOW_P (it->f))
23133 {
23134
23135
23136
23137
23138
23139
23140
23141 int w = 0;
23142 struct glyph *g = to;
23143 short used;
23144
23145
23146
23147
23148
23149
23150 it->glyph_row->x = 0;
23151 while (g < toend && w < it->truncation_pixel_width)
23152 {
23153 w += g->pixel_width;
23154 ++g;
23155 }
23156 if (g - to - tused > 0)
23157 {
23158 memmove (to + tused, g, (toend - g) * sizeof(*g));
23159 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
23160 }
23161 used = it->glyph_row->used[TEXT_AREA];
23162 if (it->glyph_row->truncated_on_right_p
23163 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
23164 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
23165 == STRETCH_GLYPH)
23166 {
23167 int extra = w - it->truncation_pixel_width;
23168
23169 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
23170 }
23171 }
23172
23173 while (from < end)
23174 *to++ = *from++;
23175
23176
23177 if (!FRAME_WINDOW_P (it->f))
23178 {
23179 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
23180 {
23181 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23182 while (from < end)
23183 *to++ = *from++;
23184 }
23185 }
23186
23187 if (to > toend)
23188 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
23189 }
23190 else
23191 {
23192 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23193
23194
23195
23196 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
23197 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23198 toend = it->glyph_row->glyphs[TEXT_AREA];
23199 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
23200 if (FRAME_WINDOW_P (it->f))
23201 {
23202 int w = 0;
23203 struct glyph *g = to;
23204
23205 while (g >= toend && w < it->truncation_pixel_width)
23206 {
23207 w += g->pixel_width;
23208 --g;
23209 }
23210 if (to - g - tused > 0)
23211 to = g + tused;
23212 if (it->glyph_row->truncated_on_right_p
23213 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
23214 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
23215 {
23216 int extra = w - it->truncation_pixel_width;
23217
23218 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
23219 }
23220 }
23221
23222 while (from >= end && to >= toend)
23223 *to-- = *from--;
23224 if (!FRAME_WINDOW_P (it->f))
23225 {
23226 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
23227 {
23228 from =
23229 truncate_it.glyph_row->glyphs[TEXT_AREA]
23230 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23231 while (from >= end && to >= toend)
23232 *to-- = *from--;
23233 }
23234 }
23235 if (from >= end)
23236 {
23237
23238
23239 int move_by = from - end + 1;
23240 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
23241 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
23242
23243 for ( ; g >= g0; g--)
23244 g[move_by] = *g;
23245 while (from >= end)
23246 *to-- = *from--;
23247 it->glyph_row->used[TEXT_AREA] += move_by;
23248 }
23249 }
23250 }
23251
23252
23253 unsigned
23254 row_hash (struct glyph_row *row)
23255 {
23256 int area, k;
23257 unsigned hashval = 0;
23258
23259 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23260 for (k = 0; k < row->used[area]; ++k)
23261 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23262 + row->glyphs[area][k].u.val
23263 + row->glyphs[area][k].face_id
23264 + row->glyphs[area][k].padding_p
23265 + (row->glyphs[area][k].type << 2));
23266
23267 return hashval;
23268 }
23269
23270
23271
23272
23273
23274
23275
23276
23277
23278
23279
23280
23281
23282
23283
23284
23285
23286
23287 static void
23288 compute_line_metrics (struct it *it)
23289 {
23290 struct glyph_row *row = it->glyph_row;
23291
23292 if (FRAME_WINDOW_P (it->f))
23293 {
23294 int i, min_y, max_y;
23295
23296
23297
23298
23299 if (row->height == 0)
23300 {
23301 if (it->max_ascent + it->max_descent == 0)
23302 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23303 row->ascent = it->max_ascent;
23304 row->height = it->max_ascent + it->max_descent;
23305 row->phys_ascent = it->max_phys_ascent;
23306 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23307 row->extra_line_spacing = it->max_extra_line_spacing;
23308 }
23309
23310
23311 row->pixel_width = row->x;
23312 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23313 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23314
23315 eassert (row->pixel_width >= 0);
23316 eassert (row->ascent >= 0 && row->height > 0);
23317
23318 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23319 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23320
23321
23322
23323
23324 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23325 && row->phys_ascent > row->ascent)
23326 {
23327 row->height += row->phys_ascent - row->ascent;
23328 row->ascent = row->phys_ascent;
23329 }
23330
23331
23332 row->visible_height = row->height;
23333
23334 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23335 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23336
23337 if (row->y < min_y)
23338 row->visible_height -= min_y - row->y;
23339 if (row->y + row->height > max_y)
23340 row->visible_height -= row->y + row->height - max_y;
23341 }
23342 else
23343 {
23344 row->pixel_width = row->used[TEXT_AREA];
23345 if (row->continued_p)
23346 row->pixel_width -= it->continuation_pixel_width;
23347 else if (row->truncated_on_right_p)
23348 row->pixel_width -= it->truncation_pixel_width;
23349 row->ascent = row->phys_ascent = 0;
23350 row->height = row->phys_height = row->visible_height = 1;
23351 row->extra_line_spacing = 0;
23352 }
23353
23354
23355 row->hash = row_hash (row);
23356
23357 it->max_ascent = it->max_descent = 0;
23358 it->max_phys_ascent = it->max_phys_descent = 0;
23359 }
23360
23361
23362 static void
23363 clear_position (struct it *it)
23364 {
23365 it->position.charpos = 0;
23366 it->position.bytepos = 0;
23367 }
23368
23369
23370
23371
23372
23373
23374
23375
23376
23377
23378
23379
23380
23381 static bool
23382 append_space_for_newline (struct it *it, bool default_face_p)
23383 {
23384 int n = it->glyph_row->used[TEXT_AREA];
23385
23386 if (it->glyph_row->glyphs[TEXT_AREA] + n
23387 < it->glyph_row->glyphs[1 + TEXT_AREA])
23388 {
23389
23390
23391
23392
23393 enum display_element_type saved_what = it->what;
23394 int saved_c = it->c, saved_len = it->len;
23395 int saved_char_to_display = it->char_to_display;
23396 int saved_x = it->current_x;
23397 const int saved_face_id = it->face_id;
23398 bool saved_box_end = it->end_of_box_run_p;
23399 struct text_pos saved_pos = it->position;
23400 Lisp_Object saved_object = it->object;
23401 struct face *face;
23402
23403 it->what = IT_CHARACTER;
23404 clear_position (it);
23405 it->object = Qnil;
23406 it->len = 1;
23407
23408 int char_width = 1;
23409
23410 if (default_face_p
23411 #ifdef HAVE_WINDOW_SYSTEM
23412 || FRAME_WINDOW_P (it->f)
23413 #endif
23414 )
23415 {
23416 const int local_default_face_id =
23417 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23418
23419 #ifdef HAVE_WINDOW_SYSTEM
23420 if (FRAME_WINDOW_P (it->f))
23421 {
23422 struct face *default_face
23423 = FACE_FROM_ID (it->f, local_default_face_id);
23424 struct font *font = (default_face->font
23425 ? default_face->font
23426 : FRAME_FONT (it->f));
23427 char_width = (font->average_width
23428 ? font->average_width
23429 : font->space_width);
23430 }
23431 #endif
23432 if (default_face_p)
23433 it->face_id = local_default_face_id;
23434 }
23435
23436
23437
23438
23439 const int indicator_column =
23440 fill_column_indicator_column (it, char_width);
23441 int saved_end_of_box_run = it->end_of_box_run_p;
23442 bool should_keep_end_of_box_run = false;
23443
23444 if (it->current_x == indicator_column)
23445 {
23446 it->c = it->char_to_display
23447 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23448 it->face_id
23449 = merge_faces (it->w, Qfill_column_indicator,
23450 0, saved_face_id);
23451 face = FACE_FROM_ID (it->f, it->face_id);
23452 }
23453 else
23454 {
23455 it->c = it->char_to_display = ' ';
23456
23457
23458
23459 face = FACE_FROM_ID (it->f, it->face_id);
23460 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23461
23462
23463
23464
23465 if (!(it->glyph_row->reversed_p
23466
23467
23468
23469 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23470 should_keep_end_of_box_run = true;
23471 }
23472 PRODUCE_GLYPHS (it);
23473
23474
23475 if (should_keep_end_of_box_run)
23476 it->end_of_box_run_p = saved_end_of_box_run;
23477 #ifdef HAVE_WINDOW_SYSTEM
23478 if (FRAME_WINDOW_P (it->f))
23479 {
23480
23481
23482
23483 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23484 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23485 if (n == 0)
23486 {
23487 Lisp_Object height, total_height;
23488 int extra_line_spacing = it->extra_line_spacing;
23489 int boff = font->baseline_offset;
23490
23491 if (font->vertical_centering)
23492 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23493
23494 it->object = saved_object;
23495 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23496
23497
23498 height = get_it_property (it, Qline_height);
23499 if (CONSP (height)
23500 && CONSP (XCDR (height))
23501 && NILP (XCDR (XCDR (height))))
23502 {
23503 total_height = XCAR (XCDR (height));
23504 height = XCAR (height);
23505 }
23506 else
23507 total_height = Qnil;
23508 height = calc_line_height_property (it, height, font, boff, true);
23509
23510 if (it->override_ascent >= 0)
23511 {
23512 it->ascent = it->override_ascent;
23513 it->descent = it->override_descent;
23514 boff = it->override_boff;
23515 }
23516 if (EQ (height, Qt))
23517 extra_line_spacing = 0;
23518 else
23519 {
23520 Lisp_Object spacing;
23521
23522 it->phys_ascent = it->ascent;
23523 it->phys_descent = it->descent;
23524 if (!NILP (height)
23525 && XFIXNUM (height) > it->ascent + it->descent)
23526 it->ascent = XFIXNUM (height) - it->descent;
23527
23528 if (!NILP (total_height))
23529 spacing = calc_line_height_property (it, total_height, font,
23530 boff, false);
23531 else
23532 {
23533 spacing = get_it_property (it, Qline_spacing);
23534 spacing = calc_line_height_property (it, spacing, font,
23535 boff, false);
23536 }
23537 if (FIXNUMP (spacing))
23538 {
23539 extra_line_spacing = XFIXNUM (spacing);
23540 if (!NILP (total_height))
23541 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23542 }
23543 }
23544 if (extra_line_spacing > 0)
23545 {
23546 it->descent += extra_line_spacing;
23547 if (extra_line_spacing > it->max_extra_line_spacing)
23548 it->max_extra_line_spacing = extra_line_spacing;
23549 }
23550 it->max_ascent = it->ascent;
23551 it->max_descent = it->descent;
23552
23553 it->glyph_row->height = 0;
23554 }
23555
23556 g->ascent = it->max_ascent;
23557 g->descent = it->max_descent;
23558 }
23559 #endif
23560 it->override_ascent = -1;
23561 it->constrain_row_ascent_descent_p = false;
23562 it->current_x = saved_x;
23563 it->object = saved_object;
23564 it->position = saved_pos;
23565 it->what = saved_what;
23566 it->face_id = saved_face_id;
23567 it->len = saved_len;
23568 it->c = saved_c;
23569 it->char_to_display = saved_char_to_display;
23570 it->end_of_box_run_p = saved_box_end;
23571 return true;
23572 }
23573
23574 return false;
23575 }
23576
23577
23578
23579
23580
23581
23582
23583
23584
23585 static void
23586 extend_face_to_end_of_line (struct it *it)
23587 {
23588 struct frame *f = it->f;
23589
23590
23591
23592
23593
23594
23595 if ((it->current_x >= it->last_visible_x
23596 + (!FRAME_WINDOW_P (f)
23597 && it->glyph_row->reversed_p
23598 && !it->glyph_row->continued_p))
23599
23600
23601 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23602 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23603 return;
23604
23605 specpdl_ref count = SPECPDL_INDEX ();
23606
23607
23608
23609
23610 specbind (Qinhibit_quit, Qt);
23611
23612 struct face *default_face =
23613 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23614 if (!default_face)
23615 return;
23616
23617 const int extend_face_id =
23618 (it->face_id == default_face->id || it->s != NULL)
23619 ? it->face_id
23620 : (it->glyph_row->ends_at_zv_p
23621 ? default_face->id
23622 : face_at_pos (it, LFACE_EXTEND_INDEX));
23623 unbind_to (count, Qnil);
23624
23625
23626
23627
23628 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23629 ? it->saved_face_id
23630 : extend_face_id));
23631
23632 if (FRAME_WINDOW_P (f)
23633 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23634 && face->box == FACE_NO_BOX
23635 && face->underline == FACE_NO_UNDERLINE
23636 && !face->overline_p
23637 && !face->strike_through_p
23638 && face->background == FRAME_BACKGROUND_PIXEL (f)
23639 #ifdef HAVE_WINDOW_SYSTEM
23640 && !face->stipple
23641 #endif
23642 && !it->glyph_row->reversed_p
23643 && !display_fill_column_indicator)
23644 return;
23645
23646
23647
23648 it->glyph_row->fill_line_p = true;
23649
23650 const int orig_face_id = it->face_id;
23651
23652
23653
23654
23655
23656 if (!ASCII_CHAR_P (it->c))
23657 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23658
23659
23660 #ifdef HAVE_WINDOW_SYSTEM
23661 if (FRAME_WINDOW_P (f))
23662 {
23663
23664
23665 if (it->glyph_row->used[TEXT_AREA] == 0)
23666 {
23667 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23668 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23669 it->glyph_row->used[TEXT_AREA] = 1;
23670 }
23671
23672
23673 if (!(it->glyph_row->mode_line_p
23674 || (WINDOWP (f->tab_bar_window)
23675 && it->w == XWINDOW (f->tab_bar_window))
23676 #ifndef HAVE_EXT_TOOL_BAR
23677 || (WINDOWP (f->tool_bar_window)
23678 && it->w == XWINDOW (f->tool_bar_window))
23679 #endif
23680 ))
23681 {
23682 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23683 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23684 {
23685 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23686 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23687 default_face->id;
23688 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23689 }
23690 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23691 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23692 {
23693 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23694 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23695 default_face->id;
23696 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23697 }
23698
23699 struct font *font = (default_face->font
23700 ? default_face->font
23701 : FRAME_FONT (f));
23702
23703 const int char_width = (font->average_width
23704 ? font->average_width
23705 : font->space_width);
23706
23707 const int indicator_column =
23708 fill_column_indicator_column (it, char_width);
23709
23710 const char saved_char = it->char_to_display;
23711 const struct text_pos saved_pos = it->position;
23712 const bool saved_avoid_cursor = it->avoid_cursor_p;
23713 const bool saved_box_start = it->start_of_box_run_p;
23714 Lisp_Object save_object = it->object;
23715 const int saved_face_id = it->face_id;
23716
23717 it->face_id = extend_face_id;
23718 it->avoid_cursor_p = true;
23719 it->object = Qnil;
23720
23721 const int stretch_height = it->ascent + it->descent;
23722 const int stretch_ascent =
23723 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23724
23725 if (indicator_column >= 0
23726 && indicator_column > it->current_x
23727 && indicator_column < it->last_visible_x)
23728 {
23729
23730
23731
23732
23733 const int stretch_width =
23734 indicator_column - it->current_x - char_width;
23735
23736 clear_position (it);
23737
23738
23739
23740 if (stretch_width > 0)
23741 {
23742 append_stretch_glyph (it, Qnil, stretch_width,
23743 stretch_height, stretch_ascent);
23744 }
23745
23746
23747
23748 if (it->current_x < indicator_column)
23749 {
23750 const int save_face_id = it->face_id;
23751 const int save_ascent = it->ascent;
23752 const int save_descent = it->descent;
23753 it->char_to_display
23754 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23755 it->face_id
23756 = merge_faces (it->w, Qfill_column_indicator,
23757 0, extend_face_id);
23758 PRODUCE_GLYPHS (it);
23759 it->face_id = save_face_id;
23760 it->ascent = save_ascent;
23761 it->descent = save_descent;
23762 }
23763 }
23764
23765
23766
23767 if (!it->glyph_row->reversed_p)
23768 {
23769 const int stretch_width = it->last_visible_x - it->current_x;
23770
23771 if (stretch_width > 0)
23772 {
23773 clear_position (it);
23774 append_stretch_glyph (it, Qnil, stretch_width,
23775 stretch_height, stretch_ascent);
23776 }
23777 }
23778
23779 it->char_to_display = saved_char;
23780 it->position = saved_pos;
23781 it->avoid_cursor_p = saved_avoid_cursor;
23782 it->start_of_box_run_p = saved_box_start;
23783 it->object = save_object;
23784 it->face_id = saved_face_id;
23785 }
23786 if (it->glyph_row->reversed_p)
23787 {
23788
23789
23790
23791
23792
23793 struct font *font = face->font ? face->font : FRAME_FONT (f);
23794 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23795 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23796 struct glyph *g;
23797 int row_width, stretch_ascent, stretch_width;
23798 struct text_pos saved_pos;
23799 int saved_face_id;
23800 bool saved_avoid_cursor, saved_box_start;
23801
23802 for (row_width = 0, g = row_start; g < row_end; g++)
23803 row_width += g->pixel_width;
23804
23805
23806
23807
23808 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23809 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23810 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23811 stretch_width = window_box_width (it->w, TEXT_AREA);
23812 else
23813 stretch_width = it->last_visible_x - it->first_visible_x;
23814 stretch_width -= row_width;
23815
23816 if (stretch_width > 0)
23817 {
23818 stretch_ascent =
23819 (((it->ascent + it->descent)
23820 * FONT_BASE (font)) / FONT_HEIGHT (font));
23821 saved_pos = it->position;
23822 clear_position (it);
23823 saved_avoid_cursor = it->avoid_cursor_p;
23824 it->avoid_cursor_p = true;
23825 saved_face_id = it->face_id;
23826 saved_box_start = it->start_of_box_run_p;
23827
23828
23829
23830 it->face_id = (it->glyph_row->ends_at_zv_p ?
23831 default_face->id : face->id);
23832
23833 it->start_of_box_run_p = false;
23834 append_stretch_glyph (it, Qnil, stretch_width,
23835 it->ascent + it->descent, stretch_ascent);
23836 it->position = saved_pos;
23837 it->avoid_cursor_p = saved_avoid_cursor;
23838 it->face_id = saved_face_id;
23839 it->start_of_box_run_p = saved_box_start;
23840 }
23841
23842
23843
23844
23845 if (stretch_width < 0)
23846 it->glyph_row->x = stretch_width;
23847 }
23848 it->face_id = orig_face_id;
23849 }
23850 else
23851 #endif
23852 {
23853
23854 int saved_x = it->current_x;
23855 struct text_pos saved_pos = it->position;
23856 Lisp_Object saved_object = it->object;;
23857 enum display_element_type saved_what = it->what;
23858
23859 it->what = IT_CHARACTER;
23860 clear_position (it);
23861 it->object = Qnil;
23862 it->c = it->char_to_display = ' ';
23863 it->len = 1;
23864
23865 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23866 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23867 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23868 && !it->glyph_row->mode_line_p
23869 && face->background != FRAME_BACKGROUND_PIXEL (f))
23870 {
23871 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23872 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23873
23874 for (it->current_x = 0; g < e; g++)
23875 it->current_x += g->pixel_width;
23876
23877 it->area = LEFT_MARGIN_AREA;
23878 it->face_id = default_face->id;
23879 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23880 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23881 && g < it->glyph_row->glyphs[TEXT_AREA])
23882 {
23883 PRODUCE_GLYPHS (it);
23884
23885
23886 it->current_x += it->pixel_width;
23887 g++;
23888 }
23889
23890 it->current_x = saved_x;
23891 it->area = TEXT_AREA;
23892 }
23893
23894
23895
23896
23897 it->face_id = (it->glyph_row->ends_at_zv_p ?
23898 default_face->id : face->id);
23899
23900
23901
23902
23903
23904 it->current_x = it->glyph_row->used[TEXT_AREA];
23905
23906
23907
23908
23909
23910
23911
23912
23913 const int indicator_column =
23914 fill_column_indicator_column (it, 1) - it->first_visible_x;
23915
23916
23917 while (it->current_x <= it->last_visible_x)
23918 {
23919 if (it->current_x != indicator_column)
23920 PRODUCE_GLYPHS (it);
23921 else
23922 {
23923 int saved_face_id = it->face_id;
23924 it->face_id
23925 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23926 it->c = it->char_to_display
23927 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23928
23929 PRODUCE_GLYPHS (it);
23930
23931 it->face_id = saved_face_id;
23932 it->c = it->char_to_display = ' ';
23933 }
23934 }
23935
23936 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23937 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23938 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23939 && !it->glyph_row->mode_line_p
23940 && face->background != FRAME_BACKGROUND_PIXEL (f))
23941 {
23942 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23943 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23944
23945 for ( ; g < e; g++)
23946 it->current_x += g->pixel_width;
23947
23948 it->area = RIGHT_MARGIN_AREA;
23949 it->face_id = default_face->id;
23950 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23951 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23952 && g < it->glyph_row->glyphs[LAST_AREA])
23953 {
23954 PRODUCE_GLYPHS (it);
23955 it->current_x += it->pixel_width;
23956 g++;
23957 }
23958
23959 it->area = TEXT_AREA;
23960 }
23961
23962
23963
23964 it->current_x = saved_x;
23965 it->object = saved_object;
23966 it->position = saved_pos;
23967 it->what = saved_what;
23968 it->face_id = orig_face_id;
23969 }
23970 }
23971
23972
23973
23974
23975
23976 static bool
23977 trailing_whitespace_p (ptrdiff_t charpos)
23978 {
23979 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23980 int c = 0;
23981
23982 while (bytepos < ZV_BYTE
23983 && (c = FETCH_BYTE (bytepos),
23984 c == ' ' || c == '\t'))
23985 ++bytepos;
23986
23987 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23988 {
23989 if (bytepos != PT_BYTE)
23990 return true;
23991 }
23992 return false;
23993 }
23994
23995
23996
23997
23998 static void
23999 highlight_trailing_whitespace (struct it *it)
24000 {
24001 struct glyph_row *row = it->glyph_row;
24002 int used = row->used[TEXT_AREA];
24003
24004 if (used)
24005 {
24006 struct glyph *start = row->glyphs[TEXT_AREA];
24007 struct glyph *glyph = start + used - 1;
24008
24009 if (row->reversed_p)
24010 {
24011
24012
24013 glyph = start;
24014 start = row->glyphs[TEXT_AREA] + used - 1;
24015 }
24016
24017
24018
24019
24020
24021 if (!row->reversed_p)
24022 {
24023 while (glyph >= start
24024 && (glyph->type == CHAR_GLYPH
24025 || glyph->type == STRETCH_GLYPH)
24026 && NILP (glyph->object))
24027 --glyph;
24028 }
24029 else
24030 {
24031 while (glyph <= start
24032 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
24033 && NILP (glyph->object))
24034 ++glyph;
24035 }
24036
24037
24038
24039
24040 if ((row->reversed_p ? glyph <= start : glyph >= start)
24041 && BUFFERP (glyph->object)
24042 && (glyph->type == STRETCH_GLYPH
24043 || (glyph->type == CHAR_GLYPH
24044 && glyph->u.ch == ' '))
24045 && trailing_whitespace_p (glyph->charpos))
24046 {
24047 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
24048 if (face_id < 0)
24049 return;
24050
24051 if (!row->reversed_p)
24052 {
24053 while (glyph >= start
24054 && BUFFERP (glyph->object)
24055 && (glyph->type == STRETCH_GLYPH
24056 || (glyph->type == CHAR_GLYPH
24057 && glyph->u.ch == ' ')))
24058 (glyph--)->face_id = face_id;
24059 }
24060 else
24061 {
24062 while (glyph <= start
24063 && BUFFERP (glyph->object)
24064 && (glyph->type == STRETCH_GLYPH
24065 || (glyph->type == CHAR_GLYPH
24066 && glyph->u.ch == ' ')))
24067 (glyph++)->face_id = face_id;
24068 }
24069 }
24070 }
24071 }
24072
24073
24074
24075
24076
24077 static bool
24078 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
24079 {
24080 bool result = true;
24081
24082 if (charpos == CHARPOS (row->end.pos)
24083 || charpos == MATRIX_ROW_END_CHARPOS (row))
24084 {
24085
24086
24087
24088
24089
24090
24091
24092
24093 if (CHARPOS (row->end.string_pos) >= 0)
24094 {
24095 if (row->continued_p)
24096 result = true;
24097 else
24098 {
24099
24100 struct glyph *beg = row->glyphs[TEXT_AREA];
24101 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
24102 struct glyph *glyph;
24103
24104 result = false;
24105 for (glyph = end; glyph >= beg; --glyph)
24106 if (STRINGP (glyph->object))
24107 {
24108 Lisp_Object prop
24109 = Fget_char_property (make_fixnum (charpos),
24110 Qdisplay, Qnil);
24111 result =
24112 (!NILP (prop)
24113 && display_prop_string_p (prop, glyph->object));
24114
24115
24116
24117 if (!result)
24118 {
24119 Lisp_Object s = glyph->object;
24120
24121 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
24122 {
24123 ptrdiff_t gpos = glyph->charpos;
24124
24125 if (!NILP (Fget_char_property (make_fixnum (gpos),
24126 Qcursor, s)))
24127 {
24128 result = true;
24129 break;
24130 }
24131 }
24132 }
24133 break;
24134 }
24135 }
24136 }
24137 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
24138 {
24139
24140
24141
24142
24143 if (!row->ends_in_ellipsis_p)
24144 result = row->continued_p;
24145 else
24146
24147
24148
24149
24150 result = false;
24151 }
24152
24153
24154 else
24155 result = row->ends_at_zv_p;
24156 }
24157
24158 return result;
24159 }
24160
24161
24162
24163
24164 static bool
24165 cursor_row_p (struct glyph_row *row)
24166 {
24167 return row_for_charpos_p (row, PT);
24168 }
24169
24170
24171
24172
24173
24174
24175
24176
24177 static bool
24178 push_prefix_prop (struct it *it, Lisp_Object prop)
24179 {
24180 struct text_pos pos =
24181 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
24182
24183 eassert (it->method == GET_FROM_BUFFER
24184 || it->method == GET_FROM_DISPLAY_VECTOR
24185 || it->method == GET_FROM_STRING
24186 || it->method == GET_FROM_IMAGE);
24187
24188
24189
24190
24191
24192 push_it (it, &pos);
24193
24194 if (STRINGP (prop))
24195 {
24196 if (SCHARS (prop) == 0)
24197 {
24198 pop_it (it);
24199 return false;
24200 }
24201
24202 it->string = prop;
24203 it->string_from_prefix_prop_p = true;
24204 it->multibyte_p = STRING_MULTIBYTE (it->string);
24205 it->current.overlay_string_index = -1;
24206 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
24207 it->end_charpos = it->string_nchars = SCHARS (it->string);
24208 it->method = GET_FROM_STRING;
24209 it->stop_charpos = 0;
24210 it->prev_stop = 0;
24211 it->base_level_stop = 0;
24212 it->cmp_it.id = -1;
24213
24214
24215
24216 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
24217 it->paragraph_embedding = it->bidi_it.paragraph_dir;
24218 else
24219 it->paragraph_embedding = L2R;
24220
24221
24222 if (it->bidi_p)
24223 {
24224 it->bidi_it.string.lstring = it->string;
24225 it->bidi_it.string.s = NULL;
24226 it->bidi_it.string.schars = it->end_charpos;
24227 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
24228 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
24229 it->bidi_it.string.unibyte = !it->multibyte_p;
24230 it->bidi_it.w = it->w;
24231 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
24232 }
24233 }
24234 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
24235 {
24236 it->method = GET_FROM_STRETCH;
24237 it->object = prop;
24238 }
24239 #ifdef HAVE_WINDOW_SYSTEM
24240 else if (IMAGEP (prop))
24241 {
24242 it->what = IT_IMAGE;
24243 it->image_id = lookup_image (it->f, prop, it->face_id);
24244 it->method = GET_FROM_IMAGE;
24245 }
24246 #endif
24247 else
24248 {
24249 pop_it (it);
24250 return false;
24251 }
24252
24253 return true;
24254 }
24255
24256
24257
24258 static Lisp_Object
24259 get_it_property (struct it *it, Lisp_Object prop)
24260 {
24261 Lisp_Object position, object = it->object;
24262
24263 if (STRINGP (object))
24264 position = make_fixnum (IT_STRING_CHARPOS (*it));
24265 else if (BUFFERP (object))
24266 {
24267 position = make_fixnum (IT_CHARPOS (*it));
24268 object = it->window;
24269 }
24270 else
24271 return Qnil;
24272
24273 return Fget_char_property (position, prop, object);
24274 }
24275
24276
24277
24278
24279 static Lisp_Object
24280 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24281 {
24282 Lisp_Object prefix = get_it_property (it, prop);
24283
24284
24285
24286 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24287 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24288 it->w->contents);
24289 return prefix;
24290 }
24291
24292
24293
24294 static void
24295 handle_line_prefix (struct it *it)
24296 {
24297 Lisp_Object prefix;
24298
24299 if (it->continuation_lines_width > 0)
24300 {
24301 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24302 if (NILP (prefix))
24303 prefix = Vwrap_prefix;
24304 }
24305 else
24306 {
24307 prefix = get_line_prefix_it_property (it, Qline_prefix);
24308 if (NILP (prefix))
24309 prefix = Vline_prefix;
24310 }
24311 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24312 {
24313
24314
24315
24316 it->line_wrap = TRUNCATE;
24317 it->avoid_cursor_p = true;
24318 }
24319 }
24320
24321
24322
24323
24324
24325
24326
24327 static void
24328 unproduce_glyphs (struct it *it, int n)
24329 {
24330 struct glyph *glyph, *end;
24331
24332 eassert (it->glyph_row);
24333 eassert (it->glyph_row->reversed_p);
24334 eassert (it->area == TEXT_AREA);
24335 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24336
24337 if (n > it->glyph_row->used[TEXT_AREA])
24338 n = it->glyph_row->used[TEXT_AREA];
24339 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24340 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24341 for ( ; glyph < end; glyph++)
24342 glyph[-n] = *glyph;
24343 }
24344
24345
24346
24347 static void
24348 find_row_edges (struct it *it, struct glyph_row *row,
24349 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24350 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24351 {
24352
24353
24354
24355
24356
24357 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24358 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24359 else
24360
24361
24362
24363 row->minpos = row->start.pos;
24364 if (max_pos <= 0)
24365 {
24366 max_pos = CHARPOS (it->current.pos);
24367 max_bpos = BYTEPOS (it->current.pos);
24368 }
24369
24370
24371
24372
24373
24374
24375
24376
24377
24378
24379
24380
24381
24382
24383
24384
24385
24386 if (row->ends_at_zv_p)
24387 row->maxpos = it->current.pos;
24388 else if (row->used[TEXT_AREA])
24389 {
24390 bool seen_this_string = false;
24391 struct glyph_row *r1 = row - 1;
24392
24393
24394 if (STRINGP (it->object)
24395
24396 && row > it->w->desired_matrix->rows
24397
24398 && !r1->mode_line_p
24399
24400 && r1->ends_in_newline_from_string_p)
24401 {
24402 struct glyph *start, *end;
24403
24404
24405
24406
24407
24408 if (!r1->reversed_p)
24409 {
24410 start = r1->glyphs[TEXT_AREA];
24411 end = start + r1->used[TEXT_AREA];
24412
24413 while (end > start
24414 && NILP ((end - 1)->object)
24415 && (end - 1)->charpos <= 0)
24416 --end;
24417 if (end > start)
24418 {
24419 if (EQ ((end - 1)->object, it->object))
24420 seen_this_string = true;
24421 }
24422 else
24423
24424
24425
24426
24427
24428 seen_this_string = true;
24429 }
24430 else
24431 {
24432 end = r1->glyphs[TEXT_AREA] - 1;
24433 start = end + r1->used[TEXT_AREA];
24434 while (end < start
24435 && NILP ((end + 1)->object)
24436 && (end + 1)->charpos <= 0)
24437 ++end;
24438 if (end < start)
24439 {
24440 if (EQ ((end + 1)->object, it->object))
24441 seen_this_string = true;
24442 }
24443 else
24444 seen_this_string = true;
24445 }
24446 }
24447
24448
24449
24450 if (row->ends_in_newline_from_string_p && !seen_this_string)
24451 {
24452
24453
24454
24455
24456
24457
24458
24459
24460 if (CHARPOS (row->end.pos) > max_pos)
24461 inc_both (&max_pos, &max_bpos);
24462 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24463 }
24464 else if (CHARPOS (it->eol_pos) > 0)
24465 SET_TEXT_POS (row->maxpos,
24466 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24467 else if (row->continued_p)
24468 {
24469
24470
24471
24472
24473
24474
24475 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24476 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24477 else
24478 {
24479 inc_both (&max_pos, &max_bpos);
24480 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24481 }
24482 }
24483 else if (row->truncated_on_right_p)
24484
24485
24486
24487 row->maxpos = it->current.pos;
24488 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24489
24490 row->maxpos = row->minpos;
24491 else
24492 emacs_abort ();
24493 }
24494 else
24495 row->maxpos = it->current.pos;
24496 }
24497
24498
24499
24500 static ptrdiff_t
24501 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24502 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24503 {
24504 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24505 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24506
24507 ptrdiff_t val;
24508 specpdl_ref pdl_count = SPECPDL_INDEX ();
24509 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24510 labeled_restrictions_remove_in_current_buffer ();
24511 Fwiden ();
24512 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24513 unbind_to (pdl_count, Qnil);
24514 return val;
24515 }
24516
24517
24518
24519 static ptrdiff_t
24520 display_count_lines_visually (struct it *it)
24521 {
24522 struct it tem_it;
24523 ptrdiff_t to;
24524 struct text_pos from;
24525
24526
24527
24528
24529
24530
24531 if (it->lnum_bytepos > 0)
24532 return it->lnum + 1;
24533 else
24534 {
24535 specpdl_ref count = SPECPDL_INDEX ();
24536
24537 if (IT_CHARPOS (*it) <= PT)
24538 {
24539 from = it->current.pos;
24540 to = PT;
24541 }
24542 else
24543 {
24544 SET_TEXT_POS (from, PT, PT_BYTE);
24545 to = IT_CHARPOS (*it);
24546 }
24547
24548
24549
24550 specbind (Qdisplay_line_numbers, Qrelative);
24551 start_display (&tem_it, it->w, from);
24552
24553
24554
24555
24556 move_it_to (&tem_it, to, -1,
24557 tem_it.last_visible_y
24558 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24559 -1, MOVE_TO_POS | MOVE_TO_Y);
24560 unbind_to (count, Qnil);
24561 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24562 }
24563 }
24564
24565
24566
24567
24568 static void
24569 maybe_produce_line_number (struct it *it)
24570 {
24571 ptrdiff_t last_line = it->lnum;
24572 ptrdiff_t start_from, bytepos;
24573 ptrdiff_t this_line;
24574 bool first_time = false;
24575 ptrdiff_t beg_byte;
24576 ptrdiff_t z_byte;
24577 bool line_numbers_wide;
24578 void *itdata = bidi_shelve_cache ();
24579
24580 if (display_line_numbers_offset
24581 && !display_line_numbers_widen
24582 && !EQ (Vdisplay_line_numbers, Qvisual)
24583 && !EQ (Vdisplay_line_numbers, Qrelative))
24584 line_numbers_wide = true;
24585 else
24586 line_numbers_wide = display_line_numbers_widen;
24587
24588 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24589 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24590
24591 if (EQ (Vdisplay_line_numbers, Qvisual))
24592 this_line = display_count_lines_visually (it);
24593 else
24594 {
24595 if (!last_line)
24596 {
24597
24598 if (it->w->base_line_number > 0
24599 && it->w->base_line_pos > 0
24600 && it->w->base_line_pos <= IT_CHARPOS (*it)
24601
24602
24603
24604
24605 && !(line_numbers_wide
24606 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24607 && !current_buffer->clip_changed)
24608 {
24609 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24610 last_line = it->w->base_line_number - 1;
24611 }
24612 else
24613 start_from = beg_byte;
24614 if (!it->lnum_bytepos)
24615 first_time = true;
24616 }
24617 else
24618 start_from = it->lnum_bytepos;
24619
24620
24621
24622
24623 if (!(beg_byte <= start_from && start_from <= z_byte))
24624 {
24625 last_line = 0;
24626 start_from = beg_byte;
24627 }
24628
24629 this_line =
24630 last_line + display_count_lines_logically (start_from,
24631 IT_BYTEPOS (*it),
24632 IT_CHARPOS (*it), &bytepos);
24633 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24634 eassert (bytepos == IT_BYTEPOS (*it));
24635 }
24636
24637
24638 if (this_line != last_line || !it->lnum_bytepos)
24639 {
24640 it->lnum = this_line;
24641 it->lnum_bytepos = IT_BYTEPOS (*it);
24642 }
24643
24644
24645 struct it tem_it;
24646 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24647 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24648 ptrdiff_t lnum_offset = -1;
24649 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24650 int current_lnum_face_id
24651 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24652
24653
24654 bool save_free_realized_faces = inhibit_free_realized_faces;
24655 inhibit_free_realized_faces = true;
24656
24657 if ((EQ (Vdisplay_line_numbers, Qrelative)
24658 || EQ (Vdisplay_line_numbers, Qvisual)
24659 || lnum_face_id != current_lnum_face_id)
24660 && !it->pt_lnum)
24661 {
24662 ptrdiff_t ignored;
24663 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24664 it->pt_lnum =
24665 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24666 PT, &ignored);
24667 else
24668 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24669 &ignored);
24670 }
24671
24672 if (!it->lnum_width)
24673 {
24674 if (FIXNATP (Vdisplay_line_numbers_width))
24675 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24676
24677
24678
24679 ptrdiff_t max_lnum;
24680
24681 if (NILP (Vdisplay_line_numbers_current_absolute)
24682 && (EQ (Vdisplay_line_numbers, Qrelative)
24683 || EQ (Vdisplay_line_numbers, Qvisual)))
24684
24685
24686 max_lnum = it->w->desired_matrix->nrows - 2;
24687 else if (EQ (Vdisplay_line_numbers, Qvisual))
24688 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24689 else
24690 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24691 max_lnum = max (1, max_lnum);
24692 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24693 eassert (it->lnum_width > 0);
24694 }
24695 if (EQ (Vdisplay_line_numbers, Qrelative))
24696 lnum_offset = it->pt_lnum;
24697 else if (EQ (Vdisplay_line_numbers, Qvisual))
24698 lnum_offset = 0;
24699 else if (display_line_numbers_offset)
24700 lnum_offset -= display_line_numbers_offset;
24701
24702
24703
24704 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24705 if ((EQ (Vdisplay_line_numbers, Qrelative)
24706 || EQ (Vdisplay_line_numbers, Qvisual))
24707 && lnum_to_display == 0
24708 && !NILP (Vdisplay_line_numbers_current_absolute))
24709 lnum_to_display = it->pt_lnum + 1;
24710
24711
24712
24713
24714
24715 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24716 strcat (lnum_buf, " ");
24717
24718
24719 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24720
24721 DEFAULT_FACE_ID);
24722 scratch_glyph_row.reversed_p = false;
24723 scratch_glyph_row.used[TEXT_AREA] = 0;
24724 SET_TEXT_POS (tem_it.position, 0, 0);
24725 tem_it.avoid_cursor_p = true;
24726 tem_it.bidi_p = true;
24727 tem_it.bidi_it.type = WEAK_EN;
24728
24729
24730
24731 tem_it.bidi_it.resolved_level = 2;
24732
24733
24734
24735 int width_limit =
24736 tem_it.last_visible_x - tem_it.first_visible_x
24737 - 3 * FRAME_COLUMN_WIDTH (it->f);
24738
24739 tem_it.face_id = lnum_face_id;
24740
24741
24742 if (lnum_face_id != current_lnum_face_id
24743 && (EQ (Vdisplay_line_numbers, Qvisual)
24744 ? this_line == 0
24745 : this_line == it->pt_lnum)
24746 && it->what != IT_EOB)
24747 tem_it.face_id = current_lnum_face_id;
24748 else if (!beyond_zv)
24749 {
24750 if (display_line_numbers_major_tick > 0
24751 && (lnum_to_display % display_line_numbers_major_tick == 0))
24752 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24753 0, DEFAULT_FACE_ID);
24754 else if (display_line_numbers_minor_tick > 0
24755 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24756 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24757 0, DEFAULT_FACE_ID);
24758 }
24759
24760
24761 for (const char *p = lnum_buf; *p; p++)
24762 {
24763
24764
24765 if (beyond_zv
24766
24767 || (!EQ (Vdisplay_line_numbers, Qvisual)
24768 && (it->continuation_lines_width > 0
24769 || (this_line == last_line && !first_time))))
24770 tem_it.c = tem_it.char_to_display = ' ';
24771 else
24772 tem_it.c = tem_it.char_to_display = *p;
24773 tem_it.len = 1;
24774
24775 SET_TEXT_POS (tem_it.position, -1, -1);
24776 PRODUCE_GLYPHS (&tem_it);
24777
24778
24779
24780 if (tem_it.current_x >= width_limit)
24781 {
24782 it->lnum_width = 0;
24783 it->lnum_pixel_width = 0;
24784 bidi_unshelve_cache (itdata, false);
24785 inhibit_free_realized_faces = save_free_realized_faces;
24786 return;
24787 }
24788 }
24789
24790 inhibit_free_realized_faces = save_free_realized_faces;
24791
24792
24793 it->lnum_pixel_width = tem_it.current_x;
24794
24795 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24796 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24797 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24798 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24799
24800 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24801
24802 for ( ; g < e; g++)
24803 {
24804 it->current_x += g->pixel_width;
24805
24806
24807
24808 if (it->current_x > it->first_visible_x)
24809 it->hpos++;
24810 if (p)
24811 {
24812 *p++ = *g;
24813 (*u)++;
24814 }
24815 }
24816
24817
24818
24819
24820 if (!beyond_zv)
24821 {
24822 if (it->glyph_row)
24823 {
24824 struct glyph_row *row = it->glyph_row;
24825
24826 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24827 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24828 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24829 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24830 tem_it.max_phys_descent);
24831 }
24832 else
24833 {
24834 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24835 it->max_descent = max (it->max_descent, tem_it.max_descent);
24836 it->max_phys_ascent = max (it->max_phys_ascent,
24837 tem_it.max_phys_ascent);
24838 it->max_phys_descent = max (it->max_phys_descent,
24839 tem_it.max_phys_descent);
24840 }
24841 }
24842
24843 it->line_number_produced_p = true;
24844
24845 bidi_unshelve_cache (itdata, false);
24846 }
24847
24848
24849
24850 static bool
24851 should_produce_line_number (struct it *it)
24852 {
24853 if (NILP (Vdisplay_line_numbers))
24854 return false;
24855
24856
24857 if (MINI_WINDOW_P (it->w))
24858 return false;
24859
24860 #ifdef HAVE_WINDOW_SYSTEM
24861
24862 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24863 return false;
24864 #endif
24865
24866
24867
24868
24869
24870 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24871 Qdisplay_line_numbers_disable,
24872 it->window);
24873
24874
24875
24876 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24877 val = disable_line_numbers_overlay_at_eob ();
24878 return NILP (val) ? true : false;
24879 }
24880
24881
24882
24883
24884
24885 static bool
24886 row_text_area_empty (struct glyph_row *row)
24887 {
24888 if (!row->reversed_p)
24889 {
24890 for (struct glyph *g = row->glyphs[TEXT_AREA];
24891 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24892 g++)
24893 if (!NILP (g->object) || g->charpos > 0)
24894 return false;
24895 }
24896 else
24897 {
24898 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24899 g > row->glyphs[TEXT_AREA];
24900 g--)
24901 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24902 return false;
24903 }
24904
24905 return true;
24906 }
24907
24908
24909
24910
24911
24912
24913
24914
24915 static bool
24916 display_line (struct it *it, int cursor_vpos)
24917 {
24918 struct glyph_row *row = it->glyph_row;
24919 Lisp_Object overlay_arrow_string;
24920 struct it wrap_it;
24921 void *wrap_data = NULL;
24922 bool may_wrap = false;
24923 int wrap_x UNINIT;
24924 int wrap_row_used = -1;
24925 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24926 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24927 int wrap_row_extra_line_spacing UNINIT;
24928 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24929 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24930 int cvpos;
24931 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24932 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24933 bool pending_handle_line_prefix = false;
24934 int tab_line = window_wants_tab_line (it->w);
24935 int header_line = window_wants_header_line (it->w);
24936 bool hscroll_this_line = (cursor_vpos >= 0
24937 && it->vpos == cursor_vpos - tab_line - header_line
24938 && hscrolling_current_line_p (it->w));
24939 int first_visible_x = it->first_visible_x;
24940 int last_visible_x = it->last_visible_x;
24941 int x_incr = 0;
24942
24943
24944 eassert (it->hpos == 0 && it->current_x == 0);
24945
24946 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24947 >= it->w->desired_matrix->nrows)
24948 {
24949 it->w->nrows_scale_factor++;
24950 it->f->fonts_changed = true;
24951 return false;
24952 }
24953
24954
24955 prepare_desired_row (it->w, row, false);
24956
24957 row->y = it->current_y;
24958 row->start = it->start;
24959 row->continuation_lines_width = it->continuation_lines_width;
24960 row->displays_text_p = true;
24961 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24962 it->starts_in_middle_of_char_p = false;
24963 it->stretch_adjust = 0;
24964 it->line_number_produced_p = false;
24965
24966
24967
24968
24969 if (hscroll_this_line)
24970 x_incr =
24971 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24972 * FRAME_COLUMN_WIDTH (it->f);
24973
24974 bool line_number_needed = should_produce_line_number (it);
24975
24976
24977
24978
24979 if (it->current_x < it->first_visible_x + x_incr)
24980 {
24981 enum move_it_result move_result;
24982
24983 this_line_min_pos = row->start.pos;
24984 if (hscroll_this_line)
24985 {
24986 it->first_visible_x += x_incr;
24987 it->last_visible_x += x_incr;
24988 }
24989 if (current_buffer->long_line_optimizations_p
24990 && it->line_wrap == TRUNCATE
24991 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24992 {
24993
24994
24995
24996
24997 ptrdiff_t chars_to_skip =
24998 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24999 move_result = fast_move_it_horizontally (it, chars_to_skip);
25000
25001 if (move_result == MOVE_X_REACHED)
25002 it->current_x = it->first_visible_x;
25003 else
25004 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
25005 }
25006 else
25007 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
25008 MOVE_TO_POS | MOVE_TO_X);
25009
25010
25011
25012
25013
25014
25015 if (it->current_x < it->first_visible_x
25016 && (move_result == MOVE_NEWLINE_OR_CR
25017 || move_result == MOVE_POS_MATCH_OR_ZV))
25018 it->current_x = it->first_visible_x;
25019
25020
25021
25022 it->line_number_produced_p = false;
25023
25024
25025
25026
25027
25028
25029
25030
25031 min_pos = CHARPOS (this_line_min_pos);
25032 min_bpos = BYTEPOS (this_line_min_pos);
25033
25034
25035 if (line_number_needed)
25036 maybe_produce_line_number (it);
25037 }
25038 else if (it->area == TEXT_AREA)
25039 {
25040
25041 if (line_number_needed)
25042 maybe_produce_line_number (it);
25043
25044
25045
25046 handle_line_prefix (it);
25047 }
25048 else
25049 {
25050
25051
25052
25053
25054
25055
25056
25057 pending_handle_line_prefix = true;
25058 }
25059
25060
25061
25062 row->ascent = it->max_ascent;
25063 row->height = it->max_ascent + it->max_descent;
25064 row->phys_ascent = it->max_phys_ascent;
25065 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
25066 row->extra_line_spacing = it->max_extra_line_spacing;
25067
25068
25069 #define RECORD_MAX_MIN_POS(IT) \
25070 do \
25071 { \
25072 bool composition_p \
25073 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
25074 ptrdiff_t current_pos = \
25075 composition_p ? (IT)->cmp_it.charpos \
25076 : IT_CHARPOS (*(IT)); \
25077 ptrdiff_t current_bpos = \
25078 composition_p ? CHAR_TO_BYTE (current_pos) \
25079 : IT_BYTEPOS (*(IT)); \
25080 if (current_pos < min_pos) \
25081 { \
25082 min_pos = current_pos; \
25083 min_bpos = current_bpos; \
25084 } \
25085 if (IT_CHARPOS (*it) > max_pos) \
25086 { \
25087 max_pos = IT_CHARPOS (*it); \
25088 max_bpos = IT_BYTEPOS (*it); \
25089 } \
25090 } \
25091 while (false)
25092
25093
25094
25095 while (true)
25096 {
25097 int n_glyphs_before, hpos_before, x_before;
25098 int x, nglyphs;
25099 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
25100
25101
25102
25103 if (!get_next_display_element (it))
25104 {
25105 bool row_has_glyphs = false;
25106
25107
25108
25109
25110 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25111 row->exact_window_width_line_p = true;
25112 else if ((append_space_for_newline (it, true)
25113 && row->used[TEXT_AREA] == 1)
25114 || row->used[TEXT_AREA] == 0
25115 || (row_has_glyphs = row_text_area_empty (row)))
25116 {
25117 row->glyphs[TEXT_AREA]->charpos = -1;
25118
25119
25120 if (!row_has_glyphs)
25121 row->displays_text_p = false;
25122
25123 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
25124 && (!MINI_WINDOW_P (it->w)))
25125 row->indicate_empty_line_p = true;
25126 }
25127
25128 it->continuation_lines_width = 0;
25129
25130
25131
25132
25133 it->font_height = Qnil;
25134 it->voffset = 0;
25135 row->ends_at_zv_p = true;
25136
25137
25138
25139
25140
25141
25142
25143
25144 if (row->reversed_p
25145 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
25146 != DEFAULT_FACE_ID)
25147 extend_face_to_end_of_line (it);
25148 break;
25149 }
25150
25151
25152
25153 n_glyphs_before = row->used[TEXT_AREA];
25154 x = it->current_x;
25155
25156
25157
25158 if (it->line_wrap != TRUNCATE)
25159 {
25160 ascent = it->max_ascent;
25161 descent = it->max_descent;
25162 phys_ascent = it->max_phys_ascent;
25163 phys_descent = it->max_phys_descent;
25164
25165 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
25166 {
25167 bool next_may_wrap = may_wrap;
25168
25169 if (char_can_wrap_after (it))
25170 next_may_wrap = true;
25171 else
25172 next_may_wrap = false;
25173
25174 if (may_wrap && char_can_wrap_before (it))
25175 {
25176 SAVE_IT (wrap_it, *it, wrap_data);
25177 wrap_x = x;
25178 wrap_row_used = row->used[TEXT_AREA];
25179 wrap_row_ascent = row->ascent;
25180 wrap_row_height = row->height;
25181 wrap_row_phys_ascent = row->phys_ascent;
25182 wrap_row_phys_height = row->phys_height;
25183 wrap_row_extra_line_spacing = row->extra_line_spacing;
25184 wrap_row_min_pos = min_pos;
25185 wrap_row_min_bpos = min_bpos;
25186 wrap_row_max_pos = max_pos;
25187 wrap_row_max_bpos = max_bpos;
25188 }
25189
25190 may_wrap = next_may_wrap;
25191 }
25192 }
25193
25194 PRODUCE_GLYPHS (it);
25195
25196
25197
25198 if (it->area != TEXT_AREA)
25199 {
25200 row->ascent = max (row->ascent, it->max_ascent);
25201 row->height = max (row->height, it->max_ascent + it->max_descent);
25202 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25203 row->phys_height = max (row->phys_height,
25204 it->max_phys_ascent + it->max_phys_descent);
25205 row->extra_line_spacing = max (row->extra_line_spacing,
25206 it->max_extra_line_spacing);
25207 set_iterator_to_next (it, true);
25208
25209
25210
25211 if (it->area == TEXT_AREA && pending_handle_line_prefix)
25212 {
25213
25214 if (line_number_needed)
25215 maybe_produce_line_number (it);
25216
25217 pending_handle_line_prefix = false;
25218 handle_line_prefix (it);
25219 }
25220 continue;
25221 }
25222
25223
25224
25225
25226
25227
25228
25229
25230
25231
25232 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
25233 hpos_before = it->hpos;
25234 x_before = x;
25235
25236 if (
25237 nglyphs > 0
25238
25239 && it->current_x < it->last_visible_x)
25240 {
25241 it->hpos += nglyphs;
25242 row->ascent = max (row->ascent, it->max_ascent);
25243 row->height = max (row->height, it->max_ascent + it->max_descent);
25244 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25245 row->phys_height = max (row->phys_height,
25246 it->max_phys_ascent + it->max_phys_descent);
25247 row->extra_line_spacing = max (row->extra_line_spacing,
25248 it->max_extra_line_spacing);
25249 if (it->current_x - it->pixel_width < it->first_visible_x
25250
25251
25252
25253 && !line_number_needed
25254
25255
25256
25257
25258 && !row->reversed_p)
25259 row->x = x - it->first_visible_x;
25260
25261
25262 if (it->bidi_p)
25263 RECORD_MAX_MIN_POS (it);
25264 }
25265 else
25266 {
25267 int i, new_x;
25268 struct glyph *glyph;
25269
25270 for (i = 0; i < nglyphs; ++i, x = new_x)
25271 {
25272
25273
25274
25275 if (!row->reversed_p)
25276 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25277 else
25278 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25279 new_x = x + glyph->pixel_width;
25280
25281 if (
25282 it->line_wrap != TRUNCATE
25283 && (
25284 new_x > it->last_visible_x
25285
25286 || (new_x == it->last_visible_x
25287 && FRAME_WINDOW_P (it->f)
25288 && (row->reversed_p
25289 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25290 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25291 {
25292
25293
25294 if (it->hpos == 0
25295 || (new_x == it->last_visible_x
25296 && FRAME_WINDOW_P (it->f)
25297 && (row->reversed_p
25298 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25299 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25300 {
25301
25302
25303
25304
25305 row->continued_p = true;
25306 it->current_x = new_x;
25307 it->continuation_lines_width += new_x;
25308 ++it->hpos;
25309 if (i == nglyphs - 1)
25310 {
25311
25312
25313 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25314 && wrap_row_used > 0
25315
25316
25317
25318
25319
25320
25321
25322
25323
25324
25325 && (!may_wrap || !char_can_wrap_before (it)))
25326 goto back_to_wrap;
25327
25328
25329
25330
25331 if (it->bidi_p)
25332 RECORD_MAX_MIN_POS (it);
25333 set_iterator_to_next (it, true);
25334 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25335 {
25336 if (!get_next_display_element (it))
25337 {
25338 row->exact_window_width_line_p = true;
25339 it->continuation_lines_width = 0;
25340 it->font_height = Qnil;
25341 it->voffset = 0;
25342 row->continued_p = false;
25343 row->ends_at_zv_p = true;
25344 }
25345 else if (ITERATOR_AT_END_OF_LINE_P (it))
25346 {
25347 row->continued_p = false;
25348 row->exact_window_width_line_p = true;
25349 }
25350
25351
25352 else if (wrap_row_used > 0
25353
25354
25355
25356
25357
25358
25359
25360
25361
25362 && (!may_wrap || !char_can_wrap_before (it)))
25363 goto back_to_wrap;
25364
25365 }
25366 }
25367 else if (it->bidi_p)
25368 RECORD_MAX_MIN_POS (it);
25369 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25370 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25371 extend_face_to_end_of_line (it);
25372 }
25373 else if (CHAR_GLYPH_PADDING_P (*glyph)
25374 && !FRAME_WINDOW_P (it->f))
25375 {
25376
25377
25378
25379 if (row->reversed_p)
25380 unproduce_glyphs (it, row->used[TEXT_AREA]
25381 - n_glyphs_before);
25382 row->used[TEXT_AREA] = n_glyphs_before;
25383
25384
25385
25386 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25387 < row->glyphs[1 + TEXT_AREA])
25388 produce_special_glyphs (it, IT_CONTINUATION);
25389
25390 row->continued_p = true;
25391 it->current_x = x_before;
25392 it->continuation_lines_width += x_before;
25393
25394
25395
25396 it->max_ascent = ascent;
25397 it->max_descent = descent;
25398 it->max_phys_ascent = phys_ascent;
25399 it->max_phys_descent = phys_descent;
25400 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25401 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25402 extend_face_to_end_of_line (it);
25403 }
25404 else if (wrap_row_used > 0)
25405 {
25406 back_to_wrap:
25407 if (row->reversed_p)
25408 unproduce_glyphs (it,
25409 row->used[TEXT_AREA] - wrap_row_used);
25410 RESTORE_IT (it, &wrap_it, wrap_data);
25411 it->continuation_lines_width += wrap_x;
25412 row->used[TEXT_AREA] = wrap_row_used;
25413 row->ascent = wrap_row_ascent;
25414 row->height = wrap_row_height;
25415 row->phys_ascent = wrap_row_phys_ascent;
25416 row->phys_height = wrap_row_phys_height;
25417 row->extra_line_spacing = wrap_row_extra_line_spacing;
25418 min_pos = wrap_row_min_pos;
25419 min_bpos = wrap_row_min_bpos;
25420 max_pos = wrap_row_max_pos;
25421 max_bpos = wrap_row_max_bpos;
25422 row->continued_p = true;
25423 row->ends_at_zv_p = false;
25424 row->exact_window_width_line_p = false;
25425
25426
25427
25428 extend_face_to_end_of_line (it);
25429 }
25430 else if ((it->what == IT_CHARACTER
25431 || it->what == IT_STRETCH
25432 || it->what == IT_COMPOSITION)
25433 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25434 {
25435
25436
25437
25438
25439
25440 if ((row->reversed_p
25441 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25442 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25443 produce_special_glyphs (it, IT_CONTINUATION);
25444 it->continuation_lines_width += it->last_visible_x;
25445 row->ends_in_middle_of_char_p = true;
25446 row->continued_p = true;
25447 glyph->pixel_width = it->last_visible_x - x;
25448 it->starts_in_middle_of_char_p = true;
25449 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25450 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25451 extend_face_to_end_of_line (it);
25452 }
25453 else
25454 {
25455
25456
25457
25458 if (row->reversed_p)
25459 unproduce_glyphs (it, row->used[TEXT_AREA]
25460 - (n_glyphs_before + i));
25461 row->used[TEXT_AREA] = n_glyphs_before + i;
25462
25463
25464 it->current_x = x_before;
25465 it->continuation_lines_width += x;
25466 if (!FRAME_WINDOW_P (it->f)
25467 || (row->reversed_p
25468 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25469 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25470 produce_special_glyphs (it, IT_CONTINUATION);
25471 row->continued_p = true;
25472
25473 extend_face_to_end_of_line (it);
25474
25475 if (nglyphs > 1 && i > 0)
25476 {
25477 row->ends_in_middle_of_char_p = true;
25478 it->starts_in_middle_of_char_p = true;
25479 }
25480
25481
25482
25483 it->max_ascent = ascent;
25484 it->max_descent = descent;
25485 it->max_phys_ascent = phys_ascent;
25486 it->max_phys_descent = phys_descent;
25487 }
25488
25489 break;
25490 }
25491 else if (new_x > it->first_visible_x)
25492 {
25493
25494 ++it->hpos;
25495
25496
25497
25498
25499 if (it->bidi_p)
25500 RECORD_MAX_MIN_POS (it);
25501
25502 if (x < it->first_visible_x && !row->reversed_p
25503 && !line_number_needed)
25504
25505
25506
25507
25508
25509
25510 row->x = x - it->first_visible_x;
25511
25512
25513
25514
25515
25516
25517 if (row->reversed_p
25518 && new_x > it->last_visible_x
25519 && !line_number_needed
25520 && !(it->line_wrap == TRUNCATE
25521 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25522 {
25523 eassert (FRAME_WINDOW_P (it->f));
25524 row->x = it->last_visible_x - new_x;
25525 }
25526 }
25527 else
25528 {
25529
25530
25531
25532
25533
25534 eassert (it->first_visible_x <= it->last_visible_x);
25535 }
25536 }
25537
25538
25539 if (it->bidi_p && nglyphs == 0)
25540 RECORD_MAX_MIN_POS (it);
25541
25542 row->ascent = max (row->ascent, it->max_ascent);
25543 row->height = max (row->height, it->max_ascent + it->max_descent);
25544 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25545 row->phys_height = max (row->phys_height,
25546 it->max_phys_ascent + it->max_phys_descent);
25547 row->extra_line_spacing = max (row->extra_line_spacing,
25548 it->max_extra_line_spacing);
25549
25550
25551 if (row->continued_p || row->ends_at_zv_p)
25552 break;
25553 }
25554
25555 at_end_of_line:
25556
25557
25558
25559 if (ITERATOR_AT_END_OF_LINE_P (it))
25560 {
25561 int used_before = row->used[TEXT_AREA];
25562
25563 row->ends_in_newline_from_string_p = STRINGP (it->object);
25564
25565
25566
25567 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25568 append_space_for_newline (it, false);
25569
25570
25571 extend_face_to_end_of_line (it);
25572
25573
25574 if (used_before == 0)
25575 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25576
25577
25578
25579 it->eol_pos = it->current.pos;
25580
25581
25582 set_iterator_to_next (it, true);
25583 it->continuation_lines_width = 0;
25584 break;
25585 }
25586
25587
25588
25589
25590
25591
25592
25593
25594 bool overwide_wrap_prefix =
25595 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25596 && it->sp > 0 && it->method == GET_FROM_STRETCH
25597 && it->current_x >= it->last_visible_x
25598 && it->continuation_lines_width > 0
25599 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25600
25601
25602
25603 if (!overwide_wrap_prefix)
25604 set_iterator_to_next (it, true);
25605
25606
25607
25608 if (it->line_wrap == TRUNCATE
25609 && ((FRAME_WINDOW_P (it->f)
25610
25611
25612
25613
25614 && ((row->reversed_p
25615 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25616 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25617 || it->what == IT_IMAGE))
25618 ? (it->current_x >= it->last_visible_x)
25619 : (it->current_x > it->last_visible_x)))
25620 {
25621
25622 if (!FRAME_WINDOW_P (it->f)
25623 || (row->reversed_p
25624 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25625 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25626 {
25627 int i, n;
25628
25629 if (!row->reversed_p)
25630 {
25631 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25632 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25633 break;
25634 }
25635 else
25636 {
25637 for (i = 0; i < row->used[TEXT_AREA]; i++)
25638 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25639 break;
25640
25641
25642
25643
25644
25645 unproduce_glyphs (it, i + 1);
25646
25647 i = row->used[TEXT_AREA] - (i + 1);
25648 }
25649
25650
25651
25652
25653 if (it->current_x > it->last_visible_x)
25654 {
25655 it->current_x = x_before;
25656 if (!FRAME_WINDOW_P (it->f))
25657 {
25658 for (n = row->used[TEXT_AREA]; i < n; ++i)
25659 {
25660 row->used[TEXT_AREA] = i;
25661 produce_special_glyphs (it, IT_TRUNCATION);
25662 }
25663 }
25664 else
25665 {
25666 row->used[TEXT_AREA] = i;
25667 produce_special_glyphs (it, IT_TRUNCATION);
25668 }
25669 it->hpos = hpos_before;
25670 }
25671 }
25672 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25673 {
25674
25675 if (!get_next_display_element (it))
25676 {
25677 it->continuation_lines_width = 0;
25678 it->font_height = Qnil;
25679 it->voffset = 0;
25680 row->ends_at_zv_p = true;
25681 row->exact_window_width_line_p = true;
25682 break;
25683 }
25684 if (ITERATOR_AT_END_OF_LINE_P (it))
25685 {
25686 row->exact_window_width_line_p = true;
25687 goto at_end_of_line;
25688 }
25689 it->current_x = x_before;
25690 it->hpos = hpos_before;
25691 }
25692
25693 row->truncated_on_right_p = true;
25694 it->continuation_lines_width = 0;
25695 reseat_at_next_visible_line_start (it, false);
25696
25697
25698
25699
25700 if (IT_BYTEPOS (*it) > BEG_BYTE)
25701 row->ends_at_zv_p =
25702 IT_BYTEPOS (*it) >= ZV_BYTE
25703 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25704 else
25705 row->ends_at_zv_p = false;
25706 break;
25707 }
25708 }
25709
25710 if (wrap_data)
25711 bidi_unshelve_cache (wrap_data, true);
25712
25713
25714
25715 if (it->first_visible_x
25716 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25717 {
25718 if (!FRAME_WINDOW_P (it->f)
25719 || (((row->reversed_p
25720 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25721 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25722
25723
25724 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25725 insert_left_trunc_glyphs (it);
25726 row->truncated_on_left_p = true;
25727 }
25728
25729
25730
25731
25732
25733
25734 row->end = it->current;
25735 if (!it->bidi_p)
25736 {
25737 row->minpos = row->start.pos;
25738 row->maxpos = row->end.pos;
25739 }
25740 else
25741 {
25742
25743
25744
25745
25746 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25747 }
25748
25749
25750
25751
25752
25753 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25754 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25755 !NILP (overlay_arrow_string)))
25756 {
25757
25758 if (STRINGP (overlay_arrow_string))
25759 {
25760 struct glyph_row *arrow_row
25761 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25762 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25763 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25764 struct glyph *p = row->glyphs[TEXT_AREA];
25765 struct glyph *p2, *end;
25766
25767
25768 while (glyph < arrow_end)
25769 *p++ = *glyph++;
25770
25771
25772 p2 = p;
25773 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25774 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25775 ++p2;
25776 if (p2 > p)
25777 {
25778 while (p2 < end)
25779 *p++ = *p2++;
25780 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25781 }
25782 }
25783 else
25784 {
25785 eassert (FIXNUMP (overlay_arrow_string));
25786 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25787 }
25788 overlay_arrow_seen = true;
25789 }
25790
25791
25792 if (!NILP (Vshow_trailing_whitespace))
25793 highlight_trailing_whitespace (it);
25794
25795
25796 compute_line_metrics (it);
25797
25798
25799
25800
25801
25802
25803
25804 row->ends_in_ellipsis_p
25805 = (it->method == GET_FROM_DISPLAY_VECTOR
25806 && it->ellipsis_p);
25807
25808
25809 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25810 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25811 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25812 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25813
25814 it->left_user_fringe_bitmap = 0;
25815 it->left_user_fringe_face_id = 0;
25816 it->right_user_fringe_bitmap = 0;
25817 it->right_user_fringe_face_id = 0;
25818
25819
25820
25821
25822
25823
25824 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25825 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25826 row->redraw_fringe_bitmaps_p = true;
25827
25828
25829 cvpos = it->w->cursor.vpos;
25830 if ((cvpos < 0
25831
25832
25833
25834
25835
25836
25837
25838
25839 || (it->bidi_p
25840 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25841 && PT >= MATRIX_ROW_START_CHARPOS (row)
25842 && PT <= MATRIX_ROW_END_CHARPOS (row)
25843 && cursor_row_p (row))
25844 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25845
25846
25847
25848
25849
25850 it->current_x = it->hpos = 0;
25851 it->current_y += row->height;
25852
25853
25854 if (hscroll_this_line)
25855 {
25856 it->first_visible_x = first_visible_x;
25857 it->last_visible_x = last_visible_x;
25858 }
25859 SET_TEXT_POS (it->eol_pos, 0, 0);
25860 ++it->vpos;
25861 ++it->glyph_row;
25862
25863
25864
25865
25866 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25867 it->glyph_row->reversed_p = row->reversed_p;
25868 it->start = row->end;
25869 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25870
25871 #undef RECORD_MAX_MIN_POS
25872 }
25873
25874 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25875 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25876 doc:
25877
25878
25879
25880
25881
25882
25883
25884
25885 )
25886 (Lisp_Object buffer)
25887 {
25888 struct buffer *buf = current_buffer;
25889 struct buffer *old = buf;
25890
25891 if (! NILP (buffer))
25892 {
25893 CHECK_BUFFER (buffer);
25894 buf = XBUFFER (buffer);
25895 }
25896
25897 if (NILP (BVAR (buf, bidi_display_reordering))
25898 || NILP (BVAR (buf, enable_multibyte_characters))
25899
25900
25901 || redisplay__inhibit_bidi)
25902 return Qleft_to_right;
25903 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25904 return BVAR (buf, bidi_paragraph_direction);
25905 else
25906 {
25907
25908
25909
25910 struct bidi_it itb;
25911 ptrdiff_t pos = BUF_PT (buf);
25912 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25913 int c;
25914 void *itb_data = bidi_shelve_cache ();
25915
25916 set_buffer_temp (buf);
25917
25918
25919
25920
25921
25922 if (pos >= ZV && pos > BEGV)
25923 dec_both (&pos, &bytepos);
25924 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25925 if (fast_looking_at (trailing_white_space,
25926 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25927 {
25928 while ((c = FETCH_BYTE (bytepos)) == '\n'
25929 || c == ' ' || c == '\t' || c == '\f')
25930 {
25931 if (bytepos <= BEGV_BYTE)
25932 break;
25933 bytepos--;
25934 pos--;
25935 }
25936 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25937 bytepos--;
25938 }
25939 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25940 itb.paragraph_dir = NEUTRAL_DIR;
25941 itb.string.s = NULL;
25942 itb.string.lstring = Qnil;
25943 itb.string.bufpos = 0;
25944 itb.string.from_disp_str = false;
25945 itb.string.unibyte = false;
25946
25947
25948
25949 itb.w = NULL;
25950 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25951 bidi_unshelve_cache (itb_data, false);
25952 set_buffer_temp (old);
25953 switch (itb.paragraph_dir)
25954 {
25955 case L2R:
25956 return Qleft_to_right;
25957 break;
25958 case R2L:
25959 return Qright_to_left;
25960 break;
25961 default:
25962 emacs_abort ();
25963 }
25964 }
25965 }
25966
25967 DEFUN ("bidi-find-overridden-directionality",
25968 Fbidi_find_overridden_directionality,
25969 Sbidi_find_overridden_directionality, 3, 4, 0,
25970 doc:
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
26001
26002
26003
26004
26005
26006
26007 )
26008 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
26009 {
26010 struct buffer *buf = current_buffer;
26011 struct buffer *old = buf;
26012 struct window *w = NULL;
26013 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
26014 struct bidi_it itb;
26015 ptrdiff_t from_pos, to_pos, from_bpos;
26016 void *itb_data;
26017
26018 if (!NILP (object))
26019 {
26020 if (BUFFERP (object))
26021 buf = XBUFFER (object);
26022 else if (WINDOWP (object))
26023 {
26024 w = decode_live_window (object);
26025 buf = XBUFFER (w->contents);
26026 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
26027 }
26028 else
26029 CHECK_STRING (object);
26030 }
26031
26032 if (STRINGP (object))
26033 {
26034
26035
26036 if (!STRING_MULTIBYTE (object)
26037
26038
26039
26040 || redisplay__inhibit_bidi)
26041 return Qnil;
26042
26043 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
26044 if (from_pos >= SCHARS (object))
26045 return Qnil;
26046
26047
26048 itb_data = bidi_shelve_cache ();
26049 itb.paragraph_dir = NEUTRAL_DIR;
26050 itb.string.lstring = object;
26051 itb.string.s = NULL;
26052 itb.string.schars = SCHARS (object);
26053 itb.string.bufpos = 0;
26054 itb.string.from_disp_str = false;
26055 itb.string.unibyte = false;
26056 itb.w = w;
26057 bidi_init_it (0, 0, frame_window_p, &itb);
26058 }
26059 else
26060 {
26061
26062
26063 if (NILP (BVAR (buf, bidi_display_reordering))
26064 || NILP (BVAR (buf, enable_multibyte_characters))
26065
26066
26067
26068 || redisplay__inhibit_bidi)
26069 return Qnil;
26070
26071 set_buffer_temp (buf);
26072 validate_region (&from, &to);
26073 from_pos = XFIXNUM (from);
26074 to_pos = XFIXNUM (to);
26075 if (from_pos >= ZV)
26076 return Qnil;
26077
26078
26079 itb_data = bidi_shelve_cache ();
26080 from_bpos = CHAR_TO_BYTE (from_pos);
26081 if (from_pos == BEGV)
26082 {
26083 itb.charpos = BEGV;
26084 itb.bytepos = BEGV_BYTE;
26085 }
26086 else if (FETCH_BYTE (from_bpos - 1) == '\n')
26087 {
26088 itb.charpos = from_pos;
26089 itb.bytepos = from_bpos;
26090 }
26091 else
26092 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
26093 -1, &itb.bytepos);
26094 itb.paragraph_dir = NEUTRAL_DIR;
26095 itb.string.s = NULL;
26096 itb.string.lstring = Qnil;
26097 itb.string.bufpos = 0;
26098 itb.string.from_disp_str = false;
26099 itb.string.unibyte = false;
26100 itb.w = w;
26101 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
26102 }
26103
26104 ptrdiff_t found;
26105 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
26106 do {
26107 bidi_paragraph_init (bdir, &itb, false);
26108 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
26109 ;
26110 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
26111
26112 bidi_unshelve_cache (itb_data, false);
26113 set_buffer_temp (old);
26114
26115 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
26116 }
26117
26118 DEFUN ("move-point-visually", Fmove_point_visually,
26119 Smove_point_visually, 1, 1, 0,
26120 doc:
26121
26122
26123
26124 )
26125 (Lisp_Object direction)
26126 {
26127 struct window *w = XWINDOW (selected_window);
26128 struct buffer *b = XBUFFER (w->contents);
26129 struct glyph_row *row;
26130 int dir;
26131 Lisp_Object paragraph_dir;
26132
26133 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
26134 (!(ROW)->continued_p \
26135 && NILP ((GLYPH)->object) \
26136 && (GLYPH)->type == CHAR_GLYPH \
26137 && (GLYPH)->u.ch == ' ' \
26138 && (GLYPH)->charpos >= 0 \
26139 && !(GLYPH)->avoid_cursor_p)
26140
26141 CHECK_FIXNUM (direction);
26142 dir = XFIXNUM (direction);
26143 if (dir > 0)
26144 dir = 1;
26145 else
26146 dir = -1;
26147
26148
26149
26150
26151 if (w->window_end_valid
26152 && !windows_or_buffers_changed
26153 && b
26154 && !b->clip_changed
26155 && !b->prevent_redisplay_optimizations_p
26156 && !window_outdated (w)
26157
26158
26159
26160 && w->last_point == BUF_PT (b)
26161 && w->cursor.vpos >= 0
26162 && w->cursor.vpos < w->current_matrix->nrows
26163 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
26164 {
26165 struct glyph *g = row->glyphs[TEXT_AREA];
26166 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
26167 struct glyph *gpt = g + w->cursor.hpos;
26168
26169 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
26170 {
26171 if (BUFFERP (g->object) && g->charpos != PT)
26172 {
26173 SET_PT (g->charpos);
26174 w->cursor.vpos = -1;
26175 return make_fixnum (PT);
26176 }
26177 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
26178 {
26179 ptrdiff_t new_pos;
26180
26181 if (BUFFERP (gpt->object))
26182 {
26183 new_pos = PT;
26184 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
26185 new_pos += (row->reversed_p ? -dir : dir);
26186 else
26187 new_pos -= (row->reversed_p ? -dir : dir);
26188 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
26189
26190
26191 if (new_pos == PT)
26192 break;
26193 }
26194 else if (BUFFERP (g->object))
26195 new_pos = g->charpos;
26196 else
26197 break;
26198 SET_PT (new_pos);
26199 w->cursor.vpos = -1;
26200 return make_fixnum (PT);
26201 }
26202 else if (ROW_GLYPH_NEWLINE_P (row, g))
26203 {
26204
26205
26206
26207 if (g->charpos > 0)
26208 SET_PT (g->charpos);
26209 else if (row->ends_at_zv_p && PT != ZV)
26210 SET_PT (ZV);
26211 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
26212 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26213 else
26214 break;
26215 w->cursor.vpos = -1;
26216 return make_fixnum (PT);
26217 }
26218 }
26219 if (g == e || NILP (g->object))
26220 {
26221 if (row->truncated_on_left_p || row->truncated_on_right_p)
26222 goto simulate_display;
26223 if (!row->reversed_p)
26224 row += dir;
26225 else
26226 row -= dir;
26227 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
26228 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
26229 goto simulate_display;
26230
26231 if (dir > 0)
26232 {
26233 if (row->reversed_p && !row->continued_p)
26234 {
26235 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26236 w->cursor.vpos = -1;
26237 return make_fixnum (PT);
26238 }
26239 g = row->glyphs[TEXT_AREA];
26240 e = g + row->used[TEXT_AREA];
26241 for ( ; g < e; g++)
26242 {
26243 if (BUFFERP (g->object)
26244
26245
26246
26247 || ROW_GLYPH_NEWLINE_P (row, g)
26248
26249
26250 || (row->ends_at_zv_p
26251 && !row->reversed_p
26252 && NILP (g->object)
26253 && g->type == CHAR_GLYPH
26254 && g->u.ch == ' '))
26255 {
26256 if (g->charpos > 0)
26257 SET_PT (g->charpos);
26258 else if (!row->reversed_p
26259 && row->ends_at_zv_p
26260 && PT != ZV)
26261 SET_PT (ZV);
26262 else
26263 continue;
26264 w->cursor.vpos = -1;
26265 return make_fixnum (PT);
26266 }
26267 }
26268 }
26269 else
26270 {
26271 if (!row->reversed_p && !row->continued_p)
26272 {
26273 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26274 w->cursor.vpos = -1;
26275 return make_fixnum (PT);
26276 }
26277 e = row->glyphs[TEXT_AREA];
26278 g = e + row->used[TEXT_AREA] - 1;
26279 for ( ; g >= e; g--)
26280 {
26281 if (BUFFERP (g->object)
26282 || (ROW_GLYPH_NEWLINE_P (row, g)
26283 && g->charpos > 0)
26284
26285
26286
26287 || g->type == STRETCH_GLYPH
26288 || (row->ends_at_zv_p
26289 && row->reversed_p
26290 && NILP (g->object)
26291 && g->type == CHAR_GLYPH
26292 && g->u.ch == ' '))
26293 {
26294 if (g->charpos > 0)
26295 SET_PT (g->charpos);
26296 else if (row->reversed_p
26297 && row->ends_at_zv_p
26298 && PT != ZV)
26299 SET_PT (ZV);
26300 else
26301 continue;
26302 w->cursor.vpos = -1;
26303 return make_fixnum (PT);
26304 }
26305 }
26306 }
26307 }
26308 }
26309
26310 simulate_display:
26311
26312
26313
26314
26315 if (b)
26316 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26317 else
26318 paragraph_dir = Qleft_to_right;
26319 if (EQ (paragraph_dir, Qright_to_left))
26320 dir = -dir;
26321 if (PT <= BEGV && dir < 0)
26322 xsignal0 (Qbeginning_of_buffer);
26323 else if (PT >= ZV && dir > 0)
26324 xsignal0 (Qend_of_buffer);
26325 else
26326 {
26327 struct text_pos pt;
26328 struct it it;
26329 int pt_x, target_x, pixel_width, pt_vpos;
26330 bool at_eol_p;
26331 bool overshoot_expected = false;
26332 bool target_is_eol_p = false;
26333 void *itdata = bidi_shelve_cache ();
26334
26335
26336 SET_TEXT_POS (pt, PT, PT_BYTE);
26337 start_display (&it, w, pt);
26338
26339
26340
26341
26342
26343
26344 if (it.line_wrap == TRUNCATE)
26345 it.last_visible_x = DISP_INFINITY;
26346
26347 if (it.cmp_it.id < 0
26348 && it.method == GET_FROM_STRING
26349 && it.area == TEXT_AREA
26350 && it.string_from_display_prop_p
26351 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26352 overshoot_expected = true;
26353
26354
26355
26356
26357
26358 reseat:
26359 reseat_at_previous_visible_line_start (&it);
26360 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26361 if (IT_CHARPOS (it) != PT)
26362 {
26363 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26364 -1, -1, -1, MOVE_TO_POS);
26365
26366
26367
26368 if (it.method == GET_FROM_DISPLAY_VECTOR
26369 && it.current.dpvec_index > 0
26370 && !overshoot_expected)
26371 {
26372 overshoot_expected = true;
26373 goto reseat;
26374 }
26375 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26376 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26377 }
26378 pt_x = it.current_x;
26379 pt_vpos = it.vpos;
26380 if (dir > 0 || overshoot_expected)
26381 {
26382 struct glyph_row *row = it.glyph_row;
26383
26384
26385
26386
26387 if (pt_x == 0)
26388 get_next_display_element (&it);
26389 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26390 it.glyph_row = NULL;
26391 PRODUCE_GLYPHS (&it);
26392 it.glyph_row = row;
26393
26394
26395
26396 it.current_x = pt_x;
26397 }
26398 else
26399 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26400 pixel_width = it.pixel_width;
26401 if (overshoot_expected && at_eol_p)
26402 pixel_width = 0;
26403 else if (pixel_width <= 0)
26404 pixel_width = 1;
26405
26406
26407
26408
26409 if (overshoot_expected)
26410 {
26411 if (it.bidi_p)
26412 pt_x += pixel_width * it.bidi_it.scan_dir;
26413 else
26414 pt_x += pixel_width;
26415 }
26416
26417
26418
26419
26420
26421
26422
26423 if (dir > 0)
26424 target_x = pt_x + pixel_width;
26425 else
26426 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26427
26428
26429
26430
26431
26432 if (dir < 0)
26433 {
26434 if (pt_x > 0)
26435 {
26436 start_display (&it, w, pt);
26437 if (it.line_wrap == TRUNCATE)
26438 it.last_visible_x = DISP_INFINITY;
26439 reseat_at_previous_visible_line_start (&it);
26440 it.current_x = it.current_y = it.hpos = 0;
26441 if (pt_vpos != 0)
26442 move_it_by_lines (&it, pt_vpos);
26443 }
26444 else
26445 {
26446 move_it_by_lines (&it, -1);
26447 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26448 target_is_eol_p = true;
26449
26450
26451
26452
26453
26454
26455
26456
26457
26458
26459 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26460 {
26461 void *it_data = NULL;
26462 struct it it2;
26463
26464 SAVE_IT (it2, it, it_data);
26465 move_it_in_display_line_to (&it, ZV, target_x,
26466 MOVE_TO_POS | MOVE_TO_X);
26467
26468
26469 if (it.current_x != target_x)
26470 target_x = it.current_x - 1;
26471 RESTORE_IT (&it, &it2, it_data);
26472 }
26473 }
26474 }
26475 else
26476 {
26477 if (at_eol_p
26478 || (target_x >= it.last_visible_x
26479 && it.line_wrap != TRUNCATE))
26480 {
26481 if (pt_x > 0)
26482 move_it_by_lines (&it, 0);
26483 move_it_by_lines (&it, 1);
26484 target_x = 0;
26485 }
26486 }
26487
26488
26489
26490
26491
26492
26493
26494 if (FRAME_WINDOW_P (it.f) && dir < 0)
26495 {
26496 struct text_pos new_pos;
26497 enum move_it_result rc = MOVE_X_REACHED;
26498
26499 if (it.current_x == 0)
26500 get_next_display_element (&it);
26501 if (it.what == IT_COMPOSITION)
26502 {
26503 new_pos.charpos = it.cmp_it.charpos;
26504 new_pos.bytepos = -1;
26505 }
26506 else
26507 new_pos = it.current.pos;
26508
26509 while (it.current_x + it.pixel_width <= target_x
26510 && (rc == MOVE_X_REACHED
26511
26512
26513
26514 || (it.line_wrap == WORD_WRAP
26515 && rc == MOVE_POS_MATCH_OR_ZV)))
26516 {
26517 int new_x = it.current_x + it.pixel_width;
26518
26519
26520
26521
26522
26523
26524
26525 if (it.what == IT_COMPOSITION)
26526 {
26527 new_pos.charpos = it.cmp_it.charpos;
26528 new_pos.bytepos = -1;
26529 }
26530 else
26531 new_pos = it.current.pos;
26532 if (new_x == it.current_x)
26533 new_x++;
26534 rc = move_it_in_display_line_to (&it, ZV, new_x,
26535 MOVE_TO_POS | MOVE_TO_X);
26536 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26537 break;
26538 }
26539
26540
26541 if (new_pos.bytepos == -1)
26542 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26543 it.current.pos = new_pos;
26544 }
26545 else if (it.current_x != target_x)
26546 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26547
26548
26549
26550 if (dir > 0)
26551 {
26552 while (IT_CHARPOS (it) == PT)
26553 {
26554 set_iterator_to_next (&it, false);
26555 if (!get_next_display_element (&it))
26556 break;
26557 }
26558 }
26559
26560
26561 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26562 bidi_unshelve_cache (itdata, false);
26563 }
26564
26565 return make_fixnum (PT);
26566
26567 #undef ROW_GLYPH_NEWLINE_P
26568 }
26569
26570 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26571 Sbidi_resolved_levels, 0, 1, 0,
26572 doc:
26573
26574
26575
26576
26577
26578
26579
26580
26581
26582
26583
26584
26585
26586
26587
26588
26589
26590
26591
26592
26593
26594
26595
26596
26597
26598 )
26599 (Lisp_Object vpos)
26600 {
26601 struct window *w = XWINDOW (selected_window);
26602 struct buffer *b = XBUFFER (w->contents);
26603 int nrow;
26604 struct glyph_row *row;
26605
26606 if (NILP (vpos))
26607 {
26608 int d1, d2, d3, d4, d5;
26609
26610 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26611 }
26612 else
26613 {
26614 CHECK_FIXNUM (vpos);
26615 nrow = XFIXNUM (vpos);
26616 }
26617
26618
26619 if (w->window_end_valid
26620 && !windows_or_buffers_changed
26621 && b
26622 && !b->clip_changed
26623 && !b->prevent_redisplay_optimizations_p
26624 && !window_outdated (w)
26625 && nrow >= 0
26626 && nrow < w->current_matrix->nrows
26627 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26628 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26629 {
26630 struct glyph *g, *e, *g1;
26631 int nglyphs, i;
26632 Lisp_Object levels;
26633
26634 if (!row->reversed_p)
26635 {
26636 g = g1 = row->glyphs[TEXT_AREA];
26637 e = g + row->used[TEXT_AREA];
26638
26639
26640
26641 while (g < e
26642 && NILP (g->object)
26643 && g->charpos < 0)
26644 g++;
26645 g1 = g;
26646
26647
26648 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26649 nglyphs++;
26650
26651
26652 levels = make_uninit_vector (nglyphs);
26653 for (i = 0; g1 < g; i++, g1++)
26654 ASET (levels, i, make_fixnum (g1->resolved_level));
26655 }
26656 else
26657 {
26658 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26659 e = row->glyphs[TEXT_AREA] - 1;
26660 while (g > e
26661 && NILP (g->object)
26662 && g->charpos < 0)
26663 g--;
26664 g1 = g;
26665 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26666 nglyphs++;
26667 levels = make_uninit_vector (nglyphs);
26668 for (i = 0; g1 > g; i++, g1--)
26669 ASET (levels, i, make_fixnum (g1->resolved_level));
26670 }
26671 return levels;
26672 }
26673 else
26674 return Qnil;
26675 }
26676
26677
26678
26679
26680
26681
26682
26683
26684
26685
26686
26687
26688
26689
26690
26691
26692
26693 static void
26694 display_menu_bar (struct window *w)
26695 {
26696 struct frame *f = XFRAME (WINDOW_FRAME (w));
26697 struct it it;
26698 Lisp_Object items;
26699 int i;
26700
26701
26702 #ifdef HAVE_NTGUI
26703 if (FRAME_W32_P (f))
26704 return;
26705 #endif
26706 #if defined (HAVE_PGTK)
26707 if (FRAME_PGTK_P (f))
26708 return;
26709 #endif
26710
26711 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26712 if (FRAME_X_P (f))
26713 return;
26714 #endif
26715
26716 #ifdef HAVE_NS
26717 if (FRAME_NS_P (f))
26718 return;
26719 #endif
26720
26721 #ifdef HAVE_HAIKU
26722 if (FRAME_HAIKU_P (f))
26723 return;
26724 #endif
26725
26726 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26727 eassert (!FRAME_WINDOW_P (f));
26728 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26729 it.first_visible_x = 0;
26730 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26731 #elif defined (HAVE_X_WINDOWS) || defined (HAVE_ANDROID)
26732 struct window *menu_window = NULL;
26733 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
26734
26735 if (FRAME_WINDOW_P (f))
26736 {
26737
26738
26739 menu_window = XWINDOW (f->menu_bar_window);
26740 init_iterator (&it, menu_window, -1, -1,
26741 menu_window->desired_matrix->rows,
26742 MENU_FACE_ID);
26743 }
26744 else
26745 #endif
26746 {
26747
26748
26749 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26750 MENU_FACE_ID);
26751 it.first_visible_x = 0;
26752 it.last_visible_x = FRAME_COLS (f);
26753 }
26754
26755
26756
26757
26758 it.paragraph_embedding = L2R;
26759
26760
26761 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26762 {
26763 struct glyph_row *row = it.glyph_row + i;
26764 clear_glyph_row (row);
26765 row->enabled_p = true;
26766 row->full_width_p = true;
26767 row->reversed_p = false;
26768 }
26769
26770
26771 items = FRAME_MENU_BAR_ITEMS (it.f);
26772 for (i = 0; i < ASIZE (items); i += 4)
26773 {
26774 Lisp_Object string;
26775
26776
26777 string = AREF (items, i + 1);
26778 if (NILP (string))
26779 break;
26780
26781
26782 ASET (items, i + 3, make_fixnum (it.hpos));
26783
26784
26785 if (it.current_x < it.last_visible_x)
26786 display_string (NULL, string, Qnil, 0, 0, &it,
26787 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26788 }
26789
26790
26791 if (it.current_x < it.last_visible_x)
26792 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26793
26794
26795 compute_line_metrics (&it);
26796 it.glyph_row->full_width_p = true;
26797 it.glyph_row->continued_p = false;
26798 it.glyph_row->truncated_on_left_p = false;
26799 it.glyph_row->truncated_on_right_p = false;
26800
26801
26802
26803
26804
26805 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
26806
26807 extend_face_to_end_of_line (&it);
26808 if (face->box != FACE_NO_BOX)
26809 {
26810 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26811 + it.glyph_row->used[TEXT_AREA] - 1);
26812 int box_thickness = face->box_vertical_line_width;
26813 last->right_box_line_p = true;
26814
26815
26816
26817
26818
26819
26820 if (box_thickness > 0)
26821 last->pixel_width += max (0, (box_thickness
26822 - (it.current_x - it.last_visible_x)));
26823 }
26824
26825
26826
26827 if (FRAME_WINDOW_P (it.f) && menu_window)
26828 {
26829 struct glyph_row *row;
26830 int delta_height;
26831
26832 row = it.glyph_row;
26833 delta_height
26834 = ((row->y + row->height)
26835 - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
26836
26837 if (delta_height != 0)
26838 {
26839 FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
26840 adjust_frame_size (it.f, -1, -1, 3, false, Qmenu_bar_lines);
26841 }
26842 }
26843 #endif
26844 }
26845
26846
26847
26848
26849 #ifndef HAVE_ANDROID
26850
26851
26852 static void
26853 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26854 {
26855 struct glyph *pointers[1 + LAST_AREA];
26856 int to_used = to->used[TEXT_AREA];
26857
26858
26859 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26860
26861
26862 *to = *from;
26863
26864
26865 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26866
26867
26868 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26869 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26870
26871
26872
26873 if (to_used > from->used[TEXT_AREA])
26874 fill_up_frame_row_with_spaces (to, to_used);
26875 }
26876
26877
26878
26879
26880
26881
26882
26883
26884
26885
26886
26887
26888
26889
26890
26891
26892
26893
26894
26895
26896
26897
26898 void
26899 display_tty_menu_item (const char *item_text, int width, int face_id,
26900 int x, int y, bool submenu)
26901 {
26902 struct it it;
26903 struct frame *f = SELECTED_FRAME ();
26904 struct window *w = XWINDOW (f->selected_window);
26905 struct glyph_row *row;
26906 size_t item_len = strlen (item_text);
26907
26908 eassert (FRAME_TERMCAP_P (f));
26909
26910
26911
26912
26913
26914
26915 if (y >= f->desired_matrix->nrows)
26916 return;
26917
26918 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26919 it.first_visible_x = 0;
26920 it.last_visible_x = FRAME_COLS (f) - 1;
26921 row = it.glyph_row;
26922
26923 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26924 bool saved_width = row->full_width_p;
26925 row->full_width_p = true;
26926 bool saved_reversed = row->reversed_p;
26927 row->reversed_p = false;
26928 row->enabled_p = true;
26929
26930
26931
26932 eassert (x < f->desired_matrix->matrix_w);
26933 it.current_x = it.hpos = x;
26934 it.current_y = it.vpos = y;
26935 int saved_used = row->used[TEXT_AREA];
26936 bool saved_truncated = row->truncated_on_right_p;
26937 row->used[TEXT_AREA] = x;
26938 it.face_id = face_id;
26939 it.line_wrap = TRUNCATE;
26940
26941
26942
26943
26944
26945
26946 it.paragraph_embedding = L2R;
26947
26948
26949 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26950 width--;
26951
26952 if (submenu)
26953 {
26954 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26955 item_len, 0, FRAME_COLS (f) - 1, -1);
26956 width -= item_len;
26957
26958 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26959 FRAME_COLS (f) - 1, -1);
26960 }
26961 else
26962 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26963 width, 0, FRAME_COLS (f) - 1, -1);
26964
26965 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26966 row->truncated_on_right_p = saved_truncated;
26967 row->hash = row_hash (row);
26968 row->full_width_p = saved_width;
26969 row->reversed_p = saved_reversed;
26970 }
26971
26972 #endif
26973
26974
26975
26976
26977
26978
26979
26980
26981
26982
26983
26984 static int
26985 redisplay_mode_lines (Lisp_Object window, bool force)
26986 {
26987 int nwindows = 0;
26988
26989 while (!NILP (window))
26990 {
26991 struct window *w = XWINDOW (window);
26992
26993 if (WINDOWP (w->contents))
26994 nwindows += redisplay_mode_lines (w->contents, force);
26995 else if (force
26996 || FRAME_GARBAGED_P (XFRAME (w->frame))
26997 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26998 {
26999 struct text_pos lpoint;
27000 struct buffer *old = current_buffer;
27001
27002
27003 SET_TEXT_POS (lpoint, PT, PT_BYTE);
27004 set_buffer_internal_1 (XBUFFER (w->contents));
27005
27006
27007
27008 if (!EQ (window, selected_window))
27009 {
27010 struct text_pos pt;
27011
27012 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
27013 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
27014 }
27015
27016
27017 clear_glyph_matrix (w->desired_matrix);
27018 if (display_mode_lines (w))
27019 ++nwindows;
27020
27021
27022 set_buffer_internal_1 (old);
27023 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
27024 }
27025
27026 window = w->next;
27027 }
27028
27029 return nwindows;
27030 }
27031
27032
27033
27034
27035
27036
27037 static int
27038 display_mode_lines (struct window *w)
27039 {
27040 Lisp_Object old_selected_window = selected_window;
27041 Lisp_Object new_frame = w->frame;
27042 specpdl_ref count = SPECPDL_INDEX ();
27043 int n = 0;
27044
27045 record_unwind_protect (restore_selected_window, selected_window);
27046 record_unwind_protect
27047 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
27048
27049 if (window_wants_mode_line (w))
27050 {
27051 Lisp_Object window;
27052 Lisp_Object default_help
27053 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
27054
27055
27056
27057 XSETWINDOW (window, w);
27058 if (FUNCTIONP (default_help))
27059 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
27060 else if (STRINGP (default_help))
27061 wset_mode_line_help_echo (w, default_help);
27062 else
27063 wset_mode_line_help_echo (w, Qnil);
27064 }
27065
27066 selected_frame = new_frame;
27067
27068
27069 XSETWINDOW (selected_window, w);
27070 XFRAME (new_frame)->selected_window = selected_window;
27071
27072
27073 line_number_displayed = false;
27074 w->column_number_displayed = -1;
27075
27076 if (window_wants_mode_line (w))
27077 {
27078 Lisp_Object window_mode_line_format
27079 = window_parameter (w, Qmode_line_format);
27080 struct window *sel_w = XWINDOW (old_selected_window);
27081
27082
27083 display_mode_line (w,
27084 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
27085 NILP (window_mode_line_format)
27086 ? BVAR (current_buffer, mode_line_format)
27087 : window_mode_line_format);
27088 ++n;
27089 }
27090
27091 if (window_wants_tab_line (w))
27092 {
27093 Lisp_Object window_tab_line_format
27094 = window_parameter (w, Qtab_line_format);
27095
27096 display_mode_line (w, TAB_LINE_FACE_ID,
27097 NILP (window_tab_line_format)
27098 ? BVAR (current_buffer, tab_line_format)
27099 : window_tab_line_format);
27100 ++n;
27101 }
27102
27103 if (window_wants_header_line (w))
27104 {
27105 Lisp_Object window_header_line_format
27106 = window_parameter (w, Qheader_line_format);
27107
27108 display_mode_line (w, HEADER_LINE_FACE_ID,
27109 NILP (window_header_line_format)
27110 ? BVAR (current_buffer, header_line_format)
27111 : window_header_line_format);
27112 ++n;
27113 }
27114
27115 unbind_to (count, Qnil);
27116
27117 if (n > 0)
27118 w->must_be_updated_p = true;
27119 return n;
27120 }
27121
27122
27123
27124
27125
27126
27127
27128
27129 static int
27130 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
27131 {
27132 struct it it;
27133 struct face *face;
27134 specpdl_ref count = SPECPDL_INDEX ();
27135
27136 init_iterator (&it, w, -1, -1, NULL, face_id);
27137
27138
27139 it.glyph_row->enabled_p = false;
27140 prepare_desired_row (w, it.glyph_row, true);
27141
27142 it.glyph_row->mode_line_p = true;
27143 if (face_id == TAB_LINE_FACE_ID)
27144 {
27145 it.glyph_row->tab_line_p = true;
27146 w->desired_matrix->tab_line_p = true;
27147 }
27148 else if (face_id == HEADER_LINE_FACE_ID)
27149 w->desired_matrix->header_line_p = true;
27150
27151
27152
27153
27154 it.paragraph_embedding = L2R;
27155
27156 record_unwind_protect (unwind_format_mode_line,
27157 format_mode_line_unwind_data (NULL, NULL,
27158 Qnil, false));
27159
27160
27161
27162
27163 push_kboard (FRAME_KBOARD (it.f));
27164 record_unwind_save_match_data ();
27165
27166 if (NILP (Vmode_line_compact)
27167 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
27168 {
27169 mode_line_target = MODE_LINE_DISPLAY;
27170 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27171 }
27172 else
27173 {
27174 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
27175 if (EQ (Vmode_line_compact, Qlong)
27176 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
27177 {
27178
27179
27180 display_string (NULL, mode_string, Qnil,
27181 0, 0, &it, 0, 0, 0,
27182 STRING_MULTIBYTE (mode_string));
27183 }
27184 else
27185 {
27186
27187 ptrdiff_t i = 0, i_byte = 0, start = 0;
27188 int prev = 0;
27189
27190 while (i < SCHARS (mode_string))
27191 {
27192 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
27193 if (c == ' ' && prev == ' ')
27194 {
27195 display_string (NULL,
27196 Fsubstring (mode_string, make_fixnum (start),
27197 make_fixnum (i - 1)),
27198 Qnil, 0, 0, &it, 0, 0, 0,
27199 STRING_MULTIBYTE (mode_string));
27200
27201 while (c == ' ' && i < SCHARS (mode_string))
27202 c = fetch_string_char_advance (mode_string, &i, &i_byte);
27203 start = i - 1;
27204 }
27205 prev = c;
27206 }
27207
27208
27209 if (start < i)
27210 display_string (NULL,
27211 Fsubstring (mode_string, make_fixnum (start),
27212 make_fixnum (i)),
27213 Qnil, 0, 0, &it, 0, 0, 0,
27214 STRING_MULTIBYTE (mode_string));
27215 }
27216 }
27217 pop_kboard ();
27218
27219 unbind_to (count, Qnil);
27220
27221
27222 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
27223
27224 compute_line_metrics (&it);
27225 it.glyph_row->full_width_p = true;
27226 it.glyph_row->continued_p = false;
27227 it.glyph_row->truncated_on_left_p = false;
27228 it.glyph_row->truncated_on_right_p = false;
27229
27230
27231 face = FACE_FROM_ID (it.f, face_id);
27232 extend_face_to_end_of_line (&it);
27233 if (face->box != FACE_NO_BOX)
27234 {
27235 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
27236 + it.glyph_row->used[TEXT_AREA] - 1);
27237 int box_thickness = face->box_vertical_line_width;
27238 last->right_box_line_p = true;
27239
27240
27241
27242
27243
27244
27245 if (box_thickness > 0)
27246 last->pixel_width += max (0, (box_thickness
27247 - (it.current_x - it.last_visible_x)));
27248 }
27249
27250 return it.glyph_row->height;
27251 }
27252
27253
27254
27255
27256 static Lisp_Object
27257 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
27258 {
27259 register Lisp_Object tail, prev;
27260 register Lisp_Object tem;
27261
27262 tail = list;
27263 prev = Qnil;
27264 while (CONSP (tail))
27265 {
27266 tem = XCAR (tail);
27267
27268 if (EQ (elt, tem))
27269 {
27270
27271 if (NILP (prev))
27272 list = XCDR (tail);
27273 else
27274 Fsetcdr (prev, XCDR (tail));
27275
27276
27277 Fsetcdr (tail, list);
27278 return tail;
27279 }
27280 else
27281 prev = tail;
27282 tail = XCDR (tail);
27283 maybe_quit ();
27284 }
27285
27286
27287 return list;
27288 }
27289
27290
27291
27292
27293
27294 static Lisp_Object
27295 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
27296 {
27297 eassert (nargs == 4);
27298 return Fset_text_properties (args[0], args[1], args[2], args[3]);
27299 }
27300
27301
27302
27303
27304
27305
27306
27307
27308
27309
27310
27311
27312
27313
27314
27315
27316
27317
27318
27319
27320
27321
27322
27323
27324
27325 static int
27326 display_mode_element (struct it *it, int depth, int field_width, int precision,
27327 Lisp_Object elt, Lisp_Object props, bool risky)
27328 {
27329 int n = 0, field, prec;
27330 bool literal = false;
27331
27332 tail_recurse:
27333 if (depth > 100)
27334 elt = build_string ("*too-deep*");
27335
27336 depth++;
27337
27338 switch (XTYPE (elt))
27339 {
27340 case Lisp_String:
27341 {
27342
27343 unsigned char c;
27344 ptrdiff_t offset = 0;
27345
27346 if (SCHARS (elt) > 0
27347 && (!NILP (props) || risky))
27348 {
27349 Lisp_Object oprops, aelt;
27350 oprops = Ftext_properties_at (make_fixnum (0), elt);
27351
27352
27353
27354
27355
27356 if (NILP (Fequal (props, oprops)) || risky)
27357 {
27358
27359
27360 if (! NILP (oprops) && !risky)
27361 {
27362 Lisp_Object tem;
27363
27364 oprops = Fcopy_sequence (oprops);
27365 tem = props;
27366 while (CONSP (tem) && CONSP (XCDR (tem)))
27367 {
27368 oprops = plist_put (oprops, XCAR (tem),
27369 XCAR (XCDR (tem)));
27370 tem = XCDR (XCDR (tem));
27371 }
27372 props = oprops;
27373 }
27374
27375 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27376 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27377 {
27378
27379
27380 elt = XCAR (aelt);
27381 mode_line_proptrans_alist
27382 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27383 }
27384 else
27385 {
27386 Lisp_Object tem;
27387
27388
27389
27390 if (! NILP (aelt))
27391 mode_line_proptrans_alist
27392 = Fdelq (aelt, mode_line_proptrans_alist);
27393
27394 elt = Fcopy_sequence (elt);
27395
27396
27397
27398 internal_condition_case_n (safe_set_text_properties,
27399 4,
27400 ((Lisp_Object [])
27401 {make_fixnum (0),
27402 Flength (elt),
27403 props,
27404 elt}),
27405 Qt, safe_eval_handler);
27406
27407 mode_line_proptrans_alist
27408 = Fcons (Fcons (elt, props),
27409 mode_line_proptrans_alist);
27410
27411
27412 tem = Fnthcdr (make_fixnum (50),
27413 mode_line_proptrans_alist);
27414 if (! NILP (tem))
27415 XSETCDR (tem, Qnil);
27416 }
27417 }
27418 }
27419
27420 offset = 0;
27421
27422 if (literal)
27423 {
27424 prec = precision - n;
27425 switch (mode_line_target)
27426 {
27427 case MODE_LINE_NOPROP:
27428 case MODE_LINE_TITLE:
27429 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27430 break;
27431 case MODE_LINE_STRING:
27432 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27433 break;
27434 case MODE_LINE_DISPLAY:
27435 n += display_string (NULL, elt, Qnil, 0, 0, it,
27436 0, prec, 0, STRING_MULTIBYTE (elt));
27437 break;
27438 }
27439
27440 break;
27441 }
27442
27443
27444
27445 while ((precision <= 0 || n < precision)
27446 && SREF (elt, offset) != 0
27447 && (mode_line_target != MODE_LINE_DISPLAY
27448 || it->current_x < it->last_visible_x))
27449 {
27450 ptrdiff_t last_offset = offset;
27451
27452
27453 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27454 ;
27455
27456 if (offset - 1 != last_offset)
27457 {
27458 ptrdiff_t nchars, nbytes;
27459
27460
27461
27462
27463 offset--;
27464
27465 prec = c_string_width (SDATA (elt) + last_offset,
27466 offset - last_offset, precision - n,
27467 &nchars, &nbytes);
27468
27469 switch (mode_line_target)
27470 {
27471 case MODE_LINE_NOPROP:
27472 case MODE_LINE_TITLE:
27473 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27474 break;
27475 case MODE_LINE_STRING:
27476 {
27477 ptrdiff_t bytepos = last_offset;
27478 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27479 ptrdiff_t endpos = (precision <= 0
27480 ? string_byte_to_char (elt, offset)
27481 : charpos + nchars);
27482 Lisp_Object mode_string
27483 = Fsubstring (elt, make_fixnum (charpos),
27484 make_fixnum (endpos));
27485 n += store_mode_line_string (NULL, mode_string, false,
27486 0, 0, Qnil);
27487 }
27488 break;
27489 case MODE_LINE_DISPLAY:
27490 {
27491 ptrdiff_t bytepos = last_offset;
27492 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27493
27494 if (precision <= 0)
27495 nchars = string_byte_to_char (elt, offset) - charpos;
27496 n += display_string (NULL, elt, Qnil, 0, charpos,
27497 it, 0, nchars, 0,
27498 STRING_MULTIBYTE (elt));
27499 }
27500 break;
27501 }
27502 }
27503 else
27504 {
27505 ptrdiff_t percent_position = offset;
27506
27507
27508
27509 field = 0;
27510 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27511 field = field * 10 + c - '0';
27512
27513
27514 if (field_width - n > 0 && field > field_width - n)
27515 field = field_width - n;
27516
27517
27518 prec = precision - n;
27519
27520 if (c == 'M')
27521 n += display_mode_element (it, depth, field, prec,
27522 Vglobal_mode_string, props,
27523 risky);
27524 else if (c != 0)
27525 {
27526 bool multibyte;
27527 ptrdiff_t bytepos, charpos;
27528 const char *spec;
27529 Lisp_Object string;
27530
27531 bytepos = percent_position;
27532 charpos = (STRING_MULTIBYTE (elt)
27533 ? string_byte_to_char (elt, bytepos)
27534 : bytepos);
27535 spec = decode_mode_spec (it->w, c, field, &string);
27536 eassert (NILP (string) || STRINGP (string));
27537 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27538
27539
27540 ptrdiff_t nbytes = strlen (spec);
27541 ptrdiff_t nchars, mb_nbytes;
27542 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27543 &nchars, &mb_nbytes);
27544 if (!(nbytes == nchars || nbytes != mb_nbytes))
27545 multibyte = true;
27546
27547 switch (mode_line_target)
27548 {
27549 case MODE_LINE_NOPROP:
27550 case MODE_LINE_TITLE:
27551 n += store_mode_line_noprop (spec, field, prec);
27552 break;
27553 case MODE_LINE_STRING:
27554 {
27555 Lisp_Object tem = build_string (spec);
27556 props = Ftext_properties_at (make_fixnum (charpos), elt);
27557
27558 n += store_mode_line_string (NULL, tem, false,
27559 field, prec, props);
27560 }
27561 break;
27562 case MODE_LINE_DISPLAY:
27563 {
27564 int nglyphs_before, nwritten;
27565
27566 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27567 nwritten = display_string (spec, string, elt,
27568 charpos, 0, it,
27569 field, prec, 0,
27570 multibyte);
27571
27572
27573
27574
27575 if (nwritten > 0)
27576 {
27577 struct glyph *glyph
27578 = (it->glyph_row->glyphs[TEXT_AREA]
27579 + nglyphs_before);
27580 int i;
27581
27582 for (i = 0; i < nwritten; ++i)
27583 {
27584 glyph[i].object = elt;
27585 glyph[i].charpos = charpos;
27586 }
27587
27588 n += nwritten;
27589 }
27590 }
27591 break;
27592 }
27593 }
27594 else
27595 break;
27596 }
27597 }
27598 }
27599 break;
27600
27601 case Lisp_Symbol:
27602
27603
27604
27605
27606 {
27607 register Lisp_Object tem;
27608
27609
27610
27611 if (NILP (Fget (elt, Qrisky_local_variable)))
27612 risky = true;
27613
27614 tem = Fboundp (elt);
27615 if (!NILP (tem))
27616 {
27617 tem = Fsymbol_value (elt);
27618
27619
27620 if (STRINGP (tem))
27621 literal = true;
27622
27623 if (!EQ (tem, elt))
27624 {
27625
27626 elt = tem;
27627 goto tail_recurse;
27628 }
27629 }
27630 }
27631 break;
27632
27633 case Lisp_Cons:
27634 {
27635 register Lisp_Object car, tem;
27636
27637
27638
27639
27640
27641
27642
27643
27644
27645
27646 car = XCAR (elt);
27647 if (EQ (car, QCeval))
27648 {
27649
27650
27651
27652 if (risky)
27653 break;
27654
27655 if (CONSP (XCDR (elt)))
27656 {
27657 Lisp_Object spec;
27658 spec = safe__eval (true, XCAR (XCDR (elt)));
27659
27660
27661
27662
27663
27664
27665 if (!FRAME_LIVE_P (it->f))
27666 signal_error (":eval deleted the frame being displayed", elt);
27667 n += display_mode_element (it, depth, field_width - n,
27668 precision - n, spec, props,
27669 risky);
27670 }
27671 }
27672 else if (EQ (car, QCpropertize))
27673 {
27674
27675
27676
27677 if (risky)
27678 break;
27679
27680 if (CONSP (XCDR (elt)))
27681 n += display_mode_element (it, depth, field_width - n,
27682 precision - n, XCAR (XCDR (elt)),
27683 XCDR (XCDR (elt)), risky);
27684 }
27685 else if (SYMBOLP (car))
27686 {
27687 tem = Fboundp (car);
27688 elt = XCDR (elt);
27689 if (!CONSP (elt))
27690 goto invalid;
27691
27692
27693 if (!NILP (tem))
27694 {
27695 tem = Fsymbol_value (car);
27696 if (!NILP (tem))
27697 {
27698 elt = XCAR (elt);
27699 goto tail_recurse;
27700 }
27701 }
27702
27703
27704
27705 elt = XCDR (elt);
27706 if (NILP (elt))
27707 break;
27708 else if (!CONSP (elt))
27709 goto invalid;
27710 elt = XCAR (elt);
27711 goto tail_recurse;
27712 }
27713 else if (FIXNUMP (car))
27714 {
27715 register int lim = XFIXNUM (car);
27716 elt = XCDR (elt);
27717 if (lim < 0)
27718 {
27719
27720 if (precision <= 0)
27721 precision = -lim;
27722 else
27723 precision = min (precision, -lim);
27724 }
27725 else if (lim > 0)
27726 {
27727
27728
27729 if (precision > 0)
27730 lim = min (precision, lim);
27731
27732
27733
27734
27735 field_width = max (lim, field_width);
27736 }
27737 goto tail_recurse;
27738 }
27739 else if (STRINGP (car) || CONSP (car))
27740 FOR_EACH_TAIL_SAFE (elt)
27741 {
27742 if (0 < precision && precision <= n)
27743 break;
27744 n += display_mode_element (it, depth,
27745
27746
27747 (! CONSP (XCDR (elt))
27748 ? field_width - n
27749 : 0),
27750 precision - n, XCAR (elt),
27751 props, risky);
27752 }
27753 }
27754 break;
27755
27756 default:
27757 invalid:
27758 elt = build_string ("*invalid*");
27759 goto tail_recurse;
27760 }
27761
27762
27763 if (field_width > 0 && n < field_width)
27764 {
27765 switch (mode_line_target)
27766 {
27767 case MODE_LINE_NOPROP:
27768 case MODE_LINE_TITLE:
27769 n += store_mode_line_noprop ("", field_width - n, 0);
27770 break;
27771 case MODE_LINE_STRING:
27772 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27773 Qnil);
27774 break;
27775 case MODE_LINE_DISPLAY:
27776 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27777 0, 0, 0);
27778 break;
27779 }
27780 }
27781
27782 return n;
27783 }
27784
27785
27786
27787
27788
27789
27790
27791
27792
27793
27794
27795
27796
27797
27798
27799
27800
27801
27802
27803
27804 static int
27805 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27806 bool copy_string,
27807 int field_width, int precision, Lisp_Object props)
27808 {
27809 ptrdiff_t len;
27810 int n = 0;
27811
27812 if (string != NULL)
27813 {
27814 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27815 lisp_string = make_string (string, len);
27816 if (NILP (props))
27817 props = mode_line_string_face_prop;
27818 else if (!NILP (mode_line_string_face))
27819 {
27820 Lisp_Object face = plist_get (props, Qface);
27821 props = Fcopy_sequence (props);
27822 if (NILP (face))
27823 face = mode_line_string_face;
27824 else
27825 face = list2 (face, mode_line_string_face);
27826 props = plist_put (props, Qface, face);
27827 }
27828 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27829 props, lisp_string);
27830 }
27831 else
27832 {
27833 len = SCHARS (lisp_string);
27834 if (precision > 0 && len > precision)
27835 {
27836 len = precision;
27837 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27838 precision = -1;
27839 }
27840 if (!NILP (mode_line_string_face))
27841 {
27842 Lisp_Object face;
27843 if (NILP (props))
27844 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27845 face = plist_get (props, Qface);
27846 if (NILP (face))
27847 face = mode_line_string_face;
27848 else
27849 face = list2 (face, mode_line_string_face);
27850 props = list2 (Qface, face);
27851 if (copy_string)
27852 lisp_string = Fcopy_sequence (lisp_string);
27853 }
27854 if (!NILP (props))
27855 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27856 props, lisp_string);
27857 }
27858
27859 if (len > 0)
27860 {
27861 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27862 n += len;
27863 }
27864
27865 if (field_width > len)
27866 {
27867 field_width -= len;
27868 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27869 Qnil);
27870 if (!NILP (props))
27871 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27872 props, lisp_string);
27873 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27874 n += field_width;
27875 }
27876
27877 return n;
27878 }
27879
27880
27881 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27882 1, 4, 0,
27883 doc:
27884
27885
27886
27887
27888
27889
27890
27891
27892
27893
27894
27895
27896
27897
27898
27899 )
27900 (Lisp_Object format, Lisp_Object face,
27901 Lisp_Object window, Lisp_Object buffer)
27902 {
27903 struct it it;
27904 int len;
27905 struct window *w;
27906 struct buffer *old_buffer = NULL;
27907 int face_id;
27908 bool no_props = FIXNUMP (face);
27909 specpdl_ref count = SPECPDL_INDEX ();
27910 Lisp_Object str;
27911 int string_start = 0;
27912
27913 w = decode_any_window (window);
27914 XSETWINDOW (window, w);
27915
27916 if (NILP (buffer))
27917 buffer = w->contents;
27918 CHECK_BUFFER (buffer);
27919 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
27920 error ("Attempt to format a mode line for a dead buffer");
27921
27922
27923
27924 if (NILP (format) || noninteractive)
27925 return empty_unibyte_string;
27926
27927 if (no_props)
27928 face = Qnil;
27929
27930 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27931 : EQ (face, Qt) ? (EQ (window, selected_window)
27932 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27933 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27934 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27935 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27936 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27937 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27938 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27939 : DEFAULT_FACE_ID;
27940
27941 old_buffer = current_buffer;
27942
27943
27944
27945 record_unwind_protect (unwind_format_mode_line,
27946 format_mode_line_unwind_data
27947 (XFRAME (WINDOW_FRAME (w)),
27948 old_buffer, selected_window, true));
27949 mode_line_proptrans_alist = Qnil;
27950
27951 Fselect_window (window, Qt);
27952 set_buffer_internal_1 (XBUFFER (buffer));
27953
27954 init_iterator (&it, w, -1, -1, NULL, face_id);
27955
27956 if (no_props)
27957 {
27958 mode_line_target = MODE_LINE_NOPROP;
27959 mode_line_string_face_prop = Qnil;
27960 mode_line_string_list = Qnil;
27961 string_start = MODE_LINE_NOPROP_LEN (0);
27962 }
27963 else
27964 {
27965 mode_line_target = MODE_LINE_STRING;
27966 mode_line_string_list = Qnil;
27967 mode_line_string_face = face;
27968 mode_line_string_face_prop
27969 = NILP (face) ? Qnil : list2 (Qface, face);
27970 }
27971
27972 push_kboard (FRAME_KBOARD (it.f));
27973 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27974 pop_kboard ();
27975
27976 if (no_props)
27977 {
27978 len = MODE_LINE_NOPROP_LEN (string_start);
27979 str = make_string (mode_line_noprop_buf + string_start, len);
27980 }
27981 else
27982 {
27983 mode_line_string_list = Fnreverse (mode_line_string_list);
27984 str = Fmapconcat (Qidentity, mode_line_string_list,
27985 empty_unibyte_string);
27986 }
27987
27988 return unbind_to (count, str);
27989 }
27990
27991
27992
27993
27994 static void
27995 pint2str (register char *buf, register int width, register ptrdiff_t d)
27996 {
27997 register char *p = buf;
27998
27999 if (d <= 0)
28000 *p++ = '0';
28001 else
28002 {
28003 while (d > 0)
28004 {
28005 *p++ = d % 10 + '0';
28006 d /= 10;
28007 }
28008 }
28009
28010 for (width -= (int) (p - buf); width > 0; --width)
28011 *p++ = ' ';
28012 *p-- = '\0';
28013 while (p > buf)
28014 {
28015 d = *buf;
28016 *buf++ = *p;
28017 *p-- = d;
28018 }
28019 }
28020
28021
28022
28023
28024
28025 static const char power_letter[] =
28026 {
28027 0,
28028 'k',
28029 'M',
28030 'G',
28031 'T',
28032 'P',
28033 'E',
28034 'Z',
28035 'Y',
28036 'R',
28037 'Q'
28038 };
28039
28040 static void
28041 pint2hrstr (char *buf, int width, ptrdiff_t d)
28042 {
28043
28044
28045 ptrdiff_t quotient = d;
28046 int remainder = 0;
28047
28048 int tenths = -1;
28049 int exponent = 0;
28050
28051
28052 int length;
28053
28054 char * psuffix;
28055 char * p;
28056
28057 if (quotient >= 1000)
28058 {
28059
28060 do
28061 {
28062 remainder = quotient % 1000;
28063 quotient /= 1000;
28064 exponent++;
28065 }
28066 while (quotient >= 1000);
28067
28068
28069 if (quotient <= 9)
28070 {
28071 tenths = remainder / 100;
28072 if (remainder % 100 >= 50)
28073 {
28074 if (tenths < 9)
28075 tenths++;
28076 else
28077 {
28078 quotient++;
28079 if (quotient == 10)
28080 tenths = -1;
28081 else
28082 tenths = 0;
28083 }
28084 }
28085 }
28086 else
28087 if (remainder >= 500)
28088 {
28089 if (quotient < 999)
28090 quotient++;
28091 else
28092 {
28093 quotient = 1;
28094 exponent++;
28095 tenths = 0;
28096 }
28097 }
28098 }
28099
28100
28101 if (tenths == -1 && quotient <= 99)
28102 if (quotient <= 9)
28103 length = 1;
28104 else
28105 length = 2;
28106 else
28107 length = 3;
28108 p = psuffix = buf + max (width, length);
28109
28110
28111 *psuffix++ = power_letter[exponent];
28112 *psuffix = '\0';
28113
28114
28115 if (tenths >= 0)
28116 {
28117 *--p = '0' + tenths;
28118 *--p = '.';
28119 }
28120
28121
28122 do
28123 {
28124 int digit = quotient % 10;
28125 *--p = '0' + digit;
28126 }
28127 while ((quotient /= 10) != 0);
28128
28129
28130 while (buf < p)
28131 *--p = ' ';
28132 }
28133
28134
28135
28136
28137
28138 static unsigned char invalid_eol_type[] = "(*invalid*)";
28139
28140 static char *
28141 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
28142 {
28143 Lisp_Object val;
28144 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
28145 const unsigned char *eol_str;
28146 int eol_str_len;
28147
28148 Lisp_Object eoltype;
28149
28150 val = CODING_SYSTEM_SPEC (coding_system);
28151 eoltype = Qnil;
28152
28153 if (!VECTORP (val))
28154 {
28155 *buf++ = multibyte ? '-' : ' ';
28156 if (eol_flag)
28157 eoltype = eol_mnemonic_undecided;
28158
28159 }
28160 else
28161 {
28162 Lisp_Object attrs;
28163 Lisp_Object eolvalue;
28164
28165 attrs = AREF (val, 0);
28166 eolvalue = AREF (val, 2);
28167
28168 if (multibyte)
28169 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
28170 (unsigned char *) buf);
28171 else
28172 *buf++ = ' ';
28173
28174 if (eol_flag)
28175 {
28176
28177
28178 if (NILP (eolvalue))
28179 eoltype = eol_mnemonic_undecided;
28180 else if (VECTORP (eolvalue))
28181 eoltype = eol_mnemonic_undecided;
28182 else
28183 eoltype = (EQ (eolvalue, Qunix)
28184 ? eol_mnemonic_unix
28185 : EQ (eolvalue, Qdos)
28186 ? eol_mnemonic_dos : eol_mnemonic_mac);
28187 }
28188 }
28189
28190 if (eol_flag)
28191 {
28192
28193 if (STRINGP (eoltype))
28194 {
28195 eol_str = SDATA (eoltype);
28196 eol_str_len = SBYTES (eoltype);
28197 }
28198 else if (CHARACTERP (eoltype))
28199 {
28200 int c = XFIXNAT (eoltype);
28201 return buf + CHAR_STRING (c, (unsigned char *) buf);
28202 }
28203 else
28204 {
28205 eol_str = invalid_eol_type;
28206 eol_str_len = sizeof (invalid_eol_type) - 1;
28207 }
28208 memcpy (buf, eol_str, eol_str_len);
28209 buf += eol_str_len;
28210 }
28211
28212 return buf;
28213 }
28214
28215
28216
28217
28218 static int
28219 percent99 (ptrdiff_t n, ptrdiff_t d)
28220 {
28221 int percent = (d - 1 + 100.0 * n) / d;
28222 return min (percent, 99);
28223 }
28224
28225
28226
28227
28228
28229
28230
28231
28232
28233 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
28234
28235 static const char *
28236 decode_mode_spec (struct window *w, register int c, int field_width,
28237 Lisp_Object *string)
28238 {
28239 Lisp_Object obj;
28240 struct frame *f = XFRAME (WINDOW_FRAME (w));
28241 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
28242
28243
28244
28245
28246
28247 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
28248 struct buffer *b = current_buffer;
28249
28250 obj = Qnil;
28251 *string = Qnil;
28252
28253 switch (c)
28254 {
28255 case '*':
28256 if (!NILP (BVAR (b, read_only)))
28257 return "%";
28258 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28259 return "*";
28260 return "-";
28261
28262 case '+':
28263
28264 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28265 return "*";
28266 if (!NILP (BVAR (b, read_only)))
28267 return "%";
28268 return "-";
28269
28270 case '&':
28271
28272 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28273 return "*";
28274 return "-";
28275
28276 case '%':
28277 return "%";
28278
28279 case '[':
28280 {
28281 int i;
28282 char *p;
28283
28284 if (command_loop_level > 5)
28285 return "[[[... ";
28286 p = decode_mode_spec_buf;
28287 for (i = 0; i < command_loop_level; i++)
28288 *p++ = '[';
28289 *p = 0;
28290 return decode_mode_spec_buf;
28291 }
28292
28293 case ']':
28294 {
28295 int i;
28296 char *p;
28297
28298 if (command_loop_level > 5)
28299 return " ...]]]";
28300 p = decode_mode_spec_buf;
28301 for (i = 0; i < command_loop_level; i++)
28302 *p++ = ']';
28303 *p = 0;
28304 return decode_mode_spec_buf;
28305 }
28306
28307 case '-':
28308 {
28309 register int i;
28310
28311
28312 if (mode_line_target == MODE_LINE_NOPROP
28313 || mode_line_target == MODE_LINE_STRING)
28314 return "--";
28315 if (field_width <= 0
28316 || field_width > sizeof (lots_of_dashes))
28317 {
28318 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28319 decode_mode_spec_buf[i] = '-';
28320 decode_mode_spec_buf[i] = '\0';
28321 return decode_mode_spec_buf;
28322 }
28323 else
28324 return lots_of_dashes;
28325 }
28326
28327 case 'b':
28328 obj = BVAR (b, name);
28329 break;
28330
28331 case 'c':
28332 case 'C':
28333
28334
28335
28336
28337
28338 if (mode_line_target == MODE_LINE_TITLE)
28339 return "";
28340 else
28341 {
28342 ptrdiff_t col = current_column ();
28343 int disp_col = (c == 'C') ? col + 1 : col;
28344 w->column_number_displayed = col;
28345 pint2str (decode_mode_spec_buf, width, disp_col);
28346 return decode_mode_spec_buf;
28347 }
28348
28349 case 'e':
28350 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28351 {
28352 if (NILP (Vmemory_full))
28353 return "";
28354 else
28355 return "!MEM FULL! ";
28356 }
28357 #else
28358 return "";
28359 #endif
28360
28361 case 'F':
28362
28363 if (!NILP (f->title))
28364 return SSDATA (f->title);
28365 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28366 return SSDATA (f->name);
28367 return "Emacs";
28368
28369 case 'f':
28370 obj = BVAR (b, filename);
28371 break;
28372
28373 case 'i':
28374 {
28375 ptrdiff_t size = ZV - BEGV;
28376 pint2str (decode_mode_spec_buf, width, size);
28377 return decode_mode_spec_buf;
28378 }
28379
28380 case 'I':
28381 {
28382 ptrdiff_t size = ZV - BEGV;
28383 pint2hrstr (decode_mode_spec_buf, width, size);
28384 return decode_mode_spec_buf;
28385 }
28386
28387 case 'l':
28388 {
28389 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28390 ptrdiff_t topline, nlines, height;
28391 ptrdiff_t junk;
28392
28393
28394 if (mode_line_target == MODE_LINE_TITLE)
28395 return "";
28396
28397 startpos = marker_position (w->start);
28398 startpos_byte = marker_byte_position (w->start);
28399 height = WINDOW_TOTAL_LINES (w);
28400
28401
28402
28403
28404
28405
28406
28407
28408 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28409 && startpos_byte <= BUF_ZV_BYTE (b)))
28410 {
28411 startpos = BUF_BEGV (b);
28412 startpos_byte = BUF_BEGV_BYTE (b);
28413 w->base_line_pos = 0;
28414 w->base_line_number = 0;
28415 }
28416
28417
28418
28419 if (w->base_line_pos == -1)
28420 goto no_value;
28421
28422
28423 if (FIXNUMP (Vline_number_display_limit)
28424 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28425 {
28426 w->base_line_pos = 0;
28427 w->base_line_number = 0;
28428 goto no_value;
28429 }
28430
28431 if (w->base_line_number > 0
28432 && w->base_line_pos > 0
28433 && w->base_line_pos <= startpos)
28434 {
28435 line = w->base_line_number;
28436 linepos = w->base_line_pos;
28437 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28438 }
28439 else
28440 {
28441 line = 1;
28442 linepos = BUF_BEGV (b);
28443 linepos_byte = BUF_BEGV_BYTE (b);
28444 }
28445
28446
28447 nlines = display_count_lines (linepos_byte,
28448 startpos_byte,
28449 startpos, &junk);
28450
28451 topline = nlines + line;
28452
28453
28454
28455
28456
28457 if (startpos == BUF_BEGV (b))
28458 {
28459 w->base_line_number = topline;
28460 w->base_line_pos = BUF_BEGV (b);
28461 }
28462 else if (nlines < height + 25 || nlines > height * 3 + 50
28463 || linepos == BUF_BEGV (b))
28464 {
28465 ptrdiff_t limit = BUF_BEGV (b);
28466 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28467 ptrdiff_t position;
28468 ptrdiff_t distance
28469 = (line_number_display_limit_width < 0 ? 0
28470 : ckd_mul (&distance, line_number_display_limit_width,
28471 height * 2 + 30)
28472 ? PTRDIFF_MAX : distance);
28473
28474 if (startpos - distance > limit)
28475 {
28476 limit = startpos - distance;
28477 limit_byte = CHAR_TO_BYTE (limit);
28478 }
28479
28480 nlines = display_count_lines (startpos_byte,
28481 limit_byte,
28482 - (height * 2 + 30),
28483 &position);
28484
28485
28486
28487 if (position == limit_byte && limit == startpos - distance)
28488 {
28489 w->base_line_pos = -1;
28490 w->base_line_number = 0;
28491 goto no_value;
28492 }
28493
28494 w->base_line_number = topline - nlines;
28495 w->base_line_pos = BYTE_TO_CHAR (position);
28496 }
28497
28498
28499 nlines = display_count_lines (startpos_byte,
28500 PT_BYTE, PT, &junk);
28501
28502
28503 line_number_displayed = true;
28504
28505
28506 pint2str (decode_mode_spec_buf, width, topline + nlines);
28507 return decode_mode_spec_buf;
28508 no_value:
28509 {
28510 char *p = decode_mode_spec_buf;
28511 int pad = width - 2;
28512 while (pad-- > 0)
28513 *p++ = ' ';
28514 *p++ = '?';
28515 *p++ = '?';
28516 *p = '\0';
28517 return decode_mode_spec_buf;
28518 }
28519 }
28520 break;
28521
28522 case 'm':
28523 obj = BVAR (b, mode_name);
28524 break;
28525
28526 case 'n':
28527 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28528 return " Narrow";
28529 break;
28530
28531
28532 case 'o':
28533 {
28534 ptrdiff_t toppos = marker_position (w->start);
28535 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28536 ptrdiff_t begv = BUF_BEGV (b);
28537 ptrdiff_t zv = BUF_ZV (b);
28538
28539 if (zv <= botpos)
28540 return toppos <= begv ? "All" : "Bottom";
28541 else if (toppos <= begv)
28542 return "Top";
28543 else
28544 {
28545 sprintf (decode_mode_spec_buf, "%2d%%",
28546 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28547 return decode_mode_spec_buf;
28548 }
28549 }
28550
28551
28552 case 'p':
28553 {
28554 ptrdiff_t pos = marker_position (w->start);
28555 ptrdiff_t begv = BUF_BEGV (b);
28556 ptrdiff_t zv = BUF_ZV (b);
28557
28558 if (w->window_end_pos <= BUF_Z (b) - zv)
28559 return pos <= begv ? "All" : "Bottom";
28560 else if (pos <= begv)
28561 return "Top";
28562 else
28563 {
28564 sprintf (decode_mode_spec_buf, "%2d%%",
28565 percent99 (pos - begv, zv - begv));
28566 return decode_mode_spec_buf;
28567 }
28568 }
28569
28570
28571 case 'P':
28572 {
28573 ptrdiff_t toppos = marker_position (w->start);
28574 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28575 ptrdiff_t begv = BUF_BEGV (b);
28576 ptrdiff_t zv = BUF_ZV (b);
28577
28578 if (zv <= botpos)
28579 return toppos <= begv ? "All" : "Bottom";
28580 else
28581 {
28582 sprintf (decode_mode_spec_buf,
28583 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28584 percent99 (botpos - begv, zv - begv));
28585 return decode_mode_spec_buf;
28586 }
28587 }
28588
28589
28590
28591 case 'q':
28592 {
28593 ptrdiff_t toppos = marker_position (w->start);
28594 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28595 ptrdiff_t begv = BUF_BEGV (b);
28596 ptrdiff_t zv = BUF_ZV (b);
28597 int top_perc, bot_perc;
28598
28599 if ((toppos <= begv) && (zv <= botpos))
28600 return "All ";
28601
28602 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28603 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28604
28605 if (top_perc == bot_perc)
28606 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28607 else
28608 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28609
28610 return decode_mode_spec_buf;
28611 }
28612
28613 case 's':
28614
28615 obj = Fget_buffer_process (Fcurrent_buffer ());
28616 if (NILP (obj))
28617 return "no process";
28618 #ifndef MSDOS
28619 obj = Fsymbol_name (Fprocess_status (obj));
28620 #endif
28621 break;
28622
28623 case '@':
28624 {
28625 specpdl_ref count = inhibit_garbage_collection ();
28626 Lisp_Object curdir = BVAR (current_buffer, directory);
28627 Lisp_Object val = Qnil;
28628
28629 if (STRINGP (curdir))
28630 val = safe_call1 (intern ("file-remote-p"), curdir);
28631
28632 val = unbind_to (count, val);
28633
28634 if (NILP (val))
28635 return "-";
28636 else
28637 return "@";
28638 }
28639
28640 case 'z':
28641
28642 case 'Z':
28643
28644 {
28645 bool eol_flag = (c == 'Z');
28646 char *p = decode_mode_spec_buf;
28647
28648 if (! FRAME_WINDOW_P (f))
28649 {
28650
28651
28652 p = decode_mode_spec_coding (CODING_ID_NAME
28653 (FRAME_KEYBOARD_CODING (f)->id),
28654 p, false);
28655 p = decode_mode_spec_coding (CODING_ID_NAME
28656 (FRAME_TERMINAL_CODING (f)->id),
28657 p, false);
28658 }
28659 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28660 p, eol_flag);
28661
28662 #if false
28663 #ifdef subprocesses
28664 obj = Fget_buffer_process (Fcurrent_buffer ());
28665 if (PROCESSP (obj))
28666 {
28667 p = decode_mode_spec_coding
28668 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28669 p = decode_mode_spec_coding
28670 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28671 }
28672 #endif
28673 #endif
28674 *p = 0;
28675 return decode_mode_spec_buf;
28676 }
28677 }
28678
28679 if (STRINGP (obj))
28680 {
28681 *string = obj;
28682 return SSDATA (obj);
28683 }
28684 else
28685 return "";
28686 }
28687
28688
28689
28690
28691 ptrdiff_t
28692 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28693 {
28694 ptrdiff_t ignored;
28695 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28696 }
28697
28698
28699
28700
28701
28702
28703
28704
28705
28706
28707
28708 static ptrdiff_t
28709 display_count_lines (ptrdiff_t start_byte,
28710 ptrdiff_t limit_byte, ptrdiff_t count,
28711 ptrdiff_t *byte_pos_ptr)
28712 {
28713 register unsigned char *cursor;
28714 unsigned char *base;
28715
28716 register ptrdiff_t ceiling;
28717 register unsigned char *ceiling_addr;
28718 ptrdiff_t orig_count = count;
28719
28720
28721
28722 bool selective_display
28723 = (!NILP (BVAR (current_buffer, selective_display))
28724 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28725
28726 if (count > 0)
28727 {
28728 while (start_byte < limit_byte)
28729 {
28730 ceiling = BUFFER_CEILING_OF (start_byte);
28731 ceiling = min (limit_byte - 1, ceiling);
28732 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28733 base = (cursor = BYTE_POS_ADDR (start_byte));
28734
28735 do
28736 {
28737 if (selective_display)
28738 {
28739 while (*cursor != '\n' && *cursor != 015
28740 && ++cursor != ceiling_addr)
28741 continue;
28742 if (cursor == ceiling_addr)
28743 break;
28744 }
28745 else
28746 {
28747 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28748 if (! cursor)
28749 break;
28750 }
28751
28752 cursor++;
28753
28754 if (--count == 0)
28755 {
28756 start_byte += cursor - base;
28757 *byte_pos_ptr = start_byte;
28758 return orig_count;
28759 }
28760 }
28761 while (cursor < ceiling_addr);
28762
28763 start_byte += ceiling_addr - base;
28764 }
28765 }
28766 else
28767 {
28768 while (start_byte > limit_byte)
28769 {
28770 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28771 ceiling = max (limit_byte, ceiling);
28772 ceiling_addr = BYTE_POS_ADDR (ceiling);
28773 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28774 while (true)
28775 {
28776 if (selective_display)
28777 {
28778 while (--cursor >= ceiling_addr
28779 && *cursor != '\n' && *cursor != 015)
28780 continue;
28781 if (cursor < ceiling_addr)
28782 break;
28783 }
28784 else
28785 {
28786 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28787 if (! cursor)
28788 break;
28789 }
28790
28791 if (++count == 0)
28792 {
28793 start_byte += cursor - base + 1;
28794 *byte_pos_ptr = start_byte;
28795
28796
28797 return - orig_count - 1;
28798 }
28799 }
28800 start_byte += ceiling_addr - base;
28801 }
28802 }
28803
28804 *byte_pos_ptr = limit_byte;
28805
28806 if (count < 0)
28807 return - orig_count + count;
28808 return orig_count - count;
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
28847
28848
28849
28850
28851
28852
28853
28854
28855
28856 static int
28857 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28858 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28859 int field_width, int precision, int max_x, int multibyte)
28860 {
28861 int hpos_at_start = it->hpos;
28862 int saved_face_id = it->face_id;
28863 struct glyph_row *row = it->glyph_row;
28864 ptrdiff_t it_charpos;
28865
28866
28867
28868 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28869 start, precision, field_width, multibyte);
28870
28871 if (string && STRINGP (lisp_string))
28872
28873
28874 it->stop_charpos = it->end_charpos;
28875
28876
28877
28878 if (STRINGP (face_string))
28879 {
28880 ptrdiff_t endptr;
28881 struct face *face;
28882
28883 it->face_id
28884 = face_at_string_position (it->w, face_string, face_string_pos,
28885 0, &endptr, it->base_face_id, false, 0);
28886 face = FACE_FROM_ID (it->f, it->face_id);
28887 it->face_box_p = face->box != FACE_NO_BOX;
28888
28889
28890
28891
28892 if (NILP (lisp_string))
28893 {
28894 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28895 face_string);
28896 if (!NILP (display))
28897 {
28898 Lisp_Object min_width = plist_get (display, Qmin_width);
28899 if (!NILP (min_width))
28900 display_min_width (it, 0, face_string, min_width);
28901 }
28902 }
28903 }
28904
28905
28906
28907 if (max_x <= 0)
28908 max_x = it->last_visible_x;
28909 else
28910 max_x = min (max_x, it->last_visible_x);
28911
28912
28913
28914 if (it->current_x < it->first_visible_x)
28915 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28916 MOVE_TO_POS | MOVE_TO_X);
28917
28918 row->ascent = it->max_ascent;
28919 row->height = it->max_ascent + it->max_descent;
28920 row->phys_ascent = it->max_phys_ascent;
28921 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28922 row->extra_line_spacing = it->max_extra_line_spacing;
28923
28924 if (STRINGP (it->string))
28925 it_charpos = IT_STRING_CHARPOS (*it);
28926 else
28927 it_charpos = IT_CHARPOS (*it);
28928
28929
28930
28931 while (it->current_x < max_x)
28932 {
28933 int x_before, x, n_glyphs_before, i, nglyphs;
28934
28935
28936 if (!get_next_display_element (it))
28937 break;
28938
28939
28940 x_before = it->current_x;
28941 n_glyphs_before = row->used[TEXT_AREA];
28942 PRODUCE_GLYPHS (it);
28943
28944 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28945 i = 0;
28946 x = x_before;
28947 while (i < nglyphs)
28948 {
28949 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28950
28951 if (it->line_wrap != TRUNCATE
28952 && x + glyph->pixel_width > max_x)
28953 {
28954
28955 if (CHAR_GLYPH_PADDING_P (*glyph))
28956 {
28957
28958 if (row->reversed_p)
28959 unproduce_glyphs (it, row->used[TEXT_AREA]
28960 - n_glyphs_before);
28961 row->used[TEXT_AREA] = n_glyphs_before;
28962 it->current_x = x_before;
28963 }
28964 else
28965 {
28966 if (row->reversed_p)
28967 unproduce_glyphs (it, row->used[TEXT_AREA]
28968 - (n_glyphs_before + i));
28969 row->used[TEXT_AREA] = n_glyphs_before + i;
28970 it->current_x = x;
28971 }
28972 break;
28973 }
28974 else if (x + glyph->pixel_width >= it->first_visible_x)
28975 {
28976
28977 ++it->hpos;
28978 if (x < it->first_visible_x)
28979 row->x = x - it->first_visible_x;
28980 }
28981 else
28982 {
28983
28984
28985 emacs_abort ();
28986 }
28987
28988 row->ascent = max (row->ascent, it->max_ascent);
28989 row->height = max (row->height, it->max_ascent + it->max_descent);
28990 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28991 row->phys_height = max (row->phys_height,
28992 it->max_phys_ascent + it->max_phys_descent);
28993 row->extra_line_spacing = max (row->extra_line_spacing,
28994 it->max_extra_line_spacing);
28995 x += glyph->pixel_width;
28996 ++i;
28997 }
28998
28999
29000 if (i < nglyphs)
29001 break;
29002
29003
29004 if (ITERATOR_AT_END_OF_LINE_P (it))
29005 {
29006 it->continuation_lines_width = 0;
29007 break;
29008 }
29009
29010 set_iterator_to_next (it, true);
29011 if (STRINGP (it->string))
29012 it_charpos = IT_STRING_CHARPOS (*it);
29013 else
29014 it_charpos = IT_CHARPOS (*it);
29015
29016
29017 if (it->line_wrap == TRUNCATE
29018 && it->current_x >= it->last_visible_x)
29019 {
29020
29021
29022
29023
29024
29025
29026 if (it_charpos <= it->string_nchars)
29027 {
29028 if (!FRAME_WINDOW_P (it->f))
29029 {
29030 int ii, n;
29031
29032 if (it->current_x > it->last_visible_x)
29033 {
29034
29035
29036 bool mode_line_p = false;
29037
29038
29039
29040 if (row->mode_line_p)
29041 {
29042 struct window *w = it->w;
29043 if (row == MATRIX_MODE_LINE_ROW (w->desired_matrix))
29044 mode_line_p = true;
29045 }
29046 if (!row->reversed_p)
29047 {
29048 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
29049 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
29050 break;
29051 }
29052 else
29053 {
29054 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
29055 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
29056 break;
29057 unproduce_glyphs (it, ii + 1);
29058 ii = row->used[TEXT_AREA] - (ii + 1);
29059 }
29060 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
29061 {
29062 row->used[TEXT_AREA] = ii;
29063 if (row->mode_line_p)
29064 pad_mode_line (it, mode_line_p);
29065 else
29066 produce_special_glyphs (it, IT_TRUNCATION);
29067 }
29068 }
29069 produce_special_glyphs (it, IT_TRUNCATION);
29070 }
29071 row->truncated_on_right_p = true;
29072 }
29073 break;
29074 }
29075 }
29076
29077
29078 if (it->first_visible_x
29079 && it_charpos > 0)
29080 {
29081 if (!FRAME_WINDOW_P (it->f)
29082 || (row->reversed_p
29083 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29084 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
29085 insert_left_trunc_glyphs (it);
29086 row->truncated_on_left_p = true;
29087 }
29088
29089 it->face_id = saved_face_id;
29090
29091
29092 return it->hpos - hpos_at_start;
29093 }
29094
29095
29096
29097
29098
29099
29100
29101
29102
29103
29104
29105 int
29106 invisible_prop (Lisp_Object propval, Lisp_Object list)
29107 {
29108 Lisp_Object tail, proptail;
29109
29110 for (tail = list; CONSP (tail); tail = XCDR (tail))
29111 {
29112 register Lisp_Object tem;
29113 tem = XCAR (tail);
29114 if (EQ (propval, tem))
29115 return 1;
29116 if (CONSP (tem) && EQ (propval, XCAR (tem)))
29117 return NILP (XCDR (tem)) ? 1 : 2;
29118 }
29119
29120 if (CONSP (propval))
29121 {
29122 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
29123 {
29124 Lisp_Object propelt;
29125 propelt = XCAR (proptail);
29126 for (tail = list; CONSP (tail); tail = XCDR (tail))
29127 {
29128 register Lisp_Object tem;
29129 tem = XCAR (tail);
29130 if (EQ (propelt, tem))
29131 return 1;
29132 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
29133 return NILP (XCDR (tem)) ? 1 : 2;
29134 }
29135 }
29136 }
29137
29138 return 0;
29139 }
29140
29141 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
29142 doc:
29143
29144
29145
29146
29147
29148
29149
29150
29151
29152
29153
29154 )
29155 (Lisp_Object pos)
29156 {
29157 Lisp_Object prop
29158 = (FIXNATP (pos) || MARKERP (pos)
29159 ? Fget_char_property (pos, Qinvisible, Qnil)
29160 : pos);
29161 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
29162 return (invis == 0 ? Qnil
29163 : invis == 1 ? Qt
29164 : make_fixnum (invis));
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
29238
29239
29240
29241
29242
29243
29244
29245
29246
29247 static bool
29248 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
29249 struct font *font, bool width_p, int *align_to)
29250 {
29251
29252
29253
29254
29255 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
29256 double pixels;
29257
29258 # define OK_PIXELS(val) (*res = (val), true)
29259 # define OK_ALIGN_TO(val) (*align_to = (val), true)
29260
29261 if (NILP (prop))
29262 return OK_PIXELS (0);
29263
29264 eassert (FRAME_LIVE_P (it->f));
29265
29266 if (SYMBOLP (prop))
29267 {
29268 if (SCHARS (SYMBOL_NAME (prop)) == 2)
29269 {
29270 char *unit = SSDATA (SYMBOL_NAME (prop));
29271
29272
29273 if (unit[0] == 'i' && unit[1] == 'n')
29274 pixels = 1.0;
29275 else if (unit[0] == 'm' && unit[1] == 'm')
29276 pixels = 25.4;
29277 else if (unit[0] == 'c' && unit[1] == 'm')
29278 pixels = 2.54;
29279 else
29280 pixels = 0;
29281 if (pixels > 0)
29282 {
29283 double ppi = (width_p ? FRAME_RES_X (it->f)
29284 : FRAME_RES_Y (it->f));
29285
29286 if (ppi > 0)
29287 return OK_PIXELS (ppi / pixels);
29288 return false;
29289 }
29290 }
29291
29292 #ifdef HAVE_WINDOW_SYSTEM
29293
29294 if (EQ (prop, Qheight))
29295 return OK_PIXELS (font
29296 ? normal_char_height (font, -1)
29297 : FRAME_LINE_HEIGHT (it->f));
29298
29299 if (EQ (prop, Qwidth))
29300 return OK_PIXELS (font
29301 ? (font->average_width
29302 ? font->average_width
29303 : font->space_width)
29304 : FRAME_COLUMN_WIDTH (it->f));
29305 #else
29306 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
29307 return OK_PIXELS (1);
29308 #endif
29309
29310
29311 if (EQ (prop, Qtext))
29312 return OK_PIXELS (width_p
29313 ? (window_box_width (it->w, TEXT_AREA)
29314 - lnum_pixel_width)
29315 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
29316
29317
29318
29319
29320 if (align_to && *align_to < 0)
29321 {
29322 *res = 0;
29323
29324 if (EQ (prop, Qleft))
29325 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29326 + lnum_pixel_width);
29327
29328 if (EQ (prop, Qright))
29329 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
29330
29331 if (EQ (prop, Qcenter))
29332 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29333 + lnum_pixel_width
29334 + window_box_width (it->w, TEXT_AREA) / 2);
29335
29336 if (EQ (prop, Qleft_fringe))
29337 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29338 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29339 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29340
29341 if (EQ (prop, Qright_fringe))
29342 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29343 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29344 : window_box_right_offset (it->w, TEXT_AREA));
29345
29346 if (EQ (prop, Qleft_margin))
29347 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29348
29349 if (EQ (prop, Qright_margin))
29350 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29351
29352 if (EQ (prop, Qscroll_bar))
29353 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29354 ? 0
29355 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29356 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29357 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29358 : 0)));
29359 }
29360 else
29361 {
29362
29363 if (EQ (prop, Qleft_fringe))
29364 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29365 if (EQ (prop, Qright_fringe))
29366 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29367 if (EQ (prop, Qleft_margin))
29368 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29369 if (EQ (prop, Qright_margin))
29370 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29371 if (EQ (prop, Qscroll_bar))
29372 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29373 }
29374
29375 prop = buffer_local_value (prop, it->w->contents);
29376 if (BASE_EQ (prop, Qunbound))
29377 prop = Qnil;
29378 }
29379
29380 if (NUMBERP (prop))
29381 {
29382 int base_unit = (width_p
29383 ? FRAME_COLUMN_WIDTH (it->f)
29384 : FRAME_LINE_HEIGHT (it->f));
29385 if (width_p && align_to && *align_to < 0)
29386 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29387 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29388 }
29389
29390 if (CONSP (prop))
29391 {
29392 Lisp_Object car = XCAR (prop);
29393 Lisp_Object cdr = XCDR (prop);
29394
29395 if (SYMBOLP (car))
29396 {
29397 #ifdef HAVE_WINDOW_SYSTEM
29398
29399 if (FRAME_WINDOW_P (it->f)
29400 && valid_image_p (prop))
29401 {
29402 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29403 struct image *img = IMAGE_FROM_ID (it->f, id);
29404
29405 return OK_PIXELS (width_p ? img->width : img->height);
29406 }
29407
29408 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29409 {
29410
29411 return OK_PIXELS (100);
29412 }
29413 #endif
29414
29415
29416 if (EQ (car, Qplus) || EQ (car, Qminus))
29417 {
29418 bool first = true;
29419 double px;
29420
29421 pixels = 0;
29422 while (CONSP (cdr))
29423 {
29424 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29425 font, width_p, align_to))
29426 return false;
29427 if (first)
29428 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29429 else
29430 pixels += px;
29431 cdr = XCDR (cdr);
29432 }
29433 if (EQ (car, Qminus))
29434 pixels = -pixels;
29435 return OK_PIXELS (pixels);
29436 }
29437
29438 car = buffer_local_value (car, it->w->contents);
29439 if (BASE_EQ (car, Qunbound))
29440 car = Qnil;
29441 }
29442
29443
29444 if (NUMBERP (car))
29445 {
29446 double fact;
29447 int offset =
29448 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29449 pixels = XFLOATINT (car);
29450 if (NILP (cdr))
29451 return OK_PIXELS (pixels + offset);
29452 if (calc_pixel_width_or_height (&fact, it, cdr,
29453 font, width_p, align_to))
29454 return OK_PIXELS (pixels * fact + offset);
29455 return false;
29456 }
29457
29458 return false;
29459 }
29460
29461 return false;
29462 }
29463
29464 void
29465 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29466 {
29467 #ifdef HAVE_WINDOW_SYSTEM
29468 normal_char_ascent_descent (font, -1, ascent, descent);
29469 #else
29470 *ascent = 1;
29471 *descent = 0;
29472 #endif
29473 }
29474
29475
29476
29477
29478
29479
29480 #ifdef HAVE_WINDOW_SYSTEM
29481
29482 #ifdef GLYPH_DEBUG
29483
29484 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29485 void
29486 dump_glyph_string (struct glyph_string *s)
29487 {
29488 fputs ("glyph string\n", stderr);
29489 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29490 s->x, s->y, s->width, s->height);
29491 fprintf (stderr, " ybase = %d\n", s->ybase);
29492 fprintf (stderr, " hl = %u\n", s->hl);
29493 fprintf (stderr, " left overhang = %d, right = %d\n",
29494 s->left_overhang, s->right_overhang);
29495 fprintf (stderr, " nchars = %d\n", s->nchars);
29496 fprintf (stderr, " extends to end of line = %d\n",
29497 s->extends_to_end_of_line_p);
29498 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29499 fprintf (stderr, " bg width = %d\n", s->background_width);
29500 }
29501
29502 #endif
29503
29504
29505
29506
29507
29508
29509
29510
29511
29512 #ifdef HAVE_NTGUI
29513
29514
29515
29516
29517
29518 # define ALLOCATE_HDC(hdc, f) \
29519 Lisp_Object prev_quit = Vinhibit_quit; \
29520 Vinhibit_quit = Qt; \
29521 HDC hdc = get_frame_dc ((f))
29522 # define RELEASE_HDC(hdc, f) \
29523 release_frame_dc ((f), (hdc)); \
29524 Vinhibit_quit = prev_quit
29525 #else
29526 # define ALLOCATE_HDC(hdc, f)
29527 # define RELEASE_HDC(hdc, f)
29528 #endif
29529
29530 static void
29531 init_glyph_string (struct glyph_string *s,
29532 #ifdef HAVE_NTGUI
29533 HDC hdc,
29534 #endif
29535 unsigned *char2b, struct window *w, struct glyph_row *row,
29536 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29537 {
29538 memset (s, 0, sizeof *s);
29539 s->w = w;
29540 s->f = XFRAME (w->frame);
29541 #ifdef HAVE_NTGUI
29542 s->hdc = hdc;
29543 #endif
29544 s->char2b = char2b;
29545 s->hl = hl;
29546 s->row = row;
29547 s->area = area;
29548 s->first_glyph = row->glyphs[area] + start;
29549 s->height = row->height;
29550 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29551 s->ybase = s->y + row->ascent;
29552 }
29553
29554
29555
29556
29557
29558 static void
29559 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29560 struct glyph_string *h, struct glyph_string *t)
29561 {
29562 if (h)
29563 {
29564 if (*head)
29565 (*tail)->next = h;
29566 else
29567 *head = h;
29568 h->prev = *tail;
29569 *tail = t;
29570 }
29571 }
29572
29573
29574
29575
29576
29577
29578 static void
29579 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29580 struct glyph_string *h, struct glyph_string *t)
29581 {
29582 if (h)
29583 {
29584 if (*head)
29585 (*head)->prev = t;
29586 else
29587 *tail = t;
29588 t->next = *head;
29589 *head = h;
29590 }
29591 }
29592
29593
29594
29595
29596
29597 static void
29598 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29599 struct glyph_string *s)
29600 {
29601 s->next = s->prev = NULL;
29602 append_glyph_string_lists (head, tail, s, s);
29603 }
29604
29605
29606
29607
29608
29609
29610
29611
29612 static struct face *
29613 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29614 unsigned *char2b, bool display_p)
29615 {
29616 struct face *face = FACE_FROM_ID (f, face_id);
29617 unsigned code = 0;
29618
29619 if (face->font)
29620 {
29621 code = face->font->driver->encode_char (face->font, c);
29622
29623 if (code == FONT_INVALID_CODE)
29624 code = 0;
29625 }
29626
29627 *char2b = code & 0xFFFF;
29628
29629
29630 #ifdef HAVE_X_WINDOWS
29631 if (display_p)
29632 #endif
29633 {
29634 eassert (face != NULL);
29635 prepare_face_for_display (f, face);
29636 }
29637
29638 return face;
29639 }
29640
29641
29642
29643
29644
29645
29646 static struct face *
29647 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29648 unsigned *char2b)
29649 {
29650 struct face *face;
29651 unsigned code = 0;
29652
29653 eassert (glyph->type == CHAR_GLYPH);
29654 face = FACE_FROM_ID (f, glyph->face_id);
29655
29656
29657 prepare_face_for_display (f, face);
29658
29659 if (face->font)
29660 {
29661 if (CHAR_BYTE8_P (glyph->u.ch))
29662 code = CHAR_TO_BYTE8 (glyph->u.ch);
29663 else
29664 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29665
29666 if (code == FONT_INVALID_CODE)
29667 code = 0;
29668 }
29669
29670
29671 *char2b = code & 0xFFFF;
29672 return face;
29673 }
29674
29675
29676
29677
29678
29679 static bool
29680 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29681 {
29682 unsigned code;
29683
29684 if (CHAR_BYTE8_P (c))
29685 code = CHAR_TO_BYTE8 (c);
29686 else
29687 code = font->driver->encode_char (font, c);
29688
29689 if (code == FONT_INVALID_CODE)
29690 return false;
29691
29692
29693 *char2b = code & 0xFFFF;
29694 return true;
29695 }
29696
29697
29698
29699
29700
29701
29702
29703
29704
29705
29706
29707
29708 static int
29709 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29710 int overlaps)
29711 {
29712 int i;
29713
29714
29715
29716 struct face *face;
29717
29718 eassert (s);
29719
29720 s->for_overlaps = overlaps;
29721 s->face = NULL;
29722 s->font = NULL;
29723 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29724 {
29725 int c = COMPOSITION_GLYPH (s->cmp, i);
29726
29727
29728
29729 if (c != '\t')
29730 {
29731 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29732 -1, Qnil);
29733
29734 face = get_char_face_and_encoding (s->f, c, face_id,
29735 s->char2b + i, true);
29736 if (face)
29737 {
29738 if (! s->face)
29739 {
29740 s->face = face;
29741 s->font = s->face->font;
29742 }
29743 else if (s->face != face)
29744 break;
29745 }
29746 }
29747 ++s->nchars;
29748 }
29749 s->cmp_to = i;
29750
29751 if (s->face == NULL)
29752 {
29753 s->face = base_face->ascii_face;
29754 s->font = s->face->font;
29755 }
29756
29757 if (s->hl == DRAW_MOUSE_FACE
29758 || (s->hl == DRAW_CURSOR
29759 && MATRIX_ROW (s->w->current_matrix,
29760 s->w->phys_cursor.vpos)->mouse_face_p
29761 && cursor_in_mouse_face_p (s->w)))
29762 {
29763 int c = COMPOSITION_GLYPH (s->cmp, 0);
29764 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29765 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29766 if (!s->face)
29767 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29768
29769 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29770 prepare_face_for_display (s->f, s->face);
29771 }
29772
29773
29774
29775 s->width = s->first_glyph->pixel_width;
29776
29777
29778
29779
29780
29781 if (s->font == NULL)
29782 {
29783 s->font_not_found_p = true;
29784 s->font = FRAME_FONT (s->f);
29785 }
29786
29787
29788 s->ybase += s->first_glyph->voffset;
29789
29790 return s->cmp_to;
29791 }
29792
29793 static int
29794 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29795 int start, int end, int overlaps)
29796 {
29797 struct glyph *glyph, *last;
29798 int voffset;
29799 Lisp_Object lgstring;
29800 int i;
29801 bool glyph_not_available_p;
29802
29803 s->for_overlaps = overlaps;
29804 glyph = s->row->glyphs[s->area] + start;
29805 last = s->row->glyphs[s->area] + end;
29806 voffset = glyph->voffset;
29807 glyph_not_available_p = glyph->glyph_not_available_p;
29808 s->cmp_id = glyph->u.cmp.id;
29809 s->cmp_from = glyph->slice.cmp.from;
29810 s->cmp_to = glyph->slice.cmp.to + 1;
29811 if (s->hl == DRAW_MOUSE_FACE
29812 || (s->hl == DRAW_CURSOR
29813 && MATRIX_ROW (s->w->current_matrix,
29814 s->w->phys_cursor.vpos)->mouse_face_p
29815 && cursor_in_mouse_face_p (s->w)))
29816 {
29817 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29818 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29819 if (!s->face)
29820 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29821 prepare_face_for_display (s->f, s->face);
29822 }
29823 else
29824 s->face = FACE_FROM_ID (s->f, face_id);
29825 lgstring = composition_gstring_from_id (s->cmp_id);
29826 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29827
29828
29829 s->width = s->first_glyph->pixel_width;
29830 glyph++;
29831 while (glyph < last
29832 && glyph->u.cmp.automatic
29833 && glyph->u.cmp.id == s->cmp_id
29834 && glyph->face_id == face_id
29835 && s->cmp_to == glyph->slice.cmp.from
29836 && glyph->glyph_not_available_p == glyph_not_available_p)
29837 {
29838 s->width += glyph->pixel_width;
29839 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29840 }
29841
29842 for (i = s->cmp_from; i < s->cmp_to; i++)
29843 {
29844 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29845 unsigned code = LGLYPH_CODE (lglyph);
29846
29847
29848 s->char2b[i] = code & 0xFFFF;
29849 }
29850
29851
29852
29853
29854 if (glyph_not_available_p)
29855 s->font_not_found_p = true;
29856
29857
29858 s->ybase += voffset;
29859
29860 return glyph - s->row->glyphs[s->area];
29861 }
29862
29863
29864
29865
29866
29867
29868
29869 static int
29870 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29871 int start, int end, int overlaps)
29872 {
29873 struct glyph *glyph, *last;
29874 int voffset;
29875
29876 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29877 s->for_overlaps = overlaps;
29878 glyph = s->row->glyphs[s->area] + start;
29879 last = s->row->glyphs[s->area] + end;
29880 voffset = glyph->voffset;
29881 s->face = FACE_FROM_ID (s->f, face_id);
29882 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29883 if (s->hl == DRAW_MOUSE_FACE
29884 || (s->hl == DRAW_CURSOR
29885 && MATRIX_ROW (s->w->current_matrix,
29886 s->w->phys_cursor.vpos)->mouse_face_p
29887 && cursor_in_mouse_face_p (s->w)))
29888 {
29889 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29890 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29891 if (!s->face)
29892 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29893 prepare_face_for_display (s->f, s->face);
29894 }
29895 s->nchars = 1;
29896 s->width = glyph->pixel_width;
29897 glyph++;
29898 while (glyph < last
29899 && glyph->type == GLYPHLESS_GLYPH
29900 && glyph->voffset == voffset
29901 && glyph->face_id == face_id)
29902 {
29903 s->nchars++;
29904 s->width += glyph->pixel_width;
29905 glyph++;
29906 }
29907 s->ybase += voffset;
29908 return glyph - s->row->glyphs[s->area];
29909 }
29910
29911
29912
29913
29914
29915
29916
29917
29918
29919
29920
29921 static int
29922 fill_glyph_string (struct glyph_string *s, int face_id,
29923 int start, int end, int overlaps)
29924 {
29925 struct glyph *glyph, *last;
29926 int voffset;
29927 bool glyph_not_available_p;
29928
29929 eassert (s->f == XFRAME (s->w->frame));
29930 eassert (s->nchars == 0);
29931 eassert (start >= 0 && end > start);
29932
29933 s->for_overlaps = overlaps;
29934 glyph = s->row->glyphs[s->area] + start;
29935 last = s->row->glyphs[s->area] + end;
29936 voffset = glyph->voffset;
29937 s->padding_p = glyph->padding_p;
29938 glyph_not_available_p = glyph->glyph_not_available_p;
29939
29940 while (glyph < last
29941 && glyph->type == CHAR_GLYPH
29942 && glyph->voffset == voffset
29943
29944 && glyph->face_id == face_id
29945 && glyph->glyph_not_available_p == glyph_not_available_p)
29946 {
29947 s->face = get_glyph_face_and_encoding (s->f, glyph,
29948 s->char2b + s->nchars);
29949 ++s->nchars;
29950 eassert (s->nchars <= end - start);
29951 s->width += glyph->pixel_width;
29952 if (glyph++->padding_p != s->padding_p)
29953 break;
29954 }
29955
29956 s->font = s->face->font;
29957
29958 if (s->hl == DRAW_MOUSE_FACE
29959 || (s->hl == DRAW_CURSOR
29960 && MATRIX_ROW (s->w->current_matrix,
29961 s->w->phys_cursor.vpos)->mouse_face_p
29962 && cursor_in_mouse_face_p (s->w)))
29963 {
29964 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29965 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29966 if (!s->face)
29967 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29968 s->face
29969 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29970 s->first_glyph->u.ch, -1, Qnil));
29971 prepare_face_for_display (s->f, s->face);
29972 }
29973
29974
29975
29976
29977
29978 if (s->font == NULL || glyph_not_available_p)
29979 {
29980 s->font_not_found_p = true;
29981 s->font = FRAME_FONT (s->f);
29982 }
29983
29984
29985 s->ybase += voffset;
29986
29987 eassert (s->face && s->face->gc);
29988 return glyph - s->row->glyphs[s->area];
29989 }
29990
29991
29992
29993
29994 static void
29995 fill_image_glyph_string (struct glyph_string *s)
29996 {
29997 eassert (s->first_glyph->type == IMAGE_GLYPH);
29998 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29999 eassert (s->img);
30000 s->slice = s->first_glyph->slice.img;
30001 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
30002 s->font = s->face->font;
30003 if (s->hl == DRAW_MOUSE_FACE
30004 || (s->hl == DRAW_CURSOR
30005 && MATRIX_ROW (s->w->current_matrix,
30006 s->w->phys_cursor.vpos)->mouse_face_p
30007 && cursor_in_mouse_face_p (s->w)))
30008 {
30009 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
30010 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
30011 if (!s->face)
30012 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30013 prepare_face_for_display (s->f, s->face);
30014 }
30015 s->width = s->first_glyph->pixel_width;
30016
30017
30018 s->ybase += s->first_glyph->voffset;
30019 }
30020
30021
30022 #ifdef HAVE_XWIDGETS
30023 static void
30024 fill_xwidget_glyph_string (struct glyph_string *s)
30025 {
30026 eassert (s->first_glyph->type == XWIDGET_GLYPH);
30027 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
30028 s->font = s->face->font;
30029 if (s->hl == DRAW_MOUSE_FACE
30030 || (s->hl == DRAW_CURSOR
30031 && MATRIX_ROW (s->w->current_matrix,
30032 s->w->phys_cursor.vpos)->mouse_face_p
30033 && cursor_in_mouse_face_p (s->w)))
30034 {
30035 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
30036 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
30037 if (!s->face)
30038 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30039 prepare_face_for_display (s->f, s->face);
30040 }
30041 s->width = s->first_glyph->pixel_width;
30042 s->ybase += s->first_glyph->voffset;
30043 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
30044 }
30045 #endif
30046
30047
30048
30049
30050
30051
30052
30053 static int
30054 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
30055 {
30056 struct glyph *glyph, *last;
30057 int voffset, face_id;
30058
30059 eassert (s->first_glyph->type == STRETCH_GLYPH);
30060
30061 glyph = s->row->glyphs[s->area] + start;
30062 last = s->row->glyphs[s->area] + end;
30063 face_id = glyph->face_id;
30064 s->face = FACE_FROM_ID (s->f, face_id);
30065 s->font = s->face->font;
30066 if (s->hl == DRAW_MOUSE_FACE
30067 || (s->hl == DRAW_CURSOR
30068 && MATRIX_ROW (s->w->current_matrix,
30069 s->w->phys_cursor.vpos)->mouse_face_p
30070 && cursor_in_mouse_face_p (s->w)))
30071 {
30072 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
30073 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
30074 if (!s->face)
30075 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30076 prepare_face_for_display (s->f, s->face);
30077 }
30078 s->width = glyph->pixel_width;
30079 s->nchars = 1;
30080 voffset = glyph->voffset;
30081
30082 for (++glyph;
30083 (glyph < last
30084 && glyph->type == STRETCH_GLYPH
30085 && glyph->voffset == voffset
30086 && glyph->face_id == face_id);
30087 ++glyph)
30088 s->width += glyph->pixel_width;
30089
30090
30091 s->ybase += voffset;
30092
30093
30094
30095 eassert (s->face);
30096 return glyph - s->row->glyphs[s->area];
30097 }
30098
30099 static struct font_metrics *
30100 get_per_char_metric (struct font *font, const unsigned *char2b)
30101 {
30102 static struct font_metrics metrics;
30103
30104 if (! font)
30105 return NULL;
30106 if (*char2b == FONT_INVALID_CODE)
30107 return NULL;
30108
30109 font->driver->text_extents (font, char2b, 1, &metrics);
30110 return &metrics;
30111 }
30112
30113
30114
30115
30116
30117
30118
30119 static void
30120 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
30121 {
30122 *ascent = FONT_BASE (font);
30123 *descent = FONT_DESCENT (font);
30124
30125 if (FONT_TOO_HIGH (font))
30126 {
30127 unsigned char2b;
30128
30129
30130
30131 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
30132 {
30133 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
30134 eassume (pcm);
30135
30136 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
30137 {
30138
30139
30140
30141 *ascent = pcm->ascent + 1;
30142 *descent = pcm->descent + 1;
30143 }
30144 }
30145 }
30146 }
30147
30148
30149
30150
30151
30152
30153 static int
30154 normal_char_height (struct font *font, int c)
30155 {
30156 int ascent, descent;
30157
30158 normal_char_ascent_descent (font, c, &ascent, &descent);
30159
30160 return ascent + descent;
30161 }
30162
30163
30164
30165
30166
30167
30168 void
30169 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
30170 {
30171 *left = *right = 0;
30172
30173 if (glyph->type == CHAR_GLYPH)
30174 {
30175 unsigned char2b;
30176 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
30177 if (face->font)
30178 {
30179 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
30180 if (pcm)
30181 {
30182 if (pcm->rbearing > pcm->width)
30183 *right = pcm->rbearing - pcm->width;
30184 if (pcm->lbearing < 0)
30185 *left = -pcm->lbearing;
30186 }
30187 }
30188 }
30189 else if (glyph->type == COMPOSITE_GLYPH)
30190 {
30191 if (! glyph->u.cmp.automatic)
30192 {
30193 struct composition *cmp = composition_table[glyph->u.cmp.id];
30194
30195 if (cmp->rbearing > cmp->pixel_width)
30196 *right = cmp->rbearing - cmp->pixel_width;
30197 if (cmp->lbearing < 0)
30198 *left = - cmp->lbearing;
30199 }
30200 else
30201 {
30202 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
30203 struct font_metrics metrics;
30204
30205 composition_gstring_width (gstring, glyph->slice.cmp.from,
30206 glyph->slice.cmp.to + 1, &metrics);
30207 if (metrics.rbearing > metrics.width)
30208 *right = metrics.rbearing - metrics.width;
30209 if (metrics.lbearing < 0)
30210 *left = - metrics.lbearing;
30211 }
30212 }
30213 }
30214
30215
30216
30217
30218
30219
30220 static int
30221 left_overwritten (struct glyph_string *s)
30222 {
30223 int k;
30224
30225 if (s->left_overhang)
30226 {
30227 int x = 0, i;
30228 struct glyph *glyphs = s->row->glyphs[s->area];
30229 int first = s->first_glyph - glyphs;
30230
30231 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
30232 x -= glyphs[i].pixel_width;
30233
30234 k = i + 1;
30235 }
30236 else
30237 k = -1;
30238
30239 return k;
30240 }
30241
30242
30243
30244
30245
30246
30247 static int
30248 left_overwriting (struct glyph_string *s)
30249 {
30250 int i, k, x;
30251 struct glyph *glyphs = s->row->glyphs[s->area];
30252 int first = s->first_glyph - glyphs;
30253
30254 k = -1;
30255 x = 0;
30256 for (i = first - 1; i >= 0; --i)
30257 {
30258 int left, right;
30259 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30260 if (x + right > 0)
30261 k = i;
30262 x -= glyphs[i].pixel_width;
30263 }
30264
30265 return k;
30266 }
30267
30268
30269
30270
30271
30272
30273 static int
30274 right_overwritten (struct glyph_string *s)
30275 {
30276 int k = -1;
30277
30278 if (s->right_overhang)
30279 {
30280 int x = 0, i;
30281 struct glyph *glyphs = s->row->glyphs[s->area];
30282 int first = (s->first_glyph - glyphs
30283 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30284 int end = s->row->used[s->area];
30285
30286 for (i = first; i < end && s->right_overhang > x; ++i)
30287 x += glyphs[i].pixel_width;
30288
30289 k = i;
30290 }
30291
30292 return k;
30293 }
30294
30295
30296
30297
30298
30299
30300 static int
30301 right_overwriting (struct glyph_string *s)
30302 {
30303 int i, k, x;
30304 int end = s->row->used[s->area];
30305 struct glyph *glyphs = s->row->glyphs[s->area];
30306 int first = (s->first_glyph - glyphs
30307 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30308
30309 k = -1;
30310 x = 0;
30311 for (i = first; i < end; ++i)
30312 {
30313 int left, right;
30314 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30315 if (x - left < 0)
30316 k = i;
30317 x += glyphs[i].pixel_width;
30318 }
30319
30320 return k;
30321 }
30322
30323
30324
30325
30326
30327
30328
30329
30330
30331
30332
30333 static void
30334 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30335 {
30336
30337
30338
30339 if (start == s->row->used[s->area]
30340 && ((s->row->fill_line_p
30341 && (s->hl == DRAW_NORMAL_TEXT
30342 || s->hl == DRAW_IMAGE_RAISED
30343 || s->hl == DRAW_IMAGE_SUNKEN))
30344 || s->hl == DRAW_MOUSE_FACE))
30345 s->extends_to_end_of_line_p = true;
30346
30347
30348
30349
30350 if (s->extends_to_end_of_line_p)
30351 s->background_width = last_x - s->x + 1;
30352 else
30353 {
30354 s->background_width = s->width;
30355 #ifdef HAVE_WINDOW_SYSTEM
30356 if (FRAME_WINDOW_P (s->f)
30357 && s->hl == DRAW_CURSOR
30358 && MATRIX_ROW (s->w->current_matrix,
30359 s->w->phys_cursor.vpos)->mouse_face_p
30360 && cursor_in_mouse_face_p (s->w))
30361 {
30362
30363
30364
30365
30366 struct glyph *g = s->first_glyph;
30367 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30368 s->background_width +=
30369 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30370 regular_face, s->face);
30371
30372 s->width = s->background_width;
30373 }
30374 #endif
30375 }
30376 }
30377
30378
30379
30380
30381
30382 static struct glyph_string *
30383 glyph_string_containing_background_width (struct glyph_string *s)
30384 {
30385 if (s->cmp)
30386 while (s->cmp_from)
30387 s = s->prev;
30388
30389 return s;
30390 }
30391
30392
30393
30394
30395
30396
30397 static void
30398 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30399 {
30400 if (backward_p)
30401 {
30402 while (s)
30403 {
30404 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30405 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30406 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30407 x -= s->width;
30408 s->x = x;
30409 s = s->prev;
30410 }
30411 }
30412 else
30413 {
30414 while (s)
30415 {
30416 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30417 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30418 s->x = x;
30419 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30420 x += s->width;
30421 s = s->next;
30422 }
30423 }
30424 }
30425
30426
30427
30428
30429
30430
30431
30432
30433
30434 #ifdef HAVE_NTGUI
30435
30436
30437 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30438 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30439 #else
30440 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30441 init_glyph_string (s, char2b, w, row, area, start, hl)
30442 #endif
30443
30444
30445
30446
30447
30448
30449
30450
30451
30452
30453
30454 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30455 do \
30456 { \
30457 s = alloca (sizeof *s); \
30458 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30459 START = fill_stretch_glyph_string (s, START, END); \
30460 append_glyph_string (&HEAD, &TAIL, s); \
30461 s->x = (X); \
30462 } \
30463 while (false)
30464
30465
30466
30467
30468
30469
30470
30471
30472
30473
30474 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30475 do \
30476 { \
30477 s = alloca (sizeof *s); \
30478 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30479 fill_image_glyph_string (s); \
30480 append_glyph_string (&HEAD, &TAIL, s); \
30481 ++START; \
30482 s->x = (X); \
30483 } \
30484 while (false)
30485
30486 #ifndef HAVE_XWIDGETS
30487 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30488 eassume (false)
30489 #else
30490 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30491 do \
30492 { \
30493 s = alloca (sizeof *s); \
30494 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30495 fill_xwidget_glyph_string (s); \
30496 append_glyph_string (&(HEAD), &(TAIL), s); \
30497 ++(START); \
30498 s->x = (X); \
30499 } \
30500 while (false)
30501 #endif
30502
30503
30504
30505
30506
30507
30508
30509
30510
30511
30512 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30513 do \
30514 { \
30515 int face_id; \
30516 unsigned *char2b; \
30517 \
30518 face_id = (row)->glyphs[area][START].face_id; \
30519 \
30520 s = alloca (sizeof *s); \
30521 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30522 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30523 append_glyph_string (&HEAD, &TAIL, s); \
30524 s->x = (X); \
30525 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30526 } \
30527 while (false)
30528
30529
30530
30531
30532
30533
30534
30535
30536
30537
30538
30539 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30540 do { \
30541 int face_id = (row)->glyphs[area][START].face_id; \
30542 struct face *base_face = FACE_FROM_ID (f, face_id); \
30543 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30544 struct composition *cmp = composition_table[cmp_id]; \
30545 unsigned *char2b; \
30546 struct glyph_string *first_s = NULL; \
30547 int n; \
30548 \
30549 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30550 \
30551
30552 \
30553 for (n = 0; n < cmp->glyph_len;) \
30554 { \
30555 s = alloca (sizeof *s); \
30556 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30557 append_glyph_string (&(HEAD), &(TAIL), s); \
30558 s->cmp = cmp; \
30559 s->cmp_from = n; \
30560 s->x = (X); \
30561 if (n == 0) \
30562 first_s = s; \
30563 n = fill_composite_glyph_string (s, base_face, overlaps); \
30564 } \
30565 \
30566 ++START; \
30567 s = first_s; \
30568 } while (false)
30569
30570
30571
30572
30573
30574 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30575 do { \
30576 int face_id; \
30577 unsigned *char2b; \
30578 Lisp_Object gstring; \
30579 \
30580 face_id = (row)->glyphs[area][START].face_id; \
30581 gstring = (composition_gstring_from_id \
30582 ((row)->glyphs[area][START].u.cmp.id)); \
30583 s = alloca (sizeof *s); \
30584 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30585 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30586 append_glyph_string (&(HEAD), &(TAIL), s); \
30587 s->x = (X); \
30588 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30589 } while (false)
30590
30591
30592
30593
30594
30595
30596 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30597 do \
30598 { \
30599 int face_id; \
30600 \
30601 face_id = (row)->glyphs[area][START].face_id; \
30602 \
30603 s = alloca (sizeof *s); \
30604 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30605 append_glyph_string (&HEAD, &TAIL, s); \
30606 s->x = (X); \
30607 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30608 overlaps); \
30609 } \
30610 while (false)
30611
30612
30613
30614
30615
30616
30617
30618
30619
30620
30621
30622
30623 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30624 do \
30625 { \
30626 HEAD = TAIL = NULL; \
30627 while (START < END) \
30628 { \
30629 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30630 switch (first_glyph->type) \
30631 { \
30632 case CHAR_GLYPH: \
30633 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30634 HL, X, LAST_X); \
30635 break; \
30636 \
30637 case COMPOSITE_GLYPH: \
30638 if (first_glyph->u.cmp.automatic) \
30639 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30640 HL, X, LAST_X); \
30641 else \
30642 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30643 HL, X, LAST_X); \
30644 break; \
30645 \
30646 case STRETCH_GLYPH: \
30647 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30648 HL, X, LAST_X); \
30649 break; \
30650 \
30651 case IMAGE_GLYPH: \
30652 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30653 HL, X, LAST_X); \
30654 break;
30655
30656 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30657 case XWIDGET_GLYPH: \
30658 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30659 HL, X, LAST_X); \
30660 break;
30661
30662 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30663 case GLYPHLESS_GLYPH: \
30664 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30665 HL, X, LAST_X); \
30666 break; \
30667 \
30668 default: \
30669 emacs_abort (); \
30670 } \
30671 \
30672 if (s) \
30673 { \
30674 set_glyph_string_background_width (s, START, LAST_X); \
30675 (X) += s->width; \
30676 } \
30677 } \
30678 } while (false)
30679
30680
30681 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30682 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30683 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30684 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30685
30686
30687
30688
30689
30690
30691
30692
30693
30694
30695
30696
30697
30698
30699
30700
30701
30702
30703
30704
30705
30706
30707
30708
30709 static int
30710 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30711 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30712 enum draw_glyphs_face hl, int overlaps)
30713 {
30714 struct glyph_string *head, *tail;
30715 struct glyph_string *s;
30716 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30717 int i, j, x_reached, last_x, area_left = 0;
30718 struct frame *f = XFRAME (WINDOW_FRAME (w));
30719
30720 ALLOCATE_HDC (hdc, f);
30721
30722
30723 end = min (end, row->used[area]);
30724 start = clip_to_bounds (0, start, end);
30725
30726
30727
30728 if (row->full_width_p)
30729 {
30730
30731
30732 area_left = WINDOW_LEFT_EDGE_X (w);
30733 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30734 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30735 }
30736 else
30737 {
30738 area_left = window_box_left (w, area);
30739 last_x = area_left + window_box_width (w, area);
30740 }
30741 x += area_left;
30742
30743
30744
30745
30746
30747 i = start;
30748 USE_SAFE_ALLOCA;
30749 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30750 if (tail)
30751 {
30752 s = glyph_string_containing_background_width (tail);
30753 x_reached = s->x + s->background_width;
30754 }
30755 else
30756 x_reached = x;
30757
30758
30759
30760
30761 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30762 {
30763 struct glyph_string *h, *t;
30764 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30765 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30766 bool check_mouse_face = false;
30767 int dummy_x = 0;
30768
30769
30770
30771 if (area == TEXT_AREA && row->mouse_face_p
30772 && hlinfo->mouse_face_beg_row >= 0
30773 && hlinfo->mouse_face_end_row >= 0)
30774 {
30775 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30776
30777 if (row_vpos >= hlinfo->mouse_face_beg_row
30778 && row_vpos <= hlinfo->mouse_face_end_row)
30779 {
30780 check_mouse_face = true;
30781 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30782 ? hlinfo->mouse_face_beg_col : 0;
30783 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30784 ? hlinfo->mouse_face_end_col
30785 : row->used[TEXT_AREA];
30786 }
30787 }
30788
30789
30790 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30791 for (s = head; s; s = s->next)
30792 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30793
30794
30795
30796
30797
30798
30799 i = left_overwritten (head);
30800 if (i >= 0)
30801 {
30802 enum draw_glyphs_face overlap_hl;
30803
30804
30805
30806
30807
30808
30809
30810
30811 if (check_mouse_face
30812 && mouse_beg_col < start && mouse_end_col > i)
30813 overlap_hl = DRAW_MOUSE_FACE;
30814 else
30815 overlap_hl = DRAW_NORMAL_TEXT;
30816
30817 if (hl != overlap_hl)
30818 clip_head = head;
30819 j = i;
30820 BUILD_GLYPH_STRINGS (j, start, h, t,
30821 overlap_hl, dummy_x, last_x);
30822 start = i;
30823 compute_overhangs_and_x (t, head->x, true);
30824 prepend_glyph_string_lists (&head, &tail, h, t);
30825 if (clip_head == NULL)
30826 clip_head = head;
30827 }
30828
30829
30830
30831
30832
30833
30834
30835
30836 i = left_overwriting (head);
30837 if (i >= 0)
30838 {
30839 enum draw_glyphs_face overlap_hl;
30840
30841 if (check_mouse_face
30842 && mouse_beg_col < start && mouse_end_col > i)
30843 overlap_hl = DRAW_MOUSE_FACE;
30844 else
30845 overlap_hl = DRAW_NORMAL_TEXT;
30846
30847 if (hl == overlap_hl || clip_head == NULL)
30848 clip_head = head;
30849 BUILD_GLYPH_STRINGS (i, start, h, t,
30850 overlap_hl, dummy_x, last_x);
30851 for (s = h; s; s = s->next)
30852 s->background_filled_p = true;
30853 compute_overhangs_and_x (t, head->x, true);
30854 prepend_glyph_string_lists (&head, &tail, h, t);
30855 }
30856
30857
30858
30859
30860
30861 i = right_overwritten (tail);
30862 if (i >= 0)
30863 {
30864 enum draw_glyphs_face overlap_hl;
30865
30866 if (check_mouse_face
30867 && mouse_beg_col < i && mouse_end_col > end)
30868 overlap_hl = DRAW_MOUSE_FACE;
30869 else
30870 overlap_hl = DRAW_NORMAL_TEXT;
30871
30872 if (hl != overlap_hl)
30873 clip_tail = tail;
30874 BUILD_GLYPH_STRINGS (end, i, h, t,
30875 overlap_hl, x, last_x);
30876
30877
30878 compute_overhangs_and_x (h, tail->x + tail->width, false);
30879 append_glyph_string_lists (&head, &tail, h, t);
30880 if (clip_tail == NULL)
30881 clip_tail = tail;
30882 }
30883
30884
30885
30886
30887
30888
30889 i = right_overwriting (tail);
30890 if (i >= 0)
30891 {
30892 enum draw_glyphs_face overlap_hl;
30893 if (check_mouse_face
30894 && mouse_beg_col < i && mouse_end_col > end)
30895 overlap_hl = DRAW_MOUSE_FACE;
30896 else
30897 overlap_hl = DRAW_NORMAL_TEXT;
30898
30899 if (hl == overlap_hl || clip_tail == NULL)
30900 clip_tail = tail;
30901 i++;
30902 BUILD_GLYPH_STRINGS (end, i, h, t,
30903 overlap_hl, x, last_x);
30904 for (s = h; s; s = s->next)
30905 s->background_filled_p = true;
30906 compute_overhangs_and_x (h, tail->x + tail->width, false);
30907 append_glyph_string_lists (&head, &tail, h, t);
30908 }
30909 tail = glyph_string_containing_background_width (tail);
30910 if (clip_tail)
30911 clip_tail = glyph_string_containing_background_width (clip_tail);
30912 if (clip_head || clip_tail)
30913 for (s = head; s; s = s->next)
30914 {
30915 s->clip_head = clip_head;
30916 s->clip_tail = clip_tail;
30917 }
30918 }
30919
30920
30921 for (s = head; s; s = s->next)
30922 FRAME_RIF (f)->draw_glyph_string (s);
30923
30924
30925
30926 if (area == TEXT_AREA
30927 && !row->full_width_p
30928
30929
30930
30931 && !overlaps)
30932 {
30933 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30934 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30935 : (tail ? tail->x + tail->background_width : x));
30936 x0 -= area_left;
30937 x1 -= area_left;
30938
30939 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30940 row->y, MATRIX_ROW_BOTTOM_Y (row));
30941 }
30942
30943
30944
30945 if (row->full_width_p)
30946 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30947 else
30948 x_reached -= area_left;
30949
30950 RELEASE_HDC (hdc, f);
30951
30952 SAFE_FREE ();
30953 return x_reached;
30954 }
30955
30956
30957
30958
30959
30960
30961
30962
30963 struct font *
30964 font_for_underline_metrics (struct glyph_string *s)
30965 {
30966 struct glyph *g0 = s->row->glyphs[s->area], *g;
30967
30968 for (g = s->first_glyph - 1; g >= g0; g--)
30969 {
30970 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30971 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30972 break;
30973 }
30974
30975
30976 if (g == s->first_glyph - 1)
30977 return s->font;
30978 else
30979 {
30980
30981
30982 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30983 }
30984 }
30985
30986
30987
30988
30989 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30990 { \
30991 if (!it->f->fonts_changed \
30992 && (it->glyph_row->glyphs[area] \
30993 < it->glyph_row->glyphs[area + 1])) \
30994 { \
30995 it->w->ncols_scale_factor++; \
30996 it->f->fonts_changed = true; \
30997 } \
30998 }
30999
31000
31001
31002
31003 static void
31004 append_glyph (struct it *it)
31005 {
31006 struct glyph *glyph;
31007 enum glyph_row_area area = it->area;
31008
31009 eassert (it->glyph_row);
31010 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
31011
31012 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31013 if (glyph < it->glyph_row->glyphs[area + 1])
31014 {
31015
31016
31017 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31018 {
31019 struct glyph *g;
31020
31021
31022 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31023 g[1] = *g;
31024 glyph = it->glyph_row->glyphs[area];
31025 }
31026 glyph->charpos = CHARPOS (it->position);
31027 glyph->object = it->object;
31028 if (it->pixel_width > 0)
31029 {
31030 eassert (it->pixel_width <= SHRT_MAX);
31031 glyph->pixel_width = it->pixel_width;
31032 glyph->padding_p = false;
31033 }
31034 else
31035 {
31036
31037
31038 glyph->pixel_width = 1;
31039 glyph->padding_p = true;
31040 }
31041 glyph->ascent = it->ascent;
31042 glyph->descent = it->descent;
31043 glyph->voffset = it->voffset;
31044 glyph->type = CHAR_GLYPH;
31045 glyph->avoid_cursor_p = it->avoid_cursor_p;
31046 glyph->multibyte_p = it->multibyte_p;
31047 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31048 {
31049
31050
31051 glyph->right_box_line_p = it->start_of_box_run_p;
31052 glyph->left_box_line_p = it->end_of_box_run_p;
31053 }
31054 else
31055 {
31056 glyph->left_box_line_p = it->start_of_box_run_p;
31057 glyph->right_box_line_p = it->end_of_box_run_p;
31058 }
31059 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31060 || it->phys_descent > it->descent);
31061 glyph->glyph_not_available_p = it->glyph_not_available_p;
31062 glyph->face_id = it->face_id;
31063 glyph->u.ch = it->char_to_display;
31064 glyph->slice.img = null_glyph_slice;
31065 glyph->font_type = FONT_TYPE_UNKNOWN;
31066 if (it->bidi_p)
31067 {
31068 glyph->resolved_level = it->bidi_it.resolved_level;
31069 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31070 glyph->bidi_type = it->bidi_it.type;
31071 }
31072 else
31073 {
31074 glyph->resolved_level = 0;
31075 glyph->bidi_type = UNKNOWN_BT;
31076 }
31077 ++it->glyph_row->used[area];
31078 }
31079 else
31080 IT_EXPAND_MATRIX_WIDTH (it, area);
31081 }
31082
31083
31084
31085
31086 static void
31087 append_composite_glyph (struct it *it)
31088 {
31089 struct glyph *glyph;
31090 enum glyph_row_area area = it->area;
31091
31092 eassert (it->glyph_row);
31093
31094 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31095 if (glyph < it->glyph_row->glyphs[area + 1])
31096 {
31097
31098
31099 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
31100 {
31101 struct glyph *g;
31102
31103
31104 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31105 g[1] = *g;
31106 glyph = it->glyph_row->glyphs[it->area];
31107 }
31108 glyph->charpos = it->cmp_it.charpos;
31109 glyph->object = it->object;
31110 eassert (it->pixel_width <= SHRT_MAX);
31111 glyph->pixel_width = it->pixel_width;
31112 glyph->ascent = it->ascent;
31113 glyph->descent = it->descent;
31114 glyph->voffset = it->voffset;
31115 glyph->type = COMPOSITE_GLYPH;
31116 if (it->cmp_it.ch < 0)
31117 {
31118 glyph->u.cmp.automatic = false;
31119 glyph->u.cmp.id = it->cmp_it.id;
31120 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
31121 }
31122 else
31123 {
31124 glyph->u.cmp.automatic = true;
31125 glyph->u.cmp.id = it->cmp_it.id;
31126 glyph->slice.cmp.from = it->cmp_it.from;
31127 glyph->slice.cmp.to = it->cmp_it.to - 1;
31128 }
31129 glyph->avoid_cursor_p = it->avoid_cursor_p;
31130 glyph->multibyte_p = it->multibyte_p;
31131 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31132 {
31133
31134
31135 glyph->right_box_line_p = it->start_of_box_run_p;
31136 glyph->left_box_line_p = it->end_of_box_run_p;
31137 }
31138 else
31139 {
31140 glyph->left_box_line_p = it->start_of_box_run_p;
31141 glyph->right_box_line_p = it->end_of_box_run_p;
31142 }
31143 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31144 || it->phys_descent > it->descent);
31145 glyph->padding_p = false;
31146 glyph->glyph_not_available_p = it->glyph_not_available_p;
31147 glyph->face_id = it->face_id;
31148 glyph->font_type = FONT_TYPE_UNKNOWN;
31149 if (it->bidi_p)
31150 {
31151 glyph->resolved_level = it->bidi_it.resolved_level;
31152 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31153 glyph->bidi_type = it->bidi_it.type;
31154 }
31155 ++it->glyph_row->used[area];
31156 }
31157 else
31158 IT_EXPAND_MATRIX_WIDTH (it, area);
31159 }
31160
31161
31162
31163
31164
31165 static void
31166 take_vertical_position_into_account (struct it *it)
31167 {
31168 if (it->voffset)
31169 {
31170 if (it->voffset < 0)
31171
31172
31173 it->ascent -= it->voffset;
31174 else
31175
31176
31177 it->descent += it->voffset;
31178 }
31179 }
31180
31181
31182
31183
31184
31185
31186 static void
31187 produce_image_glyph (struct it *it)
31188 {
31189 struct image *img;
31190 struct face *face;
31191 int glyph_ascent, crop;
31192 struct glyph_slice slice;
31193
31194 eassert (it->what == IT_IMAGE);
31195
31196 face = FACE_FROM_ID (it->f, it->face_id);
31197
31198 prepare_face_for_display (it->f, face);
31199
31200 if (it->image_id < 0)
31201 {
31202
31203 it->ascent = it->phys_ascent = 0;
31204 it->descent = it->phys_descent = 0;
31205 it->pixel_width = 0;
31206 it->nglyphs = 0;
31207 return;
31208 }
31209
31210 img = IMAGE_FROM_ID (it->f, it->image_id);
31211
31212 prepare_image_for_display (it->f, img);
31213
31214 slice.x = slice.y = 0;
31215 slice.width = img->width;
31216 slice.height = img->height;
31217
31218 if (FIXNUMP (it->slice.x))
31219 slice.x = XFIXNUM (it->slice.x);
31220 else if (FLOATP (it->slice.x))
31221 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
31222
31223 if (FIXNUMP (it->slice.y))
31224 slice.y = XFIXNUM (it->slice.y);
31225 else if (FLOATP (it->slice.y))
31226 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
31227
31228 if (FIXNUMP (it->slice.width))
31229 slice.width = XFIXNUM (it->slice.width);
31230 else if (FLOATP (it->slice.width))
31231 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
31232
31233 if (FIXNUMP (it->slice.height))
31234 slice.height = XFIXNUM (it->slice.height);
31235 else if (FLOATP (it->slice.height))
31236 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
31237
31238 if (slice.x >= img->width)
31239 slice.x = img->width;
31240 if (slice.y >= img->height)
31241 slice.y = img->height;
31242 if (slice.x + slice.width >= img->width)
31243 slice.width = img->width - slice.x;
31244 if (slice.y + slice.height > img->height)
31245 slice.height = img->height - slice.y;
31246
31247 if (slice.width == 0 || slice.height == 0)
31248 return;
31249
31250 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
31251
31252 it->descent = slice.height - glyph_ascent;
31253 if (slice.y == 0)
31254 it->descent += img->vmargin;
31255 if (slice.y + slice.height == img->height)
31256 it->descent += img->vmargin;
31257 it->phys_descent = it->descent;
31258
31259 it->pixel_width = slice.width;
31260 if (slice.x == 0)
31261 it->pixel_width += img->hmargin;
31262 if (slice.x + slice.width == img->width)
31263 it->pixel_width += img->hmargin;
31264
31265
31266
31267 if (it->descent < 0)
31268 it->descent = 0;
31269
31270 it->nglyphs = 1;
31271
31272 if (face->box != FACE_NO_BOX)
31273 {
31274
31275
31276 if (face->box_horizontal_line_width > 0)
31277 {
31278 if (slice.y == 0)
31279 it->ascent += face->box_horizontal_line_width;
31280 if (slice.y + slice.height == img->height)
31281 it->descent += face->box_horizontal_line_width;
31282 }
31283
31284 if (face->box_vertical_line_width > 0)
31285 {
31286 if (it->start_of_box_run_p && slice.x == 0)
31287 it->pixel_width += face->box_vertical_line_width;
31288 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
31289 it->pixel_width += face->box_vertical_line_width;
31290 }
31291 }
31292
31293 take_vertical_position_into_account (it);
31294
31295
31296
31297 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
31298 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31299 {
31300 it->pixel_width -= crop;
31301 slice.width -= crop;
31302 }
31303
31304 if (it->glyph_row)
31305 {
31306 struct glyph *glyph;
31307 enum glyph_row_area area = it->area;
31308
31309 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31310 if (it->glyph_row->reversed_p)
31311 {
31312 struct glyph *g;
31313
31314
31315 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31316 g[1] = *g;
31317 glyph = it->glyph_row->glyphs[it->area];
31318 }
31319 if (glyph < it->glyph_row->glyphs[area + 1])
31320 {
31321 glyph->charpos = CHARPOS (it->position);
31322 glyph->object = it->object;
31323 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31324 glyph->ascent = glyph_ascent;
31325 glyph->descent = it->descent;
31326 glyph->voffset = it->voffset;
31327 glyph->type = IMAGE_GLYPH;
31328 glyph->avoid_cursor_p = it->avoid_cursor_p;
31329 glyph->multibyte_p = it->multibyte_p;
31330 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31331 {
31332
31333
31334 glyph->right_box_line_p = it->start_of_box_run_p;
31335 glyph->left_box_line_p = it->end_of_box_run_p;
31336 }
31337 else
31338 {
31339 glyph->left_box_line_p = it->start_of_box_run_p;
31340 glyph->right_box_line_p = it->end_of_box_run_p;
31341 }
31342 glyph->overlaps_vertically_p = false;
31343 glyph->padding_p = false;
31344 glyph->glyph_not_available_p = false;
31345 glyph->face_id = it->face_id;
31346 glyph->u.img_id = img->id;
31347 glyph->slice.img = slice;
31348 glyph->font_type = FONT_TYPE_UNKNOWN;
31349 if (it->bidi_p)
31350 {
31351 glyph->resolved_level = it->bidi_it.resolved_level;
31352 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31353 glyph->bidi_type = it->bidi_it.type;
31354 }
31355 ++it->glyph_row->used[area];
31356 }
31357 else
31358 IT_EXPAND_MATRIX_WIDTH (it, area);
31359 }
31360 }
31361
31362 static void
31363 produce_xwidget_glyph (struct it *it)
31364 {
31365 #ifdef HAVE_XWIDGETS
31366 struct xwidget *xw;
31367 int glyph_ascent, crop;
31368 eassert (it->what == IT_XWIDGET);
31369
31370 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31371
31372 prepare_face_for_display (it->f, face);
31373
31374 xw = it->xwidget;
31375 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31376 it->descent = xw->height/2;
31377 it->phys_descent = it->descent;
31378 it->pixel_width = xw->width;
31379
31380
31381 if (it->descent < 0)
31382 it->descent = 0;
31383
31384 it->nglyphs = 1;
31385
31386 if (face->box != FACE_NO_BOX)
31387 {
31388 if (face->box_horizontal_line_width > 0)
31389 {
31390 it->ascent += face->box_horizontal_line_width;
31391 it->descent += face->box_horizontal_line_width;
31392 }
31393
31394 if (face->box_vertical_line_width > 0)
31395 {
31396 if (it->start_of_box_run_p)
31397 it->pixel_width += face->box_vertical_line_width;
31398 it->pixel_width += face->box_vertical_line_width;
31399 }
31400 }
31401
31402 take_vertical_position_into_account (it);
31403
31404
31405
31406 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31407 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31408 it->pixel_width -= crop;
31409
31410 if (it->glyph_row)
31411 {
31412 enum glyph_row_area area = it->area;
31413 struct glyph *glyph
31414 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31415
31416 if (it->glyph_row->reversed_p)
31417 {
31418 struct glyph *g;
31419
31420
31421 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31422 g[1] = *g;
31423 glyph = it->glyph_row->glyphs[it->area];
31424 }
31425 if (glyph < it->glyph_row->glyphs[area + 1])
31426 {
31427 glyph->charpos = CHARPOS (it->position);
31428 glyph->object = it->object;
31429 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31430 glyph->ascent = glyph_ascent;
31431 glyph->descent = it->descent;
31432 glyph->voffset = it->voffset;
31433 glyph->type = XWIDGET_GLYPH;
31434 glyph->avoid_cursor_p = it->avoid_cursor_p;
31435 glyph->multibyte_p = it->multibyte_p;
31436 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31437 {
31438
31439
31440 glyph->right_box_line_p = it->start_of_box_run_p;
31441 glyph->left_box_line_p = it->end_of_box_run_p;
31442 }
31443 else
31444 {
31445 glyph->left_box_line_p = it->start_of_box_run_p;
31446 glyph->right_box_line_p = it->end_of_box_run_p;
31447 }
31448 glyph->overlaps_vertically_p = 0;
31449 glyph->padding_p = 0;
31450 glyph->glyph_not_available_p = 0;
31451 glyph->face_id = it->face_id;
31452 glyph->u.xwidget = it->xwidget->xwidget_id;
31453 glyph->font_type = FONT_TYPE_UNKNOWN;
31454 if (it->bidi_p)
31455 {
31456 glyph->resolved_level = it->bidi_it.resolved_level;
31457 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31458 glyph->bidi_type = it->bidi_it.type;
31459 }
31460 ++it->glyph_row->used[area];
31461 }
31462 else
31463 IT_EXPAND_MATRIX_WIDTH (it, area);
31464 }
31465 #endif
31466 }
31467
31468
31469
31470
31471
31472 static void
31473 append_stretch_glyph (struct it *it, Lisp_Object object,
31474 int width, int height, int ascent)
31475 {
31476 struct glyph *glyph;
31477 enum glyph_row_area area = it->area;
31478
31479 eassert (ascent >= 0 && ascent <= height);
31480
31481 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31482 if (glyph < it->glyph_row->glyphs[area + 1])
31483 {
31484
31485
31486 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31487 {
31488 struct glyph *g;
31489
31490
31491 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31492 g[1] = *g;
31493 glyph = it->glyph_row->glyphs[area];
31494
31495
31496
31497
31498
31499
31500
31501
31502
31503
31504
31505
31506
31507
31508
31509 if (it->current_x < it->first_visible_x)
31510 width -= it->first_visible_x - it->current_x;
31511 eassert (width > 0);
31512 }
31513 glyph->charpos = CHARPOS (it->position);
31514 glyph->object = object;
31515
31516
31517 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31518 glyph->ascent = ascent;
31519 glyph->descent = height - ascent;
31520 glyph->voffset = it->voffset;
31521 glyph->type = STRETCH_GLYPH;
31522 glyph->avoid_cursor_p = it->avoid_cursor_p;
31523 glyph->multibyte_p = it->multibyte_p;
31524 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31525 {
31526
31527
31528 glyph->right_box_line_p = it->start_of_box_run_p;
31529 glyph->left_box_line_p = it->end_of_box_run_p;
31530 }
31531 else
31532 {
31533 glyph->left_box_line_p = it->start_of_box_run_p;
31534 glyph->right_box_line_p = it->end_of_box_run_p;
31535 }
31536 glyph->overlaps_vertically_p = false;
31537 glyph->padding_p = false;
31538 glyph->glyph_not_available_p = false;
31539 glyph->face_id = it->face_id;
31540 glyph->u.stretch.ascent = ascent;
31541 glyph->u.stretch.height = height;
31542 glyph->slice.img = null_glyph_slice;
31543 glyph->font_type = FONT_TYPE_UNKNOWN;
31544 if (it->bidi_p)
31545 {
31546 glyph->resolved_level = it->bidi_it.resolved_level;
31547 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31548 glyph->bidi_type = it->bidi_it.type;
31549 }
31550 else
31551 {
31552 glyph->resolved_level = 0;
31553 glyph->bidi_type = UNKNOWN_BT;
31554 }
31555 ++it->glyph_row->used[area];
31556 }
31557 else
31558 IT_EXPAND_MATRIX_WIDTH (it, area);
31559 }
31560
31561 #endif
31562
31563
31564
31565
31566
31567
31568
31569
31570
31571
31572
31573
31574
31575
31576
31577
31578
31579
31580
31581
31582
31583
31584
31585
31586
31587
31588
31589
31590
31591
31592
31593
31594 void
31595 produce_stretch_glyph (struct it *it)
31596 {
31597
31598 Lisp_Object prop, plist;
31599 int width = 0, height = 0, align_to = -1;
31600 bool zero_width_ok_p = false;
31601 double tem;
31602 struct font *font = NULL;
31603
31604 #ifdef HAVE_WINDOW_SYSTEM
31605 int ascent = 0;
31606 bool zero_height_ok_p = false;
31607 struct face *face = NULL;
31608
31609 if (FRAME_WINDOW_P (it->f))
31610 {
31611 face = FACE_FROM_ID (it->f, it->face_id);
31612 font = face->font ? face->font : FRAME_FONT (it->f);
31613 prepare_face_for_display (it->f, face);
31614 }
31615 #endif
31616
31617
31618 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31619 plist = XCDR (it->object);
31620
31621
31622 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31623 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31624 {
31625
31626 zero_width_ok_p = true;
31627 width = (int)tem;
31628 }
31629 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31630 {
31631
31632
31633
31634 struct it it2;
31635 Lisp_Object object =
31636 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31637 unsigned char *p = (STRINGP (object)
31638 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31639 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31640 bool multibyte_p =
31641 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31642
31643 it2 = *it;
31644 if (multibyte_p)
31645 {
31646 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31647 #ifdef HAVE_WINDOW_SYSTEM
31648 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31649 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31650 IT_CHARPOS (*it),
31651 STRINGP (object)? object : Qnil);
31652 #endif
31653 }
31654 else
31655 {
31656 it2.c = it2.char_to_display = *p, it2.len = 1;
31657 if (! ASCII_CHAR_P (it2.c))
31658 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31659 }
31660
31661 it2.glyph_row = NULL;
31662 it2.what = IT_CHARACTER;
31663 PRODUCE_GLYPHS (&it2);
31664 width = NUMVAL (prop) * it2.pixel_width;
31665 }
31666 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31667 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31668 &align_to))
31669 {
31670 int x = it->current_x + it->continuation_lines_width;
31671 int x0 = x;
31672
31673 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31674 {
31675 x -= it->lnum_pixel_width;
31676
31677 if (x + it->stretch_adjust >= it->first_visible_x)
31678 x += it->stretch_adjust;
31679 }
31680
31681 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31682 align_to = (align_to < 0
31683 ? 0
31684 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31685 else if (align_to < 0)
31686 align_to = window_box_left_offset (it->w, TEXT_AREA);
31687 width = max (0, (int)tem + align_to - x);
31688
31689 int next_x = x + width;
31690 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31691 {
31692
31693
31694 if (x < it->first_visible_x)
31695 {
31696 next_x -= it->first_visible_x - x;
31697 it->stretch_adjust = it->first_visible_x - x;
31698 }
31699 else
31700 next_x -= it->stretch_adjust;
31701 }
31702 width = next_x - x0;
31703 zero_width_ok_p = true;
31704 }
31705 else
31706
31707 width = FRAME_COLUMN_WIDTH (it->f);
31708
31709 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31710 width = 1;
31711
31712 #ifdef HAVE_WINDOW_SYSTEM
31713
31714 if (FRAME_WINDOW_P (it->f))
31715 {
31716 int default_height = normal_char_height (font, ' ');
31717
31718 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31719 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31720 {
31721 height = (int)tem;
31722 zero_height_ok_p = true;
31723 }
31724 else if (prop = plist_get (plist, QCrelative_height),
31725 NUMVAL (prop) > 0)
31726 height = default_height * NUMVAL (prop);
31727 else
31728 height = default_height;
31729
31730 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31731 height = 1;
31732
31733
31734
31735
31736 if (prop = plist_get (plist, QCascent),
31737 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31738 ascent = height * NUMVAL (prop) / 100.0;
31739 else if (!NILP (prop)
31740 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31741 ascent = min (max (0, (int)tem), height);
31742 else
31743 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31744 }
31745 else
31746 #endif
31747 height = 1;
31748
31749 if (width > 0
31750 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31751 && it->current_x + width > it->last_visible_x)
31752 {
31753 width = it->last_visible_x - it->current_x;
31754 #ifdef HAVE_WINDOW_SYSTEM
31755
31756
31757 width -= FRAME_WINDOW_P (it->f);
31758 #endif
31759 }
31760
31761 if (width > 0 && height > 0 && it->glyph_row)
31762 {
31763 Lisp_Object o_object = it->object;
31764 Lisp_Object object =
31765 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31766 int n = width;
31767
31768 if (!STRINGP (object))
31769 object = it->w->contents;
31770 #ifdef HAVE_WINDOW_SYSTEM
31771 if (FRAME_WINDOW_P (it->f))
31772 append_stretch_glyph (it, object, width, height, ascent);
31773 else
31774 #endif
31775 {
31776 it->object = object;
31777 it->char_to_display = ' ';
31778 it->pixel_width = it->len = 1;
31779 while (n--)
31780 tty_append_glyph (it);
31781 it->object = o_object;
31782 }
31783 }
31784
31785 it->pixel_width = width;
31786 #ifdef HAVE_WINDOW_SYSTEM
31787 if (FRAME_WINDOW_P (it->f))
31788 {
31789 it->ascent = it->phys_ascent = ascent;
31790 it->descent = it->phys_descent = height - it->ascent;
31791 it->nglyphs = width > 0 && height > 0;
31792 take_vertical_position_into_account (it);
31793 }
31794 else
31795 #endif
31796 it->nglyphs = width;
31797 }
31798
31799
31800
31801
31802
31803
31804
31805 static void
31806 produce_special_glyphs (struct it *it, enum display_element_type what)
31807 {
31808 struct it temp_it;
31809 Lisp_Object gc;
31810 GLYPH glyph;
31811
31812 temp_it = *it;
31813 temp_it.object = Qnil;
31814 memset (&temp_it.current, 0, sizeof temp_it.current);
31815
31816 if (what == IT_CONTINUATION)
31817 {
31818
31819 if (it->bidi_it.paragraph_dir == R2L)
31820 SET_GLYPH_FROM_CHAR (glyph, '/');
31821 else
31822 SET_GLYPH_FROM_CHAR (glyph, '\\');
31823 if (it->dp
31824 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31825 {
31826
31827 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31828 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31829 }
31830 }
31831 else if (what == IT_TRUNCATION)
31832 {
31833
31834 SET_GLYPH_FROM_CHAR (glyph, '$');
31835 if (it->dp
31836 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31837 {
31838
31839 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31840 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31841 }
31842 }
31843 else
31844 emacs_abort ();
31845
31846 #ifdef HAVE_WINDOW_SYSTEM
31847
31848
31849
31850
31851
31852 if (FRAME_WINDOW_P (temp_it.f)
31853
31854
31855
31856 && temp_it.glyph_row
31857
31858
31859
31860 && temp_it.glyph_row->used[TEXT_AREA] > 0
31861 && (temp_it.glyph_row->reversed_p
31862 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31863 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31864 {
31865 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31866
31867 if (stretch_width > 0)
31868 {
31869 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31870 struct font *font =
31871 face->font ? face->font : FRAME_FONT (temp_it.f);
31872 int stretch_ascent =
31873 (((temp_it.ascent + temp_it.descent)
31874 * FONT_BASE (font)) / FONT_HEIGHT (font));
31875
31876 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31877 temp_it.ascent + temp_it.descent,
31878 stretch_ascent);
31879 }
31880 }
31881 #endif
31882
31883 temp_it.dp = NULL;
31884 temp_it.what = IT_CHARACTER;
31885 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31886 temp_it.face_id = GLYPH_FACE (glyph);
31887 temp_it.len = CHAR_BYTES (temp_it.c);
31888
31889 PRODUCE_GLYPHS (&temp_it);
31890 it->pixel_width = temp_it.pixel_width;
31891 it->nglyphs = temp_it.nglyphs;
31892 }
31893
31894
31895
31896
31897
31898
31899
31900
31901
31902 static void
31903 pad_mode_line (struct it *it, bool mode_line_p)
31904 {
31905 struct it temp_it;
31906 GLYPH glyph;
31907
31908 eassert (!FRAME_WINDOW_P (it->f));
31909 temp_it = *it;
31910 temp_it.object = Qnil;
31911 memset (&temp_it.current, 0, sizeof temp_it.current);
31912
31913 SET_GLYPH (glyph, mode_line_p ? '-' : ' ', it->base_face_id);
31914
31915 temp_it.dp = NULL;
31916 temp_it.what = IT_CHARACTER;
31917 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31918 temp_it.face_id = GLYPH_FACE (glyph);
31919 temp_it.len = CHAR_BYTES (temp_it.c);
31920
31921 PRODUCE_GLYPHS (&temp_it);
31922 it->pixel_width = temp_it.pixel_width;
31923 it->nglyphs = temp_it.nglyphs;
31924 }
31925
31926 #ifdef HAVE_WINDOW_SYSTEM
31927
31928
31929
31930
31931
31932
31933
31934
31935
31936 static Lisp_Object
31937 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31938 int boff, bool override)
31939 {
31940 Lisp_Object face_name = Qnil;
31941 int ascent, descent, height;
31942
31943 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31944 return val;
31945
31946 if (CONSP (val))
31947 {
31948 face_name = XCAR (val);
31949 val = XCDR (val);
31950 if (!NUMBERP (val))
31951 val = make_fixnum (1);
31952 if (NILP (face_name))
31953 {
31954 height = it->ascent + it->descent;
31955 goto scale;
31956 }
31957 }
31958
31959 if (NILP (face_name))
31960 {
31961 font = FRAME_FONT (it->f);
31962 boff = FRAME_BASELINE_OFFSET (it->f);
31963 }
31964 else if (EQ (face_name, Qt))
31965 {
31966 override = false;
31967 }
31968 else
31969 {
31970 int face_id;
31971 struct face *face;
31972
31973 face_id = lookup_named_face (it->w, it->f, face_name, false);
31974 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31975 if (face == NULL || ((font = face->font) == NULL))
31976 return make_fixnum (-1);
31977 boff = font->baseline_offset;
31978 if (font->vertical_centering)
31979 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31980 }
31981
31982 normal_char_ascent_descent (font, -1, &ascent, &descent);
31983
31984 if (override)
31985 {
31986 it->override_ascent = ascent;
31987 it->override_descent = descent;
31988 it->override_boff = boff;
31989 }
31990
31991 height = ascent + descent;
31992
31993 scale:
31994
31995 if (FLOATP (val))
31996 height = (int)(XFLOAT_DATA (val) * height);
31997 else if (INTEGERP (val))
31998 {
31999 intmax_t v;
32000 if (integer_to_intmax (val, &v))
32001 height *= v;
32002 }
32003
32004 return make_fixnum (height);
32005 }
32006
32007
32008
32009
32010
32011
32012
32013
32014
32015
32016
32017
32018
32019
32020 static void
32021 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
32022 short upper_xoff, short upper_yoff,
32023 short lower_xoff, short lower_yoff)
32024 {
32025 struct glyph *glyph;
32026 enum glyph_row_area area = it->area;
32027
32028 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
32029 if (glyph < it->glyph_row->glyphs[area + 1])
32030 {
32031
32032
32033 if (it->glyph_row->reversed_p && area == TEXT_AREA)
32034 {
32035 struct glyph *g;
32036
32037
32038 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
32039 g[1] = *g;
32040 glyph = it->glyph_row->glyphs[area];
32041 }
32042 glyph->charpos = CHARPOS (it->position);
32043 glyph->object = it->object;
32044 eassert (it->pixel_width <= SHRT_MAX);
32045 glyph->pixel_width = it->pixel_width;
32046 glyph->ascent = it->ascent;
32047 glyph->descent = it->descent;
32048 glyph->voffset = it->voffset;
32049 glyph->type = GLYPHLESS_GLYPH;
32050 glyph->u.glyphless.method = it->glyphless_method;
32051 glyph->u.glyphless.for_no_font = for_no_font;
32052 glyph->u.glyphless.len = len;
32053 glyph->u.glyphless.ch = it->c;
32054 glyph->slice.glyphless.upper_xoff = upper_xoff;
32055 glyph->slice.glyphless.upper_yoff = upper_yoff;
32056 glyph->slice.glyphless.lower_xoff = lower_xoff;
32057 glyph->slice.glyphless.lower_yoff = lower_yoff;
32058 glyph->avoid_cursor_p = it->avoid_cursor_p;
32059 glyph->multibyte_p = it->multibyte_p;
32060 if (it->glyph_row->reversed_p && area == TEXT_AREA)
32061 {
32062
32063
32064 glyph->right_box_line_p = it->start_of_box_run_p;
32065 glyph->left_box_line_p = it->end_of_box_run_p;
32066 }
32067 else
32068 {
32069 glyph->left_box_line_p = it->start_of_box_run_p;
32070 glyph->right_box_line_p = it->end_of_box_run_p;
32071 }
32072 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
32073 || it->phys_descent > it->descent);
32074 glyph->padding_p = false;
32075 glyph->glyph_not_available_p = false;
32076 glyph->face_id = face_id;
32077 glyph->font_type = FONT_TYPE_UNKNOWN;
32078 if (it->bidi_p)
32079 {
32080 glyph->resolved_level = it->bidi_it.resolved_level;
32081 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
32082 glyph->bidi_type = it->bidi_it.type;
32083 }
32084 ++it->glyph_row->used[area];
32085 }
32086 else
32087 IT_EXPAND_MATRIX_WIDTH (it, area);
32088 }
32089
32090
32091
32092
32093
32094
32095
32096
32097
32098
32099
32100 static void
32101 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
32102 {
32103 int face_id;
32104 struct face *face;
32105 struct font *font;
32106 int base_width, base_height, width, height;
32107 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
32108 int len;
32109
32110
32111
32112
32113 face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
32114 if (face)
32115 face = face->ascii_face;
32116 font = (face && face->font) ? face->font : FRAME_FONT (it->f);
32117 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
32118 it->ascent += font->baseline_offset;
32119 it->descent -= font->baseline_offset;
32120 base_height = it->ascent + it->descent;
32121 base_width = font->average_width;
32122
32123 face_id = merge_glyphless_glyph_face (it);
32124
32125 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
32126 {
32127 it->pixel_width = THIN_SPACE_WIDTH;
32128 len = 0;
32129 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32130 }
32131 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
32132 {
32133 width = CHARACTER_WIDTH (it->c);
32134 if (width == 0)
32135 width = 1;
32136 else if (width > 4)
32137 width = 4;
32138 it->pixel_width = base_width * width;
32139 len = 0;
32140 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32141 }
32142 else
32143 {
32144 char buf[7];
32145 const char *str;
32146 unsigned int code[6];
32147 int upper_len;
32148 int ascent, descent;
32149 struct font_metrics metrics_upper, metrics_lower;
32150
32151 face = FACE_FROM_ID (it->f, face_id);
32152 font = face->font ? face->font : FRAME_FONT (it->f);
32153 prepare_face_for_display (it->f, face);
32154
32155 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
32156 {
32157 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
32158 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
32159 if (CONSP (acronym))
32160 acronym = XCAR (acronym);
32161 str = STRINGP (acronym) ? SSDATA (acronym) : "";
32162 }
32163 else
32164 {
32165 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
32166 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
32167 str = buf;
32168 }
32169 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
32170 code[len] = font->driver->encode_char (font, str[len]);
32171 upper_len = (len + 1) / 2;
32172 font->driver->text_extents (font, code, upper_len,
32173 &metrics_upper);
32174 font->driver->text_extents (font, code + upper_len, len - upper_len,
32175 &metrics_lower);
32176
32177
32178
32179
32180 width = max (metrics_upper.width, metrics_lower.width) + 4;
32181 upper_xoff = lower_xoff = 2;
32182 if (base_width >= width)
32183 {
32184
32185 it->pixel_width = base_width;
32186 lower_xoff = base_width - 2 - metrics_lower.width;
32187 }
32188 else
32189 {
32190
32191 it->pixel_width = width;
32192 if (metrics_upper.width >= metrics_lower.width)
32193 lower_xoff = (width - metrics_lower.width) / 2;
32194 else
32195 upper_xoff = (width - metrics_upper.width) / 2;
32196 }
32197
32198
32199
32200 height = (metrics_upper.ascent + metrics_upper.descent
32201 + metrics_lower.ascent + metrics_lower.descent) + 5;
32202
32203
32204
32205
32206
32207
32208
32209
32210 ascent = - (it->descent - (base_height + height + 1) / 2);
32211 descent = it->descent - (base_height - height) / 2;
32212 lower_yoff = descent - 2 - metrics_lower.descent;
32213 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
32214 - metrics_upper.descent);
32215
32216 if (height > base_height)
32217 {
32218 it->ascent = ascent;
32219 it->descent = descent;
32220 }
32221 }
32222
32223 it->phys_ascent = it->ascent;
32224 it->phys_descent = it->descent;
32225 if (it->glyph_row)
32226 append_glyphless_glyph (it, face_id, for_no_font, len,
32227 upper_xoff, upper_yoff,
32228 lower_xoff, lower_yoff);
32229 it->nglyphs = 1;
32230 take_vertical_position_into_account (it);
32231 }
32232
32233
32234
32235
32236
32237 #define IT_APPLY_FACE_BOX(it, face) \
32238 do { \
32239 if (face->box != FACE_NO_BOX) \
32240 { \
32241 int thick = face->box_horizontal_line_width; \
32242 if (thick > 0) \
32243 { \
32244 it->ascent += thick; \
32245 it->descent += thick; \
32246 } \
32247 \
32248 thick = face->box_vertical_line_width; \
32249 if (thick > 0) \
32250 { \
32251 if (it->start_of_box_run_p) \
32252 it->pixel_width += thick; \
32253 if (it->end_of_box_run_p) \
32254 it->pixel_width += thick; \
32255 } \
32256 } \
32257 } while (false)
32258
32259
32260
32261
32262
32263
32264 void
32265 gui_produce_glyphs (struct it *it)
32266 {
32267 int extra_line_spacing = it->extra_line_spacing;
32268
32269 it->glyph_not_available_p = false;
32270
32271 if (it->what == IT_CHARACTER)
32272 {
32273 unsigned char2b;
32274 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32275 struct font *font = face->font;
32276 struct font_metrics *pcm = NULL;
32277 int boff;
32278
32279 if (font == NULL)
32280 {
32281
32282
32283
32284 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
32285
32286 eassert (it->what == IT_GLYPHLESS);
32287 produce_glyphless_glyph (it, true,
32288 STRINGP (acronym) ? acronym : Qnil);
32289 goto done;
32290 }
32291
32292 boff = font->baseline_offset;
32293 if (font->vertical_centering)
32294 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32295
32296 if (it->char_to_display != '\n' && it->char_to_display != '\t')
32297 {
32298 it->nglyphs = 1;
32299
32300 if (it->override_ascent >= 0)
32301 {
32302 it->ascent = it->override_ascent;
32303 it->descent = it->override_descent;
32304 boff = it->override_boff;
32305 }
32306 else
32307 {
32308 it->ascent = FONT_BASE (font) + boff;
32309 it->descent = FONT_DESCENT (font) - boff;
32310 }
32311
32312 if (get_char_glyph_code (it->char_to_display, font, &char2b))
32313 {
32314 pcm = get_per_char_metric (font, &char2b);
32315 if (pcm->width == 0
32316 && pcm->rbearing == 0 && pcm->lbearing == 0)
32317 pcm = NULL;
32318 }
32319
32320 if (pcm)
32321 {
32322 it->phys_ascent = pcm->ascent + boff;
32323 it->phys_descent = pcm->descent - boff;
32324 it->pixel_width = pcm->width;
32325
32326
32327 if (it->override_ascent < 0)
32328 {
32329 if (FONT_TOO_HIGH (font))
32330 {
32331 it->ascent = it->phys_ascent;
32332 it->descent = it->phys_descent;
32333
32334
32335 if (it->ascent < 0)
32336 it->ascent = 0;
32337 if (it->descent < 0)
32338 it->descent = 0;
32339 }
32340 }
32341 }
32342 else
32343 {
32344 it->glyph_not_available_p = true;
32345 it->phys_ascent = it->ascent;
32346 it->phys_descent = it->descent;
32347 it->pixel_width = font->space_width;
32348 }
32349
32350 if (it->constrain_row_ascent_descent_p)
32351 {
32352 if (it->descent > it->max_descent)
32353 {
32354 it->ascent += it->descent - it->max_descent;
32355 it->descent = it->max_descent;
32356 }
32357 if (it->ascent > it->max_ascent)
32358 {
32359 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32360 it->ascent = it->max_ascent;
32361 }
32362 it->phys_ascent = min (it->phys_ascent, it->ascent);
32363 it->phys_descent = min (it->phys_descent, it->descent);
32364 extra_line_spacing = 0;
32365 }
32366
32367
32368
32369 bool stretched_p
32370 = it->char_to_display == ' ' && !NILP (it->space_width);
32371 if (stretched_p)
32372 it->pixel_width *= XFLOATINT (it->space_width);
32373
32374 IT_APPLY_FACE_BOX(it, face);
32375
32376
32377
32378 if (face->overline_p)
32379 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32380
32381 if (it->constrain_row_ascent_descent_p)
32382 {
32383 if (it->ascent > it->max_ascent)
32384 it->ascent = it->max_ascent;
32385 if (it->descent > it->max_descent)
32386 it->descent = it->max_descent;
32387 }
32388
32389 take_vertical_position_into_account (it);
32390
32391
32392 if (it->glyph_row)
32393 {
32394 if (stretched_p)
32395 {
32396
32397
32398 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32399 / FONT_HEIGHT (font));
32400 append_stretch_glyph (it, it->object, it->pixel_width,
32401 it->ascent + it->descent, ascent);
32402 }
32403 else
32404 append_glyph (it);
32405
32406
32407
32408
32409 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32410 it->glyph_row->contains_overlapping_glyphs_p = true;
32411 }
32412 if (! stretched_p && it->pixel_width == 0)
32413
32414
32415 it->pixel_width = 1;
32416 }
32417 else if (it->char_to_display == '\n')
32418 {
32419
32420
32421
32422
32423 Lisp_Object height;
32424 Lisp_Object total_height = Qnil;
32425
32426 it->override_ascent = -1;
32427 it->pixel_width = 0;
32428 it->nglyphs = 0;
32429
32430 height = get_it_property (it, Qline_height);
32431
32432 if (CONSP (height)
32433 && CONSP (XCDR (height))
32434 && NILP (XCDR (XCDR (height))))
32435 {
32436 total_height = XCAR (XCDR (height));
32437 height = XCAR (height);
32438 }
32439 height = calc_line_height_property (it, height, font, boff, true);
32440
32441 if (it->override_ascent >= 0)
32442 {
32443 it->ascent = it->override_ascent;
32444 it->descent = it->override_descent;
32445 boff = it->override_boff;
32446 }
32447 else
32448 {
32449 if (FONT_TOO_HIGH (font))
32450 {
32451 it->ascent = font->pixel_size + boff - 1;
32452 it->descent = -boff + 1;
32453 if (it->descent < 0)
32454 it->descent = 0;
32455 }
32456 else
32457 {
32458 it->ascent = FONT_BASE (font) + boff;
32459 it->descent = FONT_DESCENT (font) - boff;
32460 }
32461 }
32462
32463 if (EQ (height, Qt))
32464 {
32465 if (it->descent > it->max_descent)
32466 {
32467 it->ascent += it->descent - it->max_descent;
32468 it->descent = it->max_descent;
32469 }
32470 if (it->ascent > it->max_ascent)
32471 {
32472 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32473 it->ascent = it->max_ascent;
32474 }
32475 it->phys_ascent = min (it->phys_ascent, it->ascent);
32476 it->phys_descent = min (it->phys_descent, it->descent);
32477 it->constrain_row_ascent_descent_p = true;
32478 extra_line_spacing = 0;
32479 }
32480 else
32481 {
32482 Lisp_Object spacing;
32483
32484 it->phys_ascent = it->ascent;
32485 it->phys_descent = it->descent;
32486
32487 if ((it->max_ascent > 0 || it->max_descent > 0)
32488 && face->box != FACE_NO_BOX
32489 && face->box_horizontal_line_width > 0)
32490 {
32491 it->ascent += face->box_horizontal_line_width;
32492 it->descent += face->box_horizontal_line_width;
32493 }
32494 if (!NILP (height)
32495 && XFIXNUM (height) > it->ascent + it->descent)
32496 it->ascent = XFIXNUM (height) - it->descent;
32497
32498 if (!NILP (total_height))
32499 spacing = calc_line_height_property (it, total_height, font,
32500 boff, false);
32501 else
32502 {
32503 spacing = get_it_property (it, Qline_spacing);
32504 spacing = calc_line_height_property (it, spacing, font,
32505 boff, false);
32506 }
32507 if (FIXNUMP (spacing))
32508 {
32509 extra_line_spacing = XFIXNUM (spacing);
32510 if (!NILP (total_height))
32511 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32512 }
32513 }
32514 }
32515 else
32516 {
32517 if (font->space_width > 0)
32518 {
32519 int tab_width = it->tab_width * font->space_width;
32520 int x = it->current_x + it->continuation_lines_width;
32521 int x0 = x;
32522
32523 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32524 {
32525 x -= it->lnum_pixel_width;
32526
32527 if (x + it->stretch_adjust >= it->first_visible_x)
32528 x += it->stretch_adjust;
32529 }
32530
32531 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32532
32533
32534
32535
32536 if (next_tab_x - x < font->space_width)
32537 next_tab_x += tab_width;
32538 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32539 {
32540 next_tab_x += it->lnum_pixel_width;
32541
32542
32543 if (x < it->first_visible_x)
32544 {
32545 next_tab_x -= it->first_visible_x - x;
32546 it->stretch_adjust = it->first_visible_x - x;
32547 }
32548 else
32549 next_tab_x -= it->stretch_adjust;
32550 }
32551
32552 it->pixel_width = next_tab_x - x0;
32553 it->nglyphs = 1;
32554 if (FONT_TOO_HIGH (font))
32555 {
32556 if (get_char_glyph_code (' ', font, &char2b))
32557 {
32558 pcm = get_per_char_metric (font, &char2b);
32559 if (pcm->width == 0
32560 && pcm->rbearing == 0 && pcm->lbearing == 0)
32561 pcm = NULL;
32562 }
32563
32564 if (pcm)
32565 {
32566 it->ascent = pcm->ascent + boff;
32567 it->descent = pcm->descent - boff;
32568 }
32569 else
32570 {
32571 it->ascent = font->pixel_size + boff - 1;
32572 it->descent = -boff + 1;
32573 }
32574 if (it->ascent < 0)
32575 it->ascent = 0;
32576 if (it->descent < 0)
32577 it->descent = 0;
32578 }
32579 else
32580 {
32581 it->ascent = FONT_BASE (font) + boff;
32582 it->descent = FONT_DESCENT (font) - boff;
32583 }
32584 it->phys_ascent = it->ascent;
32585 it->phys_descent = it->descent;
32586
32587 if (it->glyph_row)
32588 {
32589 append_stretch_glyph (it, it->object, it->pixel_width,
32590 it->ascent + it->descent, it->ascent);
32591 }
32592 }
32593 else
32594 {
32595 it->pixel_width = 0;
32596 it->nglyphs = 1;
32597 }
32598 }
32599
32600 if (FONT_TOO_HIGH (font))
32601 {
32602 int font_ascent, font_descent;
32603
32604
32605
32606
32607
32608
32609
32610
32611 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32612 it->max_ascent = max (it->max_ascent, font_ascent);
32613 it->max_descent = max (it->max_descent, font_descent);
32614 }
32615
32616 if (it->ascent < 0)
32617 it->ascent = 0;
32618 if (it->descent < 0)
32619 it->descent = 0;
32620 }
32621 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32622 {
32623
32624
32625
32626
32627
32628
32629
32630
32631 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32632 int boff;
32633 struct composition *cmp = composition_table[it->cmp_it.id];
32634 int glyph_len = cmp->glyph_len;
32635 struct font *font = face->font;
32636
32637 it->nglyphs = 1;
32638
32639
32640
32641
32642
32643
32644
32645
32646 if (! cmp->font || cmp->font != font)
32647 {
32648
32649
32650
32651
32652 int font_ascent, font_descent, font_height;
32653
32654 int leftmost, rightmost, lowest, highest;
32655 int lbearing, rbearing;
32656 int i, width, ascent, descent;
32657 int c;
32658 unsigned char2b;
32659 struct font_metrics *pcm;
32660 ptrdiff_t pos;
32661
32662 eassume (0 < glyph_len);
32663 do
32664 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32665 while (c == '\t' && 0 < --glyph_len);
32666
32667 bool right_padded = glyph_len < cmp->glyph_len;
32668 for (i = 0; i < glyph_len; i++)
32669 {
32670 c = COMPOSITION_GLYPH (cmp, i);
32671 if (c != '\t')
32672 break;
32673 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32674 }
32675 bool left_padded = i > 0;
32676
32677 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32678 : IT_CHARPOS (*it));
32679
32680 bool font_not_found_p = font == NULL;
32681 if (font_not_found_p)
32682 {
32683 face = face->ascii_face;
32684 font = face->font;
32685 }
32686 boff = font->baseline_offset;
32687 if (font->vertical_centering)
32688 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32689 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32690 font_ascent += boff;
32691 font_descent -= boff;
32692 font_height = font_ascent + font_descent;
32693
32694 cmp->font = font;
32695
32696 pcm = NULL;
32697 if (! font_not_found_p)
32698 {
32699 get_char_face_and_encoding (it->f, c, it->face_id,
32700 &char2b, false);
32701 pcm = get_per_char_metric (font, &char2b);
32702 }
32703
32704
32705 if (pcm)
32706 {
32707 width = cmp->glyph_len > 0 ? pcm->width : 0;
32708 ascent = pcm->ascent;
32709 descent = pcm->descent;
32710 lbearing = pcm->lbearing;
32711 rbearing = pcm->rbearing;
32712 }
32713 else
32714 {
32715 width = cmp->glyph_len > 0 ? font->space_width : 0;
32716 ascent = FONT_BASE (font);
32717 descent = FONT_DESCENT (font);
32718 lbearing = 0;
32719 rbearing = width;
32720 }
32721
32722 rightmost = width;
32723 leftmost = 0;
32724 lowest = - descent + boff;
32725 highest = ascent + boff;
32726
32727 if (! font_not_found_p
32728 && font->default_ascent
32729 && CHAR_TABLE_P (Vuse_default_ascent)
32730 && !NILP (Faref (Vuse_default_ascent,
32731 make_fixnum (it->char_to_display))))
32732 highest = font->default_ascent + boff;
32733
32734
32735
32736
32737 cmp->offsets[i * 2] = 0;
32738 cmp->offsets[i * 2 + 1] = boff;
32739 cmp->lbearing = lbearing;
32740 cmp->rbearing = rbearing;
32741
32742
32743 for (i++; i < glyph_len; i++)
32744 {
32745 int left, right, btm, top;
32746 int ch = COMPOSITION_GLYPH (cmp, i);
32747 int face_id;
32748 struct face *this_face;
32749
32750 if (ch == '\t')
32751 ch = ' ';
32752 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32753 this_face = FACE_FROM_ID (it->f, face_id);
32754 font = this_face->font;
32755
32756 if (font == NULL)
32757 pcm = NULL;
32758 else
32759 {
32760 get_char_face_and_encoding (it->f, ch, face_id,
32761 &char2b, false);
32762 pcm = get_per_char_metric (font, &char2b);
32763 }
32764 if (! pcm)
32765 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32766 else
32767 {
32768 width = pcm->width;
32769 ascent = pcm->ascent;
32770 descent = pcm->descent;
32771 lbearing = pcm->lbearing;
32772 rbearing = pcm->rbearing;
32773 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32774 {
32775
32776
32777 left = (leftmost + rightmost - width) / 2;
32778 btm = - descent + boff;
32779 if (font->relative_compose
32780 && (! CHAR_TABLE_P (Vignore_relative_composition)
32781 || NILP (Faref (Vignore_relative_composition,
32782 make_fixnum (ch)))))
32783 {
32784
32785 if (- descent >= font->relative_compose)
32786
32787 btm = highest + 1;
32788 else if (ascent <= 0)
32789
32790 btm = lowest - 1 - ascent - descent;
32791 }
32792 }
32793 else
32794 {
32795
32796
32797
32798
32799
32800
32801
32802
32803
32804
32805
32806
32807
32808
32809
32810 int rule = COMPOSITION_RULE (cmp, i);
32811 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32812
32813 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32814 grefx = gref % 3, nrefx = nref % 3;
32815 grefy = gref / 3, nrefy = nref / 3;
32816 if (xoff)
32817 xoff = font_height * (xoff - 128) / 256;
32818 if (yoff)
32819 yoff = font_height * (yoff - 128) / 256;
32820
32821 left = (leftmost
32822 + grefx * (rightmost - leftmost) / 2
32823 - nrefx * width / 2
32824 + xoff);
32825
32826 btm = ((grefy == 0 ? highest
32827 : grefy == 1 ? 0
32828 : grefy == 2 ? lowest
32829 : (highest + lowest) / 2)
32830 - (nrefy == 0 ? ascent + descent
32831 : nrefy == 1 ? descent - boff
32832 : nrefy == 2 ? 0
32833 : (ascent + descent) / 2)
32834 + yoff);
32835 }
32836
32837 cmp->offsets[i * 2] = left;
32838 cmp->offsets[i * 2 + 1] = btm + descent;
32839
32840
32841 if (width > 0)
32842 {
32843 right = left + width;
32844 if (left < leftmost)
32845 leftmost = left;
32846 if (right > rightmost)
32847 rightmost = right;
32848 }
32849 top = btm + descent + ascent;
32850 if (top > highest)
32851 highest = top;
32852 if (btm < lowest)
32853 lowest = btm;
32854
32855 if (cmp->lbearing > left + lbearing)
32856 cmp->lbearing = left + lbearing;
32857 if (cmp->rbearing < left + rbearing)
32858 cmp->rbearing = left + rbearing;
32859 }
32860 }
32861
32862
32863
32864
32865 if (leftmost < 0)
32866 {
32867 for (i = 0; i < cmp->glyph_len; i++)
32868 cmp->offsets[i * 2] -= leftmost;
32869 rightmost -= leftmost;
32870 cmp->lbearing -= leftmost;
32871 cmp->rbearing -= leftmost;
32872 }
32873
32874 if (left_padded && cmp->lbearing < 0)
32875 {
32876 for (i = 0; i < cmp->glyph_len; i++)
32877 cmp->offsets[i * 2] -= cmp->lbearing;
32878 rightmost -= cmp->lbearing;
32879 cmp->rbearing -= cmp->lbearing;
32880 cmp->lbearing = 0;
32881 }
32882 if (right_padded && rightmost < cmp->rbearing)
32883 {
32884 rightmost = cmp->rbearing;
32885 }
32886
32887 cmp->pixel_width = rightmost;
32888 cmp->ascent = highest;
32889 cmp->descent = - lowest;
32890 if (cmp->ascent < font_ascent)
32891 cmp->ascent = font_ascent;
32892 if (cmp->descent < font_descent)
32893 cmp->descent = font_descent;
32894 }
32895
32896 if (it->glyph_row
32897 && (cmp->lbearing < 0
32898 || cmp->rbearing > cmp->pixel_width))
32899 it->glyph_row->contains_overlapping_glyphs_p = true;
32900
32901 it->pixel_width = cmp->pixel_width;
32902 it->ascent = it->phys_ascent = cmp->ascent;
32903 it->descent = it->phys_descent = cmp->descent;
32904 IT_APPLY_FACE_BOX(it, face);
32905
32906
32907
32908 if (face->overline_p)
32909 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32910
32911 take_vertical_position_into_account (it);
32912 if (it->ascent < 0)
32913 it->ascent = 0;
32914 if (it->descent < 0)
32915 it->descent = 0;
32916
32917 if (it->glyph_row && cmp->glyph_len > 0)
32918 append_composite_glyph (it);
32919 }
32920 else if (it->what == IT_COMPOSITION)
32921 {
32922
32923 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32924 Lisp_Object gstring;
32925 struct font_metrics metrics;
32926
32927 it->nglyphs = 1;
32928
32929 gstring = composition_gstring_from_id (it->cmp_it.id);
32930 it->pixel_width
32931 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32932 &metrics);
32933 if (it->pixel_width == 0)
32934 {
32935 it->glyph_not_available_p = true;
32936 it->phys_ascent = it->ascent;
32937 it->phys_descent = it->descent;
32938 it->pixel_width = face->font->space_width;
32939 }
32940 else
32941 {
32942 if (it->glyph_row
32943 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32944 it->glyph_row->contains_overlapping_glyphs_p = true;
32945 it->ascent = it->phys_ascent = metrics.ascent;
32946 it->descent = it->phys_descent = metrics.descent;
32947 }
32948 IT_APPLY_FACE_BOX(it, face);
32949
32950
32951
32952 if (face->overline_p)
32953 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32954 take_vertical_position_into_account (it);
32955 if (it->ascent < 0)
32956 it->ascent = 0;
32957 if (it->descent < 0)
32958 it->descent = 0;
32959
32960 if (it->glyph_row)
32961 append_composite_glyph (it);
32962 }
32963 else if (it->what == IT_GLYPHLESS)
32964 produce_glyphless_glyph (it, false, Qnil);
32965 else if (it->what == IT_IMAGE)
32966 produce_image_glyph (it);
32967 else if (it->what == IT_STRETCH)
32968 produce_stretch_glyph (it);
32969 else if (it->what == IT_XWIDGET)
32970 produce_xwidget_glyph (it);
32971
32972 done:
32973
32974
32975 eassert (it->ascent >= 0 && it->descent >= 0);
32976 if (it->area == TEXT_AREA)
32977 it->current_x += it->pixel_width;
32978
32979 if (extra_line_spacing > 0)
32980 {
32981 it->descent += extra_line_spacing;
32982 if (extra_line_spacing > it->max_extra_line_spacing)
32983 it->max_extra_line_spacing = extra_line_spacing;
32984 }
32985
32986 it->max_ascent = max (it->max_ascent, it->ascent);
32987 it->max_descent = max (it->max_descent, it->descent);
32988 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32989 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32990 }
32991
32992
32993
32994
32995
32996
32997 void
32998 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32999 struct glyph *start, enum glyph_row_area updated_area, int len)
33000 {
33001 int x, hpos, chpos = w->phys_cursor.hpos;
33002
33003 eassert (updated_row);
33004
33005
33006
33007 if (!updated_row->reversed_p && chpos < 0)
33008 chpos = 0;
33009 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
33010 chpos = updated_row->used[TEXT_AREA] - 1;
33011
33012 block_input ();
33013
33014
33015
33016 hpos = start - updated_row->glyphs[updated_area];
33017 x = draw_glyphs (w, w->output_cursor.x,
33018 updated_row, updated_area,
33019 hpos, hpos + len,
33020 DRAW_NORMAL_TEXT, 0);
33021
33022
33023 if (updated_area == TEXT_AREA
33024 && w->phys_cursor_on_p
33025 && w->phys_cursor.vpos == w->output_cursor.vpos
33026 && chpos >= hpos
33027 && chpos < hpos + len)
33028 w->phys_cursor_on_p = false;
33029
33030 unblock_input ();
33031
33032
33033 w->output_cursor.hpos += len;
33034 w->output_cursor.x = x;
33035 }
33036
33037
33038
33039
33040
33041 void
33042 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
33043 struct glyph *start, enum glyph_row_area updated_area, int len)
33044 {
33045 struct frame *f;
33046 int line_height, shift_by_width, shifted_region_width;
33047 struct glyph_row *row;
33048 struct glyph *glyph;
33049 int frame_x, frame_y;
33050 ptrdiff_t hpos;
33051
33052 eassert (updated_row);
33053 block_input ();
33054 f = XFRAME (WINDOW_FRAME (w));
33055
33056
33057 row = updated_row;
33058 line_height = row->height;
33059
33060
33061 shift_by_width = 0;
33062 for (glyph = start; glyph < start + len; ++glyph)
33063 shift_by_width += glyph->pixel_width;
33064
33065
33066 shifted_region_width = (window_box_width (w, updated_area)
33067 - w->output_cursor.x
33068 - shift_by_width);
33069
33070
33071 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
33072 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
33073
33074 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
33075 line_height, shift_by_width);
33076
33077
33078 hpos = start - row->glyphs[updated_area];
33079 draw_glyphs (w, w->output_cursor.x, row, updated_area,
33080 hpos, hpos + len,
33081 DRAW_NORMAL_TEXT, 0);
33082
33083
33084 w->output_cursor.hpos += len;
33085 w->output_cursor.x += shift_by_width;
33086 unblock_input ();
33087 }
33088
33089
33090
33091
33092
33093
33094
33095
33096
33097
33098 void
33099 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
33100 enum glyph_row_area updated_area, int to_x)
33101 {
33102 struct frame *f;
33103 int max_x, min_y, max_y;
33104 int from_x, from_y, to_y;
33105 struct face *face;
33106
33107 eassert (updated_row);
33108 f = XFRAME (w->frame);
33109 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
33110
33111 if (updated_row->full_width_p)
33112 max_x = (WINDOW_PIXEL_WIDTH (w)
33113 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
33114 else
33115 max_x = window_box_width (w, updated_area);
33116 max_y = window_text_bottom_y (w);
33117
33118
33119
33120 if (to_x == 0)
33121 return;
33122 else if (to_x < 0)
33123 to_x = max_x;
33124 else
33125 to_x = min (to_x, max_x);
33126
33127 to_y = min (max_y, w->output_cursor.y + updated_row->height);
33128
33129
33130 if (!updated_row->full_width_p)
33131 notice_overwritten_cursor (w, updated_area,
33132 w->output_cursor.x, -1,
33133 updated_row->y,
33134 MATRIX_ROW_BOTTOM_Y (updated_row));
33135
33136 from_x = w->output_cursor.x;
33137
33138
33139 if (updated_row->full_width_p)
33140 {
33141 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
33142 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
33143 }
33144 else
33145 {
33146 int area_left = window_box_left (w, updated_area);
33147 from_x += area_left;
33148 to_x += area_left;
33149 }
33150
33151 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
33152 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
33153 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
33154
33155
33156 if (to_x > from_x && to_y > from_y)
33157 {
33158 block_input ();
33159 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
33160 to_x - from_x, to_y - from_y);
33161
33162 if (face && !updated_row->stipple_p)
33163 updated_row->stipple_p = face->stipple;
33164 unblock_input ();
33165 }
33166 }
33167
33168 #endif
33169
33170
33171
33172
33173
33174
33175
33176
33177
33178
33179
33180 static enum text_cursor_kinds
33181 get_specified_cursor_type (Lisp_Object arg, int *width)
33182 {
33183 enum text_cursor_kinds type;
33184
33185 if (NILP (arg))
33186 return NO_CURSOR;
33187
33188 if (EQ (arg, Qbox))
33189 return FILLED_BOX_CURSOR;
33190
33191 if (EQ (arg, Qhollow))
33192 return HOLLOW_BOX_CURSOR;
33193
33194 if (EQ (arg, Qbar))
33195 {
33196 *width = 2;
33197 return BAR_CURSOR;
33198 }
33199
33200 if (EQ (arg, Qhbar))
33201 {
33202 *width = 2;
33203 return HBAR_CURSOR;
33204 }
33205
33206 if (CONSP (arg)
33207 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
33208 {
33209 *width = XFIXNUM (XCDR (arg));
33210
33211 if (EQ (XCAR (arg), Qbox))
33212 return FILLED_BOX_CURSOR;
33213 else if (EQ (XCAR (arg), Qbar))
33214 return BAR_CURSOR;
33215 else if (EQ (XCAR (arg), Qhbar))
33216 return HBAR_CURSOR;
33217 }
33218
33219
33220
33221
33222 type = HOLLOW_BOX_CURSOR;
33223
33224 return type;
33225 }
33226
33227
33228 void
33229 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
33230 {
33231 int width = 1;
33232 Lisp_Object tem;
33233
33234 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
33235 FRAME_CURSOR_WIDTH (f) = width;
33236
33237
33238
33239 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
33240 if (!NILP (tem))
33241 {
33242 FRAME_BLINK_OFF_CURSOR (f)
33243 = get_specified_cursor_type (XCDR (tem), &width);
33244 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
33245 }
33246 else
33247 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
33248
33249
33250 f->cursor_type_changed = true;
33251 }
33252
33253
33254 #ifdef HAVE_WINDOW_SYSTEM
33255
33256
33257
33258
33259
33260
33261
33262
33263
33264
33265
33266
33267 static enum text_cursor_kinds
33268 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
33269 bool *active_cursor)
33270 {
33271 struct frame *f = XFRAME (w->frame);
33272 struct buffer *b = XBUFFER (w->contents);
33273 int cursor_type = DEFAULT_CURSOR;
33274 Lisp_Object alt_cursor;
33275 bool non_selected = false;
33276
33277 *active_cursor = true;
33278
33279
33280 if (cursor_in_echo_area
33281 && FRAME_HAS_MINIBUF_P (f)
33282 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
33283 {
33284 if (w == XWINDOW (echo_area_window))
33285 {
33286 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
33287 {
33288 *width = FRAME_CURSOR_WIDTH (f);
33289 return FRAME_DESIRED_CURSOR (f);
33290 }
33291 else
33292 return get_specified_cursor_type (BVAR (b, cursor_type), width);
33293 }
33294
33295 *active_cursor = false;
33296 non_selected = true;
33297 }
33298
33299
33300 else if (w != XWINDOW (f->selected_window)
33301 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
33302 {
33303 *active_cursor = false;
33304
33305 if (MINI_WINDOW_P (w) &&
33306 (minibuf_level == 0
33307 || is_minibuffer (0, w->contents)))
33308 return NO_CURSOR;
33309
33310 non_selected = true;
33311 }
33312
33313
33314 if (NILP (BVAR (b, cursor_type)))
33315 return NO_CURSOR;
33316
33317
33318 if (EQ (BVAR (b, cursor_type), Qt))
33319 {
33320 cursor_type = FRAME_DESIRED_CURSOR (f);
33321 *width = FRAME_CURSOR_WIDTH (f);
33322 }
33323 else
33324 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
33325
33326
33327
33328 if (non_selected)
33329 {
33330 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
33331 if (!EQ (Qt, alt_cursor))
33332 return get_specified_cursor_type (alt_cursor, width);
33333
33334 if (cursor_type == FILLED_BOX_CURSOR)
33335 cursor_type = HOLLOW_BOX_CURSOR;
33336 else if (cursor_type == BAR_CURSOR && *width > 1)
33337 --*width;
33338 return cursor_type;
33339 }
33340
33341
33342 if (!w->cursor_off_p)
33343 {
33344 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
33345 return NO_CURSOR;
33346 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
33347 {
33348 if (cursor_type == FILLED_BOX_CURSOR)
33349 {
33350
33351
33352
33353
33354 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
33355 if (img != NULL && IMAGEP (img->spec))
33356 {
33357
33358
33359
33360
33361
33362
33363 if (!img->mask
33364 || (CONSP (BVAR (b, cursor_type))
33365 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33366 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33367 cursor_type = HOLLOW_BOX_CURSOR;
33368 }
33369 }
33370 else if (cursor_type != NO_CURSOR)
33371 {
33372
33373
33374
33375 cursor_type = HOLLOW_BOX_CURSOR;
33376 }
33377 }
33378 return cursor_type;
33379 }
33380
33381
33382
33383
33384 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33385 return get_specified_cursor_type (XCDR (alt_cursor), width);
33386
33387
33388 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33389 {
33390 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33391 return FRAME_BLINK_OFF_CURSOR (f);
33392 }
33393
33394 #if false
33395
33396
33397
33398
33399
33400
33401
33402
33403
33404
33405 if (cursor_type == FILLED_BOX_CURSOR)
33406 return HOLLOW_BOX_CURSOR;
33407
33408 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33409 {
33410 *width = 1;
33411 return cursor_type;
33412 }
33413 #endif
33414
33415 return NO_CURSOR;
33416 }
33417
33418
33419
33420
33421
33422
33423
33424
33425
33426 static void
33427 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33428 int x0, int x1, int y0, int y1)
33429 {
33430 int cx0, cx1, cy0, cy1;
33431 struct glyph_row *row;
33432
33433 if (!w->phys_cursor_on_p)
33434 return;
33435 if (area != TEXT_AREA)
33436 return;
33437
33438 if (w->phys_cursor.vpos < 0
33439 || w->phys_cursor.vpos >= w->current_matrix->nrows
33440 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33441 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33442 return;
33443
33444 if (row->cursor_in_fringe_p)
33445 {
33446 row->cursor_in_fringe_p = false;
33447 draw_fringe_bitmap (w, row, row->reversed_p);
33448 w->phys_cursor_on_p = false;
33449 return;
33450 }
33451
33452 cx0 = w->phys_cursor.x;
33453 cx1 = cx0 + w->phys_cursor_width;
33454 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33455 return;
33456
33457
33458
33459
33460
33461
33462
33463
33464
33465
33466
33467
33468
33469
33470
33471
33472
33473 cy0 = w->phys_cursor.y;
33474 cy1 = cy0 + w->phys_cursor_height;
33475 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33476 return;
33477
33478 w->phys_cursor_on_p = false;
33479 }
33480
33481 #endif
33482
33483
33484
33485
33486
33487
33488 #ifdef HAVE_WINDOW_SYSTEM
33489
33490
33491
33492
33493
33494 void
33495 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33496 enum glyph_row_area area, int overlaps)
33497 {
33498 int i, x;
33499
33500 block_input ();
33501
33502 x = 0;
33503 for (i = 0; i < row->used[area];)
33504 {
33505 if (row->glyphs[area][i].overlaps_vertically_p)
33506 {
33507 int start = i, start_x = x;
33508
33509 do
33510 {
33511 x += row->glyphs[area][i].pixel_width;
33512 ++i;
33513 }
33514 while (i < row->used[area]
33515 && row->glyphs[area][i].overlaps_vertically_p);
33516
33517 draw_glyphs (w, start_x, row, area,
33518 start, i,
33519 DRAW_NORMAL_TEXT, overlaps);
33520 }
33521 else
33522 {
33523 x += row->glyphs[area][i].pixel_width;
33524 ++i;
33525 }
33526 }
33527
33528 unblock_input ();
33529 }
33530
33531
33532
33533
33534
33535
33536 void
33537 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33538 enum draw_glyphs_face hl)
33539 {
33540
33541
33542
33543 if ((row->reversed_p
33544 ? (w->phys_cursor.hpos >= 0)
33545 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33546 {
33547 bool on_p = w->phys_cursor_on_p;
33548 int x1;
33549 int hpos = w->phys_cursor.hpos;
33550
33551
33552
33553
33554 if (!row->reversed_p && hpos < 0)
33555 hpos = 0;
33556 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33557 hpos = row->used[TEXT_AREA] - 1;
33558
33559 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33560 hl, 0);
33561 w->phys_cursor_on_p = on_p;
33562
33563 if (hl == DRAW_CURSOR)
33564 w->phys_cursor_width = x1 - w->phys_cursor.x;
33565
33566
33567
33568 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33569 {
33570 w->phys_cursor_width = x1 - w->phys_cursor.x;
33571
33572 if (row > w->current_matrix->rows
33573 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33574 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33575 OVERLAPS_ERASED_CURSOR);
33576
33577 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33578 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33579 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33580 OVERLAPS_ERASED_CURSOR);
33581 }
33582 }
33583 }
33584
33585
33586
33587
33588 void
33589 erase_phys_cursor (struct window *w)
33590 {
33591 struct frame *f = XFRAME (w->frame);
33592 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33593 int hpos = w->phys_cursor.hpos;
33594 int vpos = w->phys_cursor.vpos;
33595 bool mouse_face_here_p = false;
33596 struct glyph_matrix *active_glyphs = w->current_matrix;
33597 struct glyph_row *cursor_row;
33598 struct glyph *cursor_glyph;
33599 enum draw_glyphs_face hl;
33600
33601
33602
33603 if (w->phys_cursor_type == NO_CURSOR)
33604 goto mark_cursor_off;
33605
33606
33607
33608 if (vpos >= active_glyphs->nrows)
33609 goto mark_cursor_off;
33610
33611
33612
33613 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33614 if (!cursor_row->enabled_p)
33615 goto mark_cursor_off;
33616
33617
33618
33619 cursor_row->visible_height = min (cursor_row->visible_height,
33620 window_text_bottom_y (w) - cursor_row->y);
33621
33622
33623
33624
33625 if (cursor_row->visible_height <= 0)
33626 goto mark_cursor_off;
33627
33628
33629 if (cursor_row->cursor_in_fringe_p)
33630 {
33631 cursor_row->cursor_in_fringe_p = false;
33632 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33633 goto mark_cursor_off;
33634 }
33635
33636
33637
33638
33639
33640
33641 if ((cursor_row->reversed_p
33642 ? (w->phys_cursor.hpos < 0)
33643 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33644 goto mark_cursor_off;
33645
33646
33647
33648
33649 if (!cursor_row->reversed_p && hpos < 0)
33650 hpos = 0;
33651 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33652 hpos = cursor_row->used[TEXT_AREA] - 1;
33653
33654
33655
33656 if (! NILP (hlinfo->mouse_face_window)
33657 && coords_in_mouse_face_p (w, hpos, vpos)
33658
33659
33660
33661 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33662 mouse_face_here_p = true;
33663
33664 #ifdef HAVE_WINDOW_SYSTEM
33665
33666
33667
33668
33669 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33670 {
33671 w->phys_cursor_on_p = false;
33672 w->phys_cursor_type = NO_CURSOR;
33673 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33674 return;
33675 }
33676 #endif
33677
33678
33679 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33680 {
33681 int x, y;
33682 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33683 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33684 int width;
33685
33686 cursor_glyph = get_phys_cursor_glyph (w);
33687 if (cursor_glyph == NULL)
33688 goto mark_cursor_off;
33689
33690 width = cursor_glyph->pixel_width;
33691 x = w->phys_cursor.x;
33692 if (x < 0)
33693 {
33694 width += x;
33695 x = 0;
33696 }
33697 width = min (width, window_box_width (w, TEXT_AREA) - x);
33698 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33699 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33700
33701 if (width > 0)
33702 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33703 }
33704
33705
33706 if (mouse_face_here_p)
33707 hl = DRAW_MOUSE_FACE;
33708 else
33709 hl = DRAW_NORMAL_TEXT;
33710 draw_phys_cursor_glyph (w, cursor_row, hl);
33711
33712 mark_cursor_off:
33713 w->phys_cursor_on_p = false;
33714 w->phys_cursor_type = NO_CURSOR;
33715 }
33716
33717
33718
33719
33720
33721
33722 void
33723 display_and_set_cursor (struct window *w, bool on,
33724 int hpos, int vpos, int x, int y)
33725 {
33726 struct frame *f = XFRAME (w->frame);
33727 int new_cursor_type;
33728 int new_cursor_width UNINIT;
33729 bool active_cursor;
33730 struct glyph_row *glyph_row;
33731 struct glyph *glyph;
33732
33733
33734
33735
33736
33737 if (! FRAME_REDISPLAY_P (f)
33738 || vpos >= w->current_matrix->nrows
33739 || hpos >= w->current_matrix->matrix_w)
33740 return;
33741
33742
33743 if (!on && !w->phys_cursor_on_p)
33744 return;
33745
33746 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33747
33748
33749 if (!glyph_row->enabled_p)
33750 {
33751 w->phys_cursor_on_p = false;
33752 return;
33753 }
33754
33755
33756
33757
33758
33759
33760
33761
33762
33763 if (FRAME_GARBAGED_P (f))
33764 {
33765 if (on)
33766 {
33767 w->phys_cursor.x = x;
33768 w->phys_cursor.y = glyph_row->y;
33769 w->phys_cursor.hpos = hpos;
33770 w->phys_cursor.vpos = vpos;
33771 }
33772 return;
33773 }
33774
33775 glyph = NULL;
33776 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33777 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33778
33779 eassert (input_blocked_p ());
33780
33781
33782 new_cursor_type = get_window_cursor_type (w, glyph,
33783 &new_cursor_width, &active_cursor);
33784
33785
33786
33787
33788 if (w->phys_cursor_on_p
33789 && (!on
33790 || w->phys_cursor.x != x
33791 || w->phys_cursor.y != y
33792
33793
33794
33795 || hpos < 0
33796 || new_cursor_type != w->phys_cursor_type
33797 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33798 && new_cursor_width != w->phys_cursor_width)))
33799 erase_phys_cursor (w);
33800
33801
33802
33803
33804
33805
33806
33807 if (on)
33808 {
33809 w->phys_cursor_ascent = glyph_row->ascent;
33810 w->phys_cursor_height = glyph_row->height;
33811
33812
33813
33814 w->phys_cursor.x = x;
33815 w->phys_cursor.y = glyph_row->y;
33816 w->phys_cursor.hpos = hpos;
33817 w->phys_cursor.vpos = vpos;
33818 }
33819
33820
33821
33822
33823
33824
33825 if (MATRIX_ROW_BOTTOM_Y (glyph_row) > 0)
33826 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33827 new_cursor_type, new_cursor_width,
33828 on, active_cursor);
33829 }
33830
33831
33832
33833
33834
33835 static void
33836 update_window_cursor (struct window *w, bool on)
33837 {
33838
33839
33840 if (w->current_matrix)
33841 {
33842 int hpos = w->phys_cursor.hpos;
33843 int vpos = w->phys_cursor.vpos;
33844 struct glyph_row *row;
33845
33846 if (vpos >= w->current_matrix->nrows
33847 || hpos >= w->current_matrix->matrix_w)
33848 return;
33849
33850 row = MATRIX_ROW (w->current_matrix, vpos);
33851
33852
33853
33854
33855 if (!row->reversed_p && hpos < 0)
33856 hpos = 0;
33857 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33858 hpos = row->used[TEXT_AREA] - 1;
33859
33860 block_input ();
33861 display_and_set_cursor (w, on, hpos, vpos,
33862 w->phys_cursor.x, w->phys_cursor.y);
33863 unblock_input ();
33864 }
33865 }
33866
33867
33868
33869
33870
33871 static void
33872 update_cursor_in_window_tree (struct window *w, bool on_p)
33873 {
33874 while (w)
33875 {
33876 if (WINDOWP (w->contents))
33877 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33878 else
33879 update_window_cursor (w, on_p);
33880
33881 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33882 }
33883 }
33884
33885
33886
33887
33888
33889
33890 void
33891 gui_update_cursor (struct frame *f, bool on_p)
33892 {
33893 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33894 }
33895
33896
33897
33898
33899
33900
33901
33902 void
33903 gui_clear_cursor (struct window *w)
33904 {
33905 if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33906 update_window_cursor (w, false);
33907 }
33908
33909 #endif
33910
33911
33912
33913 static void
33914 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33915 int start_hpos, int end_hpos,
33916 enum draw_glyphs_face draw)
33917 {
33918 #ifdef HAVE_WINDOW_SYSTEM
33919 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33920 {
33921 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33922 return;
33923 }
33924 #endif
33925
33926 #ifndef HAVE_ANDROID
33927 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33928 #endif
33929 }
33930
33931
33932
33933 static void
33934 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33935 {
33936
33937
33938 if (!WINDOWP (hlinfo->mouse_face_window))
33939 return;
33940
33941 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33942 struct frame *f = XFRAME (WINDOW_FRAME (w));
33943
33944
33945 if (f != hlinfo->mouse_face_mouse_frame)
33946 return;
33947
33948 if (
33949
33950 w->current_matrix != NULL
33951
33952 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33953
33954
33955 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33956 {
33957 bool phys_cursor_on_p = w->phys_cursor_on_p;
33958 #ifdef HAVE_WINDOW_SYSTEM
33959 int mouse_off = 0;
33960 #endif
33961 struct glyph_row *row, *first, *last;
33962
33963 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33964 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33965
33966 for (row = first; row <= last && row->enabled_p; ++row)
33967 {
33968 int start_hpos, end_hpos, start_x;
33969
33970
33971 if (row == first)
33972 {
33973
33974
33975
33976
33977 if (!row->reversed_p)
33978 {
33979 start_hpos = hlinfo->mouse_face_beg_col;
33980 start_x = hlinfo->mouse_face_beg_x;
33981 }
33982 else if (row == last)
33983 {
33984 start_hpos = hlinfo->mouse_face_end_col;
33985 start_x = hlinfo->mouse_face_end_x;
33986 }
33987 else
33988 {
33989 start_hpos = 0;
33990 start_x = 0;
33991 }
33992 }
33993 else if (row->reversed_p && row == last)
33994 {
33995 start_hpos = hlinfo->mouse_face_end_col;
33996 start_x = hlinfo->mouse_face_end_x;
33997 }
33998 else
33999 {
34000 start_hpos = 0;
34001 start_x = 0;
34002 }
34003
34004 if (row == last)
34005 {
34006 if (!row->reversed_p)
34007 end_hpos = hlinfo->mouse_face_end_col;
34008 else if (row == first)
34009 end_hpos = hlinfo->mouse_face_beg_col;
34010 else
34011 {
34012 end_hpos = row->used[TEXT_AREA];
34013 if (draw == DRAW_NORMAL_TEXT)
34014 row->fill_line_p = true;
34015 }
34016 }
34017 else if (row->reversed_p && row == first)
34018 end_hpos = hlinfo->mouse_face_beg_col;
34019 else
34020 {
34021 end_hpos = row->used[TEXT_AREA];
34022 if (draw == DRAW_NORMAL_TEXT)
34023 row->fill_line_p = true;
34024 }
34025
34026 if (end_hpos > start_hpos)
34027 {
34028 draw_row_with_mouse_face (w, start_x, row,
34029 start_hpos, end_hpos, draw);
34030
34031 row->mouse_face_p
34032 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
34033 }
34034 #ifdef HAVE_WINDOW_SYSTEM
34035
34036 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
34037
34038
34039 && !w->pseudo_window_p
34040 && draw == DRAW_MOUSE_FACE)
34041 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
34042 #endif
34043 }
34044
34045
34046
34047 if (FRAME_WINDOW_P (f)
34048 && phys_cursor_on_p && !w->phys_cursor_on_p)
34049 {
34050 #ifdef HAVE_WINDOW_SYSTEM
34051 int hpos = w->phys_cursor.hpos;
34052 int old_phys_cursor_x = w->phys_cursor.x;
34053
34054
34055
34056
34057 if (!row->reversed_p && hpos < 0)
34058 hpos = 0;
34059 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
34060 hpos = row->used[TEXT_AREA] - 1;
34061
34062 block_input ();
34063 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
34064 w->phys_cursor.x + mouse_off,
34065 w->phys_cursor.y);
34066
34067
34068 w->phys_cursor.x = old_phys_cursor_x;
34069 unblock_input ();
34070 #endif
34071 }
34072 }
34073
34074 #ifdef HAVE_WINDOW_SYSTEM
34075
34076 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
34077 {
34078 if (draw == DRAW_NORMAL_TEXT
34079 #ifndef HAVE_EXT_TOOL_BAR
34080 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
34081 #endif
34082 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
34083 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
34084 else
34085 if (draw == DRAW_MOUSE_FACE)
34086 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
34087 else
34088 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
34089 }
34090 #endif
34091 }
34092
34093
34094
34095
34096
34097
34098 bool
34099 clear_mouse_face (Mouse_HLInfo *hlinfo)
34100 {
34101 bool cleared
34102 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
34103 if (cleared)
34104 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
34105 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
34106 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
34107 hlinfo->mouse_face_window = Qnil;
34108 hlinfo->mouse_face_overlay = Qnil;
34109 return cleared;
34110 }
34111
34112
34113
34114 static bool
34115 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
34116 {
34117 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
34118
34119
34120 if (!(WINDOWP (hlinfo->mouse_face_window)
34121 && XWINDOW (hlinfo->mouse_face_window) == w))
34122 return false;
34123 if (vpos < hlinfo->mouse_face_beg_row
34124 || vpos > hlinfo->mouse_face_end_row)
34125 return false;
34126 if (vpos > hlinfo->mouse_face_beg_row
34127 && vpos < hlinfo->mouse_face_end_row)
34128 return true;
34129
34130 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
34131 {
34132 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34133 {
34134 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
34135 return true;
34136 }
34137 else if ((vpos == hlinfo->mouse_face_beg_row
34138 && hpos >= hlinfo->mouse_face_beg_col)
34139 || (vpos == hlinfo->mouse_face_end_row
34140 && hpos < hlinfo->mouse_face_end_col))
34141 return true;
34142 }
34143 else
34144 {
34145 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34146 {
34147 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
34148 return true;
34149 }
34150 else if ((vpos == hlinfo->mouse_face_beg_row
34151 && hpos <= hlinfo->mouse_face_beg_col)
34152 || (vpos == hlinfo->mouse_face_end_row
34153 && hpos > hlinfo->mouse_face_end_col))
34154 return true;
34155 }
34156 return false;
34157 }
34158
34159
34160
34161
34162
34163 bool
34164 cursor_in_mouse_face_p (struct window *w)
34165 {
34166 int vpos = w->phys_cursor.vpos;
34167
34168
34169
34170 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
34171 return false;
34172
34173 int hpos = w->phys_cursor.hpos;
34174 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
34175
34176
34177
34178
34179 if (!row->reversed_p && hpos < 0)
34180 hpos = 0;
34181 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
34182 hpos = row->used[TEXT_AREA] - 1;
34183
34184 return coords_in_mouse_face_p (w, hpos, vpos);
34185 }
34186
34187
34188
34189
34190
34191
34192
34193
34194
34195 static void
34196 rows_from_pos_range (struct window *w,
34197 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
34198 Lisp_Object disp_string,
34199 struct glyph_row **start, struct glyph_row **end)
34200 {
34201 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34202 int last_y = window_text_bottom_y (w);
34203 struct glyph_row *row;
34204
34205 *start = NULL;
34206 *end = NULL;
34207
34208 while (!first->enabled_p
34209 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
34210 first++;
34211
34212
34213 for (row = first;
34214 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
34215 row++)
34216 {
34217
34218
34219
34220 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
34221 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
34222
34223
34224
34225
34226 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
34227 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
34228 && !row->ends_at_zv_p
34229 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
34230 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
34231 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
34232 && !row->ends_at_zv_p
34233 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
34234 {
34235
34236
34237
34238
34239
34240
34241
34242
34243
34244
34245 struct glyph *g = row->glyphs[TEXT_AREA];
34246 struct glyph *e = g + row->used[TEXT_AREA];
34247
34248 while (g < e)
34249 {
34250 if (((BUFFERP (g->object) || NILP (g->object))
34251 && start_charpos <= g->charpos && g->charpos < end_charpos)
34252
34253
34254 || EQ (g->object, disp_string))
34255 *start = row;
34256 g++;
34257 }
34258 if (*start)
34259 break;
34260 }
34261 }
34262
34263
34264 if (!*start
34265
34266
34267 && !(row->enabled_p
34268 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
34269 row = first;
34270 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
34271 {
34272 struct glyph_row *next = row + 1;
34273 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
34274
34275 if (!next->enabled_p
34276 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
34277
34278
34279
34280 || (start_charpos < next_start
34281 && end_charpos < next_start)
34282 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
34283 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
34284 && !next->ends_at_zv_p
34285 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
34286 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
34287 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
34288 && !next->ends_at_zv_p
34289 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
34290 {
34291 *end = row;
34292 break;
34293 }
34294 else
34295 {
34296
34297
34298
34299 struct glyph *g = next->glyphs[TEXT_AREA];
34300 struct glyph *s = g;
34301 struct glyph *e = g + next->used[TEXT_AREA];
34302
34303 while (g < e)
34304 {
34305 if (((BUFFERP (g->object) || NILP (g->object))
34306 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
34307
34308
34309
34310
34311
34312 || (((!next->reversed_p && g == s)
34313 || (next->reversed_p && g == e - 1))
34314 && (g->charpos == end_charpos
34315
34316
34317 || (g->charpos == -1
34318 && !row->ends_at_zv_p
34319 && next_start == end_charpos)))))
34320
34321
34322 || EQ (g->object, disp_string))
34323 break;
34324 g++;
34325 }
34326 if (g == e)
34327 {
34328 *end = row;
34329 break;
34330 }
34331
34332
34333 else if (next->ends_at_zv_p)
34334 {
34335 *end = next;
34336 break;
34337 }
34338 }
34339 }
34340 }
34341
34342
34343
34344
34345
34346
34347
34348
34349
34350
34351 static void
34352 mouse_face_from_buffer_pos (Lisp_Object window,
34353 Mouse_HLInfo *hlinfo,
34354 ptrdiff_t mouse_charpos,
34355 ptrdiff_t start_charpos,
34356 ptrdiff_t end_charpos,
34357 Lisp_Object before_string,
34358 Lisp_Object after_string,
34359 Lisp_Object disp_string)
34360 {
34361 struct window *w = XWINDOW (window);
34362 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34363 struct glyph_row *r1, *r2;
34364 struct glyph *glyph, *end;
34365 ptrdiff_t ignore, pos;
34366 int x;
34367
34368 eassert (NILP (disp_string) || STRINGP (disp_string));
34369 eassert (NILP (before_string) || STRINGP (before_string));
34370 eassert (NILP (after_string) || STRINGP (after_string));
34371
34372
34373 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
34374 if (r1 == NULL)
34375 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34376
34377
34378 if (!NILP (before_string) || !NILP (disp_string))
34379 {
34380 struct glyph_row *prev;
34381 while ((prev = r1 - 1, prev >= first)
34382 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34383 && prev->used[TEXT_AREA] > 0)
34384 {
34385 struct glyph *beg = prev->glyphs[TEXT_AREA];
34386 glyph = beg + prev->used[TEXT_AREA];
34387 while (--glyph >= beg && NILP (glyph->object));
34388 if (glyph < beg
34389 || !(EQ (glyph->object, before_string)
34390 || EQ (glyph->object, disp_string)))
34391 break;
34392 r1 = prev;
34393 }
34394 }
34395 if (r2 == NULL)
34396 {
34397 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34398 hlinfo->mouse_face_past_end = true;
34399 }
34400 else if (!NILP (after_string))
34401 {
34402
34403 struct glyph_row *next;
34404 struct glyph_row *last
34405 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34406
34407 for (next = r2 + 1;
34408 next <= last
34409 && next->used[TEXT_AREA] > 0
34410 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34411 ++next)
34412 r2 = next;
34413 }
34414
34415
34416
34417
34418
34419 if (r1->y > r2->y)
34420 {
34421 struct glyph_row *tem = r2;
34422
34423 r2 = r1;
34424 r1 = tem;
34425 }
34426
34427 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34428 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34429
34430
34431
34432
34433
34434
34435
34436
34437
34438
34439
34440 if (!r1->reversed_p)
34441 {
34442
34443
34444 glyph = r1->glyphs[TEXT_AREA];
34445 end = glyph + r1->used[TEXT_AREA];
34446 x = r1->x;
34447
34448
34449 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34450 for (; glyph < end
34451 && NILP (glyph->object)
34452 && glyph->charpos < 0;
34453 ++glyph)
34454 x += glyph->pixel_width;
34455
34456
34457
34458
34459 for (; glyph < end
34460 && !NILP (glyph->object)
34461 && !EQ (glyph->object, disp_string)
34462 && !(BUFFERP (glyph->object)
34463 && (glyph->charpos >= start_charpos
34464 && glyph->charpos < end_charpos));
34465 ++glyph)
34466 {
34467
34468
34469
34470 if (EQ (glyph->object, before_string))
34471 {
34472 pos = string_buffer_position (before_string,
34473 start_charpos);
34474
34475
34476 if (!pos || (pos >= start_charpos && pos < end_charpos))
34477 break;
34478 }
34479 else if (EQ (glyph->object, after_string))
34480 {
34481 pos = string_buffer_position (after_string, end_charpos);
34482 if (!pos || (pos >= start_charpos && pos < end_charpos))
34483 break;
34484 }
34485 x += glyph->pixel_width;
34486 }
34487 hlinfo->mouse_face_beg_x = x;
34488 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34489 }
34490 else
34491 {
34492
34493
34494 struct glyph *g;
34495
34496 end = r1->glyphs[TEXT_AREA] - 1;
34497 glyph = end + r1->used[TEXT_AREA];
34498
34499
34500 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34501 for (; glyph > end
34502 && NILP (glyph->object)
34503 && glyph->charpos < 0;
34504 --glyph)
34505 ;
34506
34507
34508
34509
34510 for (; glyph > end
34511 && !NILP (glyph->object)
34512 && !EQ (glyph->object, disp_string)
34513 && !(BUFFERP (glyph->object)
34514 && (glyph->charpos >= start_charpos
34515 && glyph->charpos < end_charpos));
34516 --glyph)
34517 {
34518
34519
34520
34521 if (EQ (glyph->object, before_string))
34522 {
34523 pos = string_buffer_position (before_string, start_charpos);
34524
34525
34526 if (!pos || (pos >= start_charpos && pos < end_charpos))
34527 break;
34528 }
34529 else if (EQ (glyph->object, after_string))
34530 {
34531 pos = string_buffer_position (after_string, end_charpos);
34532 if (!pos || (pos >= start_charpos && pos < end_charpos))
34533 break;
34534 }
34535 }
34536
34537 glyph++;
34538 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34539 x += g->pixel_width;
34540 hlinfo->mouse_face_beg_x = x;
34541 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34542 }
34543
34544
34545
34546
34547 if (r2 != r1)
34548 {
34549 if (!r2->reversed_p)
34550 {
34551 glyph = r2->glyphs[TEXT_AREA];
34552 end = glyph + r2->used[TEXT_AREA];
34553 x = r2->x;
34554 }
34555 else
34556 {
34557 end = r2->glyphs[TEXT_AREA] - 1;
34558 glyph = end + r2->used[TEXT_AREA];
34559 }
34560 }
34561
34562 if (!r2->reversed_p)
34563 {
34564
34565
34566
34567 while (end > glyph
34568 && NILP ((end - 1)->object))
34569 --end;
34570
34571
34572
34573
34574 for (--end;
34575 end > glyph
34576 && !NILP (end->object)
34577 && !EQ (end->object, disp_string)
34578 && !(BUFFERP (end->object)
34579 && (end->charpos >= start_charpos
34580 && end->charpos < end_charpos));
34581 --end)
34582 {
34583
34584
34585
34586 if (EQ (end->object, before_string))
34587 {
34588 pos = string_buffer_position (before_string, start_charpos);
34589 if (!pos || (pos >= start_charpos && pos < end_charpos))
34590 break;
34591 }
34592 else if (EQ (end->object, after_string))
34593 {
34594 pos = string_buffer_position (after_string, end_charpos);
34595 if (!pos || (pos >= start_charpos && pos < end_charpos))
34596 break;
34597 }
34598 }
34599
34600 for (; glyph <= end; ++glyph)
34601 x += glyph->pixel_width;
34602
34603 hlinfo->mouse_face_end_x = x;
34604 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34605 }
34606 else
34607 {
34608
34609
34610
34611 x = r2->x;
34612 end++;
34613 while (end < glyph
34614 && NILP (end->object))
34615 {
34616 x += end->pixel_width;
34617 ++end;
34618 }
34619
34620
34621
34622
34623 for ( ;
34624 end < glyph
34625 && !NILP (end->object)
34626 && !EQ (end->object, disp_string)
34627 && !(BUFFERP (end->object)
34628 && (end->charpos >= start_charpos
34629 && end->charpos < end_charpos));
34630 ++end)
34631 {
34632
34633
34634
34635 if (EQ (end->object, before_string))
34636 {
34637 pos = string_buffer_position (before_string, start_charpos);
34638 if (!pos || (pos >= start_charpos && pos < end_charpos))
34639 break;
34640 }
34641 else if (EQ (end->object, after_string))
34642 {
34643 pos = string_buffer_position (after_string, end_charpos);
34644 if (!pos || (pos >= start_charpos && pos < end_charpos))
34645 break;
34646 }
34647 x += end->pixel_width;
34648 }
34649
34650
34651
34652
34653
34654 if (end == glyph
34655 && BUFFERP (end->object)
34656 && (end->charpos < start_charpos
34657 || end->charpos >= end_charpos))
34658 {
34659 x += end->pixel_width;
34660 ++end;
34661 }
34662 hlinfo->mouse_face_end_x = x;
34663 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34664 }
34665
34666 hlinfo->mouse_face_window = window;
34667 hlinfo->mouse_face_face_id
34668 = face_at_buffer_position (w, mouse_charpos, &ignore,
34669 mouse_charpos + 1,
34670 !hlinfo->mouse_face_hidden, -1, 0);
34671 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34672 }
34673
34674
34675
34676
34677
34678 #if false
34679
34680
34681
34682
34683
34684
34685
34686
34687
34688
34689
34690
34691
34692
34693
34694
34695 static bool
34696 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34697 int *hpos, int *vpos, int *x, int *y, bool right_p)
34698 {
34699 int yb = window_text_bottom_y (w);
34700 struct glyph_row *r;
34701 struct glyph *best_glyph = NULL;
34702 struct glyph_row *best_row = NULL;
34703 int best_x = 0;
34704
34705 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34706 r->enabled_p && r->y < yb;
34707 ++r)
34708 {
34709 struct glyph *g = r->glyphs[TEXT_AREA];
34710 struct glyph *e = g + r->used[TEXT_AREA];
34711 int gx;
34712
34713 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34714 if (EQ (g->object, object))
34715 {
34716 if (g->charpos == pos)
34717 {
34718 best_glyph = g;
34719 best_x = gx;
34720 best_row = r;
34721 goto found;
34722 }
34723 else if (best_glyph == NULL
34724 || ((eabs (g->charpos - pos)
34725 < eabs (best_glyph->charpos - pos))
34726 && (right_p
34727 ? g->charpos < pos
34728 : g->charpos > pos)))
34729 {
34730 best_glyph = g;
34731 best_x = gx;
34732 best_row = r;
34733 }
34734 }
34735 }
34736
34737 found:
34738
34739 if (best_glyph)
34740 {
34741 *x = best_x;
34742 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34743
34744 if (right_p)
34745 {
34746 *x += best_glyph->pixel_width;
34747 ++*hpos;
34748 }
34749
34750 *y = best_row->y;
34751 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34752 }
34753
34754 return best_glyph != NULL;
34755 }
34756 #endif
34757
34758
34759
34760
34761
34762
34763 static void
34764 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34765 Lisp_Object object,
34766 ptrdiff_t startpos, ptrdiff_t endpos)
34767 {
34768 int yb = window_text_bottom_y (w);
34769 struct glyph_row *r;
34770 struct glyph *g, *e;
34771 int gx;
34772 bool found = false;
34773
34774
34775
34776
34777 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34778 r->enabled_p && r->y < yb;
34779 ++r)
34780 {
34781 if (!r->reversed_p)
34782 {
34783 g = r->glyphs[TEXT_AREA];
34784 e = g + r->used[TEXT_AREA];
34785 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34786 if (EQ (g->object, object)
34787 && startpos <= g->charpos && g->charpos < endpos)
34788 {
34789 hlinfo->mouse_face_beg_row
34790 = MATRIX_ROW_VPOS (r, w->current_matrix);
34791 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34792 hlinfo->mouse_face_beg_x = gx;
34793 found = true;
34794 break;
34795 }
34796 }
34797 else
34798 {
34799 struct glyph *g1;
34800
34801 e = r->glyphs[TEXT_AREA];
34802 g = e + r->used[TEXT_AREA];
34803 for ( ; g > e; --g)
34804 if (EQ ((g-1)->object, object)
34805 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34806 {
34807 hlinfo->mouse_face_beg_row
34808 = MATRIX_ROW_VPOS (r, w->current_matrix);
34809 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34810 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34811 gx += g1->pixel_width;
34812 hlinfo->mouse_face_beg_x = gx;
34813 found = true;
34814 break;
34815 }
34816 }
34817 if (found)
34818 break;
34819 }
34820
34821 if (!found)
34822 return;
34823
34824
34825
34826 for (++r; r->enabled_p && r->y < yb; ++r)
34827 {
34828 g = r->glyphs[TEXT_AREA];
34829 e = g + r->used[TEXT_AREA];
34830 found = false;
34831 for ( ; g < e; ++g)
34832 if (EQ (g->object, object)
34833 && startpos <= g->charpos && g->charpos < endpos)
34834 {
34835 found = true;
34836 break;
34837 }
34838 if (!found)
34839 break;
34840 }
34841
34842
34843 r--;
34844
34845
34846 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34847
34848
34849
34850 if (!r->reversed_p)
34851 {
34852 g = r->glyphs[TEXT_AREA];
34853 e = g + r->used[TEXT_AREA];
34854 for ( ; e > g; --e)
34855 if (EQ ((e-1)->object, object)
34856 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34857 break;
34858 hlinfo->mouse_face_end_col = e - g;
34859
34860 for (gx = r->x; g < e; ++g)
34861 gx += g->pixel_width;
34862 hlinfo->mouse_face_end_x = gx;
34863 }
34864 else
34865 {
34866 e = r->glyphs[TEXT_AREA];
34867 g = e + r->used[TEXT_AREA];
34868 for (gx = r->x ; e < g; ++e)
34869 {
34870 if (EQ (e->object, object)
34871 && startpos <= e->charpos && e->charpos < endpos)
34872 break;
34873 gx += e->pixel_width;
34874 }
34875 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34876 hlinfo->mouse_face_end_x = gx;
34877 }
34878 }
34879
34880 #ifdef HAVE_WINDOW_SYSTEM
34881
34882
34883
34884 static bool
34885 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34886 {
34887 if (!CONSP (hot_spot))
34888 return false;
34889
34890 if (EQ (XCAR (hot_spot), Qrect))
34891 {
34892
34893 Lisp_Object rect = XCDR (hot_spot);
34894 Lisp_Object tem;
34895 if (!CONSP (rect))
34896 return false;
34897 if (!CONSP (XCAR (rect)))
34898 return false;
34899 if (!CONSP (XCDR (rect)))
34900 return false;
34901 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34902 return false;
34903 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34904 return false;
34905 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34906 return false;
34907 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34908 return false;
34909 return true;
34910 }
34911 else if (EQ (XCAR (hot_spot), Qcircle))
34912 {
34913
34914 Lisp_Object circ = XCDR (hot_spot);
34915 Lisp_Object lr, lx0, ly0;
34916 if (CONSP (circ)
34917 && CONSP (XCAR (circ))
34918 && (lr = XCDR (circ), NUMBERP (lr))
34919 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34920 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34921 {
34922 double r = XFLOATINT (lr);
34923 double dx = XFIXNUM (lx0) - x;
34924 double dy = XFIXNUM (ly0) - y;
34925 return (dx * dx + dy * dy <= r * r);
34926 }
34927 }
34928 else if (EQ (XCAR (hot_spot), Qpoly))
34929 {
34930
34931 if (VECTORP (XCDR (hot_spot)))
34932 {
34933 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34934 Lisp_Object *poly = v->contents;
34935 ptrdiff_t n = v->header.size;
34936 ptrdiff_t i;
34937 bool inside = false;
34938 Lisp_Object lx, ly;
34939 int x0, y0;
34940
34941
34942 if (n < 6 || n & 1)
34943 return false;
34944
34945
34946
34947
34948
34949 if ((lx = poly[n-2], !FIXNUMP (lx))
34950 || (ly = poly[n-1], !FIXNUMP (lx)))
34951 return false;
34952 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34953 for (i = 0; i < n; i += 2)
34954 {
34955 int x1 = x0, y1 = y0;
34956 if ((lx = poly[i], !FIXNUMP (lx))
34957 || (ly = poly[i+1], !FIXNUMP (ly)))
34958 return false;
34959 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34960
34961
34962 if (x0 >= x)
34963 {
34964 if (x1 >= x)
34965 continue;
34966 }
34967 else if (x1 < x)
34968 continue;
34969 if (y > y0 && y > y1)
34970 continue;
34971 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34972 inside = !inside;
34973 }
34974 return inside;
34975 }
34976 }
34977 return false;
34978 }
34979
34980 Lisp_Object
34981 find_hot_spot (Lisp_Object map, int x, int y)
34982 {
34983 while (CONSP (map))
34984 {
34985 if (CONSP (XCAR (map))
34986 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34987 return XCAR (map);
34988 map = XCDR (map);
34989 }
34990
34991 return Qnil;
34992 }
34993
34994 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34995 3, 3, 0,
34996 doc:
34997
34998
34999
35000
35001
35002
35003
35004
35005 )
35006 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
35007 {
35008 if (NILP (map))
35009 return Qnil;
35010
35011 CHECK_FIXNUM (x);
35012 CHECK_FIXNUM (y);
35013
35014 return find_hot_spot (map,
35015 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
35016 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
35017 }
35018 #endif
35019
35020
35021
35022 static void
35023 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
35024 {
35025 #ifdef HAVE_WINDOW_SYSTEM
35026 if (!FRAME_WINDOW_P (f))
35027 return;
35028
35029
35030 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
35031 || EQ (track_mouse, Qdrag_source))
35032 return;
35033
35034 if (!NILP (pointer))
35035 {
35036 if (EQ (pointer, Qarrow))
35037 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35038 else if (EQ (pointer, Qhand))
35039 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35040 else if (EQ (pointer, Qtext))
35041 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35042 else if (EQ (pointer, intern ("hdrag")))
35043 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35044 else if (EQ (pointer, intern ("nhdrag")))
35045 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35046 # ifdef HAVE_X_WINDOWS
35047 else if (EQ (pointer, intern ("vdrag")))
35048 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
35049 # endif
35050 else if (EQ (pointer, intern ("hourglass")))
35051 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
35052 else if (EQ (pointer, Qmodeline))
35053 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
35054 else
35055 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35056 }
35057
35058 if (cursor != No_Cursor)
35059 FRAME_RIF (f)->define_frame_cursor (f, cursor);
35060 #endif
35061 }
35062
35063
35064
35065
35066
35067
35068
35069 static void
35070 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
35071 enum window_part area)
35072 {
35073 struct window *w = XWINDOW (window);
35074 struct frame *f = XFRAME (w->frame);
35075 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35076 Emacs_Cursor cursor = No_Cursor;
35077 Lisp_Object pointer = Qnil;
35078 int dx, dy, width, height;
35079 ptrdiff_t charpos;
35080 Lisp_Object string, object = Qnil;
35081 Lisp_Object pos UNINIT;
35082 Lisp_Object mouse_face;
35083 int original_x_pixel = x;
35084 struct glyph * glyph = NULL, * row_start_glyph = NULL;
35085 struct glyph_row *row UNINIT;
35086
35087 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
35088 {
35089 int x0;
35090 struct glyph *end;
35091
35092
35093
35094 string = mode_line_string (w, area, &x, &y, &charpos,
35095 &object, &dx, &dy, &width, &height);
35096
35097 row = (area == ON_MODE_LINE
35098 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
35099 : (area == ON_TAB_LINE
35100 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
35101 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
35102
35103
35104 if (row->mode_line_p && row->enabled_p)
35105 {
35106 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
35107 end = glyph + row->used[TEXT_AREA];
35108
35109 for (x0 = original_x_pixel;
35110 glyph < end && x0 >= glyph->pixel_width;
35111 ++glyph)
35112 x0 -= glyph->pixel_width;
35113
35114 if (glyph >= end)
35115 glyph = NULL;
35116 }
35117 }
35118 else
35119 {
35120 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
35121
35122
35123 string = marginal_area_string (w, area, &x, &y, &charpos,
35124 &object, &dx, &dy, &width, &height);
35125 }
35126
35127 Lisp_Object help = Qnil;
35128
35129 #ifdef HAVE_WINDOW_SYSTEM
35130 if (IMAGEP (object))
35131 {
35132 Lisp_Object image_map, hotspot;
35133 if ((image_map = plist_get (XCDR (object), QCmap),
35134 !NILP (image_map))
35135 && (hotspot = find_hot_spot (image_map, dx, dy),
35136 CONSP (hotspot))
35137 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35138 {
35139 Lisp_Object plist;
35140
35141
35142
35143
35144 hotspot = XCDR (hotspot);
35145 if (CONSP (hotspot)
35146 && (plist = XCAR (hotspot), CONSP (plist)))
35147 {
35148 pointer = plist_get (plist, Qpointer);
35149 if (NILP (pointer))
35150 pointer = Qhand;
35151 help = plist_get (plist, Qhelp_echo);
35152 if (!NILP (help))
35153 {
35154 help_echo_string = help;
35155 XSETWINDOW (help_echo_window, w);
35156 help_echo_object = w->contents;
35157 help_echo_pos = charpos;
35158 }
35159 }
35160 }
35161 if (NILP (pointer))
35162 pointer = plist_get (XCDR (object), QCpointer);
35163 }
35164 #endif
35165
35166
35167
35168
35169 if (STRINGP (string))
35170 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
35171
35172
35173
35174
35175
35176 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
35177 || area == ON_TAB_LINE)
35178 {
35179
35180
35181 if (NILP (help))
35182 {
35183 if (STRINGP (string))
35184 help = Fget_text_property (pos, Qhelp_echo, string);
35185
35186 if (!NILP (help))
35187 {
35188 help_echo_string = help;
35189 XSETWINDOW (help_echo_window, w);
35190 help_echo_object = string;
35191 help_echo_pos = charpos;
35192 }
35193 else if (area == ON_MODE_LINE
35194 && !NILP (w->mode_line_help_echo))
35195 {
35196 help_echo_string = w->mode_line_help_echo;
35197 XSETWINDOW (help_echo_window, w);
35198 help_echo_object = Qnil;
35199 help_echo_pos = -1;
35200 }
35201 }
35202
35203 #ifdef HAVE_WINDOW_SYSTEM
35204
35205 if (FRAME_WINDOW_P (f))
35206 {
35207 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
35208 || minibuf_level
35209 || NILP (Vresize_mini_windows));
35210
35211 if (STRINGP (string))
35212 {
35213 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35214
35215 if (NILP (pointer))
35216 pointer = Fget_text_property (pos, Qpointer, string);
35217
35218
35219 if (NILP (pointer)
35220 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
35221 || area == ON_TAB_LINE))
35222 {
35223 Lisp_Object map;
35224
35225 map = Fget_text_property (pos, Qlocal_map, string);
35226 if (!KEYMAPP (map))
35227 map = Fget_text_property (pos, Qkeymap, string);
35228 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
35229 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35230 }
35231 }
35232 else if (draggable && area == ON_MODE_LINE)
35233 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35234 else if ((area == ON_MODE_LINE
35235 && WINDOW_BOTTOMMOST_P (w)
35236 && !FRAME_HAS_MINIBUF_P (f)
35237 && !NILP (Fframe_parameter
35238 (w->frame, Qdrag_with_mode_line)))
35239 || (((area == ON_HEADER_LINE
35240 && !NILP (Fframe_parameter
35241 (w->frame, Qdrag_with_header_line)))
35242 || (area == ON_TAB_LINE
35243 && !NILP (Fframe_parameter
35244 (w->frame, Qdrag_with_tab_line))))
35245 && WINDOW_TOPMOST_P (w)))
35246 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35247 else
35248 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35249 }
35250 #endif
35251 }
35252
35253
35254 bool mouse_face_shown = false;
35255
35256 if (STRINGP (string))
35257 {
35258 mouse_face = Fget_text_property (pos, Qmouse_face, string);
35259 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
35260 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
35261 || (area == ON_TAB_LINE))
35262 && glyph)
35263 {
35264 Lisp_Object b, e;
35265
35266 struct glyph * tmp_glyph;
35267
35268 int gpos;
35269 int gseq_length;
35270 int total_pixel_width;
35271 ptrdiff_t begpos, endpos, ignore;
35272
35273 int vpos, hpos;
35274
35275 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
35276 Qmouse_face, string, Qnil);
35277 if (NILP (b))
35278 begpos = 0;
35279 else
35280 begpos = XFIXNUM (b);
35281
35282 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
35283 if (NILP (e))
35284 endpos = SCHARS (string);
35285 else
35286 endpos = XFIXNUM (e);
35287
35288
35289
35290
35291
35292
35293
35294
35295
35296
35297
35298 tmp_glyph = row_start_glyph;
35299 while (tmp_glyph < glyph
35300 && (!(EQ (tmp_glyph->object, glyph->object)
35301 && begpos <= tmp_glyph->charpos
35302 && tmp_glyph->charpos < endpos)))
35303 tmp_glyph++;
35304 gpos = glyph - tmp_glyph;
35305
35306
35307
35308
35309
35310
35311 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
35312 tmp_glyph > glyph
35313 && (!(EQ (tmp_glyph->object, glyph->object)
35314 && begpos <= tmp_glyph->charpos
35315 && tmp_glyph->charpos < endpos));
35316 tmp_glyph--)
35317 ;
35318 gseq_length = gpos + (tmp_glyph - glyph) + 1;
35319
35320
35321
35322 total_pixel_width = 0;
35323 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
35324 total_pixel_width += tmp_glyph->pixel_width;
35325
35326
35327
35328
35329 hpos = x - gpos;
35330 vpos = (area == ON_MODE_LINE
35331 ? (w->current_matrix)->nrows - 1
35332 : (area == ON_TAB_LINE
35333 ? 0
35334 : (w->current_matrix->tab_line_p
35335 ? 1
35336 : 0)));
35337
35338
35339
35340 if ( EQ (window, hlinfo->mouse_face_window)
35341 && (!row->reversed_p
35342 ? (hlinfo->mouse_face_beg_col <= hpos
35343 && hpos < hlinfo->mouse_face_end_col)
35344
35345 : (hlinfo->mouse_face_end_col <= hpos
35346 && hpos < hlinfo->mouse_face_beg_col))
35347 && hlinfo->mouse_face_beg_row == vpos )
35348 return;
35349
35350 if (clear_mouse_face (hlinfo))
35351 cursor = No_Cursor;
35352
35353 if (!row->reversed_p)
35354 {
35355 hlinfo->mouse_face_beg_col = hpos;
35356 hlinfo->mouse_face_beg_x = original_x_pixel
35357 - (total_pixel_width + dx);
35358 hlinfo->mouse_face_end_col = hpos + gseq_length;
35359 hlinfo->mouse_face_end_x = 0;
35360 }
35361 else
35362 {
35363
35364
35365 hlinfo->mouse_face_end_col = hpos;
35366 hlinfo->mouse_face_end_x = original_x_pixel
35367 - (total_pixel_width + dx);
35368 hlinfo->mouse_face_beg_col = hpos + gseq_length;
35369 hlinfo->mouse_face_beg_x = 0;
35370 }
35371
35372 hlinfo->mouse_face_beg_row = vpos;
35373 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
35374 hlinfo->mouse_face_past_end = false;
35375 hlinfo->mouse_face_window = window;
35376
35377 hlinfo->mouse_face_face_id =
35378 face_at_string_position (w, string, charpos, 0, &ignore,
35379 glyph->face_id, true, 0);
35380
35381 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35382 mouse_face_shown = true;
35383
35384 if (NILP (pointer))
35385 pointer = Qhand;
35386 }
35387 }
35388
35389
35390
35391 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35392 || area == ON_TAB_LINE) && !mouse_face_shown)
35393 clear_mouse_face (hlinfo);
35394
35395 define_frame_cursor1 (f, cursor, pointer);
35396 }
35397
35398
35399
35400
35401
35402
35403
35404
35405
35406
35407 void
35408 note_mouse_highlight (struct frame *f, int x, int y)
35409 {
35410 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35411 enum window_part part = ON_NOTHING;
35412 Lisp_Object window;
35413 struct window *w;
35414 Emacs_Cursor cursor = No_Cursor;
35415 Lisp_Object pointer = Qnil;
35416 struct buffer *b;
35417
35418
35419 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS) \
35420 || defined (HAVE_ANDROID)
35421 if (popup_activated ())
35422 return;
35423 #endif
35424
35425 #if defined (HAVE_HAIKU)
35426 if (popup_activated_p)
35427 return;
35428 #endif
35429
35430 if (!f->glyphs_initialized_p
35431 || f->pointer_invisible)
35432 return;
35433
35434 hlinfo->mouse_face_mouse_x = x;
35435 hlinfo->mouse_face_mouse_y = y;
35436 hlinfo->mouse_face_mouse_frame = f;
35437
35438 if (hlinfo->mouse_face_defer)
35439 return;
35440
35441
35442 window = window_from_coordinates (f, x, y, &part, true, true);
35443
35444
35445 if (! EQ (window, hlinfo->mouse_face_window)
35446
35447 || (!NILP (hlinfo->mouse_face_window)
35448 && !NILP (window)
35449 && part != ON_TEXT
35450 && part != ON_MODE_LINE
35451 && part != ON_HEADER_LINE
35452 && part != ON_TAB_LINE))
35453 clear_mouse_face (hlinfo);
35454
35455
35456 help_echo_string = Qnil;
35457
35458
35459 if (!FRAME_WINDOW_P (f)
35460 && (y >= FRAME_MENU_BAR_LINES (f)
35461 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35462 {
35463 int prop_idx;
35464 bool ignore;
35465 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35466
35467 if (!NILP (caption))
35468 {
35469 help_echo_object = help_echo_window = Qnil;
35470 help_echo_pos = -1;
35471 help_echo_string = AREF (f->tab_bar_items,
35472 prop_idx * TAB_BAR_ITEM_NSLOTS
35473 + TAB_BAR_ITEM_HELP);
35474 if (NILP (help_echo_string))
35475 help_echo_string = caption;
35476 }
35477 }
35478
35479 #ifdef HAVE_WINDOW_SYSTEM
35480
35481
35482 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35483 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35484 {
35485 enum internal_border_part part = frame_internal_border_part (f, x, y);
35486
35487 switch (part)
35488 {
35489 case INTERNAL_BORDER_NONE:
35490 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35491
35492 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35493 break;
35494 case INTERNAL_BORDER_LEFT_EDGE:
35495 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35496 break;
35497 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35498 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35499 break;
35500 case INTERNAL_BORDER_TOP_EDGE:
35501 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35502 break;
35503 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35504 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35505 break;
35506 case INTERNAL_BORDER_RIGHT_EDGE:
35507 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35508 break;
35509 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35510 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35511 break;
35512 case INTERNAL_BORDER_BOTTOM_EDGE:
35513 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35514 break;
35515 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35516 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35517 break;
35518 default:
35519
35520 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35521 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35522 }
35523
35524 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35525 {
35526
35527 help_echo_string = build_string ("drag-mouse-1: resize frame");
35528 goto set_cursor;
35529 }
35530 }
35531 #endif
35532
35533
35534 if (!WINDOWP (window))
35535 return;
35536
35537
35538 w = XWINDOW (window);
35539 frame_to_window_pixel_xy (w, &x, &y);
35540
35541 #if defined (HAVE_WINDOW_SYSTEM)
35542
35543
35544 if (EQ (window, f->tab_bar_window))
35545 {
35546 note_tab_bar_highlight (f, x, y);
35547 if (tab_bar__dragging_in_progress)
35548 {
35549 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35550 goto set_cursor;
35551 }
35552 else
35553 return;
35554 }
35555 else
35556 {
35557
35558
35559
35560
35561 f->last_tab_bar_item = -1;
35562 }
35563 #endif
35564
35565 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35566
35567
35568 if (EQ (window, f->tool_bar_window))
35569 {
35570 note_tool_bar_highlight (f, x, y);
35571 return;
35572 }
35573 #endif
35574
35575
35576 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35577 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35578 {
35579 note_mode_line_or_margin_highlight (window, x, y, part);
35580
35581 #ifdef HAVE_WINDOW_SYSTEM
35582 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35583 {
35584 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35585
35586 goto set_cursor;
35587 }
35588 else
35589 #endif
35590 return;
35591 }
35592
35593 #ifdef HAVE_WINDOW_SYSTEM
35594 if (part == ON_VERTICAL_BORDER)
35595 {
35596 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35597 help_echo_string = build_string ("drag-mouse-1: resize");
35598 goto set_cursor;
35599 }
35600 else if (part == ON_RIGHT_DIVIDER)
35601 {
35602 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35603 help_echo_string = build_string ("drag-mouse-1: resize");
35604 goto set_cursor;
35605 }
35606 else if (part == ON_BOTTOM_DIVIDER)
35607 if (! WINDOW_BOTTOMMOST_P (w)
35608 || minibuf_level
35609 || NILP (Vresize_mini_windows))
35610 {
35611 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35612 help_echo_string = build_string ("drag-mouse-1: resize");
35613 goto set_cursor;
35614 }
35615 else
35616 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35617 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35618 || part == ON_VERTICAL_SCROLL_BAR
35619 || part == ON_HORIZONTAL_SCROLL_BAR)
35620 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35621 else
35622 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35623 #endif
35624
35625
35626
35627 b = XBUFFER (w->contents);
35628 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35629 {
35630 int hpos, vpos, dx, dy, area = LAST_AREA;
35631 ptrdiff_t pos;
35632 struct glyph *glyph;
35633 Lisp_Object object;
35634 Lisp_Object mouse_face = Qnil, position;
35635 Lisp_Object *overlay_vec = NULL;
35636 ptrdiff_t i, noverlays;
35637 struct buffer *obuf;
35638 ptrdiff_t obegv, ozv;
35639 bool same_region;
35640
35641
35642 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35643
35644 #ifdef HAVE_WINDOW_SYSTEM
35645
35646 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35647 {
35648 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35649 if (img != NULL && IMAGEP (img->spec))
35650 {
35651 Lisp_Object image_map, hotspot;
35652 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35653 !NILP (image_map))
35654 && (hotspot = find_hot_spot (image_map,
35655 glyph->slice.img.x + dx,
35656 glyph->slice.img.y + dy),
35657 CONSP (hotspot))
35658 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35659 {
35660 Lisp_Object plist;
35661
35662
35663
35664
35665
35666 hotspot = XCDR (hotspot);
35667 if (CONSP (hotspot)
35668 && (plist = XCAR (hotspot), CONSP (plist)))
35669 {
35670 pointer = plist_get (plist, Qpointer);
35671 if (NILP (pointer))
35672 pointer = Qhand;
35673 help_echo_string = plist_get (plist, Qhelp_echo);
35674 if (!NILP (help_echo_string))
35675 {
35676 help_echo_window = window;
35677 help_echo_object = glyph->object;
35678 help_echo_pos = glyph->charpos;
35679 }
35680 }
35681 }
35682 if (NILP (pointer))
35683 pointer = plist_get (XCDR (img->spec), QCpointer);
35684 }
35685 }
35686 #endif
35687
35688
35689 if (glyph == NULL
35690 || area != TEXT_AREA
35691 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35692
35693
35694
35695
35696
35697 || NILP (glyph->object)
35698
35699
35700
35701
35702 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35703 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35704 && glyph->type == STRETCH_GLYPH
35705 && glyph->avoid_cursor_p))
35706 {
35707 if (clear_mouse_face (hlinfo))
35708 cursor = No_Cursor;
35709 if (FRAME_WINDOW_P (f) && NILP (pointer))
35710 {
35711 #ifdef HAVE_WINDOW_SYSTEM
35712 if (area != TEXT_AREA)
35713 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35714 else
35715 pointer = Vvoid_text_area_pointer;
35716 #endif
35717 }
35718 goto set_cursor;
35719 }
35720
35721 pos = glyph->charpos;
35722 object = glyph->object;
35723 if (!STRINGP (object) && !BUFFERP (object))
35724 goto set_cursor;
35725
35726
35727 if (BUFFERP (object) && pos > BUF_Z (b))
35728 goto set_cursor;
35729
35730
35731
35732 obuf = current_buffer;
35733 current_buffer = b;
35734 obegv = BEGV;
35735 ozv = ZV;
35736 BEGV = BEG;
35737 ZV = Z;
35738
35739
35740 position = make_fixnum (pos);
35741
35742 USE_SAFE_ALLOCA;
35743
35744 if (BUFFERP (object))
35745 {
35746
35747 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35748
35749 noverlays = sort_overlays (overlay_vec, noverlays, w);
35750 }
35751 else
35752 noverlays = 0;
35753
35754 if (NILP (Vmouse_highlight))
35755 {
35756 clear_mouse_face (hlinfo);
35757 goto check_help_echo;
35758 }
35759
35760 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35761
35762 if (same_region)
35763 cursor = No_Cursor;
35764
35765
35766 if (! same_region
35767
35768
35769
35770
35771
35772 || (!hlinfo->mouse_face_hidden
35773 && OVERLAYP (hlinfo->mouse_face_overlay)
35774
35775 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35776 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35777 {
35778
35779 Lisp_Object overlay = Qnil;
35780 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35781 {
35782 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35783 if (!NILP (mouse_face))
35784 overlay = overlay_vec[i];
35785 }
35786
35787
35788
35789 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35790 goto check_help_echo;
35791
35792
35793 if (clear_mouse_face (hlinfo))
35794 cursor = No_Cursor;
35795
35796
35797 hlinfo->mouse_face_overlay = overlay;
35798
35799
35800 if (NILP (overlay))
35801 mouse_face = Fget_text_property (position, Qmouse_face, object);
35802
35803
35804
35805 if (!NILP (mouse_face) && STRINGP (object))
35806 {
35807
35808
35809 Lisp_Object s, e;
35810 ptrdiff_t ignore;
35811
35812 s = Fprevious_single_property_change
35813 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35814 e = Fnext_single_property_change
35815 (position, Qmouse_face, object, Qnil);
35816 if (NILP (s))
35817 s = make_fixnum (0);
35818 if (NILP (e))
35819 e = make_fixnum (SCHARS (object));
35820 mouse_face_from_string_pos (w, hlinfo, object,
35821 XFIXNUM (s), XFIXNUM (e));
35822 hlinfo->mouse_face_past_end = false;
35823 hlinfo->mouse_face_window = window;
35824 hlinfo->mouse_face_face_id
35825 = face_at_string_position (w, object, pos, 0, &ignore,
35826 glyph->face_id, true, 0);
35827 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35828 cursor = No_Cursor;
35829 }
35830 else
35831 {
35832
35833
35834 Lisp_Object buffer UNINIT;
35835 Lisp_Object disp_string UNINIT;
35836
35837 if (STRINGP (object))
35838 {
35839
35840
35841 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35842 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35843 pos = string_buffer_position (object, start);
35844 if (pos > 0)
35845 {
35846 mouse_face = get_char_property_and_overlay
35847 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35848 buffer = w->contents;
35849 disp_string = object;
35850 }
35851 }
35852 else
35853 {
35854 buffer = object;
35855 disp_string = Qnil;
35856 }
35857
35858 if (!NILP (mouse_face))
35859 {
35860 Lisp_Object before, after;
35861 Lisp_Object before_string, after_string;
35862
35863
35864
35865
35866
35867
35868
35869
35870
35871
35872 Lisp_Object lim1
35873 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35874 ? Fmarker_position (w->start)
35875 : Qnil;
35876 Lisp_Object lim2
35877 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35878 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35879 - w->window_end_pos)
35880 : Qnil;
35881
35882 if (NILP (overlay))
35883 {
35884
35885 before = Fprevious_single_property_change
35886 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35887 after = Fnext_single_property_change
35888 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35889 before_string = after_string = Qnil;
35890 }
35891 else
35892 {
35893
35894 before = Foverlay_start (overlay);
35895 after = Foverlay_end (overlay);
35896 before_string = Foverlay_get (overlay, Qbefore_string);
35897 after_string = Foverlay_get (overlay, Qafter_string);
35898
35899 if (!STRINGP (before_string)) before_string = Qnil;
35900 if (!STRINGP (after_string)) after_string = Qnil;
35901 }
35902
35903 mouse_face_from_buffer_pos (window, hlinfo, pos,
35904 NILP (before)
35905 ? 1
35906 : XFIXNAT (before),
35907 NILP (after)
35908 ? BUF_Z (XBUFFER (buffer))
35909 : XFIXNAT (after),
35910 before_string, after_string,
35911 disp_string);
35912 cursor = No_Cursor;
35913 }
35914 }
35915 }
35916
35917 check_help_echo:
35918
35919
35920 if (NILP (help_echo_string)) {
35921 Lisp_Object help, overlay;
35922
35923
35924 help = overlay = Qnil;
35925 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35926 {
35927 overlay = overlay_vec[i];
35928 help = Foverlay_get (overlay, Qhelp_echo);
35929 }
35930
35931 if (!NILP (help))
35932 {
35933 help_echo_string = help;
35934 help_echo_window = window;
35935 help_echo_object = overlay;
35936 help_echo_pos = pos;
35937 }
35938 else
35939 {
35940 Lisp_Object obj = glyph->object;
35941 ptrdiff_t charpos = glyph->charpos;
35942
35943
35944 if (STRINGP (obj)
35945 && charpos >= 0
35946 && charpos < SCHARS (obj))
35947 {
35948 help = Fget_text_property (make_fixnum (charpos),
35949 Qhelp_echo, obj);
35950 if (NILP (help))
35951 {
35952
35953
35954 struct glyph_row *r
35955 = MATRIX_ROW (w->current_matrix, vpos);
35956 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35957 ptrdiff_t p = string_buffer_position (obj, start);
35958 if (p > 0)
35959 {
35960 help = Fget_char_property (make_fixnum (p),
35961 Qhelp_echo, w->contents);
35962 if (!NILP (help))
35963 {
35964 charpos = p;
35965 obj = w->contents;
35966 }
35967 }
35968 }
35969 }
35970 else if (BUFFERP (obj)
35971 && charpos >= BEGV
35972 && charpos < ZV)
35973 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35974 obj);
35975
35976 if (!NILP (help))
35977 {
35978 help_echo_string = help;
35979 help_echo_window = window;
35980 help_echo_object = obj;
35981 help_echo_pos = charpos;
35982 }
35983 }
35984 }
35985
35986 #ifdef HAVE_WINDOW_SYSTEM
35987
35988 if (FRAME_WINDOW_P (f) && NILP (pointer))
35989 {
35990
35991 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35992 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35993
35994 if (NILP (pointer))
35995 {
35996 Lisp_Object obj = glyph->object;
35997 ptrdiff_t charpos = glyph->charpos;
35998
35999
36000 if (STRINGP (obj)
36001 && charpos >= 0
36002 && charpos < SCHARS (obj))
36003 {
36004 pointer = Fget_text_property (make_fixnum (charpos),
36005 Qpointer, obj);
36006 if (NILP (pointer))
36007 {
36008
36009
36010 struct glyph_row *r
36011 = MATRIX_ROW (w->current_matrix, vpos);
36012 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
36013 ptrdiff_t p = string_buffer_position (obj, start);
36014 if (p > 0)
36015 pointer = Fget_char_property (make_fixnum (p),
36016 Qpointer, w->contents);
36017 }
36018 }
36019 else if (BUFFERP (obj)
36020 && charpos >= BEGV
36021 && charpos < ZV)
36022 pointer = Fget_text_property (make_fixnum (charpos),
36023 Qpointer, obj);
36024 }
36025 }
36026 #endif
36027
36028 BEGV = obegv;
36029 ZV = ozv;
36030 current_buffer = obuf;
36031 SAFE_FREE ();
36032 }
36033
36034 set_cursor:
36035 define_frame_cursor1 (f, cursor, pointer);
36036 }
36037
36038
36039
36040
36041
36042
36043
36044 void
36045 gui_clear_window_mouse_face (struct window *w)
36046 {
36047 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
36048 Lisp_Object window;
36049
36050 block_input ();
36051 XSETWINDOW (window, w);
36052 if (EQ (window, hlinfo->mouse_face_window))
36053 clear_mouse_face (hlinfo);
36054 unblock_input ();
36055 }
36056
36057
36058
36059
36060
36061
36062 void
36063 cancel_mouse_face (struct frame *f)
36064 {
36065 Lisp_Object window;
36066 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36067
36068 window = hlinfo->mouse_face_window;
36069 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
36070 reset_mouse_highlight (hlinfo);
36071 }
36072
36073
36074
36075
36076
36077
36078
36079 #ifdef HAVE_WINDOW_SYSTEM
36080
36081
36082
36083
36084 static void
36085 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
36086 enum glyph_row_area area)
36087 {
36088 struct glyph *first = row->glyphs[area];
36089 struct glyph *end = row->glyphs[area] + row->used[area];
36090 struct glyph *last;
36091 int first_x, start_x, x;
36092
36093 if (area == TEXT_AREA && row->fill_line_p)
36094
36095 draw_glyphs (w, row->x, row, area,
36096 0, row->used[area],
36097 DRAW_NORMAL_TEXT, 0);
36098 else
36099 {
36100
36101
36102
36103 start_x = window_box_left_offset (w, area);
36104 x = start_x;
36105 if (area == TEXT_AREA)
36106 x += row->x;
36107
36108
36109 while (first < end
36110 && x + first->pixel_width < r->x)
36111 {
36112 x += first->pixel_width;
36113 ++first;
36114 }
36115
36116
36117 last = first;
36118 first_x = x;
36119
36120
36121
36122 int r_end = r->x + r->width;
36123 while (last < end && x < r_end)
36124 {
36125 x += last->pixel_width;
36126 ++last;
36127 }
36128
36129
36130 if (last > first)
36131 draw_glyphs (w, first_x - start_x, row, area,
36132 first - row->glyphs[area], last - row->glyphs[area],
36133 DRAW_NORMAL_TEXT, 0);
36134 }
36135 }
36136
36137
36138
36139
36140
36141
36142 static bool
36143 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
36144 {
36145 eassert (row->enabled_p);
36146
36147 if (row->mode_line_p || w->pseudo_window_p)
36148 draw_glyphs (w, 0, row, TEXT_AREA,
36149 0, row->used[TEXT_AREA],
36150 DRAW_NORMAL_TEXT, 0);
36151 else
36152 {
36153 if (row->used[LEFT_MARGIN_AREA])
36154 expose_area (w, row, r, LEFT_MARGIN_AREA);
36155 if (row->used[TEXT_AREA])
36156 expose_area (w, row, r, TEXT_AREA);
36157 if (row->used[RIGHT_MARGIN_AREA])
36158 expose_area (w, row, r, RIGHT_MARGIN_AREA);
36159 draw_row_fringe_bitmaps (w, row);
36160 }
36161
36162 return row->mouse_face_p;
36163 }
36164
36165
36166
36167
36168
36169
36170
36171
36172
36173
36174 static void
36175 expose_overlaps (struct window *w,
36176 struct glyph_row *first_overlapping_row,
36177 struct glyph_row *last_overlapping_row,
36178 const Emacs_Rectangle *r)
36179 {
36180 struct glyph_row *row;
36181
36182 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
36183 if (row->overlapping_p)
36184 {
36185 eassert (row->enabled_p && !row->mode_line_p);
36186
36187 row->clip = r;
36188 if (row->used[LEFT_MARGIN_AREA])
36189 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
36190
36191 if (row->used[TEXT_AREA])
36192 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
36193
36194 if (row->used[RIGHT_MARGIN_AREA])
36195 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
36196 row->clip = NULL;
36197 }
36198 }
36199
36200
36201
36202
36203 static bool
36204 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
36205 {
36206 Emacs_Rectangle cr, result;
36207 struct glyph *cursor_glyph;
36208 struct glyph_row *row;
36209
36210 if (w->phys_cursor.vpos >= 0
36211 && w->phys_cursor.vpos < w->current_matrix->nrows
36212 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
36213 row->enabled_p)
36214 && row->cursor_in_fringe_p)
36215 {
36216
36217 cr.x = window_box_right_offset (w,
36218 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
36219 ? RIGHT_MARGIN_AREA
36220 : TEXT_AREA));
36221 cr.y = row->y;
36222 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
36223 cr.height = row->height;
36224 return gui_intersect_rectangles (&cr, r, &result);
36225 }
36226
36227 cursor_glyph = get_phys_cursor_glyph (w);
36228 if (cursor_glyph)
36229 {
36230
36231
36232 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
36233 cr.y = w->phys_cursor.y;
36234 cr.width = cursor_glyph->pixel_width;
36235 cr.height = w->phys_cursor_height;
36236
36237
36238 return gui_intersect_rectangles (&cr, r, &result);
36239 }
36240
36241 return false;
36242 }
36243
36244
36245
36246
36247
36248
36249 void
36250 gui_draw_vertical_border (struct window *w)
36251 {
36252 struct frame *f = XFRAME (WINDOW_FRAME (w));
36253
36254
36255
36256
36257
36258
36259
36260
36261
36262 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
36263 return;
36264
36265
36266
36267
36268 if (!WINDOW_RIGHTMOST_P (w)
36269 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
36270 {
36271 int x0, x1, y0, y1;
36272
36273 window_box_edges (w, &x0, &y0, &x1, &y1);
36274 y1 -= 1;
36275
36276 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36277 x1 -= 1;
36278
36279 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
36280 }
36281
36282 if (!WINDOW_LEFTMOST_P (w)
36283 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
36284 {
36285 int x0, x1, y0, y1;
36286
36287 window_box_edges (w, &x0, &y0, &x1, &y1);
36288 y1 -= 1;
36289
36290 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36291 x0 -= 1;
36292
36293 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
36294 }
36295 }
36296
36297
36298
36299
36300 void
36301 gui_draw_right_divider (struct window *w)
36302 {
36303 struct frame *f = WINDOW_XFRAME (w);
36304
36305 if (w->mini || w->pseudo_window_p)
36306 return;
36307 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36308 {
36309 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
36310 int x1 = WINDOW_RIGHT_EDGE_X (w);
36311 int y0 = WINDOW_TOP_EDGE_Y (w);
36312 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36313
36314
36315
36316 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
36317 && !NILP (w->parent)
36318 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
36319 && !NILP (w->next))
36320 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36321
36322 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36323 }
36324 }
36325
36326 static void
36327 gui_draw_bottom_divider (struct window *w)
36328 {
36329 struct frame *f = XFRAME (WINDOW_FRAME (w));
36330
36331 if (w->mini || w->pseudo_window_p)
36332 return;
36333 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36334 {
36335 int x0 = WINDOW_LEFT_EDGE_X (w);
36336 int x1 = WINDOW_RIGHT_EDGE_X (w);
36337 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36338 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36339 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
36340
36341
36342
36343 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
36344 && p
36345 && ((WINDOW_VERTICAL_COMBINATION_P (p)
36346 && !NILP (w->next))
36347 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
36348 && NILP (w->next)
36349 && !NILP (p->parent)
36350 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
36351 && !NILP (XWINDOW (p->parent)->next))))
36352 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
36353
36354 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36355 }
36356 }
36357
36358
36359
36360
36361
36362
36363 static bool
36364 expose_window (struct window *w, const Emacs_Rectangle *fr)
36365 {
36366 struct frame *f = XFRAME (w->frame);
36367 Emacs_Rectangle wr, r;
36368 bool mouse_face_overwritten_p = false;
36369
36370
36371
36372
36373
36374 if (w->current_matrix == NULL)
36375 return false;
36376
36377
36378
36379
36380 if (w->must_be_updated_p)
36381 {
36382 SET_FRAME_GARBAGED (f);
36383 return false;
36384 }
36385
36386
36387 wr.x = WINDOW_LEFT_EDGE_X (w);
36388 wr.y = WINDOW_TOP_EDGE_Y (w);
36389 wr.width = WINDOW_PIXEL_WIDTH (w);
36390 wr.height = WINDOW_PIXEL_HEIGHT (w);
36391
36392 if (gui_intersect_rectangles (fr, &wr, &r))
36393 {
36394 int yb = window_text_bottom_y (w);
36395 struct glyph_row *row;
36396 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36397
36398 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36399 r.x, r.y, r.width, r.height);
36400
36401
36402 r.x -= WINDOW_LEFT_EDGE_X (w);
36403 r.y -= WINDOW_TOP_EDGE_Y (w);
36404
36405
36406 bool cursor_cleared_p = (!w->pseudo_window_p
36407 && phys_cursor_in_rect_p (w, &r));
36408 if (cursor_cleared_p)
36409 gui_clear_cursor (w);
36410
36411
36412
36413
36414
36415
36416 bool phys_cursor_on_p = w->phys_cursor_on_p;
36417
36418
36419
36420
36421 int r_bottom = r.y + r.height;
36422
36423
36424
36425
36426
36427 bool buffer_changed = false;
36428 struct buffer *oldbuf = current_buffer;
36429 if (!w->pseudo_window_p)
36430 {
36431 set_buffer_internal_1 (XBUFFER (w->contents));
36432 buffer_changed = true;
36433 }
36434
36435
36436 first_overlapping_row = last_overlapping_row = NULL;
36437 for (row = w->current_matrix->rows;
36438 row->enabled_p;
36439 ++row)
36440 {
36441 int y0 = row->y;
36442 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36443
36444 if ((y0 >= r.y && y0 < r_bottom)
36445 || (y1 > r.y && y1 < r_bottom)
36446 || (r.y >= y0 && r.y < y1)
36447 || (r_bottom > y0 && r_bottom < y1))
36448 {
36449
36450
36451 if (row->overlapping_p && !row->mode_line_p)
36452 {
36453 if (first_overlapping_row == NULL)
36454 first_overlapping_row = row;
36455 last_overlapping_row = row;
36456 }
36457
36458 row->clip = fr;
36459 if (expose_line (w, row, &r))
36460 mouse_face_overwritten_p = true;
36461 row->clip = NULL;
36462 }
36463 else if (row->overlapping_p)
36464 {
36465
36466 if (y0 < r.y
36467 ? y0 + row->phys_height > r.y
36468 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36469 {
36470 if (first_overlapping_row == NULL)
36471 first_overlapping_row = row;
36472 last_overlapping_row = row;
36473 }
36474 }
36475
36476 if (y1 >= yb)
36477 break;
36478 }
36479
36480 if (buffer_changed)
36481 set_buffer_internal_1 (oldbuf);
36482
36483
36484 if (window_wants_mode_line (w)
36485 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36486 row->enabled_p)
36487 && row->y < r_bottom)
36488 {
36489 if (expose_line (w, row, &r))
36490 mouse_face_overwritten_p = true;
36491 }
36492
36493 if (!w->pseudo_window_p)
36494 {
36495
36496 if (first_overlapping_row)
36497 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36498 fr);
36499
36500
36501 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36502 gui_draw_right_divider (w);
36503 else
36504 gui_draw_vertical_border (w);
36505
36506 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36507 gui_draw_bottom_divider (w);
36508
36509
36510 if (cursor_cleared_p
36511 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36512 update_window_cursor (w, true);
36513 }
36514 }
36515
36516 return mouse_face_overwritten_p;
36517 }
36518
36519
36520
36521
36522
36523
36524
36525 static bool
36526 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36527 {
36528 struct frame *f = XFRAME (w->frame);
36529 bool mouse_face_overwritten_p = false;
36530
36531 while (w && !FRAME_GARBAGED_P (f))
36532 {
36533 mouse_face_overwritten_p
36534 |= (WINDOWP (w->contents)
36535 ? expose_window_tree (XWINDOW (w->contents), r)
36536 : expose_window (w, r));
36537
36538 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36539 }
36540
36541 return mouse_face_overwritten_p;
36542 }
36543
36544
36545
36546
36547
36548
36549
36550
36551 void
36552 expose_frame (struct frame *f, int x, int y, int w, int h)
36553 {
36554 Emacs_Rectangle r;
36555 bool mouse_face_overwritten_p = false;
36556
36557 if (FRAME_GARBAGED_P (f))
36558 {
36559 redisplay_trace ("expose_frame garbaged\n");
36560 return;
36561 }
36562
36563
36564
36565
36566 if (FRAME_FACE_CACHE (f) == NULL
36567 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36568 {
36569 redisplay_trace ("expose_frame no faces\n");
36570 return;
36571 }
36572
36573 if (w == 0 || h == 0)
36574 {
36575 r.x = r.y = 0;
36576 r.width = FRAME_TEXT_WIDTH (f);
36577 r.height = FRAME_TEXT_HEIGHT (f);
36578 }
36579 else
36580 {
36581 r.x = x;
36582 r.y = y;
36583 r.width = w;
36584 r.height = h;
36585 }
36586
36587 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36588 r.x, r.y, r.width, r.height);
36589 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36590
36591 if (WINDOWP (f->tab_bar_window))
36592 mouse_face_overwritten_p
36593 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36594
36595 #ifndef HAVE_EXT_TOOL_BAR
36596 if (WINDOWP (f->tool_bar_window))
36597 mouse_face_overwritten_p
36598 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36599 #endif
36600
36601 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
36602 if (WINDOWP (f->menu_bar_window))
36603 mouse_face_overwritten_p
36604 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36605 #endif
36606
36607
36608
36609
36610
36611
36612
36613
36614
36615
36616
36617
36618
36619
36620 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36621 {
36622 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36623 if (f == hlinfo->mouse_face_mouse_frame)
36624 {
36625 int mouse_x = hlinfo->mouse_face_mouse_x;
36626 int mouse_y = hlinfo->mouse_face_mouse_y;
36627 clear_mouse_face (hlinfo);
36628 note_mouse_highlight (f, mouse_x, mouse_y);
36629 }
36630 }
36631 }
36632
36633
36634
36635
36636
36637
36638
36639 bool
36640 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36641 Emacs_Rectangle *result)
36642 {
36643 const Emacs_Rectangle *left, *right;
36644 const Emacs_Rectangle *upper, *lower;
36645 bool intersection_p = false;
36646
36647
36648 if (r1->x < r2->x)
36649 left = r1, right = r2;
36650 else
36651 left = r2, right = r1;
36652
36653
36654
36655 if (right->x <= left->x + left->width)
36656 {
36657 result->x = right->x;
36658
36659
36660
36661 result->width = (min (left->x + left->width, right->x + right->width)
36662 - result->x);
36663
36664
36665 if (r1->y < r2->y)
36666 upper = r1, lower = r2;
36667 else
36668 upper = r2, lower = r1;
36669
36670
36671
36672 if (lower->y <= upper->y + upper->height)
36673 {
36674 result->y = lower->y;
36675
36676
36677
36678 result->height = (min (lower->y + lower->height,
36679 upper->y + upper->height)
36680 - result->y);
36681 intersection_p = true;
36682 }
36683 }
36684
36685 return intersection_p;
36686 }
36687
36688
36689
36690
36691
36692
36693 void
36694 gui_union_rectangles (const Emacs_Rectangle *a, const Emacs_Rectangle *b,
36695 Emacs_Rectangle *result)
36696 {
36697 struct gui_box a_box, b_box, result_box;
36698
36699
36700
36701 if (!a->width || !a->height)
36702 {
36703 *result = *b;
36704 return;
36705 }
36706 else if (!b->width || !b->height)
36707 {
36708 *result = *a;
36709 return;
36710 }
36711
36712
36713 a_box.x1 = a->x;
36714 a_box.y1 = a->y;
36715 a_box.x2 = a->x + a->width;
36716 a_box.y2 = a->y + a->height;
36717
36718 b_box.x1 = b->x;
36719 b_box.y1 = b->y;
36720 b_box.x2 = b->x + b->width;
36721 b_box.y2 = b->y + b->height;
36722
36723
36724 result_box.x1 = min (a_box.x1, b_box.x1);
36725 result_box.y1 = min (a_box.y1, b_box.y1);
36726 result_box.x2 = max (a_box.x2, b_box.x2);
36727 result_box.y2 = max (a_box.y2, b_box.y2);
36728
36729
36730
36731 result->x = result_box.x1;
36732 result->y = result_box.y1;
36733 result->width = result_box.x2 - result_box.x1;
36734 result->height = result_box.y2 - result_box.y1;
36735 }
36736
36737 #endif
36738
36739
36740
36741
36742
36743
36744 void
36745 syms_of_xdisp (void)
36746 {
36747 Vwith_echo_area_save_vector = Qnil;
36748 staticpro (&Vwith_echo_area_save_vector);
36749
36750 Vmessage_stack = Qnil;
36751 staticpro (&Vmessage_stack);
36752
36753
36754 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36755
36756 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36757
36758 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36759 scroll_minibuffer_conservatively,
36760 doc:
36761
36762 );
36763 scroll_minibuffer_conservatively = true;
36764
36765 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36766 doc:
36767
36768
36769
36770
36771
36772 );
36773 inhibit_message = false;
36774
36775 message_dolog_marker1 = Fmake_marker ();
36776 staticpro (&message_dolog_marker1);
36777 message_dolog_marker2 = Fmake_marker ();
36778 staticpro (&message_dolog_marker2);
36779 message_dolog_marker3 = Fmake_marker ();
36780 staticpro (&message_dolog_marker3);
36781
36782 defsubr (&Sset_buffer_redisplay);
36783 #ifdef GLYPH_DEBUG
36784 defsubr (&Sdump_frame_glyph_matrix);
36785 defsubr (&Sdump_glyph_matrix);
36786 defsubr (&Sdump_glyph_row);
36787 defsubr (&Sdump_tab_bar_row);
36788 defsubr (&Sdump_tool_bar_row);
36789 defsubr (&Strace_redisplay);
36790 defsubr (&Strace_to_stderr);
36791 #endif
36792 #ifdef HAVE_WINDOW_SYSTEM
36793 defsubr (&Stab_bar_height);
36794 defsubr (&Stool_bar_height);
36795 defsubr (&Slookup_image_map);
36796 #endif
36797 defsubr (&Sline_pixel_height);
36798 defsubr (&Sformat_mode_line);
36799 defsubr (&Sinvisible_p);
36800 defsubr (&Scurrent_bidi_paragraph_direction);
36801 defsubr (&Swindow_text_pixel_size);
36802 defsubr (&Sbuffer_text_pixel_size);
36803 defsubr (&Smove_point_visually);
36804 defsubr (&Sbidi_find_overridden_directionality);
36805 defsubr (&Sdisplay__line_is_continued_p);
36806 defsubr (&Sget_display_property);
36807 defsubr (&Slong_line_optimizations_p);
36808
36809 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36810 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36811 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36812 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36813 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36814 DEFSYM (Qeval, "eval");
36815 DEFSYM (QCdata, ":data");
36816
36817
36818 DEFSYM (Qdisplay, "display");
36819 DEFSYM (Qspace_width, "space-width");
36820 DEFSYM (Qraise, "raise");
36821 DEFSYM (Qslice, "slice");
36822 DEFSYM (Qspace, "space");
36823 DEFSYM (Qmargin, "margin");
36824 DEFSYM (Qpointer, "pointer");
36825 DEFSYM (Qleft_margin, "left-margin");
36826 DEFSYM (Qright_margin, "right-margin");
36827 DEFSYM (Qcenter, "center");
36828 DEFSYM (Qline_height, "line-height");
36829 DEFSYM (QCalign_to, ":align-to");
36830 DEFSYM (QCrelative_width, ":relative-width");
36831 DEFSYM (QCrelative_height, ":relative-height");
36832 DEFSYM (QCeval, ":eval");
36833 DEFSYM (QCpropertize, ":propertize");
36834 DEFSYM (QCfile, ":file");
36835 DEFSYM (Qfontified, "fontified");
36836 DEFSYM (Qfontification_functions, "fontification-functions");
36837 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36838 "long-line-optimizations-in-fontification-functions");
36839
36840
36841
36842 DEFSYM (Qdisable_eval, "disable-eval");
36843
36844
36845 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36846
36847
36848 DEFSYM (Qline_number, "line-number");
36849 DEFSYM (Qline_number_current_line, "line-number-current-line");
36850 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36851 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36852
36853 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36854
36855
36856 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36857
36858
36859 DEFSYM (Qescape_glyph, "escape-glyph");
36860
36861
36862
36863 DEFSYM (Qnobreak_space, "nobreak-space");
36864 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36865
36866
36867
36868 DEFSYM (Qimage, "image");
36869
36870
36871 DEFSYM (Qtext, "text");
36872 DEFSYM (Qboth, "both");
36873 DEFSYM (Qboth_horiz, "both-horiz");
36874 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36875
36876
36877 DEFSYM (QCmap, ":map");
36878 DEFSYM (QCpointer, ":pointer");
36879 DEFSYM (Qrect, "rect");
36880 DEFSYM (Qcircle, "circle");
36881 DEFSYM (Qpoly, "poly");
36882
36883 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36884
36885 DEFSYM (Qgrow_only, "grow-only");
36886 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36887 DEFSYM (Qposition, "position");
36888 DEFSYM (Qbuffer_position, "buffer-position");
36889 DEFSYM (Qobject, "object");
36890
36891
36892 DEFSYM (Qbar, "bar");
36893 DEFSYM (Qhbar, "hbar");
36894 DEFSYM (Qbox, "box");
36895 DEFSYM (Qhollow, "hollow");
36896
36897
36898 DEFSYM (Qhand, "hand");
36899 DEFSYM (Qarrow, "arrow");
36900
36901
36902 DEFSYM (Qdragging, "dragging");
36903 DEFSYM (Qdropping, "dropping");
36904 DEFSYM (Qdrag_source, "drag-source");
36905
36906 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36907 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36908 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36909
36910 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36911
36912 list_of_error = list1 (Qerror);
36913 staticpro (&list_of_error);
36914
36915
36916
36917
36918
36919 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36920 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36921
36922
36923
36924 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36925 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36926
36927 echo_buffer[0] = echo_buffer[1] = Qnil;
36928 staticpro (&echo_buffer[0]);
36929 staticpro (&echo_buffer[1]);
36930
36931 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36932 staticpro (&echo_area_buffer[0]);
36933 staticpro (&echo_area_buffer[1]);
36934
36935 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36936 doc:
36937
36938
36939
36940 );
36941 Vmessages_buffer_name = build_string ("*Messages*");
36942
36943 mode_line_proptrans_alist = Qnil;
36944 staticpro (&mode_line_proptrans_alist);
36945 mode_line_string_list = Qnil;
36946 staticpro (&mode_line_string_list);
36947 mode_line_string_face = Qnil;
36948 staticpro (&mode_line_string_face);
36949 mode_line_string_face_prop = Qnil;
36950 staticpro (&mode_line_string_face_prop);
36951 Vmode_line_unwind_vector = Qnil;
36952 staticpro (&Vmode_line_unwind_vector);
36953
36954 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36955
36956 help_echo_string = Qnil;
36957 staticpro (&help_echo_string);
36958 help_echo_object = Qnil;
36959 staticpro (&help_echo_object);
36960 help_echo_window = Qnil;
36961 staticpro (&help_echo_window);
36962 previous_help_echo_string = Qnil;
36963 staticpro (&previous_help_echo_string);
36964 help_echo_pos = -1;
36965
36966 DEFSYM (Qright_to_left, "right-to-left");
36967 DEFSYM (Qleft_to_right, "left-to-right");
36968 defsubr (&Sbidi_resolved_levels);
36969
36970 #ifdef HAVE_WINDOW_SYSTEM
36971 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36972 doc:
36973
36974 );
36975 x_stretch_cursor_p = 0;
36976 #endif
36977
36978 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36979 doc:
36980 );
36981 Vshow_trailing_whitespace = Qnil;
36982
36983 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36984 doc:
36985
36986
36987 );
36988 Vmode_line_compact = Qnil;
36989 DEFSYM (Qlong, "long");
36990
36991 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36992 doc:
36993
36994
36995
36996
36997
36998
36999
37000
37001
37002
37003
37004 );
37005 Vnobreak_char_display = Qt;
37006
37007 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
37008 doc:
37009
37010
37011
37012
37013
37014
37015
37016
37017
37018
37019
37020
37021
37022
37023
37024 );
37025 nobreak_char_ascii_display = false;
37026
37027 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
37028 doc:
37029
37030
37031 );
37032 Vvoid_text_area_pointer = Qarrow;
37033
37034 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
37035 doc:
37036 );
37037 Vinhibit_redisplay = Qnil;
37038
37039 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
37040 doc: );
37041 Vglobal_mode_string = Qnil;
37042
37043 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
37044 doc:
37045
37046 );
37047 Voverlay_arrow_position = Qnil;
37048
37049 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
37050 doc:
37051 );
37052 Voverlay_arrow_string = build_pure_c_string ("=>");
37053
37054 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
37055 doc:
37056
37057 );
37058 Voverlay_arrow_variable_list
37059 = list1 (intern_c_string ("overlay-arrow-position"));
37060
37061 DEFVAR_INT ("scroll-step", emacs_scroll_step,
37062 doc:
37063
37064
37065
37066 );
37067
37068 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
37069 doc:
37070
37071
37072
37073
37074
37075
37076
37077
37078
37079 );
37080 scroll_conservatively = 0;
37081
37082 DEFVAR_INT ("scroll-margin", scroll_margin,
37083 doc:
37084
37085 );
37086 scroll_margin = 0;
37087
37088 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
37089 doc:
37090
37091
37092
37093 );
37094 Vmaximum_scroll_margin = make_float (0.25);
37095
37096 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
37097 doc:
37098 );
37099 Vdisplay_pixels_per_inch = make_float (72.0);
37100
37101 #ifdef GLYPH_DEBUG
37102 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
37103 #endif
37104
37105 DEFVAR_LISP ("truncate-partial-width-windows",
37106 Vtruncate_partial_width_windows,
37107 doc:
37108
37109
37110
37111
37112
37113
37114
37115
37116
37117
37118
37119
37120
37121
37122
37123 );
37124 Vtruncate_partial_width_windows = make_fixnum (50);
37125
37126 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
37127
37128
37129
37130
37131
37132
37133
37134
37135
37136
37137
37138
37139
37140 );
37141 word_wrap_by_category = false;
37142
37143 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
37144 doc:
37145
37146 );
37147 Vline_number_display_limit = Qnil;
37148
37149 DEFVAR_INT ("line-number-display-limit-width",
37150 line_number_display_limit_width,
37151 doc:
37152
37153 );
37154 line_number_display_limit_width = 200;
37155
37156 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
37157 doc:
37158
37159 );
37160 highlight_nonselected_windows = false;
37161
37162 DEFVAR_BOOL ("multiple-frames", multiple_frames,
37163 doc:
37164
37165
37166 );
37167
37168 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
37169 doc:
37170
37171
37172
37173
37174 );
37175
37176 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
37177 doc:
37178
37179
37180
37181
37182
37183 );
37184
37185
37186 Lisp_Object icon_title_name_format
37187 = pure_list (empty_unibyte_string,
37188 build_pure_c_string ("%b - GNU Emacs at "),
37189 intern_c_string ("system-name"));
37190 Vicon_title_format
37191 = Vframe_title_format
37192 = pure_list (intern_c_string ("multiple-frames"),
37193 build_pure_c_string ("%b"),
37194 icon_title_name_format);
37195
37196 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
37197 doc:
37198
37199 );
37200 Vmessage_log_max = make_fixnum (1000);
37201
37202 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
37203 doc:
37204
37205
37206
37207
37208
37209
37210
37211
37212
37213
37214
37215
37216
37217 );
37218 Vwindow_scroll_functions = Qnil;
37219
37220 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
37221 doc:
37222
37223
37224
37225
37226
37227
37228
37229
37230
37231
37232
37233
37234
37235
37236
37237
37238
37239 );
37240 Vmouse_autoselect_window = Qnil;
37241
37242 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
37243 doc:
37244
37245
37246
37247
37248 );
37249 Vauto_resize_tab_bars = Qt;
37250
37251 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
37252 doc: );
37253 auto_raise_tab_bar_buttons_p = true;
37254
37255 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
37256 doc:
37257
37258
37259
37260
37261 );
37262 Vauto_resize_tool_bars = Qt;
37263
37264 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
37265 doc: );
37266 auto_raise_tool_bar_buttons_p = true;
37267
37268 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
37269 doc:
37270
37271
37272
37273
37274 );
37275 Vmake_cursor_line_fully_visible = Qt;
37276 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
37277
37278 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
37279 doc: );
37280 make_window_start_visible = false;
37281 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
37282 Fmake_variable_buffer_local (Qmake_window_start_visible);
37283
37284 DEFSYM (Qclose_tab, "close-tab");
37285 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
37286 doc:
37287
37288
37289
37290 );
37291 Vtab_bar_border = Qinternal_border_width;
37292
37293 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
37294 doc:
37295
37296
37297
37298 );
37299 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
37300
37301 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
37302 doc: );
37303 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
37304
37305 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
37306 doc:
37307
37308
37309
37310 );
37311 Vtool_bar_border = Qinternal_border_width;
37312
37313 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
37314 doc:
37315
37316
37317
37318 );
37319 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
37320
37321 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
37322 doc: );
37323 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
37324
37325 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
37326 doc:
37327
37328
37329
37330
37331
37332
37333
37334
37335 );
37336 Vtool_bar_style = Qnil;
37337
37338 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
37339 doc:
37340
37341 );
37342 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
37343
37344 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
37345 doc:
37346
37347
37348
37349
37350
37351
37352
37353
37354 );
37355 Vfontification_functions = Qnil;
37356 Fmake_variable_buffer_local (Qfontification_functions);
37357
37358 DEFVAR_BOOL ("unibyte-display-via-language-environment",
37359 unibyte_display_via_language_environment,
37360 doc:
37361
37362
37363
37364
37365
37366
37367 );
37368 unibyte_display_via_language_environment = false;
37369
37370 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
37371 doc:
37372
37373
37374
37375 );
37376 Vmax_mini_window_height = make_float (0.25);
37377
37378 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
37379 doc:
37380
37381
37382
37383
37384
37385
37386
37387
37388 );
37389
37390
37391
37392
37393
37394 Vresize_mini_windows = Qnil;
37395
37396 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
37397 doc:
37398
37399
37400
37401
37402
37403
37404
37405 );
37406 Vblink_cursor_alist = Qnil;
37407
37408 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
37409 doc:
37410
37411
37412
37413 );
37414 automatic_hscrolling = Qt;
37415 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
37416 DEFSYM (Qcurrent_line, "current-line");
37417
37418 DEFVAR_INT ("hscroll-margin", hscroll_margin,
37419 doc:
37420 );
37421 hscroll_margin = 5;
37422
37423 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37424 doc:
37425
37426
37427
37428
37429
37430
37431
37432
37433
37434
37435
37436
37437
37438 );
37439 Vhscroll_step = make_fixnum (0);
37440
37441 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37442 doc:
37443 );
37444 message_truncate_lines = false;
37445
37446 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37447 doc:
37448
37449
37450 );
37451 Vmenu_bar_update_hook = Qnil;
37452
37453 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37454 doc:
37455 );
37456 Vmenu_updating_frame = Qnil;
37457
37458 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37459 doc: );
37460 inhibit_menubar_update = false;
37461
37462 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37463 doc:
37464
37465
37466
37467
37468
37469
37470 );
37471 Vwrap_prefix = Qnil;
37472 DEFSYM (Qwrap_prefix, "wrap-prefix");
37473 Fmake_variable_buffer_local (Qwrap_prefix);
37474
37475 DEFVAR_LISP ("line-prefix", Vline_prefix,
37476 doc:
37477
37478
37479
37480
37481
37482
37483 );
37484 Vline_prefix = Qnil;
37485 DEFSYM (Qline_prefix, "line-prefix");
37486 Fmake_variable_buffer_local (Qline_prefix);
37487
37488 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37489 doc:
37490
37491
37492
37493
37494
37495
37496
37497
37498
37499
37500
37501
37502
37503
37504
37505
37506
37507
37508
37509
37510
37511
37512 );
37513 Vdisplay_line_numbers = Qnil;
37514 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37515 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37516 DEFSYM (Qrelative, "relative");
37517 DEFSYM (Qvisual, "visual");
37518
37519 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37520 doc:
37521
37522
37523
37524 );
37525 Vdisplay_line_numbers_width = Qnil;
37526 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37527 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37528
37529 DEFVAR_LISP ("display-line-numbers-current-absolute",
37530 Vdisplay_line_numbers_current_absolute,
37531 doc:
37532
37533 );
37534 Vdisplay_line_numbers_current_absolute = Qt;
37535
37536 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37537 doc: );
37538 display_line_numbers_widen = false;
37539 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37540 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37541
37542 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37543 doc:
37544
37545
37546 );
37547 display_line_numbers_offset = 0;
37548 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37549 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37550
37551 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37552 doc:
37553
37554
37555 );
37556 display_fill_column_indicator = false;
37557 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37558 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37559
37560 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37561 doc:
37562
37563
37564
37565 );
37566 Vdisplay_fill_column_indicator_column = Qt;
37567 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37568 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37569
37570 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37571 doc:
37572
37573
37574 );
37575 Vdisplay_fill_column_indicator_character = Qnil;
37576 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37577 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37578
37579 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37580 doc:
37581
37582
37583 );
37584 display_line_numbers_major_tick = 0;
37585
37586 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37587 doc:
37588
37589
37590 );
37591 display_line_numbers_minor_tick = 0;
37592
37593 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37594 doc: );
37595 inhibit_eval_during_redisplay = false;
37596
37597 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37598 doc: );
37599 inhibit_free_realized_faces = false;
37600
37601 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37602 doc:
37603
37604 );
37605 inhibit_bidi_mirroring = false;
37606
37607 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37608 doc:
37609
37610
37611
37612 );
37613 bidi_inhibit_bpa = false;
37614
37615 #ifdef GLYPH_DEBUG
37616 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37617 doc: );
37618 inhibit_try_window_id = false;
37619
37620 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37621 doc: );
37622 inhibit_try_window_reusing = false;
37623
37624 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37625 doc: );
37626 inhibit_try_cursor_movement = false;
37627 #endif
37628
37629 DEFVAR_INT ("overline-margin", overline_margin,
37630 doc:
37631
37632 );
37633 overline_margin = 2;
37634
37635 DEFVAR_INT ("underline-minimum-offset",
37636 underline_minimum_offset,
37637 doc:
37638
37639
37640
37641 );
37642 underline_minimum_offset = 1;
37643 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37644
37645 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37646 doc:
37647
37648 );
37649 display_hourglass_p = true;
37650
37651 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37652 doc: );
37653 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37654
37655 #ifdef HAVE_WINDOW_SYSTEM
37656 hourglass_atimer = NULL;
37657 hourglass_shown_p = false;
37658 #endif
37659
37660
37661 DEFSYM (Qglyphless_char, "glyphless-char");
37662
37663
37664 DEFSYM (Qhex_code, "hex-code");
37665 DEFSYM (Qempty_box, "empty-box");
37666 DEFSYM (Qthin_space, "thin-space");
37667 DEFSYM (Qzero_width, "zero-width");
37668
37669 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37670 doc:
37671
37672
37673 );
37674 Vpre_redisplay_function = intern ("ignore");
37675
37676
37677 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37678 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37679
37680 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37681 doc:
37682
37683
37684
37685
37686
37687
37688
37689
37690
37691
37692
37693
37694
37695
37696
37697
37698
37699
37700
37701
37702
37703
37704
37705 );
37706 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37707 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37708 Qempty_box);
37709
37710 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37711 doc: );
37712 Vdebug_on_message = Qnil;
37713
37714 DEFVAR_LISP ("set-message-function", Vset_message_function,
37715 doc:
37716
37717
37718
37719
37720
37721
37722
37723
37724
37725 );
37726 Vset_message_function = Qnil;
37727
37728 DEFSYM (Qdont_clear_message, "dont-clear-message");
37729 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37730 doc:
37731
37732
37733
37734
37735
37736
37737
37738
37739
37740
37741 );
37742 Vclear_message_function = Qnil;
37743
37744 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37745 doc:
37746 );
37747 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37748
37749 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37750 doc:
37751 );
37752 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37753
37754 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37755 doc: );
37756
37757
37758 redisplay__inhibit_bidi = true;
37759
37760 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37761 doc:
37762
37763 );
37764 display_raw_bytes_as_hex = false;
37765
37766 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37767 doc:
37768
37769
37770
37771
37772 );
37773 mouse_fine_grained_tracking = false;
37774
37775 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37776 doc: );
37777 tab_bar__dragging_in_progress = false;
37778
37779 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37780 doc:
37781
37782
37783
37784 );
37785 redisplay_skip_initial_frame = true;
37786
37787 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37788 redisplay_skip_fontification_on_input,
37789 doc:
37790
37791
37792
37793
37794
37795
37796
37797 );
37798 redisplay_skip_fontification_on_input = false;
37799
37800 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37801 redisplay_adhoc_scroll_in_resize_mini_windows,
37802 doc:
37803
37804 );
37805
37806 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37807
37808 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37809 doc:
37810
37811 );
37812 composition_break_at_point = false;
37813
37814 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37815 doc:
37816
37817
37818
37819
37820
37821
37822
37823
37824
37825
37826
37827 );
37828 max_redisplay_ticks = 0;
37829 }
37830
37831
37832
37833
37834 void
37835 init_xdisp (void)
37836 {
37837 CHARPOS (this_line_start_pos) = 0;
37838
37839 echo_area_window = minibuf_window;
37840
37841 if (!noninteractive)
37842 {
37843 struct window *m = XWINDOW (minibuf_window);
37844 Lisp_Object frame = m->frame;
37845 struct frame *f = XFRAME (frame);
37846 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37847 struct window *r = XWINDOW (root);
37848 int i;
37849
37850 r->top_line = FRAME_TOP_MARGIN (f);
37851 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37852 r->total_cols = FRAME_COLS (f);
37853 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37854 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_MARGINS (f);
37855 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37856
37857 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37858 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37859 m->total_cols = FRAME_COLS (f);
37860 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37861 m->total_lines = 1;
37862 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37863
37864 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37865 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37866 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37867
37868
37869 for (i = 0; i < 3; ++i)
37870 default_invis_vector[i] = make_fixnum ('.');
37871 }
37872
37873 {
37874
37875
37876 int size = 100;
37877 mode_line_noprop_buf = xmalloc (size);
37878 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37879 mode_line_noprop_ptr = mode_line_noprop_buf;
37880 mode_line_target = MODE_LINE_DISPLAY;
37881 }
37882
37883 help_echo_showing_p = false;
37884 }
37885
37886 #ifdef HAVE_WINDOW_SYSTEM
37887
37888
37889
37890
37891
37892 static void
37893 show_hourglass (struct atimer *timer)
37894 {
37895
37896
37897
37898 hourglass_atimer = NULL;
37899
37900 if (!hourglass_shown_p)
37901 {
37902 Lisp_Object tail, frame;
37903
37904 block_input ();
37905
37906 FOR_EACH_FRAME (tail, frame)
37907 {
37908 struct frame *f = XFRAME (frame);
37909
37910 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37911 && FRAME_RIF (f)->show_hourglass)
37912 FRAME_RIF (f)->show_hourglass (f);
37913 }
37914
37915 hourglass_shown_p = true;
37916 unblock_input ();
37917 }
37918 }
37919
37920
37921
37922 void
37923 start_hourglass (void)
37924 {
37925 struct timespec delay;
37926
37927 cancel_hourglass ();
37928
37929 if (FIXNUMP (Vhourglass_delay)
37930 && XFIXNUM (Vhourglass_delay) > 0)
37931 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37932 TYPE_MAXIMUM (time_t)),
37933 0);
37934 else if (FLOATP (Vhourglass_delay)
37935 && XFLOAT_DATA (Vhourglass_delay) > 0)
37936 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37937 else
37938 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37939
37940 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37941 show_hourglass, NULL);
37942 }
37943
37944
37945
37946
37947 void
37948 cancel_hourglass (void)
37949 {
37950 if (hourglass_atimer)
37951 {
37952 cancel_atimer (hourglass_atimer);
37953 hourglass_atimer = NULL;
37954 }
37955
37956 if (hourglass_shown_p)
37957 {
37958 Lisp_Object tail, frame;
37959
37960 block_input ();
37961
37962 FOR_EACH_FRAME (tail, frame)
37963 {
37964 struct frame *f = XFRAME (frame);
37965
37966 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37967 && FRAME_RIF (f)->hide_hourglass)
37968 FRAME_RIF (f)->hide_hourglass (f);
37969 #ifdef HAVE_NTGUI
37970
37971 else if (!FRAME_W32_P (f))
37972 w32_arrow_cursor ();
37973 #endif
37974 }
37975
37976 hourglass_shown_p = false;
37977 unblock_input ();
37978 }
37979 }
37980
37981
37982
37983
37984
37985
37986
37987
37988 static int
37989 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37990 struct window *w,
37991 struct face *original_face,
37992 struct face *mouse_face)
37993 {
37994 int sum = 0;
37995
37996 bool do_left_box_p = g->left_box_line_p;
37997 bool do_right_box_p = g->right_box_line_p;
37998
37999
38000
38001 if (g->type == IMAGE_GLYPH)
38002 {
38003 if (!row->reversed_p)
38004 {
38005 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
38006 g->u.img_id);
38007 do_left_box_p = g->left_box_line_p &&
38008 g->slice.img.x == 0;
38009 do_right_box_p = g->right_box_line_p &&
38010 g->slice.img.x + g->slice.img.width == img->width;
38011 }
38012 else
38013 {
38014 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
38015 g->u.img_id);
38016 do_left_box_p = g->left_box_line_p &&
38017 g->slice.img.x + g->slice.img.width == img->width;
38018 do_right_box_p = g->right_box_line_p &&
38019 g->slice.img.x == 0;
38020 }
38021 }
38022
38023
38024 if (do_left_box_p)
38025 sum -= max (0, original_face->box_vertical_line_width);
38026
38027
38028 if (do_right_box_p)
38029 sum -= max (0, original_face->box_vertical_line_width);
38030
38031 if (g->left_box_line_p)
38032 sum += max (0, mouse_face->box_vertical_line_width);
38033 if (g->right_box_line_p)
38034 sum += max (0, mouse_face->box_vertical_line_width);
38035
38036 return sum;
38037 }
38038
38039
38040
38041
38042
38043
38044
38045
38046
38047 static void
38048 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
38049 int *offset)
38050 {
38051 int sum = 0;
38052
38053 if (row->mode_line_p)
38054 return;
38055
38056 block_input ();
38057
38058 struct frame *f = WINDOW_XFRAME (w);
38059 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
38060 struct glyph *start, *end;
38061 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
38062 int hpos = w->phys_cursor.hpos;
38063 end = &row->glyphs[TEXT_AREA][hpos];
38064
38065 if (!row->reversed_p)
38066 {
38067 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
38068 hlinfo->mouse_face_beg_row)
38069 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
38070 else
38071 start = row->glyphs[TEXT_AREA];
38072 }
38073 else
38074 {
38075 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
38076 hlinfo->mouse_face_end_row)
38077 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
38078 else
38079 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
38080 }
38081
38082
38083
38084
38085 for ( ; row->reversed_p ? start > end : start < end;
38086 row->reversed_p ? --start : ++start)
38087 sum += adjust_glyph_width_for_mouse_face (start, row, w,
38088 FACE_FROM_ID (f, start->face_id),
38089 mouse_face);
38090
38091 if (row->reversed_p)
38092 sum = -sum;
38093
38094 *offset = sum;
38095
38096 unblock_input ();
38097 }
38098 #endif