1 |
/* Display generation from window structure and buffer text. |
/* Display generation from window structure and buffer text. |
2 |
Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99, 2000, 2001, 2002 |
Copyright (C) 1985,86,87,88,93,94,95,97,98,99, 2000, 2001, 2002, 2003 |
3 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of GNU Emacs. |
This file is part of GNU Emacs. |
64 |
| |
| |
65 |
X expose events -----+ |
X expose events -----+ |
66 |
|
|
67 |
What does redisplay? Obviously, it has to figure out somehow what |
What does redisplay do? Obviously, it has to figure out somehow what |
68 |
has been changed since the last time the display has been updated, |
has been changed since the last time the display has been updated, |
69 |
and to make these changes visible. Preferably it would do that in |
and to make these changes visible. Preferably it would do that in |
70 |
a moderately intelligent way, i.e. fast. |
a moderately intelligent way, i.e. fast. |
120 |
on various settings of buffers and windows, on overlays and text |
on various settings of buffers and windows, on overlays and text |
121 |
properties, on display tables, on selective display. The good news |
properties, on display tables, on selective display. The good news |
122 |
is that all this hairy stuff is hidden behind a small set of |
is that all this hairy stuff is hidden behind a small set of |
123 |
interface functions taking a iterator structure (struct it) |
interface functions taking an iterator structure (struct it) |
124 |
argument. |
argument. |
125 |
|
|
126 |
Iteration over things to be displayed is then simple. It is |
Iteration over things to be displayed is then simple. It is |
179 |
#include "charset.h" |
#include "charset.h" |
180 |
#include "indent.h" |
#include "indent.h" |
181 |
#include "commands.h" |
#include "commands.h" |
182 |
|
#include "keymap.h" |
183 |
#include "macros.h" |
#include "macros.h" |
184 |
#include "disptab.h" |
#include "disptab.h" |
185 |
#include "termhooks.h" |
#include "termhooks.h" |
188 |
#include "process.h" |
#include "process.h" |
189 |
#include "region-cache.h" |
#include "region-cache.h" |
190 |
#include "fontset.h" |
#include "fontset.h" |
191 |
|
#include "blockinput.h" |
192 |
|
|
193 |
#ifdef HAVE_X_WINDOWS |
#ifdef HAVE_X_WINDOWS |
194 |
#include "xterm.h" |
#include "xterm.h" |
198 |
#endif |
#endif |
199 |
#ifdef MAC_OS |
#ifdef MAC_OS |
200 |
#include "macterm.h" |
#include "macterm.h" |
201 |
|
|
202 |
|
Cursor No_Cursor; |
203 |
|
#endif |
204 |
|
|
205 |
|
#ifndef FRAME_X_OUTPUT |
206 |
|
#define FRAME_X_OUTPUT(f) ((f)->output_data.x) |
207 |
#endif |
#endif |
208 |
|
|
209 |
#define INFINITY 10000000 |
#define INFINITY 10000000 |
210 |
|
|
211 |
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) |
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ |
212 |
|
|| defined (USE_GTK) |
213 |
extern void set_frame_menubar P_ ((struct frame *f, int, int)); |
extern void set_frame_menubar P_ ((struct frame *f, int, int)); |
214 |
extern int pending_menu_activation; |
extern int pending_menu_activation; |
215 |
#endif |
#endif |
218 |
extern int command_loop_level; |
extern int command_loop_level; |
219 |
|
|
220 |
extern int minibuffer_auto_raise; |
extern int minibuffer_auto_raise; |
221 |
|
extern Lisp_Object Vminibuffer_list; |
222 |
|
|
223 |
extern Lisp_Object Qface; |
extern Lisp_Object Qface; |
224 |
|
extern Lisp_Object Qmode_line, Qmode_line_inactive, Qheader_line; |
225 |
|
|
226 |
extern Lisp_Object Voverriding_local_map; |
extern Lisp_Object Voverriding_local_map; |
227 |
extern Lisp_Object Voverriding_local_map_menu_flag; |
extern Lisp_Object Voverriding_local_map_menu_flag; |
228 |
extern Lisp_Object Qmenu_item; |
extern Lisp_Object Qmenu_item; |
229 |
|
extern Lisp_Object Qwhen; |
230 |
|
extern Lisp_Object Qhelp_echo; |
231 |
|
|
232 |
Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; |
Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; |
233 |
Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; |
Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; |
234 |
Lisp_Object Qredisplay_end_trigger_functions; |
Lisp_Object Qredisplay_end_trigger_functions; |
235 |
Lisp_Object Qinhibit_point_motion_hooks; |
Lisp_Object Qinhibit_point_motion_hooks; |
236 |
Lisp_Object QCeval, Qwhen, QCfile, QCdata, QCpropertize; |
Lisp_Object QCeval, QCfile, QCdata, QCpropertize; |
237 |
Lisp_Object Qfontified; |
Lisp_Object Qfontified; |
238 |
Lisp_Object Qgrow_only; |
Lisp_Object Qgrow_only; |
239 |
Lisp_Object Qinhibit_eval_during_redisplay; |
Lisp_Object Qinhibit_eval_during_redisplay; |
240 |
Lisp_Object Qbuffer_position, Qposition, Qobject; |
Lisp_Object Qbuffer_position, Qposition, Qobject; |
241 |
|
|
242 |
|
/* Cursor shapes */ |
243 |
|
Lisp_Object Qbar, Qhbar, Qbox, Qhollow; |
244 |
|
|
245 |
Lisp_Object Qrisky_local_variable; |
Lisp_Object Qrisky_local_variable; |
246 |
|
|
247 |
/* Holds the list (error). */ |
/* Holds the list (error). */ |
252 |
Lisp_Object Vfontification_functions; |
Lisp_Object Vfontification_functions; |
253 |
Lisp_Object Qfontification_functions; |
Lisp_Object Qfontification_functions; |
254 |
|
|
255 |
|
/* Non-zero means automatically select any window when the mouse |
256 |
|
cursor moves into it. */ |
257 |
|
int mouse_autoselect_window; |
258 |
|
|
259 |
/* Non-zero means draw tool bar buttons raised when the mouse moves |
/* Non-zero means draw tool bar buttons raised when the mouse moves |
260 |
over them. */ |
over them. */ |
261 |
|
|
274 |
|
|
275 |
int auto_resize_tool_bars_p; |
int auto_resize_tool_bars_p; |
276 |
|
|
277 |
|
/* Non-zero means draw block and hollow cursor as wide as the glyph |
278 |
|
under it. For example, if a block cursor is over a tab, it will be |
279 |
|
drawn as wide as that tab on the display. */ |
280 |
|
|
281 |
|
int x_stretch_cursor_p; |
282 |
|
|
283 |
/* Non-nil means don't actually do any redisplay. */ |
/* Non-nil means don't actually do any redisplay. */ |
284 |
|
|
285 |
Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay; |
Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay; |
299 |
Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise; |
Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise; |
300 |
Lisp_Object Qmargin; |
Lisp_Object Qmargin; |
301 |
extern Lisp_Object Qheight; |
extern Lisp_Object Qheight; |
302 |
|
extern Lisp_Object QCwidth, QCheight, QCascent; |
303 |
|
|
304 |
/* Non-nil means highlight trailing whitespace. */ |
/* Non-nil means highlight trailing whitespace. */ |
305 |
|
|
557 |
/* Non-zero means we want a hollow cursor in windows that are not |
/* Non-zero means we want a hollow cursor in windows that are not |
558 |
selected. Zero means there's no cursor in such windows. */ |
selected. Zero means there's no cursor in such windows. */ |
559 |
|
|
560 |
int cursor_in_non_selected_windows; |
Lisp_Object Vcursor_in_non_selected_windows; |
561 |
Lisp_Object Qcursor_in_non_selected_windows; |
Lisp_Object Qcursor_in_non_selected_windows; |
562 |
|
|
563 |
|
/* How to blink the default frame cursor off. */ |
564 |
|
Lisp_Object Vblink_cursor_alist; |
565 |
|
|
566 |
/* A scratch glyph row with contents used for generating truncation |
/* A scratch glyph row with contents used for generating truncation |
567 |
glyphs. Also used in direct_output_for_insert. */ |
glyphs. Also used in direct_output_for_insert. */ |
568 |
|
|
719 |
MOVE_NEWLINE_OR_CR |
MOVE_NEWLINE_OR_CR |
720 |
}; |
}; |
721 |
|
|
722 |
|
/* This counter is used to clear the face cache every once in a while |
723 |
|
in redisplay_internal. It is incremented for each redisplay. |
724 |
|
Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is |
725 |
|
cleared. */ |
726 |
|
|
727 |
|
#define CLEAR_FACE_CACHE_COUNT 500 |
728 |
|
static int clear_face_cache_count; |
729 |
|
|
730 |
|
/* Record the previous terminal frame we displayed. */ |
731 |
|
|
732 |
|
static struct frame *previous_terminal_frame; |
733 |
|
|
734 |
|
/* Non-zero while redisplay_internal is in progress. */ |
735 |
|
|
736 |
|
int redisplaying_p; |
737 |
|
|
738 |
|
/* Non-zero means don't free realized faces. Bound while freeing |
739 |
|
realized faces is dangerous because glyph matrices might still |
740 |
|
reference them. */ |
741 |
|
|
742 |
|
int inhibit_free_realized_faces; |
743 |
|
Lisp_Object Qinhibit_free_realized_faces; |
744 |
|
|
745 |
|
/* If a string, XTread_socket generates an event to display that string. |
746 |
|
(The display is done in read_char.) */ |
747 |
|
|
748 |
|
Lisp_Object help_echo_string; |
749 |
|
Lisp_Object help_echo_window; |
750 |
|
Lisp_Object help_echo_object; |
751 |
|
int help_echo_pos; |
752 |
|
|
753 |
|
/* Temporary variable for XTread_socket. */ |
754 |
|
|
755 |
|
Lisp_Object previous_help_echo_string; |
756 |
|
|
757 |
|
|
758 |
|
|
759 |
/* Function prototypes. */ |
/* Function prototypes. */ |
777 |
static void reconsider_clip_changes P_ ((struct window *, struct buffer *)); |
static void reconsider_clip_changes P_ ((struct window *, struct buffer *)); |
778 |
static int text_outside_line_unchanged_p P_ ((struct window *, int, int)); |
static int text_outside_line_unchanged_p P_ ((struct window *, int, int)); |
779 |
static void store_frame_title_char P_ ((char)); |
static void store_frame_title_char P_ ((char)); |
780 |
static int store_frame_title P_ ((unsigned char *, int, int)); |
static int store_frame_title P_ ((const unsigned char *, int, int)); |
781 |
static void x_consider_frame_title P_ ((Lisp_Object)); |
static void x_consider_frame_title P_ ((Lisp_Object)); |
782 |
static void handle_stop P_ ((struct it *)); |
static void handle_stop P_ ((struct it *)); |
783 |
static int tool_bar_lines_needed P_ ((struct frame *)); |
static int tool_bar_lines_needed P_ ((struct frame *)); |
796 |
static int display_echo_area_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT)); |
static int display_echo_area_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT)); |
797 |
static int resize_mini_window_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT)); |
static int resize_mini_window_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT)); |
798 |
static Lisp_Object unwind_redisplay P_ ((Lisp_Object)); |
static Lisp_Object unwind_redisplay P_ ((Lisp_Object)); |
799 |
static int string_char_and_length P_ ((unsigned char *, int, int *)); |
static int string_char_and_length P_ ((const unsigned char *, int, int *)); |
800 |
static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object, |
static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object, |
801 |
struct text_pos)); |
struct text_pos)); |
802 |
static int compute_window_start_on_continuation_line P_ ((struct window *)); |
static int compute_window_start_on_continuation_line P_ ((struct window *)); |
806 |
static void extend_face_to_end_of_line P_ ((struct it *)); |
static void extend_face_to_end_of_line P_ ((struct it *)); |
807 |
static int append_space P_ ((struct it *, int)); |
static int append_space P_ ((struct it *, int)); |
808 |
static int make_cursor_line_fully_visible P_ ((struct window *)); |
static int make_cursor_line_fully_visible P_ ((struct window *)); |
809 |
static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int)); |
static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int, int)); |
810 |
static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *)); |
static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *)); |
811 |
static int trailing_whitespace_p P_ ((int)); |
static int trailing_whitespace_p P_ ((int)); |
812 |
static int message_log_check_duplicate P_ ((int, int, int, int)); |
static int message_log_check_duplicate P_ ((int, int, int, int)); |
827 |
static int display_mode_lines P_ ((struct window *)); |
static int display_mode_lines P_ ((struct window *)); |
828 |
static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object)); |
static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object)); |
829 |
static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object, Lisp_Object, int)); |
static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object, Lisp_Object, int)); |
830 |
|
static int store_mode_line_string P_ ((char *, Lisp_Object, int, int, int, Lisp_Object)); |
831 |
static char *decode_mode_spec P_ ((struct window *, int, int, int, int *)); |
static char *decode_mode_spec P_ ((struct window *, int, int, int, int *)); |
832 |
static void display_menu_bar P_ ((struct window *)); |
static void display_menu_bar P_ ((struct window *)); |
833 |
static int display_count_lines P_ ((int, int, int, int, int *)); |
static int display_count_lines P_ ((int, int, int, int, int *)); |
889 |
static void build_desired_tool_bar_string P_ ((struct frame *f)); |
static void build_desired_tool_bar_string P_ ((struct frame *f)); |
890 |
static int redisplay_tool_bar P_ ((struct frame *)); |
static int redisplay_tool_bar P_ ((struct frame *)); |
891 |
static void display_tool_bar_line P_ ((struct it *)); |
static void display_tool_bar_line P_ ((struct it *)); |
892 |
|
static void notice_overwritten_cursor P_ ((struct window *, |
893 |
|
enum glyph_row_area, |
894 |
|
int, int, int, int)); |
895 |
|
|
896 |
|
|
897 |
|
|
898 |
#endif /* HAVE_WINDOW_SYSTEM */ |
#endif /* HAVE_WINDOW_SYSTEM */ |
899 |
|
|
902 |
Window display dimensions |
Window display dimensions |
903 |
***********************************************************************/ |
***********************************************************************/ |
904 |
|
|
905 |
/* Return the window-relative maximum y + 1 for glyph rows displaying |
/* Return the bottom boundary y-position for text lines in window W. |
906 |
text in window W. This is the height of W minus the height of a |
This is the first y position at which a line cannot start. |
907 |
mode line, if any. */ |
It is relative to the top of the window. |
908 |
|
|
909 |
|
This is the height of W minus the height of a mode line, if any. */ |
910 |
|
|
911 |
INLINE int |
INLINE int |
912 |
window_text_bottom_y (w) |
window_text_bottom_y (w) |
1220 |
|
|
1221 |
static INLINE int |
static INLINE int |
1222 |
string_char_and_length (str, maxlen, len) |
string_char_and_length (str, maxlen, len) |
1223 |
unsigned char *str; |
const unsigned char *str; |
1224 |
int maxlen, *len; |
int maxlen, *len; |
1225 |
{ |
{ |
1226 |
int c; |
int c; |
1251 |
if (STRING_MULTIBYTE (string)) |
if (STRING_MULTIBYTE (string)) |
1252 |
{ |
{ |
1253 |
int rest = SBYTES (string) - BYTEPOS (pos); |
int rest = SBYTES (string) - BYTEPOS (pos); |
1254 |
unsigned char *p = SDATA (string) + BYTEPOS (pos); |
const unsigned char *p = SDATA (string) + BYTEPOS (pos); |
1255 |
int len; |
int len; |
1256 |
|
|
1257 |
while (nchars--) |
while (nchars--) |
1369 |
BYTEPOS (*newpos) = CHARPOS (*newpos); |
BYTEPOS (*newpos) = CHARPOS (*newpos); |
1370 |
} |
} |
1371 |
|
|
1372 |
|
/* EXPORT: |
1373 |
|
Return an estimation of the pixel height of mode or top lines on |
1374 |
|
frame F. FACE_ID specifies what line's height to estimate. */ |
1375 |
|
|
1376 |
|
int |
1377 |
|
estimate_mode_line_height (f, face_id) |
1378 |
|
struct frame *f; |
1379 |
|
enum face_id face_id; |
1380 |
|
{ |
1381 |
|
#ifdef HAVE_WINDOW_SYSTEM |
1382 |
|
if (FRAME_WINDOW_P (f)) |
1383 |
|
{ |
1384 |
|
int height = FONT_HEIGHT (FRAME_FONT (f)); |
1385 |
|
|
1386 |
|
/* This function is called so early when Emacs starts that the face |
1387 |
|
cache and mode line face are not yet initialized. */ |
1388 |
|
if (FRAME_FACE_CACHE (f)) |
1389 |
|
{ |
1390 |
|
struct face *face = FACE_FROM_ID (f, face_id); |
1391 |
|
if (face) |
1392 |
|
{ |
1393 |
|
if (face->font) |
1394 |
|
height = FONT_HEIGHT (face->font); |
1395 |
|
if (face->box_line_width > 0) |
1396 |
|
height += 2 * face->box_line_width; |
1397 |
|
} |
1398 |
|
} |
1399 |
|
|
1400 |
|
return height; |
1401 |
|
} |
1402 |
|
#endif |
1403 |
|
|
1404 |
|
return 1; |
1405 |
|
} |
1406 |
|
|
1407 |
|
/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph |
1408 |
|
co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the |
1409 |
|
glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do |
1410 |
|
not force the value into range. */ |
1411 |
|
|
1412 |
|
void |
1413 |
|
pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip) |
1414 |
|
FRAME_PTR f; |
1415 |
|
register int pix_x, pix_y; |
1416 |
|
int *x, *y; |
1417 |
|
NativeRectangle *bounds; |
1418 |
|
int noclip; |
1419 |
|
{ |
1420 |
|
|
1421 |
|
#ifdef HAVE_WINDOW_SYSTEM |
1422 |
|
if (FRAME_WINDOW_P (f)) |
1423 |
|
{ |
1424 |
|
/* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down |
1425 |
|
even for negative values. */ |
1426 |
|
if (pix_x < 0) |
1427 |
|
pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1; |
1428 |
|
if (pix_y < 0) |
1429 |
|
pix_y -= FRAME_X_OUTPUT(f)->line_height - 1; |
1430 |
|
|
1431 |
|
pix_x = PIXEL_TO_CHAR_COL (f, pix_x); |
1432 |
|
pix_y = PIXEL_TO_CHAR_ROW (f, pix_y); |
1433 |
|
|
1434 |
|
if (bounds) |
1435 |
|
STORE_NATIVE_RECT (*bounds, |
1436 |
|
CHAR_TO_PIXEL_COL (f, pix_x), |
1437 |
|
CHAR_TO_PIXEL_ROW (f, pix_y), |
1438 |
|
FONT_WIDTH (FRAME_FONT (f)) - 1, |
1439 |
|
FRAME_X_OUTPUT (f)->line_height - 1); |
1440 |
|
|
1441 |
|
if (!noclip) |
1442 |
|
{ |
1443 |
|
if (pix_x < 0) |
1444 |
|
pix_x = 0; |
1445 |
|
else if (pix_x > FRAME_WINDOW_WIDTH (f)) |
1446 |
|
pix_x = FRAME_WINDOW_WIDTH (f); |
1447 |
|
|
1448 |
|
if (pix_y < 0) |
1449 |
|
pix_y = 0; |
1450 |
|
else if (pix_y > f->height) |
1451 |
|
pix_y = f->height; |
1452 |
|
} |
1453 |
|
} |
1454 |
|
#endif |
1455 |
|
|
1456 |
|
*x = pix_x; |
1457 |
|
*y = pix_y; |
1458 |
|
} |
1459 |
|
|
1460 |
|
|
1461 |
|
/* Given HPOS/VPOS in the current matrix of W, return corresponding |
1462 |
|
frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we |
1463 |
|
can't tell the positions because W's display is not up to date, |
1464 |
|
return 0. */ |
1465 |
|
|
1466 |
|
int |
1467 |
|
glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y) |
1468 |
|
struct window *w; |
1469 |
|
int hpos, vpos; |
1470 |
|
int *frame_x, *frame_y; |
1471 |
|
{ |
1472 |
|
#ifdef HAVE_WINDOW_SYSTEM |
1473 |
|
if (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w)))) |
1474 |
|
{ |
1475 |
|
int success_p; |
1476 |
|
|
1477 |
|
xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w); |
1478 |
|
xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h); |
1479 |
|
|
1480 |
|
if (display_completed) |
1481 |
|
{ |
1482 |
|
struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos); |
1483 |
|
struct glyph *glyph = row->glyphs[TEXT_AREA]; |
1484 |
|
struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]); |
1485 |
|
|
1486 |
|
hpos = row->x; |
1487 |
|
vpos = row->y; |
1488 |
|
while (glyph < end) |
1489 |
|
{ |
1490 |
|
hpos += glyph->pixel_width; |
1491 |
|
++glyph; |
1492 |
|
} |
1493 |
|
|
1494 |
|
success_p = 1; |
1495 |
|
} |
1496 |
|
else |
1497 |
|
{ |
1498 |
|
hpos = vpos = 0; |
1499 |
|
success_p = 0; |
1500 |
|
} |
1501 |
|
|
1502 |
|
*frame_x = WINDOW_TO_FRAME_PIXEL_X (w, hpos); |
1503 |
|
*frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, vpos); |
1504 |
|
return success_p; |
1505 |
|
} |
1506 |
|
#endif |
1507 |
|
|
1508 |
|
*frame_x = hpos; |
1509 |
|
*frame_y = vpos; |
1510 |
|
return 1; |
1511 |
|
} |
1512 |
|
|
1513 |
|
|
1514 |
|
#ifdef HAVE_WINDOW_SYSTEM |
1515 |
|
|
1516 |
|
/* Find the glyph under window-relative coordinates X/Y in window W. |
1517 |
|
Consider only glyphs from buffer text, i.e. no glyphs from overlay |
1518 |
|
strings. Return in *HPOS and *VPOS the row and column number of |
1519 |
|
the glyph found. Return in *AREA the glyph area containing X. |
1520 |
|
Value is a pointer to the glyph found or null if X/Y is not on |
1521 |
|
text, or we can't tell because W's current matrix is not up to |
1522 |
|
date. */ |
1523 |
|
|
1524 |
|
static struct glyph * |
1525 |
|
x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p) |
1526 |
|
struct window *w; |
1527 |
|
int x, y; |
1528 |
|
int *hpos, *vpos, *area; |
1529 |
|
int buffer_only_p; |
1530 |
|
{ |
1531 |
|
struct glyph *glyph, *end; |
1532 |
|
struct glyph_row *row = NULL; |
1533 |
|
int x0, i, left_area_width; |
1534 |
|
|
1535 |
|
/* Find row containing Y. Give up if some row is not enabled. */ |
1536 |
|
for (i = 0; i < w->current_matrix->nrows; ++i) |
1537 |
|
{ |
1538 |
|
row = MATRIX_ROW (w->current_matrix, i); |
1539 |
|
if (!row->enabled_p) |
1540 |
|
return NULL; |
1541 |
|
if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row)) |
1542 |
|
break; |
1543 |
|
} |
1544 |
|
|
1545 |
|
*vpos = i; |
1546 |
|
*hpos = 0; |
1547 |
|
|
1548 |
|
/* Give up if Y is not in the window. */ |
1549 |
|
if (i == w->current_matrix->nrows) |
1550 |
|
return NULL; |
1551 |
|
|
1552 |
|
/* Get the glyph area containing X. */ |
1553 |
|
if (w->pseudo_window_p) |
1554 |
|
{ |
1555 |
|
*area = TEXT_AREA; |
1556 |
|
x0 = 0; |
1557 |
|
} |
1558 |
|
else |
1559 |
|
{ |
1560 |
|
left_area_width = window_box_width (w, LEFT_MARGIN_AREA); |
1561 |
|
if (x < left_area_width) |
1562 |
|
{ |
1563 |
|
*area = LEFT_MARGIN_AREA; |
1564 |
|
x0 = 0; |
1565 |
|
} |
1566 |
|
else if (x < left_area_width + window_box_width (w, TEXT_AREA)) |
1567 |
|
{ |
1568 |
|
*area = TEXT_AREA; |
1569 |
|
x0 = row->x + left_area_width; |
1570 |
|
} |
1571 |
|
else |
1572 |
|
{ |
1573 |
|
*area = RIGHT_MARGIN_AREA; |
1574 |
|
x0 = left_area_width + window_box_width (w, TEXT_AREA); |
1575 |
|
} |
1576 |
|
} |
1577 |
|
|
1578 |
|
/* Find glyph containing X. */ |
1579 |
|
glyph = row->glyphs[*area]; |
1580 |
|
end = glyph + row->used[*area]; |
1581 |
|
while (glyph < end) |
1582 |
|
{ |
1583 |
|
if (x < x0 + glyph->pixel_width) |
1584 |
|
{ |
1585 |
|
if (w->pseudo_window_p) |
1586 |
|
break; |
1587 |
|
else if (!buffer_only_p || BUFFERP (glyph->object)) |
1588 |
|
break; |
1589 |
|
} |
1590 |
|
|
1591 |
|
x0 += glyph->pixel_width; |
1592 |
|
++glyph; |
1593 |
|
} |
1594 |
|
|
1595 |
|
if (glyph == end) |
1596 |
|
return NULL; |
1597 |
|
|
1598 |
|
*hpos = glyph - row->glyphs[*area]; |
1599 |
|
return glyph; |
1600 |
|
} |
1601 |
|
|
1602 |
|
|
1603 |
|
/* EXPORT: |
1604 |
|
Convert frame-relative x/y to coordinates relative to window W. |
1605 |
|
Takes pseudo-windows into account. */ |
1606 |
|
|
1607 |
|
void |
1608 |
|
frame_to_window_pixel_xy (w, x, y) |
1609 |
|
struct window *w; |
1610 |
|
int *x, *y; |
1611 |
|
{ |
1612 |
|
if (w->pseudo_window_p) |
1613 |
|
{ |
1614 |
|
/* A pseudo-window is always full-width, and starts at the |
1615 |
|
left edge of the frame, plus a frame border. */ |
1616 |
|
struct frame *f = XFRAME (w->frame); |
1617 |
|
*x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f); |
1618 |
|
*y = FRAME_TO_WINDOW_PIXEL_Y (w, *y); |
1619 |
|
} |
1620 |
|
else |
1621 |
|
{ |
1622 |
|
*x = FRAME_TO_WINDOW_PIXEL_X (w, *x); |
1623 |
|
*y = FRAME_TO_WINDOW_PIXEL_Y (w, *y); |
1624 |
|
} |
1625 |
|
} |
1626 |
|
|
1627 |
|
/* EXPORT: |
1628 |
|
Return in *R the clipping rectangle for glyph string S. */ |
1629 |
|
|
1630 |
|
void |
1631 |
|
get_glyph_string_clip_rect (s, nr) |
1632 |
|
struct glyph_string *s; |
1633 |
|
NativeRectangle *nr; |
1634 |
|
{ |
1635 |
|
XRectangle r; |
1636 |
|
|
1637 |
|
if (s->row->full_width_p) |
1638 |
|
{ |
1639 |
|
/* Draw full-width. X coordinates are relative to S->w->left. */ |
1640 |
|
int canon_x = CANON_X_UNIT (s->f); |
1641 |
|
|
1642 |
|
r.x = WINDOW_LEFT_MARGIN (s->w) * canon_x; |
1643 |
|
r.width = XFASTINT (s->w->width) * canon_x; |
1644 |
|
|
1645 |
|
if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f)) |
1646 |
|
{ |
1647 |
|
int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x; |
1648 |
|
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f)) |
1649 |
|
r.x -= width; |
1650 |
|
} |
1651 |
|
|
1652 |
|
r.x += FRAME_INTERNAL_BORDER_WIDTH (s->f); |
1653 |
|
|
1654 |
|
/* Unless displaying a mode or menu bar line, which are always |
1655 |
|
fully visible, clip to the visible part of the row. */ |
1656 |
|
if (s->w->pseudo_window_p) |
1657 |
|
r.height = s->row->visible_height; |
1658 |
|
else |
1659 |
|
r.height = s->height; |
1660 |
|
} |
1661 |
|
else |
1662 |
|
{ |
1663 |
|
/* This is a text line that may be partially visible. */ |
1664 |
|
r.x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0); |
1665 |
|
r.width = window_box_width (s->w, s->area); |
1666 |
|
r.height = s->row->visible_height; |
1667 |
|
} |
1668 |
|
|
1669 |
|
/* If S draws overlapping rows, it's sufficient to use the top and |
1670 |
|
bottom of the window for clipping because this glyph string |
1671 |
|
intentionally draws over other lines. */ |
1672 |
|
if (s->for_overlaps_p) |
1673 |
|
{ |
1674 |
|
r.y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w); |
1675 |
|
r.height = window_text_bottom_y (s->w) - r.y; |
1676 |
|
} |
1677 |
|
else |
1678 |
|
{ |
1679 |
|
/* Don't use S->y for clipping because it doesn't take partially |
1680 |
|
visible lines into account. For example, it can be negative for |
1681 |
|
partially visible lines at the top of a window. */ |
1682 |
|
if (!s->row->full_width_p |
1683 |
|
&& MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row)) |
1684 |
|
r.y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w); |
1685 |
|
else |
1686 |
|
r.y = max (0, s->row->y); |
1687 |
|
|
1688 |
|
/* If drawing a tool-bar window, draw it over the internal border |
1689 |
|
at the top of the window. */ |
1690 |
|
if (s->w == XWINDOW (s->f->tool_bar_window)) |
1691 |
|
r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f); |
1692 |
|
} |
1693 |
|
|
1694 |
|
r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y); |
1695 |
|
|
1696 |
|
#ifdef HAVE_NTGUI |
1697 |
|
/* ++KFS: From W32 port, but it looks ok for all platforms to me. */ |
1698 |
|
/* If drawing the cursor, don't let glyph draw outside its |
1699 |
|
advertised boundaries. Cleartype does this under some circumstances. */ |
1700 |
|
if (s->hl == DRAW_CURSOR) |
1701 |
|
{ |
1702 |
|
if (s->x > r.x) |
1703 |
|
{ |
1704 |
|
r.width -= s->x - r.x; |
1705 |
|
r.x = s->x; |
1706 |
|
} |
1707 |
|
r.width = min (r.width, s->first_glyph->pixel_width); |
1708 |
|
} |
1709 |
|
#endif |
1710 |
|
|
1711 |
|
#ifdef CONVERT_FROM_XRECT |
1712 |
|
CONVERT_FROM_XRECT (r, *nr); |
1713 |
|
#else |
1714 |
|
*nr = r; |
1715 |
|
#endif |
1716 |
|
} |
1717 |
|
|
1718 |
|
#endif /* HAVE_WINDOW_SYSTEM */ |
1719 |
|
|
1720 |
|
|
1721 |
/*********************************************************************** |
/*********************************************************************** |
1746 |
val = Qnil; |
val = Qnil; |
1747 |
else |
else |
1748 |
{ |
{ |
1749 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
1750 |
struct gcpro gcpro1; |
struct gcpro gcpro1; |
1751 |
|
|
1752 |
GCPRO1 (sexpr); |
GCPRO1 (sexpr); |
1778 |
val = Qnil; |
val = Qnil; |
1779 |
else |
else |
1780 |
{ |
{ |
1781 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
1782 |
struct gcpro gcpro1; |
struct gcpro gcpro1; |
1783 |
|
|
1784 |
GCPRO1 (args[0]); |
GCPRO1 (args[0]); |
1921 |
|
|
1922 |
/* If face attributes have been changed since the last redisplay, |
/* If face attributes have been changed since the last redisplay, |
1923 |
free realized faces now because they depend on face definitions |
free realized faces now because they depend on face definitions |
1924 |
that might have changed. */ |
that might have changed. Don't free faces while there might be |
1925 |
if (face_change_count) |
desired matrices pending which reference these faces. */ |
1926 |
|
if (face_change_count && !inhibit_free_realized_faces) |
1927 |
{ |
{ |
1928 |
face_change_count = 0; |
face_change_count = 0; |
1929 |
free_all_realized_faces (Qnil); |
free_all_realized_faces (Qnil); |
2181 |
|| FETCH_BYTE (BYTEPOS (pos) - 1) == '\n'); |
|| FETCH_BYTE (BYTEPOS (pos) - 1) == '\n'); |
2182 |
if (!start_at_line_beg_p) |
if (!start_at_line_beg_p) |
2183 |
{ |
{ |
2184 |
|
int new_x; |
2185 |
|
|
2186 |
reseat_at_previous_visible_line_start (it); |
reseat_at_previous_visible_line_start (it); |
2187 |
move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS); |
move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS); |
2188 |
|
|
2189 |
|
new_x = it->current_x + it->pixel_width; |
2190 |
|
|
2191 |
/* If lines are continued, this line may end in the middle |
/* If lines are continued, this line may end in the middle |
2192 |
of a multi-glyph character (e.g. a control character |
of a multi-glyph character (e.g. a control character |
2193 |
displayed as \003, or in the middle of an overlay |
displayed as \003, or in the middle of an overlay |
2194 |
string). In this case move_it_to above will not have |
string). In this case move_it_to above will not have |
2195 |
taken us to the start of the continuation line but to the |
taken us to the start of the continuation line but to the |
2196 |
end of the continued line. */ |
end of the continued line. */ |
2197 |
if (it->current_x > 0) |
if (it->current_x > 0 |
2198 |
|
&& !it->truncate_lines_p /* Lines are continued. */ |
2199 |
|
&& (/* And glyph doesn't fit on the line. */ |
2200 |
|
new_x > it->last_visible_x |
2201 |
|
/* Or it fits exactly and we're on a window |
2202 |
|
system frame. */ |
2203 |
|
|| (new_x == it->last_visible_x |
2204 |
|
&& FRAME_WINDOW_P (it->f)))) |
2205 |
{ |
{ |
2206 |
if (it->current.dpvec_index >= 0 |
if (it->current.dpvec_index >= 0 |
2207 |
|| it->current.overlay_string_index >= 0) |
|| it->current.overlay_string_index >= 0) |
2308 |
|
|
2309 |
for (i = 0; i < it->n_overlay_strings; ++i) |
for (i = 0; i < it->n_overlay_strings; ++i) |
2310 |
{ |
{ |
2311 |
char *s = SDATA (it->overlay_strings[i]); |
const char *s = SDATA (it->overlay_strings[i]); |
2312 |
char *e = s + SBYTES (it->overlay_strings[i]); |
const char *e = s + SBYTES (it->overlay_strings[i]); |
2313 |
|
|
2314 |
while (s < e && *s != '\n') |
while (s < e && *s != '\n') |
2315 |
++s; |
++s; |
2671 |
prop = Fget_char_property (pos, Qfontified, Qnil), |
prop = Fget_char_property (pos, Qfontified, Qnil), |
2672 |
NILP (prop))) |
NILP (prop))) |
2673 |
{ |
{ |
2674 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
2675 |
Lisp_Object val; |
Lisp_Object val; |
2676 |
|
|
2677 |
val = Vfontification_functions; |
val = Vfontification_functions; |
2915 |
suitable for unibyte text if IT->string is unibyte. */ |
suitable for unibyte text if IT->string is unibyte. */ |
2916 |
if (STRING_MULTIBYTE (it->string)) |
if (STRING_MULTIBYTE (it->string)) |
2917 |
{ |
{ |
2918 |
unsigned char *p = SDATA (it->string) + BYTEPOS (pos); |
const unsigned char *p = SDATA (it->string) + BYTEPOS (pos); |
2919 |
int rest = SBYTES (it->string) - BYTEPOS (pos); |
int rest = SBYTES (it->string) - BYTEPOS (pos); |
2920 |
int c, len; |
int c, len; |
2921 |
struct face *face = FACE_FROM_ID (it->f, face_id); |
struct face *face = FACE_FROM_ID (it->f, face_id); |
2958 |
suitable for unibyte text if current_buffer is unibyte. */ |
suitable for unibyte text if current_buffer is unibyte. */ |
2959 |
if (it->multibyte_p) |
if (it->multibyte_p) |
2960 |
{ |
{ |
2961 |
int c = FETCH_MULTIBYTE_CHAR (CHARPOS (pos)); |
int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos)); |
2962 |
struct face *face = FACE_FROM_ID (it->f, face_id); |
struct face *face = FACE_FROM_ID (it->f, face_id); |
2963 |
face_id = FACE_FOR_CHAR (it->f, face, c); |
face_id = FACE_FOR_CHAR (it->f, face, c); |
2964 |
} |
} |
3294 |
|
|
3295 |
if (!NILP (form) && !EQ (form, Qt)) |
if (!NILP (form) && !EQ (form, Qt)) |
3296 |
{ |
{ |
3297 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
3298 |
struct gcpro gcpro1; |
struct gcpro gcpro1; |
3299 |
|
|
3300 |
/* Bind `object' to the object having the `display' property, a |
/* Bind `object' to the object having the `display' property, a |
3365 |
/* Evaluate IT->font_height with `height' bound to the |
/* Evaluate IT->font_height with `height' bound to the |
3366 |
current specified height to get the new height. */ |
current specified height to get the new height. */ |
3367 |
Lisp_Object value; |
Lisp_Object value; |
3368 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
3369 |
|
|
3370 |
specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]); |
specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]); |
3371 |
value = safe_eval (it->font_height); |
value = safe_eval (it->font_height); |
3545 |
prop = XCDR (prop); |
prop = XCDR (prop); |
3546 |
} |
} |
3547 |
|
|
3548 |
|
if (STRINGP (prop)) |
3549 |
|
return 1; |
3550 |
|
|
3551 |
if (!CONSP (prop)) |
if (!CONSP (prop)) |
3552 |
return 0; |
return 0; |
3553 |
|
|
4131 |
it->stop_charpos = 0; |
it->stop_charpos = 0; |
4132 |
xassert (STRINGP (it->string)); |
xassert (STRINGP (it->string)); |
4133 |
it->end_charpos = SCHARS (it->string); |
it->end_charpos = SCHARS (it->string); |
4134 |
it->multibyte_p = SMBP (it->string); |
it->multibyte_p = STRING_MULTIBYTE (it->string); |
4135 |
it->method = next_element_from_string; |
it->method = next_element_from_string; |
4136 |
} |
} |
4137 |
else |
else |
4282 |
n += STRINGP (it->string) ? 0 : 1) |
n += STRINGP (it->string) ? 0 : 1) |
4283 |
{ |
{ |
4284 |
if (!get_next_display_element (it)) |
if (!get_next_display_element (it)) |
4285 |
break; |
return 0; |
4286 |
newline_found_p = it->what == IT_CHARACTER && it->c == '\n'; |
newline_found_p = it->what == IT_CHARACTER && it->c == '\n'; |
4287 |
set_iterator_to_next (it, 0); |
set_iterator_to_next (it, 0); |
4288 |
} |
} |
4289 |
|
|
4290 |
/* If we didn't find a newline near enough, see if we can use a |
/* If we didn't find a newline near enough, see if we can use a |
4291 |
short-cut. */ |
short-cut. */ |
4292 |
if (n == MAX_NEWLINE_DISTANCE) |
if (!newline_found_p) |
4293 |
{ |
{ |
4294 |
int start = IT_CHARPOS (*it); |
int start = IT_CHARPOS (*it); |
4295 |
int limit = find_next_newline_no_quit (start, 1); |
int limit = find_next_newline_no_quit (start, 1); |
4353 |
are invisible. */ |
are invisible. */ |
4354 |
if (it->selective > 0 |
if (it->selective > 0 |
4355 |
&& indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it), |
&& indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it), |
4356 |
(float) it->selective)) /* iftc */ |
(double) it->selective)) /* iftc */ |
4357 |
visible_p = 0; |
visible_p = 0; |
4358 |
else |
else |
4359 |
{ |
{ |
4413 |
if (it->selective > 0) |
if (it->selective > 0) |
4414 |
while (IT_CHARPOS (*it) < ZV |
while (IT_CHARPOS (*it) < ZV |
4415 |
&& indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it), |
&& indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it), |
4416 |
(float) it->selective)) /* iftc */ |
(double) it->selective)) /* iftc */ |
4417 |
{ |
{ |
4418 |
xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n'); |
xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n'); |
4419 |
newline_found_p = forward_to_next_line_start (it, &skipped_p); |
newline_found_p = forward_to_next_line_start (it, &skipped_p); |
4619 |
get_next_display_element (it) |
get_next_display_element (it) |
4620 |
struct it *it; |
struct it *it; |
4621 |
{ |
{ |
4622 |
/* Non-zero means that we found an display element. Zero means that |
/* Non-zero means that we found a display element. Zero means that |
4623 |
we hit the end of what we iterate over. Performance note: the |
we hit the end of what we iterate over. Performance note: the |
4624 |
function pointer `method' used here turns out to be faster than |
function pointer `method' used here turns out to be faster than |
4625 |
using a sequence of if-statements. */ |
using a sequence of if-statements. */ |
4671 |
the translation. This could easily be changed but I |
the translation. This could easily be changed but I |
4672 |
don't believe that it is worth doing. |
don't believe that it is worth doing. |
4673 |
|
|
4674 |
Non-printable multibyte characters are also translated |
If it->multibyte_p is nonzero, eight-bit characters and |
4675 |
octal form. */ |
non-printable multibyte characters are also translated to |
4676 |
|
octal form. |
4677 |
|
|
4678 |
|
If it->multibyte_p is zero, eight-bit characters that |
4679 |
|
don't have corresponding multibyte char code are also |
4680 |
|
translated to octal form. */ |
4681 |
else if ((it->c < ' ' |
else if ((it->c < ' ' |
4682 |
&& (it->area != TEXT_AREA |
&& (it->area != TEXT_AREA |
4683 |
|| (it->c != '\n' && it->c != '\t'))) |
|| (it->c != '\n' && it->c != '\t'))) |
4684 |
|| (it->c >= 127 |
|| (it->multibyte_p |
4685 |
&& it->len == 1) |
? ((it->c >= 127 |
4686 |
|| !CHAR_PRINTABLE_P (it->c)) |
&& it->len == 1) |
4687 |
|
|| !CHAR_PRINTABLE_P (it->c)) |
4688 |
|
: (it->c >= 127 |
4689 |
|
&& it->c == unibyte_char_to_multibyte (it->c)))) |
4690 |
{ |
{ |
4691 |
/* IT->c is a control character which must be displayed |
/* IT->c is a control character which must be displayed |
4692 |
either as '\003' or as `^C' where the '\\' and '^' |
either as '\003' or as `^C' where the '\\' and '^' |
5053 |
else if (STRING_MULTIBYTE (it->string)) |
else if (STRING_MULTIBYTE (it->string)) |
5054 |
{ |
{ |
5055 |
int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it); |
int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it); |
5056 |
unsigned char *s = SDATA (it->string) + IT_STRING_BYTEPOS (*it); |
const unsigned char *s = (SDATA (it->string) |
5057 |
|
+ IT_STRING_BYTEPOS (*it)); |
5058 |
it->c = string_char_and_length (s, remaining, &it->len); |
it->c = string_char_and_length (s, remaining, &it->len); |
5059 |
} |
} |
5060 |
else |
else |
5083 |
else if (STRING_MULTIBYTE (it->string)) |
else if (STRING_MULTIBYTE (it->string)) |
5084 |
{ |
{ |
5085 |
int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it); |
int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it); |
5086 |
unsigned char *s = SDATA (it->string) + IT_STRING_BYTEPOS (*it); |
const unsigned char *s = (SDATA (it->string) |
5087 |
|
+ IT_STRING_BYTEPOS (*it)); |
5088 |
it->c = string_char_and_length (s, maxlen, &it->len); |
it->c = string_char_and_length (s, maxlen, &it->len); |
5089 |
} |
} |
5090 |
else |
else |
5316 |
&& IT_CHARPOS (*it) + 1 < ZV |
&& IT_CHARPOS (*it) + 1 < ZV |
5317 |
&& indented_beyond_p (IT_CHARPOS (*it) + 1, |
&& indented_beyond_p (IT_CHARPOS (*it) + 1, |
5318 |
IT_BYTEPOS (*it) + 1, |
IT_BYTEPOS (*it) + 1, |
5319 |
(float) it->selective)) /* iftc */ |
(double) it->selective)) /* iftc */ |
5320 |
{ |
{ |
5321 |
success_p = next_element_from_ellipsis (it); |
success_p = next_element_from_ellipsis (it); |
5322 |
it->dpvec_char_len = -1; |
it->dpvec_char_len = -1; |
5808 |
|
|
5809 |
/* We are now surely at a line start. */ |
/* We are now surely at a line start. */ |
5810 |
it->current_x = it->hpos = 0; |
it->current_x = it->hpos = 0; |
5811 |
|
it->continuation_lines_width = 0; |
5812 |
|
|
5813 |
/* Move forward and see what y-distance we moved. First move to the |
/* Move forward and see what y-distance we moved. First move to the |
5814 |
start of the next line so that we get its height. We need this |
start of the next line so that we get its height. We need this |
6035 |
} |
} |
6036 |
} |
} |
6037 |
|
|
6038 |
|
/* Return 1 if IT points into the middle of a display vector. */ |
6039 |
|
|
6040 |
|
int |
6041 |
|
in_display_vector_p (it) |
6042 |
|
struct it *it; |
6043 |
|
{ |
6044 |
|
return (it->method == next_element_from_display_vector |
6045 |
|
&& it->current.dpvec_index > 0 |
6046 |
|
&& it->dpvec + it->current.dpvec_index != it->dpend); |
6047 |
|
} |
6048 |
|
|
6049 |
|
|
6050 |
/*********************************************************************** |
/*********************************************************************** |
6107 |
|
|
6108 |
void |
void |
6109 |
message_dolog (m, nbytes, nlflag, multibyte) |
message_dolog (m, nbytes, nlflag, multibyte) |
6110 |
char *m; |
const char *m; |
6111 |
int nbytes, nlflag, multibyte; |
int nbytes, nlflag, multibyte; |
6112 |
{ |
{ |
6113 |
|
if (!NILP (Vmemory_full)) |
6114 |
|
return; |
6115 |
|
|
6116 |
if (!NILP (Vmessage_log_max)) |
if (!NILP (Vmessage_log_max)) |
6117 |
{ |
{ |
6118 |
struct buffer *oldbuf; |
struct buffer *oldbuf; |
6157 |
|
|
6158 |
/* Convert a multibyte string to single-byte |
/* Convert a multibyte string to single-byte |
6159 |
for the *Message* buffer. */ |
for the *Message* buffer. */ |
6160 |
for (i = 0; i < nbytes; i += nbytes) |
for (i = 0; i < nbytes; i += char_bytes) |
6161 |
{ |
{ |
6162 |
c = string_char_and_length (m + i, nbytes - i, &char_bytes); |
c = string_char_and_length (m + i, nbytes - i, &char_bytes); |
6163 |
work[0] = (SINGLE_BYTE_CHAR_P (c) |
work[0] = (SINGLE_BYTE_CHAR_P (c) |
6321 |
|
|
6322 |
void |
void |
6323 |
message2 (m, nbytes, multibyte) |
message2 (m, nbytes, multibyte) |
6324 |
char *m; |
const char *m; |
6325 |
int nbytes; |
int nbytes; |
6326 |
int multibyte; |
int multibyte; |
6327 |
{ |
{ |
6337 |
|
|
6338 |
void |
void |
6339 |
message2_nolog (m, nbytes, multibyte) |
message2_nolog (m, nbytes, multibyte) |
6340 |
char *m; |
const char *m; |
6341 |
int nbytes; |
int nbytes, multibyte; |
6342 |
{ |
{ |
6343 |
struct frame *sf = SELECTED_FRAME (); |
struct frame *sf = SELECTED_FRAME (); |
6344 |
message_enable_multibyte = multibyte; |
message_enable_multibyte = multibyte; |
6556 |
message = Fformat (2, args); |
message = Fformat (2, args); |
6557 |
|
|
6558 |
if (log) |
if (log) |
6559 |
message3 (message, SBYTES (message), SMBP (message)); |
message3 (message, SBYTES (message), STRING_MULTIBYTE (message)); |
6560 |
else |
else |
6561 |
message3_nolog (message, SBYTES (message), SMBP (message)); |
message3_nolog (message, SBYTES (message), STRING_MULTIBYTE (message)); |
6562 |
|
|
6563 |
UNGCPRO; |
UNGCPRO; |
6564 |
|
|
6673 |
} |
} |
6674 |
|
|
6675 |
|
|
6676 |
/* Make sure echo area buffers in echo_buffers[] are life. If they |
/* Make sure echo area buffers in `echo_buffers' are live. |
6677 |
aren't, make new ones. */ |
If they aren't, make new ones. */ |
6678 |
|
|
6679 |
static void |
static void |
6680 |
ensure_echo_area_buffers () |
ensure_echo_area_buffers () |
6728 |
{ |
{ |
6729 |
Lisp_Object buffer; |
Lisp_Object buffer; |
6730 |
int this_one, the_other, clear_buffer_p, rc; |
int this_one, the_other, clear_buffer_p, rc; |
6731 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
6732 |
|
|
6733 |
/* If buffers aren't live, make new ones. */ |
/* If buffers aren't live, make new ones. */ |
6734 |
ensure_echo_area_buffers (); |
ensure_echo_area_buffers (); |
6886 |
setup_echo_area_for_printing (multibyte_p) |
setup_echo_area_for_printing (multibyte_p) |
6887 |
int multibyte_p; |
int multibyte_p; |
6888 |
{ |
{ |
6889 |
|
/* If we can't find an echo area any more, exit. */ |
6890 |
|
if (! FRAME_LIVE_P (XFRAME (selected_frame))) |
6891 |
|
Fkill_emacs (Qnil); |
6892 |
|
|
6893 |
ensure_echo_area_buffers (); |
ensure_echo_area_buffers (); |
6894 |
|
|
6895 |
if (!message_buf_print) |
if (!message_buf_print) |
6907 |
|
|
6908 |
if (Z > BEG) |
if (Z > BEG) |
6909 |
{ |
{ |
6910 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
6911 |
specbind (Qinhibit_read_only, Qt); |
specbind (Qinhibit_read_only, Qt); |
6912 |
|
/* Note that undo recording is always disabled. */ |
6913 |
del_range (BEG, Z); |
del_range (BEG, Z); |
6914 |
unbind_to (count, Qnil); |
unbind_to (count, Qnil); |
6915 |
} |
} |
7094 |
|
|
7095 |
/* Nil means don't try to resize. */ |
/* Nil means don't try to resize. */ |
7096 |
if (NILP (Vresize_mini_windows) |
if (NILP (Vresize_mini_windows) |
7097 |
|| (FRAME_X_P (f) && f->output_data.x == NULL)) |
|| (FRAME_X_P (f) && FRAME_X_OUTPUT (f) == NULL)) |
7098 |
return 0; |
return 0; |
7099 |
|
|
7100 |
if (!FRAME_MINIBUF_ONLY_P (f)) |
if (!FRAME_MINIBUF_ONLY_P (f)) |
7261 |
} |
} |
7262 |
|
|
7263 |
|
|
|
/* Handler for record_unwind_protect calling pop_message. */ |
|
|
|
|
|
Lisp_Object |
|
|
push_message_unwind (dummy) |
|
|
Lisp_Object dummy; |
|
|
{ |
|
|
pop_message (); |
|
|
return Qnil; |
|
|
} |
|
|
|
|
|
|
|
7264 |
/* Restore message display from the top of Vmessage_stack. */ |
/* Restore message display from the top of Vmessage_stack. */ |
7265 |
|
|
7266 |
void |
void |
7271 |
xassert (CONSP (Vmessage_stack)); |
xassert (CONSP (Vmessage_stack)); |
7272 |
msg = XCAR (Vmessage_stack); |
msg = XCAR (Vmessage_stack); |
7273 |
if (STRINGP (msg)) |
if (STRINGP (msg)) |
7274 |
message3_nolog (msg, SBYTES (msg), SMBP (msg)); |
message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg)); |
7275 |
else |
else |
7276 |
message3_nolog (msg, 0, 0); |
message3_nolog (msg, 0, 0); |
7277 |
} |
} |
7278 |
|
|
7279 |
|
|
7280 |
|
/* Handler for record_unwind_protect calling pop_message. */ |
7281 |
|
|
7282 |
|
Lisp_Object |
7283 |
|
pop_message_unwind (dummy) |
7284 |
|
Lisp_Object dummy; |
7285 |
|
{ |
7286 |
|
pop_message (); |
7287 |
|
return Qnil; |
7288 |
|
} |
7289 |
|
|
7290 |
/* Pop the top-most entry off Vmessage_stack. */ |
/* Pop the top-most entry off Vmessage_stack. */ |
7291 |
|
|
7292 |
void |
void |
7361 |
|
|
7362 |
void |
void |
7363 |
set_message (s, string, nbytes, multibyte_p) |
set_message (s, string, nbytes, multibyte_p) |
7364 |
char *s; |
const char *s; |
7365 |
Lisp_Object string; |
Lisp_Object string; |
7366 |
int nbytes; |
int nbytes, multibyte_p; |
7367 |
{ |
{ |
7368 |
message_enable_multibyte |
message_enable_multibyte |
7369 |
= ((s && multibyte_p) |
= ((s && multibyte_p) |
7387 |
Lisp_Object a2; |
Lisp_Object a2; |
7388 |
EMACS_INT nbytes, multibyte_p; |
EMACS_INT nbytes, multibyte_p; |
7389 |
{ |
{ |
7390 |
char *s = (char *) a1; |
const char *s = (const char *) a1; |
7391 |
Lisp_Object string = a2; |
Lisp_Object string = a2; |
7392 |
|
|
7393 |
xassert (BEG == Z); |
xassert (BEG == Z); |
7441 |
{ |
{ |
7442 |
/* Convert from single-byte to multi-byte. */ |
/* Convert from single-byte to multi-byte. */ |
7443 |
int i, c, n; |
int i, c, n; |
7444 |
unsigned char *msg = (unsigned char *) s; |
const unsigned char *msg = (const unsigned char *) s; |
7445 |
unsigned char str[MAX_MULTIBYTE_LENGTH]; |
unsigned char str[MAX_MULTIBYTE_LENGTH]; |
7446 |
|
|
7447 |
/* Convert a single-byte string to multibyte. */ |
/* Convert a single-byte string to multibyte. */ |
7587 |
/* Must update other windows. Likewise as in other |
/* Must update other windows. Likewise as in other |
7588 |
cases, don't let this update be interrupted by |
cases, don't let this update be interrupted by |
7589 |
pending input. */ |
pending input. */ |
7590 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
7591 |
specbind (Qredisplay_dont_pause, Qt); |
specbind (Qredisplay_dont_pause, Qt); |
7592 |
windows_or_buffers_changed = 1; |
windows_or_buffers_changed = 1; |
7593 |
redisplay_internal (0); |
redisplay_internal (0); |
7651 |
Re-allocate frame_title_buf if necessary. */ |
Re-allocate frame_title_buf if necessary. */ |
7652 |
|
|
7653 |
static void |
static void |
7654 |
|
#ifdef PROTOTYPES |
7655 |
|
store_frame_title_char (char c) |
7656 |
|
#else |
7657 |
store_frame_title_char (c) |
store_frame_title_char (c) |
7658 |
char c; |
char c; |
7659 |
|
#endif |
7660 |
{ |
{ |
7661 |
/* If output position has reached the end of the allocated buffer, |
/* If output position has reached the end of the allocated buffer, |
7662 |
double the buffer's size. */ |
double the buffer's size. */ |
7683 |
|
|
7684 |
static int |
static int |
7685 |
store_frame_title (str, field_width, precision) |
store_frame_title (str, field_width, precision) |
7686 |
unsigned char *str; |
const unsigned char *str; |
7687 |
int field_width, precision; |
int field_width, precision; |
7688 |
{ |
{ |
7689 |
int n = 0; |
int n = 0; |
7824 |
if (all_windows) |
if (all_windows) |
7825 |
{ |
{ |
7826 |
Lisp_Object tail, frame; |
Lisp_Object tail, frame; |
7827 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
7828 |
|
|
7829 |
record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil)); |
record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil)); |
7830 |
|
|
7916 |
|
|
7917 |
if (FRAME_WINDOW_P (f) |
if (FRAME_WINDOW_P (f) |
7918 |
? |
? |
7919 |
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) |
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ |
7920 |
|
|| defined (USE_GTK) |
7921 |
FRAME_EXTERNAL_MENU_BAR (f) |
FRAME_EXTERNAL_MENU_BAR (f) |
7922 |
#else |
#else |
7923 |
FRAME_MENU_BAR_LINES (f) > 0 |
FRAME_MENU_BAR_LINES (f) > 0 |
7943 |
!= !NILP (w->region_showing))) |
!= !NILP (w->region_showing))) |
7944 |
{ |
{ |
7945 |
struct buffer *prev = current_buffer; |
struct buffer *prev = current_buffer; |
7946 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
7947 |
|
|
7948 |
specbind (Qinhibit_menubar_update, Qt); |
specbind (Qinhibit_menubar_update, Qt); |
7949 |
|
|
7968 |
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); |
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); |
7969 |
|
|
7970 |
/* Redisplay the menu bar in case we changed it. */ |
/* Redisplay the menu bar in case we changed it. */ |
7971 |
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) |
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ |
7972 |
|
|| defined (USE_GTK) |
7973 |
if (FRAME_WINDOW_P (f) |
if (FRAME_WINDOW_P (f) |
7974 |
#if defined (MAC_OS) |
#if defined (MAC_OS) |
7975 |
/* All frames on Mac OS share the same menubar. So only the |
/* All frames on Mac OS share the same menubar. So only the |
7982 |
/* On a terminal screen, the menu bar is an ordinary screen |
/* On a terminal screen, the menu bar is an ordinary screen |
7983 |
line, and this makes it get updated. */ |
line, and this makes it get updated. */ |
7984 |
w->update_mode_line = Qt; |
w->update_mode_line = Qt; |
7985 |
#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */ |
#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */ |
7986 |
/* In the non-toolkit version, the menu bar is an ordinary screen |
/* In the non-toolkit version, the menu bar is an ordinary screen |
7987 |
line, and this makes it get updated. */ |
line, and this makes it get updated. */ |
7988 |
w->update_mode_line = Qt; |
w->update_mode_line = Qt; |
7989 |
#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */ |
#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */ |
7990 |
|
|
7991 |
unbind_to (count, Qnil); |
unbind_to (count, Qnil); |
7992 |
set_buffer_internal_1 (prev); |
set_buffer_internal_1 (prev); |
7997 |
|
|
7998 |
|
|
7999 |
/*********************************************************************** |
/*********************************************************************** |
8000 |
|
Output Cursor |
8001 |
|
***********************************************************************/ |
8002 |
|
|
8003 |
|
#ifdef HAVE_WINDOW_SYSTEM |
8004 |
|
|
8005 |
|
/* EXPORT: |
8006 |
|
Nominal cursor position -- where to draw output. |
8007 |
|
HPOS and VPOS are window relative glyph matrix coordinates. |
8008 |
|
X and Y are window relative pixel coordinates. */ |
8009 |
|
|
8010 |
|
struct cursor_pos output_cursor; |
8011 |
|
|
8012 |
|
|
8013 |
|
/* EXPORT: |
8014 |
|
Set the global variable output_cursor to CURSOR. All cursor |
8015 |
|
positions are relative to updated_window. */ |
8016 |
|
|
8017 |
|
void |
8018 |
|
set_output_cursor (cursor) |
8019 |
|
struct cursor_pos *cursor; |
8020 |
|
{ |
8021 |
|
output_cursor.hpos = cursor->hpos; |
8022 |
|
output_cursor.vpos = cursor->vpos; |
8023 |
|
output_cursor.x = cursor->x; |
8024 |
|
output_cursor.y = cursor->y; |
8025 |
|
} |
8026 |
|
|
8027 |
|
|
8028 |
|
/* EXPORT for RIF: |
8029 |
|
Set a nominal cursor position. |
8030 |
|
|
8031 |
|
HPOS and VPOS are column/row positions in a window glyph matrix. X |
8032 |
|
and Y are window text area relative pixel positions. |
8033 |
|
|
8034 |
|
If this is done during an update, updated_window will contain the |
8035 |
|
window that is being updated and the position is the future output |
8036 |
|
cursor position for that window. If updated_window is null, use |
8037 |
|
selected_window and display the cursor at the given position. */ |
8038 |
|
|
8039 |
|
void |
8040 |
|
x_cursor_to (vpos, hpos, y, x) |
8041 |
|
int vpos, hpos, y, x; |
8042 |
|
{ |
8043 |
|
struct window *w; |
8044 |
|
|
8045 |
|
/* If updated_window is not set, work on selected_window. */ |
8046 |
|
if (updated_window) |
8047 |
|
w = updated_window; |
8048 |
|
else |
8049 |
|
w = XWINDOW (selected_window); |
8050 |
|
|
8051 |
|
/* Set the output cursor. */ |
8052 |
|
output_cursor.hpos = hpos; |
8053 |
|
output_cursor.vpos = vpos; |
8054 |
|
output_cursor.x = x; |
8055 |
|
output_cursor.y = y; |
8056 |
|
|
8057 |
|
/* If not called as part of an update, really display the cursor. |
8058 |
|
This will also set the cursor position of W. */ |
8059 |
|
if (updated_window == NULL) |
8060 |
|
{ |
8061 |
|
BLOCK_INPUT; |
8062 |
|
display_and_set_cursor (w, 1, hpos, vpos, x, y); |
8063 |
|
if (rif->flush_display_optional) |
8064 |
|
rif->flush_display_optional (SELECTED_FRAME ()); |
8065 |
|
UNBLOCK_INPUT; |
8066 |
|
} |
8067 |
|
} |
8068 |
|
|
8069 |
|
#endif /* HAVE_WINDOW_SYSTEM */ |
8070 |
|
|
8071 |
|
|
8072 |
|
/*********************************************************************** |
8073 |
Tool-bars |
Tool-bars |
8074 |
***********************************************************************/ |
***********************************************************************/ |
8075 |
|
|
8076 |
#ifdef HAVE_WINDOW_SYSTEM |
#ifdef HAVE_WINDOW_SYSTEM |
8077 |
|
|
8078 |
|
/* Where the mouse was last time we reported a mouse event. */ |
8079 |
|
|
8080 |
|
FRAME_PTR last_mouse_frame; |
8081 |
|
|
8082 |
|
/* Tool-bar item index of the item on which a mouse button was pressed |
8083 |
|
or -1. */ |
8084 |
|
|
8085 |
|
int last_tool_bar_item; |
8086 |
|
|
8087 |
|
|
8088 |
/* Update the tool-bar item list for frame F. This has to be done |
/* Update the tool-bar item list for frame F. This has to be done |
8089 |
before we start to fill in any display lines. Called from |
before we start to fill in any display lines. Called from |
8090 |
prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save |
prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save |
8095 |
struct frame *f; |
struct frame *f; |
8096 |
int save_match_data; |
int save_match_data; |
8097 |
{ |
{ |
8098 |
if (WINDOWP (f->tool_bar_window) |
#ifdef USE_GTK |
8099 |
&& XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0) |
int do_update = FRAME_EXTERNAL_TOOL_BAR(f); |
8100 |
|
#else |
8101 |
|
int do_update = WINDOWP (f->tool_bar_window) |
8102 |
|
&& XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0; |
8103 |
|
#endif |
8104 |
|
|
8105 |
|
if (do_update) |
8106 |
{ |
{ |
8107 |
Lisp_Object window; |
Lisp_Object window; |
8108 |
struct window *w; |
struct window *w; |
8119 |
windows_or_buffers_changed anyway. */ |
windows_or_buffers_changed anyway. */ |
8120 |
if (windows_or_buffers_changed |
if (windows_or_buffers_changed |
8121 |
|| !NILP (w->update_mode_line) |
|| !NILP (w->update_mode_line) |
8122 |
|
|| update_mode_lines |
8123 |
|| ((BUF_SAVE_MODIFF (XBUFFER (w->buffer)) |
|| ((BUF_SAVE_MODIFF (XBUFFER (w->buffer)) |
8124 |
< BUF_MODIFF (XBUFFER (w->buffer))) |
< BUF_MODIFF (XBUFFER (w->buffer))) |
8125 |
!= !NILP (w->last_had_star)) |
!= !NILP (w->last_had_star)) |
8128 |
!= !NILP (w->region_showing))) |
!= !NILP (w->region_showing))) |
8129 |
{ |
{ |
8130 |
struct buffer *prev = current_buffer; |
struct buffer *prev = current_buffer; |
8131 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
8132 |
|
Lisp_Object old_tool_bar; |
8133 |
|
struct gcpro gcpro1; |
8134 |
|
|
8135 |
/* Set current_buffer to the buffer of the selected |
/* Set current_buffer to the buffer of the selected |
8136 |
window of the frame, so that we get the right local |
window of the frame, so that we get the right local |
8148 |
specbind (Qoverriding_local_map, Qnil); |
specbind (Qoverriding_local_map, Qnil); |
8149 |
} |
} |
8150 |
|
|
8151 |
|
old_tool_bar = f->tool_bar_items; |
8152 |
|
GCPRO1 (old_tool_bar); |
8153 |
|
|
8154 |
/* Build desired tool-bar items from keymaps. */ |
/* Build desired tool-bar items from keymaps. */ |
8155 |
f->tool_bar_items |
f->tool_bar_items |
8156 |
= tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items); |
= tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items); |
8157 |
|
|
8158 |
/* Redisplay the tool-bar in case we changed it. */ |
/* Redisplay the tool-bar if we changed it. */ |
8159 |
w->update_mode_line = Qt; |
if (! NILP (Fequal (old_tool_bar, f->tool_bar_items))) |
8160 |
|
w->update_mode_line = Qt; |
8161 |
|
|
8162 |
unbind_to (count, Qnil); |
unbind_to (count, Qnil); |
8163 |
set_buffer_internal_1 (prev); |
set_buffer_internal_1 (prev); |
8488 |
struct glyph_row *row; |
struct glyph_row *row; |
8489 |
int change_height_p = 0; |
int change_height_p = 0; |
8490 |
|
|
8491 |
|
#ifdef USE_GTK |
8492 |
|
if (FRAME_EXTERNAL_TOOL_BAR(f)) |
8493 |
|
update_frame_tool_bar (f); |
8494 |
|
return 0; |
8495 |
|
#endif |
8496 |
|
|
8497 |
/* If frame hasn't a tool-bar window or if it is zero-height, don't |
/* If frame hasn't a tool-bar window or if it is zero-height, don't |
8498 |
do anything. This means you must start with tool-bar-lines |
do anything. This means you must start with tool-bar-lines |
8499 |
non-zero to get the auto-sizing effect. Or in other words, you |
non-zero to get the auto-sizing effect. Or in other words, you |
8500 |
can turn off tool-bars by specifying tool-bar-lines zero. */ |
can turn off tool-bars by specifying tool-bar-lines zero. */ |
8501 |
if (!WINDOWP (f->tool_bar_window) |
if (!WINDOWP (f->tool_bar_window) |
8502 |
|| (w = XWINDOW (f->tool_bar_window), |
|| (w = XWINDOW (f->tool_bar_window), |
8503 |
XFASTINT (w->height) == 0)) |
XFASTINT (w->height) == 0)) |
8504 |
return 0; |
return 0; |
8505 |
|
|
8506 |
/* Set up an iterator for the tool-bar window. */ |
/* Set up an iterator for the tool-bar window. */ |
8575 |
properties start in F->tool_bar_items. Value is zero if |
properties start in F->tool_bar_items. Value is zero if |
8576 |
GLYPH doesn't display a tool-bar item. */ |
GLYPH doesn't display a tool-bar item. */ |
8577 |
|
|
8578 |
int |
static int |
8579 |
tool_bar_item_info (f, glyph, prop_idx) |
tool_bar_item_info (f, glyph, prop_idx) |
8580 |
struct frame *f; |
struct frame *f; |
8581 |
struct glyph *glyph; |
struct glyph *glyph; |
8607 |
return success_p; |
return success_p; |
8608 |
} |
} |
8609 |
|
|
8610 |
|
|
8611 |
|
/* Get information about the tool-bar item at position X/Y on frame F. |
8612 |
|
Return in *GLYPH a pointer to the glyph of the tool-bar item in |
8613 |
|
the current matrix of the tool-bar window of F, or NULL if not |
8614 |
|
on a tool-bar item. Return in *PROP_IDX the index of the tool-bar |
8615 |
|
item in F->tool_bar_items. Value is |
8616 |
|
|
8617 |
|
-1 if X/Y is not on a tool-bar item |
8618 |
|
0 if X/Y is on the same item that was highlighted before. |
8619 |
|
1 otherwise. */ |
8620 |
|
|
8621 |
|
static int |
8622 |
|
get_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx) |
8623 |
|
struct frame *f; |
8624 |
|
int x, y; |
8625 |
|
struct glyph **glyph; |
8626 |
|
int *hpos, *vpos, *prop_idx; |
8627 |
|
{ |
8628 |
|
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
8629 |
|
struct window *w = XWINDOW (f->tool_bar_window); |
8630 |
|
int area; |
8631 |
|
|
8632 |
|
/* Find the glyph under X/Y. */ |
8633 |
|
*glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0); |
8634 |
|
if (*glyph == NULL) |
8635 |
|
return -1; |
8636 |
|
|
8637 |
|
/* Get the start of this tool-bar item's properties in |
8638 |
|
f->tool_bar_items. */ |
8639 |
|
if (!tool_bar_item_info (f, *glyph, prop_idx)) |
8640 |
|
return -1; |
8641 |
|
|
8642 |
|
/* Is mouse on the highlighted item? */ |
8643 |
|
if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window) |
8644 |
|
&& *vpos >= dpyinfo->mouse_face_beg_row |
8645 |
|
&& *vpos <= dpyinfo->mouse_face_end_row |
8646 |
|
&& (*vpos > dpyinfo->mouse_face_beg_row |
8647 |
|
|| *hpos >= dpyinfo->mouse_face_beg_col) |
8648 |
|
&& (*vpos < dpyinfo->mouse_face_end_row |
8649 |
|
|| *hpos < dpyinfo->mouse_face_end_col |
8650 |
|
|| dpyinfo->mouse_face_past_end)) |
8651 |
|
return 0; |
8652 |
|
|
8653 |
|
return 1; |
8654 |
|
} |
8655 |
|
|
8656 |
|
|
8657 |
|
/* EXPORT: |
8658 |
|
Handle mouse button event on the tool-bar of frame F, at |
8659 |
|
frame-relative coordinates X/Y. DOWN_P is 1 for a button press, |
8660 |
|
0 for button release. MODIFIERS is event modifiers for button |
8661 |
|
release. */ |
8662 |
|
|
8663 |
|
void |
8664 |
|
handle_tool_bar_click (f, x, y, down_p, modifiers) |
8665 |
|
struct frame *f; |
8666 |
|
int x, y, down_p; |
8667 |
|
unsigned int modifiers; |
8668 |
|
{ |
8669 |
|
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
8670 |
|
struct window *w = XWINDOW (f->tool_bar_window); |
8671 |
|
int hpos, vpos, prop_idx; |
8672 |
|
struct glyph *glyph; |
8673 |
|
Lisp_Object enabled_p; |
8674 |
|
|
8675 |
|
/* If not on the highlighted tool-bar item, return. */ |
8676 |
|
frame_to_window_pixel_xy (w, &x, &y); |
8677 |
|
if (get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0) |
8678 |
|
return; |
8679 |
|
|
8680 |
|
/* If item is disabled, do nothing. */ |
8681 |
|
enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P); |
8682 |
|
if (NILP (enabled_p)) |
8683 |
|
return; |
8684 |
|
|
8685 |
|
if (down_p) |
8686 |
|
{ |
8687 |
|
/* Show item in pressed state. */ |
8688 |
|
show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN); |
8689 |
|
dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN; |
8690 |
|
last_tool_bar_item = prop_idx; |
8691 |
|
} |
8692 |
|
else |
8693 |
|
{ |
8694 |
|
Lisp_Object key, frame; |
8695 |
|
struct input_event event; |
8696 |
|
|
8697 |
|
/* Show item in released state. */ |
8698 |
|
show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED); |
8699 |
|
dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED; |
8700 |
|
|
8701 |
|
key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY); |
8702 |
|
|
8703 |
|
XSETFRAME (frame, f); |
8704 |
|
event.kind = TOOL_BAR_EVENT; |
8705 |
|
event.frame_or_window = frame; |
8706 |
|
event.arg = frame; |
8707 |
|
kbd_buffer_store_event (&event); |
8708 |
|
|
8709 |
|
event.kind = TOOL_BAR_EVENT; |
8710 |
|
event.frame_or_window = frame; |
8711 |
|
event.arg = key; |
8712 |
|
event.modifiers = modifiers; |
8713 |
|
kbd_buffer_store_event (&event); |
8714 |
|
last_tool_bar_item = -1; |
8715 |
|
} |
8716 |
|
} |
8717 |
|
|
8718 |
|
|
8719 |
|
/* Possibly highlight a tool-bar item on frame F when mouse moves to |
8720 |
|
tool-bar window-relative coordinates X/Y. Called from |
8721 |
|
note_mouse_highlight. */ |
8722 |
|
|
8723 |
|
static void |
8724 |
|
note_tool_bar_highlight (f, x, y) |
8725 |
|
struct frame *f; |
8726 |
|
int x, y; |
8727 |
|
{ |
8728 |
|
Lisp_Object window = f->tool_bar_window; |
8729 |
|
struct window *w = XWINDOW (window); |
8730 |
|
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
8731 |
|
int hpos, vpos; |
8732 |
|
struct glyph *glyph; |
8733 |
|
struct glyph_row *row; |
8734 |
|
int i; |
8735 |
|
Lisp_Object enabled_p; |
8736 |
|
int prop_idx; |
8737 |
|
enum draw_glyphs_face draw = DRAW_IMAGE_RAISED; |
8738 |
|
int mouse_down_p, rc; |
8739 |
|
|
8740 |
|
/* Function note_mouse_highlight is called with negative x(y |
8741 |
|
values when mouse moves outside of the frame. */ |
8742 |
|
if (x <= 0 || y <= 0) |
8743 |
|
{ |
8744 |
|
clear_mouse_face (dpyinfo); |
8745 |
|
return; |
8746 |
|
} |
8747 |
|
|
8748 |
|
rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx); |
8749 |
|
if (rc < 0) |
8750 |
|
{ |
8751 |
|
/* Not on tool-bar item. */ |
8752 |
|
clear_mouse_face (dpyinfo); |
8753 |
|
return; |
8754 |
|
} |
8755 |
|
else if (rc == 0) |
8756 |
|
/* On same tool-bar item as before. */ |
8757 |
|
goto set_help_echo; |
8758 |
|
|
8759 |
|
clear_mouse_face (dpyinfo); |
8760 |
|
|
8761 |
|
/* Mouse is down, but on different tool-bar item? */ |
8762 |
|
mouse_down_p = (dpyinfo->grabbed |
8763 |
|
&& f == last_mouse_frame |
8764 |
|
&& FRAME_LIVE_P (f)); |
8765 |
|
if (mouse_down_p |
8766 |
|
&& last_tool_bar_item != prop_idx) |
8767 |
|
return; |
8768 |
|
|
8769 |
|
dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT; |
8770 |
|
draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; |
8771 |
|
|
8772 |
|
/* If tool-bar item is not enabled, don't highlight it. */ |
8773 |
|
enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P); |
8774 |
|
if (!NILP (enabled_p)) |
8775 |
|
{ |
8776 |
|
/* Compute the x-position of the glyph. In front and past the |
8777 |
|
image is a space. We include this is the highlighted area. */ |
8778 |
|
row = MATRIX_ROW (w->current_matrix, vpos); |
8779 |
|
for (i = x = 0; i < hpos; ++i) |
8780 |
|
x += row->glyphs[TEXT_AREA][i].pixel_width; |
8781 |
|
|
8782 |
|
/* Record this as the current active region. */ |
8783 |
|
dpyinfo->mouse_face_beg_col = hpos; |
8784 |
|
dpyinfo->mouse_face_beg_row = vpos; |
8785 |
|
dpyinfo->mouse_face_beg_x = x; |
8786 |
|
dpyinfo->mouse_face_beg_y = row->y; |
8787 |
|
dpyinfo->mouse_face_past_end = 0; |
8788 |
|
|
8789 |
|
dpyinfo->mouse_face_end_col = hpos + 1; |
8790 |
|
dpyinfo->mouse_face_end_row = vpos; |
8791 |
|
dpyinfo->mouse_face_end_x = x + glyph->pixel_width; |
8792 |
|
dpyinfo->mouse_face_end_y = row->y; |
8793 |
|
dpyinfo->mouse_face_window = window; |
8794 |
|
dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID; |
8795 |
|
|
8796 |
|
/* Display it as active. */ |
8797 |
|
show_mouse_face (dpyinfo, draw); |
8798 |
|
dpyinfo->mouse_face_image_state = draw; |
8799 |
|
} |
8800 |
|
|
8801 |
|
set_help_echo: |
8802 |
|
|
8803 |
|
/* Set help_echo_string to a help string to display for this tool-bar item. |
8804 |
|
XTread_socket does the rest. */ |
8805 |
|
help_echo_object = help_echo_window = Qnil; |
8806 |
|
help_echo_pos = -1; |
8807 |
|
help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP); |
8808 |
|
if (NILP (help_echo_string)) |
8809 |
|
help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION); |
8810 |
|
} |
8811 |
|
|
8812 |
|
#endif /* HAVE_WINDOW_SYSTEM */ |
8813 |
|
|
8814 |
|
|
8815 |
|
|
8816 |
|
/*********************************************************************** |
8817 |
|
Fringes |
8818 |
|
***********************************************************************/ |
8819 |
|
|
8820 |
|
#ifdef HAVE_WINDOW_SYSTEM |
8821 |
|
|
8822 |
|
/* An arrow like this: `<-'. */ |
8823 |
|
static unsigned char left_bits[] = { |
8824 |
|
0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18}; |
8825 |
|
|
8826 |
|
/* Right truncation arrow bitmap `->'. */ |
8827 |
|
static unsigned char right_bits[] = { |
8828 |
|
0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18}; |
8829 |
|
|
8830 |
|
/* Marker for continued lines. */ |
8831 |
|
static unsigned char continued_bits[] = { |
8832 |
|
0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c}; |
8833 |
|
|
8834 |
|
/* Marker for continuation lines. */ |
8835 |
|
static unsigned char continuation_bits[] = { |
8836 |
|
0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e}; |
8837 |
|
|
8838 |
|
/* Overlay arrow bitmap. A triangular arrow. */ |
8839 |
|
static unsigned char ov_bits[] = { |
8840 |
|
0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03}; |
8841 |
|
|
8842 |
|
/* Bitmap drawn to indicate lines not displaying text if |
8843 |
|
`indicate-empty-lines' is non-nil. */ |
8844 |
|
static unsigned char zv_bits[] = { |
8845 |
|
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, |
8846 |
|
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, |
8847 |
|
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, |
8848 |
|
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, |
8849 |
|
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, |
8850 |
|
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, |
8851 |
|
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, |
8852 |
|
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00}; |
8853 |
|
|
8854 |
|
struct fringe_bitmap fringe_bitmaps[MAX_FRINGE_BITMAPS] = |
8855 |
|
{ |
8856 |
|
{ 0, 0, 0, NULL /* NO_FRINGE_BITMAP */ }, |
8857 |
|
{ 8, sizeof (left_bits), 0, left_bits }, |
8858 |
|
{ 8, sizeof (right_bits), 0, right_bits }, |
8859 |
|
{ 8, sizeof (continued_bits), 0, continued_bits }, |
8860 |
|
{ 8, sizeof (continuation_bits), 0, continuation_bits }, |
8861 |
|
{ 8, sizeof (ov_bits), 0, ov_bits }, |
8862 |
|
{ 8, sizeof (zv_bits), 3, zv_bits } |
8863 |
|
}; |
8864 |
|
|
8865 |
|
|
8866 |
|
/* Draw the bitmap WHICH in one of the left or right fringes of |
8867 |
|
window W. ROW is the glyph row for which to display the bitmap; it |
8868 |
|
determines the vertical position at which the bitmap has to be |
8869 |
|
drawn. */ |
8870 |
|
|
8871 |
|
static void |
8872 |
|
draw_fringe_bitmap (w, row, which, left_p) |
8873 |
|
struct window *w; |
8874 |
|
struct glyph_row *row; |
8875 |
|
enum fringe_bitmap_type which; |
8876 |
|
int left_p; |
8877 |
|
{ |
8878 |
|
struct frame *f = XFRAME (WINDOW_FRAME (w)); |
8879 |
|
struct draw_fringe_bitmap_params p; |
8880 |
|
|
8881 |
|
/* Convert row to frame coordinates. */ |
8882 |
|
p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); |
8883 |
|
|
8884 |
|
p.which = which; |
8885 |
|
p.wd = fringe_bitmaps[which].width; |
8886 |
|
|
8887 |
|
p.h = fringe_bitmaps[which].height; |
8888 |
|
p.dh = (fringe_bitmaps[which].period |
8889 |
|
? (p.y % fringe_bitmaps[which].period) |
8890 |
|
: 0); |
8891 |
|
p.h -= p.dh; |
8892 |
|
/* Clip bitmap if too high. */ |
8893 |
|
if (p.h > row->height) |
8894 |
|
p.h = row->height; |
8895 |
|
|
8896 |
|
p.face = FACE_FROM_ID (f, FRINGE_FACE_ID); |
8897 |
|
PREPARE_FACE_FOR_DISPLAY (f, p.face); |
8898 |
|
|
8899 |
|
/* Clear left fringe if no bitmap to draw or if bitmap doesn't fill |
8900 |
|
the fringe. */ |
8901 |
|
p.bx = -1; |
8902 |
|
if (left_p) |
8903 |
|
{ |
8904 |
|
if (p.wd > FRAME_X_LEFT_FRINGE_WIDTH (f)) |
8905 |
|
p.wd = FRAME_X_LEFT_FRINGE_WIDTH (f); |
8906 |
|
p.x = (WINDOW_TO_FRAME_PIXEL_X (w, 0) |
8907 |
|
- p.wd |
8908 |
|
- (FRAME_X_LEFT_FRINGE_WIDTH (f) - p.wd) / 2); |
8909 |
|
if (p.wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > p.h) |
8910 |
|
{ |
8911 |
|
/* If W has a vertical border to its left, don't draw over it. */ |
8912 |
|
int border = ((XFASTINT (w->left) > 0 |
8913 |
|
&& !FRAME_HAS_VERTICAL_SCROLL_BARS (f)) |
8914 |
|
? 1 : 0); |
8915 |
|
p.bx = (window_box_left (w, -1) |
8916 |
|
- FRAME_X_LEFT_FRINGE_WIDTH (f) |
8917 |
|
+ border); |
8918 |
|
p.nx = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border); |
8919 |
|
} |
8920 |
|
} |
8921 |
|
else |
8922 |
|
{ |
8923 |
|
if (p.wd > FRAME_X_RIGHT_FRINGE_WIDTH (f)) |
8924 |
|
p.wd = FRAME_X_RIGHT_FRINGE_WIDTH (f); |
8925 |
|
p.x = (window_box_right (w, -1) |
8926 |
|
+ (FRAME_X_RIGHT_FRINGE_WIDTH (f) - p.wd) / 2); |
8927 |
|
/* Clear right fringe if no bitmap to draw of if bitmap doesn't fill |
8928 |
|
the fringe. */ |
8929 |
|
if (p.wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > p.h) |
8930 |
|
{ |
8931 |
|
p.bx = window_box_right (w, -1); |
8932 |
|
p.nx = FRAME_X_RIGHT_FRINGE_WIDTH (f); |
8933 |
|
} |
8934 |
|
} |
8935 |
|
|
8936 |
|
if (p.bx >= 0) |
8937 |
|
{ |
8938 |
|
int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); |
8939 |
|
|
8940 |
|
p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y)); |
8941 |
|
p.ny = row->visible_height; |
8942 |
|
} |
8943 |
|
|
8944 |
|
/* Adjust y to the offset in the row to start drawing the bitmap. */ |
8945 |
|
p.y += (row->height - p.h) / 2; |
8946 |
|
|
8947 |
|
rif->draw_fringe_bitmap (w, row, &p); |
8948 |
|
} |
8949 |
|
|
8950 |
|
/* Draw fringe bitmaps for glyph row ROW on window W. Call this |
8951 |
|
function with input blocked. */ |
8952 |
|
|
8953 |
|
void |
8954 |
|
draw_row_fringe_bitmaps (w, row) |
8955 |
|
struct window *w; |
8956 |
|
struct glyph_row *row; |
8957 |
|
{ |
8958 |
|
struct frame *f = XFRAME (w->frame); |
8959 |
|
enum fringe_bitmap_type bitmap; |
8960 |
|
|
8961 |
|
xassert (interrupt_input_blocked); |
8962 |
|
|
8963 |
|
/* If row is completely invisible, because of vscrolling, we |
8964 |
|
don't have to draw anything. */ |
8965 |
|
if (row->visible_height <= 0) |
8966 |
|
return; |
8967 |
|
|
8968 |
|
if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0) |
8969 |
|
{ |
8970 |
|
/* Decide which bitmap to draw in the left fringe. */ |
8971 |
|
if (row->overlay_arrow_p) |
8972 |
|
bitmap = OVERLAY_ARROW_BITMAP; |
8973 |
|
else if (row->truncated_on_left_p) |
8974 |
|
bitmap = LEFT_TRUNCATION_BITMAP; |
8975 |
|
else if (MATRIX_ROW_CONTINUATION_LINE_P (row)) |
8976 |
|
bitmap = CONTINUATION_LINE_BITMAP; |
8977 |
|
else if (row->indicate_empty_line_p) |
8978 |
|
bitmap = ZV_LINE_BITMAP; |
8979 |
|
else |
8980 |
|
bitmap = NO_FRINGE_BITMAP; |
8981 |
|
|
8982 |
|
draw_fringe_bitmap (w, row, bitmap, 1); |
8983 |
|
} |
8984 |
|
|
8985 |
|
if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0) |
8986 |
|
{ |
8987 |
|
/* Decide which bitmap to draw in the right fringe. */ |
8988 |
|
if (row->truncated_on_right_p) |
8989 |
|
bitmap = RIGHT_TRUNCATION_BITMAP; |
8990 |
|
else if (row->continued_p) |
8991 |
|
bitmap = CONTINUED_LINE_BITMAP; |
8992 |
|
else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0) |
8993 |
|
bitmap = ZV_LINE_BITMAP; |
8994 |
|
else |
8995 |
|
bitmap = NO_FRINGE_BITMAP; |
8996 |
|
|
8997 |
|
draw_fringe_bitmap (w, row, bitmap, 0); |
8998 |
|
} |
8999 |
|
} |
9000 |
|
|
9001 |
|
|
9002 |
|
/* Compute actual fringe widths */ |
9003 |
|
|
9004 |
|
void |
9005 |
|
compute_fringe_widths (f, redraw) |
9006 |
|
struct frame *f; |
9007 |
|
int redraw; |
9008 |
|
{ |
9009 |
|
int o_left = FRAME_X_LEFT_FRINGE_WIDTH (f); |
9010 |
|
int o_right = FRAME_X_RIGHT_FRINGE_WIDTH (f); |
9011 |
|
int o_cols = FRAME_X_FRINGE_COLS (f); |
9012 |
|
|
9013 |
|
Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist); |
9014 |
|
Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist); |
9015 |
|
int left_fringe_width, right_fringe_width; |
9016 |
|
|
9017 |
|
if (!NILP (left_fringe)) |
9018 |
|
left_fringe = Fcdr (left_fringe); |
9019 |
|
if (!NILP (right_fringe)) |
9020 |
|
right_fringe = Fcdr (right_fringe); |
9021 |
|
|
9022 |
|
left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 : |
9023 |
|
XINT (left_fringe)); |
9024 |
|
right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 : |
9025 |
|
XINT (right_fringe)); |
9026 |
|
|
9027 |
|
if (left_fringe_width || right_fringe_width) |
9028 |
|
{ |
9029 |
|
int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width; |
9030 |
|
int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width; |
9031 |
|
int conf_wid = left_wid + right_wid; |
9032 |
|
int font_wid = FONT_WIDTH (FRAME_FONT (f)); |
9033 |
|
int cols = (left_wid + right_wid + font_wid-1) / font_wid; |
9034 |
|
int real_wid = cols * font_wid; |
9035 |
|
if (left_wid && right_wid) |
9036 |
|
{ |
9037 |
|
if (left_fringe_width < 0) |
9038 |
|
{ |
9039 |
|
/* Left fringe width is fixed, adjust right fringe if necessary */ |
9040 |
|
FRAME_X_LEFT_FRINGE_WIDTH (f) = left_wid; |
9041 |
|
FRAME_X_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid; |
9042 |
|
} |
9043 |
|
else if (right_fringe_width < 0) |
9044 |
|
{ |
9045 |
|
/* Right fringe width is fixed, adjust left fringe if necessary */ |
9046 |
|
FRAME_X_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid; |
9047 |
|
FRAME_X_RIGHT_FRINGE_WIDTH (f) = right_wid; |
9048 |
|
} |
9049 |
|
else |
9050 |
|
{ |
9051 |
|
/* Adjust both fringes with an equal amount. |
9052 |
|
Note that we are doing integer arithmetic here, so don't |
9053 |
|
lose a pixel if the total width is an odd number. */ |
9054 |
|
int fill = real_wid - conf_wid; |
9055 |
|
FRAME_X_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2; |
9056 |
|
FRAME_X_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2; |
9057 |
|
} |
9058 |
|
} |
9059 |
|
else if (left_fringe_width) |
9060 |
|
{ |
9061 |
|
FRAME_X_LEFT_FRINGE_WIDTH (f) = real_wid; |
9062 |
|
FRAME_X_RIGHT_FRINGE_WIDTH (f) = 0; |
9063 |
|
} |
9064 |
|
else |
9065 |
|
{ |
9066 |
|
FRAME_X_LEFT_FRINGE_WIDTH (f) = 0; |
9067 |
|
FRAME_X_RIGHT_FRINGE_WIDTH (f) = real_wid; |
9068 |
|
} |
9069 |
|
FRAME_X_FRINGE_COLS (f) = cols; |
9070 |
|
FRAME_X_FRINGE_WIDTH (f) = real_wid; |
9071 |
|
} |
9072 |
|
else |
9073 |
|
{ |
9074 |
|
FRAME_X_LEFT_FRINGE_WIDTH (f) = 0; |
9075 |
|
FRAME_X_RIGHT_FRINGE_WIDTH (f) = 0; |
9076 |
|
FRAME_X_FRINGE_COLS (f) = 0; |
9077 |
|
FRAME_X_FRINGE_WIDTH (f) = 0; |
9078 |
|
} |
9079 |
|
|
9080 |
|
if (redraw && FRAME_VISIBLE_P (f)) |
9081 |
|
if (o_left != FRAME_X_LEFT_FRINGE_WIDTH (f) || |
9082 |
|
o_right != FRAME_X_RIGHT_FRINGE_WIDTH (f) || |
9083 |
|
o_cols != FRAME_X_FRINGE_COLS (f)) |
9084 |
|
redraw_frame (f); |
9085 |
|
} |
9086 |
|
|
9087 |
#endif /* HAVE_WINDOW_SYSTEM */ |
#endif /* HAVE_WINDOW_SYSTEM */ |
9088 |
|
|
9089 |
|
|
9328 |
#endif /* GLYPH_DEBUG */ |
#endif /* GLYPH_DEBUG */ |
9329 |
|
|
9330 |
|
|
|
/* This counter is used to clear the face cache every once in a while |
|
|
in redisplay_internal. It is incremented for each redisplay. |
|
|
Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is |
|
|
cleared. */ |
|
|
|
|
|
#define CLEAR_FACE_CACHE_COUNT 500 |
|
|
static int clear_face_cache_count; |
|
|
|
|
|
/* Record the previous terminal frame we displayed. */ |
|
|
|
|
|
static struct frame *previous_terminal_frame; |
|
|
|
|
|
/* Non-zero while redisplay_internal is in progress. */ |
|
|
|
|
|
int redisplaying_p; |
|
|
|
|
|
|
|
9331 |
/* Value is non-zero if all changes in window W, which displays |
/* Value is non-zero if all changes in window W, which displays |
9332 |
current_buffer, are in the text between START and END. START is a |
current_buffer, are in the text between START and END. START is a |
9333 |
buffer position, END is given as a distance from Z. Used in |
buffer position, END is given as a distance from Z. Used in |
9445 |
struct window *w; |
struct window *w; |
9446 |
struct buffer *b; |
struct buffer *b; |
9447 |
{ |
{ |
9448 |
if (b->prevent_redisplay_optimizations_p) |
if (b->clip_changed |
|
b->clip_changed = 1; |
|
|
else if (b->clip_changed |
|
9449 |
&& !NILP (w->window_end_valid) |
&& !NILP (w->window_end_valid) |
9450 |
&& w->current_matrix->buffer == b |
&& w->current_matrix->buffer == b |
9451 |
&& w->current_matrix->zv == BUF_ZV (b) |
&& w->current_matrix->zv == BUF_ZV (b) |
9475 |
b->clip_changed = 1; |
b->clip_changed = 1; |
9476 |
} |
} |
9477 |
} |
} |
9478 |
|
|
9479 |
|
#define STOP_POLLING \ |
9480 |
|
do { if (! polling_stopped_here) stop_polling (); \ |
9481 |
|
polling_stopped_here = 1; } while (0) |
9482 |
|
|
9483 |
|
#define RESUME_POLLING \ |
9484 |
|
do { if (polling_stopped_here) start_polling (); \ |
9485 |
|
polling_stopped_here = 0; } while (0) |
9486 |
|
|
9487 |
|
|
9488 |
/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in |
/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in |
9503 |
int number_of_visible_frames; |
int number_of_visible_frames; |
9504 |
int count; |
int count; |
9505 |
struct frame *sf = SELECTED_FRAME (); |
struct frame *sf = SELECTED_FRAME (); |
9506 |
|
int polling_stopped_here = 0; |
9507 |
|
|
9508 |
/* Non-zero means redisplay has to consider all windows on all |
/* Non-zero means redisplay has to consider all windows on all |
9509 |
frames. Zero means, only selected_window is considered. */ |
frames. Zero means, only selected_window is considered. */ |
9529 |
return; |
return; |
9530 |
} |
} |
9531 |
|
|
9532 |
#ifdef USE_X_TOOLKIT |
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) |
9533 |
if (popup_activated ()) |
if (popup_activated ()) |
9534 |
return; |
return; |
9535 |
#endif |
#endif |
9540 |
|
|
9541 |
/* Record a function that resets redisplaying_p to its old value |
/* Record a function that resets redisplaying_p to its old value |
9542 |
when we leave this function. */ |
when we leave this function. */ |
9543 |
count = BINDING_STACK_SIZE (); |
count = SPECPDL_INDEX (); |
9544 |
record_unwind_protect (unwind_redisplay, make_number (redisplaying_p)); |
record_unwind_protect (unwind_redisplay, make_number (redisplaying_p)); |
9545 |
++redisplaying_p; |
++redisplaying_p; |
9546 |
|
specbind (Qinhibit_free_realized_faces, Qnil); |
9547 |
|
|
9548 |
retry: |
retry: |
9549 |
pause = 0; |
pause = 0; |
9722 |
&& CHARPOS (tlbufpos) > 0 |
&& CHARPOS (tlbufpos) > 0 |
9723 |
&& NILP (w->update_mode_line) |
&& NILP (w->update_mode_line) |
9724 |
&& !current_buffer->clip_changed |
&& !current_buffer->clip_changed |
9725 |
|
&& !current_buffer->prevent_redisplay_optimizations_p |
9726 |
&& FRAME_VISIBLE_P (XFRAME (w->frame)) |
&& FRAME_VISIBLE_P (XFRAME (w->frame)) |
9727 |
&& !FRAME_OBSCURED_P (XFRAME (w->frame)) |
&& !FRAME_OBSCURED_P (XFRAME (w->frame)) |
9728 |
/* Make sure recorded data applies to current buffer, etc. */ |
/* Make sure recorded data applies to current buffer, etc. */ |
9729 |
&& this_line_buffer == current_buffer |
&& this_line_buffer == current_buffer |
9730 |
&& current_buffer == XBUFFER (w->buffer) |
&& current_buffer == XBUFFER (w->buffer) |
9731 |
&& NILP (w->force_start) |
&& NILP (w->force_start) |
9732 |
|
&& NILP (w->optional_new_start) |
9733 |
/* Point must be on the line that we have info recorded about. */ |
/* Point must be on the line that we have info recorded about. */ |
9734 |
&& PT >= CHARPOS (tlbufpos) |
&& PT >= CHARPOS (tlbufpos) |
9735 |
&& PT <= Z - CHARPOS (tlendpos) |
&& PT <= Z - CHARPOS (tlendpos) |
9975 |
judge_scroll_bars_hook (f); |
judge_scroll_bars_hook (f); |
9976 |
|
|
9977 |
/* If fonts changed, display again. */ |
/* If fonts changed, display again. */ |
9978 |
|
/* ??? rms: I suspect it is a mistake to jump all the way |
9979 |
|
back to retry here. It should just retry this frame. */ |
9980 |
if (fonts_changed_p) |
if (fonts_changed_p) |
9981 |
goto retry; |
goto retry; |
9982 |
|
|
9992 |
error. */ |
error. */ |
9993 |
if (interrupt_input) |
if (interrupt_input) |
9994 |
unrequest_sigio (); |
unrequest_sigio (); |
9995 |
stop_polling (); |
STOP_POLLING; |
9996 |
|
|
9997 |
/* Update the display. */ |
/* Update the display. */ |
9998 |
set_window_update_flags (XWINDOW (f->root_window), 1); |
set_window_update_flags (XWINDOW (f->root_window), 1); |
10037 |
redisplay_window_error); |
redisplay_window_error); |
10038 |
|
|
10039 |
/* Compare desired and current matrices, perform output. */ |
/* Compare desired and current matrices, perform output. */ |
|
update: |
|
10040 |
|
|
10041 |
|
update: |
10042 |
/* If fonts changed, display again. */ |
/* If fonts changed, display again. */ |
10043 |
if (fonts_changed_p) |
if (fonts_changed_p) |
10044 |
goto retry; |
goto retry; |
10048 |
which can cause an apparent I/O error. */ |
which can cause an apparent I/O error. */ |
10049 |
if (interrupt_input) |
if (interrupt_input) |
10050 |
unrequest_sigio (); |
unrequest_sigio (); |
10051 |
stop_polling (); |
STOP_POLLING; |
10052 |
|
|
10053 |
if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf)) |
if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf)) |
10054 |
{ |
{ |
10124 |
But it is much hairier to try to do anything about that. */ |
But it is much hairier to try to do anything about that. */ |
10125 |
if (interrupt_input) |
if (interrupt_input) |
10126 |
request_sigio (); |
request_sigio (); |
10127 |
start_polling (); |
RESUME_POLLING; |
10128 |
|
|
10129 |
/* If a frame has become visible which was not before, redisplay |
/* If a frame has become visible which was not before, redisplay |
10130 |
again, so that we display it. Expose events for such a frame |
again, so that we display it. Expose events for such a frame |
10163 |
if (windows_or_buffers_changed && !pause) |
if (windows_or_buffers_changed && !pause) |
10164 |
goto retry; |
goto retry; |
10165 |
|
|
10166 |
end_of_redisplay:; |
end_of_redisplay: |
|
|
|
10167 |
unbind_to (count, Qnil); |
unbind_to (count, Qnil); |
10168 |
|
RESUME_POLLING; |
10169 |
} |
} |
10170 |
|
|
10171 |
|
|
10200 |
|
|
10201 |
|
|
10202 |
/* Function registered with record_unwind_protect in |
/* Function registered with record_unwind_protect in |
10203 |
redisplay_internal. Clears the flag indicating that a redisplay is |
redisplay_internal. Reset redisplaying_p to the value it had |
10204 |
in progress. */ |
before redisplay_internal was called, and clear |
10205 |
|
prevent_freeing_realized_faces_p. */ |
10206 |
|
|
10207 |
static Lisp_Object |
static Lisp_Object |
10208 |
unwind_redisplay (old_redisplaying_p) |
unwind_redisplay (old_redisplaying_p) |
10410 |
return Qnil; |
return Qnil; |
10411 |
} |
} |
10412 |
|
|
10413 |
|
|
10414 |
|
/* Increment GLYPH until it reaches END or CONDITION fails while |
10415 |
|
adding (GLYPH)->pixel_width to X. */ |
10416 |
|
|
10417 |
|
#define SKIP_GLYPHS(glyph, end, x, condition) \ |
10418 |
|
do \ |
10419 |
|
{ \ |
10420 |
|
(x) += (glyph)->pixel_width; \ |
10421 |
|
++(glyph); \ |
10422 |
|
} \ |
10423 |
|
while ((glyph) < (end) && (condition)) |
10424 |
|
|
10425 |
|
|
10426 |
/* Set cursor position of W. PT is assumed to be displayed in ROW. |
/* Set cursor position of W. PT is assumed to be displayed in ROW. |
10427 |
DELTA is the number of bytes by which positions recorded in ROW |
DELTA is the number of bytes by which positions recorded in ROW |
10428 |
differ from current buffer positions. */ |
differ from current buffer positions. */ |
10436 |
{ |
{ |
10437 |
struct glyph *glyph = row->glyphs[TEXT_AREA]; |
struct glyph *glyph = row->glyphs[TEXT_AREA]; |
10438 |
struct glyph *end = glyph + row->used[TEXT_AREA]; |
struct glyph *end = glyph + row->used[TEXT_AREA]; |
10439 |
|
/* The first glyph that starts a sequence of glyphs from string. */ |
10440 |
|
struct glyph *string_start; |
10441 |
|
/* The X coordinate of string_start. */ |
10442 |
|
int string_start_x; |
10443 |
|
/* The last known character position. */ |
10444 |
|
int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta; |
10445 |
|
/* The last known character position before string_start. */ |
10446 |
|
int string_before_pos; |
10447 |
int x = row->x; |
int x = row->x; |
10448 |
int pt_old = PT - delta; |
int pt_old = PT - delta; |
10449 |
|
|
10459 |
++glyph; |
++glyph; |
10460 |
} |
} |
10461 |
|
|
10462 |
|
string_start = NULL; |
10463 |
while (glyph < end |
while (glyph < end |
10464 |
&& !INTEGERP (glyph->object) |
&& !INTEGERP (glyph->object) |
10465 |
&& (!BUFFERP (glyph->object) |
&& (!BUFFERP (glyph->object) |
10466 |
|| glyph->charpos < pt_old)) |
|| (last_pos = glyph->charpos) < pt_old)) |
10467 |
{ |
{ |
10468 |
x += glyph->pixel_width; |
if (! STRINGP (glyph->object)) |
10469 |
++glyph; |
{ |
10470 |
|
string_start = NULL; |
10471 |
|
x += glyph->pixel_width; |
10472 |
|
++glyph; |
10473 |
|
} |
10474 |
|
else |
10475 |
|
{ |
10476 |
|
string_before_pos = last_pos; |
10477 |
|
string_start = glyph; |
10478 |
|
string_start_x = x; |
10479 |
|
/* Skip all glyphs from string. */ |
10480 |
|
SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object)); |
10481 |
|
} |
10482 |
|
} |
10483 |
|
|
10484 |
|
if (string_start |
10485 |
|
&& (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old)) |
10486 |
|
{ |
10487 |
|
/* We may have skipped over point because the previous glyphs |
10488 |
|
are from string. As there's no easy way to know the |
10489 |
|
character position of the current glyph, find the correct |
10490 |
|
glyph on point by scanning from string_start again. */ |
10491 |
|
Lisp_Object limit; |
10492 |
|
Lisp_Object string; |
10493 |
|
int pos; |
10494 |
|
|
10495 |
|
limit = make_number (pt_old + 1); |
10496 |
|
end = glyph; |
10497 |
|
glyph = string_start; |
10498 |
|
x = string_start_x; |
10499 |
|
string = glyph->object; |
10500 |
|
pos = string_buffer_position (w, string, string_before_pos); |
10501 |
|
/* If STRING is from overlay, LAST_POS == 0. We skip such glyphs |
10502 |
|
because we always put cursor after overlay strings. */ |
10503 |
|
while (pos == 0 && glyph < end) |
10504 |
|
{ |
10505 |
|
string = glyph->object; |
10506 |
|
SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string)); |
10507 |
|
if (glyph < end) |
10508 |
|
pos = string_buffer_position (w, glyph->object, string_before_pos); |
10509 |
|
} |
10510 |
|
|
10511 |
|
while (glyph < end) |
10512 |
|
{ |
10513 |
|
pos = XINT (Fnext_single_char_property_change |
10514 |
|
(make_number (pos), Qdisplay, Qnil, limit)); |
10515 |
|
if (pos > pt_old) |
10516 |
|
break; |
10517 |
|
/* Skip glyphs from the same string. */ |
10518 |
|
string = glyph->object; |
10519 |
|
SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string)); |
10520 |
|
/* Skip glyphs from an overlay. */ |
10521 |
|
while (glyph < end |
10522 |
|
&& ! string_buffer_position (w, glyph->object, pos)) |
10523 |
|
{ |
10524 |
|
string = glyph->object; |
10525 |
|
SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string)); |
10526 |
|
} |
10527 |
|
} |
10528 |
} |
} |
10529 |
|
|
10530 |
w->cursor.hpos = glyph - row->glyphs[TEXT_AREA]; |
w->cursor.hpos = glyph - row->glyphs[TEXT_AREA]; |
10591 |
} |
} |
10592 |
|
|
10593 |
|
|
10594 |
/* Modify the desired matrix of window W and W->vscroll so that the |
/* Make sure the line containing the cursor is fully visible. |
10595 |
line containing the cursor is fully visible. If this requires |
A value of 1 means there is nothing to be done. |
10596 |
larger matrices than are allocated, set fonts_changed_p and return |
(Either the line is fully visible, or it cannot be made so, |
10597 |
0. */ |
or we cannot tell.) |
10598 |
|
A value of 0 means the caller should do scrolling |
10599 |
|
as if point had gone off the screen. */ |
10600 |
|
|
10601 |
static int |
static int |
10602 |
make_cursor_line_fully_visible (w) |
make_cursor_line_fully_visible (w) |
10614 |
matrix = w->desired_matrix; |
matrix = w->desired_matrix; |
10615 |
row = MATRIX_ROW (matrix, w->cursor.vpos); |
row = MATRIX_ROW (matrix, w->cursor.vpos); |
10616 |
|
|
10617 |
/* If the cursor row is not partially visible, there's nothing |
/* If the cursor row is not partially visible, there's nothing to do. */ |
|
to do. */ |
|
10618 |
if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row)) |
if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row)) |
10619 |
return 1; |
return 1; |
10620 |
|
|
10624 |
if (row->height >= window_height) |
if (row->height >= window_height) |
10625 |
return 1; |
return 1; |
10626 |
|
|
10627 |
|
return 0; |
10628 |
|
|
10629 |
|
#if 0 |
10630 |
|
/* This code used to try to scroll the window just enough to make |
10631 |
|
the line visible. It returned 0 to say that the caller should |
10632 |
|
allocate larger glyph matrices. */ |
10633 |
|
|
10634 |
if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row)) |
if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row)) |
10635 |
{ |
{ |
10636 |
int dy = row->height - row->visible_height; |
int dy = row->height - row->visible_height; |
10662 |
} |
} |
10663 |
|
|
10664 |
return 1; |
return 1; |
10665 |
|
#endif /* 0 */ |
10666 |
} |
} |
10667 |
|
|
10668 |
|
|
10672 |
in redisplay_window to bring a partially visible line into view in |
in redisplay_window to bring a partially visible line into view in |
10673 |
the case that only the cursor has moved. |
the case that only the cursor has moved. |
10674 |
|
|
10675 |
|
LAST_LINE_MISFIT should be nonzero if we're scrolling because the |
10676 |
|
last screen line's vertical height extends past the end of the screen. |
10677 |
|
|
10678 |
Value is |
Value is |
10679 |
|
|
10680 |
1 if scrolling succeeded |
1 if scrolling succeeded |
10693 |
|
|
10694 |
static int |
static int |
10695 |
try_scrolling (window, just_this_one_p, scroll_conservatively, |
try_scrolling (window, just_this_one_p, scroll_conservatively, |
10696 |
scroll_step, temp_scroll_step) |
scroll_step, temp_scroll_step, last_line_misfit) |
10697 |
Lisp_Object window; |
Lisp_Object window; |
10698 |
int just_this_one_p; |
int just_this_one_p; |
10699 |
EMACS_INT scroll_conservatively, scroll_step; |
EMACS_INT scroll_conservatively, scroll_step; |
10700 |
int temp_scroll_step; |
int temp_scroll_step; |
10701 |
|
int last_line_misfit; |
10702 |
{ |
{ |
10703 |
struct window *w = XWINDOW (window); |
struct window *w = XWINDOW (window); |
10704 |
struct frame *f = XFRAME (w->frame); |
struct frame *f = XFRAME (w->frame); |
10714 |
int amount_to_scroll = 0; |
int amount_to_scroll = 0; |
10715 |
Lisp_Object aggressive; |
Lisp_Object aggressive; |
10716 |
int height; |
int height; |
10717 |
|
int end_scroll_margin; |
10718 |
|
|
10719 |
#if GLYPH_DEBUG |
#if GLYPH_DEBUG |
10720 |
debug_method_add (w, "try_scrolling"); |
debug_method_add (w, "try_scrolling"); |
10751 |
and move this_scroll_margin up to find the position of the scroll |
and move this_scroll_margin up to find the position of the scroll |
10752 |
margin. */ |
margin. */ |
10753 |
window_end = Fwindow_end (window, Qt); |
window_end = Fwindow_end (window, Qt); |
10754 |
|
|
10755 |
|
too_near_end: |
10756 |
|
|
10757 |
CHARPOS (scroll_margin_pos) = XINT (window_end); |
CHARPOS (scroll_margin_pos) = XINT (window_end); |
10758 |
BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos)); |
BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos)); |
10759 |
if (this_scroll_margin) |
|
10760 |
|
end_scroll_margin = this_scroll_margin + !!last_line_misfit; |
10761 |
|
if (end_scroll_margin) |
10762 |
{ |
{ |
10763 |
start_display (&it, w, scroll_margin_pos); |
start_display (&it, w, scroll_margin_pos); |
10764 |
move_it_vertically (&it, - this_scroll_margin); |
move_it_vertically (&it, - end_scroll_margin); |
10765 |
scroll_margin_pos = it.current.pos; |
scroll_margin_pos = it.current.pos; |
10766 |
} |
} |
10767 |
|
|
10793 |
start_display (&it, w, startp); |
start_display (&it, w, startp); |
10794 |
|
|
10795 |
if (scroll_conservatively) |
if (scroll_conservatively) |
10796 |
|
/* Set AMOUNT_TO_SCROLL to at least one line, |
10797 |
|
and at most scroll_conservatively lines. */ |
10798 |
amount_to_scroll |
amount_to_scroll |
10799 |
= max (max (dy, CANON_Y_UNIT (f)), |
= min (max (dy, CANON_Y_UNIT (f)), |
10800 |
CANON_Y_UNIT (f) * max (scroll_step, temp_scroll_step)); |
CANON_Y_UNIT (f) * scroll_conservatively); |
10801 |
else if (scroll_step || temp_scroll_step) |
else if (scroll_step || temp_scroll_step) |
10802 |
amount_to_scroll = scroll_max; |
amount_to_scroll = scroll_max; |
10803 |
else |
else |
10812 |
if (amount_to_scroll <= 0) |
if (amount_to_scroll <= 0) |
10813 |
return SCROLLING_FAILED; |
return SCROLLING_FAILED; |
10814 |
|
|
10815 |
|
/* If moving by amount_to_scroll leaves STARTP unchanged, |
10816 |
|
move it down one screen line. */ |
10817 |
|
|
10818 |
move_it_vertically (&it, amount_to_scroll); |
move_it_vertically (&it, amount_to_scroll); |
10819 |
|
if (CHARPOS (it.current.pos) == CHARPOS (startp)) |
10820 |
|
move_it_by_lines (&it, 1, 1); |
10821 |
startp = it.current.pos; |
startp = it.current.pos; |
10822 |
} |
} |
10823 |
else |
else |
10896 |
|| BEG_UNCHANGED < CHARPOS (startp)) |
|| BEG_UNCHANGED < CHARPOS (startp)) |
10897 |
w->base_line_number = Qnil; |
w->base_line_number = Qnil; |
10898 |
|
|
10899 |
/* If cursor ends up on a partially visible line, shift display |
/* If cursor ends up on a partially visible line, |
10900 |
lines up or down. If that fails because we need larger |
treat that as being off the bottom of the screen. */ |
10901 |
matrices, give up. */ |
if (! make_cursor_line_fully_visible (w)) |
10902 |
if (!make_cursor_line_fully_visible (w)) |
{ |
10903 |
rc = SCROLLING_NEED_LARGER_MATRICES; |
clear_glyph_matrix (w->desired_matrix); |
10904 |
else |
last_line_misfit = 1; |
10905 |
rc = SCROLLING_SUCCESS; |
goto too_near_end; |
10906 |
|
} |
10907 |
|
rc = SCROLLING_SUCCESS; |
10908 |
} |
} |
10909 |
|
|
10910 |
return rc; |
return rc; |
11191 |
else |
else |
11192 |
{ |
{ |
11193 |
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); |
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); |
|
try_window (window, startp); |
|
11194 |
if (!make_cursor_line_fully_visible (w)) |
if (!make_cursor_line_fully_visible (w)) |
11195 |
rc = CURSOR_MOVEMENT_NEED_LARGER_MATRICES; |
rc = CURSOR_MOVEMENT_MUST_SCROLL; |
11196 |
else |
else |
11197 |
rc = CURSOR_MOVEMENT_SUCCESS; |
rc = CURSOR_MOVEMENT_SUCCESS; |
11198 |
} |
} |
11210 |
return rc; |
return rc; |
11211 |
} |
} |
11212 |
|
|
11213 |
|
void |
11214 |
|
set_vertical_scroll_bar (w) |
11215 |
|
struct window *w; |
11216 |
|
{ |
11217 |
|
int start, end, whole; |
11218 |
|
|
11219 |
|
/* Calculate the start and end positions for the current window. |
11220 |
|
At some point, it would be nice to choose between scrollbars |
11221 |
|
which reflect the whole buffer size, with special markers |
11222 |
|
indicating narrowing, and scrollbars which reflect only the |
11223 |
|
visible region. |
11224 |
|
|
11225 |
|
Note that mini-buffers sometimes aren't displaying any text. */ |
11226 |
|
if (!MINI_WINDOW_P (w) |
11227 |
|
|| (w == XWINDOW (minibuf_window) |
11228 |
|
&& NILP (echo_area_buffer[0]))) |
11229 |
|
{ |
11230 |
|
struct buffer *buf = XBUFFER (w->buffer); |
11231 |
|
whole = BUF_ZV (buf) - BUF_BEGV (buf); |
11232 |
|
start = marker_position (w->start) - BUF_BEGV (buf); |
11233 |
|
/* I don't think this is guaranteed to be right. For the |
11234 |
|
moment, we'll pretend it is. */ |
11235 |
|
end = BUF_Z (buf) - XFASTINT (w->window_end_pos) - BUF_BEGV (buf); |
11236 |
|
|
11237 |
|
if (end < start) |
11238 |
|
end = start; |
11239 |
|
if (whole < (end - start)) |
11240 |
|
whole = end - start; |
11241 |
|
} |
11242 |
|
else |
11243 |
|
start = end = whole = 0; |
11244 |
|
|
11245 |
|
/* Indicate what this scroll bar ought to be displaying now. */ |
11246 |
|
set_vertical_scroll_bar_hook (w, end - start, whole, start); |
11247 |
|
} |
11248 |
|
|
11249 |
/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only |
/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only |
11250 |
selected_window is redisplayed. */ |
selected_window is redisplayed. |
11251 |
|
|
11252 |
|
We can return without actually redisplaying the window if |
11253 |
|
fonts_changed_p is nonzero. In that case, redisplay_internal will |
11254 |
|
retry. */ |
11255 |
|
|
11256 |
static void |
static void |
11257 |
redisplay_window (window, just_this_one_p) |
redisplay_window (window, just_this_one_p) |
11268 |
struct it it; |
struct it it; |
11269 |
/* Record it now because it's overwritten. */ |
/* Record it now because it's overwritten. */ |
11270 |
int current_matrix_up_to_date_p = 0; |
int current_matrix_up_to_date_p = 0; |
11271 |
|
/* This is less strict than current_matrix_up_to_date_p. |
11272 |
|
It indictes that the buffer contents and narrowing are unchanged. */ |
11273 |
|
int buffer_unchanged_p = 0; |
11274 |
int temp_scroll_step = 0; |
int temp_scroll_step = 0; |
11275 |
int count = BINDING_STACK_SIZE (); |
int count = SPECPDL_INDEX (); |
11276 |
int rc; |
int rc; |
11277 |
|
int centering_position; |
11278 |
|
int last_line_misfit = 0; |
11279 |
|
|
11280 |
SET_TEXT_POS (lpoint, PT, PT_BYTE); |
SET_TEXT_POS (lpoint, PT, PT_BYTE); |
11281 |
opoint = lpoint; |
opoint = lpoint; |
11293 |
/* Has the mode line to be updated? */ |
/* Has the mode line to be updated? */ |
11294 |
update_mode_line = (!NILP (w->update_mode_line) |
update_mode_line = (!NILP (w->update_mode_line) |
11295 |
|| update_mode_lines |
|| update_mode_lines |
11296 |
|| buffer->clip_changed); |
|| buffer->clip_changed |
11297 |
|
|| buffer->prevent_redisplay_optimizations_p); |
11298 |
|
|
11299 |
if (MINI_WINDOW_P (w)) |
if (MINI_WINDOW_P (w)) |
11300 |
{ |
{ |
11309 |
/* We've already displayed the echo area glyphs in this window. */ |
/* We've already displayed the echo area glyphs in this window. */ |
11310 |
goto finish_scroll_bars; |
goto finish_scroll_bars; |
11311 |
} |
} |
11312 |
else if (w != XWINDOW (minibuf_window)) |
else if ((w != XWINDOW (minibuf_window) |
11313 |
|
|| minibuf_level == 0) |
11314 |
|
/* When buffer is nonempty, redisplay window normally. */ |
11315 |
|
&& BUF_Z (XBUFFER (w->buffer)) == BUF_BEG (XBUFFER (w->buffer)) |
11316 |
|
/* Quail displays non-mini buffers in minibuffer window. |
11317 |
|
In that case, redisplay the window normally. */ |
11318 |
|
&& !NILP (Fmemq (w->buffer, Vminibuffer_list))) |
11319 |
{ |
{ |
11320 |
/* W is a mini-buffer window, but it's not the currently |
/* W is a mini-buffer window, but it's not active, so clear |
11321 |
active one, so clear it. */ |
it. */ |
11322 |
int yb = window_text_bottom_y (w); |
int yb = window_text_bottom_y (w); |
11323 |
struct glyph_row *row; |
struct glyph_row *row; |
11324 |
int y; |
int y; |
11343 |
current_matrix_up_to_date_p |
current_matrix_up_to_date_p |
11344 |
= (!NILP (w->window_end_valid) |
= (!NILP (w->window_end_valid) |
11345 |
&& !current_buffer->clip_changed |
&& !current_buffer->clip_changed |
11346 |
|
&& !current_buffer->prevent_redisplay_optimizations_p |
11347 |
|
&& XFASTINT (w->last_modified) >= MODIFF |
11348 |
|
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF); |
11349 |
|
|
11350 |
|
buffer_unchanged_p |
11351 |
|
= (!NILP (w->window_end_valid) |
11352 |
|
&& !current_buffer->clip_changed |
11353 |
&& XFASTINT (w->last_modified) >= MODIFF |
&& XFASTINT (w->last_modified) >= MODIFF |
11354 |
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF); |
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF); |
11355 |
|
|
11465 |
if (!NILP (w->force_start) |
if (!NILP (w->force_start) |
11466 |
|| w->frozen_window_start_p) |
|| w->frozen_window_start_p) |
11467 |
{ |
{ |
11468 |
|
/* We set this later on if we have to adjust point. */ |
11469 |
|
int new_vpos = -1; |
11470 |
|
|
11471 |
w->force_start = Qnil; |
w->force_start = Qnil; |
11472 |
w->vscroll = 0; |
w->vscroll = 0; |
11473 |
w->window_end_valid = Qnil; |
w->window_end_valid = Qnil; |
11474 |
|
|
11475 |
/* Forget any recorded base line for line number display. */ |
/* Forget any recorded base line for line number display. */ |
11476 |
if (!current_matrix_up_to_date_p |
if (!buffer_unchanged_p) |
|
|| current_buffer->clip_changed) |
|
11477 |
w->base_line_number = Qnil; |
w->base_line_number = Qnil; |
11478 |
|
|
11479 |
/* Redisplay the mode line. Select the buffer properly for that. |
/* Redisplay the mode line. Select the buffer properly for that. |
11504 |
{ |
{ |
11505 |
w->force_start = Qt; |
w->force_start = Qt; |
11506 |
clear_glyph_matrix (w->desired_matrix); |
clear_glyph_matrix (w->desired_matrix); |
11507 |
goto finish_scroll_bars; |
goto need_larger_matrices; |
11508 |
} |
} |
11509 |
|
|
11510 |
if (w->cursor.vpos < 0 && !w->frozen_window_start_p) |
if (w->cursor.vpos < 0 && !w->frozen_window_start_p) |
11512 |
/* If point does not appear, try to move point so it does |
/* If point does not appear, try to move point so it does |
11513 |
appear. The desired matrix has been built above, so we |
appear. The desired matrix has been built above, so we |
11514 |
can use it here. */ |
can use it here. */ |
11515 |
int window_height; |
new_vpos = window_box_height (w) / 2; |
11516 |
|
} |
11517 |
|
|
11518 |
|
if (!make_cursor_line_fully_visible (w)) |
11519 |
|
{ |
11520 |
|
/* Point does appear, but on a line partly visible at end of window. |
11521 |
|
Move it back to a fully-visible line. */ |
11522 |
|
new_vpos = window_box_height (w); |
11523 |
|
} |
11524 |
|
|
11525 |
|
/* If we need to move point for either of the above reasons, |
11526 |
|
now actually do it. */ |
11527 |
|
if (new_vpos >= 0) |
11528 |
|
{ |
11529 |
struct glyph_row *row; |
struct glyph_row *row; |
11530 |
|
|
|
window_height = window_box_height (w) / 2; |
|
11531 |
row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix); |
row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix); |
11532 |
while (MATRIX_ROW_BOTTOM_Y (row) < window_height) |
while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos) |
11533 |
++row; |
++row; |
11534 |
|
|
11535 |
TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row), |
TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row), |
11553 |
} |
} |
11554 |
} |
} |
11555 |
|
|
|
if (!make_cursor_line_fully_visible (w)) |
|
|
goto need_larger_matrices; |
|
11556 |
#if GLYPH_DEBUG |
#if GLYPH_DEBUG |
11557 |
debug_method_add (w, "forced window start"); |
debug_method_add (w, "forced window start"); |
11558 |
#endif |
#endif |
11560 |
} |
} |
11561 |
|
|
11562 |
/* Handle case where text has not changed, only point, and it has |
/* Handle case where text has not changed, only point, and it has |
11563 |
not moved off the frame. */ |
not moved off the frame, and we are not retrying after hscroll. |
11564 |
|
(current_matrix_up_to_date_p is nonzero when retrying.) */ |
11565 |
if (current_matrix_up_to_date_p |
if (current_matrix_up_to_date_p |
11566 |
&& (rc = try_cursor_movement (window, startp, &temp_scroll_step), |
&& (rc = try_cursor_movement (window, startp, &temp_scroll_step), |
11567 |
rc != CURSOR_MOVEMENT_CANNOT_BE_USED)) |
rc != CURSOR_MOVEMENT_CANNOT_BE_USED)) |
11571 |
case CURSOR_MOVEMENT_SUCCESS: |
case CURSOR_MOVEMENT_SUCCESS: |
11572 |
goto done; |
goto done; |
11573 |
|
|
11574 |
|
#if 0 /* try_cursor_movement never returns this value. */ |
11575 |
case CURSOR_MOVEMENT_NEED_LARGER_MATRICES: |
case CURSOR_MOVEMENT_NEED_LARGER_MATRICES: |
11576 |
goto need_larger_matrices; |
goto need_larger_matrices; |
11577 |
|
#endif |
11578 |
|
|
11579 |
case CURSOR_MOVEMENT_MUST_SCROLL: |
case CURSOR_MOVEMENT_MUST_SCROLL: |
11580 |
goto try_to_scroll; |
goto try_to_scroll; |
11651 |
w->base_line_number = Qnil; |
w->base_line_number = Qnil; |
11652 |
|
|
11653 |
if (!make_cursor_line_fully_visible (w)) |
if (!make_cursor_line_fully_visible (w)) |
11654 |
goto need_larger_matrices; |
{ |
11655 |
goto done; |
clear_glyph_matrix (w->desired_matrix); |
11656 |
|
last_line_misfit = 1; |
11657 |
|
} |
11658 |
|
/* Drop through and scroll. */ |
11659 |
|
else |
11660 |
|
goto done; |
11661 |
} |
} |
11662 |
else |
else |
11663 |
clear_glyph_matrix (w->desired_matrix); |
clear_glyph_matrix (w->desired_matrix); |
11690 |
int rc = try_scrolling (window, just_this_one_p, |
int rc = try_scrolling (window, just_this_one_p, |
11691 |
scroll_conservatively, |
scroll_conservatively, |
11692 |
scroll_step, |
scroll_step, |
11693 |
temp_scroll_step); |
temp_scroll_step, last_line_misfit); |
11694 |
switch (rc) |
switch (rc) |
11695 |
{ |
{ |
11696 |
case SCROLLING_SUCCESS: |
case SCROLLING_SUCCESS: |
11710 |
/* Finally, just choose place to start which centers point */ |
/* Finally, just choose place to start which centers point */ |
11711 |
|
|
11712 |
recenter: |
recenter: |
11713 |
|
centering_position = window_box_height (w) / 2; |
11714 |
|
|
11715 |
|
point_at_top: |
11716 |
|
/* Jump here with centering_position already set to 0. */ |
11717 |
|
|
11718 |
#if GLYPH_DEBUG |
#if GLYPH_DEBUG |
11719 |
debug_method_add (w, "recenter"); |
debug_method_add (w, "recenter"); |
11722 |
/* w->vscroll = 0; */ |
/* w->vscroll = 0; */ |
11723 |
|
|
11724 |
/* Forget any previously recorded base line for line number display. */ |
/* Forget any previously recorded base line for line number display. */ |
11725 |
if (!current_matrix_up_to_date_p |
if (!buffer_unchanged_p) |
|
|| current_buffer->clip_changed) |
|
11726 |
w->base_line_number = Qnil; |
w->base_line_number = Qnil; |
11727 |
|
|
11728 |
/* Move backward half the height of the window. */ |
/* Move backward half the height of the window. */ |
11729 |
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); |
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); |
11730 |
it.current_y = it.last_visible_y; |
it.current_y = it.last_visible_y; |
11731 |
move_it_vertically_backward (&it, window_box_height (w) / 2); |
move_it_vertically_backward (&it, centering_position); |
11732 |
xassert (IT_CHARPOS (it) >= BEGV); |
xassert (IT_CHARPOS (it) >= BEGV); |
11733 |
|
|
11734 |
/* The function move_it_vertically_backward may move over more |
/* The function move_it_vertically_backward may move over more |
11810 |
} |
} |
11811 |
|
|
11812 |
if (!make_cursor_line_fully_visible (w)) |
if (!make_cursor_line_fully_visible (w)) |
11813 |
goto need_larger_matrices; |
{ |
11814 |
|
/* If vscroll is enabled, disable it and try again. */ |
11815 |
|
if (w->vscroll) |
11816 |
|
{ |
11817 |
|
w->vscroll = 0; |
11818 |
|
clear_glyph_matrix (w->desired_matrix); |
11819 |
|
goto recenter; |
11820 |
|
} |
11821 |
|
|
11822 |
|
/* If centering point failed to make the whole line visible, |
11823 |
|
put point at the top instead. That has to make the whole line |
11824 |
|
visible, if it can be done. */ |
11825 |
|
centering_position = 0; |
11826 |
|
goto point_at_top; |
11827 |
|
} |
11828 |
|
|
11829 |
done: |
done: |
11830 |
|
|
11892 |
&& EQ (FRAME_SELECTED_WINDOW (f), window)) |
&& EQ (FRAME_SELECTED_WINDOW (f), window)) |
11893 |
{ |
{ |
11894 |
int redisplay_menu_p = 0; |
int redisplay_menu_p = 0; |
11895 |
|
int redisplay_tool_bar_p = 0; |
11896 |
|
|
11897 |
if (FRAME_WINDOW_P (f)) |
if (FRAME_WINDOW_P (f)) |
11898 |
{ |
{ |
11899 |
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) |
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ |
11900 |
|
|| defined (USE_GTK) |
11901 |
redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f); |
redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f); |
11902 |
#else |
#else |
11903 |
redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0; |
redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0; |
11910 |
display_menu_bar (w); |
display_menu_bar (w); |
11911 |
|
|
11912 |
#ifdef HAVE_WINDOW_SYSTEM |
#ifdef HAVE_WINDOW_SYSTEM |
11913 |
if (WINDOWP (f->tool_bar_window) |
#ifdef USE_GTK |
11914 |
&& (FRAME_TOOL_BAR_LINES (f) > 0 |
redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f); |
11915 |
|| auto_resize_tool_bars_p)) |
#else |
11916 |
redisplay_tool_bar (f); |
redisplay_tool_bar_p = WINDOWP (f->tool_bar_window) |
11917 |
|
&& (FRAME_TOOL_BAR_LINES (f) > 0 |
11918 |
|
|| auto_resize_tool_bars_p); |
11919 |
|
|
11920 |
|
#endif |
11921 |
|
|
11922 |
|
if (redisplay_tool_bar_p) |
11923 |
|
redisplay_tool_bar (f); |
11924 |
#endif |
#endif |
11925 |
} |
} |
11926 |
|
|
11927 |
|
/* We go to this label, with fonts_changed_p nonzero, |
11928 |
|
if it is necessary to try again using larger glyph matrices. |
11929 |
|
We have to redeem the scroll bar even in this case, |
11930 |
|
because the loop in redisplay_internal expects that. */ |
11931 |
need_larger_matrices: |
need_larger_matrices: |
11932 |
; |
; |
11933 |
finish_scroll_bars: |
finish_scroll_bars: |
11934 |
|
|
11935 |
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) |
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) |
11936 |
{ |
{ |
11937 |
int start, end, whole; |
/* Set the thumb's position and size. */ |
11938 |
|
set_vertical_scroll_bar (w); |
|
/* Calculate the start and end positions for the current window. |
|
|
At some point, it would be nice to choose between scrollbars |
|
|
which reflect the whole buffer size, with special markers |
|
|
indicating narrowing, and scrollbars which reflect only the |
|
|
visible region. |
|
|
|
|
|
Note that mini-buffers sometimes aren't displaying any text. */ |
|
|
if (!MINI_WINDOW_P (w) |
|
|
|| (w == XWINDOW (minibuf_window) |
|
|
&& NILP (echo_area_buffer[0]))) |
|
|
{ |
|
|
whole = ZV - BEGV; |
|
|
start = marker_position (w->start) - BEGV; |
|
|
/* I don't think this is guaranteed to be right. For the |
|
|
moment, we'll pretend it is. */ |
|
|
end = (Z - XFASTINT (w->window_end_pos)) - BEGV; |
|
|
|
|
|
if (end < start) |
|
|
end = start; |
|
|
if (whole < (end - start)) |
|
|
whole = end - start; |
|
|
} |
|
|
else |
|
|
start = end = whole = 0; |
|
|
|
|
|
/* Indicate what this scroll bar ought to be displaying now. */ |
|
|
set_vertical_scroll_bar_hook (w, end - start, whole, start); |
|
11939 |
|
|
11940 |
/* Note that we actually used the scroll bar attached to this |
/* Note that we actually used the scroll bar attached to this |
11941 |
window, so it shouldn't be deleted at the end of redisplay. */ |
window, so it shouldn't be deleted at the end of redisplay. */ |
12148 |
{ |
{ |
12149 |
update_begin (f); |
update_begin (f); |
12150 |
rif->update_window_begin_hook (w); |
rif->update_window_begin_hook (w); |
12151 |
rif->clear_mouse_face (w); |
rif->clear_window_mouse_face (w); |
12152 |
rif->scroll_run_hook (w, &run); |
rif->scroll_run_hook (w, &run); |
12153 |
rif->update_window_end_hook (w, 0, 0); |
rif->update_window_end_hook (w, 0, 0); |
12154 |
update_end (f); |
update_end (f); |
12320 |
struct frame *f = XFRAME (WINDOW_FRAME (w)); |
struct frame *f = XFRAME (WINDOW_FRAME (w)); |
12321 |
update_begin (f); |
update_begin (f); |
12322 |
rif->update_window_begin_hook (w); |
rif->update_window_begin_hook (w); |
12323 |
rif->clear_mouse_face (w); |
rif->clear_window_mouse_face (w); |
12324 |
rif->scroll_run_hook (w, &run); |
rif->scroll_run_hook (w, &run); |
12325 |
rif->update_window_end_hook (w, 0, 0); |
rif->update_window_end_hook (w, 0, 0); |
12326 |
update_end (f); |
update_end (f); |
12625 |
|
|
12626 |
last_y = window_text_bottom_y (w) - dy; |
last_y = window_text_bottom_y (w) - dy; |
12627 |
|
|
12628 |
while ((end == NULL || row < end) |
while (1) |
12629 |
&& MATRIX_ROW_BOTTOM_Y (row) < last_y |
{ |
12630 |
&& (MATRIX_ROW_END_CHARPOS (row) < charpos |
/* Give up if we have gone too far. */ |
12631 |
|
if (end && row >= end) |
12632 |
|
return NULL; |
12633 |
|
/* This formerly returned if they were equal. |
12634 |
|
I think that both quantities are of a "last plus one" type; |
12635 |
|
if so, when they are equal, the row is within the screen. -- rms. */ |
12636 |
|
if (MATRIX_ROW_BOTTOM_Y (row) > last_y) |
12637 |
|
return NULL; |
12638 |
|
|
12639 |
|
/* If it is in this row, return this row. */ |
12640 |
|
if (! (MATRIX_ROW_END_CHARPOS (row) < charpos |
12641 |
|| (MATRIX_ROW_END_CHARPOS (row) == charpos |
|| (MATRIX_ROW_END_CHARPOS (row) == charpos |
12642 |
/* The end position of a row equals the start |
/* The end position of a row equals the start |
12643 |
position of the next row. If CHARPOS is there, we |
position of the next row. If CHARPOS is there, we |
12644 |
would rather display it in the next line, except |
would rather display it in the next line, except |
12645 |
when this line ends in ZV. */ |
when this line ends in ZV. */ |
12646 |
&& !row->ends_at_zv_p |
&& !row->ends_at_zv_p |
12647 |
&& !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))) |
&& !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))) |
12648 |
++row; |
&& charpos >= MATRIX_ROW_START_CHARPOS (row)) |
12649 |
|
return row; |
12650 |
/* Give up if CHARPOS not found. */ |
++row; |
12651 |
if ((end && row >= end) |
} |
|
|| charpos < MATRIX_ROW_START_CHARPOS (row) |
|
|
|| charpos > MATRIX_ROW_END_CHARPOS (row)) |
|
|
row = NULL; |
|
|
|
|
|
return row; |
|
12652 |
} |
} |
12653 |
|
|
12654 |
|
|
12735 |
if (windows_or_buffers_changed || cursor_type_changed) |
if (windows_or_buffers_changed || cursor_type_changed) |
12736 |
GIVE_UP (2); |
GIVE_UP (2); |
12737 |
|
|
12738 |
/* Verify that narrowing has not changed. This flag is also set to prevent |
/* Verify that narrowing has not changed. |
12739 |
redisplay optimizations. It would be nice to further |
Also verify that we were not told to prevent redisplay optimizations. |
12740 |
|
It would be nice to further |
12741 |
reduce the number of cases where this prevents try_window_id. */ |
reduce the number of cases where this prevents try_window_id. */ |
12742 |
if (current_buffer->clip_changed) |
if (current_buffer->clip_changed |
12743 |
|
|| current_buffer->prevent_redisplay_optimizations_p) |
12744 |
GIVE_UP (3); |
GIVE_UP (3); |
12745 |
|
|
12746 |
/* Window must either use window-based redisplay or be full width. */ |
/* Window must either use window-based redisplay or be full width. */ |
12851 |
|
|
12852 |
/* Set the cursor. */ |
/* Set the cursor. */ |
12853 |
row = row_containing_pos (w, PT, r0, NULL, 0); |
row = row_containing_pos (w, PT, r0, NULL, 0); |
12854 |
set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0); |
if (row) |
12855 |
|
set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0); |
12856 |
|
else |
12857 |
|
abort (); |
12858 |
return 1; |
return 1; |
12859 |
} |
} |
12860 |
} |
} |
12892 |
|
|
12893 |
/* Set the cursor. */ |
/* Set the cursor. */ |
12894 |
row = row_containing_pos (w, PT, r0, NULL, 0); |
row = row_containing_pos (w, PT, r0, NULL, 0); |
12895 |
set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0); |
if (row) |
12896 |
|
set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0); |
12897 |
|
else |
12898 |
|
abort (); |
12899 |
return 2; |
return 2; |
12900 |
} |
} |
12901 |
} |
} |
13148 |
if (FRAME_WINDOW_P (f)) |
if (FRAME_WINDOW_P (f)) |
13149 |
{ |
{ |
13150 |
rif->update_window_begin_hook (w); |
rif->update_window_begin_hook (w); |
13151 |
rif->clear_mouse_face (w); |
rif->clear_window_mouse_face (w); |
13152 |
rif->scroll_run_hook (w, &run); |
rif->scroll_run_hook (w, &run); |
13153 |
rif->update_window_end_hook (w, 0, 0); |
rif->update_window_end_hook (w, 0, 0); |
13154 |
} |
} |
13689 |
|
|
13690 |
|
|
13691 |
DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "", |
DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "", |
13692 |
doc: /* Like `format', but print result to stderr. */) |
doc: /* Like `format', but print result to stderr. |
13693 |
|
usage: (trace-to-stderr STRING &rest OBJECTS) */) |
13694 |
(nargs, args) |
(nargs, args) |
13695 |
int nargs; |
int nargs; |
13696 |
Lisp_Object *args; |
Lisp_Object *args; |
13718 |
struct frame *f = XFRAME (WINDOW_FRAME (w)); |
struct frame *f = XFRAME (WINDOW_FRAME (w)); |
13719 |
struct buffer *buffer = XBUFFER (w->buffer); |
struct buffer *buffer = XBUFFER (w->buffer); |
13720 |
struct buffer *old = current_buffer; |
struct buffer *old = current_buffer; |
13721 |
unsigned char *arrow_string = SDATA (Voverlay_arrow_string); |
const unsigned char *arrow_string = SDATA (Voverlay_arrow_string); |
13722 |
int arrow_len = SCHARS (Voverlay_arrow_string); |
int arrow_len = SCHARS (Voverlay_arrow_string); |
13723 |
unsigned char *arrow_end = arrow_string + arrow_len; |
const unsigned char *arrow_end = arrow_string + arrow_len; |
13724 |
unsigned char *p; |
const unsigned char *p; |
13725 |
struct it it; |
struct it it; |
13726 |
int multibyte_p; |
int multibyte_p; |
13727 |
int n_glyphs_before; |
int n_glyphs_before; |
14434 |
{ |
{ |
14435 |
/* Glyph is completely off the left margin of the |
/* Glyph is completely off the left margin of the |
14436 |
window. This should not happen because of the |
window. This should not happen because of the |
14437 |
move_it_in_display_line at the start of |
move_it_in_display_line at the start of this |
14438 |
this function. */ |
function, unless the text display area of the |
14439 |
abort (); |
window is empty. */ |
14440 |
|
xassert (it->first_visible_x <= it->last_visible_x); |
14441 |
} |
} |
14442 |
} |
} |
14443 |
|
|
14624 |
if (!NILP (Vwindow_system)) |
if (!NILP (Vwindow_system)) |
14625 |
return; |
return; |
14626 |
#endif |
#endif |
14627 |
#ifdef USE_X_TOOLKIT |
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) |
14628 |
if (FRAME_X_P (f)) |
if (FRAME_X_P (f)) |
14629 |
return; |
return; |
14630 |
#endif |
#endif |
14872 |
Each element is (PROPERTIZED-STRING . PROPERTY-LIST). */ |
Each element is (PROPERTIZED-STRING . PROPERTY-LIST). */ |
14873 |
Lisp_Object mode_line_proptrans_alist; |
Lisp_Object mode_line_proptrans_alist; |
14874 |
|
|
14875 |
|
/* List of strings making up the mode-line. */ |
14876 |
|
Lisp_Object mode_line_string_list; |
14877 |
|
|
14878 |
|
/* Base face property when building propertized mode line string. */ |
14879 |
|
static Lisp_Object mode_line_string_face; |
14880 |
|
static Lisp_Object mode_line_string_face_prop; |
14881 |
|
|
14882 |
|
|
14883 |
/* Contribute ELT to the mode line for window IT->w. How it |
/* Contribute ELT to the mode line for window IT->w. How it |
14884 |
translates into text depends on its data type. |
translates into text depends on its data type. |
14885 |
|
|
14898 |
PROPS is a property list to add to any string we encounter. |
PROPS is a property list to add to any string we encounter. |
14899 |
|
|
14900 |
If RISKY is nonzero, remove (disregard) any properties in any string |
If RISKY is nonzero, remove (disregard) any properties in any string |
14901 |
we encounter, and ignore :eval and :propertize. */ |
we encounter, and ignore :eval and :propertize. |
14902 |
|
|
14903 |
|
If the global variable `frame_title_ptr' is non-NULL, then the output |
14904 |
|
is passed to `store_frame_title' instead of `display_string'. */ |
14905 |
|
|
14906 |
static int |
static int |
14907 |
display_mode_element (it, depth, field_width, precision, elt, props, risky) |
display_mode_element (it, depth, field_width, precision, elt, props, risky) |
14926 |
{ |
{ |
14927 |
/* A string: output it and check for %-constructs within it. */ |
/* A string: output it and check for %-constructs within it. */ |
14928 |
unsigned char c; |
unsigned char c; |
14929 |
unsigned char *this, *lisp_string; |
const unsigned char *this, *lisp_string; |
14930 |
|
|
14931 |
if (!NILP (props) || risky) |
if (!NILP (props) || risky) |
14932 |
{ |
{ |
14988 |
prec = precision - n; |
prec = precision - n; |
14989 |
if (frame_title_ptr) |
if (frame_title_ptr) |
14990 |
n += store_frame_title (SDATA (elt), -1, prec); |
n += store_frame_title (SDATA (elt), -1, prec); |
14991 |
|
else if (!NILP (mode_line_string_list)) |
14992 |
|
n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil); |
14993 |
else |
else |
14994 |
n += display_string (NULL, elt, Qnil, 0, 0, it, |
n += display_string (NULL, elt, Qnil, 0, 0, it, |
14995 |
0, prec, 0, STRING_MULTIBYTE (elt)); |
0, prec, 0, STRING_MULTIBYTE (elt)); |
15000 |
while ((precision <= 0 || n < precision) |
while ((precision <= 0 || n < precision) |
15001 |
&& *this |
&& *this |
15002 |
&& (frame_title_ptr |
&& (frame_title_ptr |
15003 |
|
|| !NILP (mode_line_string_list) |
15004 |
|| it->current_x < it->last_visible_x)) |
|| it->current_x < it->last_visible_x)) |
15005 |
{ |
{ |
15006 |
unsigned char *last = this; |
const unsigned char *last = this; |
15007 |
|
|
15008 |
/* Advance to end of string or next format specifier. */ |
/* Advance to end of string or next format specifier. */ |
15009 |
while ((c = *this++) != '\0' && c != '%') |
while ((c = *this++) != '\0' && c != '%') |
15022 |
|
|
15023 |
if (frame_title_ptr) |
if (frame_title_ptr) |
15024 |
n += store_frame_title (last, 0, prec); |
n += store_frame_title (last, 0, prec); |
15025 |
|
else if (!NILP (mode_line_string_list)) |
15026 |
|
{ |
15027 |
|
int bytepos = last - lisp_string; |
15028 |
|
int charpos = string_byte_to_char (elt, bytepos); |
15029 |
|
n += store_mode_line_string (NULL, |
15030 |
|
Fsubstring (elt, make_number (charpos), |
15031 |
|
make_number (charpos + prec)), |
15032 |
|
0, 0, 0, Qnil); |
15033 |
|
} |
15034 |
else |
else |
15035 |
{ |
{ |
15036 |
int bytepos = last - lisp_string; |
int bytepos = last - lisp_string; |
15042 |
} |
} |
15043 |
else /* c == '%' */ |
else /* c == '%' */ |
15044 |
{ |
{ |
15045 |
unsigned char *percent_position = this; |
const unsigned char *percent_position = this; |
15046 |
|
|
15047 |
/* Get the specified minimum width. Zero means |
/* Get the specified minimum width. Zero means |
15048 |
don't pad. */ |
don't pad. */ |
15077 |
|
|
15078 |
if (frame_title_ptr) |
if (frame_title_ptr) |
15079 |
n += store_frame_title (spec, field, prec); |
n += store_frame_title (spec, field, prec); |
15080 |
|
else if (!NILP (mode_line_string_list)) |
15081 |
|
{ |
15082 |
|
int len = strlen (spec); |
15083 |
|
Lisp_Object tem = make_string (spec, len); |
15084 |
|
props = Ftext_properties_at (make_number (charpos), elt); |
15085 |
|
/* Should only keep face property in props */ |
15086 |
|
n += store_mode_line_string (NULL, tem, 0, field, prec, props); |
15087 |
|
} |
15088 |
else |
else |
15089 |
{ |
{ |
15090 |
int nglyphs_before, nwritten; |
int nglyphs_before, nwritten; |
15273 |
invalid: |
invalid: |
15274 |
if (frame_title_ptr) |
if (frame_title_ptr) |
15275 |
n += store_frame_title ("*invalid*", 0, precision - n); |
n += store_frame_title ("*invalid*", 0, precision - n); |
15276 |
|
else if (!NILP (mode_line_string_list)) |
15277 |
|
n += store_mode_line_string ("*invalid*", Qnil, 0, 0, precision - n, Qnil); |
15278 |
else |
else |
15279 |
n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0, |
n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0, |
15280 |
precision - n, 0, 0); |
precision - n, 0, 0); |
15286 |
{ |
{ |
15287 |
if (frame_title_ptr) |
if (frame_title_ptr) |
15288 |
n += store_frame_title ("", field_width - n, 0); |
n += store_frame_title ("", field_width - n, 0); |
15289 |
|
else if (!NILP (mode_line_string_list)) |
15290 |
|
n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil); |
15291 |
else |
else |
15292 |
n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n, |
n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n, |
15293 |
0, 0, 0); |
0, 0, 0); |
15296 |
return n; |
return n; |
15297 |
} |
} |
15298 |
|
|
15299 |
|
/* Store a mode-line string element in mode_line_string_list. |
15300 |
|
|
15301 |
|
If STRING is non-null, display that C string. Otherwise, the Lisp |
15302 |
|
string LISP_STRING is displayed. |
15303 |
|
|
15304 |
|
FIELD_WIDTH is the minimum number of output glyphs to produce. |
15305 |
|
If STRING has fewer characters than FIELD_WIDTH, pad to the right |
15306 |
|
with spaces. FIELD_WIDTH <= 0 means don't pad. |
15307 |
|
|
15308 |
|
PRECISION is the maximum number of characters to output from |
15309 |
|
STRING. PRECISION <= 0 means don't truncate the string. |
15310 |
|
|
15311 |
|
If COPY_STRING is non-zero, make a copy of LISP_STRING before adding |
15312 |
|
properties to the string. |
15313 |
|
|
15314 |
|
PROPS are the properties to add to the string. |
15315 |
|
The mode_line_string_face face property is always added to the string. |
15316 |
|
*/ |
15317 |
|
|
15318 |
|
static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props) |
15319 |
|
char *string; |
15320 |
|
Lisp_Object lisp_string; |
15321 |
|
int copy_string; |
15322 |
|
int field_width; |
15323 |
|
int precision; |
15324 |
|
Lisp_Object props; |
15325 |
|
{ |
15326 |
|
int len; |
15327 |
|
int n = 0; |
15328 |
|
|
15329 |
|
if (string != NULL) |
15330 |
|
{ |
15331 |
|
len = strlen (string); |
15332 |
|
if (precision > 0 && len > precision) |
15333 |
|
len = precision; |
15334 |
|
lisp_string = make_string (string, len); |
15335 |
|
if (NILP (props)) |
15336 |
|
props = mode_line_string_face_prop; |
15337 |
|
else if (!NILP (mode_line_string_face)) |
15338 |
|
{ |
15339 |
|
Lisp_Object face = Fplist_get (props, Qface); |
15340 |
|
props = Fcopy_sequence (props); |
15341 |
|
if (NILP (face)) |
15342 |
|
face = mode_line_string_face; |
15343 |
|
else |
15344 |
|
face = Fcons (face, Fcons (mode_line_string_face, Qnil)); |
15345 |
|
props = Fplist_put (props, Qface, face); |
15346 |
|
} |
15347 |
|
Fadd_text_properties (make_number (0), make_number (len), |
15348 |
|
props, lisp_string); |
15349 |
|
} |
15350 |
|
else |
15351 |
|
{ |
15352 |
|
len = XFASTINT (Flength (lisp_string)); |
15353 |
|
if (precision > 0 && len > precision) |
15354 |
|
{ |
15355 |
|
len = precision; |
15356 |
|
lisp_string = Fsubstring (lisp_string, make_number (0), make_number (len)); |
15357 |
|
precision = -1; |
15358 |
|
} |
15359 |
|
if (!NILP (mode_line_string_face)) |
15360 |
|
{ |
15361 |
|
Lisp_Object face; |
15362 |
|
if (NILP (props)) |
15363 |
|
props = Ftext_properties_at (make_number (0), lisp_string); |
15364 |
|
face = Fplist_get (props, Qface); |
15365 |
|
if (NILP (face)) |
15366 |
|
face = mode_line_string_face; |
15367 |
|
else |
15368 |
|
face = Fcons (face, Fcons (mode_line_string_face, Qnil)); |
15369 |
|
props = Fcons (Qface, Fcons (face, Qnil)); |
15370 |
|
if (copy_string) |
15371 |
|
lisp_string = Fcopy_sequence (lisp_string); |
15372 |
|
} |
15373 |
|
if (!NILP (props)) |
15374 |
|
Fadd_text_properties (make_number (0), make_number (len), |
15375 |
|
props, lisp_string); |
15376 |
|
} |
15377 |
|
|
15378 |
|
if (len > 0) |
15379 |
|
{ |
15380 |
|
mode_line_string_list = Fcons (lisp_string, mode_line_string_list); |
15381 |
|
n += len; |
15382 |
|
} |
15383 |
|
|
15384 |
|
if (field_width > len) |
15385 |
|
{ |
15386 |
|
field_width -= len; |
15387 |
|
lisp_string = Fmake_string (make_number (field_width), make_number (' ')); |
15388 |
|
if (!NILP (props)) |
15389 |
|
Fadd_text_properties (make_number (0), make_number (field_width), |
15390 |
|
props, lisp_string); |
15391 |
|
mode_line_string_list = Fcons (lisp_string, mode_line_string_list); |
15392 |
|
n += field_width; |
15393 |
|
} |
15394 |
|
|
15395 |
|
return n; |
15396 |
|
} |
15397 |
|
|
15398 |
|
|
15399 |
DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line, |
DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line, |
15400 |
0, 2, 0, |
0, 3, 0, |
15401 |
doc: /* Return the mode-line of selected window as a string. |
doc: /* Return the mode-line of selected window as a string. |
15402 |
First optional arg FORMAT specifies a different format string (see |
First optional arg FORMAT specifies a different format string (see |
15403 |
`mode-line-format' for for details) to use. If FORMAT is t, return |
`mode-line-format' for details) to use. If FORMAT is t, return |
15404 |
the buffer's header-line. Second optional arg WINDOW specifies a |
the buffer's header-line. Second optional arg WINDOW specifies a |
15405 |
different window to use as the context for the formatting. */) |
different window to use as the context for the formatting. |
15406 |
(format, window) |
If third optional arg NO-PROPS is non-nil, string is not propertized. */) |
15407 |
Lisp_Object format, window; |
(format, window, no_props) |
15408 |
|
Lisp_Object format, window, no_props; |
15409 |
{ |
{ |
15410 |
struct it it; |
struct it it; |
|
struct face *face; |
|
15411 |
int len; |
int len; |
15412 |
struct window *w; |
struct window *w; |
15413 |
struct buffer *old_buffer = NULL; |
struct buffer *old_buffer = NULL; |
15414 |
|
enum face_id face_id = DEFAULT_FACE_ID; |
15415 |
|
|
15416 |
if (NILP (window)) |
if (NILP (window)) |
15417 |
window = selected_window; |
window = selected_window; |
15426 |
} |
} |
15427 |
|
|
15428 |
if (NILP (format) || EQ (format, Qt)) |
if (NILP (format) || EQ (format, Qt)) |
15429 |
format = NILP (format) |
{ |
15430 |
? current_buffer->mode_line_format |
face_id = NILP (format) |
15431 |
: current_buffer->header_line_format; |
? CURRENT_MODE_LINE_FACE_ID (w) : |
15432 |
|
HEADER_LINE_FACE_ID; |
15433 |
|
format = NILP (format) |
15434 |
|
? current_buffer->mode_line_format |
15435 |
|
: current_buffer->header_line_format; |
15436 |
|
} |
15437 |
|
|
15438 |
init_iterator (&it, w, -1, -1, NULL, DEFAULT_FACE_ID); |
init_iterator (&it, w, -1, -1, NULL, face_id); |
15439 |
|
|
15440 |
frame_title_ptr = frame_title_buf; |
if (NILP (no_props)) |
15441 |
|
{ |
15442 |
|
mode_line_string_face = |
15443 |
|
(face_id == MODE_LINE_FACE_ID ? Qmode_line : |
15444 |
|
face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive : |
15445 |
|
face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil); |
15446 |
|
|
15447 |
|
mode_line_string_face_prop = |
15448 |
|
NILP (mode_line_string_face) ? Qnil : |
15449 |
|
Fcons (Qface, Fcons (mode_line_string_face, Qnil)); |
15450 |
|
|
15451 |
|
/* We need a dummy last element in mode_line_string_list to |
15452 |
|
indicate we are building the propertized mode-line string. |
15453 |
|
Using mode_line_string_face_prop here GC protects it. */ |
15454 |
|
mode_line_string_list = |
15455 |
|
Fcons (mode_line_string_face_prop, Qnil); |
15456 |
|
frame_title_ptr = NULL; |
15457 |
|
} |
15458 |
|
else |
15459 |
|
{ |
15460 |
|
mode_line_string_face_prop = Qnil; |
15461 |
|
mode_line_string_list = Qnil; |
15462 |
|
frame_title_ptr = frame_title_buf; |
15463 |
|
} |
15464 |
|
|
15465 |
push_frame_kboard (it.f); |
push_frame_kboard (it.f); |
15466 |
display_mode_element (&it, 0, 0, 0, format, Qnil, 0); |
display_mode_element (&it, 0, 0, 0, format, Qnil, 0); |
15469 |
if (old_buffer) |
if (old_buffer) |
15470 |
set_buffer_internal_1 (old_buffer); |
set_buffer_internal_1 (old_buffer); |
15471 |
|
|
15472 |
|
if (NILP (no_props)) |
15473 |
|
{ |
15474 |
|
Lisp_Object str; |
15475 |
|
mode_line_string_list = Fnreverse (mode_line_string_list); |
15476 |
|
str = Fmapconcat (intern ("identity"), XCDR (mode_line_string_list), |
15477 |
|
make_string ("", 0)); |
15478 |
|
mode_line_string_face_prop = Qnil; |
15479 |
|
mode_line_string_list = Qnil; |
15480 |
|
return str; |
15481 |
|
} |
15482 |
|
|
15483 |
len = frame_title_ptr - frame_title_buf; |
len = frame_title_ptr - frame_title_buf; |
15484 |
if (len > 0 && frame_title_ptr[-1] == '-') |
if (len > 0 && frame_title_ptr[-1] == '-') |
15485 |
{ |
{ |
15542 |
{ |
{ |
15543 |
Lisp_Object val; |
Lisp_Object val; |
15544 |
int multibyte = !NILP (current_buffer->enable_multibyte_characters); |
int multibyte = !NILP (current_buffer->enable_multibyte_characters); |
15545 |
unsigned char *eol_str; |
const unsigned char *eol_str; |
15546 |
int eol_str_len; |
int eol_str_len; |
15547 |
/* The EOL conversion we are using. */ |
/* The EOL conversion we are using. */ |
15548 |
Lisp_Object eoltype; |
Lisp_Object eoltype; |
15594 |
else if (INTEGERP (eoltype) |
else if (INTEGERP (eoltype) |
15595 |
&& CHAR_VALID_P (XINT (eoltype), 0)) |
&& CHAR_VALID_P (XINT (eoltype), 0)) |
15596 |
{ |
{ |
15597 |
eol_str = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH); |
unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH); |
15598 |
eol_str_len = CHAR_STRING (XINT (eoltype), eol_str); |
eol_str_len = CHAR_STRING (XINT (eoltype), tmp); |
15599 |
|
eol_str = tmp; |
15600 |
} |
} |
15601 |
else |
else |
15602 |
{ |
{ |
15692 |
register int i; |
register int i; |
15693 |
|
|
15694 |
/* Let lots_of_dashes be a string of infinite length. */ |
/* Let lots_of_dashes be a string of infinite length. */ |
15695 |
|
if (!NILP (mode_line_string_list)) |
15696 |
|
return "--"; |
15697 |
if (field_width <= 0 |
if (field_width <= 0 |
15698 |
|| field_width > sizeof (lots_of_dashes)) |
|| field_width > sizeof (lots_of_dashes)) |
15699 |
{ |
{ |
16347 |
|
|
16348 |
|
|
16349 |
/*********************************************************************** |
/*********************************************************************** |
16350 |
|
Glyph Display |
16351 |
|
***********************************************************************/ |
16352 |
|
|
16353 |
|
#ifdef HAVE_WINDOW_SYSTEM |
16354 |
|
|
16355 |
|
#if GLYPH_DEBUG |
16356 |
|
|
16357 |
|
void |
16358 |
|
dump_glyph_string (s) |
16359 |
|
struct glyph_string *s; |
16360 |
|
{ |
16361 |
|
fprintf (stderr, "glyph string\n"); |
16362 |
|
fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n", |
16363 |
|
s->x, s->y, s->width, s->height); |
16364 |
|
fprintf (stderr, " ybase = %d\n", s->ybase); |
16365 |
|
fprintf (stderr, " hl = %d\n", s->hl); |
16366 |
|
fprintf (stderr, " left overhang = %d, right = %d\n", |
16367 |
|
s->left_overhang, s->right_overhang); |
16368 |
|
fprintf (stderr, " nchars = %d\n", s->nchars); |
16369 |
|
fprintf (stderr, " extends to end of line = %d\n", |
16370 |
|
s->extends_to_end_of_line_p); |
16371 |
|
fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font)); |
16372 |
|
fprintf (stderr, " bg width = %d\n", s->background_width); |
16373 |
|
} |
16374 |
|
|
16375 |
|
#endif /* GLYPH_DEBUG */ |
16376 |
|
|
16377 |
|
/* Initialize glyph string S. CHAR2B is a suitably allocated vector |
16378 |
|
of XChar2b structures for S; it can't be allocated in |
16379 |
|
init_glyph_string because it must be allocated via `alloca'. W |
16380 |
|
is the window on which S is drawn. ROW and AREA are the glyph row |
16381 |
|
and area within the row from which S is constructed. START is the |
16382 |
|
index of the first glyph structure covered by S. HL is a |
16383 |
|
face-override for drawing S. */ |
16384 |
|
|
16385 |
|
#ifdef HAVE_NTGUI |
16386 |
|
#define OPTIONAL_HDC(hdc) hdc, |
16387 |
|
#define DECLARE_HDC(hdc) HDC hdc; |
16388 |
|
#define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f)) |
16389 |
|
#define RELEASE_HDC(hdc, f) release_frame_dc ((f), (hdc)) |
16390 |
|
#endif |
16391 |
|
|
16392 |
|
#ifndef OPTIONAL_HDC |
16393 |
|
#define OPTIONAL_HDC(hdc) |
16394 |
|
#define DECLARE_HDC(hdc) |
16395 |
|
#define ALLOCATE_HDC(hdc, f) |
16396 |
|
#define RELEASE_HDC(hdc, f) |
16397 |
|
#endif |
16398 |
|
|
16399 |
|
static void |
16400 |
|
init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl) |
16401 |
|
struct glyph_string *s; |
16402 |
|
DECLARE_HDC (hdc) |
16403 |
|
XChar2b *char2b; |
16404 |
|
struct window *w; |
16405 |
|
struct glyph_row *row; |
16406 |
|
enum glyph_row_area area; |
16407 |
|
int start; |
16408 |
|
enum draw_glyphs_face hl; |
16409 |
|
{ |
16410 |
|
bzero (s, sizeof *s); |
16411 |
|
s->w = w; |
16412 |
|
s->f = XFRAME (w->frame); |
16413 |
|
#ifdef HAVE_NTGUI |
16414 |
|
s->hdc = hdc; |
16415 |
|
#endif |
16416 |
|
s->display = FRAME_X_DISPLAY (s->f); |
16417 |
|
s->window = FRAME_X_WINDOW (s->f); |
16418 |
|
s->char2b = char2b; |
16419 |
|
s->hl = hl; |
16420 |
|
s->row = row; |
16421 |
|
s->area = area; |
16422 |
|
s->first_glyph = row->glyphs[area] + start; |
16423 |
|
s->height = row->height; |
16424 |
|
s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); |
16425 |
|
|
16426 |
|
/* Display the internal border below the tool-bar window. */ |
16427 |
|
if (s->w == XWINDOW (s->f->tool_bar_window)) |
16428 |
|
s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f); |
16429 |
|
|
16430 |
|
s->ybase = s->y + row->ascent; |
16431 |
|
} |
16432 |
|
|
16433 |
|
|
16434 |
|
/* Append the list of glyph strings with head H and tail T to the list |
16435 |
|
with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */ |
16436 |
|
|
16437 |
|
static INLINE void |
16438 |
|
append_glyph_string_lists (head, tail, h, t) |
16439 |
|
struct glyph_string **head, **tail; |
16440 |
|
struct glyph_string *h, *t; |
16441 |
|
{ |
16442 |
|
if (h) |
16443 |
|
{ |
16444 |
|
if (*head) |
16445 |
|
(*tail)->next = h; |
16446 |
|
else |
16447 |
|
*head = h; |
16448 |
|
h->prev = *tail; |
16449 |
|
*tail = t; |
16450 |
|
} |
16451 |
|
} |
16452 |
|
|
16453 |
|
|
16454 |
|
/* Prepend the list of glyph strings with head H and tail T to the |
16455 |
|
list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the |
16456 |
|
result. */ |
16457 |
|
|
16458 |
|
static INLINE void |
16459 |
|
prepend_glyph_string_lists (head, tail, h, t) |
16460 |
|
struct glyph_string **head, **tail; |
16461 |
|
struct glyph_string *h, *t; |
16462 |
|
{ |
16463 |
|
if (h) |
16464 |
|
{ |
16465 |
|
if (*head) |
16466 |
|
(*head)->prev = t; |
16467 |
|
else |
16468 |
|
*tail = t; |
16469 |
|
t->next = *head; |
16470 |
|
*head = h; |
16471 |
|
} |
16472 |
|
} |
16473 |
|
|
16474 |
|
|
16475 |
|
/* Append glyph string S to the list with head *HEAD and tail *TAIL. |
16476 |
|
Set *HEAD and *TAIL to the resulting list. */ |
16477 |
|
|
16478 |
|
static INLINE void |
16479 |
|
append_glyph_string (head, tail, s) |
16480 |
|
struct glyph_string **head, **tail; |
16481 |
|
struct glyph_string *s; |
16482 |
|
{ |
16483 |
|
s->next = s->prev = NULL; |
16484 |
|
append_glyph_string_lists (head, tail, s, s); |
16485 |
|
} |
16486 |
|
|
16487 |
|
|
16488 |
|
/* Get face and two-byte form of character glyph GLYPH on frame F. |
16489 |
|
The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is |
16490 |
|
a pointer to a realized face that is ready for display. */ |
16491 |
|
|
16492 |
|
static INLINE struct face * |
16493 |
|
get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p) |
16494 |
|
struct frame *f; |
16495 |
|
struct glyph *glyph; |
16496 |
|
XChar2b *char2b; |
16497 |
|
int *two_byte_p; |
16498 |
|
{ |
16499 |
|
struct face *face; |
16500 |
|
|
16501 |
|
xassert (glyph->type == CHAR_GLYPH); |
16502 |
|
face = FACE_FROM_ID (f, glyph->face_id); |
16503 |
|
|
16504 |
|
if (two_byte_p) |
16505 |
|
*two_byte_p = 0; |
16506 |
|
|
16507 |
|
if (!glyph->multibyte_p) |
16508 |
|
{ |
16509 |
|
/* Unibyte case. We don't have to encode, but we have to make |
16510 |
|
sure to use a face suitable for unibyte. */ |
16511 |
|
STORE_XCHAR2B (char2b, 0, glyph->u.ch); |
16512 |
|
} |
16513 |
|
else if (glyph->u.ch < 128 |
16514 |
|
&& glyph->face_id < BASIC_FACE_ID_SENTINEL) |
16515 |
|
{ |
16516 |
|
/* Case of ASCII in a face known to fit ASCII. */ |
16517 |
|
STORE_XCHAR2B (char2b, 0, glyph->u.ch); |
16518 |
|
} |
16519 |
|
else |
16520 |
|
{ |
16521 |
|
int c1, c2, charset; |
16522 |
|
|
16523 |
|
/* Split characters into bytes. If c2 is -1 afterwards, C is |
16524 |
|
really a one-byte character so that byte1 is zero. */ |
16525 |
|
SPLIT_CHAR (glyph->u.ch, charset, c1, c2); |
16526 |
|
if (c2 > 0) |
16527 |
|
STORE_XCHAR2B (char2b, c1, c2); |
16528 |
|
else |
16529 |
|
STORE_XCHAR2B (char2b, 0, c1); |
16530 |
|
|
16531 |
|
/* Maybe encode the character in *CHAR2B. */ |
16532 |
|
if (charset != CHARSET_ASCII) |
16533 |
|
{ |
16534 |
|
struct font_info *font_info |
16535 |
|
= FONT_INFO_FROM_ID (f, face->font_info_id); |
16536 |
|
if (font_info) |
16537 |
|
glyph->font_type |
16538 |
|
= rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p); |
16539 |
|
} |
16540 |
|
} |
16541 |
|
|
16542 |
|
/* Make sure X resources of the face are allocated. */ |
16543 |
|
xassert (face != NULL); |
16544 |
|
PREPARE_FACE_FOR_DISPLAY (f, face); |
16545 |
|
return face; |
16546 |
|
} |
16547 |
|
|
16548 |
|
|
16549 |
|
/* Fill glyph string S with composition components specified by S->cmp. |
16550 |
|
|
16551 |
|
FACES is an array of faces for all components of this composition. |
16552 |
|
S->gidx is the index of the first component for S. |
16553 |
|
OVERLAPS_P non-zero means S should draw the foreground only, and |
16554 |
|
use its physical height for clipping. |
16555 |
|
|
16556 |
|
Value is the index of a component not in S. */ |
16557 |
|
|
16558 |
|
static int |
16559 |
|
fill_composite_glyph_string (s, faces, overlaps_p) |
16560 |
|
struct glyph_string *s; |
16561 |
|
struct face **faces; |
16562 |
|
int overlaps_p; |
16563 |
|
{ |
16564 |
|
int i; |
16565 |
|
|
16566 |
|
xassert (s); |
16567 |
|
|
16568 |
|
s->for_overlaps_p = overlaps_p; |
16569 |
|
|
16570 |
|
s->face = faces[s->gidx]; |
16571 |
|
s->font = s->face->font; |
16572 |
|
s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id); |
16573 |
|
|
16574 |
|
/* For all glyphs of this composition, starting at the offset |
16575 |
|
S->gidx, until we reach the end of the definition or encounter a |
16576 |
|
glyph that requires the different face, add it to S. */ |
16577 |
|
++s->nchars; |
16578 |
|
for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i) |
16579 |
|
++s->nchars; |
16580 |
|
|
16581 |
|
/* All glyph strings for the same composition has the same width, |
16582 |
|
i.e. the width set for the first component of the composition. */ |
16583 |
|
|
16584 |
|
s->width = s->first_glyph->pixel_width; |
16585 |
|
|
16586 |
|
/* If the specified font could not be loaded, use the frame's |
16587 |
|
default font, but record the fact that we couldn't load it in |
16588 |
|
the glyph string so that we can draw rectangles for the |
16589 |
|
characters of the glyph string. */ |
16590 |
|
if (s->font == NULL) |
16591 |
|
{ |
16592 |
|
s->font_not_found_p = 1; |
16593 |
|
s->font = FRAME_FONT (s->f); |
16594 |
|
} |
16595 |
|
|
16596 |
|
/* Adjust base line for subscript/superscript text. */ |
16597 |
|
s->ybase += s->first_glyph->voffset; |
16598 |
|
|
16599 |
|
xassert (s->face && s->face->gc); |
16600 |
|
|
16601 |
|
/* This glyph string must always be drawn with 16-bit functions. */ |
16602 |
|
s->two_byte_p = 1; |
16603 |
|
|
16604 |
|
return s->gidx + s->nchars; |
16605 |
|
} |
16606 |
|
|
16607 |
|
|
16608 |
|
/* Fill glyph string S from a sequence of character glyphs. |
16609 |
|
|
16610 |
|
FACE_ID is the face id of the string. START is the index of the |
16611 |
|
first glyph to consider, END is the index of the last + 1. |
16612 |
|
OVERLAPS_P non-zero means S should draw the foreground only, and |
16613 |
|
use its physical height for clipping. |
16614 |
|
|
16615 |
|
Value is the index of the first glyph not in S. */ |
16616 |
|
|
16617 |
|
static int |
16618 |
|
fill_glyph_string (s, face_id, start, end, overlaps_p) |
16619 |
|
struct glyph_string *s; |
16620 |
|
int face_id; |
16621 |
|
int start, end, overlaps_p; |
16622 |
|
{ |
16623 |
|
struct glyph *glyph, *last; |
16624 |
|
int voffset; |
16625 |
|
int glyph_not_available_p; |
16626 |
|
|
16627 |
|
xassert (s->f == XFRAME (s->w->frame)); |
16628 |
|
xassert (s->nchars == 0); |
16629 |
|
xassert (start >= 0 && end > start); |
16630 |
|
|
16631 |
|
s->for_overlaps_p = overlaps_p, |
16632 |
|
glyph = s->row->glyphs[s->area] + start; |
16633 |
|
last = s->row->glyphs[s->area] + end; |
16634 |
|
voffset = glyph->voffset; |
16635 |
|
|
16636 |
|
glyph_not_available_p = glyph->glyph_not_available_p; |
16637 |
|
|
16638 |
|
while (glyph < last |
16639 |
|
&& glyph->type == CHAR_GLYPH |
16640 |
|
&& glyph->voffset == voffset |
16641 |
|
/* Same face id implies same font, nowadays. */ |
16642 |
|
&& glyph->face_id == face_id |
16643 |
|
&& glyph->glyph_not_available_p == glyph_not_available_p) |
16644 |
|
{ |
16645 |
|
int two_byte_p; |
16646 |
|
|
16647 |
|
s->face = get_glyph_face_and_encoding (s->f, glyph, |
16648 |
|
s->char2b + s->nchars, |
16649 |
|
&two_byte_p); |
16650 |
|
s->two_byte_p = two_byte_p; |
16651 |
|
++s->nchars; |
16652 |
|
xassert (s->nchars <= end - start); |
16653 |
|
s->width += glyph->pixel_width; |
16654 |
|
++glyph; |
16655 |
|
} |
16656 |
|
|
16657 |
|
s->font = s->face->font; |
16658 |
|
s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id); |
16659 |
|
|
16660 |
|
/* If the specified font could not be loaded, use the frame's font, |
16661 |
|
but record the fact that we couldn't load it in |
16662 |
|
S->font_not_found_p so that we can draw rectangles for the |
16663 |
|
characters of the glyph string. */ |
16664 |
|
if (s->font == NULL || glyph_not_available_p) |
16665 |
|
{ |
16666 |
|
s->font_not_found_p = 1; |
16667 |
|
s->font = FRAME_FONT (s->f); |
16668 |
|
} |
16669 |
|
|
16670 |
|
/* Adjust base line for subscript/superscript text. */ |
16671 |
|
s->ybase += voffset; |
16672 |
|
|
16673 |
|
xassert (s->face && s->face->gc); |
16674 |
|
return glyph - s->row->glyphs[s->area]; |
16675 |
|
} |
16676 |
|
|
16677 |
|
|
16678 |
|
/* Fill glyph string S from image glyph S->first_glyph. */ |
16679 |
|
|
16680 |
|
static void |
16681 |
|
fill_image_glyph_string (s) |
16682 |
|
struct glyph_string *s; |
16683 |
|
{ |
16684 |
|
xassert (s->first_glyph->type == IMAGE_GLYPH); |
16685 |
|
s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id); |
16686 |
|
xassert (s->img); |
16687 |
|
s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id); |
16688 |
|
s->font = s->face->font; |
16689 |
|
s->width = s->first_glyph->pixel_width; |
16690 |
|
|
16691 |
|
/* Adjust base line for subscript/superscript text. */ |
16692 |
|
s->ybase += s->first_glyph->voffset; |
16693 |
|
} |
16694 |
|
|
16695 |
|
|
16696 |
|
/* Fill glyph string S from a sequence of stretch glyphs. |
16697 |
|
|
16698 |
|
ROW is the glyph row in which the glyphs are found, AREA is the |
16699 |
|
area within the row. START is the index of the first glyph to |
16700 |
|
consider, END is the index of the last + 1. |
16701 |
|
|
16702 |
|
Value is the index of the first glyph not in S. */ |
16703 |
|
|
16704 |
|
static int |
16705 |
|
fill_stretch_glyph_string (s, row, area, start, end) |
16706 |
|
struct glyph_string *s; |
16707 |
|
struct glyph_row *row; |
16708 |
|
enum glyph_row_area area; |
16709 |
|
int start, end; |
16710 |
|
{ |
16711 |
|
struct glyph *glyph, *last; |
16712 |
|
int voffset, face_id; |
16713 |
|
|
16714 |
|
xassert (s->first_glyph->type == STRETCH_GLYPH); |
16715 |
|
|
16716 |
|
glyph = s->row->glyphs[s->area] + start; |
16717 |
|
last = s->row->glyphs[s->area] + end; |
16718 |
|
face_id = glyph->face_id; |
16719 |
|
s->face = FACE_FROM_ID (s->f, face_id); |
16720 |
|
s->font = s->face->font; |
16721 |
|
s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id); |
16722 |
|
s->width = glyph->pixel_width; |
16723 |
|
voffset = glyph->voffset; |
16724 |
|
|
16725 |
|
for (++glyph; |
16726 |
|
(glyph < last |
16727 |
|
&& glyph->type == STRETCH_GLYPH |
16728 |
|
&& glyph->voffset == voffset |
16729 |
|
&& glyph->face_id == face_id); |
16730 |
|
++glyph) |
16731 |
|
s->width += glyph->pixel_width; |
16732 |
|
|
16733 |
|
/* Adjust base line for subscript/superscript text. */ |
16734 |
|
s->ybase += voffset; |
16735 |
|
|
16736 |
|
/* The case that face->gc == 0 is handled when drawing the glyph |
16737 |
|
string by calling PREPARE_FACE_FOR_DISPLAY. */ |
16738 |
|
xassert (s->face); |
16739 |
|
return glyph - s->row->glyphs[s->area]; |
16740 |
|
} |
16741 |
|
|
16742 |
|
|
16743 |
|
/* EXPORT for RIF: |
16744 |
|
Set *LEFT and *RIGHT to the left and right overhang of GLYPH on |
16745 |
|
frame F. Overhangs of glyphs other than type CHAR_GLYPH are |
16746 |
|
assumed to be zero. */ |
16747 |
|
|
16748 |
|
void |
16749 |
|
x_get_glyph_overhangs (glyph, f, left, right) |
16750 |
|
struct glyph *glyph; |
16751 |
|
struct frame *f; |
16752 |
|
int *left, *right; |
16753 |
|
{ |
16754 |
|
*left = *right = 0; |
16755 |
|
|
16756 |
|
if (glyph->type == CHAR_GLYPH) |
16757 |
|
{ |
16758 |
|
XFontStruct *font; |
16759 |
|
struct face *face; |
16760 |
|
struct font_info *font_info; |
16761 |
|
XChar2b char2b; |
16762 |
|
XCharStruct *pcm; |
16763 |
|
|
16764 |
|
face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL); |
16765 |
|
font = face->font; |
16766 |
|
font_info = FONT_INFO_FROM_ID (f, face->font_info_id); |
16767 |
|
if (font /* ++KFS: Should this be font_info ? */ |
16768 |
|
&& (pcm = rif->per_char_metric (font, &char2b, glyph->font_type))) |
16769 |
|
{ |
16770 |
|
if (pcm->rbearing > pcm->width) |
16771 |
|
*right = pcm->rbearing - pcm->width; |
16772 |
|
if (pcm->lbearing < 0) |
16773 |
|
*left = -pcm->lbearing; |
16774 |
|
} |
16775 |
|
} |
16776 |
|
} |
16777 |
|
|
16778 |
|
|
16779 |
|
/* Return the index of the first glyph preceding glyph string S that |
16780 |
|
is overwritten by S because of S's left overhang. Value is -1 |
16781 |
|
if no glyphs are overwritten. */ |
16782 |
|
|
16783 |
|
static int |
16784 |
|
left_overwritten (s) |
16785 |
|
struct glyph_string *s; |
16786 |
|
{ |
16787 |
|
int k; |
16788 |
|
|
16789 |
|
if (s->left_overhang) |
16790 |
|
{ |
16791 |
|
int x = 0, i; |
16792 |
|
struct glyph *glyphs = s->row->glyphs[s->area]; |
16793 |
|
int first = s->first_glyph - glyphs; |
16794 |
|
|
16795 |
|
for (i = first - 1; i >= 0 && x > -s->left_overhang; --i) |
16796 |
|
x -= glyphs[i].pixel_width; |
16797 |
|
|
16798 |
|
k = i + 1; |
16799 |
|
} |
16800 |
|
else |
16801 |
|
k = -1; |
16802 |
|
|
16803 |
|
return k; |
16804 |
|
} |
16805 |
|
|
16806 |
|
|
16807 |
|
/* Return the index of the first glyph preceding glyph string S that |
16808 |
|
is overwriting S because of its right overhang. Value is -1 if no |
16809 |
|
glyph in front of S overwrites S. */ |
16810 |
|
|
16811 |
|
static int |
16812 |
|
left_overwriting (s) |
16813 |
|
struct glyph_string *s; |
16814 |
|
{ |
16815 |
|
int i, k, x; |
16816 |
|
struct glyph *glyphs = s->row->glyphs[s->area]; |
16817 |
|
int first = s->first_glyph - glyphs; |
16818 |
|
|
16819 |
|
k = -1; |
16820 |
|
x = 0; |
16821 |
|
for (i = first - 1; i >= 0; --i) |
16822 |
|
{ |
16823 |
|
int left, right; |
16824 |
|
x_get_glyph_overhangs (glyphs + i, s->f, &left, &right); |
16825 |
|
if (x + right > 0) |
16826 |
|
k = i; |
16827 |
|
x -= glyphs[i].pixel_width; |
16828 |
|
} |
16829 |
|
|
16830 |
|
return k; |
16831 |
|
} |
16832 |
|
|
16833 |
|
|
16834 |
|
/* Return the index of the last glyph following glyph string S that is |
16835 |
|
not overwritten by S because of S's right overhang. Value is -1 if |
16836 |
|
no such glyph is found. */ |
16837 |
|
|
16838 |
|
static int |
16839 |
|
right_overwritten (s) |
16840 |
|
struct glyph_string *s; |
16841 |
|
{ |
16842 |
|
int k = -1; |
16843 |
|
|
16844 |
|
if (s->right_overhang) |
16845 |
|
{ |
16846 |
|
int x = 0, i; |
16847 |
|
struct glyph *glyphs = s->row->glyphs[s->area]; |
16848 |
|
int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars); |
16849 |
|
int end = s->row->used[s->area]; |
16850 |
|
|
16851 |
|
for (i = first; i < end && s->right_overhang > x; ++i) |
16852 |
|
x += glyphs[i].pixel_width; |
16853 |
|
|
16854 |
|
k = i; |
16855 |
|
} |
16856 |
|
|
16857 |
|
return k; |
16858 |
|
} |
16859 |
|
|
16860 |
|
|
16861 |
|
/* Return the index of the last glyph following glyph string S that |
16862 |
|
overwrites S because of its left overhang. Value is negative |
16863 |
|
if no such glyph is found. */ |
16864 |
|
|
16865 |
|
static int |
16866 |
|
right_overwriting (s) |
16867 |
|
struct glyph_string *s; |
16868 |
|
{ |
16869 |
|
int i, k, x; |
16870 |
|
int end = s->row->used[s->area]; |
16871 |
|
struct glyph *glyphs = s->row->glyphs[s->area]; |
16872 |
|
int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars); |
16873 |
|
|
16874 |
|
k = -1; |
16875 |
|
x = 0; |
16876 |
|
for (i = first; i < end; ++i) |
16877 |
|
{ |
16878 |
|
int left, right; |
16879 |
|
x_get_glyph_overhangs (glyphs + i, s->f, &left, &right); |
16880 |
|
if (x - left < 0) |
16881 |
|
k = i; |
16882 |
|
x += glyphs[i].pixel_width; |
16883 |
|
} |
16884 |
|
|
16885 |
|
return k; |
16886 |
|
} |
16887 |
|
|
16888 |
|
|
16889 |
|
/* Get face and two-byte form of character C in face FACE_ID on frame |
16890 |
|
F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero |
16891 |
|
means we want to display multibyte text. DISPLAY_P non-zero means |
16892 |
|
make sure that X resources for the face returned are allocated. |
16893 |
|
Value is a pointer to a realized face that is ready for display if |
16894 |
|
DISPLAY_P is non-zero. */ |
16895 |
|
|
16896 |
|
static INLINE struct face * |
16897 |
|
get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p) |
16898 |
|
struct frame *f; |
16899 |
|
int c, face_id; |
16900 |
|
XChar2b *char2b; |
16901 |
|
int multibyte_p, display_p; |
16902 |
|
{ |
16903 |
|
struct face *face = FACE_FROM_ID (f, face_id); |
16904 |
|
|
16905 |
|
if (!multibyte_p) |
16906 |
|
{ |
16907 |
|
/* Unibyte case. We don't have to encode, but we have to make |
16908 |
|
sure to use a face suitable for unibyte. */ |
16909 |
|
STORE_XCHAR2B (char2b, 0, c); |
16910 |
|
face_id = FACE_FOR_CHAR (f, face, c); |
16911 |
|
face = FACE_FROM_ID (f, face_id); |
16912 |
|
} |
16913 |
|
else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL) |
16914 |
|
{ |
16915 |
|
/* Case of ASCII in a face known to fit ASCII. */ |
16916 |
|
STORE_XCHAR2B (char2b, 0, c); |
16917 |
|
} |
16918 |
|
else |
16919 |
|
{ |
16920 |
|
int c1, c2, charset; |
16921 |
|
|
16922 |
|
/* Split characters into bytes. If c2 is -1 afterwards, C is |
16923 |
|
really a one-byte character so that byte1 is zero. */ |
16924 |
|
SPLIT_CHAR (c, charset, c1, c2); |
16925 |
|
if (c2 > 0) |
16926 |
|
STORE_XCHAR2B (char2b, c1, c2); |
16927 |
|
else |
16928 |
|
STORE_XCHAR2B (char2b, 0, c1); |
16929 |
|
|
16930 |
|
/* Maybe encode the character in *CHAR2B. */ |
16931 |
|
if (face->font != NULL) |
16932 |
|
{ |
16933 |
|
struct font_info *font_info |
16934 |
|
= FONT_INFO_FROM_ID (f, face->font_info_id); |
16935 |
|
if (font_info) |
16936 |
|
rif->encode_char (c, char2b, font_info, 0); |
16937 |
|
} |
16938 |
|
} |
16939 |
|
|
16940 |
|
/* Make sure X resources of the face are allocated. */ |
16941 |
|
#ifdef HAVE_X_WINDOWS |
16942 |
|
if (display_p) |
16943 |
|
#endif |
16944 |
|
{ |
16945 |
|
xassert (face != NULL); |
16946 |
|
PREPARE_FACE_FOR_DISPLAY (f, face); |
16947 |
|
} |
16948 |
|
|
16949 |
|
return face; |
16950 |
|
} |
16951 |
|
|
16952 |
|
|
16953 |
|
/* Set background width of glyph string S. START is the index of the |
16954 |
|
first glyph following S. LAST_X is the right-most x-position + 1 |
16955 |
|
in the drawing area. */ |
16956 |
|
|
16957 |
|
static INLINE void |
16958 |
|
set_glyph_string_background_width (s, start, last_x) |
16959 |
|
struct glyph_string *s; |
16960 |
|
int start; |
16961 |
|
int last_x; |
16962 |
|
{ |
16963 |
|
/* If the face of this glyph string has to be drawn to the end of |
16964 |
|
the drawing area, set S->extends_to_end_of_line_p. */ |
16965 |
|
struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID); |
16966 |
|
|
16967 |
|
if (start == s->row->used[s->area] |
16968 |
|
&& s->area == TEXT_AREA |
16969 |
|
&& ((s->hl == DRAW_NORMAL_TEXT |
16970 |
|
&& (s->row->fill_line_p |
16971 |
|
|| s->face->background != default_face->background |
16972 |
|
|| s->face->stipple != default_face->stipple |
16973 |
|
|| s->row->mouse_face_p)) |
16974 |
|
|| s->hl == DRAW_MOUSE_FACE |
16975 |
|
|| ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) |
16976 |
|
&& s->row->fill_line_p))) |
16977 |
|
s->extends_to_end_of_line_p = 1; |
16978 |
|
|
16979 |
|
/* If S extends its face to the end of the line, set its |
16980 |
|
background_width to the distance to the right edge of the drawing |
16981 |
|
area. */ |
16982 |
|
if (s->extends_to_end_of_line_p) |
16983 |
|
s->background_width = last_x - s->x + 1; |
16984 |
|
else |
16985 |
|
s->background_width = s->width; |
16986 |
|
} |
16987 |
|
|
16988 |
|
|
16989 |
|
/* Compute overhangs and x-positions for glyph string S and its |
16990 |
|
predecessors, or successors. X is the starting x-position for S. |
16991 |
|
BACKWARD_P non-zero means process predecessors. */ |
16992 |
|
|
16993 |
|
static void |
16994 |
|
compute_overhangs_and_x (s, x, backward_p) |
16995 |
|
struct glyph_string *s; |
16996 |
|
int x; |
16997 |
|
int backward_p; |
16998 |
|
{ |
16999 |
|
if (backward_p) |
17000 |
|
{ |
17001 |
|
while (s) |
17002 |
|
{ |
17003 |
|
if (rif->compute_glyph_string_overhangs) |
17004 |
|
rif->compute_glyph_string_overhangs (s); |
17005 |
|
x -= s->width; |
17006 |
|
s->x = x; |
17007 |
|
s = s->prev; |
17008 |
|
} |
17009 |
|
} |
17010 |
|
else |
17011 |
|
{ |
17012 |
|
while (s) |
17013 |
|
{ |
17014 |
|
if (rif->compute_glyph_string_overhangs) |
17015 |
|
rif->compute_glyph_string_overhangs (s); |
17016 |
|
s->x = x; |
17017 |
|
x += s->width; |
17018 |
|
s = s->next; |
17019 |
|
} |
17020 |
|
} |
17021 |
|
} |
17022 |
|
|
17023 |
|
|
17024 |
|
|
17025 |
|
/* The following macros are only called from draw_glyphs below. |
17026 |
|
They reference the following parameters of that function directly: |
17027 |
|
`w', `row', `area', and `overlap_p' |
17028 |
|
as well as the following local variables: |
17029 |
|
`s', `f', and `hdc' (in W32) */ |
17030 |
|
|
17031 |
|
#ifdef HAVE_NTGUI |
17032 |
|
/* On W32, silently add local `hdc' variable to argument list of |
17033 |
|
init_glyph_string. */ |
17034 |
|
#define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \ |
17035 |
|
init_glyph_string (s, hdc, char2b, w, row, area, start, hl) |
17036 |
|
#else |
17037 |
|
#define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \ |
17038 |
|
init_glyph_string (s, char2b, w, row, area, start, hl) |
17039 |
|
#endif |
17040 |
|
|
17041 |
|
/* Add a glyph string for a stretch glyph to the list of strings |
17042 |
|
between HEAD and TAIL. START is the index of the stretch glyph in |
17043 |
|
row area AREA of glyph row ROW. END is the index of the last glyph |
17044 |
|
in that glyph row area. X is the current output position assigned |
17045 |
|
to the new glyph string constructed. HL overrides that face of the |
17046 |
|
glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X |
17047 |
|
is the right-most x-position of the drawing area. */ |
17048 |
|
|
17049 |
|
/* SunOS 4 bundled cc, barfed on continuations in the arg lists here |
17050 |
|
and below -- keep them on one line. */ |
17051 |
|
#define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ |
17052 |
|
do \ |
17053 |
|
{ \ |
17054 |
|
s = (struct glyph_string *) alloca (sizeof *s); \ |
17055 |
|
INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \ |
17056 |
|
START = fill_stretch_glyph_string (s, row, area, START, END); \ |
17057 |
|
append_glyph_string (&HEAD, &TAIL, s); \ |
17058 |
|
s->x = (X); \ |
17059 |
|
} \ |
17060 |
|
while (0) |
17061 |
|
|
17062 |
|
|
17063 |
|
/* Add a glyph string for an image glyph to the list of strings |
17064 |
|
between HEAD and TAIL. START is the index of the image glyph in |
17065 |
|
row area AREA of glyph row ROW. END is the index of the last glyph |
17066 |
|
in that glyph row area. X is the current output position assigned |
17067 |
|
to the new glyph string constructed. HL overrides that face of the |
17068 |
|
glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X |
17069 |
|
is the right-most x-position of the drawing area. */ |
17070 |
|
|
17071 |
|
#define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ |
17072 |
|
do \ |
17073 |
|
{ \ |
17074 |
|
s = (struct glyph_string *) alloca (sizeof *s); \ |
17075 |
|
INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \ |
17076 |
|
fill_image_glyph_string (s); \ |
17077 |
|
append_glyph_string (&HEAD, &TAIL, s); \ |
17078 |
|
++START; \ |
17079 |
|
s->x = (X); \ |
17080 |
|
} \ |
17081 |
|
while (0) |
17082 |
|
|
17083 |
|
|
17084 |
|
/* Add a glyph string for a sequence of character glyphs to the list |
17085 |
|
of strings between HEAD and TAIL. START is the index of the first |
17086 |
|
glyph in row area AREA of glyph row ROW that is part of the new |
17087 |
|
glyph string. END is the index of the last glyph in that glyph row |
17088 |
|
area. X is the current output position assigned to the new glyph |
17089 |
|
string constructed. HL overrides that face of the glyph; e.g. it |
17090 |
|
is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the |
17091 |
|
right-most x-position of the drawing area. */ |
17092 |
|
|
17093 |
|
#define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ |
17094 |
|
do \ |
17095 |
|
{ \ |
17096 |
|
int c, face_id; \ |
17097 |
|
XChar2b *char2b; \ |
17098 |
|
\ |
17099 |
|
c = (row)->glyphs[area][START].u.ch; \ |
17100 |
|
face_id = (row)->glyphs[area][START].face_id; \ |
17101 |
|
\ |
17102 |
|
s = (struct glyph_string *) alloca (sizeof *s); \ |
17103 |
|
char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \ |
17104 |
|
INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ |
17105 |
|
append_glyph_string (&HEAD, &TAIL, s); \ |
17106 |
|
s->x = (X); \ |
17107 |
|
START = fill_glyph_string (s, face_id, START, END, overlaps_p); \ |
17108 |
|
} \ |
17109 |
|
while (0) |
17110 |
|
|
17111 |
|
|
17112 |
|
/* Add a glyph string for a composite sequence to the list of strings |
17113 |
|
between HEAD and TAIL. START is the index of the first glyph in |
17114 |
|
row area AREA of glyph row ROW that is part of the new glyph |
17115 |
|
string. END is the index of the last glyph in that glyph row area. |
17116 |
|
X is the current output position assigned to the new glyph string |
17117 |
|
constructed. HL overrides that face of the glyph; e.g. it is |
17118 |
|
DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most |
17119 |
|
x-position of the drawing area. */ |
17120 |
|
|
17121 |
|
#define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ |
17122 |
|
do { \ |
17123 |
|
int cmp_id = (row)->glyphs[area][START].u.cmp_id; \ |
17124 |
|
int face_id = (row)->glyphs[area][START].face_id; \ |
17125 |
|
struct face *base_face = FACE_FROM_ID (f, face_id); \ |
17126 |
|
struct composition *cmp = composition_table[cmp_id]; \ |
17127 |
|
int glyph_len = cmp->glyph_len; \ |
17128 |
|
XChar2b *char2b; \ |
17129 |
|
struct face **faces; \ |
17130 |
|
struct glyph_string *first_s = NULL; \ |
17131 |
|
int n; \ |
17132 |
|
\ |
17133 |
|
base_face = base_face->ascii_face; \ |
17134 |
|
char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \ |
17135 |
|
faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \ |
17136 |
|
/* At first, fill in `char2b' and `faces'. */ \ |
17137 |
|
for (n = 0; n < glyph_len; n++) \ |
17138 |
|
{ \ |
17139 |
|
int c = COMPOSITION_GLYPH (cmp, n); \ |
17140 |
|
int this_face_id = FACE_FOR_CHAR (f, base_face, c); \ |
17141 |
|
faces[n] = FACE_FROM_ID (f, this_face_id); \ |
17142 |
|
get_char_face_and_encoding (f, c, this_face_id, \ |
17143 |
|
char2b + n, 1, 1); \ |
17144 |
|
} \ |
17145 |
|
\ |
17146 |
|
/* Make glyph_strings for each glyph sequence that is drawable by \ |
17147 |
|
the same face, and append them to HEAD/TAIL. */ \ |
17148 |
|
for (n = 0; n < cmp->glyph_len;) \ |
17149 |
|
{ \ |
17150 |
|
s = (struct glyph_string *) alloca (sizeof *s); \ |
17151 |
|
INIT_GLYPH_STRING (s, char2b + n, w, row, area, START, HL); \ |
17152 |
|
append_glyph_string (&(HEAD), &(TAIL), s); \ |
17153 |
|
s->cmp = cmp; \ |
17154 |
|
s->gidx = n; \ |
17155 |
|
s->x = (X); \ |
17156 |
|
\ |
17157 |
|
if (n == 0) \ |
17158 |
|
first_s = s; \ |
17159 |
|
\ |
17160 |
|
n = fill_composite_glyph_string (s, faces, overlaps_p); \ |
17161 |
|
} \ |
17162 |
|
\ |
17163 |
|
++START; \ |
17164 |
|
s = first_s; \ |
17165 |
|
} while (0) |
17166 |
|
|
17167 |
|
|
17168 |
|
/* Build a list of glyph strings between HEAD and TAIL for the glyphs |
17169 |
|
of AREA of glyph row ROW on window W between indices START and END. |
17170 |
|
HL overrides the face for drawing glyph strings, e.g. it is |
17171 |
|
DRAW_CURSOR to draw a cursor. X and LAST_X are start and end |
17172 |
|
x-positions of the drawing area. |
17173 |
|
|
17174 |
|
This is an ugly monster macro construct because we must use alloca |
17175 |
|
to allocate glyph strings (because draw_glyphs can be called |
17176 |
|
asynchronously). */ |
17177 |
|
|
17178 |
|
#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ |
17179 |
|
do \ |
17180 |
|
{ \ |
17181 |
|
HEAD = TAIL = NULL; \ |
17182 |
|
while (START < END) \ |
17183 |
|
{ \ |
17184 |
|
struct glyph *first_glyph = (row)->glyphs[area] + START; \ |
17185 |
|
switch (first_glyph->type) \ |
17186 |
|
{ \ |
17187 |
|
case CHAR_GLYPH: \ |
17188 |
|
BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \ |
17189 |
|
HL, X, LAST_X); \ |
17190 |
|
break; \ |
17191 |
|
\ |
17192 |
|
case COMPOSITE_GLYPH: \ |
17193 |
|
BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \ |
17194 |
|
HL, X, LAST_X); \ |
17195 |
|
break; \ |
17196 |
|
\ |
17197 |
|
case STRETCH_GLYPH: \ |
17198 |
|
BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \ |
17199 |
|
HL, X, LAST_X); \ |
17200 |
|
break; \ |
17201 |
|
\ |
17202 |
|
case IMAGE_GLYPH: \ |
17203 |
|
BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ |
17204 |
|
HL, X, LAST_X); \ |
17205 |
|
break; \ |
17206 |
|
\ |
17207 |
|
default: \ |
17208 |
|
abort (); \ |
17209 |
|
} \ |
17210 |
|
\ |
17211 |
|
set_glyph_string_background_width (s, START, LAST_X); \ |
17212 |
|
(X) += s->width; \ |
17213 |
|
} \ |
17214 |
|
} \ |
17215 |
|
while (0) |
17216 |
|
|
17217 |
|
|
17218 |
|
/* Draw glyphs between START and END in AREA of ROW on window W, |
17219 |
|
starting at x-position X. X is relative to AREA in W. HL is a |
17220 |
|
face-override with the following meaning: |
17221 |
|
|
17222 |
|
DRAW_NORMAL_TEXT draw normally |
17223 |
|
DRAW_CURSOR draw in cursor face |
17224 |
|
DRAW_MOUSE_FACE draw in mouse face. |
17225 |
|
DRAW_INVERSE_VIDEO draw in mode line face |
17226 |
|
DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it |
17227 |
|
DRAW_IMAGE_RAISED draw an image with a raised relief around it |
17228 |
|
|
17229 |
|
If OVERLAPS_P is non-zero, draw only the foreground of characters |
17230 |
|
and clip to the physical height of ROW. |
17231 |
|
|
17232 |
|
Value is the x-position reached, relative to AREA of W. */ |
17233 |
|
|
17234 |
|
static int |
17235 |
|
draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) |
17236 |
|
struct window *w; |
17237 |
|
int x; |
17238 |
|
struct glyph_row *row; |
17239 |
|
enum glyph_row_area area; |
17240 |
|
int start, end; |
17241 |
|
enum draw_glyphs_face hl; |
17242 |
|
int overlaps_p; |
17243 |
|
{ |
17244 |
|
struct glyph_string *head, *tail; |
17245 |
|
struct glyph_string *s; |
17246 |
|
int last_x, area_width; |
17247 |
|
int x_reached; |
17248 |
|
int i, j; |
17249 |
|
struct frame *f = XFRAME (WINDOW_FRAME (w)); |
17250 |
|
DECLARE_HDC (hdc); |
17251 |
|
|
17252 |
|
ALLOCATE_HDC (hdc, f); |
17253 |
|
|
17254 |
|
/* Let's rather be paranoid than getting a SEGV. */ |
17255 |
|
end = min (end, row->used[area]); |
17256 |
|
start = max (0, start); |
17257 |
|
start = min (end, start); |
17258 |
|
|
17259 |
|
/* Translate X to frame coordinates. Set last_x to the right |
17260 |
|
end of the drawing area. */ |
17261 |
|
if (row->full_width_p) |
17262 |
|
{ |
17263 |
|
/* X is relative to the left edge of W, without scroll bars |
17264 |
|
or fringes. */ |
17265 |
|
int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f); |
17266 |
|
|
17267 |
|
x += window_left_x; |
17268 |
|
area_width = XFASTINT (w->width) * CANON_X_UNIT (f); |
17269 |
|
last_x = window_left_x + area_width; |
17270 |
|
|
17271 |
|
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) |
17272 |
|
{ |
17273 |
|
int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f); |
17274 |
|
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) |
17275 |
|
last_x += width; |
17276 |
|
else |
17277 |
|
x -= width; |
17278 |
|
} |
17279 |
|
|
17280 |
|
x += FRAME_INTERNAL_BORDER_WIDTH (f); |
17281 |
|
/* ++KFS: W32 and MAC versions had -= in next line (bug??) */ |
17282 |
|
last_x += FRAME_INTERNAL_BORDER_WIDTH (f); |
17283 |
|
} |
17284 |
|
else |
17285 |
|
{ |
17286 |
|
x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x); |
17287 |
|
area_width = window_box_width (w, area); |
17288 |
|
last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width); |
17289 |
|
} |
17290 |
|
|
17291 |
|
/* Build a doubly-linked list of glyph_string structures between |
17292 |
|
head and tail from what we have to draw. Note that the macro |
17293 |
|
BUILD_GLYPH_STRINGS will modify its start parameter. That's |
17294 |
|
the reason we use a separate variable `i'. */ |
17295 |
|
i = start; |
17296 |
|
BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x); |
17297 |
|
if (tail) |
17298 |
|
x_reached = tail->x + tail->background_width; |
17299 |
|
else |
17300 |
|
x_reached = x; |
17301 |
|
|
17302 |
|
/* If there are any glyphs with lbearing < 0 or rbearing > width in |
17303 |
|
the row, redraw some glyphs in front or following the glyph |
17304 |
|
strings built above. */ |
17305 |
|
if (head && !overlaps_p && row->contains_overlapping_glyphs_p) |
17306 |
|
{ |
17307 |
|
int dummy_x = 0; |
17308 |
|
struct glyph_string *h, *t; |
17309 |
|
|
17310 |
|
/* Compute overhangs for all glyph strings. */ |
17311 |
|
if (rif->compute_glyph_string_overhangs) |
17312 |
|
for (s = head; s; s = s->next) |
17313 |
|
rif->compute_glyph_string_overhangs (s); |
17314 |
|
|
17315 |
|
/* Prepend glyph strings for glyphs in front of the first glyph |
17316 |
|
string that are overwritten because of the first glyph |
17317 |
|
string's left overhang. The background of all strings |
17318 |
|
prepended must be drawn because the first glyph string |
17319 |
|
draws over it. */ |
17320 |
|
i = left_overwritten (head); |
17321 |
|
if (i >= 0) |
17322 |
|
{ |
17323 |
|
j = i; |
17324 |
|
BUILD_GLYPH_STRINGS (j, start, h, t, |
17325 |
|
DRAW_NORMAL_TEXT, dummy_x, last_x); |
17326 |
|
start = i; |
17327 |
|
compute_overhangs_and_x (t, head->x, 1); |
17328 |
|
prepend_glyph_string_lists (&head, &tail, h, t); |
17329 |
|
} |
17330 |
|
|
17331 |
|
/* Prepend glyph strings for glyphs in front of the first glyph |
17332 |
|
string that overwrite that glyph string because of their |
17333 |
|
right overhang. For these strings, only the foreground must |
17334 |
|
be drawn, because it draws over the glyph string at `head'. |
17335 |
|
The background must not be drawn because this would overwrite |
17336 |
|
right overhangs of preceding glyphs for which no glyph |
17337 |
|
strings exist. */ |
17338 |
|
i = left_overwriting (head); |
17339 |
|
if (i >= 0) |
17340 |
|
{ |
17341 |
|
BUILD_GLYPH_STRINGS (i, start, h, t, |
17342 |
|
DRAW_NORMAL_TEXT, dummy_x, last_x); |
17343 |
|
for (s = h; s; s = s->next) |
17344 |
|
s->background_filled_p = 1; |
17345 |
|
compute_overhangs_and_x (t, head->x, 1); |
17346 |
|
prepend_glyph_string_lists (&head, &tail, h, t); |
17347 |
|
} |
17348 |
|
|
17349 |
|
/* Append glyphs strings for glyphs following the last glyph |
17350 |
|
string tail that are overwritten by tail. The background of |
17351 |
|
these strings has to be drawn because tail's foreground draws |
17352 |
|
over it. */ |
17353 |
|
i = right_overwritten (tail); |
17354 |
|
if (i >= 0) |
17355 |
|
{ |
17356 |
|
BUILD_GLYPH_STRINGS (end, i, h, t, |
17357 |
|
DRAW_NORMAL_TEXT, x, last_x); |
17358 |
|
compute_overhangs_and_x (h, tail->x + tail->width, 0); |
17359 |
|
append_glyph_string_lists (&head, &tail, h, t); |
17360 |
|
} |
17361 |
|
|
17362 |
|
/* Append glyph strings for glyphs following the last glyph |
17363 |
|
string tail that overwrite tail. The foreground of such |
17364 |
|
glyphs has to be drawn because it writes into the background |
17365 |
|
of tail. The background must not be drawn because it could |
17366 |
|
paint over the foreground of following glyphs. */ |
17367 |
|
i = right_overwriting (tail); |
17368 |
|
if (i >= 0) |
17369 |
|
{ |
17370 |
|
BUILD_GLYPH_STRINGS (end, i, h, t, |
17371 |
|
DRAW_NORMAL_TEXT, x, last_x); |
17372 |
|
for (s = h; s; s = s->next) |
17373 |
|
s->background_filled_p = 1; |
17374 |
|
compute_overhangs_and_x (h, tail->x + tail->width, 0); |
17375 |
|
append_glyph_string_lists (&head, &tail, h, t); |
17376 |
|
} |
17377 |
|
} |
17378 |
|
|
17379 |
|
/* Draw all strings. */ |
17380 |
|
for (s = head; s; s = s->next) |
17381 |
|
rif->draw_glyph_string (s); |
17382 |
|
|
17383 |
|
if (area == TEXT_AREA |
17384 |
|
&& !row->full_width_p |
17385 |
|
/* When drawing overlapping rows, only the glyph strings' |
17386 |
|
foreground is drawn, which doesn't erase a cursor |
17387 |
|
completely. */ |
17388 |
|
&& !overlaps_p) |
17389 |
|
{ |
17390 |
|
int x0 = head ? head->x : x; |
17391 |
|
int x1 = tail ? tail->x + tail->background_width : x; |
17392 |
|
|
17393 |
|
x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0); |
17394 |
|
x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1); |
17395 |
|
|
17396 |
|
/* ++KFS: W32 and MAC versions had following test here: |
17397 |
|
if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0) |
17398 |
|
*/ |
17399 |
|
|
17400 |
|
if (XFASTINT (w->left_margin_width) != 0) |
17401 |
|
{ |
17402 |
|
int left_area_width = window_box_width (w, LEFT_MARGIN_AREA); |
17403 |
|
x0 -= left_area_width; |
17404 |
|
x1 -= left_area_width; |
17405 |
|
} |
17406 |
|
|
17407 |
|
notice_overwritten_cursor (w, area, x0, x1, |
17408 |
|
row->y, MATRIX_ROW_BOTTOM_Y (row)); |
17409 |
|
} |
17410 |
|
|
17411 |
|
/* Value is the x-position up to which drawn, relative to AREA of W. |
17412 |
|
This doesn't include parts drawn because of overhangs. */ |
17413 |
|
x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached); |
17414 |
|
if (!row->full_width_p) |
17415 |
|
{ |
17416 |
|
/* ++KFS: W32 and MAC versions only had this test here: |
17417 |
|
if (area > LEFT_MARGIN_AREA) |
17418 |
|
*/ |
17419 |
|
|
17420 |
|
if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0) |
17421 |
|
x_reached -= window_box_width (w, LEFT_MARGIN_AREA); |
17422 |
|
if (area > TEXT_AREA) |
17423 |
|
x_reached -= window_box_width (w, TEXT_AREA); |
17424 |
|
} |
17425 |
|
|
17426 |
|
RELEASE_HDC (hdc, f); |
17427 |
|
|
17428 |
|
return x_reached; |
17429 |
|
} |
17430 |
|
|
17431 |
|
|
17432 |
|
/* Store one glyph for IT->char_to_display in IT->glyph_row. |
17433 |
|
Called from x_produce_glyphs when IT->glyph_row is non-null. */ |
17434 |
|
|
17435 |
|
static INLINE void |
17436 |
|
append_glyph (it) |
17437 |
|
struct it *it; |
17438 |
|
{ |
17439 |
|
struct glyph *glyph; |
17440 |
|
enum glyph_row_area area = it->area; |
17441 |
|
|
17442 |
|
xassert (it->glyph_row); |
17443 |
|
xassert (it->char_to_display != '\n' && it->char_to_display != '\t'); |
17444 |
|
|
17445 |
|
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; |
17446 |
|
if (glyph < it->glyph_row->glyphs[area + 1]) |
17447 |
|
{ |
17448 |
|
glyph->charpos = CHARPOS (it->position); |
17449 |
|
glyph->object = it->object; |
17450 |
|
glyph->pixel_width = it->pixel_width; |
17451 |
|
glyph->voffset = it->voffset; |
17452 |
|
glyph->type = CHAR_GLYPH; |
17453 |
|
glyph->multibyte_p = it->multibyte_p; |
17454 |
|
glyph->left_box_line_p = it->start_of_box_run_p; |
17455 |
|
glyph->right_box_line_p = it->end_of_box_run_p; |
17456 |
|
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent |
17457 |
|
|| it->phys_descent > it->descent); |
17458 |
|
glyph->padding_p = 0; |
17459 |
|
glyph->glyph_not_available_p = it->glyph_not_available_p; |
17460 |
|
glyph->face_id = it->face_id; |
17461 |
|
glyph->u.ch = it->char_to_display; |
17462 |
|
glyph->font_type = FONT_TYPE_UNKNOWN; |
17463 |
|
++it->glyph_row->used[area]; |
17464 |
|
} |
17465 |
|
} |
17466 |
|
|
17467 |
|
/* Store one glyph for the composition IT->cmp_id in IT->glyph_row. |
17468 |
|
Called from x_produce_glyphs when IT->glyph_row is non-null. */ |
17469 |
|
|
17470 |
|
static INLINE void |
17471 |
|
append_composite_glyph (it) |
17472 |
|
struct it *it; |
17473 |
|
{ |
17474 |
|
struct glyph *glyph; |
17475 |
|
enum glyph_row_area area = it->area; |
17476 |
|
|
17477 |
|
xassert (it->glyph_row); |
17478 |
|
|
17479 |
|
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; |
17480 |
|
if (glyph < it->glyph_row->glyphs[area + 1]) |
17481 |
|
{ |
17482 |
|
glyph->charpos = CHARPOS (it->position); |
17483 |
|
glyph->object = it->object; |
17484 |
|
glyph->pixel_width = it->pixel_width; |
17485 |
|
glyph->voffset = it->voffset; |
17486 |
|
glyph->type = COMPOSITE_GLYPH; |
17487 |
|
glyph->multibyte_p = it->multibyte_p; |
17488 |
|
glyph->left_box_line_p = it->start_of_box_run_p; |
17489 |
|
glyph->right_box_line_p = it->end_of_box_run_p; |
17490 |
|
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent |
17491 |
|
|| it->phys_descent > it->descent); |
17492 |
|
glyph->padding_p = 0; |
17493 |
|
glyph->glyph_not_available_p = 0; |
17494 |
|
glyph->face_id = it->face_id; |
17495 |
|
glyph->u.cmp_id = it->cmp_id; |
17496 |
|
glyph->font_type = FONT_TYPE_UNKNOWN; |
17497 |
|
++it->glyph_row->used[area]; |
17498 |
|
} |
17499 |
|
} |
17500 |
|
|
17501 |
|
|
17502 |
|
/* Change IT->ascent and IT->height according to the setting of |
17503 |
|
IT->voffset. */ |
17504 |
|
|
17505 |
|
static INLINE void |
17506 |
|
take_vertical_position_into_account (it) |
17507 |
|
struct it *it; |
17508 |
|
{ |
17509 |
|
if (it->voffset) |
17510 |
|
{ |
17511 |
|
if (it->voffset < 0) |
17512 |
|
/* Increase the ascent so that we can display the text higher |
17513 |
|
in the line. */ |
17514 |
|
it->ascent += abs (it->voffset); |
17515 |
|
else |
17516 |
|
/* Increase the descent so that we can display the text lower |
17517 |
|
in the line. */ |
17518 |
|
it->descent += it->voffset; |
17519 |
|
} |
17520 |
|
} |
17521 |
|
|
17522 |
|
|
17523 |
|
/* Produce glyphs/get display metrics for the image IT is loaded with. |
17524 |
|
See the description of struct display_iterator in dispextern.h for |
17525 |
|
an overview of struct display_iterator. */ |
17526 |
|
|
17527 |
|
static void |
17528 |
|
produce_image_glyph (it) |
17529 |
|
struct it *it; |
17530 |
|
{ |
17531 |
|
struct image *img; |
17532 |
|
struct face *face; |
17533 |
|
|
17534 |
|
xassert (it->what == IT_IMAGE); |
17535 |
|
|
17536 |
|
face = FACE_FROM_ID (it->f, it->face_id); |
17537 |
|
img = IMAGE_FROM_ID (it->f, it->image_id); |
17538 |
|
xassert (img); |
17539 |
|
|
17540 |
|
/* Make sure X resources of the face and image are loaded. */ |
17541 |
|
PREPARE_FACE_FOR_DISPLAY (it->f, face); |
17542 |
|
prepare_image_for_display (it->f, img); |
17543 |
|
|
17544 |
|
it->ascent = it->phys_ascent = image_ascent (img, face); |
17545 |
|
it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent; |
17546 |
|
it->pixel_width = img->width + 2 * img->hmargin; |
17547 |
|
|
17548 |
|
it->nglyphs = 1; |
17549 |
|
|
17550 |
|
if (face->box != FACE_NO_BOX) |
17551 |
|
{ |
17552 |
|
if (face->box_line_width > 0) |
17553 |
|
{ |
17554 |
|
it->ascent += face->box_line_width; |
17555 |
|
it->descent += face->box_line_width; |
17556 |
|
} |
17557 |
|
|
17558 |
|
if (it->start_of_box_run_p) |
17559 |
|
it->pixel_width += abs (face->box_line_width); |
17560 |
|
if (it->end_of_box_run_p) |
17561 |
|
it->pixel_width += abs (face->box_line_width); |
17562 |
|
} |
17563 |
|
|
17564 |
|
take_vertical_position_into_account (it); |
17565 |
|
|
17566 |
|
if (it->glyph_row) |
17567 |
|
{ |
17568 |
|
struct glyph *glyph; |
17569 |
|
enum glyph_row_area area = it->area; |
17570 |
|
|
17571 |
|
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; |
17572 |
|
if (glyph < it->glyph_row->glyphs[area + 1]) |
17573 |
|
{ |
17574 |
|
glyph->charpos = CHARPOS (it->position); |
17575 |
|
glyph->object = it->object; |
17576 |
|
glyph->pixel_width = it->pixel_width; |
17577 |
|
glyph->voffset = it->voffset; |
17578 |
|
glyph->type = IMAGE_GLYPH; |
17579 |
|
glyph->multibyte_p = it->multibyte_p; |
17580 |
|
glyph->left_box_line_p = it->start_of_box_run_p; |
17581 |
|
glyph->right_box_line_p = it->end_of_box_run_p; |
17582 |
|
glyph->overlaps_vertically_p = 0; |
17583 |
|
glyph->padding_p = 0; |
17584 |
|
glyph->glyph_not_available_p = 0; |
17585 |
|
glyph->face_id = it->face_id; |
17586 |
|
glyph->u.img_id = img->id; |
17587 |
|
glyph->font_type = FONT_TYPE_UNKNOWN; |
17588 |
|
++it->glyph_row->used[area]; |
17589 |
|
} |
17590 |
|
} |
17591 |
|
} |
17592 |
|
|
17593 |
|
|
17594 |
|
/* Append a stretch glyph to IT->glyph_row. OBJECT is the source |
17595 |
|
of the glyph, WIDTH and HEIGHT are the width and height of the |
17596 |
|
stretch. ASCENT is the percentage/100 of HEIGHT to use for the |
17597 |
|
ascent of the glyph (0 <= ASCENT <= 1). */ |
17598 |
|
|
17599 |
|
static void |
17600 |
|
append_stretch_glyph (it, object, width, height, ascent) |
17601 |
|
struct it *it; |
17602 |
|
Lisp_Object object; |
17603 |
|
int width, height; |
17604 |
|
double ascent; |
17605 |
|
{ |
17606 |
|
struct glyph *glyph; |
17607 |
|
enum glyph_row_area area = it->area; |
17608 |
|
|
17609 |
|
xassert (ascent >= 0 && ascent <= 1); |
17610 |
|
|
17611 |
|
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; |
17612 |
|
if (glyph < it->glyph_row->glyphs[area + 1]) |
17613 |
|
{ |
17614 |
|
glyph->charpos = CHARPOS (it->position); |
17615 |
|
glyph->object = object; |
17616 |
|
glyph->pixel_width = width; |
17617 |
|
glyph->voffset = it->voffset; |
17618 |
|
glyph->type = STRETCH_GLYPH; |
17619 |
|
glyph->multibyte_p = it->multibyte_p; |
17620 |
|
glyph->left_box_line_p = it->start_of_box_run_p; |
17621 |
|
glyph->right_box_line_p = it->end_of_box_run_p; |
17622 |
|
glyph->overlaps_vertically_p = 0; |
17623 |
|
glyph->padding_p = 0; |
17624 |
|
glyph->glyph_not_available_p = 0; |
17625 |
|
glyph->face_id = it->face_id; |
17626 |
|
glyph->u.stretch.ascent = height * ascent; |
17627 |
|
glyph->u.stretch.height = height; |
17628 |
|
glyph->font_type = FONT_TYPE_UNKNOWN; |
17629 |
|
++it->glyph_row->used[area]; |
17630 |
|
} |
17631 |
|
} |
17632 |
|
|
17633 |
|
|
17634 |
|
/* Produce a stretch glyph for iterator IT. IT->object is the value |
17635 |
|
of the glyph property displayed. The value must be a list |
17636 |
|
`(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs |
17637 |
|
being recognized: |
17638 |
|
|
17639 |
|
1. `:width WIDTH' specifies that the space should be WIDTH * |
17640 |
|
canonical char width wide. WIDTH may be an integer or floating |
17641 |
|
point number. |
17642 |
|
|
17643 |
|
2. `:relative-width FACTOR' specifies that the width of the stretch |
17644 |
|
should be computed from the width of the first character having the |
17645 |
|
`glyph' property, and should be FACTOR times that width. |
17646 |
|
|
17647 |
|
3. `:align-to HPOS' specifies that the space should be wide enough |
17648 |
|
to reach HPOS, a value in canonical character units. |
17649 |
|
|
17650 |
|
Exactly one of the above pairs must be present. |
17651 |
|
|
17652 |
|
4. `:height HEIGHT' specifies that the height of the stretch produced |
17653 |
|
should be HEIGHT, measured in canonical character units. |
17654 |
|
|
17655 |
|
5. `:relative-height FACTOR' specifies that the height of the |
17656 |
|
stretch should be FACTOR times the height of the characters having |
17657 |
|
the glyph property. |
17658 |
|
|
17659 |
|
Either none or exactly one of 4 or 5 must be present. |
17660 |
|
|
17661 |
|
6. `:ascent ASCENT' specifies that ASCENT percent of the height |
17662 |
|
of the stretch should be used for the ascent of the stretch. |
17663 |
|
ASCENT must be in the range 0 <= ASCENT <= 100. */ |
17664 |
|
|
17665 |
|
#define NUMVAL(X) \ |
17666 |
|
((INTEGERP (X) || FLOATP (X)) \ |
17667 |
|
? XFLOATINT (X) \ |
17668 |
|
: - 1) |
17669 |
|
|
17670 |
|
|
17671 |
|
static void |
17672 |
|
produce_stretch_glyph (it) |
17673 |
|
struct it *it; |
17674 |
|
{ |
17675 |
|
/* (space :width WIDTH :height HEIGHT. */ |
17676 |
|
Lisp_Object prop, plist; |
17677 |
|
int width = 0, height = 0; |
17678 |
|
double ascent = 0; |
17679 |
|
struct face *face = FACE_FROM_ID (it->f, it->face_id); |
17680 |
|
XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f); |
17681 |
|
|
17682 |
|
PREPARE_FACE_FOR_DISPLAY (it->f, face); |
17683 |
|
|
17684 |
|
/* List should start with `space'. */ |
17685 |
|
xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace)); |
17686 |
|
plist = XCDR (it->object); |
17687 |
|
|
17688 |
|
/* Compute the width of the stretch. */ |
17689 |
|
if (prop = Fplist_get (plist, QCwidth), |
17690 |
|
NUMVAL (prop) > 0) |
17691 |
|
/* Absolute width `:width WIDTH' specified and valid. */ |
17692 |
|
width = NUMVAL (prop) * CANON_X_UNIT (it->f); |
17693 |
|
else if (prop = Fplist_get (plist, QCrelative_width), |
17694 |
|
NUMVAL (prop) > 0) |
17695 |
|
{ |
17696 |
|
/* Relative width `:relative-width FACTOR' specified and valid. |
17697 |
|
Compute the width of the characters having the `glyph' |
17698 |
|
property. */ |
17699 |
|
struct it it2; |
17700 |
|
unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it)); |
17701 |
|
|
17702 |
|
it2 = *it; |
17703 |
|
if (it->multibyte_p) |
17704 |
|
{ |
17705 |
|
int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT) |
17706 |
|
- IT_BYTEPOS (*it)); |
17707 |
|
it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len); |
17708 |
|
} |
17709 |
|
else |
17710 |
|
it2.c = *p, it2.len = 1; |
17711 |
|
|
17712 |
|
it2.glyph_row = NULL; |
17713 |
|
it2.what = IT_CHARACTER; |
17714 |
|
x_produce_glyphs (&it2); |
17715 |
|
width = NUMVAL (prop) * it2.pixel_width; |
17716 |
|
} |
17717 |
|
else if (prop = Fplist_get (plist, QCalign_to), |
17718 |
|
NUMVAL (prop) > 0) |
17719 |
|
width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x; |
17720 |
|
else |
17721 |
|
/* Nothing specified -> width defaults to canonical char width. */ |
17722 |
|
width = CANON_X_UNIT (it->f); |
17723 |
|
|
17724 |
|
/* Compute height. */ |
17725 |
|
if (prop = Fplist_get (plist, QCheight), |
17726 |
|
NUMVAL (prop) > 0) |
17727 |
|
height = NUMVAL (prop) * CANON_Y_UNIT (it->f); |
17728 |
|
else if (prop = Fplist_get (plist, QCrelative_height), |
17729 |
|
NUMVAL (prop) > 0) |
17730 |
|
height = FONT_HEIGHT (font) * NUMVAL (prop); |
17731 |
|
else |
17732 |
|
height = FONT_HEIGHT (font); |
17733 |
|
|
17734 |
|
/* Compute percentage of height used for ascent. If |
17735 |
|
`:ascent ASCENT' is present and valid, use that. Otherwise, |
17736 |
|
derive the ascent from the font in use. */ |
17737 |
|
if (prop = Fplist_get (plist, QCascent), |
17738 |
|
NUMVAL (prop) > 0 && NUMVAL (prop) <= 100) |
17739 |
|
ascent = NUMVAL (prop) / 100.0; |
17740 |
|
else |
17741 |
|
ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font); |
17742 |
|
|
17743 |
|
if (width <= 0) |
17744 |
|
width = 1; |
17745 |
|
if (height <= 0) |
17746 |
|
height = 1; |
17747 |
|
|
17748 |
|
if (it->glyph_row) |
17749 |
|
{ |
17750 |
|
Lisp_Object object = it->stack[it->sp - 1].string; |
17751 |
|
if (!STRINGP (object)) |
17752 |
|
object = it->w->buffer; |
17753 |
|
append_stretch_glyph (it, object, width, height, ascent); |
17754 |
|
} |
17755 |
|
|
17756 |
|
it->pixel_width = width; |
17757 |
|
it->ascent = it->phys_ascent = height * ascent; |
17758 |
|
it->descent = it->phys_descent = height - it->ascent; |
17759 |
|
it->nglyphs = 1; |
17760 |
|
|
17761 |
|
if (face->box != FACE_NO_BOX) |
17762 |
|
{ |
17763 |
|
if (face->box_line_width > 0) |
17764 |
|
{ |
17765 |
|
it->ascent += face->box_line_width; |
17766 |
|
it->descent += face->box_line_width; |
17767 |
|
} |
17768 |
|
|
17769 |
|
if (it->start_of_box_run_p) |
17770 |
|
it->pixel_width += abs (face->box_line_width); |
17771 |
|
if (it->end_of_box_run_p) |
17772 |
|
it->pixel_width += abs (face->box_line_width); |
17773 |
|
} |
17774 |
|
|
17775 |
|
take_vertical_position_into_account (it); |
17776 |
|
} |
17777 |
|
|
17778 |
|
/* RIF: |
17779 |
|
Produce glyphs/get display metrics for the display element IT is |
17780 |
|
loaded with. See the description of struct display_iterator in |
17781 |
|
dispextern.h for an overview of struct display_iterator. */ |
17782 |
|
|
17783 |
|
void |
17784 |
|
x_produce_glyphs (it) |
17785 |
|
struct it *it; |
17786 |
|
{ |
17787 |
|
it->glyph_not_available_p = 0; |
17788 |
|
|
17789 |
|
if (it->what == IT_CHARACTER) |
17790 |
|
{ |
17791 |
|
XChar2b char2b; |
17792 |
|
XFontStruct *font; |
17793 |
|
struct face *face = FACE_FROM_ID (it->f, it->face_id); |
17794 |
|
XCharStruct *pcm; |
17795 |
|
int font_not_found_p; |
17796 |
|
struct font_info *font_info; |
17797 |
|
int boff; /* baseline offset */ |
17798 |
|
/* We may change it->multibyte_p upon unibyte<->multibyte |
17799 |
|
conversion. So, save the current value now and restore it |
17800 |
|
later. |
17801 |
|
|
17802 |
|
Note: It seems that we don't have to record multibyte_p in |
17803 |
|
struct glyph because the character code itself tells if or |
17804 |
|
not the character is multibyte. Thus, in the future, we must |
17805 |
|
consider eliminating the field `multibyte_p' in the struct |
17806 |
|
glyph. */ |
17807 |
|
int saved_multibyte_p = it->multibyte_p; |
17808 |
|
|
17809 |
|
/* Maybe translate single-byte characters to multibyte, or the |
17810 |
|
other way. */ |
17811 |
|
it->char_to_display = it->c; |
17812 |
|
if (!ASCII_BYTE_P (it->c)) |
17813 |
|
{ |
17814 |
|
if (unibyte_display_via_language_environment |
17815 |
|
&& SINGLE_BYTE_CHAR_P (it->c) |
17816 |
|
&& (it->c >= 0240 |
17817 |
|
|| !NILP (Vnonascii_translation_table))) |
17818 |
|
{ |
17819 |
|
it->char_to_display = unibyte_char_to_multibyte (it->c); |
17820 |
|
it->multibyte_p = 1; |
17821 |
|
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display); |
17822 |
|
face = FACE_FROM_ID (it->f, it->face_id); |
17823 |
|
} |
17824 |
|
else if (!SINGLE_BYTE_CHAR_P (it->c) |
17825 |
|
&& !it->multibyte_p) |
17826 |
|
{ |
17827 |
|
it->multibyte_p = 1; |
17828 |
|
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display); |
17829 |
|
face = FACE_FROM_ID (it->f, it->face_id); |
17830 |
|
} |
17831 |
|
} |
17832 |
|
|
17833 |
|
/* Get font to use. Encode IT->char_to_display. */ |
17834 |
|
get_char_face_and_encoding (it->f, it->char_to_display, it->face_id, |
17835 |
|
&char2b, it->multibyte_p, 0); |
17836 |
|
font = face->font; |
17837 |
|
|
17838 |
|
/* When no suitable font found, use the default font. */ |
17839 |
|
font_not_found_p = font == NULL; |
17840 |
|
if (font_not_found_p) |
17841 |
|
{ |
17842 |
|
font = FRAME_FONT (it->f); |
17843 |
|
boff = FRAME_BASELINE_OFFSET (it->f); |
17844 |
|
font_info = NULL; |
17845 |
|
} |
17846 |
|
else |
17847 |
|
{ |
17848 |
|
font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id); |
17849 |
|
boff = font_info->baseline_offset; |
17850 |
|
if (font_info->vertical_centering) |
17851 |
|
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; |
17852 |
|
} |
17853 |
|
|
17854 |
|
if (it->char_to_display >= ' ' |
17855 |
|
&& (!it->multibyte_p || it->char_to_display < 128)) |
17856 |
|
{ |
17857 |
|
/* Either unibyte or ASCII. */ |
17858 |
|
int stretched_p; |
17859 |
|
|
17860 |
|
it->nglyphs = 1; |
17861 |
|
|
17862 |
|
pcm = rif->per_char_metric (font, &char2b, |
17863 |
|
FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display)); |
17864 |
|
it->ascent = FONT_BASE (font) + boff; |
17865 |
|
it->descent = FONT_DESCENT (font) - boff; |
17866 |
|
|
17867 |
|
if (pcm) |
17868 |
|
{ |
17869 |
|
it->phys_ascent = pcm->ascent + boff; |
17870 |
|
it->phys_descent = pcm->descent - boff; |
17871 |
|
it->pixel_width = pcm->width; |
17872 |
|
} |
17873 |
|
else |
17874 |
|
{ |
17875 |
|
it->glyph_not_available_p = 1; |
17876 |
|
it->phys_ascent = FONT_BASE (font) + boff; |
17877 |
|
it->phys_descent = FONT_DESCENT (font) - boff; |
17878 |
|
it->pixel_width = FONT_WIDTH (font); |
17879 |
|
} |
17880 |
|
|
17881 |
|
/* If this is a space inside a region of text with |
17882 |
|
`space-width' property, change its width. */ |
17883 |
|
stretched_p = it->char_to_display == ' ' && !NILP (it->space_width); |
17884 |
|
if (stretched_p) |
17885 |
|
it->pixel_width *= XFLOATINT (it->space_width); |
17886 |
|
|
17887 |
|
/* If face has a box, add the box thickness to the character |
17888 |
|
height. If character has a box line to the left and/or |
17889 |
|
right, add the box line width to the character's width. */ |
17890 |
|
if (face->box != FACE_NO_BOX) |
17891 |
|
{ |
17892 |
|
int thick = face->box_line_width; |
17893 |
|
|
17894 |
|
if (thick > 0) |
17895 |
|
{ |
17896 |
|
it->ascent += thick; |
17897 |
|
it->descent += thick; |
17898 |
|
} |
17899 |
|
else |
17900 |
|
thick = -thick; |
17901 |
|
|
17902 |
|
if (it->start_of_box_run_p) |
17903 |
|
it->pixel_width += thick; |
17904 |
|
if (it->end_of_box_run_p) |
17905 |
|
it->pixel_width += thick; |
17906 |
|
} |
17907 |
|
|
17908 |
|
/* If face has an overline, add the height of the overline |
17909 |
|
(1 pixel) and a 1 pixel margin to the character height. */ |
17910 |
|
if (face->overline_p) |
17911 |
|
it->ascent += 2; |
17912 |
|
|
17913 |
|
take_vertical_position_into_account (it); |
17914 |
|
|
17915 |
|
/* If we have to actually produce glyphs, do it. */ |
17916 |
|
if (it->glyph_row) |
17917 |
|
{ |
17918 |
|
if (stretched_p) |
17919 |
|
{ |
17920 |
|
/* Translate a space with a `space-width' property |
17921 |
|
into a stretch glyph. */ |
17922 |
|
double ascent = (double) FONT_BASE (font) |
17923 |
|
/ FONT_HEIGHT (font); |
17924 |
|
append_stretch_glyph (it, it->object, it->pixel_width, |
17925 |
|
it->ascent + it->descent, ascent); |
17926 |
|
} |
17927 |
|
else |
17928 |
|
append_glyph (it); |
17929 |
|
|
17930 |
|
/* If characters with lbearing or rbearing are displayed |
17931 |
|
in this line, record that fact in a flag of the |
17932 |
|
glyph row. This is used to optimize X output code. */ |
17933 |
|
if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width)) |
17934 |
|
it->glyph_row->contains_overlapping_glyphs_p = 1; |
17935 |
|
} |
17936 |
|
} |
17937 |
|
else if (it->char_to_display == '\n') |
17938 |
|
{ |
17939 |
|
/* A newline has no width but we need the height of the line. */ |
17940 |
|
it->pixel_width = 0; |
17941 |
|
it->nglyphs = 0; |
17942 |
|
it->ascent = it->phys_ascent = FONT_BASE (font) + boff; |
17943 |
|
it->descent = it->phys_descent = FONT_DESCENT (font) - boff; |
17944 |
|
|
17945 |
|
if (face->box != FACE_NO_BOX |
17946 |
|
&& face->box_line_width > 0) |
17947 |
|
{ |
17948 |
|
it->ascent += face->box_line_width; |
17949 |
|
it->descent += face->box_line_width; |
17950 |
|
} |
17951 |
|
} |
17952 |
|
else if (it->char_to_display == '\t') |
17953 |
|
{ |
17954 |
|
int tab_width = it->tab_width * CANON_X_UNIT (it->f); |
17955 |
|
int x = it->current_x + it->continuation_lines_width; |
17956 |
|
int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width; |
17957 |
|
|
17958 |
|
/* If the distance from the current position to the next tab |
17959 |
|
stop is less than a canonical character width, use the |
17960 |
|
tab stop after that. */ |
17961 |
|
if (next_tab_x - x < CANON_X_UNIT (it->f)) |
17962 |
|
next_tab_x += tab_width; |
17963 |
|
|
17964 |
|
it->pixel_width = next_tab_x - x; |
17965 |
|
it->nglyphs = 1; |
17966 |
|
it->ascent = it->phys_ascent = FONT_BASE (font) + boff; |
17967 |
|
it->descent = it->phys_descent = FONT_DESCENT (font) - boff; |
17968 |
|
|
17969 |
|
if (it->glyph_row) |
17970 |
|
{ |
17971 |
|
double ascent = (double) it->ascent / (it->ascent + it->descent); |
17972 |
|
append_stretch_glyph (it, it->object, it->pixel_width, |
17973 |
|
it->ascent + it->descent, ascent); |
17974 |
|
} |
17975 |
|
} |
17976 |
|
else |
17977 |
|
{ |
17978 |
|
/* A multi-byte character. Assume that the display width of the |
17979 |
|
character is the width of the character multiplied by the |
17980 |
|
width of the font. */ |
17981 |
|
|
17982 |
|
/* If we found a font, this font should give us the right |
17983 |
|
metrics. If we didn't find a font, use the frame's |
17984 |
|
default font and calculate the width of the character |
17985 |
|
from the charset width; this is what old redisplay code |
17986 |
|
did. */ |
17987 |
|
|
17988 |
|
pcm = rif->per_char_metric (font, &char2b, |
17989 |
|
FONT_TYPE_FOR_MULTIBYTE (font, it->c)); |
17990 |
|
|
17991 |
|
if (font_not_found_p || !pcm) |
17992 |
|
{ |
17993 |
|
int charset = CHAR_CHARSET (it->char_to_display); |
17994 |
|
|
17995 |
|
it->glyph_not_available_p = 1; |
17996 |
|
it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f)) |
17997 |
|
* CHARSET_WIDTH (charset)); |
17998 |
|
it->phys_ascent = FONT_BASE (font) + boff; |
17999 |
|
it->phys_descent = FONT_DESCENT (font) - boff; |
18000 |
|
} |
18001 |
|
else |
18002 |
|
{ |
18003 |
|
it->pixel_width = pcm->width; |
18004 |
|
it->phys_ascent = pcm->ascent + boff; |
18005 |
|
it->phys_descent = pcm->descent - boff; |
18006 |
|
if (it->glyph_row |
18007 |
|
&& (pcm->lbearing < 0 |
18008 |
|
|| pcm->rbearing > pcm->width)) |
18009 |
|
it->glyph_row->contains_overlapping_glyphs_p = 1; |
18010 |
|
} |
18011 |
|
it->nglyphs = 1; |
18012 |
|
it->ascent = FONT_BASE (font) + boff; |
18013 |
|
it->descent = FONT_DESCENT (font) - boff; |
18014 |
|
if (face->box != FACE_NO_BOX) |
18015 |
|
{ |
18016 |
|
int thick = face->box_line_width; |
18017 |
|
|
18018 |
|
if (thick > 0) |
18019 |
|
{ |
18020 |
|
it->ascent += thick; |
18021 |
|
it->descent += thick; |
18022 |
|
} |
18023 |
|
else |
18024 |
|
thick = - thick; |
18025 |
|
|
18026 |
|
if (it->start_of_box_run_p) |
18027 |
|
it->pixel_width += thick; |
18028 |
|
if (it->end_of_box_run_p) |
18029 |
|
it->pixel_width += thick; |
18030 |
|
} |
18031 |
|
|
18032 |
|
/* If face has an overline, add the height of the overline |
18033 |
|
(1 pixel) and a 1 pixel margin to the character height. */ |
18034 |
|
if (face->overline_p) |
18035 |
|
it->ascent += 2; |
18036 |
|
|
18037 |
|
take_vertical_position_into_account (it); |
18038 |
|
|
18039 |
|
if (it->glyph_row) |
18040 |
|
append_glyph (it); |
18041 |
|
} |
18042 |
|
it->multibyte_p = saved_multibyte_p; |
18043 |
|
} |
18044 |
|
else if (it->what == IT_COMPOSITION) |
18045 |
|
{ |
18046 |
|
/* Note: A composition is represented as one glyph in the |
18047 |
|
glyph matrix. There are no padding glyphs. */ |
18048 |
|
XChar2b char2b; |
18049 |
|
XFontStruct *font; |
18050 |
|
struct face *face = FACE_FROM_ID (it->f, it->face_id); |
18051 |
|
XCharStruct *pcm; |
18052 |
|
int font_not_found_p; |
18053 |
|
struct font_info *font_info; |
18054 |
|
int boff; /* baseline offset */ |
18055 |
|
struct composition *cmp = composition_table[it->cmp_id]; |
18056 |
|
|
18057 |
|
/* Maybe translate single-byte characters to multibyte. */ |
18058 |
|
it->char_to_display = it->c; |
18059 |
|
if (unibyte_display_via_language_environment |
18060 |
|
&& SINGLE_BYTE_CHAR_P (it->c) |
18061 |
|
&& (it->c >= 0240 |
18062 |
|
|| (it->c >= 0200 |
18063 |
|
&& !NILP (Vnonascii_translation_table)))) |
18064 |
|
{ |
18065 |
|
it->char_to_display = unibyte_char_to_multibyte (it->c); |
18066 |
|
} |
18067 |
|
|
18068 |
|
/* Get face and font to use. Encode IT->char_to_display. */ |
18069 |
|
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display); |
18070 |
|
face = FACE_FROM_ID (it->f, it->face_id); |
18071 |
|
get_char_face_and_encoding (it->f, it->char_to_display, it->face_id, |
18072 |
|
&char2b, it->multibyte_p, 0); |
18073 |
|
font = face->font; |
18074 |
|
|
18075 |
|
/* When no suitable font found, use the default font. */ |
18076 |
|
font_not_found_p = font == NULL; |
18077 |
|
if (font_not_found_p) |
18078 |
|
{ |
18079 |
|
font = FRAME_FONT (it->f); |
18080 |
|
boff = FRAME_BASELINE_OFFSET (it->f); |
18081 |
|
font_info = NULL; |
18082 |
|
} |
18083 |
|
else |
18084 |
|
{ |
18085 |
|
font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id); |
18086 |
|
boff = font_info->baseline_offset; |
18087 |
|
if (font_info->vertical_centering) |
18088 |
|
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; |
18089 |
|
} |
18090 |
|
|
18091 |
|
/* There are no padding glyphs, so there is only one glyph to |
18092 |
|
produce for the composition. Important is that pixel_width, |
18093 |
|
ascent and descent are the values of what is drawn by |
18094 |
|
draw_glyphs (i.e. the values of the overall glyphs composed). */ |
18095 |
|
it->nglyphs = 1; |
18096 |
|
|
18097 |
|
/* If we have not yet calculated pixel size data of glyphs of |
18098 |
|
the composition for the current face font, calculate them |
18099 |
|
now. Theoretically, we have to check all fonts for the |
18100 |
|
glyphs, but that requires much time and memory space. So, |
18101 |
|
here we check only the font of the first glyph. This leads |
18102 |
|
to incorrect display very rarely, and C-l (recenter) can |
18103 |
|
correct the display anyway. */ |
18104 |
|
if (cmp->font != (void *) font) |
18105 |
|
{ |
18106 |
|
/* Ascent and descent of the font of the first character of |
18107 |
|
this composition (adjusted by baseline offset). Ascent |
18108 |
|
and descent of overall glyphs should not be less than |
18109 |
|
them respectively. */ |
18110 |
|
int font_ascent = FONT_BASE (font) + boff; |
18111 |
|
int font_descent = FONT_DESCENT (font) - boff; |
18112 |
|
/* Bounding box of the overall glyphs. */ |
18113 |
|
int leftmost, rightmost, lowest, highest; |
18114 |
|
int i, width, ascent, descent; |
18115 |
|
|
18116 |
|
cmp->font = (void *) font; |
18117 |
|
|
18118 |
|
/* Initialize the bounding box. */ |
18119 |
|
if (font_info |
18120 |
|
&& (pcm = rif->per_char_metric (font, &char2b, |
18121 |
|
FONT_TYPE_FOR_MULTIBYTE (font, it->c)))) |
18122 |
|
{ |
18123 |
|
width = pcm->width; |
18124 |
|
ascent = pcm->ascent; |
18125 |
|
descent = pcm->descent; |
18126 |
|
} |
18127 |
|
else |
18128 |
|
{ |
18129 |
|
width = FONT_WIDTH (font); |
18130 |
|
ascent = FONT_BASE (font); |
18131 |
|
descent = FONT_DESCENT (font); |
18132 |
|
} |
18133 |
|
|
18134 |
|
rightmost = width; |
18135 |
|
lowest = - descent + boff; |
18136 |
|
highest = ascent + boff; |
18137 |
|
leftmost = 0; |
18138 |
|
|
18139 |
|
if (font_info |
18140 |
|
&& font_info->default_ascent |
18141 |
|
&& CHAR_TABLE_P (Vuse_default_ascent) |
18142 |
|
&& !NILP (Faref (Vuse_default_ascent, |
18143 |
|
make_number (it->char_to_display)))) |
18144 |
|
highest = font_info->default_ascent + boff; |
18145 |
|
|
18146 |
|
/* Draw the first glyph at the normal position. It may be |
18147 |
|
shifted to right later if some other glyphs are drawn at |
18148 |
|
the left. */ |
18149 |
|
cmp->offsets[0] = 0; |
18150 |
|
cmp->offsets[1] = boff; |
18151 |
|
|
18152 |
|
/* Set cmp->offsets for the remaining glyphs. */ |
18153 |
|
for (i = 1; i < cmp->glyph_len; i++) |
18154 |
|
{ |
18155 |
|
int left, right, btm, top; |
18156 |
|
int ch = COMPOSITION_GLYPH (cmp, i); |
18157 |
|
int face_id = FACE_FOR_CHAR (it->f, face, ch); |
18158 |
|
|
18159 |
|
face = FACE_FROM_ID (it->f, face_id); |
18160 |
|
get_char_face_and_encoding (it->f, ch, face->id, |
18161 |
|
&char2b, it->multibyte_p, 0); |
18162 |
|
font = face->font; |
18163 |
|
if (font == NULL) |
18164 |
|
{ |
18165 |
|
font = FRAME_FONT (it->f); |
18166 |
|
boff = FRAME_BASELINE_OFFSET (it->f); |
18167 |
|
font_info = NULL; |
18168 |
|
} |
18169 |
|
else |
18170 |
|
{ |
18171 |
|
font_info |
18172 |
|
= FONT_INFO_FROM_ID (it->f, face->font_info_id); |
18173 |
|
boff = font_info->baseline_offset; |
18174 |
|
if (font_info->vertical_centering) |
18175 |
|
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; |
18176 |
|
} |
18177 |
|
|
18178 |
|
if (font_info |
18179 |
|
&& (pcm = rif->per_char_metric (font, &char2b, |
18180 |
|
FONT_TYPE_FOR_MULTIBYTE (font, ch)))) |
18181 |
|
{ |
18182 |
|
width = pcm->width; |
18183 |
|
ascent = pcm->ascent; |
18184 |
|
descent = pcm->descent; |
18185 |
|
} |
18186 |
|
else |
18187 |
|
{ |
18188 |
|
width = FONT_WIDTH (font); |
18189 |
|
ascent = 1; |
18190 |
|
descent = 0; |
18191 |
|
} |
18192 |
|
|
18193 |
|
if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS) |
18194 |
|
{ |
18195 |
|
/* Relative composition with or without |
18196 |
|
alternate chars. */ |
18197 |
|
left = (leftmost + rightmost - width) / 2; |
18198 |
|
btm = - descent + boff; |
18199 |
|
if (font_info && font_info->relative_compose |
18200 |
|
&& (! CHAR_TABLE_P (Vignore_relative_composition) |
18201 |
|
|| NILP (Faref (Vignore_relative_composition, |
18202 |
|
make_number (ch))))) |
18203 |
|
{ |
18204 |
|
|
18205 |
|
if (- descent >= font_info->relative_compose) |
18206 |
|
/* One extra pixel between two glyphs. */ |
18207 |
|
btm = highest + 1; |
18208 |
|
else if (ascent <= 0) |
18209 |
|
/* One extra pixel between two glyphs. */ |
18210 |
|
btm = lowest - 1 - ascent - descent; |
18211 |
|
} |
18212 |
|
} |
18213 |
|
else |
18214 |
|
{ |
18215 |
|
/* A composition rule is specified by an integer |
18216 |
|
value that encodes global and new reference |
18217 |
|
points (GREF and NREF). GREF and NREF are |
18218 |
|
specified by numbers as below: |
18219 |
|
|
18220 |
|
0---1---2 -- ascent |
18221 |
|
| | |
18222 |
|
| | |
18223 |
|
| | |
18224 |
|
9--10--11 -- center |
18225 |
|
| | |
18226 |
|
---3---4---5--- baseline |
18227 |
|
| | |
18228 |
|
6---7---8 -- descent |
18229 |
|
*/ |
18230 |
|
int rule = COMPOSITION_RULE (cmp, i); |
18231 |
|
int gref, nref, grefx, grefy, nrefx, nrefy; |
18232 |
|
|
18233 |
|
COMPOSITION_DECODE_RULE (rule, gref, nref); |
18234 |
|
grefx = gref % 3, nrefx = nref % 3; |
18235 |
|
grefy = gref / 3, nrefy = nref / 3; |
18236 |
|
|
18237 |
|
left = (leftmost |
18238 |
|
+ grefx * (rightmost - leftmost) / 2 |
18239 |
|
- nrefx * width / 2); |
18240 |
|
btm = ((grefy == 0 ? highest |
18241 |
|
: grefy == 1 ? 0 |
18242 |
|
: grefy == 2 ? lowest |
18243 |
|
: (highest + lowest) / 2) |
18244 |
|
- (nrefy == 0 ? ascent + descent |
18245 |
|
: nrefy == 1 ? descent - boff |
18246 |
|
: nrefy == 2 ? 0 |
18247 |
|
: (ascent + descent) / 2)); |
18248 |
|
} |
18249 |
|
|
18250 |
|
cmp->offsets[i * 2] = left; |
18251 |
|
cmp->offsets[i * 2 + 1] = btm + descent; |
18252 |
|
|
18253 |
|
/* Update the bounding box of the overall glyphs. */ |
18254 |
|
right = left + width; |
18255 |
|
top = btm + descent + ascent; |
18256 |
|
if (left < leftmost) |
18257 |
|
leftmost = left; |
18258 |
|
if (right > rightmost) |
18259 |
|
rightmost = right; |
18260 |
|
if (top > highest) |
18261 |
|
highest = top; |
18262 |
|
if (btm < lowest) |
18263 |
|
lowest = btm; |
18264 |
|
} |
18265 |
|
|
18266 |
|
/* If there are glyphs whose x-offsets are negative, |
18267 |
|
shift all glyphs to the right and make all x-offsets |
18268 |
|
non-negative. */ |
18269 |
|
if (leftmost < 0) |
18270 |
|
{ |
18271 |
|
for (i = 0; i < cmp->glyph_len; i++) |
18272 |
|
cmp->offsets[i * 2] -= leftmost; |
18273 |
|
rightmost -= leftmost; |
18274 |
|
} |
18275 |
|
|
18276 |
|
cmp->pixel_width = rightmost; |
18277 |
|
cmp->ascent = highest; |
18278 |
|
cmp->descent = - lowest; |
18279 |
|
if (cmp->ascent < font_ascent) |
18280 |
|
cmp->ascent = font_ascent; |
18281 |
|
if (cmp->descent < font_descent) |
18282 |
|
cmp->descent = font_descent; |
18283 |
|
} |
18284 |
|
|
18285 |
|
it->pixel_width = cmp->pixel_width; |
18286 |
|
it->ascent = it->phys_ascent = cmp->ascent; |
18287 |
|
it->descent = it->phys_descent = cmp->descent; |
18288 |
|
|
18289 |
|
if (face->box != FACE_NO_BOX) |
18290 |
|
{ |
18291 |
|
int thick = face->box_line_width; |
18292 |
|
|
18293 |
|
if (thick > 0) |
18294 |
|
{ |
18295 |
|
it->ascent += thick; |
18296 |
|
it->descent += thick; |
18297 |
|
} |
18298 |
|
else |
18299 |
|
thick = - thick; |
18300 |
|
|
18301 |
|
if (it->start_of_box_run_p) |
18302 |
|
it->pixel_width += thick; |
18303 |
|
if (it->end_of_box_run_p) |
18304 |
|
it->pixel_width += thick; |
18305 |
|
} |
18306 |
|
|
18307 |
|
/* If face has an overline, add the height of the overline |
18308 |
|
(1 pixel) and a 1 pixel margin to the character height. */ |
18309 |
|
if (face->overline_p) |
18310 |
|
it->ascent += 2; |
18311 |
|
|
18312 |
|
take_vertical_position_into_account (it); |
18313 |
|
|
18314 |
|
if (it->glyph_row) |
18315 |
|
append_composite_glyph (it); |
18316 |
|
} |
18317 |
|
else if (it->what == IT_IMAGE) |
18318 |
|
produce_image_glyph (it); |
18319 |
|
else if (it->what == IT_STRETCH) |
18320 |
|
produce_stretch_glyph (it); |
18321 |
|
|
18322 |
|
/* Accumulate dimensions. Note: can't assume that it->descent > 0 |
18323 |
|
because this isn't true for images with `:ascent 100'. */ |
18324 |
|
xassert (it->ascent >= 0 && it->descent >= 0); |
18325 |
|
if (it->area == TEXT_AREA) |
18326 |
|
it->current_x += it->pixel_width; |
18327 |
|
|
18328 |
|
it->descent += it->extra_line_spacing; |
18329 |
|
|
18330 |
|
it->max_ascent = max (it->max_ascent, it->ascent); |
18331 |
|
it->max_descent = max (it->max_descent, it->descent); |
18332 |
|
it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent); |
18333 |
|
it->max_phys_descent = max (it->max_phys_descent, it->phys_descent); |
18334 |
|
} |
18335 |
|
|
18336 |
|
/* EXPORT for RIF: |
18337 |
|
Output LEN glyphs starting at START at the nominal cursor position. |
18338 |
|
Advance the nominal cursor over the text. The global variable |
18339 |
|
updated_window contains the window being updated, updated_row is |
18340 |
|
the glyph row being updated, and updated_area is the area of that |
18341 |
|
row being updated. */ |
18342 |
|
|
18343 |
|
void |
18344 |
|
x_write_glyphs (start, len) |
18345 |
|
struct glyph *start; |
18346 |
|
int len; |
18347 |
|
{ |
18348 |
|
int x, hpos; |
18349 |
|
|
18350 |
|
xassert (updated_window && updated_row); |
18351 |
|
BLOCK_INPUT; |
18352 |
|
|
18353 |
|
/* Write glyphs. */ |
18354 |
|
|
18355 |
|
hpos = start - updated_row->glyphs[updated_area]; |
18356 |
|
x = draw_glyphs (updated_window, output_cursor.x, |
18357 |
|
updated_row, updated_area, |
18358 |
|
hpos, hpos + len, |
18359 |
|
DRAW_NORMAL_TEXT, 0); |
18360 |
|
|
18361 |
|
/* Invalidate old phys cursor if the glyph at its hpos is redrawn. */ |
18362 |
|
if (updated_area == TEXT_AREA |
18363 |
|
&& updated_window->phys_cursor_on_p |
18364 |
|
&& updated_window->phys_cursor.vpos == output_cursor.vpos |
18365 |
|
&& updated_window->phys_cursor.hpos >= hpos |
18366 |
|
&& updated_window->phys_cursor.hpos < hpos + len) |
18367 |
|
updated_window->phys_cursor_on_p = 0; |
18368 |
|
|
18369 |
|
UNBLOCK_INPUT; |
18370 |
|
|
18371 |
|
/* Advance the output cursor. */ |
18372 |
|
output_cursor.hpos += len; |
18373 |
|
output_cursor.x = x; |
18374 |
|
} |
18375 |
|
|
18376 |
|
|
18377 |
|
/* EXPORT for RIF: |
18378 |
|
Insert LEN glyphs from START at the nominal cursor position. */ |
18379 |
|
|
18380 |
|
void |
18381 |
|
x_insert_glyphs (start, len) |
18382 |
|
struct glyph *start; |
18383 |
|
int len; |
18384 |
|
{ |
18385 |
|
struct frame *f; |
18386 |
|
struct window *w; |
18387 |
|
int line_height, shift_by_width, shifted_region_width; |
18388 |
|
struct glyph_row *row; |
18389 |
|
struct glyph *glyph; |
18390 |
|
int frame_x, frame_y, hpos; |
18391 |
|
|
18392 |
|
xassert (updated_window && updated_row); |
18393 |
|
BLOCK_INPUT; |
18394 |
|
w = updated_window; |
18395 |
|
f = XFRAME (WINDOW_FRAME (w)); |
18396 |
|
|
18397 |
|
/* Get the height of the line we are in. */ |
18398 |
|
row = updated_row; |
18399 |
|
line_height = row->height; |
18400 |
|
|
18401 |
|
/* Get the width of the glyphs to insert. */ |
18402 |
|
shift_by_width = 0; |
18403 |
|
for (glyph = start; glyph < start + len; ++glyph) |
18404 |
|
shift_by_width += glyph->pixel_width; |
18405 |
|
|
18406 |
|
/* Get the width of the region to shift right. */ |
18407 |
|
shifted_region_width = (window_box_width (w, updated_area) |
18408 |
|
- output_cursor.x |
18409 |
|
- shift_by_width); |
18410 |
|
|
18411 |
|
/* Shift right. */ |
18412 |
|
frame_x = window_box_left (w, updated_area) + output_cursor.x; |
18413 |
|
frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y); |
18414 |
|
|
18415 |
|
rif->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width, |
18416 |
|
line_height, shift_by_width); |
18417 |
|
|
18418 |
|
/* Write the glyphs. */ |
18419 |
|
hpos = start - row->glyphs[updated_area]; |
18420 |
|
draw_glyphs (w, output_cursor.x, row, updated_area, |
18421 |
|
hpos, hpos + len, |
18422 |
|
DRAW_NORMAL_TEXT, 0); |
18423 |
|
|
18424 |
|
/* Advance the output cursor. */ |
18425 |
|
output_cursor.hpos += len; |
18426 |
|
output_cursor.x += shift_by_width; |
18427 |
|
UNBLOCK_INPUT; |
18428 |
|
} |
18429 |
|
|
18430 |
|
|
18431 |
|
/* EXPORT for RIF: |
18432 |
|
Erase the current text line from the nominal cursor position |
18433 |
|
(inclusive) to pixel column TO_X (exclusive). The idea is that |
18434 |
|
everything from TO_X onward is already erased. |
18435 |
|
|
18436 |
|
TO_X is a pixel position relative to updated_area of |
18437 |
|
updated_window. TO_X == -1 means clear to the end of this area. */ |
18438 |
|
|
18439 |
|
void |
18440 |
|
x_clear_end_of_line (to_x) |
18441 |
|
int to_x; |
18442 |
|
{ |
18443 |
|
struct frame *f; |
18444 |
|
struct window *w = updated_window; |
18445 |
|
int max_x, min_y, max_y; |
18446 |
|
int from_x, from_y, to_y; |
18447 |
|
|
18448 |
|
xassert (updated_window && updated_row); |
18449 |
|
f = XFRAME (w->frame); |
18450 |
|
|
18451 |
|
if (updated_row->full_width_p) |
18452 |
|
{ |
18453 |
|
max_x = XFASTINT (w->width) * CANON_X_UNIT (f); |
18454 |
|
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) |
18455 |
|
&& !w->pseudo_window_p) |
18456 |
|
max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f); |
18457 |
|
} |
18458 |
|
else |
18459 |
|
max_x = window_box_width (w, updated_area); |
18460 |
|
max_y = window_text_bottom_y (w); |
18461 |
|
|
18462 |
|
/* TO_X == 0 means don't do anything. TO_X < 0 means clear to end |
18463 |
|
of window. For TO_X > 0, truncate to end of drawing area. */ |
18464 |
|
if (to_x == 0) |
18465 |
|
return; |
18466 |
|
else if (to_x < 0) |
18467 |
|
to_x = max_x; |
18468 |
|
else |
18469 |
|
to_x = min (to_x, max_x); |
18470 |
|
|
18471 |
|
to_y = min (max_y, output_cursor.y + updated_row->height); |
18472 |
|
|
18473 |
|
/* Notice if the cursor will be cleared by this operation. */ |
18474 |
|
if (!updated_row->full_width_p) |
18475 |
|
notice_overwritten_cursor (w, updated_area, |
18476 |
|
output_cursor.x, -1, |
18477 |
|
updated_row->y, |
18478 |
|
MATRIX_ROW_BOTTOM_Y (updated_row)); |
18479 |
|
|
18480 |
|
from_x = output_cursor.x; |
18481 |
|
|
18482 |
|
/* Translate to frame coordinates. */ |
18483 |
|
if (updated_row->full_width_p) |
18484 |
|
{ |
18485 |
|
from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x); |
18486 |
|
to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x); |
18487 |
|
} |
18488 |
|
else |
18489 |
|
{ |
18490 |
|
from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x); |
18491 |
|
to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x); |
18492 |
|
} |
18493 |
|
|
18494 |
|
min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); |
18495 |
|
from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y)); |
18496 |
|
to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y); |
18497 |
|
|
18498 |
|
/* Prevent inadvertently clearing to end of the X window. */ |
18499 |
|
if (to_x > from_x && to_y > from_y) |
18500 |
|
{ |
18501 |
|
BLOCK_INPUT; |
18502 |
|
rif->clear_frame_area (f, from_x, from_y, |
18503 |
|
to_x - from_x, to_y - from_y); |
18504 |
|
UNBLOCK_INPUT; |
18505 |
|
} |
18506 |
|
} |
18507 |
|
|
18508 |
|
#endif /* HAVE_WINDOW_SYSTEM */ |
18509 |
|
|
18510 |
|
|
18511 |
|
|
18512 |
|
/*********************************************************************** |
18513 |
|
Cursor types |
18514 |
|
***********************************************************************/ |
18515 |
|
|
18516 |
|
/* Value is the internal representation of the specified cursor type |
18517 |
|
ARG. If type is BAR_CURSOR, return in *WIDTH the specified width |
18518 |
|
of the bar cursor. */ |
18519 |
|
|
18520 |
|
enum text_cursor_kinds |
18521 |
|
get_specified_cursor_type (arg, width) |
18522 |
|
Lisp_Object arg; |
18523 |
|
int *width; |
18524 |
|
{ |
18525 |
|
enum text_cursor_kinds type; |
18526 |
|
|
18527 |
|
if (NILP (arg)) |
18528 |
|
return NO_CURSOR; |
18529 |
|
|
18530 |
|
if (EQ (arg, Qbox)) |
18531 |
|
return FILLED_BOX_CURSOR; |
18532 |
|
|
18533 |
|
if (EQ (arg, Qhollow)) |
18534 |
|
return HOLLOW_BOX_CURSOR; |
18535 |
|
|
18536 |
|
if (EQ (arg, Qbar)) |
18537 |
|
{ |
18538 |
|
*width = 2; |
18539 |
|
return BAR_CURSOR; |
18540 |
|
} |
18541 |
|
|
18542 |
|
if (CONSP (arg) |
18543 |
|
&& EQ (XCAR (arg), Qbar) |
18544 |
|
&& INTEGERP (XCDR (arg)) |
18545 |
|
&& XINT (XCDR (arg)) >= 0) |
18546 |
|
{ |
18547 |
|
*width = XINT (XCDR (arg)); |
18548 |
|
return BAR_CURSOR; |
18549 |
|
} |
18550 |
|
|
18551 |
|
if (EQ (arg, Qhbar)) |
18552 |
|
{ |
18553 |
|
*width = 2; |
18554 |
|
return HBAR_CURSOR; |
18555 |
|
} |
18556 |
|
|
18557 |
|
if (CONSP (arg) |
18558 |
|
&& EQ (XCAR (arg), Qhbar) |
18559 |
|
&& INTEGERP (XCDR (arg)) |
18560 |
|
&& XINT (XCDR (arg)) >= 0) |
18561 |
|
{ |
18562 |
|
*width = XINT (XCDR (arg)); |
18563 |
|
return HBAR_CURSOR; |
18564 |
|
} |
18565 |
|
|
18566 |
|
/* Treat anything unknown as "hollow box cursor". |
18567 |
|
It was bad to signal an error; people have trouble fixing |
18568 |
|
.Xdefaults with Emacs, when it has something bad in it. */ |
18569 |
|
type = HOLLOW_BOX_CURSOR; |
18570 |
|
|
18571 |
|
return type; |
18572 |
|
} |
18573 |
|
|
18574 |
|
/* Set the default cursor types for specified frame. */ |
18575 |
|
void |
18576 |
|
set_frame_cursor_types (f, arg) |
18577 |
|
struct frame *f; |
18578 |
|
Lisp_Object arg; |
18579 |
|
{ |
18580 |
|
int width; |
18581 |
|
Lisp_Object tem; |
18582 |
|
|
18583 |
|
FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width); |
18584 |
|
FRAME_CURSOR_WIDTH (f) = width; |
18585 |
|
|
18586 |
|
/* By default, set up the blink-off state depending on the on-state. */ |
18587 |
|
|
18588 |
|
tem = Fassoc (arg, Vblink_cursor_alist); |
18589 |
|
if (!NILP (tem)) |
18590 |
|
{ |
18591 |
|
FRAME_BLINK_OFF_CURSOR (f) |
18592 |
|
= get_specified_cursor_type (XCDR (tem), &width); |
18593 |
|
FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width; |
18594 |
|
} |
18595 |
|
else |
18596 |
|
FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR; |
18597 |
|
} |
18598 |
|
|
18599 |
|
|
18600 |
|
/* Return the cursor we want to be displayed in window W. Return |
18601 |
|
width of bar/hbar cursor through WIDTH arg. Return with |
18602 |
|
ACTIVE_CURSOR arg set to 1 if cursor in window W is `active' |
18603 |
|
(i.e. if the `system caret' should track this cursor). |
18604 |
|
|
18605 |
|
In a mini-buffer window, we want the cursor only to appear if we |
18606 |
|
are reading input from this window. For the selected window, we |
18607 |
|
want the cursor type given by the frame parameter or buffer local |
18608 |
|
setting of cursor-type. If explicitly marked off, draw no cursor. |
18609 |
|
In all other cases, we want a hollow box cursor. */ |
18610 |
|
|
18611 |
|
enum text_cursor_kinds |
18612 |
|
get_window_cursor_type (w, width, active_cursor) |
18613 |
|
struct window *w; |
18614 |
|
int *width; |
18615 |
|
int *active_cursor; |
18616 |
|
{ |
18617 |
|
struct frame *f = XFRAME (w->frame); |
18618 |
|
struct buffer *b = XBUFFER (w->buffer); |
18619 |
|
int cursor_type = DEFAULT_CURSOR; |
18620 |
|
Lisp_Object alt_cursor; |
18621 |
|
int non_selected = 0; |
18622 |
|
|
18623 |
|
*active_cursor = 1; |
18624 |
|
|
18625 |
|
/* Echo area */ |
18626 |
|
if (cursor_in_echo_area |
18627 |
|
&& FRAME_HAS_MINIBUF_P (f) |
18628 |
|
&& EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)) |
18629 |
|
{ |
18630 |
|
if (w == XWINDOW (echo_area_window)) |
18631 |
|
{ |
18632 |
|
*width = FRAME_CURSOR_WIDTH (f); |
18633 |
|
return FRAME_DESIRED_CURSOR (f); |
18634 |
|
} |
18635 |
|
|
18636 |
|
*active_cursor = 0; |
18637 |
|
non_selected = 1; |
18638 |
|
} |
18639 |
|
|
18640 |
|
/* Nonselected window or nonselected frame. */ |
18641 |
|
else if (w != XWINDOW (f->selected_window) |
18642 |
|
#ifdef HAVE_WINDOW_SYSTEM |
18643 |
|
|| f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame |
18644 |
|
#endif |
18645 |
|
) |
18646 |
|
{ |
18647 |
|
*active_cursor = 0; |
18648 |
|
|
18649 |
|
if (MINI_WINDOW_P (w) && minibuf_level == 0) |
18650 |
|
return NO_CURSOR; |
18651 |
|
|
18652 |
|
non_selected = 1; |
18653 |
|
} |
18654 |
|
|
18655 |
|
/* Never display a cursor in a window in which cursor-type is nil. */ |
18656 |
|
if (NILP (b->cursor_type)) |
18657 |
|
return NO_CURSOR; |
18658 |
|
|
18659 |
|
/* Use cursor-in-non-selected-windows for non-selected window or frame. */ |
18660 |
|
if (non_selected) |
18661 |
|
{ |
18662 |
|
alt_cursor = Fbuffer_local_value (Qcursor_in_non_selected_windows, w->buffer); |
18663 |
|
return get_specified_cursor_type (alt_cursor, width); |
18664 |
|
} |
18665 |
|
|
18666 |
|
/* Get the normal cursor type for this window. */ |
18667 |
|
if (EQ (b->cursor_type, Qt)) |
18668 |
|
{ |
18669 |
|
cursor_type = FRAME_DESIRED_CURSOR (f); |
18670 |
|
*width = FRAME_CURSOR_WIDTH (f); |
18671 |
|
} |
18672 |
|
else |
18673 |
|
cursor_type = get_specified_cursor_type (b->cursor_type, width); |
18674 |
|
|
18675 |
|
/* Use normal cursor if not blinked off. */ |
18676 |
|
if (!w->cursor_off_p) |
18677 |
|
return cursor_type; |
18678 |
|
|
18679 |
|
/* Cursor is blinked off, so determine how to "toggle" it. */ |
18680 |
|
|
18681 |
|
/* First look for an entry matching the buffer's cursor-type in blink-cursor-alist. */ |
18682 |
|
if ((alt_cursor = Fassoc (b->cursor_type, Vblink_cursor_alist), !NILP (alt_cursor))) |
18683 |
|
return get_specified_cursor_type (XCDR (alt_cursor), width); |
18684 |
|
|
18685 |
|
/* Then see if frame has specified a specific blink off cursor type. */ |
18686 |
|
if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR) |
18687 |
|
{ |
18688 |
|
*width = FRAME_BLINK_OFF_CURSOR_WIDTH (f); |
18689 |
|
return FRAME_BLINK_OFF_CURSOR (f); |
18690 |
|
} |
18691 |
|
|
18692 |
|
/* Finally perform built-in cursor blinking: |
18693 |
|
filled box <-> hollow box |
18694 |
|
wide [h]bar <-> narrow [h]bar |
18695 |
|
narrow [h]bar <-> no cursor |
18696 |
|
other type <-> no cursor */ |
18697 |
|
|
18698 |
|
if (cursor_type == FILLED_BOX_CURSOR) |
18699 |
|
return HOLLOW_BOX_CURSOR; |
18700 |
|
|
18701 |
|
if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1) |
18702 |
|
{ |
18703 |
|
*width = 1; |
18704 |
|
return cursor_type; |
18705 |
|
} |
18706 |
|
|
18707 |
|
return NO_CURSOR; |
18708 |
|
} |
18709 |
|
|
18710 |
|
|
18711 |
|
#ifdef HAVE_WINDOW_SYSTEM |
18712 |
|
|
18713 |
|
/* Notice when the text cursor of window W has been completely |
18714 |
|
overwritten by a drawing operation that outputs glyphs in AREA |
18715 |
|
starting at X0 and ending at X1 in the line starting at Y0 and |
18716 |
|
ending at Y1. X coordinates are area-relative. X1 < 0 means all |
18717 |
|
the rest of the line after X0 has been written. Y coordinates |
18718 |
|
are window-relative. */ |
18719 |
|
|
18720 |
|
static void |
18721 |
|
notice_overwritten_cursor (w, area, x0, x1, y0, y1) |
18722 |
|
struct window *w; |
18723 |
|
enum glyph_row_area area; |
18724 |
|
int x0, y0, x1, y1; |
18725 |
|
{ |
18726 |
|
if (area == TEXT_AREA && w->phys_cursor_on_p) |
18727 |
|
{ |
18728 |
|
int cx0 = w->phys_cursor.x; |
18729 |
|
int cx1 = cx0 + w->phys_cursor_width; |
18730 |
|
int cy0 = w->phys_cursor.y; |
18731 |
|
int cy1 = cy0 + w->phys_cursor_height; |
18732 |
|
|
18733 |
|
if (x0 <= cx0 && (x1 < 0 || x1 >= cx1)) |
18734 |
|
{ |
18735 |
|
/* The cursor image will be completely removed from the |
18736 |
|
screen if the output area intersects the cursor area in |
18737 |
|
y-direction. When we draw in [y0 y1[, and some part of |
18738 |
|
the cursor is at y < y0, that part must have been drawn |
18739 |
|
before. When scrolling, the cursor is erased before |
18740 |
|
actually scrolling, so we don't come here. When not |
18741 |
|
scrolling, the rows above the old cursor row must have |
18742 |
|
changed, and in this case these rows must have written |
18743 |
|
over the cursor image. |
18744 |
|
|
18745 |
|
Likewise if part of the cursor is below y1, with the |
18746 |
|
exception of the cursor being in the first blank row at |
18747 |
|
the buffer and window end because update_text_area |
18748 |
|
doesn't draw that row. (Except when it does, but |
18749 |
|
that's handled in update_text_area.) */ |
18750 |
|
|
18751 |
|
if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1)) |
18752 |
|
&& w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p) |
18753 |
|
w->phys_cursor_on_p = 0; |
18754 |
|
} |
18755 |
|
} |
18756 |
|
} |
18757 |
|
|
18758 |
|
#endif /* HAVE_WINDOW_SYSTEM */ |
18759 |
|
|
18760 |
|
|
18761 |
|
/************************************************************************ |
18762 |
|
Mouse Face |
18763 |
|
************************************************************************/ |
18764 |
|
|
18765 |
|
#ifdef HAVE_WINDOW_SYSTEM |
18766 |
|
|
18767 |
|
/* EXPORT for RIF: |
18768 |
|
Fix the display of area AREA of overlapping row ROW in window W. */ |
18769 |
|
|
18770 |
|
void |
18771 |
|
x_fix_overlapping_area (w, row, area) |
18772 |
|
struct window *w; |
18773 |
|
struct glyph_row *row; |
18774 |
|
enum glyph_row_area area; |
18775 |
|
{ |
18776 |
|
int i, x; |
18777 |
|
|
18778 |
|
BLOCK_INPUT; |
18779 |
|
|
18780 |
|
if (area == LEFT_MARGIN_AREA) |
18781 |
|
x = 0; |
18782 |
|
else if (area == TEXT_AREA) |
18783 |
|
x = row->x + window_box_width (w, LEFT_MARGIN_AREA); |
18784 |
|
else |
18785 |
|
x = (window_box_width (w, LEFT_MARGIN_AREA) |
18786 |
|
+ window_box_width (w, TEXT_AREA)); |
18787 |
|
|
18788 |
|
for (i = 0; i < row->used[area];) |
18789 |
|
{ |
18790 |
|
if (row->glyphs[area][i].overlaps_vertically_p) |
18791 |
|
{ |
18792 |
|
int start = i, start_x = x; |
18793 |
|
|
18794 |
|
do |
18795 |
|
{ |
18796 |
|
x += row->glyphs[area][i].pixel_width; |
18797 |
|
++i; |
18798 |
|
} |
18799 |
|
while (i < row->used[area] |
18800 |
|
&& row->glyphs[area][i].overlaps_vertically_p); |
18801 |
|
|
18802 |
|
draw_glyphs (w, start_x, row, area, |
18803 |
|
start, i, |
18804 |
|
DRAW_NORMAL_TEXT, 1); |
18805 |
|
} |
18806 |
|
else |
18807 |
|
{ |
18808 |
|
x += row->glyphs[area][i].pixel_width; |
18809 |
|
++i; |
18810 |
|
} |
18811 |
|
} |
18812 |
|
|
18813 |
|
UNBLOCK_INPUT; |
18814 |
|
} |
18815 |
|
|
18816 |
|
|
18817 |
|
/* EXPORT: |
18818 |
|
Draw the cursor glyph of window W in glyph row ROW. See the |
18819 |
|
comment of draw_glyphs for the meaning of HL. */ |
18820 |
|
|
18821 |
|
void |
18822 |
|
draw_phys_cursor_glyph (w, row, hl) |
18823 |
|
struct window *w; |
18824 |
|
struct glyph_row *row; |
18825 |
|
enum draw_glyphs_face hl; |
18826 |
|
{ |
18827 |
|
/* If cursor hpos is out of bounds, don't draw garbage. This can |
18828 |
|
happen in mini-buffer windows when switching between echo area |
18829 |
|
glyphs and mini-buffer. */ |
18830 |
|
if (w->phys_cursor.hpos < row->used[TEXT_AREA]) |
18831 |
|
{ |
18832 |
|
int on_p = w->phys_cursor_on_p; |
18833 |
|
int x1; |
18834 |
|
x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, |
18835 |
|
w->phys_cursor.hpos, w->phys_cursor.hpos + 1, |
18836 |
|
hl, 0); |
18837 |
|
w->phys_cursor_on_p = on_p; |
18838 |
|
|
18839 |
|
if (hl == DRAW_CURSOR) |
18840 |
|
w->phys_cursor_width = x1 - w->phys_cursor.x; |
18841 |
|
/* When we erase the cursor, and ROW is overlapped by other |
18842 |
|
rows, make sure that these overlapping parts of other rows |
18843 |
|
are redrawn. */ |
18844 |
|
else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p) |
18845 |
|
{ |
18846 |
|
if (row > w->current_matrix->rows |
18847 |
|
&& MATRIX_ROW_OVERLAPS_SUCC_P (row - 1)) |
18848 |
|
x_fix_overlapping_area (w, row - 1, TEXT_AREA); |
18849 |
|
|
18850 |
|
if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w) |
18851 |
|
&& MATRIX_ROW_OVERLAPS_PRED_P (row + 1)) |
18852 |
|
x_fix_overlapping_area (w, row + 1, TEXT_AREA); |
18853 |
|
} |
18854 |
|
} |
18855 |
|
} |
18856 |
|
|
18857 |
|
|
18858 |
|
/* EXPORT: |
18859 |
|
Erase the image of a cursor of window W from the screen. */ |
18860 |
|
|
18861 |
|
void |
18862 |
|
erase_phys_cursor (w) |
18863 |
|
struct window *w; |
18864 |
|
{ |
18865 |
|
struct frame *f = XFRAME (w->frame); |
18866 |
|
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
18867 |
|
int hpos = w->phys_cursor.hpos; |
18868 |
|
int vpos = w->phys_cursor.vpos; |
18869 |
|
int mouse_face_here_p = 0; |
18870 |
|
struct glyph_matrix *active_glyphs = w->current_matrix; |
18871 |
|
struct glyph_row *cursor_row; |
18872 |
|
struct glyph *cursor_glyph; |
18873 |
|
enum draw_glyphs_face hl; |
18874 |
|
|
18875 |
|
/* No cursor displayed or row invalidated => nothing to do on the |
18876 |
|
screen. */ |
18877 |
|
if (w->phys_cursor_type == NO_CURSOR) |
18878 |
|
goto mark_cursor_off; |
18879 |
|
|
18880 |
|
/* VPOS >= active_glyphs->nrows means that window has been resized. |
18881 |
|
Don't bother to erase the cursor. */ |
18882 |
|
if (vpos >= active_glyphs->nrows) |
18883 |
|
goto mark_cursor_off; |
18884 |
|
|
18885 |
|
/* If row containing cursor is marked invalid, there is nothing we |
18886 |
|
can do. */ |
18887 |
|
cursor_row = MATRIX_ROW (active_glyphs, vpos); |
18888 |
|
if (!cursor_row->enabled_p) |
18889 |
|
goto mark_cursor_off; |
18890 |
|
|
18891 |
|
/* If row is completely invisible, don't attempt to delete a cursor which |
18892 |
|
isn't there. This can happen if cursor is at top of a window, and |
18893 |
|
we switch to a buffer with a header line in that window. */ |
18894 |
|
if (cursor_row->visible_height <= 0) |
18895 |
|
goto mark_cursor_off; |
18896 |
|
|
18897 |
|
/* This can happen when the new row is shorter than the old one. |
18898 |
|
In this case, either draw_glyphs or clear_end_of_line |
18899 |
|
should have cleared the cursor. Note that we wouldn't be |
18900 |
|
able to erase the cursor in this case because we don't have a |
18901 |
|
cursor glyph at hand. */ |
18902 |
|
if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA]) |
18903 |
|
goto mark_cursor_off; |
18904 |
|
|
18905 |
|
/* If the cursor is in the mouse face area, redisplay that when |
18906 |
|
we clear the cursor. */ |
18907 |
|
if (! NILP (dpyinfo->mouse_face_window) |
18908 |
|
&& w == XWINDOW (dpyinfo->mouse_face_window) |
18909 |
|
&& (vpos > dpyinfo->mouse_face_beg_row |
18910 |
|
|| (vpos == dpyinfo->mouse_face_beg_row |
18911 |
|
&& hpos >= dpyinfo->mouse_face_beg_col)) |
18912 |
|
&& (vpos < dpyinfo->mouse_face_end_row |
18913 |
|
|| (vpos == dpyinfo->mouse_face_end_row |
18914 |
|
&& hpos < dpyinfo->mouse_face_end_col)) |
18915 |
|
/* Don't redraw the cursor's spot in mouse face if it is at the |
18916 |
|
end of a line (on a newline). The cursor appears there, but |
18917 |
|
mouse highlighting does not. */ |
18918 |
|
&& cursor_row->used[TEXT_AREA] > hpos) |
18919 |
|
mouse_face_here_p = 1; |
18920 |
|
|
18921 |
|
/* Maybe clear the display under the cursor. */ |
18922 |
|
if (w->phys_cursor_type == HOLLOW_BOX_CURSOR) |
18923 |
|
{ |
18924 |
|
int x, y; |
18925 |
|
int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); |
18926 |
|
|
18927 |
|
cursor_glyph = get_phys_cursor_glyph (w); |
18928 |
|
if (cursor_glyph == NULL) |
18929 |
|
goto mark_cursor_off; |
18930 |
|
|
18931 |
|
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); |
18932 |
|
y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y)); |
18933 |
|
|
18934 |
|
rif->clear_frame_area (f, x, y, |
18935 |
|
cursor_glyph->pixel_width, cursor_row->visible_height); |
18936 |
|
} |
18937 |
|
|
18938 |
|
/* Erase the cursor by redrawing the character underneath it. */ |
18939 |
|
if (mouse_face_here_p) |
18940 |
|
hl = DRAW_MOUSE_FACE; |
18941 |
|
else |
18942 |
|
hl = DRAW_NORMAL_TEXT; |
18943 |
|
draw_phys_cursor_glyph (w, cursor_row, hl); |
18944 |
|
|
18945 |
|
mark_cursor_off: |
18946 |
|
w->phys_cursor_on_p = 0; |
18947 |
|
w->phys_cursor_type = NO_CURSOR; |
18948 |
|
} |
18949 |
|
|
18950 |
|
|
18951 |
|
/* EXPORT: |
18952 |
|
Display or clear cursor of window W. If ON is zero, clear the |
18953 |
|
cursor. If it is non-zero, display the cursor. If ON is nonzero, |
18954 |
|
where to put the cursor is specified by HPOS, VPOS, X and Y. */ |
18955 |
|
|
18956 |
|
void |
18957 |
|
display_and_set_cursor (w, on, hpos, vpos, x, y) |
18958 |
|
struct window *w; |
18959 |
|
int on, hpos, vpos, x, y; |
18960 |
|
{ |
18961 |
|
struct frame *f = XFRAME (w->frame); |
18962 |
|
int new_cursor_type; |
18963 |
|
int new_cursor_width; |
18964 |
|
int active_cursor; |
18965 |
|
struct glyph_matrix *current_glyphs; |
18966 |
|
struct glyph_row *glyph_row; |
18967 |
|
struct glyph *glyph; |
18968 |
|
|
18969 |
|
/* This is pointless on invisible frames, and dangerous on garbaged |
18970 |
|
windows and frames; in the latter case, the frame or window may |
18971 |
|
be in the midst of changing its size, and x and y may be off the |
18972 |
|
window. */ |
18973 |
|
if (! FRAME_VISIBLE_P (f) |
18974 |
|
|| FRAME_GARBAGED_P (f) |
18975 |
|
|| vpos >= w->current_matrix->nrows |
18976 |
|
|| hpos >= w->current_matrix->matrix_w) |
18977 |
|
return; |
18978 |
|
|
18979 |
|
/* If cursor is off and we want it off, return quickly. */ |
18980 |
|
if (!on && !w->phys_cursor_on_p) |
18981 |
|
return; |
18982 |
|
|
18983 |
|
current_glyphs = w->current_matrix; |
18984 |
|
glyph_row = MATRIX_ROW (current_glyphs, vpos); |
18985 |
|
glyph = glyph_row->glyphs[TEXT_AREA] + hpos; |
18986 |
|
|
18987 |
|
/* If cursor row is not enabled, we don't really know where to |
18988 |
|
display the cursor. */ |
18989 |
|
if (!glyph_row->enabled_p) |
18990 |
|
{ |
18991 |
|
w->phys_cursor_on_p = 0; |
18992 |
|
return; |
18993 |
|
} |
18994 |
|
|
18995 |
|
xassert (interrupt_input_blocked); |
18996 |
|
|
18997 |
|
/* Set new_cursor_type to the cursor we want to be displayed. */ |
18998 |
|
new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor); |
18999 |
|
|
19000 |
|
/* If cursor is currently being shown and we don't want it to be or |
19001 |
|
it is in the wrong place, or the cursor type is not what we want, |
19002 |
|
erase it. */ |
19003 |
|
if (w->phys_cursor_on_p |
19004 |
|
&& (!on |
19005 |
|
|| w->phys_cursor.x != x |
19006 |
|
|| w->phys_cursor.y != y |
19007 |
|
|| new_cursor_type != w->phys_cursor_type |
19008 |
|
|| ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR) |
19009 |
|
&& new_cursor_width != w->phys_cursor_width))) |
19010 |
|
erase_phys_cursor (w); |
19011 |
|
|
19012 |
|
/* Don't check phys_cursor_on_p here because that flag is only set |
19013 |
|
to zero in some cases where we know that the cursor has been |
19014 |
|
completely erased, to avoid the extra work of erasing the cursor |
19015 |
|
twice. In other words, phys_cursor_on_p can be 1 and the cursor |
19016 |
|
still not be visible, or it has only been partly erased. */ |
19017 |
|
if (on) |
19018 |
|
{ |
19019 |
|
w->phys_cursor_ascent = glyph_row->ascent; |
19020 |
|
w->phys_cursor_height = glyph_row->height; |
19021 |
|
|
19022 |
|
/* Set phys_cursor_.* before x_draw_.* is called because some |
19023 |
|
of them may need the information. */ |
19024 |
|
w->phys_cursor.x = x; |
19025 |
|
w->phys_cursor.y = glyph_row->y; |
19026 |
|
w->phys_cursor.hpos = hpos; |
19027 |
|
w->phys_cursor.vpos = vpos; |
19028 |
|
} |
19029 |
|
|
19030 |
|
rif->draw_window_cursor (w, glyph_row, x, y, |
19031 |
|
new_cursor_type, new_cursor_width, |
19032 |
|
on, active_cursor); |
19033 |
|
} |
19034 |
|
|
19035 |
|
|
19036 |
|
/* Switch the display of W's cursor on or off, according to the value |
19037 |
|
of ON. */ |
19038 |
|
|
19039 |
|
static void |
19040 |
|
update_window_cursor (w, on) |
19041 |
|
struct window *w; |
19042 |
|
int on; |
19043 |
|
{ |
19044 |
|
/* Don't update cursor in windows whose frame is in the process |
19045 |
|
of being deleted. */ |
19046 |
|
if (w->current_matrix) |
19047 |
|
{ |
19048 |
|
BLOCK_INPUT; |
19049 |
|
display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos, |
19050 |
|
w->phys_cursor.x, w->phys_cursor.y); |
19051 |
|
UNBLOCK_INPUT; |
19052 |
|
} |
19053 |
|
} |
19054 |
|
|
19055 |
|
|
19056 |
|
/* Call update_window_cursor with parameter ON_P on all leaf windows |
19057 |
|
in the window tree rooted at W. */ |
19058 |
|
|
19059 |
|
static void |
19060 |
|
update_cursor_in_window_tree (w, on_p) |
19061 |
|
struct window *w; |
19062 |
|
int on_p; |
19063 |
|
{ |
19064 |
|
while (w) |
19065 |
|
{ |
19066 |
|
if (!NILP (w->hchild)) |
19067 |
|
update_cursor_in_window_tree (XWINDOW (w->hchild), on_p); |
19068 |
|
else if (!NILP (w->vchild)) |
19069 |
|
update_cursor_in_window_tree (XWINDOW (w->vchild), on_p); |
19070 |
|
else |
19071 |
|
update_window_cursor (w, on_p); |
19072 |
|
|
19073 |
|
w = NILP (w->next) ? 0 : XWINDOW (w->next); |
19074 |
|
} |
19075 |
|
} |
19076 |
|
|
19077 |
|
|
19078 |
|
/* EXPORT: |
19079 |
|
Display the cursor on window W, or clear it, according to ON_P. |
19080 |
|
Don't change the cursor's position. */ |
19081 |
|
|
19082 |
|
void |
19083 |
|
x_update_cursor (f, on_p) |
19084 |
|
struct frame *f; |
19085 |
|
int on_p; |
19086 |
|
{ |
19087 |
|
update_cursor_in_window_tree (XWINDOW (f->root_window), on_p); |
19088 |
|
} |
19089 |
|
|
19090 |
|
|
19091 |
|
/* EXPORT: |
19092 |
|
Clear the cursor of window W to background color, and mark the |
19093 |
|
cursor as not shown. This is used when the text where the cursor |
19094 |
|
is is about to be rewritten. */ |
19095 |
|
|
19096 |
|
void |
19097 |
|
x_clear_cursor (w) |
19098 |
|
struct window *w; |
19099 |
|
{ |
19100 |
|
if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p) |
19101 |
|
update_window_cursor (w, 0); |
19102 |
|
} |
19103 |
|
|
19104 |
|
|
19105 |
|
/* EXPORT: |
19106 |
|
Display the active region described by mouse_face_* according to DRAW. */ |
19107 |
|
|
19108 |
|
void |
19109 |
|
show_mouse_face (dpyinfo, draw) |
19110 |
|
Display_Info *dpyinfo; |
19111 |
|
enum draw_glyphs_face draw; |
19112 |
|
{ |
19113 |
|
struct window *w = XWINDOW (dpyinfo->mouse_face_window); |
19114 |
|
struct frame *f = XFRAME (WINDOW_FRAME (w)); |
19115 |
|
|
19116 |
|
if (/* If window is in the process of being destroyed, don't bother |
19117 |
|
to do anything. */ |
19118 |
|
w->current_matrix != NULL |
19119 |
|
/* Don't update mouse highlight if hidden */ |
19120 |
|
&& (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden) |
19121 |
|
/* Recognize when we are called to operate on rows that don't exist |
19122 |
|
anymore. This can happen when a window is split. */ |
19123 |
|
&& dpyinfo->mouse_face_end_row < w->current_matrix->nrows) |
19124 |
|
{ |
19125 |
|
int phys_cursor_on_p = w->phys_cursor_on_p; |
19126 |
|
struct glyph_row *row, *first, *last; |
19127 |
|
|
19128 |
|
first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row); |
19129 |
|
last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row); |
19130 |
|
|
19131 |
|
for (row = first; row <= last && row->enabled_p; ++row) |
19132 |
|
{ |
19133 |
|
int start_hpos, end_hpos, start_x; |
19134 |
|
|
19135 |
|
/* For all but the first row, the highlight starts at column 0. */ |
19136 |
|
if (row == first) |
19137 |
|
{ |
19138 |
|
start_hpos = dpyinfo->mouse_face_beg_col; |
19139 |
|
start_x = dpyinfo->mouse_face_beg_x; |
19140 |
|
} |
19141 |
|
else |
19142 |
|
{ |
19143 |
|
start_hpos = 0; |
19144 |
|
start_x = 0; |
19145 |
|
} |
19146 |
|
|
19147 |
|
if (row == last) |
19148 |
|
end_hpos = dpyinfo->mouse_face_end_col; |
19149 |
|
else |
19150 |
|
end_hpos = row->used[TEXT_AREA]; |
19151 |
|
|
19152 |
|
if (end_hpos > start_hpos) |
19153 |
|
{ |
19154 |
|
draw_glyphs (w, start_x, row, TEXT_AREA, |
19155 |
|
start_hpos, end_hpos, |
19156 |
|
draw, 0); |
19157 |
|
|
19158 |
|
row->mouse_face_p |
19159 |
|
= draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED; |
19160 |
|
} |
19161 |
|
} |
19162 |
|
|
19163 |
|
/* When we've written over the cursor, arrange for it to |
19164 |
|
be displayed again. */ |
19165 |
|
if (phys_cursor_on_p && !w->phys_cursor_on_p) |
19166 |
|
{ |
19167 |
|
BLOCK_INPUT; |
19168 |
|
display_and_set_cursor (w, 1, |
19169 |
|
w->phys_cursor.hpos, w->phys_cursor.vpos, |
19170 |
|
w->phys_cursor.x, w->phys_cursor.y); |
19171 |
|
UNBLOCK_INPUT; |
19172 |
|
} |
19173 |
|
} |
19174 |
|
|
19175 |
|
/* Change the mouse cursor. */ |
19176 |
|
if (draw == DRAW_NORMAL_TEXT) |
19177 |
|
rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor); |
19178 |
|
else if (draw == DRAW_MOUSE_FACE) |
19179 |
|
rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor); |
19180 |
|
else |
19181 |
|
rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor); |
19182 |
|
} |
19183 |
|
|
19184 |
|
/* EXPORT: |
19185 |
|
Clear out the mouse-highlighted active region. |
19186 |
|
Redraw it un-highlighted first. Value is non-zero if mouse |
19187 |
|
face was actually drawn unhighlighted. */ |
19188 |
|
|
19189 |
|
int |
19190 |
|
clear_mouse_face (dpyinfo) |
19191 |
|
Display_Info *dpyinfo; |
19192 |
|
{ |
19193 |
|
int cleared = 0; |
19194 |
|
|
19195 |
|
if (!NILP (dpyinfo->mouse_face_window)) |
19196 |
|
{ |
19197 |
|
show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT); |
19198 |
|
cleared = 1; |
19199 |
|
} |
19200 |
|
|
19201 |
|
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; |
19202 |
|
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; |
19203 |
|
dpyinfo->mouse_face_window = Qnil; |
19204 |
|
dpyinfo->mouse_face_overlay = Qnil; |
19205 |
|
return cleared; |
19206 |
|
} |
19207 |
|
|
19208 |
|
|
19209 |
|
/* EXPORT: |
19210 |
|
Non-zero if physical cursor of window W is within mouse face. */ |
19211 |
|
|
19212 |
|
int |
19213 |
|
cursor_in_mouse_face_p (w) |
19214 |
|
struct window *w; |
19215 |
|
{ |
19216 |
|
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); |
19217 |
|
int in_mouse_face = 0; |
19218 |
|
|
19219 |
|
if (WINDOWP (dpyinfo->mouse_face_window) |
19220 |
|
&& XWINDOW (dpyinfo->mouse_face_window) == w) |
19221 |
|
{ |
19222 |
|
int hpos = w->phys_cursor.hpos; |
19223 |
|
int vpos = w->phys_cursor.vpos; |
19224 |
|
|
19225 |
|
if (vpos >= dpyinfo->mouse_face_beg_row |
19226 |
|
&& vpos <= dpyinfo->mouse_face_end_row |
19227 |
|
&& (vpos > dpyinfo->mouse_face_beg_row |
19228 |
|
|| hpos >= dpyinfo->mouse_face_beg_col) |
19229 |
|
&& (vpos < dpyinfo->mouse_face_end_row |
19230 |
|
|| hpos < dpyinfo->mouse_face_end_col |
19231 |
|
|| dpyinfo->mouse_face_past_end)) |
19232 |
|
in_mouse_face = 1; |
19233 |
|
} |
19234 |
|
|
19235 |
|
return in_mouse_face; |
19236 |
|
} |
19237 |
|
|
19238 |
|
|
19239 |
|
|
19240 |
|
|
19241 |
|
/* Find the glyph matrix position of buffer position CHARPOS in window |
19242 |
|
*W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's |
19243 |
|
current glyphs must be up to date. If CHARPOS is above window |
19244 |
|
start return (0, 0, 0, 0). If CHARPOS is after end of W, return end |
19245 |
|
of last line in W. In the row containing CHARPOS, stop before glyphs |
19246 |
|
having STOP as object. */ |
19247 |
|
|
19248 |
|
#if 0 /* This is a version of fast_find_position that's more correct |
19249 |
|
in the presence of hscrolling, for example. I didn't install |
19250 |
|
it right away because the problem fixed is minor, it failed |
19251 |
|
in 20.x as well, and I think it's too risky to install |
19252 |
|
so near the release of 21.1. 2001-09-25 gerd. */ |
19253 |
|
|
19254 |
|
static int |
19255 |
|
fast_find_position (w, charpos, hpos, vpos, x, y, stop) |
19256 |
|
struct window *w; |
19257 |
|
int charpos; |
19258 |
|
int *hpos, *vpos, *x, *y; |
19259 |
|
Lisp_Object stop; |
19260 |
|
{ |
19261 |
|
struct glyph_row *row, *first; |
19262 |
|
struct glyph *glyph, *end; |
19263 |
|
int i, past_end = 0; |
19264 |
|
|
19265 |
|
first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
19266 |
|
row = row_containing_pos (w, charpos, first, NULL, 0); |
19267 |
|
if (row == NULL) |
19268 |
|
{ |
19269 |
|
if (charpos < MATRIX_ROW_START_CHARPOS (first)) |
19270 |
|
{ |
19271 |
|
*x = *y = *hpos = *vpos = 0; |
19272 |
|
return 0; |
19273 |
|
} |
19274 |
|
else |
19275 |
|
{ |
19276 |
|
row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); |
19277 |
|
past_end = 1; |
19278 |
|
} |
19279 |
|
} |
19280 |
|
|
19281 |
|
*x = row->x; |
19282 |
|
*y = row->y; |
19283 |
|
*vpos = MATRIX_ROW_VPOS (row, w->current_matrix); |
19284 |
|
|
19285 |
|
glyph = row->glyphs[TEXT_AREA]; |
19286 |
|
end = glyph + row->used[TEXT_AREA]; |
19287 |
|
|
19288 |
|
/* Skip over glyphs not having an object at the start of the row. |
19289 |
|
These are special glyphs like truncation marks on terminal |
19290 |
|
frames. */ |
19291 |
|
if (row->displays_text_p) |
19292 |
|
while (glyph < end |
19293 |
|
&& INTEGERP (glyph->object) |
19294 |
|
&& !EQ (stop, glyph->object) |
19295 |
|
&& glyph->charpos < 0) |
19296 |
|
{ |
19297 |
|
*x += glyph->pixel_width; |
19298 |
|
++glyph; |
19299 |
|
} |
19300 |
|
|
19301 |
|
while (glyph < end |
19302 |
|
&& !INTEGERP (glyph->object) |
19303 |
|
&& !EQ (stop, glyph->object) |
19304 |
|
&& (!BUFFERP (glyph->object) |
19305 |
|
|| glyph->charpos < charpos)) |
19306 |
|
{ |
19307 |
|
*x += glyph->pixel_width; |
19308 |
|
++glyph; |
19309 |
|
} |
19310 |
|
|
19311 |
|
*hpos = glyph - row->glyphs[TEXT_AREA]; |
19312 |
|
return past_end; |
19313 |
|
} |
19314 |
|
|
19315 |
|
#else /* not 0 */ |
19316 |
|
|
19317 |
|
static int |
19318 |
|
fast_find_position (w, pos, hpos, vpos, x, y, stop) |
19319 |
|
struct window *w; |
19320 |
|
int pos; |
19321 |
|
int *hpos, *vpos, *x, *y; |
19322 |
|
Lisp_Object stop; |
19323 |
|
{ |
19324 |
|
int i; |
19325 |
|
int lastcol; |
19326 |
|
int maybe_next_line_p = 0; |
19327 |
|
int line_start_position; |
19328 |
|
int yb = window_text_bottom_y (w); |
19329 |
|
struct glyph_row *row, *best_row; |
19330 |
|
int row_vpos, best_row_vpos; |
19331 |
|
int current_x; |
19332 |
|
|
19333 |
|
row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
19334 |
|
row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix); |
19335 |
|
|
19336 |
|
while (row->y < yb) |
19337 |
|
{ |
19338 |
|
if (row->used[TEXT_AREA]) |
19339 |
|
line_start_position = row->glyphs[TEXT_AREA]->charpos; |
19340 |
|
else |
19341 |
|
line_start_position = 0; |
19342 |
|
|
19343 |
|
if (line_start_position > pos) |
19344 |
|
break; |
19345 |
|
/* If the position sought is the end of the buffer, |
19346 |
|
don't include the blank lines at the bottom of the window. */ |
19347 |
|
else if (line_start_position == pos |
19348 |
|
&& pos == BUF_ZV (XBUFFER (w->buffer))) |
19349 |
|
{ |
19350 |
|
maybe_next_line_p = 1; |
19351 |
|
break; |
19352 |
|
} |
19353 |
|
else if (line_start_position > 0) |
19354 |
|
{ |
19355 |
|
best_row = row; |
19356 |
|
best_row_vpos = row_vpos; |
19357 |
|
} |
19358 |
|
|
19359 |
|
if (row->y + row->height >= yb) |
19360 |
|
break; |
19361 |
|
|
19362 |
|
++row; |
19363 |
|
++row_vpos; |
19364 |
|
} |
19365 |
|
|
19366 |
|
/* Find the right column within BEST_ROW. */ |
19367 |
|
lastcol = 0; |
19368 |
|
current_x = best_row->x; |
19369 |
|
for (i = 0; i < best_row->used[TEXT_AREA]; i++) |
19370 |
|
{ |
19371 |
|
struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i; |
19372 |
|
int charpos = glyph->charpos; |
19373 |
|
|
19374 |
|
if (BUFFERP (glyph->object)) |
19375 |
|
{ |
19376 |
|
if (charpos == pos) |
19377 |
|
{ |
19378 |
|
*hpos = i; |
19379 |
|
*vpos = best_row_vpos; |
19380 |
|
*x = current_x; |
19381 |
|
*y = best_row->y; |
19382 |
|
return 1; |
19383 |
|
} |
19384 |
|
else if (charpos > pos) |
19385 |
|
break; |
19386 |
|
} |
19387 |
|
else if (EQ (glyph->object, stop)) |
19388 |
|
break; |
19389 |
|
|
19390 |
|
if (charpos > 0) |
19391 |
|
lastcol = i; |
19392 |
|
current_x += glyph->pixel_width; |
19393 |
|
} |
19394 |
|
|
19395 |
|
/* If we're looking for the end of the buffer, |
19396 |
|
and we didn't find it in the line we scanned, |
19397 |
|
use the start of the following line. */ |
19398 |
|
if (maybe_next_line_p) |
19399 |
|
{ |
19400 |
|
++best_row; |
19401 |
|
++best_row_vpos; |
19402 |
|
lastcol = 0; |
19403 |
|
current_x = best_row->x; |
19404 |
|
} |
19405 |
|
|
19406 |
|
*vpos = best_row_vpos; |
19407 |
|
*hpos = lastcol + 1; |
19408 |
|
*x = current_x; |
19409 |
|
*y = best_row->y; |
19410 |
|
return 0; |
19411 |
|
} |
19412 |
|
|
19413 |
|
#endif /* not 0 */ |
19414 |
|
|
19415 |
|
|
19416 |
|
/* Find the position of the glyph for position POS in OBJECT in |
19417 |
|
window W's current matrix, and return in *X, *Y the pixel |
19418 |
|
coordinates, and return in *HPOS, *VPOS the column/row of the glyph. |
19419 |
|
|
19420 |
|
RIGHT_P non-zero means return the position of the right edge of the |
19421 |
|
glyph, RIGHT_P zero means return the left edge position. |
19422 |
|
|
19423 |
|
If no glyph for POS exists in the matrix, return the position of |
19424 |
|
the glyph with the next smaller position that is in the matrix, if |
19425 |
|
RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS |
19426 |
|
exists in the matrix, return the position of the glyph with the |
19427 |
|
next larger position in OBJECT. |
19428 |
|
|
19429 |
|
Value is non-zero if a glyph was found. */ |
19430 |
|
|
19431 |
|
static int |
19432 |
|
fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p) |
19433 |
|
struct window *w; |
19434 |
|
int pos; |
19435 |
|
Lisp_Object object; |
19436 |
|
int *hpos, *vpos, *x, *y; |
19437 |
|
int right_p; |
19438 |
|
{ |
19439 |
|
int yb = window_text_bottom_y (w); |
19440 |
|
struct glyph_row *r; |
19441 |
|
struct glyph *best_glyph = NULL; |
19442 |
|
struct glyph_row *best_row = NULL; |
19443 |
|
int best_x = 0; |
19444 |
|
|
19445 |
|
for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
19446 |
|
r->enabled_p && r->y < yb; |
19447 |
|
++r) |
19448 |
|
{ |
19449 |
|
struct glyph *g = r->glyphs[TEXT_AREA]; |
19450 |
|
struct glyph *e = g + r->used[TEXT_AREA]; |
19451 |
|
int gx; |
19452 |
|
|
19453 |
|
for (gx = r->x; g < e; gx += g->pixel_width, ++g) |
19454 |
|
if (EQ (g->object, object)) |
19455 |
|
{ |
19456 |
|
if (g->charpos == pos) |
19457 |
|
{ |
19458 |
|
best_glyph = g; |
19459 |
|
best_x = gx; |
19460 |
|
best_row = r; |
19461 |
|
goto found; |
19462 |
|
} |
19463 |
|
else if (best_glyph == NULL |
19464 |
|
|| ((abs (g->charpos - pos) |
19465 |
|
< abs (best_glyph->charpos - pos)) |
19466 |
|
&& (right_p |
19467 |
|
? g->charpos < pos |
19468 |
|
: g->charpos > pos))) |
19469 |
|
{ |
19470 |
|
best_glyph = g; |
19471 |
|
best_x = gx; |
19472 |
|
best_row = r; |
19473 |
|
} |
19474 |
|
} |
19475 |
|
} |
19476 |
|
|
19477 |
|
found: |
19478 |
|
|
19479 |
|
if (best_glyph) |
19480 |
|
{ |
19481 |
|
*x = best_x; |
19482 |
|
*hpos = best_glyph - best_row->glyphs[TEXT_AREA]; |
19483 |
|
|
19484 |
|
if (right_p) |
19485 |
|
{ |
19486 |
|
*x += best_glyph->pixel_width; |
19487 |
|
++*hpos; |
19488 |
|
} |
19489 |
|
|
19490 |
|
*y = best_row->y; |
19491 |
|
*vpos = best_row - w->current_matrix->rows; |
19492 |
|
} |
19493 |
|
|
19494 |
|
return best_glyph != NULL; |
19495 |
|
} |
19496 |
|
|
19497 |
|
|
19498 |
|
/* Take proper action when mouse has moved to the mode or header line |
19499 |
|
or marginal area AREA of window W, x-position X and y-position Y. |
19500 |
|
X is relative to the start of the text display area of W, so the |
19501 |
|
width of bitmap areas and scroll bars must be subtracted to get a |
19502 |
|
position relative to the start of the mode line. */ |
19503 |
|
|
19504 |
|
static void |
19505 |
|
note_mode_line_or_margin_highlight (w, x, y, area) |
19506 |
|
struct window *w; |
19507 |
|
int x, y; |
19508 |
|
enum window_part area; |
19509 |
|
{ |
19510 |
|
struct frame *f = XFRAME (w->frame); |
19511 |
|
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
19512 |
|
Cursor cursor = dpyinfo->vertical_scroll_bar_cursor; |
19513 |
|
int charpos; |
19514 |
|
Lisp_Object string, help, map, pos; |
19515 |
|
|
19516 |
|
if (area == ON_MODE_LINE || area == ON_HEADER_LINE) |
19517 |
|
string = mode_line_string (w, x, y, area, &charpos); |
19518 |
|
else |
19519 |
|
string = marginal_area_string (w, x, y, area, &charpos); |
19520 |
|
|
19521 |
|
if (STRINGP (string)) |
19522 |
|
{ |
19523 |
|
pos = make_number (charpos); |
19524 |
|
|
19525 |
|
/* If we're on a string with `help-echo' text property, arrange |
19526 |
|
for the help to be displayed. This is done by setting the |
19527 |
|
global variable help_echo_string to the help string. */ |
19528 |
|
help = Fget_text_property (pos, Qhelp_echo, string); |
19529 |
|
if (!NILP (help)) |
19530 |
|
{ |
19531 |
|
help_echo_string = help; |
19532 |
|
XSETWINDOW (help_echo_window, w); |
19533 |
|
help_echo_object = string; |
19534 |
|
help_echo_pos = charpos; |
19535 |
|
} |
19536 |
|
|
19537 |
|
/* Change the mouse pointer according to what is under X/Y. */ |
19538 |
|
map = Fget_text_property (pos, Qlocal_map, string); |
19539 |
|
if (!KEYMAPP (map)) |
19540 |
|
map = Fget_text_property (pos, Qkeymap, string); |
19541 |
|
if (KEYMAPP (map)) |
19542 |
|
cursor = FRAME_X_OUTPUT (f)->nontext_cursor; |
19543 |
|
} |
19544 |
|
|
19545 |
|
rif->define_frame_cursor (f, cursor); |
19546 |
|
} |
19547 |
|
|
19548 |
|
|
19549 |
|
/* EXPORT: |
19550 |
|
Take proper action when the mouse has moved to position X, Y on |
19551 |
|
frame F as regards highlighting characters that have mouse-face |
19552 |
|
properties. Also de-highlighting chars where the mouse was before. |
19553 |
|
X and Y can be negative or out of range. */ |
19554 |
|
|
19555 |
|
void |
19556 |
|
note_mouse_highlight (f, x, y) |
19557 |
|
struct frame *f; |
19558 |
|
int x, y; |
19559 |
|
{ |
19560 |
|
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
19561 |
|
enum window_part part; |
19562 |
|
Lisp_Object window; |
19563 |
|
struct window *w; |
19564 |
|
Cursor cursor = No_Cursor; |
19565 |
|
struct buffer *b; |
19566 |
|
|
19567 |
|
/* When a menu is active, don't highlight because this looks odd. */ |
19568 |
|
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI) |
19569 |
|
if (popup_activated ()) |
19570 |
|
return; |
19571 |
|
#endif |
19572 |
|
|
19573 |
|
if (NILP (Vmouse_highlight) |
19574 |
|
|| !f->glyphs_initialized_p) |
19575 |
|
return; |
19576 |
|
|
19577 |
|
dpyinfo->mouse_face_mouse_x = x; |
19578 |
|
dpyinfo->mouse_face_mouse_y = y; |
19579 |
|
dpyinfo->mouse_face_mouse_frame = f; |
19580 |
|
|
19581 |
|
if (dpyinfo->mouse_face_defer) |
19582 |
|
return; |
19583 |
|
|
19584 |
|
if (gc_in_progress) |
19585 |
|
{ |
19586 |
|
dpyinfo->mouse_face_deferred_gc = 1; |
19587 |
|
return; |
19588 |
|
} |
19589 |
|
|
19590 |
|
/* Which window is that in? */ |
19591 |
|
window = window_from_coordinates (f, x, y, &part, 1); |
19592 |
|
|
19593 |
|
/* If we were displaying active text in another window, clear that. */ |
19594 |
|
if (! EQ (window, dpyinfo->mouse_face_window)) |
19595 |
|
clear_mouse_face (dpyinfo); |
19596 |
|
|
19597 |
|
/* Not on a window -> return. */ |
19598 |
|
if (!WINDOWP (window)) |
19599 |
|
return; |
19600 |
|
|
19601 |
|
/* Reset help_echo_string. It will get recomputed below. */ |
19602 |
|
/* ++KFS: X version didn't do this, but it looks harmless. */ |
19603 |
|
help_echo_string = Qnil; |
19604 |
|
|
19605 |
|
/* Convert to window-relative pixel coordinates. */ |
19606 |
|
w = XWINDOW (window); |
19607 |
|
frame_to_window_pixel_xy (w, &x, &y); |
19608 |
|
|
19609 |
|
/* Handle tool-bar window differently since it doesn't display a |
19610 |
|
buffer. */ |
19611 |
|
if (EQ (window, f->tool_bar_window)) |
19612 |
|
{ |
19613 |
|
note_tool_bar_highlight (f, x, y); |
19614 |
|
return; |
19615 |
|
} |
19616 |
|
|
19617 |
|
/* Mouse is on the mode, header line or margin? */ |
19618 |
|
if (part == ON_MODE_LINE || part == ON_HEADER_LINE |
19619 |
|
|| part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN) |
19620 |
|
{ |
19621 |
|
note_mode_line_or_margin_highlight (w, x, y, part); |
19622 |
|
return; |
19623 |
|
} |
19624 |
|
|
19625 |
|
if (part == ON_VERTICAL_BORDER) |
19626 |
|
cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; |
19627 |
|
else |
19628 |
|
cursor = FRAME_X_OUTPUT (f)->text_cursor; |
19629 |
|
|
19630 |
|
/* Are we in a window whose display is up to date? |
19631 |
|
And verify the buffer's text has not changed. */ |
19632 |
|
b = XBUFFER (w->buffer); |
19633 |
|
if (part == ON_TEXT |
19634 |
|
&& EQ (w->window_end_valid, w->buffer) |
19635 |
|
&& XFASTINT (w->last_modified) == BUF_MODIFF (b) |
19636 |
|
&& XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b)) |
19637 |
|
{ |
19638 |
|
int hpos, vpos, pos, i, area; |
19639 |
|
struct glyph *glyph; |
19640 |
|
Lisp_Object object; |
19641 |
|
Lisp_Object mouse_face = Qnil, overlay = Qnil, position; |
19642 |
|
Lisp_Object *overlay_vec = NULL; |
19643 |
|
int len, noverlays; |
19644 |
|
struct buffer *obuf; |
19645 |
|
int obegv, ozv, same_region; |
19646 |
|
|
19647 |
|
/* Find the glyph under X/Y. */ |
19648 |
|
glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0); |
19649 |
|
|
19650 |
|
/* Clear mouse face if X/Y not over text. */ |
19651 |
|
if (glyph == NULL |
19652 |
|
|| area != TEXT_AREA |
19653 |
|
|| !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p) |
19654 |
|
{ |
19655 |
|
#if defined (HAVE_NTGUI) |
19656 |
|
/* ++KFS: Why is this necessary on W32 ? */ |
19657 |
|
clear_mouse_face (dpyinfo); |
19658 |
|
cursor = FRAME_X_OUTPUT (f)->nontext_cursor; |
19659 |
|
#else |
19660 |
|
if (clear_mouse_face (dpyinfo)) |
19661 |
|
cursor = No_Cursor; |
19662 |
|
#endif |
19663 |
|
goto set_cursor; |
19664 |
|
} |
19665 |
|
|
19666 |
|
pos = glyph->charpos; |
19667 |
|
object = glyph->object; |
19668 |
|
if (!STRINGP (object) && !BUFFERP (object)) |
19669 |
|
goto set_cursor; |
19670 |
|
|
19671 |
|
/* If we get an out-of-range value, return now; avoid an error. */ |
19672 |
|
if (BUFFERP (object) && pos > BUF_Z (b)) |
19673 |
|
goto set_cursor; |
19674 |
|
|
19675 |
|
/* Make the window's buffer temporarily current for |
19676 |
|
overlays_at and compute_char_face. */ |
19677 |
|
obuf = current_buffer; |
19678 |
|
current_buffer = b; |
19679 |
|
obegv = BEGV; |
19680 |
|
ozv = ZV; |
19681 |
|
BEGV = BEG; |
19682 |
|
ZV = Z; |
19683 |
|
|
19684 |
|
/* Is this char mouse-active or does it have help-echo? */ |
19685 |
|
position = make_number (pos); |
19686 |
|
|
19687 |
|
if (BUFFERP (object)) |
19688 |
|
{ |
19689 |
|
/* Put all the overlays we want in a vector in overlay_vec. |
19690 |
|
Store the length in len. If there are more than 10, make |
19691 |
|
enough space for all, and try again. */ |
19692 |
|
len = 10; |
19693 |
|
overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); |
19694 |
|
noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0); |
19695 |
|
if (noverlays > len) |
19696 |
|
{ |
19697 |
|
len = noverlays; |
19698 |
|
overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); |
19699 |
|
noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0); |
19700 |
|
} |
19701 |
|
|
19702 |
|
/* Sort overlays into increasing priority order. */ |
19703 |
|
noverlays = sort_overlays (overlay_vec, noverlays, w); |
19704 |
|
} |
19705 |
|
else |
19706 |
|
noverlays = 0; |
19707 |
|
|
19708 |
|
same_region = (EQ (window, dpyinfo->mouse_face_window) |
19709 |
|
&& vpos >= dpyinfo->mouse_face_beg_row |
19710 |
|
&& vpos <= dpyinfo->mouse_face_end_row |
19711 |
|
&& (vpos > dpyinfo->mouse_face_beg_row |
19712 |
|
|| hpos >= dpyinfo->mouse_face_beg_col) |
19713 |
|
&& (vpos < dpyinfo->mouse_face_end_row |
19714 |
|
|| hpos < dpyinfo->mouse_face_end_col |
19715 |
|
|| dpyinfo->mouse_face_past_end)); |
19716 |
|
|
19717 |
|
if (same_region) |
19718 |
|
cursor = No_Cursor; |
19719 |
|
|
19720 |
|
/* Check mouse-face highlighting. */ |
19721 |
|
if (! same_region |
19722 |
|
/* If there exists an overlay with mouse-face overlapping |
19723 |
|
the one we are currently highlighting, we have to |
19724 |
|
check if we enter the overlapping overlay, and then |
19725 |
|
highlight only that. */ |
19726 |
|
|| (OVERLAYP (dpyinfo->mouse_face_overlay) |
19727 |
|
&& mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay))) |
19728 |
|
{ |
19729 |
|
/* Find the highest priority overlay that has a mouse-face |
19730 |
|
property. */ |
19731 |
|
overlay = Qnil; |
19732 |
|
for (i = noverlays - 1; i >= 0 && NILP (overlay); --i) |
19733 |
|
{ |
19734 |
|
mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); |
19735 |
|
if (!NILP (mouse_face)) |
19736 |
|
overlay = overlay_vec[i]; |
19737 |
|
} |
19738 |
|
|
19739 |
|
/* If we're actually highlighting the same overlay as |
19740 |
|
before, there's no need to do that again. */ |
19741 |
|
if (!NILP (overlay) |
19742 |
|
&& EQ (overlay, dpyinfo->mouse_face_overlay)) |
19743 |
|
goto check_help_echo; |
19744 |
|
|
19745 |
|
dpyinfo->mouse_face_overlay = overlay; |
19746 |
|
|
19747 |
|
/* Clear the display of the old active region, if any. */ |
19748 |
|
if (clear_mouse_face (dpyinfo)) |
19749 |
|
cursor = No_Cursor; |
19750 |
|
|
19751 |
|
/* If no overlay applies, get a text property. */ |
19752 |
|
if (NILP (overlay)) |
19753 |
|
mouse_face = Fget_text_property (position, Qmouse_face, object); |
19754 |
|
|
19755 |
|
/* Handle the overlay case. */ |
19756 |
|
if (!NILP (overlay)) |
19757 |
|
{ |
19758 |
|
/* Find the range of text around this char that |
19759 |
|
should be active. */ |
19760 |
|
Lisp_Object before, after; |
19761 |
|
int ignore; |
19762 |
|
|
19763 |
|
before = Foverlay_start (overlay); |
19764 |
|
after = Foverlay_end (overlay); |
19765 |
|
/* Record this as the current active region. */ |
19766 |
|
fast_find_position (w, XFASTINT (before), |
19767 |
|
&dpyinfo->mouse_face_beg_col, |
19768 |
|
&dpyinfo->mouse_face_beg_row, |
19769 |
|
&dpyinfo->mouse_face_beg_x, |
19770 |
|
&dpyinfo->mouse_face_beg_y, Qnil); |
19771 |
|
|
19772 |
|
dpyinfo->mouse_face_past_end |
19773 |
|
= !fast_find_position (w, XFASTINT (after), |
19774 |
|
&dpyinfo->mouse_face_end_col, |
19775 |
|
&dpyinfo->mouse_face_end_row, |
19776 |
|
&dpyinfo->mouse_face_end_x, |
19777 |
|
&dpyinfo->mouse_face_end_y, Qnil); |
19778 |
|
dpyinfo->mouse_face_window = window; |
19779 |
|
|
19780 |
|
dpyinfo->mouse_face_face_id |
19781 |
|
= face_at_buffer_position (w, pos, 0, 0, |
19782 |
|
&ignore, pos + 1, |
19783 |
|
!dpyinfo->mouse_face_hidden); |
19784 |
|
|
19785 |
|
/* Display it as active. */ |
19786 |
|
show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); |
19787 |
|
cursor = No_Cursor; |
19788 |
|
} |
19789 |
|
/* Handle the text property case. */ |
19790 |
|
else if (!NILP (mouse_face) && BUFFERP (object)) |
19791 |
|
{ |
19792 |
|
/* Find the range of text around this char that |
19793 |
|
should be active. */ |
19794 |
|
Lisp_Object before, after, beginning, end; |
19795 |
|
int ignore; |
19796 |
|
|
19797 |
|
beginning = Fmarker_position (w->start); |
19798 |
|
end = make_number (BUF_Z (XBUFFER (object)) |
19799 |
|
- XFASTINT (w->window_end_pos)); |
19800 |
|
before |
19801 |
|
= Fprevious_single_property_change (make_number (pos + 1), |
19802 |
|
Qmouse_face, |
19803 |
|
object, beginning); |
19804 |
|
after |
19805 |
|
= Fnext_single_property_change (position, Qmouse_face, |
19806 |
|
object, end); |
19807 |
|
|
19808 |
|
/* Record this as the current active region. */ |
19809 |
|
fast_find_position (w, XFASTINT (before), |
19810 |
|
&dpyinfo->mouse_face_beg_col, |
19811 |
|
&dpyinfo->mouse_face_beg_row, |
19812 |
|
&dpyinfo->mouse_face_beg_x, |
19813 |
|
&dpyinfo->mouse_face_beg_y, Qnil); |
19814 |
|
dpyinfo->mouse_face_past_end |
19815 |
|
= !fast_find_position (w, XFASTINT (after), |
19816 |
|
&dpyinfo->mouse_face_end_col, |
19817 |
|
&dpyinfo->mouse_face_end_row, |
19818 |
|
&dpyinfo->mouse_face_end_x, |
19819 |
|
&dpyinfo->mouse_face_end_y, Qnil); |
19820 |
|
dpyinfo->mouse_face_window = window; |
19821 |
|
|
19822 |
|
if (BUFFERP (object)) |
19823 |
|
dpyinfo->mouse_face_face_id |
19824 |
|
= face_at_buffer_position (w, pos, 0, 0, |
19825 |
|
&ignore, pos + 1, |
19826 |
|
!dpyinfo->mouse_face_hidden); |
19827 |
|
|
19828 |
|
/* Display it as active. */ |
19829 |
|
show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); |
19830 |
|
cursor = No_Cursor; |
19831 |
|
} |
19832 |
|
else if (!NILP (mouse_face) && STRINGP (object)) |
19833 |
|
{ |
19834 |
|
Lisp_Object b, e; |
19835 |
|
int ignore; |
19836 |
|
|
19837 |
|
b = Fprevious_single_property_change (make_number (pos + 1), |
19838 |
|
Qmouse_face, |
19839 |
|
object, Qnil); |
19840 |
|
e = Fnext_single_property_change (position, Qmouse_face, |
19841 |
|
object, Qnil); |
19842 |
|
if (NILP (b)) |
19843 |
|
b = make_number (0); |
19844 |
|
if (NILP (e)) |
19845 |
|
e = make_number (SCHARS (object) - 1); |
19846 |
|
fast_find_string_pos (w, XINT (b), object, |
19847 |
|
&dpyinfo->mouse_face_beg_col, |
19848 |
|
&dpyinfo->mouse_face_beg_row, |
19849 |
|
&dpyinfo->mouse_face_beg_x, |
19850 |
|
&dpyinfo->mouse_face_beg_y, 0); |
19851 |
|
fast_find_string_pos (w, XINT (e), object, |
19852 |
|
&dpyinfo->mouse_face_end_col, |
19853 |
|
&dpyinfo->mouse_face_end_row, |
19854 |
|
&dpyinfo->mouse_face_end_x, |
19855 |
|
&dpyinfo->mouse_face_end_y, 1); |
19856 |
|
dpyinfo->mouse_face_past_end = 0; |
19857 |
|
dpyinfo->mouse_face_window = window; |
19858 |
|
dpyinfo->mouse_face_face_id |
19859 |
|
= face_at_string_position (w, object, pos, 0, 0, 0, &ignore, |
19860 |
|
glyph->face_id, 1); |
19861 |
|
show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); |
19862 |
|
cursor = No_Cursor; |
19863 |
|
} |
19864 |
|
else if (STRINGP (object) && NILP (mouse_face)) |
19865 |
|
{ |
19866 |
|
/* A string which doesn't have mouse-face, but |
19867 |
|
the text ``under'' it might have. */ |
19868 |
|
struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos); |
19869 |
|
int start = MATRIX_ROW_START_CHARPOS (r); |
19870 |
|
|
19871 |
|
pos = string_buffer_position (w, object, start); |
19872 |
|
if (pos > 0) |
19873 |
|
mouse_face = get_char_property_and_overlay (make_number (pos), |
19874 |
|
Qmouse_face, |
19875 |
|
w->buffer, |
19876 |
|
&overlay); |
19877 |
|
if (!NILP (mouse_face) && !NILP (overlay)) |
19878 |
|
{ |
19879 |
|
Lisp_Object before = Foverlay_start (overlay); |
19880 |
|
Lisp_Object after = Foverlay_end (overlay); |
19881 |
|
int ignore; |
19882 |
|
|
19883 |
|
/* Note that we might not be able to find position |
19884 |
|
BEFORE in the glyph matrix if the overlay is |
19885 |
|
entirely covered by a `display' property. In |
19886 |
|
this case, we overshoot. So let's stop in |
19887 |
|
the glyph matrix before glyphs for OBJECT. */ |
19888 |
|
fast_find_position (w, XFASTINT (before), |
19889 |
|
&dpyinfo->mouse_face_beg_col, |
19890 |
|
&dpyinfo->mouse_face_beg_row, |
19891 |
|
&dpyinfo->mouse_face_beg_x, |
19892 |
|
&dpyinfo->mouse_face_beg_y, |
19893 |
|
object); |
19894 |
|
|
19895 |
|
dpyinfo->mouse_face_past_end |
19896 |
|
= !fast_find_position (w, XFASTINT (after), |
19897 |
|
&dpyinfo->mouse_face_end_col, |
19898 |
|
&dpyinfo->mouse_face_end_row, |
19899 |
|
&dpyinfo->mouse_face_end_x, |
19900 |
|
&dpyinfo->mouse_face_end_y, |
19901 |
|
Qnil); |
19902 |
|
dpyinfo->mouse_face_window = window; |
19903 |
|
dpyinfo->mouse_face_face_id |
19904 |
|
= face_at_buffer_position (w, pos, 0, 0, |
19905 |
|
&ignore, pos + 1, |
19906 |
|
!dpyinfo->mouse_face_hidden); |
19907 |
|
|
19908 |
|
/* Display it as active. */ |
19909 |
|
show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); |
19910 |
|
cursor = No_Cursor; |
19911 |
|
} |
19912 |
|
} |
19913 |
|
} |
19914 |
|
|
19915 |
|
check_help_echo: |
19916 |
|
|
19917 |
|
/* Look for a `help-echo' property. */ |
19918 |
|
{ |
19919 |
|
Lisp_Object help, overlay; |
19920 |
|
|
19921 |
|
/* Check overlays first. */ |
19922 |
|
help = overlay = Qnil; |
19923 |
|
for (i = noverlays - 1; i >= 0 && NILP (help); --i) |
19924 |
|
{ |
19925 |
|
overlay = overlay_vec[i]; |
19926 |
|
help = Foverlay_get (overlay, Qhelp_echo); |
19927 |
|
} |
19928 |
|
|
19929 |
|
if (!NILP (help)) |
19930 |
|
{ |
19931 |
|
help_echo_string = help; |
19932 |
|
help_echo_window = window; |
19933 |
|
help_echo_object = overlay; |
19934 |
|
help_echo_pos = pos; |
19935 |
|
} |
19936 |
|
else |
19937 |
|
{ |
19938 |
|
Lisp_Object object = glyph->object; |
19939 |
|
int charpos = glyph->charpos; |
19940 |
|
|
19941 |
|
/* Try text properties. */ |
19942 |
|
if (STRINGP (object) |
19943 |
|
&& charpos >= 0 |
19944 |
|
&& charpos < SCHARS (object)) |
19945 |
|
{ |
19946 |
|
help = Fget_text_property (make_number (charpos), |
19947 |
|
Qhelp_echo, object); |
19948 |
|
if (NILP (help)) |
19949 |
|
{ |
19950 |
|
/* If the string itself doesn't specify a help-echo, |
19951 |
|
see if the buffer text ``under'' it does. */ |
19952 |
|
struct glyph_row *r |
19953 |
|
= MATRIX_ROW (w->current_matrix, vpos); |
19954 |
|
int start = MATRIX_ROW_START_CHARPOS (r); |
19955 |
|
int pos = string_buffer_position (w, object, start); |
19956 |
|
if (pos > 0) |
19957 |
|
{ |
19958 |
|
help = Fget_char_property (make_number (pos), |
19959 |
|
Qhelp_echo, w->buffer); |
19960 |
|
if (!NILP (help)) |
19961 |
|
{ |
19962 |
|
charpos = pos; |
19963 |
|
object = w->buffer; |
19964 |
|
} |
19965 |
|
} |
19966 |
|
} |
19967 |
|
} |
19968 |
|
else if (BUFFERP (object) |
19969 |
|
&& charpos >= BEGV |
19970 |
|
&& charpos < ZV) |
19971 |
|
help = Fget_text_property (make_number (charpos), Qhelp_echo, |
19972 |
|
object); |
19973 |
|
|
19974 |
|
if (!NILP (help)) |
19975 |
|
{ |
19976 |
|
help_echo_string = help; |
19977 |
|
help_echo_window = window; |
19978 |
|
help_echo_object = object; |
19979 |
|
help_echo_pos = charpos; |
19980 |
|
} |
19981 |
|
} |
19982 |
|
} |
19983 |
|
|
19984 |
|
BEGV = obegv; |
19985 |
|
ZV = ozv; |
19986 |
|
current_buffer = obuf; |
19987 |
|
} |
19988 |
|
|
19989 |
|
set_cursor: |
19990 |
|
|
19991 |
|
#ifndef HAVE_CARBON |
19992 |
|
if (cursor != No_Cursor) |
19993 |
|
#else |
19994 |
|
if (bcmp (&cursor, &No_Cursor, sizeof (Cursor))) |
19995 |
|
#endif |
19996 |
|
rif->define_frame_cursor (f, cursor); |
19997 |
|
} |
19998 |
|
|
19999 |
|
|
20000 |
|
/* EXPORT for RIF: |
20001 |
|
Clear any mouse-face on window W. This function is part of the |
20002 |
|
redisplay interface, and is called from try_window_id and similar |
20003 |
|
functions to ensure the mouse-highlight is off. */ |
20004 |
|
|
20005 |
|
void |
20006 |
|
x_clear_window_mouse_face (w) |
20007 |
|
struct window *w; |
20008 |
|
{ |
20009 |
|
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); |
20010 |
|
Lisp_Object window; |
20011 |
|
|
20012 |
|
BLOCK_INPUT; |
20013 |
|
XSETWINDOW (window, w); |
20014 |
|
if (EQ (window, dpyinfo->mouse_face_window)) |
20015 |
|
clear_mouse_face (dpyinfo); |
20016 |
|
UNBLOCK_INPUT; |
20017 |
|
} |
20018 |
|
|
20019 |
|
|
20020 |
|
/* EXPORT: |
20021 |
|
Just discard the mouse face information for frame F, if any. |
20022 |
|
This is used when the size of F is changed. */ |
20023 |
|
|
20024 |
|
void |
20025 |
|
cancel_mouse_face (f) |
20026 |
|
struct frame *f; |
20027 |
|
{ |
20028 |
|
Lisp_Object window; |
20029 |
|
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
20030 |
|
|
20031 |
|
window = dpyinfo->mouse_face_window; |
20032 |
|
if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f) |
20033 |
|
{ |
20034 |
|
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; |
20035 |
|
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; |
20036 |
|
dpyinfo->mouse_face_window = Qnil; |
20037 |
|
} |
20038 |
|
} |
20039 |
|
|
20040 |
|
|
20041 |
|
#endif /* HAVE_WINDOW_SYSTEM */ |
20042 |
|
|
20043 |
|
|
20044 |
|
/*********************************************************************** |
20045 |
|
Exposure Events |
20046 |
|
***********************************************************************/ |
20047 |
|
|
20048 |
|
#ifdef HAVE_WINDOW_SYSTEM |
20049 |
|
|
20050 |
|
/* Redraw the part of glyph row area AREA of glyph row ROW on window W |
20051 |
|
which intersects rectangle R. R is in window-relative coordinates. */ |
20052 |
|
|
20053 |
|
static void |
20054 |
|
expose_area (w, row, r, area) |
20055 |
|
struct window *w; |
20056 |
|
struct glyph_row *row; |
20057 |
|
XRectangle *r; |
20058 |
|
enum glyph_row_area area; |
20059 |
|
{ |
20060 |
|
struct glyph *first = row->glyphs[area]; |
20061 |
|
struct glyph *end = row->glyphs[area] + row->used[area]; |
20062 |
|
struct glyph *last; |
20063 |
|
int first_x, start_x, x; |
20064 |
|
|
20065 |
|
if (area == TEXT_AREA && row->fill_line_p) |
20066 |
|
/* If row extends face to end of line write the whole line. */ |
20067 |
|
draw_glyphs (w, 0, row, area, |
20068 |
|
0, row->used[area], |
20069 |
|
DRAW_NORMAL_TEXT, 0); |
20070 |
|
else |
20071 |
|
{ |
20072 |
|
/* Set START_X to the window-relative start position for drawing glyphs of |
20073 |
|
AREA. The first glyph of the text area can be partially visible. |
20074 |
|
The first glyphs of other areas cannot. */ |
20075 |
|
if (area == LEFT_MARGIN_AREA) |
20076 |
|
start_x = 0; |
20077 |
|
else if (area == TEXT_AREA) |
20078 |
|
start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA); |
20079 |
|
else |
20080 |
|
start_x = (window_box_width (w, LEFT_MARGIN_AREA) |
20081 |
|
+ window_box_width (w, TEXT_AREA)); |
20082 |
|
x = start_x; |
20083 |
|
|
20084 |
|
/* Find the first glyph that must be redrawn. */ |
20085 |
|
while (first < end |
20086 |
|
&& x + first->pixel_width < r->x) |
20087 |
|
{ |
20088 |
|
x += first->pixel_width; |
20089 |
|
++first; |
20090 |
|
} |
20091 |
|
|
20092 |
|
/* Find the last one. */ |
20093 |
|
last = first; |
20094 |
|
first_x = x; |
20095 |
|
while (last < end |
20096 |
|
&& x < r->x + r->width) |
20097 |
|
{ |
20098 |
|
x += last->pixel_width; |
20099 |
|
++last; |
20100 |
|
} |
20101 |
|
|
20102 |
|
/* Repaint. */ |
20103 |
|
if (last > first) |
20104 |
|
draw_glyphs (w, first_x - start_x, row, area, |
20105 |
|
first - row->glyphs[area], last - row->glyphs[area], |
20106 |
|
DRAW_NORMAL_TEXT, 0); |
20107 |
|
} |
20108 |
|
} |
20109 |
|
|
20110 |
|
|
20111 |
|
/* Redraw the parts of the glyph row ROW on window W intersecting |
20112 |
|
rectangle R. R is in window-relative coordinates. Value is |
20113 |
|
non-zero if mouse-face was overwritten. */ |
20114 |
|
|
20115 |
|
static int |
20116 |
|
expose_line (w, row, r) |
20117 |
|
struct window *w; |
20118 |
|
struct glyph_row *row; |
20119 |
|
XRectangle *r; |
20120 |
|
{ |
20121 |
|
xassert (row->enabled_p); |
20122 |
|
|
20123 |
|
if (row->mode_line_p || w->pseudo_window_p) |
20124 |
|
draw_glyphs (w, 0, row, TEXT_AREA, |
20125 |
|
0, row->used[TEXT_AREA], |
20126 |
|
DRAW_NORMAL_TEXT, 0); |
20127 |
|
else |
20128 |
|
{ |
20129 |
|
if (row->used[LEFT_MARGIN_AREA]) |
20130 |
|
expose_area (w, row, r, LEFT_MARGIN_AREA); |
20131 |
|
if (row->used[TEXT_AREA]) |
20132 |
|
expose_area (w, row, r, TEXT_AREA); |
20133 |
|
if (row->used[RIGHT_MARGIN_AREA]) |
20134 |
|
expose_area (w, row, r, RIGHT_MARGIN_AREA); |
20135 |
|
draw_row_fringe_bitmaps (w, row); |
20136 |
|
} |
20137 |
|
|
20138 |
|
return row->mouse_face_p; |
20139 |
|
} |
20140 |
|
|
20141 |
|
|
20142 |
|
/* Redraw those parts of glyphs rows during expose event handling that |
20143 |
|
overlap other rows. Redrawing of an exposed line writes over parts |
20144 |
|
of lines overlapping that exposed line; this function fixes that. |
20145 |
|
|
20146 |
|
W is the window being exposed. FIRST_OVERLAPPING_ROW is the first |
20147 |
|
row in W's current matrix that is exposed and overlaps other rows. |
20148 |
|
LAST_OVERLAPPING_ROW is the last such row. */ |
20149 |
|
|
20150 |
|
static void |
20151 |
|
expose_overlaps (w, first_overlapping_row, last_overlapping_row) |
20152 |
|
struct window *w; |
20153 |
|
struct glyph_row *first_overlapping_row; |
20154 |
|
struct glyph_row *last_overlapping_row; |
20155 |
|
{ |
20156 |
|
struct glyph_row *row; |
20157 |
|
|
20158 |
|
for (row = first_overlapping_row; row <= last_overlapping_row; ++row) |
20159 |
|
if (row->overlapping_p) |
20160 |
|
{ |
20161 |
|
xassert (row->enabled_p && !row->mode_line_p); |
20162 |
|
|
20163 |
|
if (row->used[LEFT_MARGIN_AREA]) |
20164 |
|
x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA); |
20165 |
|
|
20166 |
|
if (row->used[TEXT_AREA]) |
20167 |
|
x_fix_overlapping_area (w, row, TEXT_AREA); |
20168 |
|
|
20169 |
|
if (row->used[RIGHT_MARGIN_AREA]) |
20170 |
|
x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA); |
20171 |
|
} |
20172 |
|
} |
20173 |
|
|
20174 |
|
|
20175 |
|
/* Return non-zero if W's cursor intersects rectangle R. */ |
20176 |
|
|
20177 |
|
static int |
20178 |
|
phys_cursor_in_rect_p (w, r) |
20179 |
|
struct window *w; |
20180 |
|
XRectangle *r; |
20181 |
|
{ |
20182 |
|
XRectangle cr, result; |
20183 |
|
struct glyph *cursor_glyph; |
20184 |
|
|
20185 |
|
cursor_glyph = get_phys_cursor_glyph (w); |
20186 |
|
if (cursor_glyph) |
20187 |
|
{ |
20188 |
|
cr.x = w->phys_cursor.x; |
20189 |
|
cr.y = w->phys_cursor.y; |
20190 |
|
cr.width = cursor_glyph->pixel_width; |
20191 |
|
cr.height = w->phys_cursor_height; |
20192 |
|
/* ++KFS: W32 version used W32-specific IntersectRect here, but |
20193 |
|
I assume the effect is the same -- and this is portable. */ |
20194 |
|
return x_intersect_rectangles (&cr, r, &result); |
20195 |
|
} |
20196 |
|
else |
20197 |
|
return 0; |
20198 |
|
} |
20199 |
|
|
20200 |
|
|
20201 |
|
/* EXPORT: |
20202 |
|
Draw a vertical window border to the right of window W if W doesn't |
20203 |
|
have vertical scroll bars. */ |
20204 |
|
|
20205 |
|
void |
20206 |
|
x_draw_vertical_border (w) |
20207 |
|
struct window *w; |
20208 |
|
{ |
20209 |
|
struct frame *f = XFRAME (WINDOW_FRAME (w)); |
20210 |
|
|
20211 |
|
/* Redraw borders between horizontally adjacent windows. Don't |
20212 |
|
do it for frames with vertical scroll bars because either the |
20213 |
|
right scroll bar of a window, or the left scroll bar of its |
20214 |
|
neighbor will suffice as a border. */ |
20215 |
|
if (!WINDOW_RIGHTMOST_P (w) |
20216 |
|
&& !FRAME_HAS_VERTICAL_SCROLL_BARS (f)) |
20217 |
|
{ |
20218 |
|
int x0, x1, y0, y1; |
20219 |
|
|
20220 |
|
window_box_edges (w, -1, &x0, &y0, &x1, &y1); |
20221 |
|
x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f); |
20222 |
|
y1 -= 1; |
20223 |
|
|
20224 |
|
rif->draw_vertical_window_border (w, x1, y0, y1); |
20225 |
|
} |
20226 |
|
} |
20227 |
|
|
20228 |
|
|
20229 |
|
/* Redraw the part of window W intersection rectangle FR. Pixel |
20230 |
|
coordinates in FR are frame-relative. Call this function with |
20231 |
|
input blocked. Value is non-zero if the exposure overwrites |
20232 |
|
mouse-face. */ |
20233 |
|
|
20234 |
|
static int |
20235 |
|
expose_window (w, fr) |
20236 |
|
struct window *w; |
20237 |
|
XRectangle *fr; |
20238 |
|
{ |
20239 |
|
struct frame *f = XFRAME (w->frame); |
20240 |
|
XRectangle wr, r; |
20241 |
|
int mouse_face_overwritten_p = 0; |
20242 |
|
|
20243 |
|
/* If window is not yet fully initialized, do nothing. This can |
20244 |
|
happen when toolkit scroll bars are used and a window is split. |
20245 |
|
Reconfiguring the scroll bar will generate an expose for a newly |
20246 |
|
created window. */ |
20247 |
|
if (w->current_matrix == NULL) |
20248 |
|
return 0; |
20249 |
|
|
20250 |
|
/* When we're currently updating the window, display and current |
20251 |
|
matrix usually don't agree. Arrange for a thorough display |
20252 |
|
later. */ |
20253 |
|
if (w == updated_window) |
20254 |
|
{ |
20255 |
|
SET_FRAME_GARBAGED (f); |
20256 |
|
return 0; |
20257 |
|
} |
20258 |
|
|
20259 |
|
/* Frame-relative pixel rectangle of W. */ |
20260 |
|
wr.x = XFASTINT (w->left) * CANON_X_UNIT (f); |
20261 |
|
wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f); |
20262 |
|
wr.width = XFASTINT (w->width) * CANON_X_UNIT (f); |
20263 |
|
wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f); |
20264 |
|
|
20265 |
|
if (x_intersect_rectangles (fr, &wr, &r)) |
20266 |
|
{ |
20267 |
|
int yb = window_text_bottom_y (w); |
20268 |
|
struct glyph_row *row; |
20269 |
|
int cursor_cleared_p; |
20270 |
|
struct glyph_row *first_overlapping_row, *last_overlapping_row; |
20271 |
|
|
20272 |
|
TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n", |
20273 |
|
r.x, r.y, r.width, r.height)); |
20274 |
|
|
20275 |
|
/* Convert to window coordinates. */ |
20276 |
|
r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x); |
20277 |
|
r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y); |
20278 |
|
|
20279 |
|
/* Turn off the cursor. */ |
20280 |
|
if (!w->pseudo_window_p |
20281 |
|
&& phys_cursor_in_rect_p (w, &r)) |
20282 |
|
{ |
20283 |
|
x_clear_cursor (w); |
20284 |
|
cursor_cleared_p = 1; |
20285 |
|
} |
20286 |
|
else |
20287 |
|
cursor_cleared_p = 0; |
20288 |
|
|
20289 |
|
/* Update lines intersecting rectangle R. */ |
20290 |
|
first_overlapping_row = last_overlapping_row = NULL; |
20291 |
|
for (row = w->current_matrix->rows; |
20292 |
|
row->enabled_p; |
20293 |
|
++row) |
20294 |
|
{ |
20295 |
|
int y0 = row->y; |
20296 |
|
int y1 = MATRIX_ROW_BOTTOM_Y (row); |
20297 |
|
|
20298 |
|
if ((y0 >= r.y && y0 < r.y + r.height) |
20299 |
|
|| (y1 > r.y && y1 < r.y + r.height) |
20300 |
|
|| (r.y >= y0 && r.y < y1) |
20301 |
|
|| (r.y + r.height > y0 && r.y + r.height < y1)) |
20302 |
|
{ |
20303 |
|
if (row->overlapping_p) |
20304 |
|
{ |
20305 |
|
if (first_overlapping_row == NULL) |
20306 |
|
first_overlapping_row = row; |
20307 |
|
last_overlapping_row = row; |
20308 |
|
} |
20309 |
|
|
20310 |
|
if (expose_line (w, row, &r)) |
20311 |
|
mouse_face_overwritten_p = 1; |
20312 |
|
} |
20313 |
|
|
20314 |
|
if (y1 >= yb) |
20315 |
|
break; |
20316 |
|
} |
20317 |
|
|
20318 |
|
/* Display the mode line if there is one. */ |
20319 |
|
if (WINDOW_WANTS_MODELINE_P (w) |
20320 |
|
&& (row = MATRIX_MODE_LINE_ROW (w->current_matrix), |
20321 |
|
row->enabled_p) |
20322 |
|
&& row->y < r.y + r.height) |
20323 |
|
{ |
20324 |
|
if (expose_line (w, row, &r)) |
20325 |
|
mouse_face_overwritten_p = 1; |
20326 |
|
} |
20327 |
|
|
20328 |
|
if (!w->pseudo_window_p) |
20329 |
|
{ |
20330 |
|
/* Fix the display of overlapping rows. */ |
20331 |
|
if (first_overlapping_row) |
20332 |
|
expose_overlaps (w, first_overlapping_row, last_overlapping_row); |
20333 |
|
|
20334 |
|
/* Draw border between windows. */ |
20335 |
|
x_draw_vertical_border (w); |
20336 |
|
|
20337 |
|
/* Turn the cursor on again. */ |
20338 |
|
if (cursor_cleared_p) |
20339 |
|
update_window_cursor (w, 1); |
20340 |
|
} |
20341 |
|
} |
20342 |
|
|
20343 |
|
#ifdef HAVE_CARBON |
20344 |
|
/* Display scroll bar for this window. */ |
20345 |
|
if (!NILP (w->vertical_scroll_bar)) |
20346 |
|
{ |
20347 |
|
/* ++KFS: |
20348 |
|
If this doesn't work here (maybe some header files are missing), |
20349 |
|
make a function in macterm.c and call it to do the job! */ |
20350 |
|
ControlHandle ch |
20351 |
|
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar)); |
20352 |
|
|
20353 |
|
Draw1Control (ch); |
20354 |
|
} |
20355 |
|
#endif |
20356 |
|
|
20357 |
|
return mouse_face_overwritten_p; |
20358 |
|
} |
20359 |
|
|
20360 |
|
|
20361 |
|
|
20362 |
|
/* Redraw (parts) of all windows in the window tree rooted at W that |
20363 |
|
intersect R. R contains frame pixel coordinates. Value is |
20364 |
|
non-zero if the exposure overwrites mouse-face. */ |
20365 |
|
|
20366 |
|
static int |
20367 |
|
expose_window_tree (w, r) |
20368 |
|
struct window *w; |
20369 |
|
XRectangle *r; |
20370 |
|
{ |
20371 |
|
struct frame *f = XFRAME (w->frame); |
20372 |
|
int mouse_face_overwritten_p = 0; |
20373 |
|
|
20374 |
|
while (w && !FRAME_GARBAGED_P (f)) |
20375 |
|
{ |
20376 |
|
if (!NILP (w->hchild)) |
20377 |
|
mouse_face_overwritten_p |
20378 |
|
|= expose_window_tree (XWINDOW (w->hchild), r); |
20379 |
|
else if (!NILP (w->vchild)) |
20380 |
|
mouse_face_overwritten_p |
20381 |
|
|= expose_window_tree (XWINDOW (w->vchild), r); |
20382 |
|
else |
20383 |
|
mouse_face_overwritten_p |= expose_window (w, r); |
20384 |
|
|
20385 |
|
w = NILP (w->next) ? NULL : XWINDOW (w->next); |
20386 |
|
} |
20387 |
|
|
20388 |
|
return mouse_face_overwritten_p; |
20389 |
|
} |
20390 |
|
|
20391 |
|
|
20392 |
|
/* EXPORT: |
20393 |
|
Redisplay an exposed area of frame F. X and Y are the upper-left |
20394 |
|
corner of the exposed rectangle. W and H are width and height of |
20395 |
|
the exposed area. All are pixel values. W or H zero means redraw |
20396 |
|
the entire frame. */ |
20397 |
|
|
20398 |
|
void |
20399 |
|
expose_frame (f, x, y, w, h) |
20400 |
|
struct frame *f; |
20401 |
|
int x, y, w, h; |
20402 |
|
{ |
20403 |
|
XRectangle r; |
20404 |
|
int mouse_face_overwritten_p = 0; |
20405 |
|
|
20406 |
|
TRACE ((stderr, "expose_frame ")); |
20407 |
|
|
20408 |
|
/* No need to redraw if frame will be redrawn soon. */ |
20409 |
|
if (FRAME_GARBAGED_P (f)) |
20410 |
|
{ |
20411 |
|
TRACE ((stderr, " garbaged\n")); |
20412 |
|
return; |
20413 |
|
} |
20414 |
|
|
20415 |
|
#ifdef HAVE_CARBON |
20416 |
|
/* MAC_TODO: this is a kludge, but if scroll bars are not activated |
20417 |
|
or deactivated here, for unknown reasons, activated scroll bars |
20418 |
|
are shown in deactivated frames in some instances. */ |
20419 |
|
if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame) |
20420 |
|
activate_scroll_bars (f); |
20421 |
|
else |
20422 |
|
deactivate_scroll_bars (f); |
20423 |
|
#endif |
20424 |
|
|
20425 |
|
/* If basic faces haven't been realized yet, there is no point in |
20426 |
|
trying to redraw anything. This can happen when we get an expose |
20427 |
|
event while Emacs is starting, e.g. by moving another window. */ |
20428 |
|
if (FRAME_FACE_CACHE (f) == NULL |
20429 |
|
|| FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL) |
20430 |
|
{ |
20431 |
|
TRACE ((stderr, " no faces\n")); |
20432 |
|
return; |
20433 |
|
} |
20434 |
|
|
20435 |
|
if (w == 0 || h == 0) |
20436 |
|
{ |
20437 |
|
r.x = r.y = 0; |
20438 |
|
r.width = CANON_X_UNIT (f) * f->width; |
20439 |
|
r.height = CANON_Y_UNIT (f) * f->height; |
20440 |
|
} |
20441 |
|
else |
20442 |
|
{ |
20443 |
|
r.x = x; |
20444 |
|
r.y = y; |
20445 |
|
r.width = w; |
20446 |
|
r.height = h; |
20447 |
|
} |
20448 |
|
|
20449 |
|
TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height)); |
20450 |
|
mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r); |
20451 |
|
|
20452 |
|
if (WINDOWP (f->tool_bar_window)) |
20453 |
|
mouse_face_overwritten_p |
20454 |
|
|= expose_window (XWINDOW (f->tool_bar_window), &r); |
20455 |
|
|
20456 |
|
#ifdef HAVE_X_WINDOWS |
20457 |
|
#ifndef MSDOS |
20458 |
|
#ifndef USE_X_TOOLKIT |
20459 |
|
if (WINDOWP (f->menu_bar_window)) |
20460 |
|
mouse_face_overwritten_p |
20461 |
|
|= expose_window (XWINDOW (f->menu_bar_window), &r); |
20462 |
|
#endif /* not USE_X_TOOLKIT */ |
20463 |
|
#endif |
20464 |
|
#endif |
20465 |
|
|
20466 |
|
/* Some window managers support a focus-follows-mouse style with |
20467 |
|
delayed raising of frames. Imagine a partially obscured frame, |
20468 |
|
and moving the mouse into partially obscured mouse-face on that |
20469 |
|
frame. The visible part of the mouse-face will be highlighted, |
20470 |
|
then the WM raises the obscured frame. With at least one WM, KDE |
20471 |
|
2.1, Emacs is not getting any event for the raising of the frame |
20472 |
|
(even tried with SubstructureRedirectMask), only Expose events. |
20473 |
|
These expose events will draw text normally, i.e. not |
20474 |
|
highlighted. Which means we must redo the highlight here. |
20475 |
|
Subsume it under ``we love X''. --gerd 2001-08-15 */ |
20476 |
|
/* Included in Windows version because Windows most likely does not |
20477 |
|
do the right thing if any third party tool offers |
20478 |
|
focus-follows-mouse with delayed raise. --jason 2001-10-12 */ |
20479 |
|
if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f)) |
20480 |
|
{ |
20481 |
|
Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
20482 |
|
if (f == dpyinfo->mouse_face_mouse_frame) |
20483 |
|
{ |
20484 |
|
int x = dpyinfo->mouse_face_mouse_x; |
20485 |
|
int y = dpyinfo->mouse_face_mouse_y; |
20486 |
|
clear_mouse_face (dpyinfo); |
20487 |
|
note_mouse_highlight (f, x, y); |
20488 |
|
} |
20489 |
|
} |
20490 |
|
} |
20491 |
|
|
20492 |
|
|
20493 |
|
/* EXPORT: |
20494 |
|
Determine the intersection of two rectangles R1 and R2. Return |
20495 |
|
the intersection in *RESULT. Value is non-zero if RESULT is not |
20496 |
|
empty. */ |
20497 |
|
|
20498 |
|
int |
20499 |
|
x_intersect_rectangles (r1, r2, result) |
20500 |
|
XRectangle *r1, *r2, *result; |
20501 |
|
{ |
20502 |
|
XRectangle *left, *right; |
20503 |
|
XRectangle *upper, *lower; |
20504 |
|
int intersection_p = 0; |
20505 |
|
|
20506 |
|
/* Rearrange so that R1 is the left-most rectangle. */ |
20507 |
|
if (r1->x < r2->x) |
20508 |
|
left = r1, right = r2; |
20509 |
|
else |
20510 |
|
left = r2, right = r1; |
20511 |
|
|
20512 |
|
/* X0 of the intersection is right.x0, if this is inside R1, |
20513 |
|
otherwise there is no intersection. */ |
20514 |
|
if (right->x <= left->x + left->width) |
20515 |
|
{ |
20516 |
|
result->x = right->x; |
20517 |
|
|
20518 |
|
/* The right end of the intersection is the minimum of the |
20519 |
|
the right ends of left and right. */ |
20520 |
|
result->width = (min (left->x + left->width, right->x + right->width) |
20521 |
|
- result->x); |
20522 |
|
|
20523 |
|
/* Same game for Y. */ |
20524 |
|
if (r1->y < r2->y) |
20525 |
|
upper = r1, lower = r2; |
20526 |
|
else |
20527 |
|
upper = r2, lower = r1; |
20528 |
|
|
20529 |
|
/* The upper end of the intersection is lower.y0, if this is inside |
20530 |
|
of upper. Otherwise, there is no intersection. */ |
20531 |
|
if (lower->y <= upper->y + upper->height) |
20532 |
|
{ |
20533 |
|
result->y = lower->y; |
20534 |
|
|
20535 |
|
/* The lower end of the intersection is the minimum of the lower |
20536 |
|
ends of upper and lower. */ |
20537 |
|
result->height = (min (lower->y + lower->height, |
20538 |
|
upper->y + upper->height) |
20539 |
|
- result->y); |
20540 |
|
intersection_p = 1; |
20541 |
|
} |
20542 |
|
} |
20543 |
|
|
20544 |
|
return intersection_p; |
20545 |
|
} |
20546 |
|
|
20547 |
|
#endif /* HAVE_WINDOW_SYSTEM */ |
20548 |
|
|
20549 |
|
|
20550 |
|
/*********************************************************************** |
20551 |
Initialization |
Initialization |
20552 |
***********************************************************************/ |
***********************************************************************/ |
20553 |
|
|
20631 |
staticpro (&QCeval); |
staticpro (&QCeval); |
20632 |
QCpropertize = intern (":propertize"); |
QCpropertize = intern (":propertize"); |
20633 |
staticpro (&QCpropertize); |
staticpro (&QCpropertize); |
|
Qwhen = intern ("when"); |
|
|
staticpro (&Qwhen); |
|
20634 |
QCfile = intern (":file"); |
QCfile = intern (":file"); |
20635 |
staticpro (&QCfile); |
staticpro (&QCfile); |
20636 |
Qfontified = intern ("fontified"); |
Qfontified = intern ("fontified"); |
20657 |
staticpro (&Qbuffer_position); |
staticpro (&Qbuffer_position); |
20658 |
Qobject = intern ("object"); |
Qobject = intern ("object"); |
20659 |
staticpro (&Qobject); |
staticpro (&Qobject); |
20660 |
|
Qbar = intern ("bar"); |
20661 |
|
staticpro (&Qbar); |
20662 |
|
Qhbar = intern ("hbar"); |
20663 |
|
staticpro (&Qhbar); |
20664 |
|
Qbox = intern ("box"); |
20665 |
|
staticpro (&Qbox); |
20666 |
|
Qhollow = intern ("hollow"); |
20667 |
|
staticpro (&Qhollow); |
20668 |
Qrisky_local_variable = intern ("risky-local-variable"); |
Qrisky_local_variable = intern ("risky-local-variable"); |
20669 |
staticpro (&Qrisky_local_variable); |
staticpro (&Qrisky_local_variable); |
20670 |
|
Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces"); |
20671 |
|
staticpro (&Qinhibit_free_realized_faces); |
20672 |
|
|
20673 |
list_of_error = Fcons (intern ("error"), Qnil); |
list_of_error = Fcons (intern ("error"), Qnil); |
20674 |
staticpro (&list_of_error); |
staticpro (&list_of_error); |
20692 |
mode_line_proptrans_alist = Qnil; |
mode_line_proptrans_alist = Qnil; |
20693 |
staticpro (&mode_line_proptrans_alist); |
staticpro (&mode_line_proptrans_alist); |
20694 |
|
|
20695 |
|
mode_line_string_list = Qnil; |
20696 |
|
staticpro (&mode_line_string_list); |
20697 |
|
|
20698 |
|
help_echo_string = Qnil; |
20699 |
|
staticpro (&help_echo_string); |
20700 |
|
help_echo_object = Qnil; |
20701 |
|
staticpro (&help_echo_object); |
20702 |
|
help_echo_window = Qnil; |
20703 |
|
staticpro (&help_echo_window); |
20704 |
|
previous_help_echo_string = Qnil; |
20705 |
|
staticpro (&previous_help_echo_string); |
20706 |
|
help_echo_pos = -1; |
20707 |
|
|
20708 |
|
#ifdef HAVE_WINDOW_SYSTEM |
20709 |
|
DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p, |
20710 |
|
doc: /* *Non-nil means draw block cursor as wide as the glyph under it. |
20711 |
|
For example, if a block cursor is over a tab, it will be drawn as |
20712 |
|
wide as that tab on the display. */); |
20713 |
|
x_stretch_cursor_p = 0; |
20714 |
|
#endif |
20715 |
|
|
20716 |
DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace, |
DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace, |
20717 |
doc: /* Non-nil means highlight trailing whitespace. |
doc: /* Non-nil means highlight trailing whitespace. |
20718 |
The face used for trailing whitespace is `trailing-whitespace'. */); |
The face used for trailing whitespace is `trailing-whitespace'. */); |
20768 |
DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video, |
DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video, |
20769 |
doc: /* nil means display the mode-line/header-line/menu-bar in the default face. |
doc: /* nil means display the mode-line/header-line/menu-bar in the default face. |
20770 |
Any other value means to use the appropriate face, `mode-line', |
Any other value means to use the appropriate face, `mode-line', |
20771 |
`header-line', or `menu' respectively. |
`header-line', or `menu' respectively. */); |
|
|
|
|
This variable is deprecated; please change the above faces instead. */); |
|
20772 |
mode_line_inverse_video = 1; |
mode_line_inverse_video = 1; |
20773 |
|
|
20774 |
DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit, |
DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit, |
20838 |
is not valid when these functions are called. */); |
is not valid when these functions are called. */); |
20839 |
Vwindow_scroll_functions = Qnil; |
Vwindow_scroll_functions = Qnil; |
20840 |
|
|
20841 |
|
DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window, |
20842 |
|
doc: /* *Non-nil means autoselect window with mouse pointer. */); |
20843 |
|
mouse_autoselect_window = 0; |
20844 |
|
|
20845 |
DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p, |
DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p, |
20846 |
doc: /* *Non-nil means automatically resize tool-bars. |
doc: /* *Non-nil means automatically resize tool-bars. |
20847 |
This increases a tool-bar's height if not all tool-bar items are visible. |
This increases a tool-bar's height if not all tool-bar items are visible. |
20897 |
go back to their normal size. */); |
go back to their normal size. */); |
20898 |
Vresize_mini_windows = Qgrow_only; |
Vresize_mini_windows = Qgrow_only; |
20899 |
|
|
20900 |
DEFVAR_BOOL ("cursor-in-non-selected-windows", |
DEFVAR_LISP ("cursor-in-non-selected-windows", |
20901 |
&cursor_in_non_selected_windows, |
&Vcursor_in_non_selected_windows, |
20902 |
doc: /* *Non-nil means display a hollow cursor in non-selected windows. |
doc: /* *Cursor type to display in non-selected windows. |
20903 |
nil means don't display a cursor there. */); |
t means to use hollow box cursor. See `cursor-type' for other values. */); |
20904 |
cursor_in_non_selected_windows = 1; |
Vcursor_in_non_selected_windows = Qt; |
20905 |
|
|
20906 |
|
DEFVAR_LISP ("blink-cursor-alist", &Vblink_cursor_alist, |
20907 |
|
doc: /* Alist specifying how to blink the cursor off. |
20908 |
|
Each element has the form (ON-STATE . OFF-STATE). Whenever the |
20909 |
|
`cursor-type' frame-parameter or variable equals ON-STATE, |
20910 |
|
comparing using `equal', Emacs uses OFF-STATE to specify |
20911 |
|
how to blink it off. */); |
20912 |
|
Vblink_cursor_alist = Qnil; |
20913 |
|
|
20914 |
DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p, |
DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p, |
20915 |
doc: /* *Non-nil means scroll the display automatically to make point visible. */); |
doc: /* *Non-nil means scroll the display automatically to make point visible. */); |
20961 |
doc: /* Non-nil means don't eval Lisp during redisplay. */); |
doc: /* Non-nil means don't eval Lisp during redisplay. */); |
20962 |
inhibit_eval_during_redisplay = 0; |
inhibit_eval_during_redisplay = 0; |
20963 |
|
|
20964 |
|
DEFVAR_BOOL ("inhibit-free-realized-faces", &inhibit_free_realized_faces, |
20965 |
|
doc: /* Non-nil means don't free realized faces. Internal use only. */); |
20966 |
|
inhibit_free_realized_faces = 0; |
20967 |
|
|
20968 |
#if GLYPH_DEBUG |
#if GLYPH_DEBUG |
20969 |
DEFVAR_BOOL ("inhibit-try-window-id", &inhibit_try_window_id, |
DEFVAR_BOOL ("inhibit-try-window-id", &inhibit_try_window_id, |
20970 |
doc: /* Inhibit try_window_id display optimization. */); |
doc: /* Inhibit try_window_id display optimization. */); |
21021 |
} |
} |
21022 |
|
|
21023 |
{ |
{ |
21024 |
/* Allocate the buffer for frame titles. */ |
/* Allocate the buffer for frame titles. |
21025 |
|
Also used for `format-mode-line'. */ |
21026 |
int size = 100; |
int size = 100; |
21027 |
frame_title_buf = (char *) xmalloc (size); |
frame_title_buf = (char *) xmalloc (size); |
21028 |
frame_title_buf_end = frame_title_buf + size; |
frame_title_buf_end = frame_title_buf + size; |