Mercurial > emacs
comparison src/xterm.c @ 24991:53d428012caf
Display-related functions implemented from scratch. Add toolkit
scroll bars, mouse-sensitive mode line, help-echo, busy-cursor.
(x_calc_absolute_position): Subtract menu bar height
for YNegative, if using X toolkit.
(XTread_socket) [USE_MOTIF] <KeyPress>: Catch events
in scroll bars.
(SET_SAVED_MENU_EVENT): Give it statement form.
(XTflash): Don't flash the toolbar window.
(XTread_socket): Workaround for LessTif popup menus
in case of ButtonPress events.
(XTread_socket): Set inhibit_busy_cursor.
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Wed, 21 Jul 1999 21:43:52 +0000 |
parents | 1edc68c613d8 |
children | 0d081383b5b8 |
comparison
equal
deleted
inserted
replaced
24990:7505930b5456 | 24991:53d428012caf |
---|---|
1 /* X Communication module for terminals which understand the X protocol. | 1 /* X Communication module for terminals which understand the X protocol. |
2 Copyright (C) 1989, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. | 2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999 |
3 Free Software Foundation, Inc. | |
3 | 4 |
4 This file is part of GNU Emacs. | 5 This file is part of GNU Emacs. |
5 | 6 |
6 GNU Emacs is free software; you can redistribute it and/or modify | 7 GNU Emacs is free software; you can redistribute it and/or modify |
7 it under the terms of the GNU General Public License as published by | 8 it under the terms of the GNU General Public License as published by |
16 You should have received a copy of the GNU General Public License | 17 You should have received a copy of the GNU General Public License |
17 along with GNU Emacs; see the file COPYING. If not, write to | 18 along with GNU Emacs; see the file COPYING. If not, write to |
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 Boston, MA 02111-1307, USA. */ | 20 Boston, MA 02111-1307, USA. */ |
20 | 21 |
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */ | |
21 /* Xt features made by Fred Pierresteguy. */ | 23 /* Xt features made by Fred Pierresteguy. */ |
22 | 24 |
23 /* On 4.3 these lose if they come after xterm.h. */ | 25 /* On 4.3 these lose if they come after xterm.h. */ |
24 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */ | 26 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */ |
25 /* Putting these at the beginning seems to be standard for other .c files. */ | 27 /* Putting these at the beginning seems to be standard for other .c files. */ |
26 #include <signal.h> | 28 #include <signal.h> |
27 | 29 |
28 #include <config.h> | 30 #include <config.h> |
29 | 31 |
30 #include <stdio.h> | 32 #include <stdio.h> |
33 #ifdef STDC_HEADERS | |
34 #include <stdlib.h> | |
35 #endif | |
31 | 36 |
32 #ifdef HAVE_X_WINDOWS | 37 #ifdef HAVE_X_WINDOWS |
33 | 38 |
34 #include "lisp.h" | 39 #include "lisp.h" |
35 #include "blockinput.h" | 40 #include "blockinput.h" |
90 | 95 |
91 #ifdef USE_X_TOOLKIT | 96 #ifdef USE_X_TOOLKIT |
92 #include <X11/Shell.h> | 97 #include <X11/Shell.h> |
93 #endif | 98 #endif |
94 | 99 |
100 #include <sys/types.h> | |
101 #ifdef HAVE_SYS_TIME_H | |
102 #include <sys/time.h> | |
103 #endif | |
104 #ifdef HAVE_UNISTD_H | |
105 #include <unistd.h> | |
106 #endif | |
107 | |
95 #ifdef USE_X_TOOLKIT | 108 #ifdef USE_X_TOOLKIT |
109 | |
96 extern void free_frame_menubar (); | 110 extern void free_frame_menubar (); |
97 extern FRAME_PTR x_menubar_window_to_frame (); | 111 extern FRAME_PTR x_menubar_window_to_frame (); |
112 | |
98 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES) | 113 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES) |
99 #define HACK_EDITRES | 114 #define HACK_EDITRES |
100 extern void _XEditResCheckMessages (); | 115 extern void _XEditResCheckMessages (); |
101 #endif /* not NO_EDITRES */ | 116 #endif /* not NO_EDITRES */ |
117 | |
118 /* Include toolkit specific headers for the scroll bar widget. */ | |
119 | |
120 #ifdef USE_TOOLKIT_SCROLL_BARS | |
121 #if defined USE_MOTIF | |
122 #include <Xm/Xm.h> /* for LESSTIF_VERSION */ | |
123 #include <Xm/ScrollBar.h> | |
124 #include <Xm/ScrollBarP.h> | |
125 #elif defined HAVE_XAW3D | |
126 #include <X11/Xaw3d/Simple.h> | |
127 #include <X11/Xaw3d/ThreeD.h> | |
128 #include <X11/Xaw3d/Scrollbar.h> | |
129 #define ARROW_SCROLLBAR | |
130 #include <X11/Xaw3d/ScrollbarP.h> | |
131 #endif /* HAVE_XAW3D */ | |
132 #endif /* USE_TOOLKIT_SCROLL_BARS */ | |
133 | |
102 #endif /* USE_X_TOOLKIT */ | 134 #endif /* USE_X_TOOLKIT */ |
103 | 135 |
104 #ifndef USE_X_TOOLKIT | 136 #ifndef USE_X_TOOLKIT |
105 #define x_any_window_to_frame x_window_to_frame | 137 #define x_any_window_to_frame x_window_to_frame |
106 #define x_top_window_to_frame x_window_to_frame | 138 #define x_top_window_to_frame x_window_to_frame |
124 <string.h> will cause a syntax error when Xfuncs.h later includes it. */ | 156 <string.h> will cause a syntax error when Xfuncs.h later includes it. */ |
125 #include <string.h> | 157 #include <string.h> |
126 #endif | 158 #endif |
127 | 159 |
128 #ifndef min | 160 #ifndef min |
129 #define min(a,b) ((a)<(b) ? (a) : (b)) | 161 #define min(a,b) ((a) < (b) ? (a) : (b)) |
130 #endif | 162 #endif |
131 #ifndef max | 163 #ifndef max |
132 #define max(a,b) ((a)>(b) ? (a) : (b)) | 164 #define max(a,b) ((a) > (b) ? (a) : (b)) |
133 #endif | 165 #endif |
166 | |
167 #define abs(x) ((x) < 0 ? -(x) : (x)) | |
168 | |
169 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER)) | |
170 | |
134 | 171 |
135 /* This is a chain of structures for all the X displays currently in use. */ | 172 /* Bitmaps for truncated lines. */ |
173 | |
174 enum bitmap_type | |
175 { | |
176 NO_BITMAP, | |
177 LEFT_TRUNCATION_BITMAP, | |
178 RIGHT_TRUNCATION_BITMAP, | |
179 OVERLAY_ARROW_BITMAP, | |
180 CONTINUED_LINE_BITMAP, | |
181 CONTINUATION_LINE_BITMAP, | |
182 ZV_LINE_BITMAP | |
183 }; | |
184 | |
185 /* Bitmap drawn to indicate lines not displaying text if | |
186 `indicate-empty-lines' is non-nil. */ | |
187 | |
188 #define zv_width 8 | |
189 #define zv_height 8 | |
190 static unsigned char zv_bits[] = { | |
191 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00}; | |
192 | |
193 /* An arrow like this: `<-'. */ | |
194 | |
195 #define left_width 8 | |
196 #define left_height 8 | |
197 static unsigned char left_bits[] = { | |
198 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18}; | |
199 | |
200 /* Marker for continued lines. */ | |
201 | |
202 #define continued_width 8 | |
203 #define continued_height 8 | |
204 static unsigned char continued_bits[] = { | |
205 0x30, 0x30, 0x30, 0x30, 0xb4, 0xfc, 0x78, 0x30}; | |
206 | |
207 #define continuation_width 8 | |
208 #define continuation_height 8 | |
209 static unsigned char continuation_bits[] = { | |
210 0x0c, 0x1e, 0x3f, 0x2d, 0x0c, 0x0c, 0x0c, 0x0c}; | |
211 | |
212 /* Right truncation arrow bitmap `->'. */ | |
213 | |
214 #define right_width 8 | |
215 #define right_height 8 | |
216 static unsigned char right_bits[] = { | |
217 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18}; | |
218 | |
219 /* Overlay arrow bitmap; a filled `<>'. */ | |
220 | |
221 #if 1 | |
222 #define ov_width 8 | |
223 #define ov_height 8 | |
224 static unsigned char ov_bits[] = { | |
225 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c}; | |
226 | |
227 #elif 0 | |
228 #define ov_width 8 | |
229 #define ov_height 8 | |
230 static unsigned char ov_bits[] = { | |
231 0x18, 0x04, 0x08, 0x1c, 0x3e, 0x3a, 0x32, 0x1c}; | |
232 #else | |
233 #define ov_width 8 | |
234 #define ov_height 8 | |
235 static unsigned char ov_bits[] = { | |
236 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18}; | |
237 #endif | |
238 | |
239 extern Lisp_Object Qhelp_echo; | |
240 | |
241 | |
242 /* Non-zero means Emacs uses toolkit scroll bars. */ | |
243 | |
244 int x_toolkit_scroll_bars_p; | |
245 | |
246 /* If a string, XTread_socket generates an event to display that string. | |
247 (The display is done in read_char.) */ | |
248 | |
249 static Lisp_Object help_echo; | |
250 | |
251 /* Temporary variable for XTread_socket. */ | |
252 | |
253 static Lisp_Object previous_help_echo; | |
254 | |
255 /* Non-zero means that a HELP_EVENT has been generated since Emacs | |
256 start. */ | |
257 | |
258 static int any_help_event_p; | |
259 | |
260 /* Non-zero means draw block and hollow cursor as wide as the glyph | |
261 under it. For example, if a block cursor is over a tab, it will be | |
262 drawn as wide as that tab on the display. */ | |
263 | |
264 int x_stretch_cursor_p; | |
265 | |
266 /* This is a chain of structures for all the X displays currently in | |
267 use. */ | |
268 | |
136 struct x_display_info *x_display_list; | 269 struct x_display_info *x_display_list; |
137 | 270 |
138 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE), | 271 /* This is a list of cons cells, each of the form (NAME |
139 one for each element of x_display_list and in the same order. | 272 . FONT-LIST-CACHE), one for each element of x_display_list and in |
140 NAME is the name of the frame. | 273 the same order. NAME is the name of the frame. FONT-LIST-CACHE |
141 FONT-LIST-CACHE records previous values returned by x-list-fonts. */ | 274 records previous values returned by x-list-fonts. */ |
275 | |
142 Lisp_Object x_display_name_list; | 276 Lisp_Object x_display_name_list; |
143 | 277 |
144 /* Frame being updated by update_frame. This is declared in term.c. | 278 /* Frame being updated by update_frame. This is declared in term.c. |
145 This is set by update_begin and looked at by all the | 279 This is set by update_begin and looked at by all the XT functions. |
146 XT functions. It is zero while not inside an update. | 280 It is zero while not inside an update. In that case, the XT |
147 In that case, the XT functions assume that `selected_frame' | 281 functions assume that `selected_frame' is the frame to apply to. */ |
148 is the frame to apply to. */ | 282 |
149 extern struct frame *updating_frame; | 283 extern struct frame *updating_frame; |
150 | 284 |
151 extern int waiting_for_input; | 285 extern int waiting_for_input; |
152 | 286 |
153 /* This is a frame waiting to be autoraised, within XTread_socket. */ | 287 /* This is a frame waiting to be auto-raised, within XTread_socket. */ |
288 | |
154 struct frame *pending_autoraise_frame; | 289 struct frame *pending_autoraise_frame; |
155 | 290 |
156 #ifdef USE_X_TOOLKIT | 291 #ifdef USE_X_TOOLKIT |
157 /* The application context for Xt use. */ | 292 /* The application context for Xt use. */ |
158 XtAppContext Xt_app_con; | 293 XtAppContext Xt_app_con; |
159 | 294 static String Xt_default_resources[] = {0}; |
160 static String Xt_default_resources[] = | 295 #endif /* USE_X_TOOLKIT */ |
161 { | 296 |
162 0 | 297 /* Nominal cursor position -- where to draw output. |
163 }; | 298 HPOS and VPOS are window relative glyph matrix coordinates. |
164 #endif | 299 X and Y are window relative pixel coordinates. */ |
165 | 300 |
166 /* During an update, maximum vpos for ins/del line operations to affect. */ | 301 struct cursor_pos output_cursor; |
167 | 302 |
168 static int flexlines; | |
169 | |
170 /* During an update, nonzero if chars output now should be highlighted. */ | |
171 | |
172 static int highlight; | |
173 | |
174 /* Nominal cursor position -- where to draw output. | |
175 During an update, these are different from the cursor-box position. */ | |
176 | |
177 static int curs_x; | |
178 static int curs_y; | |
179 | 303 |
180 /* Mouse movement. | 304 /* Mouse movement. |
181 | 305 |
182 Formerly, we used PointerMotionHintMask (in STANDARD_EVENT_MASK) | 306 Formerly, we used PointerMotionHintMask (in standard_event_mask) |
183 so that we would have to call XQueryPointer after each MotionNotify | 307 so that we would have to call XQueryPointer after each MotionNotify |
184 event to ask for another such event. However, this made mouse tracking | 308 event to ask for another such event. However, this made mouse tracking |
185 slow, and there was a bug that made it eventually stop. | 309 slow, and there was a bug that made it eventually stop. |
186 | 310 |
187 Simply asking for MotionNotify all the time seems to work better. | 311 Simply asking for MotionNotify all the time seems to work better. |
196 is at least as efficient as getting motion events when mouse | 320 is at least as efficient as getting motion events when mouse |
197 tracking is on, and I suspect only negligibly worse when tracking | 321 tracking is on, and I suspect only negligibly worse when tracking |
198 is off. */ | 322 is off. */ |
199 | 323 |
200 /* Where the mouse was last time we reported a mouse event. */ | 324 /* Where the mouse was last time we reported a mouse event. */ |
201 static FRAME_PTR last_mouse_frame; | 325 |
326 FRAME_PTR last_mouse_frame; | |
202 static XRectangle last_mouse_glyph; | 327 static XRectangle last_mouse_glyph; |
203 | |
204 static Lisp_Object last_mouse_press_frame; | 328 static Lisp_Object last_mouse_press_frame; |
205 | 329 |
206 /* The scroll bar in which the last X motion event occurred. | 330 /* The scroll bar in which the last X motion event occurred. |
207 | 331 |
208 If the last X motion event occurred in a scroll bar, we set this | 332 If the last X motion event occurred in a scroll bar, we set this so |
209 so XTmouse_position can know whether to report a scroll bar motion or | 333 XTmouse_position can know whether to report a scroll bar motion or |
210 an ordinary motion. | 334 an ordinary motion. |
211 | 335 |
212 If the last X motion event didn't occur in a scroll bar, we set this | 336 If the last X motion event didn't occur in a scroll bar, we set |
213 to Qnil, to tell XTmouse_position to return an ordinary motion event. */ | 337 this to Qnil, to tell XTmouse_position to return an ordinary motion |
338 event. */ | |
339 | |
214 static Lisp_Object last_mouse_scroll_bar; | 340 static Lisp_Object last_mouse_scroll_bar; |
215 | 341 |
216 /* This is a hack. We would really prefer that XTmouse_position would | 342 /* This is a hack. We would really prefer that XTmouse_position would |
217 return the time associated with the position it returns, but there | 343 return the time associated with the position it returns, but there |
218 doesn't seem to be any way to wrest the timestamp from the server | 344 doesn't seem to be any way to wrest the time-stamp from the server |
219 along with the position query. So, we just keep track of the time | 345 along with the position query. So, we just keep track of the time |
220 of the last movement we received, and return that in hopes that | 346 of the last movement we received, and return that in hopes that |
221 it's somewhat accurate. */ | 347 it's somewhat accurate. */ |
348 | |
222 static Time last_mouse_movement_time; | 349 static Time last_mouse_movement_time; |
223 | 350 |
224 /* Incremented by XTread_socket whenever it really tries to read events. */ | 351 /* Incremented by XTread_socket whenever it really tries to read |
352 events. */ | |
353 | |
225 #ifdef __STDC__ | 354 #ifdef __STDC__ |
226 static int volatile input_signal_count; | 355 static int volatile input_signal_count; |
227 #else | 356 #else |
228 static int input_signal_count; | 357 static int input_signal_count; |
229 #endif | 358 #endif |
230 | 359 |
231 /* Used locally within XTread_socket. */ | 360 /* Used locally within XTread_socket. */ |
361 | |
232 static int x_noop_count; | 362 static int x_noop_count; |
233 | 363 |
234 /* Initial values of argv and argc. */ | 364 /* Initial values of argv and argc. */ |
365 | |
235 extern char **initial_argv; | 366 extern char **initial_argv; |
236 extern int initial_argc; | 367 extern int initial_argc; |
237 | 368 |
238 extern Lisp_Object Vcommand_line_args, Vsystem_name; | 369 extern Lisp_Object Vcommand_line_args, Vsystem_name; |
239 | 370 |
240 /* Tells if a window manager is present or not. */ | 371 /* Tells if a window manager is present or not. */ |
241 | 372 |
242 extern Lisp_Object Vx_no_window_manager; | 373 extern Lisp_Object Vx_no_window_manager; |
243 | 374 |
244 extern Lisp_Object Qface, Qmouse_face; | 375 extern Lisp_Object Qface, Qmouse_face; |
245 | 376 |
246 extern int errno; | 377 extern int errno; |
247 | 378 |
248 /* A mask of extra modifier bits to put into every keyboard char. */ | 379 /* A mask of extra modifier bits to put into every keyboard char. */ |
380 | |
249 extern int extra_keyboard_modifiers; | 381 extern int extra_keyboard_modifiers; |
250 | 382 |
251 static Lisp_Object Qvendor_specific_keysyms; | 383 static Lisp_Object Qvendor_specific_keysyms; |
252 | 384 |
253 extern XrmDatabase x_load_resources (); | 385 extern XrmDatabase x_load_resources (); |
254 | |
255 extern Lisp_Object x_icon_type (); | 386 extern Lisp_Object x_icon_type (); |
256 | 387 |
257 void x_delete_display (); | 388 |
258 | 389 /* Enumeration for overriding/changing the face to use for drawing |
259 static void redraw_previous_char (); | 390 glyphs in x_draw_glyphs. */ |
260 static void redraw_following_char (); | 391 |
261 static unsigned int x_x_to_emacs_modifiers (); | 392 enum draw_glyphs_face |
262 | 393 { |
263 static int fast_find_position (); | 394 DRAW_NORMAL_TEXT, |
264 static void note_mouse_highlight (); | 395 DRAW_INVERSE_VIDEO, |
265 static void clear_mouse_face (); | 396 DRAW_CURSOR, |
266 static void show_mouse_face (); | 397 DRAW_MOUSE_FACE, |
267 static void do_line_dance (); | 398 DRAW_IMAGE_RAISED, |
268 | 399 DRAW_IMAGE_SUNKEN |
269 static void XTcursor_to (); | 400 }; |
270 static void XTclear_end_of_line (); | 401 |
271 static int x_io_error_quitter (); | 402 static void x_update_window_end P_ ((struct window *, int)); |
272 int x_catch_errors (); | 403 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *)); |
273 void x_uncatch_errors (); | 404 void x_delete_display P_ ((struct x_display_info *)); |
405 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *, | |
406 unsigned)); | |
407 static int fast_find_position P_ ((struct window *, int, int *, int *, | |
408 int *, int *)); | |
409 static void set_output_cursor P_ ((struct cursor_pos *)); | |
410 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int, | |
411 int *, int *, int *)); | |
412 static void note_mode_line_highlight P_ ((struct window *, int, int)); | |
413 static void x_check_font P_ ((struct frame *, XFontStruct *)); | |
414 static void note_mouse_highlight P_ ((struct frame *, int, int)); | |
415 static void note_toolbar_highlight P_ ((struct frame *f, int, int)); | |
416 static void x_handle_toolbar_click P_ ((struct frame *, XButtonEvent *)); | |
417 static void show_mouse_face P_ ((struct x_display_info *, | |
418 enum draw_glyphs_face)); | |
419 static int x_io_error_quitter P_ ((Display *)); | |
420 int x_catch_errors P_ ((Display *)); | |
421 void x_uncatch_errors P_ ((Display *, int)); | |
422 void x_lower_frame P_ ((struct frame *)); | |
423 void x_scroll_bar_clear P_ ((struct frame *)); | |
424 int x_had_errors_p P_ ((Display *)); | |
425 void x_wm_set_size_hint P_ ((struct frame *, long, int)); | |
426 void x_raise_frame P_ ((struct frame *)); | |
427 void x_set_window_size P_ ((struct frame *, int, int, int)); | |
428 void x_wm_set_window_state P_ ((struct frame *, int)); | |
429 void x_wm_set_icon_pixmap P_ ((struct frame *, int)); | |
430 void x_initialize P_ ((void)); | |
431 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *)); | |
432 static int x_compute_min_glyph_bounds P_ ((struct frame *)); | |
433 static void x_draw_phys_cursor_glyph P_ ((struct window *, | |
434 struct glyph_row *, | |
435 enum draw_glyphs_face)); | |
436 static void x_update_end P_ ((struct frame *)); | |
437 static void XTframe_up_to_date P_ ((struct frame *)); | |
438 static void XTreassert_line_highlight P_ ((int, int)); | |
439 static void x_change_line_highlight P_ ((int, int, int, int)); | |
440 static void XTset_terminal_modes P_ ((void)); | |
441 static void XTreset_terminal_modes P_ ((void)); | |
442 static void XTcursor_to P_ ((int, int, int, int)); | |
443 static void x_write_glyphs P_ ((struct glyph *, int)); | |
444 static void x_clear_end_of_line P_ ((int)); | |
445 static void x_clear_frame P_ ((void)); | |
446 static void x_clear_cursor P_ ((struct window *)); | |
447 static void frame_highlight P_ ((struct frame *)); | |
448 static void frame_unhighlight P_ ((struct frame *)); | |
449 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *)); | |
450 static void XTframe_rehighlight P_ ((struct frame *)); | |
451 static void x_frame_rehighlight P_ ((struct x_display_info *)); | |
452 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); | |
453 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *)); | |
454 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *, | |
455 XRectangle *)); | |
456 static void expose_frame P_ ((struct frame *, int, int, int, int)); | |
457 static void expose_window_tree P_ ((struct window *, XRectangle *)); | |
458 static void expose_window P_ ((struct window *, XRectangle *)); | |
459 static void expose_area P_ ((struct window *, struct glyph_row *, | |
460 XRectangle *, enum glyph_row_area)); | |
461 static void expose_line P_ ((struct window *, struct glyph_row *, | |
462 XRectangle *)); | |
463 static void x_update_cursor_in_window_tree P_ ((struct window *, int)); | |
464 static void x_update_window_cursor P_ ((struct window *, int)); | |
465 static void x_erase_phys_cursor P_ ((struct window *)); | |
466 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int)); | |
467 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *, | |
468 enum bitmap_type)); | |
469 | |
470 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, | |
471 GC, int)); | |
472 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *)); | |
473 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *)); | |
474 static void note_overwritten_text_cursor P_ ((struct window *, int, int)); | |
475 static void x_flush P_ ((struct frame *f)); | |
476 | |
477 | |
478 /* Flush display of frame F, or of all frames if F is null. */ | |
479 | |
480 static void | |
481 x_flush (f) | |
482 struct frame *f; | |
483 { | |
484 BLOCK_INPUT; | |
485 if (f == NULL) | |
486 { | |
487 Lisp_Object rest, frame; | |
488 FOR_EACH_FRAME (rest, frame) | |
489 x_flush (XFRAME (frame)); | |
490 } | |
491 else if (FRAME_X_P (f)) | |
492 XFlush (FRAME_X_DISPLAY (f)); | |
493 UNBLOCK_INPUT; | |
494 } | |
495 | |
496 | |
497 /* Remove calls to XFlush by defining XFlush to an empty replacement. | |
498 Calls to XFlush should be unnecessary because the X output buffer | |
499 is flushed automatically as needed by calls to XPending, | |
500 XNextEvent, or XWindowEvent according to the XFlush man page. | |
501 XTread_socket calls XPending. Removing XFlush improves | |
502 performance. */ | |
503 | |
504 #define XFlush(DISPLAY) (void) 0 | |
505 | |
274 | 506 |
507 /*********************************************************************** | |
508 Debugging | |
509 ***********************************************************************/ | |
510 | |
275 #if 0 | 511 #if 0 |
276 /* This is a function useful for recording debugging information | 512 |
277 about the sequence of occurrences in this file. */ | 513 /* This is a function useful for recording debugging information about |
514 the sequence of occurrences in this file. */ | |
278 | 515 |
279 struct record | 516 struct record |
280 { | 517 { |
281 char *locus; | 518 char *locus; |
282 int type; | 519 int type; |
297 event_record[event_record_index].type = type; | 534 event_record[event_record_index].type = type; |
298 event_record_index++; | 535 event_record_index++; |
299 } | 536 } |
300 | 537 |
301 #endif /* 0 */ | 538 #endif /* 0 */ |
539 | |
540 | |
302 | 541 |
303 /* Return the struct x_display_info corresponding to DPY. */ | 542 /* Return the struct x_display_info corresponding to DPY. */ |
304 | 543 |
305 struct x_display_info * | 544 struct x_display_info * |
306 x_display_info_for_display (dpy) | 545 x_display_info_for_display (dpy) |
312 if (dpyinfo->display == dpy) | 551 if (dpyinfo->display == dpy) |
313 return dpyinfo; | 552 return dpyinfo; |
314 | 553 |
315 return 0; | 554 return 0; |
316 } | 555 } |
556 | |
557 | |
317 | 558 |
318 /* Starting and ending updates. | 559 /*********************************************************************** |
319 | 560 Starting and ending an update |
320 These hooks are called by update_frame at the beginning and end | 561 ***********************************************************************/ |
321 of a frame update. We record in `updating_frame' the identity | 562 |
322 of the frame being updated, so that the XT... functions do not | 563 /* Start an update of frame F. This function is installed as a hook |
323 need to take a frame as argument. Most of the XT... functions | 564 for update_begin, i.e. it is called when update_begin is called. |
324 should never be called except during an update, the only exceptions | 565 This function is called prior to calls to x_update_window_begin for |
325 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */ | 566 each window being updated. Currently, there is nothing to do here |
567 because all interesting stuff is done on a window basis. */ | |
326 | 568 |
327 static void | 569 static void |
328 XTupdate_begin (f) | 570 x_update_begin (f) |
329 struct frame *f; | 571 struct frame *f; |
330 { | 572 { |
331 int mask; | 573 /* Nothing to do. */ |
332 | 574 } |
333 if (f == 0) | 575 |
334 abort (); | 576 |
335 | 577 /* Start update of window W. Set the global variable updated_window |
336 flexlines = f->height; | 578 to the window being updated and set output_cursor to the cursor |
337 highlight = 0; | 579 position of W. */ |
580 | |
581 static void | |
582 x_update_window_begin (w) | |
583 struct window *w; | |
584 { | |
585 struct frame *f = XFRAME (WINDOW_FRAME (w)); | |
586 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f); | |
587 | |
588 updated_window = w; | |
589 set_output_cursor (&w->cursor); | |
338 | 590 |
339 BLOCK_INPUT; | 591 BLOCK_INPUT; |
340 | 592 |
341 curs_x = FRAME_CURSOR_X (f); | 593 if (f == display_info->mouse_face_mouse_frame) |
342 curs_y = FRAME_CURSOR_Y (f); | |
343 | |
344 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame) | |
345 { | 594 { |
346 /* Don't do highlighting for mouse motion during the update. */ | 595 /* Don't do highlighting for mouse motion during the update. */ |
347 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 1; | 596 display_info->mouse_face_defer = 1; |
348 | 597 |
349 /* If the frame needs to be redrawn, | 598 /* If F needs to be redrawn, simply forget about any prior mouse |
350 simply forget about any prior mouse highlighting. */ | 599 highlighting. */ |
351 if (FRAME_GARBAGED_P (f)) | 600 if (FRAME_GARBAGED_P (f)) |
352 FRAME_X_DISPLAY_INFO (f)->mouse_face_window = Qnil; | 601 display_info->mouse_face_window = Qnil; |
353 | 602 |
354 if (!NILP (FRAME_X_DISPLAY_INFO (f)->mouse_face_window)) | 603 /* Can we tell that this update does not affect the window |
604 where the mouse highlight is? If so, no need to turn off. | |
605 Likewise, don't do anything if the frame is garbaged; | |
606 in that case, the frame's current matrix that we would use | |
607 is all wrong, and we will redisplay that line anyway. */ | |
608 if (!NILP (display_info->mouse_face_window) | |
609 && w == XWINDOW (display_info->mouse_face_window)) | |
355 { | 610 { |
356 int firstline, lastline, i; | 611 int i; |
357 struct window *w = XWINDOW (FRAME_X_DISPLAY_INFO (f)->mouse_face_window); | 612 |
358 | 613 for (i = 0; i < w->desired_matrix->nrows; ++i) |
359 /* Find the first, and the last+1, lines affected by redisplay. */ | 614 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)) |
360 for (firstline = 0; firstline < f->height; firstline++) | |
361 if (FRAME_DESIRED_GLYPHS (f)->enable[firstline]) | |
362 break; | 615 break; |
363 | 616 |
364 lastline = f->height; | 617 if (i < w->desired_matrix->nrows) |
365 for (i = f->height - 1; i >= 0; i--) | 618 clear_mouse_face (display_info); |
366 { | |
367 if (FRAME_DESIRED_GLYPHS (f)->enable[i]) | |
368 break; | |
369 else | |
370 lastline = i; | |
371 } | |
372 | |
373 /* Can we tell that this update does not affect the window | |
374 where the mouse highlight is? If so, no need to turn off. | |
375 Likewise, don't do anything if the frame is garbaged; | |
376 in that case, the FRAME_CURRENT_GLYPHS that we would use | |
377 are all wrong, and we will redisplay that line anyway. */ | |
378 if (! (firstline > (XFASTINT (w->top) + window_internal_height (w)) | |
379 || lastline < XFASTINT (w->top))) | |
380 clear_mouse_face (FRAME_X_DISPLAY_INFO (f)); | |
381 } | 619 } |
382 } | 620 } |
383 | 621 |
384 UNBLOCK_INPUT; | 622 UNBLOCK_INPUT; |
385 } | 623 } |
386 | 624 |
625 | |
626 /* Draw a vertical window border to the right of window W if W doesn't | |
627 have vertical scroll bars. */ | |
628 | |
387 static void | 629 static void |
388 XTupdate_end (f) | 630 x_draw_vertical_border (w) |
631 struct window *w; | |
632 { | |
633 struct frame *f = XFRAME (WINDOW_FRAME (w)); | |
634 | |
635 /* Redraw borders between horizontally adjacent windows. Don't | |
636 do it for frames with vertical scroll bars because either the | |
637 right scroll bar of a window, or the left scroll bar of its | |
638 neighbor will suffice as a border. */ | |
639 if (!WINDOW_RIGHTMOST_P (w) | |
640 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)) | |
641 { | |
642 int x0, x1, y0, y1; | |
643 | |
644 window_box_edges (w, -1, &x0, &y0, &x1, &y1); | |
645 x1 += FRAME_X_FLAGS_AREA_WIDTH (f); | |
646 y1 -= 1; | |
647 | |
648 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
649 f->output_data.x->normal_gc, x1, y0, x1, y1); | |
650 } | |
651 } | |
652 | |
653 | |
654 /* End update of window W (which is equal to updated_window). Draw | |
655 vertical borders between horizontally adjacent windows, and display | |
656 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar | |
657 pseudo-window in case we don't have X toolkit support. Such | |
658 windows don't have a cursor, so don't display it here. */ | |
659 | |
660 static void | |
661 x_update_window_end (w, cursor_on_p) | |
662 struct window *w; | |
663 int cursor_on_p; | |
664 { | |
665 if (!w->pseudo_window_p) | |
666 { | |
667 BLOCK_INPUT; | |
668 if (cursor_on_p) | |
669 x_display_and_set_cursor (w, 1, output_cursor.hpos, | |
670 output_cursor.vpos, | |
671 output_cursor.x, output_cursor.y); | |
672 x_draw_vertical_border (w); | |
673 UNBLOCK_INPUT; | |
674 } | |
675 | |
676 updated_window = NULL; | |
677 } | |
678 | |
679 | |
680 /* End update of frame F. This function is installed as a hook in | |
681 update_end. */ | |
682 | |
683 static void | |
684 x_update_end (f) | |
389 struct frame *f; | 685 struct frame *f; |
390 { | 686 { |
391 int mask; | 687 /* Mouse highlight may be displayed again. */ |
688 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0; | |
392 | 689 |
393 BLOCK_INPUT; | 690 BLOCK_INPUT; |
394 | |
395 do_line_dance (); | |
396 x_display_cursor (f, 1, curs_x, curs_y); | |
397 | |
398 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0; | |
399 #if 0 | |
400 /* This fails in the case of having updated only the echo area | |
401 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS | |
402 has no relation to the current contents, and its charstarts | |
403 have no relation to the contents of the window-buffer. | |
404 I don't know a clean way to check | |
405 for that case. window_end_valid isn't set up yet. */ | |
406 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame) | |
407 note_mouse_highlight (f, FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x, | |
408 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y); | |
409 #endif | |
410 | |
411 XFlush (FRAME_X_DISPLAY (f)); | 691 XFlush (FRAME_X_DISPLAY (f)); |
412 UNBLOCK_INPUT; | 692 UNBLOCK_INPUT; |
413 } | 693 } |
414 | 694 |
415 /* This is called after a redisplay on frame F. */ | 695 |
696 /* This function is called from various places in xdisp.c whenever a | |
697 complete update has been performed. The global variable | |
698 updated_window is not available here. */ | |
416 | 699 |
417 static void | 700 static void |
418 XTframe_up_to_date (f) | 701 XTframe_up_to_date (f) |
419 FRAME_PTR f; | 702 struct frame *f; |
420 { | 703 { |
421 BLOCK_INPUT; | 704 if (FRAME_X_P (f)) |
422 if (FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc | 705 { |
423 || f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame) | 706 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
424 { | 707 if (dpyinfo->mouse_face_deferred_gc |
425 if (FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame) | 708 || f == dpyinfo->mouse_face_mouse_frame) |
426 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame, | 709 { |
427 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x, | 710 BLOCK_INPUT; |
428 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y); | 711 if (dpyinfo->mouse_face_mouse_frame) |
429 FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0; | 712 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame, |
430 } | 713 dpyinfo->mouse_face_mouse_x, |
431 UNBLOCK_INPUT; | 714 dpyinfo->mouse_face_mouse_y); |
432 } | 715 dpyinfo->mouse_face_deferred_gc = 0; |
716 UNBLOCK_INPUT; | |
717 } | |
718 } | |
719 } | |
720 | |
721 | |
722 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay | |
723 arrow bitmaps, or clear the areas where they would be displayed | |
724 before DESIRED_ROW is made current. The window being updated is | |
725 found in updated_window. This function It is called from | |
726 update_window_line only if it is known that there are differences | |
727 between bitmaps to be drawn between current row and DESIRED_ROW. */ | |
728 | |
729 static void | |
730 x_after_update_window_line (desired_row) | |
731 struct glyph_row *desired_row; | |
732 { | |
733 struct window *w = updated_window; | |
734 | |
735 xassert (w); | |
736 | |
737 if (!desired_row->mode_line_p && !w->pseudo_window_p) | |
738 { | |
739 BLOCK_INPUT; | |
740 x_draw_row_bitmaps (w, desired_row); | |
741 | |
742 /* When a window has disappeared, make sure that no rest of | |
743 full-width rows stays visible in the internal border. */ | |
744 if (windows_or_buffers_changed) | |
745 { | |
746 struct frame *f = XFRAME (w->frame); | |
747 int width = FRAME_INTERNAL_BORDER_WIDTH (f); | |
748 int height = desired_row->visible_height; | |
749 int x = window_box_right (w, -1) + FRAME_X_FLAGS_AREA_WIDTH (f); | |
750 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y)); | |
751 | |
752 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
753 x, y, width, height, False); | |
754 } | |
755 | |
756 UNBLOCK_INPUT; | |
757 } | |
758 } | |
759 | |
760 | |
761 /* Draw the bitmap WHICH in one of the areas to the left or right of | |
762 window W. ROW is the glyph row for which to display the bitmap; it | |
763 determines the vertical position at which the bitmap has to be | |
764 drawn. */ | |
765 | |
766 static void | |
767 x_draw_bitmap (w, row, which) | |
768 struct window *w; | |
769 struct glyph_row *row; | |
770 enum bitmap_type which; | |
771 { | |
772 struct frame *f = XFRAME (WINDOW_FRAME (w)); | |
773 Display *display = FRAME_X_DISPLAY (f); | |
774 Window window = FRAME_X_WINDOW (f); | |
775 int x, y, wd, h, dy; | |
776 unsigned char *bits; | |
777 Pixmap pixmap; | |
778 GC gc = f->output_data.x->normal_gc; | |
779 struct face *face; | |
780 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f)); | |
781 | |
782 /* Must clip because of partially visible lines. */ | |
783 x_clip_to_row (w, row, gc, 1); | |
784 | |
785 switch (which) | |
786 { | |
787 case LEFT_TRUNCATION_BITMAP: | |
788 wd = left_width; | |
789 h = left_height; | |
790 bits = left_bits; | |
791 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0) | |
792 - wd | |
793 - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2); | |
794 break; | |
795 | |
796 case OVERLAY_ARROW_BITMAP: | |
797 wd = left_width; | |
798 h = left_height; | |
799 bits = ov_bits; | |
800 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0) | |
801 - wd | |
802 - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2); | |
803 break; | |
804 | |
805 case RIGHT_TRUNCATION_BITMAP: | |
806 wd = right_width; | |
807 h = right_height; | |
808 bits = right_bits; | |
809 x = window_box_right (w, -1); | |
810 x += (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2; | |
811 break; | |
812 | |
813 case CONTINUED_LINE_BITMAP: | |
814 wd = right_width; | |
815 h = right_height; | |
816 bits = continued_bits; | |
817 x = window_box_right (w, -1); | |
818 x += (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2; | |
819 break; | |
820 | |
821 case CONTINUATION_LINE_BITMAP: | |
822 wd = continuation_width; | |
823 h = continuation_height; | |
824 bits = continuation_bits; | |
825 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0) | |
826 - wd | |
827 - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2); | |
828 break; | |
829 | |
830 case ZV_LINE_BITMAP: | |
831 wd = zv_width; | |
832 h = zv_height; | |
833 bits = zv_bits; | |
834 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0) | |
835 - wd | |
836 - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2); | |
837 break; | |
838 | |
839 default: | |
840 abort (); | |
841 } | |
842 | |
843 /* Convert to frame coordinates. Set dy to the offset in the row to | |
844 start drawing the bitmap. */ | |
845 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); | |
846 dy = (row->height - h) / 2; | |
847 | |
848 /* Draw the bitmap. I believe these small pixmaps can be cached | |
849 by the server. */ | |
850 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID); | |
851 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h, | |
852 face->foreground, | |
853 face->background, depth); | |
854 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy); | |
855 XFreePixmap (display, pixmap); | |
856 XSetClipMask (display, gc, None); | |
857 } | |
858 | |
859 | |
860 /* Draw flags bitmaps for glyph row ROW on window W. Call this | |
861 function with input blocked. */ | |
862 | |
863 static void | |
864 x_draw_row_bitmaps (w, row) | |
865 struct window *w; | |
866 struct glyph_row *row; | |
867 { | |
868 struct frame *f = XFRAME (w->frame); | |
869 enum bitmap_type bitmap; | |
870 struct face *face; | |
871 int top_line_height = -1; | |
872 | |
873 xassert (interrupt_input_blocked); | |
874 | |
875 /* If row is completely invisible, because of vscrolling, we | |
876 don't have to draw anything. */ | |
877 if (row->visible_height <= 0) | |
878 return; | |
879 | |
880 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID); | |
881 PREPARE_FACE_FOR_DISPLAY (f, face); | |
882 | |
883 /* Decide which bitmap to draw at the left side. */ | |
884 if (row->overlay_arrow_p) | |
885 bitmap = OVERLAY_ARROW_BITMAP; | |
886 else if (row->truncated_on_left_p) | |
887 bitmap = LEFT_TRUNCATION_BITMAP; | |
888 else if (MATRIX_ROW_CONTINUATION_LINE_P (row)) | |
889 bitmap = CONTINUATION_LINE_BITMAP; | |
890 else if (row->indicate_empty_line_p) | |
891 bitmap = ZV_LINE_BITMAP; | |
892 else | |
893 bitmap = NO_BITMAP; | |
894 | |
895 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill | |
896 the flags area. */ | |
897 if (bitmap == NO_BITMAP | |
898 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_FLAGS_AREA_WIDTH (f) | |
899 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f)) | |
900 { | |
901 /* If W has a vertical border to its left, don't draw over it. */ | |
902 int border = ((XFASTINT (w->left) > 0 | |
903 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)) | |
904 ? 1 : 0); | |
905 int left = window_box_left (w, -1); | |
906 | |
907 if (top_line_height < 0) | |
908 top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w); | |
909 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background); | |
910 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
911 face->gc, | |
912 (left | |
913 - FRAME_X_FLAGS_AREA_WIDTH (f) | |
914 + border), | |
915 WINDOW_TO_FRAME_PIXEL_Y (w, max (top_line_height, | |
916 row->y)), | |
917 FRAME_X_FLAGS_AREA_WIDTH (f) - border, | |
918 row->visible_height); | |
919 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground); | |
920 } | |
921 | |
922 /* Draw the left bitmap. */ | |
923 if (bitmap != NO_BITMAP) | |
924 x_draw_bitmap (w, row, bitmap); | |
925 | |
926 /* Decide which bitmap to draw at the right side. */ | |
927 if (row->truncated_on_right_p) | |
928 bitmap = RIGHT_TRUNCATION_BITMAP; | |
929 else if (row->continued_p) | |
930 bitmap = CONTINUED_LINE_BITMAP; | |
931 else | |
932 bitmap = NO_BITMAP; | |
933 | |
934 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill | |
935 the flags area. */ | |
936 if (bitmap == NO_BITMAP | |
937 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_FLAGS_AREA_WIDTH (f) | |
938 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f)) | |
939 { | |
940 int right = window_box_right (w, -1); | |
941 | |
942 if (top_line_height < 0) | |
943 top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w); | |
944 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background); | |
945 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
946 face->gc, | |
947 right, | |
948 WINDOW_TO_FRAME_PIXEL_Y (w, max (top_line_height, | |
949 row->y)), | |
950 FRAME_X_FLAGS_AREA_WIDTH (f), | |
951 row->visible_height); | |
952 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground); | |
953 } | |
954 | |
955 /* Draw the right bitmap. */ | |
956 if (bitmap != NO_BITMAP) | |
957 x_draw_bitmap (w, row, bitmap); | |
958 } | |
959 | |
433 | 960 |
434 /* External interface to control of standout mode. | 961 /*********************************************************************** |
435 Call this when about to modify line at position VPOS | 962 Line Highlighting |
436 and not change whether it is highlighted. */ | 963 ***********************************************************************/ |
437 | 964 |
438 void | 965 /* External interface to control of standout mode. Not used for X |
966 frames. Aborts when called. */ | |
967 | |
968 static void | |
439 XTreassert_line_highlight (new, vpos) | 969 XTreassert_line_highlight (new, vpos) |
440 int new, vpos; | 970 int new, vpos; |
441 { | 971 { |
442 highlight = new; | 972 abort (); |
443 } | 973 } |
444 | 974 |
445 /* Call this when about to modify line at position VPOS | 975 |
446 and change whether it is highlighted. */ | 976 /* Call this when about to modify line at position VPOS and change |
977 whether it is highlighted. Not used for X frames. Aborts when | |
978 called. */ | |
447 | 979 |
448 static void | 980 static void |
449 XTchange_line_highlight (new_highlight, vpos, first_unused_hpos) | 981 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos) |
450 int new_highlight, vpos, first_unused_hpos; | 982 int new_highlight, vpos, y, first_unused_hpos; |
451 { | 983 { |
452 highlight = new_highlight; | 984 abort (); |
453 XTcursor_to (vpos, 0); | 985 } |
454 XTclear_end_of_line (FRAME_WINDOW_WIDTH (updating_frame)); | 986 |
455 } | 987 |
456 | 988 /* This is called when starting Emacs and when restarting after |
457 /* This is used when starting Emacs and when restarting after suspend. | 989 suspend. When starting Emacs, no X window is mapped. And nothing |
458 When starting Emacs, no X window is mapped. And nothing must be done | 990 must be done to Emacs's own window if it is suspended (though that |
459 to Emacs's own window if it is suspended (though that rarely happens). */ | 991 rarely happens). */ |
460 | 992 |
461 static void | 993 static void |
462 XTset_terminal_modes () | 994 XTset_terminal_modes () |
463 { | 995 { |
464 } | 996 } |
465 | 997 |
466 /* This is called when exiting or suspending Emacs. | 998 /* This is called when exiting or suspending Emacs. Exiting will make |
467 Exiting will make the X-windows go away, and suspending | 999 the X-windows go away, and suspending requires no action. */ |
468 requires no action. */ | |
469 | 1000 |
470 static void | 1001 static void |
471 XTreset_terminal_modes () | 1002 XTreset_terminal_modes () |
472 { | 1003 { |
473 /* XTclear_frame (); */ | 1004 } |
474 } | 1005 |
1006 | |
475 | 1007 |
476 /* Set the nominal cursor position of the frame. | 1008 /*********************************************************************** |
477 This is where display update commands will take effect. | 1009 Output Cursor |
478 This does not affect the place where the cursor-box is displayed. */ | 1010 ***********************************************************************/ |
1011 | |
1012 /* Set the global variable output_cursor to CURSOR. All cursor | |
1013 positions are relative to updated_window. */ | |
479 | 1014 |
480 static void | 1015 static void |
481 XTcursor_to (row, col) | 1016 set_output_cursor (cursor) |
482 register int row, col; | 1017 struct cursor_pos *cursor; |
483 { | 1018 { |
484 int mask; | 1019 output_cursor.hpos = cursor->hpos; |
485 int orow = row; | 1020 output_cursor.vpos = cursor->vpos; |
486 struct frame *f; | 1021 output_cursor.x = cursor->x; |
487 | 1022 output_cursor.y = cursor->y; |
488 f = updating_frame; | 1023 } |
489 if (f == 0) | 1024 |
490 f = selected_frame; | 1025 |
491 | 1026 /* Set a nominal cursor position. |
492 curs_x = col; | 1027 |
493 if (curs_x >= FRAME_CURSOR_X_LIMIT (f)) | 1028 HPOS and VPOS are column/row positions in a window glyph matrix. X |
494 curs_x = FRAME_CURSOR_X_LIMIT (f) - 1; | 1029 and Y are window text area relative pixel positions. |
495 | 1030 |
496 curs_y = row; | 1031 If this is done during an update, updated_window will contain the |
497 | 1032 window that is being updated and the position is the future output |
498 if (updating_frame == 0) | 1033 cursor position for that window. If updated_window is null, use |
1034 selected_window and display the cursor at the given position. */ | |
1035 | |
1036 static void | |
1037 XTcursor_to (vpos, hpos, y, x) | |
1038 int vpos, hpos, y, x; | |
1039 { | |
1040 struct window *w; | |
1041 | |
1042 /* If updated_window is not set, work on selected_window. */ | |
1043 if (updated_window) | |
1044 w = updated_window; | |
1045 else | |
1046 w = XWINDOW (selected_window); | |
1047 | |
1048 /* Set the output cursor. */ | |
1049 output_cursor.hpos = hpos; | |
1050 output_cursor.vpos = vpos; | |
1051 output_cursor.x = x; | |
1052 output_cursor.y = y; | |
1053 | |
1054 /* If not called as part of an update, really display the cursor. | |
1055 This will also set the cursor position of W. */ | |
1056 if (updated_window == NULL) | |
499 { | 1057 { |
500 BLOCK_INPUT; | 1058 BLOCK_INPUT; |
501 x_display_cursor (selected_frame, 1, curs_x, curs_y); | 1059 x_display_cursor (w, 1, hpos, vpos, x, y); |
502 XFlush (FRAME_X_DISPLAY (selected_frame)); | 1060 XFlush (FRAME_X_DISPLAY (selected_frame)); |
503 UNBLOCK_INPUT; | 1061 UNBLOCK_INPUT; |
504 } | 1062 } |
505 } | 1063 } |
1064 | |
1065 | |
506 | 1066 |
507 | 1067 /*********************************************************************** |
508 /* Return a pointer to per char metric information in FONT of a | 1068 Display Iterator |
509 character pointed by B (*XChar2b). */ | 1069 ***********************************************************************/ |
1070 | |
1071 /* Function prototypes of this page. */ | |
1072 | |
1073 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *, | |
1074 struct glyph *, | |
1075 XChar2b *)); | |
1076 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int, | |
1077 int, XChar2b *, int)); | |
1078 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *)); | |
1079 static void x_encode_char P_ ((int, XChar2b *, struct font_info *)); | |
1080 static void x_append_glyph P_ ((struct it *)); | |
1081 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object, | |
1082 int, int, double)); | |
1083 static void x_produce_glyphs P_ ((struct it *)); | |
1084 static void x_produce_special_glyphs P_ ((struct it *, enum display_element_type)); | |
1085 static void x_produce_image_glyph P_ ((struct it *it)); | |
1086 | |
1087 | |
1088 /* Return a pointer to per-char metric information in FONT of a | |
1089 character pointed by B which is a pointer to an XChar2b. */ | |
510 | 1090 |
511 #define PER_CHAR_METRIC(font, b) \ | 1091 #define PER_CHAR_METRIC(font, b) \ |
512 ((font)->per_char \ | 1092 ((font)->per_char \ |
513 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \ | 1093 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \ |
514 + (((font)->min_byte1 || (font)->max_byte1) \ | 1094 + (((font)->min_byte1 || (font)->max_byte1) \ |
515 ? (((b)->byte1 - (font)->min_byte1) \ | 1095 ? (((b)->byte1 - (font)->min_byte1) \ |
516 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \ | 1096 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \ |
517 : 0)) \ | 1097 : 0)) \ |
518 : &((font)->max_bounds)) | 1098 : &((font)->max_bounds)) |
519 | 1099 |
520 /* Display a sequence of N glyphs found at GP. | 1100 |
521 WINDOW is the x-window to output to. LEFT and TOP are starting coords. | 1101 /* Get metrics of character CHAR2B in FONT. Value is always non-null. |
522 HL is 1 if this text is highlighted, 2 if the cursor is on it, | 1102 If CHAR2B is not contained in FONT, the font's default character |
523 3 if should appear in its mouse-face. | 1103 metric is returned. */ |
524 JUST_FOREGROUND if 1 means draw only the foreground; | 1104 |
525 don't alter the background. | 1105 static INLINE XCharStruct * |
526 | 1106 x_per_char_metric (font, char2b) |
527 CMPCHARP if non NULL is a pointer to the struct cmpchar_info, which | 1107 XFontStruct *font; |
528 means drawing glyphs on the same column. This is set to non NULL | 1108 XChar2b *char2b; |
529 only when recursively called within dumpglyphs to draw a composite | 1109 { |
530 character specified by CMPCHAR. | 1110 /* The result metric information. */ |
531 | 1111 XCharStruct *pcm = NULL; |
532 FONT is the default font to use (for glyphs whose font-code is 0). | 1112 |
533 | 1113 xassert (font && char2b); |
534 Since the display generation code is responsible for calling | 1114 |
535 compute_char_face and compute_glyph_face on everything it puts in | 1115 if (font->per_char != NULL) |
536 the display structure, we can assume that the face code on each | 1116 { |
537 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one | 1117 if (font->min_byte1 == 0 && font->max_byte1 == 0) |
538 to which we can actually apply intern_face. | 1118 { |
539 Call this function with input blocked. | 1119 /* min_char_or_byte2 specifies the linear character index |
540 | 1120 corresponding to the first element of the per_char array, |
541 Return overall pixel width of the drawn glyphs. */ | 1121 max_char_or_byte2 is the index of the last character. A |
542 | 1122 character with non-zero CHAR2B->byte1 is not in the font. |
543 #if 1 | 1123 A character with byte2 less than min_char_or_byte2 or |
544 /* This is the multi-face code. */ | 1124 greater max_char_or_byte2 is not in the font. */ |
1125 if (char2b->byte1 == 0 | |
1126 && char2b->byte2 >= font->min_char_or_byte2 | |
1127 && char2b->byte2 <= font->max_char_or_byte2) | |
1128 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2; | |
1129 } | |
1130 else | |
1131 { | |
1132 /* If either min_byte1 or max_byte1 are nonzero, both | |
1133 min_char_or_byte2 and max_char_or_byte2 are less than | |
1134 256, and the 2-byte character index values corresponding | |
1135 to the per_char array element N (counting from 0) are: | |
1136 | |
1137 byte1 = N/D + min_byte1 | |
1138 byte2 = N\D + min_char_or_byte2 | |
1139 | |
1140 where: | |
1141 | |
1142 D = max_char_or_byte2 - min_char_or_byte2 + 1 | |
1143 / = integer division | |
1144 \ = integer modulus */ | |
1145 if (char2b->byte1 >= font->min_byte1 | |
1146 && char2b->byte1 <= font->max_byte1 | |
1147 && char2b->byte2 >= font->min_char_or_byte2 | |
1148 && char2b->byte2 <= font->max_char_or_byte2) | |
1149 { | |
1150 pcm = (font->per_char | |
1151 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1) | |
1152 * (char2b->byte1 - font->min_byte1)) | |
1153 + (char2b->byte2 - font->min_char_or_byte2)); | |
1154 } | |
1155 } | |
1156 } | |
1157 else | |
1158 { | |
1159 /* If the per_char pointer is null, all glyphs between the first | |
1160 and last character indexes inclusive have the same | |
1161 information, as given by both min_bounds and max_bounds. */ | |
1162 if (char2b->byte2 >= font->min_char_or_byte2 | |
1163 && char2b->byte2 <= font->max_char_or_byte2) | |
1164 pcm = &font->max_bounds; | |
1165 } | |
1166 | |
1167 | |
1168 if (pcm == NULL || pcm->width == 0) | |
1169 { | |
1170 /* Character not contained in the font. FONT->default_char | |
1171 gives the character that will be printed. FONT->default_char | |
1172 is a 16-bit character code with byte1 in the most significant | |
1173 byte and byte2 in the least significant byte. */ | |
1174 XChar2b default_char; | |
1175 default_char.byte1 = (font->default_char >> BITS_PER_CHAR) & 0xff; | |
1176 default_char.byte2 = font->default_char & 0xff; | |
1177 | |
1178 /* Avoid an endless recursion if FONT->default_char itself | |
1179 hasn't per char metrics. handa@etl.go.jp reports that some | |
1180 fonts have this problem. */ | |
1181 if (default_char.byte1 != char2b->byte1 | |
1182 || default_char.byte2 != char2b->byte2) | |
1183 pcm = x_per_char_metric (font, &default_char); | |
1184 else | |
1185 pcm = &font->max_bounds; | |
1186 } | |
1187 | |
1188 return pcm; | |
1189 } | |
1190 | |
1191 | |
1192 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is | |
1193 the two-byte form of C. Encoding is returned in *CHAR2B. */ | |
1194 | |
1195 static INLINE void | |
1196 x_encode_char (c, char2b, font_info) | |
1197 int c; | |
1198 XChar2b *char2b; | |
1199 struct font_info *font_info; | |
1200 { | |
1201 int charset = CHAR_CHARSET (c); | |
1202 XFontStruct *font = font_info->font; | |
1203 | |
1204 /* FONT_INFO may define a scheme by which to encode byte1 and byte2. | |
1205 This may be either a program in a special encoder language or a | |
1206 fixed encoding. */ | |
1207 if (font_info->font_encoder) | |
1208 { | |
1209 /* It's a program. */ | |
1210 struct ccl_program *ccl = font_info->font_encoder; | |
1211 | |
1212 if (CHARSET_DIMENSION (charset) == 1) | |
1213 { | |
1214 ccl->reg[0] = charset; | |
1215 ccl->reg[1] = char2b->byte2; | |
1216 } | |
1217 else | |
1218 { | |
1219 ccl->reg[0] = charset; | |
1220 ccl->reg[1] = char2b->byte1; | |
1221 ccl->reg[2] = char2b->byte2; | |
1222 } | |
1223 | |
1224 ccl_driver (ccl, NULL, NULL, 0, 0, NULL); | |
1225 | |
1226 /* We assume that MSBs are appropriately set/reset by CCL | |
1227 program. */ | |
1228 if (font->max_byte1 == 0) /* 1-byte font */ | |
1229 char2b->byte2 = ccl->reg[1]; | |
1230 else | |
1231 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2]; | |
1232 } | |
1233 else if (font_info->encoding[charset]) | |
1234 { | |
1235 /* Fixed encoding scheme. See fontset.h for the meaning of the | |
1236 encoding numbers. */ | |
1237 int enc = font_info->encoding[charset]; | |
1238 | |
1239 if ((enc == 1 || enc == 2) | |
1240 && CHARSET_DIMENSION (charset) == 2) | |
1241 char2b->byte1 |= 0x80; | |
1242 | |
1243 if (enc == 1 || enc == 3) | |
1244 char2b->byte2 |= 0x80; | |
1245 } | |
1246 } | |
1247 | |
1248 | |
1249 /* Get face and two-byte form of character C in face FACE_ID on frame | |
1250 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero | |
1251 means we want to display multibyte text. Value is a pointer to a | |
1252 realized face that is ready for display. */ | |
1253 | |
1254 static INLINE struct face * | |
1255 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p) | |
1256 struct frame *f; | |
1257 int c, face_id; | |
1258 XChar2b *char2b; | |
1259 int multibyte_p; | |
1260 { | |
1261 struct face *face = FACE_FROM_ID (f, face_id); | |
1262 | |
1263 if (!multibyte_p) | |
1264 { | |
1265 /* Unibyte case. We don't have to encode, but we have to make | |
1266 sure to use a face suitable for unibyte. */ | |
1267 char2b->byte1 = 0; | |
1268 char2b->byte2 = c; | |
1269 | |
1270 if (!FACE_SUITABLE_FOR_CHARSET_P (face, -1)) | |
1271 { | |
1272 face_id = FACE_FOR_CHARSET (f, face_id, -1); | |
1273 face = FACE_FROM_ID (f, face_id); | |
1274 } | |
1275 } | |
1276 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL) | |
1277 { | |
1278 /* Case of ASCII in a face known to fit ASCII. */ | |
1279 char2b->byte1 = 0; | |
1280 char2b->byte2 = c; | |
1281 } | |
1282 else | |
1283 { | |
1284 int c1, c2, charset; | |
1285 | |
1286 /* Split characters into bytes. If c2 is -1 afterwards, C is | |
1287 really a one-byte character so that byte1 is zero. */ | |
1288 SPLIT_CHAR (c, charset, c1, c2); | |
1289 if (c2 > 0) | |
1290 char2b->byte1 = c1, char2b->byte2 = c2; | |
1291 else | |
1292 char2b->byte1 = 0, char2b->byte2 = c1; | |
1293 | |
1294 /* Get the face for displaying C. If `face' is not suitable for | |
1295 charset, get the one that fits. (This can happen for the | |
1296 translations of composite characters where the glyph | |
1297 specifies a face for ASCII, but translations have a different | |
1298 charset.) */ | |
1299 if (!FACE_SUITABLE_FOR_CHARSET_P (face, charset)) | |
1300 { | |
1301 face_id = FACE_FOR_CHARSET (f, face_id, charset); | |
1302 face = FACE_FROM_ID (f, face_id); | |
1303 } | |
1304 | |
1305 /* Maybe encode the character in *CHAR2B. */ | |
1306 if (charset != CHARSET_ASCII) | |
1307 { | |
1308 struct font_info *font_info | |
1309 = FONT_INFO_FROM_ID (f, face->font_info_id); | |
1310 if (font_info) | |
1311 { | |
1312 x_encode_char (c, char2b, font_info); | |
1313 if (charset == charset_latin_iso8859_1) | |
1314 { | |
1315 xassert (((XFontStruct *) font_info->font)->max_char_or_byte2 | |
1316 >= 0x80); | |
1317 char2b->byte2 |= 0x80; | |
1318 } | |
1319 } | |
1320 } | |
1321 } | |
1322 | |
1323 /* Make sure X resources of the face are allocated. */ | |
1324 xassert (face != NULL); | |
1325 PREPARE_FACE_FOR_DISPLAY (f, face); | |
1326 | |
1327 return face; | |
1328 } | |
1329 | |
1330 | |
1331 /* Get face and two-byte form of character glyph GLYPH on frame F. | |
1332 The encoding of GLYPH->u.ch.code is returned in *CHAR2B. Value is | |
1333 a pointer to a realized face that is ready for display. */ | |
1334 | |
1335 static INLINE struct face * | |
1336 x_get_glyph_face_and_encoding (f, glyph, char2b) | |
1337 struct frame *f; | |
1338 struct glyph *glyph; | |
1339 XChar2b *char2b; | |
1340 { | |
1341 struct face *face; | |
1342 | |
1343 xassert (glyph->type == CHAR_GLYPH); | |
1344 face = FACE_FROM_ID (f, glyph->u.ch.face_id); | |
1345 | |
1346 if (!glyph->multibyte_p) | |
1347 { | |
1348 /* Unibyte case. We don't have to encode, but we have to make | |
1349 sure to use a face suitable for unibyte. */ | |
1350 char2b->byte1 = 0; | |
1351 char2b->byte2 = glyph->u.ch.code; | |
1352 } | |
1353 else if (glyph->u.ch.code < 128 | |
1354 && glyph->u.ch.face_id < BASIC_FACE_ID_SENTINEL) | |
1355 { | |
1356 /* Case of ASCII in a face known to fit ASCII. */ | |
1357 char2b->byte1 = 0; | |
1358 char2b->byte2 = glyph->u.ch.code; | |
1359 } | |
1360 else | |
1361 { | |
1362 int c1, c2, charset; | |
1363 | |
1364 /* Split characters into bytes. If c2 is -1 afterwards, C is | |
1365 really a one-byte character so that byte1 is zero. */ | |
1366 SPLIT_CHAR (glyph->u.ch.code, charset, c1, c2); | |
1367 if (c2 > 0) | |
1368 char2b->byte1 = c1, char2b->byte2 = c2; | |
1369 else | |
1370 char2b->byte1 = 0, char2b->byte2 = c1; | |
1371 | |
1372 /* Maybe encode the character in *CHAR2B. */ | |
1373 if (charset != CHARSET_ASCII) | |
1374 { | |
1375 struct font_info *font_info | |
1376 = FONT_INFO_FROM_ID (f, face->font_info_id); | |
1377 if (font_info) | |
1378 { | |
1379 x_encode_char (glyph->u.ch.code, char2b, font_info); | |
1380 if (charset == charset_latin_iso8859_1) | |
1381 char2b->byte2 |= 0x80; | |
1382 } | |
1383 } | |
1384 } | |
1385 | |
1386 /* Make sure X resources of the face are allocated. */ | |
1387 xassert (face != NULL); | |
1388 PREPARE_FACE_FOR_DISPLAY (f, face); | |
1389 return face; | |
1390 } | |
1391 | |
1392 | |
1393 /* Store one glyph for IT->char_to_display in IT->glyph_row. | |
1394 Called from x_produce_glyphs when IT->glyph_row is non-null. */ | |
1395 | |
1396 static INLINE void | |
1397 x_append_glyph (it) | |
1398 struct it *it; | |
1399 { | |
1400 struct glyph *glyph; | |
1401 enum glyph_row_area area = it->area; | |
1402 | |
1403 xassert (it->glyph_row); | |
1404 xassert (it->char_to_display != '\n' && it->char_to_display != '\t'); | |
1405 | |
1406 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; | |
1407 if (glyph < it->glyph_row->glyphs[area + 1]) | |
1408 { | |
1409 /* Play it safe. If sub-structures of the glyph are not all the | |
1410 same size, it otherwise be that some bits stay set. This | |
1411 would prevent a comparison with GLYPH_EQUAL_P. */ | |
1412 glyph->u.val = 0; | |
1413 | |
1414 glyph->type = CHAR_GLYPH; | |
1415 glyph->pixel_width = it->pixel_width; | |
1416 glyph->u.ch.code = it->char_to_display; | |
1417 glyph->u.ch.face_id = it->face_id; | |
1418 glyph->charpos = CHARPOS (it->position); | |
1419 glyph->object = it->object; | |
1420 glyph->left_box_line_p = it->start_of_box_run_p; | |
1421 glyph->right_box_line_p = it->end_of_box_run_p; | |
1422 glyph->voffset = it->voffset; | |
1423 glyph->multibyte_p = it->multibyte_p; | |
1424 ++it->glyph_row->used[area]; | |
1425 } | |
1426 } | |
1427 | |
1428 | |
1429 /* Change IT->ascent and IT->height according to the setting of | |
1430 IT->voffset. */ | |
1431 | |
1432 static INLINE void | |
1433 take_vertical_position_into_account (it) | |
1434 struct it *it; | |
1435 { | |
1436 if (it->voffset) | |
1437 { | |
1438 if (it->voffset < 0) | |
1439 /* Increase the ascent so that we can display the text higher | |
1440 in the line. */ | |
1441 it->ascent += abs (it->voffset); | |
1442 else | |
1443 /* Increase the descent so that we can display the text lower | |
1444 in the line. */ | |
1445 it->descent += it->voffset; | |
1446 } | |
1447 } | |
1448 | |
1449 | |
1450 /* Produce glyphs/get display metrics for the image IT is loaded with. | |
1451 See the description of struct display_iterator in dispextern.h for | |
1452 an overview of struct display_iterator. */ | |
1453 | |
1454 static void | |
1455 x_produce_image_glyph (it) | |
1456 struct it *it; | |
1457 { | |
1458 struct image *img; | |
1459 struct face *face; | |
1460 | |
1461 xassert (it->what == IT_IMAGE); | |
1462 | |
1463 face = FACE_FROM_ID (it->f, it->face_id); | |
1464 img = IMAGE_FROM_ID (it->f, it->image_id); | |
1465 xassert (img); | |
1466 | |
1467 /* Make sure X resources of the face and image are loaded. */ | |
1468 PREPARE_FACE_FOR_DISPLAY (it->f, face); | |
1469 prepare_image_for_display (it->f, img); | |
1470 | |
1471 it->ascent = IMAGE_ASCENT (img); | |
1472 it->descent = img->height + 2 * img->margin - it->ascent; | |
1473 it->pixel_width = img->width + 2 * img->margin; | |
1474 | |
1475 it->nglyphs = 1; | |
1476 | |
1477 if (face->box != FACE_NO_BOX) | |
1478 { | |
1479 it->ascent += face->box_line_width; | |
1480 it->descent += face->box_line_width; | |
1481 | |
1482 if (it->start_of_box_run_p) | |
1483 it->pixel_width += face->box_line_width; | |
1484 if (it->end_of_box_run_p) | |
1485 it->pixel_width += face->box_line_width; | |
1486 } | |
1487 | |
1488 take_vertical_position_into_account (it); | |
1489 | |
1490 if (it->glyph_row) | |
1491 { | |
1492 struct glyph *glyph; | |
1493 enum glyph_row_area area = it->area; | |
1494 | |
1495 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; | |
1496 if (glyph < it->glyph_row->glyphs[area + 1]) | |
1497 { | |
1498 glyph->type = IMAGE_GLYPH; | |
1499 glyph->u.img.id = img->id; | |
1500 glyph->u.img.face_id = it->face_id; | |
1501 glyph->pixel_width = it->pixel_width; | |
1502 glyph->charpos = CHARPOS (it->position); | |
1503 glyph->object = it->object; | |
1504 glyph->left_box_line_p = it->start_of_box_run_p; | |
1505 glyph->right_box_line_p = it->end_of_box_run_p; | |
1506 glyph->voffset = it->voffset; | |
1507 glyph->multibyte_p = it->multibyte_p; | |
1508 ++it->glyph_row->used[area]; | |
1509 } | |
1510 } | |
1511 } | |
1512 | |
1513 | |
1514 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source | |
1515 of the glyph, WIDTH and HEIGHT are the width and height of the | |
1516 stretch. ASCENT is the percentage/100 of HEIGHT to use for the | |
1517 ascent of the glyph (0 <= ASCENT <= 1). */ | |
1518 | |
1519 static void | |
1520 x_append_stretch_glyph (it, object, width, height, ascent) | |
1521 struct it *it; | |
1522 Lisp_Object object; | |
1523 int width, height; | |
1524 double ascent; | |
1525 { | |
1526 struct glyph *glyph; | |
1527 enum glyph_row_area area = it->area; | |
1528 | |
1529 xassert (ascent >= 0 && ascent <= 1); | |
1530 | |
1531 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; | |
1532 if (glyph < it->glyph_row->glyphs[area + 1]) | |
1533 { | |
1534 glyph->type = STRETCH_GLYPH; | |
1535 glyph->u.stretch.ascent = height * ascent; | |
1536 glyph->u.stretch.height = height; | |
1537 glyph->u.stretch.face_id = it->face_id; | |
1538 glyph->pixel_width = width; | |
1539 glyph->charpos = CHARPOS (it->position); | |
1540 glyph->object = object; | |
1541 glyph->left_box_line_p = it->start_of_box_run_p; | |
1542 glyph->right_box_line_p = it->end_of_box_run_p; | |
1543 glyph->voffset = it->voffset; | |
1544 glyph->multibyte_p = it->multibyte_p; | |
1545 ++it->glyph_row->used[area]; | |
1546 } | |
1547 } | |
1548 | |
1549 | |
1550 /* Produce a stretch glyph for iterator IT. IT->object is the value | |
1551 of the glyph property displayed. The value must be a list | |
1552 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs | |
1553 being recognized: | |
1554 | |
1555 1. `:width WIDTH' specifies that the space should be WIDTH * | |
1556 canonical char width wide. WIDTH may be an integer or floating | |
1557 point number. | |
1558 | |
1559 2. `:relative-width FACTOR' specifies that the width of the stretch | |
1560 should be computed from the width of the first character having the | |
1561 `glyph' property, and should be FACTOR times that width. | |
1562 | |
1563 3. `:align-to HPOS' specifies that the space should be wide enough | |
1564 to reach HPOS, a value in canonical character units. | |
1565 | |
1566 Exactly one of the above pairs must be present. | |
1567 | |
1568 4. `:height HEIGHT' specifies that the height of the stretch produced | |
1569 should be HEIGHT, measured in canonical character units. | |
1570 | |
1571 5. `:relative-height FACTOR' specifies that the height of the the | |
1572 stretch should be FACTOR times the height of the characters having | |
1573 the glyph property. | |
1574 | |
1575 Either none or exactly one of 4 or 5 must be present. | |
1576 | |
1577 6. `:ascent ASCENT' specifies that ASCENT percent of the height | |
1578 of the stretch should be used for the ascent of the stretch. | |
1579 ASCENT must be in the range 0 <= ASCENT <= 100. */ | |
1580 | |
1581 #define NUMVAL(X) \ | |
1582 ((INTEGERP (X) || FLOATP (X)) \ | |
1583 ? XFLOATINT (X) \ | |
1584 : - 1) | |
1585 | |
1586 | |
1587 static void | |
1588 x_produce_stretch_glyph (it) | |
1589 struct it *it; | |
1590 { | |
1591 /* (space :width WIDTH :height HEIGHT. */ | |
1592 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace; | |
1593 extern Lisp_Object QCrelative_width, QCrelative_height; | |
1594 extern Lisp_Object QCalign_to; | |
1595 Lisp_Object prop, plist; | |
1596 double width = 0, height = 0, ascent = 0; | |
1597 struct face *face = FACE_FROM_ID (it->f, it->face_id); | |
1598 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f); | |
1599 | |
1600 PREPARE_FACE_FOR_DISPLAY (it->f, face); | |
1601 | |
1602 /* List should start with `space'. */ | |
1603 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace)); | |
1604 plist = XCDR (it->object); | |
1605 | |
1606 /* Compute the width of the stretch. */ | |
1607 if (prop = Fplist_get (plist, QCwidth), | |
1608 NUMVAL (prop) > 0) | |
1609 /* Absolute width `:width WIDTH' specified and valid. */ | |
1610 width = NUMVAL (prop) * CANON_X_UNIT (it->f); | |
1611 else if (prop = Fplist_get (plist, QCrelative_width), | |
1612 NUMVAL (prop) > 0) | |
1613 { | |
1614 /* Relative width `:relative-width FACTOR' specified and valid. | |
1615 Compute the width of the characters having the `glyph' | |
1616 property. */ | |
1617 struct it it2; | |
1618 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it)); | |
1619 | |
1620 it2 = *it; | |
1621 if (it->multibyte_p) | |
1622 { | |
1623 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT) | |
1624 - IT_BYTEPOS (*it)); | |
1625 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len); | |
1626 } | |
1627 else | |
1628 it2.c = *p, it2.len = 1; | |
1629 | |
1630 it2.glyph_row = NULL; | |
1631 it2.what = IT_CHARACTER; | |
1632 x_produce_glyphs (&it2); | |
1633 width = NUMVAL (prop) * it2.pixel_width; | |
1634 } | |
1635 else if (prop = Fplist_get (plist, QCalign_to), | |
1636 NUMVAL (prop) > 0) | |
1637 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x; | |
1638 else | |
1639 /* Nothing specified -> width defaults to canonical char width. */ | |
1640 width = CANON_X_UNIT (it->f); | |
1641 | |
1642 /* Compute height. */ | |
1643 if (prop = Fplist_get (plist, QCheight), | |
1644 NUMVAL (prop) > 0) | |
1645 height = NUMVAL (prop) * CANON_Y_UNIT (it->f); | |
1646 else if (prop = Fplist_get (plist, QCrelative_height), | |
1647 NUMVAL (prop) > 0) | |
1648 height = FONT_HEIGHT (font) * NUMVAL (prop); | |
1649 else | |
1650 height = FONT_HEIGHT (font); | |
1651 | |
1652 /* Compute percentage of height used for ascent. If | |
1653 `:ascent ASCENT' is present and valid, use that. Otherwise, | |
1654 derive the ascent from the font in use. */ | |
1655 if (prop = Fplist_get (plist, QCascent), | |
1656 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100) | |
1657 ascent = NUMVAL (prop) / 100.0; | |
1658 else | |
1659 ascent = (double) font->ascent / FONT_HEIGHT (font); | |
1660 | |
1661 if (width <= 0) | |
1662 width = 1; | |
1663 if (height <= 0) | |
1664 height = 1; | |
1665 | |
1666 if (it->glyph_row) | |
1667 { | |
1668 Lisp_Object object = it->stack[it->sp - 1].string; | |
1669 if (!STRINGP (object)) | |
1670 object = it->w->buffer; | |
1671 x_append_stretch_glyph (it, object, width, height, ascent); | |
1672 } | |
1673 | |
1674 it->pixel_width = width; | |
1675 it->ascent = height * ascent; | |
1676 it->descent = height - it->ascent; | |
1677 it->nglyphs = 1; | |
1678 | |
1679 if (face->box != FACE_NO_BOX) | |
1680 { | |
1681 it->ascent += face->box_line_width; | |
1682 it->descent += face->box_line_width; | |
1683 | |
1684 if (it->start_of_box_run_p) | |
1685 it->pixel_width += face->box_line_width; | |
1686 if (it->end_of_box_run_p) | |
1687 it->pixel_width += face->box_line_width; | |
1688 } | |
1689 | |
1690 take_vertical_position_into_account (it); | |
1691 } | |
1692 | |
1693 | |
1694 /* Produce glyphs/get display metrics for the display element IT is | |
1695 loaded with. See the description of struct display_iterator in | |
1696 dispextern.h for an overview of struct display_iterator. */ | |
1697 | |
1698 static void | |
1699 x_produce_glyphs (it) | |
1700 struct it *it; | |
1701 { | |
1702 if (it->what == IT_CHARACTER) | |
1703 { | |
1704 XChar2b char2b; | |
1705 XFontStruct *font; | |
1706 struct face *face; | |
1707 XCharStruct *pcm; | |
1708 struct it ci; | |
1709 int font_not_found_p; | |
1710 int c; | |
1711 | |
1712 /* Maybe translate single-byte characters to multibyte. */ | |
1713 it->char_to_display = it->c; | |
1714 if (unibyte_display_via_language_environment | |
1715 && SINGLE_BYTE_CHAR_P (it->c) | |
1716 && (it->c >= 0240 | |
1717 || (it->c >= 0200 | |
1718 && !NILP (Vnonascii_translation_table)))) | |
1719 { | |
1720 it->char_to_display = unibyte_char_to_multibyte (it->c); | |
1721 it->charset = CHAR_CHARSET (it->char_to_display); | |
1722 } | |
1723 | |
1724 /* Get face and font to use. Encode IT->char_to_display. */ | |
1725 face = x_get_char_face_and_encoding (it->f, it->char_to_display, | |
1726 it->face_id, &char2b, | |
1727 it->multibyte_p); | |
1728 font = face->font; | |
1729 | |
1730 /* When no suitable font found, use the default font. */ | |
1731 font_not_found_p = font == NULL; | |
1732 if (font_not_found_p) | |
1733 font = FRAME_FONT (it->f); | |
1734 | |
1735 if (it->char_to_display >= ' ' | |
1736 && (!it->multibyte_p || it->char_to_display < 128)) | |
1737 { | |
1738 /* Either unibyte or ASCII. */ | |
1739 int stretched_p; | |
1740 | |
1741 it->nglyphs = 1; | |
1742 it->ascent = font->ascent; | |
1743 it->descent = font->descent; | |
1744 | |
1745 pcm = x_per_char_metric (font, &char2b); | |
1746 it->pixel_width = pcm->width; | |
1747 | |
1748 /* If this is a space inside a region of text with | |
1749 `space-width' property, change its width. */ | |
1750 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width); | |
1751 if (stretched_p) | |
1752 it->pixel_width *= XFLOATINT (it->space_width); | |
1753 | |
1754 /* If face has a box, add the box thickness to the character | |
1755 height. If character has a box line to the left and/or | |
1756 right, add the box line width to the character's width. */ | |
1757 if (face->box != FACE_NO_BOX) | |
1758 { | |
1759 int thick = face->box_line_width; | |
1760 | |
1761 it->ascent += thick; | |
1762 it->descent += thick; | |
1763 | |
1764 if (it->start_of_box_run_p) | |
1765 it->pixel_width += thick; | |
1766 if (it->end_of_box_run_p) | |
1767 it->pixel_width += thick; | |
1768 } | |
1769 | |
1770 /* If face has an overline, add the height of the overline | |
1771 (1 pixel) and a 1 pixel margin to the character height. */ | |
1772 if (face->overline_p) | |
1773 it->ascent += 2; | |
1774 | |
1775 take_vertical_position_into_account (it); | |
1776 | |
1777 /* If we have to actually produce glyphs, do it. */ | |
1778 if (it->glyph_row) | |
1779 { | |
1780 if (stretched_p) | |
1781 { | |
1782 /* Translate a space with a `space-width' property | |
1783 into a stretch glyph. */ | |
1784 double ascent = (double) font->ascent / FONT_HEIGHT (font); | |
1785 x_append_stretch_glyph (it, it->object, it->pixel_width, | |
1786 it->ascent + it->descent, ascent); | |
1787 } | |
1788 else | |
1789 x_append_glyph (it); | |
1790 | |
1791 /* If characters with lbearing or rbearing are displayed | |
1792 in this line, record that fact in a flag of the | |
1793 glyph row. This is used to optimize X output code. */ | |
1794 if (pcm->lbearing < 0 | |
1795 || pcm->rbearing > pcm->width) | |
1796 it->glyph_row->contains_overlapping_glyphs_p = 1; | |
1797 } | |
1798 } | |
1799 else if (it->char_to_display == '\n') | |
1800 { | |
1801 /* A newline has no width but we need the height of the line. */ | |
1802 it->pixel_width = 0; | |
1803 it->nglyphs = 0; | |
1804 it->ascent = font->ascent; | |
1805 it->descent = font->descent; | |
1806 | |
1807 if (face->box != FACE_NO_BOX) | |
1808 { | |
1809 int thick = face->box_line_width; | |
1810 it->ascent += thick; | |
1811 it->descent += thick; | |
1812 } | |
1813 } | |
1814 else if (it->char_to_display == '\t') | |
1815 { | |
1816 int tab_width = it->tab_width * CANON_X_UNIT (it->f); | |
1817 int x = (it->current_x | |
1818 - it->prompt_width | |
1819 + it->continuation_lines_width); | |
1820 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width; | |
1821 | |
1822 it->pixel_width = next_tab_x - x; | |
1823 it->nglyphs = 1; | |
1824 it->ascent = font->ascent; | |
1825 it->descent = font->descent; | |
1826 | |
1827 if (it->glyph_row) | |
1828 { | |
1829 double ascent = (double) it->ascent / (it->ascent + it->descent); | |
1830 x_append_stretch_glyph (it, it->object, it->pixel_width, | |
1831 it->ascent + it->descent, ascent); | |
1832 } | |
1833 } | |
1834 else | |
1835 { | |
1836 /* A multi-byte character. Assume that the display width of the | |
1837 character is the width of the character multiplied by the | |
1838 width of the font. There has to be better support for | |
1839 variable sizes in cmpchar_info to do anything better than | |
1840 that. | |
1841 | |
1842 Note: composite characters are represented as one glyph in | |
1843 the glyph matrix. There are no padding glyphs. */ | |
1844 if (it->charset == CHARSET_COMPOSITION) | |
1845 { | |
1846 struct cmpchar_info *cmpcharp; | |
1847 int idx; | |
1848 | |
1849 idx = COMPOSITE_CHAR_ID (it->char_to_display); | |
1850 cmpcharp = cmpchar_table[idx]; | |
1851 it->pixel_width = font->max_bounds.width * cmpcharp->width; | |
1852 | |
1853 /* There are no padding glyphs, so there is only one glyph | |
1854 to produce for the composite char. Important is that | |
1855 pixel_width, ascent and descent are the values of what is | |
1856 drawn by draw_glyphs. */ | |
1857 it->nglyphs = 1; | |
1858 | |
1859 /* These settings may not be correct. We must have more | |
1860 information in cmpcharp to do the correct setting. */ | |
1861 it->ascent = font->ascent; | |
1862 it->descent = font->descent; | |
1863 } | |
1864 else | |
1865 { | |
1866 /* If we found a font, this font should give us the right | |
1867 metrics. If we didn't find a font, use the frame's | |
1868 default font and calculate the width of the character | |
1869 from the charset width; this is what old redisplay code | |
1870 did. */ | |
1871 pcm = x_per_char_metric (font, &char2b); | |
1872 it->pixel_width = pcm->width; | |
1873 if (font_not_found_p) | |
1874 it->pixel_width *= CHARSET_WIDTH (it->charset); | |
1875 it->nglyphs = 1; | |
1876 it->ascent = font->ascent; | |
1877 it->descent = font->descent; | |
1878 if (it->glyph_row | |
1879 && (pcm->lbearing < 0 | |
1880 || pcm->rbearing > pcm->width)) | |
1881 it->glyph_row->contains_overlapping_glyphs_p = 1; | |
1882 } | |
1883 | |
1884 if (face->box != FACE_NO_BOX) | |
1885 { | |
1886 int thick = face->box_line_width; | |
1887 it->ascent += thick; | |
1888 it->descent += thick; | |
1889 | |
1890 if (it->start_of_box_run_p) | |
1891 it->pixel_width += thick; | |
1892 if (it->end_of_box_run_p) | |
1893 it->pixel_width += thick; | |
1894 } | |
1895 | |
1896 /* If face has an overline, add the height of the overline | |
1897 (1 pixel) and a 1 pixel margin to the character height. */ | |
1898 if (face->overline_p) | |
1899 it->ascent += 2; | |
1900 | |
1901 take_vertical_position_into_account (it); | |
1902 | |
1903 if (it->glyph_row) | |
1904 x_append_glyph (it); | |
1905 } | |
1906 } | |
1907 else if (it->what == IT_IMAGE) | |
1908 x_produce_image_glyph (it); | |
1909 else if (it->what == IT_STRETCH) | |
1910 x_produce_stretch_glyph (it); | |
1911 | |
1912 /* Accumulate dimensions. */ | |
1913 xassert (it->ascent >= 0 && it->descent > 0); | |
1914 if (it->area == TEXT_AREA) | |
1915 it->current_x += it->pixel_width; | |
1916 it->max_ascent = max (it->max_ascent, it->ascent); | |
1917 it->max_descent = max (it->max_descent, it->descent); | |
1918 } | |
1919 | |
1920 | |
1921 /* Estimate the pixel height of the mode or top line on frame F. | |
1922 FACE_ID specifies what line's height to estimate. */ | |
1923 | |
1924 int | |
1925 x_estimate_mode_line_height (f, face_id) | |
1926 struct frame *f; | |
1927 enum face_id face_id; | |
1928 { | |
1929 int height = 1; | |
1930 | |
1931 /* This function is called so early when Emacs starts that the face | |
1932 cache and mode line face are not yet initialized. */ | |
1933 if (FRAME_FACE_CACHE (f)) | |
1934 { | |
1935 struct face *face = FACE_FROM_ID (f, face_id); | |
1936 if (face) | |
1937 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width; | |
1938 } | |
1939 | |
1940 return height; | |
1941 } | |
1942 | |
1943 | |
1944 /*********************************************************************** | |
1945 Glyph display | |
1946 ***********************************************************************/ | |
1947 | |
1948 /* A sequence of glyphs to be drawn in the same face. | |
1949 | |
1950 This data structure is not really completely X specific, so it | |
1951 could possibly, at least partially, be useful for other systems. It | |
1952 is currently not part of the external redisplay interface because | |
1953 it's not clear what other systems will need. */ | |
1954 | |
1955 struct glyph_string | |
1956 { | |
1957 /* X-origin of the string. */ | |
1958 int x; | |
1959 | |
1960 /* Y-origin and y-position of the base line of this string. */ | |
1961 int y, ybase; | |
1962 | |
1963 /* The width of the string, not including a face extension. */ | |
1964 int width; | |
1965 | |
1966 /* The width of the string, including a face extension. */ | |
1967 int background_width; | |
1968 | |
1969 /* The height of this string. This is the height of the line this | |
1970 string is drawn in, and can be different from the height of the | |
1971 font the string is drawn in. */ | |
1972 int height; | |
1973 | |
1974 /* Number of pixels this string overwrites in front of its x-origin. | |
1975 This number is zero if the string has an lbearing >= 0; it is | |
1976 -lbearing, if the string has an lbearing < 0. */ | |
1977 int left_overhang; | |
1978 | |
1979 /* Number of pixels this string overwrites past its right-most | |
1980 nominal x-position, i.e. x + width. Zero if the string's | |
1981 rbearing is <= its nominal width, rbearing - width otherwise. */ | |
1982 int right_overhang; | |
1983 | |
1984 /* The frame on which the glyph string is drawn. */ | |
1985 struct frame *f; | |
1986 | |
1987 /* The window on which the glyph string is drawn. */ | |
1988 struct window *w; | |
1989 | |
1990 /* X display and window for convenience. */ | |
1991 Display *display; | |
1992 Window window; | |
1993 | |
1994 /* The glyph row for which this string was built. It determines the | |
1995 y-origin and height of the string. */ | |
1996 struct glyph_row *row; | |
1997 | |
1998 /* The area within row. */ | |
1999 enum glyph_row_area area; | |
2000 | |
2001 /* Characters to be drawn, and number of characters. */ | |
2002 XChar2b *char2b; | |
2003 int nchars; | |
2004 | |
2005 /* Character set of this glyph string. */ | |
2006 int charset; | |
2007 | |
2008 /* A face-override for drawing cursors, mouse face and similar. */ | |
2009 enum draw_glyphs_face hl; | |
2010 | |
2011 /* Face in which this string is to be drawn. */ | |
2012 struct face *face; | |
2013 | |
2014 /* Font in which this string is to be drawn. */ | |
2015 XFontStruct *font; | |
2016 | |
2017 /* Font info for this string. */ | |
2018 struct font_info *font_info; | |
2019 | |
2020 /* Non-null means this string describes (part of) a composite | |
2021 character. All characters from char2b are drawn at the same | |
2022 x-origin in that case. */ | |
2023 struct cmpchar_info *cmpcharp; | |
2024 | |
2025 /* Index of this glyph string's first character in the glyph | |
2026 definition of cmpcharp. If this is zero, this glyph string | |
2027 describes the first character of a composite character. */ | |
2028 int gidx; | |
2029 | |
2030 /* 1 means this glyph strings face has to be drawn to the right end | |
2031 of the window's drawing area. */ | |
2032 unsigned extends_to_end_of_line_p : 1; | |
2033 | |
2034 /* 1 means the background of this string has been drawn. */ | |
2035 unsigned background_filled_p : 1; | |
2036 | |
2037 /* 1 means glyph string must be drawn with 16-bit functions. */ | |
2038 unsigned two_byte_p : 1; | |
2039 | |
2040 /* 1 means that the original font determined for drawing this glyph | |
2041 string could not be loaded. The member `font' has been set to | |
2042 the frame's default font in this case. */ | |
2043 unsigned font_not_found_p : 1; | |
2044 | |
2045 /* 1 means that the face in which this glyph string is drawn has a | |
2046 stipple pattern. */ | |
2047 unsigned stippled_p : 1; | |
2048 | |
2049 /* The GC to use for drawing this glyph string. */ | |
2050 GC gc; | |
2051 | |
2052 /* A pointer to the first glyph in the string. This glyph | |
2053 corresponds to char2b[0]. Needed to draw rectangles if | |
2054 font_not_found_p is 1. */ | |
2055 struct glyph *first_glyph; | |
2056 | |
2057 /* Image, if any. */ | |
2058 struct image *img; | |
2059 | |
2060 struct glyph_string *next, *prev; | |
2061 }; | |
2062 | |
2063 | |
2064 #if GLYPH_DEBUG | |
2065 | |
2066 static void | |
2067 x_dump_glyph_string (s) | |
2068 struct glyph_string *s; | |
2069 { | |
2070 fprintf (stderr, "glyph string\n"); | |
2071 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n", | |
2072 s->x, s->y, s->width, s->height); | |
2073 fprintf (stderr, " ybase = %d\n", s->ybase); | |
2074 fprintf (stderr, " hl = %d\n", s->hl); | |
2075 fprintf (stderr, " left overhang = %d, right = %d\n", | |
2076 s->left_overhang, s->right_overhang); | |
2077 fprintf (stderr, " nchars = %d\n", s->nchars); | |
2078 fprintf (stderr, " extends to end of line = %d\n", | |
2079 s->extends_to_end_of_line_p); | |
2080 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font)); | |
2081 fprintf (stderr, " bg width = %d\n", s->background_width); | |
2082 } | |
2083 | |
2084 #endif /* GLYPH_DEBUG */ | |
2085 | |
2086 | |
2087 | |
2088 static void x_append_glyph_string_lists P_ ((struct glyph_string **, | |
2089 struct glyph_string **, | |
2090 struct glyph_string *, | |
2091 struct glyph_string *)); | |
2092 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **, | |
2093 struct glyph_string **, | |
2094 struct glyph_string *, | |
2095 struct glyph_string *)); | |
2096 static void x_append_glyph_string P_ ((struct glyph_string **, | |
2097 struct glyph_string **, | |
2098 struct glyph_string *)); | |
2099 static int x_left_overwritten P_ ((struct glyph_string *)); | |
2100 static int x_left_overwriting P_ ((struct glyph_string *)); | |
2101 static int x_right_overwritten P_ ((struct glyph_string *)); | |
2102 static int x_right_overwriting P_ ((struct glyph_string *)); | |
2103 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int)); | |
2104 static void x_init_glyph_string P_ ((struct glyph_string *, | |
2105 XChar2b *, struct window *, | |
2106 struct glyph_row *, | |
2107 enum glyph_row_area, int, | |
2108 enum draw_glyphs_face)); | |
2109 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *, | |
2110 enum glyph_row_area, int, int, | |
2111 enum draw_glyphs_face, int *, int *)); | |
2112 static void x_set_glyph_string_clipping P_ ((struct glyph_string *)); | |
2113 static void x_set_glyph_string_gc P_ ((struct glyph_string *)); | |
2114 static void x_draw_glyph_string_background P_ ((struct glyph_string *, | |
2115 int)); | |
2116 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *)); | |
2117 static void x_draw_glyph_string_underline P_ ((struct glyph_string *)); | |
2118 static void x_draw_glyph_string_box P_ ((struct glyph_string *)); | |
2119 static void x_draw_glyph_string P_ ((struct glyph_string *)); | |
2120 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *)); | |
2121 static void x_set_cursor_gc P_ ((struct glyph_string *)); | |
2122 static void x_set_mode_line_face_gc P_ ((struct glyph_string *)); | |
2123 static void x_set_mouse_face_gc P_ ((struct glyph_string *)); | |
2124 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *, | |
2125 int *, int *)); | |
2126 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int)); | |
2127 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap, | |
2128 unsigned long *, float, int)); | |
2129 static void x_setup_relief_color P_ ((struct frame *, struct relief *, | |
2130 float, int, unsigned long)); | |
2131 static void x_setup_relief_colors P_ ((struct glyph_string *)); | |
2132 static void x_draw_image_glyph_string P_ ((struct glyph_string *)); | |
2133 static void x_draw_image_relief P_ ((struct glyph_string *)); | |
2134 static void x_draw_image_foreground P_ ((struct glyph_string *)); | |
2135 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap)); | |
2136 static void x_fill_image_glyph_string P_ ((struct glyph_string *)); | |
2137 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int, | |
2138 int, int, int)); | |
2139 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int, | |
2140 int, int, int, int, XRectangle *)); | |
2141 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int, | |
2142 int, int, int, XRectangle *)); | |
2143 | |
2144 | |
2145 | |
2146 /* Append the list of glyph strings with head H and tail T to the list | |
2147 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */ | |
2148 | |
2149 static INLINE void | |
2150 x_append_glyph_string_lists (head, tail, h, t) | |
2151 struct glyph_string **head, **tail; | |
2152 struct glyph_string *h, *t; | |
2153 { | |
2154 if (h) | |
2155 { | |
2156 if (*head) | |
2157 (*tail)->next = h; | |
2158 else | |
2159 *head = h; | |
2160 h->prev = *tail; | |
2161 *tail = t; | |
2162 } | |
2163 } | |
2164 | |
2165 | |
2166 /* Prepend the list of glyph strings with head H and tail T to the | |
2167 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the | |
2168 result. */ | |
2169 | |
2170 static INLINE void | |
2171 x_prepend_glyph_string_lists (head, tail, h, t) | |
2172 struct glyph_string **head, **tail; | |
2173 struct glyph_string *h, *t; | |
2174 { | |
2175 if (h) | |
2176 { | |
2177 if (*head) | |
2178 (*head)->prev = t; | |
2179 else | |
2180 *tail = t; | |
2181 t->next = *head; | |
2182 *head = h; | |
2183 } | |
2184 } | |
2185 | |
2186 | |
2187 /* Append glyph string S to the list with head *HEAD and tail *TAIL. | |
2188 Set *HEAD and *TAIL to the resulting list. */ | |
2189 | |
2190 static INLINE void | |
2191 x_append_glyph_string (head, tail, s) | |
2192 struct glyph_string **head, **tail; | |
2193 struct glyph_string *s; | |
2194 { | |
2195 s->next = s->prev = NULL; | |
2196 x_append_glyph_string_lists (head, tail, s, s); | |
2197 } | |
2198 | |
2199 | |
2200 /* Set S->gc to a suitable GC for drawing glyph string S in cursor | |
2201 face. */ | |
2202 | |
2203 static void | |
2204 x_set_cursor_gc (s) | |
2205 struct glyph_string *s; | |
2206 { | |
2207 if (s->font == FRAME_FONT (s->f) | |
2208 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f) | |
2209 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f) | |
2210 && !s->cmpcharp) | |
2211 s->gc = s->f->output_data.x->cursor_gc; | |
2212 else | |
2213 { | |
2214 /* Cursor on non-default face: must merge. */ | |
2215 XGCValues xgcv; | |
2216 unsigned long mask; | |
2217 | |
2218 xgcv.background = s->f->output_data.x->cursor_pixel; | |
2219 xgcv.foreground = s->face->background; | |
2220 | |
2221 /* If the glyph would be invisible, try a different foreground. */ | |
2222 if (xgcv.foreground == xgcv.background) | |
2223 xgcv.foreground = s->face->foreground; | |
2224 if (xgcv.foreground == xgcv.background) | |
2225 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel; | |
2226 if (xgcv.foreground == xgcv.background) | |
2227 xgcv.foreground = s->face->foreground; | |
2228 | |
2229 /* Make sure the cursor is distinct from text in this face. */ | |
2230 if (xgcv.background == s->face->background | |
2231 && xgcv.foreground == s->face->foreground) | |
2232 { | |
2233 xgcv.background = s->face->foreground; | |
2234 xgcv.foreground = s->face->background; | |
2235 } | |
2236 | |
2237 IF_DEBUG (x_check_font (s->f, s->font)); | |
2238 xgcv.font = s->font->fid; | |
2239 xgcv.graphics_exposures = False; | |
2240 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; | |
2241 | |
2242 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc) | |
2243 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc, | |
2244 mask, &xgcv); | |
2245 else | |
2246 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc | |
2247 = XCreateGC (s->display, s->window, mask, &xgcv); | |
2248 | |
2249 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc; | |
2250 } | |
2251 } | |
2252 | |
2253 | |
2254 /* Set up S->gc of glyph string S for drawing text in mouse face. */ | |
2255 | |
2256 static void | |
2257 x_set_mouse_face_gc (s) | |
2258 struct glyph_string *s; | |
2259 { | |
2260 int face_id; | |
2261 | |
2262 /* What face has to be used for the mouse face? */ | |
2263 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id; | |
2264 face_id = FACE_FOR_CHARSET (s->f, face_id, s->charset); | |
2265 s->face = FACE_FROM_ID (s->f, face_id); | |
2266 PREPARE_FACE_FOR_DISPLAY (s->f, s->face); | |
2267 | |
2268 /* If font in this face is same as S->font, use it. */ | |
2269 if (s->font == s->face->font) | |
2270 s->gc = s->face->gc; | |
2271 else | |
2272 { | |
2273 /* Otherwise construct scratch_cursor_gc with values from FACE | |
2274 but font FONT. */ | |
2275 XGCValues xgcv; | |
2276 unsigned long mask; | |
2277 | |
2278 xgcv.background = s->face->background; | |
2279 xgcv.foreground = s->face->foreground; | |
2280 IF_DEBUG (x_check_font (s->f, s->font)); | |
2281 xgcv.font = s->font->fid; | |
2282 xgcv.graphics_exposures = False; | |
2283 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; | |
2284 | |
2285 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc) | |
2286 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc, | |
2287 mask, &xgcv); | |
2288 else | |
2289 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc | |
2290 = XCreateGC (s->display, s->window, mask, &xgcv); | |
2291 | |
2292 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc; | |
2293 } | |
2294 | |
2295 xassert (s->gc != 0); | |
2296 } | |
2297 | |
2298 | |
2299 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line. | |
2300 Faces to use in the mode line have already been computed when the | |
2301 matrix was built, so there isn't much to do, here. */ | |
2302 | |
2303 static INLINE void | |
2304 x_set_mode_line_face_gc (s) | |
2305 struct glyph_string *s; | |
2306 { | |
2307 s->gc = s->face->gc; | |
2308 xassert (s->gc != 0); | |
2309 } | |
2310 | |
2311 | |
2312 /* Set S->gc of glyph string S for drawing that glyph string. Set | |
2313 S->stippled_p to a non-zero value if the face of S has a stipple | |
2314 pattern. */ | |
2315 | |
2316 static INLINE void | |
2317 x_set_glyph_string_gc (s) | |
2318 struct glyph_string *s; | |
2319 { | |
2320 if (s->hl == DRAW_NORMAL_TEXT) | |
2321 { | |
2322 s->gc = s->face->gc; | |
2323 s->stippled_p = s->face->stipple != 0; | |
2324 } | |
2325 else if (s->hl == DRAW_INVERSE_VIDEO) | |
2326 { | |
2327 x_set_mode_line_face_gc (s); | |
2328 s->stippled_p = s->face->stipple != 0; | |
2329 } | |
2330 else if (s->hl == DRAW_CURSOR) | |
2331 { | |
2332 x_set_cursor_gc (s); | |
2333 s->stippled_p = 0; | |
2334 } | |
2335 else if (s->hl == DRAW_MOUSE_FACE) | |
2336 { | |
2337 x_set_mouse_face_gc (s); | |
2338 s->stippled_p = s->face->stipple != 0; | |
2339 } | |
2340 else if (s->hl == DRAW_IMAGE_RAISED | |
2341 || s->hl == DRAW_IMAGE_SUNKEN) | |
2342 { | |
2343 s->gc = s->face->gc; | |
2344 s->stippled_p = s->face->stipple != 0; | |
2345 } | |
2346 else | |
2347 { | |
2348 s->gc = s->face->gc; | |
2349 s->stippled_p = s->face->stipple != 0; | |
2350 } | |
2351 | |
2352 /* GC must have been set. */ | |
2353 xassert (s->gc != 0); | |
2354 } | |
2355 | |
2356 | |
2357 /* Return in *R the clipping rectangle for glyph string S. */ | |
2358 | |
2359 static void | |
2360 x_get_glyph_string_clip_rect (s, r) | |
2361 struct glyph_string *s; | |
2362 XRectangle *r; | |
2363 { | |
2364 if (s->row->full_width_p) | |
2365 { | |
2366 /* Draw full-width. X coordinates are relative to S->w->left. */ | |
2367 r->x = WINDOW_LEFT_MARGIN (s->w) * CANON_X_UNIT (s->f); | |
2368 r->width = XFASTINT (s->w->width) * CANON_X_UNIT (s->f); | |
2369 | |
2370 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f)) | |
2371 { | |
2372 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f); | |
2373 r->width += width; | |
2374 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f)) | |
2375 r->x -= width; | |
2376 } | |
2377 | |
2378 /* Unless displaying a mode or menu bar line, which are always | |
2379 fully visible, clip to the visible part of the row. */ | |
2380 if (s->w->pseudo_window_p) | |
2381 r->height = s->row->visible_height; | |
2382 else | |
2383 r->height = s->height; | |
2384 } | |
2385 else | |
2386 { | |
2387 /* This is a text line that may be partially visible. */ | |
2388 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0); | |
2389 r->width = window_box_width (s->w, s->area); | |
2390 r->height = s->row->visible_height; | |
2391 } | |
2392 | |
2393 /* Don't use S->y for clipping because it doesn't take partially | |
2394 visible lines into account. For example, it can be negative for | |
2395 partially visible lines at the top of a window. */ | |
2396 if (!s->row->full_width_p | |
2397 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row)) | |
2398 r->y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (s->w); | |
2399 else | |
2400 r->y = max (0, s->row->y); | |
2401 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y); | |
2402 | |
2403 /* If drawing a toolbar window, draw it over the internal border | |
2404 at the top of the window. */ | |
2405 if (s->w == XWINDOW (s->f->toolbar_window)) | |
2406 r->y -= s->f->output_data.x->internal_border_width; | |
2407 } | |
2408 | |
2409 | |
2410 /* Set clipping for output of glyph string S. S may be part of a mode | |
2411 line or menu if we don't have X toolkit support. */ | |
2412 | |
2413 static INLINE void | |
2414 x_set_glyph_string_clipping (s) | |
2415 struct glyph_string *s; | |
2416 { | |
2417 XRectangle r; | |
2418 x_get_glyph_string_clip_rect (s, &r); | |
2419 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted); | |
2420 } | |
2421 | |
2422 | |
2423 /* Compute left and right overhang of glyph string S. If S is a glyph | |
2424 string for a composite character, assume overhangs don't exist. */ | |
2425 | |
2426 static INLINE void | |
2427 x_compute_glyph_string_overhangs (s) | |
2428 struct glyph_string *s; | |
2429 { | |
2430 if (s->cmpcharp == NULL | |
2431 && s->first_glyph->type == CHAR_GLYPH) | |
2432 { | |
2433 XCharStruct cs; | |
2434 int direction, font_ascent, font_descent; | |
2435 XTextExtents16 (s->font, s->char2b, s->nchars, &direction, | |
2436 &font_ascent, &font_descent, &cs); | |
2437 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0; | |
2438 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0; | |
2439 } | |
2440 } | |
2441 | |
2442 | |
2443 /* Compute overhangs and x-positions for glyph string S and its | |
2444 predecessors, or successors. X is the starting x-position for S. | |
2445 BACKWARD_P non-zero means process predecessors. */ | |
2446 | |
2447 static void | |
2448 x_compute_overhangs_and_x (s, x, backward_p) | |
2449 struct glyph_string *s; | |
2450 int x; | |
2451 int backward_p; | |
2452 { | |
2453 if (backward_p) | |
2454 { | |
2455 while (s) | |
2456 { | |
2457 x_compute_glyph_string_overhangs (s); | |
2458 x -= s->width; | |
2459 s->x = x; | |
2460 s = s->prev; | |
2461 } | |
2462 } | |
2463 else | |
2464 { | |
2465 while (s) | |
2466 { | |
2467 x_compute_glyph_string_overhangs (s); | |
2468 s->x = x; | |
2469 x += s->width; | |
2470 s = s->next; | |
2471 } | |
2472 } | |
2473 } | |
2474 | |
2475 | |
2476 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on | |
2477 frame F. Overhangs of glyphs other than type CHAR_GLYPH or of | |
2478 character glyphs for composite characters are assumed to be zero. */ | |
2479 | |
2480 static void | |
2481 x_get_glyph_overhangs (glyph, f, left, right) | |
2482 struct glyph *glyph; | |
2483 struct frame *f; | |
2484 int *left, *right; | |
2485 { | |
2486 int c; | |
2487 | |
2488 *left = *right = 0; | |
2489 | |
2490 if (glyph->type == CHAR_GLYPH | |
2491 && (c = glyph->u.ch.code, | |
2492 CHAR_CHARSET (c) != CHARSET_COMPOSITION)) | |
2493 { | |
2494 XFontStruct *font; | |
2495 struct face *face; | |
2496 struct font_info *font_info; | |
2497 XChar2b char2b; | |
2498 | |
2499 face = x_get_glyph_face_and_encoding (f, glyph, &char2b); | |
2500 font = face->font; | |
2501 font_info = FONT_INFO_FROM_ID (f, face->font_info_id); | |
2502 if (font) | |
2503 { | |
2504 XCharStruct *pcm = x_per_char_metric (font, &char2b); | |
2505 | |
2506 if (pcm->rbearing > pcm->width) | |
2507 *right = pcm->rbearing - pcm->width; | |
2508 if (pcm->lbearing < 0) | |
2509 *left = -pcm->lbearing; | |
2510 } | |
2511 } | |
2512 } | |
2513 | |
2514 | |
2515 /* Return the index of the first glyph preceding glyph string S that | |
2516 is overwritten by S because of S's left overhang. Value is -1 | |
2517 if no glyphs are overwritten. */ | |
545 | 2518 |
546 static int | 2519 static int |
547 dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp) | 2520 x_left_overwritten (s) |
2521 struct glyph_string *s; | |
2522 { | |
2523 int k; | |
2524 | |
2525 if (s->left_overhang) | |
2526 { | |
2527 int x = 0, i; | |
2528 struct glyph *glyphs = s->row->glyphs[s->area]; | |
2529 int first = s->first_glyph - glyphs; | |
2530 | |
2531 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i) | |
2532 x -= glyphs[i].pixel_width; | |
2533 | |
2534 k = i + 1; | |
2535 } | |
2536 else | |
2537 k = -1; | |
2538 | |
2539 return k; | |
2540 } | |
2541 | |
2542 | |
2543 /* Return the index of the first glyph preceding glyph string S that | |
2544 is overwriting S because of its right overhang. Value is -1 if no | |
2545 glyph in front of S overwrites S. */ | |
2546 | |
2547 static int | |
2548 x_left_overwriting (s) | |
2549 struct glyph_string *s; | |
2550 { | |
2551 int i, k, x; | |
2552 struct glyph *glyphs = s->row->glyphs[s->area]; | |
2553 int first = s->first_glyph - glyphs; | |
2554 | |
2555 k = -1; | |
2556 x = 0; | |
2557 for (i = first - 1; i >= 0; --i) | |
2558 { | |
2559 int left, right; | |
2560 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right); | |
2561 if (x + right > 0) | |
2562 k = i; | |
2563 x -= glyphs[i].pixel_width; | |
2564 } | |
2565 | |
2566 return k; | |
2567 } | |
2568 | |
2569 | |
2570 /* Return the index of the last glyph following glyph string S that is | |
2571 not overwritten by S because of S's right overhang. Value is -1 if | |
2572 no such glyph is found. */ | |
2573 | |
2574 static int | |
2575 x_right_overwritten (s) | |
2576 struct glyph_string *s; | |
2577 { | |
2578 int k = -1; | |
2579 | |
2580 if (s->right_overhang) | |
2581 { | |
2582 int x = 0, i; | |
2583 struct glyph *glyphs = s->row->glyphs[s->area]; | |
2584 int first = (s->first_glyph - glyphs) + (s->cmpcharp ? 1 : s->nchars); | |
2585 int end = s->row->used[s->area]; | |
2586 | |
2587 for (i = first; i < end && s->right_overhang > x; ++i) | |
2588 x += glyphs[i].pixel_width; | |
2589 | |
2590 k = i; | |
2591 } | |
2592 | |
2593 return k; | |
2594 } | |
2595 | |
2596 | |
2597 /* Return the index of the last glyph following glyph string S that | |
2598 overwrites S because of its left overhang. Value is negative | |
2599 if no such glyph is found. */ | |
2600 | |
2601 static int | |
2602 x_right_overwriting (s) | |
2603 struct glyph_string *s; | |
2604 { | |
2605 int i, k, x; | |
2606 int end = s->row->used[s->area]; | |
2607 struct glyph *glyphs = s->row->glyphs[s->area]; | |
2608 int first = (s->first_glyph - glyphs) + (s->cmpcharp ? 1 : s->nchars); | |
2609 | |
2610 k = -1; | |
2611 x = 0; | |
2612 for (i = first; i < end; ++i) | |
2613 { | |
2614 int left, right; | |
2615 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right); | |
2616 if (x - left < 0) | |
2617 k = i; | |
2618 x += glyphs[i].pixel_width; | |
2619 } | |
2620 | |
2621 return k; | |
2622 } | |
2623 | |
2624 | |
2625 /* Fill rectangle X, Y, W, H with background color of glyph string S. */ | |
2626 | |
2627 static INLINE void | |
2628 x_clear_glyph_string_rect (s, x, y, w, h) | |
2629 struct glyph_string *s; | |
2630 int x, y, w, h; | |
2631 { | |
2632 XGCValues xgcv; | |
2633 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv); | |
2634 XSetForeground (s->display, s->gc, xgcv.background); | |
2635 XFillRectangle (s->display, s->window, s->gc, x, y, w, h); | |
2636 XSetForeground (s->display, s->gc, xgcv.foreground); | |
2637 } | |
2638 | |
2639 | |
2640 /* Draw the background of glyph_string S. If S->background_filled_p | |
2641 is non-zero don't draw it. FORCE_P non-zero means draw the | |
2642 background even if it wouldn't be drawn normally. This is used | |
2643 when a string preceding S draws into the background of S. */ | |
2644 | |
2645 static void | |
2646 x_draw_glyph_string_background (s, force_p) | |
2647 struct glyph_string *s; | |
2648 int force_p; | |
2649 { | |
2650 /* Nothing to do if background has already been drawn or if it | |
2651 shouldn't be drawn in the first place. */ | |
2652 if (!s->background_filled_p) | |
2653 { | |
2654 if (s->cmpcharp | |
2655 && s->gidx > 0 | |
2656 && !s->font_not_found_p | |
2657 && !s->extends_to_end_of_line_p) | |
2658 { | |
2659 /* Don't draw background for glyphs of a composite | |
2660 characters, except for the first one. */ | |
2661 s->background_filled_p = 1; | |
2662 } | |
2663 else if (s->stippled_p) | |
2664 { | |
2665 /* Fill background with a stipple pattern. */ | |
2666 XSetFillStyle (s->display, s->gc, FillOpaqueStippled); | |
2667 XFillRectangle (s->display, s->window, s->gc, s->x, | |
2668 s->y + s->face->box_line_width, | |
2669 s->background_width, | |
2670 s->height - 2 * s->face->box_line_width); | |
2671 XSetFillStyle (s->display, s->gc, FillSolid); | |
2672 s->background_filled_p = 1; | |
2673 } | |
2674 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width | |
2675 || s->font_not_found_p | |
2676 || s->extends_to_end_of_line_p | |
2677 || s->cmpcharp | |
2678 || force_p) | |
2679 { | |
2680 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width, | |
2681 s->background_width, | |
2682 s->height - 2 * s->face->box_line_width); | |
2683 s->background_filled_p = 1; | |
2684 } | |
2685 } | |
2686 } | |
2687 | |
2688 | |
2689 /* Draw the foreground of glyph string S. */ | |
2690 | |
2691 static void | |
2692 x_draw_glyph_string_foreground (s) | |
2693 struct glyph_string *s; | |
2694 { | |
2695 int i, x; | |
2696 | |
2697 /* If first glyph of S has a left box line, start drawing the text | |
2698 of S to the right of that box line. */ | |
2699 if (s->face->box != FACE_NO_BOX | |
2700 && s->first_glyph->left_box_line_p) | |
2701 x = s->x + s->face->box_line_width; | |
2702 else | |
2703 x = s->x; | |
2704 | |
2705 if (s->cmpcharp == NULL) | |
2706 { | |
2707 /* Not a composite character. Draw characters of S as | |
2708 rectangles if S's font could not be loaded. */ | |
2709 if (s->font_not_found_p) | |
2710 { | |
2711 for (i = 0; i < s->nchars; ++i) | |
2712 { | |
2713 struct glyph *g = s->first_glyph + i; | |
2714 XDrawRectangle (s->display, s->window, | |
2715 s->gc, x, s->y, g->pixel_width - 1, | |
2716 s->height - 1); | |
2717 x += g->pixel_width; | |
2718 } | |
2719 } | |
2720 else | |
2721 { | |
2722 char *char1b = (char *) s->char2b; | |
2723 | |
2724 /* If we can use 8-bit functions, condense S->char2b. */ | |
2725 if (!s->two_byte_p) | |
2726 for (i = 0; i < s->nchars; ++i) | |
2727 char1b[i] = s->char2b[i].byte2; | |
2728 | |
2729 /* Draw text with XDrawString if background has already been | |
2730 filled. Otherwise, use XDrawImageString. (Note that | |
2731 XDrawImageString is usually faster than XDrawString.) | |
2732 Always use XDrawImageString when drawing the cursor so | |
2733 that there is no chance that characters under a box | |
2734 cursor are invisible. */ | |
2735 if (s->background_filled_p && s->hl != DRAW_CURSOR) | |
2736 { | |
2737 /* Draw characters with 16-bit or 8-bit functions. */ | |
2738 if (s->two_byte_p) | |
2739 XDrawString16 (s->display, s->window, s->gc, x, s->ybase, | |
2740 s->char2b, s->nchars); | |
2741 else | |
2742 XDrawString (s->display, s->window, s->gc, x, s->ybase, | |
2743 char1b, s->nchars); | |
2744 } | |
2745 else | |
2746 { | |
2747 if (s->two_byte_p) | |
2748 XDrawImageString16 (s->display, s->window, s->gc, | |
2749 x, s->ybase, s->char2b, s->nchars); | |
2750 else | |
2751 XDrawImageString (s->display, s->window, s->gc, | |
2752 x, s->ybase, char1b, s->nchars); | |
2753 } | |
2754 } | |
2755 } | |
2756 else | |
2757 { | |
2758 /* S is a glyph string for a composite character. S->gidx is the | |
2759 index of the first character drawn in the vector | |
2760 S->cmpcharp->glyph. S->gidx == 0 means we are drawing the | |
2761 very first component character of a composite char. */ | |
2762 | |
2763 /* Draw a single rectangle for the composite character if S's | |
2764 font could not be loaded. */ | |
2765 if (s->font_not_found_p && s->gidx == 0) | |
2766 XDrawRectangle (s->display, s->window, s->gc, x, s->y, | |
2767 s->width - 1, s->height - 1); | |
2768 else | |
2769 { | |
2770 XCharStruct *pcm; | |
2771 int relative_compose, default_ascent, i; | |
2772 int highest = 0, lowest = 0; | |
2773 | |
2774 /* The value of font_info my be null if we couldn't find it | |
2775 in x_get_char_face_and_encoding. */ | |
2776 if (s->cmpcharp->cmp_rule == NULL && s->font_info) | |
2777 { | |
2778 relative_compose = s->font_info->relative_compose; | |
2779 default_ascent = s->font_info->default_ascent; | |
2780 } | |
2781 else | |
2782 relative_compose = default_ascent = 0; | |
2783 | |
2784 if ((s->cmpcharp->cmp_rule || relative_compose) | |
2785 && s->gidx == 0) | |
2786 { | |
2787 /* This is the first character. Initialize variables. | |
2788 Highest is the highest position of glyphs ever | |
2789 written, lowest the lowest position. */ | |
2790 int x_offset = 0; | |
2791 int first_ch = s->first_glyph->u.ch.code; | |
2792 | |
2793 if (default_ascent | |
2794 && CHAR_TABLE_P (Vuse_default_ascent) | |
2795 && !NILP (Faref (Vuse_default_ascent, first_ch))) | |
2796 { | |
2797 highest = default_ascent; | |
2798 lowest = 0; | |
2799 } | |
2800 else | |
2801 { | |
2802 pcm = PER_CHAR_METRIC (s->font, s->char2b); | |
2803 highest = pcm->ascent + 1; | |
2804 lowest = - pcm->descent; | |
2805 } | |
2806 | |
2807 if (s->cmpcharp->cmp_rule) | |
2808 x_offset = (s->cmpcharp->col_offset[0] | |
2809 * FONT_WIDTH (s->f->output_data.x->font)); | |
2810 | |
2811 /* Draw the first character at the normal position. */ | |
2812 XDrawString16 (s->display, s->window, s->gc, | |
2813 x + x_offset, | |
2814 s->ybase, s->char2b, 1); | |
2815 i = 1; | |
2816 ++s->gidx; | |
2817 } | |
2818 else | |
2819 i = 0; | |
2820 | |
2821 for (; i < s->nchars; i++, ++s->gidx) | |
2822 { | |
2823 int x_offset = 0, y_offset = 0; | |
2824 | |
2825 if (relative_compose) | |
2826 { | |
2827 pcm = PER_CHAR_METRIC (s->font, s->char2b + i); | |
2828 if (NILP (Vignore_relative_composition) | |
2829 || NILP (Faref (Vignore_relative_composition, | |
2830 make_number (s->cmpcharp->glyph[s->gidx])))) | |
2831 { | |
2832 if (- pcm->descent >= relative_compose) | |
2833 { | |
2834 /* Draw above the current glyphs. */ | |
2835 y_offset = highest + pcm->descent; | |
2836 highest += pcm->ascent + pcm->descent; | |
2837 } | |
2838 else if (pcm->ascent <= 0) | |
2839 { | |
2840 /* Draw beneath the current glyphs. */ | |
2841 y_offset = lowest - pcm->ascent; | |
2842 lowest -= pcm->ascent + pcm->descent; | |
2843 } | |
2844 } | |
2845 else | |
2846 { | |
2847 /* Draw the glyph at normal position. If | |
2848 it sticks out of HIGHEST or LOWEST, | |
2849 update them appropriately. */ | |
2850 if (pcm->ascent > highest) | |
2851 highest = pcm->ascent; | |
2852 else if (- pcm->descent < lowest) | |
2853 lowest = - pcm->descent; | |
2854 } | |
2855 } | |
2856 else if (s->cmpcharp->cmp_rule) | |
2857 { | |
2858 int gref = (s->cmpcharp->cmp_rule[s->gidx] - 0xA0) / 9; | |
2859 int nref = (s->cmpcharp->cmp_rule[s->gidx] - 0xA0) % 9; | |
2860 int bottom, top; | |
2861 | |
2862 /* Re-encode GREF and NREF so that they specify | |
2863 only Y-axis information: | |
2864 0:top, 1:base, 2:bottom, 3:center */ | |
2865 gref = gref / 3 + (gref == 4) * 2; | |
2866 nref = nref / 3 + (nref == 4) * 2; | |
2867 | |
2868 pcm = PER_CHAR_METRIC (s->font, s->char2b + i); | |
2869 bottom = ((gref == 0 ? highest : gref == 1 ? 0 | |
2870 : gref == 2 ? lowest | |
2871 : (highest + lowest) / 2) | |
2872 - (nref == 0 ? pcm->ascent + pcm->descent | |
2873 : nref == 1 ? pcm->descent : nref == 2 ? 0 | |
2874 : (pcm->ascent + pcm->descent) / 2)); | |
2875 top = bottom + (pcm->ascent + pcm->descent); | |
2876 if (top > highest) | |
2877 highest = top; | |
2878 if (bottom < lowest) | |
2879 lowest = bottom; | |
2880 y_offset = bottom + pcm->descent; | |
2881 x_offset = (s->cmpcharp->col_offset[s->gidx] | |
2882 * FONT_WIDTH (FRAME_FONT (s->f))); | |
2883 } | |
2884 | |
2885 XDrawString16 (s->display, s->window, s->gc, | |
2886 x + x_offset, s->ybase - y_offset, | |
2887 s->char2b + i, 1); | |
2888 } | |
2889 } | |
2890 } | |
2891 } | |
2892 | |
2893 | |
2894 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap | |
2895 CMAP. If an exact match can't be allocated, try the nearest color | |
2896 available. Value is non-zero if successful. Set *COLOR to the | |
2897 color allocated. */ | |
2898 | |
2899 int | |
2900 x_alloc_nearest_color (display, screen, cmap, color) | |
2901 Display *display; | |
2902 Screen *screen; | |
2903 Colormap cmap; | |
2904 XColor *color; | |
2905 { | |
2906 int rc = XAllocColor (display, cmap, color); | |
2907 if (rc == 0) | |
2908 { | |
2909 /* If we got to this point, the colormap is full, so we're going | |
2910 to try to get the next closest color. The algorithm used is | |
2911 a least-squares matching, which is what X uses for closest | |
2912 color matching with StaticColor visuals. */ | |
2913 int nearest, i; | |
2914 unsigned long nearest_delta = ~0; | |
2915 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen)); | |
2916 XColor *cells = (XColor *) alloca (ncells * sizeof *cells); | |
2917 | |
2918 for (i = 0; i < ncells; ++i) | |
2919 cells[i].pixel = i; | |
2920 XQueryColors (display, cmap, cells, ncells); | |
2921 | |
2922 for (nearest = i = 0; i < ncells; ++i) | |
2923 { | |
2924 long dred = (color->red >> 8) - (cells[i].red >> 8); | |
2925 long dgreen = (color->green >> 8) - (cells[i].green >> 8); | |
2926 long dblue = (color->blue >> 8) - (cells[i].blue >> 8); | |
2927 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue; | |
2928 | |
2929 if (delta < nearest_delta) | |
2930 { | |
2931 nearest = i; | |
2932 nearest_delta = delta; | |
2933 } | |
2934 } | |
2935 | |
2936 color->red = cells[nearest].red; | |
2937 color->green = cells[nearest].green; | |
2938 color->blue = cells[nearest].blue; | |
2939 rc = XAllocColor (display, cmap, color); | |
2940 } | |
2941 | |
2942 return rc; | |
2943 } | |
2944 | |
2945 | |
2946 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR | |
2947 or DELTA. Try a color with RGB values multiplied by FACTOR first. | |
2948 If this produces the same color as PIXEL, try a color where all RGB | |
2949 values have DELTA added. Return the allocated color in *PIXEL. | |
2950 DISPLAY is the X display, CMAP is the colormap to operate on. | |
2951 Value is non-zero if successful. */ | |
2952 | |
2953 static int | |
2954 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta) | |
548 struct frame *f; | 2955 struct frame *f; |
549 int left, top; | 2956 Display *display; |
550 register GLYPH *gp; /* Points to first GLYPH. */ | 2957 Colormap cmap; |
551 register int n; /* Number of glyphs to display. */ | 2958 unsigned long *pixel; |
552 int hl; | 2959 float factor; |
553 int just_foreground; | 2960 int delta; |
554 struct cmpchar_info *cmpcharp; | 2961 { |
555 { | 2962 XColor color, new; |
556 /* Holds characters to be displayed. */ | 2963 int success_p; |
557 XChar2b *x_2byte_buffer | 2964 |
558 = (XChar2b *) alloca (FRAME_WINDOW_WIDTH (f) * sizeof (*x_2byte_buffer)); | 2965 /* Get RGB color values. */ |
559 register XChar2b *cp; /* Steps through x_2byte_buffer[]. */ | 2966 color.pixel = *pixel; |
560 char *x_1byte_buffer | 2967 XQueryColor (display, cmap, &color); |
561 = (char *) alloca (FRAME_WINDOW_WIDTH (f) * sizeof (*x_1byte_buffer)); | 2968 |
562 register int tlen = GLYPH_TABLE_LENGTH; | 2969 /* Change RGB values by specified FACTOR. Avoid overflow! */ |
563 register Lisp_Object *tbase = GLYPH_TABLE_BASE; | 2970 xassert (factor >= 0); |
564 Window window = FRAME_X_WINDOW (f); | 2971 new.red = min (0xffff, factor * color.red); |
565 int orig_left = left; | 2972 new.green = min (0xffff, factor * color.green); |
566 int gidx = 0; | 2973 new.blue = min (0xffff, factor * color.blue); |
2974 | |
2975 /* Try to allocate the color. */ | |
2976 success_p = x_alloc_nearest_color (display, FRAME_X_SCREEN (f), cmap, &new); | |
2977 if (success_p) | |
2978 { | |
2979 if (new.pixel == *pixel) | |
2980 { | |
2981 /* If we end up with the same color as before, try adding | |
2982 delta to the RGB values. */ | |
2983 int class = FRAME_X_DISPLAY_INFO (f)->visual->class; | |
2984 | |
2985 /* If display has an immutable color map, freeing colors is | |
2986 not necessary and some servers don't allow it. So don't | |
2987 do it. */ | |
2988 if (class != StaticColor | |
2989 && class != StaticGray | |
2990 && class != TrueColor) | |
2991 XFreeColors (display, cmap, &new.pixel, 1, 0); | |
2992 | |
2993 new.red = min (0xffff, delta + color.red); | |
2994 new.green = min (0xffff, delta + color.green); | |
2995 new.blue = min (0xffff, delta + color.blue); | |
2996 success_p = x_alloc_nearest_color (display, FRAME_X_SCREEN (f), | |
2997 cmap, &new); | |
2998 } | |
2999 else | |
3000 success_p = 1; | |
3001 *pixel = new.pixel; | |
3002 } | |
3003 | |
3004 return success_p; | |
3005 } | |
3006 | |
3007 | |
3008 /* Set up the foreground color for drawing relief lines of glyph | |
3009 string S. RELIEF is a pointer to a struct relief containing the GC | |
3010 with which lines will be drawn. Use a color that is FACTOR or | |
3011 DELTA lighter or darker than the relief's background which is found | |
3012 in S->f->output_data.x->relief_background. If such a color cannot | |
3013 be allocated, use DEFAULT_PIXEL, instead. */ | |
3014 | |
3015 static void | |
3016 x_setup_relief_color (f, relief, factor, delta, default_pixel) | |
3017 struct frame *f; | |
3018 struct relief *relief; | |
3019 float factor; | |
3020 int delta; | |
3021 unsigned long default_pixel; | |
3022 { | |
3023 XGCValues xgcv; | |
3024 struct x_output *di = f->output_data.x; | |
3025 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures; | |
3026 unsigned long pixel; | |
3027 unsigned long background = di->relief_background; | |
3028 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f)); | |
3029 | |
3030 xgcv.graphics_exposures = False; | |
3031 xgcv.line_width = 1; | |
3032 | |
3033 /* Free previously allocated color. The color cell will be reused | |
3034 when it has been freed as many times as it was allocated, so this | |
3035 doesn't affect faces using the same colors. */ | |
3036 if (relief->gc | |
3037 && relief->allocated_p) | |
3038 { | |
3039 /* If display has an immutable color map, freeing colors is not | |
3040 necessary and some servers don't allow it. So don't do it. */ | |
3041 int class = FRAME_X_DISPLAY_INFO (f)->visual->class; | |
3042 if (class != StaticColor | |
3043 && class != StaticGray | |
3044 && class != TrueColor) | |
3045 XFreeColors (FRAME_X_DISPLAY (f), cmap, &relief->pixel, 1, 0); | |
3046 relief->allocated_p = 0; | |
3047 } | |
3048 | |
3049 /* Allocate new color. */ | |
3050 xgcv.foreground = default_pixel; | |
3051 pixel = background; | |
3052 if (x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), cmap, &pixel, | |
3053 factor, delta)) | |
3054 { | |
3055 relief->allocated_p = 1; | |
3056 xgcv.foreground = relief->pixel = pixel; | |
3057 } | |
3058 | |
3059 if (relief->gc == 0) | |
3060 { | |
3061 xgcv.stipple = FRAME_X_DISPLAY_INFO (f)->gray; | |
3062 mask |= GCStipple; | |
3063 relief->gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
3064 mask, &xgcv); | |
3065 } | |
3066 else | |
3067 XChangeGC (FRAME_X_DISPLAY (f), relief->gc, mask, &xgcv); | |
3068 } | |
3069 | |
3070 | |
3071 /* Set up colors for the relief lines around glyph string S. */ | |
3072 | |
3073 static void | |
3074 x_setup_relief_colors (s) | |
3075 struct glyph_string *s; | |
3076 { | |
3077 struct x_output *di = s->f->output_data.x; | |
3078 unsigned long color; | |
3079 | |
3080 if (s->face->use_box_color_for_shadows_p) | |
3081 color = s->face->box_color; | |
3082 else | |
3083 { | |
3084 XGCValues xgcv; | |
3085 | |
3086 /* Get the background color of the face. */ | |
3087 XGetGCValues (s->display, s->gc, GCBackground, &xgcv); | |
3088 color = xgcv.background; | |
3089 } | |
3090 | |
3091 if (di->white_relief.gc == 0 | |
3092 || color != di->relief_background) | |
3093 { | |
3094 di->relief_background = color; | |
3095 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000, | |
3096 WHITE_PIX_DEFAULT (s->f)); | |
3097 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000, | |
3098 BLACK_PIX_DEFAULT (s->f)); | |
3099 } | |
3100 } | |
3101 | |
3102 | |
3103 /* Draw a relief on frame F inside the rectangle given by LEFT_X, | |
3104 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief | |
3105 to draw, it must be >= 0. RAISED_P non-zero means draw a raised | |
3106 relief. LEFT_P non-zero means draw a relief on the left side of | |
3107 the rectangle. RIGHT_P non-zero means draw a relief on the right | |
3108 side of the rectangle. CLIP_RECT is the clipping rectangle to use | |
3109 when drawing. */ | |
3110 | |
3111 static void | |
3112 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, | |
3113 raised_p, left_p, right_p, clip_rect) | |
3114 struct frame *f; | |
3115 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p; | |
3116 XRectangle *clip_rect; | |
3117 { | |
567 int i; | 3118 int i; |
568 | 3119 GC gc; |
569 while (n > 0) | 3120 |
570 { | 3121 if (raised_p) |
571 /* Get the face-code of the next GLYPH. */ | 3122 gc = f->output_data.x->white_relief.gc; |
572 int cf, len; | 3123 else |
573 GLYPH g = *gp; | 3124 gc = f->output_data.x->black_relief.gc; |
574 int ch, charset; | 3125 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted); |
575 Lisp_Object first_ch; | 3126 |
576 /* HIGHEST and LOWEST are used while drawing a composite | 3127 /* Top. */ |
577 character. The meanings are described later. */ | 3128 for (i = 0; i < width; ++i) |
578 int highest, lowest; | 3129 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
579 | 3130 left_x + i * left_p, top_y + i, |
580 GLYPH_FOLLOW_ALIASES (tbase, tlen, g); | 3131 right_x + 1 - i * right_p, top_y + i); |
581 cf = (cmpcharp ? cmpcharp->face_work : FAST_GLYPH_FACE (g)); | 3132 |
582 ch = FAST_GLYPH_CHAR (g); | 3133 /* Left. */ |
583 if (unibyte_display_via_language_environment | 3134 if (left_p) |
584 && SINGLE_BYTE_CHAR_P (ch) | 3135 for (i = 0; i < width; ++i) |
585 && (ch >= 0240 | 3136 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
586 || (ch >= 0200 && !NILP (Vnonascii_translation_table)))) | 3137 left_x + i, top_y + i, left_x + i, bottom_y - i); |
587 ch = unibyte_char_to_multibyte (ch); | 3138 |
588 if (gidx == 0) XSETFASTINT (first_ch, ch); | 3139 XSetClipMask (FRAME_X_DISPLAY (f), gc, None); |
589 charset = CHAR_CHARSET (ch); | 3140 if (raised_p) |
590 if (charset == CHARSET_COMPOSITION) | 3141 gc = f->output_data.x->black_relief.gc; |
3142 else | |
3143 gc = f->output_data.x->white_relief.gc; | |
3144 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted); | |
3145 | |
3146 /* Bottom. */ | |
3147 for (i = 0; i < width; ++i) | |
3148 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | |
3149 left_x + i * left_p, bottom_y - i, | |
3150 right_x + 1 - i * right_p, bottom_y - i); | |
3151 | |
3152 /* Right. */ | |
3153 if (right_p) | |
3154 for (i = 0; i < width; ++i) | |
3155 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | |
3156 right_x - i, top_y + i + 1, right_x - i, bottom_y - i); | |
3157 | |
3158 XSetClipMask (FRAME_X_DISPLAY (f), gc, None); | |
3159 } | |
3160 | |
3161 | |
3162 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y, | |
3163 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to | |
3164 draw, it must be >= 0. LEFT_P non-zero means draw a line on the | |
3165 left side of the rectangle. RIGHT_P non-zero means draw a line | |
3166 on the right side of the rectangle. CLIP_RECT is the clipping | |
3167 rectangle to use when drawing. */ | |
3168 | |
3169 static void | |
3170 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, | |
3171 left_p, right_p, clip_rect) | |
3172 struct glyph_string *s; | |
3173 int left_x, top_y, right_x, bottom_y, left_p, right_p; | |
3174 XRectangle *clip_rect; | |
3175 { | |
3176 XGCValues xgcv; | |
3177 | |
3178 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); | |
3179 XSetForeground (s->display, s->gc, s->face->box_color); | |
3180 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted); | |
3181 | |
3182 /* Top. */ | |
3183 XFillRectangle (s->display, s->window, s->gc, | |
3184 left_x, top_y, right_x - left_x, width); | |
3185 | |
3186 /* Left. */ | |
3187 if (left_p) | |
3188 XFillRectangle (s->display, s->window, s->gc, | |
3189 left_x, top_y, width, bottom_y - top_y); | |
3190 | |
3191 /* Bottom. */ | |
3192 XFillRectangle (s->display, s->window, s->gc, | |
3193 left_x, bottom_y - width, right_x - left_x, width); | |
3194 | |
3195 /* Right. */ | |
3196 if (right_p) | |
3197 XFillRectangle (s->display, s->window, s->gc, | |
3198 right_x - width, top_y, width, bottom_y - top_y); | |
3199 | |
3200 XSetForeground (s->display, s->gc, xgcv.foreground); | |
3201 XSetClipMask (s->display, s->gc, None); | |
3202 } | |
3203 | |
3204 | |
3205 /* Draw a box around glyph string S. */ | |
3206 | |
3207 static void | |
3208 x_draw_glyph_string_box (s) | |
3209 struct glyph_string *s; | |
3210 { | |
3211 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p; | |
3212 int left_p, right_p; | |
3213 struct glyph *last_glyph; | |
3214 XRectangle clip_rect; | |
3215 | |
3216 last_x = window_box_right (s->w, s->area); | |
3217 if (s->row->full_width_p | |
3218 && !s->w->pseudo_window_p) | |
3219 { | |
3220 last_x += FRAME_X_FLAGS_AREA_WIDTH (s->f); | |
3221 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f)) | |
3222 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f); | |
3223 } | |
3224 | |
3225 /* The glyph that may have a right box line. */ | |
3226 last_glyph = (s->cmpcharp || s->img | |
3227 ? s->first_glyph | |
3228 : s->first_glyph + s->nchars - 1); | |
3229 | |
3230 width = s->face->box_line_width; | |
3231 raised_p = s->face->box == FACE_RAISED_BOX; | |
3232 left_x = s->x; | |
3233 right_x = ((s->row->full_width_p | |
3234 ? last_x | |
3235 : min (last_x, s->x + s->width) - 1)); | |
3236 top_y = s->y; | |
3237 bottom_y = top_y + s->height - 1; | |
3238 | |
3239 left_p = (s->first_glyph->left_box_line_p | |
3240 || (s->hl == DRAW_MOUSE_FACE | |
3241 && (s->prev == NULL | |
3242 || s->prev->hl != s->hl))); | |
3243 right_p = (last_glyph->right_box_line_p | |
3244 || (s->hl == DRAW_MOUSE_FACE | |
3245 && (s->next == NULL | |
3246 || s->next->hl != s->hl))); | |
3247 | |
3248 x_get_glyph_string_clip_rect (s, &clip_rect); | |
3249 | |
3250 if (s->face->box == FACE_SIMPLE_BOX) | |
3251 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, | |
3252 left_p, right_p, &clip_rect); | |
3253 else | |
3254 { | |
3255 x_setup_relief_colors (s); | |
3256 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, | |
3257 width, raised_p, left_p, right_p, &clip_rect); | |
3258 } | |
3259 } | |
3260 | |
3261 | |
3262 /* Draw foreground of image glyph string S. */ | |
3263 | |
3264 static void | |
3265 x_draw_image_foreground (s) | |
3266 struct glyph_string *s; | |
3267 { | |
3268 int x; | |
3269 int y = s->ybase - IMAGE_ASCENT (s->img); | |
3270 | |
3271 /* If first glyph of S has a left box line, start drawing it to the | |
3272 right of that line. */ | |
3273 if (s->face->box != FACE_NO_BOX | |
3274 && s->first_glyph->left_box_line_p) | |
3275 x = s->x + s->face->box_line_width; | |
3276 else | |
3277 x = s->x; | |
3278 | |
3279 /* If there is a margin around the image, adjust x- and y-position | |
3280 by that margin. */ | |
3281 if (s->img->margin) | |
3282 { | |
3283 x += s->img->margin; | |
3284 y += s->img->margin; | |
3285 } | |
3286 | |
3287 if (s->img->pixmap) | |
3288 { | |
3289 if (s->img->mask) | |
591 { | 3290 { |
592 /* We must draw components of the composite character on the | 3291 /* We can't set both a clip mask and use XSetClipRectangles |
593 same column. */ | 3292 because the latter also sets a clip mask. We also can't |
594 cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (ch)]; | 3293 trust on the shape extension to be available |
595 | 3294 (XShapeCombineRegion). So, compute the rectangle to draw |
596 /* Set the face in the slot for work. */ | 3295 manually. */ |
597 cmpcharp->face_work = cf; | 3296 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin |
598 | 3297 | GCFunction); |
599 /* We don't need the return value ... */ | 3298 XGCValues xgcv; |
600 dumpglyphs (f, left, top, cmpcharp->glyph, cmpcharp->glyph_len, | 3299 XRectangle clip_rect, image_rect, r; |
601 hl, just_foreground, cmpcharp); | 3300 |
602 /* ... because the width of just drawn text can be | 3301 xgcv.clip_mask = s->img->mask; |
603 calculated as follows. */ | 3302 xgcv.clip_x_origin = x; |
604 left += FONT_WIDTH (f->output_data.x->font) * cmpcharp->width; | 3303 xgcv.clip_y_origin = y; |
605 | 3304 xgcv.function = GXcopy; |
606 ++gp, --n; | 3305 XChangeGC (s->display, s->gc, mask, &xgcv); |
607 while (gp && (*gp & GLYPH_MASK_PADDING)) ++gp, --n; | 3306 |
608 cmpcharp = NULL; | 3307 x_get_glyph_string_clip_rect (s, &clip_rect); |
609 continue; | 3308 image_rect.x = x; |
3309 image_rect.y = y; | |
3310 image_rect.width = s->img->width; | |
3311 image_rect.height = s->img->height; | |
3312 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) | |
3313 XCopyArea (s->display, s->img->pixmap, s->window, s->gc, | |
3314 r.x - x, r.y - y, r.width, r.height, r.x, r.y); | |
610 } | 3315 } |
611 | 3316 else |
612 /* Find the run of consecutive glyphs which can be drawn with | |
613 the same GC (i.e. the same charset and the same face-code). | |
614 Extract their character codes into X_2BYTE_BUFFER. | |
615 If CMPCHARP is not NULL, face-code is not checked because we | |
616 use only the face specified in `cmpcharp->face_work'. */ | |
617 cp = x_2byte_buffer; | |
618 while (n > 0) | |
619 { | 3317 { |
620 int this_charset, c1, c2; | 3318 XCopyArea (s->display, s->img->pixmap, s->window, s->gc, |
621 | 3319 0, 0, s->img->width, s->img->height, x, y); |
622 g = *gp; | 3320 |
623 GLYPH_FOLLOW_ALIASES (tbase, tlen, g); | 3321 /* When the image has a mask, we can expect that at |
624 ch = FAST_GLYPH_CHAR (g); | 3322 least part of a mouse highlight or a block cursor will |
625 if (unibyte_display_via_language_environment | 3323 be visible. If the image doesn't have a mask, make |
626 && SINGLE_BYTE_CHAR_P (ch) | 3324 a block cursor visible by drawing a rectangle around |
627 && (ch >= 0240 | 3325 the image. I believe it's looking better if we do |
628 || (ch >= 0200 && !NILP (Vnonascii_translation_table)))) | 3326 nothing here for mouse-face. */ |
629 ch = unibyte_char_to_multibyte (ch); | 3327 if (s->hl == DRAW_CURSOR) |
630 SPLIT_CHAR (ch, this_charset, c1, c2); | 3328 XDrawRectangle (s->display, s->window, s->gc, x, y, |
631 if (this_charset != charset | 3329 s->img->width - 1, s->img->height - 1); |
632 || (cmpcharp == NULL && FAST_GLYPH_FACE (g) != cf)) | 3330 } |
633 break; | 3331 } |
634 | 3332 else |
635 if (c2 > 0) | 3333 /* Draw a rectangle if image could not be loaded. */ |
636 cp->byte1 = c1, cp->byte2 = c2; | 3334 XDrawRectangle (s->display, s->window, s->gc, x, y, |
3335 s->img->width - 1, s->img->height - 1); | |
3336 } | |
3337 | |
3338 | |
3339 /* Draw a relief around the image glyph string S. */ | |
3340 | |
3341 static void | |
3342 x_draw_image_relief (s) | |
3343 struct glyph_string *s; | |
3344 { | |
3345 int x0, y0, x1, y1, thick, raised_p; | |
3346 XRectangle r; | |
3347 int x; | |
3348 int y = s->ybase - IMAGE_ASCENT (s->img); | |
3349 | |
3350 /* If first glyph of S has a left box line, start drawing it to the | |
3351 right of that line. */ | |
3352 if (s->face->box != FACE_NO_BOX | |
3353 && s->first_glyph->left_box_line_p) | |
3354 x = s->x + s->face->box_line_width; | |
3355 else | |
3356 x = s->x; | |
3357 | |
3358 /* If there is a margin around the image, adjust x- and y-position | |
3359 by that margin. */ | |
3360 if (s->img->margin) | |
3361 { | |
3362 x += s->img->margin; | |
3363 y += s->img->margin; | |
3364 } | |
3365 | |
3366 if (s->hl == DRAW_IMAGE_SUNKEN | |
3367 || s->hl == DRAW_IMAGE_RAISED) | |
3368 { | |
3369 thick = toolbar_button_relief > 0 ? toolbar_button_relief : 3; | |
3370 raised_p = s->hl == DRAW_IMAGE_RAISED; | |
3371 } | |
3372 else | |
3373 { | |
3374 thick = abs (s->img->relief); | |
3375 raised_p = s->img->relief > 0; | |
3376 } | |
3377 | |
3378 x0 = x - thick; | |
3379 y0 = y - thick; | |
3380 x1 = x + s->img->width + thick - 1; | |
3381 y1 = y + s->img->height + thick - 1; | |
3382 | |
3383 x_setup_relief_colors (s); | |
3384 x_get_glyph_string_clip_rect (s, &r); | |
3385 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r); | |
3386 } | |
3387 | |
3388 | |
3389 /* Draw the foreground of image glyph string S to PIXMAP. */ | |
3390 | |
3391 static void | |
3392 x_draw_image_foreground_1 (s, pixmap) | |
3393 struct glyph_string *s; | |
3394 Pixmap pixmap; | |
3395 { | |
3396 int x; | |
3397 int y = s->ybase - s->y - IMAGE_ASCENT (s->img); | |
3398 | |
3399 /* If first glyph of S has a left box line, start drawing it to the | |
3400 right of that line. */ | |
3401 if (s->face->box != FACE_NO_BOX | |
3402 && s->first_glyph->left_box_line_p) | |
3403 x = s->face->box_line_width; | |
3404 else | |
3405 x = 0; | |
3406 | |
3407 /* If there is a margin around the image, adjust x- and y-position | |
3408 by that margin. */ | |
3409 if (s->img->margin) | |
3410 { | |
3411 x += s->img->margin; | |
3412 y += s->img->margin; | |
3413 } | |
3414 | |
3415 if (s->img->pixmap) | |
3416 { | |
3417 if (s->img->mask) | |
3418 { | |
3419 /* We can't set both a clip mask and use XSetClipRectangles | |
3420 because the latter also sets a clip mask. We also can't | |
3421 trust on the shape extension to be available | |
3422 (XShapeCombineRegion). So, compute the rectangle to draw | |
3423 manually. */ | |
3424 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin | |
3425 | GCFunction); | |
3426 XGCValues xgcv; | |
3427 | |
3428 xgcv.clip_mask = s->img->mask; | |
3429 xgcv.clip_x_origin = x; | |
3430 xgcv.clip_y_origin = y; | |
3431 xgcv.function = GXcopy; | |
3432 XChangeGC (s->display, s->gc, mask, &xgcv); | |
3433 | |
3434 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc, | |
3435 0, 0, s->img->width, s->img->height, x, y); | |
3436 XSetClipMask (s->display, s->gc, None); | |
3437 } | |
3438 else | |
3439 { | |
3440 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc, | |
3441 0, 0, s->img->width, s->img->height, x, y); | |
3442 | |
3443 /* When the image has a mask, we can expect that at | |
3444 least part of a mouse highlight or a block cursor will | |
3445 be visible. If the image doesn't have a mask, make | |
3446 a block cursor visible by drawing a rectangle around | |
3447 the image. I believe it's looking better if we do | |
3448 nothing here for mouse-face. */ | |
3449 if (s->hl == DRAW_CURSOR) | |
3450 XDrawRectangle (s->display, pixmap, s->gc, x, y, | |
3451 s->img->width - 1, s->img->height - 1); | |
3452 } | |
3453 } | |
3454 else | |
3455 /* Draw a rectangle if image could not be loaded. */ | |
3456 XDrawRectangle (s->display, pixmap, s->gc, x, y, | |
3457 s->img->width - 1, s->img->height - 1); | |
3458 } | |
3459 | |
3460 | |
3461 /* Draw part of the background of glyph string S. X, Y, W, and H | |
3462 give the rectangle to draw. */ | |
3463 | |
3464 static void | |
3465 x_draw_glyph_string_bg_rect (s, x, y, w, h) | |
3466 struct glyph_string *s; | |
3467 int x, y, w, h; | |
3468 { | |
3469 if (s->stippled_p) | |
3470 { | |
3471 /* Fill background with a stipple pattern. */ | |
3472 XSetFillStyle (s->display, s->gc, FillOpaqueStippled); | |
3473 XFillRectangle (s->display, s->window, s->gc, x, y, w, h); | |
3474 XSetFillStyle (s->display, s->gc, FillSolid); | |
3475 } | |
3476 else | |
3477 x_clear_glyph_string_rect (s, x, y, w, h); | |
3478 } | |
3479 | |
3480 | |
3481 /* Draw image glyph string S. | |
3482 | |
3483 s->y | |
3484 s->x +------------------------- | |
3485 | s->face->box | |
3486 | | |
3487 | +------------------------- | |
3488 | | s->img->margin | |
3489 | | | |
3490 | | +------------------- | |
3491 | | | the image | |
3492 | |
3493 */ | |
3494 | |
3495 static void | |
3496 x_draw_image_glyph_string (s) | |
3497 struct glyph_string *s; | |
3498 { | |
3499 int x, y; | |
3500 int box_line_width = s->face->box_line_width; | |
3501 int margin = s->img->margin; | |
3502 int height; | |
3503 Pixmap pixmap = None; | |
3504 | |
3505 height = s->height - 2 * box_line_width; | |
3506 | |
3507 /* Fill background with face under the image. Do it only if row is | |
3508 taller than image or if image has a clip mask to reduce | |
3509 flickering. */ | |
3510 s->stippled_p = s->face->stipple != 0; | |
3511 if (height > s->img->height | |
3512 || margin | |
3513 || s->img->mask | |
3514 || s->img->pixmap == 0 | |
3515 || s->width != s->background_width) | |
3516 { | |
3517 if (box_line_width && s->first_glyph->left_box_line_p) | |
3518 x = s->x + box_line_width; | |
3519 else | |
3520 x = s->x; | |
3521 | |
3522 y = s->y + box_line_width; | |
3523 | |
3524 if (s->img->mask) | |
3525 { | |
3526 /* Create a pixmap as large as the glyph string Fill it with | |
3527 the background color. Copy the image to it, using its | |
3528 mask. Copy the temporary pixmap to the display. */ | |
3529 Screen *screen = FRAME_X_SCREEN (s->f); | |
3530 int depth = DefaultDepthOfScreen (screen); | |
3531 | |
3532 /* Create a pixmap as large as the glyph string. */ | |
3533 pixmap = XCreatePixmap (s->display, s->window, | |
3534 s->background_width, | |
3535 s->height, depth); | |
3536 | |
3537 /* Don't clip in the following because we're working on the | |
3538 pixmap. */ | |
3539 XSetClipMask (s->display, s->gc, None); | |
3540 | |
3541 /* Fill the pixmap with the background color/stipple. */ | |
3542 if (s->stippled_p) | |
3543 { | |
3544 /* Fill background with a stipple pattern. */ | |
3545 XSetFillStyle (s->display, s->gc, FillOpaqueStippled); | |
3546 XFillRectangle (s->display, pixmap, s->gc, | |
3547 0, 0, s->background_width, s->height); | |
3548 XSetFillStyle (s->display, s->gc, FillSolid); | |
3549 } | |
637 else | 3550 else |
638 cp->byte1 = 0, cp->byte2 = c1; | 3551 { |
639 ++cp; | 3552 XGCValues xgcv; |
640 ++gp, --n; | 3553 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, |
641 while (gp && (*gp & GLYPH_MASK_PADDING)) | 3554 &xgcv); |
642 ++gp, --n; | 3555 XSetForeground (s->display, s->gc, xgcv.background); |
3556 XFillRectangle (s->display, pixmap, s->gc, | |
3557 0, 0, s->background_width, s->height); | |
3558 XSetForeground (s->display, s->gc, xgcv.foreground); | |
3559 } | |
643 } | 3560 } |
644 | 3561 else |
645 /* LEN gets the length of the run. */ | 3562 /* Implementation idea: Is it possible to construct a mask? |
646 len = cp - x_2byte_buffer; | 3563 We could look at the color at the margins of the image, and |
647 /* Now output this run of chars, with the font and pixel values | 3564 say that this color is probably the background color of the |
648 determined by the face code CF. */ | 3565 image. */ |
649 { | 3566 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height); |
650 struct face *face = FRAME_DEFAULT_FACE (f); | 3567 |
651 XFontStruct *font = NULL; | 3568 s->background_filled_p = 1; |
652 GC gc; | 3569 } |
653 int stippled = 0; | 3570 |
654 int line_height = f->output_data.x->line_height; | 3571 /* Draw the foreground. */ |
655 /* Pixel width of each glyph in this run. */ | 3572 if (pixmap != None) |
656 int glyph_width | 3573 { |
657 = (FONT_WIDTH (f->output_data.x->font) | 3574 x_draw_image_foreground_1 (s, pixmap); |
658 * (cmpcharp ? cmpcharp->width : CHARSET_WIDTH (charset))); | 3575 x_set_glyph_string_clipping (s); |
659 /* Overall pixel width of this run. */ | 3576 XCopyArea (s->display, pixmap, s->window, s->gc, |
660 int run_width | 3577 0, 0, s->background_width, s->height, s->x, s->y); |
661 = (FONT_WIDTH (f->output_data.x->font) | 3578 XFreePixmap (s->display, pixmap); |
662 * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset))); | 3579 } |
663 /* A flag to tell if we have already filled background. We | 3580 else |
664 fill background in advance in the following cases: | 3581 x_draw_image_foreground (s); |
665 1) A face has stipple. | 3582 |
666 2) A height of font is shorter than LINE_HEIGHT. | 3583 /* If we must draw a relief around the image, do it. */ |
667 3) Drawing a composite character. | 3584 if (s->img->relief |
668 4) Font has non-zero _MULE_BASELINE_OFFSET property. | 3585 || s->hl == DRAW_IMAGE_RAISED |
669 After filling background, we draw glyphs by XDrawString16. */ | 3586 || s->hl == DRAW_IMAGE_SUNKEN) |
670 int background_filled; | 3587 x_draw_image_relief (s); |
671 /* Baseline position of a character, offset from TOP. */ | 3588 } |
672 int baseline; | 3589 |
673 /* The property value of `_MULE_RELATIVE_COMPOSE' and | 3590 |
674 `_MULE_DEFAULT_ASCENT'. */ | 3591 /* Draw stretch glyph string S. */ |
675 int relative_compose = 0, default_ascent = 0; | 3592 |
676 /* 1 if we find no font or a font of inappropriate size. */ | 3593 static void |
677 int require_clipping; | 3594 x_draw_stretch_glyph_string (s) |
678 | 3595 struct glyph_string *s; |
679 /* HL = 3 means use a mouse face previously chosen. */ | 3596 { |
680 if (hl == 3) | 3597 xassert (s->first_glyph->type == STRETCH_GLYPH); |
681 cf = FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id; | 3598 s->stippled_p = s->face->stipple != 0; |
682 | 3599 |
683 /* First look at the face of the text itself. */ | 3600 if (s->hl == DRAW_CURSOR |
684 if (cf != 0) | 3601 && !x_stretch_cursor_p) |
685 { | 3602 { |
686 /* It's possible for the display table to specify | 3603 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor |
687 a face code that is out of range. Use 0 in that case. */ | 3604 as wide as the stretch glyph. */ |
688 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f) | 3605 int width = min (CANON_X_UNIT (s->f), s->background_width); |
689 || FRAME_COMPUTED_FACES (f) [cf] == 0) | 3606 |
690 cf = 0; | 3607 /* Draw cursor. */ |
691 | 3608 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height); |
692 if (cf == 1) | 3609 |
693 face = FRAME_MODE_LINE_FACE (f); | 3610 /* Clear rest using the GC of the original non-cursor face. */ |
694 else | 3611 if (width < s->background_width) |
695 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]); | |
696 if (FACE_STIPPLE (face)) | |
697 stippled = 1; | |
698 } | |
699 | |
700 /* Then comes the distinction between modeline and normal text. */ | |
701 else if (hl == 0) | |
702 ; | |
703 else if (hl == 1) | |
704 { | |
705 face = FRAME_MODE_LINE_FACE (f); | |
706 if (FACE_STIPPLE (face)) | |
707 stippled = 1; | |
708 } | |
709 | |
710 #define FACE_DEFAULT (~0) | |
711 | |
712 /* Setting appropriate font and gc for this charset. */ | |
713 if (charset != CHARSET_ASCII) | |
714 { | |
715 int font_id; | |
716 int fontset = FACE_FONTSET (face); | |
717 struct font_info *fontp; | |
718 | |
719 if ((fontset < 0 && (fontset = FRAME_FONTSET (f)) < 0) | |
720 || !(fontp = FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f), | |
721 charset, NULL, fontset))) | |
722 goto font_not_found; | |
723 | |
724 font = (XFontStruct *) (fontp->font); | |
725 gc = FACE_NON_ASCII_GC (face); | |
726 XSetFont (FRAME_X_DISPLAY (f), gc, font->fid); | |
727 baseline | |
728 = (font->max_byte1 != 0 | |
729 ? (line_height + font->ascent - font->descent) / 2 | |
730 : f->output_data.x->font_baseline - fontp->baseline_offset); | |
731 if (FONT_HEIGHT (font) <= line_height | |
732 && (font->ascent > baseline | |
733 || font->descent > line_height - baseline)) | |
734 /* Adjust baseline for this font to show the whole | |
735 glyphs in a line. */ | |
736 baseline = line_height - font->descent; | |
737 | |
738 if (cmpcharp && cmpcharp->cmp_rule == NULL) | |
739 { | |
740 relative_compose = fontp->relative_compose; | |
741 default_ascent = fontp->default_ascent; | |
742 } | |
743 | |
744 /* We have to change code points in the following cases. */ | |
745 if (fontp->font_encoder) | |
746 { | |
747 /* This font requires CCL program to calculate code | |
748 point of characters. */ | |
749 struct ccl_program *ccl = fontp->font_encoder; | |
750 | |
751 if (CHARSET_DIMENSION (charset) == 1) | |
752 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++) | |
753 { | |
754 ccl->reg[0] = charset; | |
755 ccl->reg[1] = cp->byte2; | |
756 ccl_driver (ccl, NULL, NULL, 0, 0, NULL); | |
757 /* We assume that MSBs are appropriately | |
758 set/reset by CCL program. */ | |
759 if (font->max_byte1 == 0) /* 1-byte font */ | |
760 cp->byte1 = 0, cp->byte2 = ccl->reg[1]; | |
761 else | |
762 cp->byte1 = ccl->reg[1], cp->byte2 = ccl->reg[2]; | |
763 } | |
764 else | |
765 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++) | |
766 { | |
767 ccl->reg[0] = charset; | |
768 ccl->reg[1] = cp->byte1, ccl->reg[2] = cp->byte2; | |
769 ccl_driver (ccl, NULL, NULL, 0, 0, NULL); | |
770 /* We assume that MSBs are appropriately | |
771 set/reset by CCL program. */ | |
772 if (font->max_byte1 == 0) /* 1-byte font */ | |
773 cp->byte1 = 0, cp->byte2 = ccl->reg[1]; | |
774 else | |
775 cp->byte1 = ccl->reg[1], cp->byte2 = ccl->reg[2]; | |
776 } | |
777 } | |
778 else if (fontp->encoding[charset]) | |
779 { | |
780 int enc = fontp->encoding[charset]; | |
781 | |
782 if ((enc == 1 || enc == 2) && CHARSET_DIMENSION (charset) == 2) | |
783 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++) | |
784 cp->byte1 |= 0x80; | |
785 if (enc == 1 || enc == 3) | |
786 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++) | |
787 cp->byte2 |= 0x80; | |
788 } | |
789 } | |
790 else | |
791 { | |
792 font_not_found: | |
793 if (charset == CHARSET_ASCII || charset == charset_latin_iso8859_1) | |
794 { | |
795 font = FACE_FONT (face); | |
796 if (!font || font == (XFontStruct *) FACE_DEFAULT) | |
797 font = f->output_data.x->font; | |
798 baseline = FONT_BASE (f->output_data.x->font); | |
799 if (charset == charset_latin_iso8859_1) | |
800 { | |
801 if (font->max_char_or_byte2 < 0x80) | |
802 /* This font can't display Latin1 characters. */ | |
803 font = NULL; | |
804 else | |
805 { | |
806 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++) | |
807 cp->byte2 |= 0x80; | |
808 } | |
809 } | |
810 } | |
811 gc = FACE_GC (face); | |
812 } | |
813 | |
814 /* Now override that if the cursor's on this character. */ | |
815 if (hl == 2) | |
816 { | |
817 /* The cursor overrides stippling. */ | |
818 stippled = 0; | |
819 | |
820 if (font == f->output_data.x->font | |
821 && face->background == f->output_data.x->background_pixel | |
822 && face->foreground == f->output_data.x->foreground_pixel | |
823 && !cmpcharp) | |
824 { | |
825 gc = f->output_data.x->cursor_gc; | |
826 } | |
827 /* Cursor on non-default face: must merge. */ | |
828 else | |
829 { | |
830 XGCValues xgcv; | |
831 unsigned long mask; | |
832 | |
833 xgcv.background = f->output_data.x->cursor_pixel; | |
834 xgcv.foreground = face->background; | |
835 /* If the glyph would be invisible, | |
836 try a different foreground. */ | |
837 if (xgcv.foreground == xgcv.background) | |
838 xgcv.foreground = face->foreground; | |
839 if (xgcv.foreground == xgcv.background) | |
840 xgcv.foreground = f->output_data.x->cursor_foreground_pixel; | |
841 if (xgcv.foreground == xgcv.background) | |
842 xgcv.foreground = face->foreground; | |
843 /* Make sure the cursor is distinct from text in this face. */ | |
844 if (xgcv.background == face->background | |
845 && xgcv.foreground == face->foreground) | |
846 { | |
847 xgcv.background = face->foreground; | |
848 xgcv.foreground = face->background; | |
849 } | |
850 xgcv.graphics_exposures = 0; | |
851 mask = GCForeground | GCBackground | GCGraphicsExposures; | |
852 if (font) | |
853 { | |
854 xgcv.font = font->fid; | |
855 mask |= GCFont; | |
856 } | |
857 | |
858 if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc) | |
859 XChangeGC (FRAME_X_DISPLAY (f), | |
860 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc, | |
861 mask, &xgcv); | |
862 else | |
863 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc | |
864 = XCreateGC (FRAME_X_DISPLAY (f), window, mask, &xgcv); | |
865 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc; | |
866 #if 0 | |
867 /* If this code is restored, it must also reset to the default stipple | |
868 if necessary. */ | |
869 if (face->stipple && face->stipple != FACE_DEFAULT) | |
870 XSetStipple (FRAME_X_DISPLAY (f), gc, face->stipple); | |
871 #endif | |
872 } | |
873 } | |
874 | |
875 if (font) | |
876 require_clipping = (!NILP (Vclip_large_size_font) | |
877 && (font->ascent > baseline | |
878 || font->descent > line_height - baseline | |
879 || (!cmpcharp | |
880 && FONT_WIDTH (font) > glyph_width))); | |
881 | |
882 if (font && (just_foreground || (cmpcharp && gidx > 0))) | |
883 background_filled = 1; | |
884 else if (stippled) | |
885 { | |
886 /* Turn stipple on. */ | |
887 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled); | |
888 | |
889 /* Draw stipple or background color on background. */ | |
890 XFillRectangle (FRAME_X_DISPLAY (f), window, gc, | |
891 left, top, run_width, line_height); | |
892 | |
893 /* Turn stipple off. */ | |
894 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid); | |
895 | |
896 background_filled = 1; | |
897 } | |
898 else if (!font | |
899 || FONT_BASE (font) < baseline | |
900 || (FONT_HEIGHT (font) - FONT_BASE (font) | |
901 < line_height - baseline) | |
902 || FONT_WIDTH (font) < glyph_width | |
903 || cmpcharp) | |
904 { | |
905 /* Fill a area for the current run in background pixle of GC. */ | |
906 XGCValues xgcv; | |
907 unsigned long mask = GCForeground | GCBackground | GCFillStyle; | |
908 | |
909 /* The current code at first set foreground to background, | |
910 fill the area, then recover the original foreground. | |
911 Aren't there any smarter ways? */ | |
912 | |
913 XGetGCValues (FRAME_X_DISPLAY (f), gc, mask, &xgcv); | |
914 XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background); | |
915 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid); | |
916 XFillRectangle (FRAME_X_DISPLAY (f), window, gc, | |
917 left, top, run_width, line_height); | |
918 XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground); | |
919 | |
920 background_filled = 1; | |
921 if (cmpcharp) | |
922 /* To assure not to fill background while drawing | |
923 remaining components. */ | |
924 just_foreground = 1; | |
925 } | |
926 else | |
927 background_filled = 0; | |
928 | |
929 if (font) | |
930 { | |
931 if (require_clipping) | |
932 { | |
933 Region region; /* Region used for setting clip mask to GC. */ | |
934 XPoint x[4]; /* Data used for creating REGION. */ | |
935 | |
936 x[0].x = x[3].x = left, x[1].x = x[2].x = left + glyph_width; | |
937 x[0].y = x[1].y = top, x[2].y = x[3].y = top + line_height; | |
938 region = XPolygonRegion (x, 4, EvenOddRule); | |
939 XSetRegion (FRAME_X_DISPLAY (f), gc, region); | |
940 XDestroyRegion (region); | |
941 } | |
942 | |
943 if (!cmpcharp) | |
944 { | |
945 if (require_clipping || FONT_WIDTH (font) != glyph_width) | |
946 for (i = 0; i < len; i++) | |
947 { | |
948 if (require_clipping && i > 0) | |
949 XSetClipOrigin (FRAME_X_DISPLAY (f), gc, | |
950 glyph_width * i, 0); | |
951 if (background_filled) | |
952 XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | |
953 left + glyph_width * i, | |
954 top + baseline, x_2byte_buffer + i, 1); | |
955 else | |
956 XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc, | |
957 left + glyph_width * i, | |
958 top + baseline, x_2byte_buffer + i, 1); | |
959 } | |
960 else | |
961 { | |
962 /* See if this whole buffer can be output as 8-bit chars. | |
963 If so, copy x_2byte_buffer to x_1byte_buffer | |
964 and do it as 8-bit chars. */ | |
965 for (i = 0; i < len; i++) | |
966 { | |
967 if (x_2byte_buffer[i].byte1 != 0) | |
968 break; | |
969 x_1byte_buffer[i] = x_2byte_buffer[i].byte2; | |
970 } | |
971 | |
972 if (i == len) | |
973 { | |
974 if (background_filled) | |
975 XDrawString (FRAME_X_DISPLAY (f), window, gc, | |
976 left, top + baseline, x_1byte_buffer, len); | |
977 else | |
978 XDrawImageString (FRAME_X_DISPLAY (f), window, gc, | |
979 left, top + baseline, x_1byte_buffer, len); | |
980 } | |
981 else | |
982 { | |
983 /* We can't output them as 8-bit chars, | |
984 so do it as 16-bit chars. */ | |
985 | |
986 if (background_filled) | |
987 XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | |
988 left, top + baseline, x_2byte_buffer, len); | |
989 else | |
990 XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc, | |
991 left, top + baseline, x_2byte_buffer, len); | |
992 } | |
993 } | |
994 } | |
995 else | |
996 { | |
997 /* Handle composite characters. */ | |
998 XCharStruct *pcm; /* Pointer to per char metric info. */ | |
999 | |
1000 if ((cmpcharp->cmp_rule || relative_compose) | |
1001 && gidx == 0) | |
1002 { | |
1003 /* This is the first character. Initialize variables. | |
1004 HIGHEST is the highest position of glyphs ever | |
1005 written, LOWEST the lowest position. */ | |
1006 int x_offset = 0; | |
1007 | |
1008 if (default_ascent | |
1009 && CHAR_TABLE_P (Vuse_default_ascent) | |
1010 && !NILP (Faref (Vuse_default_ascent, first_ch))) | |
1011 { | |
1012 highest = default_ascent; | |
1013 lowest = 0; | |
1014 } | |
1015 else | |
1016 { | |
1017 pcm = PER_CHAR_METRIC (font, x_2byte_buffer); | |
1018 highest = pcm->ascent + 1; | |
1019 lowest = - pcm->descent; | |
1020 } | |
1021 | |
1022 if (cmpcharp->cmp_rule) | |
1023 x_offset = (cmpcharp->col_offset[0] | |
1024 * FONT_WIDTH (f->output_data.x->font)); | |
1025 /* Draw the first character at the normal position. */ | |
1026 XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | |
1027 left + x_offset, top + baseline, x_2byte_buffer, 1); | |
1028 i = 1; | |
1029 gidx++; | |
1030 } | |
1031 else | |
1032 i = 0; | |
1033 | |
1034 for (; i < len; i++, gidx++) | |
1035 { | |
1036 int x_offset = 0, y_offset = 0; | |
1037 | |
1038 if (relative_compose) | |
1039 { | |
1040 pcm = PER_CHAR_METRIC (font, x_2byte_buffer + i); | |
1041 if (NILP (Vignore_relative_composition) | |
1042 || NILP (Faref (Vignore_relative_composition, | |
1043 make_number (cmpcharp->glyph[gidx])))) | |
1044 { | |
1045 if (- pcm->descent >= relative_compose) | |
1046 { | |
1047 /* Draw above the current glyphs. */ | |
1048 y_offset = highest + pcm->descent; | |
1049 highest += pcm->ascent + pcm->descent; | |
1050 } | |
1051 else if (pcm->ascent <= 0) | |
1052 { | |
1053 /* Draw beneath the current glyphs. */ | |
1054 y_offset = lowest - pcm->ascent; | |
1055 lowest -= pcm->ascent + pcm->descent; | |
1056 } | |
1057 } | |
1058 else | |
1059 { | |
1060 /* Draw the glyph at normal position. If | |
1061 it sticks out of HIGHEST or LOWEST, | |
1062 update them appropriately. */ | |
1063 if (pcm->ascent > highest) | |
1064 highest = pcm->ascent; | |
1065 else if (- pcm->descent < lowest) | |
1066 lowest = - pcm->descent; | |
1067 } | |
1068 } | |
1069 else if (cmpcharp->cmp_rule) | |
1070 { | |
1071 int gref = (cmpcharp->cmp_rule[gidx] - 0xA0) / 9; | |
1072 int nref = (cmpcharp->cmp_rule[gidx] - 0xA0) % 9; | |
1073 int bottom, top; | |
1074 | |
1075 /* Re-encode GREF and NREF so that they specify | |
1076 only Y-axis information: | |
1077 0:top, 1:base, 2:bottom, 3:center */ | |
1078 gref = gref / 3 + (gref == 4) * 2; | |
1079 nref = nref / 3 + (nref == 4) * 2; | |
1080 | |
1081 pcm = PER_CHAR_METRIC (font, x_2byte_buffer + i); | |
1082 bottom = ((gref == 0 ? highest : gref == 1 ? 0 | |
1083 : gref == 2 ? lowest | |
1084 : (highest + lowest) / 2) | |
1085 - (nref == 0 ? pcm->ascent + pcm->descent | |
1086 : nref == 1 ? pcm->descent : nref == 2 ? 0 | |
1087 : (pcm->ascent + pcm->descent) / 2)); | |
1088 top = bottom + (pcm->ascent + pcm->descent); | |
1089 if (top > highest) | |
1090 highest = top; | |
1091 if (bottom < lowest) | |
1092 lowest = bottom; | |
1093 y_offset = bottom + pcm->descent; | |
1094 x_offset = (cmpcharp->col_offset[gidx] | |
1095 * FONT_WIDTH (f->output_data.x->font)); | |
1096 } | |
1097 XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | |
1098 left + x_offset, top + baseline - y_offset, | |
1099 x_2byte_buffer + i, 1); | |
1100 } | |
1101 } | |
1102 if (require_clipping) | |
1103 XSetClipMask (FRAME_X_DISPLAY (f), gc, None); | |
1104 | |
1105 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS, | |
1106 which often is not up to date yet. */ | |
1107 if (!just_foreground) | |
1108 { | |
1109 if (left == orig_left) | |
1110 redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left), | |
1111 PIXEL_TO_CHAR_ROW (f, top), hl == 1); | |
1112 if (n == 0) | |
1113 redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)), | |
1114 PIXEL_TO_CHAR_ROW (f, top), hl == 1); | |
1115 } | |
1116 #endif | |
1117 } | |
1118 if (!font) | |
1119 { | |
1120 /* Show rectangles to indicate that we found no font. */ | |
1121 int limit = cmpcharp ? 1 : len; | |
1122 | |
1123 for (i = 0; i < limit; i++) | |
1124 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | |
1125 left + glyph_width * i, top, | |
1126 glyph_width - 1, line_height - 1); | |
1127 } | |
1128 else if (require_clipping && !NILP (Vhighlight_wrong_size_font)) | |
1129 { | |
1130 /* Show ??? to indicate that we found a font of | |
1131 inappropriate size. */ | |
1132 int limit = cmpcharp ? 1 : len; | |
1133 | |
1134 for (i = 0; i < limit; i++) | |
1135 { | |
1136 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | |
1137 left + glyph_width * i, top + line_height - 1, | |
1138 left + glyph_width * i + 1, top + line_height - 1); | |
1139 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | |
1140 left + glyph_width * i, top + line_height - 3, | |
1141 left + glyph_width * i, top + line_height - 1); | |
1142 } | |
1143 } | |
1144 | |
1145 /* We should probably check for XA_UNDERLINE_POSITION and | |
1146 XA_UNDERLINE_THICKNESS properties on the font, but let's | |
1147 just get the thing working, and come back to that. */ | |
1148 { | 3612 { |
1149 /* Setting underline position based on the metric of the | 3613 GC gc = s->face->gc; |
1150 current font results in shaky underline if it strides | 3614 int x = s->x + width, y = s->y; |
1151 over different fonts. So, we set the position based only | 3615 int w = s->background_width - width, h = s->height; |
1152 on the default font of this frame. */ | 3616 XRectangle r; |
1153 int underline_position = f->output_data.x->font_baseline + 1; | 3617 |
1154 | 3618 x_get_glyph_string_clip_rect (s, &r); |
1155 if (underline_position >= line_height) | 3619 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted); |
1156 underline_position = line_height - 1; | 3620 |
1157 | 3621 if (s->face->stipple) |
1158 if (face->underline) | 3622 { |
1159 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 3623 /* Fill background with a stipple pattern. */ |
1160 FACE_GC (face), | 3624 XSetFillStyle (s->display, gc, FillOpaqueStippled); |
1161 left, top + underline_position, run_width, 1); | 3625 XFillRectangle (s->display, s->window, gc, x, y, w, h); |
3626 XSetFillStyle (s->display, gc, FillSolid); | |
3627 } | |
3628 else | |
3629 { | |
3630 XGCValues xgcv; | |
3631 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv); | |
3632 XSetForeground (s->display, gc, xgcv.background); | |
3633 XFillRectangle (s->display, s->window, gc, x, y, w, h); | |
3634 XSetForeground (s->display, gc, xgcv.foreground); | |
3635 } | |
1162 } | 3636 } |
1163 | 3637 } |
1164 if (!cmpcharp) | 3638 else |
1165 left += run_width; | 3639 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width, |
1166 } | 3640 s->height); |
1167 } | 3641 |
1168 | 3642 s->background_filled_p = 1; |
1169 return (left - orig_left); | 3643 } |
1170 } | 3644 |
1171 #endif /* 1 */ | 3645 |
1172 | 3646 /* Draw glyph string S. */ |
1173 #if 0 | |
1174 /* This is the old single-face code. */ | |
1175 | 3647 |
1176 static void | 3648 static void |
1177 dumpglyphs (f, left, top, gp, n, hl, font) | 3649 x_draw_glyph_string (s) |
1178 struct frame *f; | 3650 struct glyph_string *s; |
1179 int left, top; | 3651 { |
1180 register GLYPH *gp; /* Points to first GLYPH. */ | 3652 /* If S draws into the background of its successor, draw the |
1181 register int n; /* Number of glyphs to display. */ | 3653 background of the successor first so that S can draw into it. |
1182 int hl; | 3654 This makes S->next use XDrawString instead of XDrawImageString. */ |
1183 XFontStruct *font; | 3655 if (s->next && s->right_overhang) |
1184 { | 3656 { |
1185 register int len; | 3657 xassert (s->next->img == NULL); |
1186 Window window = FRAME_X_WINDOW (f); | 3658 x_set_glyph_string_gc (s->next); |
1187 GC drawing_gc = (hl == 2 ? f->output_data.x->cursor_gc | 3659 x_set_glyph_string_clipping (s->next); |
1188 : (hl ? f->output_data.x->reverse_gc | 3660 x_draw_glyph_string_background (s->next, 1); |
1189 : f->output_data.x->normal_gc)); | 3661 } |
1190 | 3662 |
1191 if (sizeof (GLYPH) == sizeof (XChar2b)) | 3663 /* Set up S->gc, set clipping and draw S. */ |
1192 XDrawImageString16 (FRAME_X_DISPLAY (f), window, drawing_gc, | 3664 x_set_glyph_string_gc (s); |
1193 left, top + FONT_BASE (font), (XChar2b *) gp, n); | 3665 x_set_glyph_string_clipping (s); |
1194 else if (sizeof (GLYPH) == sizeof (unsigned char)) | 3666 |
1195 XDrawImageString (FRAME_X_DISPLAY (f), window, drawing_gc, | 3667 switch (s->first_glyph->type) |
1196 left, top + FONT_BASE (font), (char *) gp, n); | 3668 { |
3669 case IMAGE_GLYPH: | |
3670 x_draw_image_glyph_string (s); | |
3671 break; | |
3672 | |
3673 case STRETCH_GLYPH: | |
3674 x_draw_stretch_glyph_string (s); | |
3675 break; | |
3676 | |
3677 case CHAR_GLYPH: | |
3678 x_draw_glyph_string_background (s, 0); | |
3679 x_draw_glyph_string_foreground (s); | |
3680 break; | |
3681 | |
3682 default: | |
3683 abort (); | |
3684 } | |
3685 | |
3686 /* Draw underline. */ | |
3687 if (s->face->underline_p) | |
3688 { | |
3689 unsigned long dy, h; | |
3690 | |
3691 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h)) | |
3692 h = 1; | |
3693 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy)) | |
3694 dy = s->height - h; | |
3695 | |
3696 if (s->face->underline_defaulted_p) | |
3697 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, | |
3698 s->width, h); | |
3699 else | |
3700 { | |
3701 XGCValues xgcv; | |
3702 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); | |
3703 XSetForeground (s->display, s->gc, s->face->underline_color); | |
3704 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, | |
3705 s->width, h); | |
3706 XSetForeground (s->display, s->gc, xgcv.foreground); | |
3707 } | |
3708 } | |
3709 | |
3710 /* Draw overline. */ | |
3711 if (s->face->overline_p) | |
3712 { | |
3713 unsigned long dy = 0, h = 1; | |
3714 | |
3715 if (s->face->overline_color_defaulted_p) | |
3716 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, | |
3717 s->width, h); | |
3718 else | |
3719 { | |
3720 XGCValues xgcv; | |
3721 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); | |
3722 XSetForeground (s->display, s->gc, s->face->overline_color); | |
3723 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, | |
3724 s->width, h); | |
3725 XSetForeground (s->display, s->gc, xgcv.foreground); | |
3726 } | |
3727 } | |
3728 | |
3729 /* Draw strike-through. */ | |
3730 if (s->face->strike_through_p) | |
3731 { | |
3732 unsigned long h = 1; | |
3733 unsigned long dy = (s->height - h) / 2; | |
3734 | |
3735 if (s->face->strike_through_color_defaulted_p) | |
3736 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, | |
3737 s->width, h); | |
3738 else | |
3739 { | |
3740 XGCValues xgcv; | |
3741 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); | |
3742 XSetForeground (s->display, s->gc, s->face->strike_through_color); | |
3743 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, | |
3744 s->width, h); | |
3745 XSetForeground (s->display, s->gc, xgcv.foreground); | |
3746 } | |
3747 } | |
3748 | |
3749 /* Draw relief. */ | |
3750 if (s->face->box != FACE_NO_BOX) | |
3751 x_draw_glyph_string_box (s); | |
3752 | |
3753 /* Reset clipping. */ | |
3754 XSetClipMask (s->display, s->gc, None); | |
3755 } | |
3756 | |
3757 | |
3758 /* A work-list entry used during the construction of glyph_string | |
3759 structures for a composite character. */ | |
3760 | |
3761 struct work | |
3762 { | |
3763 /* Pointer to composite char info defining has the composite | |
3764 character is drawn. */ | |
3765 struct cmpchar_info *cmpcharp; | |
3766 | |
3767 /* Start index in compcharp->glyph[]. */ | |
3768 int gidx; | |
3769 | |
3770 /* Next in stack. */ | |
3771 struct work *next; | |
3772 }; | |
3773 | |
3774 | |
3775 static void x_fill_composite_glyph_string P_ ((struct glyph_string *, | |
3776 int, struct work **, | |
3777 struct work **)); | |
3778 | |
3779 | |
3780 /* Load glyph string S with information from the top of *STACK for a | |
3781 composite character. FACE_ID is the id of the face in which S is | |
3782 drawn. *NEW is a pointer to a struct work not on the stack, that | |
3783 can be used if this function needs to push a new structure on the | |
3784 stack. If it uses it, *NEW is set to null. */ | |
3785 | |
3786 static void | |
3787 x_fill_composite_glyph_string (s, face_id, stack, new) | |
3788 struct glyph_string *s; | |
3789 int face_id; | |
3790 struct work **stack, **new; | |
3791 { | |
3792 int i, c; | |
3793 struct work *work; | |
3794 | |
3795 xassert (s && *new && *stack); | |
3796 | |
3797 /* Pop the work stack. */ | |
3798 work = *stack; | |
3799 *stack = work->next; | |
3800 | |
3801 /* For all glyphs of cmpcharp->glyph, starting at the offset | |
3802 work->offset, until we reach the end of the definition or | |
3803 encounter another composite char, get the font and face to use, | |
3804 and add it to S. */ | |
3805 for (i = work->gidx; i < work->cmpcharp->glyph_len; ++i) | |
3806 { | |
3807 c = FAST_GLYPH_CHAR (work->cmpcharp->glyph[i]); | |
3808 if (CHAR_CHARSET (c) == CHARSET_COMPOSITION) | |
3809 break; | |
3810 s->face = x_get_char_face_and_encoding (s->f, c, face_id, | |
3811 s->char2b + s->nchars, 1); | |
3812 s->font = s->face->font; | |
3813 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id); | |
3814 ++s->nchars; | |
3815 } | |
3816 | |
3817 /* If we find another composite char in the glyph definition of | |
3818 work->cmpcharp, put back the rest of the glyphs on the work | |
3819 stack, and make a new entry for the composite char. */ | |
3820 if (i < work->cmpcharp->glyph_len) | |
3821 { | |
3822 /* Push back an unprocessed rest of this glyph spec. */ | |
3823 if (i < work->cmpcharp->glyph_len - 1) | |
3824 { | |
3825 work->gidx = i + 1; | |
3826 work->next = *stack; | |
3827 *stack = work; | |
3828 work = *new; | |
3829 *new = NULL; | |
3830 } | |
3831 | |
3832 /* Make an entry for the composite char on the work stack. */ | |
3833 work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)]; | |
3834 work->gidx = 0; | |
3835 work->next = *stack; | |
3836 *stack = work; | |
3837 } | |
3838 | |
3839 /* The width of this glyph string equals the width of the first | |
3840 glyph. All characters are drawn at the same x-position. */ | |
3841 s->width = s->first_glyph->pixel_width; | |
3842 | |
3843 /* If the specified font could not be loaded, use the frame's | |
3844 default font, but record the fact that we couldn't load it in | |
3845 the glyph string so that we can draw rectangles for the | |
3846 characters of the glyph string. */ | |
3847 if (s->font == NULL) | |
3848 { | |
3849 s->font_not_found_p = 1; | |
3850 s->font = FRAME_FONT (s->f); | |
3851 } | |
3852 | |
3853 /* Adjust base line for subscript/superscript text. */ | |
3854 s->ybase += s->first_glyph->voffset; | |
3855 | |
3856 xassert (s->face && s->face->gc); | |
3857 | |
3858 /* This glyph string must always be drawn with 16-bit functions. */ | |
3859 s->two_byte_p = 1; | |
3860 } | |
3861 | |
3862 | |
3863 /* Load glyph string S with a sequence of non-composite characters. | |
3864 FACE_ID is the face id of the string. START is the index of the | |
3865 first glyph to consider, END is the index of the last + 1. Value | |
3866 is the index of the first glyph not in S. */ | |
3867 | |
3868 static int | |
3869 x_fill_glyph_string (s, face_id, start, end) | |
3870 struct glyph_string *s; | |
3871 int face_id; | |
3872 int start, end; | |
3873 { | |
3874 struct glyph *glyph, *last; | |
3875 int voffset; | |
3876 | |
3877 xassert (s->charset != CHARSET_COMPOSITION); | |
3878 xassert (s->f == XFRAME (s->w->frame)); | |
3879 xassert (s->nchars == 0); | |
3880 xassert (start >= 0 && end > start); | |
3881 | |
3882 glyph = s->row->glyphs[s->area] + start; | |
3883 last = s->row->glyphs[s->area] + end; | |
3884 voffset = glyph->voffset; | |
3885 | |
3886 while (glyph < last | |
3887 && glyph->type == CHAR_GLYPH | |
3888 && glyph->voffset == voffset | |
3889 /* Same face id implies same charset, nowadays. */ | |
3890 && glyph->u.ch.face_id == face_id) | |
3891 { | |
3892 s->face = x_get_glyph_face_and_encoding (s->f, glyph, | |
3893 s->char2b + s->nchars); | |
3894 if (s->char2b[s->nchars].byte2 != 0) | |
3895 s->two_byte_p = 1; | |
3896 | |
3897 ++s->nchars; | |
3898 xassert (s->nchars <= end - start); | |
3899 s->width += glyph->pixel_width; | |
3900 ++glyph; | |
3901 } | |
3902 | |
3903 s->font = s->face->font; | |
3904 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id); | |
3905 | |
3906 /* If the specified font could not be loaded, use the frame's font, | |
3907 but record the fact that we couldn't load it in | |
3908 S->font_not_found_p so that we can draw rectangles for the | |
3909 characters of the glyph string. */ | |
3910 if (s->font == NULL) | |
3911 { | |
3912 s->font_not_found_p = 1; | |
3913 s->font = FRAME_FONT (s->f); | |
3914 } | |
3915 | |
3916 /* Adjust base line for subscript/superscript text. */ | |
3917 s->ybase += voffset; | |
3918 | |
3919 xassert (s->face && s->face->gc); | |
3920 return glyph - s->row->glyphs[s->area]; | |
3921 } | |
3922 | |
3923 | |
3924 /* Fill glyph string S from image glyph S->first_glyph. */ | |
3925 | |
3926 static void | |
3927 x_fill_image_glyph_string (s) | |
3928 struct glyph_string *s; | |
3929 { | |
3930 xassert (s->first_glyph->type == IMAGE_GLYPH); | |
3931 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img.id); | |
3932 xassert (s->img); | |
3933 s->face = FACE_FROM_ID (s->f, s->first_glyph->u.img.face_id); | |
3934 s->font = s->face->font; | |
3935 s->width = s->first_glyph->pixel_width; | |
3936 | |
3937 /* Adjust base line for subscript/superscript text. */ | |
3938 s->ybase += s->first_glyph->voffset; | |
3939 } | |
3940 | |
3941 | |
3942 /* Fill glyph string S from stretch glyph S->first_glyph. */ | |
3943 | |
3944 static void | |
3945 x_fill_stretch_glyph_string (s) | |
3946 struct glyph_string *s; | |
3947 { | |
3948 xassert (s->first_glyph->type == STRETCH_GLYPH); | |
3949 s->face = FACE_FROM_ID (s->f, s->first_glyph->u.stretch.face_id); | |
3950 s->font = s->face->font; | |
3951 s->width = s->first_glyph->pixel_width; | |
3952 | |
3953 /* Adjust base line for subscript/superscript text. */ | |
3954 s->ybase += s->first_glyph->voffset; | |
3955 } | |
3956 | |
3957 | |
3958 /* Initialize glyph string S. CHAR2B is a suitably allocated vector | |
3959 of XChar2b structures for S; it can't be allocated in | |
3960 x_init_glyph_string because it must be allocated via `alloca'. W | |
3961 is the window on which S is drawn. ROW and AREA are the glyph row | |
3962 and area within the row from which S is constructed. START is the | |
3963 index of the first glyph structure covered by S. HL is a | |
3964 face-override for drawing S. */ | |
3965 | |
3966 static void | |
3967 x_init_glyph_string (s, char2b, w, row, area, start, hl) | |
3968 struct glyph_string *s; | |
3969 XChar2b *char2b; | |
3970 struct window *w; | |
3971 struct glyph_row *row; | |
3972 enum glyph_row_area area; | |
3973 int start; | |
3974 enum draw_glyphs_face hl; | |
3975 { | |
3976 bzero (s, sizeof *s); | |
3977 s->w = w; | |
3978 s->f = XFRAME (w->frame); | |
3979 s->display = FRAME_X_DISPLAY (s->f); | |
3980 s->window = FRAME_X_WINDOW (s->f); | |
3981 s->char2b = char2b; | |
3982 s->hl = hl; | |
3983 s->row = row; | |
3984 s->area = area; | |
3985 s->first_glyph = row->glyphs[area] + start; | |
3986 s->height = row->height; | |
3987 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); | |
3988 | |
3989 /* Display the internal border below the toolbar window. */ | |
3990 if (s->w == XWINDOW (s->f->toolbar_window)) | |
3991 s->y -= s->f->output_data.x->internal_border_width; | |
3992 | |
3993 s->ybase = s->y + row->ascent; | |
3994 } | |
3995 | |
3996 | |
3997 /* Set background width of glyph string S. START is the index of the | |
3998 first glyph following S. LAST_X is the right-most x-position + 1 | |
3999 in the drawing area. */ | |
4000 | |
4001 static INLINE void | |
4002 x_set_glyph_string_background_width (s, start, last_x) | |
4003 struct glyph_string *s; | |
4004 int start; | |
4005 int last_x; | |
4006 { | |
4007 /* If the face of this glyph string has to be drawn to the end of | |
4008 the drawing area, set S->extends_to_end_of_line_p. */ | |
4009 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID); | |
4010 | |
4011 if (start == s->row->used[s->area] | |
4012 && s->hl == DRAW_NORMAL_TEXT | |
4013 && ((s->area == TEXT_AREA && s->row->fill_line_p) | |
4014 || s->face->background != default_face->background | |
4015 || s->face->stipple != default_face->stipple)) | |
4016 s->extends_to_end_of_line_p = 1; | |
4017 | |
4018 /* If S extends its face to the end of the line, set its | |
4019 background_width to the distance to the right edge of the drawing | |
4020 area. */ | |
4021 if (s->extends_to_end_of_line_p) | |
4022 s->background_width = last_x - s->x; | |
1197 else | 4023 else |
1198 /* What size of glyph ARE you using? And does X have a function to | 4024 s->background_width = s->width; |
1199 draw them? */ | 4025 } |
1200 abort (); | 4026 |
1201 } | 4027 |
1202 #endif | 4028 /* Add a glyph string for a stretch glyph to the list of strings |
1203 | 4029 between HEAD and TAIL. START is the index of the stretch glyph in |
1204 /* Output some text at the nominal frame cursor position. | 4030 row area AREA of glyph row ROW. END is the index of the last glyph |
1205 Advance the cursor over the text. | 4031 in that glyph row area. X is the current output position assigned |
1206 Output LEN glyphs at START. | 4032 to the new glyph string constructed. HL overrides that face of the |
1207 | 4033 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X |
1208 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight, | 4034 is the right-most x-position of the drawing area. */ |
1209 controls the pixel values used for foreground and background. */ | 4035 |
4036 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, \ | |
4037 HL, X, LAST_X) \ | |
4038 do \ | |
4039 { \ | |
4040 s = (struct glyph_string *) alloca (sizeof *s); \ | |
4041 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \ | |
4042 x_fill_stretch_glyph_string (s); \ | |
4043 x_append_glyph_string (&HEAD, &TAIL, s); \ | |
4044 ++START; \ | |
4045 s->x = (X); \ | |
4046 } \ | |
4047 while (0) | |
4048 | |
4049 | |
4050 /* Add a glyph string for an image glyph to the list of strings | |
4051 between HEAD and TAIL. START is the index of the image glyph in | |
4052 row area AREA of glyph row ROW. END is the index of the last glyph | |
4053 in that glyph row area. X is the current output position assigned | |
4054 to the new glyph string constructed. HL overrides that face of the | |
4055 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X | |
4056 is the right-most x-position of the drawing area. */ | |
4057 | |
4058 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, \ | |
4059 HL, X, LAST_X) \ | |
4060 do \ | |
4061 { \ | |
4062 s = (struct glyph_string *) alloca (sizeof *s); \ | |
4063 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \ | |
4064 x_fill_image_glyph_string (s); \ | |
4065 x_append_glyph_string (&HEAD, &TAIL, s); \ | |
4066 ++START; \ | |
4067 s->x = (X); \ | |
4068 } \ | |
4069 while (0) | |
4070 | |
4071 | |
4072 /* Add a glyph string for a sequence of character glyphs to the list | |
4073 of strings between HEAD and TAIL. START is the index of the first | |
4074 glyph in row area AREA of glyph row ROW that is part of the new | |
4075 glyph string. END is the index of the last glyph in that glyph row | |
4076 area. X is the current output position assigned to the new glyph | |
4077 string constructed. HL overrides that face of the glyph; e.g. it | |
4078 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the | |
4079 right-most x-position of the drawing area. */ | |
4080 | |
4081 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, \ | |
4082 X, LAST_X) \ | |
4083 do \ | |
4084 { \ | |
4085 int c, charset, face_id; \ | |
4086 XChar2b *char2b; \ | |
4087 \ | |
4088 c = (ROW)->glyphs[AREA][START].u.ch.code; \ | |
4089 charset = CHAR_CHARSET (c); \ | |
4090 face_id = (ROW)->glyphs[AREA][START].u.ch.face_id; \ | |
4091 \ | |
4092 if (charset == CHARSET_COMPOSITION) \ | |
4093 { \ | |
4094 struct work *stack, *work, *new = NULL; \ | |
4095 int n = 0; \ | |
4096 struct glyph_string *first_s = NULL; \ | |
4097 \ | |
4098 /* Push an initial entry for character c on the stack. */ \ | |
4099 stack = NULL; \ | |
4100 work = (struct work *) alloca (sizeof *work); \ | |
4101 work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)]; \ | |
4102 work->gidx = 0; \ | |
4103 work->next = stack; \ | |
4104 stack = work; \ | |
4105 \ | |
4106 /* While the stack is not empty, append glyph_strings \ | |
4107 to head/tail for glyphs to draw. */ \ | |
4108 while (stack) \ | |
4109 { \ | |
4110 s = (struct glyph_string *) alloca (sizeof *s); \ | |
4111 char2b = (XChar2b *) alloca (stack->cmpcharp->glyph_len \ | |
4112 * sizeof (XChar2b)); \ | |
4113 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \ | |
4114 x_append_glyph_string (&(HEAD), &(TAIL), s); \ | |
4115 s->cmpcharp = stack->cmpcharp; \ | |
4116 s->gidx = stack->gidx; \ | |
4117 s->charset = charset; \ | |
4118 s->x = (X); \ | |
4119 \ | |
4120 if (n == 0) \ | |
4121 { \ | |
4122 /* Don't draw the background except for the \ | |
4123 first glyph string. */ \ | |
4124 s->background_filled_p = n > 0; \ | |
4125 first_s = s; \ | |
4126 } \ | |
4127 ++n; \ | |
4128 \ | |
4129 if (new == NULL) \ | |
4130 new = (struct work *) alloca (sizeof *new); \ | |
4131 x_fill_composite_glyph_string (s, face_id, &stack, \ | |
4132 &new); \ | |
4133 } \ | |
4134 \ | |
4135 ++START; \ | |
4136 s = first_s; \ | |
4137 } \ | |
4138 else \ | |
4139 { \ | |
4140 s = (struct glyph_string *) alloca (sizeof *s); \ | |
4141 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \ | |
4142 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \ | |
4143 x_append_glyph_string (&HEAD, &TAIL, s); \ | |
4144 s->charset = charset; \ | |
4145 s->x = (X); \ | |
4146 START = x_fill_glyph_string (s, face_id, START, END); \ | |
4147 } \ | |
4148 } \ | |
4149 while (0) | |
4150 | |
4151 | |
4152 /* Build a list of glyph strings between HEAD and TAIL for the glyphs | |
4153 of AREA of glyph row ROW on window W between indices START and END. | |
4154 HL overrides the face for drawing glyph strings, e.g. it is | |
4155 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end | |
4156 x-positions of the drawing area. | |
4157 | |
4158 This is an ugly monster macro construct because we must use alloca | |
4159 to allocate glyph strings (because x_draw_glyphs can be called | |
4160 asynchronously). */ | |
4161 | |
4162 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, \ | |
4163 X, LAST_X) \ | |
4164 do \ | |
4165 { \ | |
4166 HEAD = TAIL = NULL; \ | |
4167 while (START < END) \ | |
4168 { \ | |
4169 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \ | |
4170 switch (first_glyph->type) \ | |
4171 { \ | |
4172 case CHAR_GLYPH: \ | |
4173 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \ | |
4174 TAIL, HL, X, LAST_X); \ | |
4175 break; \ | |
4176 \ | |
4177 case STRETCH_GLYPH: \ | |
4178 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \ | |
4179 HEAD, TAIL, HL, X, LAST_X); \ | |
4180 break; \ | |
4181 \ | |
4182 case IMAGE_GLYPH: \ | |
4183 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \ | |
4184 TAIL, HL, X, LAST_X); \ | |
4185 break; \ | |
4186 \ | |
4187 default: \ | |
4188 abort (); \ | |
4189 } \ | |
4190 \ | |
4191 x_set_glyph_string_background_width (s, START, LAST_X); \ | |
4192 (X) += s->width; \ | |
4193 } \ | |
4194 } \ | |
4195 while (0) | |
4196 | |
4197 | |
4198 /* Draw glyphs between START and END in AREA of ROW on window W, | |
4199 starting at x-position X. X is relative to AREA in W. HL is a | |
4200 face-override with the following meaning: | |
4201 | |
4202 DRAW_NORMAL_TEXT draw normally | |
4203 DRAW_CURSOR draw in cursor face | |
4204 DRAW_MOUSE_FACE draw in mouse face. | |
4205 DRAW_INVERSE_VIDEO draw in mode line face | |
4206 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it | |
4207 DRAW_IMAGE_RAISED draw an image with a raised relief around it | |
4208 | |
4209 If REAL_START is non-null, return in *REAL_START the real starting | |
4210 position for display. This can be different from START in case | |
4211 overlapping glyphs must be displayed. If REAL_END is non-null, | |
4212 return in *REAL_END the real end position for display. This can be | |
4213 different from END in case overlapping glyphs must be displayed. | |
4214 | |
4215 Value is the x-position reached, relative to AREA of W. */ | |
4216 | |
4217 static int | |
4218 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end) | |
4219 struct window *w; | |
4220 int x; | |
4221 struct glyph_row *row; | |
4222 enum glyph_row_area area; | |
4223 int start, end; | |
4224 enum draw_glyphs_face hl; | |
4225 int *real_start, *real_end; | |
4226 { | |
4227 struct glyph_string *head, *tail; | |
4228 struct glyph_string *s; | |
4229 int last_x, area_width; | |
4230 int x_reached; | |
4231 int i, j; | |
4232 | |
4233 /* Let's rather be paranoid than getting a SEGV. */ | |
4234 start = max (0, start); | |
4235 end = min (end, row->used[area]); | |
4236 if (real_start) | |
4237 *real_start = start; | |
4238 if (real_end) | |
4239 *real_end = end; | |
4240 | |
4241 /* Translate X to frame coordinates. Set last_x to the right | |
4242 end of the drawing area. */ | |
4243 if (row->full_width_p) | |
4244 { | |
4245 /* X is relative to the left edge of W, without scroll bars | |
4246 or flag areas. */ | |
4247 struct frame *f = XFRAME (w->frame); | |
4248 int width = FRAME_FLAGS_AREA_WIDTH (f); | |
4249 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f); | |
4250 | |
4251 x += window_left_x; | |
4252 area_width = XFASTINT (w->width) * CANON_X_UNIT (f); | |
4253 last_x = window_left_x + area_width; | |
4254 | |
4255 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) | |
4256 { | |
4257 width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f); | |
4258 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) | |
4259 last_x += width; | |
4260 else | |
4261 x -= width; | |
4262 } | |
4263 | |
4264 /* If row should extend over internal borders, adjust x and | |
4265 width accordingly. */ | |
4266 if (row->internal_border_p) | |
4267 { | |
4268 x += FRAME_INTERNAL_BORDER_WIDTH (f); | |
4269 width -= 2 * FRAME_INTERNAL_BORDER_WIDTH (f); | |
4270 } | |
4271 } | |
4272 else | |
4273 { | |
4274 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x); | |
4275 area_width = window_box_width (w, area); | |
4276 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width); | |
4277 } | |
4278 | |
4279 /* Build a doubly-linked list of glyph_string structures between | |
4280 head and tail from what we have to draw. Note that the macro | |
4281 BUILD_GLYPH_STRINGS will modify its start parameter. That's | |
4282 the reason we use a separate variable `i'. */ | |
4283 i = start; | |
4284 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x); | |
4285 if (tail) | |
4286 x_reached = tail->x + tail->background_width; | |
4287 else | |
4288 x_reached = x; | |
4289 | |
4290 /* If there are any glyphs with lbearing < 0 or rbearing > width in | |
4291 the row, redraw some glyphs in front or following the glyph | |
4292 strings built above. */ | |
4293 if (row->contains_overlapping_glyphs_p) | |
4294 { | |
4295 int dummy_x = 0; | |
4296 struct glyph_string *h, *t; | |
4297 | |
4298 /* Compute overhangs for all glyph strings. */ | |
4299 for (s = head; s; s = s->next) | |
4300 x_compute_glyph_string_overhangs (s); | |
4301 | |
4302 /* Prepend glyph strings for glyphs in front of the first glyph | |
4303 string that are overwritten because of the first glyph | |
4304 string's left overhang. The background of all strings | |
4305 prepended must be drawn because the first glyph string | |
4306 draws over it. */ | |
4307 i = x_left_overwritten (head); | |
4308 if (i >= 0) | |
4309 { | |
4310 j = i; | |
4311 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t, | |
4312 DRAW_NORMAL_TEXT, dummy_x, last_x); | |
4313 start = i; | |
4314 if (real_start) | |
4315 *real_start = start; | |
4316 x_compute_overhangs_and_x (t, head->x, 1); | |
4317 x_prepend_glyph_string_lists (&head, &tail, h, t); | |
4318 } | |
4319 | |
4320 /* Prepend glyph strings for glyphs in front of the first glyph | |
4321 string that overwrite that glyph string because of their | |
4322 right overhang. For these strings, only the foreground must | |
4323 be drawn, because it draws over the glyph string at `head'. | |
4324 The background must not be drawn because this would overwrite | |
4325 right overhangs of preceding glyphs for which no glyph | |
4326 strings exist. */ | |
4327 i = x_left_overwriting (head); | |
4328 if (i >= 0) | |
4329 { | |
4330 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t, | |
4331 DRAW_NORMAL_TEXT, dummy_x, last_x); | |
4332 for (s = h; s; s = s->next) | |
4333 s->background_filled_p = 1; | |
4334 if (real_start) | |
4335 *real_start = i; | |
4336 x_compute_overhangs_and_x (t, head->x, 1); | |
4337 x_prepend_glyph_string_lists (&head, &tail, h, t); | |
4338 } | |
4339 | |
4340 /* Append glyphs strings for glyphs following the last glyph | |
4341 string tail that are overwritten by tail. The background of | |
4342 these strings has to be drawn because tail's foreground draws | |
4343 over it. */ | |
4344 i = x_right_overwritten (tail); | |
4345 if (i >= 0) | |
4346 { | |
4347 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t, | |
4348 DRAW_NORMAL_TEXT, x, last_x); | |
4349 x_compute_overhangs_and_x (h, tail->x + tail->width, 0); | |
4350 x_append_glyph_string_lists (&head, &tail, h, t); | |
4351 if (real_end) | |
4352 *real_end = i; | |
4353 } | |
4354 | |
4355 /* Append glyph strings for glyphs following the last glyph | |
4356 string tail that overwrite tail. The foreground of such | |
4357 glyphs has to be drawn because it writes into the background | |
4358 of tail. The background must not be drawn because it could | |
4359 paint over the foreground of following glyphs. */ | |
4360 i = x_right_overwriting (tail); | |
4361 if (i >= 0) | |
4362 { | |
4363 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t, | |
4364 DRAW_NORMAL_TEXT, x, last_x); | |
4365 for (s = h; s; s = s->next) | |
4366 s->background_filled_p = 1; | |
4367 x_compute_overhangs_and_x (h, tail->x + tail->width, 0); | |
4368 x_append_glyph_string_lists (&head, &tail, h, t); | |
4369 if (real_end) | |
4370 *real_end = i; | |
4371 } | |
4372 } | |
4373 | |
4374 /* Draw all strings. */ | |
4375 for (s = head; s; s = s->next) | |
4376 x_draw_glyph_string (s); | |
4377 | |
4378 /* Value is the x-position up to which drawn, relative to AREA of W. | |
4379 This doesn't include parts drawn because of overhangs. */ | |
4380 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached); | |
4381 if (!row->full_width_p) | |
4382 { | |
4383 if (area > LEFT_MARGIN_AREA) | |
4384 x_reached -= window_box_width (w, LEFT_MARGIN_AREA); | |
4385 if (area > TEXT_AREA) | |
4386 x_reached -= window_box_width (w, TEXT_AREA); | |
4387 } | |
4388 return x_reached; | |
4389 } | |
4390 | |
4391 | |
4392 /* Output LEN glyphs starting at START at the nominal cursor position. | |
4393 Advance the nominal cursor over the text. The global variable | |
4394 updated_window contains the window being updated, updated_row is | |
4395 the glyph row being updated, and updated_area is the area of that | |
4396 row being updated. */ | |
1210 | 4397 |
1211 static void | 4398 static void |
1212 XTwrite_glyphs (start, len) | 4399 x_write_glyphs (start, len) |
1213 register GLYPH *start; | 4400 struct glyph *start; |
1214 int len; | 4401 int len; |
1215 { | 4402 { |
1216 register int temp_length; | 4403 int x, hpos, real_start, real_end; |
1217 int mask; | 4404 |
4405 xassert (updated_window && updated_row); | |
4406 BLOCK_INPUT; | |
4407 | |
4408 /* Write glyphs. */ | |
4409 | |
4410 hpos = start - updated_row->glyphs[updated_area]; | |
4411 x = x_draw_glyphs (updated_window, output_cursor.x, | |
4412 updated_row, updated_area, | |
4413 hpos, hpos + len, | |
4414 (updated_row->inverse_p | |
4415 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT), | |
4416 &real_start, &real_end); | |
4417 | |
4418 /* If we drew over the cursor, note that it is not visible any more. */ | |
4419 note_overwritten_text_cursor (updated_window, real_start, | |
4420 real_end - real_start); | |
4421 | |
4422 UNBLOCK_INPUT; | |
4423 | |
4424 /* Advance the output cursor. */ | |
4425 output_cursor.hpos += len; | |
4426 output_cursor.x = x; | |
4427 } | |
4428 | |
4429 | |
4430 /* Insert LEN glyphs from START at the nominal cursor position. */ | |
4431 | |
4432 static void | |
4433 x_insert_glyphs (start, len) | |
4434 struct glyph *start; | |
4435 register int len; | |
4436 { | |
1218 struct frame *f; | 4437 struct frame *f; |
1219 | 4438 struct window *w; |
4439 int line_height, shift_by_width, shifted_region_width; | |
4440 struct glyph_row *row; | |
4441 struct glyph *glyph; | |
4442 int frame_x, frame_y, hpos, real_start, real_end; | |
4443 | |
4444 xassert (updated_window && updated_row); | |
1220 BLOCK_INPUT; | 4445 BLOCK_INPUT; |
1221 | 4446 w = updated_window; |
1222 do_line_dance (); | 4447 f = XFRAME (WINDOW_FRAME (w)); |
1223 f = updating_frame; | 4448 |
1224 if (f == 0) | 4449 /* Get the height of the line we are in. */ |
1225 { | 4450 row = updated_row; |
1226 f = selected_frame; | 4451 line_height = row->height; |
1227 /* If not within an update, | 4452 |
1228 output at the frame's visible cursor. */ | 4453 /* Get the width of the glyphs to insert. */ |
1229 curs_x = FRAME_CURSOR_X (f); | 4454 shift_by_width = 0; |
1230 curs_y = FRAME_CURSOR_Y (f); | 4455 for (glyph = start; glyph < start + len; ++glyph) |
1231 } | 4456 shift_by_width += glyph->pixel_width; |
1232 | 4457 |
1233 dumpglyphs (f, | 4458 /* Get the width of the region to shift right. */ |
1234 CHAR_TO_PIXEL_COL (f, curs_x), | 4459 shifted_region_width = (window_box_width (w, updated_area) |
1235 CHAR_TO_PIXEL_ROW (f, curs_y), | 4460 - output_cursor.x |
1236 start, len, highlight, 0, NULL); | 4461 - shift_by_width); |
1237 | 4462 |
1238 /* If we drew on top of the cursor, note that it is turned off. */ | 4463 /* Shift right. */ |
1239 if (curs_y == f->phys_cursor_y | 4464 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x); |
1240 && curs_x <= f->phys_cursor_x | 4465 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y); |
1241 && curs_x + len > f->phys_cursor_x) | 4466 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), |
1242 f->phys_cursor_on = 0; | 4467 f->output_data.x->normal_gc, |
1243 | 4468 frame_x, frame_y, |
1244 curs_x += len; | 4469 shifted_region_width, line_height, |
1245 if (curs_x >= FRAME_CURSOR_X_LIMIT (f)) | 4470 frame_x + shift_by_width, frame_y); |
1246 curs_x = FRAME_CURSOR_X_LIMIT (f) - 1; | 4471 |
1247 | 4472 /* Write the glyphs. */ |
1248 if (updating_frame == 0) | 4473 hpos = start - row->glyphs[updated_area]; |
1249 x_display_cursor (f, 1, curs_x, FRAME_CURSOR_Y (f)); | 4474 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len, |
1250 | 4475 DRAW_NORMAL_TEXT, &real_start, &real_end); |
1251 | 4476 note_overwritten_text_cursor (w, real_start, real_end - real_start); |
4477 | |
4478 /* Advance the output cursor. */ | |
4479 output_cursor.hpos += len; | |
4480 output_cursor.x += shift_by_width; | |
1252 UNBLOCK_INPUT; | 4481 UNBLOCK_INPUT; |
1253 } | 4482 } |
1254 | 4483 |
1255 /* Clear to the end of the line. | 4484 |
1256 Erase the current text line from the nominal cursor position (inclusive) | 4485 /* Delete N glyphs at the nominal cursor position. Not implemented |
1257 to column FIRST_UNUSED (exclusive). The idea is that everything | 4486 for X frames. */ |
1258 from FIRST_UNUSED onward is already erased. */ | |
1259 | 4487 |
1260 static void | 4488 static void |
1261 XTclear_end_of_line (first_unused) | 4489 x_delete_glyphs (n) |
1262 register int first_unused; | 4490 register int n; |
1263 { | 4491 { |
1264 struct frame *f = updating_frame; | 4492 abort (); |
1265 int mask; | 4493 } |
1266 | 4494 |
1267 if (f == 0) | 4495 |
1268 abort (); | 4496 /* Erase the current text line from the nominal cursor position |
1269 | 4497 (inclusive) to pixel column TO_X (exclusive). The idea is that |
1270 if (curs_y < 0 || curs_y >= f->height) | 4498 everything from TO_X onward is already erased. |
4499 | |
4500 TO_X is a pixel position relative to updated_area of | |
4501 updated_window. TO_X == -1 means clear to the end of this area. */ | |
4502 | |
4503 static void | |
4504 x_clear_end_of_line (to_x) | |
4505 int to_x; | |
4506 { | |
4507 struct frame *f; | |
4508 struct window *w = updated_window; | |
4509 int max_x, min_y, max_y; | |
4510 int from_x, from_y, to_y; | |
4511 | |
4512 xassert (updated_window && updated_row); | |
4513 f = XFRAME (w->frame); | |
4514 | |
4515 if (updated_row->full_width_p) | |
4516 { | |
4517 max_x = XFASTINT (w->width) * CANON_X_UNIT (f); | |
4518 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) | |
4519 && !w->pseudo_window_p) | |
4520 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f); | |
4521 } | |
4522 else | |
4523 max_x = window_box_width (w, updated_area); | |
4524 max_y = window_text_bottom_y (w); | |
4525 | |
4526 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end | |
4527 of window. For TO_X > 0, truncate to end of drawing area. */ | |
4528 if (to_x == 0) | |
1271 return; | 4529 return; |
1272 if (first_unused <= 0) | 4530 else if (to_x < 0) |
1273 return; | 4531 to_x = max_x; |
1274 | 4532 else |
1275 if (first_unused >= FRAME_WINDOW_WIDTH (f)) | 4533 to_x = min (to_x, max_x); |
1276 first_unused = FRAME_WINDOW_WIDTH (f); | 4534 |
1277 | 4535 to_y = min (max_y, output_cursor.y + updated_row->height); |
1278 first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f); | 4536 |
1279 | 4537 /* Notice if the cursor will be cleared by this operation. */ |
4538 if (!updated_row->full_width_p) | |
4539 note_overwritten_text_cursor (w, output_cursor.hpos, -1); | |
4540 | |
4541 from_x = output_cursor.x; | |
4542 | |
4543 /* Translate to frame coordinates. */ | |
4544 if (updated_row->full_width_p) | |
4545 { | |
4546 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x); | |
4547 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x); | |
4548 } | |
4549 else | |
4550 { | |
4551 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x); | |
4552 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x); | |
4553 } | |
4554 | |
4555 min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w); | |
4556 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y)); | |
4557 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y); | |
4558 | |
4559 /* Prevent inadvertently clearing to end of the X window. */ | |
4560 if (to_x > from_x && to_y > from_y) | |
4561 { | |
4562 BLOCK_INPUT; | |
4563 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
4564 from_x, from_y, to_x - from_x, to_y - from_y, | |
4565 False); | |
4566 UNBLOCK_INPUT; | |
4567 } | |
4568 } | |
4569 | |
4570 | |
4571 /* Clear entire frame. If updating_frame is non-null, clear that | |
4572 frame. Otherwise clear selected_frame. */ | |
4573 | |
4574 static void | |
4575 x_clear_frame () | |
4576 { | |
4577 struct frame *f; | |
4578 | |
4579 if (updating_frame) | |
4580 f = updating_frame; | |
4581 else | |
4582 f = selected_frame; | |
4583 | |
4584 /* Clearing the frame will erase any cursor, so mark them all as no | |
4585 longer visible. */ | |
4586 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); | |
4587 output_cursor.hpos = output_cursor.vpos = 0; | |
4588 output_cursor.x = -1; | |
4589 | |
4590 /* We don't set the output cursor here because there will always | |
4591 follow an explicit cursor_to. */ | |
1280 BLOCK_INPUT; | 4592 BLOCK_INPUT; |
1281 | |
1282 do_line_dance (); | |
1283 | |
1284 /* Notice if the cursor will be cleared by this operation. */ | |
1285 if (curs_y == f->phys_cursor_y | |
1286 && curs_x <= f->phys_cursor_x | |
1287 && f->phys_cursor_x < first_unused) | |
1288 f->phys_cursor_on = 0; | |
1289 | |
1290 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
1291 CHAR_TO_PIXEL_COL (f, curs_x), | |
1292 CHAR_TO_PIXEL_ROW (f, curs_y), | |
1293 FONT_WIDTH (f->output_data.x->font) * (first_unused - curs_x), | |
1294 f->output_data.x->line_height, False); | |
1295 #if 0 | |
1296 redraw_previous_char (f, curs_x, curs_y, highlight); | |
1297 #endif | |
1298 | |
1299 UNBLOCK_INPUT; | |
1300 } | |
1301 | |
1302 static void | |
1303 XTclear_frame () | |
1304 { | |
1305 int mask; | |
1306 struct frame *f = updating_frame; | |
1307 | |
1308 if (f == 0) | |
1309 f = selected_frame; | |
1310 | |
1311 f->phys_cursor_on = 0; /* Cursor not visible. */ | |
1312 curs_x = 0; /* Nominal cursor position is top left. */ | |
1313 curs_y = 0; | |
1314 | |
1315 BLOCK_INPUT; | |
1316 | |
1317 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); | 4593 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); |
1318 | 4594 |
1319 /* We have to clear the scroll bars, too. If we have changed | 4595 /* We have to clear the scroll bars, too. If we have changed |
1320 colors or something like that, then they should be notified. */ | 4596 colors or something like that, then they should be notified. */ |
1321 x_scroll_bar_clear (f); | 4597 x_scroll_bar_clear (f); |
1322 | 4598 |
1323 XFlush (FRAME_X_DISPLAY (f)); | 4599 XFlush (FRAME_X_DISPLAY (f)); |
1324 UNBLOCK_INPUT; | 4600 UNBLOCK_INPUT; |
1325 } | 4601 } |
1326 | 4602 |
1327 #if 0 | 4603 |
1328 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't | |
1329 always contain the right glyphs to use. | |
1330 | |
1331 It also needs to be changed to look at the details of the font and | |
1332 see whether there is really overlap, and do nothing when there is | |
1333 not. This can use font_char_overlap_left and font_char_overlap_right, | |
1334 but just how to use them is not clear. */ | |
1335 | |
1336 /* Erase the character (if any) at the position just before X, Y in frame F, | |
1337 then redraw it and the character before it. | |
1338 This is necessary when we erase starting at X, | |
1339 in case the character after X overlaps into the one before X. | |
1340 Call this function with input blocked. */ | |
1341 | |
1342 static void | |
1343 redraw_previous_char (f, x, y, highlight_flag) | |
1344 FRAME_PTR f; | |
1345 int x, y; | |
1346 int highlight_flag; | |
1347 { | |
1348 /* Erase the character before the new ones, in case | |
1349 what was here before overlaps it. | |
1350 Reoutput that character, and the previous character | |
1351 (in case the previous character overlaps it). */ | |
1352 if (x > 0) | |
1353 { | |
1354 int start_x = x - 2; | |
1355 if (start_x < 0) | |
1356 start_x = 0; | |
1357 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
1358 CHAR_TO_PIXEL_COL (f, x - 1), | |
1359 CHAR_TO_PIXEL_ROW (f, y), | |
1360 FONT_WIDTH (f->output_data.x->font), | |
1361 f->output_data.x->line_height, False); | |
1362 | |
1363 dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x), | |
1364 CHAR_TO_PIXEL_ROW (f, y), | |
1365 &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x], | |
1366 x - start_x, highlight_flag, 1, NULL); | |
1367 } | |
1368 } | |
1369 | |
1370 /* Erase the character (if any) at the position X, Y in frame F, | |
1371 then redraw it and the character after it. | |
1372 This is necessary when we erase endng at X, | |
1373 in case the character after X overlaps into the one before X. | |
1374 Call this function with input blocked. */ | |
1375 | |
1376 static void | |
1377 redraw_following_char (f, x, y, highlight_flag) | |
1378 FRAME_PTR f; | |
1379 int x, y; | |
1380 int highlight_flag; | |
1381 { | |
1382 int limit = FRAME_CURRENT_GLYPHS (f)->used[y]; | |
1383 /* Erase the character after the new ones, in case | |
1384 what was here before overlaps it. | |
1385 Reoutput that character, and the following character | |
1386 (in case the following character overlaps it). */ | |
1387 if (x < limit | |
1388 && FRAME_CURRENT_GLYPHS (f)->glyphs[y][x] != SPACEGLYPH) | |
1389 { | |
1390 int end_x = x + 2; | |
1391 if (end_x > limit) | |
1392 end_x = limit; | |
1393 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
1394 CHAR_TO_PIXEL_COL (f, x), | |
1395 CHAR_TO_PIXEL_ROW (f, y), | |
1396 FONT_WIDTH (f->output_data.x->font), | |
1397 f->output_data.x->line_height, False); | |
1398 | |
1399 dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x), | |
1400 CHAR_TO_PIXEL_ROW (f, y), | |
1401 &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x], | |
1402 end_x - x, highlight_flag, 1, NULL); | |
1403 } | |
1404 } | |
1405 #endif /* 0 */ | |
1406 | |
1407 #if 0 /* Not in use yet */ | |
1408 | |
1409 /* Return 1 if character C in font F extends past its left edge. */ | |
1410 | |
1411 static int | |
1412 font_char_overlap_left (font, c) | |
1413 XFontStruct *font; | |
1414 int c; | |
1415 { | |
1416 XCharStruct *s; | |
1417 | |
1418 /* Find the bounding-box info for C. */ | |
1419 if (font->per_char == 0) | |
1420 s = &font->max_bounds; | |
1421 else | |
1422 { | |
1423 int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1; | |
1424 int row, within; | |
1425 | |
1426 /* Decode char into row number (byte 1) and code within row (byte 2). */ | |
1427 row = c >> 8; | |
1428 within = c & 0177; | |
1429 if (!(within >= font->min_char_or_byte2 | |
1430 && within <= font->max_char_or_byte2 | |
1431 && row >= font->min_byte1 | |
1432 && row <= font->max_byte1)) | |
1433 { | |
1434 /* If char is out of range, try the font's default char instead. */ | |
1435 c = font->default_char; | |
1436 row = c >> (BITS_PER_INT - 8); | |
1437 within = c & 0177; | |
1438 } | |
1439 if (!(within >= font->min_char_or_byte2 | |
1440 && within <= font->max_char_or_byte2 | |
1441 && row >= font->min_byte1 | |
1442 && row <= font->max_byte1)) | |
1443 /* Still out of range means this char does not overlap. */ | |
1444 return 0; | |
1445 else | |
1446 /* We found the info for this char. */ | |
1447 s = (font->per_char + (within - font->min_char_or_byte2) | |
1448 + row * rowlen); | |
1449 } | |
1450 | |
1451 return (s && s->lbearing < 0); | |
1452 } | |
1453 | |
1454 /* Return 1 if character C in font F extends past its right edge. */ | |
1455 | |
1456 static int | |
1457 font_char_overlap_right (font, c) | |
1458 XFontStruct *font; | |
1459 int c; | |
1460 { | |
1461 XCharStruct *s; | |
1462 | |
1463 /* Find the bounding-box info for C. */ | |
1464 if (font->per_char == 0) | |
1465 s = &font->max_bounds; | |
1466 else | |
1467 { | |
1468 int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1; | |
1469 int row, within; | |
1470 | |
1471 /* Decode char into row number (byte 1) and code within row (byte 2). */ | |
1472 row = c >> 8; | |
1473 within = c & 0177; | |
1474 if (!(within >= font->min_char_or_byte2 | |
1475 && within <= font->max_char_or_byte2 | |
1476 && row >= font->min_byte1 | |
1477 && row <= font->max_byte1)) | |
1478 { | |
1479 /* If char is out of range, try the font's default char instead. */ | |
1480 c = font->default_char; | |
1481 row = c >> (BITS_PER_INT - 8); | |
1482 within = c & 0177; | |
1483 } | |
1484 if (!(within >= font->min_char_or_byte2 | |
1485 && within <= font->max_char_or_byte2 | |
1486 && row >= font->min_byte1 | |
1487 && row <= font->max_byte1)) | |
1488 /* Still out of range means this char does not overlap. */ | |
1489 return 0; | |
1490 else | |
1491 /* We found the info for this char. */ | |
1492 s = (font->per_char + (within - font->min_char_or_byte2) | |
1493 + row * rowlen); | |
1494 } | |
1495 | |
1496 return (s && s->rbearing >= s->width); | |
1497 } | |
1498 #endif /* 0 */ | |
1499 | 4604 |
1500 /* Invert the middle quarter of the frame for .15 sec. */ | 4605 /* Invert the middle quarter of the frame for .15 sec. */ |
1501 | 4606 |
1502 /* We use the select system call to do the waiting, so we have to make sure | 4607 /* We use the select system call to do the waiting, so we have to make |
1503 it's available. If it isn't, we just won't do visual bells. */ | 4608 sure it's available. If it isn't, we just won't do visual bells. */ |
4609 | |
1504 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) | 4610 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) |
1505 | 4611 |
1506 /* Subtract the `struct timeval' values X and Y, | 4612 |
1507 storing the result in RESULT. | 4613 /* Subtract the `struct timeval' values X and Y, storing the result in |
1508 Return 1 if the difference is negative, otherwise 0. */ | 4614 *RESULT. Return 1 if the difference is negative, otherwise 0. */ |
1509 | 4615 |
1510 static int | 4616 static int |
1511 timeval_subtract (result, x, y) | 4617 timeval_subtract (result, x, y) |
1512 struct timeval *result, x, y; | 4618 struct timeval *result, x, y; |
1513 { | 4619 { |
1514 /* Perform the carry for the later subtraction by updating y. | 4620 /* Perform the carry for the later subtraction by updating y. This |
1515 This is safer because on some systems | 4621 is safer because on some systems the tv_sec member is unsigned. */ |
1516 the tv_sec member is unsigned. */ | |
1517 if (x.tv_usec < y.tv_usec) | 4622 if (x.tv_usec < y.tv_usec) |
1518 { | 4623 { |
1519 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; | 4624 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; |
1520 y.tv_usec -= 1000000 * nsec; | 4625 y.tv_usec -= 1000000 * nsec; |
1521 y.tv_sec += nsec; | 4626 y.tv_sec += nsec; |
1522 } | 4627 } |
4628 | |
1523 if (x.tv_usec - y.tv_usec > 1000000) | 4629 if (x.tv_usec - y.tv_usec > 1000000) |
1524 { | 4630 { |
1525 int nsec = (y.tv_usec - x.tv_usec) / 1000000; | 4631 int nsec = (y.tv_usec - x.tv_usec) / 1000000; |
1526 y.tv_usec += 1000000 * nsec; | 4632 y.tv_usec += 1000000 * nsec; |
1527 y.tv_sec -= nsec; | 4633 y.tv_sec -= nsec; |
1528 } | 4634 } |
1529 | 4635 |
1530 /* Compute the time remaining to wait. tv_usec is certainly positive. */ | 4636 /* Compute the time remaining to wait. tv_usec is certainly |
4637 positive. */ | |
1531 result->tv_sec = x.tv_sec - y.tv_sec; | 4638 result->tv_sec = x.tv_sec - y.tv_sec; |
1532 result->tv_usec = x.tv_usec - y.tv_usec; | 4639 result->tv_usec = x.tv_usec - y.tv_usec; |
1533 | 4640 |
1534 /* Return indication of whether the result should be considered negative. */ | 4641 /* Return indication of whether the result should be considered |
4642 negative. */ | |
1535 return x.tv_sec < y.tv_sec; | 4643 return x.tv_sec < y.tv_sec; |
1536 } | 4644 } |
1537 | 4645 |
1538 void | 4646 void |
1539 XTflash (f) | 4647 XTflash (f) |
1542 BLOCK_INPUT; | 4650 BLOCK_INPUT; |
1543 | 4651 |
1544 { | 4652 { |
1545 GC gc; | 4653 GC gc; |
1546 | 4654 |
1547 /* Create a GC that will use the GXxor function to flip foreground pixels | 4655 /* Create a GC that will use the GXxor function to flip foreground |
1548 into background pixels. */ | 4656 pixels into background pixels. */ |
1549 { | 4657 { |
1550 XGCValues values; | 4658 XGCValues values; |
1551 | 4659 |
1552 values.function = GXxor; | 4660 values.function = GXxor; |
1553 values.foreground = (f->output_data.x->foreground_pixel | 4661 values.foreground = (f->output_data.x->foreground_pixel |
1577 break; | 4685 break; |
1578 | 4686 |
1579 case vertical_scroll_bar_right: | 4687 case vertical_scroll_bar_right: |
1580 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM; | 4688 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM; |
1581 break; | 4689 break; |
4690 | |
4691 default: | |
4692 break; | |
1582 } | 4693 } |
1583 | 4694 |
1584 width = flash_right - flash_left; | 4695 width = flash_right - flash_left; |
1585 | 4696 |
1586 /* If window is tall, flash top and bottom line. */ | 4697 /* If window is tall, flash top and bottom line. */ |
1587 if (height > 3 * FRAME_LINE_HEIGHT (f)) | 4698 if (height > 3 * FRAME_LINE_HEIGHT (f)) |
1588 { | 4699 { |
1589 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | 4700 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
1590 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), | 4701 flash_left, |
4702 (FRAME_INTERNAL_BORDER_WIDTH (f) | |
4703 + FRAME_TOOLBAR_LINES (f) * CANON_Y_UNIT (f)), | |
1591 width, flash_height); | 4704 width, flash_height); |
1592 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | 4705 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
1593 flash_left, | 4706 flash_left, |
1594 (height - flash_height | 4707 (height - flash_height |
1595 - FRAME_INTERNAL_BORDER_WIDTH (f)), | 4708 - FRAME_INTERNAL_BORDER_WIDTH (f)), |
1599 /* If it is short, flash it all. */ | 4712 /* If it is short, flash it all. */ |
1600 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | 4713 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
1601 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), | 4714 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), |
1602 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); | 4715 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); |
1603 | 4716 |
1604 XFlush (FRAME_X_DISPLAY (f)); | 4717 x_flush (f); |
1605 | 4718 |
1606 { | 4719 { |
1607 struct timeval wakeup, now; | 4720 struct timeval wakeup; |
1608 | 4721 |
1609 EMACS_GET_TIME (wakeup); | 4722 EMACS_GET_TIME (wakeup); |
1610 | 4723 |
1611 /* Compute time to wait until, propagating carry from usecs. */ | 4724 /* Compute time to wait until, propagating carry from usecs. */ |
1612 wakeup.tv_usec += 150000; | 4725 wakeup.tv_usec += 150000; |
1632 | 4745 |
1633 /* If window is tall, flash top and bottom line. */ | 4746 /* If window is tall, flash top and bottom line. */ |
1634 if (height > 3 * FRAME_LINE_HEIGHT (f)) | 4747 if (height > 3 * FRAME_LINE_HEIGHT (f)) |
1635 { | 4748 { |
1636 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | 4749 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
1637 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), | 4750 flash_left, |
4751 (FRAME_INTERNAL_BORDER_WIDTH (f) | |
4752 + FRAME_TOOLBAR_LINES (f) * CANON_Y_UNIT (f)), | |
1638 width, flash_height); | 4753 width, flash_height); |
1639 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | 4754 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
1640 flash_left, | 4755 flash_left, |
1641 (height - flash_height | 4756 (height - flash_height |
1642 - FRAME_INTERNAL_BORDER_WIDTH (f)), | 4757 - FRAME_INTERNAL_BORDER_WIDTH (f)), |
1647 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | 4762 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
1648 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), | 4763 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), |
1649 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); | 4764 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); |
1650 | 4765 |
1651 XFreeGC (FRAME_X_DISPLAY (f), gc); | 4766 XFreeGC (FRAME_X_DISPLAY (f), gc); |
1652 XFlush (FRAME_X_DISPLAY (f)); | 4767 x_flush (f); |
1653 } | 4768 } |
1654 } | 4769 } |
1655 | 4770 |
1656 UNBLOCK_INPUT; | 4771 UNBLOCK_INPUT; |
1657 } | 4772 } |
1658 | 4773 |
1659 #endif | 4774 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */ |
1660 | 4775 |
1661 | 4776 |
1662 /* Make audible bell. */ | 4777 /* Make audible bell. */ |
1663 | 4778 |
1664 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0) | 4779 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0) |
1679 XRINGBELL; | 4794 XRINGBELL; |
1680 XFlush (FRAME_X_DISPLAY (selected_frame)); | 4795 XFlush (FRAME_X_DISPLAY (selected_frame)); |
1681 UNBLOCK_INPUT; | 4796 UNBLOCK_INPUT; |
1682 } | 4797 } |
1683 } | 4798 } |
1684 | 4799 |
1685 /* Insert and delete character. | |
1686 These are not supposed to be used because we are supposed to turn | |
1687 off the feature of using them. */ | |
1688 | |
1689 static void | |
1690 XTinsert_glyphs (start, len) | |
1691 register char *start; | |
1692 register int len; | |
1693 { | |
1694 abort (); | |
1695 } | |
1696 | |
1697 static void | |
1698 XTdelete_glyphs (n) | |
1699 register int n; | |
1700 { | |
1701 abort (); | |
1702 } | |
1703 | 4800 |
1704 /* Specify how many text lines, from the top of the window, | 4801 /* Specify how many text lines, from the top of the window, |
1705 should be affected by insert-lines and delete-lines operations. | 4802 should be affected by insert-lines and delete-lines operations. |
1706 This, and those operations, are used only within an update | 4803 This, and those operations, are used only within an update |
1707 that is bounded by calls to XTupdate_begin and XTupdate_end. */ | 4804 that is bounded by calls to x_update_begin and x_update_end. */ |
1708 | 4805 |
1709 static void | 4806 static void |
1710 XTset_terminal_window (n) | 4807 XTset_terminal_window (n) |
1711 register int n; | 4808 register int n; |
1712 { | 4809 { |
1713 if (updating_frame == 0) | 4810 /* This function intentionally left blank. */ |
1714 abort (); | 4811 } |
1715 | 4812 |
1716 if ((n <= 0) || (n > updating_frame->height)) | 4813 |
1717 flexlines = updating_frame->height; | 4814 |
4815 /*********************************************************************** | |
4816 Line Dance | |
4817 ***********************************************************************/ | |
4818 | |
4819 /* Perform an insert-lines or delete-lines operation, inserting N | |
4820 lines or deleting -N lines at vertical position VPOS. */ | |
4821 | |
4822 static void | |
4823 x_ins_del_lines (vpos, n) | |
4824 int vpos, n; | |
4825 { | |
4826 abort (); | |
4827 } | |
4828 | |
4829 | |
4830 /* Scroll part of the display as described by RUN. */ | |
4831 | |
4832 static void | |
4833 x_scroll_run (w, run) | |
4834 struct window *w; | |
4835 struct run *run; | |
4836 { | |
4837 struct frame *f = XFRAME (w->frame); | |
4838 int x, y, width, height, from_y, to_y, bottom_y; | |
4839 | |
4840 /* Get frame-relative bounding box of the text display area of W, | |
4841 without mode lines. Include in this box the flags areas to the | |
4842 left and right of W. */ | |
4843 window_box (w, -1, &x, &y, &width, &height); | |
4844 width += 2 * FRAME_X_FLAGS_AREA_WIDTH (f); | |
4845 x -= FRAME_X_FLAGS_AREA_WIDTH (f); | |
4846 | |
4847 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y); | |
4848 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y); | |
4849 bottom_y = y + height; | |
4850 | |
4851 if (to_y < from_y) | |
4852 { | |
4853 /* Scrolling up. Make sure we don't copy part of the mode | |
4854 line at the bottom. */ | |
4855 if (from_y + run->height > bottom_y) | |
4856 height = bottom_y - from_y; | |
4857 else | |
4858 height = run->height; | |
4859 } | |
1718 else | 4860 else |
1719 flexlines = n; | 4861 { |
1720 } | 4862 /* Scolling down. Make sure we don't copy over the mode line. |
4863 at the bottom. */ | |
4864 if (to_y + run->height > bottom_y) | |
4865 height = bottom_y - to_y; | |
4866 else | |
4867 height = run->height; | |
4868 } | |
4869 | |
4870 BLOCK_INPUT; | |
4871 | |
4872 /* Cursor off. Will be switched on again in x_update_window_end. */ | |
4873 updated_window = w; | |
4874 x_clear_cursor (w); | |
4875 | |
4876 XCopyArea (FRAME_X_DISPLAY (f), | |
4877 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), | |
4878 f->output_data.x->normal_gc, | |
4879 x, from_y, | |
4880 width, height, | |
4881 x, to_y); | |
4882 | |
4883 UNBLOCK_INPUT; | |
4884 } | |
4885 | |
4886 | |
1721 | 4887 |
1722 /* These variables need not be per frame | 4888 /*********************************************************************** |
1723 because redisplay is done on a frame-by-frame basis | 4889 Exposure Events |
1724 and the line dance for one frame is finished before | 4890 ***********************************************************************/ |
1725 anything is done for anoter frame. */ | 4891 |
1726 | 4892 /* Redisplay an exposed area of frame F. X and Y are the upper-left |
1727 /* Array of line numbers from cached insert/delete operations. | 4893 corner of the exposed rectangle. W and H are width and height of |
1728 line_dance[i] is the old position of the line that we want | 4894 the exposed area. All are pixel values. W or H zero means redraw |
1729 to move to line i, or -1 if we want a blank line there. */ | 4895 the entire frame. */ |
1730 static int *line_dance; | 4896 |
1731 | 4897 static void |
1732 /* Allocated length of that array. */ | 4898 expose_frame (f, x, y, w, h) |
1733 static int line_dance_len; | 4899 struct frame *f; |
1734 | 4900 int x, y, w, h; |
1735 /* Flag indicating whether we've done any work. */ | 4901 { |
1736 static int line_dance_in_progress; | 4902 XRectangle r; |
1737 | 4903 |
1738 /* Perform an insert-lines or delete-lines operation, | 4904 TRACE ((stderr, "expose_frame ")); |
1739 inserting N lines or deleting -N lines at vertical position VPOS. */ | 4905 |
1740 void | 4906 /* No need to redraw if frame will be redrawn soon. */ |
1741 XTins_del_lines (vpos, n) | 4907 if (FRAME_GARBAGED_P (f)) |
1742 int vpos, n; | 4908 { |
1743 { | 4909 TRACE ((stderr, " garbaged\n")); |
1744 register int fence, i; | 4910 return; |
1745 | 4911 } |
1746 if (vpos >= flexlines) | 4912 |
1747 return; | 4913 /* If basic faces haven't been realized yet, there is no point in |
1748 | 4914 trying to redraw anything. This can happen when we get an expose |
1749 if (!line_dance_in_progress) | 4915 event while Emacs is starting, e.g. by moving another window. */ |
1750 { | 4916 if (FRAME_FACE_CACHE (f) == NULL |
1751 int ht = updating_frame->height; | 4917 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL) |
1752 if (ht > line_dance_len) | 4918 { |
4919 TRACE ((stderr, " no faces\n")); | |
4920 return; | |
4921 } | |
4922 | |
4923 if (w == 0 || h == 0) | |
4924 { | |
4925 r.x = r.y = 0; | |
4926 r.width = CANON_X_UNIT (f) * f->width; | |
4927 r.height = CANON_Y_UNIT (f) * f->height; | |
4928 } | |
4929 else | |
4930 { | |
4931 r.x = x; | |
4932 r.y = y; | |
4933 r.width = w; | |
4934 r.height = h; | |
4935 } | |
4936 | |
4937 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height)); | |
4938 expose_window_tree (XWINDOW (f->root_window), &r); | |
4939 | |
4940 if (WINDOWP (f->toolbar_window)) | |
4941 { | |
4942 struct window *w = XWINDOW (f->toolbar_window); | |
4943 XRectangle window_rect; | |
4944 XRectangle intersection_rect; | |
4945 int window_x, window_y, window_width, window_height; | |
4946 | |
4947 | |
4948 window_box (w, -1, &window_x, &window_y, &window_width, &window_height); | |
4949 window_rect.x = window_x; | |
4950 window_rect.y = window_y; | |
4951 window_rect.width = window_width; | |
4952 window_rect.height = window_height; | |
4953 | |
4954 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect)) | |
4955 expose_window (w, &intersection_rect); | |
4956 } | |
4957 | |
4958 #ifndef USE_X_TOOLKIT | |
4959 if (WINDOWP (f->menu_bar_window)) | |
4960 { | |
4961 struct window *w = XWINDOW (f->menu_bar_window); | |
4962 XRectangle window_rect; | |
4963 XRectangle intersection_rect; | |
4964 int window_x, window_y, window_width, window_height; | |
4965 | |
4966 | |
4967 window_box (w, -1, &window_x, &window_y, &window_width, &window_height); | |
4968 window_rect.x = window_x; | |
4969 window_rect.y = window_y; | |
4970 window_rect.width = window_width; | |
4971 window_rect.height = window_height; | |
4972 | |
4973 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect)) | |
4974 expose_window (w, &intersection_rect); | |
4975 } | |
4976 #endif /* not USE_X_TOOLKIT */ | |
4977 } | |
4978 | |
4979 | |
4980 /* Redraw (parts) of all windows in the window tree rooted at W that | |
4981 intersect R. R contains frame pixel coordinates. */ | |
4982 | |
4983 static void | |
4984 expose_window_tree (w, r) | |
4985 struct window *w; | |
4986 XRectangle *r; | |
4987 { | |
4988 while (w) | |
4989 { | |
4990 if (!NILP (w->hchild)) | |
4991 expose_window_tree (XWINDOW (w->hchild), r); | |
4992 else if (!NILP (w->vchild)) | |
4993 expose_window_tree (XWINDOW (w->vchild), r); | |
4994 else | |
1753 { | 4995 { |
1754 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int)); | 4996 XRectangle window_rect; |
1755 line_dance_len = ht; | 4997 XRectangle intersection_rect; |
4998 struct frame *f = XFRAME (w->frame); | |
4999 int window_x, window_y, window_width, window_height; | |
5000 | |
5001 /* Frame-relative pixel rectangle of W. */ | |
5002 window_box (w, -1, &window_x, &window_y, &window_width, | |
5003 &window_height); | |
5004 window_rect.x | |
5005 = (window_x | |
5006 - FRAME_X_FLAGS_AREA_WIDTH (f) | |
5007 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f)); | |
5008 window_rect.y = window_y; | |
5009 window_rect.width | |
5010 = (window_width | |
5011 + 2 * FRAME_X_FLAGS_AREA_WIDTH (f) | |
5012 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)); | |
5013 window_rect.height | |
5014 = window_height + CURRENT_MODE_LINE_HEIGHT (w); | |
5015 | |
5016 if (x_intersect_rectangles (r, &window_rect, &intersection_rect)) | |
5017 expose_window (w, &intersection_rect); | |
1756 } | 5018 } |
1757 for (i = 0; i < ht; ++i) line_dance[i] = i; | 5019 |
1758 line_dance_in_progress = 1; | 5020 w = NILP (w->next) ? 0 : XWINDOW (w->next); |
1759 } | 5021 } |
1760 if (n >= 0) | 5022 } |
1761 { | 5023 |
1762 if (n > flexlines - vpos) | 5024 |
1763 n = flexlines - vpos; | 5025 /* Redraw the part of glyph row area AREA of glyph row ROW on window W |
1764 fence = vpos + n; | 5026 which intersects rectangle R. R is in window-relative coordinates. */ |
1765 for (i = flexlines; --i >= fence;) | 5027 |
1766 line_dance[i] = line_dance[i-n]; | 5028 static void |
1767 for (i = fence; --i >= vpos;) | 5029 expose_area (w, row, r, area) |
1768 line_dance[i] = -1; | 5030 struct window *w; |
1769 } | 5031 struct glyph_row *row; |
5032 XRectangle *r; | |
5033 enum glyph_row_area area; | |
5034 { | |
5035 int x; | |
5036 struct glyph *first = row->glyphs[area]; | |
5037 struct glyph *end = row->glyphs[area] + row->used[area]; | |
5038 struct glyph *last; | |
5039 int first_x; | |
5040 | |
5041 /* Set x to the window-relative start position for drawing glyphs of | |
5042 AREA. The first glyph of the text area can be partially visible. | |
5043 The first glyphs of other areas cannot. */ | |
5044 if (area == LEFT_MARGIN_AREA) | |
5045 x = 0; | |
5046 else if (area == TEXT_AREA) | |
5047 x = row->x + window_box_width (w, LEFT_MARGIN_AREA); | |
1770 else | 5048 else |
1771 { | 5049 x = (window_box_width (w, LEFT_MARGIN_AREA) |
1772 n = -n; | 5050 + window_box_width (w, TEXT_AREA)); |
1773 if (n > flexlines - vpos) | 5051 |
1774 n = flexlines - vpos; | 5052 /* Find the first glyph that must be redrawn. */ |
1775 fence = flexlines - n; | 5053 while (first < end |
1776 for (i = vpos; i < fence; ++i) | 5054 && x + first->pixel_width < r->x) |
1777 line_dance[i] = line_dance[i + n]; | 5055 { |
1778 for (i = fence; i < flexlines; ++i) | 5056 x += first->pixel_width; |
1779 line_dance[i] = -1; | 5057 ++first; |
1780 } | 5058 } |
1781 } | 5059 |
1782 | 5060 /* Find the last one. */ |
1783 /* Here's where we actually move the pixels around. | 5061 last = first; |
1784 Must be called with input blocked. */ | 5062 first_x = x; |
5063 while (last < end | |
5064 && x < r->x + r->width) | |
5065 { | |
5066 x += last->pixel_width; | |
5067 ++last; | |
5068 } | |
5069 | |
5070 /* Repaint. */ | |
5071 if (last > first) | |
5072 x_draw_glyphs (w, first_x, row, area, | |
5073 first - row->glyphs[area], | |
5074 last - row->glyphs[area], | |
5075 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT, | |
5076 NULL, NULL); | |
5077 } | |
5078 | |
5079 | |
5080 /* Redraw the parts of the glyph row ROW on window W intersecting | |
5081 rectangle R. R is in window-relative coordinates. */ | |
5082 | |
1785 static void | 5083 static void |
1786 do_line_dance () | 5084 expose_line (w, row, r) |
1787 { | 5085 struct window *w; |
1788 register int i, j, distance; | 5086 struct glyph_row *row; |
1789 register struct frame *f; | 5087 XRectangle *r; |
1790 int ht; | 5088 { |
1791 int intborder; | 5089 xassert (row->enabled_p); |
1792 | 5090 |
1793 /* Must check this flag first. If it's not set, then not only is the | 5091 if (row->mode_line_p || w->pseudo_window_p) |
1794 array uninitialized, but we might not even have a frame. */ | 5092 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA], |
1795 if (!line_dance_in_progress) | 5093 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT, |
1796 return; | 5094 NULL, NULL); |
1797 | 5095 else |
1798 f = updating_frame; | 5096 { |
1799 if (f == 0) | 5097 if (row->used[LEFT_MARGIN_AREA]) |
1800 abort (); | 5098 expose_area (w, row, r, LEFT_MARGIN_AREA); |
1801 | 5099 if (row->used[TEXT_AREA]) |
1802 ht = f->height; | 5100 expose_area (w, row, r, TEXT_AREA); |
1803 intborder = CHAR_TO_PIXEL_COL (f, FRAME_LEFT_SCROLL_BAR_WIDTH (f)); | 5101 if (row->used[RIGHT_MARGIN_AREA]) |
1804 | 5102 expose_area (w, row, r, RIGHT_MARGIN_AREA); |
1805 x_update_cursor (updating_frame, 0); | 5103 x_draw_row_bitmaps (w, row); |
1806 | 5104 } |
1807 for (i = 0; i < ht; ++i) | 5105 } |
1808 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0) | 5106 |
1809 { | 5107 |
1810 for (j = i; (j < ht && line_dance[j] != -1 | 5108 /* Return non-zero if W's cursor intersects rectangle R. */ |
1811 && line_dance[j]-j == distance); ++j); | 5109 |
1812 /* Copy [i,j) upward from [i+distance,j+distance) */ | 5110 static int |
1813 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 5111 x_phys_cursor_in_rect_p (w, r) |
1814 FRAME_X_WINDOW (f), f->output_data.x->normal_gc, | 5112 struct window *w; |
1815 intborder, CHAR_TO_PIXEL_ROW (f, i+distance), | 5113 XRectangle *r; |
1816 FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font), | 5114 { |
1817 (j-i) * f->output_data.x->line_height, | 5115 XRectangle cr, result; |
1818 intborder, CHAR_TO_PIXEL_ROW (f, i)); | 5116 struct glyph *cursor_glyph; |
1819 i = j-1; | 5117 |
1820 } | 5118 cursor_glyph = get_phys_cursor_glyph (w); |
1821 | 5119 if (cursor_glyph) |
1822 for (i = ht; --i >=0; ) | 5120 { |
1823 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0) | 5121 cr.x = w->phys_cursor.x; |
1824 { | 5122 cr.y = w->phys_cursor.y; |
1825 for (j = i; (--j >= 0 && line_dance[j] != -1 | 5123 cr.width = cursor_glyph->pixel_width; |
1826 && line_dance[j]-j == distance);); | 5124 cr.height = w->phys_cursor_height; |
1827 /* Copy (j,i] downward from (j+distance, i+distance] */ | 5125 return x_intersect_rectangles (&cr, r, &result); |
1828 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 5126 } |
1829 FRAME_X_WINDOW (f), f->output_data.x->normal_gc, | 5127 else |
1830 intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance), | 5128 return 0; |
1831 FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font), | 5129 } |
1832 (i-j) * f->output_data.x->line_height, | 5130 |
1833 intborder, CHAR_TO_PIXEL_ROW (f, j+1)); | 5131 |
1834 i = j+1; | 5132 /* Redraw a rectangle of window W. R is a rectangle in window |
1835 } | 5133 relative coordinates. Call this function with input blocked. */ |
1836 | |
1837 for (i = 0; i < ht; ++i) | |
1838 if (line_dance[i] == -1) | |
1839 { | |
1840 for (j = i; j < ht && line_dance[j] == -1; ++j); | |
1841 /* Clear [i,j) */ | |
1842 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
1843 intborder, CHAR_TO_PIXEL_ROW (f, i), | |
1844 FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font), | |
1845 (j-i) * f->output_data.x->line_height, False); | |
1846 i = j-1; | |
1847 } | |
1848 line_dance_in_progress = 0; | |
1849 } | |
1850 | |
1851 /* Support routines for exposure events. */ | |
1852 static void clear_cursor (); | |
1853 | |
1854 /* Output into a rectangle of an X-window (for frame F) | |
1855 the characters in f->phys_lines that overlap that rectangle. | |
1856 TOP and LEFT are the position of the upper left corner of the rectangle. | |
1857 ROWS and COLS are the size of the rectangle. | |
1858 Call this function with input blocked. */ | |
1859 | 5134 |
1860 static void | 5135 static void |
1861 dumprectangle (f, left, top, cols, rows) | 5136 expose_window (w, r) |
1862 struct frame *f; | 5137 struct window *w; |
1863 register int left, top, cols, rows; | 5138 XRectangle *r; |
1864 { | 5139 { |
1865 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f); | 5140 struct glyph_row *row; |
1866 int cursor_cleared = 0; | 5141 int y; |
1867 int bottom, right; | 5142 int yb = window_text_bottom_y (w); |
1868 register int y; | 5143 int cursor_cleared_p; |
1869 | 5144 |
1870 if (FRAME_GARBAGED_P (f)) | 5145 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n", |
1871 return; | 5146 r->x, r->y, r->width, r->height)); |
1872 | 5147 |
1873 /* Express rectangle as four edges, instead of position-and-size. */ | 5148 /* Convert to window coordinates. */ |
1874 bottom = top + rows; | 5149 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x); |
1875 right = left + cols; | 5150 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y); |
1876 | 5151 |
1877 /* Convert rectangle edges in pixels to edges in chars. | 5152 /* Turn off the cursor. */ |
1878 Round down for left and top, up for right and bottom. */ | 5153 if (!w->pseudo_window_p |
1879 top = PIXEL_TO_CHAR_ROW (f, top); | 5154 && x_phys_cursor_in_rect_p (w, r)) |
1880 left = PIXEL_TO_CHAR_COL (f, left); | 5155 { |
1881 bottom += (f->output_data.x->line_height - 1); | 5156 x_clear_cursor (w); |
1882 right += (FONT_WIDTH (f->output_data.x->font) - 1); | 5157 cursor_cleared_p = 1; |
1883 bottom = PIXEL_TO_CHAR_ROW (f, bottom); | 5158 } |
1884 right = PIXEL_TO_CHAR_COL (f, right); | 5159 else |
1885 | 5160 cursor_cleared_p = 0; |
1886 /* Clip the rectangle to what can be visible. */ | 5161 |
1887 if (left < 0) | 5162 /* Find the first row intersecting the rectangle R. */ |
1888 left = 0; | 5163 row = w->current_matrix->rows; |
1889 if (top < 0) | 5164 y = 0; |
1890 top = 0; | 5165 while (row->enabled_p |
1891 if (right > FRAME_WINDOW_WIDTH (f)) | 5166 && y < yb |
1892 right = FRAME_WINDOW_WIDTH (f); | 5167 && y + row->height < r->y) |
1893 if (bottom > f->height) | 5168 { |
1894 bottom = f->height; | 5169 y += row->height; |
1895 | 5170 ++row; |
1896 /* Get size in chars of the rectangle. */ | 5171 } |
1897 cols = right - left; | 5172 |
1898 rows = bottom - top; | |
1899 | |
1900 /* If rectangle has zero area, return. */ | |
1901 if (rows <= 0) return; | |
1902 if (cols <= 0) return; | |
1903 | |
1904 /* Turn off the cursor if it is in the rectangle. | |
1905 We will turn it back on afterward. */ | |
1906 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right) | |
1907 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom)) | |
1908 { | |
1909 clear_cursor (f); | |
1910 cursor_cleared = 1; | |
1911 } | |
1912 | |
1913 /* Display the text in the rectangle, one text line at a time. */ | 5173 /* Display the text in the rectangle, one text line at a time. */ |
1914 | 5174 while (row->enabled_p |
1915 for (y = top; y < bottom; y++) | 5175 && y < yb |
1916 { | 5176 && y < r->y + r->height) |
1917 GLYPH *line = &active_frame->glyphs[y][left]; | 5177 { |
1918 | 5178 expose_line (w, row, r); |
1919 if (! active_frame->enable[y] || left > active_frame->used[y]) | 5179 y += row->height; |
1920 continue; | 5180 ++row; |
1921 | 5181 } |
1922 while (*line & GLYPH_MASK_PADDING) | 5182 |
5183 /* Display the mode line if there is one. */ | |
5184 if (WINDOW_WANTS_MODELINE_P (w) | |
5185 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix), | |
5186 row->enabled_p) | |
5187 && row->y < r->y + r->height) | |
5188 expose_line (w, row, r); | |
5189 | |
5190 if (!w->pseudo_window_p) | |
5191 { | |
5192 /* Draw border between windows. */ | |
5193 x_draw_vertical_border (w); | |
5194 | |
5195 /* Turn the cursor on again. */ | |
5196 if (cursor_cleared_p) | |
5197 x_update_window_cursor (w, 1); | |
5198 } | |
5199 } | |
5200 | |
5201 | |
5202 /* Determine the intersection of two rectangles R1 and R2. Return | |
5203 the intersection in *RESULT. Value is non-zero if RESULT is not | |
5204 empty. */ | |
5205 | |
5206 static int | |
5207 x_intersect_rectangles (r1, r2, result) | |
5208 XRectangle *r1, *r2, *result; | |
5209 { | |
5210 XRectangle *left, *right; | |
5211 XRectangle *upper, *lower; | |
5212 int intersection_p = 0; | |
5213 | |
5214 /* Rearrange so that R1 is the left-most rectangle. */ | |
5215 if (r1->x < r2->x) | |
5216 left = r1, right = r2; | |
5217 else | |
5218 left = r2, right = r1; | |
5219 | |
5220 /* X0 of the intersection is right.x0, if this is inside R1, | |
5221 otherwise there is no intersection. */ | |
5222 if (right->x <= left->x + left->width) | |
5223 { | |
5224 result->x = right->x; | |
5225 | |
5226 /* The right end of the intersection is the minimum of the | |
5227 the right ends of left and right. */ | |
5228 result->width = (min (left->x + left->width, right->x + right->width) | |
5229 - result->x); | |
5230 | |
5231 /* Same game for Y. */ | |
5232 if (r1->y < r2->y) | |
5233 upper = r1, lower = r2; | |
5234 else | |
5235 upper = r2, lower = r1; | |
5236 | |
5237 /* The upper end of the intersection is lower.y0, if this is inside | |
5238 of upper. Otherwise, there is no intersection. */ | |
5239 if (lower->y <= upper->y + upper->height) | |
1923 { | 5240 { |
1924 /* We must display the whole glyph of a wide-column | 5241 result->y = lower->y; |
1925 character. */ | 5242 |
1926 left--; | 5243 /* The lower end of the intersection is the minimum of the lower |
1927 line--; | 5244 ends of upper and lower. */ |
1928 cols++; | 5245 result->height = (min (lower->y + lower->height, |
5246 upper->y + upper->height) | |
5247 - result->y); | |
5248 intersection_p = 1; | |
1929 } | 5249 } |
1930 dumpglyphs (f, | 5250 } |
1931 CHAR_TO_PIXEL_COL (f, left), | 5251 |
1932 CHAR_TO_PIXEL_ROW (f, y), | 5252 return intersection_p; |
1933 line, min (cols, active_frame->used[y] - left), | 5253 } |
1934 active_frame->highlight[y], 0, NULL); | 5254 |
1935 } | 5255 |
1936 | 5256 |
1937 /* Turn the cursor on if we turned it off. */ | 5257 |
1938 | |
1939 if (cursor_cleared) | |
1940 x_update_cursor (f, 1); | |
1941 } | |
1942 | 5258 |
1943 static void | 5259 static void |
1944 frame_highlight (f) | 5260 frame_highlight (f) |
1945 struct frame *f; | 5261 struct frame *f; |
1946 { | 5262 { |
1968 f->output_data.x->border_tile); | 5284 f->output_data.x->border_tile); |
1969 UNBLOCK_INPUT; | 5285 UNBLOCK_INPUT; |
1970 x_update_cursor (f, 1); | 5286 x_update_cursor (f, 1); |
1971 } | 5287 } |
1972 | 5288 |
1973 static void XTframe_rehighlight (); | |
1974 static void x_frame_rehighlight (); | |
1975 | |
1976 /* The focus has changed. Update the frames as necessary to reflect | 5289 /* The focus has changed. Update the frames as necessary to reflect |
1977 the new situation. Note that we can't change the selected frame | 5290 the new situation. Note that we can't change the selected frame |
1978 here, because the Lisp code we are interrupting might become confused. | 5291 here, because the Lisp code we are interrupting might become confused. |
1979 Each event gets marked with the frame in which it occurred, so the | 5292 Each event gets marked with the frame in which it occurred, so the |
1980 Lisp code can tell when the switch took place by examining the events. */ | 5293 Lisp code can tell when the switch took place by examining the events. */ |
1983 x_new_focus_frame (dpyinfo, frame) | 5296 x_new_focus_frame (dpyinfo, frame) |
1984 struct x_display_info *dpyinfo; | 5297 struct x_display_info *dpyinfo; |
1985 struct frame *frame; | 5298 struct frame *frame; |
1986 { | 5299 { |
1987 struct frame *old_focus = dpyinfo->x_focus_frame; | 5300 struct frame *old_focus = dpyinfo->x_focus_frame; |
1988 int events_enqueued = 0; | |
1989 | 5301 |
1990 if (frame != dpyinfo->x_focus_frame) | 5302 if (frame != dpyinfo->x_focus_frame) |
1991 { | 5303 { |
1992 /* Set this before calling other routines, so that they see | 5304 /* Set this before calling other routines, so that they see |
1993 the correct value of x_focus_frame. */ | 5305 the correct value of x_focus_frame. */ |
2022 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame); | 5334 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame); |
2023 } | 5335 } |
2024 | 5336 |
2025 /* The focus has changed, or we have redirected a frame's focus to | 5337 /* The focus has changed, or we have redirected a frame's focus to |
2026 another frame (this happens when a frame uses a surrogate | 5338 another frame (this happens when a frame uses a surrogate |
2027 minibuffer frame). Shift the highlight as appropriate. | 5339 mini-buffer frame). Shift the highlight as appropriate. |
2028 | 5340 |
2029 The FRAME argument doesn't necessarily have anything to do with which | 5341 The FRAME argument doesn't necessarily have anything to do with which |
2030 frame is being highlighted or unhighlighted; we only use it to find | 5342 frame is being highlighted or un-highlighted; we only use it to find |
2031 the appropriate X display info. */ | 5343 the appropriate X display info. */ |
5344 | |
2032 static void | 5345 static void |
2033 XTframe_rehighlight (frame) | 5346 XTframe_rehighlight (frame) |
2034 struct frame *frame; | 5347 struct frame *frame; |
2035 { | 5348 { |
2036 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame)); | 5349 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame)); |
2063 frame_unhighlight (old_highlight); | 5376 frame_unhighlight (old_highlight); |
2064 if (dpyinfo->x_highlight_frame) | 5377 if (dpyinfo->x_highlight_frame) |
2065 frame_highlight (dpyinfo->x_highlight_frame); | 5378 frame_highlight (dpyinfo->x_highlight_frame); |
2066 } | 5379 } |
2067 } | 5380 } |
5381 | |
5382 | |
2068 | 5383 |
2069 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */ | 5384 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */ |
2070 | 5385 |
2071 /* Initialize mode_switch_bit and modifier_meaning. */ | 5386 /* Initialize mode_switch_bit and modifier_meaning. */ |
2072 static void | 5387 static void |
2073 x_find_modifier_meanings (dpyinfo) | 5388 x_find_modifier_meanings (dpyinfo) |
2074 struct x_display_info *dpyinfo; | 5389 struct x_display_info *dpyinfo; |
2097 mods = XGetModifierMapping (dpyinfo->display); | 5412 mods = XGetModifierMapping (dpyinfo->display); |
2098 | 5413 |
2099 /* Scan the modifier table to see which modifier bits the Meta and | 5414 /* Scan the modifier table to see which modifier bits the Meta and |
2100 Alt keysyms are on. */ | 5415 Alt keysyms are on. */ |
2101 { | 5416 { |
2102 int row, col; /* The row and column in the modifier table. */ | 5417 int row, col; /* The row and column in the modifier table. */ |
2103 | 5418 |
2104 for (row = 3; row < 8; row++) | 5419 for (row = 3; row < 8; row++) |
2105 for (col = 0; col < mods->max_keypermod; col++) | 5420 for (col = 0; col < mods->max_keypermod; col++) |
2106 { | 5421 { |
2107 KeyCode code | 5422 KeyCode code |
2170 XFreeModifiermap (mods); | 5485 XFreeModifiermap (mods); |
2171 } | 5486 } |
2172 | 5487 |
2173 /* Convert between the modifier bits X uses and the modifier bits | 5488 /* Convert between the modifier bits X uses and the modifier bits |
2174 Emacs uses. */ | 5489 Emacs uses. */ |
5490 | |
2175 static unsigned int | 5491 static unsigned int |
2176 x_x_to_emacs_modifiers (dpyinfo, state) | 5492 x_x_to_emacs_modifiers (dpyinfo, state) |
2177 struct x_display_info *dpyinfo; | 5493 struct x_display_info *dpyinfo; |
2178 unsigned int state; | 5494 unsigned int state; |
2179 { | 5495 { |
2210 value = XKeysymToString (keysym); | 5526 value = XKeysymToString (keysym); |
2211 UNBLOCK_INPUT; | 5527 UNBLOCK_INPUT; |
2212 | 5528 |
2213 return value; | 5529 return value; |
2214 } | 5530 } |
5531 | |
5532 | |
2215 | 5533 |
2216 /* Mouse clicks and mouse movement. Rah. */ | 5534 /* Mouse clicks and mouse movement. Rah. */ |
2217 | 5535 |
2218 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return | 5536 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph |
2219 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle | 5537 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the |
2220 that the glyph at X, Y occupies, if BOUNDS != 0. | 5538 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do |
2221 If NOCLIP is nonzero, do not force the value into range. */ | 5539 not force the value into range. */ |
2222 | 5540 |
2223 void | 5541 void |
2224 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip) | 5542 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip) |
2225 FRAME_PTR f; | 5543 FRAME_PTR f; |
2226 register int pix_x, pix_y; | 5544 register int pix_x, pix_y; |
2227 register int *x, *y; | 5545 register int *x, *y; |
2228 XRectangle *bounds; | 5546 XRectangle *bounds; |
2229 int noclip; | 5547 int noclip; |
2230 { | 5548 { |
2231 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down | 5549 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down |
2232 even for negative values. */ | 5550 even for negative values. */ |
2233 if (pix_x < 0) | 5551 if (pix_x < 0) |
2234 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1; | 5552 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1; |
2235 if (pix_y < 0) | 5553 if (pix_y < 0) |
2236 pix_y -= (f)->output_data.x->line_height - 1; | 5554 pix_y -= (f)->output_data.x->line_height - 1; |
2261 | 5579 |
2262 *x = pix_x; | 5580 *x = pix_x; |
2263 *y = pix_y; | 5581 *y = pix_y; |
2264 } | 5582 } |
2265 | 5583 |
2266 void | 5584 |
2267 glyph_to_pixel_coords (f, x, y, pix_x, pix_y) | 5585 /* Given HPOS/VPOS in the current matrix of W, return corresponding |
2268 FRAME_PTR f; | 5586 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we |
2269 register int x, y; | 5587 can't tell the positions because W's display is not up to date, |
2270 register int *pix_x, *pix_y; | 5588 return 0. */ |
2271 { | 5589 |
2272 *pix_x = CHAR_TO_PIXEL_COL (f, x); | 5590 int |
2273 *pix_y = CHAR_TO_PIXEL_ROW (f, y); | 5591 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y) |
2274 } | 5592 struct window *w; |
5593 int hpos, vpos; | |
5594 int *frame_x, *frame_y; | |
5595 { | |
5596 int success_p; | |
5597 | |
5598 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w); | |
5599 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h); | |
5600 | |
5601 if (display_completed) | |
5602 { | |
5603 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos); | |
5604 struct glyph *glyph = row->glyphs[TEXT_AREA]; | |
5605 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]); | |
5606 | |
5607 *frame_y = row->y; | |
5608 *frame_x = row->x; | |
5609 while (glyph < end) | |
5610 { | |
5611 *frame_x += glyph->pixel_width; | |
5612 ++glyph; | |
5613 } | |
5614 | |
5615 success_p = 1; | |
5616 } | |
5617 else | |
5618 { | |
5619 *frame_y = *frame_x = 0; | |
5620 success_p = 0; | |
5621 } | |
5622 | |
5623 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y); | |
5624 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x); | |
5625 return success_p; | |
5626 } | |
5627 | |
2275 | 5628 |
2276 /* Prepare a mouse-event in *RESULT for placement in the input queue. | 5629 /* Prepare a mouse-event in *RESULT for placement in the input queue. |
2277 | 5630 |
2278 If the event is a button press, then note that we have grabbed | 5631 If the event is a button press, then note that we have grabbed |
2279 the mouse. */ | 5632 the mouse. */ |
2293 event->state) | 5646 event->state) |
2294 | (event->type == ButtonRelease | 5647 | (event->type == ButtonRelease |
2295 ? up_modifier | 5648 ? up_modifier |
2296 : down_modifier)); | 5649 : down_modifier)); |
2297 | 5650 |
2298 { | 5651 XSETINT (result->x, event->x); |
2299 int row, column; | 5652 XSETINT (result->y, event->y); |
2300 | 5653 XSETFRAME (result->frame_or_window, f); |
2301 #if 0 | 5654 return Qnil; |
2302 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL, 0); | 5655 } |
2303 XSETFASTINT (result->x, column); | 5656 |
2304 XSETFASTINT (result->y, row); | 5657 #if 0 /* This function isn't called. --gerd */ |
2305 #endif | |
2306 XSETINT (result->x, event->x); | |
2307 XSETINT (result->y, event->y); | |
2308 XSETFRAME (result->frame_or_window, f); | |
2309 } | |
2310 } | |
2311 | 5658 |
2312 /* Prepare a menu-event in *RESULT for placement in the input queue. */ | 5659 /* Prepare a menu-event in *RESULT for placement in the input queue. */ |
2313 | 5660 |
2314 static Lisp_Object | 5661 static Lisp_Object |
2315 construct_menu_click (result, event, f) | 5662 construct_menu_click (result, event, f) |
2330 | 5677 |
2331 XSETINT (result->x, event->x); | 5678 XSETINT (result->x, event->x); |
2332 XSETINT (result->y, -1); | 5679 XSETINT (result->y, -1); |
2333 XSETFRAME (result->frame_or_window, f); | 5680 XSETFRAME (result->frame_or_window, f); |
2334 } | 5681 } |
5682 | |
5683 #endif /* 0 */ | |
5684 | |
2335 | 5685 |
2336 /* Function to report a mouse movement to the mainstream Emacs code. | 5686 /* Function to report a mouse movement to the mainstream Emacs code. |
2337 The input handler calls this. | 5687 The input handler calls this. |
2338 | 5688 |
2339 We have received a mouse movement event, which is given in *event. | 5689 We have received a mouse movement event, which is given in *event. |
2340 If the mouse is over a different glyph than it was last time, tell | 5690 If the mouse is over a different glyph than it was last time, tell |
2341 the mainstream emacs code by setting mouse_moved. If not, ask for | 5691 the mainstream emacs code by setting mouse_moved. If not, ask for |
2342 another motion event, so we can check again the next time it moves. */ | 5692 another motion event, so we can check again the next time it moves. */ |
2343 | 5693 |
5694 static XMotionEvent last_mouse_motion_event; | |
5695 static Lisp_Object last_mouse_motion_frame; | |
5696 | |
2344 static void | 5697 static void |
2345 note_mouse_movement (frame, event) | 5698 note_mouse_movement (frame, event) |
2346 FRAME_PTR frame; | 5699 FRAME_PTR frame; |
2347 XMotionEvent *event; | 5700 XMotionEvent *event; |
2348 { | 5701 { |
2349 last_mouse_movement_time = event->time; | 5702 last_mouse_movement_time = event->time; |
5703 last_mouse_motion_event = *event; | |
5704 XSETFRAME (last_mouse_motion_frame, frame); | |
2350 | 5705 |
2351 if (event->window != FRAME_X_WINDOW (frame)) | 5706 if (event->window != FRAME_X_WINDOW (frame)) |
2352 { | 5707 { |
2353 frame->mouse_moved = 1; | 5708 frame->mouse_moved = 1; |
2354 last_mouse_scroll_bar = Qnil; | 5709 last_mouse_scroll_bar = Qnil; |
2355 | |
2356 note_mouse_highlight (frame, -1, -1); | 5710 note_mouse_highlight (frame, -1, -1); |
2357 } | 5711 } |
2358 | 5712 |
2359 /* Has the mouse moved off the glyph it was on at the last sighting? */ | 5713 /* Has the mouse moved off the glyph it was on at the last sighting? */ |
2360 else if (event->x < last_mouse_glyph.x | 5714 else if (event->x < last_mouse_glyph.x |
2362 || event->y < last_mouse_glyph.y | 5716 || event->y < last_mouse_glyph.y |
2363 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) | 5717 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) |
2364 { | 5718 { |
2365 frame->mouse_moved = 1; | 5719 frame->mouse_moved = 1; |
2366 last_mouse_scroll_bar = Qnil; | 5720 last_mouse_scroll_bar = Qnil; |
2367 | |
2368 note_mouse_highlight (frame, event->x, event->y); | 5721 note_mouse_highlight (frame, event->x, event->y); |
2369 } | 5722 } |
2370 } | 5723 } |
2371 | 5724 |
2372 /* This is used for debugging, to turn off note_mouse_highlight. */ | 5725 /* This is used for debugging, to turn off note_mouse_highlight. */ |
2373 static int disable_mouse_highlight; | 5726 |
2374 | 5727 int disable_mouse_highlight; |
2375 /* Take proper action when the mouse has moved to position X, Y on frame F | 5728 |
2376 as regards highlighting characters that have mouse-face properties. | 5729 |
2377 Also dehighlighting chars where the mouse was before. | 5730 |
5731 /************************************************************************ | |
5732 Mouse Face | |
5733 ************************************************************************/ | |
5734 | |
5735 /* Find the glyph under window-relative coordinates X/Y in window W. | |
5736 Consider only glyphs from buffer text, i.e. no glyphs from overlay | |
5737 strings. Return in *HPOS and *VPOS the row and column number of | |
5738 the glyph found. Return in *AREA the glyph area containing X. | |
5739 Value is a pointer to the glyph found or null if X/Y is not on | |
5740 text, or we can't tell because W's current matrix is not up to | |
5741 date. */ | |
5742 | |
5743 static struct glyph * | |
5744 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area) | |
5745 struct window *w; | |
5746 int x, y; | |
5747 int *hpos, *vpos, *area; | |
5748 { | |
5749 struct glyph *glyph, *end; | |
5750 struct glyph_row *row; | |
5751 int x0, i, left_area_width; | |
5752 | |
5753 /* Find row containing Y. Give up if some row is not enabled. */ | |
5754 for (i = 0; i < w->current_matrix->nrows; ++i) | |
5755 { | |
5756 row = MATRIX_ROW (w->current_matrix, i); | |
5757 if (!row->enabled_p) | |
5758 return NULL; | |
5759 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row)) | |
5760 break; | |
5761 } | |
5762 | |
5763 *vpos = i; | |
5764 *hpos = 0; | |
5765 | |
5766 /* Give up if Y is not in the window. */ | |
5767 if (i == w->current_matrix->nrows) | |
5768 return NULL; | |
5769 | |
5770 /* Get the glyph area containing X. */ | |
5771 if (w->pseudo_window_p) | |
5772 { | |
5773 *area = TEXT_AREA; | |
5774 x0 = 0; | |
5775 } | |
5776 else | |
5777 { | |
5778 left_area_width = window_box_width (w, LEFT_MARGIN_AREA); | |
5779 if (x < left_area_width) | |
5780 { | |
5781 *area = LEFT_MARGIN_AREA; | |
5782 x0 = 0; | |
5783 } | |
5784 else if (x < left_area_width + window_box_width (w, TEXT_AREA)) | |
5785 { | |
5786 *area = TEXT_AREA; | |
5787 x0 = row->x + left_area_width; | |
5788 } | |
5789 else | |
5790 { | |
5791 *area = RIGHT_MARGIN_AREA; | |
5792 x0 = left_area_width + window_box_width (w, TEXT_AREA); | |
5793 } | |
5794 } | |
5795 | |
5796 /* Find glyph containing X. */ | |
5797 glyph = row->glyphs[*area]; | |
5798 end = glyph + row->used[*area]; | |
5799 while (glyph < end) | |
5800 { | |
5801 if (x < x0 + glyph->pixel_width) | |
5802 { | |
5803 if (w->pseudo_window_p) | |
5804 break; | |
5805 else if (BUFFERP (glyph->object)) | |
5806 break; | |
5807 } | |
5808 | |
5809 x0 += glyph->pixel_width; | |
5810 ++glyph; | |
5811 } | |
5812 | |
5813 if (glyph == end) | |
5814 return NULL; | |
5815 | |
5816 *hpos = glyph - row->glyphs[*area]; | |
5817 return glyph; | |
5818 } | |
5819 | |
5820 | |
5821 /* Convert frame-relative x/y to coordinates relative to window W. | |
5822 Takes pseudo-windows into account. */ | |
5823 | |
5824 static void | |
5825 frame_to_window_pixel_xy (w, x, y) | |
5826 struct window *w; | |
5827 int *x, *y; | |
5828 { | |
5829 if (w->pseudo_window_p) | |
5830 { | |
5831 /* A pseudo-window is always full-width, and starts at the | |
5832 left edge of the frame, plus a frame border. */ | |
5833 struct frame *f = XFRAME (w->frame); | |
5834 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f); | |
5835 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y); | |
5836 } | |
5837 else | |
5838 { | |
5839 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x); | |
5840 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y); | |
5841 } | |
5842 } | |
5843 | |
5844 | |
5845 /* Take proper action when mouse has moved to the mode or top line of | |
5846 window W, x-position X. MODE_LINE_P non-zero means mouse is on the | |
5847 mode line. X is relative to the start of the text display area of | |
5848 W, so the width of bitmap areas and scroll bars must be subtracted | |
5849 to get a position relative to the start of the mode line. */ | |
5850 | |
5851 static void | |
5852 note_mode_line_highlight (w, x, mode_line_p) | |
5853 struct window *w; | |
5854 int x, mode_line_p; | |
5855 { | |
5856 struct frame *f = XFRAME (w->frame); | |
5857 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
5858 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor; | |
5859 struct glyph_row *row; | |
5860 | |
5861 if (mode_line_p) | |
5862 row = MATRIX_MODE_LINE_ROW (w->current_matrix); | |
5863 else | |
5864 row = MATRIX_TOP_LINE_ROW (w->current_matrix); | |
5865 | |
5866 if (row->enabled_p) | |
5867 { | |
5868 struct glyph *glyph, *end; | |
5869 Lisp_Object help, map; | |
5870 int x0; | |
5871 | |
5872 /* Find the glyph under X. */ | |
5873 glyph = row->glyphs[TEXT_AREA]; | |
5874 end = glyph + row->used[TEXT_AREA]; | |
5875 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f) | |
5876 + FRAME_X_FLAGS_AREA_WIDTH (f)); | |
5877 while (glyph < end | |
5878 && x >= x0 + glyph->pixel_width) | |
5879 { | |
5880 x0 += glyph->pixel_width; | |
5881 ++glyph; | |
5882 } | |
5883 | |
5884 if (glyph < end | |
5885 && STRINGP (glyph->object) | |
5886 && XSTRING (glyph->object)->intervals | |
5887 && glyph->charpos >= 0 | |
5888 && glyph->charpos < XSTRING (glyph->object)->size) | |
5889 { | |
5890 /* If we're on a string with `help-echo' text property, | |
5891 arrange for the help to be displayed. This is done by | |
5892 setting the global variable help_echo to the help string. */ | |
5893 help = Fget_text_property (make_number (glyph->charpos), | |
5894 Qhelp_echo, glyph->object); | |
5895 if (STRINGP (help)) | |
5896 help_echo = help; | |
5897 | |
5898 /* Change the mouse pointer according to what is under X/Y. */ | |
5899 map = Fget_text_property (make_number (glyph->charpos), | |
5900 Qlocal_map, glyph->object); | |
5901 if (!NILP (Fkeymapp (map))) | |
5902 cursor = f->output_data.x->nontext_cursor; | |
5903 } | |
5904 } | |
5905 | |
5906 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor); | |
5907 } | |
5908 | |
5909 | |
5910 /* Take proper action when the mouse has moved to position X, Y on | |
5911 frame F as regards highlighting characters that have mouse-face | |
5912 properties. Also de-highlighting chars where the mouse was before. | |
2378 X and Y can be negative or out of range. */ | 5913 X and Y can be negative or out of range. */ |
2379 | 5914 |
2380 static void | 5915 static void |
2381 note_mouse_highlight (f, x, y) | 5916 note_mouse_highlight (f, x, y) |
2382 FRAME_PTR f; | 5917 struct frame *f; |
2383 int x, y; | 5918 int x, y; |
2384 { | 5919 { |
2385 int row, column, portion; | 5920 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
2386 XRectangle new_glyph; | 5921 int portion; |
2387 Lisp_Object window; | 5922 Lisp_Object window; |
2388 struct window *w; | 5923 struct window *w; |
2389 | 5924 |
5925 /* When a menu is active, don't highlight because this looks odd. */ | |
5926 #ifdef USE_X_TOOLKIT | |
5927 if (popup_activated ()) | |
5928 return; | |
5929 #endif | |
5930 | |
2390 if (disable_mouse_highlight) | 5931 if (disable_mouse_highlight) |
2391 return; | 5932 return; |
2392 | 5933 |
2393 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x = x; | 5934 dpyinfo->mouse_face_mouse_x = x; |
2394 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y = y; | 5935 dpyinfo->mouse_face_mouse_y = y; |
2395 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame = f; | 5936 dpyinfo->mouse_face_mouse_frame = f; |
2396 | 5937 |
2397 if (FRAME_X_DISPLAY_INFO (f)->mouse_face_defer) | 5938 if (dpyinfo->mouse_face_defer) |
2398 return; | 5939 return; |
2399 | 5940 |
2400 if (gc_in_progress) | 5941 if (gc_in_progress) |
2401 { | 5942 { |
2402 FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1; | 5943 dpyinfo->mouse_face_deferred_gc = 1; |
2403 return; | 5944 return; |
2404 } | 5945 } |
2405 | 5946 |
2406 /* Find out which glyph the mouse is on. */ | |
2407 pixel_to_glyph_coords (f, x, y, &column, &row, | |
2408 &new_glyph, FRAME_X_DISPLAY_INFO (f)->grabbed); | |
2409 | |
2410 /* Which window is that in? */ | 5947 /* Which window is that in? */ |
2411 window = window_from_coordinates (f, column, row, &portion); | 5948 window = window_from_coordinates (f, x, y, &portion, 1); |
5949 | |
5950 /* If we were displaying active text in another window, clear that. */ | |
5951 if (! EQ (window, dpyinfo->mouse_face_window)) | |
5952 clear_mouse_face (dpyinfo); | |
5953 | |
5954 /* Not on a window -> return. */ | |
5955 if (!WINDOWP (window)) | |
5956 return; | |
5957 | |
5958 /* Convert to window-relative pixel coordinates. */ | |
2412 w = XWINDOW (window); | 5959 w = XWINDOW (window); |
2413 | 5960 frame_to_window_pixel_xy (w, &x, &y); |
2414 /* If we were displaying active text in another window, clear that. */ | 5961 |
2415 if (! EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window)) | 5962 /* Handle toolbar window differently since it doesn't display a |
2416 clear_mouse_face (FRAME_X_DISPLAY_INFO (f)); | 5963 buffer. */ |
5964 if (EQ (window, f->toolbar_window)) | |
5965 { | |
5966 note_toolbar_highlight (f, x, y); | |
5967 return; | |
5968 } | |
5969 | |
5970 if (portion == 1 || portion == 3) | |
5971 { | |
5972 /* Mouse is on the mode or top line. */ | |
5973 note_mode_line_highlight (w, x, portion == 1); | |
5974 return; | |
5975 } | |
5976 else | |
5977 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
5978 f->output_data.x->text_cursor); | |
2417 | 5979 |
2418 /* Are we in a window whose display is up to date? | 5980 /* Are we in a window whose display is up to date? |
2419 And verify the buffer's text has not changed. */ | 5981 And verify the buffer's text has not changed. */ |
2420 if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0 | 5982 if (/* Within text portion of the window. */ |
2421 && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f) | 5983 portion == 0 |
2422 && EQ (w->window_end_valid, w->buffer) | 5984 && EQ (w->window_end_valid, w->buffer) |
2423 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer)) | 5985 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer)) |
2424 && (XFASTINT (w->last_overlay_modified) | 5986 && (XFASTINT (w->last_overlay_modified) |
2425 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))) | 5987 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))) |
2426 { | 5988 { |
2427 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row]; | 5989 int hpos, vpos, pos, i, area; |
2428 int i, pos; | 5990 struct glyph *glyph; |
2429 | 5991 |
2430 /* Find which buffer position the mouse corresponds to. */ | 5992 /* Find the glyph under X/Y. */ |
2431 for (i = column; i >= 0; i--) | 5993 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area); |
2432 if (ptr[i] > 0) | 5994 |
2433 break; | 5995 /* Clear mouse face if X/Y not over text. */ |
2434 pos = ptr[i]; | 5996 if (glyph == NULL |
2435 /* Is it outside the displayed active region (if any)? */ | 5997 || area != TEXT_AREA |
2436 if (pos <= 0) | 5998 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p) |
2437 clear_mouse_face (FRAME_X_DISPLAY_INFO (f)); | |
2438 else if (! (EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window) | |
2439 && row >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row | |
2440 && row <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row | |
2441 && (row > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row | |
2442 || column >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col) | |
2443 && (row < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row | |
2444 || column < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col | |
2445 || FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end))) | |
2446 { | 5999 { |
2447 Lisp_Object mouse_face, overlay, position; | 6000 clear_mouse_face (dpyinfo); |
2448 Lisp_Object *overlay_vec; | 6001 return; |
2449 int len, noverlays, ignor1; | |
2450 struct buffer *obuf; | |
2451 int obegv, ozv; | |
2452 | |
2453 /* If we get an out-of-range value, return now; avoid an error. */ | |
2454 if (pos > BUF_Z (XBUFFER (w->buffer))) | |
2455 return; | |
2456 | |
2457 /* Make the window's buffer temporarily current for | |
2458 overlays_at and compute_char_face. */ | |
2459 obuf = current_buffer; | |
2460 current_buffer = XBUFFER (w->buffer); | |
2461 obegv = BEGV; | |
2462 ozv = ZV; | |
2463 BEGV = BEG; | |
2464 ZV = Z; | |
2465 | |
2466 /* Yes. Clear the display of the old active region, if any. */ | |
2467 clear_mouse_face (FRAME_X_DISPLAY_INFO (f)); | |
2468 | |
2469 /* Is this char mouse-active? */ | |
2470 XSETINT (position, pos); | |
2471 | |
2472 len = 10; | |
2473 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object)); | |
2474 | |
2475 /* Put all the overlays we want in a vector in overlay_vec. | |
2476 Store the length in len. */ | |
2477 noverlays = overlays_at (pos, 1, &overlay_vec, &len, | |
2478 NULL, NULL); | |
2479 noverlays = sort_overlays (overlay_vec, noverlays, w); | |
2480 | |
2481 /* Find the highest priority overlay that has a mouse-face prop. */ | |
2482 overlay = Qnil; | |
2483 for (i = 0; i < noverlays; i++) | |
2484 { | |
2485 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); | |
2486 if (!NILP (mouse_face)) | |
2487 { | |
2488 overlay = overlay_vec[i]; | |
2489 break; | |
2490 } | |
2491 } | |
2492 free (overlay_vec); | |
2493 /* If no overlay applies, get a text property. */ | |
2494 if (NILP (overlay)) | |
2495 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer); | |
2496 | |
2497 /* Handle the overlay case. */ | |
2498 if (! NILP (overlay)) | |
2499 { | |
2500 /* Find the range of text around this char that | |
2501 should be active. */ | |
2502 Lisp_Object before, after; | |
2503 int ignore; | |
2504 | |
2505 before = Foverlay_start (overlay); | |
2506 after = Foverlay_end (overlay); | |
2507 /* Record this as the current active region. */ | |
2508 fast_find_position (window, XFASTINT (before), | |
2509 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col, | |
2510 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row); | |
2511 FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end | |
2512 = !fast_find_position (window, XFASTINT (after), | |
2513 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col, | |
2514 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row); | |
2515 FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window; | |
2516 FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id | |
2517 = compute_char_face (f, w, pos, 0, 0, | |
2518 &ignore, pos + 1, 1); | |
2519 | |
2520 /* Display it as active. */ | |
2521 show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1); | |
2522 } | |
2523 /* Handle the text property case. */ | |
2524 else if (! NILP (mouse_face)) | |
2525 { | |
2526 /* Find the range of text around this char that | |
2527 should be active. */ | |
2528 Lisp_Object before, after, beginning, end; | |
2529 int ignore; | |
2530 | |
2531 beginning = Fmarker_position (w->start); | |
2532 XSETINT (end, (BUF_Z (XBUFFER (w->buffer)) | |
2533 - XFASTINT (w->window_end_pos))); | |
2534 before | |
2535 = Fprevious_single_property_change (make_number (pos + 1), | |
2536 Qmouse_face, | |
2537 w->buffer, beginning); | |
2538 after | |
2539 = Fnext_single_property_change (position, Qmouse_face, | |
2540 w->buffer, end); | |
2541 /* Record this as the current active region. */ | |
2542 fast_find_position (window, XFASTINT (before), | |
2543 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col, | |
2544 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row); | |
2545 FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end | |
2546 = !fast_find_position (window, XFASTINT (after), | |
2547 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col, | |
2548 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row); | |
2549 FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window; | |
2550 FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id | |
2551 = compute_char_face (f, w, pos, 0, 0, | |
2552 &ignore, pos + 1, 1); | |
2553 | |
2554 /* Display it as active. */ | |
2555 show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1); | |
2556 } | |
2557 BEGV = obegv; | |
2558 ZV = ozv; | |
2559 current_buffer = obuf; | |
2560 } | 6002 } |
2561 } | 6003 |
2562 } | 6004 pos = glyph->charpos; |
6005 xassert (w->pseudo_window_p || BUFFERP (glyph->object)); | |
6006 | |
6007 /* Check for mouse-face and help-echo. */ | |
6008 { | |
6009 Lisp_Object mouse_face, overlay, position; | |
6010 Lisp_Object *overlay_vec; | |
6011 int len, noverlays; | |
6012 struct buffer *obuf; | |
6013 int obegv, ozv; | |
6014 | |
6015 /* If we get an out-of-range value, return now; avoid an error. */ | |
6016 if (pos > BUF_Z (XBUFFER (w->buffer))) | |
6017 return; | |
6018 | |
6019 /* Make the window's buffer temporarily current for | |
6020 overlays_at and compute_char_face. */ | |
6021 obuf = current_buffer; | |
6022 current_buffer = XBUFFER (w->buffer); | |
6023 obegv = BEGV; | |
6024 ozv = ZV; | |
6025 BEGV = BEG; | |
6026 ZV = Z; | |
6027 | |
6028 /* Is this char mouse-active or does it have help-echo? */ | |
6029 XSETINT (position, pos); | |
6030 | |
6031 /* Put all the overlays we want in a vector in overlay_vec. | |
6032 Store the length in len. If there are more than 10, make | |
6033 enough space for all, and try again. */ | |
6034 len = 10; | |
6035 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); | |
6036 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL); | |
6037 if (noverlays > len) | |
6038 { | |
6039 len = noverlays; | |
6040 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); | |
6041 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL); | |
6042 } | |
6043 | |
6044 noverlays = sort_overlays (overlay_vec, noverlays, w); | |
6045 | |
6046 /* Check mouse-face highlighting. */ | |
6047 if (! (EQ (window, dpyinfo->mouse_face_window) | |
6048 && vpos >= dpyinfo->mouse_face_beg_row | |
6049 && vpos <= dpyinfo->mouse_face_end_row | |
6050 && (vpos > dpyinfo->mouse_face_beg_row | |
6051 || hpos >= dpyinfo->mouse_face_beg_col) | |
6052 && (vpos < dpyinfo->mouse_face_end_row | |
6053 || hpos < dpyinfo->mouse_face_end_col | |
6054 || dpyinfo->mouse_face_past_end))) | |
6055 { | |
6056 /* Clear the display of the old active region, if any. */ | |
6057 clear_mouse_face (dpyinfo); | |
6058 | |
6059 /* Find the highest priority overlay that has a mouse-face prop. */ | |
6060 overlay = Qnil; | |
6061 for (i = 0; i < noverlays; i++) | |
6062 { | |
6063 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); | |
6064 if (!NILP (mouse_face)) | |
6065 { | |
6066 overlay = overlay_vec[i]; | |
6067 break; | |
6068 } | |
6069 } | |
6070 | |
6071 /* If no overlay applies, get a text property. */ | |
6072 if (NILP (overlay)) | |
6073 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer); | |
6074 | |
6075 /* Handle the overlay case. */ | |
6076 if (! NILP (overlay)) | |
6077 { | |
6078 /* Find the range of text around this char that | |
6079 should be active. */ | |
6080 Lisp_Object before, after; | |
6081 int ignore; | |
6082 | |
6083 before = Foverlay_start (overlay); | |
6084 after = Foverlay_end (overlay); | |
6085 /* Record this as the current active region. */ | |
6086 fast_find_position (w, XFASTINT (before), | |
6087 &dpyinfo->mouse_face_beg_col, | |
6088 &dpyinfo->mouse_face_beg_row, | |
6089 &dpyinfo->mouse_face_beg_x, | |
6090 &dpyinfo->mouse_face_beg_y); | |
6091 dpyinfo->mouse_face_past_end | |
6092 = !fast_find_position (w, XFASTINT (after), | |
6093 &dpyinfo->mouse_face_end_col, | |
6094 &dpyinfo->mouse_face_end_row, | |
6095 &dpyinfo->mouse_face_end_x, | |
6096 &dpyinfo->mouse_face_end_y); | |
6097 dpyinfo->mouse_face_window = window; | |
6098 dpyinfo->mouse_face_face_id | |
6099 = face_at_buffer_position (w, pos, 0, 0, | |
6100 &ignore, pos + 1, 1); | |
6101 | |
6102 /* Display it as active. */ | |
6103 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | |
6104 } | |
6105 /* Handle the text property case. */ | |
6106 else if (! NILP (mouse_face)) | |
6107 { | |
6108 /* Find the range of text around this char that | |
6109 should be active. */ | |
6110 Lisp_Object before, after, beginning, end; | |
6111 int ignore; | |
6112 | |
6113 beginning = Fmarker_position (w->start); | |
6114 XSETINT (end, (BUF_Z (XBUFFER (w->buffer)) | |
6115 - XFASTINT (w->window_end_pos))); | |
6116 before | |
6117 = Fprevious_single_property_change (make_number (pos + 1), | |
6118 Qmouse_face, | |
6119 w->buffer, beginning); | |
6120 after | |
6121 = Fnext_single_property_change (position, Qmouse_face, | |
6122 w->buffer, end); | |
6123 /* Record this as the current active region. */ | |
6124 fast_find_position (w, XFASTINT (before), | |
6125 &dpyinfo->mouse_face_beg_col, | |
6126 &dpyinfo->mouse_face_beg_row, | |
6127 &dpyinfo->mouse_face_beg_x, | |
6128 &dpyinfo->mouse_face_beg_y); | |
6129 dpyinfo->mouse_face_past_end | |
6130 = !fast_find_position (w, XFASTINT (after), | |
6131 &dpyinfo->mouse_face_end_col, | |
6132 &dpyinfo->mouse_face_end_row, | |
6133 &dpyinfo->mouse_face_end_x, | |
6134 &dpyinfo->mouse_face_end_y); | |
6135 dpyinfo->mouse_face_window = window; | |
6136 dpyinfo->mouse_face_face_id | |
6137 = face_at_buffer_position (w, pos, 0, 0, | |
6138 &ignore, pos + 1, 1); | |
6139 | |
6140 /* Display it as active. */ | |
6141 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | |
6142 } | |
6143 } | |
6144 | |
6145 /* Look for a `help-echo' property. */ | |
6146 { | |
6147 Lisp_Object help; | |
6148 | |
6149 /* Check overlays first. */ | |
6150 help = Qnil; | |
6151 for (i = 0; i < noverlays && !STRINGP (help); ++i) | |
6152 help = Foverlay_get (overlay_vec[i], Qhelp_echo); | |
6153 | |
6154 /* Try text properties. */ | |
6155 if (!STRINGP (help) | |
6156 && ((STRINGP (glyph->object) | |
6157 && glyph->charpos >= 0 | |
6158 && glyph->charpos < XSTRING (glyph->object)->size) | |
6159 || (BUFFERP (glyph->object) | |
6160 && glyph->charpos >= BEGV | |
6161 && glyph->charpos < ZV))) | |
6162 help = Fget_text_property (make_number (glyph->charpos), | |
6163 Qhelp_echo, glyph->object); | |
6164 | |
6165 if (STRINGP (help)) | |
6166 help_echo = help; | |
6167 } | |
6168 | |
6169 BEGV = obegv; | |
6170 ZV = ozv; | |
6171 current_buffer = obuf; | |
6172 } | |
6173 } | |
6174 } | |
6175 | |
6176 static void | |
6177 redo_mouse_highlight () | |
6178 { | |
6179 if (!NILP (last_mouse_motion_frame) | |
6180 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame))) | |
6181 note_mouse_highlight (XFRAME (last_mouse_motion_frame), | |
6182 last_mouse_motion_event.x, | |
6183 last_mouse_motion_event.y); | |
6184 } | |
6185 | |
6186 | |
2563 | 6187 |
2564 /* Find the row and column of position POS in window WINDOW. | 6188 /*********************************************************************** |
2565 Store them in *COLUMNP and *ROWP. | 6189 Toolbars |
2566 This assumes display in WINDOW is up to date. | 6190 ***********************************************************************/ |
2567 If POS is above start of WINDOW, return coords | 6191 |
2568 of start of first screen line. | 6192 static int x_toolbar_item P_ ((struct frame *, int, int, |
2569 If POS is after end of WINDOW, return coords of end of last screen line. | 6193 struct glyph **, int *, int *, int *)); |
2570 | 6194 |
2571 Value is 1 if POS is in range, 0 if it was off screen. */ | 6195 /* Toolbar item index of the item on which a mouse button was pressed |
6196 or -1. */ | |
6197 | |
6198 static int last_toolbar_item; | |
6199 | |
6200 | |
6201 /* Get information about the toolbar item at position X/Y on frame F. | |
6202 Return in *GLYPH a pointer to the glyph of the toolbar item in | |
6203 the current matrix of the toolbar window of F, or NULL if not | |
6204 on a toolbar item. Return in *PROP_IDX the index of the toolbar | |
6205 item in F->current_toolbar_items. Value is | |
6206 | |
6207 -1 if X/Y is not on a toolbar item | |
6208 0 if X/Y is on the same item that was highlighted before. | |
6209 1 otherwise. */ | |
2572 | 6210 |
2573 static int | 6211 static int |
2574 fast_find_position (window, pos, columnp, rowp) | 6212 x_toolbar_item (f, x, y, glyph, hpos, vpos, prop_idx) |
2575 Lisp_Object window; | 6213 struct frame *f; |
6214 int x, y; | |
6215 struct glyph **glyph; | |
6216 int *hpos, *vpos, *prop_idx; | |
6217 { | |
6218 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
6219 struct window *w = XWINDOW (f->toolbar_window); | |
6220 int area; | |
6221 | |
6222 /* Find the glyph under X/Y. */ | |
6223 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area); | |
6224 if (*glyph == NULL) | |
6225 return -1; | |
6226 | |
6227 /* Get the start of this toolbar item's properties in | |
6228 f->current_toolbar_items. */ | |
6229 if (!toolbar_item_info (f, *glyph, prop_idx)) | |
6230 return -1; | |
6231 | |
6232 /* Is mouse on the highlighted item? */ | |
6233 if (EQ (f->toolbar_window, dpyinfo->mouse_face_window) | |
6234 && *vpos >= dpyinfo->mouse_face_beg_row | |
6235 && *vpos <= dpyinfo->mouse_face_end_row | |
6236 && (*vpos > dpyinfo->mouse_face_beg_row | |
6237 || *hpos >= dpyinfo->mouse_face_beg_col) | |
6238 && (*vpos < dpyinfo->mouse_face_end_row | |
6239 || *hpos < dpyinfo->mouse_face_end_col | |
6240 || dpyinfo->mouse_face_past_end)) | |
6241 return 0; | |
6242 | |
6243 return 1; | |
6244 } | |
6245 | |
6246 | |
6247 /* Handle mouse button event on the toolbar of frame F, at | |
6248 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress | |
6249 or ButtonRelase. */ | |
6250 | |
6251 static void | |
6252 x_handle_toolbar_click (f, button_event) | |
6253 struct frame *f; | |
6254 XButtonEvent *button_event; | |
6255 { | |
6256 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
6257 struct window *w = XWINDOW (f->toolbar_window); | |
6258 int hpos, vpos, prop_idx; | |
6259 struct glyph *glyph; | |
6260 Lisp_Object enabled_p; | |
6261 int x = button_event->x; | |
6262 int y = button_event->y; | |
6263 | |
6264 /* If not on the highlighted toolbar item, return. */ | |
6265 frame_to_window_pixel_xy (w, &x, &y); | |
6266 if (x_toolbar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0) | |
6267 return; | |
6268 | |
6269 /* If item is disabled, do nothing. */ | |
6270 enabled_p = (XVECTOR (f->current_toolbar_items) | |
6271 ->contents[prop_idx + TOOLBAR_ITEM_ENABLED_P]); | |
6272 if (NILP (enabled_p)) | |
6273 return; | |
6274 | |
6275 if (button_event->type == ButtonPress) | |
6276 { | |
6277 /* Show item in pressed state. */ | |
6278 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN); | |
6279 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN; | |
6280 last_toolbar_item = prop_idx; | |
6281 } | |
6282 else | |
6283 { | |
6284 Lisp_Object key, frame; | |
6285 struct input_event event; | |
6286 | |
6287 /* Show item in released state. */ | |
6288 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED); | |
6289 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED; | |
6290 | |
6291 key = (XVECTOR (f->current_toolbar_items) | |
6292 ->contents[prop_idx + TOOLBAR_ITEM_KEY]); | |
6293 | |
6294 XSETFRAME (frame, f); | |
6295 event.kind = TOOLBAR_EVENT; | |
6296 event.frame_or_window = Fcons (frame, Fcons (Qtoolbar, Qnil)); | |
6297 kbd_buffer_store_event (&event); | |
6298 | |
6299 event.kind = TOOLBAR_EVENT; | |
6300 event.frame_or_window = Fcons (frame, key); | |
6301 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), | |
6302 button_event->state); | |
6303 kbd_buffer_store_event (&event); | |
6304 last_toolbar_item = -1; | |
6305 } | |
6306 } | |
6307 | |
6308 | |
6309 /* Possibly highlight a toolbar item on frame F when mouse moves to | |
6310 toolbar window-relative coordinates X/Y. Called from | |
6311 note_mouse_highlight. */ | |
6312 | |
6313 static void | |
6314 note_toolbar_highlight (f, x, y) | |
6315 struct frame *f; | |
6316 int x, y; | |
6317 { | |
6318 Lisp_Object window = f->toolbar_window; | |
6319 struct window *w = XWINDOW (window); | |
6320 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
6321 int hpos, vpos; | |
6322 struct glyph *glyph; | |
6323 struct glyph_row *row; | |
6324 int i, j, area; | |
6325 Lisp_Object enabled_p; | |
6326 int prop_idx; | |
6327 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED; | |
6328 int on_highlight_p, mouse_down_p, rc; | |
6329 | |
6330 /* Function note_mouse_highlight is called with negative x(y | |
6331 values when mouse moves outside of the frame. */ | |
6332 if (x <= 0 || y <= 0) | |
6333 { | |
6334 clear_mouse_face (dpyinfo); | |
6335 return; | |
6336 } | |
6337 | |
6338 rc = x_toolbar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx); | |
6339 if (rc < 0) | |
6340 { | |
6341 /* Not on toolbar item. */ | |
6342 clear_mouse_face (dpyinfo); | |
6343 return; | |
6344 } | |
6345 else if (rc == 0) | |
6346 /* On same toolbar item as before. */ | |
6347 goto set_help_echo; | |
6348 | |
6349 clear_mouse_face (dpyinfo); | |
6350 | |
6351 /* Mouse is down, but on different toolbar item? */ | |
6352 mouse_down_p = (dpyinfo->grabbed | |
6353 && f == last_mouse_frame | |
6354 && FRAME_LIVE_P (f)); | |
6355 if (mouse_down_p | |
6356 && last_toolbar_item != prop_idx) | |
6357 return; | |
6358 | |
6359 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT; | |
6360 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; | |
6361 | |
6362 /* If toolbar item is not enabled, don't highlight it. */ | |
6363 enabled_p = (XVECTOR (f->current_toolbar_items) | |
6364 ->contents[prop_idx + TOOLBAR_ITEM_ENABLED_P]); | |
6365 if (!NILP (enabled_p)) | |
6366 { | |
6367 /* Compute the x-position of the glyph. In front and past the | |
6368 image is a space. We include this is the highlighted area. */ | |
6369 row = MATRIX_ROW (w->current_matrix, vpos); | |
6370 for (i = x = 0; i < hpos; ++i) | |
6371 x += row->glyphs[TEXT_AREA][i].pixel_width; | |
6372 | |
6373 /* Record this as the current active region. */ | |
6374 dpyinfo->mouse_face_beg_col = hpos; | |
6375 dpyinfo->mouse_face_beg_row = vpos; | |
6376 dpyinfo->mouse_face_beg_x = x; | |
6377 dpyinfo->mouse_face_beg_y = row->y; | |
6378 dpyinfo->mouse_face_past_end = 0; | |
6379 | |
6380 dpyinfo->mouse_face_end_col = hpos + 1; | |
6381 dpyinfo->mouse_face_end_row = vpos; | |
6382 dpyinfo->mouse_face_end_x = x + glyph->pixel_width; | |
6383 dpyinfo->mouse_face_end_y = row->y; | |
6384 dpyinfo->mouse_face_window = window; | |
6385 dpyinfo->mouse_face_face_id = TOOLBAR_FACE_ID; | |
6386 | |
6387 /* Display it as active. */ | |
6388 show_mouse_face (dpyinfo, draw); | |
6389 dpyinfo->mouse_face_image_state = draw; | |
6390 } | |
6391 | |
6392 set_help_echo: | |
6393 | |
6394 /* Set help_echo to a help string.to display for this toolbar item. | |
6395 XTread_socket does the rest. */ | |
6396 help_echo = (XVECTOR (f->current_toolbar_items) | |
6397 ->contents[prop_idx + TOOLBAR_ITEM_HELP]); | |
6398 if (!STRINGP (help_echo)) | |
6399 help_echo = (XVECTOR (f->current_toolbar_items) | |
6400 ->contents[prop_idx + TOOLBAR_ITEM_CAPTION]); | |
6401 } | |
6402 | |
6403 | |
6404 | |
6405 /* Find the glyph matrix position of buffer position POS in window W. | |
6406 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's | |
6407 current glyphs must be up to date. If POS is above window start | |
6408 return (0, 0, 0, 0). If POS is after end of W, return end of | |
6409 last line in W. */ | |
6410 | |
6411 static int | |
6412 fast_find_position (w, pos, hpos, vpos, x, y) | |
6413 struct window *w; | |
2576 int pos; | 6414 int pos; |
2577 int *columnp, *rowp; | 6415 int *hpos, *vpos, *x, *y; |
2578 { | 6416 { |
2579 struct window *w = XWINDOW (window); | |
2580 FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); | |
2581 int i; | 6417 int i; |
2582 int row = 0; | |
2583 int left = WINDOW_LEFT_MARGIN (w); | |
2584 int top = XFASTINT (w->top); | |
2585 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w); | |
2586 int width = window_internal_width (w); | |
2587 int *charstarts; | |
2588 int lastcol; | 6418 int lastcol; |
2589 int maybe_next_line = 0; | 6419 int maybe_next_line_p = 0; |
2590 | 6420 int line_start_position; |
2591 /* Find the right row. */ | 6421 int yb = window_text_bottom_y (w); |
2592 for (i = 0; | 6422 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0); |
2593 i < height; | 6423 struct glyph_row *best_row = row; |
2594 i++) | 6424 int row_vpos = 0, best_row_vpos = 0; |
2595 { | 6425 int current_x; |
2596 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left]; | 6426 |
2597 if (linestart > pos) | 6427 while (row->y < yb) |
6428 { | |
6429 if (row->used[TEXT_AREA]) | |
6430 line_start_position = row->glyphs[TEXT_AREA]->charpos; | |
6431 else | |
6432 line_start_position = 0; | |
6433 | |
6434 if (line_start_position > pos) | |
2598 break; | 6435 break; |
2599 /* If the position sought is the end of the buffer, | 6436 /* If the position sought is the end of the buffer, |
2600 don't include the blank lines at the bottom of the window. */ | 6437 don't include the blank lines at the bottom of the window. */ |
2601 if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer))) | 6438 else if (line_start_position == pos |
6439 && pos == BUF_ZV (XBUFFER (w->buffer))) | |
2602 { | 6440 { |
2603 maybe_next_line = 1; | 6441 maybe_next_line_p = 1; |
2604 break; | 6442 break; |
2605 } | 6443 } |
2606 if (linestart > 0) | 6444 else if (line_start_position > 0) |
2607 row = i; | |
2608 } | |
2609 | |
2610 /* Find the right column with in it. */ | |
2611 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row]; | |
2612 lastcol = left; | |
2613 for (i = 0; i < width; i++) | |
2614 { | |
2615 if (charstarts[left + i] == pos) | |
2616 { | 6445 { |
2617 *rowp = row + top; | 6446 best_row = row; |
2618 *columnp = i + left; | 6447 best_row_vpos = row_vpos; |
6448 } | |
6449 | |
6450 ++row; | |
6451 ++row_vpos; | |
6452 } | |
6453 | |
6454 /* Find the right column within BEST_ROW. */ | |
6455 lastcol = 0; | |
6456 current_x = best_row->x; | |
6457 for (i = 0; i < best_row->used[TEXT_AREA]; i++) | |
6458 { | |
6459 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i; | |
6460 int charpos; | |
6461 | |
6462 charpos = glyph->charpos; | |
6463 if (charpos == pos) | |
6464 { | |
6465 *hpos = i; | |
6466 *vpos = best_row_vpos; | |
6467 *x = current_x; | |
6468 *y = best_row->y; | |
2619 return 1; | 6469 return 1; |
2620 } | 6470 } |
2621 else if (charstarts[left + i] > pos) | 6471 else if (charpos > pos) |
2622 break; | 6472 break; |
2623 else if (charstarts[left + i] > 0) | 6473 else if (charpos > 0) |
2624 lastcol = left + i + 1; | 6474 lastcol = i; |
6475 | |
6476 current_x += glyph->pixel_width; | |
2625 } | 6477 } |
2626 | 6478 |
2627 /* If we're looking for the end of the buffer, | 6479 /* If we're looking for the end of the buffer, |
2628 and we didn't find it in the line we scanned, | 6480 and we didn't find it in the line we scanned, |
2629 use the start of the following line. */ | 6481 use the start of the following line. */ |
2630 if (maybe_next_line) | 6482 if (maybe_next_line_p) |
2631 { | 6483 { |
2632 row++; | 6484 ++best_row; |
2633 lastcol = left; | 6485 ++best_row_vpos; |
2634 } | 6486 lastcol = 0; |
2635 | 6487 current_x = best_row->x; |
2636 *rowp = row + top; | 6488 } |
2637 *columnp = lastcol; | 6489 |
6490 *vpos = best_row_vpos; | |
6491 *hpos = lastcol + 1; | |
6492 *x = current_x; | |
6493 *y = best_row->y; | |
2638 return 0; | 6494 return 0; |
2639 } | 6495 } |
6496 | |
2640 | 6497 |
2641 /* Display the active region described by mouse_face_* | 6498 /* Display the active region described by mouse_face_* |
2642 in its mouse-face if HL > 0, in its normal face if HL = 0. */ | 6499 in its mouse-face if HL > 0, in its normal face if HL = 0. */ |
2643 | 6500 |
2644 static void | 6501 static void |
2645 show_mouse_face (dpyinfo, hl) | 6502 show_mouse_face (dpyinfo, draw) |
2646 struct x_display_info *dpyinfo; | 6503 struct x_display_info *dpyinfo; |
2647 int hl; | 6504 enum draw_glyphs_face draw; |
2648 { | 6505 { |
2649 struct window *w = XWINDOW (dpyinfo->mouse_face_window); | 6506 struct window *w = XWINDOW (dpyinfo->mouse_face_window); |
2650 int width = window_internal_width (w); | 6507 struct frame *f = XFRAME (WINDOW_FRAME (w)); |
2651 FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); | |
2652 int i; | 6508 int i; |
2653 int cursor_off = 0; | 6509 int cursor_off_p = 0; |
2654 int old_curs_x = curs_x; | 6510 struct cursor_pos saved_cursor; |
2655 int old_curs_y = curs_y; | 6511 |
2656 | 6512 saved_cursor = output_cursor; |
2657 /* Set these variables temporarily | 6513 |
2658 so that if we have to turn the cursor off and on again | 6514 /* If window is in the process of being destroyed, don't bother |
2659 we will put it back at the same place. */ | 6515 to do anything. */ |
2660 curs_x = f->phys_cursor_x; | 6516 if (w->current_matrix == NULL) |
2661 curs_y = f->phys_cursor_y; | 6517 goto set_x_cursor; |
2662 for (i = FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row; | 6518 |
2663 i <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row; i++) | 6519 /* Recognize when we are called to operate on rows that don't exist |
2664 { | 6520 anymore. This can happen when a window is split. */ |
2665 int column = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row | 6521 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows) |
2666 ? FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col | 6522 goto set_x_cursor; |
2667 : WINDOW_LEFT_MARGIN (w)); | 6523 |
2668 int endcolumn = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row | 6524 set_output_cursor (&w->phys_cursor); |
2669 ? FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col | 6525 |
2670 : WINDOW_LEFT_MARGIN (w) + width); | 6526 /* Note that mouse_face_beg_row etc. are window relative. */ |
2671 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]); | 6527 for (i = dpyinfo->mouse_face_beg_row; |
2672 | 6528 i <= dpyinfo->mouse_face_end_row; |
2673 /* If the cursor's in the text we are about to rewrite, | 6529 i++) |
2674 turn the cursor off. */ | 6530 { |
2675 if (i == curs_y | 6531 int start_hpos, end_hpos, start_x; |
2676 && curs_x >= column - 1 | 6532 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i); |
2677 && curs_x <= endcolumn) | 6533 |
6534 /* Don't do anything if row doesn't have valid contents. */ | |
6535 if (!row->enabled_p) | |
6536 continue; | |
6537 | |
6538 /* For all but the first row, the highlight starts at column 0. */ | |
6539 if (i == dpyinfo->mouse_face_beg_row) | |
2678 { | 6540 { |
2679 x_update_cursor (f, 0); | 6541 start_hpos = dpyinfo->mouse_face_beg_col; |
2680 cursor_off = 1; | 6542 start_x = dpyinfo->mouse_face_beg_x; |
2681 } | 6543 } |
2682 | 6544 else |
2683 dumpglyphs (f, | 6545 { |
2684 CHAR_TO_PIXEL_COL (f, column), | 6546 start_hpos = 0; |
2685 CHAR_TO_PIXEL_ROW (f, i), | 6547 start_x = 0; |
2686 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column, | 6548 } |
2687 endcolumn - column, | 6549 |
2688 /* Highlight with mouse face if hl > 0. */ | 6550 if (i == dpyinfo->mouse_face_end_row) |
2689 hl > 0 ? 3 : 0, 0, NULL); | 6551 end_hpos = dpyinfo->mouse_face_end_col; |
6552 else | |
6553 end_hpos = row->used[TEXT_AREA]; | |
6554 | |
6555 /* If the cursor's in the text we are about to rewrite, turn the | |
6556 cursor off. */ | |
6557 if (!w->pseudo_window_p | |
6558 && i == output_cursor.vpos | |
6559 && output_cursor.hpos >= start_hpos - 1 | |
6560 && output_cursor.hpos <= end_hpos) | |
6561 { | |
6562 x_update_window_cursor (w, 0); | |
6563 cursor_off_p = 1; | |
6564 } | |
6565 | |
6566 if (end_hpos > start_hpos) | |
6567 x_draw_glyphs (w, start_x, row, updated_area, | |
6568 start_hpos, end_hpos, draw, NULL, NULL); | |
2690 } | 6569 } |
2691 | 6570 |
2692 /* If we turned the cursor off, turn it back on. */ | 6571 /* If we turned the cursor off, turn it back on. */ |
2693 if (cursor_off) | 6572 if (cursor_off_p) |
2694 x_display_cursor (f, 1, curs_x, curs_y); | 6573 x_display_cursor (w, 1, |
2695 | 6574 output_cursor.hpos, output_cursor.vpos, |
2696 curs_x = old_curs_x; | 6575 output_cursor.x, output_cursor.y); |
2697 curs_y = old_curs_y; | 6576 |
2698 | 6577 output_cursor = saved_cursor; |
2699 /* Change the mouse cursor according to the value of HL. */ | 6578 |
2700 if (hl > 0) | 6579 set_x_cursor: |
6580 | |
6581 /* Change the mouse cursor. */ | |
6582 if (draw == DRAW_NORMAL_TEXT) | |
6583 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
6584 f->output_data.x->text_cursor); | |
6585 else if (draw == DRAW_MOUSE_FACE) | |
2701 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 6586 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
2702 f->output_data.x->cross_cursor); | 6587 f->output_data.x->cross_cursor); |
2703 else | 6588 else |
2704 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 6589 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
2705 f->output_data.x->text_cursor); | 6590 f->output_data.x->nontext_cursor); |
2706 } | 6591 } |
2707 | 6592 |
2708 /* Clear out the mouse-highlighted active region. | 6593 /* Clear out the mouse-highlighted active region. |
2709 Redraw it unhighlighted first. */ | 6594 Redraw it un-highlighted first. */ |
2710 | 6595 |
2711 static void | 6596 void |
2712 clear_mouse_face (dpyinfo) | 6597 clear_mouse_face (dpyinfo) |
2713 struct x_display_info *dpyinfo; | 6598 struct x_display_info *dpyinfo; |
2714 { | 6599 { |
6600 if (tip_frame) | |
6601 return; | |
6602 | |
2715 if (! NILP (dpyinfo->mouse_face_window)) | 6603 if (! NILP (dpyinfo->mouse_face_window)) |
2716 show_mouse_face (dpyinfo, 0); | 6604 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT); |
2717 | 6605 |
2718 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; | 6606 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; |
2719 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; | 6607 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; |
2720 dpyinfo->mouse_face_window = Qnil; | 6608 dpyinfo->mouse_face_window = Qnil; |
2721 } | 6609 } |
2752 | 6640 |
2753 If the mouse movement started elsewhere, set *fp to the frame the | 6641 If the mouse movement started elsewhere, set *fp to the frame the |
2754 mouse is on, *bar_window to nil, and *x and *y to the character cell | 6642 mouse is on, *bar_window to nil, and *x and *y to the character cell |
2755 the mouse is over. | 6643 the mouse is over. |
2756 | 6644 |
2757 Set *time to the server timestamp for the time at which the mouse | 6645 Set *time to the server time-stamp for the time at which the mouse |
2758 was at this position. | 6646 was at this position. |
2759 | 6647 |
2760 Don't store anything if we don't have a valid set of values to report. | 6648 Don't store anything if we don't have a valid set of values to report. |
2761 | 6649 |
2762 This clears the mouse_moved flag, so we can wait for the next mouse | 6650 This clears the mouse_moved flag, so we can wait for the next mouse |
2818 /* Now we have a position on the root; find the innermost window | 6706 /* Now we have a position on the root; find the innermost window |
2819 containing the pointer. */ | 6707 containing the pointer. */ |
2820 { | 6708 { |
2821 Window win, child; | 6709 Window win, child; |
2822 int win_x, win_y; | 6710 int win_x, win_y; |
2823 int parent_x, parent_y; | 6711 int parent_x = 0, parent_y = 0; |
2824 int count; | 6712 int count; |
2825 | 6713 |
2826 win = root; | 6714 win = root; |
2827 | 6715 |
2828 /* XTranslateCoordinates can get errors if the window | 6716 /* XTranslateCoordinates can get errors if the window |
2907 if (f1 == 0 && insist > 0) | 6795 if (f1 == 0 && insist > 0) |
2908 f1 = selected_frame; | 6796 f1 = selected_frame; |
2909 | 6797 |
2910 if (f1) | 6798 if (f1) |
2911 { | 6799 { |
6800 /* Ok, we found a frame. Store all the values. | |
6801 last_mouse_glyph is a rectangle used to reduce the | |
6802 generation of mouse events. To not miss any motion | |
6803 events, we must divide the frame into rectangles of the | |
6804 size of the smallest character that could be displayed | |
6805 on it, i.e. into the same rectangles that matrices on | |
6806 the frame are divided into. */ | |
6807 | |
6808 #if OLD_REDISPLAY_CODE | |
2912 int ignore1, ignore2; | 6809 int ignore1, ignore2; |
2913 | |
2914 /* Ok, we found a frame. Store all the values. */ | |
2915 | |
2916 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2, | 6810 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2, |
2917 &last_mouse_glyph, | 6811 &last_mouse_glyph, |
2918 FRAME_X_DISPLAY_INFO (f1)->grabbed | 6812 FRAME_X_DISPLAY_INFO (f1)->grabbed |
2919 || insist); | 6813 || insist); |
6814 #else | |
6815 { | |
6816 int width = FRAME_SMALLEST_CHAR_WIDTH (f1); | |
6817 int height = FRAME_SMALLEST_FONT_HEIGHT (f1); | |
6818 int x = win_x; | |
6819 int y = win_y; | |
6820 | |
6821 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to | |
6822 round down even for negative values. */ | |
6823 if (x < 0) | |
6824 x -= width - 1; | |
6825 if (y < 0) | |
6826 y -= height - 1; | |
6827 | |
6828 last_mouse_glyph.width = width; | |
6829 last_mouse_glyph.height = height; | |
6830 last_mouse_glyph.x = (x + width - 1) / width * width; | |
6831 last_mouse_glyph.y = (y + height - 1) / height * height; | |
6832 } | |
6833 #endif | |
2920 | 6834 |
2921 *bar_window = Qnil; | 6835 *bar_window = Qnil; |
2922 *part = 0; | 6836 *part = 0; |
2923 *fp = f1; | 6837 *fp = f1; |
2924 XSETINT (*x, win_x); | 6838 XSETINT (*x, win_x); |
2928 } | 6842 } |
2929 } | 6843 } |
2930 | 6844 |
2931 UNBLOCK_INPUT; | 6845 UNBLOCK_INPUT; |
2932 } | 6846 } |
6847 | |
6848 | |
6849 DEFUN ("xt-process-timeouts", Fxt_process_timeouts, Sxt_process_timeouts, | |
6850 0, 0, 0, | |
6851 "Arrange for Xt timeout callbacks to be called.") | |
6852 () | |
6853 { | |
6854 #ifdef USE_X_TOOLKIT | |
6855 BLOCK_INPUT; | |
6856 while (XtAppPending (Xt_app_con) & XtIMTimer) | |
6857 XtAppProcessEvent (Xt_app_con, XtIMTimer); | |
6858 UNBLOCK_INPUT; | |
6859 #endif /* USE_X_TOOLKIT */ | |
6860 | |
6861 return Qnil; | |
6862 } | |
6863 | |
6864 | |
2933 | 6865 |
2934 /* Scroll bar support. */ | 6866 /* Scroll bar support. */ |
2935 | 6867 |
2936 /* Given an X window ID, find the struct scroll_bar which manages it. | 6868 /* Given an X window ID, find the struct scroll_bar which manages it. |
2937 This can be called in GC, so we have to make sure to strip off mark | 6869 This can be called in GC, so we have to make sure to strip off mark |
2938 bits. */ | 6870 bits. */ |
2939 static struct scroll_bar * | 6871 static struct scroll_bar * |
2940 x_window_to_scroll_bar (window_id) | 6872 x_window_to_scroll_bar (window_id) |
2941 Window window_id; | 6873 Window window_id; |
2942 { | 6874 { |
2943 Lisp_Object tail, frame; | 6875 Lisp_Object tail; |
2944 | 6876 |
2945 for (tail = Vframe_list; | 6877 for (tail = Vframe_list; |
2946 XGCTYPE (tail) == Lisp_Cons; | 6878 XGCTYPE (tail) == Lisp_Cons; |
2947 tail = XCONS (tail)->cdr) | 6879 tail = XCONS (tail)->cdr) |
2948 { | 6880 { |
2968 } | 6900 } |
2969 | 6901 |
2970 return 0; | 6902 return 0; |
2971 } | 6903 } |
2972 | 6904 |
2973 /* Open a new X window to serve as a scroll bar, and return the | 6905 |
2974 scroll bar vector for it. */ | 6906 |
6907 /************************************************************************ | |
6908 Toolkit scroll bars | |
6909 ************************************************************************/ | |
6910 | |
6911 #if USE_TOOLKIT_SCROLL_BARS | |
6912 | |
6913 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *)); | |
6914 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int)); | |
6915 static void x_create_toolkit_scroll_bar P_ ((struct frame *, | |
6916 struct scroll_bar *)); | |
6917 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *, | |
6918 int, int, int)); | |
6919 | |
6920 | |
6921 /* Id of action hook installed for scroll bars. */ | |
6922 | |
6923 static XtActionHookId action_hook_id; | |
6924 | |
6925 /* Lisp window being scrolled. Set when starting to interact with | |
6926 a toolkit scroll bar, reset to nil when ending the interaction. */ | |
6927 | |
6928 static Lisp_Object window_being_scrolled; | |
6929 | |
6930 /* Last scroll bar part sent in xm_scroll_callback. */ | |
6931 | |
6932 static int last_scroll_bar_part; | |
6933 | |
6934 | |
6935 /* Action hook installed via XtAppAddActionHook when toolkit scroll | |
6936 bars are used.. The hoos is responsible for detecting when | |
6937 the user ends an interaction with the scroll bar, and generates | |
6938 a `end-scroll' scroll_bar_click' event if so. */ | |
6939 | |
6940 static void | |
6941 xt_action_hook (widget, client_data, action_name, event, params, | |
6942 num_params) | |
6943 Widget widget; | |
6944 XtPointer client_data; | |
6945 String action_name; | |
6946 XEvent *event; | |
6947 String *params; | |
6948 Cardinal *num_params; | |
6949 { | |
6950 int scroll_bar_p; | |
6951 char *end_action; | |
6952 | |
6953 #ifdef USE_MOTIF | |
6954 scroll_bar_p = XmIsScrollBar (widget); | |
6955 end_action = "Release"; | |
6956 #elif defined HAVE_XAW3D | |
6957 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass); | |
6958 end_action = "EndScroll"; | |
6959 #else | |
6960 #error unknown scroll bar toolkit | |
6961 #endif /* HAVE_XAW3D */ | |
6962 | |
6963 /* Although LessTif uses XtTimeouts like Xaw3d, the timer hack to | |
6964 let Xt timeouts be processed doesn't work. */ | |
6965 if (scroll_bar_p | |
6966 && strcmp (action_name, end_action) == 0 | |
6967 && WINDOWP (window_being_scrolled)) | |
6968 { | |
6969 struct window *w; | |
6970 | |
6971 x_send_scroll_bar_event (window_being_scrolled, | |
6972 scroll_bar_end_scroll, 0, 0); | |
6973 w = XWINDOW (window_being_scrolled); | |
6974 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil; | |
6975 window_being_scrolled = Qnil; | |
6976 last_scroll_bar_part = -1; | |
6977 } | |
6978 } | |
6979 | |
6980 | |
6981 /* Send a client message with message type Xatom_Scrollbar for a | |
6982 scroll action to the frame of WINDOW. PART is a value identifying | |
6983 the part of the scroll bar that was clicked on. PORTION is the | |
6984 amount to scroll of a whole of WHOLE. */ | |
6985 | |
6986 static void | |
6987 x_send_scroll_bar_event (window, part, portion, whole) | |
6988 Lisp_Object window; | |
6989 int part, portion, whole; | |
6990 { | |
6991 XEvent event; | |
6992 XClientMessageEvent *ev = (XClientMessageEvent *) &event; | |
6993 struct frame *f = XFRAME (XWINDOW (window)->frame); | |
6994 | |
6995 /* Construct a ClientMessage event to send to the frame. */ | |
6996 ev->type = ClientMessage; | |
6997 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar; | |
6998 ev->display = FRAME_X_DISPLAY (f); | |
6999 ev->window = FRAME_X_WINDOW (f); | |
7000 ev->format = 32; | |
7001 ev->data.l[0] = (long) window; | |
7002 ev->data.l[1] = (long) part; | |
7003 ev->data.l[2] = (long) 0; | |
7004 ev->data.l[3] = (long) portion; | |
7005 ev->data.l[4] = (long) whole; | |
7006 | |
7007 /* Setting the event mask to zero means that the message will | |
7008 be sent to the client that created the window, and if that | |
7009 window no longer exists, no event will be sent. */ | |
7010 BLOCK_INPUT; | |
7011 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event); | |
7012 UNBLOCK_INPUT; | |
7013 } | |
7014 | |
7015 | |
7016 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event | |
7017 in *IEVENT. */ | |
7018 | |
7019 static void | |
7020 x_scroll_bar_to_input_event (event, ievent) | |
7021 XEvent *event; | |
7022 struct input_event *ievent; | |
7023 { | |
7024 XClientMessageEvent *ev = (XClientMessageEvent *) event; | |
7025 Lisp_Object window = (Lisp_Object) ev->data.l[0]; | |
7026 struct frame *f = XFRAME (XWINDOW (window)->frame); | |
7027 | |
7028 ievent->kind = scroll_bar_click; | |
7029 ievent->frame_or_window = window; | |
7030 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f)); | |
7031 ievent->part = ev->data.l[1]; | |
7032 ievent->code = ev->data.l[2]; | |
7033 ievent->x = make_number ((int) ev->data.l[3]); | |
7034 ievent->y = make_number ((int) ev->data.l[4]); | |
7035 ievent->modifiers = 0; | |
7036 } | |
7037 | |
7038 | |
7039 #ifdef USE_MOTIF | |
7040 | |
7041 /* Minimum and maximum values used for Motif scroll bars. */ | |
7042 | |
7043 #define XM_SB_MIN 1 | |
7044 #define XM_SB_MAX 10000000 | |
7045 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN) | |
7046 | |
7047 | |
7048 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll | |
7049 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure. | |
7050 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */ | |
7051 | |
7052 static void | |
7053 xm_scroll_callback (widget, client_data, call_data) | |
7054 Widget widget; | |
7055 XtPointer client_data, call_data; | |
7056 { | |
7057 struct scroll_bar *bar = (struct scroll_bar *) client_data; | |
7058 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data; | |
7059 double percent; | |
7060 int part = -1, whole = 0, portion = 0; | |
7061 | |
7062 switch (cs->reason) | |
7063 { | |
7064 case XmCR_DECREMENT: | |
7065 bar->dragging = Qnil; | |
7066 part = scroll_bar_up_arrow; | |
7067 break; | |
7068 | |
7069 case XmCR_INCREMENT: | |
7070 bar->dragging = Qnil; | |
7071 part = scroll_bar_down_arrow; | |
7072 break; | |
7073 | |
7074 case XmCR_PAGE_DECREMENT: | |
7075 bar->dragging = Qnil; | |
7076 part = scroll_bar_above_handle; | |
7077 break; | |
7078 | |
7079 case XmCR_PAGE_INCREMENT: | |
7080 bar->dragging = Qnil; | |
7081 part = scroll_bar_below_handle; | |
7082 break; | |
7083 | |
7084 case XmCR_TO_TOP: | |
7085 bar->dragging = Qnil; | |
7086 part = scroll_bar_to_top; | |
7087 break; | |
7088 | |
7089 case XmCR_TO_BOTTOM: | |
7090 bar->dragging = Qnil; | |
7091 part = scroll_bar_to_bottom; | |
7092 break; | |
7093 | |
7094 case XmCR_DRAG: | |
7095 { | |
7096 int slider_size; | |
7097 int dragging_down_p = (INTEGERP (bar->dragging) | |
7098 && XINT (bar->dragging) <= cs->value); | |
7099 | |
7100 /* Get the slider size. */ | |
7101 BLOCK_INPUT; | |
7102 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL); | |
7103 UNBLOCK_INPUT; | |
7104 | |
7105 /* At the max position of the scroll bar, do a line-wise | |
7106 movement. Without doing anything, the LessTif scroll bar | |
7107 calls us with the same cs->value again and again. If we | |
7108 want to make sure that we can reach the end of the buffer, | |
7109 we have to do something. | |
7110 | |
7111 Implementation note: setting bar->dragging always to | |
7112 cs->value gives a smoother movement at the max position. | |
7113 Setting it to nil when doing line-wise movement gives | |
7114 a better slider behavior. */ | |
7115 | |
7116 if (cs->value + slider_size == XM_SB_MAX | |
7117 || (dragging_down_p | |
7118 && last_scroll_bar_part == scroll_bar_down_arrow)) | |
7119 { | |
7120 part = scroll_bar_down_arrow; | |
7121 bar->dragging = Qnil; | |
7122 } | |
7123 else | |
7124 { | |
7125 whole = XM_SB_RANGE; | |
7126 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size); | |
7127 part = scroll_bar_handle; | |
7128 bar->dragging = make_number (cs->value); | |
7129 } | |
7130 } | |
7131 break; | |
7132 | |
7133 case XmCR_VALUE_CHANGED: | |
7134 break; | |
7135 }; | |
7136 | |
7137 if (part >= 0) | |
7138 { | |
7139 window_being_scrolled = bar->window; | |
7140 last_scroll_bar_part = part; | |
7141 x_send_scroll_bar_event (bar->window, part, portion, whole); | |
7142 } | |
7143 } | |
7144 | |
7145 | |
7146 #else /* not USE_MOTIF, i.e. XAW3D. */ | |
7147 | |
7148 | |
7149 /* Xaw3d scroll bar callback. Invoked when the thumb is dragged. | |
7150 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the | |
7151 scroll bar struct. CALL_DATA is a pointer to a float saying where | |
7152 the thumb is. */ | |
7153 | |
7154 static void | |
7155 xaw3d_jump_callback (widget, client_data, call_data) | |
7156 Widget widget; | |
7157 XtPointer client_data, call_data; | |
7158 { | |
7159 struct scroll_bar *bar = (struct scroll_bar *) client_data; | |
7160 float top = *(float *) call_data; | |
7161 float shown; | |
7162 int whole, portion; | |
7163 int dragging_down_p, part; | |
7164 double epsilon = 0.01; | |
7165 | |
7166 /* Get the size of the thumb, a value between 0 and 1. */ | |
7167 BLOCK_INPUT; | |
7168 XtVaGetValues (widget, XtNshown, &shown, NULL); | |
7169 UNBLOCK_INPUT; | |
7170 | |
7171 whole = 10000000; | |
7172 portion = shown < 1 ? top * whole : 0; | |
7173 dragging_down_p = (INTEGERP (bar->dragging) | |
7174 && XINT (bar->dragging) < portion); | |
7175 | |
7176 if (shown < 1 | |
7177 && (abs (top + shown - 1) < epsilon | |
7178 || (dragging_down_p | |
7179 && last_scroll_bar_part == scroll_bar_down_arrow))) | |
7180 part = scroll_bar_down_arrow; | |
7181 else | |
7182 part = scroll_bar_handle; | |
7183 | |
7184 window_being_scrolled = bar->window; | |
7185 bar->dragging = make_number (portion); | |
7186 last_scroll_bar_part = part; | |
7187 x_send_scroll_bar_event (bar->window, part, portion, whole); | |
7188 } | |
7189 | |
7190 | |
7191 /* Xaw3d scroll bar callback. Invoked for incremental scrolling., | |
7192 i.e. line or page up or down. WIDGET is the Xaw3d scroll bar | |
7193 widget. CLIENT_DATA is a pointer to the scroll_bar structure for | |
7194 the scroll bar. CALL_DATA is an integer specifying the action that | |
7195 has taken place. It's magnitude is in the range 0..height of the | |
7196 scroll bar. Negative values mean scroll towards buffer start. | |
7197 Values < height of scroll bar mean line-wise movement. */ | |
7198 | |
7199 static void | |
7200 xaw3d_scroll_callback (widget, client_data, call_data) | |
7201 Widget widget; | |
7202 XtPointer client_data, call_data; | |
7203 { | |
7204 struct scroll_bar *bar = (struct scroll_bar *) client_data; | |
7205 int position = (int) call_data; | |
7206 Dimension height; | |
7207 int part; | |
7208 | |
7209 /* Get the height of the scroll bar. */ | |
7210 BLOCK_INPUT; | |
7211 XtVaGetValues (widget, XtNheight, &height, NULL); | |
7212 UNBLOCK_INPUT; | |
7213 | |
7214 if (position < 0) | |
7215 { | |
7216 if (abs (position) < height) | |
7217 part = scroll_bar_up_arrow; | |
7218 else | |
7219 part = scroll_bar_above_handle; | |
7220 } | |
7221 else | |
7222 { | |
7223 if (abs (position) < height) | |
7224 part = scroll_bar_down_arrow; | |
7225 else | |
7226 part = scroll_bar_below_handle; | |
7227 } | |
7228 | |
7229 window_being_scrolled = bar->window; | |
7230 bar->dragging = Qnil; | |
7231 last_scroll_bar_part = part; | |
7232 x_send_scroll_bar_event (bar->window, part, 0, 0); | |
7233 } | |
7234 | |
7235 | |
7236 #endif /* not USE_MOTIF */ | |
7237 | |
7238 | |
7239 /* Create the widget for scroll bar BAR on frame F. Record the widget | |
7240 and X window of the scroll bar in BAR. */ | |
7241 | |
7242 static void | |
7243 x_create_toolkit_scroll_bar (f, bar) | |
7244 struct frame *f; | |
7245 struct scroll_bar *bar; | |
7246 { | |
7247 Window xwindow; | |
7248 Widget widget; | |
7249 Arg av[20]; | |
7250 int ac = 0; | |
7251 char *scroll_bar_name = "verticalScrollBar"; | |
7252 unsigned long pixel; | |
7253 | |
7254 BLOCK_INPUT; | |
7255 | |
7256 #ifdef USE_MOTIF | |
7257 /* LessTif 0.85, problems: | |
7258 | |
7259 1. When the mouse if over the scroll bar, the scroll bar will | |
7260 get keyboard events. I didn't find a way to turn this off. | |
7261 | |
7262 2. Do we have to explicitly set the cursor to get an arrow | |
7263 cursor (see below)? */ | |
7264 | |
7265 /* Set resources. Create the widget. */ | |
7266 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac; | |
7267 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac; | |
7268 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac; | |
7269 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac; | |
7270 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac; | |
7271 XtSetArg (av[ac], XmNincrement, 1); ++ac; | |
7272 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac; | |
7273 | |
7274 pixel = f->output_data.x->scroll_bar_foreground_pixel; | |
7275 if (pixel != -1) | |
7276 { | |
7277 XtSetArg (av[ac], XmNforeground, pixel); | |
7278 ++ac; | |
7279 } | |
7280 | |
7281 pixel = f->output_data.x->scroll_bar_background_pixel; | |
7282 if (pixel != -1) | |
7283 { | |
7284 XtSetArg (av[ac], XmNbackground, pixel); | |
7285 ++ac; | |
7286 } | |
7287 | |
7288 widget = XmCreateScrollBar (f->output_data.x->edit_widget, | |
7289 scroll_bar_name, av, ac); | |
7290 | |
7291 /* Add one callback for everything that can happen. */ | |
7292 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback, | |
7293 (XtPointer) bar); | |
7294 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback, | |
7295 (XtPointer) bar); | |
7296 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback, | |
7297 (XtPointer) bar); | |
7298 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback, | |
7299 (XtPointer) bar); | |
7300 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback, | |
7301 (XtPointer) bar); | |
7302 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback, | |
7303 (XtPointer) bar); | |
7304 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback, | |
7305 (XtPointer) bar); | |
7306 | |
7307 /* Realize the widget. Only after that is the X window created. */ | |
7308 XtRealizeWidget (widget); | |
7309 | |
7310 /* Set the cursor to an arrow. I didn't find a resource to do that. | |
7311 And I'm wondering why it hasn't an arrow cursor by default. */ | |
7312 XDefineCursor (XtDisplay (widget), XtWindow (widget), | |
7313 f->output_data.x->nontext_cursor); | |
7314 | |
7315 #elif defined HAVE_XAW3D | |
7316 | |
7317 /* Set resources. Create the widget. The background of the | |
7318 Xaw3d scroll bar widget is a little bit light for my taste. | |
7319 We don't alter it here to let users change it according | |
7320 to their taste with `emacs*verticalScrollBar.background: xxx'. */ | |
7321 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac; | |
7322 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac; | |
7323 XtSetArg (av[ac], XtNcursorName, "left_ptr"); ++ac; | |
7324 XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; | |
7325 | |
7326 pixel = f->output_data.x->scroll_bar_foreground_pixel; | |
7327 if (pixel != -1) | |
7328 { | |
7329 XtSetArg (av[ac], XtNforeground, pixel); | |
7330 ++ac; | |
7331 } | |
7332 | |
7333 pixel = f->output_data.x->scroll_bar_background_pixel; | |
7334 if (pixel != -1) | |
7335 { | |
7336 XtSetArg (av[ac], XtNbackground, pixel); | |
7337 ++ac; | |
7338 } | |
7339 | |
7340 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass, | |
7341 f->output_data.x->edit_widget, av, ac); | |
7342 | |
7343 /* Define callbacks. */ | |
7344 XtAddCallback (widget, XtNjumpProc, xaw3d_jump_callback, (XtPointer) bar); | |
7345 XtAddCallback (widget, XtNscrollProc, xaw3d_scroll_callback, | |
7346 (XtPointer) bar); | |
7347 | |
7348 /* Realize the widget. Only after that is the X window created. */ | |
7349 XtRealizeWidget (widget); | |
7350 | |
7351 #endif /* HAVE_XAW3D */ | |
7352 | |
7353 /* Install an action hook that let's us detect when the user | |
7354 finishes interacting with a scroll bar. */ | |
7355 if (action_hook_id == 0) | |
7356 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0); | |
7357 | |
7358 /* Remember X window and widget in the scroll bar vector. */ | |
7359 SET_SCROLL_BAR_X_WIDGET (bar, widget); | |
7360 xwindow = XtWindow (widget); | |
7361 SET_SCROLL_BAR_X_WINDOW (bar, xwindow); | |
7362 | |
7363 UNBLOCK_INPUT; | |
7364 } | |
7365 | |
7366 | |
7367 /* Set the thumb size and position of scroll bar BAR. We are currently | |
7368 displaying PORTION out of a whole WHOLE, and our position POSITION. */ | |
7369 | |
7370 static void | |
7371 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole) | |
7372 struct scroll_bar *bar; | |
7373 int portion, position, whole; | |
7374 { | |
7375 float top, shown; | |
7376 Arg av[2]; | |
7377 Widget widget = SCROLL_BAR_X_WIDGET (bar); | |
7378 | |
7379 if (whole == 0) | |
7380 top = 0, shown = 1; | |
7381 else | |
7382 { | |
7383 top = (float) position / whole; | |
7384 shown = (float) portion / whole; | |
7385 } | |
7386 | |
7387 BLOCK_INPUT; | |
7388 | |
7389 #ifdef USE_MOTIF | |
7390 { | |
7391 int size, value; | |
7392 Boolean arrow1_selected, arrow2_selected; | |
7393 unsigned char flags; | |
7394 XmScrollBarWidget sb; | |
7395 | |
7396 /* Slider size. Must be in the range [1 .. MAX - MIN] where NAX | |
7397 is the scroll bar's maximum and MIN is the scroll bar's minimum | |
7398 value. */ | |
7399 size = shown * XM_SB_RANGE; | |
7400 size = min (size, XM_SB_RANGE); | |
7401 size = max (size, 1); | |
7402 | |
7403 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */ | |
7404 value = top * XM_SB_RANGE; | |
7405 value = min (value, XM_SB_MAX - size); | |
7406 value = max (value, XM_SB_MIN); | |
7407 | |
7408 /* LessTif: Calling XmScrollBarSetValues after an increment or | |
7409 decrement turns off auto-repeat LessTif-internally. This can | |
7410 be seen in ScrollBar.c which resets Arrow1Selected and | |
7411 Arrow2Selected. It also sets internal flags so that LessTif | |
7412 believes the mouse is in the slider. We either have to change | |
7413 our code, or work around that by accessing private data. */ | |
7414 | |
7415 sb = (XmScrollBarWidget) widget; | |
7416 arrow1_selected = sb->scrollBar.arrow1_selected; | |
7417 arrow2_selected = sb->scrollBar.arrow2_selected; | |
7418 flags = sb->scrollBar.flags; | |
7419 | |
7420 if (NILP (bar->dragging)) | |
7421 XmScrollBarSetValues (widget, value, size, 0, 0, False); | |
7422 else if (last_scroll_bar_part == scroll_bar_down_arrow) | |
7423 /* This has the negative side effect that the slider value is | |
7424 not would it would be if we scrolled here using line-wise or | |
7425 page-wise movement. */ | |
7426 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False); | |
7427 else | |
7428 { | |
7429 /* If currently dragging, only update the slider size. | |
7430 This reduces flicker effects. */ | |
7431 int old_value, old_size, increment, page_increment; | |
7432 | |
7433 XmScrollBarGetValues (widget, &old_value, &old_size, | |
7434 &increment, &page_increment); | |
7435 XmScrollBarSetValues (widget, old_value, | |
7436 min (size, XM_SB_RANGE - old_value), | |
7437 0, 0, False); | |
7438 } | |
7439 | |
7440 sb->scrollBar.arrow1_selected = arrow1_selected; | |
7441 sb->scrollBar.arrow2_selected = arrow2_selected; | |
7442 sb->scrollBar.flags = flags; | |
7443 } | |
7444 #elif defined HAVE_XAW3D | |
7445 { | |
7446 /* Restrict to [0 1]. */ | |
7447 top = max (0, min (1, top)); | |
7448 shown = max (0, min (1, shown)); | |
7449 | |
7450 /* If the call to XawScrollbarSetThumb below doesn't seem to work, | |
7451 check that your system's configuration file contains a define | |
7452 for `NARROWPROTO'. See s/freebsd.h for an example. */ | |
7453 if (NILP (bar->dragging)) | |
7454 XawScrollbarSetThumb (widget, top, shown); | |
7455 else | |
7456 { | |
7457 ScrollbarWidget sb = (ScrollbarWidget) widget; | |
7458 int scroll_mode = sb->scrollbar.scroll_mode; | |
7459 | |
7460 sb->scrollbar.scroll_mode = 0; | |
7461 | |
7462 if (last_scroll_bar_part == scroll_bar_down_arrow) | |
7463 XawScrollbarSetThumb (widget, top, 1 - top); | |
7464 else | |
7465 { | |
7466 float old_top; | |
7467 XtVaGetValues (widget, XtNtopOfThumb, &old_top, NULL); | |
7468 XawScrollbarSetThumb (widget, old_top, min (shown, 1 - old_top)); | |
7469 } | |
7470 | |
7471 sb->scrollbar.scroll_mode = scroll_mode; | |
7472 } | |
7473 } | |
7474 #endif /* HAVE_XAW3D */ | |
7475 | |
7476 UNBLOCK_INPUT; | |
7477 } | |
7478 | |
7479 #endif /* USE_TOOLKIT_SCROLL_BARS */ | |
7480 | |
7481 | |
7482 | |
7483 /************************************************************************ | |
7484 Scroll bars, general | |
7485 ************************************************************************/ | |
7486 | |
7487 /* Create a scroll bar and return the scroll bar vector for it. W is | |
7488 the Emacs window on which to create the scroll bar. TOP, LEFT, | |
7489 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the | |
7490 scroll bar. */ | |
7491 | |
2975 static struct scroll_bar * | 7492 static struct scroll_bar * |
2976 x_scroll_bar_create (window, top, left, width, height) | 7493 x_scroll_bar_create (w, top, left, width, height) |
2977 struct window *window; | 7494 struct window *w; |
2978 int top, left, width, height; | 7495 int top, left, width, height; |
2979 { | 7496 { |
2980 FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); | 7497 struct frame *f = XFRAME (w->frame); |
7498 #ifdef USE_X_TOOLKIT | |
7499 Arg av[10]; | |
7500 #endif | |
7501 int ac = 0; | |
7502 Window window; | |
2981 struct scroll_bar *bar | 7503 struct scroll_bar *bar |
2982 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil)); | 7504 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil)); |
2983 | 7505 |
2984 BLOCK_INPUT; | 7506 BLOCK_INPUT; |
2985 | 7507 |
7508 #if USE_TOOLKIT_SCROLL_BARS | |
7509 x_create_toolkit_scroll_bar (f, bar); | |
7510 #else /* not USE_TOOLKIT_SCROLL_BARS */ | |
2986 { | 7511 { |
2987 XSetWindowAttributes a; | 7512 XSetWindowAttributes a; |
2988 unsigned long mask; | 7513 unsigned long mask; |
2989 a.background_pixel = f->output_data.x->background_pixel; | 7514 |
7515 a.background_pixel = f->output_data.x->scroll_bar_background_pixel; | |
7516 if (a.background_pixel == -1) | |
7517 a.background_pixel = f->output_data.x->background_pixel; | |
7518 | |
2990 a.event_mask = (ButtonPressMask | ButtonReleaseMask | 7519 a.event_mask = (ButtonPressMask | ButtonReleaseMask |
2991 | ButtonMotionMask | PointerMotionHintMask | 7520 | ButtonMotionMask | PointerMotionHintMask |
2992 | ExposureMask); | 7521 | ExposureMask); |
2993 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor; | 7522 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor; |
2994 | 7523 |
2995 mask = (CWBackPixel | CWEventMask | CWCursor); | 7524 mask = (CWBackPixel | CWEventMask | CWCursor); |
2996 | 7525 |
2997 #if 0 | 7526 /* Clear the area of W that will serve as a scroll bar. This is |
2998 | 7527 for the case that a window has been split horizontally. In |
2999 ac = 0; | 7528 this case, no clear_frame is generated to reduce flickering. */ |
3000 XtSetArg (al[ac], XtNx, left); ac++; | 7529 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
3001 XtSetArg (al[ac], XtNy, top); ac++; | 7530 left, top, width, |
3002 XtSetArg (al[ac], XtNwidth, width); ac++; | 7531 window_box_height (w), False); |
3003 XtSetArg (al[ac], XtNheight, height); ac++; | 7532 |
3004 XtSetArg (al[ac], XtNborderWidth, 0); ac++; | 7533 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
3005 sb_widget = XtCreateManagedWidget ("box", | 7534 /* Position and size of scroll bar. */ |
3006 boxWidgetClass, | 7535 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, |
3007 f->output_data.x->edit_widget, al, ac); | 7536 top, |
3008 SET_SCROLL_BAR_X_WINDOW | 7537 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, |
3009 (bar, sb_widget->core.window); | 7538 height, |
3010 #endif | 7539 /* Border width, depth, class, and visual. */ |
3011 SET_SCROLL_BAR_X_WINDOW | 7540 0, |
3012 (bar, | 7541 CopyFromParent, |
3013 XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 7542 CopyFromParent, |
3014 | 7543 CopyFromParent, |
3015 /* Position and size of scroll bar. */ | 7544 /* Attributes. */ |
3016 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, top, | 7545 mask, &a); |
3017 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, height, | 7546 SET_SCROLL_BAR_X_WINDOW (bar, window); |
3018 | |
3019 /* Border width, depth, class, and visual. */ | |
3020 0, CopyFromParent, CopyFromParent, CopyFromParent, | |
3021 | |
3022 /* Attributes. */ | |
3023 mask, &a)); | |
3024 } | 7547 } |
3025 | 7548 #endif /* not USE_TOOLKIT_SCROLL_BARS */ |
3026 XSETWINDOW (bar->window, window); | 7549 |
7550 XSETWINDOW (bar->window, w); | |
3027 XSETINT (bar->top, top); | 7551 XSETINT (bar->top, top); |
3028 XSETINT (bar->left, left); | 7552 XSETINT (bar->left, left); |
3029 XSETINT (bar->width, width); | 7553 XSETINT (bar->width, width); |
3030 XSETINT (bar->height, height); | 7554 XSETINT (bar->height, height); |
3031 XSETINT (bar->start, 0); | 7555 XSETINT (bar->start, 0); |
3034 | 7558 |
3035 /* Add bar to its frame's list of scroll bars. */ | 7559 /* Add bar to its frame's list of scroll bars. */ |
3036 bar->next = FRAME_SCROLL_BARS (f); | 7560 bar->next = FRAME_SCROLL_BARS (f); |
3037 bar->prev = Qnil; | 7561 bar->prev = Qnil; |
3038 XSETVECTOR (FRAME_SCROLL_BARS (f), bar); | 7562 XSETVECTOR (FRAME_SCROLL_BARS (f), bar); |
3039 if (! NILP (bar->next)) | 7563 if (!NILP (bar->next)) |
3040 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); | 7564 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); |
3041 | 7565 |
7566 /* Map the window/widget. */ | |
7567 #if USE_TOOLKIT_SCROLL_BARS | |
7568 XtMapWidget (SCROLL_BAR_X_WIDGET (bar)); | |
7569 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar), | |
7570 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, | |
7571 top, | |
7572 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, | |
7573 height, 0); | |
7574 #else /* not USE_TOOLKIT_SCROLL_BARS */ | |
3042 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar)); | 7575 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar)); |
7576 #endif /* not USE_TOOLKIT_SCROLL_BARS */ | |
3043 | 7577 |
3044 UNBLOCK_INPUT; | 7578 UNBLOCK_INPUT; |
3045 | |
3046 return bar; | 7579 return bar; |
3047 } | 7580 } |
3048 | 7581 |
7582 | |
3049 /* Draw BAR's handle in the proper position. | 7583 /* Draw BAR's handle in the proper position. |
7584 | |
3050 If the handle is already drawn from START to END, don't bother | 7585 If the handle is already drawn from START to END, don't bother |
3051 redrawing it, unless REBUILD is non-zero; in that case, always | 7586 redrawing it, unless REBUILD is non-zero; in that case, always |
3052 redraw it. (REBUILD is handy for drawing the handle after expose | 7587 redraw it. (REBUILD is handy for drawing the handle after expose |
3053 events.) | 7588 events.) |
3054 | 7589 |
3055 Normally, we want to constrain the start and end of the handle to | 7590 Normally, we want to constrain the start and end of the handle to |
3056 fit inside its rectangle, but if the user is dragging the scroll bar | 7591 fit inside its rectangle, but if the user is dragging the scroll |
3057 handle, we want to let them drag it down all the way, so that the | 7592 bar handle, we want to let them drag it down all the way, so that |
3058 bar's top is as far down as it goes; otherwise, there's no way to | 7593 the bar's top is as far down as it goes; otherwise, there's no way |
3059 move to the very end of the buffer. */ | 7594 to move to the very end of the buffer. */ |
7595 | |
3060 static void | 7596 static void |
3061 x_scroll_bar_set_handle (bar, start, end, rebuild) | 7597 x_scroll_bar_set_handle (bar, start, end, rebuild) |
3062 struct scroll_bar *bar; | 7598 struct scroll_bar *bar; |
3063 int start, end; | 7599 int start, end; |
3064 int rebuild; | 7600 int rebuild; |
3065 { | 7601 { |
7602 #ifndef USE_TOOLKIT_SCROLL_BARS | |
3066 int dragging = ! NILP (bar->dragging); | 7603 int dragging = ! NILP (bar->dragging); |
3067 Window w = SCROLL_BAR_X_WINDOW (bar); | 7604 Window w = SCROLL_BAR_X_WINDOW (bar); |
3068 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | 7605 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); |
3069 GC gc = f->output_data.x->normal_gc; | 7606 GC gc = f->output_data.x->normal_gc; |
3070 | 7607 |
3120 VERTICAL_SCROLL_BAR_LEFT_BORDER, | 7657 VERTICAL_SCROLL_BAR_LEFT_BORDER, |
3121 VERTICAL_SCROLL_BAR_TOP_BORDER, | 7658 VERTICAL_SCROLL_BAR_TOP_BORDER, |
3122 inside_width, start, | 7659 inside_width, start, |
3123 False); | 7660 False); |
3124 | 7661 |
7662 /* Change to proper foreground color if one is specified. */ | |
7663 if (f->output_data.x->scroll_bar_foreground_pixel != -1) | |
7664 XSetForeground (FRAME_X_DISPLAY (f), gc, | |
7665 f->output_data.x->scroll_bar_foreground_pixel); | |
7666 | |
3125 /* Draw the handle itself. */ | 7667 /* Draw the handle itself. */ |
3126 XFillRectangle (FRAME_X_DISPLAY (f), w, gc, | 7668 XFillRectangle (FRAME_X_DISPLAY (f), w, gc, |
3127 | 7669 |
3128 /* x, y, width, height */ | 7670 /* x, y, width, height */ |
3129 VERTICAL_SCROLL_BAR_LEFT_BORDER, | 7671 VERTICAL_SCROLL_BAR_LEFT_BORDER, |
3130 VERTICAL_SCROLL_BAR_TOP_BORDER + start, | 7672 VERTICAL_SCROLL_BAR_TOP_BORDER + start, |
3131 inside_width, end - start); | 7673 inside_width, end - start); |
3132 | 7674 |
7675 /* Restore the foreground color of the GC if we changed it above. */ | |
7676 if (f->output_data.x->scroll_bar_foreground_pixel != -1) | |
7677 XSetForeground (FRAME_X_DISPLAY (f), gc, | |
7678 f->output_data.x->foreground_pixel); | |
3133 | 7679 |
3134 /* Draw the empty space below the handle. Note that we can't | 7680 /* Draw the empty space below the handle. Note that we can't |
3135 clear zero-height areas; that means "clear to end of window." */ | 7681 clear zero-height areas; that means "clear to end of window." */ |
3136 if (end < inside_height) | 7682 if (end < inside_height) |
3137 XClearArea (FRAME_X_DISPLAY (f), w, | 7683 XClearArea (FRAME_X_DISPLAY (f), w, |
3143 False); | 7689 False); |
3144 | 7690 |
3145 } | 7691 } |
3146 | 7692 |
3147 UNBLOCK_INPUT; | 7693 UNBLOCK_INPUT; |
3148 } | 7694 #endif /* not USE_TOOLKIT_SCROLL_BARS */ |
3149 | 7695 } |
3150 /* Move a scroll bar around on the screen, to accommodate changing | 7696 |
3151 window configurations. */ | 7697 |
3152 static void | 7698 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to |
3153 x_scroll_bar_move (bar, top, left, width, height) | 7699 nil. */ |
3154 struct scroll_bar *bar; | 7700 |
3155 int top, left, width, height; | |
3156 { | |
3157 Window w = SCROLL_BAR_X_WINDOW (bar); | |
3158 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | |
3159 | |
3160 BLOCK_INPUT; | |
3161 | |
3162 { | |
3163 XWindowChanges wc; | |
3164 unsigned int mask = 0; | |
3165 | |
3166 wc.x = left + VERTICAL_SCROLL_BAR_WIDTH_TRIM; | |
3167 wc.y = top; | |
3168 | |
3169 wc.width = width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2; | |
3170 wc.height = height; | |
3171 | |
3172 if (left != XINT (bar->left)) mask |= CWX; | |
3173 if (top != XINT (bar->top)) mask |= CWY; | |
3174 if (width != XINT (bar->width)) mask |= CWWidth; | |
3175 if (height != XINT (bar->height)) mask |= CWHeight; | |
3176 | |
3177 if (mask) | |
3178 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar), | |
3179 mask, &wc); | |
3180 } | |
3181 | |
3182 XSETINT (bar->left, left); | |
3183 XSETINT (bar->top, top); | |
3184 XSETINT (bar->width, width); | |
3185 XSETINT (bar->height, height); | |
3186 | |
3187 UNBLOCK_INPUT; | |
3188 } | |
3189 | |
3190 /* Destroy the X window for BAR, and set its Emacs window's scroll bar | |
3191 to nil. */ | |
3192 static void | 7701 static void |
3193 x_scroll_bar_remove (bar) | 7702 x_scroll_bar_remove (bar) |
3194 struct scroll_bar *bar; | 7703 struct scroll_bar *bar; |
3195 { | 7704 { |
3196 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | 7705 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); |
3197 | 7706 |
3198 BLOCK_INPUT; | 7707 BLOCK_INPUT; |
3199 | 7708 |
3200 /* Destroy the window. */ | 7709 #if USE_TOOLKIT_SCROLL_BARS |
7710 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar)); | |
7711 #else /* not USE_TOOLKIT_SCROLL_BARS */ | |
3201 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar)); | 7712 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar)); |
3202 | 7713 #endif /* not USE_TOOLKIT_SCROLL_BARS */ |
7714 | |
3203 /* Disassociate this scroll bar from its window. */ | 7715 /* Disassociate this scroll bar from its window. */ |
3204 XWINDOW (bar->window)->vertical_scroll_bar = Qnil; | 7716 XWINDOW (bar->window)->vertical_scroll_bar = Qnil; |
3205 | 7717 |
3206 UNBLOCK_INPUT; | 7718 UNBLOCK_INPUT; |
3207 } | 7719 } |
7720 | |
3208 | 7721 |
3209 /* Set the handle of the vertical scroll bar for WINDOW to indicate | 7722 /* Set the handle of the vertical scroll bar for WINDOW to indicate |
3210 that we are displaying PORTION characters out of a total of WHOLE | 7723 that we are displaying PORTION characters out of a total of WHOLE |
3211 characters, starting at POSITION. If WINDOW has no scroll bar, | 7724 characters, starting at POSITION. If WINDOW has no scroll bar, |
3212 create one. */ | 7725 create one. */ |
7726 | |
3213 static void | 7727 static void |
3214 XTset_vertical_scroll_bar (window, portion, whole, position) | 7728 XTset_vertical_scroll_bar (w, portion, whole, position) |
3215 struct window *window; | 7729 struct window *w; |
3216 int portion, whole, position; | 7730 int portion, whole, position; |
3217 { | 7731 { |
3218 FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); | 7732 struct frame *f = XFRAME (w->frame); |
3219 int top = XINT (window->top); | |
3220 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window); | |
3221 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window); | |
3222 | |
3223 /* Where should this scroll bar be, pixelwise? */ | |
3224 int pixel_top = CHAR_TO_PIXEL_ROW (f, top); | |
3225 int pixel_left = CHAR_TO_PIXEL_COL (f, left); | |
3226 int pixel_width | |
3227 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0 | |
3228 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f) | |
3229 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font))); | |
3230 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height); | |
3231 | |
3232 struct scroll_bar *bar; | 7733 struct scroll_bar *bar; |
7734 int pixel_top, pixel_left, pixel_width, pixel_height; | |
7735 int window_x, window_y, window_width, window_height; | |
7736 int scroll_bar_area_width; | |
7737 | |
7738 window_box (w, -1, &window_x, &window_y, &window_width, &window_height); | |
7739 | |
7740 /* Where should this scroll bar be, pixel-wise? */ | |
7741 pixel_top = window_y; | |
7742 pixel_height = window_height; | |
7743 | |
7744 /* The width of the scroll bar itself. */ | |
7745 pixel_width = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0 | |
7746 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f) | |
7747 : (FRAME_SCROLL_BAR_COLS (f) | |
7748 * FONT_WIDTH (FRAME_FONT (f)))); | |
7749 | |
7750 /* The width on the screen reserved for the scroll bar plus maybe | |
7751 some empty room at both sides of the scroll bar. */ | |
7752 scroll_bar_area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f); | |
7753 | |
7754 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) | |
7755 pixel_left = (window_x | |
7756 + window_width | |
7757 + FRAME_FLAGS_AREA_WIDTH (f) | |
7758 + scroll_bar_area_width | |
7759 - pixel_width + 1); | |
7760 else | |
7761 pixel_left = (window_x | |
7762 - FRAME_FLAGS_AREA_WIDTH (f) | |
7763 - scroll_bar_area_width); | |
3233 | 7764 |
3234 /* Does the scroll bar exist yet? */ | 7765 /* Does the scroll bar exist yet? */ |
3235 if (NILP (window->vertical_scroll_bar)) | 7766 if (NILP (w->vertical_scroll_bar)) |
3236 bar = x_scroll_bar_create (window, | 7767 bar = x_scroll_bar_create (w, pixel_top, pixel_left, pixel_width, |
3237 pixel_top, pixel_left, | 7768 pixel_height); |
3238 pixel_width, pixel_height); | |
3239 else | 7769 else |
3240 { | 7770 { |
3241 /* It may just need to be moved and resized. */ | 7771 /* It may just need to be moved and resized. */ |
3242 bar = XSCROLL_BAR (window->vertical_scroll_bar); | 7772 unsigned int mask = 0; |
3243 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height); | 7773 |
3244 } | 7774 bar = XSCROLL_BAR (w->vertical_scroll_bar); |
3245 | 7775 |
7776 BLOCK_INPUT; | |
7777 | |
7778 if (pixel_left != XINT (bar->left)) | |
7779 mask |= CWX; | |
7780 if (pixel_top != XINT (bar->top)) | |
7781 mask |= CWY; | |
7782 if (pixel_width != XINT (bar->width)) | |
7783 mask |= CWWidth; | |
7784 if (pixel_height != XINT (bar->height)) | |
7785 mask |= CWHeight; | |
7786 | |
7787 #ifdef USE_TOOLKIT_SCROLL_BARS | |
7788 | |
7789 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) | |
7790 { | |
7791 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
7792 pixel_left + pixel_width - scroll_bar_area_width, | |
7793 pixel_top, | |
7794 (scroll_bar_area_width | |
7795 - pixel_width | |
7796 + VERTICAL_SCROLL_BAR_WIDTH_TRIM), | |
7797 pixel_height, False); | |
7798 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
7799 (pixel_left | |
7800 + pixel_width | |
7801 - VERTICAL_SCROLL_BAR_WIDTH_TRIM), | |
7802 pixel_top, | |
7803 VERTICAL_SCROLL_BAR_WIDTH_TRIM, | |
7804 pixel_height, False); | |
7805 } | |
7806 else | |
7807 { | |
7808 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
7809 pixel_left, pixel_top, | |
7810 VERTICAL_SCROLL_BAR_WIDTH_TRIM, pixel_height, False); | |
7811 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
7812 (pixel_left | |
7813 + pixel_width | |
7814 - VERTICAL_SCROLL_BAR_WIDTH_TRIM), | |
7815 pixel_top, | |
7816 (scroll_bar_area_width | |
7817 - pixel_width | |
7818 + VERTICAL_SCROLL_BAR_WIDTH_TRIM), | |
7819 pixel_height, False); | |
7820 } | |
7821 | |
7822 /* Move/size the scroll bar widget. */ | |
7823 if (mask) | |
7824 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar), | |
7825 pixel_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, | |
7826 pixel_top, | |
7827 pixel_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, | |
7828 pixel_height, 0); | |
7829 | |
7830 #else /* not USE_TOOLKIT_SCROLL_BARS */ | |
7831 | |
7832 /* Clear areas not covered by the scroll bar. This makes sure a | |
7833 previous mode line display is cleared after C-x 2 C-x 1, for | |
7834 example. Non-toolkit scroll bars are as wide as the area | |
7835 reserved for scroll bars - trim at both sides. */ | |
7836 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
7837 pixel_left, pixel_top, VERTICAL_SCROLL_BAR_WIDTH_TRIM, | |
7838 pixel_height, False); | |
7839 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
7840 (pixel_left | |
7841 + pixel_width | |
7842 - VERTICAL_SCROLL_BAR_WIDTH_TRIM), | |
7843 pixel_top, | |
7844 VERTICAL_SCROLL_BAR_WIDTH_TRIM, | |
7845 pixel_height, False); | |
7846 | |
7847 /* Move/size the scroll bar window. */ | |
7848 if (mask) | |
7849 { | |
7850 XWindowChanges wc; | |
7851 | |
7852 wc.x = pixel_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM; | |
7853 wc.y = pixel_top; | |
7854 wc.width = pixel_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2; | |
7855 wc.height = pixel_height; | |
7856 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar), | |
7857 mask, &wc); | |
7858 } | |
7859 | |
7860 #endif /* not USE_TOOLKIT_SCROLL_BARS */ | |
7861 | |
7862 /* Remember new settings. */ | |
7863 XSETINT (bar->left, pixel_left); | |
7864 XSETINT (bar->top, pixel_top); | |
7865 XSETINT (bar->width, pixel_width); | |
7866 XSETINT (bar->height, pixel_height); | |
7867 | |
7868 UNBLOCK_INPUT; | |
7869 } | |
7870 | |
7871 #if USE_TOOLKIT_SCROLL_BARS | |
7872 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole); | |
7873 #else /* not USE_TOOLKIT_SCROLL_BARS */ | |
3246 /* Set the scroll bar's current state, unless we're currently being | 7874 /* Set the scroll bar's current state, unless we're currently being |
3247 dragged. */ | 7875 dragged. */ |
3248 if (NILP (bar->dragging)) | 7876 if (NILP (bar->dragging)) |
3249 { | 7877 { |
3250 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, pixel_height); | 7878 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, pixel_height); |
3253 x_scroll_bar_set_handle (bar, 0, top_range, 0); | 7881 x_scroll_bar_set_handle (bar, 0, top_range, 0); |
3254 else | 7882 else |
3255 { | 7883 { |
3256 int start = ((double) position * top_range) / whole; | 7884 int start = ((double) position * top_range) / whole; |
3257 int end = ((double) (position + portion) * top_range) / whole; | 7885 int end = ((double) (position + portion) * top_range) / whole; |
3258 | |
3259 x_scroll_bar_set_handle (bar, start, end, 0); | 7886 x_scroll_bar_set_handle (bar, start, end, 0); |
3260 } | 7887 } |
3261 } | 7888 } |
3262 | 7889 #endif /* not USE_TOOLKIT_SCROLL_BARS */ |
3263 XSETVECTOR (window->vertical_scroll_bar, bar); | 7890 |
7891 XSETVECTOR (w->vertical_scroll_bar, bar); | |
3264 } | 7892 } |
3265 | 7893 |
3266 | 7894 |
3267 /* The following three hooks are used when we're doing a thorough | 7895 /* The following three hooks are used when we're doing a thorough |
3268 redisplay of the frame. We don't explicitly know which scroll bars | 7896 redisplay of the frame. We don't explicitly know which scroll bars |
3272 that *all* scroll bars are to be removed, and then save a scroll bar | 7900 that *all* scroll bars are to be removed, and then save a scroll bar |
3273 from the fiery pit when we actually redisplay its window. */ | 7901 from the fiery pit when we actually redisplay its window. */ |
3274 | 7902 |
3275 /* Arrange for all scroll bars on FRAME to be removed at the next call | 7903 /* Arrange for all scroll bars on FRAME to be removed at the next call |
3276 to `*judge_scroll_bars_hook'. A scroll bar may be spared if | 7904 to `*judge_scroll_bars_hook'. A scroll bar may be spared if |
3277 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */ | 7905 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */ |
7906 | |
3278 static void | 7907 static void |
3279 XTcondemn_scroll_bars (frame) | 7908 XTcondemn_scroll_bars (frame) |
3280 FRAME_PTR frame; | 7909 FRAME_PTR frame; |
3281 { | 7910 { |
3282 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */ | 7911 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */ |
3291 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar; | 7920 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar; |
3292 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar; | 7921 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar; |
3293 } | 7922 } |
3294 } | 7923 } |
3295 | 7924 |
3296 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle. | 7925 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle. |
3297 Note that WINDOW isn't necessarily condemned at all. */ | 7926 Note that WINDOW isn't necessarily condemned at all. */ |
3298 static void | 7927 static void |
3299 XTredeem_scroll_bar (window) | 7928 XTredeem_scroll_bar (window) |
3300 struct window *window; | 7929 struct window *window; |
3301 { | 7930 { |
3340 } | 7969 } |
3341 } | 7970 } |
3342 | 7971 |
3343 /* Remove all scroll bars on FRAME that haven't been saved since the | 7972 /* Remove all scroll bars on FRAME that haven't been saved since the |
3344 last call to `*condemn_scroll_bars_hook'. */ | 7973 last call to `*condemn_scroll_bars_hook'. */ |
7974 | |
3345 static void | 7975 static void |
3346 XTjudge_scroll_bars (f) | 7976 XTjudge_scroll_bars (f) |
3347 FRAME_PTR f; | 7977 FRAME_PTR f; |
3348 { | 7978 { |
3349 Lisp_Object bar, next; | 7979 Lisp_Object bar, next; |
3367 /* Now there should be no references to the condemned scroll bars, | 7997 /* Now there should be no references to the condemned scroll bars, |
3368 and they should get garbage-collected. */ | 7998 and they should get garbage-collected. */ |
3369 } | 7999 } |
3370 | 8000 |
3371 | 8001 |
3372 /* Handle an Expose or GraphicsExpose event on a scroll bar. | 8002 /* Handle an Expose or GraphicsExpose event on a scroll bar. This |
8003 is a no-op when using toolkit scroll bars. | |
3373 | 8004 |
3374 This may be called from a signal handler, so we have to ignore GC | 8005 This may be called from a signal handler, so we have to ignore GC |
3375 mark bits. */ | 8006 mark bits. */ |
8007 | |
3376 static void | 8008 static void |
3377 x_scroll_bar_expose (bar, event) | 8009 x_scroll_bar_expose (bar, event) |
3378 struct scroll_bar *bar; | 8010 struct scroll_bar *bar; |
3379 XEvent *event; | 8011 XEvent *event; |
3380 { | 8012 { |
8013 #ifndef USE_TOOLKIT_SCROLL_BARS | |
8014 | |
3381 Window w = SCROLL_BAR_X_WINDOW (bar); | 8015 Window w = SCROLL_BAR_X_WINDOW (bar); |
3382 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | 8016 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); |
3383 GC gc = f->output_data.x->normal_gc; | 8017 GC gc = f->output_data.x->normal_gc; |
3384 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM; | 8018 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM; |
3385 | 8019 |
3386 BLOCK_INPUT; | 8020 BLOCK_INPUT; |
3387 | 8021 |
3388 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1); | 8022 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1); |
3389 | 8023 |
3390 /* Draw a one-pixel border just inside the edges of the scroll bar. */ | 8024 /* Draw a one-pixel border just inside the edges of the scroll bar. */ |
3391 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc, | 8025 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc, |
3392 | 8026 |
3393 /* x, y, width, height */ | 8027 /* x, y, width, height */ |
3394 0, 0, | 8028 0, 0, |
3395 XINT (bar->width) - 1 - width_trim - width_trim, | 8029 XINT (bar->width) - 1 - width_trim - width_trim, |
3396 XINT (bar->height) - 1); | 8030 XINT (bar->height) - 1); |
3397 | 8031 |
3398 UNBLOCK_INPUT; | 8032 UNBLOCK_INPUT; |
8033 | |
8034 #endif /* not USE_TOOLKIT_SCROLL_BARS */ | |
3399 } | 8035 } |
3400 | 8036 |
3401 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind | 8037 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind |
3402 is set to something other than no_event, it is enqueued. | 8038 is set to something other than no_event, it is enqueued. |
3403 | 8039 |
3404 This may be called from a signal handler, so we have to ignore GC | 8040 This may be called from a signal handler, so we have to ignore GC |
3405 mark bits. */ | 8041 mark bits. */ |
8042 | |
3406 static void | 8043 static void |
3407 x_scroll_bar_handle_click (bar, event, emacs_event) | 8044 x_scroll_bar_handle_click (bar, event, emacs_event) |
3408 struct scroll_bar *bar; | 8045 struct scroll_bar *bar; |
3409 XEvent *event; | 8046 XEvent *event; |
3410 struct input_event *emacs_event; | 8047 struct input_event *emacs_event; |
3422 ? up_modifier | 8059 ? up_modifier |
3423 : down_modifier)); | 8060 : down_modifier)); |
3424 emacs_event->frame_or_window = bar->window; | 8061 emacs_event->frame_or_window = bar->window; |
3425 emacs_event->timestamp = event->xbutton.time; | 8062 emacs_event->timestamp = event->xbutton.time; |
3426 { | 8063 { |
8064 #if 0 | |
3427 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | 8065 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); |
3428 int internal_height | 8066 int internal_height |
3429 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height)); | 8067 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height)); |
8068 #endif | |
3430 int top_range | 8069 int top_range |
3431 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)); | 8070 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)); |
3432 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER; | 8071 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER; |
3433 | 8072 |
3434 if (y < 0) y = 0; | 8073 if (y < 0) y = 0; |
3481 | 8120 |
3482 /* Handle some mouse motion while someone is dragging the scroll bar. | 8121 /* Handle some mouse motion while someone is dragging the scroll bar. |
3483 | 8122 |
3484 This may be called from a signal handler, so we have to ignore GC | 8123 This may be called from a signal handler, so we have to ignore GC |
3485 mark bits. */ | 8124 mark bits. */ |
8125 | |
3486 static void | 8126 static void |
3487 x_scroll_bar_note_movement (bar, event) | 8127 x_scroll_bar_note_movement (bar, event) |
3488 struct scroll_bar *bar; | 8128 struct scroll_bar *bar; |
3489 XEvent *event; | 8129 XEvent *event; |
3490 { | 8130 { |
3510 } | 8150 } |
3511 } | 8151 } |
3512 | 8152 |
3513 /* Return information to the user about the current position of the mouse | 8153 /* Return information to the user about the current position of the mouse |
3514 on the scroll bar. */ | 8154 on the scroll bar. */ |
8155 | |
3515 static void | 8156 static void |
3516 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time) | 8157 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time) |
3517 FRAME_PTR *fp; | 8158 FRAME_PTR *fp; |
3518 Lisp_Object *bar_window; | 8159 Lisp_Object *bar_window; |
3519 enum scroll_bar_part *part; | 8160 enum scroll_bar_part *part; |
3544 /* Mouse buttons and modifier keys. */ | 8185 /* Mouse buttons and modifier keys. */ |
3545 &dummy_mask)) | 8186 &dummy_mask)) |
3546 ; | 8187 ; |
3547 else | 8188 else |
3548 { | 8189 { |
8190 #if 0 | |
3549 int inside_height | 8191 int inside_height |
3550 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height)); | 8192 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height)); |
8193 #endif | |
3551 int top_range | 8194 int top_range |
3552 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)); | 8195 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)); |
3553 | 8196 |
3554 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER; | 8197 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER; |
3555 | 8198 |
3593 | 8236 |
3594 void | 8237 void |
3595 x_scroll_bar_clear (f) | 8238 x_scroll_bar_clear (f) |
3596 FRAME_PTR f; | 8239 FRAME_PTR f; |
3597 { | 8240 { |
8241 #ifndef USE_TOOLKIT_SCROLL_BARS | |
3598 Lisp_Object bar; | 8242 Lisp_Object bar; |
3599 | 8243 |
3600 /* We can have scroll bars even if this is 0, | 8244 /* We can have scroll bars even if this is 0, |
3601 if we just turned off scroll bar mode. | 8245 if we just turned off scroll bar mode. |
3602 But in that case we should not clear them. */ | 8246 But in that case we should not clear them. */ |
3603 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) | 8247 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)) |
3604 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar); | 8248 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar); |
3605 bar = XSCROLL_BAR (bar)->next) | 8249 bar = XSCROLL_BAR (bar)->next) |
3606 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)), | 8250 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)), |
3607 0, 0, 0, 0, True); | 8251 0, 0, 0, 0, True); |
3608 } | 8252 #endif /* not USE_TOOLKIT_SCROLL_BARS */ |
3609 | 8253 } |
3610 /* This processes Expose events from the menubar specific X event | 8254 |
8255 /* This processes Expose events from the menu-bar specific X event | |
3611 loop in xmenu.c. This allows to redisplay the frame if necessary | 8256 loop in xmenu.c. This allows to redisplay the frame if necessary |
3612 when handling menubar or popup items. */ | 8257 when handling menu-bar or pop-up items. */ |
3613 | 8258 |
3614 void | 8259 int |
3615 process_expose_from_menu (event) | 8260 process_expose_from_menu (event) |
3616 XEvent event; | 8261 XEvent event; |
3617 { | 8262 { |
3618 FRAME_PTR f; | 8263 FRAME_PTR f; |
3619 struct x_display_info *dpyinfo; | 8264 struct x_display_info *dpyinfo; |
8265 int frame_exposed_p = 0; | |
3620 | 8266 |
3621 BLOCK_INPUT; | 8267 BLOCK_INPUT; |
3622 | 8268 |
3623 dpyinfo = x_display_info_for_display (event.xexpose.display); | 8269 dpyinfo = x_display_info_for_display (event.xexpose.display); |
3624 f = x_window_to_frame (dpyinfo, event.xexpose.window); | 8270 f = x_window_to_frame (dpyinfo, event.xexpose.window); |
3631 f->output_data.x->has_been_visible = 1; | 8277 f->output_data.x->has_been_visible = 1; |
3632 SET_FRAME_GARBAGED (f); | 8278 SET_FRAME_GARBAGED (f); |
3633 } | 8279 } |
3634 else | 8280 else |
3635 { | 8281 { |
3636 dumprectangle (x_window_to_frame (dpyinfo, event.xexpose.window), | 8282 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window), |
3637 event.xexpose.x, event.xexpose.y, | 8283 event.xexpose.x, event.xexpose.y, |
3638 event.xexpose.width, event.xexpose.height); | 8284 event.xexpose.width, event.xexpose.height); |
8285 frame_exposed_p = 1; | |
3639 } | 8286 } |
3640 } | 8287 } |
3641 else | 8288 else |
3642 { | 8289 { |
3643 struct scroll_bar *bar | 8290 struct scroll_bar *bar |
3646 if (bar) | 8293 if (bar) |
3647 x_scroll_bar_expose (bar, &event); | 8294 x_scroll_bar_expose (bar, &event); |
3648 } | 8295 } |
3649 | 8296 |
3650 UNBLOCK_INPUT; | 8297 UNBLOCK_INPUT; |
8298 return frame_exposed_p; | |
3651 } | 8299 } |
3652 | 8300 |
3653 /* Define a queue to save up SelectionRequest events for later handling. */ | 8301 /* Define a queue to save up SelectionRequest events for later handling. */ |
3654 | 8302 |
3655 struct selection_event_queue | 8303 struct selection_event_queue |
3659 }; | 8307 }; |
3660 | 8308 |
3661 static struct selection_event_queue *queue; | 8309 static struct selection_event_queue *queue; |
3662 | 8310 |
3663 /* Nonzero means queue up certain events--don't process them yet. */ | 8311 /* Nonzero means queue up certain events--don't process them yet. */ |
8312 | |
3664 static int x_queue_selection_requests; | 8313 static int x_queue_selection_requests; |
3665 | 8314 |
3666 /* Queue up an X event *EVENT, to be processed later. */ | 8315 /* Queue up an X event *EVENT, to be processed later. */ |
3667 | 8316 |
3668 static void | 8317 static void |
3669 x_queue_event (f, event) | 8318 x_queue_event (f, event) |
3670 FRAME_PTR f; | 8319 FRAME_PTR f; |
3671 XEvent *event; | 8320 XEvent *event; |
3672 { | 8321 { |
3673 struct selection_event_queue *queue_tmp | 8322 struct selection_event_queue *queue_tmp |
3674 = (struct selection_event_queue *) malloc (sizeof (struct selection_event_queue)); | 8323 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue)); |
3675 | 8324 |
3676 if (queue_tmp != NULL) | 8325 if (queue_tmp != NULL) |
3677 { | 8326 { |
3678 queue_tmp->event = *event; | 8327 queue_tmp->event = *event; |
3679 queue_tmp->next = queue; | 8328 queue_tmp->next = queue; |
3691 while (queue != NULL) | 8340 while (queue != NULL) |
3692 { | 8341 { |
3693 struct selection_event_queue *queue_tmp = queue; | 8342 struct selection_event_queue *queue_tmp = queue; |
3694 XPutBackEvent (display, &queue_tmp->event); | 8343 XPutBackEvent (display, &queue_tmp->event); |
3695 queue = queue_tmp->next; | 8344 queue = queue_tmp->next; |
3696 free ((char *)queue_tmp); | 8345 xfree ((char *)queue_tmp); |
3697 } | 8346 } |
3698 } | 8347 } |
3699 | 8348 |
3700 /* Start queuing SelectionRequest events. */ | 8349 /* Start queuing SelectionRequest events. */ |
3701 | 8350 |
3716 x_unqueue_events (display); | 8365 x_unqueue_events (display); |
3717 } | 8366 } |
3718 | 8367 |
3719 /* The main X event-reading loop - XTread_socket. */ | 8368 /* The main X event-reading loop - XTread_socket. */ |
3720 | 8369 |
3721 /* Timestamp of enter window event. This is only used by XTread_socket, | 8370 /* Time stamp of enter window event. This is only used by XTread_socket, |
3722 but we have to put it out here, since static variables within functions | 8371 but we have to put it out here, since static variables within functions |
3723 sometimes don't work. */ | 8372 sometimes don't work. */ |
8373 | |
3724 static Time enter_timestamp; | 8374 static Time enter_timestamp; |
3725 | 8375 |
3726 /* This holds the state XLookupString needs to implement dead keys | 8376 /* This holds the state XLookupString needs to implement dead keys |
3727 and other tricks known as "compose processing". _X Window System_ | 8377 and other tricks known as "compose processing". _X Window System_ |
3728 says that a portable program can't use this, but Stephen Gildea assures | 8378 says that a portable program can't use this, but Stephen Gildea assures |
3729 me that letting the compiler initialize it to zeros will work okay. | 8379 me that letting the compiler initialize it to zeros will work okay. |
3730 | 8380 |
3731 This must be defined outside of XTread_socket, for the same reasons | 8381 This must be defined outside of XTread_socket, for the same reasons |
3732 given for enter_timestamp, above. */ | 8382 given for enter_time stamp, above. */ |
8383 | |
3733 static XComposeStatus compose_status; | 8384 static XComposeStatus compose_status; |
3734 | 8385 |
3735 /* Record the last 100 characters stored | 8386 /* Record the last 100 characters stored |
3736 to help debug the loss-of-chars-during-GC problem. */ | 8387 to help debug the loss-of-chars-during-GC problem. */ |
8388 | |
3737 static int temp_index; | 8389 static int temp_index; |
3738 static short temp_buffer[100]; | 8390 static short temp_buffer[100]; |
3739 | 8391 |
3740 /* Set this to nonzero to fake an "X I/O error" | 8392 /* Set this to nonzero to fake an "X I/O error" |
3741 on a particular display. */ | 8393 on a particular display. */ |
8394 | |
3742 struct x_display_info *XTread_socket_fake_io_error; | 8395 struct x_display_info *XTread_socket_fake_io_error; |
3743 | 8396 |
3744 /* When we find no input here, we occasionally do a no-op command | 8397 /* When we find no input here, we occasionally do a no-op command |
3745 to verify that the X server is still running and we can still talk with it. | 8398 to verify that the X server is still running and we can still talk with it. |
3746 We try all the open displays, one by one. | 8399 We try all the open displays, one by one. |
3747 This variable is used for cycling thru the displays. */ | 8400 This variable is used for cycling thru the displays. */ |
8401 | |
3748 static struct x_display_info *next_noop_dpyinfo; | 8402 static struct x_display_info *next_noop_dpyinfo; |
3749 | 8403 |
3750 #define SET_SAVED_MENU_EVENT(size) { \ | 8404 #define SET_SAVED_MENU_EVENT(size) \ |
3751 if (f->output_data.x->saved_menu_event == 0) \ | 8405 do \ |
3752 f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); \ | 8406 { \ |
3753 bcopy (&event, f->output_data.x->saved_menu_event, size); \ | 8407 if (f->output_data.x->saved_menu_event == 0) \ |
3754 if (numchars >= 1) \ | 8408 f->output_data.x->saved_menu_event \ |
3755 { \ | 8409 = (XEvent *) xmalloc (sizeof (XEvent)); \ |
3756 bufp->kind = menu_bar_activate_event; \ | 8410 bcopy (&event, f->output_data.x->saved_menu_event, size); \ |
3757 XSETFRAME (bufp->frame_or_window, f); \ | 8411 if (numchars >= 1) \ |
3758 bufp++; \ | 8412 { \ |
3759 count++; \ | 8413 bufp->kind = menu_bar_activate_event; \ |
3760 numchars--; \ | 8414 XSETFRAME (bufp->frame_or_window, f); \ |
3761 } \ | 8415 bufp++; \ |
3762 } | 8416 count++; \ |
8417 numchars--; \ | |
8418 } \ | |
8419 } \ | |
8420 while (0) | |
8421 | |
3763 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent)) | 8422 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent)) |
3764 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent)) | 8423 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent)) |
3765 | 8424 |
3766 /* Read events coming from the X server. | 8425 /* Read events coming from the X server. |
3767 This routine is called by the SIGIO handler. | 8426 This routine is called by the SIGIO handler. |
3768 We return as soon as there are no more events to be read. | 8427 We return as soon as there are no more events to be read. |
3769 | 8428 |
3781 /* register */ int numchars; | 8440 /* register */ int numchars; |
3782 int expected; | 8441 int expected; |
3783 { | 8442 { |
3784 int count = 0; | 8443 int count = 0; |
3785 int nbytes = 0; | 8444 int nbytes = 0; |
3786 int mask; | |
3787 int items_pending; /* How many items are in the X queue. */ | |
3788 XEvent event; | 8445 XEvent event; |
3789 struct frame *f; | 8446 struct frame *f; |
3790 int event_found = 0; | 8447 int event_found = 0; |
3791 int prefix; | |
3792 Lisp_Object part; | |
3793 struct x_display_info *dpyinfo; | 8448 struct x_display_info *dpyinfo; |
3794 #ifdef HAVE_X_I18N | 8449 #ifdef HAVE_X_I18N |
3795 Status status_return; | 8450 Status status_return; |
3796 #endif | 8451 #endif |
3797 | 8452 |
3806 | 8461 |
3807 /* So people can tell when we have read the available input. */ | 8462 /* So people can tell when we have read the available input. */ |
3808 input_signal_count++; | 8463 input_signal_count++; |
3809 | 8464 |
3810 if (numchars <= 0) | 8465 if (numchars <= 0) |
3811 abort (); /* Don't think this happens. */ | 8466 abort (); /* Don't think this happens. */ |
3812 | 8467 |
3813 /* Find the display we are supposed to read input for. | 8468 /* Find the display we are supposed to read input for. |
3814 It's the one communicating on descriptor SD. */ | 8469 It's the one communicating on descriptor SD. */ |
3815 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) | 8470 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) |
3816 { | 8471 { |
3817 #if 0 /* This ought to be unnecessary; let's verify it. */ | 8472 #if 0 /* This ought to be unnecessary; let's verify it. */ |
3818 #ifdef FIOSNBIO | 8473 #ifdef FIOSNBIO |
3819 /* If available, Xlib uses FIOSNBIO to make the socket | 8474 /* If available, Xlib uses FIOSNBIO to make the socket |
3820 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set, | 8475 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set, |
3821 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK, | 8476 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK, |
3822 a read returns 0, which Xlib interprets as equivalent to EPIPE. */ | 8477 a read returns 0, which Xlib interprets as equivalent to EPIPE. */ |
3823 fcntl (dpyinfo->connection, F_SETFL, 0); | 8478 fcntl (dpyinfo->connection, F_SETFL, 0); |
3824 #endif /* ! defined (FIOSNBIO) */ | 8479 #endif /* ! defined (FIOSNBIO) */ |
3825 #endif | 8480 #endif |
3826 | 8481 |
3827 #if 0 /* This code can't be made to work, with multiple displays, | 8482 #if 0 /* This code can't be made to work, with multiple displays, |
3846 { | 8501 { |
3847 XTread_socket_fake_io_error = 0; | 8502 XTread_socket_fake_io_error = 0; |
3848 x_io_error_quitter (dpyinfo->display); | 8503 x_io_error_quitter (dpyinfo->display); |
3849 } | 8504 } |
3850 | 8505 |
3851 while (XPending (dpyinfo->display) != 0) | 8506 while (XPending (dpyinfo->display)) |
3852 { | 8507 { |
3853 #ifdef USE_X_TOOLKIT | |
3854 /* needed to raise Motif submenus */ | |
3855 XtAppNextEvent (Xt_app_con, &event); | |
3856 #else | |
3857 XNextEvent (dpyinfo->display, &event); | 8508 XNextEvent (dpyinfo->display, &event); |
3858 #endif | 8509 |
8510 if (display_busy_cursor_p) | |
8511 { | |
8512 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor | |
8513 display until the next X event is read and we come | |
8514 here again. Setting it to 1 inhibits busy-cursor | |
8515 display for direct commands. */ | |
8516 if (event.type == MotionNotify | |
8517 || event.type == EnterNotify | |
8518 || (dpyinfo->grabbed | |
8519 && event.type != ButtonRelease)) | |
8520 inhibit_busy_cursor = 2; | |
8521 else | |
8522 inhibit_busy_cursor = 1; | |
8523 } | |
8524 | |
3859 #ifdef HAVE_X_I18N | 8525 #ifdef HAVE_X_I18N |
3860 { | 8526 { |
3861 struct frame *f1 = x_any_window_to_frame (dpyinfo, | 8527 struct frame *f1 = x_any_window_to_frame (dpyinfo, |
3862 event.xclient.window); | 8528 event.xclient.window); |
3863 /* The necessity of the following line took me | 8529 /* The necessity of the following line took me |
3909 } | 8575 } |
3910 else if (event.xclient.data.l[0] | 8576 else if (event.xclient.data.l[0] |
3911 == dpyinfo->Xatom_wm_save_yourself) | 8577 == dpyinfo->Xatom_wm_save_yourself) |
3912 { | 8578 { |
3913 /* Save state modify the WM_COMMAND property to | 8579 /* Save state modify the WM_COMMAND property to |
3914 something which can reinstate us. This notifies | 8580 something which can reinstate us. This notifies |
3915 the session manager, who's looking for such a | 8581 the session manager, who's looking for such a |
3916 PropertyNotify. Can restart processing when | 8582 PropertyNotify. Can restart processing when |
3917 a keyboard or mouse event arrives. */ | 8583 a keyboard or mouse event arrives. */ |
3918 if (numchars > 0) | 8584 if (numchars > 0) |
3919 { | 8585 { |
3920 f = x_top_window_to_frame (dpyinfo, | 8586 f = x_top_window_to_frame (dpyinfo, |
3921 event.xclient.window); | 8587 event.xclient.window); |
3922 | 8588 |
3981 = x_any_window_to_frame (dpyinfo, event.xclient.window); | 8647 = x_any_window_to_frame (dpyinfo, event.xclient.window); |
3982 _XEditResCheckMessages (f->output_data.x->widget, NULL, | 8648 _XEditResCheckMessages (f->output_data.x->widget, NULL, |
3983 &event, NULL); | 8649 &event, NULL); |
3984 } | 8650 } |
3985 #endif /* HACK_EDITRES */ | 8651 #endif /* HACK_EDITRES */ |
8652 else if ((event.xclient.message_type | |
8653 == dpyinfo->Xatom_DONE) | |
8654 || (event.xclient.message_type | |
8655 == dpyinfo->Xatom_PAGE)) | |
8656 { | |
8657 /* Ghostview job completed. Kill it. We could | |
8658 reply with "Next" if we received "Page", but we | |
8659 currently never do because we are interested in | |
8660 images, only, which should have 1 page. */ | |
8661 Window gs_window = (Window) event.xclient.data.l[0]; | |
8662 Pixmap pixmap = (Pixmap) event.xclient.data.l[1]; | |
8663 struct frame *f | |
8664 = x_window_to_frame (dpyinfo, event.xclient.window); | |
8665 x_kill_gs_process (pixmap, f); | |
8666 expose_frame (f, 0, 0, 0, 0); | |
8667 } | |
8668 #ifdef USE_TOOLKIT_SCROLL_BARS | |
8669 /* Scroll bar callbacks send a ClientMessage from which | |
8670 we construct an input_event. */ | |
8671 else if (event.xclient.message_type | |
8672 == dpyinfo->Xatom_Scrollbar) | |
8673 { | |
8674 x_scroll_bar_to_input_event (&event, bufp); | |
8675 ++bufp, ++count, --numchars; | |
8676 goto out; | |
8677 } | |
8678 #endif /* USE_TOOLKIT_SCROLL_BARS */ | |
8679 else | |
8680 goto OTHER; | |
3986 } | 8681 } |
3987 break; | 8682 break; |
3988 | 8683 |
3989 case SelectionNotify: | 8684 case SelectionNotify: |
3990 #ifdef USE_X_TOOLKIT | 8685 #ifdef USE_X_TOOLKIT |
3992 goto OTHER; | 8687 goto OTHER; |
3993 #endif /* not USE_X_TOOLKIT */ | 8688 #endif /* not USE_X_TOOLKIT */ |
3994 x_handle_selection_notify (&event.xselection); | 8689 x_handle_selection_notify (&event.xselection); |
3995 break; | 8690 break; |
3996 | 8691 |
3997 case SelectionClear: /* Someone has grabbed ownership. */ | 8692 case SelectionClear: /* Someone has grabbed ownership. */ |
3998 #ifdef USE_X_TOOLKIT | 8693 #ifdef USE_X_TOOLKIT |
3999 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window)) | 8694 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window)) |
4000 goto OTHER; | 8695 goto OTHER; |
4001 #endif /* USE_X_TOOLKIT */ | 8696 #endif /* USE_X_TOOLKIT */ |
4002 { | 8697 { |
4015 count += 1; | 8710 count += 1; |
4016 numchars -= 1; | 8711 numchars -= 1; |
4017 } | 8712 } |
4018 break; | 8713 break; |
4019 | 8714 |
4020 case SelectionRequest: /* Someone wants our selection. */ | 8715 case SelectionRequest: /* Someone wants our selection. */ |
4021 #ifdef USE_X_TOOLKIT | 8716 #ifdef USE_X_TOOLKIT |
4022 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner)) | 8717 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner)) |
4023 goto OTHER; | 8718 goto OTHER; |
4024 #endif /* USE_X_TOOLKIT */ | 8719 #endif /* USE_X_TOOLKIT */ |
4025 if (x_queue_selection_requests) | 8720 if (x_queue_selection_requests) |
4077 f->async_iconified = 0; | 8772 f->async_iconified = 0; |
4078 f->output_data.x->has_been_visible = 1; | 8773 f->output_data.x->has_been_visible = 1; |
4079 SET_FRAME_GARBAGED (f); | 8774 SET_FRAME_GARBAGED (f); |
4080 } | 8775 } |
4081 else | 8776 else |
4082 dumprectangle (x_window_to_frame (dpyinfo, | 8777 expose_frame (x_window_to_frame (dpyinfo, |
4083 event.xexpose.window), | 8778 event.xexpose.window), |
4084 event.xexpose.x, event.xexpose.y, | 8779 event.xexpose.x, event.xexpose.y, |
4085 event.xexpose.width, event.xexpose.height); | 8780 event.xexpose.width, event.xexpose.height); |
4086 } | 8781 } |
4087 else | 8782 else |
4088 { | 8783 { |
8784 #ifdef USE_TOOLKIT_SCROLL_BARS | |
8785 /* Dispatch event to the widget. */ | |
8786 goto OTHER; | |
8787 #else /* not USE_TOOLKIT_SCROLL_BARS */ | |
4089 struct scroll_bar *bar | 8788 struct scroll_bar *bar |
4090 = x_window_to_scroll_bar (event.xexpose.window); | 8789 = x_window_to_scroll_bar (event.xexpose.window); |
4091 | 8790 |
4092 if (bar) | 8791 if (bar) |
4093 x_scroll_bar_expose (bar, &event); | 8792 x_scroll_bar_expose (bar, &event); |
4094 #ifdef USE_X_TOOLKIT | 8793 #ifdef USE_X_TOOLKIT |
4095 else | 8794 else |
4096 goto OTHER; | 8795 goto OTHER; |
4097 #endif /* USE_X_TOOLKIT */ | 8796 #endif /* USE_X_TOOLKIT */ |
8797 #endif /* not USE_TOOLKIT_SCROLL_BARS */ | |
4098 } | 8798 } |
4099 break; | 8799 break; |
4100 | 8800 |
4101 case GraphicsExpose: /* This occurs when an XCopyArea's | 8801 case GraphicsExpose: /* This occurs when an XCopyArea's |
4102 source area was obscured or not | 8802 source area was obscured or not |
4103 available.*/ | 8803 available.*/ |
4104 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable); | 8804 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable); |
4105 if (f) | 8805 if (f) |
4106 { | 8806 { |
4107 dumprectangle (f, | 8807 expose_frame (f, |
4108 event.xgraphicsexpose.x, event.xgraphicsexpose.y, | 8808 event.xgraphicsexpose.x, event.xgraphicsexpose.y, |
4109 event.xgraphicsexpose.width, | 8809 event.xgraphicsexpose.width, |
4110 event.xgraphicsexpose.height); | 8810 event.xgraphicsexpose.height); |
4111 } | 8811 } |
4112 #ifdef USE_X_TOOLKIT | 8812 #ifdef USE_X_TOOLKIT |
4113 else | 8813 else |
4114 goto OTHER; | 8814 goto OTHER; |
4115 #endif /* USE_X_TOOLKIT */ | 8815 #endif /* USE_X_TOOLKIT */ |
4116 break; | 8816 break; |
4117 | 8817 |
4118 case NoExpose: /* This occurs when an XCopyArea's | 8818 case NoExpose: /* This occurs when an XCopyArea's |
4119 source area was completely | 8819 source area was completely |
4120 available */ | 8820 available */ |
4121 break; | 8821 break; |
4122 | 8822 |
4123 case UnmapNotify: | 8823 case UnmapNotify: |
8824 /* Redo the mouse-highlight after the tooltip has gone. */ | |
8825 if (event.xmap.window == tip_window) | |
8826 { | |
8827 tip_window = 0; | |
8828 redo_mouse_highlight (); | |
8829 } | |
8830 | |
4124 f = x_top_window_to_frame (dpyinfo, event.xunmap.window); | 8831 f = x_top_window_to_frame (dpyinfo, event.xunmap.window); |
4125 if (f) /* F may no longer exist if | 8832 if (f) /* F may no longer exist if |
4126 the frame was deleted. */ | 8833 the frame was deleted. */ |
4127 { | 8834 { |
4128 /* While a frame is unmapped, display generation is | 8835 /* While a frame is unmapped, display generation is |
4147 } | 8854 } |
4148 } | 8855 } |
4149 goto OTHER; | 8856 goto OTHER; |
4150 | 8857 |
4151 case MapNotify: | 8858 case MapNotify: |
4152 /* We use x_top_window_to_frame because map events can come | 8859 if (event.xmap.window == tip_window) |
4153 for subwindows and they don't mean that the frame is visible. */ | 8860 /* The tooltip has been drawn already. Avoid |
8861 the SET_FRAME_GARBAGED below. */ | |
8862 goto OTHER; | |
8863 | |
8864 /* We use x_top_window_to_frame because map events can | |
8865 come for sub-windows and they don't mean that the | |
8866 frame is visible. */ | |
4154 f = x_top_window_to_frame (dpyinfo, event.xmap.window); | 8867 f = x_top_window_to_frame (dpyinfo, event.xmap.window); |
4155 if (f) | 8868 if (f) |
4156 { | 8869 { |
4157 f->async_visible = 1; | 8870 f->async_visible = 1; |
4158 f->async_iconified = 0; | 8871 f->async_iconified = 0; |
4177 in case this is the second frame. */ | 8890 in case this is the second frame. */ |
4178 record_asynch_buffer_change (); | 8891 record_asynch_buffer_change (); |
4179 } | 8892 } |
4180 goto OTHER; | 8893 goto OTHER; |
4181 | 8894 |
4182 /* Turn off processing if we become fully obscured. */ | |
4183 case VisibilityNotify: | |
4184 break; | |
4185 | |
4186 case KeyPress: | 8895 case KeyPress: |
4187 f = x_any_window_to_frame (dpyinfo, event.xkey.window); | 8896 f = x_any_window_to_frame (dpyinfo, event.xkey.window); |
8897 | |
8898 #ifdef USE_MOTIF | |
8899 /* I couldn't find a way to prevent LessTif scroll bars | |
8900 from consuming key events. */ | |
8901 if (f == 0) | |
8902 { | |
8903 Widget widget = XtWindowToWidget (dpyinfo->display, | |
8904 event.xkey.window); | |
8905 if (widget && XmIsScrollBar (widget)) | |
8906 { | |
8907 widget = XtParent (widget); | |
8908 f = x_any_window_to_frame (dpyinfo, XtWindow (widget)); | |
8909 } | |
8910 } | |
8911 #endif /* USE_MOTIF */ | |
4188 | 8912 |
4189 if (f != 0) | 8913 if (f != 0) |
4190 { | 8914 { |
4191 KeySym keysym, orig_keysym; | 8915 KeySym keysym, orig_keysym; |
4192 /* al%imercury@uunet.uu.net says that making this 81 instead of | 8916 /* al%imercury@uunet.uu.net says that making this 81 instead of |
4193 80 fixed a bug whereby meta chars made his Emacs hang. */ | 8917 80 fixed a bug whereby meta chars made his Emacs hang. */ |
4194 unsigned char copy_buffer[81]; | 8918 unsigned char copy_buffer[81]; |
4195 int modifiers; | 8919 int modifiers; |
4196 | |
4197 #if 0 /* This was how we made f10 work in Motif. | |
4198 The drawback is, you can't type at Emacs when the | |
4199 the mouse is in the menu bar. So it is better to | |
4200 turn off f10 in Motif and let Emacs handle it. */ | |
4201 #ifdef USE_MOTIF | |
4202 if (lw_window_is_in_menubar (event.xkey.window, | |
4203 f->output_data.x->menubar_widget | |
4204 )) | |
4205 { | |
4206 SET_SAVED_KEY_EVENT; | |
4207 break; | |
4208 } | |
4209 #endif /* USE_MOTIF */ | |
4210 #endif /* 0 */ | |
4211 | 8920 |
4212 event.xkey.state | 8921 event.xkey.state |
4213 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f), | 8922 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f), |
4214 extra_keyboard_modifiers); | 8923 extra_keyboard_modifiers); |
4215 modifiers = event.xkey.state; | 8924 modifiers = event.xkey.state; |
4344 modifiers); | 9053 modifiers); |
4345 bufp->timestamp = event.xkey.time; | 9054 bufp->timestamp = event.xkey.time; |
4346 bufp++; | 9055 bufp++; |
4347 count++; | 9056 count++; |
4348 numchars--; | 9057 numchars--; |
9058 | |
9059 if (display_busy_cursor_p) | |
9060 if (keysym != XK_Return || minibuf_level == 0) | |
9061 inhibit_busy_cursor = 2; | |
4349 } | 9062 } |
4350 else if (numchars > nbytes) | 9063 else if (numchars > nbytes) |
4351 { | 9064 { |
4352 register int i; | 9065 register int i; |
4353 | 9066 |
4379 abort (); | 9092 abort (); |
4380 } | 9093 } |
4381 goto OTHER; | 9094 goto OTHER; |
4382 | 9095 |
4383 /* Here's a possible interpretation of the whole | 9096 /* Here's a possible interpretation of the whole |
4384 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a | 9097 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If |
4385 FocusIn event, you have to get a FocusOut event before you | 9098 you get a FocusIn event, you have to get a FocusOut |
4386 relinquish the focus. If you haven't received a FocusIn event, | 9099 event before you relinquish the focus. If you |
4387 then a mere LeaveNotify is enough to free you. */ | 9100 haven't received a FocusIn event, then a mere |
9101 LeaveNotify is enough to free you. */ | |
4388 | 9102 |
4389 case EnterNotify: | 9103 case EnterNotify: |
4390 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window); | 9104 { |
4391 | 9105 int from_menu_bar_p = 0; |
4392 if (event.xcrossing.focus) /* Entered Window */ | 9106 |
4393 { | 9107 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window); |
4394 /* Avoid nasty pop/raise loops. */ | 9108 |
4395 if (f && (!(f->auto_raise) | 9109 #ifdef LESSTIF_VERSION |
4396 || !(f->auto_lower) | 9110 /* When clicking outside of a menu bar popup to close |
4397 || (event.xcrossing.time - enter_timestamp) > 500)) | 9111 it, we get a FocusIn/ EnterNotify sequence of |
4398 { | 9112 events. The flag event.xcrossing.focus is not set |
4399 x_new_focus_frame (dpyinfo, f); | 9113 in the EnterNotify event of that sequence because |
4400 enter_timestamp = event.xcrossing.time; | 9114 the focus is in the menu bar, |
4401 } | 9115 event.xcrossing.window is the frame's X window. |
4402 } | 9116 Unconditionally setting the focus frame to null in |
4403 else if (f == dpyinfo->x_focus_frame) | 9117 this case is not the right thing, because no event |
4404 x_new_focus_frame (dpyinfo, 0); | 9118 follows that could set the focus frame to the right |
4405 /* EnterNotify counts as mouse movement, | 9119 value. |
4406 so update things that depend on mouse position. */ | 9120 |
4407 if (f) | 9121 This could be a LessTif bug, but I wasn't able to |
4408 note_mouse_movement (f, &event.xmotion); | 9122 reproduce the behavior in a simple test program. |
4409 goto OTHER; | 9123 |
9124 (gerd, LessTif 0.88.1). */ | |
9125 | |
9126 if (!event.xcrossing.focus | |
9127 && f | |
9128 && f->output_data.x->menubar_widget) | |
9129 { | |
9130 Window focus; | |
9131 int revert; | |
9132 | |
9133 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert); | |
9134 if (focus == XtWindow (f->output_data.x->menubar_widget)) | |
9135 from_menu_bar_p = 1; | |
9136 } | |
9137 #endif /* LESSTIF_VERSION */ | |
9138 | |
9139 if (event.xcrossing.focus || from_menu_bar_p) | |
9140 { | |
9141 /* Avoid nasty pop/raise loops. */ | |
9142 if (f && (!(f->auto_raise) | |
9143 || !(f->auto_lower) | |
9144 || (event.xcrossing.time - enter_timestamp) > 500)) | |
9145 { | |
9146 x_new_focus_frame (dpyinfo, f); | |
9147 enter_timestamp = event.xcrossing.time; | |
9148 } | |
9149 } | |
9150 else if (f == dpyinfo->x_focus_frame) | |
9151 x_new_focus_frame (dpyinfo, 0); | |
9152 | |
9153 /* EnterNotify counts as mouse movement, | |
9154 so update things that depend on mouse position. */ | |
9155 if (f && !f->output_data.x->busy_p) | |
9156 note_mouse_movement (f, &event.xmotion); | |
9157 goto OTHER; | |
9158 } | |
4410 | 9159 |
4411 case FocusIn: | 9160 case FocusIn: |
4412 f = x_any_window_to_frame (dpyinfo, event.xfocus.window); | 9161 f = x_any_window_to_frame (dpyinfo, event.xfocus.window); |
4413 if (event.xfocus.detail != NotifyPointer) | 9162 if (event.xfocus.detail != NotifyPointer) |
4414 dpyinfo->x_focus_event_frame = f; | 9163 dpyinfo->x_focus_event_frame = f; |
4424 | 9173 |
4425 case LeaveNotify: | 9174 case LeaveNotify: |
4426 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window); | 9175 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window); |
4427 if (f) | 9176 if (f) |
4428 { | 9177 { |
9178 Lisp_Object frame; | |
9179 int from_menu_bar_p = 0; | |
9180 | |
4429 if (f == dpyinfo->mouse_face_mouse_frame) | 9181 if (f == dpyinfo->mouse_face_mouse_frame) |
4430 /* If we move outside the frame, | 9182 { |
4431 then we're certainly no longer on any text in the frame. */ | 9183 /* If we move outside the frame, then we're |
4432 clear_mouse_face (dpyinfo); | 9184 certainly no longer on any text in the frame. */ |
4433 | 9185 clear_mouse_face (dpyinfo); |
4434 if (event.xcrossing.focus) | 9186 dpyinfo->mouse_face_mouse_frame = 0; |
9187 } | |
9188 | |
9189 /* Generate a nil HELP_EVENT to cancel a help-echo. | |
9190 Do it only if there's something to cancel. | |
9191 Otherwise, the startup message is cleared when | |
9192 the mouse leaves the frame. */ | |
9193 if (any_help_event_p) | |
9194 { | |
9195 XSETFRAME (frame, f); | |
9196 bufp->kind = HELP_EVENT; | |
9197 bufp->frame_or_window = Fcons (frame, Qnil); | |
9198 ++bufp, ++count, --numchars; | |
9199 } | |
9200 | |
9201 #ifdef LESSTIF_VERSION | |
9202 /* Please see the comment at the start of the | |
9203 EnterNotify case. */ | |
9204 if (!event.xcrossing.focus | |
9205 && f->output_data.x->menubar_widget) | |
9206 { | |
9207 Window focus; | |
9208 int revert; | |
9209 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert); | |
9210 if (focus == XtWindow (f->output_data.x->menubar_widget)) | |
9211 from_menu_bar_p = 1; | |
9212 } | |
9213 #endif /* LESSTIF_VERSION */ | |
9214 | |
9215 if (event.xcrossing.focus || from_menu_bar_p) | |
4435 x_mouse_leave (dpyinfo); | 9216 x_mouse_leave (dpyinfo); |
4436 else | 9217 else |
4437 { | 9218 { |
4438 if (f == dpyinfo->x_focus_event_frame) | 9219 if (f == dpyinfo->x_focus_event_frame) |
4439 dpyinfo->x_focus_event_frame = 0; | 9220 dpyinfo->x_focus_event_frame = 0; |
4458 | 9239 |
4459 goto OTHER; | 9240 goto OTHER; |
4460 | 9241 |
4461 case MotionNotify: | 9242 case MotionNotify: |
4462 { | 9243 { |
9244 previous_help_echo = help_echo; | |
9245 help_echo = Qnil; | |
9246 | |
4463 if (dpyinfo->grabbed && last_mouse_frame | 9247 if (dpyinfo->grabbed && last_mouse_frame |
4464 && FRAME_LIVE_P (last_mouse_frame)) | 9248 && FRAME_LIVE_P (last_mouse_frame)) |
4465 f = last_mouse_frame; | 9249 f = last_mouse_frame; |
4466 else | 9250 else |
4467 f = x_window_to_frame (dpyinfo, event.xmotion.window); | 9251 f = x_window_to_frame (dpyinfo, event.xmotion.window); |
9252 | |
4468 if (f) | 9253 if (f) |
4469 note_mouse_movement (f, &event.xmotion); | 9254 note_mouse_movement (f, &event.xmotion); |
4470 else | 9255 else |
4471 { | 9256 { |
9257 #ifndef USE_X_TOOLKIT | |
4472 struct scroll_bar *bar | 9258 struct scroll_bar *bar |
4473 = x_window_to_scroll_bar (event.xmotion.window); | 9259 = x_window_to_scroll_bar (event.xmotion.window); |
4474 | 9260 |
4475 if (bar) | 9261 if (bar) |
4476 x_scroll_bar_note_movement (bar, &event); | 9262 x_scroll_bar_note_movement (bar, &event); |
4477 | 9263 #endif /* USE_X_TOOLKIT */ |
4478 /* If we move outside the frame, | 9264 |
4479 then we're certainly no longer on any text in the frame. */ | 9265 /* If we move outside the frame, then we're |
9266 certainly no longer on any text in the frame. */ | |
4480 clear_mouse_face (dpyinfo); | 9267 clear_mouse_face (dpyinfo); |
4481 } | 9268 } |
9269 | |
9270 /* If the contents of the global variable help_echo | |
9271 has changed, generate a HELP_EVENT. */ | |
9272 if (STRINGP (help_echo) | |
9273 || STRINGP (previous_help_echo)) | |
9274 { | |
9275 Lisp_Object frame; | |
9276 | |
9277 if (f) | |
9278 XSETFRAME (frame, f); | |
9279 else | |
9280 frame = Qnil; | |
9281 | |
9282 any_help_event_p = 1; | |
9283 bufp->kind = HELP_EVENT; | |
9284 bufp->frame_or_window = Fcons (frame, help_echo); | |
9285 ++bufp, ++count, --numchars; | |
9286 } | |
9287 | |
9288 goto OTHER; | |
4482 } | 9289 } |
4483 goto OTHER; | |
4484 | 9290 |
4485 case ConfigureNotify: | 9291 case ConfigureNotify: |
4486 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window); | 9292 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window); |
4487 if (f) | 9293 if (f) |
4488 { | 9294 { |
4489 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height); | 9295 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height); |
4490 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width); | 9296 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width); |
9297 | |
4491 #ifndef USE_X_TOOLKIT | 9298 #ifndef USE_X_TOOLKIT |
4492 /* In the toolkit version, change_frame_size | 9299 /* In the toolkit version, change_frame_size |
4493 is called by the code that handles resizing | 9300 is called by the code that handles resizing |
4494 of the EmacsFrame widget. */ | 9301 of the EmacsFrame widget. */ |
4495 | 9302 |
4529 if (event.xconfigure.x == 0 && event.xconfigure.y == 0) | 9336 if (event.xconfigure.x == 0 && event.xconfigure.y == 0) |
4530 { | 9337 { |
4531 event.xconfigure.x = f->output_data.x->widget->core.x; | 9338 event.xconfigure.x = f->output_data.x->widget->core.x; |
4532 event.xconfigure.y = f->output_data.x->widget->core.y; | 9339 event.xconfigure.y = f->output_data.x->widget->core.y; |
4533 } | 9340 } |
4534 #endif | 9341 #endif /* USE_MOTIF */ |
4535 /* If cursor was outside the new size, mark it as off. */ | |
4536 if (f->phys_cursor_y >= rows | |
4537 || f->phys_cursor_x >= columns) | |
4538 { | |
4539 f->phys_cursor_x = 0; | |
4540 f->phys_cursor_y = 0; | |
4541 f->phys_cursor_on = 0; | |
4542 } | |
4543 } | 9342 } |
4544 | |
4545 goto OTHER; | 9343 goto OTHER; |
4546 | 9344 |
4547 case ButtonPress: | 9345 case ButtonPress: |
4548 case ButtonRelease: | 9346 case ButtonRelease: |
4549 { | 9347 { |
4550 /* If we decide we want to generate an event to be seen | 9348 /* If we decide we want to generate an event to be seen |
4551 by the rest of Emacs, we put it here. */ | 9349 by the rest of Emacs, we put it here. */ |
4552 struct input_event emacs_event; | 9350 struct input_event emacs_event; |
9351 int toolbar_p = 0; | |
9352 | |
4553 emacs_event.kind = no_event; | 9353 emacs_event.kind = no_event; |
4554 | |
4555 bzero (&compose_status, sizeof (compose_status)); | 9354 bzero (&compose_status, sizeof (compose_status)); |
4556 | 9355 |
4557 if (dpyinfo->grabbed && last_mouse_frame | 9356 if (dpyinfo->grabbed |
9357 && last_mouse_frame | |
4558 && FRAME_LIVE_P (last_mouse_frame)) | 9358 && FRAME_LIVE_P (last_mouse_frame)) |
4559 f = last_mouse_frame; | 9359 f = last_mouse_frame; |
4560 else | 9360 else |
4561 f = x_window_to_frame (dpyinfo, event.xbutton.window); | 9361 f = x_window_to_frame (dpyinfo, event.xbutton.window); |
4562 | 9362 |
4563 if (f) | 9363 if (f) |
4564 { | 9364 { |
4565 if (!dpyinfo->x_focus_frame || f == dpyinfo->x_focus_frame) | 9365 /* Is this in the toolbar? */ |
4566 construct_mouse_click (&emacs_event, &event, f); | 9366 if (WINDOWP (f->toolbar_window) |
9367 && XFASTINT (XWINDOW (f->toolbar_window)->height)) | |
9368 { | |
9369 Lisp_Object window; | |
9370 int p, x, y; | |
9371 | |
9372 x = event.xbutton.x; | |
9373 y = event.xbutton.y; | |
9374 | |
9375 /* Set x and y. */ | |
9376 window = window_from_coordinates (f, x, y, &p, 1); | |
9377 if (EQ (window, f->toolbar_window)) | |
9378 { | |
9379 x_handle_toolbar_click (f, &event.xbutton); | |
9380 toolbar_p = 1; | |
9381 } | |
9382 } | |
9383 | |
9384 if (!toolbar_p) | |
9385 if (!dpyinfo->x_focus_frame | |
9386 || f == dpyinfo->x_focus_frame) | |
9387 construct_mouse_click (&emacs_event, &event, f); | |
4567 } | 9388 } |
4568 else | 9389 else |
4569 { | 9390 { |
9391 #ifndef USE_TOOLKIT_SCROLL_BARS | |
4570 struct scroll_bar *bar | 9392 struct scroll_bar *bar |
4571 = x_window_to_scroll_bar (event.xbutton.window); | 9393 = x_window_to_scroll_bar (event.xbutton.window); |
4572 | 9394 |
4573 if (bar) | 9395 if (bar) |
4574 x_scroll_bar_handle_click (bar, &event, &emacs_event); | 9396 x_scroll_bar_handle_click (bar, &event, &emacs_event); |
9397 #endif /* not USE_TOOLKIT_SCROLL_BARS */ | |
4575 } | 9398 } |
4576 | 9399 |
4577 if (event.type == ButtonPress) | 9400 if (event.type == ButtonPress) |
4578 { | 9401 { |
4579 dpyinfo->grabbed |= (1 << event.xbutton.button); | 9402 dpyinfo->grabbed |= (1 << event.xbutton.button); |
4582 before this event; any subsequent mouse-movement | 9405 before this event; any subsequent mouse-movement |
4583 Emacs events should reflect only motion after | 9406 Emacs events should reflect only motion after |
4584 the ButtonPress. */ | 9407 the ButtonPress. */ |
4585 if (f != 0) | 9408 if (f != 0) |
4586 f->mouse_moved = 0; | 9409 f->mouse_moved = 0; |
9410 | |
9411 if (!toolbar_p) | |
9412 last_toolbar_item = -1; | |
9413 if (display_busy_cursor_p) | |
9414 inhibit_busy_cursor = 2; | |
4587 } | 9415 } |
4588 else | 9416 else |
4589 { | 9417 { |
4590 dpyinfo->grabbed &= ~(1 << event.xbutton.button); | 9418 dpyinfo->grabbed &= ~(1 << event.xbutton.button); |
4591 } | 9419 } |
4620 else if (event.type == ButtonPress) | 9448 else if (event.type == ButtonPress) |
4621 { | 9449 { |
4622 last_mouse_press_frame = Qnil; | 9450 last_mouse_press_frame = Qnil; |
4623 goto OTHER; | 9451 goto OTHER; |
4624 } | 9452 } |
9453 | |
4625 #ifdef USE_MOTIF /* This should do not harm for Lucid, | 9454 #ifdef USE_MOTIF /* This should do not harm for Lucid, |
4626 but I am trying to be cautious. */ | 9455 but I am trying to be cautious. */ |
4627 else if (event.type == ButtonRelease) | 9456 else if (event.type == ButtonRelease) |
4628 { | 9457 { |
4629 if (!NILP (last_mouse_press_frame)) | 9458 if (!NILP (last_mouse_press_frame)) |
4630 { | 9459 { |
4631 f = XFRAME (last_mouse_press_frame); | 9460 f = XFRAME (last_mouse_press_frame); |
4632 if (f->output_data.x) | 9461 if (f->output_data.x) |
4633 { | 9462 SET_SAVED_BUTTON_EVENT; |
4634 SET_SAVED_BUTTON_EVENT; | |
4635 } | |
4636 } | 9463 } |
4637 else | 9464 else |
4638 goto OTHER; | 9465 goto OTHER; |
4639 } | 9466 } |
4640 #endif /* USE_MOTIF */ | 9467 #endif /* USE_MOTIF */ |
4641 else | 9468 else |
4642 goto OTHER; | 9469 goto OTHER; |
4643 #endif /* USE_X_TOOLKIT */ | 9470 #endif /* USE_X_TOOLKIT */ |
4644 } | 9471 } |
4645 break; | 9472 break; |
4646 | 9473 |
4647 case CirculateNotify: | 9474 case CirculateNotify: |
4648 break; | 9475 goto OTHER; |
9476 | |
4649 case CirculateRequest: | 9477 case CirculateRequest: |
4650 break; | 9478 goto OTHER; |
9479 | |
9480 case VisibilityNotify: | |
9481 goto OTHER; | |
4651 | 9482 |
4652 case MappingNotify: | 9483 case MappingNotify: |
4653 /* Someone has changed the keyboard mapping - update the | 9484 /* Someone has changed the keyboard mapping - update the |
4654 local cache. */ | 9485 local cache. */ |
4655 switch (event.xmapping.request) | 9486 switch (event.xmapping.request) |
4672 break; | 9503 break; |
4673 } | 9504 } |
4674 } | 9505 } |
4675 } | 9506 } |
4676 | 9507 |
9508 out:; | |
9509 | |
4677 /* On some systems, an X bug causes Emacs to get no more events | 9510 /* On some systems, an X bug causes Emacs to get no more events |
4678 when the window is destroyed. Detect that. (1994.) */ | 9511 when the window is destroyed. Detect that. (1994.) */ |
4679 if (! event_found) | 9512 if (! event_found) |
4680 { | 9513 { |
4681 /* Emacs and the X Server eats up CPU time if XNoOp is done every time. | 9514 /* Emacs and the X Server eats up CPU time if XNoOp is done every time. |
4694 /* Each time we get here, cycle through the displays now open. */ | 9527 /* Each time we get here, cycle through the displays now open. */ |
4695 next_noop_dpyinfo = next_noop_dpyinfo->next; | 9528 next_noop_dpyinfo = next_noop_dpyinfo->next; |
4696 } | 9529 } |
4697 } | 9530 } |
4698 | 9531 |
4699 /* If the focus was just given to an autoraising frame, | 9532 /* If the focus was just given to an auto-raising frame, |
4700 raise it now. */ | 9533 raise it now. */ |
4701 /* ??? This ought to be able to handle more than one such frame. */ | 9534 /* ??? This ought to be able to handle more than one such frame. */ |
4702 if (pending_autoraise_frame) | 9535 if (pending_autoraise_frame) |
4703 { | 9536 { |
4704 x_raise_frame (pending_autoraise_frame); | 9537 x_raise_frame (pending_autoraise_frame); |
4706 } | 9539 } |
4707 | 9540 |
4708 UNBLOCK_INPUT; | 9541 UNBLOCK_INPUT; |
4709 return count; | 9542 return count; |
4710 } | 9543 } |
9544 | |
9545 | |
9546 | |
4711 | 9547 |
4712 /* Drawing the cursor. */ | 9548 /*********************************************************************** |
4713 | 9549 Text Cursor |
4714 | 9550 ***********************************************************************/ |
4715 /* Draw a hollow box cursor on frame F at X, Y. | 9551 |
4716 Don't change the inside of the box. */ | 9552 /* Note if the text cursor of window W has been overwritten by a |
9553 drawing operation that outputs N glyphs starting at HPOS in the | |
9554 line given by output_cursor.vpos. N < 0 means all the rest of the | |
9555 line after HPOS has been written. */ | |
4717 | 9556 |
4718 static void | 9557 static void |
4719 x_draw_box (f, x, y) | 9558 note_overwritten_text_cursor (w, hpos, n) |
4720 struct frame *f; | 9559 struct window *w; |
4721 int x, y; | 9560 int hpos, n; |
4722 { | 9561 { |
4723 int left = CHAR_TO_PIXEL_COL (f, x); | 9562 if (updated_area == TEXT_AREA |
4724 int top = CHAR_TO_PIXEL_ROW (f, y); | 9563 && output_cursor.vpos == w->phys_cursor.vpos |
4725 int width = FONT_WIDTH (f->output_data.x->font); | 9564 && hpos <= w->phys_cursor.hpos |
4726 int height = f->output_data.x->line_height; | 9565 && (n < 0 |
4727 int c = FAST_GLYPH_CHAR (f->phys_cursor_glyph); | 9566 || hpos + n > w->phys_cursor.hpos)) |
4728 int charset = CHAR_CHARSET (c); | 9567 w->phys_cursor_on_p = 0; |
4729 | 9568 } |
9569 | |
9570 | |
9571 /* Set clipping for output in glyph row ROW. W is the window in which | |
9572 we operate. GC is the graphics context to set clipping in. | |
9573 WHOLE_LINE_P non-zero means include the areas used for truncation | |
9574 mark display and alike in the clipping rectangle. | |
9575 | |
9576 ROW may be a text row or, e.g., a mode line. Text rows must be | |
9577 clipped to the interior of the window dedicated to text display, | |
9578 mode lines must be clipped to the whole window. */ | |
9579 | |
9580 static void | |
9581 x_clip_to_row (w, row, gc, whole_line_p) | |
9582 struct window *w; | |
9583 struct glyph_row *row; | |
9584 GC gc; | |
9585 int whole_line_p; | |
9586 { | |
9587 struct frame *f = XFRAME (WINDOW_FRAME (w)); | |
9588 XRectangle clip_rect; | |
9589 int window_x, window_y, window_width, window_height; | |
9590 | |
9591 window_box (w, -1, &window_x, &window_y, &window_width, &window_height); | |
9592 | |
9593 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0); | |
9594 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); | |
9595 clip_rect.y = max (clip_rect.y, window_y); | |
9596 clip_rect.width = window_width; | |
9597 clip_rect.height = row->visible_height; | |
9598 | |
9599 /* If clipping to the whole line, including trunc marks, extend | |
9600 the rectangle to the left and increase its width. */ | |
9601 if (whole_line_p) | |
9602 { | |
9603 clip_rect.x -= FRAME_X_FLAGS_AREA_WIDTH (f); | |
9604 clip_rect.width += 2 * FRAME_X_FLAGS_AREA_WIDTH (f); | |
9605 } | |
9606 | |
9607 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted); | |
9608 } | |
9609 | |
9610 | |
9611 /* Draw a hollow box cursor on window W in glyph row ROW. */ | |
9612 | |
9613 static void | |
9614 x_draw_hollow_cursor (w, row) | |
9615 struct window *w; | |
9616 struct glyph_row *row; | |
9617 { | |
9618 struct frame *f = XFRAME (WINDOW_FRAME (w)); | |
9619 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
9620 Display *dpy = FRAME_X_DISPLAY (f); | |
9621 int x, y, wd, h; | |
4730 XGCValues xgcv; | 9622 XGCValues xgcv; |
4731 unsigned long mask = GCForeground; | 9623 struct glyph *cursor_glyph; |
4732 | 9624 GC gc; |
9625 | |
9626 /* Compute frame-relative coordinates from window-relative | |
9627 coordinates. */ | |
9628 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); | |
9629 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y) | |
9630 + row->ascent - w->phys_cursor_ascent); | |
9631 h = row->height - 1; | |
9632 | |
9633 /* Get the glyph the cursor is on. If we can't tell because | |
9634 the current matrix is invalid or such, give up. */ | |
9635 cursor_glyph = get_phys_cursor_glyph (w); | |
9636 if (cursor_glyph == NULL) | |
9637 return; | |
9638 | |
9639 /* Compute the width of the rectangle to draw. If on a stretch | |
9640 glyph, and `x-stretch-block-cursor' is nil, don't draw a | |
9641 rectangle as wide as the glyph, but use a canonical character | |
9642 width instead. */ | |
9643 wd = cursor_glyph->pixel_width - 1; | |
9644 if (cursor_glyph->type == STRETCH_GLYPH | |
9645 && !x_stretch_cursor_p) | |
9646 wd = min (CANON_X_UNIT (f), wd); | |
9647 | |
9648 /* The foreground of cursor_gc is typically the same as the normal | |
9649 background color, which can cause the cursor box to be invisible. */ | |
4733 xgcv.foreground = f->output_data.x->cursor_pixel; | 9650 xgcv.foreground = f->output_data.x->cursor_pixel; |
4734 | 9651 if (dpyinfo->scratch_cursor_gc) |
4735 /* cursor_gc's foreground color is typically the same as the normal | 9652 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv); |
4736 background color, which can cause the cursor box to be invisible. */ | |
4737 if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc) | |
4738 XChangeGC (FRAME_X_DISPLAY (f), | |
4739 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc, | |
4740 mask, &xgcv); | |
4741 else | 9653 else |
4742 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc | 9654 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f), |
4743 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, &xgcv); | 9655 GCForeground, &xgcv); |
4744 | 9656 gc = dpyinfo->scratch_cursor_gc; |
4745 /* If cursor is on a multi-column character, multiply WIDTH by columns. */ | 9657 |
4746 width *= (charset == CHARSET_COMPOSITION | 9658 /* Set clipping, draw the rectangle, and reset clipping again. */ |
4747 ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width | 9659 x_clip_to_row (w, row, gc, 0); |
4748 : CHARSET_WIDTH (charset)); | 9660 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h); |
4749 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 9661 XSetClipMask (dpy, gc, None); |
4750 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc, | 9662 } |
4751 left, top, width - 1, height - 1); | 9663 |
4752 } | 9664 |
4753 | 9665 /* Draw a bar cursor on window W in glyph row ROW. |
4754 /* Clear the cursor of frame F to background color, | 9666 |
4755 and mark the cursor as not shown. | 9667 Implementation note: One would like to draw a bar cursor with an |
4756 This is used when the text where the cursor is | 9668 angle equal to the one given by the font property XA_ITALIC_ANGLE. |
4757 is about to be rewritten. */ | 9669 Unfortunately, I didn't find a font yet that has this property set. |
9670 --gerd. */ | |
4758 | 9671 |
4759 static void | 9672 static void |
4760 clear_cursor (f) | 9673 x_draw_bar_cursor (w, row) |
4761 struct frame *f; | 9674 struct window *w; |
4762 { | 9675 struct glyph_row *row; |
4763 int mask; | 9676 { |
4764 | 9677 /* If cursor hpos is out of bounds, don't draw garbage. This can |
9678 happen in mini-buffer windows when switching between echo area | |
9679 glyphs and mini-buffer. */ | |
9680 if (w->phys_cursor.hpos < row->used[TEXT_AREA]) | |
9681 { | |
9682 struct frame *f = XFRAME (w->frame); | |
9683 struct glyph *cursor_glyph; | |
9684 GC gc; | |
9685 int x; | |
9686 unsigned long mask; | |
9687 XGCValues xgcv; | |
9688 Display *dpy; | |
9689 Window window; | |
9690 | |
9691 cursor_glyph = get_phys_cursor_glyph (w); | |
9692 if (cursor_glyph == NULL) | |
9693 return; | |
9694 | |
9695 xgcv.background = f->output_data.x->cursor_pixel; | |
9696 xgcv.foreground = f->output_data.x->cursor_pixel; | |
9697 xgcv.graphics_exposures = 0; | |
9698 mask = GCForeground | GCBackground | GCGraphicsExposures; | |
9699 dpy = FRAME_X_DISPLAY (f); | |
9700 window = FRAME_X_WINDOW (f); | |
9701 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc; | |
9702 | |
9703 if (gc) | |
9704 XChangeGC (dpy, gc, mask, &xgcv); | |
9705 else | |
9706 { | |
9707 gc = XCreateGC (dpy, window, mask, &xgcv); | |
9708 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc; | |
9709 } | |
9710 | |
9711 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); | |
9712 x_clip_to_row (w, row, gc, 0); | |
9713 XFillRectangle (dpy, window, gc, | |
9714 x, | |
9715 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), | |
9716 min (cursor_glyph->pixel_width, | |
9717 f->output_data.x->cursor_width), | |
9718 row->height); | |
9719 XSetClipMask (dpy, gc, None); | |
9720 } | |
9721 } | |
9722 | |
9723 | |
9724 /* Clear the cursor of window W to background color, and mark the | |
9725 cursor as not shown. This is used when the text where the cursor | |
9726 is is about to be rewritten. */ | |
9727 | |
9728 static void | |
9729 x_clear_cursor (w) | |
9730 struct window *w; | |
9731 { | |
9732 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p) | |
9733 x_update_window_cursor (w, 0); | |
9734 } | |
9735 | |
9736 | |
9737 /* Draw the cursor glyph of window W in glyph row ROW. See the | |
9738 comment of x_draw_glyphs for the meaning of HL. */ | |
9739 | |
9740 static void | |
9741 x_draw_phys_cursor_glyph (w, row, hl) | |
9742 struct window *w; | |
9743 struct glyph_row *row; | |
9744 enum draw_glyphs_face hl; | |
9745 { | |
9746 /* If cursor hpos is out of bounds, don't draw garbage. This can | |
9747 happen in mini-buffer windows when switching between echo area | |
9748 glyphs and mini-buffer. */ | |
9749 if (w->phys_cursor.hpos < row->used[TEXT_AREA]) | |
9750 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, | |
9751 w->phys_cursor.hpos, w->phys_cursor.hpos + 1, hl, 0, 0); | |
9752 } | |
9753 | |
9754 | |
9755 /* Erase the image of a cursor of window W from the screen. */ | |
9756 | |
9757 static void | |
9758 x_erase_phys_cursor (w) | |
9759 struct window *w; | |
9760 { | |
9761 struct frame *f = XFRAME (w->frame); | |
9762 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
9763 int hpos = w->phys_cursor.hpos; | |
9764 int vpos = w->phys_cursor.vpos; | |
9765 int mouse_face_here_p = 0; | |
9766 struct glyph_matrix *active_glyphs = w->current_matrix; | |
9767 struct glyph_row *cursor_row; | |
9768 struct glyph *cursor_glyph; | |
9769 enum draw_glyphs_face hl; | |
9770 | |
9771 /* No cursor displayed or row invalidated => nothing to do on the | |
9772 screen. */ | |
9773 if (w->phys_cursor_type == NO_CURSOR) | |
9774 goto mark_cursor_off; | |
9775 | |
9776 /* VPOS >= active_glyphs->nrows means that window has been resized. | |
9777 Don't bother to erase the cursor. */ | |
9778 if (vpos >= active_glyphs->nrows) | |
9779 goto mark_cursor_off; | |
9780 | |
9781 /* If row containing cursor is marked invalid, there is nothing we | |
9782 can do. */ | |
9783 cursor_row = MATRIX_ROW (active_glyphs, vpos); | |
9784 if (!cursor_row->enabled_p) | |
9785 goto mark_cursor_off; | |
9786 | |
9787 /* This can happen when the new row is shorter than the old one. | |
9788 In this case, either x_draw_glyphs or clear_end_of_line | |
9789 should have cleared the cursor. Note that we wouldn't be | |
9790 able to erase the cursor in this case because we don't have a | |
9791 cursor glyph at hand. */ | |
9792 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA]) | |
9793 goto mark_cursor_off; | |
9794 | |
9795 /* If the cursor is in the mouse face area, redisplay that when | |
9796 we clear the cursor. */ | |
9797 if (w == XWINDOW (dpyinfo->mouse_face_window) | |
9798 && (vpos > dpyinfo->mouse_face_beg_row | |
9799 || (vpos == dpyinfo->mouse_face_beg_row | |
9800 && hpos >= dpyinfo->mouse_face_beg_col)) | |
9801 && (vpos < dpyinfo->mouse_face_end_row | |
9802 || (vpos == dpyinfo->mouse_face_end_row | |
9803 && hpos < dpyinfo->mouse_face_end_col)) | |
9804 /* Don't redraw the cursor's spot in mouse face if it is at the | |
9805 end of a line (on a newline). The cursor appears there, but | |
9806 mouse highlighting does not. */ | |
9807 && cursor_row->used[TEXT_AREA] > hpos) | |
9808 mouse_face_here_p = 1; | |
9809 | |
9810 /* Maybe clear the display under the cursor. */ | |
9811 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR) | |
9812 { | |
9813 int x; | |
9814 int top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w); | |
9815 | |
9816 cursor_glyph = get_phys_cursor_glyph (w); | |
9817 if (cursor_glyph == NULL) | |
9818 goto mark_cursor_off; | |
9819 | |
9820 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x), | |
9821 | |
9822 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
9823 x, | |
9824 WINDOW_TO_FRAME_PIXEL_Y (w, max (top_line_height, | |
9825 cursor_row->y)), | |
9826 cursor_glyph->pixel_width, | |
9827 cursor_row->visible_height, | |
9828 False); | |
9829 } | |
9830 | |
9831 /* Erase the cursor by redrawing the character underneath it. */ | |
9832 if (mouse_face_here_p) | |
9833 hl = DRAW_MOUSE_FACE; | |
9834 else if (cursor_row->inverse_p) | |
9835 hl = DRAW_INVERSE_VIDEO; | |
9836 else | |
9837 hl = DRAW_NORMAL_TEXT; | |
9838 x_draw_phys_cursor_glyph (w, cursor_row, hl); | |
9839 | |
9840 mark_cursor_off: | |
9841 w->phys_cursor_on_p = 0; | |
9842 w->phys_cursor_type = NO_CURSOR; | |
9843 } | |
9844 | |
9845 | |
9846 /* Display or clear cursor of window W. If ON is zero, clear the | |
9847 cursor. If it is non-zero, display the cursor. If ON is nonzero, | |
9848 where to put the cursor is specified by HPOS, VPOS, X and Y. */ | |
9849 | |
9850 void | |
9851 x_display_and_set_cursor (w, on, hpos, vpos, x, y) | |
9852 struct window *w; | |
9853 int on, hpos, vpos, x, y; | |
9854 { | |
9855 struct frame *f = XFRAME (w->frame); | |
9856 int new_cursor_type; | |
9857 struct glyph_matrix *current_glyphs; | |
9858 struct glyph_row *glyph_row; | |
9859 struct glyph *glyph; | |
9860 | |
9861 /* This is pointless on invisible frames, and dangerous on garbaged | |
9862 windows and frames; in the latter case, the frame or window may | |
9863 be in the midst of changing its size, and x and y may be off the | |
9864 window. */ | |
4765 if (! FRAME_VISIBLE_P (f) | 9865 if (! FRAME_VISIBLE_P (f) |
4766 || ! f->phys_cursor_on) | 9866 || FRAME_GARBAGED_P (f) |
9867 || vpos >= w->current_matrix->nrows | |
9868 || hpos >= w->current_matrix->matrix_w) | |
4767 return; | 9869 return; |
4768 | 9870 |
4769 x_update_cursor (f, 0); | 9871 /* If cursor is off and we want it off, return quickly. */ |
4770 f->phys_cursor_on = 0; | 9872 if (!on && !w->phys_cursor_on_p) |
4771 } | |
4772 | |
4773 /* Redraw the glyph at ROW, COLUMN on frame F, in the style | |
4774 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the | |
4775 glyph drawn. */ | |
4776 | |
4777 static void | |
4778 x_draw_single_glyph (f, row, column, glyph, highlight) | |
4779 struct frame *f; | |
4780 int row, column; | |
4781 GLYPH glyph; | |
4782 int highlight; | |
4783 { | |
4784 dumpglyphs (f, | |
4785 CHAR_TO_PIXEL_COL (f, column), | |
4786 CHAR_TO_PIXEL_ROW (f, row), | |
4787 &glyph, 1, highlight, 0, NULL); | |
4788 } | |
4789 | |
4790 static void | |
4791 x_display_bar_cursor (f, on, x, y) | |
4792 struct frame *f; | |
4793 int on; | |
4794 int x, y; | |
4795 { | |
4796 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f); | |
4797 | |
4798 /* This is pointless on invisible frames, and dangerous on garbaged | |
4799 frames; in the latter case, the frame may be in the midst of | |
4800 changing its size, and x and y may be off the frame. */ | |
4801 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f)) | |
4802 return; | 9873 return; |
4803 | 9874 |
4804 if (! on && ! f->phys_cursor_on) | 9875 current_glyphs = w->current_matrix; |
4805 return; | 9876 glyph_row = MATRIX_ROW (current_glyphs, vpos); |
4806 | 9877 glyph = glyph_row->glyphs[TEXT_AREA] + hpos; |
4807 /* If there is anything wrong with the current cursor state, remove it. */ | 9878 |
4808 if (f->phys_cursor_on | 9879 /* If cursor row is not enabled, we don't really know where to |
9880 display the cursor. */ | |
9881 if (!glyph_row->enabled_p) | |
9882 { | |
9883 w->phys_cursor_on_p = 0; | |
9884 return; | |
9885 } | |
9886 | |
9887 xassert (interrupt_input_blocked); | |
9888 | |
9889 /* Set new_cursor_type to the cursor we want to be displayed. In a | |
9890 mini-buffer window, we want the cursor only to appear if we are | |
9891 reading input from this window. For the selected window, we want | |
9892 the cursor type given by the frame parameter. If explicitly | |
9893 marked off, draw no cursor. In all other cases, we want a hollow | |
9894 box cursor. */ | |
9895 if (w != XWINDOW (selected_window) | |
9896 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame) | |
9897 { | |
9898 if (MINI_WINDOW_P (w)) | |
9899 new_cursor_type = NO_CURSOR; | |
9900 else | |
9901 new_cursor_type = HOLLOW_BOX_CURSOR; | |
9902 } | |
9903 else if (w->cursor_off_p) | |
9904 new_cursor_type = NO_CURSOR; | |
9905 else | |
9906 new_cursor_type = FRAME_DESIRED_CURSOR (f); | |
9907 | |
9908 /* If cursor is currently being shown and we don't want it to be or | |
9909 it is in the wrong place, or the cursor type is not what we want, | |
9910 erase it. */ | |
9911 if (w->phys_cursor_on_p | |
4809 && (!on | 9912 && (!on |
4810 || f->phys_cursor_x != x | 9913 || w->phys_cursor.x != x |
4811 || f->phys_cursor_y != y | 9914 || w->phys_cursor.y != y |
4812 || f->output_data.x->current_cursor != bar_cursor)) | 9915 || new_cursor_type != w->phys_cursor_type)) |
4813 { | 9916 x_erase_phys_cursor (w); |
4814 /* Erase the cursor by redrawing the character underneath it. */ | 9917 |
4815 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x, | 9918 /* If the cursor is now invisible and we want it to be visible, |
4816 f->phys_cursor_glyph, | 9919 display it. */ |
4817 current_glyphs->highlight[f->phys_cursor_y]); | 9920 if (on && !w->phys_cursor_on_p) |
4818 f->phys_cursor_on = 0; | 9921 { |
4819 } | 9922 w->phys_cursor_ascent = glyph_row->ascent; |
4820 | 9923 w->phys_cursor_height = glyph_row->height; |
4821 /* If we now need a cursor in the new place or in the new form, do it so. */ | 9924 |
4822 if (on | 9925 /* Set phys_cursor_.* before x_draw_.* is called because some |
4823 && (! f->phys_cursor_on | 9926 of them may need the information. */ |
4824 || (f->output_data.x->current_cursor != bar_cursor))) | 9927 w->phys_cursor.x = x; |
4825 { | 9928 w->phys_cursor.y = glyph_row->y; |
4826 f->phys_cursor_glyph | 9929 w->phys_cursor.hpos = hpos; |
4827 = ((current_glyphs->enable[y] | 9930 w->phys_cursor.vpos = vpos; |
4828 && x < current_glyphs->used[y]) | 9931 w->phys_cursor_type = new_cursor_type; |
4829 ? current_glyphs->glyphs[y][x] | 9932 w->phys_cursor_on_p = 1; |
4830 : SPACEGLYPH); | 9933 |
4831 | 9934 switch (new_cursor_type) |
4832 { | 9935 { |
4833 XGCValues xgcv; | 9936 case HOLLOW_BOX_CURSOR: |
4834 unsigned long mask; | 9937 x_draw_hollow_cursor (w, glyph_row); |
4835 | 9938 break; |
4836 xgcv.background = f->output_data.x->cursor_pixel; | 9939 |
4837 xgcv.foreground = f->output_data.x->cursor_pixel; | 9940 case FILLED_BOX_CURSOR: |
4838 xgcv.graphics_exposures = 0; | 9941 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); |
4839 mask = GCForeground | GCBackground | GCGraphicsExposures; | 9942 break; |
4840 | 9943 |
4841 if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc) | 9944 case BAR_CURSOR: |
4842 XChangeGC (FRAME_X_DISPLAY (f), | 9945 x_draw_bar_cursor (w, glyph_row); |
4843 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc, | 9946 break; |
4844 mask, &xgcv); | 9947 |
4845 else | 9948 case NO_CURSOR: |
4846 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc | 9949 break; |
4847 = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), mask, &xgcv); | 9950 |
4848 } | 9951 default: |
4849 | 9952 abort (); |
4850 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 9953 } |
4851 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc, | 9954 } |
4852 CHAR_TO_PIXEL_COL (f, x), | 9955 |
4853 CHAR_TO_PIXEL_ROW (f, y), | 9956 #ifndef XFlush |
4854 max (f->output_data.x->cursor_width, 1), | |
4855 f->output_data.x->line_height); | |
4856 | |
4857 f->phys_cursor_x = x; | |
4858 f->phys_cursor_y = y; | |
4859 f->phys_cursor_on = 1; | |
4860 | |
4861 f->output_data.x->current_cursor = bar_cursor; | |
4862 } | |
4863 | |
4864 if (updating_frame != f) | 9957 if (updating_frame != f) |
4865 XFlush (FRAME_X_DISPLAY (f)); | 9958 XFlush (FRAME_X_DISPLAY (f)); |
4866 } | 9959 #endif |
4867 | 9960 } |
4868 | 9961 |
4869 /* Turn the displayed cursor of frame F on or off according to ON. | 9962 |
4870 If ON is nonzero, where to put the cursor is specified by X and Y. */ | 9963 /* Display the cursor on window W, or clear it. X and Y are window |
9964 relative pixel coordinates. HPOS and VPOS are glyph matrix | |
9965 positions. If W is not the selected window, display a hollow | |
9966 cursor. ON non-zero means display the cursor at X, Y which | |
9967 correspond to HPOS, VPOS, otherwise it is cleared. */ | |
9968 | |
9969 void | |
9970 x_display_cursor (w, on, hpos, vpos, x, y) | |
9971 struct window *w; | |
9972 int on, hpos, vpos, x, y; | |
9973 { | |
9974 BLOCK_INPUT; | |
9975 x_display_and_set_cursor (w, on, hpos, vpos, x, y); | |
9976 UNBLOCK_INPUT; | |
9977 } | |
9978 | |
9979 | |
9980 /* Display the cursor on window W, or clear it, according to ON_P. | |
9981 Don't change the cursor's position. */ | |
9982 | |
9983 void | |
9984 x_update_cursor (f, on_p) | |
9985 struct frame *f; | |
9986 { | |
9987 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p); | |
9988 } | |
9989 | |
9990 | |
9991 /* Call x_update_window_cursor with parameter ON_P on all leaf windows | |
9992 in the window tree rooted at W. */ | |
4871 | 9993 |
4872 static void | 9994 static void |
4873 x_display_box_cursor (f, on, x, y) | 9995 x_update_cursor_in_window_tree (w, on_p) |
4874 struct frame *f; | 9996 struct window *w; |
9997 int on_p; | |
9998 { | |
9999 while (w) | |
10000 { | |
10001 if (!NILP (w->hchild)) | |
10002 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p); | |
10003 else if (!NILP (w->vchild)) | |
10004 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p); | |
10005 else | |
10006 x_update_window_cursor (w, on_p); | |
10007 | |
10008 w = NILP (w->next) ? 0 : XWINDOW (w->next); | |
10009 } | |
10010 } | |
10011 | |
10012 | |
10013 /* Switch the display of W's cursor on or off, according to the value | |
10014 of ON. */ | |
10015 | |
10016 static void | |
10017 x_update_window_cursor (w, on) | |
10018 struct window *w; | |
4875 int on; | 10019 int on; |
4876 int x, y; | |
4877 { | |
4878 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f); | |
4879 | |
4880 /* This is pointless on invisible frames, and dangerous on garbaged | |
4881 frames; in the latter case, the frame may be in the midst of | |
4882 changing its size, and x and y may be off the frame. */ | |
4883 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f)) | |
4884 return; | |
4885 | |
4886 /* If cursor is off and we want it off, return quickly. */ | |
4887 if (!on && ! f->phys_cursor_on) | |
4888 return; | |
4889 | |
4890 /* If cursor is currently being shown and we don't want it to be | |
4891 or it is in the wrong place, | |
4892 or we want a hollow box and it's not so, (pout!) | |
4893 erase it. */ | |
4894 if (f->phys_cursor_on | |
4895 && (!on | |
4896 || f->phys_cursor_x != x | |
4897 || f->phys_cursor_y != y | |
4898 || (f->output_data.x->current_cursor != hollow_box_cursor | |
4899 && (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)))) | |
4900 { | |
4901 int mouse_face_here = 0; | |
4902 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f); | |
4903 | |
4904 /* If the cursor is in the mouse face area, redisplay that when | |
4905 we clear the cursor. */ | |
4906 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame | |
4907 && | |
4908 (f->phys_cursor_y > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row | |
4909 || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row | |
4910 && f->phys_cursor_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col)) | |
4911 && | |
4912 (f->phys_cursor_y < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row | |
4913 || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row | |
4914 && f->phys_cursor_x < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col)) | |
4915 /* Don't redraw the cursor's spot in mouse face | |
4916 if it is at the end of a line (on a newline). | |
4917 The cursor appears there, but mouse highlighting does not. */ | |
4918 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x) | |
4919 mouse_face_here = 1; | |
4920 | |
4921 /* If the font is not as tall as a whole line, | |
4922 we must explicitly clear the line's whole height. */ | |
4923 if (FONT_HEIGHT (f->output_data.x->font) != f->output_data.x->line_height) | |
4924 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
4925 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x), | |
4926 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y), | |
4927 FONT_WIDTH (f->output_data.x->font), | |
4928 f->output_data.x->line_height, False); | |
4929 /* Erase the cursor by redrawing the character underneath it. */ | |
4930 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x, | |
4931 f->phys_cursor_glyph, | |
4932 (mouse_face_here | |
4933 ? 3 | |
4934 : current_glyphs->highlight[f->phys_cursor_y])); | |
4935 f->phys_cursor_on = 0; | |
4936 } | |
4937 | |
4938 /* If we want to show a cursor, | |
4939 or we want a box cursor and it's not so, | |
4940 write it in the right place. */ | |
4941 if (on | |
4942 && (! f->phys_cursor_on | |
4943 || (f->output_data.x->current_cursor != filled_box_cursor | |
4944 && f == FRAME_X_DISPLAY_INFO (f)->x_highlight_frame))) | |
4945 { | |
4946 f->phys_cursor_glyph | |
4947 = ((current_glyphs->enable[y] | |
4948 && x < current_glyphs->used[y]) | |
4949 ? current_glyphs->glyphs[y][x] | |
4950 : SPACEGLYPH); | |
4951 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame) | |
4952 { | |
4953 x_draw_box (f, x, y); | |
4954 f->output_data.x->current_cursor = hollow_box_cursor; | |
4955 } | |
4956 else | |
4957 { | |
4958 x_draw_single_glyph (f, y, x, | |
4959 f->phys_cursor_glyph, 2); | |
4960 f->output_data.x->current_cursor = filled_box_cursor; | |
4961 } | |
4962 | |
4963 f->phys_cursor_x = x; | |
4964 f->phys_cursor_y = y; | |
4965 f->phys_cursor_on = 1; | |
4966 } | |
4967 | |
4968 if (updating_frame != f) | |
4969 XFlush (FRAME_X_DISPLAY (f)); | |
4970 } | |
4971 | |
4972 /* Display the cursor on frame F, or clear it, according to ON. | |
4973 Also set the frame's cursor position to X and Y. */ | |
4974 | |
4975 void | |
4976 x_display_cursor (f, on, x, y) | |
4977 struct frame *f; | |
4978 int on; | |
4979 int x, y; | |
4980 { | 10020 { |
4981 BLOCK_INPUT; | 10021 BLOCK_INPUT; |
4982 | 10022 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos, |
4983 if ((unsigned) x >= FRAME_CURSOR_X_LIMIT (f) | 10023 w->phys_cursor.x, w->phys_cursor.y); |
4984 || (unsigned) y >= FRAME_HEIGHT (f)) | |
4985 abort (); | |
4986 | |
4987 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor) | |
4988 x_display_box_cursor (f, on, x, y); | |
4989 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor) | |
4990 x_display_bar_cursor (f, on, x, y); | |
4991 else | |
4992 /* Those are the only two we have implemented! */ | |
4993 abort (); | |
4994 | |
4995 UNBLOCK_INPUT; | 10024 UNBLOCK_INPUT; |
4996 } | 10025 } |
4997 | 10026 |
4998 /* Display the cursor on frame F, or clear it, according to ON. | 10027 |
4999 Don't change the cursor's position. */ | 10028 |
5000 | |
5001 void | |
5002 x_update_cursor (f, on) | |
5003 struct frame *f; | |
5004 int on; | |
5005 { | |
5006 BLOCK_INPUT; | |
5007 | |
5008 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor) | |
5009 x_display_box_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y); | |
5010 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor) | |
5011 x_display_bar_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y); | |
5012 else | |
5013 /* Those are the only two we have implemented! */ | |
5014 abort (); | |
5015 | |
5016 UNBLOCK_INPUT; | |
5017 } | |
5018 | 10029 |
5019 /* Icons. */ | 10030 /* Icons. */ |
5020 | 10031 |
5021 /* Refresh bitmap kitchen sink icon for frame F | 10032 /* Refresh bitmap kitchen sink icon for frame F |
5022 when we get an expose event for it. */ | 10033 when we get an expose event for it. */ |
5023 | 10034 |
5024 void | 10035 void |
5025 refreshicon (f) | 10036 refreshicon (f) |
5026 struct frame *f; | 10037 struct frame *f; |
5027 { | 10038 { |
5028 /* Normally, the window manager handles this function. */ | 10039 /* Normally, the window manager handles this function. */ |
5029 } | 10040 } |
5030 | 10041 |
5031 /* Make the x-window of frame F use the gnu icon bitmap. */ | 10042 /* Make the x-window of frame F use the gnu icon bitmap. */ |
5032 | 10043 |
5033 int | 10044 int |
5034 x_bitmap_icon (f, file) | 10045 x_bitmap_icon (f, file) |
5035 struct frame *f; | 10046 struct frame *f; |
5036 Lisp_Object file; | 10047 Lisp_Object file; |
5037 { | 10048 { |
5038 int mask, bitmap_id; | 10049 int bitmap_id; |
5039 Window icon_window; | |
5040 | 10050 |
5041 if (FRAME_X_WINDOW (f) == 0) | 10051 if (FRAME_X_WINDOW (f) == 0) |
5042 return 1; | 10052 return 1; |
5043 | 10053 |
5044 /* Free up our existing icon bitmap if any. */ | 10054 /* Free up our existing icon bitmap if any. */ |
5055 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id | 10065 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id |
5056 = x_create_bitmap_from_data (f, gnu_bits, | 10066 = x_create_bitmap_from_data (f, gnu_bits, |
5057 gnu_width, gnu_height); | 10067 gnu_width, gnu_height); |
5058 | 10068 |
5059 /* The first time we create the GNU bitmap, | 10069 /* The first time we create the GNU bitmap, |
5060 this increments the refcount one extra time. | 10070 this increments the ref-count one extra time. |
5061 As a result, the GNU bitmap is never freed. | 10071 As a result, the GNU bitmap is never freed. |
5062 That way, we don't have to worry about allocating it again. */ | 10072 That way, we don't have to worry about allocating it again. */ |
5063 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); | 10073 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); |
5064 | 10074 |
5065 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id; | 10075 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id; |
5118 | 10128 |
5119 /* An X error handler which stores the error message in | 10129 /* An X error handler which stores the error message in |
5120 x_error_message_string. This is called from x_error_handler if | 10130 x_error_message_string. This is called from x_error_handler if |
5121 x_catch_errors is in effect. */ | 10131 x_catch_errors is in effect. */ |
5122 | 10132 |
5123 static int | 10133 static void |
5124 x_error_catcher (display, error) | 10134 x_error_catcher (display, error) |
5125 Display *display; | 10135 Display *display; |
5126 XErrorEvent *error; | 10136 XErrorEvent *error; |
5127 { | 10137 { |
5128 XGetErrorText (display, error->error_code, | 10138 XGetErrorText (display, error->error_code, |
5202 return XSTRING (x_error_message_string)->data[0] != 0; | 10212 return XSTRING (x_error_message_string)->data[0] != 0; |
5203 } | 10213 } |
5204 | 10214 |
5205 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */ | 10215 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */ |
5206 | 10216 |
5207 int | 10217 void |
5208 x_clear_errors (dpy) | 10218 x_clear_errors (dpy) |
5209 Display *dpy; | 10219 Display *dpy; |
5210 { | 10220 { |
5211 XSTRING (x_error_message_string)->data[0] = 0; | 10221 XSTRING (x_error_message_string)->data[0] = 0; |
5212 } | 10222 } |
5235 | 10245 |
5236 /* Handle SIGPIPE, which can happen when the connection to a server | 10246 /* Handle SIGPIPE, which can happen when the connection to a server |
5237 simply goes away. SIGPIPE is handled by x_connection_signal. | 10247 simply goes away. SIGPIPE is handled by x_connection_signal. |
5238 Don't need to do anything, because the write which caused the | 10248 Don't need to do anything, because the write which caused the |
5239 SIGPIPE will fail, causing Xlib to invoke the X IO error handler, | 10249 SIGPIPE will fail, causing Xlib to invoke the X IO error handler, |
5240 which will do the appropriate cleanup for us. */ | 10250 which will do the appropriate cleanup for us. */ |
5241 | 10251 |
5242 static SIGTYPE | 10252 static SIGTYPE |
5243 x_connection_signal (signalnum) /* If we don't have an argument, */ | 10253 x_connection_signal (signalnum) /* If we don't have an argument, */ |
5244 int signalnum; /* some compilers complain in signal calls. */ | 10254 int signalnum; /* some compilers complain in signal calls. */ |
5245 { | 10255 { |
5246 #ifdef USG | 10256 #ifdef USG |
5247 /* USG systems forget handlers when they are used; | 10257 /* USG systems forget handlers when they are used; |
5248 must reestablish each time */ | 10258 must reestablish each time */ |
5249 signal (signalnum, x_connection_signal); | 10259 signal (signalnum, x_connection_signal); |
5268 XtCloseDisplay (display); | 10278 XtCloseDisplay (display); |
5269 #endif | 10279 #endif |
5270 | 10280 |
5271 dpyinfo->display = 0; | 10281 dpyinfo->display = 0; |
5272 | 10282 |
5273 /* First delete frames whose minibuffers are on frames | 10283 /* First delete frames whose mini-buffers are on frames |
5274 that are on the dead display. */ | 10284 that are on the dead display. */ |
5275 FOR_EACH_FRAME (tail, frame) | 10285 FOR_EACH_FRAME (tail, frame) |
5276 { | 10286 { |
5277 Lisp_Object minibuf_frame; | 10287 Lisp_Object minibuf_frame; |
5278 minibuf_frame | 10288 minibuf_frame |
5283 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo) | 10293 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo) |
5284 Fdelete_frame (frame, Qt); | 10294 Fdelete_frame (frame, Qt); |
5285 } | 10295 } |
5286 | 10296 |
5287 /* Now delete all remaining frames on the dead display. | 10297 /* Now delete all remaining frames on the dead display. |
5288 We are now sure none of these is used as the minibuffer | 10298 We are now sure none of these is used as the mini-buffer |
5289 for another frame that we need to delete. */ | 10299 for another frame that we need to delete. */ |
5290 FOR_EACH_FRAME (tail, frame) | 10300 FOR_EACH_FRAME (tail, frame) |
5291 if (FRAME_X_P (XFRAME (frame)) | 10301 if (FRAME_X_P (XFRAME (frame)) |
5292 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo) | 10302 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo) |
5293 { | 10303 { |
5320 | 10330 |
5321 /* This is the usual handler for X protocol errors. | 10331 /* This is the usual handler for X protocol errors. |
5322 It kills all frames on the display that we got the error for. | 10332 It kills all frames on the display that we got the error for. |
5323 If that was the only one, it prints an error message and kills Emacs. */ | 10333 If that was the only one, it prints an error message and kills Emacs. */ |
5324 | 10334 |
5325 static int | 10335 static void |
5326 x_error_quitter (display, error) | 10336 x_error_quitter (display, error) |
5327 Display *display; | 10337 Display *display; |
5328 XErrorEvent *error; | 10338 XErrorEvent *error; |
5329 { | 10339 { |
5330 char buf[256], buf1[356]; | 10340 char buf[256], buf1[356]; |
5344 static int | 10354 static int |
5345 x_error_handler (display, error) | 10355 x_error_handler (display, error) |
5346 Display *display; | 10356 Display *display; |
5347 XErrorEvent *error; | 10357 XErrorEvent *error; |
5348 { | 10358 { |
5349 char buf[256], buf1[356]; | |
5350 | |
5351 if (! NILP (x_error_message_string)) | 10359 if (! NILP (x_error_message_string)) |
5352 x_error_catcher (display, error); | 10360 x_error_catcher (display, error); |
5353 else | 10361 else |
5354 x_error_quitter (display, error); | 10362 x_error_quitter (display, error); |
10363 return 0; | |
5355 } | 10364 } |
5356 | 10365 |
5357 /* This is the handler for X IO errors, always. | 10366 /* This is the handler for X IO errors, always. |
5358 It kills all frames on the display that we lost touch with. | 10367 It kills all frames on the display that we lost touch with. |
5359 If that was the only one, it prints an error message and kills Emacs. */ | 10368 If that was the only one, it prints an error message and kills Emacs. */ |
5364 { | 10373 { |
5365 char buf[256]; | 10374 char buf[256]; |
5366 | 10375 |
5367 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display)); | 10376 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display)); |
5368 x_connection_closed (display, buf); | 10377 x_connection_closed (display, buf); |
10378 return 0; | |
5369 } | 10379 } |
5370 | 10380 |
5371 /* Changing the font of the frame. */ | 10381 /* Changing the font of the frame. */ |
5372 | 10382 |
5373 /* Give frame F the font named FONTNAME as its default font, and | 10383 /* Give frame F the font named FONTNAME as its default font, and |
5471 | 10481 |
5472 void | 10482 void |
5473 x_calc_absolute_position (f) | 10483 x_calc_absolute_position (f) |
5474 struct frame *f; | 10484 struct frame *f; |
5475 { | 10485 { |
5476 Window win, child; | 10486 Window child; |
5477 int win_x = 0, win_y = 0; | 10487 int win_x = 0, win_y = 0; |
5478 int flags = f->output_data.x->size_hint_flags; | 10488 int flags = f->output_data.x->size_hint_flags; |
5479 int this_window; | 10489 int this_window; |
5480 | 10490 |
5481 /* We have nothing to do if the current position | 10491 /* We have nothing to do if the current position |
5541 - 2 * f->output_data.x->border_width - win_x | 10551 - 2 * f->output_data.x->border_width - win_x |
5542 - PIXEL_WIDTH (f) | 10552 - PIXEL_WIDTH (f) |
5543 + f->output_data.x->left_pos); | 10553 + f->output_data.x->left_pos); |
5544 | 10554 |
5545 if (flags & YNegative) | 10555 if (flags & YNegative) |
5546 /* We used to subtract f->output_data.x->menubar_height here | 10556 { |
5547 in the toolkit case, but PIXEL_HEIGHT already includes that. */ | 10557 int menubar_height = 0; |
5548 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height | 10558 |
5549 - 2 * f->output_data.x->border_width - win_y | 10559 #ifdef USE_X_TOOLKIT |
5550 - PIXEL_HEIGHT (f) | 10560 if (f->output_data.x->menubar_widget) |
5551 + f->output_data.x->top_pos); | 10561 menubar_height |
10562 = (f->output_data.x->menubar_widget->core.height | |
10563 + f->output_data.x->menubar_widget->core.border_width); | |
10564 #endif | |
10565 | |
10566 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height | |
10567 - 2 * f->output_data.x->border_width | |
10568 - win_y | |
10569 - PIXEL_HEIGHT (f) | |
10570 - menubar_height | |
10571 + f->output_data.x->top_pos); | |
10572 } | |
5552 | 10573 |
5553 /* The left_pos and top_pos | 10574 /* The left_pos and top_pos |
5554 are now relative to the top and left screen edges, | 10575 are now relative to the top and left screen edges, |
5555 so the flags should correspond. */ | 10576 so the flags should correspond. */ |
5556 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative); | 10577 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative); |
5618 x_set_window_size (f, change_gravity, cols, rows) | 10639 x_set_window_size (f, change_gravity, cols, rows) |
5619 struct frame *f; | 10640 struct frame *f; |
5620 int change_gravity; | 10641 int change_gravity; |
5621 int cols, rows; | 10642 int cols, rows; |
5622 { | 10643 { |
10644 #ifndef USE_X_TOOLKIT | |
5623 int pixelwidth, pixelheight; | 10645 int pixelwidth, pixelheight; |
5624 int mask; | 10646 #endif |
5625 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
5626 | 10647 |
5627 BLOCK_INPUT; | 10648 BLOCK_INPUT; |
5628 | 10649 |
5629 #ifdef USE_X_TOOLKIT | 10650 #ifdef USE_X_TOOLKIT |
5630 { | 10651 { |
5646 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f) | 10667 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f) |
5647 ? 0 | 10668 ? 0 |
5648 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0 | 10669 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0 |
5649 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f) | 10670 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f) |
5650 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font))); | 10671 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font))); |
10672 f->output_data.x->flags_areas_extra | |
10673 = 2 * FRAME_FLAGS_AREA_WIDTH (f); | |
5651 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols); | 10674 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols); |
5652 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows); | 10675 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows); |
5653 | 10676 |
5654 f->output_data.x->win_gravity = NorthWestGravity; | 10677 f->output_data.x->win_gravity = NorthWestGravity; |
5655 x_wm_set_size_hint (f, (long) 0, 0); | 10678 x_wm_set_size_hint (f, (long) 0, 0); |
5681 XFlush (FRAME_X_DISPLAY (f)); | 10704 XFlush (FRAME_X_DISPLAY (f)); |
5682 | 10705 |
5683 #endif /* not USE_X_TOOLKIT */ | 10706 #endif /* not USE_X_TOOLKIT */ |
5684 | 10707 |
5685 /* If cursor was outside the new size, mark it as off. */ | 10708 /* If cursor was outside the new size, mark it as off. */ |
5686 if (f->phys_cursor_y >= rows | 10709 mark_window_cursors_off (XWINDOW (f->root_window)); |
5687 || f->phys_cursor_x >= cols) | |
5688 { | |
5689 f->phys_cursor_x = 0; | |
5690 f->phys_cursor_y = 0; | |
5691 f->phys_cursor_on = 0; | |
5692 } | |
5693 | 10710 |
5694 /* Clear out any recollection of where the mouse highlighting was, | 10711 /* Clear out any recollection of where the mouse highlighting was, |
5695 since it might be in a place that's outside the new frame size. | 10712 since it might be in a place that's outside the new frame size. |
5696 Actually checking whether it is outside is a pain in the neck, | 10713 Actually checking whether it is outside is a pain in the neck, |
5697 so don't try--just let the highlighting be done afresh with new size. */ | 10714 so don't try--just let the highlighting be done afresh with new size. */ |
5829 | 10846 |
5830 void | 10847 void |
5831 x_make_frame_visible (f) | 10848 x_make_frame_visible (f) |
5832 struct frame *f; | 10849 struct frame *f; |
5833 { | 10850 { |
5834 int mask; | |
5835 Lisp_Object type; | 10851 Lisp_Object type; |
5836 int starting_flags = f->output_data.x->size_hint_flags; | |
5837 int original_top, original_left; | 10852 int original_top, original_left; |
5838 | 10853 |
5839 BLOCK_INPUT; | 10854 BLOCK_INPUT; |
5840 | 10855 |
5841 type = x_icon_type (f); | 10856 type = x_icon_type (f); |
5905 && previously_visible) | 10920 && previously_visible) |
5906 { | 10921 { |
5907 Drawable rootw; | 10922 Drawable rootw; |
5908 int x, y; | 10923 int x, y; |
5909 unsigned int width, height, border, depth; | 10924 unsigned int width, height, border, depth; |
5910 | 10925 |
5911 BLOCK_INPUT; | 10926 BLOCK_INPUT; |
5912 | 10927 |
5913 /* On some window managers (Such as FVWM) moving an existing window, | 10928 /* On some window managers (such as FVWM) moving an existing |
5914 even to the same place, causes the window manager to introduce | 10929 window, even to the same place, causes the window manager |
5915 an offset. This can cause the window to move to an unexpected | 10930 to introduce an offset. This can cause the window to move |
5916 location. Check the geometry (A little slow here) and then verify | 10931 to an unexpected location. Check the geometry (a little |
5917 that the window is in the right place. If the window is not in | 10932 slow here) and then verify that the window is in the right |
5918 the right place, move it there, and take the potential window | 10933 place. If the window is not in the right place, move it |
5919 manager hit. */ | 10934 there, and take the potential window manager hit. */ |
5920 | |
5921 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), | 10935 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), |
5922 &rootw, &x, &y, &width, &height, &border, &depth); | 10936 &rootw, &x, &y, &width, &height, &border, &depth); |
5923 | 10937 |
5924 if (original_left != x || original_top != y) | 10938 if (original_left != x || original_top != y) |
5925 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), | 10939 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), |
5962 } | 10976 } |
5963 FRAME_SAMPLE_VISIBILITY (f); | 10977 FRAME_SAMPLE_VISIBILITY (f); |
5964 } | 10978 } |
5965 } | 10979 } |
5966 | 10980 |
5967 /* Change from mapped state to withdrawn state. */ | 10981 /* Change from mapped state to withdrawn state. */ |
5968 | 10982 |
5969 /* Make the frame visible (mapped and not iconified). */ | 10983 /* Make the frame visible (mapped and not iconified). */ |
5970 | 10984 |
5971 void | 10985 void |
5972 x_make_frame_invisible (f) | 10986 x_make_frame_invisible (f) |
5973 struct frame *f; | 10987 struct frame *f; |
5974 { | 10988 { |
5975 int mask; | |
5976 Window window; | 10989 Window window; |
5977 | 10990 |
5978 #ifdef USE_X_TOOLKIT | 10991 #ifdef USE_X_TOOLKIT |
5979 /* Use the frame's outermost window, not the one we normally draw on. */ | 10992 /* Use the frame's outermost window, not the one we normally draw on. */ |
5980 window = XtWindow (f->output_data.x->widget); | 10993 window = XtWindow (f->output_data.x->widget); |
6020 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f)); | 11033 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f)); |
6021 unmap.xunmap.from_configure = False; | 11034 unmap.xunmap.from_configure = False; |
6022 if (! XSendEvent (FRAME_X_DISPLAY (f), | 11035 if (! XSendEvent (FRAME_X_DISPLAY (f), |
6023 DefaultRootWindow (FRAME_X_DISPLAY (f)), | 11036 DefaultRootWindow (FRAME_X_DISPLAY (f)), |
6024 False, | 11037 False, |
6025 SubstructureRedirectMask|SubstructureNotifyMask, | 11038 SubstructureRedirectMaskSubstructureNotifyMask, |
6026 &unmap)) | 11039 &unmap)) |
6027 { | 11040 { |
6028 UNBLOCK_INPUT_RESIGNAL; | 11041 UNBLOCK_INPUT_RESIGNAL; |
6029 error ("Can't notify window manager of withdrawal"); | 11042 error ("Can't notify window manager of withdrawal"); |
6030 } | 11043 } |
6047 x_sync (f); | 11060 x_sync (f); |
6048 | 11061 |
6049 UNBLOCK_INPUT; | 11062 UNBLOCK_INPUT; |
6050 } | 11063 } |
6051 | 11064 |
6052 /* Change window state from mapped to iconified. */ | 11065 /* Change window state from mapped to iconified. */ |
6053 | 11066 |
6054 void | 11067 void |
6055 x_iconify_frame (f) | 11068 x_iconify_frame (f) |
6056 struct frame *f; | 11069 struct frame *f; |
6057 { | 11070 { |
6058 int mask; | |
6059 int result; | 11071 int result; |
6060 Lisp_Object type; | 11072 Lisp_Object type; |
6061 | 11073 |
6062 /* Don't keep the highlight on an invisible frame. */ | 11074 /* Don't keep the highlight on an invisible frame. */ |
6063 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f) | 11075 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f) |
6186 #endif | 11198 #endif |
6187 } | 11199 } |
6188 #endif | 11200 #endif |
6189 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc); | 11201 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc); |
6190 #ifdef USE_X_TOOLKIT | 11202 #ifdef USE_X_TOOLKIT |
6191 XtDestroyWidget (f->output_data.x->widget); | 11203 if (f->output_data.x->widget) |
11204 XtDestroyWidget (f->output_data.x->widget); | |
6192 free_frame_menubar (f); | 11205 free_frame_menubar (f); |
6193 #endif /* USE_X_TOOLKIT */ | 11206 #endif /* USE_X_TOOLKIT */ |
6194 | 11207 |
6195 free_frame_faces (f); | 11208 free_frame_faces (f); |
6196 XFlush (FRAME_X_DISPLAY (f)); | 11209 XFlush (FRAME_X_DISPLAY (f)); |
6197 } | 11210 } |
6198 | 11211 |
6199 if (f->output_data.x->saved_menu_event) | 11212 if (f->output_data.x->saved_menu_event) |
6200 free (f->output_data.x->saved_menu_event); | 11213 xfree (f->output_data.x->saved_menu_event); |
6201 | 11214 |
6202 xfree (f->output_data.x); | 11215 xfree (f->output_data.x); |
6203 f->output_data.x = 0; | 11216 f->output_data.x = 0; |
6204 if (f == dpyinfo->x_focus_frame) | 11217 if (f == dpyinfo->x_focus_frame) |
6205 dpyinfo->x_focus_frame = 0; | 11218 dpyinfo->x_focus_frame = 0; |
6249 Window window = FRAME_X_WINDOW (f); | 11262 Window window = FRAME_X_WINDOW (f); |
6250 #endif /* not USE_X_TOOLKIT */ | 11263 #endif /* not USE_X_TOOLKIT */ |
6251 | 11264 |
6252 /* Setting PMaxSize caused various problems. */ | 11265 /* Setting PMaxSize caused various problems. */ |
6253 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */; | 11266 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */; |
6254 | |
6255 flexlines = f->height; | |
6256 | 11267 |
6257 size_hints.x = f->output_data.x->left_pos; | 11268 size_hints.x = f->output_data.x->left_pos; |
6258 size_hints.y = f->output_data.x->top_pos; | 11269 size_hints.y = f->output_data.x->top_pos; |
6259 | 11270 |
6260 #ifdef USE_X_TOOLKIT | 11271 #ifdef USE_X_TOOLKIT |
6353 if (hints.flags & USSize) | 11364 if (hints.flags & USSize) |
6354 size_hints.flags |= USSize; | 11365 size_hints.flags |= USSize; |
6355 } | 11366 } |
6356 } | 11367 } |
6357 | 11368 |
11369 #ifndef USE_X_TOOLKIT | |
6358 no_read: | 11370 no_read: |
11371 #endif | |
6359 | 11372 |
6360 #ifdef PWinGravity | 11373 #ifdef PWinGravity |
6361 size_hints.win_gravity = f->output_data.x->win_gravity; | 11374 size_hints.win_gravity = f->output_data.x->win_gravity; |
6362 size_hints.flags |= PWinGravity; | 11375 size_hints.flags |= PWinGravity; |
6363 | 11376 |
6374 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints); | 11387 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints); |
6375 #endif | 11388 #endif |
6376 } | 11389 } |
6377 | 11390 |
6378 /* Used for IconicState or NormalState */ | 11391 /* Used for IconicState or NormalState */ |
11392 | |
6379 void | 11393 void |
6380 x_wm_set_window_state (f, state) | 11394 x_wm_set_window_state (f, state) |
6381 struct frame *f; | 11395 struct frame *f; |
6382 int state; | 11396 int state; |
6383 { | 11397 { |
6401 struct frame *f; | 11415 struct frame *f; |
6402 int pixmap_id; | 11416 int pixmap_id; |
6403 { | 11417 { |
6404 Pixmap icon_pixmap; | 11418 Pixmap icon_pixmap; |
6405 | 11419 |
6406 #ifdef USE_X_TOOLKIT | 11420 #ifndef USE_X_TOOLKIT |
6407 Window window = XtWindow (f->output_data.x->widget); | |
6408 #else | |
6409 Window window = FRAME_X_WINDOW (f); | 11421 Window window = FRAME_X_WINDOW (f); |
6410 #endif | 11422 #endif |
6411 | 11423 |
6412 if (pixmap_id > 0) | 11424 if (pixmap_id > 0) |
6413 { | 11425 { |
6463 | 11475 |
6464 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints); | 11476 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints); |
6465 } | 11477 } |
6466 | 11478 |
6467 | 11479 |
6468 /* Interface to fontset handler. */ | 11480 /*********************************************************************** |
11481 Fonts | |
11482 ***********************************************************************/ | |
6469 | 11483 |
6470 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */ | 11484 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */ |
11485 | |
6471 struct font_info * | 11486 struct font_info * |
6472 x_get_font_info (f, font_idx) | 11487 x_get_font_info (f, font_idx) |
6473 FRAME_PTR f; | 11488 FRAME_PTR f; |
6474 int font_idx; | 11489 int font_idx; |
6475 { | 11490 { |
6488 FRAME_PTR f; | 11503 FRAME_PTR f; |
6489 Lisp_Object pattern; | 11504 Lisp_Object pattern; |
6490 int size; | 11505 int size; |
6491 int maxnames; | 11506 int maxnames; |
6492 { | 11507 { |
6493 Lisp_Object list = Qnil, patterns, newlist = Qnil, key, tem, second_best; | 11508 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil; |
11509 Lisp_Object tem, second_best; | |
6494 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display; | 11510 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display; |
6495 int try_XLoadQueryFont = 0; | 11511 int try_XLoadQueryFont = 0; |
6496 int count; | 11512 int count; |
6497 | 11513 |
6498 patterns = Fassoc (pattern, Valternate_fontname_alist); | 11514 patterns = Fassoc (pattern, Valternate_fontname_alist); |
6595 | 11611 |
6596 /* Make a list of all the fonts we got back. | 11612 /* Make a list of all the fonts we got back. |
6597 Store that in the font cache for the display. */ | 11613 Store that in the font cache for the display. */ |
6598 for (i = 0; i < num_fonts; i++) | 11614 for (i = 0; i < num_fonts; i++) |
6599 { | 11615 { |
11616 int width = 0; | |
6600 char *p = names[i]; | 11617 char *p = names[i]; |
6601 int average_width = -1, dashes = 0, width = 0; | 11618 int average_width = -1, dashes = 0; |
6602 | 11619 |
6603 /* Count the number of dashes in NAMES[I]. If there are | 11620 /* Count the number of dashes in NAMES[I]. If there are |
6604 14 dashes, and the field value following 12th dash | 11621 14 dashes, and the field value following 12th dash |
6605 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which | 11622 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which |
6606 is usually too ugly to be used for editing. Let's | 11623 is usually too ugly to be used for editing. Let's |
6607 ignore it. */ | 11624 ignore it. */ |
6689 : make_number (thisinfo->max_bounds.width)); | 11706 : make_number (thisinfo->max_bounds.width)); |
6690 XFreeFont (dpy, thisinfo); | 11707 XFreeFont (dpy, thisinfo); |
6691 } | 11708 } |
6692 else | 11709 else |
6693 /* For unknown reason, the previous call of XListFont had | 11710 /* For unknown reason, the previous call of XListFont had |
6694 retruned a font which can't be opened. Record the size | 11711 returned a font which can't be opened. Record the size |
6695 as 0 not to try to open it again. */ | 11712 as 0 not to try to open it again. */ |
6696 XCONS (tem)->cdr = make_number (0); | 11713 XCONS (tem)->cdr = make_number (0); |
6697 } | 11714 } |
6698 | 11715 |
6699 found_size = XINT (XCONS (tem)->cdr); | 11716 found_size = XINT (XCONS (tem)->cdr); |
6727 } | 11744 } |
6728 | 11745 |
6729 return newlist; | 11746 return newlist; |
6730 } | 11747 } |
6731 | 11748 |
11749 | |
11750 #if GLYPH_DEBUG | |
11751 | |
11752 /* Check that FONT is valid on frame F. It is if it can be found in F's | |
11753 font table. */ | |
11754 | |
11755 static void | |
11756 x_check_font (f, font) | |
11757 struct frame *f; | |
11758 XFontStruct *font; | |
11759 { | |
11760 int i; | |
11761 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
11762 | |
11763 xassert (font != NULL); | |
11764 | |
11765 for (i = 0; i < dpyinfo->n_fonts; i++) | |
11766 if (dpyinfo->font_table[i].name | |
11767 && font == dpyinfo->font_table[i].font) | |
11768 break; | |
11769 | |
11770 xassert (i < dpyinfo->n_fonts); | |
11771 } | |
11772 | |
11773 #endif /* GLYPH_DEBUG != 0 */ | |
11774 | |
11775 /* Set *W to the minimum width, *H to the minimum font height of FONT. | |
11776 Note: There are (broken) X fonts out there with invalid XFontStruct | |
11777 min_bounds contents. For example, handa@etl.go.jp reports that | |
11778 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts | |
11779 have font->min_bounds.width == 0. */ | |
11780 | |
11781 static INLINE void | |
11782 x_font_min_bounds (font, w, h) | |
11783 XFontStruct *font; | |
11784 int *w, *h; | |
11785 { | |
11786 *h = FONT_HEIGHT (font); | |
11787 *w = font->min_bounds.width; | |
11788 | |
11789 /* Try to handle the case where FONT->min_bounds has invalid | |
11790 contents. Since the only font known to have invalid min_bounds | |
11791 is fixed-width, use max_bounds if min_bounds seems to be invalid. */ | |
11792 if (*w <= 0) | |
11793 *w = font->max_bounds.width; | |
11794 } | |
11795 | |
11796 | |
11797 /* Compute the smallest character width and smallest font height over | |
11798 all fonts available on frame F. Set the members smallest_char_width | |
11799 and smallest_font_height in F's x_display_info structure to | |
11800 the values computed. Value is non-zero if smallest_font_height or | |
11801 smallest_char_width become smaller than they were before. */ | |
11802 | |
11803 static int | |
11804 x_compute_min_glyph_bounds (f) | |
11805 struct frame *f; | |
11806 { | |
11807 int i; | |
11808 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
11809 XFontStruct *font; | |
11810 int old_width = dpyinfo->smallest_char_width; | |
11811 int old_height = dpyinfo->smallest_font_height; | |
11812 | |
11813 dpyinfo->smallest_font_height = 100000; | |
11814 dpyinfo->smallest_char_width = 100000; | |
11815 | |
11816 for (i = 0; i < dpyinfo->n_fonts; ++i) | |
11817 if (dpyinfo->font_table[i].name) | |
11818 { | |
11819 struct font_info *fontp = dpyinfo->font_table + i; | |
11820 int w, h; | |
11821 | |
11822 font = (XFontStruct *) fontp->font; | |
11823 xassert (font != (XFontStruct *) ~0); | |
11824 x_font_min_bounds (font, &w, &h); | |
11825 | |
11826 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h); | |
11827 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w); | |
11828 } | |
11829 | |
11830 xassert (dpyinfo->smallest_char_width > 0 | |
11831 && dpyinfo->smallest_font_height > 0); | |
11832 | |
11833 return (dpyinfo->n_fonts == 1 | |
11834 || dpyinfo->smallest_char_width < old_width | |
11835 || dpyinfo->smallest_font_height < old_height); | |
11836 } | |
11837 | |
11838 | |
6732 /* Load font named FONTNAME of the size SIZE for frame F, and return a | 11839 /* Load font named FONTNAME of the size SIZE for frame F, and return a |
6733 pointer to the structure font_info while allocating it dynamically. | 11840 pointer to the structure font_info while allocating it dynamically. |
6734 If SIZE is 0, load any size of font. | 11841 If SIZE is 0, load any size of font. |
6735 If loading is failed, return NULL. */ | 11842 If loading is failed, return NULL. */ |
6736 | 11843 |
6754 Lisp_Object tail; | 11861 Lisp_Object tail; |
6755 int i; | 11862 int i; |
6756 | 11863 |
6757 for (i = 0; i < dpyinfo->n_fonts; i++) | 11864 for (i = 0; i < dpyinfo->n_fonts; i++) |
6758 for (tail = font_names; CONSP (tail); tail = XCONS (tail)->cdr) | 11865 for (tail = font_names; CONSP (tail); tail = XCONS (tail)->cdr) |
6759 if (!strcmp (dpyinfo->font_table[i].name, | 11866 if (dpyinfo->font_table[i].name |
6760 XSTRING (XCONS (tail)->car)->data) | 11867 && (!strcmp (dpyinfo->font_table[i].name, |
6761 || !strcmp (dpyinfo->font_table[i].full_name, | 11868 XSTRING (XCONS (tail)->car)->data) |
6762 XSTRING (XCONS (tail)->car)->data)) | 11869 || !strcmp (dpyinfo->font_table[i].full_name, |
11870 XSTRING (XCONS (tail)->car)->data))) | |
6763 return (dpyinfo->font_table + i); | 11871 return (dpyinfo->font_table + i); |
6764 } | 11872 } |
6765 | 11873 |
6766 /* Load the font and add it to the table. */ | 11874 /* Load the font and add it to the table. */ |
6767 { | 11875 { |
6768 char *full_name; | 11876 char *full_name; |
6769 XFontStruct *font; | 11877 XFontStruct *font; |
6770 struct font_info *fontp; | 11878 struct font_info *fontp; |
6771 unsigned long value; | 11879 unsigned long value; |
11880 int i; | |
6772 | 11881 |
6773 /* If we have found fonts by x_list_font, load one of them. If | 11882 /* If we have found fonts by x_list_font, load one of them. If |
6774 not, we still try to load a font by the name given as FONTNAME | 11883 not, we still try to load a font by the name given as FONTNAME |
6775 because XListFonts (called in x_list_font) of some X server has | 11884 because XListFonts (called in x_list_font) of some X server has |
6776 a bug of not finding a font even if the font surely exists and | 11885 a bug of not finding a font even if the font surely exists and |
6791 x_uncatch_errors (FRAME_X_DISPLAY (f), count); | 11900 x_uncatch_errors (FRAME_X_DISPLAY (f), count); |
6792 UNBLOCK_INPUT; | 11901 UNBLOCK_INPUT; |
6793 if (!font) | 11902 if (!font) |
6794 return NULL; | 11903 return NULL; |
6795 | 11904 |
6796 /* Do we need to create the table? */ | 11905 /* Find a free slot in the font table. */ |
6797 if (dpyinfo->font_table_size == 0) | 11906 for (i = 0; i < dpyinfo->n_fonts; ++i) |
11907 if (dpyinfo->font_table[i].name == NULL) | |
11908 break; | |
11909 | |
11910 /* If no free slot found, maybe enlarge the font table. */ | |
11911 if (i == dpyinfo->n_fonts | |
11912 && dpyinfo->n_fonts == dpyinfo->font_table_size) | |
6798 { | 11913 { |
6799 dpyinfo->font_table_size = 16; | 11914 int sz; |
11915 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size); | |
11916 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table; | |
6800 dpyinfo->font_table | 11917 dpyinfo->font_table |
6801 = (struct font_info *) xmalloc (dpyinfo->font_table_size | 11918 = (struct font_info *) xrealloc (dpyinfo->font_table, sz); |
6802 * sizeof (struct font_info)); | |
6803 } | 11919 } |
6804 /* Do we need to grow the table? */ | 11920 |
6805 else if (dpyinfo->n_fonts | 11921 fontp = dpyinfo->font_table + i; |
6806 >= dpyinfo->font_table_size) | 11922 if (i == dpyinfo->n_fonts) |
6807 { | 11923 ++dpyinfo->n_fonts; |
6808 dpyinfo->font_table_size *= 2; | |
6809 dpyinfo->font_table | |
6810 = (struct font_info *) xrealloc (dpyinfo->font_table, | |
6811 (dpyinfo->font_table_size | |
6812 * sizeof (struct font_info))); | |
6813 } | |
6814 | |
6815 fontp = dpyinfo->font_table + dpyinfo->n_fonts; | |
6816 | 11924 |
6817 /* Now fill in the slots of *FONTP. */ | 11925 /* Now fill in the slots of *FONTP. */ |
6818 BLOCK_INPUT; | 11926 BLOCK_INPUT; |
6819 fontp->font = font; | 11927 fontp->font = font; |
6820 fontp->font_idx = dpyinfo->n_fonts; | 11928 fontp->font_idx = i; |
6821 fontp->name = (char *) xmalloc (strlen (fontname) + 1); | 11929 fontp->name = (char *) xmalloc (strlen (fontname) + 1); |
6822 bcopy (fontname, fontp->name, strlen (fontname) + 1); | 11930 bcopy (fontname, fontp->name, strlen (fontname) + 1); |
6823 | 11931 |
6824 /* Try to get the full name of FONT. Put it in FULL_NAME. */ | 11932 /* Try to get the full name of FONT. Put it in FULL_NAME. */ |
6825 full_name = 0; | 11933 full_name = 0; |
6892 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to | 12000 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to |
6893 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F, | 12001 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F, |
6894 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, | 12002 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, |
6895 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or | 12003 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or |
6896 2:0xA020..0xFF7F). For the moment, we don't know which charset | 12004 2:0xA020..0xFF7F). For the moment, we don't know which charset |
6897 uses this font. So, we set informatoin in fontp->encoding[1] | 12005 uses this font. So, we set information in fontp->encoding[1] |
6898 which is never used by any charset. If mapping can't be | 12006 which is never used by any charset. If mapping can't be |
6899 decided, set FONT_ENCODING_NOT_DECIDED. */ | 12007 decided, set FONT_ENCODING_NOT_DECIDED. */ |
6900 fontp->encoding[1] | 12008 fontp->encoding[1] |
6901 = (font->max_byte1 == 0 | 12009 = (font->max_byte1 == 0 |
6902 /* 1-byte font */ | 12010 /* 1-byte font */ |
6928 ? (long) value : 0); | 12036 ? (long) value : 0); |
6929 fontp->default_ascent | 12037 fontp->default_ascent |
6930 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value) | 12038 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value) |
6931 ? (long) value : 0); | 12039 ? (long) value : 0); |
6932 | 12040 |
12041 /* Set global flag fonts_changed_p to non-zero if the font loaded | |
12042 has a character with a smaller width than any other character | |
12043 before, or if the font loaded has a smalle>r height than any | |
12044 other font loaded before. If this happens, it will make a | |
12045 glyph matrix reallocation necessary. */ | |
12046 fonts_changed_p = x_compute_min_glyph_bounds (f); | |
6933 UNBLOCK_INPUT; | 12047 UNBLOCK_INPUT; |
6934 dpyinfo->n_fonts++; | |
6935 | |
6936 return fontp; | 12048 return fontp; |
6937 } | 12049 } |
6938 } | 12050 } |
6939 | 12051 |
6940 /* Return a pointer to struct font_info of a font named FONTNAME for frame F. | 12052 |
6941 If no such font is loaded, return NULL. */ | 12053 /* Return a pointer to struct font_info of a font named FONTNAME for |
12054 frame F. If no such font is loaded, return NULL. */ | |
12055 | |
6942 struct font_info * | 12056 struct font_info * |
6943 x_query_font (f, fontname) | 12057 x_query_font (f, fontname) |
6944 struct frame *f; | 12058 struct frame *f; |
6945 register char *fontname; | 12059 register char *fontname; |
6946 { | 12060 { |
6947 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 12061 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
6948 int i; | 12062 int i; |
6949 | 12063 |
6950 for (i = 0; i < dpyinfo->n_fonts; i++) | 12064 for (i = 0; i < dpyinfo->n_fonts; i++) |
6951 if (!strcmp (dpyinfo->font_table[i].name, fontname) | 12065 if (dpyinfo->font_table[i].name |
6952 || !strcmp (dpyinfo->font_table[i].full_name, fontname)) | 12066 && (!strcmp (dpyinfo->font_table[i].name, fontname) |
12067 || !strcmp (dpyinfo->font_table[i].full_name, fontname))) | |
6953 return (dpyinfo->font_table + i); | 12068 return (dpyinfo->font_table + i); |
6954 return NULL; | 12069 return NULL; |
6955 } | 12070 } |
6956 | 12071 |
6957 /* Find a CCL program for a font specified by FONTP, and set the memer | 12072 |
12073 /* Find a CCL program for a font specified by FONTP, and set the member | |
6958 `encoder' of the structure. */ | 12074 `encoder' of the structure. */ |
6959 | 12075 |
6960 void | 12076 void |
6961 x_find_ccl_program (fontp) | 12077 x_find_ccl_program (fontp) |
6962 struct font_info *fontp; | 12078 struct font_info *fontp; |
6994 break; | 12110 break; |
6995 } | 12111 } |
6996 } | 12112 } |
6997 } | 12113 } |
6998 | 12114 |
12115 | |
6999 | 12116 |
7000 /* Initialization. */ | 12117 /*********************************************************************** |
12118 Initialization | |
12119 ***********************************************************************/ | |
7001 | 12120 |
7002 #ifdef USE_X_TOOLKIT | 12121 #ifdef USE_X_TOOLKIT |
7003 static XrmOptionDescRec emacs_options[] = { | 12122 static XrmOptionDescRec emacs_options[] = { |
7004 {"-geometry", ".geometry", XrmoptionSepArg, NULL}, | 12123 {"-geometry", ".geometry", XrmoptionSepArg, NULL}, |
7005 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"}, | 12124 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"}, |
7095 x_term_init (display_name, xrm_option, resource_name) | 12214 x_term_init (display_name, xrm_option, resource_name) |
7096 Lisp_Object display_name; | 12215 Lisp_Object display_name; |
7097 char *xrm_option; | 12216 char *xrm_option; |
7098 char *resource_name; | 12217 char *resource_name; |
7099 { | 12218 { |
7100 Lisp_Object frame; | |
7101 char *defaultvalue; | |
7102 int connection; | 12219 int connection; |
7103 Display *dpy; | 12220 Display *dpy; |
7104 struct x_display_info *dpyinfo; | 12221 struct x_display_info *dpyinfo; |
7105 XrmDatabase xrdb; | 12222 XrmDatabase xrdb; |
7106 | 12223 |
7193 | 12310 |
7194 dpyinfo->kboard->next_kboard = all_kboards; | 12311 dpyinfo->kboard->next_kboard = all_kboards; |
7195 all_kboards = dpyinfo->kboard; | 12312 all_kboards = dpyinfo->kboard; |
7196 /* Don't let the initial kboard remain current longer than necessary. | 12313 /* Don't let the initial kboard remain current longer than necessary. |
7197 That would cause problems if a file loaded on startup tries to | 12314 That would cause problems if a file loaded on startup tries to |
7198 prompt in the minibuffer. */ | 12315 prompt in the mini-buffer. */ |
7199 if (current_kboard == initial_kboard) | 12316 if (current_kboard == initial_kboard) |
7200 current_kboard = dpyinfo->kboard; | 12317 current_kboard = dpyinfo->kboard; |
7201 } | 12318 } |
7202 dpyinfo->kboard->reference_count++; | 12319 dpyinfo->kboard->reference_count++; |
7203 } | 12320 } |
7251 dpyinfo->width = WidthOfScreen (dpyinfo->screen); | 12368 dpyinfo->width = WidthOfScreen (dpyinfo->screen); |
7252 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen); | 12369 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen); |
7253 dpyinfo->grabbed = 0; | 12370 dpyinfo->grabbed = 0; |
7254 dpyinfo->reference_count = 0; | 12371 dpyinfo->reference_count = 0; |
7255 dpyinfo->icon_bitmap_id = -1; | 12372 dpyinfo->icon_bitmap_id = -1; |
12373 dpyinfo->font_table = NULL; | |
7256 dpyinfo->n_fonts = 0; | 12374 dpyinfo->n_fonts = 0; |
7257 dpyinfo->font_table_size = 0; | 12375 dpyinfo->font_table_size = 0; |
7258 dpyinfo->bitmaps = 0; | 12376 dpyinfo->bitmaps = 0; |
7259 dpyinfo->bitmaps_size = 0; | 12377 dpyinfo->bitmaps_size = 0; |
7260 dpyinfo->bitmaps_last = 0; | 12378 dpyinfo->bitmaps_last = 0; |
7261 dpyinfo->scratch_cursor_gc = 0; | 12379 dpyinfo->scratch_cursor_gc = 0; |
7262 dpyinfo->mouse_face_mouse_frame = 0; | 12380 dpyinfo->mouse_face_mouse_frame = 0; |
7263 dpyinfo->mouse_face_deferred_gc = 0; | 12381 dpyinfo->mouse_face_deferred_gc = 0; |
7264 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; | 12382 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; |
7265 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; | 12383 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; |
7266 dpyinfo->mouse_face_face_id = 0; | 12384 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID; |
7267 dpyinfo->mouse_face_window = Qnil; | 12385 dpyinfo->mouse_face_window = Qnil; |
7268 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0; | 12386 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0; |
7269 dpyinfo->mouse_face_defer = 0; | 12387 dpyinfo->mouse_face_defer = 0; |
7270 dpyinfo->x_focus_frame = 0; | 12388 dpyinfo->x_focus_frame = 0; |
7271 dpyinfo->x_focus_event_frame = 0; | 12389 dpyinfo->x_focus_event_frame = 0; |
7272 dpyinfo->x_highlight_frame = 0; | 12390 dpyinfo->x_highlight_frame = 0; |
7273 | 12391 dpyinfo->image_cache = make_image_cache (); |
12392 | |
12393 { | |
12394 int screen_number = XScreenNumberOfScreen (dpyinfo->screen); | |
12395 double pixels = DisplayHeight (dpyinfo->display, screen_number); | |
12396 double mm = DisplayHeightMM (dpyinfo->display, screen_number); | |
12397 dpyinfo->resy = pixels * 25.4 / mm; | |
12398 pixels = DisplayWidth (dpyinfo->display, screen_number); | |
12399 mm = DisplayWidthMM (dpyinfo->display, screen_number); | |
12400 dpyinfo->resx = pixels * 25.4 / mm; | |
12401 } | |
12402 | |
7274 dpyinfo->Xatom_wm_protocols | 12403 dpyinfo->Xatom_wm_protocols |
7275 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False); | 12404 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False); |
7276 dpyinfo->Xatom_wm_take_focus | 12405 dpyinfo->Xatom_wm_take_focus |
7277 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False); | 12406 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False); |
7278 dpyinfo->Xatom_wm_save_yourself | 12407 dpyinfo->Xatom_wm_save_yourself |
7317 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE | 12446 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE |
7318 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False); | 12447 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False); |
7319 dpyinfo->Xatom_MULE_DEFAULT_ASCENT | 12448 dpyinfo->Xatom_MULE_DEFAULT_ASCENT |
7320 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False); | 12449 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False); |
7321 | 12450 |
12451 /* Ghostscript support. */ | |
12452 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False); | |
12453 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False); | |
12454 | |
12455 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR", | |
12456 False); | |
12457 | |
7322 dpyinfo->cut_buffers_initialized = 0; | 12458 dpyinfo->cut_buffers_initialized = 0; |
7323 | 12459 |
7324 connection = ConnectionNumber (dpyinfo->display); | 12460 connection = ConnectionNumber (dpyinfo->display); |
7325 dpyinfo->connection = connection; | 12461 dpyinfo->connection = connection; |
7326 | 12462 |
7331 | 12467 |
7332 dpyinfo->null_pixel | 12468 dpyinfo->null_pixel |
7333 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window, | 12469 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window, |
7334 null_bits, 1, 1, (long) 0, (long) 0, | 12470 null_bits, 1, 1, (long) 0, (long) 0, |
7335 1); | 12471 1); |
12472 } | |
12473 | |
12474 { | |
12475 extern int gray_bitmap_width, gray_bitmap_height; | |
12476 extern unsigned char *gray_bitmap_bits; | |
12477 dpyinfo->gray | |
12478 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window, | |
12479 gray_bitmap_bits, | |
12480 gray_bitmap_width, gray_bitmap_height, | |
12481 (unsigned long) 1, (unsigned long) 0, 1); | |
7336 } | 12482 } |
7337 | 12483 |
7338 #ifdef subprocesses | 12484 #ifdef subprocesses |
7339 /* This is only needed for distinguishing keyboard and process input. */ | 12485 /* This is only needed for distinguishing keyboard and process input. */ |
7340 if (connection != 0) | 12486 if (connection != 0) |
7381 x_uncatch_errors (dpy, count); | 12527 x_uncatch_errors (dpy, count); |
7382 } | 12528 } |
7383 #endif | 12529 #endif |
7384 #endif | 12530 #endif |
7385 | 12531 |
7386 | |
7387 UNBLOCK_INPUT; | 12532 UNBLOCK_INPUT; |
7388 | 12533 |
7389 return dpyinfo; | 12534 return dpyinfo; |
7390 } | 12535 } |
7391 | 12536 |
7445 xfree (dpyinfo); | 12590 xfree (dpyinfo); |
7446 } | 12591 } |
7447 | 12592 |
7448 /* Set up use of X before we make the first connection. */ | 12593 /* Set up use of X before we make the first connection. */ |
7449 | 12594 |
12595 static struct redisplay_interface x_redisplay_interface = | |
12596 { | |
12597 x_produce_glyphs, | |
12598 x_write_glyphs, | |
12599 x_insert_glyphs, | |
12600 x_clear_end_of_line, | |
12601 x_scroll_run, | |
12602 x_after_update_window_line, | |
12603 x_update_window_begin, | |
12604 x_update_window_end, | |
12605 XTcursor_to, | |
12606 x_flush, | |
12607 x_get_glyph_overhangs | |
12608 }; | |
12609 | |
7450 void | 12610 void |
7451 x_initialize () | 12611 x_initialize () |
7452 { | 12612 { |
7453 clear_frame_hook = XTclear_frame; | 12613 rif = &x_redisplay_interface; |
7454 clear_end_of_line_hook = XTclear_end_of_line; | 12614 |
7455 ins_del_lines_hook = XTins_del_lines; | 12615 clear_frame_hook = x_clear_frame; |
7456 change_line_highlight_hook = XTchange_line_highlight; | 12616 ins_del_lines_hook = x_ins_del_lines; |
7457 insert_glyphs_hook = XTinsert_glyphs; | 12617 change_line_highlight_hook = x_change_line_highlight; |
7458 write_glyphs_hook = XTwrite_glyphs; | 12618 delete_glyphs_hook = x_delete_glyphs; |
7459 delete_glyphs_hook = XTdelete_glyphs; | |
7460 ring_bell_hook = XTring_bell; | 12619 ring_bell_hook = XTring_bell; |
7461 reset_terminal_modes_hook = XTreset_terminal_modes; | 12620 reset_terminal_modes_hook = XTreset_terminal_modes; |
7462 set_terminal_modes_hook = XTset_terminal_modes; | 12621 set_terminal_modes_hook = XTset_terminal_modes; |
7463 update_begin_hook = XTupdate_begin; | 12622 update_begin_hook = x_update_begin; |
7464 update_end_hook = XTupdate_end; | 12623 update_end_hook = x_update_end; |
7465 set_terminal_window_hook = XTset_terminal_window; | 12624 set_terminal_window_hook = XTset_terminal_window; |
7466 read_socket_hook = XTread_socket; | 12625 read_socket_hook = XTread_socket; |
7467 frame_up_to_date_hook = XTframe_up_to_date; | 12626 frame_up_to_date_hook = XTframe_up_to_date; |
7468 cursor_to_hook = XTcursor_to; | |
7469 reassert_line_highlight_hook = XTreassert_line_highlight; | 12627 reassert_line_highlight_hook = XTreassert_line_highlight; |
7470 mouse_position_hook = XTmouse_position; | 12628 mouse_position_hook = XTmouse_position; |
7471 frame_rehighlight_hook = XTframe_rehighlight; | 12629 frame_rehighlight_hook = XTframe_rehighlight; |
7472 frame_raise_lower_hook = XTframe_raise_lower; | 12630 frame_raise_lower_hook = XTframe_raise_lower; |
7473 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar; | 12631 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar; |
7474 condemn_scroll_bars_hook = XTcondemn_scroll_bars; | 12632 condemn_scroll_bars_hook = XTcondemn_scroll_bars; |
7475 redeem_scroll_bar_hook = XTredeem_scroll_bar; | 12633 redeem_scroll_bar_hook = XTredeem_scroll_bar; |
7476 judge_scroll_bars_hook = XTjudge_scroll_bars; | 12634 judge_scroll_bars_hook = XTjudge_scroll_bars; |
12635 estimate_mode_line_height_hook = x_estimate_mode_line_height; | |
7477 | 12636 |
7478 scroll_region_ok = 1; /* we'll scroll partial frames */ | 12637 scroll_region_ok = 1; /* we'll scroll partial frames */ |
7479 char_ins_del_ok = 0; /* just as fast to write the line */ | 12638 char_ins_del_ok = 0; /* just as fast to write the line */ |
7480 line_ins_del_ok = 1; /* we'll just blt 'em */ | 12639 line_ins_del_ok = 1; /* we'll just blt 'em */ |
7481 fast_clear_end_of_line = 1; /* X does this well */ | 12640 fast_clear_end_of_line = 1; /* X does this well */ |
7482 memory_below_frame = 0; /* we don't remember what scrolls | 12641 memory_below_frame = 0; /* we don't remember what scrolls |
7483 off the bottom */ | 12642 off the bottom */ |
7484 baud_rate = 19200; | 12643 baud_rate = 19200; |
7485 | 12644 |
7486 x_noop_count = 0; | 12645 x_noop_count = 0; |
7487 | 12646 last_toolbar_item = -1; |
12647 any_help_event_p = 0; | |
12648 | |
7488 /* Try to use interrupt input; if we can't, then start polling. */ | 12649 /* Try to use interrupt input; if we can't, then start polling. */ |
7489 Fset_input_mode (Qt, Qnil, Qt, Qnil); | 12650 Fset_input_mode (Qt, Qnil, Qt, Qnil); |
7490 | 12651 |
7491 #ifdef USE_X_TOOLKIT | 12652 #ifdef USE_X_TOOLKIT |
7492 XtToolkitInitialize (); | 12653 XtToolkitInitialize (); |
7497 /* Note that there is no real way portable across R3/R4 to get the | 12658 /* Note that there is no real way portable across R3/R4 to get the |
7498 original error handler. */ | 12659 original error handler. */ |
7499 XSetErrorHandler (x_error_handler); | 12660 XSetErrorHandler (x_error_handler); |
7500 XSetIOErrorHandler (x_io_error_quitter); | 12661 XSetIOErrorHandler (x_io_error_quitter); |
7501 | 12662 |
7502 /* Disable Window Change signals; they are handled by X events. */ | 12663 /* Disable Window Change signals; they are handled by X events. */ |
7503 #ifdef SIGWINCH | 12664 #ifdef SIGWINCH |
7504 signal (SIGWINCH, SIG_DFL); | 12665 signal (SIGWINCH, SIG_DFL); |
7505 #endif /* ! defined (SIGWINCH) */ | 12666 #endif /* ! defined (SIGWINCH) */ |
7506 | 12667 |
7507 signal (SIGPIPE, x_connection_signal); | 12668 signal (SIGPIPE, x_connection_signal); |
7508 } | 12669 } |
7509 | 12670 |
12671 | |
7510 void | 12672 void |
7511 syms_of_xterm () | 12673 syms_of_xterm () |
7512 { | 12674 { |
7513 staticpro (&x_error_message_string); | 12675 staticpro (&x_error_message_string); |
7514 x_error_message_string = Qnil; | 12676 x_error_message_string = Qnil; |
7522 staticpro (&Qvendor_specific_keysyms); | 12684 staticpro (&Qvendor_specific_keysyms); |
7523 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms"); | 12685 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms"); |
7524 | 12686 |
7525 staticpro (&last_mouse_press_frame); | 12687 staticpro (&last_mouse_press_frame); |
7526 last_mouse_press_frame = Qnil; | 12688 last_mouse_press_frame = Qnil; |
12689 | |
12690 staticpro (&help_echo); | |
12691 help_echo = Qnil; | |
12692 staticpro (&previous_help_echo); | |
12693 previous_help_echo = Qnil; | |
12694 | |
12695 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p, | |
12696 "*Non-nil means draw block cursor as wide as the glyph under it.\n\ | |
12697 For example, if a block cursor is over a tab, it will be drawn as\n\ | |
12698 wide as that tab on the display."); | |
12699 x_stretch_cursor_p = 0; | |
12700 | |
12701 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p, | |
12702 "If not nil, Emacs uses toolkit scroll bars."); | |
12703 #if USE_TOOLKIT_SCROLL_BARS | |
12704 x_toolkit_scroll_bars_p = 1; | |
12705 #else | |
12706 x_toolkit_scroll_bars_p = 0; | |
12707 #endif | |
12708 | |
12709 defsubr (&Sxt_process_timeouts); | |
12710 staticpro (&last_mouse_motion_frame); | |
12711 last_mouse_motion_frame = Qnil; | |
7527 } | 12712 } |
7528 | 12713 |
7529 #endif /* not HAVE_X_WINDOWS */ | 12714 #endif /* not HAVE_X_WINDOWS */ |
12715 |