]> code.delx.au - gnu-emacs/blob - src/macterm.c
(get_window_cursor_type): New arg ACTIVE_CURSOR.
[gnu-emacs] / src / macterm.c
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 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 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 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 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
22
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "lisp.h"
28 #include "charset.h"
29 #include "blockinput.h"
30
31 #include "macterm.h"
32
33 #ifndef MAC_OSX
34 #include <alloca.h>
35 #endif
36
37 #ifdef MAC_OSX
38 #undef mktime
39 #undef DEBUG
40 #undef free
41 #undef malloc
42 #undef realloc
43 /* Macros max and min defined in lisp.h conflict with those in
44 precompiled header Carbon.h. */
45 #undef max
46 #undef min
47 #undef init_process
48 #include <Carbon/Carbon.h>
49 #undef free
50 #define free unexec_free
51 #undef malloc
52 #define malloc unexec_malloc
53 #undef realloc
54 #define realloc unexec_realloc
55 #undef min
56 #define min(a, b) ((a) < (b) ? (a) : (b))
57 #undef max
58 #define max(a, b) ((a) > (b) ? (a) : (b))
59 #undef init_process
60 #define init_process emacs_init_process
61 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
62 obtain events from the event queue. If set to 0, WaitNextEvent is
63 used instead. */
64 #define USE_CARBON_EVENTS 1
65 #else /* not MAC_OSX */
66 #include <Quickdraw.h>
67 #include <ToolUtils.h>
68 #include <Sound.h>
69 #include <Events.h>
70 #include <Script.h>
71 #include <Resources.h>
72 #include <Fonts.h>
73 #include <TextUtils.h>
74 #include <LowMem.h>
75 #include <Controls.h>
76 #if defined (__MRC__) || (__MSL__ >= 0x6000)
77 #include <ControlDefinitions.h>
78 #endif
79 #include <Gestalt.h>
80
81 #if __profile__
82 #include <profiler.h>
83 #endif
84 #endif /* not MAC_OSX */
85
86 #include "systty.h"
87 #include "systime.h"
88 #include "atimer.h"
89 #include "keymap.h"
90
91 #include <ctype.h>
92 #include <errno.h>
93 #include <setjmp.h>
94 #include <sys/stat.h>
95
96 #include "keyboard.h"
97 #include "frame.h"
98 #include "dispextern.h"
99 #include "fontset.h"
100 #include "termhooks.h"
101 #include "termopts.h"
102 #include "termchar.h"
103 #include "gnu.h"
104 #include "disptab.h"
105 #include "buffer.h"
106 #include "window.h"
107 #include "intervals.h"
108 #include "composite.h"
109 #include "coding.h"
110
111 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
112
113 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
114 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
115 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
116 #define macShiftKey (shiftKey)
117 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
118 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
119 : controlKey)
120 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
121
122 \f
123 /* Fringe bitmaps. */
124
125 enum fringe_bitmap_type
126 {
127 NO_FRINGE_BITMAP,
128 LEFT_TRUNCATION_BITMAP,
129 RIGHT_TRUNCATION_BITMAP,
130 OVERLAY_ARROW_BITMAP,
131 CONTINUED_LINE_BITMAP,
132 CONTINUATION_LINE_BITMAP,
133 ZV_LINE_BITMAP
134 };
135
136 /* Bitmap drawn to indicate lines not displaying text if
137 `indicate-empty-lines' is non-nil. */
138
139 #define zv_width 8
140 #define zv_height 72
141 #define zv_period 3
142 static unsigned char zv_bits[] = {
143 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
144 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
145 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
146 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
147 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
148 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
149 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
150 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
151
152 /* An arrow like this: `<-'. */
153
154 #define left_width 8
155 #define left_height 8
156 static unsigned char left_bits[] = {
157 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
158
159 /* Right truncation arrow bitmap `->'. */
160
161 #define right_width 8
162 #define right_height 8
163 static unsigned char right_bits[] = {
164 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
165
166 /* Marker for continued lines. */
167
168 #define continued_width 8
169 #define continued_height 8
170 static unsigned char continued_bits[] = {
171 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
172
173 /* Marker for continuation lines. */
174
175 #define continuation_width 8
176 #define continuation_height 8
177 static unsigned char continuation_bits[] = {
178 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
179
180 /* Overlay arrow bitmap. */
181
182 #if 0
183 /* A bomb. */
184 #define ov_width 8
185 #define ov_height 8
186 static unsigned char ov_bits[] = {
187 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
188 #else
189 /* A triangular arrow. */
190 #define ov_width 8
191 #define ov_height 8
192 static unsigned char ov_bits[] = {
193 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
194 #endif
195
196 extern Lisp_Object Qhelp_echo;
197
198 \f
199 /* Non-nil means Emacs uses toolkit scroll bars. */
200
201 Lisp_Object Vx_toolkit_scroll_bars;
202
203 /* If a string, XTread_socket generates an event to display that string.
204 (The display is done in read_char.) */
205
206 static Lisp_Object help_echo;
207 static Lisp_Object help_echo_window;
208 static Lisp_Object help_echo_object;
209 static int help_echo_pos;
210
211 /* Temporary variable for XTread_socket. */
212
213 static Lisp_Object previous_help_echo;
214
215 /* Non-zero means that a HELP_EVENT has been generated since Emacs
216 start. */
217
218 static int any_help_event_p;
219
220 /* Non-zero means autoselect window with the mouse cursor. */
221
222 int x_autoselect_window_p;
223
224 /* Non-zero means draw block and hollow cursor as wide as the glyph
225 under it. For example, if a block cursor is over a tab, it will be
226 drawn as wide as that tab on the display. */
227
228 int x_stretch_cursor_p;
229
230 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
231
232 int x_use_underline_position_properties;
233
234 /* This is a chain of structures for all the X displays currently in
235 use. */
236
237 struct x_display_info *x_display_list;
238
239 /* This is a list of cons cells, each of the form (NAME
240 . FONT-LIST-CACHE), one for each element of x_display_list and in
241 the same order. NAME is the name of the frame. FONT-LIST-CACHE
242 records previous values returned by x-list-fonts. */
243
244 Lisp_Object x_display_name_list;
245
246 /* This is display since Mac does not support multiple ones. */
247 struct mac_display_info one_mac_display_info;
248
249 /* Frame being updated by update_frame. This is declared in term.c.
250 This is set by update_begin and looked at by all the XT functions.
251 It is zero while not inside an update. In that case, the XT
252 functions assume that `selected_frame' is the frame to apply to. */
253
254 extern struct frame *updating_frame;
255
256 extern int waiting_for_input;
257
258 /* This is a frame waiting to be auto-raised, within XTread_socket. */
259
260 struct frame *pending_autoraise_frame;
261
262 /* Nominal cursor position -- where to draw output.
263 HPOS and VPOS are window relative glyph matrix coordinates.
264 X and Y are window relative pixel coordinates. */
265
266 struct cursor_pos output_cursor;
267
268 /* Non-zero means user is interacting with a toolkit scroll bar. */
269
270 static int toolkit_scroll_bar_interaction;
271
272 /* Mouse movement.
273
274 Formerly, we used PointerMotionHintMask (in standard_event_mask)
275 so that we would have to call XQueryPointer after each MotionNotify
276 event to ask for another such event. However, this made mouse tracking
277 slow, and there was a bug that made it eventually stop.
278
279 Simply asking for MotionNotify all the time seems to work better.
280
281 In order to avoid asking for motion events and then throwing most
282 of them away or busy-polling the server for mouse positions, we ask
283 the server for pointer motion hints. This means that we get only
284 one event per group of mouse movements. "Groups" are delimited by
285 other kinds of events (focus changes and button clicks, for
286 example), or by XQueryPointer calls; when one of these happens, we
287 get another MotionNotify event the next time the mouse moves. This
288 is at least as efficient as getting motion events when mouse
289 tracking is on, and I suspect only negligibly worse when tracking
290 is off. */
291
292 /* Where the mouse was last time we reported a mouse event. */
293
294 FRAME_PTR last_mouse_frame;
295 static Rect last_mouse_glyph;
296 static Lisp_Object last_mouse_press_frame;
297
298 /* The scroll bar in which the last X motion event occurred.
299
300 If the last X motion event occurred in a scroll bar, we set this so
301 XTmouse_position can know whether to report a scroll bar motion or
302 an ordinary motion.
303
304 If the last X motion event didn't occur in a scroll bar, we set
305 this to Qnil, to tell XTmouse_position to return an ordinary motion
306 event. */
307
308 static Lisp_Object last_mouse_scroll_bar;
309
310 /* This is a hack. We would really prefer that XTmouse_position would
311 return the time associated with the position it returns, but there
312 doesn't seem to be any way to wrest the time-stamp from the server
313 along with the position query. So, we just keep track of the time
314 of the last movement we received, and return that in hopes that
315 it's somewhat accurate. */
316
317 static Time last_mouse_movement_time;
318
319 enum mouse_tracking_type {
320 mouse_tracking_none,
321 mouse_tracking_mouse_movement,
322 mouse_tracking_scroll_bar
323 };
324
325 enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
326
327 struct scroll_bar *tracked_scroll_bar = NULL;
328
329 /* Incremented by XTread_socket whenever it really tries to read
330 events. */
331
332 #ifdef __STDC__
333 static int volatile input_signal_count;
334 #else
335 static int input_signal_count;
336 #endif
337
338 /* Used locally within XTread_socket. */
339
340 static int x_noop_count;
341
342 /* Initial values of argv and argc. */
343
344 extern char **initial_argv;
345 extern int initial_argc;
346
347 extern Lisp_Object Vcommand_line_args, Vsystem_name;
348
349 /* Tells if a window manager is present or not. */
350
351 extern Lisp_Object Vx_no_window_manager;
352
353 extern Lisp_Object Qface, Qmouse_face;
354
355 extern int errno;
356
357 /* A mask of extra modifier bits to put into every keyboard char. */
358
359 extern int extra_keyboard_modifiers;
360
361 static Lisp_Object Qvendor_specific_keysyms;
362
363 #if 0
364 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
365 #endif
366
367 extern Lisp_Object x_icon_type P_ ((struct frame *));
368
369 extern int inhibit_window_system;
370
371 #if __MRC__
372 QDGlobals qd; /* QuickDraw global information structure. */
373 #endif
374
375
376 /* Enumeration for overriding/changing the face to use for drawing
377 glyphs in x_draw_glyphs. */
378
379 enum draw_glyphs_face
380 {
381 DRAW_NORMAL_TEXT,
382 DRAW_INVERSE_VIDEO,
383 DRAW_CURSOR,
384 DRAW_MOUSE_FACE,
385 DRAW_IMAGE_RAISED,
386 DRAW_IMAGE_SUNKEN
387 };
388
389 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
390 struct mac_display_info *mac_display_info_for_display (Display *);
391 static void x_update_window_end P_ ((struct window *, int, int));
392 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
393 static int fast_find_position P_ ((struct window *, int, int *, int *,
394 int *, int *, Lisp_Object));
395 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
396 int *, int *, int *, int *, int));
397 static void set_output_cursor P_ ((struct cursor_pos *));
398 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
399 int *, int *, int *, int));
400 static void note_mode_line_highlight P_ ((struct window *, int, int));
401 static void note_mouse_highlight P_ ((struct frame *, int, int));
402 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
403 static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
404 static void show_mouse_face P_ ((struct x_display_info *,
405 enum draw_glyphs_face));
406 static int cursor_in_mouse_face_p P_ ((struct window *));
407 static int clear_mouse_face P_ ((struct mac_display_info *));
408 static int x_io_error_quitter P_ ((Display *));
409 int x_catch_errors P_ ((Display *));
410 void x_uncatch_errors P_ ((Display *, int));
411 void x_lower_frame P_ ((struct frame *));
412 void x_scroll_bar_clear P_ ((struct frame *));
413 int x_had_errors_p P_ ((Display *));
414 void x_wm_set_size_hint P_ ((struct frame *, long, int));
415 void x_raise_frame P_ ((struct frame *));
416 void x_set_window_size P_ ((struct frame *, int, int, int));
417 void x_wm_set_window_state P_ ((struct frame *, int));
418 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
419 void mac_initialize P_ ((void));
420 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
421 static int x_compute_min_glyph_bounds P_ ((struct frame *));
422 static void x_draw_phys_cursor_glyph P_ ((struct window *,
423 struct glyph_row *,
424 enum draw_glyphs_face));
425 static void x_update_end P_ ((struct frame *));
426 static void XTframe_up_to_date P_ ((struct frame *));
427 static void XTreassert_line_highlight P_ ((int, int));
428 static void x_change_line_highlight P_ ((int, int, int, int));
429 static void XTset_terminal_modes P_ ((void));
430 static void XTreset_terminal_modes P_ ((void));
431 static void XTcursor_to P_ ((int, int, int, int));
432 static void x_write_glyphs P_ ((struct glyph *, int));
433 static void x_clear_end_of_line P_ ((int));
434 static void x_clear_frame P_ ((void));
435 static void x_clear_cursor P_ ((struct window *));
436 static void frame_highlight P_ ((struct frame *));
437 static void frame_unhighlight P_ ((struct frame *));
438 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
439 static void XTframe_rehighlight P_ ((struct frame *));
440 static void x_frame_rehighlight P_ ((struct x_display_info *));
441 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
442 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
443 static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
444 static void expose_frame P_ ((struct frame *, int, int, int, int));
445 static int expose_window_tree P_ ((struct window *, Rect *));
446 static void expose_overlaps P_ ((struct window *, struct glyph_row *,
447 struct glyph_row *));
448 static int expose_window P_ ((struct window *, Rect *));
449 static void expose_area P_ ((struct window *, struct glyph_row *,
450 Rect *, enum glyph_row_area));
451 static int expose_line P_ ((struct window *, struct glyph_row *,
452 Rect *));
453 void x_display_cursor (struct window *, int, int, int, int, int);
454 void x_update_cursor P_ ((struct frame *, int));
455 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
456 static void x_update_window_cursor P_ ((struct window *, int));
457 static void x_erase_phys_cursor P_ ((struct window *));
458 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
459 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
460 enum fringe_bitmap_type, int left_p));
461 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
462 GC, int));
463 static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
464 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
465 static void notice_overwritten_cursor P_ ((struct window *,
466 enum glyph_row_area,
467 int, int, int, int));
468 static void x_flush P_ ((struct frame *f));
469 static void x_update_begin P_ ((struct frame *));
470 static void x_update_window_begin P_ ((struct window *));
471 static void x_draw_vertical_border P_ ((struct window *));
472 static void x_after_update_window_line P_ ((struct glyph_row *));
473 static INLINE void take_vertical_position_into_account P_ ((struct it *));
474 static void x_produce_stretch_glyph P_ ((struct it *));
475
476 static void activate_scroll_bars (FRAME_PTR);
477 static void deactivate_scroll_bars (FRAME_PTR);
478
479 static int is_emacs_window (WindowPtr);
480
481 extern int image_ascent (struct image *, struct face *);
482 void x_set_offset (struct frame *, int, int, int);
483 int x_bitmap_icon (struct frame *, Lisp_Object);
484 void x_make_frame_visible (struct frame *);
485
486 extern void window_scroll (Lisp_Object, int, int, int);
487
488 /* Defined in macmenu.h. */
489 extern void menubar_selection_callback (FRAME_PTR, int);
490 extern void set_frame_menubar (FRAME_PTR, int, int);
491
492 /* X display function emulation */
493
494 /* Structure borrowed from Xlib.h to represent two-byte characters in
495 dumpglyphs. */
496
497 typedef struct {
498 unsigned char byte1;
499 unsigned char byte2;
500 } XChar2b;
501
502 static void
503 XFreePixmap (display, pixmap)
504 Display *display;
505 Pixmap pixmap;
506 {
507 PixMap *p = (PixMap *) pixmap;
508
509 xfree (p->baseAddr);
510 xfree (p);
511 }
512
513
514 /* Set foreground color for subsequent QuickDraw commands. Assume
515 graphic port has already been set. */
516
517 static void
518 mac_set_forecolor (unsigned long color)
519 {
520 RGBColor fg_color;
521
522 fg_color.red = RED_FROM_ULONG (color) * 256;
523 fg_color.green = GREEN_FROM_ULONG (color) * 256;
524 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
525
526 RGBForeColor (&fg_color);
527 }
528
529
530 /* Set background color for subsequent QuickDraw commands. Assume
531 graphic port has already been set. */
532
533 static void
534 mac_set_backcolor (unsigned long color)
535 {
536 RGBColor bg_color;
537
538 bg_color.red = RED_FROM_ULONG (color) * 256;
539 bg_color.green = GREEN_FROM_ULONG (color) * 256;
540 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
541
542 RGBBackColor (&bg_color);
543 }
544
545 /* Set foreground and background color for subsequent QuickDraw
546 commands. Assume that the graphic port has already been set. */
547
548 static void
549 mac_set_colors (GC gc)
550 {
551 mac_set_forecolor (gc->foreground);
552 mac_set_backcolor (gc->background);
553 }
554
555 /* Mac version of XDrawLine. */
556
557 static void
558 XDrawLine (display, w, gc, x1, y1, x2, y2)
559 Display *display;
560 WindowPtr w;
561 GC gc;
562 int x1, y1, x2, y2;
563 {
564 #if TARGET_API_MAC_CARBON
565 SetPort (GetWindowPort (w));
566 #else
567 SetPort (w);
568 #endif
569
570 mac_set_colors (gc);
571
572 MoveTo (x1, y1);
573 LineTo (x2, y2);
574 }
575
576 /* Mac version of XClearArea. */
577
578 void
579 XClearArea (display, w, x, y, width, height, exposures)
580 Display *display;
581 WindowPtr w;
582 int x, y;
583 unsigned int width, height;
584 int exposures;
585 {
586 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
587 Rect r;
588 XGCValues xgc;
589
590 xgc.foreground = mwp->x_compatible.foreground_pixel;
591 xgc.background = mwp->x_compatible.background_pixel;
592
593 #if TARGET_API_MAC_CARBON
594 SetPort (GetWindowPort (w));
595 #else
596 SetPort (w);
597 #endif
598
599 mac_set_colors (&xgc);
600 SetRect (&r, x, y, x + width, y + height);
601
602 EraseRect (&r);
603 }
604
605 /* Mac version of XClearWindow. */
606
607 static void
608 XClearWindow (display, w)
609 Display *display;
610 WindowPtr w;
611 {
612 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
613 XGCValues xgc;
614
615 xgc.foreground = mwp->x_compatible.foreground_pixel;
616 xgc.background = mwp->x_compatible.background_pixel;
617
618 #if TARGET_API_MAC_CARBON
619 SetPort (GetWindowPort (w));
620 #else
621 SetPort (w);
622 #endif
623
624 mac_set_colors (&xgc);
625
626 #if TARGET_API_MAC_CARBON
627 {
628 Rect r;
629
630 GetWindowPortBounds (w, &r);
631 EraseRect (&r);
632 }
633 #else /* not TARGET_API_MAC_CARBON */
634 EraseRect (&(w->portRect));
635 #endif /* not TARGET_API_MAC_CARBON */
636 }
637
638
639 /* Mac replacement for XCopyArea. */
640
641 static void
642 mac_draw_bitmap (display, w, gc, x, y, bitmap)
643 Display *display;
644 WindowPtr w;
645 GC gc;
646 int x, y;
647 BitMap *bitmap;
648 {
649 Rect r;
650
651 #if TARGET_API_MAC_CARBON
652 SetPort (GetWindowPort (w));
653 #else
654 SetPort (w);
655 #endif
656
657 mac_set_colors (gc);
658 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
659
660 #if TARGET_API_MAC_CARBON
661 {
662 PixMapHandle pmh;
663
664 LockPortBits (GetWindowPort (w));
665 pmh = GetPortPixMap (GetWindowPort (w));
666 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
667 UnlockPortBits (GetWindowPort (w));
668 }
669 #else /* not TARGET_API_MAC_CARBON */
670 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
671 #endif /* not TARGET_API_MAC_CARBON */
672 }
673
674
675 /* Mac replacement for XSetClipRectangles. */
676
677 static void
678 mac_set_clip_rectangle (display, w, r)
679 Display *display;
680 WindowPtr w;
681 Rect *r;
682 {
683 #if TARGET_API_MAC_CARBON
684 SetPort (GetWindowPort (w));
685 #else
686 SetPort (w);
687 #endif
688
689 ClipRect (r);
690 }
691
692
693 /* Mac replacement for XSetClipMask. */
694
695 static void
696 mac_reset_clipping (display, w)
697 Display *display;
698 WindowPtr w;
699 {
700 Rect r;
701
702 #if TARGET_API_MAC_CARBON
703 SetPort (GetWindowPort (w));
704 #else
705 SetPort (w);
706 #endif
707
708 SetRect (&r, -32767, -32767, 32767, 32767);
709 ClipRect (&r);
710 }
711
712
713 /* Mac replacement for XCreateBitmapFromBitmapData. */
714
715 static void
716 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
717 BitMap *bitmap;
718 char *bits;
719 int w, h;
720 {
721 int bytes_per_row, i, j;
722
723 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
724 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
725 if (!bitmap->baseAddr)
726 abort ();
727
728 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
729 for (i = 0; i < h; i++)
730 for (j = 0; j < w; j++)
731 if (BitTst (bits, i * w + j))
732 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
733
734 SetRect (&(bitmap->bounds), 0, 0, w, h);
735 }
736
737
738 static void
739 mac_free_bitmap (bitmap)
740 BitMap *bitmap;
741 {
742 xfree (bitmap->baseAddr);
743 }
744
745 /* Mac replacement for XFillRectangle. */
746
747 static void
748 XFillRectangle (display, w, gc, x, y, width, height)
749 Display *display;
750 WindowPtr w;
751 GC gc;
752 int x, y;
753 unsigned int width, height;
754 {
755 Rect r;
756
757 #if TARGET_API_MAC_CARBON
758 SetPort (GetWindowPort (w));
759 #else
760 SetPort (w);
761 #endif
762
763 mac_set_colors (gc);
764 SetRect (&r, x, y, x + width, y + height);
765
766 PaintRect (&r); /* using foreground color of gc */
767 }
768
769
770 /* Mac replacement for XDrawRectangle: dest is a window. */
771
772 static void
773 mac_draw_rectangle (display, w, gc, x, y, width, height)
774 Display *display;
775 WindowPtr w;
776 GC gc;
777 int x, y;
778 unsigned int width, height;
779 {
780 Rect r;
781
782 #if TARGET_API_MAC_CARBON
783 SetPort (GetWindowPort (w));
784 #else
785 SetPort (w);
786 #endif
787
788 mac_set_colors (gc);
789 SetRect (&r, x, y, x + width + 1, y + height + 1);
790
791 FrameRect (&r); /* using foreground color of gc */
792 }
793
794
795 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
796
797 static void
798 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
799 Display *display;
800 Pixmap p;
801 GC gc;
802 int x, y;
803 unsigned int width, height;
804 {
805 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
806 Rect r;
807
808 #if TARGET_API_MAC_CARBON
809 SetPort (GetWindowPort (w));
810 #else
811 SetPort (w);
812 #endif
813
814 mac_set_colors (gc);
815 SetRect (&r, x, y, x + width, y + height);
816
817 FrameRect (&r); /* using foreground color of gc */
818 #endif /* 0 */
819 }
820
821
822 static void
823 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
824 bytes_per_char)
825 Display *display;
826 WindowPtr w;
827 GC gc;
828 int x, y;
829 char *buf;
830 int nchars, mode, bytes_per_char;
831 {
832 #if TARGET_API_MAC_CARBON
833 SetPort (GetWindowPort (w));
834 #else
835 SetPort (w);
836 #endif
837
838 mac_set_colors (gc);
839
840 TextFont (gc->font->mac_fontnum);
841 TextSize (gc->font->mac_fontsize);
842 TextFace (gc->font->mac_fontface);
843 TextMode (mode);
844
845 MoveTo (x, y);
846 DrawText (buf, 0, nchars * bytes_per_char);
847 }
848
849
850 /* Mac replacement for XDrawString. */
851
852 static void
853 XDrawString (display, w, gc, x, y, buf, nchars)
854 Display *display;
855 WindowPtr w;
856 GC gc;
857 int x, y;
858 char *buf;
859 int nchars;
860 {
861 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
862 }
863
864
865 /* Mac replacement for XDrawString16. */
866
867 static void
868 XDrawString16 (display, w, gc, x, y, buf, nchars)
869 Display *display;
870 WindowPtr w;
871 GC gc;
872 int x, y;
873 XChar2b *buf;
874 int nchars;
875 {
876 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
877 2);
878 }
879
880
881 /* Mac replacement for XDrawImageString. */
882
883 static void
884 XDrawImageString (display, w, gc, x, y, buf, nchars)
885 Display *display;
886 WindowPtr w;
887 GC gc;
888 int x, y;
889 char *buf;
890 int nchars;
891 {
892 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
893 }
894
895
896 /* Mac replacement for XDrawString16. */
897
898 static void
899 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
900 Display *display;
901 WindowPtr w;
902 GC gc;
903 int x, y;
904 XChar2b *buf;
905 int nchars;
906 {
907 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
908 2);
909 }
910
911
912 /* Mac replacement for XCopyArea: dest must be window. */
913
914 static void
915 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
916 dest_y)
917 Display *display;
918 Pixmap src;
919 WindowPtr dest;
920 GC gc;
921 int src_x, src_y;
922 unsigned int width, height;
923 int dest_x, dest_y;
924 {
925 Rect src_r, dest_r;
926
927 #if TARGET_API_MAC_CARBON
928 SetPort (GetWindowPort (dest));
929 #else
930 SetPort (dest);
931 #endif
932
933 mac_set_colors (gc);
934
935 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
936 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
937
938 #if TARGET_API_MAC_CARBON
939 {
940 PixMapHandle pmh;
941
942 LockPortBits (GetWindowPort (dest));
943 pmh = GetPortPixMap (GetWindowPort (dest));
944 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
945 UnlockPortBits (GetWindowPort (dest));
946 }
947 #else /* not TARGET_API_MAC_CARBON */
948 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
949 #endif /* not TARGET_API_MAC_CARBON */
950 }
951
952
953 #if 0
954 /* Convert a pair of local coordinates to global (screen) coordinates.
955 Assume graphic port has been properly set. */
956 static void
957 local_to_global_coord (short *h, short *v)
958 {
959 Point p;
960
961 p.h = *h;
962 p.v = *v;
963
964 LocalToGlobal (&p);
965
966 *h = p.h;
967 *v = p.v;
968 }
969 #endif
970
971 /* Mac replacement for XCopyArea: used only for scrolling. */
972
973 static void
974 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
975 Display *display;
976 WindowPtr w;
977 GC gc;
978 int src_x, src_y;
979 unsigned int width, height;
980 int dest_x, dest_y;
981 {
982 #if TARGET_API_MAC_CARBON
983 Rect gw_r, src_r, dest_r;
984 PixMapHandle pmh;
985
986 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
987 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
988
989 SetPort (GetWindowPort (w));
990
991 ForeColor (blackColor);
992 BackColor (whiteColor);
993
994 LockPortBits (GetWindowPort (w));
995 pmh = GetPortPixMap (GetWindowPort (w));
996 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
997 UnlockPortBits (GetWindowPort (w));
998
999 mac_set_colors (gc);
1000 #else /* not TARGET_API_MAC_CARBON */
1001 Rect src_r, dest_r;
1002
1003 SetPort (w);
1004 #if 0
1005 mac_set_colors (gc);
1006 #endif
1007
1008 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1009 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1010
1011 #if 0
1012 /* Need to use global coordinates and screenBits since src and dest
1013 areas overlap in general. */
1014 local_to_global_coord (&src_r.left, &src_r.top);
1015 local_to_global_coord (&src_r.right, &src_r.bottom);
1016 local_to_global_coord (&dest_r.left, &dest_r.top);
1017 local_to_global_coord (&dest_r.right, &dest_r.bottom);
1018
1019 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
1020 #else
1021 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1022 color mapping in CopyBits. Otherwise, it will be slow. */
1023 ForeColor (blackColor);
1024 BackColor (whiteColor);
1025 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1026
1027 mac_set_colors (gc);
1028 #endif
1029 #endif /* not TARGET_API_MAC_CARBON */
1030 }
1031
1032
1033 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1034
1035 static void
1036 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1037 dest_x, dest_y)
1038 Display *display;
1039 Pixmap src;
1040 Pixmap dest;
1041 GC gc;
1042 int src_x, src_y;
1043 unsigned int width, height;
1044 int dest_x, dest_y;
1045 {
1046 Rect src_r, dest_r;
1047 int src_right = ((PixMap *) src)->bounds.right;
1048 int src_bottom = ((PixMap *) src)->bounds.bottom;
1049 int w = src_right - src_x;
1050 int h = src_bottom - src_y;
1051
1052 mac_set_colors (gc);
1053
1054 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
1055 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
1056
1057 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
1058 }
1059
1060
1061 /* Mac replacement for XChangeGC. */
1062
1063 static void
1064 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1065 XGCValues *xgcv)
1066 {
1067 if (mask & GCForeground)
1068 gc->foreground = xgcv->foreground;
1069 if (mask & GCBackground)
1070 gc->background = xgcv->background;
1071 if (mask & GCFont)
1072 gc->font = xgcv->font;
1073 }
1074
1075
1076 /* Mac replacement for XCreateGC. */
1077
1078 XGCValues *
1079 XCreateGC (void * ignore, Window window, unsigned long mask,
1080 XGCValues *xgcv)
1081 {
1082 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1083 bzero (gc, sizeof (XGCValues));
1084
1085 XChangeGC (ignore, gc, mask, xgcv);
1086
1087 return gc;
1088 }
1089
1090
1091 /* Used in xfaces.c. */
1092
1093 void
1094 XFreeGC (display, gc)
1095 Display *display;
1096 GC gc;
1097 {
1098 xfree (gc);
1099 }
1100
1101
1102 /* Mac replacement for XGetGCValues. */
1103
1104 static void
1105 XGetGCValues (void* ignore, XGCValues *gc,
1106 unsigned long mask, XGCValues *xgcv)
1107 {
1108 XChangeGC (ignore, xgcv, mask, gc);
1109 }
1110
1111
1112 /* Mac replacement for XSetForeground. */
1113
1114 static void
1115 XSetForeground (display, gc, color)
1116 Display *display;
1117 GC gc;
1118 unsigned long color;
1119 {
1120 gc->foreground = color;
1121 }
1122
1123
1124 /* Mac replacement for XSetFont. */
1125
1126 static void
1127 XSetFont (display, gc, font)
1128 Display *display;
1129 GC gc;
1130 XFontStruct *font;
1131 {
1132 gc->font = font;
1133 }
1134
1135
1136 static void
1137 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1138 int *direction,int *font_ascent,
1139 int *font_descent, XCharStruct *cs)
1140 {
1141 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1142 }
1143
1144
1145 /* x_sync is a no-op on Mac. */
1146 void
1147 x_sync (f)
1148 void *f;
1149 {
1150 }
1151
1152
1153 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1154 Calls to XFlush should be unnecessary because the X output buffer
1155 is flushed automatically as needed by calls to XPending,
1156 XNextEvent, or XWindowEvent according to the XFlush man page.
1157 XTread_socket calls XPending. Removing XFlush improves
1158 performance. */
1159
1160 #if TARGET_API_MAC_CARBON
1161 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1162 #else
1163 #define XFlush(DISPLAY) (void) 0
1164 #endif
1165
1166 /* Flush display of frame F, or of all frames if F is null. */
1167
1168 void
1169 x_flush (f)
1170 struct frame *f;
1171 {
1172 #if TARGET_API_MAC_CARBON
1173 BLOCK_INPUT;
1174 if (f == NULL)
1175 {
1176 Lisp_Object rest, frame;
1177 FOR_EACH_FRAME (rest, frame)
1178 x_flush (XFRAME (frame));
1179 }
1180 else if (FRAME_X_P (f))
1181 XFlush (FRAME_MAC_DISPLAY (f));
1182 UNBLOCK_INPUT;
1183 #endif /* TARGET_API_MAC_CARBON */
1184 }
1185
1186
1187 \f
1188 /* Return the struct mac_display_info corresponding to DPY. There's
1189 only one. */
1190
1191 struct mac_display_info *
1192 mac_display_info_for_display (dpy)
1193 Display *dpy;
1194 {
1195 return &one_mac_display_info;
1196 }
1197
1198
1199 \f
1200 /***********************************************************************
1201 Starting and ending an update
1202 ***********************************************************************/
1203
1204 /* Start an update of frame F. This function is installed as a hook
1205 for update_begin, i.e. it is called when update_begin is called.
1206 This function is called prior to calls to x_update_window_begin for
1207 each window being updated. */
1208
1209 static void
1210 x_update_begin (f)
1211 struct frame *f;
1212 {
1213 /* Nothing to do. */
1214 }
1215
1216
1217 /* Start update of window W. Set the global variable updated_window
1218 to the window being updated and set output_cursor to the cursor
1219 position of W. */
1220
1221 static void
1222 x_update_window_begin (w)
1223 struct window *w;
1224 {
1225 struct frame *f = XFRAME (WINDOW_FRAME (w));
1226 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1227
1228 updated_window = w;
1229 set_output_cursor (&w->cursor);
1230
1231 BLOCK_INPUT;
1232
1233 if (f == display_info->mouse_face_mouse_frame)
1234 {
1235 /* Don't do highlighting for mouse motion during the update. */
1236 display_info->mouse_face_defer = 1;
1237
1238 /* If F needs to be redrawn, simply forget about any prior mouse
1239 highlighting. */
1240 if (FRAME_GARBAGED_P (f))
1241 display_info->mouse_face_window = Qnil;
1242
1243 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1244 their mouse_face_p flag set, which means that they are always
1245 unequal to rows in a desired matrix which never have that
1246 flag set. So, rows containing mouse-face glyphs are never
1247 scrolled, and we don't have to switch the mouse highlight off
1248 here to prevent it from being scrolled. */
1249
1250 /* Can we tell that this update does not affect the window
1251 where the mouse highlight is? If so, no need to turn off.
1252 Likewise, don't do anything if the frame is garbaged;
1253 in that case, the frame's current matrix that we would use
1254 is all wrong, and we will redisplay that line anyway. */
1255 if (!NILP (display_info->mouse_face_window)
1256 && w == XWINDOW (display_info->mouse_face_window))
1257 {
1258 int i;
1259
1260 for (i = 0; i < w->desired_matrix->nrows; ++i)
1261 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1262 break;
1263
1264 if (i < w->desired_matrix->nrows)
1265 clear_mouse_face (display_info);
1266 }
1267 #endif /* 0 */
1268 }
1269
1270 UNBLOCK_INPUT;
1271 }
1272
1273
1274 /* Draw a vertical window border to the right of window W if W doesn't
1275 have vertical scroll bars. */
1276
1277 static void
1278 x_draw_vertical_border (w)
1279 struct window *w;
1280 {
1281 struct frame *f = XFRAME (WINDOW_FRAME (w));
1282
1283 /* Redraw borders between horizontally adjacent windows. Don't
1284 do it for frames with vertical scroll bars because either the
1285 right scroll bar of a window, or the left scroll bar of its
1286 neighbor will suffice as a border. */
1287 if (!WINDOW_RIGHTMOST_P (w)
1288 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1289 {
1290 int x0, x1, y0, y1;
1291
1292 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
1293 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1294 y1 -= 1;
1295
1296 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1297 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1298 }
1299 }
1300
1301
1302 /* End update of window W (which is equal to updated_window).
1303
1304 Draw vertical borders between horizontally adjacent windows, and
1305 display W's cursor if CURSOR_ON_P is non-zero.
1306
1307 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1308 glyphs in mouse-face were overwritten. In that case we have to
1309 make sure that the mouse-highlight is properly redrawn.
1310
1311 W may be a menu bar pseudo-window in case we don't have X toolkit
1312 support. Such windows don't have a cursor, so don't display it
1313 here. */
1314
1315 static void
1316 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1317 struct window *w;
1318 int cursor_on_p, mouse_face_overwritten_p;
1319 {
1320 struct mac_display_info *dpyinfo
1321 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1322
1323 if (!w->pseudo_window_p)
1324 {
1325 BLOCK_INPUT;
1326
1327 if (cursor_on_p)
1328 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1329 output_cursor.vpos,
1330 output_cursor.x, output_cursor.y);
1331
1332 x_draw_vertical_border (w);
1333 UNBLOCK_INPUT;
1334 }
1335
1336 /* If a row with mouse-face was overwritten, arrange for
1337 XTframe_up_to_date to redisplay the mouse highlight. */
1338 if (mouse_face_overwritten_p)
1339 {
1340 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1341 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1342 dpyinfo->mouse_face_window = Qnil;
1343 }
1344
1345 #if 0
1346 /* Unhide the caret. This won't actually show the cursor, unless it
1347 was visible before the corresponding call to HideCaret in
1348 x_update_window_begin. */
1349 if (w32_use_visible_system_caret)
1350 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1351 #endif
1352
1353 updated_window = NULL;
1354 }
1355
1356
1357 /* End update of frame F. This function is installed as a hook in
1358 update_end. */
1359
1360 static void
1361 x_update_end (f)
1362 struct frame *f;
1363 {
1364 /* Reset the background color of Mac OS Window to that of the frame after
1365 update so that it is used by Mac Toolbox to clear the update region before
1366 an update event is generated. */
1367 #if TARGET_API_MAC_CARBON
1368 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1369 #else
1370 SetPort (FRAME_MAC_WINDOW (f));
1371 #endif
1372
1373 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1374
1375 /* Mouse highlight may be displayed again. */
1376 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1377
1378 BLOCK_INPUT;
1379 XFlush (FRAME_MAC_DISPLAY (f));
1380 UNBLOCK_INPUT;
1381 }
1382
1383
1384 /* This function is called from various places in xdisp.c whenever a
1385 complete update has been performed. The global variable
1386 updated_window is not available here. */
1387
1388 static void
1389 XTframe_up_to_date (f)
1390 struct frame *f;
1391 {
1392 if (FRAME_X_P (f))
1393 {
1394 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1395
1396 if (dpyinfo->mouse_face_deferred_gc
1397 || f == dpyinfo->mouse_face_mouse_frame)
1398 {
1399 BLOCK_INPUT;
1400 if (dpyinfo->mouse_face_mouse_frame)
1401 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1402 dpyinfo->mouse_face_mouse_x,
1403 dpyinfo->mouse_face_mouse_y);
1404 dpyinfo->mouse_face_deferred_gc = 0;
1405 UNBLOCK_INPUT;
1406 }
1407 }
1408 }
1409
1410
1411 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1412 arrow bitmaps, or clear the fringes if no bitmaps are required
1413 before DESIRED_ROW is made current. The window being updated is
1414 found in updated_window. This function is called from
1415 update_window_line only if it is known that there are differences
1416 between bitmaps to be drawn between current row and DESIRED_ROW. */
1417
1418 static void
1419 x_after_update_window_line (desired_row)
1420 struct glyph_row *desired_row;
1421 {
1422 struct window *w = updated_window;
1423 struct frame *f;
1424 int width, height;
1425
1426 xassert (w);
1427
1428 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1429 {
1430 BLOCK_INPUT;
1431 x_draw_row_fringe_bitmaps (w, desired_row);
1432 UNBLOCK_INPUT;
1433 }
1434
1435 /* When a window has disappeared, make sure that no rest of
1436 full-width rows stays visible in the internal border. Could
1437 check here if updated_window is the leftmost/rightmost window,
1438 but I guess it's not worth doing since vertically split windows
1439 are almost never used, internal border is rarely set, and the
1440 overhead is very small. */
1441 if (windows_or_buffers_changed
1442 && desired_row->full_width_p
1443 && (f = XFRAME (w->frame),
1444 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1445 width != 0)
1446 && (height = desired_row->visible_height,
1447 height > 0))
1448 {
1449 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1450 /* Internal border is drawn below the tool bar. */
1451 if (WINDOWP (f->tool_bar_window)
1452 && w == XWINDOW (f->tool_bar_window))
1453 y -= width;
1454
1455 BLOCK_INPUT;
1456
1457 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1458 0, y, width, height, 0);
1459 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1460 f->output_data.mac->pixel_width - width, y,
1461 width, height, 0);
1462
1463 UNBLOCK_INPUT;
1464 }
1465 }
1466
1467
1468 /* Draw the bitmap WHICH in one of the left or right fringes of
1469 window W. ROW is the glyph row for which to display the bitmap; it
1470 determines the vertical position at which the bitmap has to be
1471 drawn. */
1472
1473 static void
1474 x_draw_fringe_bitmap (w, row, which, left_p)
1475 struct window *w;
1476 struct glyph_row *row;
1477 enum fringe_bitmap_type which;
1478 int left_p;
1479 {
1480 struct frame *f = XFRAME (WINDOW_FRAME (w));
1481 Display *display = FRAME_MAC_DISPLAY (f);
1482 WindowPtr window = FRAME_MAC_WINDOW (f);
1483 int x, y, wd, h, dy;
1484 int b1, b2;
1485 unsigned char *bits;
1486 BitMap bitmap;
1487 XGCValues gcv;
1488 GC gc = f->output_data.mac->normal_gc;
1489 struct face *face;
1490
1491 /* Must clip because of partially visible lines. */
1492 x_clip_to_row (w, row, gc, 1);
1493
1494 /* Convert row to frame coordinates. */
1495 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1496
1497 switch (which)
1498 {
1499 case NO_FRINGE_BITMAP:
1500 wd = 0;
1501 h = 0;
1502 break;
1503
1504 case LEFT_TRUNCATION_BITMAP:
1505 wd = left_width;
1506 h = left_height;
1507 bits = left_bits;
1508 break;
1509
1510 case OVERLAY_ARROW_BITMAP:
1511 wd = ov_width;
1512 h = ov_height;
1513 bits = ov_bits;
1514 break;
1515
1516 case RIGHT_TRUNCATION_BITMAP:
1517 wd = right_width;
1518 h = right_height;
1519 bits = right_bits;
1520 break;
1521
1522 case CONTINUED_LINE_BITMAP:
1523 wd = continued_width;
1524 h = continued_height;
1525 bits = continued_bits;
1526 break;
1527
1528 case CONTINUATION_LINE_BITMAP:
1529 wd = continuation_width;
1530 h = continuation_height;
1531 bits = continuation_bits;
1532 break;
1533
1534 case ZV_LINE_BITMAP:
1535 wd = zv_width;
1536 h = zv_height - (y % zv_period);
1537 bits = zv_bits + (y % zv_period);
1538 break;
1539
1540 default:
1541 abort ();
1542 }
1543
1544 /* Clip bitmap if too high. */
1545 if (h > row->height)
1546 h = row->height;
1547
1548 /* Set dy to the offset in the row to start drawing the bitmap. */
1549 dy = (row->height - h) / 2;
1550
1551 /* Draw the bitmap. */
1552 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
1553 PREPARE_FACE_FOR_DISPLAY (f, face);
1554
1555 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1556 the fringe. */
1557 b1 = -1;
1558 if (left_p)
1559 {
1560 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
1561 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
1562 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1563 - wd
1564 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
1565 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
1566 {
1567 /* If W has a vertical border to its left, don't draw over it. */
1568 int border = ((XFASTINT (w->left) > 0
1569 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1570 ? 1 : 0);
1571 b1 = (window_box_left (w, -1)
1572 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1573 + border);
1574 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1575 }
1576 }
1577 else
1578 {
1579 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
1580 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1581 x = (window_box_right (w, -1)
1582 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
1583 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1584 the fringe. */
1585 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
1586 {
1587 b1 = window_box_right (w, -1);
1588 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1589 }
1590 }
1591
1592 if (b1 >= 0)
1593 {
1594 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1595 XGCValues gcv;
1596 gcv.foreground = face->background;
1597
1598 #if 0 /* MAC_TODO: stipple */
1599 /* In case the same realized face is used for fringes and
1600 for something displayed in the text (e.g. face `region' on
1601 mono-displays, the fill style may have been changed to
1602 FillSolid in x_draw_glyph_string_background. */
1603 if (face->stipple)
1604 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1605 else
1606 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1607 #endif
1608
1609 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1610 &gcv,
1611 b1,
1612 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1613 row->y)),
1614 b2,
1615 row->visible_height);
1616
1617 #if 0 /* MAC_TODO: stipple */
1618 if (!face->stipple)
1619 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1620 #endif
1621 }
1622
1623 if (which == NO_FRINGE_BITMAP)
1624 {
1625 mac_reset_clipping (display, window);
1626 return;
1627 }
1628
1629 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1630 gcv.foreground = face->foreground;
1631 gcv.background = face->background;
1632
1633 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1634
1635 mac_free_bitmap (&bitmap);
1636 mac_reset_clipping (display, window);
1637 }
1638
1639
1640 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1641 function with input blocked. */
1642
1643 static void
1644 x_draw_row_fringe_bitmaps (w, row)
1645 struct window *w;
1646 struct glyph_row *row;
1647 {
1648 struct frame *f = XFRAME (w->frame);
1649 enum fringe_bitmap_type bitmap;
1650
1651 xassert (interrupt_input_blocked);
1652
1653 /* If row is completely invisible, because of vscrolling, we
1654 don't have to draw anything. */
1655 if (row->visible_height <= 0)
1656 return;
1657
1658 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1659 {
1660 /* Decide which bitmap to draw in the left fringe. */
1661 if (row->overlay_arrow_p)
1662 bitmap = OVERLAY_ARROW_BITMAP;
1663 else if (row->truncated_on_left_p)
1664 bitmap = LEFT_TRUNCATION_BITMAP;
1665 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1666 bitmap = CONTINUATION_LINE_BITMAP;
1667 else if (row->indicate_empty_line_p)
1668 bitmap = ZV_LINE_BITMAP;
1669 else
1670 bitmap = NO_FRINGE_BITMAP;
1671
1672 x_draw_fringe_bitmap (w, row, bitmap, 1);
1673 }
1674
1675 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1676 {
1677 /* Decide which bitmap to draw in the right fringe. */
1678 if (row->truncated_on_right_p)
1679 bitmap = RIGHT_TRUNCATION_BITMAP;
1680 else if (row->continued_p)
1681 bitmap = CONTINUED_LINE_BITMAP;
1682 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1683 bitmap = ZV_LINE_BITMAP;
1684 else
1685 bitmap = NO_FRINGE_BITMAP;
1686
1687 x_draw_fringe_bitmap (w, row, bitmap, 0);
1688 }
1689 }
1690
1691 \f
1692 /* This is called when starting Emacs and when restarting after
1693 suspend. When starting Emacs, no window is mapped. And nothing
1694 must be done to Emacs's own window if it is suspended (though that
1695 rarely happens). */
1696
1697 static void
1698 XTset_terminal_modes ()
1699 {
1700 }
1701
1702 /* This is called when exiting or suspending Emacs. Exiting will make
1703 the windows go away, and suspending requires no action. */
1704
1705 static void
1706 XTreset_terminal_modes ()
1707 {
1708 }
1709
1710
1711 \f
1712 /***********************************************************************
1713 Output Cursor
1714 ***********************************************************************/
1715
1716 /* Set the global variable output_cursor to CURSOR. All cursor
1717 positions are relative to updated_window. */
1718
1719 static void
1720 set_output_cursor (cursor)
1721 struct cursor_pos *cursor;
1722 {
1723 output_cursor.hpos = cursor->hpos;
1724 output_cursor.vpos = cursor->vpos;
1725 output_cursor.x = cursor->x;
1726 output_cursor.y = cursor->y;
1727 }
1728
1729
1730 /* Set a nominal cursor position.
1731
1732 HPOS and VPOS are column/row positions in a window glyph matrix. X
1733 and Y are window text area relative pixel positions.
1734
1735 If this is done during an update, updated_window will contain the
1736 window that is being updated and the position is the future output
1737 cursor position for that window. If updated_window is null, use
1738 selected_window and display the cursor at the given position. */
1739
1740 static void
1741 XTcursor_to (vpos, hpos, y, x)
1742 int vpos, hpos, y, x;
1743 {
1744 struct window *w;
1745
1746 /* If updated_window is not set, work on selected_window. */
1747 if (updated_window)
1748 w = updated_window;
1749 else
1750 w = XWINDOW (selected_window);
1751
1752 /* Set the output cursor. */
1753 output_cursor.hpos = hpos;
1754 output_cursor.vpos = vpos;
1755 output_cursor.x = x;
1756 output_cursor.y = y;
1757
1758 /* If not called as part of an update, really display the cursor.
1759 This will also set the cursor position of W. */
1760 if (updated_window == NULL)
1761 {
1762 BLOCK_INPUT;
1763 x_display_cursor (w, 1, hpos, vpos, x, y);
1764 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1765 UNBLOCK_INPUT;
1766 }
1767 }
1768
1769
1770 \f
1771 /***********************************************************************
1772 Display Iterator
1773 ***********************************************************************/
1774
1775 /* Function prototypes of this page. */
1776
1777 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1778 struct glyph *,
1779 XChar2b *,
1780 int *));
1781 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1782 int, XChar2b *, int));
1783 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1784 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1785 static void x_append_glyph P_ ((struct it *));
1786 static void x_append_composite_glyph P_ ((struct it *));
1787 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1788 int, int, double));
1789 static void x_produce_glyphs P_ ((struct it *));
1790 static void x_produce_image_glyph P_ ((struct it *it));
1791
1792
1793 /* Return a pointer to per-char metric information in FONT of a
1794 character pointed by B which is a pointer to an XChar2b. */
1795
1796 #define PER_CHAR_METRIC(font, b) \
1797 ((font)->per_char \
1798 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1799 + (((font)->min_byte1 || (font)->max_byte1) \
1800 ? (((b)->byte1 - (font)->min_byte1) \
1801 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1802 : 0)) \
1803 : &((font)->max_bounds))
1804
1805
1806 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1807 is not contained in the font. */
1808
1809 static INLINE XCharStruct *
1810 x_per_char_metric (font, char2b)
1811 XFontStruct *font;
1812 XChar2b *char2b;
1813 {
1814 /* The result metric information. */
1815 XCharStruct *pcm = NULL;
1816
1817 xassert (font && char2b);
1818
1819 if (font->per_char != NULL)
1820 {
1821 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1822 {
1823 /* min_char_or_byte2 specifies the linear character index
1824 corresponding to the first element of the per_char array,
1825 max_char_or_byte2 is the index of the last character. A
1826 character with non-zero CHAR2B->byte1 is not in the font.
1827 A character with byte2 less than min_char_or_byte2 or
1828 greater max_char_or_byte2 is not in the font. */
1829 if (char2b->byte1 == 0
1830 && char2b->byte2 >= font->min_char_or_byte2
1831 && char2b->byte2 <= font->max_char_or_byte2)
1832 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1833 }
1834 else
1835 {
1836 /* If either min_byte1 or max_byte1 are nonzero, both
1837 min_char_or_byte2 and max_char_or_byte2 are less than
1838 256, and the 2-byte character index values corresponding
1839 to the per_char array element N (counting from 0) are:
1840
1841 byte1 = N/D + min_byte1
1842 byte2 = N\D + min_char_or_byte2
1843
1844 where:
1845
1846 D = max_char_or_byte2 - min_char_or_byte2 + 1
1847 / = integer division
1848 \ = integer modulus */
1849 if (char2b->byte1 >= font->min_byte1
1850 && char2b->byte1 <= font->max_byte1
1851 && char2b->byte2 >= font->min_char_or_byte2
1852 && char2b->byte2 <= font->max_char_or_byte2)
1853 {
1854 pcm = (font->per_char
1855 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1856 * (char2b->byte1 - font->min_byte1))
1857 + (char2b->byte2 - font->min_char_or_byte2));
1858 }
1859 }
1860 }
1861 else
1862 {
1863 /* If the per_char pointer is null, all glyphs between the first
1864 and last character indexes inclusive have the same
1865 information, as given by both min_bounds and max_bounds. */
1866 if (char2b->byte2 >= font->min_char_or_byte2
1867 && char2b->byte2 <= font->max_char_or_byte2)
1868 pcm = &font->max_bounds;
1869 }
1870
1871 return ((pcm == NULL
1872 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1873 ? NULL : pcm);
1874 }
1875
1876
1877 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1878 the two-byte form of C. Encoding is returned in *CHAR2B. */
1879
1880 static INLINE void
1881 x_encode_char (c, char2b, font_info)
1882 int c;
1883 XChar2b *char2b;
1884 struct font_info *font_info;
1885 {
1886 int charset = CHAR_CHARSET (c);
1887 XFontStruct *font = font_info->font;
1888
1889 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1890 This may be either a program in a special encoder language or a
1891 fixed encoding. */
1892 if (font_info->font_encoder)
1893 {
1894 /* It's a program. */
1895 struct ccl_program *ccl = font_info->font_encoder;
1896
1897 if (CHARSET_DIMENSION (charset) == 1)
1898 {
1899 ccl->reg[0] = charset;
1900 ccl->reg[1] = char2b->byte2;
1901 }
1902 else
1903 {
1904 ccl->reg[0] = charset;
1905 ccl->reg[1] = char2b->byte1;
1906 ccl->reg[2] = char2b->byte2;
1907 }
1908
1909 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1910
1911 /* We assume that MSBs are appropriately set/reset by CCL
1912 program. */
1913 if (font->max_byte1 == 0) /* 1-byte font */
1914 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1915 else
1916 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1917 }
1918 else if (font_info->encoding[charset])
1919 {
1920 /* Fixed encoding scheme. See fontset.h for the meaning of the
1921 encoding numbers. */
1922 int enc = font_info->encoding[charset];
1923
1924 if ((enc == 1 || enc == 2)
1925 && CHARSET_DIMENSION (charset) == 2)
1926 char2b->byte1 |= 0x80;
1927
1928 if (enc == 1 || enc == 3)
1929 char2b->byte2 |= 0x80;
1930
1931 if (enc == 4)
1932 {
1933 int sjis1, sjis2;
1934
1935 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1936 char2b->byte1 = sjis1;
1937 char2b->byte2 = sjis2;
1938 }
1939 }
1940 }
1941
1942
1943 /* Get face and two-byte form of character C in face FACE_ID on frame
1944 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1945 means we want to display multibyte text. Value is a pointer to a
1946 realized face that is ready for display. */
1947
1948 static INLINE struct face *
1949 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1950 struct frame *f;
1951 int c, face_id;
1952 XChar2b *char2b;
1953 int multibyte_p;
1954 {
1955 struct face *face = FACE_FROM_ID (f, face_id);
1956
1957 if (!multibyte_p)
1958 {
1959 /* Unibyte case. We don't have to encode, but we have to make
1960 sure to use a face suitable for unibyte. */
1961 char2b->byte1 = 0;
1962 char2b->byte2 = c;
1963 face_id = FACE_FOR_CHAR (f, face, c);
1964 face = FACE_FROM_ID (f, face_id);
1965 }
1966 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1967 {
1968 /* Case of ASCII in a face known to fit ASCII. */
1969 char2b->byte1 = 0;
1970 char2b->byte2 = c;
1971 }
1972 else
1973 {
1974 int c1, c2, charset;
1975
1976 /* Split characters into bytes. If c2 is -1 afterwards, C is
1977 really a one-byte character so that byte1 is zero. */
1978 SPLIT_CHAR (c, charset, c1, c2);
1979 if (c2 > 0)
1980 char2b->byte1 = c1, char2b->byte2 = c2;
1981 else
1982 char2b->byte1 = 0, char2b->byte2 = c1;
1983
1984 /* Maybe encode the character in *CHAR2B. */
1985 if (face->font != NULL)
1986 {
1987 struct font_info *font_info
1988 = FONT_INFO_FROM_ID (f, face->font_info_id);
1989 if (font_info)
1990 x_encode_char (c, char2b, font_info);
1991 }
1992 }
1993
1994 /* Make sure X resources of the face are allocated. */
1995 xassert (face != NULL);
1996 PREPARE_FACE_FOR_DISPLAY (f, face);
1997
1998 return face;
1999 }
2000
2001
2002 /* Get face and two-byte form of character glyph GLYPH on frame F.
2003 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
2004 a pointer to a realized face that is ready for display. */
2005
2006 static INLINE struct face *
2007 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
2008 struct frame *f;
2009 struct glyph *glyph;
2010 XChar2b *char2b;
2011 int *two_byte_p;
2012 {
2013 struct face *face;
2014
2015 xassert (glyph->type == CHAR_GLYPH);
2016 face = FACE_FROM_ID (f, glyph->face_id);
2017
2018 if (two_byte_p)
2019 *two_byte_p = 0;
2020
2021 if (!glyph->multibyte_p)
2022 {
2023 /* Unibyte case. We don't have to encode, but we have to make
2024 sure to use a face suitable for unibyte. */
2025 char2b->byte1 = 0;
2026 char2b->byte2 = glyph->u.ch;
2027 }
2028 else if (glyph->u.ch < 128
2029 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
2030 {
2031 /* Case of ASCII in a face known to fit ASCII. */
2032 char2b->byte1 = 0;
2033 char2b->byte2 = glyph->u.ch;
2034 }
2035 else
2036 {
2037 int c1, c2, charset;
2038
2039 /* Split characters into bytes. If c2 is -1 afterwards, C is
2040 really a one-byte character so that byte1 is zero. */
2041 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
2042 if (c2 > 0)
2043 char2b->byte1 = c1, char2b->byte2 = c2;
2044 else
2045 char2b->byte1 = 0, char2b->byte2 = c1;
2046
2047 /* Maybe encode the character in *CHAR2B. */
2048 if (charset != CHARSET_ASCII)
2049 {
2050 struct font_info *font_info
2051 = FONT_INFO_FROM_ID (f, face->font_info_id);
2052 if (font_info)
2053 {
2054 x_encode_char (glyph->u.ch, char2b, font_info);
2055 if (two_byte_p)
2056 *two_byte_p
2057 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2058 }
2059 }
2060 }
2061
2062 /* Make sure X resources of the face are allocated. */
2063 xassert (face != NULL);
2064 PREPARE_FACE_FOR_DISPLAY (f, face);
2065 return face;
2066 }
2067
2068
2069 /* Store one glyph for IT->char_to_display in IT->glyph_row.
2070 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2071
2072 static INLINE void
2073 x_append_glyph (it)
2074 struct it *it;
2075 {
2076 struct glyph *glyph;
2077 enum glyph_row_area area = it->area;
2078
2079 xassert (it->glyph_row);
2080 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
2081
2082 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2083 if (glyph < it->glyph_row->glyphs[area + 1])
2084 {
2085 glyph->charpos = CHARPOS (it->position);
2086 glyph->object = it->object;
2087 glyph->pixel_width = it->pixel_width;
2088 glyph->voffset = it->voffset;
2089 glyph->type = CHAR_GLYPH;
2090 glyph->multibyte_p = it->multibyte_p;
2091 glyph->left_box_line_p = it->start_of_box_run_p;
2092 glyph->right_box_line_p = it->end_of_box_run_p;
2093 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2094 || it->phys_descent > it->descent);
2095 glyph->padding_p = 0;
2096 glyph->glyph_not_available_p = it->glyph_not_available_p;
2097 glyph->face_id = it->face_id;
2098 glyph->u.ch = it->char_to_display;
2099 ++it->glyph_row->used[area];
2100 }
2101 }
2102
2103 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2104 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2105
2106 static INLINE void
2107 x_append_composite_glyph (it)
2108 struct it *it;
2109 {
2110 struct glyph *glyph;
2111 enum glyph_row_area area = it->area;
2112
2113 xassert (it->glyph_row);
2114
2115 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2116 if (glyph < it->glyph_row->glyphs[area + 1])
2117 {
2118 glyph->charpos = CHARPOS (it->position);
2119 glyph->object = it->object;
2120 glyph->pixel_width = it->pixel_width;
2121 glyph->voffset = it->voffset;
2122 glyph->type = COMPOSITE_GLYPH;
2123 glyph->multibyte_p = it->multibyte_p;
2124 glyph->left_box_line_p = it->start_of_box_run_p;
2125 glyph->right_box_line_p = it->end_of_box_run_p;
2126 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2127 || it->phys_descent > it->descent);
2128 glyph->padding_p = 0;
2129 glyph->glyph_not_available_p = 0;
2130 glyph->face_id = it->face_id;
2131 glyph->u.cmp_id = it->cmp_id;
2132 ++it->glyph_row->used[area];
2133 }
2134 }
2135
2136
2137 /* Change IT->ascent and IT->height according to the setting of
2138 IT->voffset. */
2139
2140 static INLINE void
2141 take_vertical_position_into_account (it)
2142 struct it *it;
2143 {
2144 if (it->voffset)
2145 {
2146 if (it->voffset < 0)
2147 /* Increase the ascent so that we can display the text higher
2148 in the line. */
2149 it->ascent += abs (it->voffset);
2150 else
2151 /* Increase the descent so that we can display the text lower
2152 in the line. */
2153 it->descent += it->voffset;
2154 }
2155 }
2156
2157
2158 /* Produce glyphs/get display metrics for the image IT is loaded with.
2159 See the description of struct display_iterator in dispextern.h for
2160 an overview of struct display_iterator. */
2161
2162 static void
2163 x_produce_image_glyph (it)
2164 struct it *it;
2165 {
2166 struct image *img;
2167 struct face *face;
2168
2169 xassert (it->what == IT_IMAGE);
2170
2171 face = FACE_FROM_ID (it->f, it->face_id);
2172 img = IMAGE_FROM_ID (it->f, it->image_id);
2173 xassert (img);
2174
2175 /* Make sure X resources of the face and image are loaded. */
2176 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2177 prepare_image_for_display (it->f, img);
2178
2179 it->ascent = it->phys_ascent = image_ascent (img, face);
2180 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
2181 it->pixel_width = img->width + 2 * img->hmargin;
2182
2183 it->nglyphs = 1;
2184
2185 if (face->box != FACE_NO_BOX)
2186 {
2187 if (face->box_line_width > 0)
2188 {
2189 it->ascent += face->box_line_width;
2190 it->descent += face->box_line_width;
2191 }
2192
2193 if (it->start_of_box_run_p)
2194 it->pixel_width += abs (face->box_line_width);
2195 if (it->end_of_box_run_p)
2196 it->pixel_width += abs (face->box_line_width);
2197 }
2198
2199 take_vertical_position_into_account (it);
2200
2201 if (it->glyph_row)
2202 {
2203 struct glyph *glyph;
2204 enum glyph_row_area area = it->area;
2205
2206 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2207 if (glyph < it->glyph_row->glyphs[area + 1])
2208 {
2209 glyph->charpos = CHARPOS (it->position);
2210 glyph->object = it->object;
2211 glyph->pixel_width = it->pixel_width;
2212 glyph->voffset = it->voffset;
2213 glyph->type = IMAGE_GLYPH;
2214 glyph->multibyte_p = it->multibyte_p;
2215 glyph->left_box_line_p = it->start_of_box_run_p;
2216 glyph->right_box_line_p = it->end_of_box_run_p;
2217 glyph->overlaps_vertically_p = 0;
2218 glyph->padding_p = 0;
2219 glyph->glyph_not_available_p = 0;
2220 glyph->face_id = it->face_id;
2221 glyph->u.img_id = img->id;
2222 ++it->glyph_row->used[area];
2223 }
2224 }
2225 }
2226
2227
2228 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2229 of the glyph, WIDTH and HEIGHT are the width and height of the
2230 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2231 ascent of the glyph (0 <= ASCENT <= 1). */
2232
2233 static void
2234 x_append_stretch_glyph (it, object, width, height, ascent)
2235 struct it *it;
2236 Lisp_Object object;
2237 int width, height;
2238 double ascent;
2239 {
2240 struct glyph *glyph;
2241 enum glyph_row_area area = it->area;
2242
2243 xassert (ascent >= 0 && ascent <= 1);
2244
2245 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2246 if (glyph < it->glyph_row->glyphs[area + 1])
2247 {
2248 glyph->charpos = CHARPOS (it->position);
2249 glyph->object = object;
2250 glyph->pixel_width = width;
2251 glyph->voffset = it->voffset;
2252 glyph->type = STRETCH_GLYPH;
2253 glyph->multibyte_p = it->multibyte_p;
2254 glyph->left_box_line_p = it->start_of_box_run_p;
2255 glyph->right_box_line_p = it->end_of_box_run_p;
2256 glyph->overlaps_vertically_p = 0;
2257 glyph->padding_p = 0;
2258 glyph->glyph_not_available_p = 0;
2259 glyph->face_id = it->face_id;
2260 glyph->u.stretch.ascent = height * ascent;
2261 glyph->u.stretch.height = height;
2262 ++it->glyph_row->used[area];
2263 }
2264 }
2265
2266
2267 /* Produce a stretch glyph for iterator IT. IT->object is the value
2268 of the glyph property displayed. The value must be a list
2269 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2270 being recognized:
2271
2272 1. `:width WIDTH' specifies that the space should be WIDTH *
2273 canonical char width wide. WIDTH may be an integer or floating
2274 point number.
2275
2276 2. `:relative-width FACTOR' specifies that the width of the stretch
2277 should be computed from the width of the first character having the
2278 `glyph' property, and should be FACTOR times that width.
2279
2280 3. `:align-to HPOS' specifies that the space should be wide enough
2281 to reach HPOS, a value in canonical character units.
2282
2283 Exactly one of the above pairs must be present.
2284
2285 4. `:height HEIGHT' specifies that the height of the stretch produced
2286 should be HEIGHT, measured in canonical character units.
2287
2288 5. `:relative-height FACTOR' specifies that the height of the
2289 stretch should be FACTOR times the height of the characters having
2290 the glyph property.
2291
2292 Either none or exactly one of 4 or 5 must be present.
2293
2294 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2295 of the stretch should be used for the ascent of the stretch.
2296 ASCENT must be in the range 0 <= ASCENT <= 100. */
2297
2298 #define NUMVAL(X) \
2299 ((INTEGERP (X) || FLOATP (X)) \
2300 ? XFLOATINT (X) \
2301 : - 1)
2302
2303
2304 static void
2305 x_produce_stretch_glyph (it)
2306 struct it *it;
2307 {
2308 /* (space :width WIDTH :height HEIGHT. */
2309 #if GLYPH_DEBUG
2310 extern Lisp_Object Qspace;
2311 #endif
2312 extern Lisp_Object QCwidth, QCheight, QCascent;
2313 extern Lisp_Object QCrelative_width, QCrelative_height;
2314 extern Lisp_Object QCalign_to;
2315 Lisp_Object prop, plist;
2316 double width = 0, height = 0, ascent = 0;
2317 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2318 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2319
2320 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2321
2322 /* List should start with `space'. */
2323 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2324 plist = XCDR (it->object);
2325
2326 /* Compute the width of the stretch. */
2327 if (prop = Fplist_get (plist, QCwidth),
2328 NUMVAL (prop) > 0)
2329 /* Absolute width `:width WIDTH' specified and valid. */
2330 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2331 else if (prop = Fplist_get (plist, QCrelative_width),
2332 NUMVAL (prop) > 0)
2333 {
2334 /* Relative width `:relative-width FACTOR' specified and valid.
2335 Compute the width of the characters having the `glyph'
2336 property. */
2337 struct it it2;
2338 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2339
2340 it2 = *it;
2341 if (it->multibyte_p)
2342 {
2343 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2344 - IT_BYTEPOS (*it));
2345 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2346 }
2347 else
2348 it2.c = *p, it2.len = 1;
2349
2350 it2.glyph_row = NULL;
2351 it2.what = IT_CHARACTER;
2352 x_produce_glyphs (&it2);
2353 width = NUMVAL (prop) * it2.pixel_width;
2354 }
2355 else if (prop = Fplist_get (plist, QCalign_to),
2356 NUMVAL (prop) > 0)
2357 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2358 else
2359 /* Nothing specified -> width defaults to canonical char width. */
2360 width = CANON_X_UNIT (it->f);
2361
2362 /* Compute height. */
2363 if (prop = Fplist_get (plist, QCheight),
2364 NUMVAL (prop) > 0)
2365 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2366 else if (prop = Fplist_get (plist, QCrelative_height),
2367 NUMVAL (prop) > 0)
2368 height = FONT_HEIGHT (font) * NUMVAL (prop);
2369 else
2370 height = FONT_HEIGHT (font);
2371
2372 /* Compute percentage of height used for ascent. If
2373 `:ascent ASCENT' is present and valid, use that. Otherwise,
2374 derive the ascent from the font in use. */
2375 if (prop = Fplist_get (plist, QCascent),
2376 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2377 ascent = NUMVAL (prop) / 100.0;
2378 else
2379 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
2380
2381 if (width <= 0)
2382 width = 1;
2383 if (height <= 0)
2384 height = 1;
2385
2386 if (it->glyph_row)
2387 {
2388 Lisp_Object object = it->stack[it->sp - 1].string;
2389 if (!STRINGP (object))
2390 object = it->w->buffer;
2391 x_append_stretch_glyph (it, object, width, height, ascent);
2392 }
2393
2394 it->pixel_width = width;
2395 it->ascent = it->phys_ascent = height * ascent;
2396 it->descent = it->phys_descent = height - it->ascent;
2397 it->nglyphs = 1;
2398
2399 if (face->box != FACE_NO_BOX)
2400 {
2401 if (face->box_line_width > 0)
2402 {
2403 it->ascent += face->box_line_width;
2404 it->descent += face->box_line_width;
2405 }
2406
2407 if (it->start_of_box_run_p)
2408 it->pixel_width += abs (face->box_line_width);
2409 if (it->end_of_box_run_p)
2410 it->pixel_width += abs (face->box_line_width);
2411 }
2412
2413 take_vertical_position_into_account (it);
2414 }
2415
2416 /* Return proper value to be used as baseline offset of font that has
2417 ASCENT and DESCENT to draw characters by the font at the vertical
2418 center of the line of frame F.
2419
2420 Here, out task is to find the value of BOFF in the following figure;
2421
2422 -------------------------+-----------+-
2423 -+-+---------+-+ | |
2424 | | | | | |
2425 | | | | F_ASCENT F_HEIGHT
2426 | | | ASCENT | |
2427 HEIGHT | | | | |
2428 | | |-|-+------+-----------|------- baseline
2429 | | | | BOFF | |
2430 | |---------|-+-+ | |
2431 | | | DESCENT | |
2432 -+-+---------+-+ F_DESCENT |
2433 -------------------------+-----------+-
2434
2435 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2436 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2437 DESCENT = FONT->descent
2438 HEIGHT = FONT_HEIGHT (FONT)
2439 F_DESCENT = (F->output_data.x->font->descent
2440 - F->output_data.x->baseline_offset)
2441 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2442 */
2443
2444 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2445 (FONT_DESCENT (FONT) \
2446 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2447 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2448 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2449
2450 /* Produce glyphs/get display metrics for the display element IT is
2451 loaded with. See the description of struct display_iterator in
2452 dispextern.h for an overview of struct display_iterator. */
2453
2454 static void
2455 x_produce_glyphs (it)
2456 struct it *it;
2457 {
2458 it->glyph_not_available_p = 0;
2459
2460 if (it->what == IT_CHARACTER)
2461 {
2462 XChar2b char2b;
2463 XFontStruct *font;
2464 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2465 XCharStruct *pcm;
2466 int font_not_found_p;
2467 struct font_info *font_info;
2468 int boff; /* baseline offset */
2469 /* We may change it->multibyte_p upon unibyte<->multibyte
2470 conversion. So, save the current value now and restore it
2471 later.
2472
2473 Note: It seems that we don't have to record multibyte_p in
2474 struct glyph because the character code itself tells if or
2475 not the character is multibyte. Thus, in the future, we must
2476 consider eliminating the field `multibyte_p' in the struct
2477 glyph.
2478 */
2479 int saved_multibyte_p = it->multibyte_p;
2480
2481 /* Maybe translate single-byte characters to multibyte, or the
2482 other way. */
2483 it->char_to_display = it->c;
2484 if (!ASCII_BYTE_P (it->c))
2485 {
2486 if (unibyte_display_via_language_environment
2487 && SINGLE_BYTE_CHAR_P (it->c)
2488 && (it->c >= 0240
2489 || !NILP (Vnonascii_translation_table)))
2490 {
2491 it->char_to_display = unibyte_char_to_multibyte (it->c);
2492 it->multibyte_p = 1;
2493 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2494 face = FACE_FROM_ID (it->f, it->face_id);
2495 }
2496 else if (!SINGLE_BYTE_CHAR_P (it->c)
2497 && !it->multibyte_p)
2498 {
2499 it->multibyte_p = 1;
2500 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2501 face = FACE_FROM_ID (it->f, it->face_id);
2502 }
2503 }
2504
2505 /* Get font to use. Encode IT->char_to_display. */
2506 x_get_char_face_and_encoding (it->f, it->char_to_display,
2507 it->face_id, &char2b,
2508 it->multibyte_p);
2509 font = face->font;
2510
2511 /* When no suitable font found, use the default font. */
2512 font_not_found_p = font == NULL;
2513 if (font_not_found_p)
2514 {
2515 font = FRAME_FONT (it->f);
2516 boff = it->f->output_data.mac->baseline_offset;
2517 font_info = NULL;
2518 }
2519 else
2520 {
2521 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2522 boff = font_info->baseline_offset;
2523 if (font_info->vertical_centering)
2524 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2525 }
2526
2527 if (it->char_to_display >= ' '
2528 && (!it->multibyte_p || it->char_to_display < 128))
2529 {
2530 /* Either unibyte or ASCII. */
2531 int stretched_p;
2532
2533 it->nglyphs = 1;
2534
2535 pcm = x_per_char_metric (font, &char2b);
2536 it->ascent = FONT_BASE (font) + boff;
2537 it->descent = FONT_DESCENT (font) - boff;
2538
2539 if (pcm)
2540 {
2541 it->phys_ascent = pcm->ascent + boff;
2542 it->phys_descent = pcm->descent - boff;
2543 it->pixel_width = pcm->width;
2544 }
2545 else
2546 {
2547 it->glyph_not_available_p = 1;
2548 it->phys_ascent = FONT_BASE (font) + boff;
2549 it->phys_descent = FONT_DESCENT (font) - boff;
2550 it->pixel_width = FONT_WIDTH (font);
2551 }
2552
2553 /* If this is a space inside a region of text with
2554 `space-width' property, change its width. */
2555 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2556 if (stretched_p)
2557 it->pixel_width *= XFLOATINT (it->space_width);
2558
2559 /* If face has a box, add the box thickness to the character
2560 height. If character has a box line to the left and/or
2561 right, add the box line width to the character's width. */
2562 if (face->box != FACE_NO_BOX)
2563 {
2564 int thick = face->box_line_width;
2565
2566 if (thick > 0)
2567 {
2568 it->ascent += thick;
2569 it->descent += thick;
2570 }
2571 else
2572 thick = -thick;
2573
2574 if (it->start_of_box_run_p)
2575 it->pixel_width += thick;
2576 if (it->end_of_box_run_p)
2577 it->pixel_width += thick;
2578 }
2579
2580 /* If face has an overline, add the height of the overline
2581 (1 pixel) and a 1 pixel margin to the character height. */
2582 if (face->overline_p)
2583 it->ascent += 2;
2584
2585 take_vertical_position_into_account (it);
2586
2587 /* If we have to actually produce glyphs, do it. */
2588 if (it->glyph_row)
2589 {
2590 if (stretched_p)
2591 {
2592 /* Translate a space with a `space-width' property
2593 into a stretch glyph. */
2594 double ascent = (double) FONT_BASE (font)
2595 / FONT_HEIGHT (font);
2596 x_append_stretch_glyph (it, it->object, it->pixel_width,
2597 it->ascent + it->descent, ascent);
2598 }
2599 else
2600 x_append_glyph (it);
2601
2602 /* If characters with lbearing or rbearing are displayed
2603 in this line, record that fact in a flag of the
2604 glyph row. This is used to optimize X output code. */
2605 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2606 it->glyph_row->contains_overlapping_glyphs_p = 1;
2607 }
2608 }
2609 else if (it->char_to_display == '\n')
2610 {
2611 /* A newline has no width but we need the height of the line. */
2612 it->pixel_width = 0;
2613 it->nglyphs = 0;
2614 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2615 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2616
2617 if (face->box != FACE_NO_BOX
2618 && face->box_line_width > 0)
2619 {
2620 it->ascent += face->box_line_width;
2621 it->descent += face->box_line_width;
2622 }
2623 }
2624 else if (it->char_to_display == '\t')
2625 {
2626 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2627 int x = it->current_x + it->continuation_lines_width;
2628 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2629
2630 /* If the distance from the current position to the next tab
2631 stop is less than a canonical character width, use the
2632 tab stop after that. */
2633 if (next_tab_x - x < CANON_X_UNIT (it->f))
2634 next_tab_x += tab_width;
2635
2636 it->pixel_width = next_tab_x - x;
2637 it->nglyphs = 1;
2638 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2639 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2640
2641 if (it->glyph_row)
2642 {
2643 double ascent = (double) it->ascent / (it->ascent + it->descent);
2644 x_append_stretch_glyph (it, it->object, it->pixel_width,
2645 it->ascent + it->descent, ascent);
2646 }
2647 }
2648 else
2649 {
2650 /* A multi-byte character. Assume that the display width of the
2651 character is the width of the character multiplied by the
2652 width of the font. */
2653
2654 /* If we found a font, this font should give us the right
2655 metrics. If we didn't find a font, use the frame's
2656 default font and calculate the width of the character
2657 from the charset width; this is what old redisplay code
2658 did. */
2659 pcm = x_per_char_metric (font, &char2b);
2660 if (font_not_found_p || !pcm)
2661 {
2662 int charset = CHAR_CHARSET (it->char_to_display);
2663
2664 it->glyph_not_available_p = 1;
2665 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2666 * CHARSET_WIDTH (charset));
2667 it->phys_ascent = FONT_BASE (font) + boff;
2668 it->phys_descent = FONT_DESCENT (font) - boff;
2669 }
2670 else
2671 {
2672 it->pixel_width = pcm->width;
2673 it->phys_ascent = pcm->ascent + boff;
2674 it->phys_descent = pcm->descent - boff;
2675 if (it->glyph_row
2676 && (pcm->lbearing < 0
2677 || pcm->rbearing > pcm->width))
2678 it->glyph_row->contains_overlapping_glyphs_p = 1;
2679 }
2680 it->nglyphs = 1;
2681 it->ascent = FONT_BASE (font) + boff;
2682 it->descent = FONT_DESCENT (font) - boff;
2683 if (face->box != FACE_NO_BOX)
2684 {
2685 int thick = face->box_line_width;
2686
2687 if (thick > 0)
2688 {
2689 it->ascent += thick;
2690 it->descent += thick;
2691 }
2692 else
2693 thick = - thick;
2694
2695 if (it->start_of_box_run_p)
2696 it->pixel_width += thick;
2697 if (it->end_of_box_run_p)
2698 it->pixel_width += thick;
2699 }
2700
2701 /* If face has an overline, add the height of the overline
2702 (1 pixel) and a 1 pixel margin to the character height. */
2703 if (face->overline_p)
2704 it->ascent += 2;
2705
2706 take_vertical_position_into_account (it);
2707
2708 if (it->glyph_row)
2709 x_append_glyph (it);
2710 }
2711 it->multibyte_p = saved_multibyte_p;
2712 }
2713 else if (it->what == IT_COMPOSITION)
2714 {
2715 /* Note: A composition is represented as one glyph in the
2716 glyph matrix. There are no padding glyphs. */
2717 XChar2b char2b;
2718 XFontStruct *font;
2719 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2720 XCharStruct *pcm;
2721 int font_not_found_p;
2722 struct font_info *font_info;
2723 int boff; /* baseline offset */
2724 struct composition *cmp = composition_table[it->cmp_id];
2725
2726 /* Maybe translate single-byte characters to multibyte. */
2727 it->char_to_display = it->c;
2728 if (unibyte_display_via_language_environment
2729 && SINGLE_BYTE_CHAR_P (it->c)
2730 && (it->c >= 0240
2731 || (it->c >= 0200
2732 && !NILP (Vnonascii_translation_table))))
2733 {
2734 it->char_to_display = unibyte_char_to_multibyte (it->c);
2735 }
2736
2737 /* Get face and font to use. Encode IT->char_to_display. */
2738 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2739 face = FACE_FROM_ID (it->f, it->face_id);
2740 x_get_char_face_and_encoding (it->f, it->char_to_display,
2741 it->face_id, &char2b, it->multibyte_p);
2742 font = face->font;
2743
2744 /* When no suitable font found, use the default font. */
2745 font_not_found_p = font == NULL;
2746 if (font_not_found_p)
2747 {
2748 font = FRAME_FONT (it->f);
2749 boff = it->f->output_data.mac->baseline_offset;
2750 font_info = NULL;
2751 }
2752 else
2753 {
2754 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2755 boff = font_info->baseline_offset;
2756 if (font_info->vertical_centering)
2757 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2758 }
2759
2760 /* There are no padding glyphs, so there is only one glyph to
2761 produce for the composition. Important is that pixel_width,
2762 ascent and descent are the values of what is drawn by
2763 draw_glyphs (i.e. the values of the overall glyphs composed). */
2764 it->nglyphs = 1;
2765
2766 /* If we have not yet calculated pixel size data of glyphs of
2767 the composition for the current face font, calculate them
2768 now. Theoretically, we have to check all fonts for the
2769 glyphs, but that requires much time and memory space. So,
2770 here we check only the font of the first glyph. This leads
2771 to incorrect display very rarely, and C-l (recenter) can
2772 correct the display anyway. */
2773 if (cmp->font != (void *) font)
2774 {
2775 /* Ascent and descent of the font of the first character of
2776 this composition (adjusted by baseline offset). Ascent
2777 and descent of overall glyphs should not be less than
2778 them respectively. */
2779 int font_ascent = FONT_BASE (font) + boff;
2780 int font_descent = FONT_DESCENT (font) - boff;
2781 /* Bounding box of the overall glyphs. */
2782 int leftmost, rightmost, lowest, highest;
2783 int i, width, ascent, descent;
2784
2785 cmp->font = (void *) font;
2786
2787 /* Initialize the bounding box. */
2788 pcm = x_per_char_metric (font, &char2b);
2789 if (pcm)
2790 {
2791 width = pcm->width;
2792 ascent = pcm->ascent;
2793 descent = pcm->descent;
2794 }
2795 else
2796 {
2797 width = FONT_WIDTH (font);
2798 ascent = FONT_BASE (font);
2799 descent = FONT_DESCENT (font);
2800 }
2801
2802 rightmost = width;
2803 lowest = - descent + boff;
2804 highest = ascent + boff;
2805 leftmost = 0;
2806
2807 if (font_info
2808 && font_info->default_ascent
2809 && CHAR_TABLE_P (Vuse_default_ascent)
2810 && !NILP (Faref (Vuse_default_ascent,
2811 make_number (it->char_to_display))))
2812 highest = font_info->default_ascent + boff;
2813
2814 /* Draw the first glyph at the normal position. It may be
2815 shifted to right later if some other glyphs are drawn at
2816 the left. */
2817 cmp->offsets[0] = 0;
2818 cmp->offsets[1] = boff;
2819
2820 /* Set cmp->offsets for the remaining glyphs. */
2821 for (i = 1; i < cmp->glyph_len; i++)
2822 {
2823 int left, right, btm, top;
2824 int ch = COMPOSITION_GLYPH (cmp, i);
2825 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2826
2827 face = FACE_FROM_ID (it->f, face_id);
2828 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2829 it->multibyte_p);
2830 font = face->font;
2831 if (font == NULL)
2832 {
2833 font = FRAME_FONT (it->f);
2834 boff = it->f->output_data.mac->baseline_offset;
2835 font_info = NULL;
2836 }
2837 else
2838 {
2839 font_info
2840 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2841 boff = font_info->baseline_offset;
2842 if (font_info->vertical_centering)
2843 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2844 }
2845
2846 pcm = x_per_char_metric (font, &char2b);
2847 if (pcm)
2848 {
2849 width = pcm->width;
2850 ascent = pcm->ascent;
2851 descent = pcm->descent;
2852 }
2853 else
2854 {
2855 width = FONT_WIDTH (font);
2856 ascent = 1;
2857 descent = 0;
2858 }
2859
2860 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2861 {
2862 /* Relative composition with or without
2863 alternate chars. */
2864 left = (leftmost + rightmost - width) / 2;
2865 btm = - descent + boff;
2866 if (font_info && font_info->relative_compose
2867 && (! CHAR_TABLE_P (Vignore_relative_composition)
2868 || NILP (Faref (Vignore_relative_composition,
2869 make_number (ch)))))
2870 {
2871
2872 if (- descent >= font_info->relative_compose)
2873 /* One extra pixel between two glyphs. */
2874 btm = highest + 1;
2875 else if (ascent <= 0)
2876 /* One extra pixel between two glyphs. */
2877 btm = lowest - 1 - ascent - descent;
2878 }
2879 }
2880 else
2881 {
2882 /* A composition rule is specified by an integer
2883 value that encodes global and new reference
2884 points (GREF and NREF). GREF and NREF are
2885 specified by numbers as below:
2886
2887 0---1---2 -- ascent
2888 | |
2889 | |
2890 | |
2891 9--10--11 -- center
2892 | |
2893 ---3---4---5--- baseline
2894 | |
2895 6---7---8 -- descent
2896 */
2897 int rule = COMPOSITION_RULE (cmp, i);
2898 int gref, nref, grefx, grefy, nrefx, nrefy;
2899
2900 COMPOSITION_DECODE_RULE (rule, gref, nref);
2901 grefx = gref % 3, nrefx = nref % 3;
2902 grefy = gref / 3, nrefy = nref / 3;
2903
2904 left = (leftmost
2905 + grefx * (rightmost - leftmost) / 2
2906 - nrefx * width / 2);
2907 btm = ((grefy == 0 ? highest
2908 : grefy == 1 ? 0
2909 : grefy == 2 ? lowest
2910 : (highest + lowest) / 2)
2911 - (nrefy == 0 ? ascent + descent
2912 : nrefy == 1 ? descent - boff
2913 : nrefy == 2 ? 0
2914 : (ascent + descent) / 2));
2915 }
2916
2917 cmp->offsets[i * 2] = left;
2918 cmp->offsets[i * 2 + 1] = btm + descent;
2919
2920 /* Update the bounding box of the overall glyphs. */
2921 right = left + width;
2922 top = btm + descent + ascent;
2923 if (left < leftmost)
2924 leftmost = left;
2925 if (right > rightmost)
2926 rightmost = right;
2927 if (top > highest)
2928 highest = top;
2929 if (btm < lowest)
2930 lowest = btm;
2931 }
2932
2933 /* If there are glyphs whose x-offsets are negative,
2934 shift all glyphs to the right and make all x-offsets
2935 non-negative. */
2936 if (leftmost < 0)
2937 {
2938 for (i = 0; i < cmp->glyph_len; i++)
2939 cmp->offsets[i * 2] -= leftmost;
2940 rightmost -= leftmost;
2941 }
2942
2943 cmp->pixel_width = rightmost;
2944 cmp->ascent = highest;
2945 cmp->descent = - lowest;
2946 if (cmp->ascent < font_ascent)
2947 cmp->ascent = font_ascent;
2948 if (cmp->descent < font_descent)
2949 cmp->descent = font_descent;
2950 }
2951
2952 it->pixel_width = cmp->pixel_width;
2953 it->ascent = it->phys_ascent = cmp->ascent;
2954 it->descent = it->phys_descent = cmp->descent;
2955
2956 if (face->box != FACE_NO_BOX)
2957 {
2958 int thick = face->box_line_width;
2959
2960 if (thick > 0)
2961 {
2962 it->ascent += thick;
2963 it->descent += thick;
2964 }
2965 else
2966 thick = - thick;
2967
2968 if (it->start_of_box_run_p)
2969 it->pixel_width += thick;
2970 if (it->end_of_box_run_p)
2971 it->pixel_width += thick;
2972 }
2973
2974 /* If face has an overline, add the height of the overline
2975 (1 pixel) and a 1 pixel margin to the character height. */
2976 if (face->overline_p)
2977 it->ascent += 2;
2978
2979 take_vertical_position_into_account (it);
2980
2981 if (it->glyph_row)
2982 x_append_composite_glyph (it);
2983 }
2984 else if (it->what == IT_IMAGE)
2985 x_produce_image_glyph (it);
2986 else if (it->what == IT_STRETCH)
2987 x_produce_stretch_glyph (it);
2988
2989 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2990 because this isn't true for images with `:ascent 100'. */
2991 xassert (it->ascent >= 0 && it->descent >= 0);
2992 if (it->area == TEXT_AREA)
2993 it->current_x += it->pixel_width;
2994
2995 it->descent += it->extra_line_spacing;
2996
2997 it->max_ascent = max (it->max_ascent, it->ascent);
2998 it->max_descent = max (it->max_descent, it->descent);
2999 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
3000 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
3001 }
3002
3003
3004 /* Estimate the pixel height of the mode or top line on frame F.
3005 FACE_ID specifies what line's height to estimate. */
3006
3007 int
3008 x_estimate_mode_line_height (f, face_id)
3009 struct frame *f;
3010 enum face_id face_id;
3011 {
3012 int height = FONT_HEIGHT (FRAME_FONT (f));
3013
3014 /* This function is called so early when Emacs starts that the face
3015 cache and mode line face are not yet initialized. */
3016 if (FRAME_FACE_CACHE (f))
3017 {
3018 struct face *face = FACE_FROM_ID (f, face_id);
3019 if (face)
3020 {
3021 if (face->font)
3022 height = FONT_HEIGHT (face->font);
3023 if (face->box_line_width > 0)
3024 height += 2 * face->box_line_width;
3025 }
3026 }
3027
3028 return height;
3029 }
3030
3031 \f
3032 /***********************************************************************
3033 Glyph display
3034 ***********************************************************************/
3035
3036 /* A sequence of glyphs to be drawn in the same face.
3037
3038 This data structure is not really completely X specific, so it
3039 could possibly, at least partially, be useful for other systems. It
3040 is currently not part of the external redisplay interface because
3041 it's not clear what other systems will need. */
3042
3043 struct glyph_string
3044 {
3045 /* X-origin of the string. */
3046 int x;
3047
3048 /* Y-origin and y-position of the base line of this string. */
3049 int y, ybase;
3050
3051 /* The width of the string, not including a face extension. */
3052 int width;
3053
3054 /* The width of the string, including a face extension. */
3055 int background_width;
3056
3057 /* The height of this string. This is the height of the line this
3058 string is drawn in, and can be different from the height of the
3059 font the string is drawn in. */
3060 int height;
3061
3062 /* Number of pixels this string overwrites in front of its x-origin.
3063 This number is zero if the string has an lbearing >= 0; it is
3064 -lbearing, if the string has an lbearing < 0. */
3065 int left_overhang;
3066
3067 /* Number of pixels this string overwrites past its right-most
3068 nominal x-position, i.e. x + width. Zero if the string's
3069 rbearing is <= its nominal width, rbearing - width otherwise. */
3070 int right_overhang;
3071
3072 /* The frame on which the glyph string is drawn. */
3073 struct frame *f;
3074
3075 /* The window on which the glyph string is drawn. */
3076 struct window *w;
3077
3078 /* X display and window for convenience. */
3079 Display *display;
3080 Window window;
3081
3082 /* The glyph row for which this string was built. It determines the
3083 y-origin and height of the string. */
3084 struct glyph_row *row;
3085
3086 /* The area within row. */
3087 enum glyph_row_area area;
3088
3089 /* Characters to be drawn, and number of characters. */
3090 XChar2b *char2b;
3091 int nchars;
3092
3093 /* A face-override for drawing cursors, mouse face and similar. */
3094 enum draw_glyphs_face hl;
3095
3096 /* Face in which this string is to be drawn. */
3097 struct face *face;
3098
3099 /* Font in which this string is to be drawn. */
3100 XFontStruct *font;
3101
3102 /* Font info for this string. */
3103 struct font_info *font_info;
3104
3105 /* Non-null means this string describes (part of) a composition.
3106 All characters from char2b are drawn composed. */
3107 struct composition *cmp;
3108
3109 /* Index of this glyph string's first character in the glyph
3110 definition of CMP. If this is zero, this glyph string describes
3111 the first character of a composition. */
3112 int gidx;
3113
3114 /* 1 means this glyph strings face has to be drawn to the right end
3115 of the window's drawing area. */
3116 unsigned extends_to_end_of_line_p : 1;
3117
3118 /* 1 means the background of this string has been drawn. */
3119 unsigned background_filled_p : 1;
3120
3121 /* 1 means glyph string must be drawn with 16-bit functions. */
3122 unsigned two_byte_p : 1;
3123
3124 /* 1 means that the original font determined for drawing this glyph
3125 string could not be loaded. The member `font' has been set to
3126 the frame's default font in this case. */
3127 unsigned font_not_found_p : 1;
3128
3129 /* 1 means that the face in which this glyph string is drawn has a
3130 stipple pattern. */
3131 unsigned stippled_p : 1;
3132
3133 /* 1 means only the foreground of this glyph string must be drawn,
3134 and we should use the physical height of the line this glyph
3135 string appears in as clip rect. */
3136 unsigned for_overlaps_p : 1;
3137
3138 /* The GC to use for drawing this glyph string. */
3139 GC gc;
3140
3141 /* A pointer to the first glyph in the string. This glyph
3142 corresponds to char2b[0]. Needed to draw rectangles if
3143 font_not_found_p is 1. */
3144 struct glyph *first_glyph;
3145
3146 /* Image, if any. */
3147 struct image *img;
3148
3149 struct glyph_string *next, *prev;
3150 };
3151
3152
3153 #if 0
3154
3155 static void
3156 x_dump_glyph_string (s)
3157 struct glyph_string *s;
3158 {
3159 fprintf (stderr, "glyph string\n");
3160 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
3161 s->x, s->y, s->width, s->height);
3162 fprintf (stderr, " ybase = %d\n", s->ybase);
3163 fprintf (stderr, " hl = %d\n", s->hl);
3164 fprintf (stderr, " left overhang = %d, right = %d\n",
3165 s->left_overhang, s->right_overhang);
3166 fprintf (stderr, " nchars = %d\n", s->nchars);
3167 fprintf (stderr, " extends to end of line = %d\n",
3168 s->extends_to_end_of_line_p);
3169 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
3170 fprintf (stderr, " bg width = %d\n", s->background_width);
3171 }
3172
3173 #endif /* GLYPH_DEBUG */
3174
3175
3176
3177 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3178 struct glyph_string **,
3179 struct glyph_string *,
3180 struct glyph_string *));
3181 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3182 struct glyph_string **,
3183 struct glyph_string *,
3184 struct glyph_string *));
3185 static void x_append_glyph_string P_ ((struct glyph_string **,
3186 struct glyph_string **,
3187 struct glyph_string *));
3188 static int x_left_overwritten P_ ((struct glyph_string *));
3189 static int x_left_overwriting P_ ((struct glyph_string *));
3190 static int x_right_overwritten P_ ((struct glyph_string *));
3191 static int x_right_overwriting P_ ((struct glyph_string *));
3192 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3193 int));
3194 static void x_init_glyph_string P_ ((struct glyph_string *,
3195 XChar2b *, struct window *,
3196 struct glyph_row *,
3197 enum glyph_row_area, int,
3198 enum draw_glyphs_face));
3199 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3200 enum glyph_row_area, int, int,
3201 enum draw_glyphs_face, int));
3202 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3203 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3204 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3205 int));
3206 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3207 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3208 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3209 static void x_draw_glyph_string P_ ((struct glyph_string *));
3210 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3211 static void x_set_cursor_gc P_ ((struct glyph_string *));
3212 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3213 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3214 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3215 int *, int *));
3216 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
3217 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3218 unsigned long *, double, int));*/
3219 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3220 double, int, unsigned long));
3221 static void x_setup_relief_colors P_ ((struct glyph_string *));
3222 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3223 static void x_draw_image_relief P_ ((struct glyph_string *));
3224 static void x_draw_image_foreground P_ ((struct glyph_string *));
3225 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3226 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3227 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3228 int, int, int));
3229 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
3230 int, int, int, int, Rect *));
3231 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
3232 int, int, int, Rect *));
3233 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3234 enum glyph_row_area));
3235 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3236 struct glyph_row *,
3237 enum glyph_row_area, int, int));
3238
3239 #if GLYPH_DEBUG
3240 static void x_check_font P_ ((struct frame *, XFontStruct *));
3241 #endif
3242
3243
3244 /* Append the list of glyph strings with head H and tail T to the list
3245 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3246
3247 static INLINE void
3248 x_append_glyph_string_lists (head, tail, h, t)
3249 struct glyph_string **head, **tail;
3250 struct glyph_string *h, *t;
3251 {
3252 if (h)
3253 {
3254 if (*head)
3255 (*tail)->next = h;
3256 else
3257 *head = h;
3258 h->prev = *tail;
3259 *tail = t;
3260 }
3261 }
3262
3263
3264 /* Prepend the list of glyph strings with head H and tail T to the
3265 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3266 result. */
3267
3268 static INLINE void
3269 x_prepend_glyph_string_lists (head, tail, h, t)
3270 struct glyph_string **head, **tail;
3271 struct glyph_string *h, *t;
3272 {
3273 if (h)
3274 {
3275 if (*head)
3276 (*head)->prev = t;
3277 else
3278 *tail = t;
3279 t->next = *head;
3280 *head = h;
3281 }
3282 }
3283
3284
3285 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3286 Set *HEAD and *TAIL to the resulting list. */
3287
3288 static INLINE void
3289 x_append_glyph_string (head, tail, s)
3290 struct glyph_string **head, **tail;
3291 struct glyph_string *s;
3292 {
3293 s->next = s->prev = NULL;
3294 x_append_glyph_string_lists (head, tail, s, s);
3295 }
3296
3297
3298 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3299 face. */
3300
3301 static void
3302 x_set_cursor_gc (s)
3303 struct glyph_string *s;
3304 {
3305 if (s->font == FRAME_FONT (s->f)
3306 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3307 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3308 && !s->cmp)
3309 s->gc = s->f->output_data.mac->cursor_gc;
3310 else
3311 {
3312 /* Cursor on non-default face: must merge. */
3313 XGCValues xgcv;
3314 unsigned long mask;
3315
3316 xgcv.background = s->f->output_data.mac->cursor_pixel;
3317 xgcv.foreground = s->face->background;
3318
3319 /* If the glyph would be invisible, try a different foreground. */
3320 if (xgcv.foreground == xgcv.background)
3321 xgcv.foreground = s->face->foreground;
3322 if (xgcv.foreground == xgcv.background)
3323 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3324 if (xgcv.foreground == xgcv.background)
3325 xgcv.foreground = s->face->foreground;
3326
3327 /* Make sure the cursor is distinct from text in this face. */
3328 if (xgcv.background == s->face->background
3329 && xgcv.foreground == s->face->foreground)
3330 {
3331 xgcv.background = s->face->foreground;
3332 xgcv.foreground = s->face->background;
3333 }
3334
3335 IF_DEBUG (x_check_font (s->f, s->font));
3336 xgcv.font = s->font;
3337 mask = GCForeground | GCBackground | GCFont;
3338
3339 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3340 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3341 mask, &xgcv);
3342 else
3343 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3344 = XCreateGC (s->display, s->window, mask, &xgcv);
3345
3346 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3347 }
3348 }
3349
3350
3351 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3352
3353 static void
3354 x_set_mouse_face_gc (s)
3355 struct glyph_string *s;
3356 {
3357 int face_id;
3358 struct face *face;
3359
3360 /* What face has to be used last for the mouse face? */
3361 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3362 face = FACE_FROM_ID (s->f, face_id);
3363 if (face == NULL)
3364 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3365
3366 if (s->first_glyph->type == CHAR_GLYPH)
3367 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3368 else
3369 face_id = FACE_FOR_CHAR (s->f, face, 0);
3370 s->face = FACE_FROM_ID (s->f, face_id);
3371 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3372
3373 /* If font in this face is same as S->font, use it. */
3374 if (s->font == s->face->font)
3375 s->gc = s->face->gc;
3376 else
3377 {
3378 /* Otherwise construct scratch_cursor_gc with values from FACE
3379 but font FONT. */
3380 XGCValues xgcv;
3381 unsigned long mask;
3382
3383 xgcv.background = s->face->background;
3384 xgcv.foreground = s->face->foreground;
3385 IF_DEBUG (x_check_font (s->f, s->font));
3386 xgcv.font = s->font;
3387 mask = GCForeground | GCBackground | GCFont;
3388
3389 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3390 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3391 mask, &xgcv);
3392 else
3393 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3394 = XCreateGC (s->display, s->window, mask, &xgcv);
3395
3396 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3397 }
3398
3399 xassert (s->gc != 0);
3400 }
3401
3402
3403 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3404 Faces to use in the mode line have already been computed when the
3405 matrix was built, so there isn't much to do, here. */
3406
3407 static INLINE void
3408 x_set_mode_line_face_gc (s)
3409 struct glyph_string *s;
3410 {
3411 s->gc = s->face->gc;
3412 }
3413
3414
3415 /* Set S->gc of glyph string S for drawing that glyph string. Set
3416 S->stippled_p to a non-zero value if the face of S has a stipple
3417 pattern. */
3418
3419 static INLINE void
3420 x_set_glyph_string_gc (s)
3421 struct glyph_string *s;
3422 {
3423 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3424
3425 if (s->hl == DRAW_NORMAL_TEXT)
3426 {
3427 s->gc = s->face->gc;
3428 s->stippled_p = s->face->stipple != 0;
3429 }
3430 else if (s->hl == DRAW_INVERSE_VIDEO)
3431 {
3432 x_set_mode_line_face_gc (s);
3433 s->stippled_p = s->face->stipple != 0;
3434 }
3435 else if (s->hl == DRAW_CURSOR)
3436 {
3437 x_set_cursor_gc (s);
3438 s->stippled_p = 0;
3439 }
3440 else if (s->hl == DRAW_MOUSE_FACE)
3441 {
3442 x_set_mouse_face_gc (s);
3443 s->stippled_p = s->face->stipple != 0;
3444 }
3445 else if (s->hl == DRAW_IMAGE_RAISED
3446 || s->hl == DRAW_IMAGE_SUNKEN)
3447 {
3448 s->gc = s->face->gc;
3449 s->stippled_p = s->face->stipple != 0;
3450 }
3451 else
3452 {
3453 s->gc = s->face->gc;
3454 s->stippled_p = s->face->stipple != 0;
3455 }
3456
3457 /* GC must have been set. */
3458 xassert (s->gc != 0);
3459 }
3460
3461
3462 /* Return in *R the clipping rectangle for glyph string S. */
3463
3464 static void
3465 x_get_glyph_string_clip_rect (s, r)
3466 struct glyph_string *s;
3467 Rect *r;
3468 {
3469 int r_height, r_width;
3470
3471 if (s->row->full_width_p)
3472 {
3473 /* Draw full-width. X coordinates are relative to S->w->left. */
3474 int canon_x = CANON_X_UNIT (s->f);
3475
3476 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3477 r_width = XFASTINT (s->w->width) * canon_x;
3478
3479 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3480 {
3481 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3482 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3483 r->left -= width;
3484 }
3485
3486 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3487
3488 /* Unless displaying a mode or menu bar line, which are always
3489 fully visible, clip to the visible part of the row. */
3490 if (s->w->pseudo_window_p)
3491 r_height = s->row->visible_height;
3492 else
3493 r_height = s->height;
3494 }
3495 else
3496 {
3497 /* This is a text line that may be partially visible. */
3498 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3499 r_width = window_box_width (s->w, s->area);
3500 r_height = s->row->visible_height;
3501 }
3502
3503 /* If S draws overlapping rows, it's sufficient to use the top and
3504 bottom of the window for clipping because this glyph string
3505 intentionally draws over other lines. */
3506 if (s->for_overlaps_p)
3507 {
3508 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3509 r_height = window_text_bottom_y (s->w) - r->top;
3510 }
3511 else
3512 {
3513 /* Don't use S->y for clipping because it doesn't take partially
3514 visible lines into account. For example, it can be negative for
3515 partially visible lines at the top of a window. */
3516 if (!s->row->full_width_p
3517 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3518 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3519 else
3520 r->top = max (0, s->row->y);
3521
3522 /* If drawing a tool-bar window, draw it over the internal border
3523 at the top of the window. */
3524 if (s->w == XWINDOW (s->f->tool_bar_window))
3525 r->top -= s->f->output_data.mac->internal_border_width;
3526 }
3527
3528 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3529
3530 r->bottom = r->top + r_height;
3531 r->right = r->left + r_width;
3532 }
3533
3534
3535 /* Set clipping for output of glyph string S. S may be part of a mode
3536 line or menu if we don't have X toolkit support. */
3537
3538 static INLINE void
3539 x_set_glyph_string_clipping (s)
3540 struct glyph_string *s;
3541 {
3542 Rect r;
3543 x_get_glyph_string_clip_rect (s, &r);
3544 mac_set_clip_rectangle (s->display, s->window, &r);
3545 }
3546
3547
3548 /* Compute left and right overhang of glyph string S. If S is a glyph
3549 string for a composition, assume overhangs don't exist. */
3550
3551 static INLINE void
3552 x_compute_glyph_string_overhangs (s)
3553 struct glyph_string *s;
3554 {
3555 if (s->cmp == NULL
3556 && s->first_glyph->type == CHAR_GLYPH)
3557 {
3558 XCharStruct cs;
3559 int direction, font_ascent, font_descent;
3560 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3561 &font_ascent, &font_descent, &cs);
3562 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3563 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3564 }
3565 }
3566
3567
3568 /* Compute overhangs and x-positions for glyph string S and its
3569 predecessors, or successors. X is the starting x-position for S.
3570 BACKWARD_P non-zero means process predecessors. */
3571
3572 static void
3573 x_compute_overhangs_and_x (s, x, backward_p)
3574 struct glyph_string *s;
3575 int x;
3576 int backward_p;
3577 {
3578 if (backward_p)
3579 {
3580 while (s)
3581 {
3582 x_compute_glyph_string_overhangs (s);
3583 x -= s->width;
3584 s->x = x;
3585 s = s->prev;
3586 }
3587 }
3588 else
3589 {
3590 while (s)
3591 {
3592 x_compute_glyph_string_overhangs (s);
3593 s->x = x;
3594 x += s->width;
3595 s = s->next;
3596 }
3597 }
3598 }
3599
3600
3601 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3602 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3603 assumed to be zero. */
3604
3605 void
3606 x_get_glyph_overhangs (glyph, f, left, right)
3607 struct glyph *glyph;
3608 struct frame *f;
3609 int *left, *right;
3610 {
3611 *left = *right = 0;
3612
3613 if (glyph->type == CHAR_GLYPH)
3614 {
3615 XFontStruct *font;
3616 struct face *face;
3617 struct font_info *font_info;
3618 XChar2b char2b;
3619 XCharStruct *pcm;
3620
3621 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3622 font = face->font;
3623 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3624 if (font
3625 && (pcm = x_per_char_metric (font, &char2b)))
3626 {
3627 if (pcm->rbearing > pcm->width)
3628 *right = pcm->rbearing - pcm->width;
3629 if (pcm->lbearing < 0)
3630 *left = -pcm->lbearing;
3631 }
3632 }
3633 }
3634
3635
3636 /* Return the index of the first glyph preceding glyph string S that
3637 is overwritten by S because of S's left overhang. Value is -1
3638 if no glyphs are overwritten. */
3639
3640 static int
3641 x_left_overwritten (s)
3642 struct glyph_string *s;
3643 {
3644 int k;
3645
3646 if (s->left_overhang)
3647 {
3648 int x = 0, i;
3649 struct glyph *glyphs = s->row->glyphs[s->area];
3650 int first = s->first_glyph - glyphs;
3651
3652 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3653 x -= glyphs[i].pixel_width;
3654
3655 k = i + 1;
3656 }
3657 else
3658 k = -1;
3659
3660 return k;
3661 }
3662
3663
3664 /* Return the index of the first glyph preceding glyph string S that
3665 is overwriting S because of its right overhang. Value is -1 if no
3666 glyph in front of S overwrites S. */
3667
3668 static int
3669 x_left_overwriting (s)
3670 struct glyph_string *s;
3671 {
3672 int i, k, x;
3673 struct glyph *glyphs = s->row->glyphs[s->area];
3674 int first = s->first_glyph - glyphs;
3675
3676 k = -1;
3677 x = 0;
3678 for (i = first - 1; i >= 0; --i)
3679 {
3680 int left, right;
3681 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3682 if (x + right > 0)
3683 k = i;
3684 x -= glyphs[i].pixel_width;
3685 }
3686
3687 return k;
3688 }
3689
3690
3691 /* Return the index of the last glyph following glyph string S that is
3692 not overwritten by S because of S's right overhang. Value is -1 if
3693 no such glyph is found. */
3694
3695 static int
3696 x_right_overwritten (s)
3697 struct glyph_string *s;
3698 {
3699 int k = -1;
3700
3701 if (s->right_overhang)
3702 {
3703 int x = 0, i;
3704 struct glyph *glyphs = s->row->glyphs[s->area];
3705 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3706 int end = s->row->used[s->area];
3707
3708 for (i = first; i < end && s->right_overhang > x; ++i)
3709 x += glyphs[i].pixel_width;
3710
3711 k = i;
3712 }
3713
3714 return k;
3715 }
3716
3717
3718 /* Return the index of the last glyph following glyph string S that
3719 overwrites S because of its left overhang. Value is negative
3720 if no such glyph is found. */
3721
3722 static int
3723 x_right_overwriting (s)
3724 struct glyph_string *s;
3725 {
3726 int i, k, x;
3727 int end = s->row->used[s->area];
3728 struct glyph *glyphs = s->row->glyphs[s->area];
3729 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3730
3731 k = -1;
3732 x = 0;
3733 for (i = first; i < end; ++i)
3734 {
3735 int left, right;
3736 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3737 if (x - left < 0)
3738 k = i;
3739 x += glyphs[i].pixel_width;
3740 }
3741
3742 return k;
3743 }
3744
3745
3746 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3747
3748 static INLINE void
3749 x_clear_glyph_string_rect (s, x, y, w, h)
3750 struct glyph_string *s;
3751 int x, y, w, h;
3752 {
3753 XGCValues xgcv;
3754
3755 xgcv.foreground = s->gc->background;
3756 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3757 }
3758
3759
3760 /* Draw the background of glyph_string S. If S->background_filled_p
3761 is non-zero don't draw it. FORCE_P non-zero means draw the
3762 background even if it wouldn't be drawn normally. This is used
3763 when a string preceding S draws into the background of S, or S
3764 contains the first component of a composition. */
3765
3766 static void
3767 x_draw_glyph_string_background (s, force_p)
3768 struct glyph_string *s;
3769 int force_p;
3770 {
3771 /* Nothing to do if background has already been drawn or if it
3772 shouldn't be drawn in the first place. */
3773 if (!s->background_filled_p)
3774 {
3775 int box_line_width = max (s->face->box_line_width, 0);
3776
3777 #if 0 /* MAC_TODO: stipple */
3778 if (s->stippled_p)
3779 {
3780 /* Fill background with a stipple pattern. */
3781 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3782 XFillRectangle (s->display, s->window, s->gc, s->x,
3783 s->y + box_line_width,
3784 s->background_width,
3785 s->height - 2 * box_line_width);
3786 XSetFillStyle (s->display, s->gc, FillSolid);
3787 s->background_filled_p = 1;
3788 }
3789 else
3790 #endif
3791 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3792 || s->font_not_found_p
3793 || s->extends_to_end_of_line_p
3794 || force_p)
3795 {
3796 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3797 s->background_width,
3798 s->height - 2 * box_line_width);
3799 s->background_filled_p = 1;
3800 }
3801 }
3802 }
3803
3804
3805 /* Draw the foreground of glyph string S. */
3806
3807 static void
3808 x_draw_glyph_string_foreground (s)
3809 struct glyph_string *s;
3810 {
3811 int i, x;
3812
3813 /* If first glyph of S has a left box line, start drawing the text
3814 of S to the right of that box line. */
3815 if (s->face->box != FACE_NO_BOX
3816 && s->first_glyph->left_box_line_p)
3817 x = s->x + abs (s->face->box_line_width);
3818 else
3819 x = s->x;
3820
3821 /* Draw characters of S as rectangles if S's font could not be
3822 loaded. */
3823 if (s->font_not_found_p)
3824 {
3825 for (i = 0; i < s->nchars; ++i)
3826 {
3827 struct glyph *g = s->first_glyph + i;
3828 mac_draw_rectangle (s->display, s->window,
3829 s->gc, x, s->y, g->pixel_width - 1,
3830 s->height - 1);
3831 x += g->pixel_width;
3832 }
3833 }
3834 else
3835 {
3836 char *char1b = (char *) s->char2b;
3837 int boff = s->font_info->baseline_offset;
3838
3839 if (s->font_info->vertical_centering)
3840 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3841
3842 /* If we can use 8-bit functions, condense S->char2b. */
3843 if (!s->two_byte_p)
3844 for (i = 0; i < s->nchars; ++i)
3845 char1b[i] = s->char2b[i].byte2;
3846
3847 /* Draw text with XDrawString if background has already been
3848 filled. Otherwise, use XDrawImageString. (Note that
3849 XDrawImageString is usually faster than XDrawString.) Always
3850 use XDrawImageString when drawing the cursor so that there is
3851 no chance that characters under a box cursor are invisible. */
3852 if (s->for_overlaps_p
3853 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3854 {
3855 /* Draw characters with 16-bit or 8-bit functions. */
3856 if (s->two_byte_p)
3857 XDrawString16 (s->display, s->window, s->gc, x,
3858 s->ybase - boff, s->char2b, s->nchars);
3859 else
3860 XDrawString (s->display, s->window, s->gc, x,
3861 s->ybase - boff, char1b, s->nchars);
3862 }
3863 else
3864 {
3865 if (s->two_byte_p)
3866 XDrawImageString16 (s->display, s->window, s->gc, x,
3867 s->ybase - boff, s->char2b, s->nchars);
3868 else
3869 XDrawImageString (s->display, s->window, s->gc, x,
3870 s->ybase - boff, char1b, s->nchars);
3871 }
3872 }
3873 }
3874
3875 /* Draw the foreground of composite glyph string S. */
3876
3877 static void
3878 x_draw_composite_glyph_string_foreground (s)
3879 struct glyph_string *s;
3880 {
3881 int i, x;
3882
3883 /* If first glyph of S has a left box line, start drawing the text
3884 of S to the right of that box line. */
3885 if (s->face->box != FACE_NO_BOX
3886 && s->first_glyph->left_box_line_p)
3887 x = s->x + abs (s->face->box_line_width);
3888 else
3889 x = s->x;
3890
3891 /* S is a glyph string for a composition. S->gidx is the index of
3892 the first character drawn for glyphs of this composition.
3893 S->gidx == 0 means we are drawing the very first character of
3894 this composition. */
3895
3896 /* Draw a rectangle for the composition if the font for the very
3897 first character of the composition could not be loaded. */
3898 if (s->font_not_found_p)
3899 {
3900 if (s->gidx == 0)
3901 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3902 s->width - 1, s->height - 1);
3903 }
3904 else
3905 {
3906 for (i = 0; i < s->nchars; i++, ++s->gidx)
3907 XDrawString16 (s->display, s->window, s->gc,
3908 x + s->cmp->offsets[s->gidx * 2],
3909 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3910 s->char2b + i, 1);
3911 }
3912 }
3913
3914
3915 #ifdef USE_X_TOOLKIT
3916
3917 static struct frame *x_frame_of_widget P_ ((Widget));
3918
3919
3920 /* Return the frame on which widget WIDGET is used.. Abort if frame
3921 cannot be determined. */
3922
3923 static struct frame *
3924 x_frame_of_widget (widget)
3925 Widget widget;
3926 {
3927 struct x_display_info *dpyinfo;
3928 Lisp_Object tail;
3929 struct frame *f;
3930
3931 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3932
3933 /* Find the top-level shell of the widget. Note that this function
3934 can be called when the widget is not yet realized, so XtWindow
3935 (widget) == 0. That's the reason we can't simply use
3936 x_any_window_to_frame. */
3937 while (!XtIsTopLevelShell (widget))
3938 widget = XtParent (widget);
3939
3940 /* Look for a frame with that top-level widget. Allocate the color
3941 on that frame to get the right gamma correction value. */
3942 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3943 if (GC_FRAMEP (XCAR (tail))
3944 && (f = XFRAME (XCAR (tail)),
3945 (f->output_data.nothing != 1
3946 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3947 && f->output_data.x->widget == widget)
3948 return f;
3949
3950 abort ();
3951 }
3952
3953
3954 /* Allocate the color COLOR->pixel on the screen and display of
3955 widget WIDGET in colormap CMAP. If an exact match cannot be
3956 allocated, try the nearest color available. Value is non-zero
3957 if successful. This is called from lwlib. */
3958
3959 int
3960 x_alloc_nearest_color_for_widget (widget, cmap, color)
3961 Widget widget;
3962 Colormap cmap;
3963 XColor *color;
3964 {
3965 struct frame *f = x_frame_of_widget (widget);
3966 return x_alloc_nearest_color (f, cmap, color);
3967 }
3968
3969
3970 #endif /* USE_X_TOOLKIT */
3971
3972 #if 0 /* MAC_TODO */
3973
3974 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3975 CMAP. If an exact match can't be allocated, try the nearest color
3976 available. Value is non-zero if successful. Set *COLOR to the
3977 color allocated. */
3978
3979 int
3980 x_alloc_nearest_color (f, cmap, color)
3981 struct frame *f;
3982 Colormap cmap;
3983 XColor *color;
3984 {
3985 Display *display = FRAME_X_DISPLAY (f);
3986 Screen *screen = FRAME_X_SCREEN (f);
3987 int rc;
3988
3989 gamma_correct (f, color);
3990 rc = XAllocColor (display, cmap, color);
3991 if (rc == 0)
3992 {
3993 /* If we got to this point, the colormap is full, so we're going
3994 to try to get the next closest color. The algorithm used is
3995 a least-squares matching, which is what X uses for closest
3996 color matching with StaticColor visuals. */
3997 int nearest, i;
3998 unsigned long nearest_delta = ~0;
3999 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
4000 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
4001
4002 for (i = 0; i < ncells; ++i)
4003 cells[i].pixel = i;
4004 XQueryColors (display, cmap, cells, ncells);
4005
4006 for (nearest = i = 0; i < ncells; ++i)
4007 {
4008 long dred = (color->red >> 8) - (cells[i].red >> 8);
4009 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
4010 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
4011 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
4012
4013 if (delta < nearest_delta)
4014 {
4015 nearest = i;
4016 nearest_delta = delta;
4017 }
4018 }
4019
4020 color->red = cells[nearest].red;
4021 color->green = cells[nearest].green;
4022 color->blue = cells[nearest].blue;
4023 rc = XAllocColor (display, cmap, color);
4024 }
4025
4026 #ifdef DEBUG_X_COLORS
4027 if (rc)
4028 register_color (color->pixel);
4029 #endif /* DEBUG_X_COLORS */
4030
4031 return rc;
4032 }
4033
4034
4035 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4036 It's necessary to do this instead of just using PIXEL directly to
4037 get color reference counts right. */
4038
4039 unsigned long
4040 x_copy_color (f, pixel)
4041 struct frame *f;
4042 unsigned long pixel;
4043 {
4044 XColor color;
4045
4046 color.pixel = pixel;
4047 BLOCK_INPUT;
4048 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4049 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4050 UNBLOCK_INPUT;
4051 #ifdef DEBUG_X_COLORS
4052 register_color (pixel);
4053 #endif
4054 return color.pixel;
4055 }
4056
4057
4058 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4059 It's necessary to do this instead of just using PIXEL directly to
4060 get color reference counts right. */
4061
4062 unsigned long
4063 x_copy_dpy_color (dpy, cmap, pixel)
4064 Display *dpy;
4065 Colormap cmap;
4066 unsigned long pixel;
4067 {
4068 XColor color;
4069
4070 color.pixel = pixel;
4071 BLOCK_INPUT;
4072 XQueryColor (dpy, cmap, &color);
4073 XAllocColor (dpy, cmap, &color);
4074 UNBLOCK_INPUT;
4075 #ifdef DEBUG_X_COLORS
4076 register_color (pixel);
4077 #endif
4078 return color.pixel;
4079 }
4080
4081 #endif /* MAC_TODO */
4082
4083 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
4084 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4085 If this produces the same color as COLOR, try a color where all RGB
4086 values have DELTA added. Return the allocated color in *COLOR.
4087 DISPLAY is the X display, CMAP is the colormap to operate on.
4088 Value is non-zero if successful. */
4089
4090 static int
4091 mac_alloc_lighter_color (f, color, factor, delta)
4092 struct frame *f;
4093 unsigned long *color;
4094 double factor;
4095 int delta;
4096 {
4097 unsigned long new;
4098
4099 /* Change RGB values by specified FACTOR. Avoid overflow! */
4100 xassert (factor >= 0);
4101 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
4102 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
4103 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
4104 if (new == *color)
4105 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
4106 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
4107 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
4108
4109 /* MAC_TODO: Map to palette and retry with delta if same? */
4110 /* MAC_TODO: Free colors (if using palette)? */
4111
4112 if (new == *color)
4113 return 0;
4114
4115 *color = new;
4116
4117 return 1;
4118 }
4119
4120
4121 /* Set up the foreground color for drawing relief lines of glyph
4122 string S. RELIEF is a pointer to a struct relief containing the GC
4123 with which lines will be drawn. Use a color that is FACTOR or
4124 DELTA lighter or darker than the relief's background which is found
4125 in S->f->output_data.x->relief_background. If such a color cannot
4126 be allocated, use DEFAULT_PIXEL, instead. */
4127
4128 static void
4129 x_setup_relief_color (f, relief, factor, delta, default_pixel)
4130 struct frame *f;
4131 struct relief *relief;
4132 double factor;
4133 int delta;
4134 unsigned long default_pixel;
4135 {
4136 XGCValues xgcv;
4137 struct mac_output *di = f->output_data.mac;
4138 unsigned long mask = GCForeground;
4139 unsigned long pixel;
4140 unsigned long background = di->relief_background;
4141 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4142
4143 /* MAC_TODO: Free colors (if using palette)? */
4144
4145 /* Allocate new color. */
4146 xgcv.foreground = default_pixel;
4147 pixel = background;
4148 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
4149 {
4150 relief->allocated_p = 1;
4151 xgcv.foreground = relief->pixel = pixel;
4152 }
4153
4154 if (relief->gc == 0)
4155 {
4156 #if 0 /* MAC_TODO: stipple */
4157 xgcv.stipple = dpyinfo->gray;
4158 mask |= GCStipple;
4159 #endif
4160 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4161 }
4162 else
4163 XChangeGC (NULL, relief->gc, mask, &xgcv);
4164 }
4165
4166
4167 /* Set up colors for the relief lines around glyph string S. */
4168
4169 static void
4170 x_setup_relief_colors (s)
4171 struct glyph_string *s;
4172 {
4173 struct mac_output *di = s->f->output_data.mac;
4174 unsigned long color;
4175
4176 if (s->face->use_box_color_for_shadows_p)
4177 color = s->face->box_color;
4178 else
4179 {
4180 XGCValues xgcv;
4181
4182 /* Get the background color of the face. */
4183 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4184 color = xgcv.background;
4185 }
4186
4187 if (di->white_relief.gc == 0
4188 || color != di->relief_background)
4189 {
4190 di->relief_background = color;
4191 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4192 WHITE_PIX_DEFAULT (s->f));
4193 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4194 BLACK_PIX_DEFAULT (s->f));
4195 }
4196 }
4197
4198
4199 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
4200 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4201 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4202 relief. LEFT_P non-zero means draw a relief on the left side of
4203 the rectangle. RIGHT_P non-zero means draw a relief on the right
4204 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4205 when drawing. */
4206
4207 static void
4208 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4209 raised_p, left_p, right_p, clip_rect)
4210 struct frame *f;
4211 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4212 Rect *clip_rect;
4213 {
4214 int i;
4215 GC gc;
4216
4217 if (raised_p)
4218 gc = f->output_data.mac->white_relief.gc;
4219 else
4220 gc = f->output_data.mac->black_relief.gc;
4221 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4222
4223 /* Top. */
4224 for (i = 0; i < width; ++i)
4225 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4226 left_x + i * left_p, top_y + i,
4227 right_x + 1 - i * right_p, top_y + i);
4228
4229 /* Left. */
4230 if (left_p)
4231 for (i = 0; i < width; ++i)
4232 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4233 left_x + i, top_y + i, left_x + i, bottom_y - i);
4234
4235 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4236 if (raised_p)
4237 gc = f->output_data.mac->black_relief.gc;
4238 else
4239 gc = f->output_data.mac->white_relief.gc;
4240 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4241 clip_rect);
4242
4243 /* Bottom. */
4244 for (i = 0; i < width; ++i)
4245 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4246 left_x + i * left_p, bottom_y - i,
4247 right_x + 1 - i * right_p, bottom_y - i);
4248
4249 /* Right. */
4250 if (right_p)
4251 for (i = 0; i < width; ++i)
4252 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4253 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4254
4255 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4256 }
4257
4258
4259 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4260 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4261 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4262 left side of the rectangle. RIGHT_P non-zero means draw a line
4263 on the right side of the rectangle. CLIP_RECT is the clipping
4264 rectangle to use when drawing. */
4265
4266 static void
4267 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4268 left_p, right_p, clip_rect)
4269 struct glyph_string *s;
4270 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4271 Rect *clip_rect;
4272 {
4273 XGCValues xgcv;
4274
4275 xgcv.foreground = s->face->box_color;
4276 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4277
4278 /* Top. */
4279 XFillRectangle (s->display, s->window, &xgcv,
4280 left_x, top_y, right_x - left_x, width);
4281
4282 /* Left. */
4283 if (left_p)
4284 XFillRectangle (s->display, s->window, &xgcv,
4285 left_x, top_y, width, bottom_y - top_y);
4286
4287 /* Bottom. */
4288 XFillRectangle (s->display, s->window, &xgcv,
4289 left_x, bottom_y - width, right_x - left_x, width);
4290
4291 /* Right. */
4292 if (right_p)
4293 XFillRectangle (s->display, s->window, &xgcv,
4294 right_x - width, top_y, width, bottom_y - top_y);
4295
4296 mac_reset_clipping (s->display, s->window);
4297 }
4298
4299
4300 /* Draw a box around glyph string S. */
4301
4302 static void
4303 x_draw_glyph_string_box (s)
4304 struct glyph_string *s;
4305 {
4306 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4307 int left_p, right_p;
4308 struct glyph *last_glyph;
4309 Rect clip_rect;
4310
4311 last_x = window_box_right (s->w, s->area);
4312 if (s->row->full_width_p
4313 && !s->w->pseudo_window_p)
4314 {
4315 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4316 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4317 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4318 }
4319
4320 /* The glyph that may have a right box line. */
4321 last_glyph = (s->cmp || s->img
4322 ? s->first_glyph
4323 : s->first_glyph + s->nchars - 1);
4324
4325 width = abs (s->face->box_line_width);
4326 raised_p = s->face->box == FACE_RAISED_BOX;
4327 left_x = s->x;
4328 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
4329 ? last_x - 1
4330 : min (last_x, s->x + s->background_width) - 1));
4331 top_y = s->y;
4332 bottom_y = top_y + s->height - 1;
4333
4334 left_p = (s->first_glyph->left_box_line_p
4335 || (s->hl == DRAW_MOUSE_FACE
4336 && (s->prev == NULL
4337 || s->prev->hl != s->hl)));
4338 right_p = (last_glyph->right_box_line_p
4339 || (s->hl == DRAW_MOUSE_FACE
4340 && (s->next == NULL
4341 || s->next->hl != s->hl)));
4342
4343 x_get_glyph_string_clip_rect (s, &clip_rect);
4344
4345 if (s->face->box == FACE_SIMPLE_BOX)
4346 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4347 left_p, right_p, &clip_rect);
4348 else
4349 {
4350 x_setup_relief_colors (s);
4351 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4352 width, raised_p, left_p, right_p, &clip_rect);
4353 }
4354 }
4355
4356
4357 /* Draw foreground of image glyph string S. */
4358
4359 static void
4360 x_draw_image_foreground (s)
4361 struct glyph_string *s;
4362 {
4363 int x;
4364 int y = s->ybase - image_ascent (s->img, s->face);
4365
4366 /* If first glyph of S has a left box line, start drawing it to the
4367 right of that line. */
4368 if (s->face->box != FACE_NO_BOX
4369 && s->first_glyph->left_box_line_p)
4370 x = s->x + abs (s->face->box_line_width);
4371 else
4372 x = s->x;
4373
4374 /* If there is a margin around the image, adjust x- and y-position
4375 by that margin. */
4376 x += s->img->hmargin;
4377 y += s->img->vmargin;
4378
4379 if (s->img->pixmap)
4380 {
4381 #if 0 /* MAC_TODO: image mask */
4382 if (s->img->mask)
4383 {
4384 /* We can't set both a clip mask and use XSetClipRectangles
4385 because the latter also sets a clip mask. We also can't
4386 trust on the shape extension to be available
4387 (XShapeCombineRegion). So, compute the rectangle to draw
4388 manually. */
4389 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4390 | GCFunction);
4391 XGCValues xgcv;
4392 XRectangle clip_rect, image_rect, r;
4393
4394 xgcv.clip_mask = s->img->mask;
4395 xgcv.clip_x_origin = x;
4396 xgcv.clip_y_origin = y;
4397 xgcv.function = GXcopy;
4398 XChangeGC (s->display, s->gc, mask, &xgcv);
4399
4400 x_get_glyph_string_clip_rect (s, &clip_rect);
4401 image_rect.x = x;
4402 image_rect.y = y;
4403 image_rect.width = s->img->width;
4404 image_rect.height = s->img->height;
4405 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4406 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4407 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4408 }
4409 else
4410 #endif /* MAC_TODO */
4411 {
4412 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4413 0, 0, s->img->width, s->img->height, x, y);
4414
4415 /* When the image has a mask, we can expect that at
4416 least part of a mouse highlight or a block cursor will
4417 be visible. If the image doesn't have a mask, make
4418 a block cursor visible by drawing a rectangle around
4419 the image. I believe it's looking better if we do
4420 nothing here for mouse-face. */
4421 if (s->hl == DRAW_CURSOR)
4422 {
4423 int r = s->img->relief;
4424 if (r < 0) r = -r;
4425 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
4426 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4427 }
4428 }
4429 }
4430 else
4431 /* Draw a rectangle if image could not be loaded. */
4432 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4433 s->img->width - 1, s->img->height - 1);
4434 }
4435
4436
4437
4438 /* Draw a relief around the image glyph string S. */
4439
4440 static void
4441 x_draw_image_relief (s)
4442 struct glyph_string *s;
4443 {
4444 int x0, y0, x1, y1, thick, raised_p;
4445 Rect r;
4446 int x;
4447 int y = s->ybase - image_ascent (s->img, s->face);
4448
4449 /* If first glyph of S has a left box line, start drawing it to the
4450 right of that line. */
4451 if (s->face->box != FACE_NO_BOX
4452 && s->first_glyph->left_box_line_p)
4453 x = s->x + abs (s->face->box_line_width);
4454 else
4455 x = s->x;
4456
4457 /* If there is a margin around the image, adjust x- and y-position
4458 by that margin. */
4459 x += s->img->hmargin;
4460 y += s->img->vmargin;
4461
4462 if (s->hl == DRAW_IMAGE_SUNKEN
4463 || s->hl == DRAW_IMAGE_RAISED)
4464 {
4465 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4466 raised_p = s->hl == DRAW_IMAGE_RAISED;
4467 }
4468 else
4469 {
4470 thick = abs (s->img->relief);
4471 raised_p = s->img->relief > 0;
4472 }
4473
4474 x0 = x - thick;
4475 y0 = y - thick;
4476 x1 = x + s->img->width + thick - 1;
4477 y1 = y + s->img->height + thick - 1;
4478
4479 x_setup_relief_colors (s);
4480 x_get_glyph_string_clip_rect (s, &r);
4481 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4482 }
4483
4484
4485 /* Draw the foreground of image glyph string S to PIXMAP. */
4486
4487 static void
4488 x_draw_image_foreground_1 (s, pixmap)
4489 struct glyph_string *s;
4490 Pixmap pixmap;
4491 {
4492 int x;
4493 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4494
4495 /* If first glyph of S has a left box line, start drawing it to the
4496 right of that line. */
4497 if (s->face->box != FACE_NO_BOX
4498 && s->first_glyph->left_box_line_p)
4499 x = abs (s->face->box_line_width);
4500 else
4501 x = 0;
4502
4503 /* If there is a margin around the image, adjust x- and y-position
4504 by that margin. */
4505 x += s->img->hmargin;
4506 y += s->img->vmargin;
4507
4508 if (s->img->pixmap)
4509 {
4510 #if 0 /* MAC_TODO: image mask */
4511 if (s->img->mask)
4512 {
4513 /* We can't set both a clip mask and use XSetClipRectangles
4514 because the latter also sets a clip mask. We also can't
4515 trust on the shape extension to be available
4516 (XShapeCombineRegion). So, compute the rectangle to draw
4517 manually. */
4518 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4519 | GCFunction);
4520 XGCValues xgcv;
4521
4522 xgcv.clip_mask = s->img->mask;
4523 xgcv.clip_x_origin = x;
4524 xgcv.clip_y_origin = y;
4525 xgcv.function = GXcopy;
4526 XChangeGC (s->display, s->gc, mask, &xgcv);
4527
4528 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4529 0, 0, s->img->width, s->img->height, x, y);
4530 XSetClipMask (s->display, s->gc, None);
4531 }
4532 else
4533 #endif /* MAC_TODO */
4534 {
4535 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4536 0, 0, s->img->width, s->img->height, x, y);
4537
4538 /* When the image has a mask, we can expect that at
4539 least part of a mouse highlight or a block cursor will
4540 be visible. If the image doesn't have a mask, make
4541 a block cursor visible by drawing a rectangle around
4542 the image. I believe it's looking better if we do
4543 nothing here for mouse-face. */
4544 if (s->hl == DRAW_CURSOR)
4545 {
4546 int r = s->img->relief;
4547 if (r < 0) r = -r;
4548 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
4549 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4550 }
4551 }
4552 }
4553 else
4554 /* Draw a rectangle if image could not be loaded. */
4555 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4556 s->img->width - 1, s->img->height - 1);
4557 }
4558
4559
4560 /* Draw part of the background of glyph string S. X, Y, W, and H
4561 give the rectangle to draw. */
4562
4563 static void
4564 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4565 struct glyph_string *s;
4566 int x, y, w, h;
4567 {
4568 #if 0 /* MAC_TODO: stipple */
4569 if (s->stippled_p)
4570 {
4571 /* Fill background with a stipple pattern. */
4572 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4573 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4574 XSetFillStyle (s->display, s->gc, FillSolid);
4575 }
4576 else
4577 #endif /* MAC_TODO */
4578 x_clear_glyph_string_rect (s, x, y, w, h);
4579 }
4580
4581
4582 /* Draw image glyph string S.
4583
4584 s->y
4585 s->x +-------------------------
4586 | s->face->box
4587 |
4588 | +-------------------------
4589 | | s->img->vmargin
4590 | |
4591 | | +-------------------
4592 | | | the image
4593
4594 */
4595
4596 static void
4597 x_draw_image_glyph_string (s)
4598 struct glyph_string *s;
4599 {
4600 int x, y;
4601 int box_line_hwidth = abs (s->face->box_line_width);
4602 int box_line_vwidth = max (s->face->box_line_width, 0);
4603 int height;
4604 Pixmap pixmap = 0;
4605
4606 height = s->height - 2 * box_line_vwidth;
4607
4608 /* Fill background with face under the image. Do it only if row is
4609 taller than image or if image has a clip mask to reduce
4610 flickering. */
4611 s->stippled_p = s->face->stipple != 0;
4612 if (height > s->img->height
4613 || s->img->hmargin
4614 || s->img->vmargin
4615 #if 0 /* TODO: image mask */
4616 || s->img->mask
4617 #endif
4618 || s->img->pixmap == 0
4619 || s->width != s->background_width)
4620 {
4621 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4622 x = s->x + box_line_hwidth;
4623 else
4624 x = s->x;
4625
4626 y = s->y + box_line_vwidth;
4627 #if 0 /* TODO: image mask */
4628 if (s->img->mask)
4629 {
4630 /* Create a pixmap as large as the glyph string. Fill it
4631 with the background color. Copy the image to it, using
4632 its mask. Copy the temporary pixmap to the display. */
4633 Screen *screen = FRAME_X_SCREEN (s->f);
4634 int depth = DefaultDepthOfScreen (screen);
4635
4636 /* Create a pixmap as large as the glyph string. */
4637 pixmap = XCreatePixmap (s->display, s->window,
4638 s->background_width,
4639 s->height, depth);
4640
4641 /* Don't clip in the following because we're working on the
4642 pixmap. */
4643 XSetClipMask (s->display, s->gc, None);
4644
4645 /* Fill the pixmap with the background color/stipple. */
4646 if (s->stippled_p)
4647 {
4648 /* Fill background with a stipple pattern. */
4649 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4650 XFillRectangle (s->display, pixmap, s->gc,
4651 0, 0, s->background_width, s->height);
4652 XSetFillStyle (s->display, s->gc, FillSolid);
4653 }
4654 else
4655 {
4656 XGCValues xgcv;
4657 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4658 &xgcv);
4659 XSetForeground (s->display, s->gc, xgcv.background);
4660 XFillRectangle (s->display, pixmap, s->gc,
4661 0, 0, s->background_width, s->height);
4662 XSetForeground (s->display, s->gc, xgcv.foreground);
4663 }
4664 }
4665 else
4666 #endif
4667 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4668
4669 s->background_filled_p = 1;
4670 }
4671
4672 /* Draw the foreground. */
4673 if (pixmap != 0)
4674 {
4675 x_draw_image_foreground_1 (s, pixmap);
4676 x_set_glyph_string_clipping (s);
4677 mac_copy_area (s->display, pixmap, s->window, s->gc,
4678 0, 0, s->background_width, s->height, s->x, s->y);
4679 mac_reset_clipping (s->display, s->window);
4680 XFreePixmap (s->display, pixmap);
4681 }
4682 else
4683 x_draw_image_foreground (s);
4684
4685 /* If we must draw a relief around the image, do it. */
4686 if (s->img->relief
4687 || s->hl == DRAW_IMAGE_RAISED
4688 || s->hl == DRAW_IMAGE_SUNKEN)
4689 x_draw_image_relief (s);
4690 }
4691
4692
4693 /* Draw stretch glyph string S. */
4694
4695 static void
4696 x_draw_stretch_glyph_string (s)
4697 struct glyph_string *s;
4698 {
4699 xassert (s->first_glyph->type == STRETCH_GLYPH);
4700 s->stippled_p = s->face->stipple != 0;
4701
4702 if (s->hl == DRAW_CURSOR
4703 && !x_stretch_cursor_p)
4704 {
4705 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4706 as wide as the stretch glyph. */
4707 int width = min (CANON_X_UNIT (s->f), s->background_width);
4708
4709 /* Draw cursor. */
4710 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4711
4712 /* Clear rest using the GC of the original non-cursor face. */
4713 if (width < s->background_width)
4714 {
4715 GC gc = s->face->gc;
4716 int x = s->x + width, y = s->y;
4717 int w = s->background_width - width, h = s->height;
4718 Rect r;
4719
4720 if (s->row->mouse_face_p
4721 && cursor_in_mouse_face_p (s->w))
4722 {
4723 x_set_mouse_face_gc (s);
4724 gc = s->gc;
4725 }
4726 else
4727 gc = s->face->gc;
4728
4729 x_get_glyph_string_clip_rect (s, &r);
4730 mac_set_clip_rectangle (s->display, s->window, &r);
4731
4732 #if 0 /* MAC_TODO: stipple */
4733 if (s->face->stipple)
4734 {
4735 /* Fill background with a stipple pattern. */
4736 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4737 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4738 XSetFillStyle (s->display, gc, FillSolid);
4739 }
4740 else
4741 #endif /* MAC_TODO */
4742 {
4743 XGCValues xgcv;
4744 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4745 XSetForeground (s->display, gc, xgcv.background);
4746 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4747 XSetForeground (s->display, gc, xgcv.foreground);
4748 }
4749
4750 mac_reset_clipping (s->display, s->window);
4751 }
4752 }
4753 else if (!s->background_filled_p)
4754 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4755 s->height);
4756
4757 s->background_filled_p = 1;
4758 }
4759
4760
4761 /* Draw glyph string S. */
4762
4763 static void
4764 x_draw_glyph_string (s)
4765 struct glyph_string *s;
4766 {
4767 int relief_drawn_p = 0;
4768
4769 /* If S draws into the background of its successor, draw the
4770 background of the successor first so that S can draw into it.
4771 This makes S->next use XDrawString instead of XDrawImageString. */
4772 if (s->next && s->right_overhang && !s->for_overlaps_p)
4773 {
4774 xassert (s->next->img == NULL);
4775 x_set_glyph_string_gc (s->next);
4776 x_set_glyph_string_clipping (s->next);
4777 x_draw_glyph_string_background (s->next, 1);
4778
4779 }
4780
4781 /* Set up S->gc, set clipping and draw S. */
4782 x_set_glyph_string_gc (s);
4783
4784 /* Draw relief (if any) in advance for char/composition so that the
4785 glyph string can be drawn over it. */
4786 if (!s->for_overlaps_p
4787 && s->face->box != FACE_NO_BOX
4788 && (s->first_glyph->type == CHAR_GLYPH
4789 || s->first_glyph->type == COMPOSITE_GLYPH))
4790
4791 {
4792 x_set_glyph_string_clipping (s);
4793 x_draw_glyph_string_background (s, 1);
4794 x_draw_glyph_string_box (s);
4795 x_set_glyph_string_clipping (s);
4796 relief_drawn_p = 1;
4797 }
4798 else
4799 x_set_glyph_string_clipping (s);
4800
4801 switch (s->first_glyph->type)
4802 {
4803 case IMAGE_GLYPH:
4804 x_draw_image_glyph_string (s);
4805 break;
4806
4807 case STRETCH_GLYPH:
4808 x_draw_stretch_glyph_string (s);
4809 break;
4810
4811 case CHAR_GLYPH:
4812 if (s->for_overlaps_p)
4813 s->background_filled_p = 1;
4814 else
4815 x_draw_glyph_string_background (s, 0);
4816 x_draw_glyph_string_foreground (s);
4817 break;
4818
4819 case COMPOSITE_GLYPH:
4820 if (s->for_overlaps_p || s->gidx > 0)
4821 s->background_filled_p = 1;
4822 else
4823 x_draw_glyph_string_background (s, 1);
4824 x_draw_composite_glyph_string_foreground (s);
4825 break;
4826
4827 default:
4828 abort ();
4829 }
4830
4831 if (!s->for_overlaps_p)
4832 {
4833 /* Draw underline. */
4834 if (s->face->underline_p)
4835 {
4836 unsigned long h = 1;
4837 unsigned long dy = s->height - h;
4838
4839 if (s->face->underline_defaulted_p)
4840 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4841 s->width, h);
4842 else
4843 {
4844 XGCValues xgcv;
4845 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4846 XSetForeground (s->display, s->gc, s->face->underline_color);
4847 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4848 s->width, h);
4849 XSetForeground (s->display, s->gc, xgcv.foreground);
4850 }
4851 }
4852
4853 /* Draw overline. */
4854 if (s->face->overline_p)
4855 {
4856 unsigned long dy = 0, h = 1;
4857
4858 if (s->face->overline_color_defaulted_p)
4859 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4860 s->width, h);
4861 else
4862 {
4863 XGCValues xgcv;
4864 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4865 XSetForeground (s->display, s->gc, s->face->overline_color);
4866 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4867 s->width, h);
4868 XSetForeground (s->display, s->gc, xgcv.foreground);
4869 }
4870 }
4871
4872 /* Draw strike-through. */
4873 if (s->face->strike_through_p)
4874 {
4875 unsigned long h = 1;
4876 unsigned long dy = (s->height - h) / 2;
4877
4878 if (s->face->strike_through_color_defaulted_p)
4879 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4880 s->width, h);
4881 else
4882 {
4883 XGCValues xgcv;
4884 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4885 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4886 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4887 s->width, h);
4888 XSetForeground (s->display, s->gc, xgcv.foreground);
4889 }
4890 }
4891
4892 /* Draw relief. */
4893 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4894 x_draw_glyph_string_box (s);
4895 }
4896
4897 /* Reset clipping. */
4898 mac_reset_clipping (s->display, s->window);
4899 }
4900
4901
4902 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4903 struct face **, int));
4904
4905
4906 /* Fill glyph string S with composition components specified by S->cmp.
4907
4908 FACES is an array of faces for all components of this composition.
4909 S->gidx is the index of the first component for S.
4910 OVERLAPS_P non-zero means S should draw the foreground only, and
4911 use its physical height for clipping.
4912
4913 Value is the index of a component not in S. */
4914
4915 static int
4916 x_fill_composite_glyph_string (s, faces, overlaps_p)
4917 struct glyph_string *s;
4918 struct face **faces;
4919 int overlaps_p;
4920 {
4921 int i;
4922
4923 xassert (s);
4924
4925 s->for_overlaps_p = overlaps_p;
4926
4927 s->face = faces[s->gidx];
4928 s->font = s->face->font;
4929 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4930
4931 /* For all glyphs of this composition, starting at the offset
4932 S->gidx, until we reach the end of the definition or encounter a
4933 glyph that requires the different face, add it to S. */
4934 ++s->nchars;
4935 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4936 ++s->nchars;
4937
4938 /* All glyph strings for the same composition has the same width,
4939 i.e. the width set for the first component of the composition. */
4940
4941 s->width = s->first_glyph->pixel_width;
4942
4943 /* If the specified font could not be loaded, use the frame's
4944 default font, but record the fact that we couldn't load it in
4945 the glyph string so that we can draw rectangles for the
4946 characters of the glyph string. */
4947 if (s->font == NULL)
4948 {
4949 s->font_not_found_p = 1;
4950 s->font = FRAME_FONT (s->f);
4951 }
4952
4953 /* Adjust base line for subscript/superscript text. */
4954 s->ybase += s->first_glyph->voffset;
4955
4956 xassert (s->face && s->face->gc);
4957
4958 /* This glyph string must always be drawn with 16-bit functions. */
4959 s->two_byte_p = 1;
4960
4961 return s->gidx + s->nchars;
4962 }
4963
4964
4965 /* Fill glyph string S from a sequence of character glyphs.
4966
4967 FACE_ID is the face id of the string. START is the index of the
4968 first glyph to consider, END is the index of the last + 1.
4969 OVERLAPS_P non-zero means S should draw the foreground only, and
4970 use its physical height for clipping.
4971
4972 Value is the index of the first glyph not in S. */
4973
4974 static int
4975 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4976 struct glyph_string *s;
4977 int face_id;
4978 int start, end, overlaps_p;
4979 {
4980 struct glyph *glyph, *last;
4981 int voffset;
4982 int glyph_not_available_p;
4983
4984 xassert (s->f == XFRAME (s->w->frame));
4985 xassert (s->nchars == 0);
4986 xassert (start >= 0 && end > start);
4987
4988 s->for_overlaps_p = overlaps_p;
4989 glyph = s->row->glyphs[s->area] + start;
4990 last = s->row->glyphs[s->area] + end;
4991 voffset = glyph->voffset;
4992
4993 glyph_not_available_p = glyph->glyph_not_available_p;
4994
4995 while (glyph < last
4996 && glyph->type == CHAR_GLYPH
4997 && glyph->voffset == voffset
4998 /* Same face id implies same font, nowadays. */
4999 && glyph->face_id == face_id
5000 && glyph->glyph_not_available_p == glyph_not_available_p)
5001 {
5002 int two_byte_p;
5003
5004 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
5005 s->char2b + s->nchars,
5006 &two_byte_p);
5007 s->two_byte_p = two_byte_p;
5008 ++s->nchars;
5009 xassert (s->nchars <= end - start);
5010 s->width += glyph->pixel_width;
5011 ++glyph;
5012 }
5013
5014 s->font = s->face->font;
5015 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5016
5017 /* If the specified font could not be loaded, use the frame's font,
5018 but record the fact that we couldn't load it in
5019 S->font_not_found_p so that we can draw rectangles for the
5020 characters of the glyph string. */
5021 if (s->font == NULL || glyph_not_available_p)
5022 {
5023 s->font_not_found_p = 1;
5024 s->font = FRAME_FONT (s->f);
5025 }
5026
5027 /* Adjust base line for subscript/superscript text. */
5028 s->ybase += voffset;
5029
5030 xassert (s->face && s->face->gc);
5031 return glyph - s->row->glyphs[s->area];
5032 }
5033
5034
5035 /* Fill glyph string S from image glyph S->first_glyph. */
5036
5037 static void
5038 x_fill_image_glyph_string (s)
5039 struct glyph_string *s;
5040 {
5041 xassert (s->first_glyph->type == IMAGE_GLYPH);
5042 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
5043 xassert (s->img);
5044 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
5045 s->font = s->face->font;
5046 s->width = s->first_glyph->pixel_width;
5047
5048 /* Adjust base line for subscript/superscript text. */
5049 s->ybase += s->first_glyph->voffset;
5050 }
5051
5052
5053 /* Fill glyph string S from a sequence of stretch glyphs.
5054
5055 ROW is the glyph row in which the glyphs are found, AREA is the
5056 area within the row. START is the index of the first glyph to
5057 consider, END is the index of the last + 1.
5058
5059 Value is the index of the first glyph not in S. */
5060
5061 static int
5062 x_fill_stretch_glyph_string (s, row, area, start, end)
5063 struct glyph_string *s;
5064 struct glyph_row *row;
5065 enum glyph_row_area area;
5066 int start, end;
5067 {
5068 struct glyph *glyph, *last;
5069 int voffset, face_id;
5070
5071 xassert (s->first_glyph->type == STRETCH_GLYPH);
5072
5073 glyph = s->row->glyphs[s->area] + start;
5074 last = s->row->glyphs[s->area] + end;
5075 face_id = glyph->face_id;
5076 s->face = FACE_FROM_ID (s->f, face_id);
5077 s->font = s->face->font;
5078 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5079 s->width = glyph->pixel_width;
5080 voffset = glyph->voffset;
5081
5082 for (++glyph;
5083 (glyph < last
5084 && glyph->type == STRETCH_GLYPH
5085 && glyph->voffset == voffset
5086 && glyph->face_id == face_id);
5087 ++glyph)
5088 s->width += glyph->pixel_width;
5089
5090 /* Adjust base line for subscript/superscript text. */
5091 s->ybase += voffset;
5092
5093 xassert (s->face);
5094 return glyph - s->row->glyphs[s->area];
5095 }
5096
5097
5098 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
5099 of XChar2b structures for S; it can't be allocated in
5100 x_init_glyph_string because it must be allocated via `alloca'. W
5101 is the window on which S is drawn. ROW and AREA are the glyph row
5102 and area within the row from which S is constructed. START is the
5103 index of the first glyph structure covered by S. HL is a
5104 face-override for drawing S. */
5105
5106 static void
5107 x_init_glyph_string (s, char2b, w, row, area, start, hl)
5108 struct glyph_string *s;
5109 XChar2b *char2b;
5110 struct window *w;
5111 struct glyph_row *row;
5112 enum glyph_row_area area;
5113 int start;
5114 enum draw_glyphs_face hl;
5115 {
5116 bzero (s, sizeof *s);
5117 s->w = w;
5118 s->f = XFRAME (w->frame);
5119 s->display = FRAME_MAC_DISPLAY (s->f);
5120 s->window = FRAME_MAC_WINDOW (s->f);
5121 s->char2b = char2b;
5122 s->hl = hl;
5123 s->row = row;
5124 s->area = area;
5125 s->first_glyph = row->glyphs[area] + start;
5126 s->height = row->height;
5127 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5128
5129 /* Display the internal border below the tool-bar window. */
5130 if (s->w == XWINDOW (s->f->tool_bar_window))
5131 s->y -= s->f->output_data.mac->internal_border_width;
5132
5133 s->ybase = s->y + row->ascent;
5134 }
5135
5136
5137 /* Set background width of glyph string S. START is the index of the
5138 first glyph following S. LAST_X is the right-most x-position + 1
5139 in the drawing area. */
5140
5141 static INLINE void
5142 x_set_glyph_string_background_width (s, start, last_x)
5143 struct glyph_string *s;
5144 int start;
5145 int last_x;
5146 {
5147 /* If the face of this glyph string has to be drawn to the end of
5148 the drawing area, set S->extends_to_end_of_line_p. */
5149 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
5150
5151 if (start == s->row->used[s->area]
5152 && s->area == TEXT_AREA
5153 && ((s->hl == DRAW_NORMAL_TEXT
5154 && (s->row->fill_line_p
5155 || s->face->background != default_face->background
5156 || s->face->stipple != default_face->stipple
5157 || s->row->mouse_face_p))
5158 || s->hl == DRAW_MOUSE_FACE
5159 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
5160 && s->row->fill_line_p)))
5161 s->extends_to_end_of_line_p = 1;
5162
5163 /* If S extends its face to the end of the line, set its
5164 background_width to the distance to the right edge of the drawing
5165 area. */
5166 if (s->extends_to_end_of_line_p)
5167 s->background_width = last_x - s->x + 1;
5168 else
5169 s->background_width = s->width;
5170 }
5171
5172
5173 /* Add a glyph string for a stretch glyph to the list of strings
5174 between HEAD and TAIL. START is the index of the stretch glyph in
5175 row area AREA of glyph row ROW. END is the index of the last glyph
5176 in that glyph row area. X is the current output position assigned
5177 to the new glyph string constructed. HL overrides that face of the
5178 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5179 is the right-most x-position of the drawing area. */
5180
5181 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5182 and below -- keep them on one line. */
5183 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5184 do \
5185 { \
5186 s = (struct glyph_string *) alloca (sizeof *s); \
5187 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5188 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5189 x_append_glyph_string (&HEAD, &TAIL, s); \
5190 s->x = (X); \
5191 } \
5192 while (0)
5193
5194
5195 /* Add a glyph string for an image glyph to the list of strings
5196 between HEAD and TAIL. START is the index of the image glyph in
5197 row area AREA of glyph row ROW. END is the index of the last glyph
5198 in that glyph row area. X is the current output position assigned
5199 to the new glyph string constructed. HL overrides that face of the
5200 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5201 is the right-most x-position of the drawing area. */
5202
5203 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5204 do \
5205 { \
5206 s = (struct glyph_string *) alloca (sizeof *s); \
5207 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5208 x_fill_image_glyph_string (s); \
5209 x_append_glyph_string (&HEAD, &TAIL, s); \
5210 ++START; \
5211 s->x = (X); \
5212 } \
5213 while (0)
5214
5215
5216 /* Add a glyph string for a sequence of character glyphs to the list
5217 of strings between HEAD and TAIL. START is the index of the first
5218 glyph in row area AREA of glyph row ROW that is part of the new
5219 glyph string. END is the index of the last glyph in that glyph row
5220 area. X is the current output position assigned to the new glyph
5221 string constructed. HL overrides that face of the glyph; e.g. it
5222 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5223 right-most x-position of the drawing area. */
5224
5225 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5226 do \
5227 { \
5228 int c, face_id; \
5229 XChar2b *char2b; \
5230 \
5231 c = (ROW)->glyphs[AREA][START].u.ch; \
5232 face_id = (ROW)->glyphs[AREA][START].face_id; \
5233 \
5234 s = (struct glyph_string *) alloca (sizeof *s); \
5235 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5236 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5237 x_append_glyph_string (&HEAD, &TAIL, s); \
5238 s->x = (X); \
5239 START = x_fill_glyph_string (s, face_id, START, END, \
5240 OVERLAPS_P); \
5241 } \
5242 while (0)
5243
5244
5245 /* Add a glyph string for a composite sequence to the list of strings
5246 between HEAD and TAIL. START is the index of the first glyph in
5247 row area AREA of glyph row ROW that is part of the new glyph
5248 string. END is the index of the last glyph in that glyph row area.
5249 X is the current output position assigned to the new glyph string
5250 constructed. HL overrides that face of the glyph; e.g. it is
5251 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5252 x-position of the drawing area. */
5253
5254 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5255 do { \
5256 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5257 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5258 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5259 struct composition *cmp = composition_table[cmp_id]; \
5260 int glyph_len = cmp->glyph_len; \
5261 XChar2b *char2b; \
5262 struct face **faces; \
5263 struct glyph_string *first_s = NULL; \
5264 int n; \
5265 \
5266 base_face = base_face->ascii_face; \
5267 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5268 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5269 /* At first, fill in `char2b' and `faces'. */ \
5270 for (n = 0; n < glyph_len; n++) \
5271 { \
5272 int c = COMPOSITION_GLYPH (cmp, n); \
5273 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5274 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5275 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5276 this_face_id, char2b + n, 1); \
5277 } \
5278 \
5279 /* Make glyph_strings for each glyph sequence that is drawable by \
5280 the same face, and append them to HEAD/TAIL. */ \
5281 for (n = 0; n < cmp->glyph_len;) \
5282 { \
5283 s = (struct glyph_string *) alloca (sizeof *s); \
5284 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5285 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5286 s->cmp = cmp; \
5287 s->gidx = n; \
5288 s->x = (X); \
5289 \
5290 if (n == 0) \
5291 first_s = s; \
5292 \
5293 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5294 } \
5295 \
5296 ++START; \
5297 s = first_s; \
5298 } while (0)
5299
5300
5301 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5302 of AREA of glyph row ROW on window W between indices START and END.
5303 HL overrides the face for drawing glyph strings, e.g. it is
5304 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5305 x-positions of the drawing area.
5306
5307 This is an ugly monster macro construct because we must use alloca
5308 to allocate glyph strings (because x_draw_glyphs can be called
5309 asynchronously). */
5310
5311 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5312 do \
5313 { \
5314 HEAD = TAIL = NULL; \
5315 while (START < END) \
5316 { \
5317 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5318 switch (first_glyph->type) \
5319 { \
5320 case CHAR_GLYPH: \
5321 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5322 TAIL, HL, X, LAST_X, \
5323 OVERLAPS_P); \
5324 break; \
5325 \
5326 case COMPOSITE_GLYPH: \
5327 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5328 HEAD, TAIL, HL, X, LAST_X,\
5329 OVERLAPS_P); \
5330 break; \
5331 \
5332 case STRETCH_GLYPH: \
5333 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5334 HEAD, TAIL, HL, X, LAST_X); \
5335 break; \
5336 \
5337 case IMAGE_GLYPH: \
5338 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5339 TAIL, HL, X, LAST_X); \
5340 break; \
5341 \
5342 default: \
5343 abort (); \
5344 } \
5345 \
5346 x_set_glyph_string_background_width (s, START, LAST_X); \
5347 (X) += s->width; \
5348 } \
5349 } \
5350 while (0)
5351
5352
5353 /* Draw glyphs between START and END in AREA of ROW on window W,
5354 starting at x-position X. X is relative to AREA in W. HL is a
5355 face-override with the following meaning:
5356
5357 DRAW_NORMAL_TEXT draw normally
5358 DRAW_CURSOR draw in cursor face
5359 DRAW_MOUSE_FACE draw in mouse face.
5360 DRAW_INVERSE_VIDEO draw in mode line face
5361 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5362 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5363
5364 If OVERLAPS_P is non-zero, draw only the foreground of characters
5365 and clip to the physical height of ROW.
5366
5367 Value is the x-position reached, relative to AREA of W. */
5368
5369 static int
5370 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5371 struct window *w;
5372 int x;
5373 struct glyph_row *row;
5374 enum glyph_row_area area;
5375 int start, end;
5376 enum draw_glyphs_face hl;
5377 int overlaps_p;
5378 {
5379 struct glyph_string *head, *tail;
5380 struct glyph_string *s;
5381 int last_x, area_width;
5382 int x_reached;
5383 int i, j;
5384
5385 /* Let's rather be paranoid than getting a SEGV. */
5386 end = min (end, row->used[area]);
5387 start = max (0, start);
5388 start = min (end, start);
5389
5390 /* Translate X to frame coordinates. Set last_x to the right
5391 end of the drawing area. */
5392 if (row->full_width_p)
5393 {
5394 /* X is relative to the left edge of W, without scroll bars
5395 or fringes. */
5396 struct frame *f = XFRAME (WINDOW_FRAME (w));
5397 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5398
5399 x += window_left_x;
5400 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5401 last_x = window_left_x + area_width;
5402
5403 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5404 {
5405 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5406 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5407 last_x += width;
5408 else
5409 x -= width;
5410 }
5411
5412 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5413 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5414 }
5415 else
5416 {
5417 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5418 area_width = window_box_width (w, area);
5419 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5420 }
5421
5422 /* Build a doubly-linked list of glyph_string structures between
5423 head and tail from what we have to draw. Note that the macro
5424 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5425 the reason we use a separate variable `i'. */
5426 i = start;
5427 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5428 overlaps_p);
5429 if (tail)
5430 x_reached = tail->x + tail->background_width;
5431 else
5432 x_reached = x;
5433
5434 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5435 the row, redraw some glyphs in front or following the glyph
5436 strings built above. */
5437 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5438 {
5439 int dummy_x = 0;
5440 struct glyph_string *h, *t;
5441
5442 /* Compute overhangs for all glyph strings. */
5443 for (s = head; s; s = s->next)
5444 x_compute_glyph_string_overhangs (s);
5445
5446 /* Prepend glyph strings for glyphs in front of the first glyph
5447 string that are overwritten because of the first glyph
5448 string's left overhang. The background of all strings
5449 prepended must be drawn because the first glyph string
5450 draws over it. */
5451 i = x_left_overwritten (head);
5452 if (i >= 0)
5453 {
5454 j = i;
5455 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5456 DRAW_NORMAL_TEXT, dummy_x, last_x,
5457 overlaps_p);
5458 start = i;
5459 x_compute_overhangs_and_x (t, head->x, 1);
5460 x_prepend_glyph_string_lists (&head, &tail, h, t);
5461 }
5462
5463 /* Prepend glyph strings for glyphs in front of the first glyph
5464 string that overwrite that glyph string because of their
5465 right overhang. For these strings, only the foreground must
5466 be drawn, because it draws over the glyph string at `head'.
5467 The background must not be drawn because this would overwrite
5468 right overhangs of preceding glyphs for which no glyph
5469 strings exist. */
5470 i = x_left_overwriting (head);
5471 if (i >= 0)
5472 {
5473 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5474 DRAW_NORMAL_TEXT, dummy_x, last_x,
5475 overlaps_p);
5476 for (s = h; s; s = s->next)
5477 s->background_filled_p = 1;
5478 x_compute_overhangs_and_x (t, head->x, 1);
5479 x_prepend_glyph_string_lists (&head, &tail, h, t);
5480 }
5481
5482 /* Append glyphs strings for glyphs following the last glyph
5483 string tail that are overwritten by tail. The background of
5484 these strings has to be drawn because tail's foreground draws
5485 over it. */
5486 i = x_right_overwritten (tail);
5487 if (i >= 0)
5488 {
5489 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5490 DRAW_NORMAL_TEXT, x, last_x,
5491 overlaps_p);
5492 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5493 x_append_glyph_string_lists (&head, &tail, h, t);
5494 }
5495
5496 /* Append glyph strings for glyphs following the last glyph
5497 string tail that overwrite tail. The foreground of such
5498 glyphs has to be drawn because it writes into the background
5499 of tail. The background must not be drawn because it could
5500 paint over the foreground of following glyphs. */
5501 i = x_right_overwriting (tail);
5502 if (i >= 0)
5503 {
5504 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5505 DRAW_NORMAL_TEXT, x, last_x,
5506 overlaps_p);
5507 for (s = h; s; s = s->next)
5508 s->background_filled_p = 1;
5509 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5510 x_append_glyph_string_lists (&head, &tail, h, t);
5511 }
5512 }
5513
5514 /* Draw all strings. */
5515 for (s = head; s; s = s->next)
5516 x_draw_glyph_string (s);
5517
5518 if (area == TEXT_AREA
5519 && !row->full_width_p
5520 /* When drawing overlapping rows, only the glyph strings'
5521 foreground is drawn, which doesn't erase a cursor
5522 completely. */
5523 && !overlaps_p)
5524 {
5525 int x0 = head ? head->x : x;
5526 int x1 = tail ? tail->x + tail->background_width : x;
5527
5528 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5529 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5530
5531 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5532 {
5533 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5534 x0 -= left_area_width;
5535 x1 -= left_area_width;
5536 }
5537
5538 notice_overwritten_cursor (w, area, x0, x1,
5539 row->y, MATRIX_ROW_BOTTOM_Y (row));
5540 }
5541
5542 /* Value is the x-position up to which drawn, relative to AREA of W.
5543 This doesn't include parts drawn because of overhangs. */
5544 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5545 if (!row->full_width_p)
5546 {
5547 if (area > LEFT_MARGIN_AREA)
5548 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5549 if (area > TEXT_AREA)
5550 x_reached -= window_box_width (w, TEXT_AREA);
5551 }
5552
5553 return x_reached;
5554 }
5555
5556
5557 /* Fix the display of area AREA of overlapping row ROW in window W. */
5558
5559 static void
5560 x_fix_overlapping_area (w, row, area)
5561 struct window *w;
5562 struct glyph_row *row;
5563 enum glyph_row_area area;
5564 {
5565 int i, x;
5566
5567 BLOCK_INPUT;
5568
5569 if (area == LEFT_MARGIN_AREA)
5570 x = 0;
5571 else if (area == TEXT_AREA)
5572 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5573 else
5574 x = (window_box_width (w, LEFT_MARGIN_AREA)
5575 + window_box_width (w, TEXT_AREA));
5576
5577 for (i = 0; i < row->used[area];)
5578 {
5579 if (row->glyphs[area][i].overlaps_vertically_p)
5580 {
5581 int start = i, start_x = x;
5582
5583 do
5584 {
5585 x += row->glyphs[area][i].pixel_width;
5586 ++i;
5587 }
5588 while (i < row->used[area]
5589 && row->glyphs[area][i].overlaps_vertically_p);
5590
5591 x_draw_glyphs (w, start_x, row, area, start, i,
5592 DRAW_NORMAL_TEXT, 1);
5593 }
5594 else
5595 {
5596 x += row->glyphs[area][i].pixel_width;
5597 ++i;
5598 }
5599 }
5600
5601 UNBLOCK_INPUT;
5602 }
5603
5604
5605 /* Output LEN glyphs starting at START at the nominal cursor position.
5606 Advance the nominal cursor over the text. The global variable
5607 updated_window contains the window being updated, updated_row is
5608 the glyph row being updated, and updated_area is the area of that
5609 row being updated. */
5610
5611 static void
5612 x_write_glyphs (start, len)
5613 struct glyph *start;
5614 int len;
5615 {
5616 int x, hpos;
5617
5618 xassert (updated_window && updated_row);
5619 BLOCK_INPUT;
5620
5621 /* Write glyphs. */
5622
5623 hpos = start - updated_row->glyphs[updated_area];
5624 x = x_draw_glyphs (updated_window, output_cursor.x,
5625 updated_row, updated_area,
5626 hpos, hpos + len,
5627 DRAW_NORMAL_TEXT, 0);
5628
5629 UNBLOCK_INPUT;
5630
5631 /* Advance the output cursor. */
5632 output_cursor.hpos += len;
5633 output_cursor.x = x;
5634 }
5635
5636
5637 /* Insert LEN glyphs from START at the nominal cursor position. */
5638
5639 static void
5640 x_insert_glyphs (start, len)
5641 struct glyph *start;
5642 register int len;
5643 {
5644 struct frame *f;
5645 struct window *w;
5646 int line_height, shift_by_width, shifted_region_width;
5647 struct glyph_row *row;
5648 struct glyph *glyph;
5649 int frame_x, frame_y, hpos;
5650
5651 xassert (updated_window && updated_row);
5652 BLOCK_INPUT;
5653 w = updated_window;
5654 f = XFRAME (WINDOW_FRAME (w));
5655
5656 /* Get the height of the line we are in. */
5657 row = updated_row;
5658 line_height = row->height;
5659
5660 /* Get the width of the glyphs to insert. */
5661 shift_by_width = 0;
5662 for (glyph = start; glyph < start + len; ++glyph)
5663 shift_by_width += glyph->pixel_width;
5664
5665 /* Get the width of the region to shift right. */
5666 shifted_region_width = (window_box_width (w, updated_area)
5667 - output_cursor.x
5668 - shift_by_width);
5669
5670 /* Shift right. */
5671 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5672 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5673
5674 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5675 f->output_data.mac->normal_gc,
5676 frame_x, frame_y,
5677 shifted_region_width, line_height,
5678 frame_x + shift_by_width, frame_y);
5679
5680 /* Write the glyphs. */
5681 hpos = start - row->glyphs[updated_area];
5682 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5683 DRAW_NORMAL_TEXT, 0);
5684
5685 /* Advance the output cursor. */
5686 output_cursor.hpos += len;
5687 output_cursor.x += shift_by_width;
5688 UNBLOCK_INPUT;
5689 }
5690
5691
5692 /* Delete N glyphs at the nominal cursor position. Not implemented
5693 for X frames. */
5694
5695 static void
5696 x_delete_glyphs (n)
5697 register int n;
5698 {
5699 abort ();
5700 }
5701
5702
5703 /* Erase the current text line from the nominal cursor position
5704 (inclusive) to pixel column TO_X (exclusive). The idea is that
5705 everything from TO_X onward is already erased.
5706
5707 TO_X is a pixel position relative to updated_area of
5708 updated_window. TO_X == -1 means clear to the end of this area. */
5709
5710 static void
5711 x_clear_end_of_line (to_x)
5712 int to_x;
5713 {
5714 struct frame *f;
5715 struct window *w = updated_window;
5716 int max_x, min_y, max_y;
5717 int from_x, from_y, to_y;
5718
5719 xassert (updated_window && updated_row);
5720 f = XFRAME (w->frame);
5721
5722 if (updated_row->full_width_p)
5723 {
5724 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5725 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5726 && !w->pseudo_window_p)
5727 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5728 }
5729 else
5730 max_x = window_box_width (w, updated_area);
5731 max_y = window_text_bottom_y (w);
5732
5733 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5734 of window. For TO_X > 0, truncate to end of drawing area. */
5735 if (to_x == 0)
5736 return;
5737 else if (to_x < 0)
5738 to_x = max_x;
5739 else
5740 to_x = min (to_x, max_x);
5741
5742 to_y = min (max_y, output_cursor.y + updated_row->height);
5743
5744 /* Notice if the cursor will be cleared by this operation. */
5745 if (!updated_row->full_width_p)
5746 notice_overwritten_cursor (w, updated_area,
5747 output_cursor.x, -1,
5748 updated_row->y,
5749 MATRIX_ROW_BOTTOM_Y (updated_row));
5750
5751 from_x = output_cursor.x;
5752
5753 /* Translate to frame coordinates. */
5754 if (updated_row->full_width_p)
5755 {
5756 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5757 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5758 }
5759 else
5760 {
5761 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5762 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5763 }
5764
5765 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5766 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5767 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5768
5769 /* Prevent inadvertently clearing to end of the X window. */
5770 if (to_x > from_x && to_y > from_y)
5771 {
5772 BLOCK_INPUT;
5773 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5774 from_x, from_y, to_x - from_x, to_y - from_y,
5775 0);
5776 UNBLOCK_INPUT;
5777 }
5778 }
5779
5780
5781 /* Clear entire frame. If updating_frame is non-null, clear that
5782 frame. Otherwise clear the selected frame. */
5783
5784 static void
5785 x_clear_frame ()
5786 {
5787 struct frame *f;
5788
5789 if (updating_frame)
5790 f = updating_frame;
5791 else
5792 f = SELECTED_FRAME ();
5793
5794 /* Clearing the frame will erase any cursor, so mark them all as no
5795 longer visible. */
5796 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5797 output_cursor.hpos = output_cursor.vpos = 0;
5798 output_cursor.x = -1;
5799
5800 /* We don't set the output cursor here because there will always
5801 follow an explicit cursor_to. */
5802 BLOCK_INPUT;
5803 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5804
5805 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5806 /* We have to clear the scroll bars, too. If we have changed
5807 colors or something like that, then they should be notified. */
5808 x_scroll_bar_clear (f);
5809 #endif
5810
5811 XFlush (FRAME_MAC_DISPLAY (f));
5812 UNBLOCK_INPUT;
5813 }
5814
5815
5816 \f
5817 /* Invert the middle quarter of the frame for .15 sec. */
5818
5819 /* We use the select system call to do the waiting, so we have to make
5820 sure it's available. If it isn't, we just won't do visual bells. */
5821
5822 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5823
5824 /* Subtract the `struct timeval' values X and Y, storing the result in
5825 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5826
5827 static int
5828 timeval_subtract (result, x, y)
5829 struct timeval *result, x, y;
5830 {
5831 /* Perform the carry for the later subtraction by updating y. This
5832 is safer because on some systems the tv_sec member is unsigned. */
5833 if (x.tv_usec < y.tv_usec)
5834 {
5835 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5836 y.tv_usec -= 1000000 * nsec;
5837 y.tv_sec += nsec;
5838 }
5839
5840 if (x.tv_usec - y.tv_usec > 1000000)
5841 {
5842 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5843 y.tv_usec += 1000000 * nsec;
5844 y.tv_sec -= nsec;
5845 }
5846
5847 /* Compute the time remaining to wait. tv_usec is certainly
5848 positive. */
5849 result->tv_sec = x.tv_sec - y.tv_sec;
5850 result->tv_usec = x.tv_usec - y.tv_usec;
5851
5852 /* Return indication of whether the result should be considered
5853 negative. */
5854 return x.tv_sec < y.tv_sec;
5855 }
5856
5857 void
5858 XTflash (f)
5859 struct frame *f;
5860 {
5861 BLOCK_INPUT;
5862
5863 FlashMenuBar (0);
5864
5865 {
5866 struct timeval wakeup;
5867
5868 EMACS_GET_TIME (wakeup);
5869
5870 /* Compute time to wait until, propagating carry from usecs. */
5871 wakeup.tv_usec += 150000;
5872 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5873 wakeup.tv_usec %= 1000000;
5874
5875 /* Keep waiting until past the time wakeup. */
5876 while (1)
5877 {
5878 struct timeval timeout;
5879
5880 EMACS_GET_TIME (timeout);
5881
5882 /* In effect, timeout = wakeup - timeout.
5883 Break if result would be negative. */
5884 if (timeval_subtract (&timeout, wakeup, timeout))
5885 break;
5886
5887 /* Try to wait that long--but we might wake up sooner. */
5888 select (0, NULL, NULL, NULL, &timeout);
5889 }
5890 }
5891
5892 FlashMenuBar (0);
5893
5894 UNBLOCK_INPUT;
5895 }
5896
5897 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5898
5899
5900 /* Make audible bell. */
5901
5902 void
5903 XTring_bell ()
5904 {
5905 struct frame *f = SELECTED_FRAME ();
5906
5907 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5908 if (visible_bell)
5909 XTflash (f);
5910 else
5911 #endif
5912 {
5913 BLOCK_INPUT;
5914 SysBeep (1);
5915 XFlush (FRAME_MAC_DISPLAY (f));
5916 UNBLOCK_INPUT;
5917 }
5918 }
5919
5920
5921 \f
5922 /* Specify how many text lines, from the top of the window,
5923 should be affected by insert-lines and delete-lines operations.
5924 This, and those operations, are used only within an update
5925 that is bounded by calls to x_update_begin and x_update_end. */
5926
5927 void
5928 XTset_terminal_window (n)
5929 register int n;
5930 {
5931 /* This function intentionally left blank. */
5932 }
5933
5934
5935 \f
5936 /***********************************************************************
5937 Line Dance
5938 ***********************************************************************/
5939
5940 /* Perform an insert-lines or delete-lines operation, inserting N
5941 lines or deleting -N lines at vertical position VPOS. */
5942
5943 static void
5944 x_ins_del_lines (vpos, n)
5945 int vpos, n;
5946 {
5947 abort ();
5948 }
5949
5950
5951 /* Scroll part of the display as described by RUN. */
5952
5953 static void
5954 x_scroll_run (w, run)
5955 struct window *w;
5956 struct run *run;
5957 {
5958 struct frame *f = XFRAME (w->frame);
5959 int x, y, width, height, from_y, to_y, bottom_y;
5960
5961 /* Get frame-relative bounding box of the text display area of W,
5962 without mode lines. Include in this box the left and right
5963 fringes of W. */
5964 window_box (w, -1, &x, &y, &width, &height);
5965 width += FRAME_X_FRINGE_WIDTH (f);
5966 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5967
5968 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5969 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5970 bottom_y = y + height;
5971
5972 if (to_y < from_y)
5973 {
5974 /* Scrolling up. Make sure we don't copy part of the mode
5975 line at the bottom. */
5976 if (from_y + run->height > bottom_y)
5977 height = bottom_y - from_y;
5978 else
5979 height = run->height;
5980 }
5981 else
5982 {
5983 /* Scolling down. Make sure we don't copy over the mode line.
5984 at the bottom. */
5985 if (to_y + run->height > bottom_y)
5986 height = bottom_y - to_y;
5987 else
5988 height = run->height;
5989 }
5990
5991 BLOCK_INPUT;
5992
5993 /* Cursor off. Will be switched on again in x_update_window_end. */
5994 updated_window = w;
5995 x_clear_cursor (w);
5996
5997 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5998 f->output_data.mac->normal_gc,
5999 x, from_y,
6000 width, height,
6001 x, to_y);
6002
6003 UNBLOCK_INPUT;
6004 }
6005
6006
6007 \f
6008 /***********************************************************************
6009 Exposure Events
6010 ***********************************************************************/
6011
6012 /* Redisplay an exposed area of frame F. X and Y are the upper-left
6013 corner of the exposed rectangle. W and H are width and height of
6014 the exposed area. All are pixel values. W or H zero means redraw
6015 the entire frame. */
6016
6017 static void
6018 expose_frame (f, x, y, w, h)
6019 struct frame *f;
6020 int x, y, w, h;
6021 {
6022 Rect r;
6023 int mouse_face_overwritten_p = 0;
6024
6025 TRACE ((stderr, "expose_frame "));
6026
6027 /* No need to redraw if frame will be redrawn soon. */
6028 if (FRAME_GARBAGED_P (f))
6029 {
6030 TRACE ((stderr, " garbaged\n"));
6031 return;
6032 }
6033
6034 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6035 or deactivated here, for unknown reasons, activated scroll bars
6036 are shown in deactivated frames in some instances. */
6037 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6038 activate_scroll_bars (f);
6039 else
6040 deactivate_scroll_bars (f);
6041
6042 /* If basic faces haven't been realized yet, there is no point in
6043 trying to redraw anything. This can happen when we get an expose
6044 event while Emacs is starting, e.g. by moving another window. */
6045 if (FRAME_FACE_CACHE (f) == NULL
6046 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
6047 {
6048 TRACE ((stderr, " no faces\n"));
6049 return;
6050 }
6051
6052 if (w == 0 || h == 0)
6053 {
6054 r.left = r.top = 0;
6055 r.right = CANON_X_UNIT (f) * f->width;
6056 r.bottom = CANON_Y_UNIT (f) * f->height;
6057 }
6058 else
6059 {
6060 r.left = x;
6061 r.top = y;
6062 r.right = x + w;
6063 r.bottom = y + h;
6064 }
6065
6066 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
6067 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
6068
6069 if (WINDOWP (f->tool_bar_window))
6070 mouse_face_overwritten_p
6071 |= expose_window (XWINDOW (f->tool_bar_window), &r);
6072
6073 /* Some window managers support a focus-follows-mouse style with
6074 delayed raising of frames. Imagine a partially obscured frame,
6075 and moving the mouse into partially obscured mouse-face on that
6076 frame. The visible part of the mouse-face will be highlighted,
6077 then the WM raises the obscured frame. With at least one WM, KDE
6078 2.1, Emacs is not getting any event for the raising of the frame
6079 (even tried with SubstructureRedirectMask), only Expose events.
6080 These expose events will draw text normally, i.e. not
6081 highlighted. Which means we must redo the highlight here.
6082 Subsume it under ``we love X''. --gerd 2001-08-15 */
6083 /* Included in Windows version because Windows most likely does not
6084 do the right thing if any third party tool offers
6085 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6086 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
6087 {
6088 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6089 if (f == dpyinfo->mouse_face_mouse_frame)
6090 {
6091 int x = dpyinfo->mouse_face_mouse_x;
6092 int y = dpyinfo->mouse_face_mouse_y;
6093 clear_mouse_face (dpyinfo);
6094 note_mouse_highlight (f, x, y);
6095 }
6096 }
6097 }
6098
6099
6100 /* Redraw (parts) of all windows in the window tree rooted at W that
6101 intersect R. R contains frame pixel coordinates. */
6102
6103 static int
6104 expose_window_tree (w, r)
6105 struct window *w;
6106 Rect *r;
6107 {
6108 struct frame *f = XFRAME (w->frame);
6109 int mouse_face_overwritten_p = 0;
6110
6111 while (w && !FRAME_GARBAGED_P (f))
6112 {
6113 if (!NILP (w->hchild))
6114 mouse_face_overwritten_p
6115 |= expose_window_tree (XWINDOW (w->hchild), r);
6116 else if (!NILP (w->vchild))
6117 mouse_face_overwritten_p
6118 |= expose_window_tree (XWINDOW (w->vchild), r);
6119 else
6120 mouse_face_overwritten_p |= expose_window (w, r);
6121
6122 w = NILP (w->next) ? NULL : XWINDOW (w->next);
6123 }
6124
6125 return mouse_face_overwritten_p;
6126 }
6127
6128
6129 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
6130 which intersects rectangle R. R is in window-relative coordinates. */
6131
6132 static void
6133 expose_area (w, row, r, area)
6134 struct window *w;
6135 struct glyph_row *row;
6136 Rect *r;
6137 enum glyph_row_area area;
6138 {
6139 struct glyph *first = row->glyphs[area];
6140 struct glyph *end = row->glyphs[area] + row->used[area];
6141 struct glyph *last;
6142 int first_x, start_x, x;
6143
6144 if (area == TEXT_AREA && row->fill_line_p)
6145 /* If row extends face to end of line write the whole line. */
6146 x_draw_glyphs (w, 0, row, area,
6147 0, row->used[area],
6148 DRAW_NORMAL_TEXT, 0);
6149 else
6150 {
6151 /* Set START_X to the window-relative start position for drawing glyphs of
6152 AREA. The first glyph of the text area can be partially visible.
6153 The first glyphs of other areas cannot. */
6154 if (area == LEFT_MARGIN_AREA)
6155 start_x = 0;
6156 else if (area == TEXT_AREA)
6157 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6158 else
6159 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6160 + window_box_width (w, TEXT_AREA));
6161 x = start_x;
6162
6163 /* Find the first glyph that must be redrawn. */
6164 while (first < end
6165 && x + first->pixel_width < r->left)
6166 {
6167 x += first->pixel_width;
6168 ++first;
6169 }
6170
6171 /* Find the last one. */
6172 last = first;
6173 first_x = x;
6174 while (last < end
6175 && x < r->right)
6176 {
6177 x += last->pixel_width;
6178 ++last;
6179 }
6180
6181 /* Repaint. */
6182 if (last > first)
6183 x_draw_glyphs (w, first_x - start_x, row, area,
6184 first - row->glyphs[area],
6185 last - row->glyphs[area],
6186 DRAW_NORMAL_TEXT, 0);
6187 }
6188 }
6189
6190
6191 /* Redraw the parts of the glyph row ROW on window W intersecting
6192 rectangle R. R is in window-relative coordinates. Value is
6193 non-zero if mouse face was overwritten. */
6194
6195 static int
6196 expose_line (w, row, r)
6197 struct window *w;
6198 struct glyph_row *row;
6199 Rect *r;
6200 {
6201 xassert (row->enabled_p);
6202
6203 if (row->mode_line_p || w->pseudo_window_p)
6204 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6205 DRAW_NORMAL_TEXT, 0);
6206 else
6207 {
6208 if (row->used[LEFT_MARGIN_AREA])
6209 expose_area (w, row, r, LEFT_MARGIN_AREA);
6210 if (row->used[TEXT_AREA])
6211 expose_area (w, row, r, TEXT_AREA);
6212 if (row->used[RIGHT_MARGIN_AREA])
6213 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6214 x_draw_row_fringe_bitmaps (w, row);
6215 }
6216
6217 return row->mouse_face_p;
6218 }
6219
6220
6221 /* Return non-zero if W's cursor intersects rectangle R. */
6222
6223 static int
6224 x_phys_cursor_in_rect_p (w, r)
6225 struct window *w;
6226 Rect *r;
6227 {
6228 Rect cr, result;
6229 struct glyph *cursor_glyph;
6230
6231 cursor_glyph = get_phys_cursor_glyph (w);
6232 if (cursor_glyph)
6233 {
6234 cr.left = w->phys_cursor.x;
6235 cr.top = w->phys_cursor.y;
6236 cr.right = cr.left + cursor_glyph->pixel_width;
6237 cr.bottom = cr.top + w->phys_cursor_height;
6238 return x_intersect_rectangles (&cr, r, &result);
6239 }
6240 else
6241 return 0;
6242 }
6243
6244
6245 /* Redraw those parts of glyphs rows during expose event handling that
6246 overlap other rows. Redrawing of an exposed line writes over parts
6247 of lines overlapping that exposed line; this function fixes that.
6248
6249 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
6250 row in W's current matrix that is exposed and overlaps other rows.
6251 LAST_OVERLAPPING_ROW is the last such row. */
6252
6253 static void
6254 expose_overlaps (w, first_overlapping_row, last_overlapping_row)
6255 struct window *w;
6256 struct glyph_row *first_overlapping_row;
6257 struct glyph_row *last_overlapping_row;
6258 {
6259 struct glyph_row *row;
6260
6261 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
6262 if (row->overlapping_p)
6263 {
6264 xassert (row->enabled_p && !row->mode_line_p);
6265
6266 if (row->used[LEFT_MARGIN_AREA])
6267 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
6268
6269 if (row->used[TEXT_AREA])
6270 x_fix_overlapping_area (w, row, TEXT_AREA);
6271
6272 if (row->used[RIGHT_MARGIN_AREA])
6273 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
6274 }
6275 }
6276
6277
6278 /* Redraw the part of window W intersection rectangle FR. Pixel
6279 coordinates in FR are frame-relative. Call this function with
6280 input blocked. Value is non-zero if the exposure overwrites
6281 mouse-face. */
6282
6283 static int
6284 expose_window (w, fr)
6285 struct window *w;
6286 Rect *fr;
6287 {
6288 struct frame *f = XFRAME (w->frame);
6289 Rect wr, r;
6290 int mouse_face_overwritten_p = 0;
6291
6292 /* If window is not yet fully initialized, do nothing. This can
6293 happen when toolkit scroll bars are used and a window is split.
6294 Reconfiguring the scroll bar will generate an expose for a newly
6295 created window. */
6296 if (w->current_matrix == NULL)
6297 return 0;
6298
6299 /* When we're currently updating the window, display and current
6300 matrix usually don't agree. Arrange for a thorough display
6301 later. */
6302 if (w == updated_window)
6303 {
6304 SET_FRAME_GARBAGED (f);
6305 return 0;
6306 }
6307
6308 /* Frame-relative pixel rectangle of W. */
6309 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6310 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6311 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6312 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6313
6314 if (x_intersect_rectangles (fr, &wr, &r))
6315 {
6316 int yb = window_text_bottom_y (w);
6317 struct glyph_row *row;
6318 int cursor_cleared_p;
6319 struct glyph_row *first_overlapping_row, *last_overlapping_row;
6320
6321 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6322 r.left, r.top, r.right, r.bottom));
6323
6324 /* Convert to window coordinates. */
6325 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6326 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6327 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6328 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6329
6330 /* Turn off the cursor. */
6331 if (!w->pseudo_window_p
6332 && x_phys_cursor_in_rect_p (w, &r))
6333 {
6334 x_clear_cursor (w);
6335 cursor_cleared_p = 1;
6336 }
6337 else
6338 cursor_cleared_p = 0;
6339
6340 /* Update lines intersecting rectangle R. */
6341 first_overlapping_row = last_overlapping_row = NULL;
6342 for (row = w->current_matrix->rows;
6343 row->enabled_p;
6344 ++row)
6345 {
6346 int y0 = row->y;
6347 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6348
6349 if ((y0 >= r.top && y0 < r.bottom)
6350 || (y1 > r.top && y1 < r.bottom)
6351 || (r.top >= y0 && r.top < y1)
6352 || (r.bottom > y0 && r.bottom < y1))
6353 {
6354 if (row->overlapping_p)
6355 {
6356 if (first_overlapping_row == NULL)
6357 first_overlapping_row = row;
6358 last_overlapping_row = row;
6359 }
6360
6361 if (expose_line (w, row, &r))
6362 mouse_face_overwritten_p = 1;
6363 }
6364
6365 if (y1 >= yb)
6366 break;
6367 }
6368
6369 /* Display the mode line if there is one. */
6370 if (WINDOW_WANTS_MODELINE_P (w)
6371 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6372 row->enabled_p)
6373 && row->y < r.bottom)
6374 {
6375 if (expose_line (w, row, &r))
6376 mouse_face_overwritten_p = 1;
6377 }
6378
6379 if (!w->pseudo_window_p)
6380 {
6381 /* Fix the display of overlapping rows. */
6382 if (first_overlapping_row)
6383 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
6384
6385 /* Draw border between windows. */
6386 x_draw_vertical_border (w);
6387
6388 /* Turn the cursor on again. */
6389 if (cursor_cleared_p)
6390 x_update_window_cursor (w, 1);
6391 }
6392 }
6393
6394 /* Display scroll bar for this window. */
6395 if (!NILP (w->vertical_scroll_bar))
6396 {
6397 ControlHandle ch
6398 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
6399
6400 Draw1Control (ch);
6401 }
6402
6403 return mouse_face_overwritten_p;
6404 }
6405
6406 static int
6407 x_intersect_rectangles (r1, r2, result)
6408 Rect *r1, *r2, *result;
6409 {
6410 Rect *left, *right;
6411 Rect *upper, *lower;
6412 int intersection_p = 0;
6413
6414 /* Rerrange so that R1 is the left-most rectangle. */
6415 if (r1->left < r2->left)
6416 left = r1, right = r2;
6417 else
6418 left = r2, right = r1;
6419
6420 /* X0 of the intersection is right.x0, if this is inside R1,
6421 otherwise there is no intersection. */
6422 if (right->left <= left->right)
6423 {
6424 result->left = right->left;
6425
6426 /* The right end of the intersection is the minimum of the
6427 the right ends of left and right. */
6428 result->right = min (left->right, right->right);
6429
6430 /* Same game for Y. */
6431 if (r1->top < r2->top)
6432 upper = r1, lower = r2;
6433 else
6434 upper = r2, lower = r1;
6435
6436 /* The upper end of the intersection is lower.y0, if this is inside
6437 of upper. Otherwise, there is no intersection. */
6438 if (lower->top <= upper->bottom)
6439 {
6440 result->top = lower->top;
6441
6442 /* The lower end of the intersection is the minimum of the lower
6443 ends of upper and lower. */
6444 result->bottom = min (lower->bottom, upper->bottom);
6445 intersection_p = 1;
6446 }
6447 }
6448
6449 return intersection_p;
6450 }
6451
6452
6453
6454
6455 \f
6456 static void
6457 frame_highlight (f)
6458 struct frame *f;
6459 {
6460 x_update_cursor (f, 1);
6461 }
6462
6463 static void
6464 frame_unhighlight (f)
6465 struct frame *f;
6466 {
6467 x_update_cursor (f, 1);
6468 }
6469
6470 /* The focus has changed. Update the frames as necessary to reflect
6471 the new situation. Note that we can't change the selected frame
6472 here, because the Lisp code we are interrupting might become confused.
6473 Each event gets marked with the frame in which it occurred, so the
6474 Lisp code can tell when the switch took place by examining the events. */
6475
6476 static void
6477 x_new_focus_frame (dpyinfo, frame)
6478 struct x_display_info *dpyinfo;
6479 struct frame *frame;
6480 {
6481 struct frame *old_focus = dpyinfo->x_focus_frame;
6482
6483 if (frame != dpyinfo->x_focus_frame)
6484 {
6485 /* Set this before calling other routines, so that they see
6486 the correct value of x_focus_frame. */
6487 dpyinfo->x_focus_frame = frame;
6488
6489 if (old_focus && old_focus->auto_lower)
6490 x_lower_frame (old_focus);
6491
6492 #if 0
6493 selected_frame = frame;
6494 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6495 selected_frame);
6496 Fselect_window (selected_frame->selected_window);
6497 choose_minibuf_frame ();
6498 #endif /* ! 0 */
6499
6500 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6501 pending_autoraise_frame = dpyinfo->x_focus_frame;
6502 else
6503 pending_autoraise_frame = 0;
6504 }
6505
6506 x_frame_rehighlight (dpyinfo);
6507 }
6508
6509 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6510
6511 void
6512 x_mouse_leave (dpyinfo)
6513 struct x_display_info *dpyinfo;
6514 {
6515 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6516 }
6517
6518 /* The focus has changed, or we have redirected a frame's focus to
6519 another frame (this happens when a frame uses a surrogate
6520 mini-buffer frame). Shift the highlight as appropriate.
6521
6522 The FRAME argument doesn't necessarily have anything to do with which
6523 frame is being highlighted or un-highlighted; we only use it to find
6524 the appropriate X display info. */
6525
6526 static void
6527 XTframe_rehighlight (frame)
6528 struct frame *frame;
6529 {
6530 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6531 }
6532
6533 static void
6534 x_frame_rehighlight (dpyinfo)
6535 struct x_display_info *dpyinfo;
6536 {
6537 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6538
6539 if (dpyinfo->x_focus_frame)
6540 {
6541 dpyinfo->x_highlight_frame
6542 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6543 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6544 : dpyinfo->x_focus_frame);
6545 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6546 {
6547 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6548 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6549 }
6550 }
6551 else
6552 dpyinfo->x_highlight_frame = 0;
6553
6554 if (dpyinfo->x_highlight_frame != old_highlight)
6555 {
6556 if (old_highlight)
6557 frame_unhighlight (old_highlight);
6558 if (dpyinfo->x_highlight_frame)
6559 frame_highlight (dpyinfo->x_highlight_frame);
6560 }
6561 }
6562
6563
6564 \f
6565 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6566
6567 #if 0 /* MAC_TODO */
6568 /* Initialize mode_switch_bit and modifier_meaning. */
6569 static void
6570 x_find_modifier_meanings (dpyinfo)
6571 struct x_display_info *dpyinfo;
6572 {
6573 int min_code, max_code;
6574 KeySym *syms;
6575 int syms_per_code;
6576 XModifierKeymap *mods;
6577
6578 dpyinfo->meta_mod_mask = 0;
6579 dpyinfo->shift_lock_mask = 0;
6580 dpyinfo->alt_mod_mask = 0;
6581 dpyinfo->super_mod_mask = 0;
6582 dpyinfo->hyper_mod_mask = 0;
6583
6584 #ifdef HAVE_X11R4
6585 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6586 #else
6587 min_code = dpyinfo->display->min_keycode;
6588 max_code = dpyinfo->display->max_keycode;
6589 #endif
6590
6591 syms = XGetKeyboardMapping (dpyinfo->display,
6592 min_code, max_code - min_code + 1,
6593 &syms_per_code);
6594 mods = XGetModifierMapping (dpyinfo->display);
6595
6596 /* Scan the modifier table to see which modifier bits the Meta and
6597 Alt keysyms are on. */
6598 {
6599 int row, col; /* The row and column in the modifier table. */
6600
6601 for (row = 3; row < 8; row++)
6602 for (col = 0; col < mods->max_keypermod; col++)
6603 {
6604 KeyCode code
6605 = mods->modifiermap[(row * mods->max_keypermod) + col];
6606
6607 /* Zeroes are used for filler. Skip them. */
6608 if (code == 0)
6609 continue;
6610
6611 /* Are any of this keycode's keysyms a meta key? */
6612 {
6613 int code_col;
6614
6615 for (code_col = 0; code_col < syms_per_code; code_col++)
6616 {
6617 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6618
6619 switch (sym)
6620 {
6621 case XK_Meta_L:
6622 case XK_Meta_R:
6623 dpyinfo->meta_mod_mask |= (1 << row);
6624 break;
6625
6626 case XK_Alt_L:
6627 case XK_Alt_R:
6628 dpyinfo->alt_mod_mask |= (1 << row);
6629 break;
6630
6631 case XK_Hyper_L:
6632 case XK_Hyper_R:
6633 dpyinfo->hyper_mod_mask |= (1 << row);
6634 break;
6635
6636 case XK_Super_L:
6637 case XK_Super_R:
6638 dpyinfo->super_mod_mask |= (1 << row);
6639 break;
6640
6641 case XK_Shift_Lock:
6642 /* Ignore this if it's not on the lock modifier. */
6643 if ((1 << row) == LockMask)
6644 dpyinfo->shift_lock_mask = LockMask;
6645 break;
6646 }
6647 }
6648 }
6649 }
6650 }
6651
6652 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6653 if (! dpyinfo->meta_mod_mask)
6654 {
6655 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6656 dpyinfo->alt_mod_mask = 0;
6657 }
6658
6659 /* If some keys are both alt and meta,
6660 make them just meta, not alt. */
6661 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6662 {
6663 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6664 }
6665
6666 XFree ((char *) syms);
6667 XFreeModifiermap (mods);
6668 }
6669
6670 #endif /* MAC_TODO */
6671
6672 /* Convert between the modifier bits X uses and the modifier bits
6673 Emacs uses. */
6674
6675 static unsigned int
6676 x_mac_to_emacs_modifiers (dpyinfo, state)
6677 struct x_display_info *dpyinfo;
6678 unsigned short state;
6679 {
6680 return (((state & shiftKey) ? shift_modifier : 0)
6681 | ((state & controlKey) ? ctrl_modifier : 0)
6682 | ((state & cmdKey) ? meta_modifier : 0)
6683 | ((state & optionKey) ? alt_modifier : 0));
6684 }
6685
6686 #if 0 /* MAC_TODO */
6687 static unsigned short
6688 x_emacs_to_x_modifiers (dpyinfo, state)
6689 struct x_display_info *dpyinfo;
6690 unsigned int state;
6691 {
6692 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6693 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6694 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6695 | ((state & shift_modifier) ? ShiftMask : 0)
6696 | ((state & ctrl_modifier) ? ControlMask : 0)
6697 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6698 }
6699 #endif /* MAC_TODO */
6700
6701 /* Convert a keysym to its name. */
6702
6703 char *
6704 x_get_keysym_name (keysym)
6705 int keysym;
6706 {
6707 char *value;
6708
6709 BLOCK_INPUT;
6710 #if 0
6711 value = XKeysymToString (keysym);
6712 #else
6713 value = 0;
6714 #endif
6715 UNBLOCK_INPUT;
6716
6717 return value;
6718 }
6719
6720
6721 \f
6722 /* Mouse clicks and mouse movement. Rah. */
6723
6724 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6725 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6726 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6727 not force the value into range. */
6728
6729 void
6730 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6731 FRAME_PTR f;
6732 register int pix_x, pix_y;
6733 register int *x, *y;
6734 Rect *bounds;
6735 int noclip;
6736 {
6737 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6738 if (NILP (Vwindow_system))
6739 {
6740 *x = pix_x;
6741 *y = pix_y;
6742 return;
6743 }
6744
6745 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6746 even for negative values. */
6747 if (pix_x < 0)
6748 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
6749 if (pix_y < 0)
6750 pix_y -= (f)->output_data.mac->line_height - 1;
6751
6752 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6753 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6754
6755 if (bounds)
6756 {
6757 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6758 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
6759 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6760 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
6761 }
6762
6763 if (!noclip)
6764 {
6765 if (pix_x < 0)
6766 pix_x = 0;
6767 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6768 pix_x = FRAME_WINDOW_WIDTH (f);
6769
6770 if (pix_y < 0)
6771 pix_y = 0;
6772 else if (pix_y > f->height)
6773 pix_y = f->height;
6774 }
6775
6776 *x = pix_x;
6777 *y = pix_y;
6778 }
6779
6780
6781 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6782 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6783 can't tell the positions because W's display is not up to date,
6784 return 0. */
6785
6786 int
6787 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6788 struct window *w;
6789 int hpos, vpos;
6790 int *frame_x, *frame_y;
6791 {
6792 int success_p;
6793
6794 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6795 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6796
6797 if (display_completed)
6798 {
6799 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6800 struct glyph *glyph = row->glyphs[TEXT_AREA];
6801 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6802
6803 *frame_y = row->y;
6804 *frame_x = row->x;
6805 while (glyph < end)
6806 {
6807 *frame_x += glyph->pixel_width;
6808 ++glyph;
6809 }
6810
6811 success_p = 1;
6812 }
6813 else
6814 {
6815 *frame_y = *frame_x = 0;
6816 success_p = 0;
6817 }
6818
6819 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6820 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6821 return success_p;
6822 }
6823
6824
6825 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6826
6827 If the event is a button press, then note that we have grabbed
6828 the mouse. */
6829
6830 static Lisp_Object
6831 construct_mouse_click (result, event, f)
6832 struct input_event *result;
6833 EventRecord *event;
6834 struct frame *f;
6835 {
6836 Point mouseLoc;
6837
6838 result->kind = MOUSE_CLICK_EVENT;
6839 result->code = 0; /* only one mouse button */
6840 result->timestamp = event->when;
6841 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6842
6843 mouseLoc = event->where;
6844
6845 #if TARGET_API_MAC_CARBON
6846 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6847 #else
6848 SetPort (FRAME_MAC_WINDOW (f));
6849 #endif
6850
6851 GlobalToLocal (&mouseLoc);
6852 XSETINT (result->x, mouseLoc.h);
6853 XSETINT (result->y, mouseLoc.v);
6854
6855 XSETFRAME (result->frame_or_window, f);
6856
6857 result->arg = Qnil;
6858 return Qnil;
6859 }
6860
6861 \f
6862 /* Function to report a mouse movement to the mainstream Emacs code.
6863 The input handler calls this.
6864
6865 We have received a mouse movement event, which is given in *event.
6866 If the mouse is over a different glyph than it was last time, tell
6867 the mainstream emacs code by setting mouse_moved. If not, ask for
6868 another motion event, so we can check again the next time it moves. */
6869
6870 static Point last_mouse_motion_position;
6871 static Lisp_Object last_mouse_motion_frame;
6872
6873 static void
6874 note_mouse_movement (frame, pos)
6875 FRAME_PTR frame;
6876 Point *pos;
6877 {
6878 #if TARGET_API_MAC_CARBON
6879 Rect r;
6880 #endif
6881
6882 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6883 last_mouse_motion_position = *pos;
6884 XSETFRAME (last_mouse_motion_frame, frame);
6885
6886 #if TARGET_API_MAC_CARBON
6887 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6888 #else
6889 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
6890 #endif
6891 {
6892 frame->mouse_moved = 1;
6893 last_mouse_scroll_bar = Qnil;
6894 note_mouse_highlight (frame, -1, -1);
6895 }
6896 /* Has the mouse moved off the glyph it was on at the last sighting? */
6897 else if (pos->h < last_mouse_glyph.left
6898 || pos->h >= last_mouse_glyph.right
6899 || pos->v < last_mouse_glyph.top
6900 || pos->v >= last_mouse_glyph.bottom)
6901 {
6902 frame->mouse_moved = 1;
6903 last_mouse_scroll_bar = Qnil;
6904 note_mouse_highlight (frame, pos->h, pos->v);
6905 }
6906 }
6907
6908 /* This is used for debugging, to turn off note_mouse_highlight. */
6909
6910 int disable_mouse_highlight;
6911
6912
6913 \f
6914 /************************************************************************
6915 Mouse Face
6916 ************************************************************************/
6917
6918 /* Find the glyph under window-relative coordinates X/Y in window W.
6919 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6920 strings. Return in *HPOS and *VPOS the row and column number of
6921 the glyph found. Return in *AREA the glyph area containing X.
6922 Value is a pointer to the glyph found or null if X/Y is not on
6923 text, or we can't tell because W's current matrix is not up to
6924 date. */
6925
6926 static struct glyph *
6927 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6928 struct window *w;
6929 int x, y;
6930 int *hpos, *vpos, *area;
6931 int buffer_only_p;
6932 {
6933 struct glyph *glyph, *end;
6934 struct glyph_row *row = NULL;
6935 int x0, i, left_area_width;
6936
6937 /* Find row containing Y. Give up if some row is not enabled. */
6938 for (i = 0; i < w->current_matrix->nrows; ++i)
6939 {
6940 row = MATRIX_ROW (w->current_matrix, i);
6941 if (!row->enabled_p)
6942 return NULL;
6943 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6944 break;
6945 }
6946
6947 *vpos = i;
6948 *hpos = 0;
6949
6950 /* Give up if Y is not in the window. */
6951 if (i == w->current_matrix->nrows)
6952 return NULL;
6953
6954 /* Get the glyph area containing X. */
6955 if (w->pseudo_window_p)
6956 {
6957 *area = TEXT_AREA;
6958 x0 = 0;
6959 }
6960 else
6961 {
6962 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6963 if (x < left_area_width)
6964 {
6965 *area = LEFT_MARGIN_AREA;
6966 x0 = 0;
6967 }
6968 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6969 {
6970 *area = TEXT_AREA;
6971 x0 = row->x + left_area_width;
6972 }
6973 else
6974 {
6975 *area = RIGHT_MARGIN_AREA;
6976 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6977 }
6978 }
6979
6980 /* Find glyph containing X. */
6981 glyph = row->glyphs[*area];
6982 end = glyph + row->used[*area];
6983 while (glyph < end)
6984 {
6985 if (x < x0 + glyph->pixel_width)
6986 {
6987 if (w->pseudo_window_p)
6988 break;
6989 else if (!buffer_only_p || BUFFERP (glyph->object))
6990 break;
6991 }
6992
6993 x0 += glyph->pixel_width;
6994 ++glyph;
6995 }
6996
6997 if (glyph == end)
6998 return NULL;
6999
7000 *hpos = glyph - row->glyphs[*area];
7001 return glyph;
7002 }
7003
7004
7005 /* Convert frame-relative x/y to coordinates relative to window W.
7006 Takes pseudo-windows into account. */
7007
7008 static void
7009 frame_to_window_pixel_xy (w, x, y)
7010 struct window *w;
7011 int *x, *y;
7012 {
7013 if (w->pseudo_window_p)
7014 {
7015 /* A pseudo-window is always full-width, and starts at the
7016 left edge of the frame, plus a frame border. */
7017 struct frame *f = XFRAME (w->frame);
7018 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
7019 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
7020 }
7021 else
7022 {
7023 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
7024 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
7025 }
7026 }
7027
7028
7029 /* Take proper action when mouse has moved to the mode or header line of
7030 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
7031 mode line. X is relative to the start of the text display area of
7032 W, so the width of fringes and scroll bars must be subtracted
7033 to get a position relative to the start of the mode line. */
7034
7035 static void
7036 note_mode_line_highlight (w, x, mode_line_p)
7037 struct window *w;
7038 int x, mode_line_p;
7039 {
7040 struct frame *f = XFRAME (w->frame);
7041 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7042 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
7043 struct glyph_row *row;
7044
7045 if (mode_line_p)
7046 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
7047 else
7048 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
7049
7050 if (row->enabled_p)
7051 {
7052 struct glyph *glyph, *end;
7053 Lisp_Object help, map;
7054 int x0;
7055
7056 /* Find the glyph under X. */
7057 glyph = row->glyphs[TEXT_AREA];
7058 end = glyph + row->used[TEXT_AREA];
7059 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
7060 + FRAME_X_LEFT_FRINGE_WIDTH (f));
7061
7062 while (glyph < end
7063 && x >= x0 + glyph->pixel_width)
7064 {
7065 x0 += glyph->pixel_width;
7066 ++glyph;
7067 }
7068
7069 if (glyph < end
7070 && STRINGP (glyph->object)
7071 && STRING_INTERVALS (glyph->object)
7072 && glyph->charpos >= 0
7073 && glyph->charpos < SCHARS (glyph->object))
7074 {
7075 /* If we're on a string with `help-echo' text property,
7076 arrange for the help to be displayed. This is done by
7077 setting the global variable help_echo to the help string. */
7078 help = Fget_text_property (make_number (glyph->charpos),
7079 Qhelp_echo, glyph->object);
7080 if (!NILP (help))
7081 {
7082 help_echo = help;
7083 XSETWINDOW (help_echo_window, w);
7084 help_echo_object = glyph->object;
7085 help_echo_pos = glyph->charpos;
7086 }
7087
7088 /* Change the mouse pointer according to what is under X/Y. */
7089 map = Fget_text_property (make_number (glyph->charpos),
7090 Qlocal_map, glyph->object);
7091 if (KEYMAPP (map))
7092 cursor = f->output_data.mac->nontext_cursor;
7093 else
7094 {
7095 map = Fget_text_property (make_number (glyph->charpos),
7096 Qkeymap, glyph->object);
7097 if (KEYMAPP (map))
7098 cursor = f->output_data.mac->nontext_cursor;
7099 }
7100 }
7101 }
7102
7103 #if 0 /* MAC_TODO: mouse cursor */
7104 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7105 #endif
7106 }
7107
7108
7109 /* Take proper action when the mouse has moved to position X, Y on
7110 frame F as regards highlighting characters that have mouse-face
7111 properties. Also de-highlighting chars where the mouse was before.
7112 X and Y can be negative or out of range. */
7113
7114 static void
7115 note_mouse_highlight (f, x, y)
7116 struct frame *f;
7117 int x, y;
7118 {
7119 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7120 int portion;
7121 Lisp_Object window;
7122 struct window *w;
7123 struct buffer *b;
7124
7125 #if 0
7126 /* When a menu is active, don't highlight because this looks odd. */
7127 if (popup_activated ())
7128 return;
7129 #endif
7130
7131 if (NILP (Vmouse_highlight)
7132 || !f->glyphs_initialized_p)
7133 return;
7134
7135 dpyinfo->mouse_face_mouse_x = x;
7136 dpyinfo->mouse_face_mouse_y = y;
7137 dpyinfo->mouse_face_mouse_frame = f;
7138
7139 if (dpyinfo->mouse_face_defer)
7140 return;
7141
7142 if (gc_in_progress)
7143 {
7144 dpyinfo->mouse_face_deferred_gc = 1;
7145 return;
7146 }
7147
7148 /* Which window is that in? */
7149 window = window_from_coordinates (f, x, y, &portion, 1);
7150
7151 /* If we were displaying active text in another window, clear that. */
7152 if (! EQ (window, dpyinfo->mouse_face_window))
7153 clear_mouse_face (dpyinfo);
7154
7155 /* Not on a window -> return. */
7156 if (!WINDOWP (window))
7157 return;
7158
7159 /* Reset help_echo. It will get recomputed below. */
7160 help_echo = Qnil;
7161
7162 /* Convert to window-relative pixel coordinates. */
7163 w = XWINDOW (window);
7164 frame_to_window_pixel_xy (w, &x, &y);
7165
7166 /* Handle tool-bar window differently since it doesn't display a
7167 buffer. */
7168 if (EQ (window, f->tool_bar_window))
7169 {
7170 note_tool_bar_highlight (f, x, y);
7171 return;
7172 }
7173
7174 /* Mouse is on the mode or header line? */
7175 if (portion == 1 || portion == 3)
7176 {
7177 note_mode_line_highlight (w, x, portion == 1);
7178 return;
7179 }
7180 #if 0 /* TODO: mouse cursor */
7181 if (portion == 2)
7182 cursor = f->output_data.x->horizontal_drag_cursor;
7183 else
7184 cursor = f->output_data.x->text_cursor;
7185 #endif
7186 /* Are we in a window whose display is up to date?
7187 And verify the buffer's text has not changed. */
7188 b = XBUFFER (w->buffer);
7189 if (/* Within text portion of the window. */
7190 portion == 0
7191 && EQ (w->window_end_valid, w->buffer)
7192 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7193 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
7194 {
7195 int hpos, vpos, pos, i, area;
7196 struct glyph *glyph;
7197 Lisp_Object object;
7198 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7199 Lisp_Object *overlay_vec = NULL;
7200 int len, noverlays;
7201 struct buffer *obuf;
7202 int obegv, ozv, same_region;
7203
7204 /* Find the glyph under X/Y. */
7205 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
7206
7207 /* Clear mouse face if X/Y not over text. */
7208 if (glyph == NULL
7209 || area != TEXT_AREA
7210 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7211 {
7212 clear_mouse_face (dpyinfo);
7213 /* TODO: mouse cursor */
7214 goto set_cursor;
7215 }
7216
7217 pos = glyph->charpos;
7218 object = glyph->object;
7219 if (!STRINGP (object) && !BUFFERP (object))
7220 goto set_cursor;
7221
7222 /* If we get an out-of-range value, return now; avoid an error. */
7223 if (BUFFERP (object) && pos > BUF_Z (b))
7224 goto set_cursor;
7225
7226 /* Make the window's buffer temporarily current for
7227 overlays_at and compute_char_face. */
7228 obuf = current_buffer;
7229 current_buffer = b;
7230 obegv = BEGV;
7231 ozv = ZV;
7232 BEGV = BEG;
7233 ZV = Z;
7234
7235 /* Is this char mouse-active or does it have help-echo? */
7236 position = make_number (pos);
7237
7238 if (BUFFERP (object))
7239 {
7240 /* Put all the overlays we want in a vector in overlay_vec.
7241 Store the length in len. If there are more than 10, make
7242 enough space for all, and try again. */
7243 len = 10;
7244 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7245 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7246 if (noverlays > len)
7247 {
7248 len = noverlays;
7249 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7250 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7251 }
7252
7253 /* Sort overlays into increasing priority order. */
7254 noverlays = sort_overlays (overlay_vec, noverlays, w);
7255 }
7256 else
7257 noverlays = 0;
7258
7259 same_region = (EQ (window, dpyinfo->mouse_face_window)
7260 && vpos >= dpyinfo->mouse_face_beg_row
7261 && vpos <= dpyinfo->mouse_face_end_row
7262 && (vpos > dpyinfo->mouse_face_beg_row
7263 || hpos >= dpyinfo->mouse_face_beg_col)
7264 && (vpos < dpyinfo->mouse_face_end_row
7265 || hpos < dpyinfo->mouse_face_end_col
7266 || dpyinfo->mouse_face_past_end));
7267
7268 /* TODO: if (same_region)
7269 mouse cursor */
7270
7271 /* Check mouse-face highlighting. */
7272 if (! same_region
7273 /* If there exists an overlay with mouse-face overlapping
7274 the one we are currently highlighting, we have to
7275 check if we enter the overlapping overlay, and then
7276 highlight that. */
7277 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7278 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7279 {
7280 /* Find the highest priority overlay that has a mouse-face
7281 property. */
7282 overlay = Qnil;
7283 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7284 {
7285 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7286 if (!NILP (mouse_face))
7287 overlay = overlay_vec[i];
7288 }
7289
7290 /* If we're actually highlighting the same overlay as
7291 before, there's no need to do that again. */
7292 if (!NILP (overlay)
7293 && EQ (overlay, dpyinfo->mouse_face_overlay))
7294 goto check_help_echo;
7295
7296 dpyinfo->mouse_face_overlay = overlay;
7297
7298 /* Clear the display of the old active region, if any. */
7299 clear_mouse_face (dpyinfo);
7300 /* TODO: mouse cursor changes. */
7301
7302 /* If no overlay applies, get a text property. */
7303 if (NILP (overlay))
7304 mouse_face = Fget_text_property (position, Qmouse_face, object);
7305
7306 /* Handle the overlay case. */
7307 if (!NILP (overlay))
7308 {
7309 /* Find the range of text around this char that
7310 should be active. */
7311 Lisp_Object before, after;
7312 int ignore;
7313
7314 before = Foverlay_start (overlay);
7315 after = Foverlay_end (overlay);
7316 /* Record this as the current active region. */
7317 fast_find_position (w, XFASTINT (before),
7318 &dpyinfo->mouse_face_beg_col,
7319 &dpyinfo->mouse_face_beg_row,
7320 &dpyinfo->mouse_face_beg_x,
7321 &dpyinfo->mouse_face_beg_y, Qnil);
7322
7323 dpyinfo->mouse_face_past_end
7324 = !fast_find_position (w, XFASTINT (after),
7325 &dpyinfo->mouse_face_end_col,
7326 &dpyinfo->mouse_face_end_row,
7327 &dpyinfo->mouse_face_end_x,
7328 &dpyinfo->mouse_face_end_y, Qnil);
7329 dpyinfo->mouse_face_window = window;
7330
7331 dpyinfo->mouse_face_face_id
7332 = face_at_buffer_position (w, pos, 0, 0,
7333 &ignore, pos + 1, 1);
7334
7335 /* Display it as active. */
7336 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7337 /* TODO: mouse cursor changes. */
7338 }
7339 /* Handle the text property case. */
7340 else if (! NILP (mouse_face) && BUFFERP (object))
7341 {
7342 /* Find the range of text around this char that
7343 should be active. */
7344 Lisp_Object before, after, beginning, end;
7345 int ignore;
7346
7347 beginning = Fmarker_position (w->start);
7348 end = make_number (BUF_Z (XBUFFER (object))
7349 - XFASTINT (w->window_end_pos));
7350 before
7351 = Fprevious_single_property_change (make_number (pos + 1),
7352 Qmouse_face,
7353 object, beginning);
7354 after
7355 = Fnext_single_property_change (position, Qmouse_face,
7356 object, end);
7357
7358 /* Record this as the current active region. */
7359 fast_find_position (w, XFASTINT (before),
7360 &dpyinfo->mouse_face_beg_col,
7361 &dpyinfo->mouse_face_beg_row,
7362 &dpyinfo->mouse_face_beg_x,
7363 &dpyinfo->mouse_face_beg_y, Qnil);
7364 dpyinfo->mouse_face_past_end
7365 = !fast_find_position (w, XFASTINT (after),
7366 &dpyinfo->mouse_face_end_col,
7367 &dpyinfo->mouse_face_end_row,
7368 &dpyinfo->mouse_face_end_x,
7369 &dpyinfo->mouse_face_end_y, Qnil);
7370 dpyinfo->mouse_face_window = window;
7371
7372 if (BUFFERP (object))
7373 dpyinfo->mouse_face_face_id
7374 = face_at_buffer_position (w, pos, 0, 0,
7375 &ignore, pos + 1, 1);
7376
7377 /* Display it as active. */
7378 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7379 /* TODO: mouse cursor changes. */
7380 }
7381 else if (!NILP (mouse_face) && STRINGP (object))
7382 {
7383 Lisp_Object b, e;
7384 int ignore;
7385
7386 b = Fprevious_single_property_change (make_number (pos + 1),
7387 Qmouse_face,
7388 object, Qnil);
7389 e = Fnext_single_property_change (position, Qmouse_face,
7390 object, Qnil);
7391 if (NILP (b))
7392 b = make_number (0);
7393 if (NILP (e))
7394 e = make_number (SCHARS (object) - 1);
7395 fast_find_string_pos (w, XINT (b), object,
7396 &dpyinfo->mouse_face_beg_col,
7397 &dpyinfo->mouse_face_beg_row,
7398 &dpyinfo->mouse_face_beg_x,
7399 &dpyinfo->mouse_face_beg_y, 0);
7400 fast_find_string_pos (w, XINT (e), object,
7401 &dpyinfo->mouse_face_end_col,
7402 &dpyinfo->mouse_face_end_row,
7403 &dpyinfo->mouse_face_end_x,
7404 &dpyinfo->mouse_face_end_y, 1);
7405 dpyinfo->mouse_face_past_end = 0;
7406 dpyinfo->mouse_face_window = window;
7407 dpyinfo->mouse_face_face_id
7408 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7409 glyph->face_id, 1);
7410 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7411 /* TODO: mouse cursor changes. */
7412 }
7413 else if (STRINGP (object) && NILP (mouse_face))
7414 {
7415 /* A string which doesn't have mouse-face, but
7416 the text ``under'' it might have. */
7417 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7418 int start = MATRIX_ROW_START_CHARPOS (r);
7419
7420 pos = string_buffer_position (w, object, start);
7421 if (pos > 0)
7422 mouse_face = get_char_property_and_overlay (make_number (pos),
7423 Qmouse_face,
7424 w->buffer,
7425 &overlay);
7426 if (!NILP (mouse_face) && !NILP (overlay))
7427 {
7428 Lisp_Object before = Foverlay_start (overlay);
7429 Lisp_Object after = Foverlay_end (overlay);
7430 int ignore;
7431
7432 /* Note that we might not be able to find position
7433 BEFORE in the glyph matrix if the overlay is
7434 entirely covered by a `display' property. In
7435 this case, we overshoot. So let's stop in
7436 the glyph matrix before glyphs for OBJECT. */
7437 fast_find_position (w, XFASTINT (before),
7438 &dpyinfo->mouse_face_beg_col,
7439 &dpyinfo->mouse_face_beg_row,
7440 &dpyinfo->mouse_face_beg_x,
7441 &dpyinfo->mouse_face_beg_y,
7442 object);
7443
7444 dpyinfo->mouse_face_past_end
7445 = !fast_find_position (w, XFASTINT (after),
7446 &dpyinfo->mouse_face_end_col,
7447 &dpyinfo->mouse_face_end_row,
7448 &dpyinfo->mouse_face_end_x,
7449 &dpyinfo->mouse_face_end_y,
7450 Qnil);
7451 dpyinfo->mouse_face_window = window;
7452 dpyinfo->mouse_face_face_id
7453 = face_at_buffer_position (w, pos, 0, 0,
7454 &ignore, pos + 1, 1);
7455
7456 /* Display it as active. */
7457 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7458 /* TODO: mouse cursor changes. */
7459 }
7460 }
7461 }
7462
7463 check_help_echo:
7464
7465 /* Look for a `help-echo' property. */
7466 {
7467 Lisp_Object help, overlay;
7468
7469 /* Check overlays first. */
7470 help = overlay = Qnil;
7471 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7472 {
7473 overlay = overlay_vec[i];
7474 help = Foverlay_get (overlay, Qhelp_echo);
7475 }
7476
7477 if (!NILP (help))
7478 {
7479 help_echo = help;
7480 help_echo_window = window;
7481 help_echo_object = overlay;
7482 help_echo_pos = pos;
7483 }
7484 else
7485 {
7486 Lisp_Object object = glyph->object;
7487 int charpos = glyph->charpos;
7488
7489 /* Try text properties. */
7490 if (STRINGP (object)
7491 && charpos >= 0
7492 && charpos < SCHARS (object))
7493 {
7494 help = Fget_text_property (make_number (charpos),
7495 Qhelp_echo, object);
7496 if (NILP (help))
7497 {
7498 /* If the string itself doesn't specify a help-echo,
7499 see if the buffer text ``under'' it does. */
7500 struct glyph_row *r
7501 = MATRIX_ROW (w->current_matrix, vpos);
7502 int start = MATRIX_ROW_START_CHARPOS (r);
7503 int pos = string_buffer_position (w, object, start);
7504 if (pos > 0)
7505 {
7506 help = Fget_char_property (make_number (pos),
7507 Qhelp_echo, w->buffer);
7508 if (!NILP (help))
7509 {
7510 charpos = pos;
7511 object = w->buffer;
7512 }
7513 }
7514 }
7515 }
7516 else if (BUFFERP (object)
7517 && charpos >= BEGV
7518 && charpos < ZV)
7519 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7520 object);
7521
7522 if (!NILP (help))
7523 {
7524 help_echo = help;
7525 help_echo_window = window;
7526 help_echo_object = object;
7527 help_echo_pos = charpos;
7528 }
7529 }
7530 }
7531
7532 BEGV = obegv;
7533 ZV = ozv;
7534 current_buffer = obuf;
7535 }
7536
7537 set_cursor:
7538 /* TODO: mouse cursor changes. */
7539 ;
7540 }
7541
7542 static void
7543 redo_mouse_highlight ()
7544 {
7545 if (!NILP (last_mouse_motion_frame)
7546 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7547 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7548 last_mouse_motion_position.h,
7549 last_mouse_motion_position.v);
7550 }
7551
7552
7553 \f
7554 /***********************************************************************
7555 Tool-bars
7556 ***********************************************************************/
7557
7558 static int x_tool_bar_item P_ ((struct frame *, int, int,
7559 struct glyph **, int *, int *, int *));
7560
7561 /* Tool-bar item index of the item on which a mouse button was pressed
7562 or -1. */
7563
7564 static int last_tool_bar_item;
7565
7566
7567 /* Get information about the tool-bar item at position X/Y on frame F.
7568 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7569 the current matrix of the tool-bar window of F, or NULL if not
7570 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7571 item in F->current_tool_bar_items. Value is
7572
7573 -1 if X/Y is not on a tool-bar item
7574 0 if X/Y is on the same item that was highlighted before.
7575 1 otherwise. */
7576
7577 static int
7578 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7579 struct frame *f;
7580 int x, y;
7581 struct glyph **glyph;
7582 int *hpos, *vpos, *prop_idx;
7583 {
7584 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7585 struct window *w = XWINDOW (f->tool_bar_window);
7586 int area;
7587
7588 /* Find the glyph under X/Y. */
7589 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7590 if (*glyph == NULL)
7591 return -1;
7592
7593 /* Get the start of this tool-bar item's properties in
7594 f->current_tool_bar_items. */
7595 if (!tool_bar_item_info (f, *glyph, prop_idx))
7596 return -1;
7597
7598 /* Is mouse on the highlighted item? */
7599 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7600 && *vpos >= dpyinfo->mouse_face_beg_row
7601 && *vpos <= dpyinfo->mouse_face_end_row
7602 && (*vpos > dpyinfo->mouse_face_beg_row
7603 || *hpos >= dpyinfo->mouse_face_beg_col)
7604 && (*vpos < dpyinfo->mouse_face_end_row
7605 || *hpos < dpyinfo->mouse_face_end_col
7606 || dpyinfo->mouse_face_past_end))
7607 return 0;
7608
7609 return 1;
7610 }
7611
7612
7613 /* Handle mouse button event on the tool-bar of frame F, at
7614 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7615 or ButtonRelase. */
7616
7617 static void
7618 x_handle_tool_bar_click (f, button_event)
7619 struct frame *f;
7620 EventRecord *button_event;
7621 {
7622 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7623 struct window *w = XWINDOW (f->tool_bar_window);
7624 int hpos, vpos, prop_idx;
7625 struct glyph *glyph;
7626 Lisp_Object enabled_p;
7627 int x = button_event->where.h;
7628 int y = button_event->where.v;
7629
7630 /* If not on the highlighted tool-bar item, return. */
7631 frame_to_window_pixel_xy (w, &x, &y);
7632 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7633 return;
7634
7635 /* If item is disabled, do nothing. */
7636 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7637 if (NILP (enabled_p))
7638 return;
7639
7640 if (button_event->what == mouseDown)
7641 {
7642 /* Show item in pressed state. */
7643 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7644 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7645 last_tool_bar_item = prop_idx;
7646 }
7647 else
7648 {
7649 Lisp_Object key, frame;
7650 struct input_event event;
7651
7652 /* Show item in released state. */
7653 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7654 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7655
7656 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7657
7658 XSETFRAME (frame, f);
7659 event.kind = TOOL_BAR_EVENT;
7660 event.frame_or_window = frame;
7661 event.arg = frame;
7662 kbd_buffer_store_event (&event);
7663
7664 event.kind = TOOL_BAR_EVENT;
7665 event.frame_or_window = frame;
7666 event.arg = key;
7667 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7668 button_event->modifiers);
7669 kbd_buffer_store_event (&event);
7670 last_tool_bar_item = -1;
7671 }
7672 }
7673
7674
7675 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7676 tool-bar window-relative coordinates X/Y. Called from
7677 note_mouse_highlight. */
7678
7679 static void
7680 note_tool_bar_highlight (f, x, y)
7681 struct frame *f;
7682 int x, y;
7683 {
7684 Lisp_Object window = f->tool_bar_window;
7685 struct window *w = XWINDOW (window);
7686 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7687 int hpos, vpos;
7688 struct glyph *glyph;
7689 struct glyph_row *row;
7690 int i;
7691 Lisp_Object enabled_p;
7692 int prop_idx;
7693 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7694 int mouse_down_p, rc;
7695
7696 /* Function note_mouse_highlight is called with negative x(y
7697 values when mouse moves outside of the frame. */
7698 if (x <= 0 || y <= 0)
7699 {
7700 clear_mouse_face (dpyinfo);
7701 return;
7702 }
7703
7704 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7705 if (rc < 0)
7706 {
7707 /* Not on tool-bar item. */
7708 clear_mouse_face (dpyinfo);
7709 return;
7710 }
7711 else if (rc == 0)
7712 /* On same tool-bar item as before. */
7713 goto set_help_echo;
7714
7715 clear_mouse_face (dpyinfo);
7716
7717 /* Mouse is down, but on different tool-bar item? */
7718 mouse_down_p = (dpyinfo->grabbed
7719 && f == last_mouse_frame
7720 && FRAME_LIVE_P (f));
7721 if (mouse_down_p
7722 && last_tool_bar_item != prop_idx)
7723 return;
7724
7725 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7726 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7727
7728 /* If tool-bar item is not enabled, don't highlight it. */
7729 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7730 if (!NILP (enabled_p))
7731 {
7732 /* Compute the x-position of the glyph. In front and past the
7733 image is a space. We include this is the highlighted area. */
7734 row = MATRIX_ROW (w->current_matrix, vpos);
7735 for (i = x = 0; i < hpos; ++i)
7736 x += row->glyphs[TEXT_AREA][i].pixel_width;
7737
7738 /* Record this as the current active region. */
7739 dpyinfo->mouse_face_beg_col = hpos;
7740 dpyinfo->mouse_face_beg_row = vpos;
7741 dpyinfo->mouse_face_beg_x = x;
7742 dpyinfo->mouse_face_beg_y = row->y;
7743 dpyinfo->mouse_face_past_end = 0;
7744
7745 dpyinfo->mouse_face_end_col = hpos + 1;
7746 dpyinfo->mouse_face_end_row = vpos;
7747 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7748 dpyinfo->mouse_face_end_y = row->y;
7749 dpyinfo->mouse_face_window = window;
7750 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7751
7752 /* Display it as active. */
7753 show_mouse_face (dpyinfo, draw);
7754 dpyinfo->mouse_face_image_state = draw;
7755 }
7756
7757 set_help_echo:
7758
7759 /* Set help_echo to a help string.to display for this tool-bar item.
7760 XTread_socket does the rest. */
7761 help_echo_object = help_echo_window = Qnil;
7762 help_echo_pos = -1;
7763 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7764 if (NILP (help_echo))
7765 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7766 }
7767
7768
7769 \f
7770 /* Find the glyph matrix position of buffer position CHARPOS in window
7771 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7772 current glyphs must be up to date. If CHARPOS is above window
7773 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7774 of last line in W. In the row containing CHARPOS, stop before glyphs
7775 having STOP as object. */
7776
7777 #if 0 /* This is a version of fast_find_position that's more correct
7778 in the presence of hscrolling, for example. I didn't install
7779 it right away because the problem fixed is minor, it failed
7780 in 20.x as well, and I think it's too risky to install
7781 so near the release of 21.1. 2001-09-25 gerd. */
7782
7783 static int
7784 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7785 struct window *w;
7786 int charpos;
7787 int *hpos, *vpos, *x, *y;
7788 Lisp_Object stop;
7789 {
7790 struct glyph_row *row, *first;
7791 struct glyph *glyph, *end;
7792 int i, past_end = 0;
7793
7794 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7795 row = row_containing_pos (w, charpos, first, NULL, 0);
7796 if (row == NULL)
7797 {
7798 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7799 {
7800 *x = *y = *hpos = *vpos = 0;
7801 return 0;
7802 }
7803 else
7804 {
7805 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7806 past_end = 1;
7807 }
7808 }
7809
7810 *x = row->x;
7811 *y = row->y;
7812 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7813
7814 glyph = row->glyphs[TEXT_AREA];
7815 end = glyph + row->used[TEXT_AREA];
7816
7817 /* Skip over glyphs not having an object at the start of the row.
7818 These are special glyphs like truncation marks on terminal
7819 frames. */
7820 if (row->displays_text_p)
7821 while (glyph < end
7822 && INTEGERP (glyph->object)
7823 && !EQ (stop, glyph->object)
7824 && glyph->charpos < 0)
7825 {
7826 *x += glyph->pixel_width;
7827 ++glyph;
7828 }
7829
7830 while (glyph < end
7831 && !INTEGERP (glyph->object)
7832 && !EQ (stop, glyph->object)
7833 && (!BUFFERP (glyph->object)
7834 || glyph->charpos < charpos))
7835 {
7836 *x += glyph->pixel_width;
7837 ++glyph;
7838 }
7839
7840 *hpos = glyph - row->glyphs[TEXT_AREA];
7841 return past_end;
7842 }
7843
7844 #else /* not 0 */
7845
7846 static int
7847 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7848 struct window *w;
7849 int pos;
7850 int *hpos, *vpos, *x, *y;
7851 Lisp_Object stop;
7852 {
7853 int i;
7854 int lastcol;
7855 int maybe_next_line_p = 0;
7856 int line_start_position;
7857 int yb = window_text_bottom_y (w);
7858 struct glyph_row *row, *best_row;
7859 int row_vpos, best_row_vpos;
7860 int current_x;
7861
7862 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7863 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7864
7865 while (row->y < yb)
7866 {
7867 if (row->used[TEXT_AREA])
7868 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7869 else
7870 line_start_position = 0;
7871
7872 if (line_start_position > pos)
7873 break;
7874 /* If the position sought is the end of the buffer,
7875 don't include the blank lines at the bottom of the window. */
7876 else if (line_start_position == pos
7877 && pos == BUF_ZV (XBUFFER (w->buffer)))
7878 {
7879 maybe_next_line_p = 1;
7880 break;
7881 }
7882 else if (line_start_position > 0)
7883 {
7884 best_row = row;
7885 best_row_vpos = row_vpos;
7886 }
7887
7888 if (row->y + row->height >= yb)
7889 break;
7890
7891 ++row;
7892 ++row_vpos;
7893 }
7894
7895 /* Find the right column within BEST_ROW. */
7896 lastcol = 0;
7897 current_x = best_row->x;
7898 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7899 {
7900 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7901 int charpos = glyph->charpos;
7902
7903 if (BUFFERP (glyph->object))
7904 {
7905 if (charpos == pos)
7906 {
7907 *hpos = i;
7908 *vpos = best_row_vpos;
7909 *x = current_x;
7910 *y = best_row->y;
7911 return 1;
7912 }
7913 else if (charpos > pos)
7914 break;
7915 }
7916 else if (EQ (glyph->object, stop))
7917 break;
7918
7919 if (charpos > 0)
7920 lastcol = i;
7921 current_x += glyph->pixel_width;
7922 }
7923
7924 /* If we're looking for the end of the buffer,
7925 and we didn't find it in the line we scanned,
7926 use the start of the following line. */
7927 if (maybe_next_line_p)
7928 {
7929 ++best_row;
7930 ++best_row_vpos;
7931 lastcol = 0;
7932 current_x = best_row->x;
7933 }
7934
7935 *vpos = best_row_vpos;
7936 *hpos = lastcol + 1;
7937 *x = current_x;
7938 *y = best_row->y;
7939 return 0;
7940 }
7941
7942 #endif /* not 0 */
7943
7944
7945 /* Find the position of the glyph for position POS in OBJECT in
7946 window W's current matrix, and return in *X/*Y the pixel
7947 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7948
7949 RIGHT_P non-zero means return the position of the right edge of the
7950 glyph, RIGHT_P zero means return the left edge position.
7951
7952 If no glyph for POS exists in the matrix, return the position of
7953 the glyph with the next smaller position that is in the matrix, if
7954 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7955 exists in the matrix, return the position of the glyph with the
7956 next larger position in OBJECT.
7957
7958 Value is non-zero if a glyph was found. */
7959
7960 static int
7961 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7962 struct window *w;
7963 int pos;
7964 Lisp_Object object;
7965 int *hpos, *vpos, *x, *y;
7966 int right_p;
7967 {
7968 int yb = window_text_bottom_y (w);
7969 struct glyph_row *r;
7970 struct glyph *best_glyph = NULL;
7971 struct glyph_row *best_row = NULL;
7972 int best_x = 0;
7973
7974 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7975 r->enabled_p && r->y < yb;
7976 ++r)
7977 {
7978 struct glyph *g = r->glyphs[TEXT_AREA];
7979 struct glyph *e = g + r->used[TEXT_AREA];
7980 int gx;
7981
7982 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7983 if (EQ (g->object, object))
7984 {
7985 if (g->charpos == pos)
7986 {
7987 best_glyph = g;
7988 best_x = gx;
7989 best_row = r;
7990 goto found;
7991 }
7992 else if (best_glyph == NULL
7993 || ((abs (g->charpos - pos)
7994 < abs (best_glyph->charpos - pos))
7995 && (right_p
7996 ? g->charpos < pos
7997 : g->charpos > pos)))
7998 {
7999 best_glyph = g;
8000 best_x = gx;
8001 best_row = r;
8002 }
8003 }
8004 }
8005
8006 found:
8007
8008 if (best_glyph)
8009 {
8010 *x = best_x;
8011 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
8012
8013 if (right_p)
8014 {
8015 *x += best_glyph->pixel_width;
8016 ++*hpos;
8017 }
8018
8019 *y = best_row->y;
8020 *vpos = best_row - w->current_matrix->rows;
8021 }
8022
8023 return best_glyph != NULL;
8024 }
8025
8026
8027 /* Display the active region described by mouse_face_*
8028 in its mouse-face if HL > 0, in its normal face if HL = 0. */
8029
8030 static void
8031 show_mouse_face (dpyinfo, draw)
8032 struct mac_display_info *dpyinfo;
8033 enum draw_glyphs_face draw;
8034 {
8035 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
8036 struct frame *f = XFRAME (WINDOW_FRAME (w));
8037
8038 if (/* If window is in the process of being destroyed, don't bother
8039 to do anything. */
8040 w->current_matrix != NULL
8041 /* Don't update mouse highlight if hidden */
8042 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
8043 /* Recognize when we are called to operate on rows that don't exist
8044 anymore. This can happen when a window is split. */
8045 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
8046 {
8047 int phys_cursor_on_p = w->phys_cursor_on_p;
8048 struct glyph_row *row, *first, *last;
8049
8050 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
8051 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
8052
8053 for (row = first; row <= last && row->enabled_p; ++row)
8054 {
8055 int start_hpos, end_hpos, start_x;
8056
8057 /* For all but the first row, the highlight starts at column 0. */
8058 if (row == first)
8059 {
8060 start_hpos = dpyinfo->mouse_face_beg_col;
8061 start_x = dpyinfo->mouse_face_beg_x;
8062 }
8063 else
8064 {
8065 start_hpos = 0;
8066 start_x = 0;
8067 }
8068
8069 if (row == last)
8070 end_hpos = dpyinfo->mouse_face_end_col;
8071 else
8072 end_hpos = row->used[TEXT_AREA];
8073
8074 if (end_hpos > start_hpos)
8075 {
8076 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8077 start_hpos, end_hpos, draw, 0);
8078
8079 row->mouse_face_p
8080 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8081 }
8082 }
8083
8084 /* When we've written over the cursor, arrange for it to
8085 be displayed again. */
8086 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8087 x_display_cursor (w, 1,
8088 w->phys_cursor.hpos, w->phys_cursor.vpos,
8089 w->phys_cursor.x, w->phys_cursor.y);
8090 }
8091
8092 #if 0 /* MAC_TODO: mouse cursor */
8093 /* Change the mouse cursor. */
8094 if (draw == DRAW_NORMAL_TEXT)
8095 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8096 f->output_data.x->text_cursor);
8097 else if (draw == DRAW_MOUSE_FACE)
8098 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8099 f->output_data.x->cross_cursor);
8100 else
8101 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8102 f->output_data.x->nontext_cursor);
8103 #endif
8104 }
8105
8106 /* Clear out the mouse-highlighted active region.
8107 Redraw it un-highlighted first. */
8108
8109 static int
8110 clear_mouse_face (dpyinfo)
8111 struct mac_display_info *dpyinfo;
8112 {
8113 int cleared = 0;
8114
8115 if (! NILP (dpyinfo->mouse_face_window))
8116 {
8117 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8118 cleared = 1;
8119 }
8120
8121 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8122 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8123 dpyinfo->mouse_face_window = Qnil;
8124 dpyinfo->mouse_face_overlay = Qnil;
8125 return cleared;
8126 }
8127
8128
8129 /* Clear any mouse-face on window W. This function is part of the
8130 redisplay interface, and is called from try_window_id and similar
8131 functions to ensure the mouse-highlight is off. */
8132
8133 static void
8134 x_clear_mouse_face (w)
8135 struct window *w;
8136 {
8137 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8138 Lisp_Object window;
8139
8140 BLOCK_INPUT;
8141 XSETWINDOW (window, w);
8142 if (EQ (window, dpyinfo->mouse_face_window))
8143 clear_mouse_face (dpyinfo);
8144 UNBLOCK_INPUT;
8145 }
8146
8147
8148 /* Just discard the mouse face information for frame F, if any.
8149 This is used when the size of F is changed. */
8150
8151 void
8152 cancel_mouse_face (f)
8153 FRAME_PTR f;
8154 {
8155 Lisp_Object window;
8156 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8157
8158 window = dpyinfo->mouse_face_window;
8159 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8160 {
8161 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8162 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8163 dpyinfo->mouse_face_window = Qnil;
8164 }
8165 }
8166 \f
8167 static struct scroll_bar *x_window_to_scroll_bar ();
8168 static void x_scroll_bar_report_motion ();
8169 static void x_check_fullscreen P_ ((struct frame *));
8170 static void x_check_fullscreen_move P_ ((struct frame *));
8171 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8172
8173
8174 /* Try to determine frame pixel position and size of the glyph under
8175 frame pixel coordinates X/Y on frame F . Return the position and
8176 size in *RECT. Value is non-zero if we could compute these
8177 values. */
8178
8179 static int
8180 glyph_rect (f, x, y, rect)
8181 struct frame *f;
8182 int x, y;
8183 Rect *rect;
8184 {
8185 Lisp_Object window;
8186 int part;
8187
8188 window = window_from_coordinates (f, x, y, &part, 0);
8189 if (!NILP (window))
8190 {
8191 struct window *w = XWINDOW (window);
8192 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8193 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8194
8195 frame_to_window_pixel_xy (w, &x, &y);
8196
8197 for (; r < end && r->enabled_p; ++r)
8198 if (r->y <= y && r->y + r->height > y)
8199 {
8200 /* Found the row at y. */
8201 struct glyph *g = r->glyphs[TEXT_AREA];
8202 struct glyph *end = g + r->used[TEXT_AREA];
8203 int gx;
8204
8205 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8206 rect->bottom = rect->top + r->height;
8207
8208 if (x < r->x)
8209 {
8210 /* x is to the left of the first glyph in the row. */
8211 rect->left = XINT (w->left);
8212 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8213 return 1;
8214 }
8215
8216 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8217 if (gx <= x && gx + g->pixel_width > x)
8218 {
8219 /* x is on a glyph. */
8220 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8221 rect->right = rect->left + g->pixel_width;
8222 return 1;
8223 }
8224
8225 /* x is to the right of the last glyph in the row. */
8226 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8227 rect->right = XINT (w->left) + XINT (w->width);
8228 return 1;
8229 }
8230 }
8231
8232 /* The y is not on any row. */
8233 return 0;
8234 }
8235
8236 /* Record the position of the mouse in last_mouse_glyph. */
8237 static void
8238 remember_mouse_glyph (f1, gx, gy)
8239 struct frame * f1;
8240 int gx, gy;
8241 {
8242 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8243 {
8244 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8245 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8246
8247 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8248 round down even for negative values. */
8249 if (gx < 0)
8250 gx -= width - 1;
8251 if (gy < 0)
8252 gy -= height - 1;
8253 #if 0
8254 /* This was the original code from XTmouse_position, but it seems
8255 to give the position of the glyph diagonally next to the one
8256 the mouse is over. */
8257 gx = (gx + width - 1) / width * width;
8258 gy = (gy + height - 1) / height * height;
8259 #else
8260 gx = gx / width * width;
8261 gy = gy / height * height;
8262 #endif
8263
8264 last_mouse_glyph.left = gx;
8265 last_mouse_glyph.top = gy;
8266 last_mouse_glyph.right = gx + width;
8267 last_mouse_glyph.bottom = gy + height;
8268 }
8269 }
8270
8271 /* Return the current position of the mouse.
8272 *fp should be a frame which indicates which display to ask about.
8273
8274 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8275 and *part to the frame, window, and scroll bar part that the mouse
8276 is over. Set *x and *y to the portion and whole of the mouse's
8277 position on the scroll bar.
8278
8279 If the mouse movement started elsewhere, set *fp to the frame the
8280 mouse is on, *bar_window to nil, and *x and *y to the character cell
8281 the mouse is over.
8282
8283 Set *time to the server time-stamp for the time at which the mouse
8284 was at this position.
8285
8286 Don't store anything if we don't have a valid set of values to report.
8287
8288 This clears the mouse_moved flag, so we can wait for the next mouse
8289 movement. */
8290
8291 static void
8292 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8293 FRAME_PTR *fp;
8294 int insist;
8295 Lisp_Object *bar_window;
8296 enum scroll_bar_part *part;
8297 Lisp_Object *x, *y;
8298 unsigned long *time;
8299 {
8300 Point mouse_pos;
8301 int ignore1, ignore2;
8302 WindowPtr wp = FrontWindow ();
8303 struct frame *f;
8304 Lisp_Object frame, tail;
8305
8306 if (is_emacs_window(wp))
8307 f = ((mac_output *) GetWRefCon (wp))->mFP;
8308
8309 BLOCK_INPUT;
8310
8311 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8312 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8313 else
8314 {
8315 /* Clear the mouse-moved flag for every frame on this display. */
8316 FOR_EACH_FRAME (tail, frame)
8317 XFRAME (frame)->mouse_moved = 0;
8318
8319 last_mouse_scroll_bar = Qnil;
8320
8321 #if TARGET_API_MAC_CARBON
8322 SetPort (GetWindowPort (wp));
8323 #else
8324 SetPort (wp);
8325 #endif
8326
8327 GetMouse (&mouse_pos);
8328
8329 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8330 &last_mouse_glyph, insist);
8331
8332 *bar_window = Qnil;
8333 *part = scroll_bar_handle;
8334 *fp = f;
8335 XSETINT (*x, mouse_pos.h);
8336 XSETINT (*y, mouse_pos.v);
8337 *time = last_mouse_movement_time;
8338 }
8339
8340 UNBLOCK_INPUT;
8341 }
8342
8343 \f
8344 /************************************************************************
8345 Scroll bars, general
8346 ************************************************************************/
8347
8348 /* Create a scroll bar and return the scroll bar vector for it. W is
8349 the Emacs window on which to create the scroll bar. TOP, LEFT,
8350 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
8351 scroll bar. */
8352
8353 static struct scroll_bar *
8354 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8355 struct window *w;
8356 int top, left, width, height, disp_top, disp_height;
8357 {
8358 struct frame *f = XFRAME (w->frame);
8359 struct scroll_bar *bar
8360 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8361 Rect r;
8362 ControlHandle ch;
8363
8364 BLOCK_INPUT;
8365
8366 r.left = left;
8367 r.top = disp_top;
8368 r.right = left + width;
8369 r.bottom = disp_top + disp_height;
8370
8371 #ifdef TARGET_API_MAC_CARBON
8372 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8373 kControlScrollBarProc, 0L);
8374 #else
8375 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8376 0L);
8377 #endif
8378 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8379 SetControlReference (ch, (long) bar);
8380
8381 XSETWINDOW (bar->window, w);
8382 XSETINT (bar->top, top);
8383 XSETINT (bar->left, left);
8384 XSETINT (bar->width, width);
8385 XSETINT (bar->height, height);
8386 XSETINT (bar->start, 0);
8387 XSETINT (bar->end, 0);
8388 bar->dragging = Qnil;
8389
8390 /* Add bar to its frame's list of scroll bars. */
8391 bar->next = FRAME_SCROLL_BARS (f);
8392 bar->prev = Qnil;
8393 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8394 if (!NILP (bar->next))
8395 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8396
8397 UNBLOCK_INPUT;
8398 return bar;
8399 }
8400
8401
8402 /* Draw BAR's handle in the proper position.
8403
8404 If the handle is already drawn from START to END, don't bother
8405 redrawing it, unless REBUILD is non-zero; in that case, always
8406 redraw it. (REBUILD is handy for drawing the handle after expose
8407 events.)
8408
8409 Normally, we want to constrain the start and end of the handle to
8410 fit inside its rectangle, but if the user is dragging the scroll
8411 bar handle, we want to let them drag it down all the way, so that
8412 the bar's top is as far down as it goes; otherwise, there's no way
8413 to move to the very end of the buffer. */
8414
8415 static void
8416 x_scroll_bar_set_handle (bar, start, end, rebuild)
8417 struct scroll_bar *bar;
8418 int start, end;
8419 int rebuild;
8420 {
8421 int dragging = ! NILP (bar->dragging);
8422 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8423 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8424 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8425 int length = end - start;
8426
8427 /* If the display is already accurate, do nothing. */
8428 if (! rebuild
8429 && start == XINT (bar->start)
8430 && end == XINT (bar->end))
8431 return;
8432
8433 BLOCK_INPUT;
8434
8435 /* Make sure the values are reasonable, and try to preserve the
8436 distance between start and end. */
8437 if (start < 0)
8438 start = 0;
8439 else if (start > top_range)
8440 start = top_range;
8441 end = start + length;
8442
8443 if (end < start)
8444 end = start;
8445 else if (end > top_range && ! dragging)
8446 end = top_range;
8447
8448 /* Store the adjusted setting in the scroll bar. */
8449 XSETINT (bar->start, start);
8450 XSETINT (bar->end, end);
8451
8452 /* Clip the end position, just for display. */
8453 if (end > top_range)
8454 end = top_range;
8455
8456 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8457 top positions, to make sure the handle is always at least that
8458 many pixels tall. */
8459 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8460
8461 SetControlMinimum (ch, 0);
8462 /* Don't inadvertently activate deactivated scroll bars */
8463 if (GetControlMaximum (ch) != -1)
8464 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8465 - (end - start));
8466 SetControlValue (ch, start);
8467 #if TARGET_API_MAC_CARBON
8468 SetControlViewSize (ch, end - start);
8469 #endif
8470
8471 UNBLOCK_INPUT;
8472 }
8473
8474
8475 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8476 nil. */
8477
8478 static void
8479 x_scroll_bar_remove (bar)
8480 struct scroll_bar *bar;
8481 {
8482 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8483
8484 BLOCK_INPUT;
8485
8486 /* Destroy the Mac scroll bar control */
8487 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8488
8489 /* Disassociate this scroll bar from its window. */
8490 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8491
8492 UNBLOCK_INPUT;
8493 }
8494
8495 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8496 that we are displaying PORTION characters out of a total of WHOLE
8497 characters, starting at POSITION. If WINDOW has no scroll bar,
8498 create one. */
8499 static void
8500 XTset_vertical_scroll_bar (w, portion, whole, position)
8501 struct window *w;
8502 int portion, whole, position;
8503 {
8504 struct frame *f = XFRAME (w->frame);
8505 struct scroll_bar *bar;
8506 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8507 int window_x, window_y, window_width, window_height;
8508
8509 /* Get window dimensions. */
8510 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8511 top = window_y;
8512 #ifdef MAC_OSX
8513 width = 16;
8514 #else
8515 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8516 #endif
8517 height = window_height;
8518
8519 /* Compute the left edge of the scroll bar area. */
8520 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8521 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8522 else
8523 left = XFASTINT (w->left);
8524 left *= CANON_X_UNIT (f);
8525 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8526
8527 /* Compute the width of the scroll bar which might be less than
8528 the width of the area reserved for the scroll bar. */
8529 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8530 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8531 else
8532 sb_width = width;
8533
8534 /* Compute the left edge of the scroll bar. */
8535 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8536 sb_left = left + width - sb_width - (width - sb_width) / 2;
8537 else
8538 sb_left = left + (width - sb_width) / 2;
8539
8540 /* Adjustments according to Inside Macintosh to make it look nice */
8541 disp_top = top;
8542 disp_height = height;
8543 if (disp_top == 0)
8544 {
8545 disp_top = -1;
8546 disp_height++;
8547 }
8548 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8549 {
8550 disp_top++;
8551 disp_height--;
8552 }
8553
8554 if (sb_left + sb_width == PIXEL_WIDTH (f))
8555 sb_left++;
8556
8557 /* Does the scroll bar exist yet? */
8558 if (NILP (w->vertical_scroll_bar))
8559 {
8560 BLOCK_INPUT;
8561 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8562 left, top, width, height, 0);
8563 UNBLOCK_INPUT;
8564 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8565 disp_height);
8566 XSETVECTOR (w->vertical_scroll_bar, bar);
8567 }
8568 else
8569 {
8570 /* It may just need to be moved and resized. */
8571 ControlHandle ch;
8572
8573 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8574 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8575
8576 BLOCK_INPUT;
8577
8578 /* If already correctly positioned, do nothing. */
8579 if (XINT (bar->left) == sb_left
8580 && XINT (bar->top) == top
8581 && XINT (bar->width) == sb_width
8582 && XINT (bar->height) == height)
8583 Draw1Control (ch);
8584 else
8585 {
8586 /* Clear areas not covered by the scroll bar because it's not as
8587 wide as the area reserved for it . This makes sure a
8588 previous mode line display is cleared after C-x 2 C-x 1, for
8589 example. */
8590 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8591 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8592 left, top, area_width, height, 0);
8593
8594 #if 0
8595 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8596 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8597 sb_left - 1, top, 1, height, 0);
8598 #endif
8599
8600 HideControl (ch);
8601 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8602 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8603 disp_height);
8604 ShowControl (ch);
8605
8606 /* Remember new settings. */
8607 XSETINT (bar->left, sb_left);
8608 XSETINT (bar->top, top);
8609 XSETINT (bar->width, sb_width);
8610 XSETINT (bar->height, height);
8611 }
8612
8613 UNBLOCK_INPUT;
8614 }
8615
8616 /* Set the scroll bar's current state, unless we're currently being
8617 dragged. */
8618 if (NILP (bar->dragging))
8619 {
8620 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8621
8622 if (whole == 0)
8623 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8624 else
8625 {
8626 int start = ((double) position * top_range) / whole;
8627 int end = ((double) (position + portion) * top_range) / whole;
8628 x_scroll_bar_set_handle (bar, start, end, 0);
8629 }
8630 }
8631 }
8632
8633
8634 /* The following three hooks are used when we're doing a thorough
8635 redisplay of the frame. We don't explicitly know which scroll bars
8636 are going to be deleted, because keeping track of when windows go
8637 away is a real pain - "Can you say set-window-configuration, boys
8638 and girls?" Instead, we just assert at the beginning of redisplay
8639 that *all* scroll bars are to be removed, and then save a scroll bar
8640 from the fiery pit when we actually redisplay its window. */
8641
8642 /* Arrange for all scroll bars on FRAME to be removed at the next call
8643 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8644 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8645
8646 static void
8647 XTcondemn_scroll_bars (frame)
8648 FRAME_PTR frame;
8649 {
8650 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8651 while (! NILP (FRAME_SCROLL_BARS (frame)))
8652 {
8653 Lisp_Object bar;
8654 bar = FRAME_SCROLL_BARS (frame);
8655 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8656 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8657 XSCROLL_BAR (bar)->prev = Qnil;
8658 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8659 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8660 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8661 }
8662 }
8663
8664
8665 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8666 Note that WINDOW isn't necessarily condemned at all. */
8667
8668 static void
8669 XTredeem_scroll_bar (window)
8670 struct window *window;
8671 {
8672 struct scroll_bar *bar;
8673
8674 /* We can't redeem this window's scroll bar if it doesn't have one. */
8675 if (NILP (window->vertical_scroll_bar))
8676 abort ();
8677
8678 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8679
8680 /* Unlink it from the condemned list. */
8681 {
8682 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8683
8684 if (NILP (bar->prev))
8685 {
8686 /* If the prev pointer is nil, it must be the first in one of
8687 the lists. */
8688 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8689 /* It's not condemned. Everything's fine. */
8690 return;
8691 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8692 window->vertical_scroll_bar))
8693 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8694 else
8695 /* If its prev pointer is nil, it must be at the front of
8696 one or the other! */
8697 abort ();
8698 }
8699 else
8700 XSCROLL_BAR (bar->prev)->next = bar->next;
8701
8702 if (! NILP (bar->next))
8703 XSCROLL_BAR (bar->next)->prev = bar->prev;
8704
8705 bar->next = FRAME_SCROLL_BARS (f);
8706 bar->prev = Qnil;
8707 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8708 if (! NILP (bar->next))
8709 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8710 }
8711 }
8712
8713 /* Remove all scroll bars on FRAME that haven't been saved since the
8714 last call to `*condemn_scroll_bars_hook'. */
8715
8716 static void
8717 XTjudge_scroll_bars (f)
8718 FRAME_PTR f;
8719 {
8720 Lisp_Object bar, next;
8721
8722 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8723
8724 /* Clear out the condemned list now so we won't try to process any
8725 more events on the hapless scroll bars. */
8726 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8727
8728 for (; ! NILP (bar); bar = next)
8729 {
8730 struct scroll_bar *b = XSCROLL_BAR (bar);
8731
8732 x_scroll_bar_remove (b);
8733
8734 next = b->next;
8735 b->next = b->prev = Qnil;
8736 }
8737
8738 /* Now there should be no references to the condemned scroll bars,
8739 and they should get garbage-collected. */
8740 }
8741
8742
8743 static void
8744 activate_scroll_bars (frame)
8745 FRAME_PTR frame;
8746 {
8747 Lisp_Object bar;
8748 ControlHandle ch;
8749
8750 bar = FRAME_SCROLL_BARS (frame);
8751 while (! NILP (bar))
8752 {
8753 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8754 #ifdef TARGET_API_MAC_CARBON
8755 ActivateControl (ch);
8756 #else
8757 SetControlMaximum (ch,
8758 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8759 XINT (XSCROLL_BAR (bar)
8760 ->height)) - 1);
8761 #endif
8762 bar = XSCROLL_BAR (bar)->next;
8763 }
8764 }
8765
8766
8767 static void
8768 deactivate_scroll_bars (frame)
8769 FRAME_PTR frame;
8770 {
8771 Lisp_Object bar;
8772 ControlHandle ch;
8773
8774 bar = FRAME_SCROLL_BARS (frame);
8775 while (! NILP (bar))
8776 {
8777 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8778 #ifdef TARGET_API_MAC_CARBON
8779 DeactivateControl (ch);
8780 #else
8781 SetControlMaximum (ch, XINT (-1));
8782 #endif
8783 bar = XSCROLL_BAR (bar)->next;
8784 }
8785 }
8786
8787 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8788 is set to something other than NO_EVENT, it is enqueued.
8789
8790 This may be called from a signal handler, so we have to ignore GC
8791 mark bits. */
8792
8793 static void
8794 x_scroll_bar_handle_click (bar, part_code, er, bufp)
8795 struct scroll_bar *bar;
8796 int part_code;
8797 EventRecord *er;
8798 struct input_event *bufp;
8799 {
8800 if (! GC_WINDOWP (bar->window))
8801 abort ();
8802
8803 bufp->kind = SCROLL_BAR_CLICK_EVENT;
8804 bufp->frame_or_window = bar->window;
8805 bufp->arg = Qnil;
8806
8807 bar->dragging = Qnil;
8808
8809 switch (part_code)
8810 {
8811 case kControlUpButtonPart:
8812 bufp->part = scroll_bar_up_arrow;
8813 break;
8814 case kControlDownButtonPart:
8815 bufp->part = scroll_bar_down_arrow;
8816 break;
8817 case kControlPageUpPart:
8818 bufp->part = scroll_bar_above_handle;
8819 break;
8820 case kControlPageDownPart:
8821 bufp->part = scroll_bar_below_handle;
8822 break;
8823 #ifdef TARGET_API_MAC_CARBON
8824 default:
8825 #else
8826 case kControlIndicatorPart:
8827 #endif
8828 if (er->what == mouseDown)
8829 bar->dragging = make_number (0);
8830 XSETVECTOR (last_mouse_scroll_bar, bar);
8831 bufp->part = scroll_bar_handle;
8832 break;
8833 }
8834 }
8835
8836
8837 /* Handle some mouse motion while someone is dragging the scroll bar.
8838
8839 This may be called from a signal handler, so we have to ignore GC
8840 mark bits. */
8841
8842 static void
8843 x_scroll_bar_note_movement (bar, y_pos, t)
8844 struct scroll_bar *bar;
8845 int y_pos;
8846 Time t;
8847 {
8848 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8849
8850 last_mouse_movement_time = t;
8851
8852 f->mouse_moved = 1;
8853 XSETVECTOR (last_mouse_scroll_bar, bar);
8854
8855 /* If we're dragging the bar, display it. */
8856 if (! GC_NILP (bar->dragging))
8857 {
8858 /* Where should the handle be now? */
8859 int new_start = y_pos - 24;
8860
8861 if (new_start != XINT (bar->start))
8862 {
8863 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8864
8865 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8866 }
8867 }
8868 }
8869
8870
8871 /* Return information to the user about the current position of the
8872 mouse on the scroll bar. */
8873
8874 static void
8875 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8876 FRAME_PTR *fp;
8877 Lisp_Object *bar_window;
8878 enum scroll_bar_part *part;
8879 Lisp_Object *x, *y;
8880 unsigned long *time;
8881 {
8882 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8883 WindowPtr wp = FrontWindow ();
8884 Point mouse_pos;
8885 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8886 int win_y, top_range;
8887
8888 #if TARGET_API_MAC_CARBON
8889 SetPort (GetWindowPort (wp));
8890 #else
8891 SetPort (wp);
8892 #endif
8893
8894 GetMouse (&mouse_pos);
8895
8896 win_y = mouse_pos.v - XINT (bar->top);
8897 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8898
8899 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8900
8901 win_y -= 24;
8902
8903 if (! NILP (bar->dragging))
8904 win_y -= XINT (bar->dragging);
8905
8906 if (win_y < 0)
8907 win_y = 0;
8908 if (win_y > top_range)
8909 win_y = top_range;
8910
8911 *fp = f;
8912 *bar_window = bar->window;
8913
8914 if (! NILP (bar->dragging))
8915 *part = scroll_bar_handle;
8916 else if (win_y < XINT (bar->start))
8917 *part = scroll_bar_above_handle;
8918 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8919 *part = scroll_bar_handle;
8920 else
8921 *part = scroll_bar_below_handle;
8922
8923 XSETINT (*x, win_y);
8924 XSETINT (*y, top_range);
8925
8926 f->mouse_moved = 0;
8927 last_mouse_scroll_bar = Qnil;
8928
8929 *time = last_mouse_movement_time;
8930 }
8931 \f
8932 /***********************************************************************
8933 Text Cursor
8934 ***********************************************************************/
8935
8936 /* Notice if the text cursor of window W has been overwritten by a
8937 drawing operation that outputs glyphs starting at START_X and
8938 ending at END_X in the line given by output_cursor.vpos.
8939 Coordinates are area-relative. END_X < 0 means all the rest
8940 of the line after START_X has been written. */
8941
8942 static void
8943 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
8944 struct window *w;
8945 enum glyph_row_area area;
8946 int x0, x1, y0, y1;
8947 {
8948 if (area == TEXT_AREA
8949 && w->phys_cursor_on_p
8950 && y0 <= w->phys_cursor.y
8951 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8952 && x0 <= w->phys_cursor.x
8953 && (x1 < 0 || x1 > w->phys_cursor.x))
8954 w->phys_cursor_on_p = 0;
8955 }
8956
8957
8958 /* Set clipping for output in glyph row ROW. W is the window in which
8959 we operate. GC is the graphics context to set clipping in.
8960 WHOLE_LINE_P non-zero means include the areas used for truncation
8961 mark display and alike in the clipping rectangle.
8962
8963 ROW may be a text row or, e.g., a mode line. Text rows must be
8964 clipped to the interior of the window dedicated to text display,
8965 mode lines must be clipped to the whole window. */
8966
8967 static void
8968 x_clip_to_row (w, row, gc, whole_line_p)
8969 struct window *w;
8970 struct glyph_row *row;
8971 GC gc;
8972 int whole_line_p;
8973 {
8974 struct frame *f = XFRAME (WINDOW_FRAME (w));
8975 Rect clip_rect;
8976 int window_x, window_y, window_width, window_height;
8977
8978 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8979
8980 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8981 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8982 clip_rect.top = max (clip_rect.top, window_y);
8983 clip_rect.right = clip_rect.left + window_width;
8984 clip_rect.bottom = clip_rect.top + row->visible_height;
8985
8986 /* If clipping to the whole line, including trunc marks, extend
8987 the rectangle to the left and increase its width. */
8988 if (whole_line_p)
8989 {
8990 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8991 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
8992 }
8993
8994 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8995 }
8996
8997
8998 /* Draw a hollow box cursor on window W in glyph row ROW. */
8999
9000 static void
9001 x_draw_hollow_cursor (w, row)
9002 struct window *w;
9003 struct glyph_row *row;
9004 {
9005 struct frame *f = XFRAME (WINDOW_FRAME (w));
9006 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9007 Display *dpy = FRAME_MAC_DISPLAY (f);
9008 int x, y, wd, h;
9009 XGCValues xgcv;
9010 struct glyph *cursor_glyph;
9011 GC gc;
9012
9013 /* Compute frame-relative coordinates from window-relative
9014 coordinates. */
9015 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9016 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9017 + row->ascent - w->phys_cursor_ascent);
9018 h = row->height - 1;
9019
9020 /* Get the glyph the cursor is on. If we can't tell because
9021 the current matrix is invalid or such, give up. */
9022 cursor_glyph = get_phys_cursor_glyph (w);
9023 if (cursor_glyph == NULL)
9024 return;
9025
9026 /* Compute the width of the rectangle to draw. If on a stretch
9027 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9028 rectangle as wide as the glyph, but use a canonical character
9029 width instead. */
9030 wd = cursor_glyph->pixel_width - 1;
9031 if (cursor_glyph->type == STRETCH_GLYPH
9032 && !x_stretch_cursor_p)
9033 wd = min (CANON_X_UNIT (f), wd);
9034
9035 /* The foreground of cursor_gc is typically the same as the normal
9036 background color, which can cause the cursor box to be invisible. */
9037 xgcv.foreground = f->output_data.mac->cursor_pixel;
9038 if (dpyinfo->scratch_cursor_gc)
9039 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
9040 else
9041 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
9042 GCForeground, &xgcv);
9043 gc = dpyinfo->scratch_cursor_gc;
9044
9045 /* Set clipping, draw the rectangle, and reset clipping again. */
9046 x_clip_to_row (w, row, gc, 0);
9047 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
9048 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9049 }
9050
9051
9052 /* Draw a bar cursor on window W in glyph row ROW.
9053
9054 Implementation note: One would like to draw a bar cursor with an
9055 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9056 Unfortunately, I didn't find a font yet that has this property set.
9057 --gerd. */
9058
9059 static void
9060 x_draw_bar_cursor (w, row, width)
9061 struct window *w;
9062 struct glyph_row *row;
9063 int width;
9064 {
9065 /* If cursor hpos is out of bounds, don't draw garbage. This can
9066 happen in mini-buffer windows when switching between echo area
9067 glyphs and mini-buffer. */
9068 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9069 {
9070 struct frame *f = XFRAME (w->frame);
9071 struct glyph *cursor_glyph;
9072 GC gc;
9073 int x;
9074 unsigned long mask;
9075 XGCValues xgcv;
9076 Display *dpy;
9077 Window window;
9078
9079 cursor_glyph = get_phys_cursor_glyph (w);
9080 if (cursor_glyph == NULL)
9081 return;
9082
9083 xgcv.background = f->output_data.mac->cursor_pixel;
9084 xgcv.foreground = f->output_data.mac->cursor_pixel;
9085 mask = GCForeground | GCBackground;
9086 dpy = FRAME_MAC_DISPLAY (f);
9087 window = FRAME_MAC_WINDOW (f);
9088 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9089
9090 if (gc)
9091 XChangeGC (dpy, gc, mask, &xgcv);
9092 else
9093 {
9094 gc = XCreateGC (dpy, window, mask, &xgcv);
9095 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9096 }
9097
9098 if (width < 0)
9099 width = FRAME_CURSOR_WIDTH (f);
9100
9101 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9102 x_clip_to_row (w, row, gc, 0);
9103 XFillRectangle (dpy, window, gc,
9104 x,
9105 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9106 min (cursor_glyph->pixel_width, width),
9107 row->height);
9108 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9109 }
9110 }
9111
9112
9113 /* Clear the cursor of window W to background color, and mark the
9114 cursor as not shown. This is used when the text where the cursor
9115 is is about to be rewritten. */
9116
9117 static void
9118 x_clear_cursor (w)
9119 struct window *w;
9120 {
9121 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9122 x_update_window_cursor (w, 0);
9123 }
9124
9125
9126 /* Draw the cursor glyph of window W in glyph row ROW. See the
9127 comment of x_draw_glyphs for the meaning of HL. */
9128
9129 static void
9130 x_draw_phys_cursor_glyph (w, row, hl)
9131 struct window *w;
9132 struct glyph_row *row;
9133 enum draw_glyphs_face hl;
9134 {
9135 /* If cursor hpos is out of bounds, don't draw garbage. This can
9136 happen in mini-buffer windows when switching between echo area
9137 glyphs and mini-buffer. */
9138 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9139 {
9140 int on_p = w->phys_cursor_on_p;
9141 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9142 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9143 hl, 0);
9144 w->phys_cursor_on_p = on_p;
9145
9146 /* When we erase the cursor, and ROW is overlapped by other
9147 rows, make sure that these overlapping parts of other rows
9148 are redrawn. */
9149 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9150 {
9151 if (row > w->current_matrix->rows
9152 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9153 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9154
9155 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9156 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9157 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9158 }
9159 }
9160 }
9161
9162
9163 /* Erase the image of a cursor of window W from the screen. */
9164
9165 static void
9166 x_erase_phys_cursor (w)
9167 struct window *w;
9168 {
9169 struct frame *f = XFRAME (w->frame);
9170 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9171 int hpos = w->phys_cursor.hpos;
9172 int vpos = w->phys_cursor.vpos;
9173 int mouse_face_here_p = 0;
9174 struct glyph_matrix *active_glyphs = w->current_matrix;
9175 struct glyph_row *cursor_row;
9176 struct glyph *cursor_glyph;
9177 enum draw_glyphs_face hl;
9178
9179 /* No cursor displayed or row invalidated => nothing to do on the
9180 screen. */
9181 if (w->phys_cursor_type == NO_CURSOR)
9182 goto mark_cursor_off;
9183
9184 /* VPOS >= active_glyphs->nrows means that window has been resized.
9185 Don't bother to erase the cursor. */
9186 if (vpos >= active_glyphs->nrows)
9187 goto mark_cursor_off;
9188
9189 /* If row containing cursor is marked invalid, there is nothing we
9190 can do. */
9191 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9192 if (!cursor_row->enabled_p)
9193 goto mark_cursor_off;
9194
9195 /* If row is completely invisible, don't attempt to delete a cursor which
9196 isn't there. This may happen if cursor is at top of window, and
9197 we switch to a buffer with a header line in that window. */
9198 if (cursor_row->visible_height <= 0)
9199 goto mark_cursor_off;
9200
9201 /* This can happen when the new row is shorter than the old one.
9202 In this case, either x_draw_glyphs or clear_end_of_line
9203 should have cleared the cursor. Note that we wouldn't be
9204 able to erase the cursor in this case because we don't have a
9205 cursor glyph at hand. */
9206 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9207 goto mark_cursor_off;
9208
9209 /* If the cursor is in the mouse face area, redisplay that when
9210 we clear the cursor. */
9211 if (! NILP (dpyinfo->mouse_face_window)
9212 && w == XWINDOW (dpyinfo->mouse_face_window)
9213 && (vpos > dpyinfo->mouse_face_beg_row
9214 || (vpos == dpyinfo->mouse_face_beg_row
9215 && hpos >= dpyinfo->mouse_face_beg_col))
9216 && (vpos < dpyinfo->mouse_face_end_row
9217 || (vpos == dpyinfo->mouse_face_end_row
9218 && hpos < dpyinfo->mouse_face_end_col))
9219 /* Don't redraw the cursor's spot in mouse face if it is at the
9220 end of a line (on a newline). The cursor appears there, but
9221 mouse highlighting does not. */
9222 && cursor_row->used[TEXT_AREA] > hpos)
9223 mouse_face_here_p = 1;
9224
9225 /* Maybe clear the display under the cursor. */
9226 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9227 {
9228 int x;
9229 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9230
9231 cursor_glyph = get_phys_cursor_glyph (w);
9232 if (cursor_glyph == NULL)
9233 goto mark_cursor_off;
9234
9235 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9236
9237 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9238 x,
9239 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9240 cursor_row->y)),
9241 cursor_glyph->pixel_width,
9242 cursor_row->visible_height,
9243 0);
9244 }
9245
9246 /* Erase the cursor by redrawing the character underneath it. */
9247 if (mouse_face_here_p)
9248 hl = DRAW_MOUSE_FACE;
9249 else
9250 hl = DRAW_NORMAL_TEXT;
9251 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9252
9253 mark_cursor_off:
9254 w->phys_cursor_on_p = 0;
9255 w->phys_cursor_type = NO_CURSOR;
9256 }
9257
9258
9259 /* Non-zero if physical cursor of window W is within mouse face. */
9260
9261 static int
9262 cursor_in_mouse_face_p (w)
9263 struct window *w;
9264 {
9265 struct mac_display_info *dpyinfo
9266 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9267 int in_mouse_face = 0;
9268
9269 if (WINDOWP (dpyinfo->mouse_face_window)
9270 && XWINDOW (dpyinfo->mouse_face_window) == w)
9271 {
9272 int hpos = w->phys_cursor.hpos;
9273 int vpos = w->phys_cursor.vpos;
9274
9275 if (vpos >= dpyinfo->mouse_face_beg_row
9276 && vpos <= dpyinfo->mouse_face_end_row
9277 && (vpos > dpyinfo->mouse_face_beg_row
9278 || hpos >= dpyinfo->mouse_face_beg_col)
9279 && (vpos < dpyinfo->mouse_face_end_row
9280 || hpos < dpyinfo->mouse_face_end_col
9281 || dpyinfo->mouse_face_past_end))
9282 in_mouse_face = 1;
9283 }
9284
9285 return in_mouse_face;
9286 }
9287
9288
9289 /* Display or clear cursor of window W. If ON is zero, clear the
9290 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9291 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9292
9293 void
9294 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9295 struct window *w;
9296 int on, hpos, vpos, x, y;
9297 {
9298 struct frame *f = XFRAME (w->frame);
9299 int new_cursor_type;
9300 int new_cursor_width;
9301 int active_cursor;
9302 struct glyph_matrix *current_glyphs;
9303 struct glyph_row *glyph_row;
9304 struct glyph *glyph;
9305
9306 /* This is pointless on invisible frames, and dangerous on garbaged
9307 windows and frames; in the latter case, the frame or window may
9308 be in the midst of changing its size, and x and y may be off the
9309 window. */
9310 if (! FRAME_VISIBLE_P (f)
9311 || FRAME_GARBAGED_P (f)
9312 || vpos >= w->current_matrix->nrows
9313 || hpos >= w->current_matrix->matrix_w)
9314 return;
9315
9316 /* If cursor is off and we want it off, return quickly. */
9317 if (!on && !w->phys_cursor_on_p)
9318 return;
9319
9320 current_glyphs = w->current_matrix;
9321 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9322 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9323
9324 /* If cursor row is not enabled, we don't really know where to
9325 display the cursor. */
9326 if (!glyph_row->enabled_p)
9327 {
9328 w->phys_cursor_on_p = 0;
9329 return;
9330 }
9331
9332 xassert (interrupt_input_blocked);
9333
9334 /* Set new_cursor_type to the cursor we want to be displayed. */
9335 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
9336
9337
9338 /* If cursor is currently being shown and we don't want it to be or
9339 it is in the wrong place, or the cursor type is not what we want,
9340 erase it. */
9341 if (w->phys_cursor_on_p
9342 && (!on
9343 || w->phys_cursor.x != x
9344 || w->phys_cursor.y != y
9345 || new_cursor_type != w->phys_cursor_type
9346 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
9347 && new_cursor_width != w->phys_cursor_width)))
9348 x_erase_phys_cursor (w);
9349
9350 /* If the cursor is now invisible and we want it to be visible,
9351 display it. */
9352 if (on && !w->phys_cursor_on_p)
9353 {
9354 w->phys_cursor_ascent = glyph_row->ascent;
9355 w->phys_cursor_height = glyph_row->height;
9356
9357 /* Set phys_cursor_.* before x_draw_.* is called because some
9358 of them may need the information. */
9359 w->phys_cursor.x = x;
9360 w->phys_cursor.y = glyph_row->y;
9361 w->phys_cursor.hpos = hpos;
9362 w->phys_cursor.vpos = vpos;
9363 w->phys_cursor_type = new_cursor_type;
9364 w->phys_cursor_width = new_cursor_width;
9365 w->phys_cursor_on_p = 1;
9366
9367 switch (new_cursor_type)
9368 {
9369 case HOLLOW_BOX_CURSOR:
9370 x_draw_hollow_cursor (w, glyph_row);
9371 break;
9372
9373 case FILLED_BOX_CURSOR:
9374 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9375 break;
9376
9377 case HBAR_CURSOR:
9378 /* TODO. For now, just draw bar cursor. */
9379 case BAR_CURSOR:
9380 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9381 break;
9382
9383 case NO_CURSOR:
9384 break;
9385
9386 default:
9387 abort ();
9388 }
9389 }
9390 }
9391
9392
9393 /* Display the cursor on window W, or clear it. X and Y are window
9394 relative pixel coordinates. HPOS and VPOS are glyph matrix
9395 positions. If W is not the selected window, display a hollow
9396 cursor. ON non-zero means display the cursor at X, Y which
9397 correspond to HPOS, VPOS, otherwise it is cleared. */
9398
9399 void
9400 x_display_cursor (w, on, hpos, vpos, x, y)
9401 struct window *w;
9402 int on, hpos, vpos, x, y;
9403 {
9404 BLOCK_INPUT;
9405 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9406 UNBLOCK_INPUT;
9407 }
9408
9409
9410 /* Display the cursor on window W, or clear it, according to ON_P.
9411 Don't change the cursor's position. */
9412
9413 void
9414 x_update_cursor (f, on_p)
9415 struct frame *f;
9416 int on_p;
9417 {
9418 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9419 }
9420
9421
9422 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9423 in the window tree rooted at W. */
9424
9425 static void
9426 x_update_cursor_in_window_tree (w, on_p)
9427 struct window *w;
9428 int on_p;
9429 {
9430 while (w)
9431 {
9432 if (!NILP (w->hchild))
9433 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9434 else if (!NILP (w->vchild))
9435 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9436 else
9437 x_update_window_cursor (w, on_p);
9438
9439 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9440 }
9441 }
9442
9443
9444 /* Switch the display of W's cursor on or off, according to the value
9445 of ON. */
9446
9447 static void
9448 x_update_window_cursor (w, on)
9449 struct window *w;
9450 int on;
9451 {
9452 /* Don't update cursor in windows whose frame is in the process
9453 of being deleted. */
9454 if (w->current_matrix)
9455 {
9456 BLOCK_INPUT;
9457 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9458 w->phys_cursor.vpos, w->phys_cursor.x,
9459 w->phys_cursor.y);
9460 UNBLOCK_INPUT;
9461 }
9462 }
9463
9464
9465
9466 \f
9467 /* Icons. */
9468
9469 #if 0 /* MAC_TODO: no icon support yet. */
9470 int
9471 x_bitmap_icon (f, icon)
9472 struct frame *f;
9473 Lisp_Object icon;
9474 {
9475 HANDLE hicon;
9476
9477 if (FRAME_W32_WINDOW (f) == 0)
9478 return 1;
9479
9480 if (NILP (icon))
9481 hicon = LoadIcon (hinst, EMACS_CLASS);
9482 else if (STRINGP (icon))
9483 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
9484 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9485 else if (SYMBOLP (icon))
9486 {
9487 LPCTSTR name;
9488
9489 if (EQ (icon, intern ("application")))
9490 name = (LPCTSTR) IDI_APPLICATION;
9491 else if (EQ (icon, intern ("hand")))
9492 name = (LPCTSTR) IDI_HAND;
9493 else if (EQ (icon, intern ("question")))
9494 name = (LPCTSTR) IDI_QUESTION;
9495 else if (EQ (icon, intern ("exclamation")))
9496 name = (LPCTSTR) IDI_EXCLAMATION;
9497 else if (EQ (icon, intern ("asterisk")))
9498 name = (LPCTSTR) IDI_ASTERISK;
9499 else if (EQ (icon, intern ("winlogo")))
9500 name = (LPCTSTR) IDI_WINLOGO;
9501 else
9502 return 1;
9503
9504 hicon = LoadIcon (NULL, name);
9505 }
9506 else
9507 return 1;
9508
9509 if (hicon == NULL)
9510 return 1;
9511
9512 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9513 (LPARAM) hicon);
9514
9515 return 0;
9516 }
9517 #endif /* MAC_TODO */
9518 \f
9519 /************************************************************************
9520 Handling X errors
9521 ************************************************************************/
9522
9523 /* Display Error Handling functions not used on W32. Listing them here
9524 helps diff stay in step when comparing w32term.c with xterm.c.
9525
9526 x_error_catcher (display, error)
9527 x_catch_errors (dpy)
9528 x_catch_errors_unwind (old_val)
9529 x_check_errors (dpy, format)
9530 x_had_errors_p (dpy)
9531 x_clear_errors (dpy)
9532 x_uncatch_errors (dpy, count)
9533 x_trace_wire ()
9534 x_connection_signal (signalnum)
9535 x_connection_closed (dpy, error_message)
9536 x_error_quitter (display, error)
9537 x_error_handler (display, error)
9538 x_io_error_quitter (display)
9539
9540 */
9541
9542 \f
9543 /* Changing the font of the frame. */
9544
9545 /* Give frame F the font named FONTNAME as its default font, and
9546 return the full name of that font. FONTNAME may be a wildcard
9547 pattern; in that case, we choose some font that fits the pattern.
9548 The return value shows which font we chose. */
9549
9550 Lisp_Object
9551 x_new_font (f, fontname)
9552 struct frame *f;
9553 register char *fontname;
9554 {
9555 struct font_info *fontp
9556 = FS_LOAD_FONT (f, 0, fontname, -1);
9557
9558 if (!fontp)
9559 return Qnil;
9560
9561 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9562 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9563 FRAME_FONTSET (f) = -1;
9564
9565 /* Compute the scroll bar width in character columns. */
9566 if (f->scroll_bar_pixel_width > 0)
9567 {
9568 int wid = FONT_WIDTH (FRAME_FONT (f));
9569 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9570 }
9571 else
9572 {
9573 int wid = FONT_WIDTH (FRAME_FONT (f));
9574 f->scroll_bar_cols = (14 + wid - 1) / wid;
9575 }
9576
9577 /* Now make the frame display the given font. */
9578 if (FRAME_MAC_WINDOW (f) != 0)
9579 {
9580 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9581 f->output_data.mac->font);
9582 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9583 f->output_data.mac->font);
9584 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9585 f->output_data.mac->font);
9586
9587 frame_update_line_height (f);
9588 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9589 x_set_window_size (f, 0, f->width, f->height);
9590 }
9591 else
9592 /* If we are setting a new frame's font for the first time,
9593 there are no faces yet, so this font's height is the line height. */
9594 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
9595
9596 return build_string (fontp->full_name);
9597 }
9598 \f
9599 /* Give frame F the fontset named FONTSETNAME as its default font, and
9600 return the full name of that fontset. FONTSETNAME may be a wildcard
9601 pattern; in that case, we choose some fontset that fits the pattern.
9602 The return value shows which fontset we chose. */
9603
9604 Lisp_Object
9605 x_new_fontset (f, fontsetname)
9606 struct frame *f;
9607 char *fontsetname;
9608 {
9609 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9610 Lisp_Object result;
9611
9612 if (fontset < 0)
9613 return Qnil;
9614
9615 if (FRAME_FONTSET (f) == fontset)
9616 /* This fontset is already set in frame F. There's nothing more
9617 to do. */
9618 return fontset_name (fontset);
9619
9620 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
9621
9622 if (!STRINGP (result))
9623 /* Can't load ASCII font. */
9624 return Qnil;
9625
9626 /* Since x_new_font doesn't update any fontset information, do it now. */
9627 FRAME_FONTSET(f) = fontset;
9628
9629 return build_string (fontsetname);
9630 }
9631
9632 /* Compute actual fringe widths */
9633
9634 void
9635 x_compute_fringe_widths (f, redraw)
9636 struct frame *f;
9637 int redraw;
9638 {
9639 int o_left = f->output_data.mac->left_fringe_width;
9640 int o_right = f->output_data.mac->right_fringe_width;
9641 int o_cols = f->output_data.mac->fringe_cols;
9642
9643 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9644 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9645 int left_fringe_width, right_fringe_width;
9646
9647 if (!NILP (left_fringe))
9648 left_fringe = Fcdr (left_fringe);
9649 if (!NILP (right_fringe))
9650 right_fringe = Fcdr (right_fringe);
9651
9652 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9653 XINT (left_fringe));
9654 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9655 XINT (right_fringe));
9656
9657 if (left_fringe_width || right_fringe_width)
9658 {
9659 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9660 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9661 int conf_wid = left_wid + right_wid;
9662 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9663 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9664 int real_wid = cols * font_wid;
9665 if (left_wid && right_wid)
9666 {
9667 if (left_fringe_width < 0)
9668 {
9669 /* Left fringe width is fixed, adjust right fringe if necessary */
9670 f->output_data.mac->left_fringe_width = left_wid;
9671 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9672 }
9673 else if (right_fringe_width < 0)
9674 {
9675 /* Right fringe width is fixed, adjust left fringe if necessary */
9676 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9677 f->output_data.mac->right_fringe_width = right_wid;
9678 }
9679 else
9680 {
9681 /* Adjust both fringes with an equal amount.
9682 Note that we are doing integer arithmetic here, so don't
9683 lose a pixel if the total width is an odd number. */
9684 int fill = real_wid - conf_wid;
9685 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9686 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9687 }
9688 }
9689 else if (left_fringe_width)
9690 {
9691 f->output_data.mac->left_fringe_width = real_wid;
9692 f->output_data.mac->right_fringe_width = 0;
9693 }
9694 else
9695 {
9696 f->output_data.mac->left_fringe_width = 0;
9697 f->output_data.mac->right_fringe_width = real_wid;
9698 }
9699 f->output_data.mac->fringe_cols = cols;
9700 f->output_data.mac->fringes_extra = real_wid;
9701 }
9702 else
9703 {
9704 f->output_data.mac->left_fringe_width = 0;
9705 f->output_data.mac->right_fringe_width = 0;
9706 f->output_data.mac->fringe_cols = 0;
9707 f->output_data.mac->fringes_extra = 0;
9708 }
9709
9710 if (redraw && FRAME_VISIBLE_P (f))
9711 if (o_left != f->output_data.mac->left_fringe_width ||
9712 o_right != f->output_data.mac->right_fringe_width ||
9713 o_cols != f->output_data.mac->fringe_cols)
9714 redraw_frame (f);
9715 }
9716 \f
9717 /***********************************************************************
9718 TODO: W32 Input Methods
9719 ***********************************************************************/
9720 /* Listing missing functions from xterm.c helps diff stay in step.
9721
9722 xim_destroy_callback (xim, client_data, call_data)
9723 xim_open_dpy (dpyinfo, resource_name)
9724 struct xim_inst_t
9725 xim_instantiate_callback (display, client_data, call_data)
9726 xim_initialize (dpyinfo, resource_name)
9727 xim_close_dpy (dpyinfo)
9728
9729 */
9730
9731 \f
9732 /* Calculate the absolute position in frame F
9733 from its current recorded position values and gravity. */
9734
9735 void
9736 x_calc_absolute_position (f)
9737 struct frame *f;
9738 {
9739 Point pt;
9740 int flags = f->output_data.mac->size_hint_flags;
9741
9742 pt.h = pt.v = 0;
9743
9744 /* Find the position of the outside upper-left corner of
9745 the inner window, with respect to the outer window. */
9746 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9747 {
9748 GrafPtr savePort;
9749 GetPort (&savePort);
9750
9751 #if TARGET_API_MAC_CARBON
9752 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9753 #else
9754 SetPort (FRAME_MAC_WINDOW (f));
9755 #endif
9756
9757 #if TARGET_API_MAC_CARBON
9758 {
9759 Rect r;
9760
9761 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9762 SetPt(&pt, r.left, r.top);
9763 }
9764 #else /* not TARGET_API_MAC_CARBON */
9765 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
9766 #endif /* not TARGET_API_MAC_CARBON */
9767 LocalToGlobal (&pt);
9768 SetPort (savePort);
9769 }
9770
9771 /* Treat negative positions as relative to the leftmost bottommost
9772 position that fits on the screen. */
9773 if (flags & XNegative)
9774 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9775 - 2 * f->output_data.mac->border_width - pt.h
9776 - PIXEL_WIDTH (f)
9777 + f->output_data.mac->left_pos);
9778 /* NTEMACS_TODO: Subtract menubar height? */
9779 if (flags & YNegative)
9780 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9781 - 2 * f->output_data.mac->border_width - pt.v
9782 - PIXEL_HEIGHT (f)
9783 + f->output_data.mac->top_pos);
9784 /* The left_pos and top_pos
9785 are now relative to the top and left screen edges,
9786 so the flags should correspond. */
9787 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9788 }
9789
9790 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9791 to really change the position, and 0 when calling from
9792 x_make_frame_visible (in that case, XOFF and YOFF are the current
9793 position values). It is -1 when calling from x_set_frame_parameters,
9794 which means, do adjust for borders but don't change the gravity. */
9795
9796 void
9797 x_set_offset (f, xoff, yoff, change_gravity)
9798 struct frame *f;
9799 register int xoff, yoff;
9800 int change_gravity;
9801 {
9802 int modified_top, modified_left;
9803
9804 if (change_gravity > 0)
9805 {
9806 f->output_data.mac->top_pos = yoff;
9807 f->output_data.mac->left_pos = xoff;
9808 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9809 if (xoff < 0)
9810 f->output_data.mac->size_hint_flags |= XNegative;
9811 if (yoff < 0)
9812 f->output_data.mac->size_hint_flags |= YNegative;
9813 f->output_data.mac->win_gravity = NorthWestGravity;
9814 }
9815 x_calc_absolute_position (f);
9816
9817 BLOCK_INPUT;
9818 x_wm_set_size_hint (f, (long) 0, 0);
9819
9820 modified_left = f->output_data.mac->left_pos;
9821 modified_top = f->output_data.mac->top_pos;
9822
9823 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9824 modified_top + 42, false);
9825
9826 UNBLOCK_INPUT;
9827 }
9828
9829 /* Call this to change the size of frame F's x-window.
9830 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9831 for this size change and subsequent size changes.
9832 Otherwise we leave the window gravity unchanged. */
9833
9834 void
9835 x_set_window_size (f, change_gravity, cols, rows)
9836 struct frame *f;
9837 int change_gravity;
9838 int cols, rows;
9839 {
9840 int pixelwidth, pixelheight;
9841
9842 BLOCK_INPUT;
9843
9844 check_frame_size (f, &rows, &cols);
9845 f->output_data.mac->vertical_scroll_bar_extra
9846 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9847 ? 0
9848 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
9849
9850 x_compute_fringe_widths (f, 0);
9851
9852 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9853 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9854
9855 f->output_data.mac->win_gravity = NorthWestGravity;
9856 x_wm_set_size_hint (f, (long) 0, 0);
9857
9858 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9859
9860 /* Now, strictly speaking, we can't be sure that this is accurate,
9861 but the window manager will get around to dealing with the size
9862 change request eventually, and we'll hear how it went when the
9863 ConfigureNotify event gets here.
9864
9865 We could just not bother storing any of this information here,
9866 and let the ConfigureNotify event set everything up, but that
9867 might be kind of confusing to the Lisp code, since size changes
9868 wouldn't be reported in the frame parameters until some random
9869 point in the future when the ConfigureNotify event arrives.
9870
9871 We pass 1 for DELAY since we can't run Lisp code inside of
9872 a BLOCK_INPUT. */
9873 change_frame_size (f, rows, cols, 0, 1, 0);
9874 PIXEL_WIDTH (f) = pixelwidth;
9875 PIXEL_HEIGHT (f) = pixelheight;
9876
9877 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9878 receive in the ConfigureNotify event; if we get what we asked
9879 for, then the event won't cause the screen to become garbaged, so
9880 we have to make sure to do it here. */
9881 SET_FRAME_GARBAGED (f);
9882
9883 XFlush (FRAME_X_DISPLAY (f));
9884
9885 /* If cursor was outside the new size, mark it as off. */
9886 mark_window_cursors_off (XWINDOW (f->root_window));
9887
9888 /* Clear out any recollection of where the mouse highlighting was,
9889 since it might be in a place that's outside the new frame size.
9890 Actually checking whether it is outside is a pain in the neck,
9891 so don't try--just let the highlighting be done afresh with new size. */
9892 cancel_mouse_face (f);
9893
9894 UNBLOCK_INPUT;
9895 }
9896 \f
9897 /* Mouse warping. */
9898
9899 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9900
9901 void
9902 x_set_mouse_position (f, x, y)
9903 struct frame *f;
9904 int x, y;
9905 {
9906 int pix_x, pix_y;
9907
9908 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9909 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9910
9911 if (pix_x < 0) pix_x = 0;
9912 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9913
9914 if (pix_y < 0) pix_y = 0;
9915 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9916
9917 x_set_mouse_pixel_position (f, pix_x, pix_y);
9918 }
9919
9920 void
9921 x_set_mouse_pixel_position (f, pix_x, pix_y)
9922 struct frame *f;
9923 int pix_x, pix_y;
9924 {
9925 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9926 BLOCK_INPUT;
9927
9928 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9929 0, 0, 0, 0, pix_x, pix_y);
9930 UNBLOCK_INPUT;
9931 #endif
9932 }
9933
9934 \f
9935 /* focus shifting, raising and lowering. */
9936
9937 void
9938 x_focus_on_frame (f)
9939 struct frame *f;
9940 {
9941 #if 0 /* This proves to be unpleasant. */
9942 x_raise_frame (f);
9943 #endif
9944 #if 0
9945 /* I don't think that the ICCCM allows programs to do things like this
9946 without the interaction of the window manager. Whatever you end up
9947 doing with this code, do it to x_unfocus_frame too. */
9948 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9949 RevertToPointerRoot, CurrentTime);
9950 #endif /* ! 0 */
9951 }
9952
9953 void
9954 x_unfocus_frame (f)
9955 struct frame *f;
9956 {
9957 }
9958
9959 /* Raise frame F. */
9960 void
9961 x_raise_frame (f)
9962 struct frame *f;
9963 {
9964 if (f->async_visible)
9965 SelectWindow (FRAME_MAC_WINDOW (f));
9966 }
9967
9968 /* Lower frame F. */
9969 void
9970 x_lower_frame (f)
9971 struct frame *f;
9972 {
9973 if (f->async_visible)
9974 SendBehind (FRAME_MAC_WINDOW (f), nil);
9975 }
9976
9977 static void
9978 XTframe_raise_lower (f, raise_flag)
9979 FRAME_PTR f;
9980 int raise_flag;
9981 {
9982 if (raise_flag)
9983 x_raise_frame (f);
9984 else
9985 x_lower_frame (f);
9986 }
9987 \f
9988 /* Change of visibility. */
9989
9990 /* This tries to wait until the frame is really visible.
9991 However, if the window manager asks the user where to position
9992 the frame, this will return before the user finishes doing that.
9993 The frame will not actually be visible at that time,
9994 but it will become visible later when the window manager
9995 finishes with it. */
9996
9997 void
9998 x_make_frame_visible (f)
9999 struct frame *f;
10000 {
10001 Lisp_Object type;
10002 int original_top, original_left;
10003
10004 BLOCK_INPUT;
10005
10006 if (! FRAME_VISIBLE_P (f))
10007 {
10008 /* We test FRAME_GARBAGED_P here to make sure we don't
10009 call x_set_offset a second time
10010 if we get to x_make_frame_visible a second time
10011 before the window gets really visible. */
10012 if (! FRAME_ICONIFIED_P (f)
10013 && ! f->output_data.mac->asked_for_visible)
10014 x_set_offset (f, f->output_data.mac->left_pos,
10015 f->output_data.mac->top_pos, 0);
10016
10017 f->output_data.mac->asked_for_visible = 1;
10018
10019 ShowWindow (FRAME_MAC_WINDOW (f));
10020 }
10021
10022 XFlush (FRAME_MAC_DISPLAY (f));
10023
10024 #if 0 /* MAC_TODO */
10025 /* Synchronize to ensure Emacs knows the frame is visible
10026 before we do anything else. We do this loop with input not blocked
10027 so that incoming events are handled. */
10028 {
10029 Lisp_Object frame;
10030 int count;
10031
10032 /* This must come after we set COUNT. */
10033 UNBLOCK_INPUT;
10034
10035 XSETFRAME (frame, f);
10036
10037 /* Wait until the frame is visible. Process X events until a
10038 MapNotify event has been seen, or until we think we won't get a
10039 MapNotify at all.. */
10040 for (count = input_signal_count + 10;
10041 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10042 {
10043 /* Force processing of queued events. */
10044 x_sync (f);
10045
10046 /* Machines that do polling rather than SIGIO have been
10047 observed to go into a busy-wait here. So we'll fake an
10048 alarm signal to let the handler know that there's something
10049 to be read. We used to raise a real alarm, but it seems
10050 that the handler isn't always enabled here. This is
10051 probably a bug. */
10052 if (input_polling_used ())
10053 {
10054 /* It could be confusing if a real alarm arrives while
10055 processing the fake one. Turn it off and let the
10056 handler reset it. */
10057 extern void poll_for_input_1 P_ ((void));
10058 int old_poll_suppress_count = poll_suppress_count;
10059 poll_suppress_count = 1;
10060 poll_for_input_1 ();
10061 poll_suppress_count = old_poll_suppress_count;
10062 }
10063
10064 /* See if a MapNotify event has been processed. */
10065 FRAME_SAMPLE_VISIBILITY (f);
10066 }
10067 }
10068 #endif /* MAC_TODO */
10069 }
10070
10071 /* Change from mapped state to withdrawn state. */
10072
10073 /* Make the frame visible (mapped and not iconified). */
10074
10075 void
10076 x_make_frame_invisible (f)
10077 struct frame *f;
10078 {
10079 /* Don't keep the highlight on an invisible frame. */
10080 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10081 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10082
10083 BLOCK_INPUT;
10084
10085 HideWindow (FRAME_MAC_WINDOW (f));
10086
10087 /* We can't distinguish this from iconification
10088 just by the event that we get from the server.
10089 So we can't win using the usual strategy of letting
10090 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10091 and synchronize with the server to make sure we agree. */
10092 f->visible = 0;
10093 FRAME_ICONIFIED_P (f) = 0;
10094 f->async_visible = 0;
10095 f->async_iconified = 0;
10096
10097 UNBLOCK_INPUT;
10098 }
10099
10100 /* Change window state from mapped to iconified. */
10101
10102 void
10103 x_iconify_frame (f)
10104 struct frame *f;
10105 {
10106 /* Don't keep the highlight on an invisible frame. */
10107 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10108 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10109
10110 #if 0
10111 /* Review: Since window is still visible in dock, still allow updates? */
10112 if (f->async_iconified)
10113 return;
10114 #endif
10115
10116 BLOCK_INPUT;
10117
10118 CollapseWindow (FRAME_MAC_WINDOW (f), true);
10119
10120 UNBLOCK_INPUT;
10121 }
10122
10123 \f
10124 /* Destroy the X window of frame F. */
10125
10126 void
10127 x_destroy_window (f)
10128 struct frame *f;
10129 {
10130 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10131
10132 BLOCK_INPUT;
10133
10134 DisposeWindow (FRAME_MAC_WINDOW (f));
10135
10136 free_frame_menubar (f);
10137 free_frame_faces (f);
10138
10139 xfree (f->output_data.mac);
10140 f->output_data.mac = 0;
10141 if (f == dpyinfo->x_focus_frame)
10142 dpyinfo->x_focus_frame = 0;
10143 if (f == dpyinfo->x_focus_event_frame)
10144 dpyinfo->x_focus_event_frame = 0;
10145 if (f == dpyinfo->x_highlight_frame)
10146 dpyinfo->x_highlight_frame = 0;
10147
10148 dpyinfo->reference_count--;
10149
10150 if (f == dpyinfo->mouse_face_mouse_frame)
10151 {
10152 dpyinfo->mouse_face_beg_row
10153 = dpyinfo->mouse_face_beg_col = -1;
10154 dpyinfo->mouse_face_end_row
10155 = dpyinfo->mouse_face_end_col = -1;
10156 dpyinfo->mouse_face_window = Qnil;
10157 dpyinfo->mouse_face_deferred_gc = 0;
10158 dpyinfo->mouse_face_mouse_frame = 0;
10159 }
10160
10161 UNBLOCK_INPUT;
10162 }
10163 \f
10164 /* Setting window manager hints. */
10165
10166 /* Set the normal size hints for the window manager, for frame F.
10167 FLAGS is the flags word to use--or 0 meaning preserve the flags
10168 that the window now has.
10169 If USER_POSITION is nonzero, we set the USPosition
10170 flag (this is useful when FLAGS is 0). */
10171 void
10172 x_wm_set_size_hint (f, flags, user_position)
10173 struct frame *f;
10174 long flags;
10175 int user_position;
10176 {
10177 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
10178 XSizeHints size_hints;
10179
10180 #ifdef USE_X_TOOLKIT
10181 Arg al[2];
10182 int ac = 0;
10183 Dimension widget_width, widget_height;
10184 Window window = XtWindow (f->output_data.x->widget);
10185 #else /* not USE_X_TOOLKIT */
10186 Window window = FRAME_X_WINDOW (f);
10187 #endif /* not USE_X_TOOLKIT */
10188
10189 /* Setting PMaxSize caused various problems. */
10190 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10191
10192 size_hints.x = f->output_data.x->left_pos;
10193 size_hints.y = f->output_data.x->top_pos;
10194
10195 #ifdef USE_X_TOOLKIT
10196 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10197 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10198 XtGetValues (f->output_data.x->widget, al, ac);
10199 size_hints.height = widget_height;
10200 size_hints.width = widget_width;
10201 #else /* not USE_X_TOOLKIT */
10202 size_hints.height = PIXEL_HEIGHT (f);
10203 size_hints.width = PIXEL_WIDTH (f);
10204 #endif /* not USE_X_TOOLKIT */
10205
10206 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10207 size_hints.height_inc = f->output_data.x->line_height;
10208 size_hints.max_width
10209 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10210 size_hints.max_height
10211 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10212
10213 /* Calculate the base and minimum sizes.
10214
10215 (When we use the X toolkit, we don't do it here.
10216 Instead we copy the values that the widgets are using, below.) */
10217 #ifndef USE_X_TOOLKIT
10218 {
10219 int base_width, base_height;
10220 int min_rows = 0, min_cols = 0;
10221
10222 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10223 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10224
10225 check_frame_size (f, &min_rows, &min_cols);
10226
10227 /* The window manager uses the base width hints to calculate the
10228 current number of rows and columns in the frame while
10229 resizing; min_width and min_height aren't useful for this
10230 purpose, since they might not give the dimensions for a
10231 zero-row, zero-column frame.
10232
10233 We use the base_width and base_height members if we have
10234 them; otherwise, we set the min_width and min_height members
10235 to the size for a zero x zero frame. */
10236
10237 #ifdef HAVE_X11R4
10238 size_hints.flags |= PBaseSize;
10239 size_hints.base_width = base_width;
10240 size_hints.base_height = base_height;
10241 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10242 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10243 #else
10244 size_hints.min_width = base_width;
10245 size_hints.min_height = base_height;
10246 #endif
10247 }
10248
10249 /* If we don't need the old flags, we don't need the old hint at all. */
10250 if (flags)
10251 {
10252 size_hints.flags |= flags;
10253 goto no_read;
10254 }
10255 #endif /* not USE_X_TOOLKIT */
10256
10257 {
10258 XSizeHints hints; /* Sometimes I hate X Windows... */
10259 long supplied_return;
10260 int value;
10261
10262 #ifdef HAVE_X11R4
10263 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10264 &supplied_return);
10265 #else
10266 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10267 #endif
10268
10269 #ifdef USE_X_TOOLKIT
10270 size_hints.base_height = hints.base_height;
10271 size_hints.base_width = hints.base_width;
10272 size_hints.min_height = hints.min_height;
10273 size_hints.min_width = hints.min_width;
10274 #endif
10275
10276 if (flags)
10277 size_hints.flags |= flags;
10278 else
10279 {
10280 if (value == 0)
10281 hints.flags = 0;
10282 if (hints.flags & PSize)
10283 size_hints.flags |= PSize;
10284 if (hints.flags & PPosition)
10285 size_hints.flags |= PPosition;
10286 if (hints.flags & USPosition)
10287 size_hints.flags |= USPosition;
10288 if (hints.flags & USSize)
10289 size_hints.flags |= USSize;
10290 }
10291 }
10292
10293 #ifndef USE_X_TOOLKIT
10294 no_read:
10295 #endif
10296
10297 #ifdef PWinGravity
10298 size_hints.win_gravity = f->output_data.x->win_gravity;
10299 size_hints.flags |= PWinGravity;
10300
10301 if (user_position)
10302 {
10303 size_hints.flags &= ~ PPosition;
10304 size_hints.flags |= USPosition;
10305 }
10306 #endif /* PWinGravity */
10307
10308 #ifdef HAVE_X11R4
10309 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10310 #else
10311 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10312 #endif
10313 #endif /* MAC_TODO */
10314 }
10315
10316 #if 0 /* MAC_TODO: hide application instead of iconify? */
10317 /* Used for IconicState or NormalState */
10318
10319 void
10320 x_wm_set_window_state (f, state)
10321 struct frame *f;
10322 int state;
10323 {
10324 #ifdef USE_X_TOOLKIT
10325 Arg al[1];
10326
10327 XtSetArg (al[0], XtNinitialState, state);
10328 XtSetValues (f->output_data.x->widget, al, 1);
10329 #else /* not USE_X_TOOLKIT */
10330 Window window = FRAME_X_WINDOW (f);
10331
10332 f->output_data.x->wm_hints.flags |= StateHint;
10333 f->output_data.x->wm_hints.initial_state = state;
10334
10335 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10336 #endif /* not USE_X_TOOLKIT */
10337 }
10338
10339 void
10340 x_wm_set_icon_pixmap (f, pixmap_id)
10341 struct frame *f;
10342 int pixmap_id;
10343 {
10344 Pixmap icon_pixmap;
10345
10346 #ifndef USE_X_TOOLKIT
10347 Window window = FRAME_X_WINDOW (f);
10348 #endif
10349
10350 if (pixmap_id > 0)
10351 {
10352 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10353 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10354 }
10355 else
10356 {
10357 /* It seems there is no way to turn off use of an icon pixmap.
10358 The following line does it, only if no icon has yet been created,
10359 for some window managers. But with mwm it crashes.
10360 Some people say it should clear the IconPixmapHint bit in this case,
10361 but that doesn't work, and the X consortium said it isn't the
10362 right thing at all. Since there is no way to win,
10363 best to explicitly give up. */
10364 #if 0
10365 f->output_data.x->wm_hints.icon_pixmap = None;
10366 #else
10367 return;
10368 #endif
10369 }
10370
10371 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10372
10373 {
10374 Arg al[1];
10375 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10376 XtSetValues (f->output_data.x->widget, al, 1);
10377 }
10378
10379 #else /* not USE_X_TOOLKIT */
10380
10381 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10382 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10383
10384 #endif /* not USE_X_TOOLKIT */
10385 }
10386
10387 #endif /* MAC_TODO */
10388
10389 void
10390 x_wm_set_icon_position (f, icon_x, icon_y)
10391 struct frame *f;
10392 int icon_x, icon_y;
10393 {
10394 #if 0 /* MAC_TODO: no icons on Mac */
10395 #ifdef USE_X_TOOLKIT
10396 Window window = XtWindow (f->output_data.x->widget);
10397 #else
10398 Window window = FRAME_X_WINDOW (f);
10399 #endif
10400
10401 f->output_data.x->wm_hints.flags |= IconPositionHint;
10402 f->output_data.x->wm_hints.icon_x = icon_x;
10403 f->output_data.x->wm_hints.icon_y = icon_y;
10404
10405 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10406 #endif /* MAC_TODO */
10407 }
10408
10409 \f
10410 /***********************************************************************
10411 Fonts
10412 ***********************************************************************/
10413
10414 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10415
10416 struct font_info *
10417 x_get_font_info (f, font_idx)
10418 FRAME_PTR f;
10419 int font_idx;
10420 {
10421 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10422 }
10423
10424 /* the global font name table */
10425 char **font_name_table = NULL;
10426 int font_name_table_size = 0;
10427 int font_name_count = 0;
10428
10429 /* compare two strings ignoring case */
10430 static int
10431 stricmp (const char *s, const char *t)
10432 {
10433 for ( ; tolower (*s) == tolower (*t); s++, t++)
10434 if (*s == '\0')
10435 return 0;
10436 return tolower (*s) - tolower (*t);
10437 }
10438
10439 /* compare two strings ignoring case and handling wildcard */
10440 static int
10441 wildstrieq (char *s1, char *s2)
10442 {
10443 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10444 return true;
10445
10446 return stricmp (s1, s2) == 0;
10447 }
10448
10449 /* Assume parameter 1 is fully qualified, no wildcards. */
10450 static int
10451 mac_font_pattern_match (fontname, pattern)
10452 char * fontname;
10453 char * pattern;
10454 {
10455 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
10456 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10457 char *ptr;
10458
10459 /* Copy fontname so we can modify it during comparison. */
10460 strcpy (font_name_copy, fontname);
10461
10462 ptr = regex;
10463 *ptr++ = '^';
10464
10465 /* Turn pattern into a regexp and do a regexp match. */
10466 for (; *pattern; pattern++)
10467 {
10468 if (*pattern == '?')
10469 *ptr++ = '.';
10470 else if (*pattern == '*')
10471 {
10472 *ptr++ = '.';
10473 *ptr++ = '*';
10474 }
10475 else
10476 *ptr++ = *pattern;
10477 }
10478 *ptr = '$';
10479 *(ptr + 1) = '\0';
10480
10481 return (fast_c_string_match_ignore_case (build_string (regex),
10482 font_name_copy) >= 0);
10483 }
10484
10485 /* Two font specs are considered to match if their foundry, family,
10486 weight, slant, and charset match. */
10487 static int
10488 mac_font_match (char *mf, char *xf)
10489 {
10490 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10491 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10492
10493 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10494 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10495 return mac_font_pattern_match (mf, xf);
10496
10497 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10498 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10499 return mac_font_pattern_match (mf, xf);
10500
10501 return (wildstrieq (m_foundry, x_foundry)
10502 && wildstrieq (m_family, x_family)
10503 && wildstrieq (m_weight, x_weight)
10504 && wildstrieq (m_slant, x_slant)
10505 && wildstrieq (m_charset, x_charset))
10506 || mac_font_pattern_match (mf, xf);
10507 }
10508
10509
10510 static char *
10511 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10512 {
10513 char foundry[32], family[32], cs[32];
10514 char xf[255], *result, *p;
10515
10516 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10517 {
10518 strcpy(foundry, "Apple");
10519 strcpy(family, name);
10520
10521 switch (scriptcode)
10522 {
10523 case smTradChinese:
10524 strcpy(cs, "big5-0");
10525 break;
10526 case smSimpChinese:
10527 strcpy(cs, "gb2312.1980-0");
10528 break;
10529 case smJapanese:
10530 strcpy(cs, "jisx0208.1983-sjis");
10531 break;
10532 case -smJapanese:
10533 /* Each Apple Japanese font is entered into the font table
10534 twice: once as a jisx0208.1983-sjis font and once as a
10535 jisx0201.1976-0 font. The latter can be used to display
10536 the ascii charset and katakana-jisx0201 charset. A
10537 negative script code signals that the name of this latter
10538 font is being built. */
10539 strcpy(cs, "jisx0201.1976-0");
10540 break;
10541 case smKorean:
10542 strcpy(cs, "ksc5601.1989-0");
10543 break;
10544 default:
10545 strcpy(cs, "mac-roman");
10546 break;
10547 }
10548 }
10549
10550 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10551 foundry, family, style & bold ? "bold" : "medium",
10552 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10553
10554 result = (char *) xmalloc (strlen (xf) + 1);
10555 strcpy (result, xf);
10556 for (p = result; *p; p++)
10557 *p = tolower(*p);
10558 return result;
10559 }
10560
10561
10562 /* Convert an X font spec to the corresponding mac font name, which
10563 can then be passed to GetFNum after conversion to a Pascal string.
10564 For ordinary Mac fonts, this should just be their names, like
10565 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10566 collection contain their charset designation in their names, like
10567 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10568 names are handled accordingly. */
10569 static void
10570 x_font_name_to_mac_font_name (char *xf, char *mf)
10571 {
10572 char foundry[32], family[32], weight[20], slant[2], cs[32];
10573
10574 strcpy (mf, "");
10575
10576 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10577 foundry, family, weight, slant, cs) != 5 &&
10578 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10579 foundry, family, weight, slant, cs) != 5)
10580 return;
10581
10582 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
10583 || strcmp (cs, "jisx0208.1983-sjis") == 0
10584 || strcmp (cs, "jisx0201.1976-0") == 0
10585 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
10586 strcpy(mf, family);
10587 else
10588 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10589 }
10590
10591
10592 static void
10593 add_font_name_table_entry (char *font_name)
10594 {
10595 if (font_name_table_size == 0)
10596 {
10597 font_name_table_size = 16;
10598 font_name_table = (char **)
10599 xmalloc (font_name_table_size * sizeof (char *));
10600 }
10601 else if (font_name_count + 1 >= font_name_table_size)
10602 {
10603 font_name_table_size += 16;
10604 font_name_table = (char **)
10605 xrealloc (font_name_table,
10606 font_name_table_size * sizeof (char *));
10607 }
10608
10609 font_name_table[font_name_count++] = font_name;
10610 }
10611
10612 /* Sets up the table font_name_table to contain the list of all fonts
10613 in the system the first time the table is used so that the Resource
10614 Manager need not be accessed every time this information is
10615 needed. */
10616
10617 static void
10618 init_font_name_table ()
10619 {
10620 #if TARGET_API_MAC_CARBON
10621 SInt32 sv;
10622
10623 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10624 {
10625 FMFontFamilyIterator ffi;
10626 FMFontFamilyInstanceIterator ffii;
10627 FMFontFamily ff;
10628
10629 /* Create a dummy instance iterator here to avoid creating and
10630 destroying it in the loop. */
10631 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10632 return;
10633 /* Create an iterator to enumerate the font families. */
10634 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10635 != noErr)
10636 {
10637 FMDisposeFontFamilyInstanceIterator (&ffii);
10638 return;
10639 }
10640
10641 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10642 {
10643 Str255 name;
10644 FMFont font;
10645 FMFontStyle style;
10646 FMFontSize size;
10647 SInt16 sc;
10648
10649 if (FMGetFontFamilyName (ff, name) != noErr)
10650 break;
10651 p2cstr (name);
10652
10653 sc = FontToScript (ff);
10654
10655 /* Point the instance iterator at the current font family. */
10656 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10657 break;
10658
10659 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10660 == noErr)
10661 if (size == 0)
10662 {
10663 add_font_name_table_entry (mac_to_x_fontname (name, size,
10664 style, sc));
10665 add_font_name_table_entry (mac_to_x_fontname (name, size,
10666 italic, sc));
10667 add_font_name_table_entry (mac_to_x_fontname (name, size,
10668 bold, sc));
10669 add_font_name_table_entry (mac_to_x_fontname (name, size,
10670 italic | bold,
10671 sc));
10672 }
10673 else
10674 {
10675 add_font_name_table_entry (mac_to_x_fontname (name, size,
10676 style, sc));
10677 if (smJapanese == sc)
10678 add_font_name_table_entry (mac_to_x_fontname (name, size,
10679 style,
10680 -smJapanese));
10681 }
10682 }
10683
10684 /* Dispose of the iterators. */
10685 FMDisposeFontFamilyIterator (&ffi);
10686 FMDisposeFontFamilyInstanceIterator (&ffii);
10687 }
10688 else
10689 {
10690 #endif /* TARGET_API_MAC_CARBON */
10691 GrafPtr port;
10692 SInt16 fontnum, old_fontnum;
10693 int num_mac_fonts = CountResources('FOND');
10694 int i, j;
10695 Handle font_handle, font_handle_2;
10696 short id, scriptcode;
10697 ResType type;
10698 Str32 name;
10699 struct FontAssoc *fat;
10700 struct AsscEntry *assc_entry;
10701
10702 GetPort (&port); /* save the current font number used */
10703 #if TARGET_API_MAC_CARBON
10704 old_fontnum = GetPortTextFont (port);
10705 #else
10706 old_fontnum = port->txFont;
10707 #endif
10708
10709 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10710 {
10711 font_handle = GetIndResource ('FOND', i);
10712 if (!font_handle)
10713 continue;
10714
10715 GetResInfo (font_handle, &id, &type, name);
10716 GetFNum (name, &fontnum);
10717 p2cstr (name);
10718 if (fontnum == 0)
10719 continue;
10720
10721 TextFont (fontnum);
10722 scriptcode = FontToScript (fontnum);
10723 do
10724 {
10725 HLock (font_handle);
10726
10727 if (GetResourceSizeOnDisk (font_handle)
10728 >= sizeof (struct FamRec))
10729 {
10730 fat = (struct FontAssoc *) (*font_handle
10731 + sizeof (struct FamRec));
10732 assc_entry
10733 = (struct AsscEntry *) (*font_handle
10734 + sizeof (struct FamRec)
10735 + sizeof (struct FontAssoc));
10736
10737 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
10738 {
10739 if (font_name_table_size == 0)
10740 {
10741 font_name_table_size = 16;
10742 font_name_table = (char **)
10743 xmalloc (font_name_table_size * sizeof (char *));
10744 }
10745 else if (font_name_count >= font_name_table_size)
10746 {
10747 font_name_table_size += 16;
10748 font_name_table = (char **)
10749 xrealloc (font_name_table,
10750 font_name_table_size * sizeof (char *));
10751 }
10752 font_name_table[font_name_count++]
10753 = mac_to_x_fontname (name,
10754 assc_entry->fontSize,
10755 assc_entry->fontStyle,
10756 scriptcode);
10757 /* Both jisx0208.1983-sjis and
10758 jisx0201.1976-sjis parts are contained in
10759 Apple Japanese (SJIS) font. */
10760 if (smJapanese == scriptcode)
10761 {
10762 font_name_table[font_name_count++]
10763 = mac_to_x_fontname (name,
10764 assc_entry->fontSize,
10765 assc_entry->fontStyle,
10766 -smJapanese);
10767 }
10768 }
10769 }
10770
10771 HUnlock (font_handle);
10772 font_handle_2 = GetNextFOND (font_handle);
10773 ReleaseResource (font_handle);
10774 font_handle = font_handle_2;
10775 }
10776 while (ResError () == noErr && font_handle);
10777 }
10778
10779 TextFont (old_fontnum);
10780 #if TARGET_API_MAC_CARBON
10781 }
10782 #endif /* TARGET_API_MAC_CARBON */
10783 }
10784
10785
10786 /* Return a list of at most MAXNAMES font specs matching the one in
10787 PATTERN. Cache matching fonts for patterns in
10788 dpyinfo->name_list_element to avoid looking them up again by
10789 calling mac_font_pattern_match (slow). */
10790
10791 Lisp_Object
10792 x_list_fonts (struct frame *f,
10793 Lisp_Object pattern,
10794 int size,
10795 int maxnames)
10796 {
10797 char *ptnstr;
10798 Lisp_Object newlist = Qnil, tem, key;
10799 int n_fonts = 0;
10800 int i;
10801 struct gcpro gcpro1, gcpro2;
10802 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
10803
10804 if (font_name_table == NULL) /* Initialize when first used. */
10805 init_font_name_table ();
10806
10807 if (dpyinfo)
10808 {
10809 tem = XCDR (dpyinfo->name_list_element);
10810 key = Fcons (pattern, make_number (maxnames));
10811
10812 newlist = Fassoc (key, tem);
10813 if (!NILP (newlist))
10814 {
10815 newlist = Fcdr_safe (newlist);
10816 goto label_cached;
10817 }
10818 }
10819
10820 ptnstr = SDATA (pattern);
10821
10822 GCPRO2 (pattern, newlist);
10823
10824 /* Scan and matching bitmap fonts. */
10825 for (i = 0; i < font_name_count; i++)
10826 {
10827 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10828 {
10829 newlist = Fcons (build_string (font_name_table[i]), newlist);
10830
10831 n_fonts++;
10832 if (n_fonts >= maxnames)
10833 break;
10834 }
10835 }
10836
10837 /* MAC_TODO: add code for matching outline fonts here */
10838
10839 UNGCPRO;
10840
10841 if (dpyinfo)
10842 {
10843 XSETCDR (dpyinfo->name_list_element,
10844 Fcons (Fcons (key, newlist),
10845 XCDR (dpyinfo->name_list_element)));
10846 }
10847 label_cached:
10848
10849 return newlist;
10850 }
10851
10852
10853 #if GLYPH_DEBUG
10854
10855 /* Check that FONT is valid on frame F. It is if it can be found in F's
10856 font table. */
10857
10858 static void
10859 x_check_font (f, font)
10860 struct frame *f;
10861 XFontStruct *font;
10862 {
10863 int i;
10864 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10865
10866 xassert (font != NULL);
10867
10868 for (i = 0; i < dpyinfo->n_fonts; i++)
10869 if (dpyinfo->font_table[i].name
10870 && font == dpyinfo->font_table[i].font)
10871 break;
10872
10873 xassert (i < dpyinfo->n_fonts);
10874 }
10875
10876 #endif /* GLYPH_DEBUG != 0 */
10877
10878 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10879 Note: There are (broken) X fonts out there with invalid XFontStruct
10880 min_bounds contents. For example, handa@etl.go.jp reports that
10881 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10882 have font->min_bounds.width == 0. */
10883
10884 static INLINE void
10885 x_font_min_bounds (font, w, h)
10886 MacFontStruct *font;
10887 int *w, *h;
10888 {
10889 /*
10890 * TODO: Windows does not appear to offer min bound, only
10891 * average and maximum width, and maximum height.
10892 */
10893 *h = FONT_HEIGHT (font);
10894 *w = FONT_WIDTH (font);
10895 }
10896
10897
10898 /* Compute the smallest character width and smallest font height over
10899 all fonts available on frame F. Set the members smallest_char_width
10900 and smallest_font_height in F's x_display_info structure to
10901 the values computed. Value is non-zero if smallest_font_height or
10902 smallest_char_width become smaller than they were before. */
10903
10904 int
10905 x_compute_min_glyph_bounds (f)
10906 struct frame *f;
10907 {
10908 int i;
10909 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10910 MacFontStruct *font;
10911 int old_width = dpyinfo->smallest_char_width;
10912 int old_height = dpyinfo->smallest_font_height;
10913
10914 dpyinfo->smallest_font_height = 100000;
10915 dpyinfo->smallest_char_width = 100000;
10916
10917 for (i = 0; i < dpyinfo->n_fonts; ++i)
10918 if (dpyinfo->font_table[i].name)
10919 {
10920 struct font_info *fontp = dpyinfo->font_table + i;
10921 int w, h;
10922
10923 font = (MacFontStruct *) fontp->font;
10924 xassert (font != (MacFontStruct *) ~0);
10925 x_font_min_bounds (font, &w, &h);
10926
10927 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10928 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10929 }
10930
10931 xassert (dpyinfo->smallest_char_width > 0
10932 && dpyinfo->smallest_font_height > 0);
10933
10934 return (dpyinfo->n_fonts == 1
10935 || dpyinfo->smallest_char_width < old_width
10936 || dpyinfo->smallest_font_height < old_height);
10937 }
10938
10939
10940 /* Determine whether given string is a fully-specified XLFD: all 14
10941 fields are present, none is '*'. */
10942
10943 static int
10944 is_fully_specified_xlfd (char *p)
10945 {
10946 int i;
10947 char *q;
10948
10949 if (*p != '-')
10950 return 0;
10951
10952 for (i = 0; i < 13; i++)
10953 {
10954 q = strchr (p + 1, '-');
10955 if (q == NULL)
10956 return 0;
10957 if (q - p == 2 && *(p + 1) == '*')
10958 return 0;
10959 p = q;
10960 }
10961
10962 if (strchr (p + 1, '-') != NULL)
10963 return 0;
10964
10965 if (*(p + 1) == '*' && *(p + 2) == '\0')
10966 return 0;
10967
10968 return 1;
10969 }
10970
10971
10972 const int kDefaultFontSize = 9;
10973
10974
10975 /* XLoadQueryFont creates and returns an internal representation for a
10976 font in a MacFontStruct struct. There is really no concept
10977 corresponding to "loading" a font on the Mac. But we check its
10978 existence and find the font number and all other information for it
10979 and store them in the returned MacFontStruct. */
10980
10981 static MacFontStruct *
10982 XLoadQueryFont (Display *dpy, char *fontname)
10983 {
10984 int i, size, is_two_byte_font, char_width;
10985 char *name;
10986 GrafPtr port;
10987 SInt16 old_fontnum, old_fontsize;
10988 Style old_fontface;
10989 Str32 mfontname;
10990 SInt16 fontnum;
10991 Style fontface = normal;
10992 MacFontStruct *font;
10993 FontInfo the_fontinfo;
10994 char s_weight[7], c_slant;
10995
10996 if (is_fully_specified_xlfd (fontname))
10997 name = fontname;
10998 else
10999 {
11000 for (i = 0; i < font_name_count; i++)
11001 if (mac_font_pattern_match (font_name_table[i], fontname))
11002 break;
11003
11004 if (i >= font_name_count)
11005 return NULL;
11006
11007 name = font_name_table[i];
11008 }
11009
11010 GetPort (&port); /* save the current font number used */
11011 #if TARGET_API_MAC_CARBON
11012 old_fontnum = GetPortTextFont (port);
11013 old_fontsize = GetPortTextSize (port);
11014 old_fontface = GetPortTextFace (port);
11015 #else
11016 old_fontnum = port->txFont;
11017 old_fontsize = port->txSize;
11018 old_fontface = port->txFace;
11019 #endif
11020
11021 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
11022 size = kDefaultFontSize;
11023
11024 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
11025 if (strcmp (s_weight, "bold") == 0)
11026 fontface |= bold;
11027
11028 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
11029 if (c_slant == 'i')
11030 fontface |= italic;
11031
11032 x_font_name_to_mac_font_name (name, mfontname);
11033 c2pstr (mfontname);
11034 GetFNum (mfontname, &fontnum);
11035 if (fontnum == 0)
11036 return NULL;
11037
11038 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
11039
11040 font->fontname = (char *) xmalloc (strlen (name) + 1);
11041 bcopy (name, font->fontname, strlen (name) + 1);
11042
11043 font->mac_fontnum = fontnum;
11044 font->mac_fontsize = size;
11045 font->mac_fontface = fontface;
11046 font->mac_scriptcode = FontToScript (fontnum);
11047
11048 /* Apple Japanese (SJIS) font is listed as both
11049 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
11050 (Roman script) in init_font_name_table (). The latter should be
11051 treated as a one-byte font. */
11052 {
11053 char cs[32];
11054
11055 if (sscanf (name,
11056 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11057 cs) == 1
11058 && 0 == strcmp (cs, "jisx0201.1976-0"))
11059 font->mac_scriptcode = smRoman;
11060 }
11061
11062 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11063 font->mac_scriptcode == smTradChinese ||
11064 font->mac_scriptcode == smSimpChinese ||
11065 font->mac_scriptcode == smKorean;
11066
11067 TextFont (fontnum);
11068 TextSize (size);
11069 TextFace (fontface);
11070
11071 GetFontInfo (&the_fontinfo);
11072
11073 font->ascent = the_fontinfo.ascent;
11074 font->descent = the_fontinfo.descent;
11075
11076 font->min_byte1 = 0;
11077 if (is_two_byte_font)
11078 font->max_byte1 = 1;
11079 else
11080 font->max_byte1 = 0;
11081 font->min_char_or_byte2 = 0x20;
11082 font->max_char_or_byte2 = 0xff;
11083
11084 if (is_two_byte_font)
11085 {
11086 /* Use the width of an "ideographic space" of that font because
11087 the_fontinfo.widMax returns the wrong width for some fonts. */
11088 switch (font->mac_scriptcode)
11089 {
11090 case smJapanese:
11091 char_width = StringWidth("\p\x81\x40");
11092 break;
11093 case smTradChinese:
11094 char_width = StringWidth("\p\xa1\x40");
11095 break;
11096 case smSimpChinese:
11097 char_width = StringWidth("\p\xa1\xa1");
11098 break;
11099 case smKorean:
11100 char_width = StringWidth("\p\xa1\xa1");
11101 break;
11102 }
11103 }
11104 else
11105 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11106 returns 15 for 12-point Monaco! */
11107 char_width = CharWidth ('m');
11108
11109 font->max_bounds.rbearing = char_width;
11110 font->max_bounds.lbearing = 0;
11111 font->max_bounds.width = char_width;
11112 font->max_bounds.ascent = the_fontinfo.ascent;
11113 font->max_bounds.descent = the_fontinfo.descent;
11114
11115 font->min_bounds = font->max_bounds;
11116
11117 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11118 font->per_char = NULL;
11119 else
11120 {
11121 font->per_char = (XCharStruct *)
11122 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11123 {
11124 int c;
11125
11126 for (c = 0x20; c <= 0xff; c++)
11127 {
11128 font->per_char[c - 0x20] = font->max_bounds;
11129 font->per_char[c - 0x20].width = CharWidth (c);
11130 }
11131 }
11132 }
11133
11134 TextFont (old_fontnum); /* restore previous font number, size and face */
11135 TextSize (old_fontsize);
11136 TextFace (old_fontface);
11137
11138 return font;
11139 }
11140
11141
11142 /* Load font named FONTNAME of the size SIZE for frame F, and return a
11143 pointer to the structure font_info while allocating it dynamically.
11144 If SIZE is 0, load any size of font.
11145 If loading is failed, return NULL. */
11146
11147 struct font_info *
11148 x_load_font (f, fontname, size)
11149 struct frame *f;
11150 register char *fontname;
11151 int size;
11152 {
11153 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11154 Lisp_Object font_names;
11155
11156 /* Get a list of all the fonts that match this name. Once we
11157 have a list of matching fonts, we compare them against the fonts
11158 we already have by comparing names. */
11159 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11160
11161 if (!NILP (font_names))
11162 {
11163 Lisp_Object tail;
11164 int i;
11165
11166 for (i = 0; i < dpyinfo->n_fonts; i++)
11167 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11168 if (dpyinfo->font_table[i].name
11169 && (!strcmp (dpyinfo->font_table[i].name,
11170 SDATA (XCAR (tail)))
11171 || !strcmp (dpyinfo->font_table[i].full_name,
11172 SDATA (XCAR (tail)))))
11173 return (dpyinfo->font_table + i);
11174 }
11175
11176 /* Load the font and add it to the table. */
11177 {
11178 char *full_name;
11179 struct MacFontStruct *font;
11180 struct font_info *fontp;
11181 unsigned long value;
11182 int i;
11183
11184 /* If we have found fonts by x_list_font, load one of them. If
11185 not, we still try to load a font by the name given as FONTNAME
11186 because XListFonts (called in x_list_font) of some X server has
11187 a bug of not finding a font even if the font surely exists and
11188 is loadable by XLoadQueryFont. */
11189 if (size > 0 && !NILP (font_names))
11190 fontname = (char *) SDATA (XCAR (font_names));
11191
11192 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11193 if (!font)
11194 return NULL;
11195
11196 /* Find a free slot in the font table. */
11197 for (i = 0; i < dpyinfo->n_fonts; ++i)
11198 if (dpyinfo->font_table[i].name == NULL)
11199 break;
11200
11201 /* If no free slot found, maybe enlarge the font table. */
11202 if (i == dpyinfo->n_fonts
11203 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11204 {
11205 int sz;
11206 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11207 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11208 dpyinfo->font_table
11209 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11210 }
11211
11212 fontp = dpyinfo->font_table + i;
11213 if (i == dpyinfo->n_fonts)
11214 ++dpyinfo->n_fonts;
11215
11216 /* Now fill in the slots of *FONTP. */
11217 BLOCK_INPUT;
11218 fontp->font = font;
11219 fontp->font_idx = i;
11220 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11221 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11222
11223 fontp->full_name = fontp->name;
11224
11225 fontp->size = font->max_bounds.width;
11226 fontp->height = FONT_HEIGHT (font);
11227 {
11228 /* For some font, ascent and descent in max_bounds field is
11229 larger than the above value. */
11230 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11231 if (max_height > fontp->height)
11232 fontp->height = max_height;
11233 }
11234
11235 /* The slot `encoding' specifies how to map a character
11236 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11237 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11238 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11239 2:0xA020..0xFF7F). For the moment, we don't know which charset
11240 uses this font. So, we set information in fontp->encoding[1]
11241 which is never used by any charset. If mapping can't be
11242 decided, set FONT_ENCODING_NOT_DECIDED. */
11243 if (font->mac_scriptcode == smJapanese)
11244 fontp->encoding[1] = 4;
11245 else
11246 {
11247 fontp->encoding[1]
11248 = (font->max_byte1 == 0
11249 /* 1-byte font */
11250 ? (font->min_char_or_byte2 < 0x80
11251 ? (font->max_char_or_byte2 < 0x80
11252 ? 0 /* 0x20..0x7F */
11253 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11254 : 1) /* 0xA0..0xFF */
11255 /* 2-byte font */
11256 : (font->min_byte1 < 0x80
11257 ? (font->max_byte1 < 0x80
11258 ? (font->min_char_or_byte2 < 0x80
11259 ? (font->max_char_or_byte2 < 0x80
11260 ? 0 /* 0x2020..0x7F7F */
11261 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11262 : 3) /* 0x20A0..0x7FFF */
11263 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11264 : (font->min_char_or_byte2 < 0x80
11265 ? (font->max_char_or_byte2 < 0x80
11266 ? 2 /* 0xA020..0xFF7F */
11267 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11268 : 1))); /* 0xA0A0..0xFFFF */
11269 }
11270
11271 #if 0 /* MAC_TODO: fill these out with more reasonably values */
11272 fontp->baseline_offset
11273 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11274 ? (long) value : 0);
11275 fontp->relative_compose
11276 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11277 ? (long) value : 0);
11278 fontp->default_ascent
11279 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11280 ? (long) value : 0);
11281 #else
11282 fontp->baseline_offset = 0;
11283 fontp->relative_compose = 0;
11284 fontp->default_ascent = 0;
11285 #endif
11286
11287 /* Set global flag fonts_changed_p to non-zero if the font loaded
11288 has a character with a smaller width than any other character
11289 before, or if the font loaded has a smalle>r height than any
11290 other font loaded before. If this happens, it will make a
11291 glyph matrix reallocation necessary. */
11292 fonts_changed_p = x_compute_min_glyph_bounds (f);
11293 UNBLOCK_INPUT;
11294 return fontp;
11295 }
11296 }
11297
11298
11299 /* Return a pointer to struct font_info of a font named FONTNAME for
11300 frame F. If no such font is loaded, return NULL. */
11301
11302 struct font_info *
11303 x_query_font (f, fontname)
11304 struct frame *f;
11305 register char *fontname;
11306 {
11307 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11308 int i;
11309
11310 for (i = 0; i < dpyinfo->n_fonts; i++)
11311 if (dpyinfo->font_table[i].name
11312 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11313 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11314 return (dpyinfo->font_table + i);
11315 return NULL;
11316 }
11317
11318
11319 /* Find a CCL program for a font specified by FONTP, and set the member
11320 `encoder' of the structure. */
11321
11322 void
11323 x_find_ccl_program (fontp)
11324 struct font_info *fontp;
11325 {
11326 Lisp_Object list, elt;
11327
11328 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11329 {
11330 elt = XCAR (list);
11331 if (CONSP (elt)
11332 && STRINGP (XCAR (elt))
11333 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11334 >= 0))
11335 break;
11336 }
11337 if (! NILP (list))
11338 {
11339 struct ccl_program *ccl
11340 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11341
11342 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11343 xfree (ccl);
11344 else
11345 fontp->font_encoder = ccl;
11346 }
11347 }
11348
11349
11350 \f
11351 /***********************************************************************
11352 Initialization
11353 ***********************************************************************/
11354
11355 #ifdef USE_X_TOOLKIT
11356 static XrmOptionDescRec emacs_options[] = {
11357 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11358 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11359
11360 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11361 XrmoptionSepArg, NULL},
11362 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11363
11364 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11365 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11366 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11367 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11368 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11369 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11370 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11371 };
11372 #endif /* USE_X_TOOLKIT */
11373
11374 static int x_initialized;
11375
11376 #ifdef MULTI_KBOARD
11377 /* Test whether two display-name strings agree up to the dot that separates
11378 the screen number from the server number. */
11379 static int
11380 same_x_server (name1, name2)
11381 char *name1, *name2;
11382 {
11383 int seen_colon = 0;
11384 unsigned char *system_name = SDATA (Vsystem_name);
11385 int system_name_length = strlen (system_name);
11386 int length_until_period = 0;
11387
11388 while (system_name[length_until_period] != 0
11389 && system_name[length_until_period] != '.')
11390 length_until_period++;
11391
11392 /* Treat `unix' like an empty host name. */
11393 if (! strncmp (name1, "unix:", 5))
11394 name1 += 4;
11395 if (! strncmp (name2, "unix:", 5))
11396 name2 += 4;
11397 /* Treat this host's name like an empty host name. */
11398 if (! strncmp (name1, system_name, system_name_length)
11399 && name1[system_name_length] == ':')
11400 name1 += system_name_length;
11401 if (! strncmp (name2, system_name, system_name_length)
11402 && name2[system_name_length] == ':')
11403 name2 += system_name_length;
11404 /* Treat this host's domainless name like an empty host name. */
11405 if (! strncmp (name1, system_name, length_until_period)
11406 && name1[length_until_period] == ':')
11407 name1 += length_until_period;
11408 if (! strncmp (name2, system_name, length_until_period)
11409 && name2[length_until_period] == ':')
11410 name2 += length_until_period;
11411
11412 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11413 {
11414 if (*name1 == ':')
11415 seen_colon++;
11416 if (seen_colon && *name1 == '.')
11417 return 1;
11418 }
11419 return (seen_colon
11420 && (*name1 == '.' || *name1 == '\0')
11421 && (*name2 == '.' || *name2 == '\0'));
11422 }
11423 #endif
11424
11425
11426 /* The Mac Event loop code */
11427
11428 #ifndef MAC_OSX
11429 #include <Events.h>
11430 #include <Quickdraw.h>
11431 #include <Balloons.h>
11432 #include <Devices.h>
11433 #include <Fonts.h>
11434 #include <Gestalt.h>
11435 #include <Menus.h>
11436 #include <Processes.h>
11437 #include <Sound.h>
11438 #include <ToolUtils.h>
11439 #include <TextUtils.h>
11440 #include <Dialogs.h>
11441 #include <Script.h>
11442 #include <Types.h>
11443 #include <TextEncodingConverter.h>
11444 #include <Resources.h>
11445
11446 #if __MWERKS__
11447 #include <unix.h>
11448 #endif
11449 #endif /* ! MAC_OSX */
11450
11451 #define M_APPLE 128
11452 #define I_ABOUT 1
11453
11454 #define WINDOW_RESOURCE 128
11455 #define TERM_WINDOW_RESOURCE 129
11456
11457 #define DEFAULT_NUM_COLS 80
11458
11459 #define MIN_DOC_SIZE 64
11460 #define MAX_DOC_SIZE 32767
11461
11462 /* sleep time for WaitNextEvent */
11463 #define WNE_SLEEP_AT_SUSPEND 10
11464 #define WNE_SLEEP_AT_RESUME 1
11465
11466 /* true when cannot handle any Mac OS events */
11467 static int handling_window_update = 0;
11468
11469 /* the flag appl_is_suspended is used both for determining the sleep
11470 time to be passed to WaitNextEvent and whether the cursor should be
11471 drawn when updating the display. The cursor is turned off when
11472 Emacs is suspended. Redrawing it is unnecessary and what needs to
11473 be done depends on whether the cursor lies inside or outside the
11474 redraw region. So we might as well skip drawing it when Emacs is
11475 suspended. */
11476 static Boolean app_is_suspended = false;
11477 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11478
11479 #define EXTRA_STACK_ALLOC (256 * 1024)
11480
11481 #define ARGV_STRING_LIST_ID 129
11482 #define ABOUT_ALERT_ID 128
11483 #define RAM_TOO_LARGE_ALERT_ID 129
11484
11485 Boolean terminate_flag = false;
11486
11487 /* True if using command key as meta key. */
11488 Lisp_Object Vmac_command_key_is_meta;
11489
11490 /* True if the ctrl and meta keys should be reversed. */
11491 Lisp_Object Vmac_reverse_ctrl_meta;
11492
11493 #if USE_CARBON_EVENTS
11494 /* True if the mouse wheel button (i.e. button 4) should map to
11495 mouse-2, instead of mouse-3. */
11496 Lisp_Object Vmac_wheel_button_is_mouse_2;
11497
11498 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
11499 for processing before Emacs sees it. */
11500 Lisp_Object Vmac_pass_command_to_system;
11501
11502 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
11503 for processing before Emacs sees it. */
11504 Lisp_Object Vmac_pass_control_to_system;
11505 #endif
11506
11507 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11508 to this text encoding */
11509 int mac_keyboard_text_encoding;
11510 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11511
11512 /* Set in term/mac-win.el to indicate that event loop can now generate
11513 drag and drop events. */
11514 Lisp_Object Qmac_ready_for_drag_n_drop;
11515
11516 Lisp_Object drag_and_drop_file_list;
11517
11518 Point saved_menu_event_location;
11519
11520 /* Apple Events */
11521 static void init_required_apple_events (void);
11522 static pascal OSErr
11523 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
11524 static pascal OSErr
11525 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
11526 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
11527 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
11528
11529 /* Drag and Drop */
11530 static OSErr init_mac_drag_n_drop ();
11531 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
11532
11533 #if USE_CARBON_EVENTS
11534 /* Preliminary Support for the OSX Services Menu */
11535 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
11536 static void init_service_handler ();
11537 #endif
11538
11539 extern void init_emacs_passwd_dir ();
11540 extern int emacs_main (int, char **, char **);
11541 extern void check_alarm ();
11542
11543 extern void initialize_applescript();
11544 extern void terminate_applescript();
11545
11546 static unsigned int
11547 #if USE_CARBON_EVENTS
11548 mac_to_emacs_modifiers (UInt32 mods)
11549 #else
11550 mac_to_emacs_modifiers (EventModifiers mods)
11551 #endif
11552 {
11553 unsigned int result = 0;
11554 if (mods & macShiftKey)
11555 result |= shift_modifier;
11556 if (mods & macCtrlKey)
11557 result |= ctrl_modifier;
11558 if (mods & macMetaKey)
11559 result |= meta_modifier;
11560 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
11561 result |= alt_modifier;
11562 return result;
11563 }
11564
11565 #if USE_CARBON_EVENTS
11566 /* Obtains the event modifiers from the event ref and then calls
11567 mac_to_emacs_modifiers. */
11568 static int
11569 mac_event_to_emacs_modifiers (EventRef eventRef)
11570 {
11571 UInt32 mods = 0;
11572 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
11573 sizeof (UInt32), NULL, &mods);
11574 return mac_to_emacs_modifiers (mods);
11575 }
11576
11577 /* Given an event ref, return the code to use for the mouse button
11578 code in the emacs input_event. */
11579 static int
11580 mac_get_mouse_btn (EventRef ref)
11581 {
11582 EventMouseButton result = kEventMouseButtonPrimary;
11583 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
11584 sizeof (EventMouseButton), NULL, &result);
11585 switch (result)
11586 {
11587 case kEventMouseButtonPrimary:
11588 return 0;
11589 case kEventMouseButtonSecondary:
11590 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
11591 case kEventMouseButtonTertiary:
11592 case 4: /* 4 is the number for the mouse wheel button */
11593 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
11594 default:
11595 return 0;
11596 }
11597 }
11598
11599 /* Normally, ConvertEventRefToEventRecord will correctly handle all
11600 events. However the click of the mouse wheel is not converted to a
11601 mouseDown or mouseUp event. This calls ConvertEventRef, but then
11602 checks to see if it is a mouse up or down carbon event that has not
11603 been converted, and if so, converts it by hand (to be picked up in
11604 the XTread_socket loop). */
11605 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
11606 {
11607 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
11608 /* Do special case for mouse wheel button. */
11609 if (!result && GetEventClass (eventRef) == kEventClassMouse)
11610 {
11611 UInt32 kind = GetEventKind (eventRef);
11612 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
11613 {
11614 eventRec->what = mouseDown;
11615 result=1;
11616 }
11617 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
11618 {
11619 eventRec->what = mouseUp;
11620 result=1;
11621 }
11622 if (result)
11623 {
11624 /* Need where and when. */
11625 UInt32 mods;
11626 GetEventParameter (eventRef, kEventParamMouseLocation,
11627 typeQDPoint, NULL, sizeof (Point),
11628 NULL, &eventRec->where);
11629 /* Use two step process because new event modifiers are
11630 32-bit and old are 16-bit. Currently, only loss is
11631 NumLock & Fn. */
11632 GetEventParameter (eventRef, kEventParamKeyModifiers,
11633 typeUInt32, NULL, sizeof (UInt32),
11634 NULL, &mods);
11635 eventRec->modifiers = mods;
11636
11637 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
11638 }
11639 }
11640 return result;
11641 }
11642
11643 #endif
11644
11645 static void
11646 do_get_menus (void)
11647 {
11648 Handle menubar_handle;
11649 MenuHandle menu_handle;
11650
11651 menubar_handle = GetNewMBar (128);
11652 if(menubar_handle == NULL)
11653 abort ();
11654 SetMenuBar (menubar_handle);
11655 DrawMenuBar ();
11656
11657 menu_handle = GetMenuHandle (M_APPLE);
11658 if(menu_handle != NULL)
11659 AppendResMenu (menu_handle,'DRVR');
11660 else
11661 abort ();
11662 }
11663
11664
11665 static void
11666 do_init_managers (void)
11667 {
11668 #if !TARGET_API_MAC_CARBON
11669 InitGraf (&qd.thePort);
11670 InitFonts ();
11671 FlushEvents (everyEvent, 0);
11672 InitWindows ();
11673 InitMenus ();
11674 TEInit ();
11675 InitDialogs (NULL);
11676 #endif /* !TARGET_API_MAC_CARBON */
11677 InitCursor ();
11678
11679 #if !TARGET_API_MAC_CARBON
11680 /* set up some extra stack space for use by emacs */
11681 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11682
11683 /* MaxApplZone must be called for AppleScript to execute more
11684 complicated scripts */
11685 MaxApplZone ();
11686 MoreMasters ();
11687 #endif /* !TARGET_API_MAC_CARBON */
11688 }
11689
11690 static void
11691 do_check_ram_size (void)
11692 {
11693 SInt32 physical_ram_size, logical_ram_size;
11694
11695 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11696 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11697 || physical_ram_size > 256 * 1024 * 1024
11698 || logical_ram_size > 256 * 1024 * 1024)
11699 {
11700 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11701 exit (1);
11702 }
11703 }
11704
11705 static void
11706 do_window_update (WindowPtr win)
11707 {
11708 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11709 struct frame *f = mwp->mFP;
11710
11711 if (f)
11712 {
11713 if (f->async_visible == 0)
11714 {
11715 f->async_visible = 1;
11716 f->async_iconified = 0;
11717 SET_FRAME_GARBAGED (f);
11718
11719 /* An update event is equivalent to MapNotify on X, so report
11720 visibility changes properly. */
11721 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11722 /* Force a redisplay sooner or later to update the
11723 frame titles in case this is the second frame. */
11724 record_asynch_buffer_change ();
11725 }
11726 else
11727 {
11728 BeginUpdate (win);
11729 handling_window_update = 1;
11730
11731 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
11732
11733 expose_frame (f, 0, 0, 0, 0);
11734
11735 handling_window_update = 0;
11736 EndUpdate (win);
11737 }
11738 }
11739 }
11740
11741 static int
11742 is_emacs_window (WindowPtr win)
11743 {
11744 Lisp_Object tail, frame;
11745
11746 if (!win)
11747 return 0;
11748
11749 FOR_EACH_FRAME (tail, frame)
11750 if (FRAME_MAC_P (XFRAME (frame)))
11751 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11752 return 1;
11753
11754 return 0;
11755 }
11756
11757 static void
11758 do_window_activate (WindowPtr win)
11759 {
11760 mac_output *mwp;
11761 struct frame *f;
11762
11763 if (is_emacs_window (win))
11764 {
11765 mwp = (mac_output *) GetWRefCon (win);
11766 f = mwp->mFP;
11767
11768 if (f)
11769 {
11770 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11771 activate_scroll_bars (f);
11772 }
11773 }
11774 }
11775
11776 static void
11777 do_window_deactivate (WindowPtr win)
11778 {
11779 mac_output *mwp;
11780 struct frame *f;
11781
11782 if (is_emacs_window (win))
11783 {
11784 mwp = (mac_output *) GetWRefCon (win);
11785 f = mwp->mFP;
11786
11787 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11788 {
11789 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11790 deactivate_scroll_bars (f);
11791 }
11792 }
11793 }
11794
11795 static void
11796 do_app_resume ()
11797 {
11798 WindowPtr wp;
11799 mac_output *mwp;
11800 struct frame *f;
11801
11802 wp = FrontWindow();
11803 if (is_emacs_window (wp))
11804 {
11805 mwp = (mac_output *) GetWRefCon (wp);
11806 f = mwp->mFP;
11807
11808 if (f)
11809 {
11810 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11811 activate_scroll_bars (f);
11812 }
11813 }
11814
11815 app_is_suspended = false;
11816 app_sleep_time = WNE_SLEEP_AT_RESUME;
11817 }
11818
11819 static void
11820 do_app_suspend ()
11821 {
11822 WindowPtr wp;
11823 mac_output *mwp;
11824 struct frame *f;
11825
11826 wp = FrontWindow();
11827 if (is_emacs_window (wp))
11828 {
11829 mwp = (mac_output *) GetWRefCon (wp);
11830 f = mwp->mFP;
11831
11832 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11833 {
11834 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11835 deactivate_scroll_bars (f);
11836 }
11837 }
11838
11839 app_is_suspended = true;
11840 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11841 }
11842
11843
11844 static void
11845 do_mouse_moved (Point mouse_pos)
11846 {
11847 WindowPtr wp = FrontWindow ();
11848 struct frame *f;
11849
11850 if (is_emacs_window (wp))
11851 {
11852 f = ((mac_output *) GetWRefCon (wp))->mFP;
11853
11854 #if TARGET_API_MAC_CARBON
11855 SetPort (GetWindowPort (wp));
11856 #else
11857 SetPort (wp);
11858 #endif
11859
11860 GlobalToLocal (&mouse_pos);
11861
11862 note_mouse_movement (f, &mouse_pos);
11863 }
11864 }
11865
11866
11867 static void
11868 do_os_event (EventRecord *erp)
11869 {
11870 switch((erp->message >> 24) & 0x000000FF)
11871 {
11872 case suspendResumeMessage:
11873 if((erp->message & resumeFlag) == 1)
11874 do_app_resume ();
11875 else
11876 do_app_suspend ();
11877 break;
11878
11879 case mouseMovedMessage:
11880 do_mouse_moved (erp->where);
11881 break;
11882 }
11883 }
11884
11885 static void
11886 do_events (EventRecord *erp)
11887 {
11888 switch (erp->what)
11889 {
11890 case updateEvt:
11891 do_window_update ((WindowPtr) erp->message);
11892 break;
11893
11894 case osEvt:
11895 do_os_event (erp);
11896 break;
11897
11898 case activateEvt:
11899 if ((erp->modifiers & activeFlag) != 0)
11900 do_window_activate ((WindowPtr) erp->message);
11901 else
11902 do_window_deactivate ((WindowPtr) erp->message);
11903 break;
11904 }
11905 }
11906
11907 static void
11908 do_apple_menu (SInt16 menu_item)
11909 {
11910 #if !TARGET_API_MAC_CARBON
11911 Str255 item_name;
11912 SInt16 da_driver_refnum;
11913
11914 if (menu_item == I_ABOUT)
11915 NoteAlert (ABOUT_ALERT_ID, NULL);
11916 else
11917 {
11918 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11919 da_driver_refnum = OpenDeskAcc (item_name);
11920 }
11921 #endif /* !TARGET_API_MAC_CARBON */
11922 }
11923
11924 void
11925 do_menu_choice (SInt32 menu_choice)
11926 {
11927 SInt16 menu_id, menu_item;
11928
11929 menu_id = HiWord (menu_choice);
11930 menu_item = LoWord (menu_choice);
11931
11932 if (menu_id == 0)
11933 return;
11934
11935 switch (menu_id)
11936 {
11937 case M_APPLE:
11938 do_apple_menu (menu_item);
11939 break;
11940
11941 default:
11942 {
11943 WindowPtr wp = FrontWindow ();
11944 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11945 MenuHandle menu = GetMenuHandle (menu_id);
11946 if (menu)
11947 {
11948 UInt32 refcon;
11949
11950 GetMenuItemRefCon (menu, menu_item, &refcon);
11951 menubar_selection_callback (f, refcon);
11952 }
11953 }
11954 }
11955
11956 HiliteMenu (0);
11957 }
11958
11959
11960 /* Handle drags in size box. Based on code contributed by Ben
11961 Mesander and IM - Window Manager A. */
11962
11963 static void
11964 do_grow_window (WindowPtr w, EventRecord *e)
11965 {
11966 long grow_size;
11967 Rect limit_rect;
11968 int rows, columns;
11969 mac_output *mwp = (mac_output *) GetWRefCon (w);
11970 struct frame *f = mwp->mFP;
11971
11972 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11973
11974 grow_size = GrowWindow (w, e->where, &limit_rect);
11975
11976 /* see if it really changed size */
11977 if (grow_size != 0)
11978 {
11979 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11980 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11981
11982 x_set_window_size (f, 0, columns, rows);
11983 }
11984 }
11985
11986
11987 /* Handle clicks in zoom box. Calculation of "standard state" based
11988 on code in IM - Window Manager A and code contributed by Ben
11989 Mesander. The standard state of an Emacs window is 80-characters
11990 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11991
11992 static void
11993 do_zoom_window (WindowPtr w, int zoom_in_or_out)
11994 {
11995 GrafPtr save_port;
11996 Rect zoom_rect, port_rect;
11997 Point top_left;
11998 int w_title_height, columns, rows, width, height, dummy, x, y;
11999 mac_output *mwp = (mac_output *) GetWRefCon (w);
12000 struct frame *f = mwp->mFP;
12001
12002 GetPort (&save_port);
12003
12004 #if TARGET_API_MAC_CARBON
12005 SetPort (GetWindowPort (w));
12006 #else
12007 SetPort (w);
12008 #endif
12009
12010 /* Clear window to avoid flicker. */
12011 #if TARGET_API_MAC_CARBON
12012 {
12013 Rect r;
12014 BitMap bm;
12015
12016 GetWindowPortBounds (w, &r);
12017 EraseRect (&r);
12018
12019 if (zoom_in_or_out == inZoomOut)
12020 {
12021 /* calculate height of window's title bar (hard card it for now). */
12022 w_title_height = 20 + GetMBarHeight ();
12023
12024 /* get maximum height of window into zoom_rect.bottom -
12025 zoom_rect.top */
12026 GetQDGlobalsScreenBits (&bm);
12027 zoom_rect = bm.bounds;
12028 zoom_rect.top += w_title_height;
12029 InsetRect (&zoom_rect, 8, 4); /* not too tight */
12030
12031 zoom_rect.right = zoom_rect.left
12032 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12033
12034 SetWindowStandardState (w, &zoom_rect);
12035 }
12036 }
12037 #else /* not TARGET_API_MAC_CARBON */
12038 EraseRect (&(w->portRect));
12039 if (zoom_in_or_out == inZoomOut)
12040 {
12041 SetPt (&top_left, w->portRect.left, w->portRect.top);
12042 LocalToGlobal (&top_left);
12043
12044 /* calculate height of window's title bar */
12045 w_title_height = top_left.v - 1
12046 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
12047
12048 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
12049 zoom_rect = qd.screenBits.bounds;
12050 zoom_rect.top += w_title_height;
12051 InsetRect (&zoom_rect, 8, 4); /* not too tight */
12052
12053 zoom_rect.right = zoom_rect.left
12054 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12055
12056 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
12057 = zoom_rect;
12058 }
12059 #endif /* not TARGET_API_MAC_CARBON */
12060
12061 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
12062
12063 /* retrieve window size and update application values */
12064 #if TARGET_API_MAC_CARBON
12065 GetWindowPortBounds (w, &port_rect);
12066 #else
12067 port_rect = w->portRect;
12068 #endif
12069 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
12070 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
12071 x_set_window_size (mwp->mFP, 0, columns, rows);
12072
12073 SetPort (save_port);
12074 }
12075
12076 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
12077 static OSErr
12078 init_mac_drag_n_drop ()
12079 {
12080 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
12081 return result;
12082 }
12083
12084 /* Intialize AppleEvent dispatcher table for the required events. */
12085 void
12086 init_required_apple_events ()
12087 {
12088 OSErr err;
12089 long result;
12090
12091 /* Make sure we have apple events before starting. */
12092 err = Gestalt (gestaltAppleEventsAttr, &result);
12093 if (err != noErr)
12094 abort ();
12095
12096 if (!(result & (1 << gestaltAppleEventsPresent)))
12097 abort ();
12098
12099 #if TARGET_API_MAC_CARBON
12100 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12101 NewAEEventHandlerUPP
12102 ((AEEventHandlerProcPtr) do_ae_open_application),
12103 0L, false);
12104 #else
12105 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12106 NewAEEventHandlerProc
12107 ((AEEventHandlerProcPtr) do_ae_open_application),
12108 0L, false);
12109 #endif
12110 if (err != noErr)
12111 abort ();
12112
12113 #if TARGET_API_MAC_CARBON
12114 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12115 NewAEEventHandlerUPP
12116 ((AEEventHandlerProcPtr) do_ae_open_documents),
12117 0L, false);
12118 #else
12119 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12120 NewAEEventHandlerProc
12121 ((AEEventHandlerProcPtr) do_ae_open_documents),
12122 0L, false);
12123 #endif
12124 if (err != noErr)
12125 abort ();
12126
12127 #if TARGET_API_MAC_CARBON
12128 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12129 NewAEEventHandlerUPP
12130 ((AEEventHandlerProcPtr) do_ae_print_documents),
12131 0L, false);
12132 #else
12133 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12134 NewAEEventHandlerProc
12135 ((AEEventHandlerProcPtr) do_ae_print_documents),
12136 0L, false);
12137 #endif
12138 if (err != noErr)
12139 abort ();
12140
12141 #if TARGET_API_MAC_CARBON
12142 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12143 NewAEEventHandlerUPP
12144 ((AEEventHandlerProcPtr) do_ae_quit_application),
12145 0L, false);
12146 #else
12147 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12148 NewAEEventHandlerProc
12149 ((AEEventHandlerProcPtr) do_ae_quit_application),
12150 0L, false);
12151 #endif
12152 if (err != noErr)
12153 abort ();
12154 }
12155
12156 #if USE_CARBON_EVENTS
12157
12158 void
12159 init_service_handler ()
12160 {
12161 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
12162 {kEventClassService, kEventServiceCopy},
12163 {kEventClassService, kEventServicePaste}};
12164 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
12165 3, specs, NULL, NULL);
12166 }
12167
12168 /*
12169 MAC_TODO: Check to see if this is called by AEProcessDesc...
12170 */
12171 OSStatus
12172 mac_handle_service_event (EventHandlerCallRef callRef,
12173 EventRef event, void *data)
12174 {
12175 OSStatus err = noErr;
12176 switch (GetEventKind (event))
12177 {
12178 case kEventServiceGetTypes:
12179 {
12180 CFMutableArrayRef copyTypes, pasteTypes;
12181 CFStringRef type;
12182 Boolean selection = true;
12183 /*
12184 GetEventParameter(event, kEventParamServicePasteTypes,
12185 typeCFMutableArrayRef, NULL,
12186 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
12187 */
12188 GetEventParameter(event, kEventParamServiceCopyTypes,
12189 typeCFMutableArrayRef, NULL,
12190 sizeof (CFMutableArrayRef), NULL, &copyTypes);
12191 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
12192 if (type) {
12193 CFArrayAppendValue (copyTypes, type);
12194 //CFArrayAppendValue (pasteTypes, type);
12195 CFRelease (type);
12196 }
12197 }
12198 case kEventServiceCopy:
12199 {
12200 ScrapRef currentScrap, specificScrap;
12201 char * buf = "";
12202 Size byteCount = 0;
12203
12204 GetCurrentScrap (&currentScrap);
12205
12206 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
12207 if (err == noErr)
12208 {
12209 void *buffer = xmalloc (byteCount);
12210 if (buffer != NULL)
12211 {
12212 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
12213 sizeof (ScrapRef), NULL, &specificScrap);
12214
12215 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
12216 &byteCount, buffer);
12217 if (err == noErr)
12218 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
12219 kScrapFlavorMaskNone, byteCount, buffer);
12220 xfree (buffer);
12221 }
12222 }
12223 err = noErr;
12224 }
12225 case kEventServicePaste:
12226 {
12227 /*
12228 // Get the current location
12229 Size byteCount;
12230 ScrapRef specificScrap;
12231 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
12232 sizeof(ScrapRef), NULL, &specificScrap);
12233 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
12234 if (err == noErr) {
12235 void * buffer = xmalloc(byteCount);
12236 if (buffer != NULL ) {
12237 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
12238 &byteCount, buffer);
12239 if (err == noErr) {
12240 // Actually place in the buffer
12241 BLOCK_INPUT;
12242 // Get the current "selection" string here
12243 UNBLOCK_INPUT;
12244 }
12245 }
12246 xfree(buffer);
12247 }
12248 */
12249 }
12250 }
12251 return err;
12252 }
12253 #endif
12254
12255 /* Open Application Apple Event */
12256 static pascal OSErr
12257 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12258 {
12259 return noErr;
12260 }
12261
12262
12263 /* Defined in mac.c. */
12264 extern int
12265 path_from_vol_dir_name (char *, int, short, long, char *);
12266
12267
12268 /* Called when we receive an AppleEvent with an ID of
12269 "kAEOpenDocuments". This routine gets the direct parameter,
12270 extracts the FSSpecs in it, and puts their names on a list. */
12271 static pascal OSErr
12272 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12273 {
12274 OSErr err, err2;
12275 AEDesc the_desc;
12276 AEKeyword keyword;
12277 DescType actual_type;
12278 Size actual_size;
12279
12280 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12281 if (err != noErr)
12282 goto descriptor_error_exit;
12283
12284 /* Check to see that we got all of the required parameters from the
12285 event descriptor. For an 'odoc' event this should just be the
12286 file list. */
12287 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
12288 &actual_type, (Ptr) &keyword,
12289 sizeof (keyword), &actual_size);
12290 /* No error means that we found some unused parameters.
12291 errAEDescNotFound means that there are no more parameters. If we
12292 get an error code other than that, flag it. */
12293 if ((err == noErr) || (err != errAEDescNotFound))
12294 {
12295 err = errAEEventNotHandled;
12296 goto error_exit;
12297 }
12298 err = noErr;
12299
12300 /* Got all the parameters we need. Now, go through the direct
12301 object list and parse it up. */
12302 {
12303 long num_files_to_open;
12304
12305 err = AECountItems (&the_desc, &num_files_to_open);
12306 if (err == noErr)
12307 {
12308 int i;
12309
12310 /* AE file list is one based so just use that for indexing here. */
12311 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
12312 {
12313 FSSpec fs;
12314 Str255 path_name, unix_path_name;
12315 #ifdef MAC_OSX
12316 FSRef fref;
12317 #endif
12318
12319 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12320 (Ptr) &fs, sizeof (fs), &actual_size);
12321 if (err != noErr) break;
12322
12323 #ifdef MAC_OSX
12324 err = FSpMakeFSRef (&fs, &fref);
12325 if (err != noErr) break;
12326
12327 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
12328 #else
12329 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12330 fs.name) &&
12331 mac_to_posix_pathname (path_name, unix_path_name, 255))
12332 #endif
12333 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12334 drag_and_drop_file_list);
12335 }
12336 }
12337 }
12338
12339 error_exit:
12340 /* Nuke the coerced file list in any case */
12341 err2 = AEDisposeDesc(&the_desc);
12342
12343 descriptor_error_exit:
12344 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12345 return err;
12346 }
12347
12348
12349 static pascal OSErr
12350 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
12351 DragReference theDrag)
12352 {
12353 short items;
12354 short index;
12355 FlavorFlags theFlags;
12356 Point mouse;
12357 OSErr result;
12358 ItemReference theItem;
12359 HFSFlavor data;
12360 FSRef fref;
12361 Size size = sizeof (HFSFlavor);
12362
12363 drag_and_drop_file_list = Qnil;
12364 GetDragMouse (theDrag, &mouse, 0L);
12365 CountDragItems (theDrag, &items);
12366 for (index = 1; index <= items; index++)
12367 {
12368 /* Only handle file references. */
12369 GetDragItemReferenceNumber (theDrag, index, &theItem);
12370 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
12371 if (result == noErr)
12372 {
12373 #ifdef MAC_OSX
12374 FSRef frref;
12375 #else
12376 Str255 path_name;
12377 #endif
12378 Str255 unix_path_name;
12379 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
12380 #ifdef MAC_OSX
12381 /* Use Carbon routines, otherwise it converts the file name
12382 to /Macintosh HD/..., which is not correct. */
12383 FSpMakeFSRef (&data.fileSpec, &fref);
12384 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
12385 #else
12386 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
12387 data.fileSpec.parID, data.fileSpec.name) &&
12388 mac_to_posix_pathname (path_name, unix_path_name, 255))
12389 #endif
12390 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12391 drag_and_drop_file_list);
12392 }
12393 else
12394 return;
12395 }
12396 /* If there are items in the list, construct an event and post it to
12397 the queue like an interrupt using kbd_buffer_store_event. */
12398 if (!NILP (drag_and_drop_file_list))
12399 {
12400 struct input_event event;
12401 Lisp_Object frame;
12402 struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
12403 SetPort (GetWindowPort (window));
12404 GlobalToLocal (&mouse);
12405
12406 event.kind = DRAG_N_DROP_EVENT;
12407 event.code = 0;
12408 event.modifiers = 0;
12409 event.timestamp = TickCount () * (1000 / 60);
12410 XSETINT (event.x, mouse.h);
12411 XSETINT (event.y, mouse.v);
12412 XSETFRAME (frame, f);
12413 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
12414 event.arg = Qnil;
12415 /* Post to the interrupt queue */
12416 kbd_buffer_store_event (&event);
12417 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
12418 {
12419 ProcessSerialNumber psn;
12420 GetCurrentProcess (&psn);
12421 SetFrontProcess (&psn);
12422 }
12423 }
12424 }
12425
12426
12427 /* Print Document Apple Event */
12428 static pascal OSErr
12429 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12430 {
12431 return errAEEventNotHandled;
12432 }
12433
12434
12435 static pascal OSErr
12436 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12437 {
12438 /* FixMe: Do we need an unwind-protect or something here? And what
12439 do we do about unsaved files. Currently just forces quit rather
12440 than doing recursive callback to get user input. */
12441
12442 terminate_flag = true;
12443
12444 /* Fkill_emacs doesn't return. We have to return. (TI) */
12445 return noErr;
12446 }
12447
12448
12449 #if __profile__
12450 void
12451 profiler_exit_proc ()
12452 {
12453 ProfilerDump ("\pEmacs.prof");
12454 ProfilerTerm ();
12455 }
12456 #endif
12457
12458 /* These few functions implement Emacs as a normal Mac application
12459 (almost): set up the heap and the Toolbox, handle necessary
12460 system events plus a few simple menu events. They also set up
12461 Emacs's access to functions defined in the rest of this file.
12462 Emacs uses function hooks to perform all its terminal I/O. A
12463 complete list of these functions appear in termhooks.h. For what
12464 they do, read the comments there and see also w32term.c and
12465 xterm.c. What's noticeably missing here is the event loop, which
12466 is normally present in most Mac application. After performing the
12467 necessary Mac initializations, main passes off control to
12468 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12469 mac_read_socket (defined further below) to read input. This is
12470 where WaitNextEvent is called to process Mac events. This is also
12471 where check_alarm in sysdep.c is called to simulate alarm signals.
12472 This makes the cursor jump back to its correct position after
12473 briefly jumping to that of the matching parenthesis, print useful
12474 hints and prompts in the minibuffer after the user stops typing for
12475 a wait, etc. */
12476
12477 #if !TARGET_API_MAC_CARBON
12478 #undef main
12479 int
12480 main (void)
12481 {
12482 #if __profile__ /* is the profiler on? */
12483 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12484 exit(1);
12485 #endif
12486
12487 #if __MWERKS__
12488 /* set creator and type for files created by MSL */
12489 _fcreator = 'EMAx';
12490 _ftype = 'TEXT';
12491 #endif
12492
12493 do_init_managers ();
12494
12495 do_get_menus ();
12496
12497 do_check_ram_size ();
12498
12499 init_emacs_passwd_dir ();
12500
12501 init_environ ();
12502
12503 initialize_applescript ();
12504
12505 init_required_apple_events ();
12506
12507 {
12508 char **argv;
12509 int argc = 0;
12510
12511 /* set up argv array from STR# resource */
12512 get_string_list (&argv, ARGV_STRING_LIST_ID);
12513 while (argv[argc])
12514 argc++;
12515
12516 /* free up AppleScript resources on exit */
12517 atexit (terminate_applescript);
12518
12519 #if __profile__ /* is the profiler on? */
12520 atexit (profiler_exit_proc);
12521 #endif
12522
12523 /* 3rd param "envp" never used in emacs_main */
12524 (void) emacs_main (argc, argv, 0);
12525 }
12526
12527 /* Never reached - real exit in Fkill_emacs */
12528 return 0;
12529 }
12530 #endif
12531
12532 /* Table for translating Mac keycode to X keysym values. Contributed
12533 by Sudhir Shenoy. */
12534 static unsigned char keycode_to_xkeysym_table[] = {
12535 /* 0x00 - 0x3f */
12536 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12537 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12538 0, 0, 0, 0, '\x0d', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12539 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12540 /* 0x40 */
12541 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12542 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12543 0, 0, 0, '\xaf' /* kp/ */,
12544 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
12545 /* 0x50 */
12546 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12547 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12548 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12549 '\xb9' /* kp9 */, 0, 0, 0,
12550 /* 0x60 */
12551 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12552 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12553 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12554 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
12555 /* 0x70 */
12556 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12557 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12558 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12559 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
12560 };
12561
12562 static int
12563 keycode_to_xkeysym (int keyCode, int *xKeySym)
12564 {
12565 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12566 return *xKeySym != 0;
12567 }
12568
12569 /* Emacs calls this whenever it wants to read an input event from the
12570 user. */
12571 int
12572 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12573 {
12574 int count = 0;
12575 #if USE_CARBON_EVENTS
12576 OSStatus rneResult;
12577 EventRef eventRef;
12578 EventMouseButton mouseBtn;
12579 #endif
12580 EventRecord er;
12581 int the_modifiers;
12582 EventMask event_mask;
12583
12584 #if 0
12585 if (interrupt_input_blocked)
12586 {
12587 interrupt_input_pending = 1;
12588 return -1;
12589 }
12590 #endif
12591
12592 interrupt_input_pending = 0;
12593 BLOCK_INPUT;
12594
12595 /* So people can tell when we have read the available input. */
12596 input_signal_count++;
12597
12598 if (numchars <= 0)
12599 abort ();
12600
12601 /* Don't poll for events to process (specifically updateEvt) if
12602 window update currently already in progress. A call to redisplay
12603 (in do_window_update) can be preempted by another call to
12604 redisplay, causing blank regions to be left on the screen and the
12605 cursor to be left at strange places. */
12606 if (handling_window_update)
12607 {
12608 UNBLOCK_INPUT;
12609 return 0;
12610 }
12611
12612 if (terminate_flag)
12613 Fkill_emacs (make_number (1));
12614
12615 /* It is necessary to set this (additional) argument slot of an
12616 event to nil because keyboard.c protects incompletely processed
12617 event from being garbage collected by placing them in the
12618 kbd_buffer_gcpro vector. */
12619 bufp->arg = Qnil;
12620
12621 event_mask = everyEvent;
12622 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
12623 event_mask -= highLevelEventMask;
12624
12625 #if USE_CARBON_EVENTS
12626 rneResult = ReceiveNextEvent (0, NULL,
12627 expected
12628 ? TicksToEventTime (app_sleep_time)
12629 : 0,
12630 true, &eventRef);
12631 if (!rneResult)
12632 {
12633 /* Handle new events */
12634 if (!mac_convert_event_ref (eventRef, &er))
12635 switch (GetEventClass (eventRef))
12636 {
12637 case kEventClassMouse:
12638 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
12639 {
12640 SInt32 delta;
12641 Point point;
12642 WindowPtr window_ptr = FrontNonFloatingWindow ();
12643 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12644 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
12645 typeSInt32, NULL, sizeof (SInt32),
12646 NULL, &delta);
12647 GetEventParameter(eventRef, kEventParamMouseLocation,
12648 typeQDPoint, NULL, sizeof (Point),
12649 NULL, &point);
12650 bufp->kind = MOUSE_WHEEL_EVENT;
12651 bufp->code = delta;
12652 bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
12653 SetPort (GetWindowPort (window_ptr));
12654 GlobalToLocal (&point);
12655 XSETINT (bufp->x, point.h);
12656 XSETINT (bufp->y, point.v);
12657 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12658 bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
12659 count++;
12660 }
12661 else
12662 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12663
12664 break;
12665 default:
12666 /* Send the event to the appropriate receiver. */
12667 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
12668 }
12669 else
12670 #else
12671 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
12672 #endif /* USE_CARBON_EVENTS */
12673 switch (er.what)
12674 {
12675 case mouseDown:
12676 case mouseUp:
12677 {
12678 WindowPtr window_ptr = FrontWindow ();
12679 SInt16 part_code;
12680
12681 #if USE_CARBON_EVENTS
12682 /* This is needed to send mouse events like aqua window buttons
12683 to the correct handler. */
12684 if (eventNotHandledErr != SendEventToEventTarget (eventRef, GetEventDispatcherTarget ())) {
12685 break;
12686 }
12687
12688 if (!is_emacs_window(window_ptr))
12689 break;
12690 #endif
12691
12692 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12693 && er.what == mouseUp)
12694 {
12695 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12696 Point mouse_loc = er.where;
12697
12698 /* Convert to local coordinates of new window. */
12699 #if TARGET_API_MAC_CARBON
12700 SetPort (GetWindowPort (window_ptr));
12701 #else
12702 SetPort (window_ptr);
12703 #endif
12704
12705 GlobalToLocal (&mouse_loc);
12706
12707 #if USE_CARBON_EVENTS
12708 bufp->code = mac_get_mouse_btn (eventRef);
12709 #else
12710 bufp->code = 0; /* only one mouse button */
12711 #endif
12712 bufp->kind = SCROLL_BAR_CLICK_EVENT;
12713 bufp->frame_or_window = tracked_scroll_bar->window;
12714 bufp->part = scroll_bar_handle;
12715 #if USE_CARBON_EVENTS
12716 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12717 #else
12718 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12719 #endif
12720 bufp->modifiers |= up_modifier;
12721 bufp->timestamp = er.when * (1000 / 60);
12722 /* ticks to milliseconds */
12723
12724 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12725 XSETINT (bufp->y, mouse_loc.v - 24);
12726 tracked_scroll_bar->dragging = Qnil;
12727 mouse_tracking_in_progress = mouse_tracking_none;
12728 tracked_scroll_bar = NULL;
12729 count++;
12730 break;
12731 }
12732
12733 part_code = FindWindow (er.where, &window_ptr);
12734
12735 switch (part_code)
12736 {
12737 case inMenuBar:
12738 {
12739 struct frame *f = ((mac_output *)
12740 GetWRefCon (FrontWindow ()))->mFP;
12741 saved_menu_event_location = er.where;
12742 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
12743 XSETFRAME (bufp->frame_or_window, f);
12744 count++;
12745 }
12746 break;
12747
12748 case inContent:
12749 if (window_ptr != FrontWindow ())
12750 SelectWindow (window_ptr);
12751 else
12752 {
12753 SInt16 control_part_code;
12754 ControlHandle ch;
12755 struct mac_output *mwp = (mac_output *)
12756 GetWRefCon (window_ptr);
12757 Point mouse_loc = er.where;
12758
12759 /* convert to local coordinates of new window */
12760 #if TARGET_API_MAC_CARBON
12761 SetPort (GetWindowPort (window_ptr));
12762 #else
12763 SetPort (window_ptr);
12764 #endif
12765
12766 GlobalToLocal (&mouse_loc);
12767 #if TARGET_API_MAC_CARBON
12768 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12769 &control_part_code);
12770 #else
12771 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
12772 #endif
12773
12774 #if USE_CARBON_EVENTS
12775 bufp->code = mac_get_mouse_btn (eventRef);
12776 #else
12777 bufp->code = 0; /* only one mouse button */
12778 #endif
12779 XSETINT (bufp->x, mouse_loc.h);
12780 XSETINT (bufp->y, mouse_loc.v);
12781 bufp->timestamp = er.when * (1000 / 60);
12782 /* ticks to milliseconds */
12783
12784 #if TARGET_API_MAC_CARBON
12785 if (ch != 0)
12786 #else
12787 if (control_part_code != 0)
12788 #endif
12789 {
12790 struct scroll_bar *bar = (struct scroll_bar *)
12791 GetControlReference (ch);
12792 x_scroll_bar_handle_click (bar, control_part_code, &er,
12793 bufp);
12794 if (er.what == mouseDown
12795 && control_part_code == kControlIndicatorPart)
12796 {
12797 mouse_tracking_in_progress
12798 = mouse_tracking_scroll_bar;
12799 tracked_scroll_bar = bar;
12800 }
12801 else
12802 {
12803 mouse_tracking_in_progress = mouse_tracking_none;
12804 tracked_scroll_bar = NULL;
12805 }
12806 }
12807 else
12808 {
12809 bufp->kind = MOUSE_CLICK_EVENT;
12810 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12811 if (er.what == mouseDown)
12812 mouse_tracking_in_progress
12813 = mouse_tracking_mouse_movement;
12814 else
12815 mouse_tracking_in_progress = mouse_tracking_none;
12816 }
12817
12818 #if USE_CARBON_EVENTS
12819 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
12820 #else
12821 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
12822 #endif
12823
12824 switch (er.what)
12825 {
12826 case mouseDown:
12827 bufp->modifiers |= down_modifier;
12828 break;
12829 case mouseUp:
12830 bufp->modifiers |= up_modifier;
12831 break;
12832 }
12833
12834 count++;
12835 }
12836 break;
12837
12838 case inDrag:
12839 #if TARGET_API_MAC_CARBON
12840 {
12841 BitMap bm;
12842
12843 GetQDGlobalsScreenBits (&bm);
12844 DragWindow (window_ptr, er.where, &bm.bounds);
12845 }
12846 #else /* not TARGET_API_MAC_CARBON */
12847 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12848 #endif /* not TARGET_API_MAC_CARBON */
12849 break;
12850
12851 case inGoAway:
12852 if (TrackGoAway (window_ptr, er.where))
12853 {
12854 bufp->kind = DELETE_WINDOW_EVENT;
12855 XSETFRAME (bufp->frame_or_window,
12856 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12857 count++;
12858 }
12859 break;
12860
12861 /* window resize handling added --ben */
12862 case inGrow:
12863 do_grow_window(window_ptr, &er);
12864 break;
12865
12866 /* window zoom handling added --ben */
12867 case inZoomIn:
12868 case inZoomOut:
12869 if (TrackBox (window_ptr, er.where, part_code))
12870 do_zoom_window (window_ptr, part_code);
12871 break;
12872
12873 default:
12874 break;
12875 }
12876 }
12877 break;
12878
12879 case updateEvt:
12880 case osEvt:
12881 case activateEvt:
12882 #if USE_CARBON_EVENTS
12883 if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
12884 #endif
12885 do_events (&er);
12886 break;
12887
12888 case keyDown:
12889 case autoKey:
12890 {
12891 int keycode = (er.message & keyCodeMask) >> 8;
12892 int xkeysym;
12893
12894 #if USE_CARBON_EVENTS
12895 /* When using Carbon Events, we need to pass raw keyboard events
12896 to the TSM ourselves. If TSM handles it, it will pass back
12897 noErr, otherwise it will pass back "eventNotHandledErr" and
12898 we can process it normally. */
12899 if ((!NILP (Vmac_pass_command_to_system)
12900 || !(er.modifiers & cmdKey))
12901 && (!NILP (Vmac_pass_control_to_system)
12902 || !(er.modifiers & controlKey)))
12903 {
12904 OSStatus err;
12905 err = SendEventToEventTarget (eventRef,
12906 GetEventDispatcherTarget ());
12907 if (err != eventNotHandledErr)
12908 break;
12909 }
12910 #endif
12911
12912 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
12913 {
12914 SysBeep (1);
12915 UNBLOCK_INPUT;
12916 return 0;
12917 }
12918
12919 ObscureCursor ();
12920
12921 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12922 {
12923 bufp->code = 0x7f;
12924 bufp->kind = ASCII_KEYSTROKE_EVENT;
12925 }
12926 else if (keycode_to_xkeysym (keycode, &xkeysym))
12927 {
12928 bufp->code = 0xff00 | xkeysym;
12929 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
12930 }
12931 else if (!NILP (Vmac_reverse_ctrl_meta) && (er.modifiers & controlKey))
12932 {
12933 /* This is a special case to deal with converting from
12934 a control character to non-control character */
12935 int new_modifiers = er.modifiers & ~controlKey;
12936 int new_keycode = keycode | new_modifiers;
12937 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12938 unsigned long some_state = 0;
12939 bufp->code = KeyTranslate (kchr_ptr, new_keycode, &some_state) & 0xff;
12940 bufp->kind = ASCII_KEYSTROKE_EVENT;
12941 }
12942 else
12943 {
12944 if (er.modifiers & macMetaKey)
12945 {
12946 /* This code comes from Keyboard Resource, Appendix
12947 C of IM - Text. This is necessary since shift is
12948 ignored in KCHR table translation when option or
12949 command is pressed. */
12950 int new_modifiers = er.modifiers & 0xf600;
12951 /* mask off option and command */
12952 int new_keycode = keycode | new_modifiers;
12953 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12954 unsigned long some_state = 0;
12955 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12956 &some_state) & 0xff;
12957 }
12958 else
12959 bufp->code = er.message & charCodeMask;
12960 bufp->kind = ASCII_KEYSTROKE_EVENT;
12961 }
12962 }
12963
12964 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12965 convert non-ASCII characters typed at the Mac keyboard
12966 (presumed to be in the Mac Roman encoding) to iso-latin-1
12967 encoding before they are passed to Emacs. This enables the
12968 Mac keyboard to be used to enter non-ASCII iso-latin-1
12969 characters directly. */
12970 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
12971 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
12972 {
12973 static TECObjectRef converter = NULL;
12974 OSStatus the_err = noErr;
12975 OSStatus convert_status = noErr;
12976
12977 if (converter == NULL)
12978 {
12979 the_err = TECCreateConverter (&converter,
12980 kTextEncodingMacRoman,
12981 mac_keyboard_text_encoding);
12982 current_mac_keyboard_text_encoding
12983 = mac_keyboard_text_encoding;
12984 }
12985 else if (mac_keyboard_text_encoding
12986 != current_mac_keyboard_text_encoding)
12987 {
12988 /* Free the converter for the current encoding before
12989 creating a new one. */
12990 TECDisposeConverter (converter);
12991 the_err = TECCreateConverter (&converter,
12992 kTextEncodingMacRoman,
12993 mac_keyboard_text_encoding);
12994 current_mac_keyboard_text_encoding
12995 = mac_keyboard_text_encoding;
12996 }
12997
12998 if (the_err == noErr)
12999 {
13000 unsigned char ch = bufp->code;
13001 ByteCount actual_input_length, actual_output_length;
13002 unsigned char outch;
13003
13004 convert_status = TECConvertText (converter, &ch, 1,
13005 &actual_input_length,
13006 &outch, 1,
13007 &actual_output_length);
13008 if (convert_status == noErr
13009 && actual_input_length == 1
13010 && actual_output_length == 1)
13011 bufp->code = outch;
13012 }
13013 }
13014
13015 #if USE_CARBON_EVENTS
13016 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13017 #else
13018 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13019 #endif
13020
13021 {
13022 mac_output *mwp
13023 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
13024 XSETFRAME (bufp->frame_or_window, mwp->mFP);
13025 }
13026
13027 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
13028
13029 count++;
13030 break;
13031
13032 case kHighLevelEvent:
13033 drag_and_drop_file_list = Qnil;
13034
13035 AEProcessAppleEvent(&er);
13036
13037 /* Build a DRAG_N_DROP_EVENT type event as is done in
13038 constuct_drag_n_drop in w32term.c. */
13039 if (!NILP (drag_and_drop_file_list))
13040 {
13041 struct frame *f = NULL;
13042 WindowPtr wp;
13043 Lisp_Object frame;
13044
13045 wp = FrontNonFloatingWindow ();
13046 if (wp && is_emacs_window(wp))
13047 f = ((mac_output *) GetWRefCon (wp))->mFP;
13048
13049 bufp->kind = DRAG_N_DROP_EVENT;
13050 bufp->code = 0;
13051 bufp->timestamp = er.when * (1000 / 60);
13052 /* ticks to milliseconds */
13053 #if USE_CARBON_EVENTS
13054 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
13055 #else
13056 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
13057 #endif
13058
13059 XSETINT (bufp->x, 0);
13060 XSETINT (bufp->y, 0);
13061
13062 XSETFRAME (frame, f);
13063 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
13064
13065 /* Regardless of whether Emacs was suspended or in the
13066 foreground, ask it to redraw its entire screen.
13067 Otherwise parts of the screen can be left in an
13068 inconsistent state. */
13069 if (wp)
13070 #if TARGET_API_MAC_CARBON
13071 {
13072 Rect r;
13073
13074 GetWindowPortBounds (wp, &r);
13075 InvalWindowRect (wp, &r);
13076 }
13077 #else /* not TARGET_API_MAC_CARBON */
13078 InvalRect (&(wp->portRect));
13079 #endif /* not TARGET_API_MAC_CARBON */
13080
13081 count++;
13082 }
13083 default:
13084 break;
13085 }
13086 #if USE_CARBON_EVENTS
13087 ReleaseEvent (eventRef);
13088 }
13089 #endif
13090
13091 /* If the focus was just given to an autoraising frame,
13092 raise it now. */
13093 /* ??? This ought to be able to handle more than one such frame. */
13094 if (pending_autoraise_frame)
13095 {
13096 x_raise_frame (pending_autoraise_frame);
13097 pending_autoraise_frame = 0;
13098 }
13099
13100 #if !TARGET_API_MAC_CARBON
13101 check_alarm (); /* simulate the handling of a SIGALRM */
13102 #endif
13103
13104 {
13105 static Point old_mouse_pos = { -1, -1 };
13106
13107 if (app_is_suspended)
13108 {
13109 old_mouse_pos.h = -1;
13110 old_mouse_pos.v = -1;
13111 }
13112 else
13113 {
13114 Point mouse_pos;
13115 WindowPtr wp;
13116 struct frame *f;
13117 Lisp_Object bar;
13118 struct scroll_bar *sb;
13119
13120 wp = FrontWindow ();
13121 if (is_emacs_window (wp))
13122 {
13123 f = ((mac_output *) GetWRefCon (wp))->mFP;
13124
13125 #if TARGET_API_MAC_CARBON
13126 SetPort (GetWindowPort (wp));
13127 #else
13128 SetPort (wp);
13129 #endif
13130
13131 GetMouse (&mouse_pos);
13132
13133 if (!EqualPt (mouse_pos, old_mouse_pos))
13134 {
13135 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
13136 && tracked_scroll_bar)
13137 x_scroll_bar_note_movement (tracked_scroll_bar,
13138 mouse_pos.v
13139 - XINT (tracked_scroll_bar->top),
13140 TickCount() * (1000 / 60));
13141 else
13142 note_mouse_movement (f, &mouse_pos);
13143
13144 old_mouse_pos = mouse_pos;
13145 }
13146 }
13147 }
13148 }
13149
13150 UNBLOCK_INPUT;
13151
13152 return count;
13153 }
13154
13155
13156 /* Need to override CodeWarrior's input function so no conversion is
13157 done on newlines Otherwise compiled functions in .elc files will be
13158 read incorrectly. Defined in ...:MSL C:MSL
13159 Common:Source:buffer_io.c. */
13160 #ifdef __MWERKS__
13161 void
13162 __convert_to_newlines (unsigned char * p, size_t * n)
13163 {
13164 #pragma unused(p,n)
13165 }
13166
13167 void
13168 __convert_from_newlines (unsigned char * p, size_t * n)
13169 {
13170 #pragma unused(p,n)
13171 }
13172 #endif
13173
13174
13175 /* Initialize the struct pointed to by MW to represent a new COLS x
13176 ROWS Macintosh window, using font with name FONTNAME and size
13177 FONTSIZE. */
13178 void
13179 NewMacWindow (FRAME_PTR fp)
13180 {
13181 mac_output *mwp;
13182 #if TARGET_API_MAC_CARBON
13183 static int making_terminal_window = 0;
13184 #else
13185 static int making_terminal_window = 1;
13186 #endif
13187
13188 mwp = fp->output_data.mac;
13189
13190 if (making_terminal_window)
13191 {
13192 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
13193 (WindowPtr) -1)))
13194 abort ();
13195 making_terminal_window = 0;
13196 }
13197 else
13198 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
13199 abort ();
13200
13201 SetWRefCon (mwp->mWP, (long) mwp);
13202 /* so that update events can find this mac_output struct */
13203 mwp->mFP = fp; /* point back to emacs frame */
13204
13205 #if TARGET_API_MAC_CARBON
13206 SetPort (GetWindowPort (mwp->mWP));
13207 #else
13208 SetPort (mwp->mWP);
13209 #endif
13210
13211 mwp->fontset = -1;
13212
13213 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
13214 ShowWindow (mwp->mWP);
13215
13216 }
13217
13218
13219 void
13220 make_mac_frame (struct frame *f)
13221 {
13222 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
13223 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
13224
13225 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
13226
13227 NewMacWindow(f);
13228
13229 f->output_data.mac->cursor_pixel = 0;
13230 f->output_data.mac->border_pixel = 0x00ff00;
13231 f->output_data.mac->mouse_pixel = 0xff00ff;
13232 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
13233
13234 f->output_data.mac->fontset = -1;
13235 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13236 f->output_data.mac->scroll_bar_background_pixel = -1;
13237 f->output_data.mac->left_pos = 4;
13238 f->output_data.mac->top_pos = 4;
13239 f->output_data.mac->border_width = 0;
13240 f->output_data.mac->explicit_parent = 0;
13241
13242 f->output_data.mac->internal_border_width = 0;
13243
13244 f->output_method = output_mac;
13245
13246 f->auto_raise = 1;
13247 f->auto_lower = 1;
13248
13249 f->new_width = 0;
13250 f->new_height = 0;
13251 }
13252
13253 void
13254 make_mac_terminal_frame (struct frame *f)
13255 {
13256 Lisp_Object frame;
13257
13258 XSETFRAME (frame, f);
13259
13260 f->output_method = output_mac;
13261 f->output_data.mac = (struct mac_output *)
13262 xmalloc (sizeof (struct mac_output));
13263 bzero (f->output_data.mac, sizeof (struct mac_output));
13264 f->output_data.mac->fontset = -1;
13265 f->output_data.mac->scroll_bar_foreground_pixel = -1;
13266 f->output_data.mac->scroll_bar_background_pixel = -1;
13267
13268 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
13269
13270 f->width = 96;
13271 f->height = 4;
13272
13273 make_mac_frame (f);
13274
13275 x_make_gc (f);
13276
13277 /* Need to be initialized for unshow_buffer in window.c. */
13278 selected_window = f->selected_window;
13279
13280 Fmodify_frame_parameters (frame,
13281 Fcons (Fcons (Qfont,
13282 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
13283 Fmodify_frame_parameters (frame,
13284 Fcons (Fcons (Qforeground_color,
13285 build_string ("black")), Qnil));
13286 Fmodify_frame_parameters (frame,
13287 Fcons (Fcons (Qbackground_color,
13288 build_string ("white")), Qnil));
13289 }
13290
13291 \f
13292 /***********************************************************************
13293 Initialization
13294 ***********************************************************************/
13295
13296 #ifdef USE_X_TOOLKIT
13297 static XrmOptionDescRec emacs_options[] = {
13298 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13299 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13300
13301 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13302 XrmoptionSepArg, NULL},
13303 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13304
13305 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13306 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13307 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13308 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13309 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13310 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13311 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13312 };
13313 #endif /* USE_X_TOOLKIT */
13314
13315 #ifdef MULTI_KBOARD
13316 /* Test whether two display-name strings agree up to the dot that separates
13317 the screen number from the server number. */
13318 static int
13319 same_x_server (name1, name2)
13320 char *name1, *name2;
13321 {
13322 int seen_colon = 0;
13323 unsigned char *system_name = SDATA (Vsystem_name);
13324 int system_name_length = strlen (system_name);
13325 int length_until_period = 0;
13326
13327 while (system_name[length_until_period] != 0
13328 && system_name[length_until_period] != '.')
13329 length_until_period++;
13330
13331 /* Treat `unix' like an empty host name. */
13332 if (! strncmp (name1, "unix:", 5))
13333 name1 += 4;
13334 if (! strncmp (name2, "unix:", 5))
13335 name2 += 4;
13336 /* Treat this host's name like an empty host name. */
13337 if (! strncmp (name1, system_name, system_name_length)
13338 && name1[system_name_length] == ':')
13339 name1 += system_name_length;
13340 if (! strncmp (name2, system_name, system_name_length)
13341 && name2[system_name_length] == ':')
13342 name2 += system_name_length;
13343 /* Treat this host's domainless name like an empty host name. */
13344 if (! strncmp (name1, system_name, length_until_period)
13345 && name1[length_until_period] == ':')
13346 name1 += length_until_period;
13347 if (! strncmp (name2, system_name, length_until_period)
13348 && name2[length_until_period] == ':')
13349 name2 += length_until_period;
13350
13351 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13352 {
13353 if (*name1 == ':')
13354 seen_colon++;
13355 if (seen_colon && *name1 == '.')
13356 return 1;
13357 }
13358 return (seen_colon
13359 && (*name1 == '.' || *name1 == '\0')
13360 && (*name2 == '.' || *name2 == '\0'));
13361 }
13362 #endif
13363
13364 int mac_initialized = 0;
13365
13366 void
13367 mac_initialize_display_info ()
13368 {
13369 struct mac_display_info *dpyinfo = &one_mac_display_info;
13370 GDHandle main_device_handle;
13371
13372 bzero (dpyinfo, sizeof (*dpyinfo));
13373
13374 /* Put it on x_display_name_list. */
13375 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
13376 x_display_name_list);
13377 dpyinfo->name_list_element = XCAR (x_display_name_list);
13378
13379 #if 0
13380 dpyinfo->mac_id_name
13381 = (char *) xmalloc (SCHARS (Vinvocation_name)
13382 + SCHARS (Vsystem_name)
13383 + 2);
13384 sprintf (dpyinfo->mac_id_name, "%s@%s",
13385 SDATA (Vinvocation_name), SDATA (Vsystem_name));
13386 #else
13387 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
13388 strcpy (dpyinfo->mac_id_name, "Mac Display");
13389 #endif
13390
13391 main_device_handle = LMGetMainDevice();
13392
13393 dpyinfo->reference_count = 0;
13394 dpyinfo->resx = 75.0;
13395 dpyinfo->resy = 75.0;
13396 dpyinfo->n_planes = 1;
13397 dpyinfo->n_cbits = 16;
13398 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13399 dpyinfo->width = (**main_device_handle).gdRect.right;
13400 dpyinfo->grabbed = 0;
13401 dpyinfo->root_window = NULL;
13402
13403 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13404 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13405 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13406 dpyinfo->mouse_face_window = Qnil;
13407 }
13408
13409 struct mac_display_info *
13410 mac_term_init (display_name, xrm_option, resource_name)
13411 Lisp_Object display_name;
13412 char *xrm_option;
13413 char *resource_name;
13414 {
13415 struct mac_display_info *dpyinfo;
13416 GDHandle main_device_handle;
13417
13418 if (!mac_initialized)
13419 {
13420 mac_initialize ();
13421 mac_initialized = 1;
13422 }
13423
13424 mac_initialize_display_info (display_name);
13425
13426 dpyinfo = &one_mac_display_info;
13427
13428 main_device_handle = LMGetMainDevice();
13429
13430 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13431 dpyinfo->width = (**main_device_handle).gdRect.right;
13432
13433 return dpyinfo;
13434 }
13435 \f
13436 #ifdef MAC_OSX
13437 void
13438 MakeMeTheFrontProcess ()
13439 {
13440 ProcessSerialNumber psn;
13441 OSErr err;
13442
13443 err = GetCurrentProcess (&psn);
13444 if (err == noErr)
13445 (void) SetFrontProcess (&psn);
13446 }
13447 #endif /* MAC_OSX */
13448
13449 /* Set up use of X before we make the first connection. */
13450
13451 static struct redisplay_interface x_redisplay_interface =
13452 {
13453 x_produce_glyphs,
13454 x_write_glyphs,
13455 x_insert_glyphs,
13456 x_clear_end_of_line,
13457 x_scroll_run,
13458 x_after_update_window_line,
13459 x_update_window_begin,
13460 x_update_window_end,
13461 XTcursor_to,
13462 x_flush,
13463 x_clear_mouse_face,
13464 x_get_glyph_overhangs,
13465 x_fix_overlapping_area
13466 };
13467
13468 void
13469 mac_initialize ()
13470 {
13471 rif = &x_redisplay_interface;
13472
13473 clear_frame_hook = x_clear_frame;
13474 ins_del_lines_hook = x_ins_del_lines;
13475 delete_glyphs_hook = x_delete_glyphs;
13476 ring_bell_hook = XTring_bell;
13477 reset_terminal_modes_hook = XTreset_terminal_modes;
13478 set_terminal_modes_hook = XTset_terminal_modes;
13479 update_begin_hook = x_update_begin;
13480 update_end_hook = x_update_end;
13481 set_terminal_window_hook = XTset_terminal_window;
13482 read_socket_hook = XTread_socket;
13483 frame_up_to_date_hook = XTframe_up_to_date;
13484 mouse_position_hook = XTmouse_position;
13485 frame_rehighlight_hook = XTframe_rehighlight;
13486 frame_raise_lower_hook = XTframe_raise_lower;
13487
13488 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13489 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13490 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13491 judge_scroll_bars_hook = XTjudge_scroll_bars;
13492
13493 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13494
13495 scroll_region_ok = 1; /* we'll scroll partial frames */
13496 char_ins_del_ok = 1;
13497 line_ins_del_ok = 1; /* we'll just blt 'em */
13498 fast_clear_end_of_line = 1; /* X does this well */
13499 memory_below_frame = 0; /* we don't remember what scrolls
13500 off the bottom */
13501 baud_rate = 19200;
13502
13503 x_noop_count = 0;
13504 last_tool_bar_item = -1;
13505 any_help_event_p = 0;
13506
13507 /* Try to use interrupt input; if we can't, then start polling. */
13508 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13509
13510 #ifdef USE_X_TOOLKIT
13511 XtToolkitInitialize ();
13512 Xt_app_con = XtCreateApplicationContext ();
13513 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13514
13515 /* Install an asynchronous timer that processes Xt timeout events
13516 every 0.1s. This is necessary because some widget sets use
13517 timeouts internally, for example the LessTif menu bar, or the
13518 Xaw3d scroll bar. When Xt timouts aren't processed, these
13519 widgets don't behave normally. */
13520 {
13521 EMACS_TIME interval;
13522 EMACS_SET_SECS_USECS (interval, 0, 100000);
13523 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13524 }
13525 #endif
13526
13527 #if USE_TOOLKIT_SCROLL_BARS
13528 xaw3d_arrow_scroll = False;
13529 xaw3d_pick_top = True;
13530 #endif
13531
13532 #if 0
13533 /* Note that there is no real way portable across R3/R4 to get the
13534 original error handler. */
13535 XSetErrorHandler (x_error_handler);
13536 XSetIOErrorHandler (x_io_error_quitter);
13537
13538 /* Disable Window Change signals; they are handled by X events. */
13539 #ifdef SIGWINCH
13540 signal (SIGWINCH, SIG_DFL);
13541 #endif /* ! defined (SIGWINCH) */
13542
13543 signal (SIGPIPE, x_connection_signal);
13544 #endif
13545
13546 mac_initialize_display_info ();
13547
13548 #if TARGET_API_MAC_CARBON
13549 init_required_apple_events ();
13550
13551 init_mac_drag_n_drop ();
13552
13553 #if USE_CARBON_EVENTS
13554 init_service_handler ();
13555 #endif
13556
13557 DisableMenuCommand (NULL, kHICommandQuit);
13558
13559 if (!inhibit_window_system)
13560 MakeMeTheFrontProcess ();
13561 #endif
13562 }
13563
13564
13565 void
13566 syms_of_macterm ()
13567 {
13568 #if 0
13569 staticpro (&x_error_message_string);
13570 x_error_message_string = Qnil;
13571 #endif
13572
13573 staticpro (&x_display_name_list);
13574 x_display_name_list = Qnil;
13575
13576 staticpro (&last_mouse_scroll_bar);
13577 last_mouse_scroll_bar = Qnil;
13578
13579 staticpro (&Qvendor_specific_keysyms);
13580 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13581
13582 staticpro (&last_mouse_press_frame);
13583 last_mouse_press_frame = Qnil;
13584
13585 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13586 staticpro (&Qmac_ready_for_drag_n_drop);
13587
13588 help_echo = Qnil;
13589 staticpro (&help_echo);
13590 help_echo_object = Qnil;
13591 staticpro (&help_echo_object);
13592 help_echo_window = Qnil;
13593 staticpro (&help_echo_window);
13594 previous_help_echo = Qnil;
13595 staticpro (&previous_help_echo);
13596 help_echo_pos = -1;
13597
13598 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13599 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13600 x_autoselect_window_p = 0;
13601
13602 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13603 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13604 For example, if a block cursor is over a tab, it will be drawn as
13605 wide as that tab on the display. */);
13606 x_stretch_cursor_p = 0;
13607
13608 #if 0 /* TODO: Setting underline position from font properties. */
13609 DEFVAR_BOOL ("x-use-underline-position-properties",
13610 &x_use_underline_position_properties,
13611 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13612 nil means ignore them. If you encounter fonts with bogus
13613 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13614 to 4.1, set this to nil. */);
13615 x_use_underline_position_properties = 1;
13616 #endif
13617
13618 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13619 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13620 Vx_toolkit_scroll_bars = Qt;
13621
13622 staticpro (&last_mouse_motion_frame);
13623 last_mouse_motion_frame = Qnil;
13624
13625 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
13626 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13627 Otherwise the option key is used. */);
13628 Vmac_command_key_is_meta = Qt;
13629
13630 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
13631 doc: /* Non-nil means that the control and meta keys are reversed. This is
13632 useful for non-standard keyboard layouts. */);
13633 Vmac_reverse_ctrl_meta = Qnil;
13634
13635 #if USE_CARBON_EVENTS
13636 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
13637 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
13638 the right click will be mouse-3.
13639 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
13640 Vmac_wheel_button_is_mouse_2 = Qnil;
13641
13642 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
13643 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
13644 Toolbox for processing before Emacs sees it. */);
13645 Vmac_pass_command_to_system = Qt;
13646
13647 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
13648 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
13649 Toolbox for processing before Emacs sees it. */);
13650 Vmac_pass_control_to_system = Qt;
13651 #endif
13652
13653 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
13654 doc: /* One of the Text Encoding Base constant values defined in the
13655 Basic Text Constants section of Inside Macintosh - Text Encoding
13656 Conversion Manager. Its value determines the encoding characters
13657 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13658 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13659 its default value, no conversion takes place. If it is set to
13660 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13661 characters typed on Mac keyboard are first converted into the
13662 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13663 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13664 command, this enables the Mac keyboard to be used to enter non-ASCII
13665 characters directly. */);
13666 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13667 }