]> code.delx.au - gnu-emacs/blob - src/macterm.c
In src/:
[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 #else /* not MAC_OSX */
62 #include <Quickdraw.h>
63 #include <ToolUtils.h>
64 #include <Sound.h>
65 #include <Events.h>
66 #include <Script.h>
67 #include <Resources.h>
68 #include <Fonts.h>
69 #include <TextUtils.h>
70 #include <LowMem.h>
71 #include <Controls.h>
72 #if defined (__MRC__) || (__MSL__ >= 0x6000)
73 #include <ControlDefinitions.h>
74 #endif
75 #include <Gestalt.h>
76
77 #if __profile__
78 #include <profiler.h>
79 #endif
80 #endif /* not MAC_OSX */
81
82 #include "systty.h"
83 #include "systime.h"
84 #include "atimer.h"
85 #include "keymap.h"
86
87 #include <ctype.h>
88 #include <errno.h>
89 #include <setjmp.h>
90 #include <sys/stat.h>
91
92 #include "keyboard.h"
93 #include "frame.h"
94 #include "dispextern.h"
95 #include "fontset.h"
96 #include "termhooks.h"
97 #include "termopts.h"
98 #include "termchar.h"
99 #include "gnu.h"
100 #include "disptab.h"
101 #include "buffer.h"
102 #include "window.h"
103 #include "intervals.h"
104 #include "composite.h"
105 #include "coding.h"
106
107 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
108
109 \f
110 /* Fringe bitmaps. */
111
112 enum fringe_bitmap_type
113 {
114 NO_FRINGE_BITMAP,
115 LEFT_TRUNCATION_BITMAP,
116 RIGHT_TRUNCATION_BITMAP,
117 OVERLAY_ARROW_BITMAP,
118 CONTINUED_LINE_BITMAP,
119 CONTINUATION_LINE_BITMAP,
120 ZV_LINE_BITMAP
121 };
122
123 /* Bitmap drawn to indicate lines not displaying text if
124 `indicate-empty-lines' is non-nil. */
125
126 #define zv_width 8
127 #define zv_height 72
128 #define zv_period 3
129 static unsigned char zv_bits[] = {
130 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
131 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
132 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
133 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
134 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
135 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
136 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
137 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
138
139 /* An arrow like this: `<-'. */
140
141 #define left_width 8
142 #define left_height 8
143 static unsigned char left_bits[] = {
144 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
145
146 /* Right truncation arrow bitmap `->'. */
147
148 #define right_width 8
149 #define right_height 8
150 static unsigned char right_bits[] = {
151 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
152
153 /* Marker for continued lines. */
154
155 #define continued_width 8
156 #define continued_height 8
157 static unsigned char continued_bits[] = {
158 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
159
160 /* Marker for continuation lines. */
161
162 #define continuation_width 8
163 #define continuation_height 8
164 static unsigned char continuation_bits[] = {
165 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
166
167 /* Overlay arrow bitmap. */
168
169 #if 0
170 /* A bomb. */
171 #define ov_width 8
172 #define ov_height 8
173 static unsigned char ov_bits[] = {
174 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
175 #else
176 /* A triangular arrow. */
177 #define ov_width 8
178 #define ov_height 8
179 static unsigned char ov_bits[] = {
180 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
181 #endif
182
183 extern Lisp_Object Qhelp_echo;
184
185 \f
186 /* Non-nil means Emacs uses toolkit scroll bars. */
187
188 Lisp_Object Vx_toolkit_scroll_bars;
189
190 /* If a string, XTread_socket generates an event to display that string.
191 (The display is done in read_char.) */
192
193 static Lisp_Object help_echo;
194 static Lisp_Object help_echo_window;
195 static Lisp_Object help_echo_object;
196 static int help_echo_pos;
197
198 /* Temporary variable for XTread_socket. */
199
200 static Lisp_Object previous_help_echo;
201
202 /* Non-zero means that a HELP_EVENT has been generated since Emacs
203 start. */
204
205 static int any_help_event_p;
206
207 /* Non-zero means autoselect window with the mouse cursor. */
208
209 int x_autoselect_window_p;
210
211 /* Non-zero means draw block and hollow cursor as wide as the glyph
212 under it. For example, if a block cursor is over a tab, it will be
213 drawn as wide as that tab on the display. */
214
215 int x_stretch_cursor_p;
216
217 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
218
219 int x_use_underline_position_properties;
220
221 /* This is a chain of structures for all the X displays currently in
222 use. */
223
224 struct x_display_info *x_display_list;
225
226 /* This is a list of cons cells, each of the form (NAME
227 . FONT-LIST-CACHE), one for each element of x_display_list and in
228 the same order. NAME is the name of the frame. FONT-LIST-CACHE
229 records previous values returned by x-list-fonts. */
230
231 Lisp_Object x_display_name_list;
232
233 /* This is display since Mac does not support multiple ones. */
234 struct mac_display_info one_mac_display_info;
235
236 /* Frame being updated by update_frame. This is declared in term.c.
237 This is set by update_begin and looked at by all the XT functions.
238 It is zero while not inside an update. In that case, the XT
239 functions assume that `selected_frame' is the frame to apply to. */
240
241 extern struct frame *updating_frame;
242
243 extern int waiting_for_input;
244
245 /* This is a frame waiting to be auto-raised, within XTread_socket. */
246
247 struct frame *pending_autoraise_frame;
248
249 /* Nominal cursor position -- where to draw output.
250 HPOS and VPOS are window relative glyph matrix coordinates.
251 X and Y are window relative pixel coordinates. */
252
253 struct cursor_pos output_cursor;
254
255 /* Non-zero means user is interacting with a toolkit scroll bar. */
256
257 static int toolkit_scroll_bar_interaction;
258
259 /* Mouse movement.
260
261 Formerly, we used PointerMotionHintMask (in standard_event_mask)
262 so that we would have to call XQueryPointer after each MotionNotify
263 event to ask for another such event. However, this made mouse tracking
264 slow, and there was a bug that made it eventually stop.
265
266 Simply asking for MotionNotify all the time seems to work better.
267
268 In order to avoid asking for motion events and then throwing most
269 of them away or busy-polling the server for mouse positions, we ask
270 the server for pointer motion hints. This means that we get only
271 one event per group of mouse movements. "Groups" are delimited by
272 other kinds of events (focus changes and button clicks, for
273 example), or by XQueryPointer calls; when one of these happens, we
274 get another MotionNotify event the next time the mouse moves. This
275 is at least as efficient as getting motion events when mouse
276 tracking is on, and I suspect only negligibly worse when tracking
277 is off. */
278
279 /* Where the mouse was last time we reported a mouse event. */
280
281 FRAME_PTR last_mouse_frame;
282 static Rect last_mouse_glyph;
283 static Lisp_Object last_mouse_press_frame;
284
285 /* The scroll bar in which the last X motion event occurred.
286
287 If the last X motion event occurred in a scroll bar, we set this so
288 XTmouse_position can know whether to report a scroll bar motion or
289 an ordinary motion.
290
291 If the last X motion event didn't occur in a scroll bar, we set
292 this to Qnil, to tell XTmouse_position to return an ordinary motion
293 event. */
294
295 static Lisp_Object last_mouse_scroll_bar;
296
297 /* This is a hack. We would really prefer that XTmouse_position would
298 return the time associated with the position it returns, but there
299 doesn't seem to be any way to wrest the time-stamp from the server
300 along with the position query. So, we just keep track of the time
301 of the last movement we received, and return that in hopes that
302 it's somewhat accurate. */
303
304 static Time last_mouse_movement_time;
305
306 enum mouse_tracking_type {
307 mouse_tracking_none,
308 mouse_tracking_mouse_movement,
309 mouse_tracking_scroll_bar
310 };
311
312 enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
313
314 struct scroll_bar *tracked_scroll_bar = NULL;
315
316 /* Incremented by XTread_socket whenever it really tries to read
317 events. */
318
319 #ifdef __STDC__
320 static int volatile input_signal_count;
321 #else
322 static int input_signal_count;
323 #endif
324
325 /* Used locally within XTread_socket. */
326
327 static int x_noop_count;
328
329 /* Initial values of argv and argc. */
330
331 extern char **initial_argv;
332 extern int initial_argc;
333
334 extern Lisp_Object Vcommand_line_args, Vsystem_name;
335
336 /* Tells if a window manager is present or not. */
337
338 extern Lisp_Object Vx_no_window_manager;
339
340 extern Lisp_Object Qface, Qmouse_face;
341
342 extern int errno;
343
344 /* A mask of extra modifier bits to put into every keyboard char. */
345
346 extern int extra_keyboard_modifiers;
347
348 static Lisp_Object Qvendor_specific_keysyms;
349
350 #if 0
351 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
352 #endif
353
354 extern Lisp_Object x_icon_type P_ ((struct frame *));
355
356
357 #if __MRC__
358 QDGlobals qd; /* QuickDraw global information structure. */
359 #endif
360
361
362 /* Enumeration for overriding/changing the face to use for drawing
363 glyphs in x_draw_glyphs. */
364
365 enum draw_glyphs_face
366 {
367 DRAW_NORMAL_TEXT,
368 DRAW_INVERSE_VIDEO,
369 DRAW_CURSOR,
370 DRAW_MOUSE_FACE,
371 DRAW_IMAGE_RAISED,
372 DRAW_IMAGE_SUNKEN
373 };
374
375 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
376 struct mac_display_info *mac_display_info_for_display (Display *);
377 static void x_update_window_end P_ ((struct window *, int, int));
378 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
379 static int fast_find_position P_ ((struct window *, int, int *, int *,
380 int *, int *, Lisp_Object));
381 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
382 int *, int *, int *, int *, int));
383 static void set_output_cursor P_ ((struct cursor_pos *));
384 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
385 int *, int *, int *, int));
386 static void note_mode_line_highlight P_ ((struct window *, int, int));
387 static void note_mouse_highlight P_ ((struct frame *, int, int));
388 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
389 static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
390 static void show_mouse_face P_ ((struct x_display_info *,
391 enum draw_glyphs_face));
392 static int cursor_in_mouse_face_p P_ ((struct window *));
393 static int clear_mouse_face P_ ((struct mac_display_info *));
394 static int x_io_error_quitter P_ ((Display *));
395 int x_catch_errors P_ ((Display *));
396 void x_uncatch_errors P_ ((Display *, int));
397 void x_lower_frame P_ ((struct frame *));
398 void x_scroll_bar_clear P_ ((struct frame *));
399 int x_had_errors_p P_ ((Display *));
400 void x_wm_set_size_hint P_ ((struct frame *, long, int));
401 void x_raise_frame P_ ((struct frame *));
402 void x_set_window_size P_ ((struct frame *, int, int, int));
403 void x_wm_set_window_state P_ ((struct frame *, int));
404 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
405 void mac_initialize P_ ((void));
406 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
407 static int x_compute_min_glyph_bounds P_ ((struct frame *));
408 enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
409 static void x_draw_phys_cursor_glyph P_ ((struct window *,
410 struct glyph_row *,
411 enum draw_glyphs_face));
412 static void x_update_end P_ ((struct frame *));
413 static void XTframe_up_to_date P_ ((struct frame *));
414 static void XTreassert_line_highlight P_ ((int, int));
415 static void x_change_line_highlight P_ ((int, int, int, int));
416 static void XTset_terminal_modes P_ ((void));
417 static void XTreset_terminal_modes P_ ((void));
418 static void XTcursor_to P_ ((int, int, int, int));
419 static void x_write_glyphs P_ ((struct glyph *, int));
420 static void x_clear_end_of_line P_ ((int));
421 static void x_clear_frame P_ ((void));
422 static void x_clear_cursor P_ ((struct window *));
423 static void frame_highlight P_ ((struct frame *));
424 static void frame_unhighlight P_ ((struct frame *));
425 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
426 static void XTframe_rehighlight P_ ((struct frame *));
427 static void x_frame_rehighlight P_ ((struct x_display_info *));
428 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
429 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
430 static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
431 static void expose_frame P_ ((struct frame *, int, int, int, int));
432 static int expose_window_tree P_ ((struct window *, Rect *));
433 static int expose_window P_ ((struct window *, Rect *));
434 static void expose_area P_ ((struct window *, struct glyph_row *,
435 Rect *, enum glyph_row_area));
436 static int expose_line P_ ((struct window *, struct glyph_row *,
437 Rect *));
438 void x_display_cursor (struct window *, int, int, int, int, int);
439 void x_update_cursor P_ ((struct frame *, int));
440 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
441 static void x_update_window_cursor P_ ((struct window *, int));
442 static void x_erase_phys_cursor P_ ((struct window *));
443 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
444 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
445 enum fringe_bitmap_type, int left_p));
446 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
447 GC, int));
448 static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
449 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
450 static void notice_overwritten_cursor P_ ((struct window *,
451 enum glyph_row_area,
452 int, int, int, int));
453 static void x_flush P_ ((struct frame *f));
454 static void x_update_begin P_ ((struct frame *));
455 static void x_update_window_begin P_ ((struct window *));
456 static void x_draw_vertical_border P_ ((struct window *));
457 static void x_after_update_window_line P_ ((struct glyph_row *));
458 static INLINE void take_vertical_position_into_account P_ ((struct it *));
459 static void x_produce_stretch_glyph P_ ((struct it *));
460
461 static void activate_scroll_bars (FRAME_PTR);
462 static void deactivate_scroll_bars (FRAME_PTR);
463
464 extern int image_ascent (struct image *, struct face *);
465 void x_set_offset (struct frame *, int, int, int);
466 int x_bitmap_icon (struct frame *, Lisp_Object);
467 void x_make_frame_visible (struct frame *);
468
469 extern void window_scroll (Lisp_Object, int, int, int);
470
471 /* Defined in macmenu.h. */
472 extern void menubar_selection_callback (FRAME_PTR, int);
473 extern void set_frame_menubar (FRAME_PTR, int, int);
474
475 /* X display function emulation */
476
477 /* Structure borrowed from Xlib.h to represent two-byte characters in
478 dumpglyphs. */
479
480 typedef struct {
481 unsigned char byte1;
482 unsigned char byte2;
483 } XChar2b;
484
485 static void
486 XFreePixmap (display, pixmap)
487 Display *display;
488 Pixmap pixmap;
489 {
490 PixMap *p = (PixMap *) pixmap;
491
492 xfree (p->baseAddr);
493 xfree (p);
494 }
495
496
497 /* Set foreground color for subsequent QuickDraw commands. Assume
498 graphic port has already been set. */
499
500 static void
501 mac_set_forecolor (unsigned long color)
502 {
503 RGBColor fg_color;
504
505 fg_color.red = RED_FROM_ULONG (color) * 256;
506 fg_color.green = GREEN_FROM_ULONG (color) * 256;
507 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
508
509 RGBForeColor (&fg_color);
510 }
511
512
513 /* Set background color for subsequent QuickDraw commands. Assume
514 graphic port has already been set. */
515
516 static void
517 mac_set_backcolor (unsigned long color)
518 {
519 RGBColor bg_color;
520
521 bg_color.red = RED_FROM_ULONG (color) * 256;
522 bg_color.green = GREEN_FROM_ULONG (color) * 256;
523 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
524
525 RGBBackColor (&bg_color);
526 }
527
528 /* Set foreground and background color for subsequent QuickDraw
529 commands. Assume that the graphic port has already been set. */
530
531 static void
532 mac_set_colors (GC gc)
533 {
534 mac_set_forecolor (gc->foreground);
535 mac_set_backcolor (gc->background);
536 }
537
538 /* Mac version of XDrawLine. */
539
540 static void
541 XDrawLine (display, w, gc, x1, y1, x2, y2)
542 Display *display;
543 WindowPtr w;
544 GC gc;
545 int x1, y1, x2, y2;
546 {
547 #if TARGET_API_MAC_CARBON
548 SetPort (GetWindowPort (w));
549 #else
550 SetPort (w);
551 #endif
552
553 mac_set_colors (gc);
554
555 MoveTo (x1, y1);
556 LineTo (x2, y2);
557 }
558
559 /* Mac version of XClearArea. */
560
561 void
562 XClearArea (display, w, x, y, width, height, exposures)
563 Display *display;
564 WindowPtr w;
565 int x, y;
566 unsigned int width, height;
567 int exposures;
568 {
569 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
570 Rect r;
571 XGCValues xgc;
572
573 xgc.foreground = mwp->x_compatible.foreground_pixel;
574 xgc.background = mwp->x_compatible.background_pixel;
575
576 #if TARGET_API_MAC_CARBON
577 SetPort (GetWindowPort (w));
578 #else
579 SetPort (w);
580 #endif
581
582 mac_set_colors (&xgc);
583 SetRect (&r, x, y, x + width, y + height);
584
585 EraseRect (&r);
586 }
587
588 /* Mac version of XClearWindow. */
589
590 static void
591 XClearWindow (display, w)
592 Display *display;
593 WindowPtr w;
594 {
595 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
596 XGCValues xgc;
597
598 xgc.foreground = mwp->x_compatible.foreground_pixel;
599 xgc.background = mwp->x_compatible.background_pixel;
600
601 #if TARGET_API_MAC_CARBON
602 SetPort (GetWindowPort (w));
603 #else
604 SetPort (w);
605 #endif
606
607 mac_set_colors (&xgc);
608
609 #if TARGET_API_MAC_CARBON
610 {
611 Rect r;
612
613 GetWindowPortBounds (w, &r);
614 EraseRect (&r);
615 }
616 #else /* not TARGET_API_MAC_CARBON */
617 EraseRect (&(w->portRect));
618 #endif /* not TARGET_API_MAC_CARBON */
619 }
620
621
622 /* Mac replacement for XCopyArea. */
623
624 static void
625 mac_draw_bitmap (display, w, gc, x, y, bitmap)
626 Display *display;
627 WindowPtr w;
628 GC gc;
629 int x, y;
630 BitMap *bitmap;
631 {
632 Rect r;
633
634 #if TARGET_API_MAC_CARBON
635 SetPort (GetWindowPort (w));
636 #else
637 SetPort (w);
638 #endif
639
640 mac_set_colors (gc);
641 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
642
643 #if TARGET_API_MAC_CARBON
644 {
645 PixMapHandle pmh;
646
647 LockPortBits (GetWindowPort (w));
648 pmh = GetPortPixMap (GetWindowPort (w));
649 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
650 UnlockPortBits (GetWindowPort (w));
651 }
652 #else /* not TARGET_API_MAC_CARBON */
653 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
654 #endif /* not TARGET_API_MAC_CARBON */
655 }
656
657
658 /* Mac replacement for XSetClipRectangles. */
659
660 static void
661 mac_set_clip_rectangle (display, w, r)
662 Display *display;
663 WindowPtr w;
664 Rect *r;
665 {
666 #if TARGET_API_MAC_CARBON
667 SetPort (GetWindowPort (w));
668 #else
669 SetPort (w);
670 #endif
671
672 ClipRect (r);
673 }
674
675
676 /* Mac replacement for XSetClipMask. */
677
678 static void
679 mac_reset_clipping (display, w)
680 Display *display;
681 WindowPtr w;
682 {
683 Rect r;
684
685 #if TARGET_API_MAC_CARBON
686 SetPort (GetWindowPort (w));
687 #else
688 SetPort (w);
689 #endif
690
691 SetRect (&r, -32767, -32767, 32767, 32767);
692 ClipRect (&r);
693 }
694
695
696 /* Mac replacement for XCreateBitmapFromBitmapData. */
697
698 static void
699 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
700 BitMap *bitmap;
701 char *bits;
702 int w, h;
703 {
704 int bytes_per_row, i, j;
705
706 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
707 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
708 if (!bitmap->baseAddr)
709 abort ();
710
711 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
712 for (i = 0; i < h; i++)
713 for (j = 0; j < w; j++)
714 if (BitTst (bits, i * w + j))
715 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
716
717 SetRect (&(bitmap->bounds), 0, 0, w, h);
718 }
719
720
721 static void
722 mac_free_bitmap (bitmap)
723 BitMap *bitmap;
724 {
725 xfree (bitmap->baseAddr);
726 }
727
728 /* Mac replacement for XFillRectangle. */
729
730 static void
731 XFillRectangle (display, w, gc, x, y, width, height)
732 Display *display;
733 WindowPtr w;
734 GC gc;
735 int x, y;
736 unsigned int width, height;
737 {
738 Rect r;
739
740 #if TARGET_API_MAC_CARBON
741 SetPort (GetWindowPort (w));
742 #else
743 SetPort (w);
744 #endif
745
746 mac_set_colors (gc);
747 SetRect (&r, x, y, x + width, y + height);
748
749 PaintRect (&r); /* using foreground color of gc */
750 }
751
752
753 /* Mac replacement for XDrawRectangle: dest is a window. */
754
755 static void
756 mac_draw_rectangle (display, w, gc, x, y, width, height)
757 Display *display;
758 WindowPtr w;
759 GC gc;
760 int x, y;
761 unsigned int width, height;
762 {
763 Rect r;
764
765 #if TARGET_API_MAC_CARBON
766 SetPort (GetWindowPort (w));
767 #else
768 SetPort (w);
769 #endif
770
771 mac_set_colors (gc);
772 SetRect (&r, x, y, x + width + 1, y + height + 1);
773
774 FrameRect (&r); /* using foreground color of gc */
775 }
776
777
778 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
779
780 static void
781 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
782 Display *display;
783 Pixmap p;
784 GC gc;
785 int x, y;
786 unsigned int width, height;
787 {
788 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
789 Rect r;
790
791 #if TARGET_API_MAC_CARBON
792 SetPort (GetWindowPort (w));
793 #else
794 SetPort (w);
795 #endif
796
797 mac_set_colors (gc);
798 SetRect (&r, x, y, x + width, y + height);
799
800 FrameRect (&r); /* using foreground color of gc */
801 #endif /* 0 */
802 }
803
804
805 static void
806 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
807 bytes_per_char)
808 Display *display;
809 WindowPtr w;
810 GC gc;
811 int x, y;
812 char *buf;
813 int nchars, mode, bytes_per_char;
814 {
815 #if TARGET_API_MAC_CARBON
816 SetPort (GetWindowPort (w));
817 #else
818 SetPort (w);
819 #endif
820
821 mac_set_colors (gc);
822
823 TextFont (gc->font->mac_fontnum);
824 TextSize (gc->font->mac_fontsize);
825 TextFace (gc->font->mac_fontface);
826 TextMode (mode);
827
828 MoveTo (x, y);
829 DrawText (buf, 0, nchars * bytes_per_char);
830 }
831
832
833 /* Mac replacement for XDrawString. */
834
835 static void
836 XDrawString (display, w, gc, x, y, buf, nchars)
837 Display *display;
838 WindowPtr w;
839 GC gc;
840 int x, y;
841 char *buf;
842 int nchars;
843 {
844 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
845 }
846
847
848 /* Mac replacement for XDrawString16. */
849
850 static void
851 XDrawString16 (display, w, gc, x, y, buf, nchars)
852 Display *display;
853 WindowPtr w;
854 GC gc;
855 int x, y;
856 XChar2b *buf;
857 int nchars;
858 {
859 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
860 2);
861 }
862
863
864 /* Mac replacement for XDrawImageString. */
865
866 static void
867 XDrawImageString (display, w, gc, x, y, buf, nchars)
868 Display *display;
869 WindowPtr w;
870 GC gc;
871 int x, y;
872 char *buf;
873 int nchars;
874 {
875 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
876 }
877
878
879 /* Mac replacement for XDrawString16. */
880
881 static void
882 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
883 Display *display;
884 WindowPtr w;
885 GC gc;
886 int x, y;
887 XChar2b *buf;
888 int nchars;
889 {
890 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
891 2);
892 }
893
894
895 /* Mac replacement for XCopyArea: dest must be window. */
896
897 static void
898 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
899 dest_y)
900 Display *display;
901 Pixmap src;
902 WindowPtr dest;
903 GC gc;
904 int src_x, src_y;
905 unsigned int width, height;
906 int dest_x, dest_y;
907 {
908 Rect src_r, dest_r;
909
910 #if TARGET_API_MAC_CARBON
911 SetPort (GetWindowPort (dest));
912 #else
913 SetPort (dest);
914 #endif
915
916 mac_set_colors (gc);
917
918 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
919 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
920
921 #if TARGET_API_MAC_CARBON
922 {
923 PixMapHandle pmh;
924
925 LockPortBits (GetWindowPort (dest));
926 pmh = GetPortPixMap (GetWindowPort (dest));
927 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
928 UnlockPortBits (GetWindowPort (dest));
929 }
930 #else /* not TARGET_API_MAC_CARBON */
931 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
932 #endif /* not TARGET_API_MAC_CARBON */
933 }
934
935
936 #if 0
937 /* Convert a pair of local coordinates to global (screen) coordinates.
938 Assume graphic port has been properly set. */
939 static void
940 local_to_global_coord (short *h, short *v)
941 {
942 Point p;
943
944 p.h = *h;
945 p.v = *v;
946
947 LocalToGlobal (&p);
948
949 *h = p.h;
950 *v = p.v;
951 }
952 #endif
953
954 /* Mac replacement for XCopyArea: used only for scrolling. */
955
956 static void
957 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
958 Display *display;
959 WindowPtr w;
960 GC gc;
961 int src_x, src_y;
962 unsigned int width, height;
963 int dest_x, dest_y;
964 {
965 #if TARGET_API_MAC_CARBON
966 Rect gw_r, src_r, dest_r;
967 PixMapHandle pmh;
968
969 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
970 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
971
972 SetPort (GetWindowPort (w));
973 mac_set_colors (gc);
974
975 LockPortBits (GetWindowPort (w));
976 pmh = GetPortPixMap (GetWindowPort (w));
977 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
978 UnlockPortBits (GetWindowPort (w));
979 #else /* not TARGET_API_MAC_CARBON */
980 Rect src_r, dest_r;
981
982 SetPort (w);
983 #if 0
984 mac_set_colors (gc);
985 #endif
986
987 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
988 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
989
990 #if 0
991 /* Need to use global coordinates and screenBits since src and dest
992 areas overlap in general. */
993 local_to_global_coord (&src_r.left, &src_r.top);
994 local_to_global_coord (&src_r.right, &src_r.bottom);
995 local_to_global_coord (&dest_r.left, &dest_r.top);
996 local_to_global_coord (&dest_r.right, &dest_r.bottom);
997
998 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
999 #else
1000 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1001 color mapping in CopyBits. Otherwise, it will be slow. */
1002 ForeColor (blackColor);
1003 BackColor (whiteColor);
1004 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1005
1006 mac_set_colors (gc);
1007 #endif
1008 #endif /* not TARGET_API_MAC_CARBON */
1009 }
1010
1011
1012 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1013
1014 static void
1015 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1016 dest_x, dest_y)
1017 Display *display;
1018 Pixmap src;
1019 Pixmap dest;
1020 GC gc;
1021 int src_x, src_y;
1022 unsigned int width, height;
1023 int dest_x, dest_y;
1024 {
1025 Rect src_r, dest_r;
1026 int src_right = ((PixMap *) src)->bounds.right;
1027 int src_bottom = ((PixMap *) src)->bounds.bottom;
1028 int w = src_right - src_x;
1029 int h = src_bottom - src_y;
1030
1031 mac_set_colors (gc);
1032
1033 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
1034 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
1035
1036 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
1037 }
1038
1039
1040 /* Mac replacement for XChangeGC. */
1041
1042 static void
1043 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1044 XGCValues *xgcv)
1045 {
1046 if (mask & GCForeground)
1047 gc->foreground = xgcv->foreground;
1048 if (mask & GCBackground)
1049 gc->background = xgcv->background;
1050 if (mask & GCFont)
1051 gc->font = xgcv->font;
1052 }
1053
1054
1055 /* Mac replacement for XCreateGC. */
1056
1057 XGCValues *
1058 XCreateGC (void * ignore, Window window, unsigned long mask,
1059 XGCValues *xgcv)
1060 {
1061 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1062 bzero (gc, sizeof (XGCValues));
1063
1064 XChangeGC (ignore, gc, mask, xgcv);
1065
1066 return gc;
1067 }
1068
1069
1070 /* Used in xfaces.c. */
1071
1072 void
1073 XFreeGC (display, gc)
1074 Display *display;
1075 GC gc;
1076 {
1077 xfree (gc);
1078 }
1079
1080
1081 /* Mac replacement for XGetGCValues. */
1082
1083 static void
1084 XGetGCValues (void* ignore, XGCValues *gc,
1085 unsigned long mask, XGCValues *xgcv)
1086 {
1087 XChangeGC (ignore, xgcv, mask, gc);
1088 }
1089
1090
1091 /* Mac replacement for XSetForeground. */
1092
1093 static void
1094 XSetForeground (display, gc, color)
1095 Display *display;
1096 GC gc;
1097 unsigned long color;
1098 {
1099 gc->foreground = color;
1100 }
1101
1102
1103 /* Mac replacement for XSetFont. */
1104
1105 static void
1106 XSetFont (display, gc, font)
1107 Display *display;
1108 GC gc;
1109 XFontStruct *font;
1110 {
1111 gc->font = font;
1112 }
1113
1114
1115 static void
1116 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1117 int *direction,int *font_ascent,
1118 int *font_descent, XCharStruct *cs)
1119 {
1120 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1121 }
1122
1123
1124 /* x_sync is a no-op on Mac. */
1125 void
1126 x_sync (f)
1127 void *f;
1128 {
1129 }
1130
1131
1132 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1133 Calls to XFlush should be unnecessary because the X output buffer
1134 is flushed automatically as needed by calls to XPending,
1135 XNextEvent, or XWindowEvent according to the XFlush man page.
1136 XTread_socket calls XPending. Removing XFlush improves
1137 performance. */
1138
1139 #if TARGET_API_MAC_CARBON
1140 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1141 #else
1142 #define XFlush(DISPLAY) (void) 0
1143 #endif
1144
1145 /* Flush display of frame F, or of all frames if F is null. */
1146
1147 void
1148 x_flush (f)
1149 struct frame *f;
1150 {
1151 #if TARGET_API_MAC_CARBON
1152 BLOCK_INPUT;
1153 if (f == NULL)
1154 {
1155 Lisp_Object rest, frame;
1156 FOR_EACH_FRAME (rest, frame)
1157 x_flush (XFRAME (frame));
1158 }
1159 else if (FRAME_X_P (f))
1160 XFlush (FRAME_MAC_DISPLAY (f));
1161 UNBLOCK_INPUT;
1162 #endif /* TARGET_API_MAC_CARBON */
1163 }
1164
1165
1166 \f
1167 /* Return the struct mac_display_info corresponding to DPY. There's
1168 only one. */
1169
1170 struct mac_display_info *
1171 mac_display_info_for_display (dpy)
1172 Display *dpy;
1173 {
1174 return &one_mac_display_info;
1175 }
1176
1177
1178 \f
1179 /***********************************************************************
1180 Starting and ending an update
1181 ***********************************************************************/
1182
1183 /* Start an update of frame F. This function is installed as a hook
1184 for update_begin, i.e. it is called when update_begin is called.
1185 This function is called prior to calls to x_update_window_begin for
1186 each window being updated. */
1187
1188 static void
1189 x_update_begin (f)
1190 struct frame *f;
1191 {
1192 /* Nothing to do. */
1193 }
1194
1195
1196 /* Start update of window W. Set the global variable updated_window
1197 to the window being updated and set output_cursor to the cursor
1198 position of W. */
1199
1200 static void
1201 x_update_window_begin (w)
1202 struct window *w;
1203 {
1204 struct frame *f = XFRAME (WINDOW_FRAME (w));
1205 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1206
1207 updated_window = w;
1208 set_output_cursor (&w->cursor);
1209
1210 BLOCK_INPUT;
1211
1212 if (f == display_info->mouse_face_mouse_frame)
1213 {
1214 /* Don't do highlighting for mouse motion during the update. */
1215 display_info->mouse_face_defer = 1;
1216
1217 /* If F needs to be redrawn, simply forget about any prior mouse
1218 highlighting. */
1219 if (FRAME_GARBAGED_P (f))
1220 display_info->mouse_face_window = Qnil;
1221
1222 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1223 their mouse_face_p flag set, which means that they are always
1224 unequal to rows in a desired matrix which never have that
1225 flag set. So, rows containing mouse-face glyphs are never
1226 scrolled, and we don't have to switch the mouse highlight off
1227 here to prevent it from being scrolled. */
1228
1229 /* Can we tell that this update does not affect the window
1230 where the mouse highlight is? If so, no need to turn off.
1231 Likewise, don't do anything if the frame is garbaged;
1232 in that case, the frame's current matrix that we would use
1233 is all wrong, and we will redisplay that line anyway. */
1234 if (!NILP (display_info->mouse_face_window)
1235 && w == XWINDOW (display_info->mouse_face_window))
1236 {
1237 int i;
1238
1239 for (i = 0; i < w->desired_matrix->nrows; ++i)
1240 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1241 break;
1242
1243 if (i < w->desired_matrix->nrows)
1244 clear_mouse_face (display_info);
1245 }
1246 #endif /* 0 */
1247 }
1248
1249 UNBLOCK_INPUT;
1250 }
1251
1252
1253 /* Draw a vertical window border to the right of window W if W doesn't
1254 have vertical scroll bars. */
1255
1256 static void
1257 x_draw_vertical_border (w)
1258 struct window *w;
1259 {
1260 struct frame *f = XFRAME (WINDOW_FRAME (w));
1261
1262 /* Redraw borders between horizontally adjacent windows. Don't
1263 do it for frames with vertical scroll bars because either the
1264 right scroll bar of a window, or the left scroll bar of its
1265 neighbor will suffice as a border. */
1266 if (!WINDOW_RIGHTMOST_P (w)
1267 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1268 {
1269 int x0, x1, y0, y1;
1270
1271 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
1272 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1273 y1 -= 1;
1274
1275 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1276 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1277 }
1278 }
1279
1280
1281 /* End update of window W (which is equal to updated_window).
1282
1283 Draw vertical borders between horizontally adjacent windows, and
1284 display W's cursor if CURSOR_ON_P is non-zero.
1285
1286 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1287 glyphs in mouse-face were overwritten. In that case we have to
1288 make sure that the mouse-highlight is properly redrawn.
1289
1290 W may be a menu bar pseudo-window in case we don't have X toolkit
1291 support. Such windows don't have a cursor, so don't display it
1292 here. */
1293
1294 static void
1295 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1296 struct window *w;
1297 int cursor_on_p, mouse_face_overwritten_p;
1298 {
1299 struct mac_display_info *dpyinfo
1300 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1301
1302 if (!w->pseudo_window_p)
1303 {
1304 BLOCK_INPUT;
1305
1306 if (cursor_on_p)
1307 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1308 output_cursor.vpos,
1309 output_cursor.x, output_cursor.y);
1310
1311 x_draw_vertical_border (w);
1312 UNBLOCK_INPUT;
1313 }
1314
1315 /* If a row with mouse-face was overwritten, arrange for
1316 XTframe_up_to_date to redisplay the mouse highlight. */
1317 if (mouse_face_overwritten_p)
1318 {
1319 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1320 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1321 dpyinfo->mouse_face_window = Qnil;
1322 }
1323
1324 #if 0
1325 /* Unhide the caret. This won't actually show the cursor, unless it
1326 was visible before the corresponding call to HideCaret in
1327 x_update_window_begin. */
1328 if (w32_use_visible_system_caret)
1329 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1330 #endif
1331
1332 updated_window = NULL;
1333 }
1334
1335
1336 /* End update of frame F. This function is installed as a hook in
1337 update_end. */
1338
1339 static void
1340 x_update_end (f)
1341 struct frame *f;
1342 {
1343 /* Reset the background color of Mac OS Window to that of the frame after
1344 update so that it is used by Mac Toolbox to clear the update region before
1345 an update event is generated. */
1346 #if TARGET_API_MAC_CARBON
1347 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1348 #else
1349 SetPort (FRAME_MAC_WINDOW (f));
1350 #endif
1351
1352 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1353
1354 /* Mouse highlight may be displayed again. */
1355 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1356
1357 BLOCK_INPUT;
1358 XFlush (FRAME_MAC_DISPLAY (f));
1359 UNBLOCK_INPUT;
1360 }
1361
1362
1363 /* This function is called from various places in xdisp.c whenever a
1364 complete update has been performed. The global variable
1365 updated_window is not available here. */
1366
1367 static void
1368 XTframe_up_to_date (f)
1369 struct frame *f;
1370 {
1371 if (FRAME_X_P (f))
1372 {
1373 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1374
1375 if (dpyinfo->mouse_face_deferred_gc
1376 || f == dpyinfo->mouse_face_mouse_frame)
1377 {
1378 BLOCK_INPUT;
1379 if (dpyinfo->mouse_face_mouse_frame)
1380 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1381 dpyinfo->mouse_face_mouse_x,
1382 dpyinfo->mouse_face_mouse_y);
1383 dpyinfo->mouse_face_deferred_gc = 0;
1384 UNBLOCK_INPUT;
1385 }
1386 }
1387 }
1388
1389
1390 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1391 arrow bitmaps, or clear the fringes if no bitmaps are required
1392 before DESIRED_ROW is made current. The window being updated is
1393 found in updated_window. This function is called from
1394 update_window_line only if it is known that there are differences
1395 between bitmaps to be drawn between current row and DESIRED_ROW. */
1396
1397 static void
1398 x_after_update_window_line (desired_row)
1399 struct glyph_row *desired_row;
1400 {
1401 struct window *w = updated_window;
1402 struct frame *f;
1403 int width, height;
1404
1405 xassert (w);
1406
1407 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1408 {
1409 BLOCK_INPUT;
1410 x_draw_row_fringe_bitmaps (w, desired_row);
1411 UNBLOCK_INPUT;
1412 }
1413
1414 /* When a window has disappeared, make sure that no rest of
1415 full-width rows stays visible in the internal border. Could
1416 check here if updated_window is the leftmost/rightmost window,
1417 but I guess it's not worth doing since vertically split windows
1418 are almost never used, internal border is rarely set, and the
1419 overhead is very small. */
1420 if (windows_or_buffers_changed
1421 && desired_row->full_width_p
1422 && (f = XFRAME (w->frame),
1423 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1424 width != 0)
1425 && (height = desired_row->visible_height,
1426 height > 0))
1427 {
1428 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1429 /* Internal border is drawn below the tool bar. */
1430 if (WINDOWP (f->tool_bar_window)
1431 && w == XWINDOW (f->tool_bar_window))
1432 y -= width;
1433
1434 BLOCK_INPUT;
1435
1436 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1437 0, y, width, height, 0);
1438 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1439 f->output_data.mac->pixel_width - width, y,
1440 width, height, 0);
1441
1442 UNBLOCK_INPUT;
1443 }
1444 }
1445
1446
1447 /* Draw the bitmap WHICH in one of the left or right fringes of
1448 window W. ROW is the glyph row for which to display the bitmap; it
1449 determines the vertical position at which the bitmap has to be
1450 drawn. */
1451
1452 static void
1453 x_draw_fringe_bitmap (w, row, which, left_p)
1454 struct window *w;
1455 struct glyph_row *row;
1456 enum fringe_bitmap_type which;
1457 int left_p;
1458 {
1459 struct frame *f = XFRAME (WINDOW_FRAME (w));
1460 Display *display = FRAME_MAC_DISPLAY (f);
1461 WindowPtr window = FRAME_MAC_WINDOW (f);
1462 int x, y, wd, h, dy;
1463 int b1, b2;
1464 unsigned char *bits;
1465 BitMap bitmap;
1466 XGCValues gcv;
1467 GC gc = f->output_data.mac->normal_gc;
1468 struct face *face;
1469
1470 /* Must clip because of partially visible lines. */
1471 x_clip_to_row (w, row, gc, 1);
1472
1473 /* Convert row to frame coordinates. */
1474 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1475
1476 switch (which)
1477 {
1478 case NO_FRINGE_BITMAP:
1479 wd = 0;
1480 h = 0;
1481 break;
1482
1483 case LEFT_TRUNCATION_BITMAP:
1484 wd = left_width;
1485 h = left_height;
1486 bits = left_bits;
1487 break;
1488
1489 case OVERLAY_ARROW_BITMAP:
1490 wd = ov_width;
1491 h = ov_height;
1492 bits = ov_bits;
1493 break;
1494
1495 case RIGHT_TRUNCATION_BITMAP:
1496 wd = right_width;
1497 h = right_height;
1498 bits = right_bits;
1499 break;
1500
1501 case CONTINUED_LINE_BITMAP:
1502 wd = continued_width;
1503 h = continued_height;
1504 bits = continued_bits;
1505 break;
1506
1507 case CONTINUATION_LINE_BITMAP:
1508 wd = continuation_width;
1509 h = continuation_height;
1510 bits = continuation_bits;
1511 break;
1512
1513 case ZV_LINE_BITMAP:
1514 wd = zv_width;
1515 h = zv_height - (y % zv_period);
1516 bits = zv_bits + (y % zv_period);
1517 break;
1518
1519 default:
1520 abort ();
1521 }
1522
1523 /* Clip bitmap if too high. */
1524 if (h > row->height)
1525 h = row->height;
1526
1527 /* Set dy to the offset in the row to start drawing the bitmap. */
1528 dy = (row->height - h) / 2;
1529
1530 /* Draw the bitmap. */
1531 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
1532 PREPARE_FACE_FOR_DISPLAY (f, face);
1533
1534 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1535 the fringe. */
1536 b1 = -1;
1537 if (left_p)
1538 {
1539 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
1540 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
1541 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1542 - wd
1543 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
1544 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
1545 {
1546 /* If W has a vertical border to its left, don't draw over it. */
1547 int border = ((XFASTINT (w->left) > 0
1548 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1549 ? 1 : 0);
1550 b1 = (window_box_left (w, -1)
1551 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1552 + border);
1553 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1554 }
1555 }
1556 else
1557 {
1558 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
1559 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1560 x = (window_box_right (w, -1)
1561 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
1562 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1563 the fringe. */
1564 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
1565 {
1566 b1 = window_box_right (w, -1);
1567 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1568 }
1569 }
1570
1571 if (b1 >= 0)
1572 {
1573 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1574 XGCValues gcv;
1575 gcv.foreground = face->background;
1576
1577 #if 0 /* MAC_TODO: stipple */
1578 /* In case the same realized face is used for fringes and
1579 for something displayed in the text (e.g. face `region' on
1580 mono-displays, the fill style may have been changed to
1581 FillSolid in x_draw_glyph_string_background. */
1582 if (face->stipple)
1583 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1584 else
1585 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1586 #endif
1587
1588 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1589 &gcv,
1590 b1,
1591 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1592 row->y)),
1593 b2,
1594 row->visible_height);
1595
1596 #if 0 /* MAC_TODO: stipple */
1597 if (!face->stipple)
1598 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1599 #endif
1600 }
1601
1602 if (which == NO_FRINGE_BITMAP)
1603 {
1604 mac_reset_clipping (display, window);
1605 return;
1606 }
1607
1608 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1609 gcv.foreground = face->foreground;
1610 gcv.background = face->background;
1611
1612 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1613
1614 mac_free_bitmap (&bitmap);
1615 mac_reset_clipping (display, window);
1616 }
1617
1618
1619 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1620 function with input blocked. */
1621
1622 static void
1623 x_draw_row_fringe_bitmaps (w, row)
1624 struct window *w;
1625 struct glyph_row *row;
1626 {
1627 struct frame *f = XFRAME (w->frame);
1628 enum fringe_bitmap_type bitmap;
1629
1630 xassert (interrupt_input_blocked);
1631
1632 /* If row is completely invisible, because of vscrolling, we
1633 don't have to draw anything. */
1634 if (row->visible_height <= 0)
1635 return;
1636
1637 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1638 {
1639 /* Decide which bitmap to draw in the left fringe. */
1640 if (row->overlay_arrow_p)
1641 bitmap = OVERLAY_ARROW_BITMAP;
1642 else if (row->truncated_on_left_p)
1643 bitmap = LEFT_TRUNCATION_BITMAP;
1644 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1645 bitmap = CONTINUATION_LINE_BITMAP;
1646 else if (row->indicate_empty_line_p)
1647 bitmap = ZV_LINE_BITMAP;
1648 else
1649 bitmap = NO_FRINGE_BITMAP;
1650
1651 x_draw_fringe_bitmap (w, row, bitmap, 1);
1652 }
1653
1654 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1655 {
1656 /* Decide which bitmap to draw in the right fringe. */
1657 if (row->truncated_on_right_p)
1658 bitmap = RIGHT_TRUNCATION_BITMAP;
1659 else if (row->continued_p)
1660 bitmap = CONTINUED_LINE_BITMAP;
1661 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1662 bitmap = ZV_LINE_BITMAP;
1663 else
1664 bitmap = NO_FRINGE_BITMAP;
1665
1666 x_draw_fringe_bitmap (w, row, bitmap, 0);
1667 }
1668 }
1669
1670 \f
1671 /* This is called when starting Emacs and when restarting after
1672 suspend. When starting Emacs, no window is mapped. And nothing
1673 must be done to Emacs's own window if it is suspended (though that
1674 rarely happens). */
1675
1676 static void
1677 XTset_terminal_modes ()
1678 {
1679 }
1680
1681 /* This is called when exiting or suspending Emacs. Exiting will make
1682 the windows go away, and suspending requires no action. */
1683
1684 static void
1685 XTreset_terminal_modes ()
1686 {
1687 }
1688
1689
1690 \f
1691 /***********************************************************************
1692 Output Cursor
1693 ***********************************************************************/
1694
1695 /* Set the global variable output_cursor to CURSOR. All cursor
1696 positions are relative to updated_window. */
1697
1698 static void
1699 set_output_cursor (cursor)
1700 struct cursor_pos *cursor;
1701 {
1702 output_cursor.hpos = cursor->hpos;
1703 output_cursor.vpos = cursor->vpos;
1704 output_cursor.x = cursor->x;
1705 output_cursor.y = cursor->y;
1706 }
1707
1708
1709 /* Set a nominal cursor position.
1710
1711 HPOS and VPOS are column/row positions in a window glyph matrix. X
1712 and Y are window text area relative pixel positions.
1713
1714 If this is done during an update, updated_window will contain the
1715 window that is being updated and the position is the future output
1716 cursor position for that window. If updated_window is null, use
1717 selected_window and display the cursor at the given position. */
1718
1719 static void
1720 XTcursor_to (vpos, hpos, y, x)
1721 int vpos, hpos, y, x;
1722 {
1723 struct window *w;
1724
1725 /* If updated_window is not set, work on selected_window. */
1726 if (updated_window)
1727 w = updated_window;
1728 else
1729 w = XWINDOW (selected_window);
1730
1731 /* Set the output cursor. */
1732 output_cursor.hpos = hpos;
1733 output_cursor.vpos = vpos;
1734 output_cursor.x = x;
1735 output_cursor.y = y;
1736
1737 /* If not called as part of an update, really display the cursor.
1738 This will also set the cursor position of W. */
1739 if (updated_window == NULL)
1740 {
1741 BLOCK_INPUT;
1742 x_display_cursor (w, 1, hpos, vpos, x, y);
1743 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1744 UNBLOCK_INPUT;
1745 }
1746 }
1747
1748
1749 \f
1750 /***********************************************************************
1751 Display Iterator
1752 ***********************************************************************/
1753
1754 /* Function prototypes of this page. */
1755
1756 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1757 struct glyph *,
1758 XChar2b *,
1759 int *));
1760 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1761 int, XChar2b *, int));
1762 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1763 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1764 static void x_append_glyph P_ ((struct it *));
1765 static void x_append_composite_glyph P_ ((struct it *));
1766 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1767 int, int, double));
1768 static void x_produce_glyphs P_ ((struct it *));
1769 static void x_produce_image_glyph P_ ((struct it *it));
1770
1771
1772 /* Return a pointer to per-char metric information in FONT of a
1773 character pointed by B which is a pointer to an XChar2b. */
1774
1775 #define PER_CHAR_METRIC(font, b) \
1776 ((font)->per_char \
1777 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1778 + (((font)->min_byte1 || (font)->max_byte1) \
1779 ? (((b)->byte1 - (font)->min_byte1) \
1780 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1781 : 0)) \
1782 : &((font)->max_bounds))
1783
1784
1785 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1786 is not contained in the font. */
1787
1788 static INLINE XCharStruct *
1789 x_per_char_metric (font, char2b)
1790 XFontStruct *font;
1791 XChar2b *char2b;
1792 {
1793 /* The result metric information. */
1794 XCharStruct *pcm = NULL;
1795
1796 xassert (font && char2b);
1797
1798 if (font->per_char != NULL)
1799 {
1800 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1801 {
1802 /* min_char_or_byte2 specifies the linear character index
1803 corresponding to the first element of the per_char array,
1804 max_char_or_byte2 is the index of the last character. A
1805 character with non-zero CHAR2B->byte1 is not in the font.
1806 A character with byte2 less than min_char_or_byte2 or
1807 greater max_char_or_byte2 is not in the font. */
1808 if (char2b->byte1 == 0
1809 && char2b->byte2 >= font->min_char_or_byte2
1810 && char2b->byte2 <= font->max_char_or_byte2)
1811 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1812 }
1813 else
1814 {
1815 /* If either min_byte1 or max_byte1 are nonzero, both
1816 min_char_or_byte2 and max_char_or_byte2 are less than
1817 256, and the 2-byte character index values corresponding
1818 to the per_char array element N (counting from 0) are:
1819
1820 byte1 = N/D + min_byte1
1821 byte2 = N\D + min_char_or_byte2
1822
1823 where:
1824
1825 D = max_char_or_byte2 - min_char_or_byte2 + 1
1826 / = integer division
1827 \ = integer modulus */
1828 if (char2b->byte1 >= font->min_byte1
1829 && char2b->byte1 <= font->max_byte1
1830 && char2b->byte2 >= font->min_char_or_byte2
1831 && char2b->byte2 <= font->max_char_or_byte2)
1832 {
1833 pcm = (font->per_char
1834 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1835 * (char2b->byte1 - font->min_byte1))
1836 + (char2b->byte2 - font->min_char_or_byte2));
1837 }
1838 }
1839 }
1840 else
1841 {
1842 /* If the per_char pointer is null, all glyphs between the first
1843 and last character indexes inclusive have the same
1844 information, as given by both min_bounds and max_bounds. */
1845 if (char2b->byte2 >= font->min_char_or_byte2
1846 && char2b->byte2 <= font->max_char_or_byte2)
1847 pcm = &font->max_bounds;
1848 }
1849
1850 return ((pcm == NULL
1851 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1852 ? NULL : pcm);
1853 }
1854
1855
1856 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1857 the two-byte form of C. Encoding is returned in *CHAR2B. */
1858
1859 static INLINE void
1860 x_encode_char (c, char2b, font_info)
1861 int c;
1862 XChar2b *char2b;
1863 struct font_info *font_info;
1864 {
1865 int charset = CHAR_CHARSET (c);
1866 XFontStruct *font = font_info->font;
1867
1868 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1869 This may be either a program in a special encoder language or a
1870 fixed encoding. */
1871 if (font_info->font_encoder)
1872 {
1873 /* It's a program. */
1874 struct ccl_program *ccl = font_info->font_encoder;
1875
1876 if (CHARSET_DIMENSION (charset) == 1)
1877 {
1878 ccl->reg[0] = charset;
1879 ccl->reg[1] = char2b->byte2;
1880 }
1881 else
1882 {
1883 ccl->reg[0] = charset;
1884 ccl->reg[1] = char2b->byte1;
1885 ccl->reg[2] = char2b->byte2;
1886 }
1887
1888 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1889
1890 /* We assume that MSBs are appropriately set/reset by CCL
1891 program. */
1892 if (font->max_byte1 == 0) /* 1-byte font */
1893 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1894 else
1895 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1896 }
1897 else if (font_info->encoding[charset])
1898 {
1899 /* Fixed encoding scheme. See fontset.h for the meaning of the
1900 encoding numbers. */
1901 int enc = font_info->encoding[charset];
1902
1903 if ((enc == 1 || enc == 2)
1904 && CHARSET_DIMENSION (charset) == 2)
1905 char2b->byte1 |= 0x80;
1906
1907 if (enc == 1 || enc == 3)
1908 char2b->byte2 |= 0x80;
1909
1910 if (enc == 4)
1911 {
1912 int sjis1, sjis2;
1913
1914 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1915 char2b->byte1 = sjis1;
1916 char2b->byte2 = sjis2;
1917 }
1918 }
1919 }
1920
1921
1922 /* Get face and two-byte form of character C in face FACE_ID on frame
1923 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1924 means we want to display multibyte text. Value is a pointer to a
1925 realized face that is ready for display. */
1926
1927 static INLINE struct face *
1928 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1929 struct frame *f;
1930 int c, face_id;
1931 XChar2b *char2b;
1932 int multibyte_p;
1933 {
1934 struct face *face = FACE_FROM_ID (f, face_id);
1935
1936 if (!multibyte_p)
1937 {
1938 /* Unibyte case. We don't have to encode, but we have to make
1939 sure to use a face suitable for unibyte. */
1940 char2b->byte1 = 0;
1941 char2b->byte2 = c;
1942 face_id = FACE_FOR_CHAR (f, face, c);
1943 face = FACE_FROM_ID (f, face_id);
1944 }
1945 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1946 {
1947 /* Case of ASCII in a face known to fit ASCII. */
1948 char2b->byte1 = 0;
1949 char2b->byte2 = c;
1950 }
1951 else
1952 {
1953 int c1, c2, charset;
1954
1955 /* Split characters into bytes. If c2 is -1 afterwards, C is
1956 really a one-byte character so that byte1 is zero. */
1957 SPLIT_CHAR (c, charset, c1, c2);
1958 if (c2 > 0)
1959 char2b->byte1 = c1, char2b->byte2 = c2;
1960 else
1961 char2b->byte1 = 0, char2b->byte2 = c1;
1962
1963 /* Maybe encode the character in *CHAR2B. */
1964 if (face->font != NULL)
1965 {
1966 struct font_info *font_info
1967 = FONT_INFO_FROM_ID (f, face->font_info_id);
1968 if (font_info)
1969 x_encode_char (c, char2b, font_info);
1970 }
1971 }
1972
1973 /* Make sure X resources of the face are allocated. */
1974 xassert (face != NULL);
1975 PREPARE_FACE_FOR_DISPLAY (f, face);
1976
1977 return face;
1978 }
1979
1980
1981 /* Get face and two-byte form of character glyph GLYPH on frame F.
1982 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1983 a pointer to a realized face that is ready for display. */
1984
1985 static INLINE struct face *
1986 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1987 struct frame *f;
1988 struct glyph *glyph;
1989 XChar2b *char2b;
1990 int *two_byte_p;
1991 {
1992 struct face *face;
1993
1994 xassert (glyph->type == CHAR_GLYPH);
1995 face = FACE_FROM_ID (f, glyph->face_id);
1996
1997 if (two_byte_p)
1998 *two_byte_p = 0;
1999
2000 if (!glyph->multibyte_p)
2001 {
2002 /* Unibyte case. We don't have to encode, but we have to make
2003 sure to use a face suitable for unibyte. */
2004 char2b->byte1 = 0;
2005 char2b->byte2 = glyph->u.ch;
2006 }
2007 else if (glyph->u.ch < 128
2008 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
2009 {
2010 /* Case of ASCII in a face known to fit ASCII. */
2011 char2b->byte1 = 0;
2012 char2b->byte2 = glyph->u.ch;
2013 }
2014 else
2015 {
2016 int c1, c2, charset;
2017
2018 /* Split characters into bytes. If c2 is -1 afterwards, C is
2019 really a one-byte character so that byte1 is zero. */
2020 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
2021 if (c2 > 0)
2022 char2b->byte1 = c1, char2b->byte2 = c2;
2023 else
2024 char2b->byte1 = 0, char2b->byte2 = c1;
2025
2026 /* Maybe encode the character in *CHAR2B. */
2027 if (charset != CHARSET_ASCII)
2028 {
2029 struct font_info *font_info
2030 = FONT_INFO_FROM_ID (f, face->font_info_id);
2031 if (font_info)
2032 {
2033 x_encode_char (glyph->u.ch, char2b, font_info);
2034 if (two_byte_p)
2035 *two_byte_p
2036 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2037 }
2038 }
2039 }
2040
2041 /* Make sure X resources of the face are allocated. */
2042 xassert (face != NULL);
2043 PREPARE_FACE_FOR_DISPLAY (f, face);
2044 return face;
2045 }
2046
2047
2048 /* Store one glyph for IT->char_to_display in IT->glyph_row.
2049 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2050
2051 static INLINE void
2052 x_append_glyph (it)
2053 struct it *it;
2054 {
2055 struct glyph *glyph;
2056 enum glyph_row_area area = it->area;
2057
2058 xassert (it->glyph_row);
2059 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
2060
2061 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2062 if (glyph < it->glyph_row->glyphs[area + 1])
2063 {
2064 glyph->charpos = CHARPOS (it->position);
2065 glyph->object = it->object;
2066 glyph->pixel_width = it->pixel_width;
2067 glyph->voffset = it->voffset;
2068 glyph->type = CHAR_GLYPH;
2069 glyph->multibyte_p = it->multibyte_p;
2070 glyph->left_box_line_p = it->start_of_box_run_p;
2071 glyph->right_box_line_p = it->end_of_box_run_p;
2072 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2073 || it->phys_descent > it->descent);
2074 glyph->padding_p = 0;
2075 glyph->glyph_not_available_p = it->glyph_not_available_p;
2076 glyph->face_id = it->face_id;
2077 glyph->u.ch = it->char_to_display;
2078 ++it->glyph_row->used[area];
2079 }
2080 }
2081
2082 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2083 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2084
2085 static INLINE void
2086 x_append_composite_glyph (it)
2087 struct it *it;
2088 {
2089 struct glyph *glyph;
2090 enum glyph_row_area area = it->area;
2091
2092 xassert (it->glyph_row);
2093
2094 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2095 if (glyph < it->glyph_row->glyphs[area + 1])
2096 {
2097 glyph->charpos = CHARPOS (it->position);
2098 glyph->object = it->object;
2099 glyph->pixel_width = it->pixel_width;
2100 glyph->voffset = it->voffset;
2101 glyph->type = COMPOSITE_GLYPH;
2102 glyph->multibyte_p = it->multibyte_p;
2103 glyph->left_box_line_p = it->start_of_box_run_p;
2104 glyph->right_box_line_p = it->end_of_box_run_p;
2105 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2106 || it->phys_descent > it->descent);
2107 glyph->padding_p = 0;
2108 glyph->glyph_not_available_p = 0;
2109 glyph->face_id = it->face_id;
2110 glyph->u.cmp_id = it->cmp_id;
2111 ++it->glyph_row->used[area];
2112 }
2113 }
2114
2115
2116 /* Change IT->ascent and IT->height according to the setting of
2117 IT->voffset. */
2118
2119 static INLINE void
2120 take_vertical_position_into_account (it)
2121 struct it *it;
2122 {
2123 if (it->voffset)
2124 {
2125 if (it->voffset < 0)
2126 /* Increase the ascent so that we can display the text higher
2127 in the line. */
2128 it->ascent += abs (it->voffset);
2129 else
2130 /* Increase the descent so that we can display the text lower
2131 in the line. */
2132 it->descent += it->voffset;
2133 }
2134 }
2135
2136
2137 /* Produce glyphs/get display metrics for the image IT is loaded with.
2138 See the description of struct display_iterator in dispextern.h for
2139 an overview of struct display_iterator. */
2140
2141 static void
2142 x_produce_image_glyph (it)
2143 struct it *it;
2144 {
2145 struct image *img;
2146 struct face *face;
2147
2148 xassert (it->what == IT_IMAGE);
2149
2150 face = FACE_FROM_ID (it->f, it->face_id);
2151 img = IMAGE_FROM_ID (it->f, it->image_id);
2152 xassert (img);
2153
2154 /* Make sure X resources of the face and image are loaded. */
2155 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2156 prepare_image_for_display (it->f, img);
2157
2158 it->ascent = it->phys_ascent = image_ascent (img, face);
2159 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
2160 it->pixel_width = img->width + 2 * img->hmargin;
2161
2162 it->nglyphs = 1;
2163
2164 if (face->box != FACE_NO_BOX)
2165 {
2166 if (face->box_line_width > 0)
2167 {
2168 it->ascent += face->box_line_width;
2169 it->descent += face->box_line_width;
2170 }
2171
2172 if (it->start_of_box_run_p)
2173 it->pixel_width += abs (face->box_line_width);
2174 if (it->end_of_box_run_p)
2175 it->pixel_width += abs (face->box_line_width);
2176 }
2177
2178 take_vertical_position_into_account (it);
2179
2180 if (it->glyph_row)
2181 {
2182 struct glyph *glyph;
2183 enum glyph_row_area area = it->area;
2184
2185 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2186 if (glyph < it->glyph_row->glyphs[area + 1])
2187 {
2188 glyph->charpos = CHARPOS (it->position);
2189 glyph->object = it->object;
2190 glyph->pixel_width = it->pixel_width;
2191 glyph->voffset = it->voffset;
2192 glyph->type = IMAGE_GLYPH;
2193 glyph->multibyte_p = it->multibyte_p;
2194 glyph->left_box_line_p = it->start_of_box_run_p;
2195 glyph->right_box_line_p = it->end_of_box_run_p;
2196 glyph->overlaps_vertically_p = 0;
2197 glyph->padding_p = 0;
2198 glyph->glyph_not_available_p = 0;
2199 glyph->face_id = it->face_id;
2200 glyph->u.img_id = img->id;
2201 ++it->glyph_row->used[area];
2202 }
2203 }
2204 }
2205
2206
2207 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2208 of the glyph, WIDTH and HEIGHT are the width and height of the
2209 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2210 ascent of the glyph (0 <= ASCENT <= 1). */
2211
2212 static void
2213 x_append_stretch_glyph (it, object, width, height, ascent)
2214 struct it *it;
2215 Lisp_Object object;
2216 int width, height;
2217 double ascent;
2218 {
2219 struct glyph *glyph;
2220 enum glyph_row_area area = it->area;
2221
2222 xassert (ascent >= 0 && ascent <= 1);
2223
2224 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2225 if (glyph < it->glyph_row->glyphs[area + 1])
2226 {
2227 glyph->charpos = CHARPOS (it->position);
2228 glyph->object = object;
2229 glyph->pixel_width = width;
2230 glyph->voffset = it->voffset;
2231 glyph->type = STRETCH_GLYPH;
2232 glyph->multibyte_p = it->multibyte_p;
2233 glyph->left_box_line_p = it->start_of_box_run_p;
2234 glyph->right_box_line_p = it->end_of_box_run_p;
2235 glyph->overlaps_vertically_p = 0;
2236 glyph->padding_p = 0;
2237 glyph->glyph_not_available_p = 0;
2238 glyph->face_id = it->face_id;
2239 glyph->u.stretch.ascent = height * ascent;
2240 glyph->u.stretch.height = height;
2241 ++it->glyph_row->used[area];
2242 }
2243 }
2244
2245
2246 /* Produce a stretch glyph for iterator IT. IT->object is the value
2247 of the glyph property displayed. The value must be a list
2248 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2249 being recognized:
2250
2251 1. `:width WIDTH' specifies that the space should be WIDTH *
2252 canonical char width wide. WIDTH may be an integer or floating
2253 point number.
2254
2255 2. `:relative-width FACTOR' specifies that the width of the stretch
2256 should be computed from the width of the first character having the
2257 `glyph' property, and should be FACTOR times that width.
2258
2259 3. `:align-to HPOS' specifies that the space should be wide enough
2260 to reach HPOS, a value in canonical character units.
2261
2262 Exactly one of the above pairs must be present.
2263
2264 4. `:height HEIGHT' specifies that the height of the stretch produced
2265 should be HEIGHT, measured in canonical character units.
2266
2267 5. `:relative-height FACTOR' specifies that the height of the
2268 stretch should be FACTOR times the height of the characters having
2269 the glyph property.
2270
2271 Either none or exactly one of 4 or 5 must be present.
2272
2273 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2274 of the stretch should be used for the ascent of the stretch.
2275 ASCENT must be in the range 0 <= ASCENT <= 100. */
2276
2277 #define NUMVAL(X) \
2278 ((INTEGERP (X) || FLOATP (X)) \
2279 ? XFLOATINT (X) \
2280 : - 1)
2281
2282
2283 static void
2284 x_produce_stretch_glyph (it)
2285 struct it *it;
2286 {
2287 /* (space :width WIDTH :height HEIGHT. */
2288 #if GLYPH_DEBUG
2289 extern Lisp_Object Qspace;
2290 #endif
2291 extern Lisp_Object QCwidth, QCheight, QCascent;
2292 extern Lisp_Object QCrelative_width, QCrelative_height;
2293 extern Lisp_Object QCalign_to;
2294 Lisp_Object prop, plist;
2295 double width = 0, height = 0, ascent = 0;
2296 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2297 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2298
2299 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2300
2301 /* List should start with `space'. */
2302 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2303 plist = XCDR (it->object);
2304
2305 /* Compute the width of the stretch. */
2306 if (prop = Fplist_get (plist, QCwidth),
2307 NUMVAL (prop) > 0)
2308 /* Absolute width `:width WIDTH' specified and valid. */
2309 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2310 else if (prop = Fplist_get (plist, QCrelative_width),
2311 NUMVAL (prop) > 0)
2312 {
2313 /* Relative width `:relative-width FACTOR' specified and valid.
2314 Compute the width of the characters having the `glyph'
2315 property. */
2316 struct it it2;
2317 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2318
2319 it2 = *it;
2320 if (it->multibyte_p)
2321 {
2322 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2323 - IT_BYTEPOS (*it));
2324 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2325 }
2326 else
2327 it2.c = *p, it2.len = 1;
2328
2329 it2.glyph_row = NULL;
2330 it2.what = IT_CHARACTER;
2331 x_produce_glyphs (&it2);
2332 width = NUMVAL (prop) * it2.pixel_width;
2333 }
2334 else if (prop = Fplist_get (plist, QCalign_to),
2335 NUMVAL (prop) > 0)
2336 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2337 else
2338 /* Nothing specified -> width defaults to canonical char width. */
2339 width = CANON_X_UNIT (it->f);
2340
2341 /* Compute height. */
2342 if (prop = Fplist_get (plist, QCheight),
2343 NUMVAL (prop) > 0)
2344 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2345 else if (prop = Fplist_get (plist, QCrelative_height),
2346 NUMVAL (prop) > 0)
2347 height = FONT_HEIGHT (font) * NUMVAL (prop);
2348 else
2349 height = FONT_HEIGHT (font);
2350
2351 /* Compute percentage of height used for ascent. If
2352 `:ascent ASCENT' is present and valid, use that. Otherwise,
2353 derive the ascent from the font in use. */
2354 if (prop = Fplist_get (plist, QCascent),
2355 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2356 ascent = NUMVAL (prop) / 100.0;
2357 else
2358 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
2359
2360 if (width <= 0)
2361 width = 1;
2362 if (height <= 0)
2363 height = 1;
2364
2365 if (it->glyph_row)
2366 {
2367 Lisp_Object object = it->stack[it->sp - 1].string;
2368 if (!STRINGP (object))
2369 object = it->w->buffer;
2370 x_append_stretch_glyph (it, object, width, height, ascent);
2371 }
2372
2373 it->pixel_width = width;
2374 it->ascent = it->phys_ascent = height * ascent;
2375 it->descent = it->phys_descent = height - it->ascent;
2376 it->nglyphs = 1;
2377
2378 if (face->box != FACE_NO_BOX)
2379 {
2380 if (face->box_line_width > 0)
2381 {
2382 it->ascent += face->box_line_width;
2383 it->descent += face->box_line_width;
2384 }
2385
2386 if (it->start_of_box_run_p)
2387 it->pixel_width += abs (face->box_line_width);
2388 if (it->end_of_box_run_p)
2389 it->pixel_width += abs (face->box_line_width);
2390 }
2391
2392 take_vertical_position_into_account (it);
2393 }
2394
2395 /* Return proper value to be used as baseline offset of font that has
2396 ASCENT and DESCENT to draw characters by the font at the vertical
2397 center of the line of frame F.
2398
2399 Here, out task is to find the value of BOFF in the following figure;
2400
2401 -------------------------+-----------+-
2402 -+-+---------+-+ | |
2403 | | | | | |
2404 | | | | F_ASCENT F_HEIGHT
2405 | | | ASCENT | |
2406 HEIGHT | | | | |
2407 | | |-|-+------+-----------|------- baseline
2408 | | | | BOFF | |
2409 | |---------|-+-+ | |
2410 | | | DESCENT | |
2411 -+-+---------+-+ F_DESCENT |
2412 -------------------------+-----------+-
2413
2414 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2415 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2416 DESCENT = FONT->descent
2417 HEIGHT = FONT_HEIGHT (FONT)
2418 F_DESCENT = (F->output_data.x->font->descent
2419 - F->output_data.x->baseline_offset)
2420 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2421 */
2422
2423 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2424 (FONT_DESCENT (FONT) \
2425 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2426 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2427 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2428
2429 /* Produce glyphs/get display metrics for the display element IT is
2430 loaded with. See the description of struct display_iterator in
2431 dispextern.h for an overview of struct display_iterator. */
2432
2433 static void
2434 x_produce_glyphs (it)
2435 struct it *it;
2436 {
2437 it->glyph_not_available_p = 0;
2438
2439 if (it->what == IT_CHARACTER)
2440 {
2441 XChar2b char2b;
2442 XFontStruct *font;
2443 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2444 XCharStruct *pcm;
2445 int font_not_found_p;
2446 struct font_info *font_info;
2447 int boff; /* baseline offset */
2448 /* We may change it->multibyte_p upon unibyte<->multibyte
2449 conversion. So, save the current value now and restore it
2450 later.
2451
2452 Note: It seems that we don't have to record multibyte_p in
2453 struct glyph because the character code itself tells if or
2454 not the character is multibyte. Thus, in the future, we must
2455 consider eliminating the field `multibyte_p' in the struct
2456 glyph.
2457 */
2458 int saved_multibyte_p = it->multibyte_p;
2459
2460 /* Maybe translate single-byte characters to multibyte, or the
2461 other way. */
2462 it->char_to_display = it->c;
2463 if (!ASCII_BYTE_P (it->c))
2464 {
2465 if (unibyte_display_via_language_environment
2466 && SINGLE_BYTE_CHAR_P (it->c)
2467 && (it->c >= 0240
2468 || !NILP (Vnonascii_translation_table)))
2469 {
2470 it->char_to_display = unibyte_char_to_multibyte (it->c);
2471 it->multibyte_p = 1;
2472 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2473 face = FACE_FROM_ID (it->f, it->face_id);
2474 }
2475 else if (!SINGLE_BYTE_CHAR_P (it->c)
2476 && !it->multibyte_p)
2477 {
2478 it->multibyte_p = 1;
2479 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2480 face = FACE_FROM_ID (it->f, it->face_id);
2481 }
2482 }
2483
2484 /* Get font to use. Encode IT->char_to_display. */
2485 x_get_char_face_and_encoding (it->f, it->char_to_display,
2486 it->face_id, &char2b,
2487 it->multibyte_p);
2488 font = face->font;
2489
2490 /* When no suitable font found, use the default font. */
2491 font_not_found_p = font == NULL;
2492 if (font_not_found_p)
2493 {
2494 font = FRAME_FONT (it->f);
2495 boff = it->f->output_data.mac->baseline_offset;
2496 font_info = NULL;
2497 }
2498 else
2499 {
2500 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2501 boff = font_info->baseline_offset;
2502 if (font_info->vertical_centering)
2503 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2504 }
2505
2506 if (it->char_to_display >= ' '
2507 && (!it->multibyte_p || it->char_to_display < 128))
2508 {
2509 /* Either unibyte or ASCII. */
2510 int stretched_p;
2511
2512 it->nglyphs = 1;
2513
2514 pcm = x_per_char_metric (font, &char2b);
2515 it->ascent = FONT_BASE (font) + boff;
2516 it->descent = FONT_DESCENT (font) - boff;
2517
2518 if (pcm)
2519 {
2520 it->phys_ascent = pcm->ascent + boff;
2521 it->phys_descent = pcm->descent - boff;
2522 it->pixel_width = pcm->width;
2523 }
2524 else
2525 {
2526 it->glyph_not_available_p = 1;
2527 it->phys_ascent = FONT_BASE (font) + boff;
2528 it->phys_descent = FONT_DESCENT (font) - boff;
2529 it->pixel_width = FONT_WIDTH (font);
2530 }
2531
2532 /* If this is a space inside a region of text with
2533 `space-width' property, change its width. */
2534 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2535 if (stretched_p)
2536 it->pixel_width *= XFLOATINT (it->space_width);
2537
2538 /* If face has a box, add the box thickness to the character
2539 height. If character has a box line to the left and/or
2540 right, add the box line width to the character's width. */
2541 if (face->box != FACE_NO_BOX)
2542 {
2543 int thick = face->box_line_width;
2544
2545 if (thick > 0)
2546 {
2547 it->ascent += thick;
2548 it->descent += thick;
2549 }
2550 else
2551 thick = -thick;
2552
2553 if (it->start_of_box_run_p)
2554 it->pixel_width += thick;
2555 if (it->end_of_box_run_p)
2556 it->pixel_width += thick;
2557 }
2558
2559 /* If face has an overline, add the height of the overline
2560 (1 pixel) and a 1 pixel margin to the character height. */
2561 if (face->overline_p)
2562 it->ascent += 2;
2563
2564 take_vertical_position_into_account (it);
2565
2566 /* If we have to actually produce glyphs, do it. */
2567 if (it->glyph_row)
2568 {
2569 if (stretched_p)
2570 {
2571 /* Translate a space with a `space-width' property
2572 into a stretch glyph. */
2573 double ascent = (double) FONT_BASE (font)
2574 / FONT_HEIGHT (font);
2575 x_append_stretch_glyph (it, it->object, it->pixel_width,
2576 it->ascent + it->descent, ascent);
2577 }
2578 else
2579 x_append_glyph (it);
2580
2581 /* If characters with lbearing or rbearing are displayed
2582 in this line, record that fact in a flag of the
2583 glyph row. This is used to optimize X output code. */
2584 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2585 it->glyph_row->contains_overlapping_glyphs_p = 1;
2586 }
2587 }
2588 else if (it->char_to_display == '\n')
2589 {
2590 /* A newline has no width but we need the height of the line. */
2591 it->pixel_width = 0;
2592 it->nglyphs = 0;
2593 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2594 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2595
2596 if (face->box != FACE_NO_BOX
2597 && face->box_line_width > 0)
2598 {
2599 it->ascent += face->box_line_width;
2600 it->descent += face->box_line_width;
2601 }
2602 }
2603 else if (it->char_to_display == '\t')
2604 {
2605 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2606 int x = it->current_x + it->continuation_lines_width;
2607 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2608
2609 /* If the distance from the current position to the next tab
2610 stop is less than a canonical character width, use the
2611 tab stop after that. */
2612 if (next_tab_x - x < CANON_X_UNIT (it->f))
2613 next_tab_x += tab_width;
2614
2615 it->pixel_width = next_tab_x - x;
2616 it->nglyphs = 1;
2617 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2618 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2619
2620 if (it->glyph_row)
2621 {
2622 double ascent = (double) it->ascent / (it->ascent + it->descent);
2623 x_append_stretch_glyph (it, it->object, it->pixel_width,
2624 it->ascent + it->descent, ascent);
2625 }
2626 }
2627 else
2628 {
2629 /* A multi-byte character. Assume that the display width of the
2630 character is the width of the character multiplied by the
2631 width of the font. */
2632
2633 /* If we found a font, this font should give us the right
2634 metrics. If we didn't find a font, use the frame's
2635 default font and calculate the width of the character
2636 from the charset width; this is what old redisplay code
2637 did. */
2638 pcm = x_per_char_metric (font, &char2b);
2639 if (font_not_found_p || !pcm)
2640 {
2641 int charset = CHAR_CHARSET (it->char_to_display);
2642
2643 it->glyph_not_available_p = 1;
2644 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2645 * CHARSET_WIDTH (charset));
2646 it->phys_ascent = FONT_BASE (font) + boff;
2647 it->phys_descent = FONT_DESCENT (font) - boff;
2648 }
2649 else
2650 {
2651 it->pixel_width = pcm->width;
2652 it->phys_ascent = pcm->ascent + boff;
2653 it->phys_descent = pcm->descent - boff;
2654 if (it->glyph_row
2655 && (pcm->lbearing < 0
2656 || pcm->rbearing > pcm->width))
2657 it->glyph_row->contains_overlapping_glyphs_p = 1;
2658 }
2659 it->nglyphs = 1;
2660 it->ascent = FONT_BASE (font) + boff;
2661 it->descent = FONT_DESCENT (font) - boff;
2662 if (face->box != FACE_NO_BOX)
2663 {
2664 int thick = face->box_line_width;
2665
2666 if (thick > 0)
2667 {
2668 it->ascent += thick;
2669 it->descent += thick;
2670 }
2671 else
2672 thick = - thick;
2673
2674 if (it->start_of_box_run_p)
2675 it->pixel_width += thick;
2676 if (it->end_of_box_run_p)
2677 it->pixel_width += thick;
2678 }
2679
2680 /* If face has an overline, add the height of the overline
2681 (1 pixel) and a 1 pixel margin to the character height. */
2682 if (face->overline_p)
2683 it->ascent += 2;
2684
2685 take_vertical_position_into_account (it);
2686
2687 if (it->glyph_row)
2688 x_append_glyph (it);
2689 }
2690 it->multibyte_p = saved_multibyte_p;
2691 }
2692 else if (it->what == IT_COMPOSITION)
2693 {
2694 /* Note: A composition is represented as one glyph in the
2695 glyph matrix. There are no padding glyphs. */
2696 XChar2b char2b;
2697 XFontStruct *font;
2698 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2699 XCharStruct *pcm;
2700 int font_not_found_p;
2701 struct font_info *font_info;
2702 int boff; /* baseline offset */
2703 struct composition *cmp = composition_table[it->cmp_id];
2704
2705 /* Maybe translate single-byte characters to multibyte. */
2706 it->char_to_display = it->c;
2707 if (unibyte_display_via_language_environment
2708 && SINGLE_BYTE_CHAR_P (it->c)
2709 && (it->c >= 0240
2710 || (it->c >= 0200
2711 && !NILP (Vnonascii_translation_table))))
2712 {
2713 it->char_to_display = unibyte_char_to_multibyte (it->c);
2714 }
2715
2716 /* Get face and font to use. Encode IT->char_to_display. */
2717 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2718 face = FACE_FROM_ID (it->f, it->face_id);
2719 x_get_char_face_and_encoding (it->f, it->char_to_display,
2720 it->face_id, &char2b, it->multibyte_p);
2721 font = face->font;
2722
2723 /* When no suitable font found, use the default font. */
2724 font_not_found_p = font == NULL;
2725 if (font_not_found_p)
2726 {
2727 font = FRAME_FONT (it->f);
2728 boff = it->f->output_data.mac->baseline_offset;
2729 font_info = NULL;
2730 }
2731 else
2732 {
2733 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2734 boff = font_info->baseline_offset;
2735 if (font_info->vertical_centering)
2736 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2737 }
2738
2739 /* There are no padding glyphs, so there is only one glyph to
2740 produce for the composition. Important is that pixel_width,
2741 ascent and descent are the values of what is drawn by
2742 draw_glyphs (i.e. the values of the overall glyphs composed). */
2743 it->nglyphs = 1;
2744
2745 /* If we have not yet calculated pixel size data of glyphs of
2746 the composition for the current face font, calculate them
2747 now. Theoretically, we have to check all fonts for the
2748 glyphs, but that requires much time and memory space. So,
2749 here we check only the font of the first glyph. This leads
2750 to incorrect display very rarely, and C-l (recenter) can
2751 correct the display anyway. */
2752 if (cmp->font != (void *) font)
2753 {
2754 /* Ascent and descent of the font of the first character of
2755 this composition (adjusted by baseline offset). Ascent
2756 and descent of overall glyphs should not be less than
2757 them respectively. */
2758 int font_ascent = FONT_BASE (font) + boff;
2759 int font_descent = FONT_DESCENT (font) - boff;
2760 /* Bounding box of the overall glyphs. */
2761 int leftmost, rightmost, lowest, highest;
2762 int i, width, ascent, descent;
2763
2764 cmp->font = (void *) font;
2765
2766 /* Initialize the bounding box. */
2767 pcm = x_per_char_metric (font, &char2b);
2768 if (pcm)
2769 {
2770 width = pcm->width;
2771 ascent = pcm->ascent;
2772 descent = pcm->descent;
2773 }
2774 else
2775 {
2776 width = FONT_WIDTH (font);
2777 ascent = FONT_BASE (font);
2778 descent = FONT_DESCENT (font);
2779 }
2780
2781 rightmost = width;
2782 lowest = - descent + boff;
2783 highest = ascent + boff;
2784 leftmost = 0;
2785
2786 if (font_info
2787 && font_info->default_ascent
2788 && CHAR_TABLE_P (Vuse_default_ascent)
2789 && !NILP (Faref (Vuse_default_ascent,
2790 make_number (it->char_to_display))))
2791 highest = font_info->default_ascent + boff;
2792
2793 /* Draw the first glyph at the normal position. It may be
2794 shifted to right later if some other glyphs are drawn at
2795 the left. */
2796 cmp->offsets[0] = 0;
2797 cmp->offsets[1] = boff;
2798
2799 /* Set cmp->offsets for the remaining glyphs. */
2800 for (i = 1; i < cmp->glyph_len; i++)
2801 {
2802 int left, right, btm, top;
2803 int ch = COMPOSITION_GLYPH (cmp, i);
2804 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2805
2806 face = FACE_FROM_ID (it->f, face_id);
2807 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2808 it->multibyte_p);
2809 font = face->font;
2810 if (font == NULL)
2811 {
2812 font = FRAME_FONT (it->f);
2813 boff = it->f->output_data.mac->baseline_offset;
2814 font_info = NULL;
2815 }
2816 else
2817 {
2818 font_info
2819 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2820 boff = font_info->baseline_offset;
2821 if (font_info->vertical_centering)
2822 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2823 }
2824
2825 pcm = x_per_char_metric (font, &char2b);
2826 if (pcm)
2827 {
2828 width = pcm->width;
2829 ascent = pcm->ascent;
2830 descent = pcm->descent;
2831 }
2832 else
2833 {
2834 width = FONT_WIDTH (font);
2835 ascent = 1;
2836 descent = 0;
2837 }
2838
2839 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2840 {
2841 /* Relative composition with or without
2842 alternate chars. */
2843 left = (leftmost + rightmost - width) / 2;
2844 btm = - descent + boff;
2845 if (font_info && font_info->relative_compose
2846 && (! CHAR_TABLE_P (Vignore_relative_composition)
2847 || NILP (Faref (Vignore_relative_composition,
2848 make_number (ch)))))
2849 {
2850
2851 if (- descent >= font_info->relative_compose)
2852 /* One extra pixel between two glyphs. */
2853 btm = highest + 1;
2854 else if (ascent <= 0)
2855 /* One extra pixel between two glyphs. */
2856 btm = lowest - 1 - ascent - descent;
2857 }
2858 }
2859 else
2860 {
2861 /* A composition rule is specified by an integer
2862 value that encodes global and new reference
2863 points (GREF and NREF). GREF and NREF are
2864 specified by numbers as below:
2865
2866 0---1---2 -- ascent
2867 | |
2868 | |
2869 | |
2870 9--10--11 -- center
2871 | |
2872 ---3---4---5--- baseline
2873 | |
2874 6---7---8 -- descent
2875 */
2876 int rule = COMPOSITION_RULE (cmp, i);
2877 int gref, nref, grefx, grefy, nrefx, nrefy;
2878
2879 COMPOSITION_DECODE_RULE (rule, gref, nref);
2880 grefx = gref % 3, nrefx = nref % 3;
2881 grefy = gref / 3, nrefy = nref / 3;
2882
2883 left = (leftmost
2884 + grefx * (rightmost - leftmost) / 2
2885 - nrefx * width / 2);
2886 btm = ((grefy == 0 ? highest
2887 : grefy == 1 ? 0
2888 : grefy == 2 ? lowest
2889 : (highest + lowest) / 2)
2890 - (nrefy == 0 ? ascent + descent
2891 : nrefy == 1 ? descent - boff
2892 : nrefy == 2 ? 0
2893 : (ascent + descent) / 2));
2894 }
2895
2896 cmp->offsets[i * 2] = left;
2897 cmp->offsets[i * 2 + 1] = btm + descent;
2898
2899 /* Update the bounding box of the overall glyphs. */
2900 right = left + width;
2901 top = btm + descent + ascent;
2902 if (left < leftmost)
2903 leftmost = left;
2904 if (right > rightmost)
2905 rightmost = right;
2906 if (top > highest)
2907 highest = top;
2908 if (btm < lowest)
2909 lowest = btm;
2910 }
2911
2912 /* If there are glyphs whose x-offsets are negative,
2913 shift all glyphs to the right and make all x-offsets
2914 non-negative. */
2915 if (leftmost < 0)
2916 {
2917 for (i = 0; i < cmp->glyph_len; i++)
2918 cmp->offsets[i * 2] -= leftmost;
2919 rightmost -= leftmost;
2920 }
2921
2922 cmp->pixel_width = rightmost;
2923 cmp->ascent = highest;
2924 cmp->descent = - lowest;
2925 if (cmp->ascent < font_ascent)
2926 cmp->ascent = font_ascent;
2927 if (cmp->descent < font_descent)
2928 cmp->descent = font_descent;
2929 }
2930
2931 it->pixel_width = cmp->pixel_width;
2932 it->ascent = it->phys_ascent = cmp->ascent;
2933 it->descent = it->phys_descent = cmp->descent;
2934
2935 if (face->box != FACE_NO_BOX)
2936 {
2937 int thick = face->box_line_width;
2938
2939 if (thick > 0)
2940 {
2941 it->ascent += thick;
2942 it->descent += thick;
2943 }
2944 else
2945 thick = - thick;
2946
2947 if (it->start_of_box_run_p)
2948 it->pixel_width += thick;
2949 if (it->end_of_box_run_p)
2950 it->pixel_width += thick;
2951 }
2952
2953 /* If face has an overline, add the height of the overline
2954 (1 pixel) and a 1 pixel margin to the character height. */
2955 if (face->overline_p)
2956 it->ascent += 2;
2957
2958 take_vertical_position_into_account (it);
2959
2960 if (it->glyph_row)
2961 x_append_composite_glyph (it);
2962 }
2963 else if (it->what == IT_IMAGE)
2964 x_produce_image_glyph (it);
2965 else if (it->what == IT_STRETCH)
2966 x_produce_stretch_glyph (it);
2967
2968 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2969 because this isn't true for images with `:ascent 100'. */
2970 xassert (it->ascent >= 0 && it->descent >= 0);
2971 if (it->area == TEXT_AREA)
2972 it->current_x += it->pixel_width;
2973
2974 it->descent += it->extra_line_spacing;
2975
2976 it->max_ascent = max (it->max_ascent, it->ascent);
2977 it->max_descent = max (it->max_descent, it->descent);
2978 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2979 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2980 }
2981
2982
2983 /* Estimate the pixel height of the mode or top line on frame F.
2984 FACE_ID specifies what line's height to estimate. */
2985
2986 int
2987 x_estimate_mode_line_height (f, face_id)
2988 struct frame *f;
2989 enum face_id face_id;
2990 {
2991 int height = FONT_HEIGHT (FRAME_FONT (f));
2992
2993 /* This function is called so early when Emacs starts that the face
2994 cache and mode line face are not yet initialized. */
2995 if (FRAME_FACE_CACHE (f))
2996 {
2997 struct face *face = FACE_FROM_ID (f, face_id);
2998 if (face)
2999 {
3000 if (face->font)
3001 height = FONT_HEIGHT (face->font);
3002 if (face->box_line_width > 0)
3003 height += 2 * face->box_line_width;
3004 }
3005 }
3006
3007 return height;
3008 }
3009
3010 \f
3011 /***********************************************************************
3012 Glyph display
3013 ***********************************************************************/
3014
3015 /* A sequence of glyphs to be drawn in the same face.
3016
3017 This data structure is not really completely X specific, so it
3018 could possibly, at least partially, be useful for other systems. It
3019 is currently not part of the external redisplay interface because
3020 it's not clear what other systems will need. */
3021
3022 struct glyph_string
3023 {
3024 /* X-origin of the string. */
3025 int x;
3026
3027 /* Y-origin and y-position of the base line of this string. */
3028 int y, ybase;
3029
3030 /* The width of the string, not including a face extension. */
3031 int width;
3032
3033 /* The width of the string, including a face extension. */
3034 int background_width;
3035
3036 /* The height of this string. This is the height of the line this
3037 string is drawn in, and can be different from the height of the
3038 font the string is drawn in. */
3039 int height;
3040
3041 /* Number of pixels this string overwrites in front of its x-origin.
3042 This number is zero if the string has an lbearing >= 0; it is
3043 -lbearing, if the string has an lbearing < 0. */
3044 int left_overhang;
3045
3046 /* Number of pixels this string overwrites past its right-most
3047 nominal x-position, i.e. x + width. Zero if the string's
3048 rbearing is <= its nominal width, rbearing - width otherwise. */
3049 int right_overhang;
3050
3051 /* The frame on which the glyph string is drawn. */
3052 struct frame *f;
3053
3054 /* The window on which the glyph string is drawn. */
3055 struct window *w;
3056
3057 /* X display and window for convenience. */
3058 Display *display;
3059 Window window;
3060
3061 /* The glyph row for which this string was built. It determines the
3062 y-origin and height of the string. */
3063 struct glyph_row *row;
3064
3065 /* The area within row. */
3066 enum glyph_row_area area;
3067
3068 /* Characters to be drawn, and number of characters. */
3069 XChar2b *char2b;
3070 int nchars;
3071
3072 /* A face-override for drawing cursors, mouse face and similar. */
3073 enum draw_glyphs_face hl;
3074
3075 /* Face in which this string is to be drawn. */
3076 struct face *face;
3077
3078 /* Font in which this string is to be drawn. */
3079 XFontStruct *font;
3080
3081 /* Font info for this string. */
3082 struct font_info *font_info;
3083
3084 /* Non-null means this string describes (part of) a composition.
3085 All characters from char2b are drawn composed. */
3086 struct composition *cmp;
3087
3088 /* Index of this glyph string's first character in the glyph
3089 definition of CMP. If this is zero, this glyph string describes
3090 the first character of a composition. */
3091 int gidx;
3092
3093 /* 1 means this glyph strings face has to be drawn to the right end
3094 of the window's drawing area. */
3095 unsigned extends_to_end_of_line_p : 1;
3096
3097 /* 1 means the background of this string has been drawn. */
3098 unsigned background_filled_p : 1;
3099
3100 /* 1 means glyph string must be drawn with 16-bit functions. */
3101 unsigned two_byte_p : 1;
3102
3103 /* 1 means that the original font determined for drawing this glyph
3104 string could not be loaded. The member `font' has been set to
3105 the frame's default font in this case. */
3106 unsigned font_not_found_p : 1;
3107
3108 /* 1 means that the face in which this glyph string is drawn has a
3109 stipple pattern. */
3110 unsigned stippled_p : 1;
3111
3112 /* 1 means only the foreground of this glyph string must be drawn,
3113 and we should use the physical height of the line this glyph
3114 string appears in as clip rect. */
3115 unsigned for_overlaps_p : 1;
3116
3117 /* The GC to use for drawing this glyph string. */
3118 GC gc;
3119
3120 /* A pointer to the first glyph in the string. This glyph
3121 corresponds to char2b[0]. Needed to draw rectangles if
3122 font_not_found_p is 1. */
3123 struct glyph *first_glyph;
3124
3125 /* Image, if any. */
3126 struct image *img;
3127
3128 struct glyph_string *next, *prev;
3129 };
3130
3131
3132 #if 0
3133
3134 static void
3135 x_dump_glyph_string (s)
3136 struct glyph_string *s;
3137 {
3138 fprintf (stderr, "glyph string\n");
3139 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
3140 s->x, s->y, s->width, s->height);
3141 fprintf (stderr, " ybase = %d\n", s->ybase);
3142 fprintf (stderr, " hl = %d\n", s->hl);
3143 fprintf (stderr, " left overhang = %d, right = %d\n",
3144 s->left_overhang, s->right_overhang);
3145 fprintf (stderr, " nchars = %d\n", s->nchars);
3146 fprintf (stderr, " extends to end of line = %d\n",
3147 s->extends_to_end_of_line_p);
3148 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
3149 fprintf (stderr, " bg width = %d\n", s->background_width);
3150 }
3151
3152 #endif /* GLYPH_DEBUG */
3153
3154
3155
3156 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3157 struct glyph_string **,
3158 struct glyph_string *,
3159 struct glyph_string *));
3160 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3161 struct glyph_string **,
3162 struct glyph_string *,
3163 struct glyph_string *));
3164 static void x_append_glyph_string P_ ((struct glyph_string **,
3165 struct glyph_string **,
3166 struct glyph_string *));
3167 static int x_left_overwritten P_ ((struct glyph_string *));
3168 static int x_left_overwriting P_ ((struct glyph_string *));
3169 static int x_right_overwritten P_ ((struct glyph_string *));
3170 static int x_right_overwriting P_ ((struct glyph_string *));
3171 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3172 int));
3173 static void x_init_glyph_string P_ ((struct glyph_string *,
3174 XChar2b *, struct window *,
3175 struct glyph_row *,
3176 enum glyph_row_area, int,
3177 enum draw_glyphs_face));
3178 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3179 enum glyph_row_area, int, int,
3180 enum draw_glyphs_face, int));
3181 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3182 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3183 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3184 int));
3185 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3186 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3187 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3188 static void x_draw_glyph_string P_ ((struct glyph_string *));
3189 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3190 static void x_set_cursor_gc P_ ((struct glyph_string *));
3191 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3192 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3193 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3194 int *, int *));
3195 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
3196 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3197 unsigned long *, double, int));*/
3198 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3199 double, int, unsigned long));
3200 static void x_setup_relief_colors P_ ((struct glyph_string *));
3201 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3202 static void x_draw_image_relief P_ ((struct glyph_string *));
3203 static void x_draw_image_foreground P_ ((struct glyph_string *));
3204 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3205 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3206 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3207 int, int, int));
3208 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
3209 int, int, int, int, Rect *));
3210 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
3211 int, int, int, Rect *));
3212 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3213 enum glyph_row_area));
3214 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3215 struct glyph_row *,
3216 enum glyph_row_area, int, int));
3217
3218 #if GLYPH_DEBUG
3219 static void x_check_font P_ ((struct frame *, XFontStruct *));
3220 #endif
3221
3222
3223 /* Append the list of glyph strings with head H and tail T to the list
3224 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3225
3226 static INLINE void
3227 x_append_glyph_string_lists (head, tail, h, t)
3228 struct glyph_string **head, **tail;
3229 struct glyph_string *h, *t;
3230 {
3231 if (h)
3232 {
3233 if (*head)
3234 (*tail)->next = h;
3235 else
3236 *head = h;
3237 h->prev = *tail;
3238 *tail = t;
3239 }
3240 }
3241
3242
3243 /* Prepend the list of glyph strings with head H and tail T to the
3244 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3245 result. */
3246
3247 static INLINE void
3248 x_prepend_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 (*head)->prev = t;
3256 else
3257 *tail = t;
3258 t->next = *head;
3259 *head = h;
3260 }
3261 }
3262
3263
3264 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3265 Set *HEAD and *TAIL to the resulting list. */
3266
3267 static INLINE void
3268 x_append_glyph_string (head, tail, s)
3269 struct glyph_string **head, **tail;
3270 struct glyph_string *s;
3271 {
3272 s->next = s->prev = NULL;
3273 x_append_glyph_string_lists (head, tail, s, s);
3274 }
3275
3276
3277 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3278 face. */
3279
3280 static void
3281 x_set_cursor_gc (s)
3282 struct glyph_string *s;
3283 {
3284 if (s->font == FRAME_FONT (s->f)
3285 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3286 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3287 && !s->cmp)
3288 s->gc = s->f->output_data.mac->cursor_gc;
3289 else
3290 {
3291 /* Cursor on non-default face: must merge. */
3292 XGCValues xgcv;
3293 unsigned long mask;
3294
3295 xgcv.background = s->f->output_data.mac->cursor_pixel;
3296 xgcv.foreground = s->face->background;
3297
3298 /* If the glyph would be invisible, try a different foreground. */
3299 if (xgcv.foreground == xgcv.background)
3300 xgcv.foreground = s->face->foreground;
3301 if (xgcv.foreground == xgcv.background)
3302 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3303 if (xgcv.foreground == xgcv.background)
3304 xgcv.foreground = s->face->foreground;
3305
3306 /* Make sure the cursor is distinct from text in this face. */
3307 if (xgcv.background == s->face->background
3308 && xgcv.foreground == s->face->foreground)
3309 {
3310 xgcv.background = s->face->foreground;
3311 xgcv.foreground = s->face->background;
3312 }
3313
3314 IF_DEBUG (x_check_font (s->f, s->font));
3315 xgcv.font = s->font;
3316 mask = GCForeground | GCBackground | GCFont;
3317
3318 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3319 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3320 mask, &xgcv);
3321 else
3322 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3323 = XCreateGC (s->display, s->window, mask, &xgcv);
3324
3325 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3326 }
3327 }
3328
3329
3330 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3331
3332 static void
3333 x_set_mouse_face_gc (s)
3334 struct glyph_string *s;
3335 {
3336 int face_id;
3337 struct face *face;
3338
3339 /* What face has to be used last for the mouse face? */
3340 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3341 face = FACE_FROM_ID (s->f, face_id);
3342 if (face == NULL)
3343 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3344
3345 if (s->first_glyph->type == CHAR_GLYPH)
3346 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3347 else
3348 face_id = FACE_FOR_CHAR (s->f, face, 0);
3349 s->face = FACE_FROM_ID (s->f, face_id);
3350 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3351
3352 /* If font in this face is same as S->font, use it. */
3353 if (s->font == s->face->font)
3354 s->gc = s->face->gc;
3355 else
3356 {
3357 /* Otherwise construct scratch_cursor_gc with values from FACE
3358 but font FONT. */
3359 XGCValues xgcv;
3360 unsigned long mask;
3361
3362 xgcv.background = s->face->background;
3363 xgcv.foreground = s->face->foreground;
3364 IF_DEBUG (x_check_font (s->f, s->font));
3365 xgcv.font = s->font;
3366 mask = GCForeground | GCBackground | GCFont;
3367
3368 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3369 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3370 mask, &xgcv);
3371 else
3372 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3373 = XCreateGC (s->display, s->window, mask, &xgcv);
3374
3375 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3376 }
3377
3378 xassert (s->gc != 0);
3379 }
3380
3381
3382 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3383 Faces to use in the mode line have already been computed when the
3384 matrix was built, so there isn't much to do, here. */
3385
3386 static INLINE void
3387 x_set_mode_line_face_gc (s)
3388 struct glyph_string *s;
3389 {
3390 s->gc = s->face->gc;
3391 }
3392
3393
3394 /* Set S->gc of glyph string S for drawing that glyph string. Set
3395 S->stippled_p to a non-zero value if the face of S has a stipple
3396 pattern. */
3397
3398 static INLINE void
3399 x_set_glyph_string_gc (s)
3400 struct glyph_string *s;
3401 {
3402 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3403
3404 if (s->hl == DRAW_NORMAL_TEXT)
3405 {
3406 s->gc = s->face->gc;
3407 s->stippled_p = s->face->stipple != 0;
3408 }
3409 else if (s->hl == DRAW_INVERSE_VIDEO)
3410 {
3411 x_set_mode_line_face_gc (s);
3412 s->stippled_p = s->face->stipple != 0;
3413 }
3414 else if (s->hl == DRAW_CURSOR)
3415 {
3416 x_set_cursor_gc (s);
3417 s->stippled_p = 0;
3418 }
3419 else if (s->hl == DRAW_MOUSE_FACE)
3420 {
3421 x_set_mouse_face_gc (s);
3422 s->stippled_p = s->face->stipple != 0;
3423 }
3424 else if (s->hl == DRAW_IMAGE_RAISED
3425 || s->hl == DRAW_IMAGE_SUNKEN)
3426 {
3427 s->gc = s->face->gc;
3428 s->stippled_p = s->face->stipple != 0;
3429 }
3430 else
3431 {
3432 s->gc = s->face->gc;
3433 s->stippled_p = s->face->stipple != 0;
3434 }
3435
3436 /* GC must have been set. */
3437 xassert (s->gc != 0);
3438 }
3439
3440
3441 /* Return in *R the clipping rectangle for glyph string S. */
3442
3443 static void
3444 x_get_glyph_string_clip_rect (s, r)
3445 struct glyph_string *s;
3446 Rect *r;
3447 {
3448 int r_height, r_width;
3449
3450 if (s->row->full_width_p)
3451 {
3452 /* Draw full-width. X coordinates are relative to S->w->left. */
3453 int canon_x = CANON_X_UNIT (s->f);
3454
3455 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3456 r_width = XFASTINT (s->w->width) * canon_x;
3457
3458 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3459 {
3460 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3461 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3462 r->left -= width;
3463 }
3464
3465 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3466
3467 /* Unless displaying a mode or menu bar line, which are always
3468 fully visible, clip to the visible part of the row. */
3469 if (s->w->pseudo_window_p)
3470 r_height = s->row->visible_height;
3471 else
3472 r_height = s->height;
3473 }
3474 else
3475 {
3476 /* This is a text line that may be partially visible. */
3477 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3478 r_width = window_box_width (s->w, s->area);
3479 r_height = s->row->visible_height;
3480 }
3481
3482 /* If S draws overlapping rows, it's sufficient to use the top and
3483 bottom of the window for clipping because this glyph string
3484 intentionally draws over other lines. */
3485 if (s->for_overlaps_p)
3486 {
3487 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3488 r_height = window_text_bottom_y (s->w) - r->top;
3489 }
3490 else
3491 {
3492 /* Don't use S->y for clipping because it doesn't take partially
3493 visible lines into account. For example, it can be negative for
3494 partially visible lines at the top of a window. */
3495 if (!s->row->full_width_p
3496 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3497 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3498 else
3499 r->top = max (0, s->row->y);
3500
3501 /* If drawing a tool-bar window, draw it over the internal border
3502 at the top of the window. */
3503 if (s->w == XWINDOW (s->f->tool_bar_window))
3504 r->top -= s->f->output_data.mac->internal_border_width;
3505 }
3506
3507 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3508
3509 r->bottom = r->top + r_height;
3510 r->right = r->left + r_width;
3511 }
3512
3513
3514 /* Set clipping for output of glyph string S. S may be part of a mode
3515 line or menu if we don't have X toolkit support. */
3516
3517 static INLINE void
3518 x_set_glyph_string_clipping (s)
3519 struct glyph_string *s;
3520 {
3521 Rect r;
3522 x_get_glyph_string_clip_rect (s, &r);
3523 mac_set_clip_rectangle (s->display, s->window, &r);
3524 }
3525
3526
3527 /* Compute left and right overhang of glyph string S. If S is a glyph
3528 string for a composition, assume overhangs don't exist. */
3529
3530 static INLINE void
3531 x_compute_glyph_string_overhangs (s)
3532 struct glyph_string *s;
3533 {
3534 if (s->cmp == NULL
3535 && s->first_glyph->type == CHAR_GLYPH)
3536 {
3537 XCharStruct cs;
3538 int direction, font_ascent, font_descent;
3539 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3540 &font_ascent, &font_descent, &cs);
3541 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3542 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3543 }
3544 }
3545
3546
3547 /* Compute overhangs and x-positions for glyph string S and its
3548 predecessors, or successors. X is the starting x-position for S.
3549 BACKWARD_P non-zero means process predecessors. */
3550
3551 static void
3552 x_compute_overhangs_and_x (s, x, backward_p)
3553 struct glyph_string *s;
3554 int x;
3555 int backward_p;
3556 {
3557 if (backward_p)
3558 {
3559 while (s)
3560 {
3561 x_compute_glyph_string_overhangs (s);
3562 x -= s->width;
3563 s->x = x;
3564 s = s->prev;
3565 }
3566 }
3567 else
3568 {
3569 while (s)
3570 {
3571 x_compute_glyph_string_overhangs (s);
3572 s->x = x;
3573 x += s->width;
3574 s = s->next;
3575 }
3576 }
3577 }
3578
3579
3580 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3581 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3582 assumed to be zero. */
3583
3584 void
3585 x_get_glyph_overhangs (glyph, f, left, right)
3586 struct glyph *glyph;
3587 struct frame *f;
3588 int *left, *right;
3589 {
3590 *left = *right = 0;
3591
3592 if (glyph->type == CHAR_GLYPH)
3593 {
3594 XFontStruct *font;
3595 struct face *face;
3596 struct font_info *font_info;
3597 XChar2b char2b;
3598 XCharStruct *pcm;
3599
3600 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3601 font = face->font;
3602 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3603 if (font
3604 && (pcm = x_per_char_metric (font, &char2b)))
3605 {
3606 if (pcm->rbearing > pcm->width)
3607 *right = pcm->rbearing - pcm->width;
3608 if (pcm->lbearing < 0)
3609 *left = -pcm->lbearing;
3610 }
3611 }
3612 }
3613
3614
3615 /* Return the index of the first glyph preceding glyph string S that
3616 is overwritten by S because of S's left overhang. Value is -1
3617 if no glyphs are overwritten. */
3618
3619 static int
3620 x_left_overwritten (s)
3621 struct glyph_string *s;
3622 {
3623 int k;
3624
3625 if (s->left_overhang)
3626 {
3627 int x = 0, i;
3628 struct glyph *glyphs = s->row->glyphs[s->area];
3629 int first = s->first_glyph - glyphs;
3630
3631 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3632 x -= glyphs[i].pixel_width;
3633
3634 k = i + 1;
3635 }
3636 else
3637 k = -1;
3638
3639 return k;
3640 }
3641
3642
3643 /* Return the index of the first glyph preceding glyph string S that
3644 is overwriting S because of its right overhang. Value is -1 if no
3645 glyph in front of S overwrites S. */
3646
3647 static int
3648 x_left_overwriting (s)
3649 struct glyph_string *s;
3650 {
3651 int i, k, x;
3652 struct glyph *glyphs = s->row->glyphs[s->area];
3653 int first = s->first_glyph - glyphs;
3654
3655 k = -1;
3656 x = 0;
3657 for (i = first - 1; i >= 0; --i)
3658 {
3659 int left, right;
3660 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3661 if (x + right > 0)
3662 k = i;
3663 x -= glyphs[i].pixel_width;
3664 }
3665
3666 return k;
3667 }
3668
3669
3670 /* Return the index of the last glyph following glyph string S that is
3671 not overwritten by S because of S's right overhang. Value is -1 if
3672 no such glyph is found. */
3673
3674 static int
3675 x_right_overwritten (s)
3676 struct glyph_string *s;
3677 {
3678 int k = -1;
3679
3680 if (s->right_overhang)
3681 {
3682 int x = 0, i;
3683 struct glyph *glyphs = s->row->glyphs[s->area];
3684 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3685 int end = s->row->used[s->area];
3686
3687 for (i = first; i < end && s->right_overhang > x; ++i)
3688 x += glyphs[i].pixel_width;
3689
3690 k = i;
3691 }
3692
3693 return k;
3694 }
3695
3696
3697 /* Return the index of the last glyph following glyph string S that
3698 overwrites S because of its left overhang. Value is negative
3699 if no such glyph is found. */
3700
3701 static int
3702 x_right_overwriting (s)
3703 struct glyph_string *s;
3704 {
3705 int i, k, x;
3706 int end = s->row->used[s->area];
3707 struct glyph *glyphs = s->row->glyphs[s->area];
3708 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3709
3710 k = -1;
3711 x = 0;
3712 for (i = first; i < end; ++i)
3713 {
3714 int left, right;
3715 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3716 if (x - left < 0)
3717 k = i;
3718 x += glyphs[i].pixel_width;
3719 }
3720
3721 return k;
3722 }
3723
3724
3725 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3726
3727 static INLINE void
3728 x_clear_glyph_string_rect (s, x, y, w, h)
3729 struct glyph_string *s;
3730 int x, y, w, h;
3731 {
3732 XGCValues xgcv;
3733
3734 xgcv.foreground = s->gc->background;
3735 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3736 }
3737
3738
3739 /* Draw the background of glyph_string S. If S->background_filled_p
3740 is non-zero don't draw it. FORCE_P non-zero means draw the
3741 background even if it wouldn't be drawn normally. This is used
3742 when a string preceding S draws into the background of S, or S
3743 contains the first component of a composition. */
3744
3745 static void
3746 x_draw_glyph_string_background (s, force_p)
3747 struct glyph_string *s;
3748 int force_p;
3749 {
3750 /* Nothing to do if background has already been drawn or if it
3751 shouldn't be drawn in the first place. */
3752 if (!s->background_filled_p)
3753 {
3754 int box_line_width = max (s->face->box_line_width, 0);
3755
3756 #if 0 /* MAC_TODO: stipple */
3757 if (s->stippled_p)
3758 {
3759 /* Fill background with a stipple pattern. */
3760 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3761 XFillRectangle (s->display, s->window, s->gc, s->x,
3762 s->y + box_line_width,
3763 s->background_width,
3764 s->height - 2 * box_line_width);
3765 XSetFillStyle (s->display, s->gc, FillSolid);
3766 s->background_filled_p = 1;
3767 }
3768 else
3769 #endif
3770 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3771 || s->font_not_found_p
3772 || s->extends_to_end_of_line_p
3773 || force_p)
3774 {
3775 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3776 s->background_width,
3777 s->height - 2 * box_line_width);
3778 s->background_filled_p = 1;
3779 }
3780 }
3781 }
3782
3783
3784 /* Draw the foreground of glyph string S. */
3785
3786 static void
3787 x_draw_glyph_string_foreground (s)
3788 struct glyph_string *s;
3789 {
3790 int i, x;
3791
3792 /* If first glyph of S has a left box line, start drawing the text
3793 of S to the right of that box line. */
3794 if (s->face->box != FACE_NO_BOX
3795 && s->first_glyph->left_box_line_p)
3796 x = s->x + abs (s->face->box_line_width);
3797 else
3798 x = s->x;
3799
3800 /* Draw characters of S as rectangles if S's font could not be
3801 loaded. */
3802 if (s->font_not_found_p)
3803 {
3804 for (i = 0; i < s->nchars; ++i)
3805 {
3806 struct glyph *g = s->first_glyph + i;
3807 mac_draw_rectangle (s->display, s->window,
3808 s->gc, x, s->y, g->pixel_width - 1,
3809 s->height - 1);
3810 x += g->pixel_width;
3811 }
3812 }
3813 else
3814 {
3815 char *char1b = (char *) s->char2b;
3816 int boff = s->font_info->baseline_offset;
3817
3818 if (s->font_info->vertical_centering)
3819 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3820
3821 /* If we can use 8-bit functions, condense S->char2b. */
3822 if (!s->two_byte_p)
3823 for (i = 0; i < s->nchars; ++i)
3824 char1b[i] = s->char2b[i].byte2;
3825
3826 /* Draw text with XDrawString if background has already been
3827 filled. Otherwise, use XDrawImageString. (Note that
3828 XDrawImageString is usually faster than XDrawString.) Always
3829 use XDrawImageString when drawing the cursor so that there is
3830 no chance that characters under a box cursor are invisible. */
3831 if (s->for_overlaps_p
3832 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3833 {
3834 /* Draw characters with 16-bit or 8-bit functions. */
3835 if (s->two_byte_p)
3836 XDrawString16 (s->display, s->window, s->gc, x,
3837 s->ybase - boff, s->char2b, s->nchars);
3838 else
3839 XDrawString (s->display, s->window, s->gc, x,
3840 s->ybase - boff, char1b, s->nchars);
3841 }
3842 else
3843 {
3844 if (s->two_byte_p)
3845 XDrawImageString16 (s->display, s->window, s->gc, x,
3846 s->ybase - boff, s->char2b, s->nchars);
3847 else
3848 XDrawImageString (s->display, s->window, s->gc, x,
3849 s->ybase - boff, char1b, s->nchars);
3850 }
3851 }
3852 }
3853
3854 /* Draw the foreground of composite glyph string S. */
3855
3856 static void
3857 x_draw_composite_glyph_string_foreground (s)
3858 struct glyph_string *s;
3859 {
3860 int i, x;
3861
3862 /* If first glyph of S has a left box line, start drawing the text
3863 of S to the right of that box line. */
3864 if (s->face->box != FACE_NO_BOX
3865 && s->first_glyph->left_box_line_p)
3866 x = s->x + abs (s->face->box_line_width);
3867 else
3868 x = s->x;
3869
3870 /* S is a glyph string for a composition. S->gidx is the index of
3871 the first character drawn for glyphs of this composition.
3872 S->gidx == 0 means we are drawing the very first character of
3873 this composition. */
3874
3875 /* Draw a rectangle for the composition if the font for the very
3876 first character of the composition could not be loaded. */
3877 if (s->font_not_found_p)
3878 {
3879 if (s->gidx == 0)
3880 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3881 s->width - 1, s->height - 1);
3882 }
3883 else
3884 {
3885 for (i = 0; i < s->nchars; i++, ++s->gidx)
3886 XDrawString16 (s->display, s->window, s->gc,
3887 x + s->cmp->offsets[s->gidx * 2],
3888 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3889 s->char2b + i, 1);
3890 }
3891 }
3892
3893
3894 #ifdef USE_X_TOOLKIT
3895
3896 static struct frame *x_frame_of_widget P_ ((Widget));
3897
3898
3899 /* Return the frame on which widget WIDGET is used.. Abort if frame
3900 cannot be determined. */
3901
3902 static struct frame *
3903 x_frame_of_widget (widget)
3904 Widget widget;
3905 {
3906 struct x_display_info *dpyinfo;
3907 Lisp_Object tail;
3908 struct frame *f;
3909
3910 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3911
3912 /* Find the top-level shell of the widget. Note that this function
3913 can be called when the widget is not yet realized, so XtWindow
3914 (widget) == 0. That's the reason we can't simply use
3915 x_any_window_to_frame. */
3916 while (!XtIsTopLevelShell (widget))
3917 widget = XtParent (widget);
3918
3919 /* Look for a frame with that top-level widget. Allocate the color
3920 on that frame to get the right gamma correction value. */
3921 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3922 if (GC_FRAMEP (XCAR (tail))
3923 && (f = XFRAME (XCAR (tail)),
3924 (f->output_data.nothing != 1
3925 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3926 && f->output_data.x->widget == widget)
3927 return f;
3928
3929 abort ();
3930 }
3931
3932
3933 /* Allocate the color COLOR->pixel on the screen and display of
3934 widget WIDGET in colormap CMAP. If an exact match cannot be
3935 allocated, try the nearest color available. Value is non-zero
3936 if successful. This is called from lwlib. */
3937
3938 int
3939 x_alloc_nearest_color_for_widget (widget, cmap, color)
3940 Widget widget;
3941 Colormap cmap;
3942 XColor *color;
3943 {
3944 struct frame *f = x_frame_of_widget (widget);
3945 return x_alloc_nearest_color (f, cmap, color);
3946 }
3947
3948
3949 #endif /* USE_X_TOOLKIT */
3950
3951 #if 0 /* MAC_TODO */
3952
3953 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3954 CMAP. If an exact match can't be allocated, try the nearest color
3955 available. Value is non-zero if successful. Set *COLOR to the
3956 color allocated. */
3957
3958 int
3959 x_alloc_nearest_color (f, cmap, color)
3960 struct frame *f;
3961 Colormap cmap;
3962 XColor *color;
3963 {
3964 Display *display = FRAME_X_DISPLAY (f);
3965 Screen *screen = FRAME_X_SCREEN (f);
3966 int rc;
3967
3968 gamma_correct (f, color);
3969 rc = XAllocColor (display, cmap, color);
3970 if (rc == 0)
3971 {
3972 /* If we got to this point, the colormap is full, so we're going
3973 to try to get the next closest color. The algorithm used is
3974 a least-squares matching, which is what X uses for closest
3975 color matching with StaticColor visuals. */
3976 int nearest, i;
3977 unsigned long nearest_delta = ~0;
3978 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3979 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3980
3981 for (i = 0; i < ncells; ++i)
3982 cells[i].pixel = i;
3983 XQueryColors (display, cmap, cells, ncells);
3984
3985 for (nearest = i = 0; i < ncells; ++i)
3986 {
3987 long dred = (color->red >> 8) - (cells[i].red >> 8);
3988 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3989 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3990 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3991
3992 if (delta < nearest_delta)
3993 {
3994 nearest = i;
3995 nearest_delta = delta;
3996 }
3997 }
3998
3999 color->red = cells[nearest].red;
4000 color->green = cells[nearest].green;
4001 color->blue = cells[nearest].blue;
4002 rc = XAllocColor (display, cmap, color);
4003 }
4004
4005 #ifdef DEBUG_X_COLORS
4006 if (rc)
4007 register_color (color->pixel);
4008 #endif /* DEBUG_X_COLORS */
4009
4010 return rc;
4011 }
4012
4013
4014 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4015 It's necessary to do this instead of just using PIXEL directly to
4016 get color reference counts right. */
4017
4018 unsigned long
4019 x_copy_color (f, pixel)
4020 struct frame *f;
4021 unsigned long pixel;
4022 {
4023 XColor color;
4024
4025 color.pixel = pixel;
4026 BLOCK_INPUT;
4027 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4028 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4029 UNBLOCK_INPUT;
4030 #ifdef DEBUG_X_COLORS
4031 register_color (pixel);
4032 #endif
4033 return color.pixel;
4034 }
4035
4036
4037 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4038 It's necessary to do this instead of just using PIXEL directly to
4039 get color reference counts right. */
4040
4041 unsigned long
4042 x_copy_dpy_color (dpy, cmap, pixel)
4043 Display *dpy;
4044 Colormap cmap;
4045 unsigned long pixel;
4046 {
4047 XColor color;
4048
4049 color.pixel = pixel;
4050 BLOCK_INPUT;
4051 XQueryColor (dpy, cmap, &color);
4052 XAllocColor (dpy, cmap, &color);
4053 UNBLOCK_INPUT;
4054 #ifdef DEBUG_X_COLORS
4055 register_color (pixel);
4056 #endif
4057 return color.pixel;
4058 }
4059
4060 #endif /* MAC_TODO */
4061
4062 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
4063 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4064 If this produces the same color as COLOR, try a color where all RGB
4065 values have DELTA added. Return the allocated color in *COLOR.
4066 DISPLAY is the X display, CMAP is the colormap to operate on.
4067 Value is non-zero if successful. */
4068
4069 static int
4070 mac_alloc_lighter_color (f, color, factor, delta)
4071 struct frame *f;
4072 unsigned long *color;
4073 double factor;
4074 int delta;
4075 {
4076 unsigned long new;
4077
4078 /* Change RGB values by specified FACTOR. Avoid overflow! */
4079 xassert (factor >= 0);
4080 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
4081 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
4082 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
4083 if (new == *color)
4084 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
4085 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
4086 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
4087
4088 /* MAC_TODO: Map to palette and retry with delta if same? */
4089 /* MAC_TODO: Free colors (if using palette)? */
4090
4091 if (new == *color)
4092 return 0;
4093
4094 *color = new;
4095
4096 return 1;
4097 }
4098
4099
4100 /* Set up the foreground color for drawing relief lines of glyph
4101 string S. RELIEF is a pointer to a struct relief containing the GC
4102 with which lines will be drawn. Use a color that is FACTOR or
4103 DELTA lighter or darker than the relief's background which is found
4104 in S->f->output_data.x->relief_background. If such a color cannot
4105 be allocated, use DEFAULT_PIXEL, instead. */
4106
4107 static void
4108 x_setup_relief_color (f, relief, factor, delta, default_pixel)
4109 struct frame *f;
4110 struct relief *relief;
4111 double factor;
4112 int delta;
4113 unsigned long default_pixel;
4114 {
4115 XGCValues xgcv;
4116 struct mac_output *di = f->output_data.mac;
4117 unsigned long mask = GCForeground;
4118 unsigned long pixel;
4119 unsigned long background = di->relief_background;
4120 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4121
4122 /* MAC_TODO: Free colors (if using palette)? */
4123
4124 /* Allocate new color. */
4125 xgcv.foreground = default_pixel;
4126 pixel = background;
4127 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
4128 {
4129 relief->allocated_p = 1;
4130 xgcv.foreground = relief->pixel = pixel;
4131 }
4132
4133 if (relief->gc == 0)
4134 {
4135 #if 0 /* MAC_TODO: stipple */
4136 xgcv.stipple = dpyinfo->gray;
4137 mask |= GCStipple;
4138 #endif
4139 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4140 }
4141 else
4142 XChangeGC (NULL, relief->gc, mask, &xgcv);
4143 }
4144
4145
4146 /* Set up colors for the relief lines around glyph string S. */
4147
4148 static void
4149 x_setup_relief_colors (s)
4150 struct glyph_string *s;
4151 {
4152 struct mac_output *di = s->f->output_data.mac;
4153 unsigned long color;
4154
4155 if (s->face->use_box_color_for_shadows_p)
4156 color = s->face->box_color;
4157 else
4158 {
4159 XGCValues xgcv;
4160
4161 /* Get the background color of the face. */
4162 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4163 color = xgcv.background;
4164 }
4165
4166 if (di->white_relief.gc == 0
4167 || color != di->relief_background)
4168 {
4169 di->relief_background = color;
4170 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4171 WHITE_PIX_DEFAULT (s->f));
4172 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4173 BLACK_PIX_DEFAULT (s->f));
4174 }
4175 }
4176
4177
4178 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
4179 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4180 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4181 relief. LEFT_P non-zero means draw a relief on the left side of
4182 the rectangle. RIGHT_P non-zero means draw a relief on the right
4183 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4184 when drawing. */
4185
4186 static void
4187 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4188 raised_p, left_p, right_p, clip_rect)
4189 struct frame *f;
4190 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4191 Rect *clip_rect;
4192 {
4193 int i;
4194 GC gc;
4195
4196 if (raised_p)
4197 gc = f->output_data.mac->white_relief.gc;
4198 else
4199 gc = f->output_data.mac->black_relief.gc;
4200 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4201
4202 /* Top. */
4203 for (i = 0; i < width; ++i)
4204 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4205 left_x + i * left_p, top_y + i,
4206 right_x + 1 - i * right_p, top_y + i);
4207
4208 /* Left. */
4209 if (left_p)
4210 for (i = 0; i < width; ++i)
4211 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4212 left_x + i, top_y + i, left_x + i, bottom_y - i);
4213
4214 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4215 if (raised_p)
4216 gc = f->output_data.mac->black_relief.gc;
4217 else
4218 gc = f->output_data.mac->white_relief.gc;
4219 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4220 clip_rect);
4221
4222 /* Bottom. */
4223 for (i = 0; i < width; ++i)
4224 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4225 left_x + i * left_p, bottom_y - i,
4226 right_x + 1 - i * right_p, bottom_y - i);
4227
4228 /* Right. */
4229 if (right_p)
4230 for (i = 0; i < width; ++i)
4231 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4232 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4233
4234 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4235 }
4236
4237
4238 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4239 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4240 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4241 left side of the rectangle. RIGHT_P non-zero means draw a line
4242 on the right side of the rectangle. CLIP_RECT is the clipping
4243 rectangle to use when drawing. */
4244
4245 static void
4246 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4247 left_p, right_p, clip_rect)
4248 struct glyph_string *s;
4249 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4250 Rect *clip_rect;
4251 {
4252 XGCValues xgcv;
4253
4254 xgcv.foreground = s->face->box_color;
4255 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4256
4257 /* Top. */
4258 XFillRectangle (s->display, s->window, &xgcv,
4259 left_x, top_y, right_x - left_x, width);
4260
4261 /* Left. */
4262 if (left_p)
4263 XFillRectangle (s->display, s->window, &xgcv,
4264 left_x, top_y, width, bottom_y - top_y);
4265
4266 /* Bottom. */
4267 XFillRectangle (s->display, s->window, &xgcv,
4268 left_x, bottom_y - width, right_x - left_x, width);
4269
4270 /* Right. */
4271 if (right_p)
4272 XFillRectangle (s->display, s->window, &xgcv,
4273 right_x - width, top_y, width, bottom_y - top_y);
4274
4275 mac_reset_clipping (s->display, s->window);
4276 }
4277
4278
4279 /* Draw a box around glyph string S. */
4280
4281 static void
4282 x_draw_glyph_string_box (s)
4283 struct glyph_string *s;
4284 {
4285 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4286 int left_p, right_p;
4287 struct glyph *last_glyph;
4288 Rect clip_rect;
4289
4290 last_x = window_box_right (s->w, s->area);
4291 if (s->row->full_width_p
4292 && !s->w->pseudo_window_p)
4293 {
4294 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4295 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4296 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4297 }
4298
4299 /* The glyph that may have a right box line. */
4300 last_glyph = (s->cmp || s->img
4301 ? s->first_glyph
4302 : s->first_glyph + s->nchars - 1);
4303
4304 width = abs (s->face->box_line_width);
4305 raised_p = s->face->box == FACE_RAISED_BOX;
4306 left_x = s->x;
4307 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
4308 ? last_x - 1
4309 : min (last_x, s->x + s->background_width) - 1));
4310 top_y = s->y;
4311 bottom_y = top_y + s->height - 1;
4312
4313 left_p = (s->first_glyph->left_box_line_p
4314 || (s->hl == DRAW_MOUSE_FACE
4315 && (s->prev == NULL
4316 || s->prev->hl != s->hl)));
4317 right_p = (last_glyph->right_box_line_p
4318 || (s->hl == DRAW_MOUSE_FACE
4319 && (s->next == NULL
4320 || s->next->hl != s->hl)));
4321
4322 x_get_glyph_string_clip_rect (s, &clip_rect);
4323
4324 if (s->face->box == FACE_SIMPLE_BOX)
4325 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4326 left_p, right_p, &clip_rect);
4327 else
4328 {
4329 x_setup_relief_colors (s);
4330 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4331 width, raised_p, left_p, right_p, &clip_rect);
4332 }
4333 }
4334
4335
4336 /* Draw foreground of image glyph string S. */
4337
4338 static void
4339 x_draw_image_foreground (s)
4340 struct glyph_string *s;
4341 {
4342 int x;
4343 int y = s->ybase - image_ascent (s->img, s->face);
4344
4345 /* If first glyph of S has a left box line, start drawing it to the
4346 right of that line. */
4347 if (s->face->box != FACE_NO_BOX
4348 && s->first_glyph->left_box_line_p)
4349 x = s->x + abs (s->face->box_line_width);
4350 else
4351 x = s->x;
4352
4353 /* If there is a margin around the image, adjust x- and y-position
4354 by that margin. */
4355 x += s->img->hmargin;
4356 y += s->img->vmargin;
4357
4358 if (s->img->pixmap)
4359 {
4360 #if 0 /* MAC_TODO: image mask */
4361 if (s->img->mask)
4362 {
4363 /* We can't set both a clip mask and use XSetClipRectangles
4364 because the latter also sets a clip mask. We also can't
4365 trust on the shape extension to be available
4366 (XShapeCombineRegion). So, compute the rectangle to draw
4367 manually. */
4368 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4369 | GCFunction);
4370 XGCValues xgcv;
4371 XRectangle clip_rect, image_rect, r;
4372
4373 xgcv.clip_mask = s->img->mask;
4374 xgcv.clip_x_origin = x;
4375 xgcv.clip_y_origin = y;
4376 xgcv.function = GXcopy;
4377 XChangeGC (s->display, s->gc, mask, &xgcv);
4378
4379 x_get_glyph_string_clip_rect (s, &clip_rect);
4380 image_rect.x = x;
4381 image_rect.y = y;
4382 image_rect.width = s->img->width;
4383 image_rect.height = s->img->height;
4384 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4385 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4386 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4387 }
4388 else
4389 #endif /* MAC_TODO */
4390 {
4391 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4392 0, 0, s->img->width, s->img->height, x, y);
4393
4394 /* When the image has a mask, we can expect that at
4395 least part of a mouse highlight or a block cursor will
4396 be visible. If the image doesn't have a mask, make
4397 a block cursor visible by drawing a rectangle around
4398 the image. I believe it's looking better if we do
4399 nothing here for mouse-face. */
4400 if (s->hl == DRAW_CURSOR)
4401 {
4402 int r = s->img->relief;
4403 if (r < 0) r = -r;
4404 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
4405 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4406 }
4407 }
4408 }
4409 else
4410 /* Draw a rectangle if image could not be loaded. */
4411 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4412 s->img->width - 1, s->img->height - 1);
4413 }
4414
4415
4416
4417 /* Draw a relief around the image glyph string S. */
4418
4419 static void
4420 x_draw_image_relief (s)
4421 struct glyph_string *s;
4422 {
4423 int x0, y0, x1, y1, thick, raised_p;
4424 Rect r;
4425 int x;
4426 int y = s->ybase - image_ascent (s->img, s->face);
4427
4428 /* If first glyph of S has a left box line, start drawing it to the
4429 right of that line. */
4430 if (s->face->box != FACE_NO_BOX
4431 && s->first_glyph->left_box_line_p)
4432 x = s->x + abs (s->face->box_line_width);
4433 else
4434 x = s->x;
4435
4436 /* If there is a margin around the image, adjust x- and y-position
4437 by that margin. */
4438 x += s->img->hmargin;
4439 y += s->img->vmargin;
4440
4441 if (s->hl == DRAW_IMAGE_SUNKEN
4442 || s->hl == DRAW_IMAGE_RAISED)
4443 {
4444 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4445 raised_p = s->hl == DRAW_IMAGE_RAISED;
4446 }
4447 else
4448 {
4449 thick = abs (s->img->relief);
4450 raised_p = s->img->relief > 0;
4451 }
4452
4453 x0 = x - thick;
4454 y0 = y - thick;
4455 x1 = x + s->img->width + thick - 1;
4456 y1 = y + s->img->height + thick - 1;
4457
4458 x_setup_relief_colors (s);
4459 x_get_glyph_string_clip_rect (s, &r);
4460 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4461 }
4462
4463
4464 /* Draw the foreground of image glyph string S to PIXMAP. */
4465
4466 static void
4467 x_draw_image_foreground_1 (s, pixmap)
4468 struct glyph_string *s;
4469 Pixmap pixmap;
4470 {
4471 int x;
4472 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4473
4474 /* If first glyph of S has a left box line, start drawing it to the
4475 right of that line. */
4476 if (s->face->box != FACE_NO_BOX
4477 && s->first_glyph->left_box_line_p)
4478 x = abs (s->face->box_line_width);
4479 else
4480 x = 0;
4481
4482 /* If there is a margin around the image, adjust x- and y-position
4483 by that margin. */
4484 x += s->img->hmargin;
4485 y += s->img->vmargin;
4486
4487 if (s->img->pixmap)
4488 {
4489 #if 0 /* MAC_TODO: image mask */
4490 if (s->img->mask)
4491 {
4492 /* We can't set both a clip mask and use XSetClipRectangles
4493 because the latter also sets a clip mask. We also can't
4494 trust on the shape extension to be available
4495 (XShapeCombineRegion). So, compute the rectangle to draw
4496 manually. */
4497 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4498 | GCFunction);
4499 XGCValues xgcv;
4500
4501 xgcv.clip_mask = s->img->mask;
4502 xgcv.clip_x_origin = x;
4503 xgcv.clip_y_origin = y;
4504 xgcv.function = GXcopy;
4505 XChangeGC (s->display, s->gc, mask, &xgcv);
4506
4507 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4508 0, 0, s->img->width, s->img->height, x, y);
4509 XSetClipMask (s->display, s->gc, None);
4510 }
4511 else
4512 #endif /* MAC_TODO */
4513 {
4514 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4515 0, 0, s->img->width, s->img->height, x, y);
4516
4517 /* When the image has a mask, we can expect that at
4518 least part of a mouse highlight or a block cursor will
4519 be visible. If the image doesn't have a mask, make
4520 a block cursor visible by drawing a rectangle around
4521 the image. I believe it's looking better if we do
4522 nothing here for mouse-face. */
4523 if (s->hl == DRAW_CURSOR)
4524 {
4525 int r = s->img->relief;
4526 if (r < 0) r = -r;
4527 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
4528 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4529 }
4530 }
4531 }
4532 else
4533 /* Draw a rectangle if image could not be loaded. */
4534 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4535 s->img->width - 1, s->img->height - 1);
4536 }
4537
4538
4539 /* Draw part of the background of glyph string S. X, Y, W, and H
4540 give the rectangle to draw. */
4541
4542 static void
4543 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4544 struct glyph_string *s;
4545 int x, y, w, h;
4546 {
4547 #if 0 /* MAC_TODO: stipple */
4548 if (s->stippled_p)
4549 {
4550 /* Fill background with a stipple pattern. */
4551 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4552 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4553 XSetFillStyle (s->display, s->gc, FillSolid);
4554 }
4555 else
4556 #endif /* MAC_TODO */
4557 x_clear_glyph_string_rect (s, x, y, w, h);
4558 }
4559
4560
4561 /* Draw image glyph string S.
4562
4563 s->y
4564 s->x +-------------------------
4565 | s->face->box
4566 |
4567 | +-------------------------
4568 | | s->img->vmargin
4569 | |
4570 | | +-------------------
4571 | | | the image
4572
4573 */
4574
4575 static void
4576 x_draw_image_glyph_string (s)
4577 struct glyph_string *s;
4578 {
4579 int x, y;
4580 int box_line_hwidth = abs (s->face->box_line_width);
4581 int box_line_vwidth = max (s->face->box_line_width, 0);
4582 int height;
4583 Pixmap pixmap = 0;
4584
4585 height = s->height - 2 * box_line_vwidth;
4586
4587 /* Fill background with face under the image. Do it only if row is
4588 taller than image or if image has a clip mask to reduce
4589 flickering. */
4590 s->stippled_p = s->face->stipple != 0;
4591 if (height > s->img->height
4592 || s->img->hmargin
4593 || s->img->vmargin
4594 #if 0 /* TODO: image mask */
4595 || s->img->mask
4596 #endif
4597 || s->img->pixmap == 0
4598 || s->width != s->background_width)
4599 {
4600 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4601 x = s->x + box_line_hwidth;
4602 else
4603 x = s->x;
4604
4605 y = s->y + box_line_vwidth;
4606 #if 0 /* TODO: image mask */
4607 if (s->img->mask)
4608 {
4609 /* Create a pixmap as large as the glyph string. Fill it
4610 with the background color. Copy the image to it, using
4611 its mask. Copy the temporary pixmap to the display. */
4612 Screen *screen = FRAME_X_SCREEN (s->f);
4613 int depth = DefaultDepthOfScreen (screen);
4614
4615 /* Create a pixmap as large as the glyph string. */
4616 pixmap = XCreatePixmap (s->display, s->window,
4617 s->background_width,
4618 s->height, depth);
4619
4620 /* Don't clip in the following because we're working on the
4621 pixmap. */
4622 XSetClipMask (s->display, s->gc, None);
4623
4624 /* Fill the pixmap with the background color/stipple. */
4625 if (s->stippled_p)
4626 {
4627 /* Fill background with a stipple pattern. */
4628 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4629 XFillRectangle (s->display, pixmap, s->gc,
4630 0, 0, s->background_width, s->height);
4631 XSetFillStyle (s->display, s->gc, FillSolid);
4632 }
4633 else
4634 {
4635 XGCValues xgcv;
4636 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4637 &xgcv);
4638 XSetForeground (s->display, s->gc, xgcv.background);
4639 XFillRectangle (s->display, pixmap, s->gc,
4640 0, 0, s->background_width, s->height);
4641 XSetForeground (s->display, s->gc, xgcv.foreground);
4642 }
4643 }
4644 else
4645 #endif
4646 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4647
4648 s->background_filled_p = 1;
4649 }
4650
4651 /* Draw the foreground. */
4652 if (pixmap != 0)
4653 {
4654 x_draw_image_foreground_1 (s, pixmap);
4655 x_set_glyph_string_clipping (s);
4656 mac_copy_area (s->display, pixmap, s->window, s->gc,
4657 0, 0, s->background_width, s->height, s->x, s->y);
4658 mac_reset_clipping (s->display, s->window);
4659 XFreePixmap (s->display, pixmap);
4660 }
4661 else
4662 x_draw_image_foreground (s);
4663
4664 /* If we must draw a relief around the image, do it. */
4665 if (s->img->relief
4666 || s->hl == DRAW_IMAGE_RAISED
4667 || s->hl == DRAW_IMAGE_SUNKEN)
4668 x_draw_image_relief (s);
4669 }
4670
4671
4672 /* Draw stretch glyph string S. */
4673
4674 static void
4675 x_draw_stretch_glyph_string (s)
4676 struct glyph_string *s;
4677 {
4678 xassert (s->first_glyph->type == STRETCH_GLYPH);
4679 s->stippled_p = s->face->stipple != 0;
4680
4681 if (s->hl == DRAW_CURSOR
4682 && !x_stretch_cursor_p)
4683 {
4684 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4685 as wide as the stretch glyph. */
4686 int width = min (CANON_X_UNIT (s->f), s->background_width);
4687
4688 /* Draw cursor. */
4689 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4690
4691 /* Clear rest using the GC of the original non-cursor face. */
4692 if (width < s->background_width)
4693 {
4694 GC gc = s->face->gc;
4695 int x = s->x + width, y = s->y;
4696 int w = s->background_width - width, h = s->height;
4697 Rect r;
4698
4699 if (s->row->mouse_face_p
4700 && cursor_in_mouse_face_p (s->w))
4701 {
4702 x_set_mouse_face_gc (s);
4703 gc = s->gc;
4704 }
4705 else
4706 gc = s->face->gc;
4707
4708 x_get_glyph_string_clip_rect (s, &r);
4709 mac_set_clip_rectangle (s->display, s->window, &r);
4710
4711 #if 0 /* MAC_TODO: stipple */
4712 if (s->face->stipple)
4713 {
4714 /* Fill background with a stipple pattern. */
4715 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4716 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4717 XSetFillStyle (s->display, gc, FillSolid);
4718 }
4719 else
4720 #endif /* MAC_TODO */
4721 {
4722 XGCValues xgcv;
4723 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4724 XSetForeground (s->display, gc, xgcv.background);
4725 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4726 XSetForeground (s->display, gc, xgcv.foreground);
4727 }
4728
4729 mac_reset_clipping (s->display, s->window);
4730 }
4731 }
4732 else if (!s->background_filled_p)
4733 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4734 s->height);
4735
4736 s->background_filled_p = 1;
4737 }
4738
4739
4740 /* Draw glyph string S. */
4741
4742 static void
4743 x_draw_glyph_string (s)
4744 struct glyph_string *s;
4745 {
4746 int relief_drawn_p = 0;
4747
4748 /* If S draws into the background of its successor, draw the
4749 background of the successor first so that S can draw into it.
4750 This makes S->next use XDrawString instead of XDrawImageString. */
4751 if (s->next && s->right_overhang && !s->for_overlaps_p)
4752 {
4753 xassert (s->next->img == NULL);
4754 x_set_glyph_string_gc (s->next);
4755 x_set_glyph_string_clipping (s->next);
4756 x_draw_glyph_string_background (s->next, 1);
4757
4758 }
4759
4760 /* Set up S->gc, set clipping and draw S. */
4761 x_set_glyph_string_gc (s);
4762
4763 /* Draw relief (if any) in advance for char/composition so that the
4764 glyph string can be drawn over it. */
4765 if (!s->for_overlaps_p
4766 && s->face->box != FACE_NO_BOX
4767 && (s->first_glyph->type == CHAR_GLYPH
4768 || s->first_glyph->type == COMPOSITE_GLYPH))
4769
4770 {
4771 x_set_glyph_string_clipping (s);
4772 x_draw_glyph_string_background (s, 1);
4773 x_draw_glyph_string_box (s);
4774 x_set_glyph_string_clipping (s);
4775 relief_drawn_p = 1;
4776 }
4777 else
4778 x_set_glyph_string_clipping (s);
4779
4780 switch (s->first_glyph->type)
4781 {
4782 case IMAGE_GLYPH:
4783 x_draw_image_glyph_string (s);
4784 break;
4785
4786 case STRETCH_GLYPH:
4787 x_draw_stretch_glyph_string (s);
4788 break;
4789
4790 case CHAR_GLYPH:
4791 if (s->for_overlaps_p)
4792 s->background_filled_p = 1;
4793 else
4794 x_draw_glyph_string_background (s, 0);
4795 x_draw_glyph_string_foreground (s);
4796 break;
4797
4798 case COMPOSITE_GLYPH:
4799 if (s->for_overlaps_p || s->gidx > 0)
4800 s->background_filled_p = 1;
4801 else
4802 x_draw_glyph_string_background (s, 1);
4803 x_draw_composite_glyph_string_foreground (s);
4804 break;
4805
4806 default:
4807 abort ();
4808 }
4809
4810 if (!s->for_overlaps_p)
4811 {
4812 /* Draw underline. */
4813 if (s->face->underline_p)
4814 {
4815 unsigned long h = 1;
4816 unsigned long dy = s->height - h;
4817
4818 if (s->face->underline_defaulted_p)
4819 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4820 s->width, h);
4821 else
4822 {
4823 XGCValues xgcv;
4824 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4825 XSetForeground (s->display, s->gc, s->face->underline_color);
4826 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4827 s->width, h);
4828 XSetForeground (s->display, s->gc, xgcv.foreground);
4829 }
4830 }
4831
4832 /* Draw overline. */
4833 if (s->face->overline_p)
4834 {
4835 unsigned long dy = 0, h = 1;
4836
4837 if (s->face->overline_color_defaulted_p)
4838 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4839 s->width, h);
4840 else
4841 {
4842 XGCValues xgcv;
4843 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4844 XSetForeground (s->display, s->gc, s->face->overline_color);
4845 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4846 s->width, h);
4847 XSetForeground (s->display, s->gc, xgcv.foreground);
4848 }
4849 }
4850
4851 /* Draw strike-through. */
4852 if (s->face->strike_through_p)
4853 {
4854 unsigned long h = 1;
4855 unsigned long dy = (s->height - h) / 2;
4856
4857 if (s->face->strike_through_color_defaulted_p)
4858 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4859 s->width, h);
4860 else
4861 {
4862 XGCValues xgcv;
4863 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4864 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4865 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4866 s->width, h);
4867 XSetForeground (s->display, s->gc, xgcv.foreground);
4868 }
4869 }
4870
4871 /* Draw relief. */
4872 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4873 x_draw_glyph_string_box (s);
4874 }
4875
4876 /* Reset clipping. */
4877 mac_reset_clipping (s->display, s->window);
4878 }
4879
4880
4881 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4882 struct face **, int));
4883
4884
4885 /* Fill glyph string S with composition components specified by S->cmp.
4886
4887 FACES is an array of faces for all components of this composition.
4888 S->gidx is the index of the first component for S.
4889 OVERLAPS_P non-zero means S should draw the foreground only, and
4890 use its physical height for clipping.
4891
4892 Value is the index of a component not in S. */
4893
4894 static int
4895 x_fill_composite_glyph_string (s, faces, overlaps_p)
4896 struct glyph_string *s;
4897 struct face **faces;
4898 int overlaps_p;
4899 {
4900 int i;
4901
4902 xassert (s);
4903
4904 s->for_overlaps_p = overlaps_p;
4905
4906 s->face = faces[s->gidx];
4907 s->font = s->face->font;
4908 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4909
4910 /* For all glyphs of this composition, starting at the offset
4911 S->gidx, until we reach the end of the definition or encounter a
4912 glyph that requires the different face, add it to S. */
4913 ++s->nchars;
4914 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4915 ++s->nchars;
4916
4917 /* All glyph strings for the same composition has the same width,
4918 i.e. the width set for the first component of the composition. */
4919
4920 s->width = s->first_glyph->pixel_width;
4921
4922 /* If the specified font could not be loaded, use the frame's
4923 default font, but record the fact that we couldn't load it in
4924 the glyph string so that we can draw rectangles for the
4925 characters of the glyph string. */
4926 if (s->font == NULL)
4927 {
4928 s->font_not_found_p = 1;
4929 s->font = FRAME_FONT (s->f);
4930 }
4931
4932 /* Adjust base line for subscript/superscript text. */
4933 s->ybase += s->first_glyph->voffset;
4934
4935 xassert (s->face && s->face->gc);
4936
4937 /* This glyph string must always be drawn with 16-bit functions. */
4938 s->two_byte_p = 1;
4939
4940 return s->gidx + s->nchars;
4941 }
4942
4943
4944 /* Fill glyph string S from a sequence of character glyphs.
4945
4946 FACE_ID is the face id of the string. START is the index of the
4947 first glyph to consider, END is the index of the last + 1.
4948 OVERLAPS_P non-zero means S should draw the foreground only, and
4949 use its physical height for clipping.
4950
4951 Value is the index of the first glyph not in S. */
4952
4953 static int
4954 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4955 struct glyph_string *s;
4956 int face_id;
4957 int start, end, overlaps_p;
4958 {
4959 struct glyph *glyph, *last;
4960 int voffset;
4961 int glyph_not_available_p;
4962
4963 xassert (s->f == XFRAME (s->w->frame));
4964 xassert (s->nchars == 0);
4965 xassert (start >= 0 && end > start);
4966
4967 s->for_overlaps_p = overlaps_p;
4968 glyph = s->row->glyphs[s->area] + start;
4969 last = s->row->glyphs[s->area] + end;
4970 voffset = glyph->voffset;
4971
4972 glyph_not_available_p = glyph->glyph_not_available_p;
4973
4974 while (glyph < last
4975 && glyph->type == CHAR_GLYPH
4976 && glyph->voffset == voffset
4977 /* Same face id implies same font, nowadays. */
4978 && glyph->face_id == face_id
4979 && glyph->glyph_not_available_p == glyph_not_available_p)
4980 {
4981 int two_byte_p;
4982
4983 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4984 s->char2b + s->nchars,
4985 &two_byte_p);
4986 s->two_byte_p = two_byte_p;
4987 ++s->nchars;
4988 xassert (s->nchars <= end - start);
4989 s->width += glyph->pixel_width;
4990 ++glyph;
4991 }
4992
4993 s->font = s->face->font;
4994 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4995
4996 /* If the specified font could not be loaded, use the frame's font,
4997 but record the fact that we couldn't load it in
4998 S->font_not_found_p so that we can draw rectangles for the
4999 characters of the glyph string. */
5000 if (s->font == NULL || glyph_not_available_p)
5001 {
5002 s->font_not_found_p = 1;
5003 s->font = FRAME_FONT (s->f);
5004 }
5005
5006 /* Adjust base line for subscript/superscript text. */
5007 s->ybase += voffset;
5008
5009 xassert (s->face && s->face->gc);
5010 return glyph - s->row->glyphs[s->area];
5011 }
5012
5013
5014 /* Fill glyph string S from image glyph S->first_glyph. */
5015
5016 static void
5017 x_fill_image_glyph_string (s)
5018 struct glyph_string *s;
5019 {
5020 xassert (s->first_glyph->type == IMAGE_GLYPH);
5021 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
5022 xassert (s->img);
5023 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
5024 s->font = s->face->font;
5025 s->width = s->first_glyph->pixel_width;
5026
5027 /* Adjust base line for subscript/superscript text. */
5028 s->ybase += s->first_glyph->voffset;
5029 }
5030
5031
5032 /* Fill glyph string S from a sequence of stretch glyphs.
5033
5034 ROW is the glyph row in which the glyphs are found, AREA is the
5035 area within the row. START is the index of the first glyph to
5036 consider, END is the index of the last + 1.
5037
5038 Value is the index of the first glyph not in S. */
5039
5040 static int
5041 x_fill_stretch_glyph_string (s, row, area, start, end)
5042 struct glyph_string *s;
5043 struct glyph_row *row;
5044 enum glyph_row_area area;
5045 int start, end;
5046 {
5047 struct glyph *glyph, *last;
5048 int voffset, face_id;
5049
5050 xassert (s->first_glyph->type == STRETCH_GLYPH);
5051
5052 glyph = s->row->glyphs[s->area] + start;
5053 last = s->row->glyphs[s->area] + end;
5054 face_id = glyph->face_id;
5055 s->face = FACE_FROM_ID (s->f, face_id);
5056 s->font = s->face->font;
5057 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5058 s->width = glyph->pixel_width;
5059 voffset = glyph->voffset;
5060
5061 for (++glyph;
5062 (glyph < last
5063 && glyph->type == STRETCH_GLYPH
5064 && glyph->voffset == voffset
5065 && glyph->face_id == face_id);
5066 ++glyph)
5067 s->width += glyph->pixel_width;
5068
5069 /* Adjust base line for subscript/superscript text. */
5070 s->ybase += voffset;
5071
5072 xassert (s->face);
5073 return glyph - s->row->glyphs[s->area];
5074 }
5075
5076
5077 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
5078 of XChar2b structures for S; it can't be allocated in
5079 x_init_glyph_string because it must be allocated via `alloca'. W
5080 is the window on which S is drawn. ROW and AREA are the glyph row
5081 and area within the row from which S is constructed. START is the
5082 index of the first glyph structure covered by S. HL is a
5083 face-override for drawing S. */
5084
5085 static void
5086 x_init_glyph_string (s, char2b, w, row, area, start, hl)
5087 struct glyph_string *s;
5088 XChar2b *char2b;
5089 struct window *w;
5090 struct glyph_row *row;
5091 enum glyph_row_area area;
5092 int start;
5093 enum draw_glyphs_face hl;
5094 {
5095 bzero (s, sizeof *s);
5096 s->w = w;
5097 s->f = XFRAME (w->frame);
5098 s->display = FRAME_MAC_DISPLAY (s->f);
5099 s->window = FRAME_MAC_WINDOW (s->f);
5100 s->char2b = char2b;
5101 s->hl = hl;
5102 s->row = row;
5103 s->area = area;
5104 s->first_glyph = row->glyphs[area] + start;
5105 s->height = row->height;
5106 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5107
5108 /* Display the internal border below the tool-bar window. */
5109 if (s->w == XWINDOW (s->f->tool_bar_window))
5110 s->y -= s->f->output_data.mac->internal_border_width;
5111
5112 s->ybase = s->y + row->ascent;
5113 }
5114
5115
5116 /* Set background width of glyph string S. START is the index of the
5117 first glyph following S. LAST_X is the right-most x-position + 1
5118 in the drawing area. */
5119
5120 static INLINE void
5121 x_set_glyph_string_background_width (s, start, last_x)
5122 struct glyph_string *s;
5123 int start;
5124 int last_x;
5125 {
5126 /* If the face of this glyph string has to be drawn to the end of
5127 the drawing area, set S->extends_to_end_of_line_p. */
5128 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
5129
5130 if (start == s->row->used[s->area]
5131 && s->area == TEXT_AREA
5132 && ((s->hl == DRAW_NORMAL_TEXT
5133 && (s->row->fill_line_p
5134 || s->face->background != default_face->background
5135 || s->face->stipple != default_face->stipple
5136 || s->row->mouse_face_p))
5137 || s->hl == DRAW_MOUSE_FACE
5138 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
5139 && s->row->fill_line_p)))
5140 s->extends_to_end_of_line_p = 1;
5141
5142 /* If S extends its face to the end of the line, set its
5143 background_width to the distance to the right edge of the drawing
5144 area. */
5145 if (s->extends_to_end_of_line_p)
5146 s->background_width = last_x - s->x + 1;
5147 else
5148 s->background_width = s->width;
5149 }
5150
5151
5152 /* Add a glyph string for a stretch glyph to the list of strings
5153 between HEAD and TAIL. START is the index of the stretch glyph in
5154 row area AREA of glyph row ROW. END is the index of the last glyph
5155 in that glyph row area. X is the current output position assigned
5156 to the new glyph string constructed. HL overrides that face of the
5157 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5158 is the right-most x-position of the drawing area. */
5159
5160 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5161 and below -- keep them on one line. */
5162 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5163 do \
5164 { \
5165 s = (struct glyph_string *) alloca (sizeof *s); \
5166 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5167 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5168 x_append_glyph_string (&HEAD, &TAIL, s); \
5169 s->x = (X); \
5170 } \
5171 while (0)
5172
5173
5174 /* Add a glyph string for an image glyph to the list of strings
5175 between HEAD and TAIL. START is the index of the image glyph in
5176 row area AREA of glyph row ROW. END is the index of the last glyph
5177 in that glyph row area. X is the current output position assigned
5178 to the new glyph string constructed. HL overrides that face of the
5179 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5180 is the right-most x-position of the drawing area. */
5181
5182 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5183 do \
5184 { \
5185 s = (struct glyph_string *) alloca (sizeof *s); \
5186 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5187 x_fill_image_glyph_string (s); \
5188 x_append_glyph_string (&HEAD, &TAIL, s); \
5189 ++START; \
5190 s->x = (X); \
5191 } \
5192 while (0)
5193
5194
5195 /* Add a glyph string for a sequence of character glyphs to the list
5196 of strings between HEAD and TAIL. START is the index of the first
5197 glyph in row area AREA of glyph row ROW that is part of the new
5198 glyph string. END is the index of the last glyph in that glyph row
5199 area. X is the current output position assigned to the new glyph
5200 string constructed. HL overrides that face of the glyph; e.g. it
5201 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5202 right-most x-position of the drawing area. */
5203
5204 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5205 do \
5206 { \
5207 int c, face_id; \
5208 XChar2b *char2b; \
5209 \
5210 c = (ROW)->glyphs[AREA][START].u.ch; \
5211 face_id = (ROW)->glyphs[AREA][START].face_id; \
5212 \
5213 s = (struct glyph_string *) alloca (sizeof *s); \
5214 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5215 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5216 x_append_glyph_string (&HEAD, &TAIL, s); \
5217 s->x = (X); \
5218 START = x_fill_glyph_string (s, face_id, START, END, \
5219 OVERLAPS_P); \
5220 } \
5221 while (0)
5222
5223
5224 /* Add a glyph string for a composite sequence to the list of strings
5225 between HEAD and TAIL. START is the index of the first glyph in
5226 row area AREA of glyph row ROW that is part of the new glyph
5227 string. END is the index of the last glyph in that glyph row area.
5228 X is the current output position assigned to the new glyph string
5229 constructed. HL overrides that face of the glyph; e.g. it is
5230 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5231 x-position of the drawing area. */
5232
5233 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5234 do { \
5235 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5236 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5237 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5238 struct composition *cmp = composition_table[cmp_id]; \
5239 int glyph_len = cmp->glyph_len; \
5240 XChar2b *char2b; \
5241 struct face **faces; \
5242 struct glyph_string *first_s = NULL; \
5243 int n; \
5244 \
5245 base_face = base_face->ascii_face; \
5246 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5247 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5248 /* At first, fill in `char2b' and `faces'. */ \
5249 for (n = 0; n < glyph_len; n++) \
5250 { \
5251 int c = COMPOSITION_GLYPH (cmp, n); \
5252 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5253 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5254 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5255 this_face_id, char2b + n, 1); \
5256 } \
5257 \
5258 /* Make glyph_strings for each glyph sequence that is drawable by \
5259 the same face, and append them to HEAD/TAIL. */ \
5260 for (n = 0; n < cmp->glyph_len;) \
5261 { \
5262 s = (struct glyph_string *) alloca (sizeof *s); \
5263 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5264 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5265 s->cmp = cmp; \
5266 s->gidx = n; \
5267 s->x = (X); \
5268 \
5269 if (n == 0) \
5270 first_s = s; \
5271 \
5272 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5273 } \
5274 \
5275 ++START; \
5276 s = first_s; \
5277 } while (0)
5278
5279
5280 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5281 of AREA of glyph row ROW on window W between indices START and END.
5282 HL overrides the face for drawing glyph strings, e.g. it is
5283 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5284 x-positions of the drawing area.
5285
5286 This is an ugly monster macro construct because we must use alloca
5287 to allocate glyph strings (because x_draw_glyphs can be called
5288 asynchronously). */
5289
5290 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5291 do \
5292 { \
5293 HEAD = TAIL = NULL; \
5294 while (START < END) \
5295 { \
5296 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5297 switch (first_glyph->type) \
5298 { \
5299 case CHAR_GLYPH: \
5300 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5301 TAIL, HL, X, LAST_X, \
5302 OVERLAPS_P); \
5303 break; \
5304 \
5305 case COMPOSITE_GLYPH: \
5306 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5307 HEAD, TAIL, HL, X, LAST_X,\
5308 OVERLAPS_P); \
5309 break; \
5310 \
5311 case STRETCH_GLYPH: \
5312 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5313 HEAD, TAIL, HL, X, LAST_X); \
5314 break; \
5315 \
5316 case IMAGE_GLYPH: \
5317 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5318 TAIL, HL, X, LAST_X); \
5319 break; \
5320 \
5321 default: \
5322 abort (); \
5323 } \
5324 \
5325 x_set_glyph_string_background_width (s, START, LAST_X); \
5326 (X) += s->width; \
5327 } \
5328 } \
5329 while (0)
5330
5331
5332 /* Draw glyphs between START and END in AREA of ROW on window W,
5333 starting at x-position X. X is relative to AREA in W. HL is a
5334 face-override with the following meaning:
5335
5336 DRAW_NORMAL_TEXT draw normally
5337 DRAW_CURSOR draw in cursor face
5338 DRAW_MOUSE_FACE draw in mouse face.
5339 DRAW_INVERSE_VIDEO draw in mode line face
5340 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5341 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5342
5343 If OVERLAPS_P is non-zero, draw only the foreground of characters
5344 and clip to the physical height of ROW.
5345
5346 Value is the x-position reached, relative to AREA of W. */
5347
5348 static int
5349 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5350 struct window *w;
5351 int x;
5352 struct glyph_row *row;
5353 enum glyph_row_area area;
5354 int start, end;
5355 enum draw_glyphs_face hl;
5356 int overlaps_p;
5357 {
5358 struct glyph_string *head, *tail;
5359 struct glyph_string *s;
5360 int last_x, area_width;
5361 int x_reached;
5362 int i, j;
5363
5364 /* Let's rather be paranoid than getting a SEGV. */
5365 end = min (end, row->used[area]);
5366 start = max (0, start);
5367 start = min (end, start);
5368
5369 /* Translate X to frame coordinates. Set last_x to the right
5370 end of the drawing area. */
5371 if (row->full_width_p)
5372 {
5373 /* X is relative to the left edge of W, without scroll bars
5374 or fringes. */
5375 struct frame *f = XFRAME (WINDOW_FRAME (w));
5376 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5377
5378 x += window_left_x;
5379 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5380 last_x = window_left_x + area_width;
5381
5382 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5383 {
5384 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5385 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5386 last_x += width;
5387 else
5388 x -= width;
5389 }
5390
5391 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5392 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5393 }
5394 else
5395 {
5396 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5397 area_width = window_box_width (w, area);
5398 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5399 }
5400
5401 /* Build a doubly-linked list of glyph_string structures between
5402 head and tail from what we have to draw. Note that the macro
5403 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5404 the reason we use a separate variable `i'. */
5405 i = start;
5406 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5407 overlaps_p);
5408 if (tail)
5409 x_reached = tail->x + tail->background_width;
5410 else
5411 x_reached = x;
5412
5413 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5414 the row, redraw some glyphs in front or following the glyph
5415 strings built above. */
5416 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5417 {
5418 int dummy_x = 0;
5419 struct glyph_string *h, *t;
5420
5421 /* Compute overhangs for all glyph strings. */
5422 for (s = head; s; s = s->next)
5423 x_compute_glyph_string_overhangs (s);
5424
5425 /* Prepend glyph strings for glyphs in front of the first glyph
5426 string that are overwritten because of the first glyph
5427 string's left overhang. The background of all strings
5428 prepended must be drawn because the first glyph string
5429 draws over it. */
5430 i = x_left_overwritten (head);
5431 if (i >= 0)
5432 {
5433 j = i;
5434 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5435 DRAW_NORMAL_TEXT, dummy_x, last_x,
5436 overlaps_p);
5437 start = i;
5438 x_compute_overhangs_and_x (t, head->x, 1);
5439 x_prepend_glyph_string_lists (&head, &tail, h, t);
5440 }
5441
5442 /* Prepend glyph strings for glyphs in front of the first glyph
5443 string that overwrite that glyph string because of their
5444 right overhang. For these strings, only the foreground must
5445 be drawn, because it draws over the glyph string at `head'.
5446 The background must not be drawn because this would overwrite
5447 right overhangs of preceding glyphs for which no glyph
5448 strings exist. */
5449 i = x_left_overwriting (head);
5450 if (i >= 0)
5451 {
5452 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5453 DRAW_NORMAL_TEXT, dummy_x, last_x,
5454 overlaps_p);
5455 for (s = h; s; s = s->next)
5456 s->background_filled_p = 1;
5457 x_compute_overhangs_and_x (t, head->x, 1);
5458 x_prepend_glyph_string_lists (&head, &tail, h, t);
5459 }
5460
5461 /* Append glyphs strings for glyphs following the last glyph
5462 string tail that are overwritten by tail. The background of
5463 these strings has to be drawn because tail's foreground draws
5464 over it. */
5465 i = x_right_overwritten (tail);
5466 if (i >= 0)
5467 {
5468 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5469 DRAW_NORMAL_TEXT, x, last_x,
5470 overlaps_p);
5471 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5472 x_append_glyph_string_lists (&head, &tail, h, t);
5473 }
5474
5475 /* Append glyph strings for glyphs following the last glyph
5476 string tail that overwrite tail. The foreground of such
5477 glyphs has to be drawn because it writes into the background
5478 of tail. The background must not be drawn because it could
5479 paint over the foreground of following glyphs. */
5480 i = x_right_overwriting (tail);
5481 if (i >= 0)
5482 {
5483 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5484 DRAW_NORMAL_TEXT, x, last_x,
5485 overlaps_p);
5486 for (s = h; s; s = s->next)
5487 s->background_filled_p = 1;
5488 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5489 x_append_glyph_string_lists (&head, &tail, h, t);
5490 }
5491 }
5492
5493 /* Draw all strings. */
5494 for (s = head; s; s = s->next)
5495 x_draw_glyph_string (s);
5496
5497 if (area == TEXT_AREA
5498 && !row->full_width_p
5499 /* When drawing overlapping rows, only the glyph strings'
5500 foreground is drawn, which doesn't erase a cursor
5501 completely. */
5502 && !overlaps_p)
5503 {
5504 int x0 = head ? head->x : x;
5505 int x1 = tail ? tail->x + tail->background_width : x;
5506
5507 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5508 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5509
5510 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5511 {
5512 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5513 x0 -= left_area_width;
5514 x1 -= left_area_width;
5515 }
5516
5517 notice_overwritten_cursor (w, area, x0, x1,
5518 row->y, MATRIX_ROW_BOTTOM_Y (row));
5519 }
5520
5521 /* Value is the x-position up to which drawn, relative to AREA of W.
5522 This doesn't include parts drawn because of overhangs. */
5523 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5524 if (!row->full_width_p)
5525 {
5526 if (area > LEFT_MARGIN_AREA)
5527 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5528 if (area > TEXT_AREA)
5529 x_reached -= window_box_width (w, TEXT_AREA);
5530 }
5531
5532 return x_reached;
5533 }
5534
5535
5536 /* Fix the display of area AREA of overlapping row ROW in window W. */
5537
5538 static void
5539 x_fix_overlapping_area (w, row, area)
5540 struct window *w;
5541 struct glyph_row *row;
5542 enum glyph_row_area area;
5543 {
5544 int i, x;
5545
5546 BLOCK_INPUT;
5547
5548 if (area == LEFT_MARGIN_AREA)
5549 x = 0;
5550 else if (area == TEXT_AREA)
5551 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5552 else
5553 x = (window_box_width (w, LEFT_MARGIN_AREA)
5554 + window_box_width (w, TEXT_AREA));
5555
5556 for (i = 0; i < row->used[area];)
5557 {
5558 if (row->glyphs[area][i].overlaps_vertically_p)
5559 {
5560 int start = i, start_x = x;
5561
5562 do
5563 {
5564 x += row->glyphs[area][i].pixel_width;
5565 ++i;
5566 }
5567 while (i < row->used[area]
5568 && row->glyphs[area][i].overlaps_vertically_p);
5569
5570 x_draw_glyphs (w, start_x, row, area, start, i,
5571 DRAW_NORMAL_TEXT, 1);
5572 }
5573 else
5574 {
5575 x += row->glyphs[area][i].pixel_width;
5576 ++i;
5577 }
5578 }
5579
5580 UNBLOCK_INPUT;
5581 }
5582
5583
5584 /* Output LEN glyphs starting at START at the nominal cursor position.
5585 Advance the nominal cursor over the text. The global variable
5586 updated_window contains the window being updated, updated_row is
5587 the glyph row being updated, and updated_area is the area of that
5588 row being updated. */
5589
5590 static void
5591 x_write_glyphs (start, len)
5592 struct glyph *start;
5593 int len;
5594 {
5595 int x, hpos;
5596
5597 xassert (updated_window && updated_row);
5598 BLOCK_INPUT;
5599
5600 /* Write glyphs. */
5601
5602 hpos = start - updated_row->glyphs[updated_area];
5603 x = x_draw_glyphs (updated_window, output_cursor.x,
5604 updated_row, updated_area,
5605 hpos, hpos + len,
5606 DRAW_NORMAL_TEXT, 0);
5607
5608 UNBLOCK_INPUT;
5609
5610 /* Advance the output cursor. */
5611 output_cursor.hpos += len;
5612 output_cursor.x = x;
5613 }
5614
5615
5616 /* Insert LEN glyphs from START at the nominal cursor position. */
5617
5618 static void
5619 x_insert_glyphs (start, len)
5620 struct glyph *start;
5621 register int len;
5622 {
5623 struct frame *f;
5624 struct window *w;
5625 int line_height, shift_by_width, shifted_region_width;
5626 struct glyph_row *row;
5627 struct glyph *glyph;
5628 int frame_x, frame_y, hpos;
5629
5630 xassert (updated_window && updated_row);
5631 BLOCK_INPUT;
5632 w = updated_window;
5633 f = XFRAME (WINDOW_FRAME (w));
5634
5635 /* Get the height of the line we are in. */
5636 row = updated_row;
5637 line_height = row->height;
5638
5639 /* Get the width of the glyphs to insert. */
5640 shift_by_width = 0;
5641 for (glyph = start; glyph < start + len; ++glyph)
5642 shift_by_width += glyph->pixel_width;
5643
5644 /* Get the width of the region to shift right. */
5645 shifted_region_width = (window_box_width (w, updated_area)
5646 - output_cursor.x
5647 - shift_by_width);
5648
5649 /* Shift right. */
5650 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5651 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5652
5653 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5654 f->output_data.mac->normal_gc,
5655 frame_x, frame_y,
5656 shifted_region_width, line_height,
5657 frame_x + shift_by_width, frame_y);
5658
5659 /* Write the glyphs. */
5660 hpos = start - row->glyphs[updated_area];
5661 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5662 DRAW_NORMAL_TEXT, 0);
5663
5664 /* Advance the output cursor. */
5665 output_cursor.hpos += len;
5666 output_cursor.x += shift_by_width;
5667 UNBLOCK_INPUT;
5668 }
5669
5670
5671 /* Delete N glyphs at the nominal cursor position. Not implemented
5672 for X frames. */
5673
5674 static void
5675 x_delete_glyphs (n)
5676 register int n;
5677 {
5678 abort ();
5679 }
5680
5681
5682 /* Erase the current text line from the nominal cursor position
5683 (inclusive) to pixel column TO_X (exclusive). The idea is that
5684 everything from TO_X onward is already erased.
5685
5686 TO_X is a pixel position relative to updated_area of
5687 updated_window. TO_X == -1 means clear to the end of this area. */
5688
5689 static void
5690 x_clear_end_of_line (to_x)
5691 int to_x;
5692 {
5693 struct frame *f;
5694 struct window *w = updated_window;
5695 int max_x, min_y, max_y;
5696 int from_x, from_y, to_y;
5697
5698 xassert (updated_window && updated_row);
5699 f = XFRAME (w->frame);
5700
5701 if (updated_row->full_width_p)
5702 {
5703 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5704 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5705 && !w->pseudo_window_p)
5706 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5707 }
5708 else
5709 max_x = window_box_width (w, updated_area);
5710 max_y = window_text_bottom_y (w);
5711
5712 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5713 of window. For TO_X > 0, truncate to end of drawing area. */
5714 if (to_x == 0)
5715 return;
5716 else if (to_x < 0)
5717 to_x = max_x;
5718 else
5719 to_x = min (to_x, max_x);
5720
5721 to_y = min (max_y, output_cursor.y + updated_row->height);
5722
5723 /* Notice if the cursor will be cleared by this operation. */
5724 if (!updated_row->full_width_p)
5725 notice_overwritten_cursor (w, updated_area,
5726 output_cursor.x, -1,
5727 updated_row->y,
5728 MATRIX_ROW_BOTTOM_Y (updated_row));
5729
5730 from_x = output_cursor.x;
5731
5732 /* Translate to frame coordinates. */
5733 if (updated_row->full_width_p)
5734 {
5735 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5736 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5737 }
5738 else
5739 {
5740 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5741 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5742 }
5743
5744 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5745 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5746 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5747
5748 /* Prevent inadvertently clearing to end of the X window. */
5749 if (to_x > from_x && to_y > from_y)
5750 {
5751 BLOCK_INPUT;
5752 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5753 from_x, from_y, to_x - from_x, to_y - from_y,
5754 0);
5755 UNBLOCK_INPUT;
5756 }
5757 }
5758
5759
5760 /* Clear entire frame. If updating_frame is non-null, clear that
5761 frame. Otherwise clear the selected frame. */
5762
5763 static void
5764 x_clear_frame ()
5765 {
5766 struct frame *f;
5767
5768 if (updating_frame)
5769 f = updating_frame;
5770 else
5771 f = SELECTED_FRAME ();
5772
5773 /* Clearing the frame will erase any cursor, so mark them all as no
5774 longer visible. */
5775 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5776 output_cursor.hpos = output_cursor.vpos = 0;
5777 output_cursor.x = -1;
5778
5779 /* We don't set the output cursor here because there will always
5780 follow an explicit cursor_to. */
5781 BLOCK_INPUT;
5782 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5783
5784 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5785 /* We have to clear the scroll bars, too. If we have changed
5786 colors or something like that, then they should be notified. */
5787 x_scroll_bar_clear (f);
5788 #endif
5789
5790 XFlush (FRAME_MAC_DISPLAY (f));
5791 UNBLOCK_INPUT;
5792 }
5793
5794
5795 \f
5796 /* Invert the middle quarter of the frame for .15 sec. */
5797
5798 /* We use the select system call to do the waiting, so we have to make
5799 sure it's available. If it isn't, we just won't do visual bells. */
5800
5801 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5802
5803 /* Subtract the `struct timeval' values X and Y, storing the result in
5804 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5805
5806 static int
5807 timeval_subtract (result, x, y)
5808 struct timeval *result, x, y;
5809 {
5810 /* Perform the carry for the later subtraction by updating y. This
5811 is safer because on some systems the tv_sec member is unsigned. */
5812 if (x.tv_usec < y.tv_usec)
5813 {
5814 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5815 y.tv_usec -= 1000000 * nsec;
5816 y.tv_sec += nsec;
5817 }
5818
5819 if (x.tv_usec - y.tv_usec > 1000000)
5820 {
5821 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5822 y.tv_usec += 1000000 * nsec;
5823 y.tv_sec -= nsec;
5824 }
5825
5826 /* Compute the time remaining to wait. tv_usec is certainly
5827 positive. */
5828 result->tv_sec = x.tv_sec - y.tv_sec;
5829 result->tv_usec = x.tv_usec - y.tv_usec;
5830
5831 /* Return indication of whether the result should be considered
5832 negative. */
5833 return x.tv_sec < y.tv_sec;
5834 }
5835
5836 void
5837 XTflash (f)
5838 struct frame *f;
5839 {
5840 BLOCK_INPUT;
5841
5842 FlashMenuBar (0);
5843
5844 {
5845 struct timeval wakeup;
5846
5847 EMACS_GET_TIME (wakeup);
5848
5849 /* Compute time to wait until, propagating carry from usecs. */
5850 wakeup.tv_usec += 150000;
5851 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5852 wakeup.tv_usec %= 1000000;
5853
5854 /* Keep waiting until past the time wakeup. */
5855 while (1)
5856 {
5857 struct timeval timeout;
5858
5859 EMACS_GET_TIME (timeout);
5860
5861 /* In effect, timeout = wakeup - timeout.
5862 Break if result would be negative. */
5863 if (timeval_subtract (&timeout, wakeup, timeout))
5864 break;
5865
5866 /* Try to wait that long--but we might wake up sooner. */
5867 select (0, NULL, NULL, NULL, &timeout);
5868 }
5869 }
5870
5871 FlashMenuBar (0);
5872
5873 UNBLOCK_INPUT;
5874 }
5875
5876 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5877
5878
5879 /* Make audible bell. */
5880
5881 void
5882 XTring_bell ()
5883 {
5884 struct frame *f = SELECTED_FRAME ();
5885
5886 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5887 if (visible_bell)
5888 XTflash (f);
5889 else
5890 #endif
5891 {
5892 BLOCK_INPUT;
5893 SysBeep (1);
5894 XFlush (FRAME_MAC_DISPLAY (f));
5895 UNBLOCK_INPUT;
5896 }
5897 }
5898
5899
5900 \f
5901 /* Specify how many text lines, from the top of the window,
5902 should be affected by insert-lines and delete-lines operations.
5903 This, and those operations, are used only within an update
5904 that is bounded by calls to x_update_begin and x_update_end. */
5905
5906 void
5907 XTset_terminal_window (n)
5908 register int n;
5909 {
5910 /* This function intentionally left blank. */
5911 }
5912
5913
5914 \f
5915 /***********************************************************************
5916 Line Dance
5917 ***********************************************************************/
5918
5919 /* Perform an insert-lines or delete-lines operation, inserting N
5920 lines or deleting -N lines at vertical position VPOS. */
5921
5922 static void
5923 x_ins_del_lines (vpos, n)
5924 int vpos, n;
5925 {
5926 abort ();
5927 }
5928
5929
5930 /* Scroll part of the display as described by RUN. */
5931
5932 static void
5933 x_scroll_run (w, run)
5934 struct window *w;
5935 struct run *run;
5936 {
5937 struct frame *f = XFRAME (w->frame);
5938 int x, y, width, height, from_y, to_y, bottom_y;
5939
5940 /* Get frame-relative bounding box of the text display area of W,
5941 without mode lines. Include in this box the left and right
5942 fringes of W. */
5943 window_box (w, -1, &x, &y, &width, &height);
5944 width += FRAME_X_FRINGE_WIDTH (f);
5945 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5946
5947 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5948 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5949 bottom_y = y + height;
5950
5951 if (to_y < from_y)
5952 {
5953 /* Scrolling up. Make sure we don't copy part of the mode
5954 line at the bottom. */
5955 if (from_y + run->height > bottom_y)
5956 height = bottom_y - from_y;
5957 else
5958 height = run->height;
5959 }
5960 else
5961 {
5962 /* Scolling down. Make sure we don't copy over the mode line.
5963 at the bottom. */
5964 if (to_y + run->height > bottom_y)
5965 height = bottom_y - to_y;
5966 else
5967 height = run->height;
5968 }
5969
5970 BLOCK_INPUT;
5971
5972 /* Cursor off. Will be switched on again in x_update_window_end. */
5973 updated_window = w;
5974 x_clear_cursor (w);
5975
5976 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5977 f->output_data.mac->normal_gc,
5978 x, from_y,
5979 width, height,
5980 x, to_y);
5981
5982 UNBLOCK_INPUT;
5983 }
5984
5985
5986 \f
5987 /***********************************************************************
5988 Exposure Events
5989 ***********************************************************************/
5990
5991 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5992 corner of the exposed rectangle. W and H are width and height of
5993 the exposed area. All are pixel values. W or H zero means redraw
5994 the entire frame. */
5995
5996 static void
5997 expose_frame (f, x, y, w, h)
5998 struct frame *f;
5999 int x, y, w, h;
6000 {
6001 Rect r;
6002 int mouse_face_overwritten_p = 0;
6003
6004 TRACE ((stderr, "expose_frame "));
6005
6006 /* No need to redraw if frame will be redrawn soon. */
6007 if (FRAME_GARBAGED_P (f))
6008 {
6009 TRACE ((stderr, " garbaged\n"));
6010 return;
6011 }
6012
6013 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6014 or deactivated here, for unknown reasons, activated scroll bars
6015 are shown in deactivated frames in some instances. */
6016 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6017 activate_scroll_bars (f);
6018 else
6019 deactivate_scroll_bars (f);
6020
6021 /* If basic faces haven't been realized yet, there is no point in
6022 trying to redraw anything. This can happen when we get an expose
6023 event while Emacs is starting, e.g. by moving another window. */
6024 if (FRAME_FACE_CACHE (f) == NULL
6025 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
6026 {
6027 TRACE ((stderr, " no faces\n"));
6028 return;
6029 }
6030
6031 if (w == 0 || h == 0)
6032 {
6033 r.left = r.top = 0;
6034 r.right = CANON_X_UNIT (f) * f->width;
6035 r.bottom = CANON_Y_UNIT (f) * f->height;
6036 }
6037 else
6038 {
6039 r.left = x;
6040 r.top = y;
6041 r.right = x + w;
6042 r.bottom = y + h;
6043 }
6044
6045 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
6046 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
6047
6048 if (WINDOWP (f->tool_bar_window))
6049 mouse_face_overwritten_p
6050 |= expose_window (XWINDOW (f->tool_bar_window), &r);
6051
6052 /* Some window managers support a focus-follows-mouse style with
6053 delayed raising of frames. Imagine a partially obscured frame,
6054 and moving the mouse into partially obscured mouse-face on that
6055 frame. The visible part of the mouse-face will be highlighted,
6056 then the WM raises the obscured frame. With at least one WM, KDE
6057 2.1, Emacs is not getting any event for the raising of the frame
6058 (even tried with SubstructureRedirectMask), only Expose events.
6059 These expose events will draw text normally, i.e. not
6060 highlighted. Which means we must redo the highlight here.
6061 Subsume it under ``we love X''. --gerd 2001-08-15 */
6062 /* Included in Windows version because Windows most likely does not
6063 do the right thing if any third party tool offers
6064 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6065 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
6066 {
6067 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6068 if (f == dpyinfo->mouse_face_mouse_frame)
6069 {
6070 int x = dpyinfo->mouse_face_mouse_x;
6071 int y = dpyinfo->mouse_face_mouse_y;
6072 clear_mouse_face (dpyinfo);
6073 note_mouse_highlight (f, x, y);
6074 }
6075 }
6076 }
6077
6078
6079 /* Redraw (parts) of all windows in the window tree rooted at W that
6080 intersect R. R contains frame pixel coordinates. */
6081
6082 static int
6083 expose_window_tree (w, r)
6084 struct window *w;
6085 Rect *r;
6086 {
6087 struct frame *f = XFRAME (w->frame);
6088 int mouse_face_overwritten_p = 0;
6089
6090 while (w && !FRAME_GARBAGED_P (f))
6091 {
6092 if (!NILP (w->hchild))
6093 mouse_face_overwritten_p
6094 |= expose_window_tree (XWINDOW (w->hchild), r);
6095 else if (!NILP (w->vchild))
6096 mouse_face_overwritten_p
6097 |= expose_window_tree (XWINDOW (w->vchild), r);
6098 else
6099 mouse_face_overwritten_p |= expose_window (w, r);
6100
6101 w = NILP (w->next) ? NULL : XWINDOW (w->next);
6102 }
6103
6104 return mouse_face_overwritten_p;
6105 }
6106
6107
6108 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
6109 which intersects rectangle R. R is in window-relative coordinates. */
6110
6111 static void
6112 expose_area (w, row, r, area)
6113 struct window *w;
6114 struct glyph_row *row;
6115 Rect *r;
6116 enum glyph_row_area area;
6117 {
6118 struct glyph *first = row->glyphs[area];
6119 struct glyph *end = row->glyphs[area] + row->used[area];
6120 struct glyph *last;
6121 int first_x, start_x, x;
6122
6123 if (area == TEXT_AREA && row->fill_line_p)
6124 /* If row extends face to end of line write the whole line. */
6125 x_draw_glyphs (w, 0, row, area,
6126 0, row->used[area],
6127 DRAW_NORMAL_TEXT, 0);
6128 else
6129 {
6130 /* Set START_X to the window-relative start position for drawing glyphs of
6131 AREA. The first glyph of the text area can be partially visible.
6132 The first glyphs of other areas cannot. */
6133 if (area == LEFT_MARGIN_AREA)
6134 start_x = 0;
6135 else if (area == TEXT_AREA)
6136 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6137 else
6138 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6139 + window_box_width (w, TEXT_AREA));
6140 x = start_x;
6141
6142 /* Find the first glyph that must be redrawn. */
6143 while (first < end
6144 && x + first->pixel_width < r->left)
6145 {
6146 x += first->pixel_width;
6147 ++first;
6148 }
6149
6150 /* Find the last one. */
6151 last = first;
6152 first_x = x;
6153 while (last < end
6154 && x < r->right)
6155 {
6156 x += last->pixel_width;
6157 ++last;
6158 }
6159
6160 /* Repaint. */
6161 if (last > first)
6162 x_draw_glyphs (w, first_x - start_x, row, area,
6163 first - row->glyphs[area],
6164 last - row->glyphs[area],
6165 DRAW_NORMAL_TEXT, 0);
6166 }
6167 }
6168
6169
6170 /* Redraw the parts of the glyph row ROW on window W intersecting
6171 rectangle R. R is in window-relative coordinates. Value is
6172 non-zero if mouse face was overwritten. */
6173
6174 static int
6175 expose_line (w, row, r)
6176 struct window *w;
6177 struct glyph_row *row;
6178 Rect *r;
6179 {
6180 xassert (row->enabled_p);
6181
6182 if (row->mode_line_p || w->pseudo_window_p)
6183 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6184 DRAW_NORMAL_TEXT, 0);
6185 else
6186 {
6187 if (row->used[LEFT_MARGIN_AREA])
6188 expose_area (w, row, r, LEFT_MARGIN_AREA);
6189 if (row->used[TEXT_AREA])
6190 expose_area (w, row, r, TEXT_AREA);
6191 if (row->used[RIGHT_MARGIN_AREA])
6192 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6193 x_draw_row_fringe_bitmaps (w, row);
6194 }
6195
6196 return row->mouse_face_p;
6197 }
6198
6199
6200 /* Return non-zero if W's cursor intersects rectangle R. */
6201
6202 static int
6203 x_phys_cursor_in_rect_p (w, r)
6204 struct window *w;
6205 Rect *r;
6206 {
6207 Rect cr, result;
6208 struct glyph *cursor_glyph;
6209
6210 cursor_glyph = get_phys_cursor_glyph (w);
6211 if (cursor_glyph)
6212 {
6213 cr.left = w->phys_cursor.x;
6214 cr.top = w->phys_cursor.y;
6215 cr.right = cr.left + cursor_glyph->pixel_width;
6216 cr.bottom = cr.top + w->phys_cursor_height;
6217 return x_intersect_rectangles (&cr, r, &result);
6218 }
6219 else
6220 return 0;
6221 }
6222
6223
6224 /* Redraw the part of window W intersection rectagle FR. Pixel
6225 coordinates in FR are frame relative. Call this function with
6226 input blocked. Value is non-zero if the exposure overwrites
6227 mouse-face. */
6228
6229 static int
6230 expose_window (w, fr)
6231 struct window *w;
6232 Rect *fr;
6233 {
6234 struct frame *f = XFRAME (w->frame);
6235 Rect wr, r;
6236 int mouse_face_overwritten_p = 0;
6237
6238 /* If window is not yet fully initialized, do nothing. This can
6239 happen when toolkit scroll bars are used and a window is split.
6240 Reconfiguring the scroll bar will generate an expose for a newly
6241 created window. */
6242 if (w->current_matrix == NULL)
6243 return 0;
6244
6245 /* When we're currently updating the window, display and current
6246 matrix usually don't agree. Arrange for a thorough display
6247 later. */
6248 if (w == updated_window)
6249 {
6250 SET_FRAME_GARBAGED (f);
6251 return 0;
6252 }
6253
6254 /* Frame-relative pixel rectangle of W. */
6255 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6256 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6257 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6258 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6259
6260 if (x_intersect_rectangles (fr, &wr, &r))
6261 {
6262 int yb = window_text_bottom_y (w);
6263 struct glyph_row *row;
6264 int cursor_cleared_p;
6265
6266 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6267 r.left, r.top, r.right, r.bottom));
6268
6269 /* Convert to window coordinates. */
6270 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6271 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6272 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6273 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6274
6275 /* Turn off the cursor. */
6276 if (!w->pseudo_window_p
6277 && x_phys_cursor_in_rect_p (w, &r))
6278 {
6279 x_clear_cursor (w);
6280 cursor_cleared_p = 1;
6281 }
6282 else
6283 cursor_cleared_p = 0;
6284
6285 /* Find the first row intersecting the rectangle R. */
6286 for (row = w->current_matrix->rows;
6287 row->enabled_p;
6288 ++row)
6289 {
6290 int y0 = row->y;
6291 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6292
6293 if ((y0 >= r.top && y0 < r.bottom)
6294 || (y1 > r.top && y1 < r.bottom)
6295 || (r.top >= y0 && r.top < y1)
6296 || (r.bottom > y0 && r.bottom < y1))
6297 {
6298 if (expose_line (w, row, &r))
6299 mouse_face_overwritten_p = 1;
6300 }
6301
6302 if (y1 >= yb)
6303 break;
6304 }
6305
6306 /* Display the mode line if there is one. */
6307 if (WINDOW_WANTS_MODELINE_P (w)
6308 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6309 row->enabled_p)
6310 && row->y < r.bottom)
6311 {
6312 if (expose_line (w, row, &r))
6313 mouse_face_overwritten_p = 1;
6314 }
6315
6316 if (!w->pseudo_window_p)
6317 {
6318 /* Draw border between windows. */
6319 x_draw_vertical_border (w);
6320
6321 /* Turn the cursor on again. */
6322 if (cursor_cleared_p)
6323 x_update_window_cursor (w, 1);
6324 }
6325 }
6326
6327 /* Display scroll bar for this window. */
6328 if (!NILP (w->vertical_scroll_bar))
6329 {
6330 ControlHandle ch
6331 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
6332
6333 Draw1Control (ch);
6334 }
6335
6336 return mouse_face_overwritten_p;
6337 }
6338
6339 static int
6340 x_intersect_rectangles (r1, r2, result)
6341 Rect *r1, *r2, *result;
6342 {
6343 Rect *left, *right;
6344 Rect *upper, *lower;
6345 int intersection_p = 0;
6346
6347 /* Rerrange so that R1 is the left-most rectangle. */
6348 if (r1->left < r2->left)
6349 left = r1, right = r2;
6350 else
6351 left = r2, right = r1;
6352
6353 /* X0 of the intersection is right.x0, if this is inside R1,
6354 otherwise there is no intersection. */
6355 if (right->left <= left->right)
6356 {
6357 result->left = right->left;
6358
6359 /* The right end of the intersection is the minimum of the
6360 the right ends of left and right. */
6361 result->right = min (left->right, right->right);
6362
6363 /* Same game for Y. */
6364 if (r1->top < r2->top)
6365 upper = r1, lower = r2;
6366 else
6367 upper = r2, lower = r1;
6368
6369 /* The upper end of the intersection is lower.y0, if this is inside
6370 of upper. Otherwise, there is no intersection. */
6371 if (lower->top <= upper->bottom)
6372 {
6373 result->top = lower->top;
6374
6375 /* The lower end of the intersection is the minimum of the lower
6376 ends of upper and lower. */
6377 result->bottom = min (lower->bottom, upper->bottom);
6378 intersection_p = 1;
6379 }
6380 }
6381
6382 return intersection_p;
6383 }
6384
6385
6386
6387
6388 \f
6389 static void
6390 frame_highlight (f)
6391 struct frame *f;
6392 {
6393 x_update_cursor (f, 1);
6394 }
6395
6396 static void
6397 frame_unhighlight (f)
6398 struct frame *f;
6399 {
6400 x_update_cursor (f, 1);
6401 }
6402
6403 /* The focus has changed. Update the frames as necessary to reflect
6404 the new situation. Note that we can't change the selected frame
6405 here, because the Lisp code we are interrupting might become confused.
6406 Each event gets marked with the frame in which it occurred, so the
6407 Lisp code can tell when the switch took place by examining the events. */
6408
6409 static void
6410 x_new_focus_frame (dpyinfo, frame)
6411 struct x_display_info *dpyinfo;
6412 struct frame *frame;
6413 {
6414 struct frame *old_focus = dpyinfo->x_focus_frame;
6415
6416 if (frame != dpyinfo->x_focus_frame)
6417 {
6418 /* Set this before calling other routines, so that they see
6419 the correct value of x_focus_frame. */
6420 dpyinfo->x_focus_frame = frame;
6421
6422 if (old_focus && old_focus->auto_lower)
6423 x_lower_frame (old_focus);
6424
6425 #if 0
6426 selected_frame = frame;
6427 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6428 selected_frame);
6429 Fselect_window (selected_frame->selected_window);
6430 choose_minibuf_frame ();
6431 #endif /* ! 0 */
6432
6433 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6434 pending_autoraise_frame = dpyinfo->x_focus_frame;
6435 else
6436 pending_autoraise_frame = 0;
6437 }
6438
6439 x_frame_rehighlight (dpyinfo);
6440 }
6441
6442 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6443
6444 void
6445 x_mouse_leave (dpyinfo)
6446 struct x_display_info *dpyinfo;
6447 {
6448 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6449 }
6450
6451 /* The focus has changed, or we have redirected a frame's focus to
6452 another frame (this happens when a frame uses a surrogate
6453 mini-buffer frame). Shift the highlight as appropriate.
6454
6455 The FRAME argument doesn't necessarily have anything to do with which
6456 frame is being highlighted or un-highlighted; we only use it to find
6457 the appropriate X display info. */
6458
6459 static void
6460 XTframe_rehighlight (frame)
6461 struct frame *frame;
6462 {
6463 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6464 }
6465
6466 static void
6467 x_frame_rehighlight (dpyinfo)
6468 struct x_display_info *dpyinfo;
6469 {
6470 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6471
6472 if (dpyinfo->x_focus_frame)
6473 {
6474 dpyinfo->x_highlight_frame
6475 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6476 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6477 : dpyinfo->x_focus_frame);
6478 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6479 {
6480 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6481 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6482 }
6483 }
6484 else
6485 dpyinfo->x_highlight_frame = 0;
6486
6487 if (dpyinfo->x_highlight_frame != old_highlight)
6488 {
6489 if (old_highlight)
6490 frame_unhighlight (old_highlight);
6491 if (dpyinfo->x_highlight_frame)
6492 frame_highlight (dpyinfo->x_highlight_frame);
6493 }
6494 }
6495
6496
6497 \f
6498 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6499
6500 #if 0 /* MAC_TODO */
6501 /* Initialize mode_switch_bit and modifier_meaning. */
6502 static void
6503 x_find_modifier_meanings (dpyinfo)
6504 struct x_display_info *dpyinfo;
6505 {
6506 int min_code, max_code;
6507 KeySym *syms;
6508 int syms_per_code;
6509 XModifierKeymap *mods;
6510
6511 dpyinfo->meta_mod_mask = 0;
6512 dpyinfo->shift_lock_mask = 0;
6513 dpyinfo->alt_mod_mask = 0;
6514 dpyinfo->super_mod_mask = 0;
6515 dpyinfo->hyper_mod_mask = 0;
6516
6517 #ifdef HAVE_X11R4
6518 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6519 #else
6520 min_code = dpyinfo->display->min_keycode;
6521 max_code = dpyinfo->display->max_keycode;
6522 #endif
6523
6524 syms = XGetKeyboardMapping (dpyinfo->display,
6525 min_code, max_code - min_code + 1,
6526 &syms_per_code);
6527 mods = XGetModifierMapping (dpyinfo->display);
6528
6529 /* Scan the modifier table to see which modifier bits the Meta and
6530 Alt keysyms are on. */
6531 {
6532 int row, col; /* The row and column in the modifier table. */
6533
6534 for (row = 3; row < 8; row++)
6535 for (col = 0; col < mods->max_keypermod; col++)
6536 {
6537 KeyCode code
6538 = mods->modifiermap[(row * mods->max_keypermod) + col];
6539
6540 /* Zeroes are used for filler. Skip them. */
6541 if (code == 0)
6542 continue;
6543
6544 /* Are any of this keycode's keysyms a meta key? */
6545 {
6546 int code_col;
6547
6548 for (code_col = 0; code_col < syms_per_code; code_col++)
6549 {
6550 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6551
6552 switch (sym)
6553 {
6554 case XK_Meta_L:
6555 case XK_Meta_R:
6556 dpyinfo->meta_mod_mask |= (1 << row);
6557 break;
6558
6559 case XK_Alt_L:
6560 case XK_Alt_R:
6561 dpyinfo->alt_mod_mask |= (1 << row);
6562 break;
6563
6564 case XK_Hyper_L:
6565 case XK_Hyper_R:
6566 dpyinfo->hyper_mod_mask |= (1 << row);
6567 break;
6568
6569 case XK_Super_L:
6570 case XK_Super_R:
6571 dpyinfo->super_mod_mask |= (1 << row);
6572 break;
6573
6574 case XK_Shift_Lock:
6575 /* Ignore this if it's not on the lock modifier. */
6576 if ((1 << row) == LockMask)
6577 dpyinfo->shift_lock_mask = LockMask;
6578 break;
6579 }
6580 }
6581 }
6582 }
6583 }
6584
6585 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6586 if (! dpyinfo->meta_mod_mask)
6587 {
6588 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6589 dpyinfo->alt_mod_mask = 0;
6590 }
6591
6592 /* If some keys are both alt and meta,
6593 make them just meta, not alt. */
6594 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6595 {
6596 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6597 }
6598
6599 XFree ((char *) syms);
6600 XFreeModifiermap (mods);
6601 }
6602
6603 #endif /* MAC_TODO */
6604
6605 /* Convert between the modifier bits X uses and the modifier bits
6606 Emacs uses. */
6607
6608 static unsigned int
6609 x_mac_to_emacs_modifiers (dpyinfo, state)
6610 struct x_display_info *dpyinfo;
6611 unsigned short state;
6612 {
6613 return (((state & shiftKey) ? shift_modifier : 0)
6614 | ((state & controlKey) ? ctrl_modifier : 0)
6615 | ((state & cmdKey) ? meta_modifier : 0)
6616 | ((state & optionKey) ? alt_modifier : 0));
6617 }
6618
6619 #if 0 /* MAC_TODO */
6620 static unsigned short
6621 x_emacs_to_x_modifiers (dpyinfo, state)
6622 struct x_display_info *dpyinfo;
6623 unsigned int state;
6624 {
6625 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6626 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6627 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6628 | ((state & shift_modifier) ? ShiftMask : 0)
6629 | ((state & ctrl_modifier) ? ControlMask : 0)
6630 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6631 }
6632 #endif /* MAC_TODO */
6633
6634 /* Convert a keysym to its name. */
6635
6636 char *
6637 x_get_keysym_name (keysym)
6638 int keysym;
6639 {
6640 char *value;
6641
6642 BLOCK_INPUT;
6643 #if 0
6644 value = XKeysymToString (keysym);
6645 #else
6646 value = 0;
6647 #endif
6648 UNBLOCK_INPUT;
6649
6650 return value;
6651 }
6652
6653
6654 \f
6655 /* Mouse clicks and mouse movement. Rah. */
6656
6657 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6658 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6659 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6660 not force the value into range. */
6661
6662 void
6663 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6664 FRAME_PTR f;
6665 register int pix_x, pix_y;
6666 register int *x, *y;
6667 Rect *bounds;
6668 int noclip;
6669 {
6670 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6671 if (NILP (Vwindow_system))
6672 {
6673 *x = pix_x;
6674 *y = pix_y;
6675 return;
6676 }
6677
6678 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6679 even for negative values. */
6680 if (pix_x < 0)
6681 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
6682 if (pix_y < 0)
6683 pix_y -= (f)->output_data.mac->line_height - 1;
6684
6685 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6686 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6687
6688 if (bounds)
6689 {
6690 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6691 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
6692 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6693 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
6694 }
6695
6696 if (!noclip)
6697 {
6698 if (pix_x < 0)
6699 pix_x = 0;
6700 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6701 pix_x = FRAME_WINDOW_WIDTH (f);
6702
6703 if (pix_y < 0)
6704 pix_y = 0;
6705 else if (pix_y > f->height)
6706 pix_y = f->height;
6707 }
6708
6709 *x = pix_x;
6710 *y = pix_y;
6711 }
6712
6713
6714 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6715 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6716 can't tell the positions because W's display is not up to date,
6717 return 0. */
6718
6719 int
6720 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6721 struct window *w;
6722 int hpos, vpos;
6723 int *frame_x, *frame_y;
6724 {
6725 int success_p;
6726
6727 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6728 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6729
6730 if (display_completed)
6731 {
6732 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6733 struct glyph *glyph = row->glyphs[TEXT_AREA];
6734 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6735
6736 *frame_y = row->y;
6737 *frame_x = row->x;
6738 while (glyph < end)
6739 {
6740 *frame_x += glyph->pixel_width;
6741 ++glyph;
6742 }
6743
6744 success_p = 1;
6745 }
6746 else
6747 {
6748 *frame_y = *frame_x = 0;
6749 success_p = 0;
6750 }
6751
6752 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6753 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6754 return success_p;
6755 }
6756
6757
6758 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6759
6760 If the event is a button press, then note that we have grabbed
6761 the mouse. */
6762
6763 static Lisp_Object
6764 construct_mouse_click (result, event, f)
6765 struct input_event *result;
6766 EventRecord *event;
6767 struct frame *f;
6768 {
6769 Point mouseLoc;
6770
6771 result->kind = MOUSE_CLICK_EVENT;
6772 result->code = 0; /* only one mouse button */
6773 result->timestamp = event->when;
6774 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6775
6776 mouseLoc = event->where;
6777
6778 #if TARGET_API_MAC_CARBON
6779 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6780 #else
6781 SetPort (FRAME_MAC_WINDOW (f));
6782 #endif
6783
6784 GlobalToLocal (&mouseLoc);
6785 XSETINT (result->x, mouseLoc.h);
6786 XSETINT (result->y, mouseLoc.v);
6787
6788 XSETFRAME (result->frame_or_window, f);
6789
6790 result->arg = Qnil;
6791 return Qnil;
6792 }
6793
6794 \f
6795 /* Function to report a mouse movement to the mainstream Emacs code.
6796 The input handler calls this.
6797
6798 We have received a mouse movement event, which is given in *event.
6799 If the mouse is over a different glyph than it was last time, tell
6800 the mainstream emacs code by setting mouse_moved. If not, ask for
6801 another motion event, so we can check again the next time it moves. */
6802
6803 static Point last_mouse_motion_position;
6804 static Lisp_Object last_mouse_motion_frame;
6805
6806 static void
6807 note_mouse_movement (frame, pos)
6808 FRAME_PTR frame;
6809 Point *pos;
6810 {
6811 #if TARGET_API_MAC_CARBON
6812 Rect r;
6813 #endif
6814
6815 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6816 last_mouse_motion_position = *pos;
6817 XSETFRAME (last_mouse_motion_frame, frame);
6818
6819 #if TARGET_API_MAC_CARBON
6820 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6821 #else
6822 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
6823 #endif
6824 {
6825 frame->mouse_moved = 1;
6826 last_mouse_scroll_bar = Qnil;
6827 note_mouse_highlight (frame, -1, -1);
6828 }
6829 /* Has the mouse moved off the glyph it was on at the last sighting? */
6830 else if (pos->h < last_mouse_glyph.left
6831 || pos->h >= last_mouse_glyph.right
6832 || pos->v < last_mouse_glyph.top
6833 || pos->v >= last_mouse_glyph.bottom)
6834 {
6835 frame->mouse_moved = 1;
6836 last_mouse_scroll_bar = Qnil;
6837 note_mouse_highlight (frame, pos->h, pos->v);
6838 }
6839 }
6840
6841 /* This is used for debugging, to turn off note_mouse_highlight. */
6842
6843 int disable_mouse_highlight;
6844
6845
6846 \f
6847 /************************************************************************
6848 Mouse Face
6849 ************************************************************************/
6850
6851 /* Find the glyph under window-relative coordinates X/Y in window W.
6852 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6853 strings. Return in *HPOS and *VPOS the row and column number of
6854 the glyph found. Return in *AREA the glyph area containing X.
6855 Value is a pointer to the glyph found or null if X/Y is not on
6856 text, or we can't tell because W's current matrix is not up to
6857 date. */
6858
6859 static struct glyph *
6860 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6861 struct window *w;
6862 int x, y;
6863 int *hpos, *vpos, *area;
6864 int buffer_only_p;
6865 {
6866 struct glyph *glyph, *end;
6867 struct glyph_row *row = NULL;
6868 int x0, i, left_area_width;
6869
6870 /* Find row containing Y. Give up if some row is not enabled. */
6871 for (i = 0; i < w->current_matrix->nrows; ++i)
6872 {
6873 row = MATRIX_ROW (w->current_matrix, i);
6874 if (!row->enabled_p)
6875 return NULL;
6876 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6877 break;
6878 }
6879
6880 *vpos = i;
6881 *hpos = 0;
6882
6883 /* Give up if Y is not in the window. */
6884 if (i == w->current_matrix->nrows)
6885 return NULL;
6886
6887 /* Get the glyph area containing X. */
6888 if (w->pseudo_window_p)
6889 {
6890 *area = TEXT_AREA;
6891 x0 = 0;
6892 }
6893 else
6894 {
6895 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6896 if (x < left_area_width)
6897 {
6898 *area = LEFT_MARGIN_AREA;
6899 x0 = 0;
6900 }
6901 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6902 {
6903 *area = TEXT_AREA;
6904 x0 = row->x + left_area_width;
6905 }
6906 else
6907 {
6908 *area = RIGHT_MARGIN_AREA;
6909 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6910 }
6911 }
6912
6913 /* Find glyph containing X. */
6914 glyph = row->glyphs[*area];
6915 end = glyph + row->used[*area];
6916 while (glyph < end)
6917 {
6918 if (x < x0 + glyph->pixel_width)
6919 {
6920 if (w->pseudo_window_p)
6921 break;
6922 else if (!buffer_only_p || BUFFERP (glyph->object))
6923 break;
6924 }
6925
6926 x0 += glyph->pixel_width;
6927 ++glyph;
6928 }
6929
6930 if (glyph == end)
6931 return NULL;
6932
6933 *hpos = glyph - row->glyphs[*area];
6934 return glyph;
6935 }
6936
6937
6938 /* Convert frame-relative x/y to coordinates relative to window W.
6939 Takes pseudo-windows into account. */
6940
6941 static void
6942 frame_to_window_pixel_xy (w, x, y)
6943 struct window *w;
6944 int *x, *y;
6945 {
6946 if (w->pseudo_window_p)
6947 {
6948 /* A pseudo-window is always full-width, and starts at the
6949 left edge of the frame, plus a frame border. */
6950 struct frame *f = XFRAME (w->frame);
6951 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6952 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6953 }
6954 else
6955 {
6956 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6957 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6958 }
6959 }
6960
6961
6962 /* Take proper action when mouse has moved to the mode or header line of
6963 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6964 mode line. X is relative to the start of the text display area of
6965 W, so the width of fringes and scroll bars must be subtracted
6966 to get a position relative to the start of the mode line. */
6967
6968 static void
6969 note_mode_line_highlight (w, x, mode_line_p)
6970 struct window *w;
6971 int x, mode_line_p;
6972 {
6973 struct frame *f = XFRAME (w->frame);
6974 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6975 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
6976 struct glyph_row *row;
6977
6978 if (mode_line_p)
6979 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6980 else
6981 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6982
6983 if (row->enabled_p)
6984 {
6985 struct glyph *glyph, *end;
6986 Lisp_Object help, map;
6987 int x0;
6988
6989 /* Find the glyph under X. */
6990 glyph = row->glyphs[TEXT_AREA];
6991 end = glyph + row->used[TEXT_AREA];
6992 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6993 + FRAME_X_LEFT_FRINGE_WIDTH (f));
6994
6995 while (glyph < end
6996 && x >= x0 + glyph->pixel_width)
6997 {
6998 x0 += glyph->pixel_width;
6999 ++glyph;
7000 }
7001
7002 if (glyph < end
7003 && STRINGP (glyph->object)
7004 && XSTRING (glyph->object)->intervals
7005 && glyph->charpos >= 0
7006 && glyph->charpos < XSTRING (glyph->object)->size)
7007 {
7008 /* If we're on a string with `help-echo' text property,
7009 arrange for the help to be displayed. This is done by
7010 setting the global variable help_echo to the help string. */
7011 help = Fget_text_property (make_number (glyph->charpos),
7012 Qhelp_echo, glyph->object);
7013 if (!NILP (help))
7014 {
7015 help_echo = help;
7016 XSETWINDOW (help_echo_window, w);
7017 help_echo_object = glyph->object;
7018 help_echo_pos = glyph->charpos;
7019 }
7020
7021 /* Change the mouse pointer according to what is under X/Y. */
7022 map = Fget_text_property (make_number (glyph->charpos),
7023 Qlocal_map, glyph->object);
7024 if (KEYMAPP (map))
7025 cursor = f->output_data.mac->nontext_cursor;
7026 else
7027 {
7028 map = Fget_text_property (make_number (glyph->charpos),
7029 Qkeymap, glyph->object);
7030 if (KEYMAPP (map))
7031 cursor = f->output_data.mac->nontext_cursor;
7032 }
7033 }
7034 }
7035
7036 #if 0 /* MAC_TODO: mouse cursor */
7037 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7038 #endif
7039 }
7040
7041
7042 /* Take proper action when the mouse has moved to position X, Y on
7043 frame F as regards highlighting characters that have mouse-face
7044 properties. Also de-highlighting chars where the mouse was before.
7045 X and Y can be negative or out of range. */
7046
7047 static void
7048 note_mouse_highlight (f, x, y)
7049 struct frame *f;
7050 int x, y;
7051 {
7052 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7053 int portion;
7054 Lisp_Object window;
7055 struct window *w;
7056 struct buffer *b;
7057
7058 #if 0
7059 /* When a menu is active, don't highlight because this looks odd. */
7060 if (popup_activated ())
7061 return;
7062 #endif
7063
7064 if (NILP (Vmouse_highlight)
7065 || !f->glyphs_initialized_p)
7066 return;
7067
7068 dpyinfo->mouse_face_mouse_x = x;
7069 dpyinfo->mouse_face_mouse_y = y;
7070 dpyinfo->mouse_face_mouse_frame = f;
7071
7072 if (dpyinfo->mouse_face_defer)
7073 return;
7074
7075 if (gc_in_progress)
7076 {
7077 dpyinfo->mouse_face_deferred_gc = 1;
7078 return;
7079 }
7080
7081 /* Which window is that in? */
7082 window = window_from_coordinates (f, x, y, &portion, 1);
7083
7084 /* If we were displaying active text in another window, clear that. */
7085 if (! EQ (window, dpyinfo->mouse_face_window))
7086 clear_mouse_face (dpyinfo);
7087
7088 /* Not on a window -> return. */
7089 if (!WINDOWP (window))
7090 return;
7091
7092 /* Reset help_echo. It will get recomputed below. */
7093 help_echo = Qnil;
7094
7095 /* Convert to window-relative pixel coordinates. */
7096 w = XWINDOW (window);
7097 frame_to_window_pixel_xy (w, &x, &y);
7098
7099 /* Handle tool-bar window differently since it doesn't display a
7100 buffer. */
7101 if (EQ (window, f->tool_bar_window))
7102 {
7103 note_tool_bar_highlight (f, x, y);
7104 return;
7105 }
7106
7107 /* Mouse is on the mode or header line? */
7108 if (portion == 1 || portion == 3)
7109 {
7110 note_mode_line_highlight (w, x, portion == 1);
7111 return;
7112 }
7113 #if 0 /* TODO: mouse cursor */
7114 if (portion == 2)
7115 cursor = f->output_data.x->horizontal_drag_cursor;
7116 else
7117 cursor = f->output_data.x->text_cursor;
7118 #endif
7119 /* Are we in a window whose display is up to date?
7120 And verify the buffer's text has not changed. */
7121 b = XBUFFER (w->buffer);
7122 if (/* Within text portion of the window. */
7123 portion == 0
7124 && EQ (w->window_end_valid, w->buffer)
7125 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7126 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
7127 {
7128 int hpos, vpos, pos, i, area;
7129 struct glyph *glyph;
7130 Lisp_Object object;
7131 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7132 Lisp_Object *overlay_vec = NULL;
7133 int len, noverlays;
7134 struct buffer *obuf;
7135 int obegv, ozv, same_region;
7136
7137 /* Find the glyph under X/Y. */
7138 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
7139
7140 /* Clear mouse face if X/Y not over text. */
7141 if (glyph == NULL
7142 || area != TEXT_AREA
7143 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7144 {
7145 clear_mouse_face (dpyinfo);
7146 /* TODO: mouse cursor */
7147 goto set_cursor;
7148 }
7149
7150 pos = glyph->charpos;
7151 object = glyph->object;
7152 if (!STRINGP (object) && !BUFFERP (object))
7153 goto set_cursor;
7154
7155 /* If we get an out-of-range value, return now; avoid an error. */
7156 if (BUFFERP (object) && pos > BUF_Z (b))
7157 goto set_cursor;
7158
7159 /* Make the window's buffer temporarily current for
7160 overlays_at and compute_char_face. */
7161 obuf = current_buffer;
7162 current_buffer = b;
7163 obegv = BEGV;
7164 ozv = ZV;
7165 BEGV = BEG;
7166 ZV = Z;
7167
7168 /* Is this char mouse-active or does it have help-echo? */
7169 position = make_number (pos);
7170
7171 if (BUFFERP (object))
7172 {
7173 /* Put all the overlays we want in a vector in overlay_vec.
7174 Store the length in len. If there are more than 10, make
7175 enough space for all, and try again. */
7176 len = 10;
7177 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7178 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7179 if (noverlays > len)
7180 {
7181 len = noverlays;
7182 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7183 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7184 }
7185
7186 /* Sort overlays into increasing priority order. */
7187 noverlays = sort_overlays (overlay_vec, noverlays, w);
7188 }
7189 else
7190 noverlays = 0;
7191
7192 same_region = (EQ (window, dpyinfo->mouse_face_window)
7193 && vpos >= dpyinfo->mouse_face_beg_row
7194 && vpos <= dpyinfo->mouse_face_end_row
7195 && (vpos > dpyinfo->mouse_face_beg_row
7196 || hpos >= dpyinfo->mouse_face_beg_col)
7197 && (vpos < dpyinfo->mouse_face_end_row
7198 || hpos < dpyinfo->mouse_face_end_col
7199 || dpyinfo->mouse_face_past_end));
7200
7201 /* TODO: if (same_region)
7202 mouse cursor */
7203
7204 /* Check mouse-face highlighting. */
7205 if (! same_region
7206 /* If there exists an overlay with mouse-face overlapping
7207 the one we are currently highlighting, we have to
7208 check if we enter the overlapping overlay, and then
7209 highlight that. */
7210 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7211 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7212 {
7213 /* Find the highest priority overlay that has a mouse-face
7214 property. */
7215 overlay = Qnil;
7216 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7217 {
7218 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7219 if (!NILP (mouse_face))
7220 overlay = overlay_vec[i];
7221 }
7222
7223 /* If we're actually highlighting the same overlay as
7224 before, there's no need to do that again. */
7225 if (!NILP (overlay)
7226 && EQ (overlay, dpyinfo->mouse_face_overlay))
7227 goto check_help_echo;
7228
7229 dpyinfo->mouse_face_overlay = overlay;
7230
7231 /* Clear the display of the old active region, if any. */
7232 clear_mouse_face (dpyinfo);
7233 /* TODO: mouse cursor changes. */
7234
7235 /* If no overlay applies, get a text property. */
7236 if (NILP (overlay))
7237 mouse_face = Fget_text_property (position, Qmouse_face, object);
7238
7239 /* Handle the overlay case. */
7240 if (!NILP (overlay))
7241 {
7242 /* Find the range of text around this char that
7243 should be active. */
7244 Lisp_Object before, after;
7245 int ignore;
7246
7247 before = Foverlay_start (overlay);
7248 after = Foverlay_end (overlay);
7249 /* Record this as the current active region. */
7250 fast_find_position (w, XFASTINT (before),
7251 &dpyinfo->mouse_face_beg_col,
7252 &dpyinfo->mouse_face_beg_row,
7253 &dpyinfo->mouse_face_beg_x,
7254 &dpyinfo->mouse_face_beg_y, Qnil);
7255
7256 dpyinfo->mouse_face_past_end
7257 = !fast_find_position (w, XFASTINT (after),
7258 &dpyinfo->mouse_face_end_col,
7259 &dpyinfo->mouse_face_end_row,
7260 &dpyinfo->mouse_face_end_x,
7261 &dpyinfo->mouse_face_end_y, Qnil);
7262 dpyinfo->mouse_face_window = window;
7263
7264 dpyinfo->mouse_face_face_id
7265 = face_at_buffer_position (w, pos, 0, 0,
7266 &ignore, pos + 1, 1);
7267
7268 /* Display it as active. */
7269 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7270 /* TODO: mouse cursor changes. */
7271 }
7272 /* Handle the text property case. */
7273 else if (! NILP (mouse_face) && BUFFERP (object))
7274 {
7275 /* Find the range of text around this char that
7276 should be active. */
7277 Lisp_Object before, after, beginning, end;
7278 int ignore;
7279
7280 beginning = Fmarker_position (w->start);
7281 end = make_number (BUF_Z (XBUFFER (object))
7282 - XFASTINT (w->window_end_pos));
7283 before
7284 = Fprevious_single_property_change (make_number (pos + 1),
7285 Qmouse_face,
7286 object, beginning);
7287 after
7288 = Fnext_single_property_change (position, Qmouse_face,
7289 object, end);
7290
7291 /* Record this as the current active region. */
7292 fast_find_position (w, XFASTINT (before),
7293 &dpyinfo->mouse_face_beg_col,
7294 &dpyinfo->mouse_face_beg_row,
7295 &dpyinfo->mouse_face_beg_x,
7296 &dpyinfo->mouse_face_beg_y, Qnil);
7297 dpyinfo->mouse_face_past_end
7298 = !fast_find_position (w, XFASTINT (after),
7299 &dpyinfo->mouse_face_end_col,
7300 &dpyinfo->mouse_face_end_row,
7301 &dpyinfo->mouse_face_end_x,
7302 &dpyinfo->mouse_face_end_y, Qnil);
7303 dpyinfo->mouse_face_window = window;
7304
7305 if (BUFFERP (object))
7306 dpyinfo->mouse_face_face_id
7307 = face_at_buffer_position (w, pos, 0, 0,
7308 &ignore, pos + 1, 1);
7309
7310 /* Display it as active. */
7311 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7312 /* TODO: mouse cursor changes. */
7313 }
7314 else if (!NILP (mouse_face) && STRINGP (object))
7315 {
7316 Lisp_Object b, e;
7317 int ignore;
7318
7319 b = Fprevious_single_property_change (make_number (pos + 1),
7320 Qmouse_face,
7321 object, Qnil);
7322 e = Fnext_single_property_change (position, Qmouse_face,
7323 object, Qnil);
7324 if (NILP (b))
7325 b = make_number (0);
7326 if (NILP (e))
7327 e = make_number (XSTRING (object)->size - 1);
7328 fast_find_string_pos (w, XINT (b), object,
7329 &dpyinfo->mouse_face_beg_col,
7330 &dpyinfo->mouse_face_beg_row,
7331 &dpyinfo->mouse_face_beg_x,
7332 &dpyinfo->mouse_face_beg_y, 0);
7333 fast_find_string_pos (w, XINT (e), object,
7334 &dpyinfo->mouse_face_end_col,
7335 &dpyinfo->mouse_face_end_row,
7336 &dpyinfo->mouse_face_end_x,
7337 &dpyinfo->mouse_face_end_y, 1);
7338 dpyinfo->mouse_face_past_end = 0;
7339 dpyinfo->mouse_face_window = window;
7340 dpyinfo->mouse_face_face_id
7341 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7342 glyph->face_id, 1);
7343 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7344 /* TODO: mouse cursor changes. */
7345 }
7346 else if (STRINGP (object) && NILP (mouse_face))
7347 {
7348 /* A string which doesn't have mouse-face, but
7349 the text ``under'' it might have. */
7350 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7351 int start = MATRIX_ROW_START_CHARPOS (r);
7352
7353 pos = string_buffer_position (w, object, start);
7354 if (pos > 0)
7355 mouse_face = get_char_property_and_overlay (make_number (pos),
7356 Qmouse_face,
7357 w->buffer,
7358 &overlay);
7359 if (!NILP (mouse_face) && !NILP (overlay))
7360 {
7361 Lisp_Object before = Foverlay_start (overlay);
7362 Lisp_Object after = Foverlay_end (overlay);
7363 int ignore;
7364
7365 /* Note that we might not be able to find position
7366 BEFORE in the glyph matrix if the overlay is
7367 entirely covered by a `display' property. In
7368 this case, we overshoot. So let's stop in
7369 the glyph matrix before glyphs for OBJECT. */
7370 fast_find_position (w, XFASTINT (before),
7371 &dpyinfo->mouse_face_beg_col,
7372 &dpyinfo->mouse_face_beg_row,
7373 &dpyinfo->mouse_face_beg_x,
7374 &dpyinfo->mouse_face_beg_y,
7375 object);
7376
7377 dpyinfo->mouse_face_past_end
7378 = !fast_find_position (w, XFASTINT (after),
7379 &dpyinfo->mouse_face_end_col,
7380 &dpyinfo->mouse_face_end_row,
7381 &dpyinfo->mouse_face_end_x,
7382 &dpyinfo->mouse_face_end_y,
7383 Qnil);
7384 dpyinfo->mouse_face_window = window;
7385 dpyinfo->mouse_face_face_id
7386 = face_at_buffer_position (w, pos, 0, 0,
7387 &ignore, pos + 1, 1);
7388
7389 /* Display it as active. */
7390 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7391 /* TODO: mouse cursor changes. */
7392 }
7393 }
7394 }
7395
7396 check_help_echo:
7397
7398 /* Look for a `help-echo' property. */
7399 {
7400 Lisp_Object help, overlay;
7401
7402 /* Check overlays first. */
7403 help = overlay = Qnil;
7404 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7405 {
7406 overlay = overlay_vec[i];
7407 help = Foverlay_get (overlay, Qhelp_echo);
7408 }
7409
7410 if (!NILP (help))
7411 {
7412 help_echo = help;
7413 help_echo_window = window;
7414 help_echo_object = overlay;
7415 help_echo_pos = pos;
7416 }
7417 else
7418 {
7419 Lisp_Object object = glyph->object;
7420 int charpos = glyph->charpos;
7421
7422 /* Try text properties. */
7423 if (STRINGP (object)
7424 && charpos >= 0
7425 && charpos < XSTRING (object)->size)
7426 {
7427 help = Fget_text_property (make_number (charpos),
7428 Qhelp_echo, object);
7429 if (NILP (help))
7430 {
7431 /* If the string itself doesn't specify a help-echo,
7432 see if the buffer text ``under'' it does. */
7433 struct glyph_row *r
7434 = MATRIX_ROW (w->current_matrix, vpos);
7435 int start = MATRIX_ROW_START_CHARPOS (r);
7436 int pos = string_buffer_position (w, object, start);
7437 if (pos > 0)
7438 {
7439 help = Fget_char_property (make_number (pos),
7440 Qhelp_echo, w->buffer);
7441 if (!NILP (help))
7442 {
7443 charpos = pos;
7444 object = w->buffer;
7445 }
7446 }
7447 }
7448 }
7449 else if (BUFFERP (object)
7450 && charpos >= BEGV
7451 && charpos < ZV)
7452 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7453 object);
7454
7455 if (!NILP (help))
7456 {
7457 help_echo = help;
7458 help_echo_window = window;
7459 help_echo_object = object;
7460 help_echo_pos = charpos;
7461 }
7462 }
7463 }
7464
7465 BEGV = obegv;
7466 ZV = ozv;
7467 current_buffer = obuf;
7468 }
7469
7470 set_cursor:
7471 /* TODO: mouse cursor changes. */
7472 ;
7473 }
7474
7475 static void
7476 redo_mouse_highlight ()
7477 {
7478 if (!NILP (last_mouse_motion_frame)
7479 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7480 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7481 last_mouse_motion_position.h,
7482 last_mouse_motion_position.v);
7483 }
7484
7485
7486 \f
7487 /***********************************************************************
7488 Tool-bars
7489 ***********************************************************************/
7490
7491 static int x_tool_bar_item P_ ((struct frame *, int, int,
7492 struct glyph **, int *, int *, int *));
7493
7494 /* Tool-bar item index of the item on which a mouse button was pressed
7495 or -1. */
7496
7497 static int last_tool_bar_item;
7498
7499
7500 /* Get information about the tool-bar item at position X/Y on frame F.
7501 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7502 the current matrix of the tool-bar window of F, or NULL if not
7503 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7504 item in F->current_tool_bar_items. Value is
7505
7506 -1 if X/Y is not on a tool-bar item
7507 0 if X/Y is on the same item that was highlighted before.
7508 1 otherwise. */
7509
7510 static int
7511 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7512 struct frame *f;
7513 int x, y;
7514 struct glyph **glyph;
7515 int *hpos, *vpos, *prop_idx;
7516 {
7517 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7518 struct window *w = XWINDOW (f->tool_bar_window);
7519 int area;
7520
7521 /* Find the glyph under X/Y. */
7522 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7523 if (*glyph == NULL)
7524 return -1;
7525
7526 /* Get the start of this tool-bar item's properties in
7527 f->current_tool_bar_items. */
7528 if (!tool_bar_item_info (f, *glyph, prop_idx))
7529 return -1;
7530
7531 /* Is mouse on the highlighted item? */
7532 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7533 && *vpos >= dpyinfo->mouse_face_beg_row
7534 && *vpos <= dpyinfo->mouse_face_end_row
7535 && (*vpos > dpyinfo->mouse_face_beg_row
7536 || *hpos >= dpyinfo->mouse_face_beg_col)
7537 && (*vpos < dpyinfo->mouse_face_end_row
7538 || *hpos < dpyinfo->mouse_face_end_col
7539 || dpyinfo->mouse_face_past_end))
7540 return 0;
7541
7542 return 1;
7543 }
7544
7545
7546 /* Handle mouse button event on the tool-bar of frame F, at
7547 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7548 or ButtonRelase. */
7549
7550 static void
7551 x_handle_tool_bar_click (f, button_event)
7552 struct frame *f;
7553 EventRecord *button_event;
7554 {
7555 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7556 struct window *w = XWINDOW (f->tool_bar_window);
7557 int hpos, vpos, prop_idx;
7558 struct glyph *glyph;
7559 Lisp_Object enabled_p;
7560 int x = button_event->where.h;
7561 int y = button_event->where.v;
7562
7563 /* If not on the highlighted tool-bar item, return. */
7564 frame_to_window_pixel_xy (w, &x, &y);
7565 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7566 return;
7567
7568 /* If item is disabled, do nothing. */
7569 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7570 if (NILP (enabled_p))
7571 return;
7572
7573 if (button_event->what == mouseDown)
7574 {
7575 /* Show item in pressed state. */
7576 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7577 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7578 last_tool_bar_item = prop_idx;
7579 }
7580 else
7581 {
7582 Lisp_Object key, frame;
7583 struct input_event event;
7584
7585 /* Show item in released state. */
7586 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7587 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7588
7589 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7590
7591 XSETFRAME (frame, f);
7592 event.kind = TOOL_BAR_EVENT;
7593 event.frame_or_window = frame;
7594 event.arg = frame;
7595 kbd_buffer_store_event (&event);
7596
7597 event.kind = TOOL_BAR_EVENT;
7598 event.frame_or_window = frame;
7599 event.arg = key;
7600 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7601 button_event->modifiers);
7602 kbd_buffer_store_event (&event);
7603 last_tool_bar_item = -1;
7604 }
7605 }
7606
7607
7608 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7609 tool-bar window-relative coordinates X/Y. Called from
7610 note_mouse_highlight. */
7611
7612 static void
7613 note_tool_bar_highlight (f, x, y)
7614 struct frame *f;
7615 int x, y;
7616 {
7617 Lisp_Object window = f->tool_bar_window;
7618 struct window *w = XWINDOW (window);
7619 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7620 int hpos, vpos;
7621 struct glyph *glyph;
7622 struct glyph_row *row;
7623 int i;
7624 Lisp_Object enabled_p;
7625 int prop_idx;
7626 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7627 int mouse_down_p, rc;
7628
7629 /* Function note_mouse_highlight is called with negative x(y
7630 values when mouse moves outside of the frame. */
7631 if (x <= 0 || y <= 0)
7632 {
7633 clear_mouse_face (dpyinfo);
7634 return;
7635 }
7636
7637 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7638 if (rc < 0)
7639 {
7640 /* Not on tool-bar item. */
7641 clear_mouse_face (dpyinfo);
7642 return;
7643 }
7644 else if (rc == 0)
7645 /* On same tool-bar item as before. */
7646 goto set_help_echo;
7647
7648 clear_mouse_face (dpyinfo);
7649
7650 /* Mouse is down, but on different tool-bar item? */
7651 mouse_down_p = (dpyinfo->grabbed
7652 && f == last_mouse_frame
7653 && FRAME_LIVE_P (f));
7654 if (mouse_down_p
7655 && last_tool_bar_item != prop_idx)
7656 return;
7657
7658 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7659 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7660
7661 /* If tool-bar item is not enabled, don't highlight it. */
7662 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7663 if (!NILP (enabled_p))
7664 {
7665 /* Compute the x-position of the glyph. In front and past the
7666 image is a space. We include this is the highlighted area. */
7667 row = MATRIX_ROW (w->current_matrix, vpos);
7668 for (i = x = 0; i < hpos; ++i)
7669 x += row->glyphs[TEXT_AREA][i].pixel_width;
7670
7671 /* Record this as the current active region. */
7672 dpyinfo->mouse_face_beg_col = hpos;
7673 dpyinfo->mouse_face_beg_row = vpos;
7674 dpyinfo->mouse_face_beg_x = x;
7675 dpyinfo->mouse_face_beg_y = row->y;
7676 dpyinfo->mouse_face_past_end = 0;
7677
7678 dpyinfo->mouse_face_end_col = hpos + 1;
7679 dpyinfo->mouse_face_end_row = vpos;
7680 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7681 dpyinfo->mouse_face_end_y = row->y;
7682 dpyinfo->mouse_face_window = window;
7683 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7684
7685 /* Display it as active. */
7686 show_mouse_face (dpyinfo, draw);
7687 dpyinfo->mouse_face_image_state = draw;
7688 }
7689
7690 set_help_echo:
7691
7692 /* Set help_echo to a help string.to display for this tool-bar item.
7693 XTread_socket does the rest. */
7694 help_echo_object = help_echo_window = Qnil;
7695 help_echo_pos = -1;
7696 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7697 if (NILP (help_echo))
7698 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7699 }
7700
7701
7702 \f
7703 /* Find the glyph matrix position of buffer position CHARPOS in window
7704 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7705 current glyphs must be up to date. If CHARPOS is above window
7706 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7707 of last line in W. In the row containing CHARPOS, stop before glyphs
7708 having STOP as object. */
7709
7710 #if 0 /* This is a version of fast_find_position that's more correct
7711 in the presence of hscrolling, for example. I didn't install
7712 it right away because the problem fixed is minor, it failed
7713 in 20.x as well, and I think it's too risky to install
7714 so near the release of 21.1. 2001-09-25 gerd. */
7715
7716 static int
7717 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7718 struct window *w;
7719 int charpos;
7720 int *hpos, *vpos, *x, *y;
7721 Lisp_Object stop;
7722 {
7723 struct glyph_row *row, *first;
7724 struct glyph *glyph, *end;
7725 int i, past_end = 0;
7726
7727 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7728 row = row_containing_pos (w, charpos, first, NULL, 0);
7729 if (row == NULL)
7730 {
7731 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7732 {
7733 *x = *y = *hpos = *vpos = 0;
7734 return 0;
7735 }
7736 else
7737 {
7738 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7739 past_end = 1;
7740 }
7741 }
7742
7743 *x = row->x;
7744 *y = row->y;
7745 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7746
7747 glyph = row->glyphs[TEXT_AREA];
7748 end = glyph + row->used[TEXT_AREA];
7749
7750 /* Skip over glyphs not having an object at the start of the row.
7751 These are special glyphs like truncation marks on terminal
7752 frames. */
7753 if (row->displays_text_p)
7754 while (glyph < end
7755 && INTEGERP (glyph->object)
7756 && !EQ (stop, glyph->object)
7757 && glyph->charpos < 0)
7758 {
7759 *x += glyph->pixel_width;
7760 ++glyph;
7761 }
7762
7763 while (glyph < end
7764 && !INTEGERP (glyph->object)
7765 && !EQ (stop, glyph->object)
7766 && (!BUFFERP (glyph->object)
7767 || glyph->charpos < charpos))
7768 {
7769 *x += glyph->pixel_width;
7770 ++glyph;
7771 }
7772
7773 *hpos = glyph - row->glyphs[TEXT_AREA];
7774 return past_end;
7775 }
7776
7777 #else /* not 0 */
7778
7779 static int
7780 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7781 struct window *w;
7782 int pos;
7783 int *hpos, *vpos, *x, *y;
7784 Lisp_Object stop;
7785 {
7786 int i;
7787 int lastcol;
7788 int maybe_next_line_p = 0;
7789 int line_start_position;
7790 int yb = window_text_bottom_y (w);
7791 struct glyph_row *row, *best_row;
7792 int row_vpos, best_row_vpos;
7793 int current_x;
7794
7795 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7796 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7797
7798 while (row->y < yb)
7799 {
7800 if (row->used[TEXT_AREA])
7801 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7802 else
7803 line_start_position = 0;
7804
7805 if (line_start_position > pos)
7806 break;
7807 /* If the position sought is the end of the buffer,
7808 don't include the blank lines at the bottom of the window. */
7809 else if (line_start_position == pos
7810 && pos == BUF_ZV (XBUFFER (w->buffer)))
7811 {
7812 maybe_next_line_p = 1;
7813 break;
7814 }
7815 else if (line_start_position > 0)
7816 {
7817 best_row = row;
7818 best_row_vpos = row_vpos;
7819 }
7820
7821 if (row->y + row->height >= yb)
7822 break;
7823
7824 ++row;
7825 ++row_vpos;
7826 }
7827
7828 /* Find the right column within BEST_ROW. */
7829 lastcol = 0;
7830 current_x = best_row->x;
7831 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7832 {
7833 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7834 int charpos = glyph->charpos;
7835
7836 if (BUFFERP (glyph->object))
7837 {
7838 if (charpos == pos)
7839 {
7840 *hpos = i;
7841 *vpos = best_row_vpos;
7842 *x = current_x;
7843 *y = best_row->y;
7844 return 1;
7845 }
7846 else if (charpos > pos)
7847 break;
7848 }
7849 else if (EQ (glyph->object, stop))
7850 break;
7851
7852 if (charpos > 0)
7853 lastcol = i;
7854 current_x += glyph->pixel_width;
7855 }
7856
7857 /* If we're looking for the end of the buffer,
7858 and we didn't find it in the line we scanned,
7859 use the start of the following line. */
7860 if (maybe_next_line_p)
7861 {
7862 ++best_row;
7863 ++best_row_vpos;
7864 lastcol = 0;
7865 current_x = best_row->x;
7866 }
7867
7868 *vpos = best_row_vpos;
7869 *hpos = lastcol + 1;
7870 *x = current_x;
7871 *y = best_row->y;
7872 return 0;
7873 }
7874
7875 #endif /* not 0 */
7876
7877
7878 /* Find the position of the glyph for position POS in OBJECT in
7879 window W's current matrix, and return in *X/*Y the pixel
7880 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7881
7882 RIGHT_P non-zero means return the position of the right edge of the
7883 glyph, RIGHT_P zero means return the left edge position.
7884
7885 If no glyph for POS exists in the matrix, return the position of
7886 the glyph with the next smaller position that is in the matrix, if
7887 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7888 exists in the matrix, return the position of the glyph with the
7889 next larger position in OBJECT.
7890
7891 Value is non-zero if a glyph was found. */
7892
7893 static int
7894 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7895 struct window *w;
7896 int pos;
7897 Lisp_Object object;
7898 int *hpos, *vpos, *x, *y;
7899 int right_p;
7900 {
7901 int yb = window_text_bottom_y (w);
7902 struct glyph_row *r;
7903 struct glyph *best_glyph = NULL;
7904 struct glyph_row *best_row = NULL;
7905 int best_x = 0;
7906
7907 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7908 r->enabled_p && r->y < yb;
7909 ++r)
7910 {
7911 struct glyph *g = r->glyphs[TEXT_AREA];
7912 struct glyph *e = g + r->used[TEXT_AREA];
7913 int gx;
7914
7915 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7916 if (EQ (g->object, object))
7917 {
7918 if (g->charpos == pos)
7919 {
7920 best_glyph = g;
7921 best_x = gx;
7922 best_row = r;
7923 goto found;
7924 }
7925 else if (best_glyph == NULL
7926 || ((abs (g->charpos - pos)
7927 < abs (best_glyph->charpos - pos))
7928 && (right_p
7929 ? g->charpos < pos
7930 : g->charpos > pos)))
7931 {
7932 best_glyph = g;
7933 best_x = gx;
7934 best_row = r;
7935 }
7936 }
7937 }
7938
7939 found:
7940
7941 if (best_glyph)
7942 {
7943 *x = best_x;
7944 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7945
7946 if (right_p)
7947 {
7948 *x += best_glyph->pixel_width;
7949 ++*hpos;
7950 }
7951
7952 *y = best_row->y;
7953 *vpos = best_row - w->current_matrix->rows;
7954 }
7955
7956 return best_glyph != NULL;
7957 }
7958
7959
7960 /* Display the active region described by mouse_face_*
7961 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7962
7963 static void
7964 show_mouse_face (dpyinfo, draw)
7965 struct mac_display_info *dpyinfo;
7966 enum draw_glyphs_face draw;
7967 {
7968 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7969 struct frame *f = XFRAME (WINDOW_FRAME (w));
7970
7971 if (/* If window is in the process of being destroyed, don't bother
7972 to do anything. */
7973 w->current_matrix != NULL
7974 /* Don't update mouse highlight if hidden */
7975 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7976 /* Recognize when we are called to operate on rows that don't exist
7977 anymore. This can happen when a window is split. */
7978 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7979 {
7980 int phys_cursor_on_p = w->phys_cursor_on_p;
7981 struct glyph_row *row, *first, *last;
7982
7983 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7984 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7985
7986 for (row = first; row <= last && row->enabled_p; ++row)
7987 {
7988 int start_hpos, end_hpos, start_x;
7989
7990 /* For all but the first row, the highlight starts at column 0. */
7991 if (row == first)
7992 {
7993 start_hpos = dpyinfo->mouse_face_beg_col;
7994 start_x = dpyinfo->mouse_face_beg_x;
7995 }
7996 else
7997 {
7998 start_hpos = 0;
7999 start_x = 0;
8000 }
8001
8002 if (row == last)
8003 end_hpos = dpyinfo->mouse_face_end_col;
8004 else
8005 end_hpos = row->used[TEXT_AREA];
8006
8007 if (end_hpos > start_hpos)
8008 {
8009 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8010 start_hpos, end_hpos, draw, 0);
8011
8012 row->mouse_face_p
8013 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8014 }
8015 }
8016
8017 /* When we've written over the cursor, arrange for it to
8018 be displayed again. */
8019 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8020 x_display_cursor (w, 1,
8021 w->phys_cursor.hpos, w->phys_cursor.vpos,
8022 w->phys_cursor.x, w->phys_cursor.y);
8023 }
8024
8025 #if 0 /* MAC_TODO: mouse cursor */
8026 /* Change the mouse cursor. */
8027 if (draw == DRAW_NORMAL_TEXT)
8028 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8029 f->output_data.x->text_cursor);
8030 else if (draw == DRAW_MOUSE_FACE)
8031 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8032 f->output_data.x->cross_cursor);
8033 else
8034 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8035 f->output_data.x->nontext_cursor);
8036 #endif
8037 }
8038
8039 /* Clear out the mouse-highlighted active region.
8040 Redraw it un-highlighted first. */
8041
8042 static int
8043 clear_mouse_face (dpyinfo)
8044 struct mac_display_info *dpyinfo;
8045 {
8046 int cleared = 0;
8047
8048 if (! NILP (dpyinfo->mouse_face_window))
8049 {
8050 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8051 cleared = 1;
8052 }
8053
8054 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8055 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8056 dpyinfo->mouse_face_window = Qnil;
8057 dpyinfo->mouse_face_overlay = Qnil;
8058 return cleared;
8059 }
8060
8061
8062 /* Clear any mouse-face on window W. This function is part of the
8063 redisplay interface, and is called from try_window_id and similar
8064 functions to ensure the mouse-highlight is off. */
8065
8066 static void
8067 x_clear_mouse_face (w)
8068 struct window *w;
8069 {
8070 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8071 Lisp_Object window;
8072
8073 BLOCK_INPUT;
8074 XSETWINDOW (window, w);
8075 if (EQ (window, dpyinfo->mouse_face_window))
8076 clear_mouse_face (dpyinfo);
8077 UNBLOCK_INPUT;
8078 }
8079
8080
8081 /* Just discard the mouse face information for frame F, if any.
8082 This is used when the size of F is changed. */
8083
8084 void
8085 cancel_mouse_face (f)
8086 FRAME_PTR f;
8087 {
8088 Lisp_Object window;
8089 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8090
8091 window = dpyinfo->mouse_face_window;
8092 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8093 {
8094 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8095 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8096 dpyinfo->mouse_face_window = Qnil;
8097 }
8098 }
8099 \f
8100 static struct scroll_bar *x_window_to_scroll_bar ();
8101 static void x_scroll_bar_report_motion ();
8102 static void x_check_fullscreen P_ ((struct frame *));
8103 static void x_check_fullscreen_move P_ ((struct frame *));
8104 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8105
8106
8107 /* Try to determine frame pixel position and size of the glyph under
8108 frame pixel coordinates X/Y on frame F . Return the position and
8109 size in *RECT. Value is non-zero if we could compute these
8110 values. */
8111
8112 static int
8113 glyph_rect (f, x, y, rect)
8114 struct frame *f;
8115 int x, y;
8116 Rect *rect;
8117 {
8118 Lisp_Object window;
8119 int part;
8120
8121 window = window_from_coordinates (f, x, y, &part, 0);
8122 if (!NILP (window))
8123 {
8124 struct window *w = XWINDOW (window);
8125 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8126 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8127
8128 frame_to_window_pixel_xy (w, &x, &y);
8129
8130 for (; r < end && r->enabled_p; ++r)
8131 if (r->y <= y && r->y + r->height > y)
8132 {
8133 /* Found the row at y. */
8134 struct glyph *g = r->glyphs[TEXT_AREA];
8135 struct glyph *end = g + r->used[TEXT_AREA];
8136 int gx;
8137
8138 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8139 rect->bottom = rect->top + r->height;
8140
8141 if (x < r->x)
8142 {
8143 /* x is to the left of the first glyph in the row. */
8144 rect->left = XINT (w->left);
8145 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8146 return 1;
8147 }
8148
8149 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8150 if (gx <= x && gx + g->pixel_width > x)
8151 {
8152 /* x is on a glyph. */
8153 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8154 rect->right = rect->left + g->pixel_width;
8155 return 1;
8156 }
8157
8158 /* x is to the right of the last glyph in the row. */
8159 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8160 rect->right = XINT (w->left) + XINT (w->width);
8161 return 1;
8162 }
8163 }
8164
8165 /* The y is not on any row. */
8166 return 0;
8167 }
8168
8169 /* Record the position of the mouse in last_mouse_glyph. */
8170 static void
8171 remember_mouse_glyph (f1, gx, gy)
8172 struct frame * f1;
8173 int gx, gy;
8174 {
8175 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8176 {
8177 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8178 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8179
8180 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8181 round down even for negative values. */
8182 if (gx < 0)
8183 gx -= width - 1;
8184 if (gy < 0)
8185 gy -= height - 1;
8186 #if 0
8187 /* This was the original code from XTmouse_position, but it seems
8188 to give the position of the glyph diagonally next to the one
8189 the mouse is over. */
8190 gx = (gx + width - 1) / width * width;
8191 gy = (gy + height - 1) / height * height;
8192 #else
8193 gx = gx / width * width;
8194 gy = gy / height * height;
8195 #endif
8196
8197 last_mouse_glyph.left = gx;
8198 last_mouse_glyph.top = gy;
8199 last_mouse_glyph.right = gx + width;
8200 last_mouse_glyph.bottom = gy + height;
8201 }
8202 }
8203
8204 /* Return the current position of the mouse.
8205 *fp should be a frame which indicates which display to ask about.
8206
8207 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8208 and *part to the frame, window, and scroll bar part that the mouse
8209 is over. Set *x and *y to the portion and whole of the mouse's
8210 position on the scroll bar.
8211
8212 If the mouse movement started elsewhere, set *fp to the frame the
8213 mouse is on, *bar_window to nil, and *x and *y to the character cell
8214 the mouse is over.
8215
8216 Set *time to the server time-stamp for the time at which the mouse
8217 was at this position.
8218
8219 Don't store anything if we don't have a valid set of values to report.
8220
8221 This clears the mouse_moved flag, so we can wait for the next mouse
8222 movement. */
8223
8224 static void
8225 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8226 FRAME_PTR *fp;
8227 int insist;
8228 Lisp_Object *bar_window;
8229 enum scroll_bar_part *part;
8230 Lisp_Object *x, *y;
8231 unsigned long *time;
8232 {
8233 Point mouse_pos;
8234 int ignore1, ignore2;
8235 WindowPtr wp = FrontWindow ();
8236 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8237 Lisp_Object frame, tail;
8238
8239 BLOCK_INPUT;
8240
8241 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8242 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8243 else
8244 {
8245 /* Clear the mouse-moved flag for every frame on this display. */
8246 FOR_EACH_FRAME (tail, frame)
8247 XFRAME (frame)->mouse_moved = 0;
8248
8249 last_mouse_scroll_bar = Qnil;
8250
8251 #if TARGET_API_MAC_CARBON
8252 SetPort (GetWindowPort (wp));
8253 #else
8254 SetPort (wp);
8255 #endif
8256
8257 GetMouse (&mouse_pos);
8258
8259 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8260 &last_mouse_glyph, insist);
8261
8262 *bar_window = Qnil;
8263 *part = scroll_bar_handle;
8264 *fp = f;
8265 XSETINT (*x, mouse_pos.h);
8266 XSETINT (*y, mouse_pos.v);
8267 *time = last_mouse_movement_time;
8268 }
8269
8270 UNBLOCK_INPUT;
8271 }
8272
8273 \f
8274 /************************************************************************
8275 Scroll bars, general
8276 ************************************************************************/
8277
8278 /* Create a scroll bar and return the scroll bar vector for it. W is
8279 the Emacs window on which to create the scroll bar. TOP, LEFT,
8280 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
8281 scroll bar. */
8282
8283 static struct scroll_bar *
8284 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8285 struct window *w;
8286 int top, left, width, height, disp_top, disp_height;
8287 {
8288 struct frame *f = XFRAME (w->frame);
8289 struct scroll_bar *bar
8290 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8291 Rect r;
8292 ControlHandle ch;
8293
8294 BLOCK_INPUT;
8295
8296 r.left = left;
8297 r.top = disp_top;
8298 r.right = left + width;
8299 r.bottom = disp_top + disp_height;
8300
8301 #ifdef TARGET_API_MAC_CARBON
8302 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8303 kControlScrollBarProc, 0L);
8304 #else
8305 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8306 0L);
8307 #endif
8308 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8309 SetControlReference (ch, (long) bar);
8310
8311 XSETWINDOW (bar->window, w);
8312 XSETINT (bar->top, top);
8313 XSETINT (bar->left, left);
8314 XSETINT (bar->width, width);
8315 XSETINT (bar->height, height);
8316 XSETINT (bar->start, 0);
8317 XSETINT (bar->end, 0);
8318 bar->dragging = Qnil;
8319
8320 /* Add bar to its frame's list of scroll bars. */
8321 bar->next = FRAME_SCROLL_BARS (f);
8322 bar->prev = Qnil;
8323 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8324 if (!NILP (bar->next))
8325 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8326
8327 UNBLOCK_INPUT;
8328 return bar;
8329 }
8330
8331
8332 /* Draw BAR's handle in the proper position.
8333
8334 If the handle is already drawn from START to END, don't bother
8335 redrawing it, unless REBUILD is non-zero; in that case, always
8336 redraw it. (REBUILD is handy for drawing the handle after expose
8337 events.)
8338
8339 Normally, we want to constrain the start and end of the handle to
8340 fit inside its rectangle, but if the user is dragging the scroll
8341 bar handle, we want to let them drag it down all the way, so that
8342 the bar's top is as far down as it goes; otherwise, there's no way
8343 to move to the very end of the buffer. */
8344
8345 static void
8346 x_scroll_bar_set_handle (bar, start, end, rebuild)
8347 struct scroll_bar *bar;
8348 int start, end;
8349 int rebuild;
8350 {
8351 int dragging = ! NILP (bar->dragging);
8352 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8353 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8354 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8355 int length = end - start;
8356
8357 /* If the display is already accurate, do nothing. */
8358 if (! rebuild
8359 && start == XINT (bar->start)
8360 && end == XINT (bar->end))
8361 return;
8362
8363 BLOCK_INPUT;
8364
8365 /* Make sure the values are reasonable, and try to preserve the
8366 distance between start and end. */
8367 if (start < 0)
8368 start = 0;
8369 else if (start > top_range)
8370 start = top_range;
8371 end = start + length;
8372
8373 if (end < start)
8374 end = start;
8375 else if (end > top_range && ! dragging)
8376 end = top_range;
8377
8378 /* Store the adjusted setting in the scroll bar. */
8379 XSETINT (bar->start, start);
8380 XSETINT (bar->end, end);
8381
8382 /* Clip the end position, just for display. */
8383 if (end > top_range)
8384 end = top_range;
8385
8386 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8387 top positions, to make sure the handle is always at least that
8388 many pixels tall. */
8389 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8390
8391 SetControlMinimum (ch, 0);
8392 /* Don't inadvertently activate deactivated scroll bars */
8393 if (GetControlMaximum (ch) != -1)
8394 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8395 - (end - start));
8396 SetControlValue (ch, start);
8397 #if TARGET_API_MAC_CARBON
8398 SetControlViewSize (ch, end - start);
8399 #endif
8400
8401 UNBLOCK_INPUT;
8402 }
8403
8404
8405 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8406 nil. */
8407
8408 static void
8409 x_scroll_bar_remove (bar)
8410 struct scroll_bar *bar;
8411 {
8412 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8413
8414 BLOCK_INPUT;
8415
8416 /* Destroy the Mac scroll bar control */
8417 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8418
8419 /* Disassociate this scroll bar from its window. */
8420 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8421
8422 UNBLOCK_INPUT;
8423 }
8424
8425 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8426 that we are displaying PORTION characters out of a total of WHOLE
8427 characters, starting at POSITION. If WINDOW has no scroll bar,
8428 create one. */
8429 static void
8430 XTset_vertical_scroll_bar (w, portion, whole, position)
8431 struct window *w;
8432 int portion, whole, position;
8433 {
8434 struct frame *f = XFRAME (w->frame);
8435 struct scroll_bar *bar;
8436 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8437 int window_x, window_y, window_width, window_height;
8438
8439 /* Get window dimensions. */
8440 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8441 top = window_y;
8442 #ifdef MAC_OSX
8443 width = 16;
8444 #else
8445 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8446 #endif
8447 height = window_height;
8448
8449 /* Compute the left edge of the scroll bar area. */
8450 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8451 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8452 else
8453 left = XFASTINT (w->left);
8454 left *= CANON_X_UNIT (f);
8455 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8456
8457 /* Compute the width of the scroll bar which might be less than
8458 the width of the area reserved for the scroll bar. */
8459 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8460 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8461 else
8462 sb_width = width;
8463
8464 /* Compute the left edge of the scroll bar. */
8465 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8466 sb_left = left + width - sb_width - (width - sb_width) / 2;
8467 else
8468 sb_left = left + (width - sb_width) / 2;
8469
8470 /* Adjustments according to Inside Macintosh to make it look nice */
8471 disp_top = top;
8472 disp_height = height;
8473 if (disp_top == 0)
8474 {
8475 disp_top = -1;
8476 disp_height++;
8477 }
8478 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8479 {
8480 disp_top++;
8481 disp_height--;
8482 }
8483
8484 if (sb_left + sb_width == PIXEL_WIDTH (f))
8485 sb_left++;
8486
8487 /* Does the scroll bar exist yet? */
8488 if (NILP (w->vertical_scroll_bar))
8489 {
8490 BLOCK_INPUT;
8491 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8492 left, top, width, height, 0);
8493 UNBLOCK_INPUT;
8494 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8495 disp_height);
8496 XSETVECTOR (w->vertical_scroll_bar, bar);
8497 }
8498 else
8499 {
8500 /* It may just need to be moved and resized. */
8501 ControlHandle ch;
8502
8503 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8504 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8505
8506 BLOCK_INPUT;
8507
8508 /* If already correctly positioned, do nothing. */
8509 if (XINT (bar->left) == sb_left
8510 && XINT (bar->top) == top
8511 && XINT (bar->width) == sb_width
8512 && XINT (bar->height) == height)
8513 Draw1Control (ch);
8514 else
8515 {
8516 /* Clear areas not covered by the scroll bar because it's not as
8517 wide as the area reserved for it . This makes sure a
8518 previous mode line display is cleared after C-x 2 C-x 1, for
8519 example. */
8520 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8521 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8522 left, top, area_width, height, 0);
8523
8524 #if 0
8525 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8526 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8527 sb_left - 1, top, 1, height, 0);
8528 #endif
8529
8530 HideControl (ch);
8531 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8532 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8533 disp_height);
8534 ShowControl (ch);
8535
8536 /* Remember new settings. */
8537 XSETINT (bar->left, sb_left);
8538 XSETINT (bar->top, top);
8539 XSETINT (bar->width, sb_width);
8540 XSETINT (bar->height, height);
8541 }
8542
8543 UNBLOCK_INPUT;
8544 }
8545
8546 /* Set the scroll bar's current state, unless we're currently being
8547 dragged. */
8548 if (NILP (bar->dragging))
8549 {
8550 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8551
8552 if (whole == 0)
8553 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8554 else
8555 {
8556 int start = ((double) position * top_range) / whole;
8557 int end = ((double) (position + portion) * top_range) / whole;
8558 x_scroll_bar_set_handle (bar, start, end, 0);
8559 }
8560 }
8561 }
8562
8563
8564 /* The following three hooks are used when we're doing a thorough
8565 redisplay of the frame. We don't explicitly know which scroll bars
8566 are going to be deleted, because keeping track of when windows go
8567 away is a real pain - "Can you say set-window-configuration, boys
8568 and girls?" Instead, we just assert at the beginning of redisplay
8569 that *all* scroll bars are to be removed, and then save a scroll bar
8570 from the fiery pit when we actually redisplay its window. */
8571
8572 /* Arrange for all scroll bars on FRAME to be removed at the next call
8573 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8574 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8575
8576 static void
8577 XTcondemn_scroll_bars (frame)
8578 FRAME_PTR frame;
8579 {
8580 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8581 while (! NILP (FRAME_SCROLL_BARS (frame)))
8582 {
8583 Lisp_Object bar;
8584 bar = FRAME_SCROLL_BARS (frame);
8585 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8586 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8587 XSCROLL_BAR (bar)->prev = Qnil;
8588 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8589 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8590 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8591 }
8592 }
8593
8594
8595 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8596 Note that WINDOW isn't necessarily condemned at all. */
8597
8598 static void
8599 XTredeem_scroll_bar (window)
8600 struct window *window;
8601 {
8602 struct scroll_bar *bar;
8603
8604 /* We can't redeem this window's scroll bar if it doesn't have one. */
8605 if (NILP (window->vertical_scroll_bar))
8606 abort ();
8607
8608 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8609
8610 /* Unlink it from the condemned list. */
8611 {
8612 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8613
8614 if (NILP (bar->prev))
8615 {
8616 /* If the prev pointer is nil, it must be the first in one of
8617 the lists. */
8618 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8619 /* It's not condemned. Everything's fine. */
8620 return;
8621 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8622 window->vertical_scroll_bar))
8623 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8624 else
8625 /* If its prev pointer is nil, it must be at the front of
8626 one or the other! */
8627 abort ();
8628 }
8629 else
8630 XSCROLL_BAR (bar->prev)->next = bar->next;
8631
8632 if (! NILP (bar->next))
8633 XSCROLL_BAR (bar->next)->prev = bar->prev;
8634
8635 bar->next = FRAME_SCROLL_BARS (f);
8636 bar->prev = Qnil;
8637 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8638 if (! NILP (bar->next))
8639 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8640 }
8641 }
8642
8643 /* Remove all scroll bars on FRAME that haven't been saved since the
8644 last call to `*condemn_scroll_bars_hook'. */
8645
8646 static void
8647 XTjudge_scroll_bars (f)
8648 FRAME_PTR f;
8649 {
8650 Lisp_Object bar, next;
8651
8652 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8653
8654 /* Clear out the condemned list now so we won't try to process any
8655 more events on the hapless scroll bars. */
8656 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8657
8658 for (; ! NILP (bar); bar = next)
8659 {
8660 struct scroll_bar *b = XSCROLL_BAR (bar);
8661
8662 x_scroll_bar_remove (b);
8663
8664 next = b->next;
8665 b->next = b->prev = Qnil;
8666 }
8667
8668 /* Now there should be no references to the condemned scroll bars,
8669 and they should get garbage-collected. */
8670 }
8671
8672
8673 static void
8674 activate_scroll_bars (frame)
8675 FRAME_PTR frame;
8676 {
8677 Lisp_Object bar;
8678 ControlHandle ch;
8679
8680 bar = FRAME_SCROLL_BARS (frame);
8681 while (! NILP (bar))
8682 {
8683 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8684 #ifdef TARGET_API_MAC_CARBON
8685 ActivateControl (ch);
8686 #else
8687 SetControlMaximum (ch,
8688 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8689 XINT (XSCROLL_BAR (bar)
8690 ->height)) - 1);
8691 #endif
8692 bar = XSCROLL_BAR (bar)->next;
8693 }
8694 }
8695
8696
8697 static void
8698 deactivate_scroll_bars (frame)
8699 FRAME_PTR frame;
8700 {
8701 Lisp_Object bar;
8702 ControlHandle ch;
8703
8704 bar = FRAME_SCROLL_BARS (frame);
8705 while (! NILP (bar))
8706 {
8707 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8708 #ifdef TARGET_API_MAC_CARBON
8709 DeactivateControl (ch);
8710 #else
8711 SetControlMaximum (ch, XINT (-1));
8712 #endif
8713 bar = XSCROLL_BAR (bar)->next;
8714 }
8715 }
8716
8717 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8718 is set to something other than NO_EVENT, it is enqueued.
8719
8720 This may be called from a signal handler, so we have to ignore GC
8721 mark bits. */
8722
8723 static void
8724 x_scroll_bar_handle_click (bar, part_code, er, bufp)
8725 struct scroll_bar *bar;
8726 int part_code;
8727 EventRecord *er;
8728 struct input_event *bufp;
8729 {
8730 if (! GC_WINDOWP (bar->window))
8731 abort ();
8732
8733 bufp->kind = SCROLL_BAR_CLICK_EVENT;
8734 bufp->frame_or_window = bar->window;
8735 bufp->arg = Qnil;
8736
8737 bar->dragging = Qnil;
8738
8739 switch (part_code)
8740 {
8741 case kControlUpButtonPart:
8742 bufp->part = scroll_bar_up_arrow;
8743 break;
8744 case kControlDownButtonPart:
8745 bufp->part = scroll_bar_down_arrow;
8746 break;
8747 case kControlPageUpPart:
8748 bufp->part = scroll_bar_above_handle;
8749 break;
8750 case kControlPageDownPart:
8751 bufp->part = scroll_bar_below_handle;
8752 break;
8753 #ifdef TARGET_API_MAC_CARBON
8754 default:
8755 #else
8756 case kControlIndicatorPart:
8757 #endif
8758 if (er->what == mouseDown)
8759 bar->dragging = make_number (0);
8760 XSETVECTOR (last_mouse_scroll_bar, bar);
8761 bufp->part = scroll_bar_handle;
8762 break;
8763 }
8764 }
8765
8766
8767 /* Handle some mouse motion while someone is dragging the scroll bar.
8768
8769 This may be called from a signal handler, so we have to ignore GC
8770 mark bits. */
8771
8772 static void
8773 x_scroll_bar_note_movement (bar, y_pos, t)
8774 struct scroll_bar *bar;
8775 int y_pos;
8776 Time t;
8777 {
8778 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8779
8780 last_mouse_movement_time = t;
8781
8782 f->mouse_moved = 1;
8783 XSETVECTOR (last_mouse_scroll_bar, bar);
8784
8785 /* If we're dragging the bar, display it. */
8786 if (! GC_NILP (bar->dragging))
8787 {
8788 /* Where should the handle be now? */
8789 int new_start = y_pos - 24;
8790
8791 if (new_start != XINT (bar->start))
8792 {
8793 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8794
8795 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8796 }
8797 }
8798 }
8799
8800
8801 /* Return information to the user about the current position of the
8802 mouse on the scroll bar. */
8803
8804 static void
8805 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8806 FRAME_PTR *fp;
8807 Lisp_Object *bar_window;
8808 enum scroll_bar_part *part;
8809 Lisp_Object *x, *y;
8810 unsigned long *time;
8811 {
8812 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8813 WindowPtr wp = FrontWindow ();
8814 Point mouse_pos;
8815 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8816 int win_y, top_range;
8817
8818 #if TARGET_API_MAC_CARBON
8819 SetPort (GetWindowPort (wp));
8820 #else
8821 SetPort (wp);
8822 #endif
8823
8824 GetMouse (&mouse_pos);
8825
8826 win_y = mouse_pos.v - XINT (bar->top);
8827 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8828
8829 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8830
8831 win_y -= 24;
8832
8833 if (! NILP (bar->dragging))
8834 win_y -= XINT (bar->dragging);
8835
8836 if (win_y < 0)
8837 win_y = 0;
8838 if (win_y > top_range)
8839 win_y = top_range;
8840
8841 *fp = f;
8842 *bar_window = bar->window;
8843
8844 if (! NILP (bar->dragging))
8845 *part = scroll_bar_handle;
8846 else if (win_y < XINT (bar->start))
8847 *part = scroll_bar_above_handle;
8848 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8849 *part = scroll_bar_handle;
8850 else
8851 *part = scroll_bar_below_handle;
8852
8853 XSETINT (*x, win_y);
8854 XSETINT (*y, top_range);
8855
8856 f->mouse_moved = 0;
8857 last_mouse_scroll_bar = Qnil;
8858
8859 *time = last_mouse_movement_time;
8860 }
8861 \f
8862 /***********************************************************************
8863 Text Cursor
8864 ***********************************************************************/
8865
8866 /* Notice if the text cursor of window W has been overwritten by a
8867 drawing operation that outputs glyphs starting at START_X and
8868 ending at END_X in the line given by output_cursor.vpos.
8869 Coordinates are area-relative. END_X < 0 means all the rest
8870 of the line after START_X has been written. */
8871
8872 static void
8873 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
8874 struct window *w;
8875 enum glyph_row_area area;
8876 int x0, x1, y0, y1;
8877 {
8878 if (area == TEXT_AREA
8879 && w->phys_cursor_on_p
8880 && y0 <= w->phys_cursor.y
8881 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8882 && x0 <= w->phys_cursor.x
8883 && (x1 < 0 || x1 > w->phys_cursor.x))
8884 w->phys_cursor_on_p = 0;
8885 }
8886
8887
8888 /* Set clipping for output in glyph row ROW. W is the window in which
8889 we operate. GC is the graphics context to set clipping in.
8890 WHOLE_LINE_P non-zero means include the areas used for truncation
8891 mark display and alike in the clipping rectangle.
8892
8893 ROW may be a text row or, e.g., a mode line. Text rows must be
8894 clipped to the interior of the window dedicated to text display,
8895 mode lines must be clipped to the whole window. */
8896
8897 static void
8898 x_clip_to_row (w, row, gc, whole_line_p)
8899 struct window *w;
8900 struct glyph_row *row;
8901 GC gc;
8902 int whole_line_p;
8903 {
8904 struct frame *f = XFRAME (WINDOW_FRAME (w));
8905 Rect clip_rect;
8906 int window_x, window_y, window_width, window_height;
8907
8908 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8909
8910 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8911 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8912 clip_rect.top = max (clip_rect.top, window_y);
8913 clip_rect.right = clip_rect.left + window_width;
8914 clip_rect.bottom = clip_rect.top + row->visible_height;
8915
8916 /* If clipping to the whole line, including trunc marks, extend
8917 the rectangle to the left and increase its width. */
8918 if (whole_line_p)
8919 {
8920 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8921 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
8922 }
8923
8924 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8925 }
8926
8927
8928 /* Draw a hollow box cursor on window W in glyph row ROW. */
8929
8930 static void
8931 x_draw_hollow_cursor (w, row)
8932 struct window *w;
8933 struct glyph_row *row;
8934 {
8935 struct frame *f = XFRAME (WINDOW_FRAME (w));
8936 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8937 Display *dpy = FRAME_MAC_DISPLAY (f);
8938 int x, y, wd, h;
8939 XGCValues xgcv;
8940 struct glyph *cursor_glyph;
8941 GC gc;
8942
8943 /* Compute frame-relative coordinates from window-relative
8944 coordinates. */
8945 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8946 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8947 + row->ascent - w->phys_cursor_ascent);
8948 h = row->height - 1;
8949
8950 /* Get the glyph the cursor is on. If we can't tell because
8951 the current matrix is invalid or such, give up. */
8952 cursor_glyph = get_phys_cursor_glyph (w);
8953 if (cursor_glyph == NULL)
8954 return;
8955
8956 /* Compute the width of the rectangle to draw. If on a stretch
8957 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8958 rectangle as wide as the glyph, but use a canonical character
8959 width instead. */
8960 wd = cursor_glyph->pixel_width - 1;
8961 if (cursor_glyph->type == STRETCH_GLYPH
8962 && !x_stretch_cursor_p)
8963 wd = min (CANON_X_UNIT (f), wd);
8964
8965 /* The foreground of cursor_gc is typically the same as the normal
8966 background color, which can cause the cursor box to be invisible. */
8967 xgcv.foreground = f->output_data.mac->cursor_pixel;
8968 if (dpyinfo->scratch_cursor_gc)
8969 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8970 else
8971 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
8972 GCForeground, &xgcv);
8973 gc = dpyinfo->scratch_cursor_gc;
8974
8975 /* Set clipping, draw the rectangle, and reset clipping again. */
8976 x_clip_to_row (w, row, gc, 0);
8977 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
8978 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8979 }
8980
8981
8982 /* Draw a bar cursor on window W in glyph row ROW.
8983
8984 Implementation note: One would like to draw a bar cursor with an
8985 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8986 Unfortunately, I didn't find a font yet that has this property set.
8987 --gerd. */
8988
8989 static void
8990 x_draw_bar_cursor (w, row, width)
8991 struct window *w;
8992 struct glyph_row *row;
8993 int width;
8994 {
8995 /* If cursor hpos is out of bounds, don't draw garbage. This can
8996 happen in mini-buffer windows when switching between echo area
8997 glyphs and mini-buffer. */
8998 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8999 {
9000 struct frame *f = XFRAME (w->frame);
9001 struct glyph *cursor_glyph;
9002 GC gc;
9003 int x;
9004 unsigned long mask;
9005 XGCValues xgcv;
9006 Display *dpy;
9007 Window window;
9008
9009 cursor_glyph = get_phys_cursor_glyph (w);
9010 if (cursor_glyph == NULL)
9011 return;
9012
9013 xgcv.background = f->output_data.mac->cursor_pixel;
9014 xgcv.foreground = f->output_data.mac->cursor_pixel;
9015 mask = GCForeground | GCBackground;
9016 dpy = FRAME_MAC_DISPLAY (f);
9017 window = FRAME_MAC_WINDOW (f);
9018 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9019
9020 if (gc)
9021 XChangeGC (dpy, gc, mask, &xgcv);
9022 else
9023 {
9024 gc = XCreateGC (dpy, window, mask, &xgcv);
9025 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9026 }
9027
9028 if (width < 0)
9029 width = f->output_data.mac->cursor_width;
9030
9031 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9032 x_clip_to_row (w, row, gc, 0);
9033 XFillRectangle (dpy, window, gc,
9034 x,
9035 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9036 min (cursor_glyph->pixel_width, width),
9037 row->height);
9038 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9039 }
9040 }
9041
9042
9043 /* Clear the cursor of window W to background color, and mark the
9044 cursor as not shown. This is used when the text where the cursor
9045 is is about to be rewritten. */
9046
9047 static void
9048 x_clear_cursor (w)
9049 struct window *w;
9050 {
9051 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9052 x_update_window_cursor (w, 0);
9053 }
9054
9055
9056 /* Draw the cursor glyph of window W in glyph row ROW. See the
9057 comment of x_draw_glyphs for the meaning of HL. */
9058
9059 static void
9060 x_draw_phys_cursor_glyph (w, row, hl)
9061 struct window *w;
9062 struct glyph_row *row;
9063 enum draw_glyphs_face hl;
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 int on_p = w->phys_cursor_on_p;
9071 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9072 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9073 hl, 0);
9074 w->phys_cursor_on_p = on_p;
9075
9076 /* When we erase the cursor, and ROW is overlapped by other
9077 rows, make sure that these overlapping parts of other rows
9078 are redrawn. */
9079 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9080 {
9081 if (row > w->current_matrix->rows
9082 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9083 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9084
9085 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9086 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9087 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9088 }
9089 }
9090 }
9091
9092
9093 /* Erase the image of a cursor of window W from the screen. */
9094
9095 static void
9096 x_erase_phys_cursor (w)
9097 struct window *w;
9098 {
9099 struct frame *f = XFRAME (w->frame);
9100 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9101 int hpos = w->phys_cursor.hpos;
9102 int vpos = w->phys_cursor.vpos;
9103 int mouse_face_here_p = 0;
9104 struct glyph_matrix *active_glyphs = w->current_matrix;
9105 struct glyph_row *cursor_row;
9106 struct glyph *cursor_glyph;
9107 enum draw_glyphs_face hl;
9108
9109 /* No cursor displayed or row invalidated => nothing to do on the
9110 screen. */
9111 if (w->phys_cursor_type == NO_CURSOR)
9112 goto mark_cursor_off;
9113
9114 /* VPOS >= active_glyphs->nrows means that window has been resized.
9115 Don't bother to erase the cursor. */
9116 if (vpos >= active_glyphs->nrows)
9117 goto mark_cursor_off;
9118
9119 /* If row containing cursor is marked invalid, there is nothing we
9120 can do. */
9121 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9122 if (!cursor_row->enabled_p)
9123 goto mark_cursor_off;
9124
9125 /* If row is completely invisible, don't attempt to delete a cursor which
9126 isn't there. This may happen if cursor is at top of window, and
9127 we switch to a buffer with a header line in that window. */
9128 if (cursor_row->visible_height <= 0)
9129 goto mark_cursor_off;
9130
9131 /* This can happen when the new row is shorter than the old one.
9132 In this case, either x_draw_glyphs or clear_end_of_line
9133 should have cleared the cursor. Note that we wouldn't be
9134 able to erase the cursor in this case because we don't have a
9135 cursor glyph at hand. */
9136 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9137 goto mark_cursor_off;
9138
9139 /* If the cursor is in the mouse face area, redisplay that when
9140 we clear the cursor. */
9141 if (! NILP (dpyinfo->mouse_face_window)
9142 && w == XWINDOW (dpyinfo->mouse_face_window)
9143 && (vpos > dpyinfo->mouse_face_beg_row
9144 || (vpos == dpyinfo->mouse_face_beg_row
9145 && hpos >= dpyinfo->mouse_face_beg_col))
9146 && (vpos < dpyinfo->mouse_face_end_row
9147 || (vpos == dpyinfo->mouse_face_end_row
9148 && hpos < dpyinfo->mouse_face_end_col))
9149 /* Don't redraw the cursor's spot in mouse face if it is at the
9150 end of a line (on a newline). The cursor appears there, but
9151 mouse highlighting does not. */
9152 && cursor_row->used[TEXT_AREA] > hpos)
9153 mouse_face_here_p = 1;
9154
9155 /* Maybe clear the display under the cursor. */
9156 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9157 {
9158 int x;
9159 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9160
9161 cursor_glyph = get_phys_cursor_glyph (w);
9162 if (cursor_glyph == NULL)
9163 goto mark_cursor_off;
9164
9165 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9166
9167 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9168 x,
9169 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9170 cursor_row->y)),
9171 cursor_glyph->pixel_width,
9172 cursor_row->visible_height,
9173 0);
9174 }
9175
9176 /* Erase the cursor by redrawing the character underneath it. */
9177 if (mouse_face_here_p)
9178 hl = DRAW_MOUSE_FACE;
9179 else
9180 hl = DRAW_NORMAL_TEXT;
9181 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9182
9183 mark_cursor_off:
9184 w->phys_cursor_on_p = 0;
9185 w->phys_cursor_type = NO_CURSOR;
9186 }
9187
9188
9189 /* Non-zero if physical cursor of window W is within mouse face. */
9190
9191 static int
9192 cursor_in_mouse_face_p (w)
9193 struct window *w;
9194 {
9195 struct mac_display_info *dpyinfo
9196 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9197 int in_mouse_face = 0;
9198
9199 if (WINDOWP (dpyinfo->mouse_face_window)
9200 && XWINDOW (dpyinfo->mouse_face_window) == w)
9201 {
9202 int hpos = w->phys_cursor.hpos;
9203 int vpos = w->phys_cursor.vpos;
9204
9205 if (vpos >= dpyinfo->mouse_face_beg_row
9206 && vpos <= dpyinfo->mouse_face_end_row
9207 && (vpos > dpyinfo->mouse_face_beg_row
9208 || hpos >= dpyinfo->mouse_face_beg_col)
9209 && (vpos < dpyinfo->mouse_face_end_row
9210 || hpos < dpyinfo->mouse_face_end_col
9211 || dpyinfo->mouse_face_past_end))
9212 in_mouse_face = 1;
9213 }
9214
9215 return in_mouse_face;
9216 }
9217
9218
9219 /* Display or clear cursor of window W. If ON is zero, clear the
9220 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9221 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9222
9223 void
9224 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9225 struct window *w;
9226 int on, hpos, vpos, x, y;
9227 {
9228 struct frame *f = XFRAME (w->frame);
9229 int new_cursor_type;
9230 int new_cursor_width;
9231 struct glyph_matrix *current_glyphs;
9232 struct glyph_row *glyph_row;
9233 struct glyph *glyph;
9234 int cursor_non_selected;
9235 int active_cursor = 1;
9236
9237 /* This is pointless on invisible frames, and dangerous on garbaged
9238 windows and frames; in the latter case, the frame or window may
9239 be in the midst of changing its size, and x and y may be off the
9240 window. */
9241 if (! FRAME_VISIBLE_P (f)
9242 || FRAME_GARBAGED_P (f)
9243 || vpos >= w->current_matrix->nrows
9244 || hpos >= w->current_matrix->matrix_w)
9245 return;
9246
9247 /* If cursor is off and we want it off, return quickly. */
9248 if (!on && !w->phys_cursor_on_p)
9249 return;
9250
9251 current_glyphs = w->current_matrix;
9252 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9253 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9254
9255 /* If cursor row is not enabled, we don't really know where to
9256 display the cursor. */
9257 if (!glyph_row->enabled_p)
9258 {
9259 w->phys_cursor_on_p = 0;
9260 return;
9261 }
9262
9263 xassert (interrupt_input_blocked);
9264
9265 /* Set new_cursor_type to the cursor we want to be displayed. In a
9266 mini-buffer window, we want the cursor only to appear if we are
9267 reading input from this window. For the selected window, we want
9268 the cursor type given by the frame parameter. If explicitly
9269 marked off, draw no cursor. In all other cases, we want a hollow
9270 box cursor. */
9271 cursor_non_selected
9272 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
9273 w->buffer));
9274 new_cursor_width = -1;
9275 if (cursor_in_echo_area
9276 && FRAME_HAS_MINIBUF_P (f)
9277 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
9278 {
9279 if (w == XWINDOW (echo_area_window))
9280 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9281 else
9282 {
9283 if (cursor_non_selected)
9284 new_cursor_type = HOLLOW_BOX_CURSOR;
9285 else
9286 new_cursor_type = NO_CURSOR;
9287 active_cursor = 0;
9288 }
9289 }
9290 else
9291 {
9292 if (f != FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame
9293 || w != XWINDOW (f->selected_window))
9294 {
9295 active_cursor = 0;
9296
9297 if (MINI_WINDOW_P (w)
9298 || !cursor_non_selected
9299 || NILP (XBUFFER (w->buffer)->cursor_type))
9300 new_cursor_type = NO_CURSOR;
9301 else
9302 new_cursor_type = HOLLOW_BOX_CURSOR;
9303 }
9304 else
9305 {
9306 struct buffer *b = XBUFFER (w->buffer);
9307
9308 if (EQ (b->cursor_type, Qt))
9309 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9310 else
9311 new_cursor_type = x_specified_cursor_type (b->cursor_type,
9312 &new_cursor_width);
9313 if (w->cursor_off_p)
9314 {
9315 if (new_cursor_type == FILLED_BOX_CURSOR)
9316 new_cursor_type = HOLLOW_BOX_CURSOR;
9317 else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
9318 new_cursor_width = 1;
9319 else
9320 new_cursor_type = NO_CURSOR;
9321 }
9322 }
9323 }
9324
9325 /* If cursor is currently being shown and we don't want it to be or
9326 it is in the wrong place, or the cursor type is not what we want,
9327 erase it. */
9328 if (w->phys_cursor_on_p
9329 && (!on
9330 || w->phys_cursor.x != x
9331 || w->phys_cursor.y != y
9332 || new_cursor_type != w->phys_cursor_type
9333 || (new_cursor_type == BAR_CURSOR
9334 && new_cursor_width != w->phys_cursor_width)))
9335 x_erase_phys_cursor (w);
9336
9337 /* If the cursor is now invisible and we want it to be visible,
9338 display it. */
9339 if (on && !w->phys_cursor_on_p)
9340 {
9341 w->phys_cursor_ascent = glyph_row->ascent;
9342 w->phys_cursor_height = glyph_row->height;
9343
9344 /* Set phys_cursor_.* before x_draw_.* is called because some
9345 of them may need the information. */
9346 w->phys_cursor.x = x;
9347 w->phys_cursor.y = glyph_row->y;
9348 w->phys_cursor.hpos = hpos;
9349 w->phys_cursor.vpos = vpos;
9350 w->phys_cursor_type = new_cursor_type;
9351 w->phys_cursor_width = new_cursor_width;
9352 w->phys_cursor_on_p = 1;
9353
9354 switch (new_cursor_type)
9355 {
9356 case HOLLOW_BOX_CURSOR:
9357 x_draw_hollow_cursor (w, glyph_row);
9358 break;
9359
9360 case FILLED_BOX_CURSOR:
9361 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9362 break;
9363
9364 case BAR_CURSOR:
9365 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9366 break;
9367
9368 case NO_CURSOR:
9369 break;
9370
9371 default:
9372 abort ();
9373 }
9374 }
9375 }
9376
9377
9378 /* Display the cursor on window W, or clear it. X and Y are window
9379 relative pixel coordinates. HPOS and VPOS are glyph matrix
9380 positions. If W is not the selected window, display a hollow
9381 cursor. ON non-zero means display the cursor at X, Y which
9382 correspond to HPOS, VPOS, otherwise it is cleared. */
9383
9384 void
9385 x_display_cursor (w, on, hpos, vpos, x, y)
9386 struct window *w;
9387 int on, hpos, vpos, x, y;
9388 {
9389 BLOCK_INPUT;
9390 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9391 UNBLOCK_INPUT;
9392 }
9393
9394
9395 /* Display the cursor on window W, or clear it, according to ON_P.
9396 Don't change the cursor's position. */
9397
9398 void
9399 x_update_cursor (f, on_p)
9400 struct frame *f;
9401 int on_p;
9402 {
9403 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9404 }
9405
9406
9407 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9408 in the window tree rooted at W. */
9409
9410 static void
9411 x_update_cursor_in_window_tree (w, on_p)
9412 struct window *w;
9413 int on_p;
9414 {
9415 while (w)
9416 {
9417 if (!NILP (w->hchild))
9418 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9419 else if (!NILP (w->vchild))
9420 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9421 else
9422 x_update_window_cursor (w, on_p);
9423
9424 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9425 }
9426 }
9427
9428
9429 /* Switch the display of W's cursor on or off, according to the value
9430 of ON. */
9431
9432 static void
9433 x_update_window_cursor (w, on)
9434 struct window *w;
9435 int on;
9436 {
9437 /* Don't update cursor in windows whose frame is in the process
9438 of being deleted. */
9439 if (w->current_matrix)
9440 {
9441 BLOCK_INPUT;
9442 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9443 w->phys_cursor.vpos, w->phys_cursor.x,
9444 w->phys_cursor.y);
9445 UNBLOCK_INPUT;
9446 }
9447 }
9448
9449
9450
9451 \f
9452 /* Icons. */
9453
9454 #if 0 /* MAC_TODO: no icon support yet. */
9455 int
9456 x_bitmap_icon (f, icon)
9457 struct frame *f;
9458 Lisp_Object icon;
9459 {
9460 HANDLE hicon;
9461
9462 if (FRAME_W32_WINDOW (f) == 0)
9463 return 1;
9464
9465 if (NILP (icon))
9466 hicon = LoadIcon (hinst, EMACS_CLASS);
9467 else if (STRINGP (icon))
9468 hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
9469 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9470 else if (SYMBOLP (icon))
9471 {
9472 LPCTSTR name;
9473
9474 if (EQ (icon, intern ("application")))
9475 name = (LPCTSTR) IDI_APPLICATION;
9476 else if (EQ (icon, intern ("hand")))
9477 name = (LPCTSTR) IDI_HAND;
9478 else if (EQ (icon, intern ("question")))
9479 name = (LPCTSTR) IDI_QUESTION;
9480 else if (EQ (icon, intern ("exclamation")))
9481 name = (LPCTSTR) IDI_EXCLAMATION;
9482 else if (EQ (icon, intern ("asterisk")))
9483 name = (LPCTSTR) IDI_ASTERISK;
9484 else if (EQ (icon, intern ("winlogo")))
9485 name = (LPCTSTR) IDI_WINLOGO;
9486 else
9487 return 1;
9488
9489 hicon = LoadIcon (NULL, name);
9490 }
9491 else
9492 return 1;
9493
9494 if (hicon == NULL)
9495 return 1;
9496
9497 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9498 (LPARAM) hicon);
9499
9500 return 0;
9501 }
9502 #endif /* MAC_TODO */
9503 \f
9504 /************************************************************************
9505 Handling X errors
9506 ************************************************************************/
9507
9508 /* Display Error Handling functions not used on W32. Listing them here
9509 helps diff stay in step when comparing w32term.c with xterm.c.
9510
9511 x_error_catcher (display, error)
9512 x_catch_errors (dpy)
9513 x_catch_errors_unwind (old_val)
9514 x_check_errors (dpy, format)
9515 x_had_errors_p (dpy)
9516 x_clear_errors (dpy)
9517 x_uncatch_errors (dpy, count)
9518 x_trace_wire ()
9519 x_connection_signal (signalnum)
9520 x_connection_closed (dpy, error_message)
9521 x_error_quitter (display, error)
9522 x_error_handler (display, error)
9523 x_io_error_quitter (display)
9524
9525 */
9526
9527 \f
9528 /* Changing the font of the frame. */
9529
9530 /* Give frame F the font named FONTNAME as its default font, and
9531 return the full name of that font. FONTNAME may be a wildcard
9532 pattern; in that case, we choose some font that fits the pattern.
9533 The return value shows which font we chose. */
9534
9535 Lisp_Object
9536 x_new_font (f, fontname)
9537 struct frame *f;
9538 register char *fontname;
9539 {
9540 struct font_info *fontp
9541 = FS_LOAD_FONT (f, 0, fontname, -1);
9542
9543 if (!fontp)
9544 return Qnil;
9545
9546 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9547 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9548 FRAME_FONTSET (f) = -1;
9549
9550 /* Compute the scroll bar width in character columns. */
9551 if (f->scroll_bar_pixel_width > 0)
9552 {
9553 int wid = FONT_WIDTH (FRAME_FONT (f));
9554 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9555 }
9556 else
9557 {
9558 int wid = FONT_WIDTH (FRAME_FONT (f));
9559 f->scroll_bar_cols = (14 + wid - 1) / wid;
9560 }
9561
9562 /* Now make the frame display the given font. */
9563 if (FRAME_MAC_WINDOW (f) != 0)
9564 {
9565 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9566 f->output_data.mac->font);
9567 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9568 f->output_data.mac->font);
9569 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9570 f->output_data.mac->font);
9571
9572 frame_update_line_height (f);
9573 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9574 x_set_window_size (f, 0, f->width, f->height);
9575 }
9576 else
9577 /* If we are setting a new frame's font for the first time,
9578 there are no faces yet, so this font's height is the line height. */
9579 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
9580
9581 return build_string (fontp->full_name);
9582 }
9583 \f
9584 /* Give frame F the fontset named FONTSETNAME as its default font, and
9585 return the full name of that fontset. FONTSETNAME may be a wildcard
9586 pattern; in that case, we choose some fontset that fits the pattern.
9587 The return value shows which fontset we chose. */
9588
9589 Lisp_Object
9590 x_new_fontset (f, fontsetname)
9591 struct frame *f;
9592 char *fontsetname;
9593 {
9594 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9595 Lisp_Object result;
9596
9597 if (fontset < 0)
9598 return Qnil;
9599
9600 if (FRAME_FONTSET (f) == fontset)
9601 /* This fontset is already set in frame F. There's nothing more
9602 to do. */
9603 return fontset_name (fontset);
9604
9605 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
9606
9607 if (!STRINGP (result))
9608 /* Can't load ASCII font. */
9609 return Qnil;
9610
9611 /* Since x_new_font doesn't update any fontset information, do it now. */
9612 FRAME_FONTSET(f) = fontset;
9613
9614 return build_string (fontsetname);
9615 }
9616
9617 /* Compute actual fringe widths */
9618
9619 void
9620 x_compute_fringe_widths (f, redraw)
9621 struct frame *f;
9622 int redraw;
9623 {
9624 int o_left = f->output_data.mac->left_fringe_width;
9625 int o_right = f->output_data.mac->right_fringe_width;
9626 int o_cols = f->output_data.mac->fringe_cols;
9627
9628 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9629 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9630 int left_fringe_width, right_fringe_width;
9631
9632 if (!NILP (left_fringe))
9633 left_fringe = Fcdr (left_fringe);
9634 if (!NILP (right_fringe))
9635 right_fringe = Fcdr (right_fringe);
9636
9637 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9638 XINT (left_fringe));
9639 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9640 XINT (right_fringe));
9641
9642 if (left_fringe_width || right_fringe_width)
9643 {
9644 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9645 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9646 int conf_wid = left_wid + right_wid;
9647 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9648 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9649 int real_wid = cols * font_wid;
9650 if (left_wid && right_wid)
9651 {
9652 if (left_fringe_width < 0)
9653 {
9654 /* Left fringe width is fixed, adjust right fringe if necessary */
9655 f->output_data.mac->left_fringe_width = left_wid;
9656 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9657 }
9658 else if (right_fringe_width < 0)
9659 {
9660 /* Right fringe width is fixed, adjust left fringe if necessary */
9661 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9662 f->output_data.mac->right_fringe_width = right_wid;
9663 }
9664 else
9665 {
9666 /* Adjust both fringes with an equal amount.
9667 Note that we are doing integer arithmetic here, so don't
9668 lose a pixel if the total width is an odd number. */
9669 int fill = real_wid - conf_wid;
9670 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9671 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9672 }
9673 }
9674 else if (left_fringe_width)
9675 {
9676 f->output_data.mac->left_fringe_width = real_wid;
9677 f->output_data.mac->right_fringe_width = 0;
9678 }
9679 else
9680 {
9681 f->output_data.mac->left_fringe_width = 0;
9682 f->output_data.mac->right_fringe_width = real_wid;
9683 }
9684 f->output_data.mac->fringe_cols = cols;
9685 f->output_data.mac->fringes_extra = real_wid;
9686 }
9687 else
9688 {
9689 f->output_data.mac->left_fringe_width = 0;
9690 f->output_data.mac->right_fringe_width = 0;
9691 f->output_data.mac->fringe_cols = 0;
9692 f->output_data.mac->fringes_extra = 0;
9693 }
9694
9695 if (redraw && FRAME_VISIBLE_P (f))
9696 if (o_left != f->output_data.mac->left_fringe_width ||
9697 o_right != f->output_data.mac->right_fringe_width ||
9698 o_cols != f->output_data.mac->fringe_cols)
9699 redraw_frame (f);
9700 }
9701 \f
9702 /***********************************************************************
9703 TODO: W32 Input Methods
9704 ***********************************************************************/
9705 /* Listing missing functions from xterm.c helps diff stay in step.
9706
9707 xim_destroy_callback (xim, client_data, call_data)
9708 xim_open_dpy (dpyinfo, resource_name)
9709 struct xim_inst_t
9710 xim_instantiate_callback (display, client_data, call_data)
9711 xim_initialize (dpyinfo, resource_name)
9712 xim_close_dpy (dpyinfo)
9713
9714 */
9715
9716 \f
9717 /* Calculate the absolute position in frame F
9718 from its current recorded position values and gravity. */
9719
9720 void
9721 x_calc_absolute_position (f)
9722 struct frame *f;
9723 {
9724 Point pt;
9725 int flags = f->output_data.mac->size_hint_flags;
9726
9727 pt.h = pt.v = 0;
9728
9729 /* Find the position of the outside upper-left corner of
9730 the inner window, with respect to the outer window. */
9731 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9732 {
9733 GrafPtr savePort;
9734 GetPort (&savePort);
9735
9736 #if TARGET_API_MAC_CARBON
9737 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9738 #else
9739 SetPort (FRAME_MAC_WINDOW (f));
9740 #endif
9741
9742 #if TARGET_API_MAC_CARBON
9743 {
9744 Rect r;
9745
9746 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9747 SetPt(&pt, r.left, r.top);
9748 }
9749 #else /* not TARGET_API_MAC_CARBON */
9750 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
9751 #endif /* not TARGET_API_MAC_CARBON */
9752 LocalToGlobal (&pt);
9753 SetPort (savePort);
9754 }
9755
9756 /* Treat negative positions as relative to the leftmost bottommost
9757 position that fits on the screen. */
9758 if (flags & XNegative)
9759 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9760 - 2 * f->output_data.mac->border_width - pt.h
9761 - PIXEL_WIDTH (f)
9762 + f->output_data.mac->left_pos);
9763 /* NTEMACS_TODO: Subtract menubar height? */
9764 if (flags & YNegative)
9765 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9766 - 2 * f->output_data.mac->border_width - pt.v
9767 - PIXEL_HEIGHT (f)
9768 + f->output_data.mac->top_pos);
9769 /* The left_pos and top_pos
9770 are now relative to the top and left screen edges,
9771 so the flags should correspond. */
9772 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9773 }
9774
9775 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9776 to really change the position, and 0 when calling from
9777 x_make_frame_visible (in that case, XOFF and YOFF are the current
9778 position values). It is -1 when calling from x_set_frame_parameters,
9779 which means, do adjust for borders but don't change the gravity. */
9780
9781 void
9782 x_set_offset (f, xoff, yoff, change_gravity)
9783 struct frame *f;
9784 register int xoff, yoff;
9785 int change_gravity;
9786 {
9787 int modified_top, modified_left;
9788
9789 if (change_gravity > 0)
9790 {
9791 f->output_data.mac->top_pos = yoff;
9792 f->output_data.mac->left_pos = xoff;
9793 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9794 if (xoff < 0)
9795 f->output_data.mac->size_hint_flags |= XNegative;
9796 if (yoff < 0)
9797 f->output_data.mac->size_hint_flags |= YNegative;
9798 f->output_data.mac->win_gravity = NorthWestGravity;
9799 }
9800 x_calc_absolute_position (f);
9801
9802 BLOCK_INPUT;
9803 x_wm_set_size_hint (f, (long) 0, 0);
9804
9805 modified_left = f->output_data.mac->left_pos;
9806 modified_top = f->output_data.mac->top_pos;
9807
9808 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9809 modified_top + 42, false);
9810
9811 UNBLOCK_INPUT;
9812 }
9813
9814 /* Call this to change the size of frame F's x-window.
9815 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9816 for this size change and subsequent size changes.
9817 Otherwise we leave the window gravity unchanged. */
9818
9819 void
9820 x_set_window_size (f, change_gravity, cols, rows)
9821 struct frame *f;
9822 int change_gravity;
9823 int cols, rows;
9824 {
9825 int pixelwidth, pixelheight;
9826
9827 BLOCK_INPUT;
9828
9829 check_frame_size (f, &rows, &cols);
9830 f->output_data.mac->vertical_scroll_bar_extra
9831 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9832 ? 0
9833 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
9834
9835 x_compute_fringe_widths (f, 0);
9836
9837 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9838 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9839
9840 f->output_data.mac->win_gravity = NorthWestGravity;
9841 x_wm_set_size_hint (f, (long) 0, 0);
9842
9843 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9844
9845 /* Now, strictly speaking, we can't be sure that this is accurate,
9846 but the window manager will get around to dealing with the size
9847 change request eventually, and we'll hear how it went when the
9848 ConfigureNotify event gets here.
9849
9850 We could just not bother storing any of this information here,
9851 and let the ConfigureNotify event set everything up, but that
9852 might be kind of confusing to the Lisp code, since size changes
9853 wouldn't be reported in the frame parameters until some random
9854 point in the future when the ConfigureNotify event arrives.
9855
9856 We pass 1 for DELAY since we can't run Lisp code inside of
9857 a BLOCK_INPUT. */
9858 change_frame_size (f, rows, cols, 0, 1, 0);
9859 PIXEL_WIDTH (f) = pixelwidth;
9860 PIXEL_HEIGHT (f) = pixelheight;
9861
9862 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9863 receive in the ConfigureNotify event; if we get what we asked
9864 for, then the event won't cause the screen to become garbaged, so
9865 we have to make sure to do it here. */
9866 SET_FRAME_GARBAGED (f);
9867
9868 XFlush (FRAME_X_DISPLAY (f));
9869
9870 /* If cursor was outside the new size, mark it as off. */
9871 mark_window_cursors_off (XWINDOW (f->root_window));
9872
9873 /* Clear out any recollection of where the mouse highlighting was,
9874 since it might be in a place that's outside the new frame size.
9875 Actually checking whether it is outside is a pain in the neck,
9876 so don't try--just let the highlighting be done afresh with new size. */
9877 cancel_mouse_face (f);
9878
9879 UNBLOCK_INPUT;
9880 }
9881 \f
9882 /* Mouse warping. */
9883
9884 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9885
9886 void
9887 x_set_mouse_position (f, x, y)
9888 struct frame *f;
9889 int x, y;
9890 {
9891 int pix_x, pix_y;
9892
9893 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9894 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9895
9896 if (pix_x < 0) pix_x = 0;
9897 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9898
9899 if (pix_y < 0) pix_y = 0;
9900 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9901
9902 x_set_mouse_pixel_position (f, pix_x, pix_y);
9903 }
9904
9905 void
9906 x_set_mouse_pixel_position (f, pix_x, pix_y)
9907 struct frame *f;
9908 int pix_x, pix_y;
9909 {
9910 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9911 BLOCK_INPUT;
9912
9913 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9914 0, 0, 0, 0, pix_x, pix_y);
9915 UNBLOCK_INPUT;
9916 #endif
9917 }
9918
9919 \f
9920 /* focus shifting, raising and lowering. */
9921
9922 void
9923 x_focus_on_frame (f)
9924 struct frame *f;
9925 {
9926 #if 0 /* This proves to be unpleasant. */
9927 x_raise_frame (f);
9928 #endif
9929 #if 0
9930 /* I don't think that the ICCCM allows programs to do things like this
9931 without the interaction of the window manager. Whatever you end up
9932 doing with this code, do it to x_unfocus_frame too. */
9933 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9934 RevertToPointerRoot, CurrentTime);
9935 #endif /* ! 0 */
9936 }
9937
9938 void
9939 x_unfocus_frame (f)
9940 struct frame *f;
9941 {
9942 }
9943
9944 /* Raise frame F. */
9945 void
9946 x_raise_frame (f)
9947 struct frame *f;
9948 {
9949 if (f->async_visible)
9950 SelectWindow (FRAME_MAC_WINDOW (f));
9951 }
9952
9953 /* Lower frame F. */
9954 void
9955 x_lower_frame (f)
9956 struct frame *f;
9957 {
9958 if (f->async_visible)
9959 SendBehind (FRAME_MAC_WINDOW (f), nil);
9960 }
9961
9962 static void
9963 XTframe_raise_lower (f, raise_flag)
9964 FRAME_PTR f;
9965 int raise_flag;
9966 {
9967 if (raise_flag)
9968 x_raise_frame (f);
9969 else
9970 x_lower_frame (f);
9971 }
9972 \f
9973 /* Change of visibility. */
9974
9975 /* This tries to wait until the frame is really visible.
9976 However, if the window manager asks the user where to position
9977 the frame, this will return before the user finishes doing that.
9978 The frame will not actually be visible at that time,
9979 but it will become visible later when the window manager
9980 finishes with it. */
9981
9982 void
9983 x_make_frame_visible (f)
9984 struct frame *f;
9985 {
9986 Lisp_Object type;
9987 int original_top, original_left;
9988
9989 BLOCK_INPUT;
9990
9991 if (! FRAME_VISIBLE_P (f))
9992 {
9993 /* We test FRAME_GARBAGED_P here to make sure we don't
9994 call x_set_offset a second time
9995 if we get to x_make_frame_visible a second time
9996 before the window gets really visible. */
9997 if (! FRAME_ICONIFIED_P (f)
9998 && ! f->output_data.mac->asked_for_visible)
9999 x_set_offset (f, f->output_data.mac->left_pos,
10000 f->output_data.mac->top_pos, 0);
10001
10002 f->output_data.mac->asked_for_visible = 1;
10003
10004 ShowWindow (FRAME_MAC_WINDOW (f));
10005 }
10006
10007 XFlush (FRAME_MAC_DISPLAY (f));
10008
10009 #if 0 /* MAC_TODO */
10010 /* Synchronize to ensure Emacs knows the frame is visible
10011 before we do anything else. We do this loop with input not blocked
10012 so that incoming events are handled. */
10013 {
10014 Lisp_Object frame;
10015 int count;
10016
10017 /* This must come after we set COUNT. */
10018 UNBLOCK_INPUT;
10019
10020 XSETFRAME (frame, f);
10021
10022 /* Wait until the frame is visible. Process X events until a
10023 MapNotify event has been seen, or until we think we won't get a
10024 MapNotify at all.. */
10025 for (count = input_signal_count + 10;
10026 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10027 {
10028 /* Force processing of queued events. */
10029 x_sync (f);
10030
10031 /* Machines that do polling rather than SIGIO have been
10032 observed to go into a busy-wait here. So we'll fake an
10033 alarm signal to let the handler know that there's something
10034 to be read. We used to raise a real alarm, but it seems
10035 that the handler isn't always enabled here. This is
10036 probably a bug. */
10037 if (input_polling_used ())
10038 {
10039 /* It could be confusing if a real alarm arrives while
10040 processing the fake one. Turn it off and let the
10041 handler reset it. */
10042 extern void poll_for_input_1 P_ ((void));
10043 int old_poll_suppress_count = poll_suppress_count;
10044 poll_suppress_count = 1;
10045 poll_for_input_1 ();
10046 poll_suppress_count = old_poll_suppress_count;
10047 }
10048
10049 /* See if a MapNotify event has been processed. */
10050 FRAME_SAMPLE_VISIBILITY (f);
10051 }
10052 }
10053 #endif /* MAC_TODO */
10054 }
10055
10056 /* Change from mapped state to withdrawn state. */
10057
10058 /* Make the frame visible (mapped and not iconified). */
10059
10060 void
10061 x_make_frame_invisible (f)
10062 struct frame *f;
10063 {
10064 /* Don't keep the highlight on an invisible frame. */
10065 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10066 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10067
10068 BLOCK_INPUT;
10069
10070 HideWindow (FRAME_MAC_WINDOW (f));
10071
10072 /* We can't distinguish this from iconification
10073 just by the event that we get from the server.
10074 So we can't win using the usual strategy of letting
10075 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10076 and synchronize with the server to make sure we agree. */
10077 f->visible = 0;
10078 FRAME_ICONIFIED_P (f) = 0;
10079 f->async_visible = 0;
10080 f->async_iconified = 0;
10081
10082 UNBLOCK_INPUT;
10083 }
10084
10085 /* Change window state from mapped to iconified. */
10086
10087 void
10088 x_iconify_frame (f)
10089 struct frame *f;
10090 {
10091 #if 0 /* MAC_TODO: really no iconify on Mac */
10092 int result;
10093 Lisp_Object type;
10094
10095 /* Don't keep the highlight on an invisible frame. */
10096 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
10097 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
10098
10099 if (f->async_iconified)
10100 return;
10101
10102 BLOCK_INPUT;
10103
10104 FRAME_SAMPLE_VISIBILITY (f);
10105
10106 type = x_icon_type (f);
10107 if (!NILP (type))
10108 x_bitmap_icon (f, type);
10109
10110 #ifdef USE_X_TOOLKIT
10111
10112 if (! FRAME_VISIBLE_P (f))
10113 {
10114 if (! EQ (Vx_no_window_manager, Qt))
10115 x_wm_set_window_state (f, IconicState);
10116 /* This was XtPopup, but that did nothing for an iconified frame. */
10117 XtMapWidget (f->output_data.x->widget);
10118 /* The server won't give us any event to indicate
10119 that an invisible frame was changed to an icon,
10120 so we have to record it here. */
10121 f->iconified = 1;
10122 f->visible = 1;
10123 f->async_iconified = 1;
10124 f->async_visible = 0;
10125 UNBLOCK_INPUT;
10126 return;
10127 }
10128
10129 result = XIconifyWindow (FRAME_X_DISPLAY (f),
10130 XtWindow (f->output_data.x->widget),
10131 DefaultScreen (FRAME_X_DISPLAY (f)));
10132 UNBLOCK_INPUT;
10133
10134 if (!result)
10135 error ("Can't notify window manager of iconification");
10136
10137 f->async_iconified = 1;
10138 f->async_visible = 0;
10139
10140
10141 BLOCK_INPUT;
10142 XFlush (FRAME_X_DISPLAY (f));
10143 UNBLOCK_INPUT;
10144 #else /* not USE_X_TOOLKIT */
10145
10146 /* Make sure the X server knows where the window should be positioned,
10147 in case the user deiconifies with the window manager. */
10148 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
10149 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
10150
10151 /* Since we don't know which revision of X we're running, we'll use both
10152 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
10153
10154 /* X11R4: send a ClientMessage to the window manager using the
10155 WM_CHANGE_STATE type. */
10156 {
10157 XEvent message;
10158
10159 message.xclient.window = FRAME_X_WINDOW (f);
10160 message.xclient.type = ClientMessage;
10161 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
10162 message.xclient.format = 32;
10163 message.xclient.data.l[0] = IconicState;
10164
10165 if (! XSendEvent (FRAME_X_DISPLAY (f),
10166 DefaultRootWindow (FRAME_X_DISPLAY (f)),
10167 False,
10168 SubstructureRedirectMask | SubstructureNotifyMask,
10169 &message))
10170 {
10171 UNBLOCK_INPUT_RESIGNAL;
10172 error ("Can't notify window manager of iconification");
10173 }
10174 }
10175
10176 /* X11R3: set the initial_state field of the window manager hints to
10177 IconicState. */
10178 x_wm_set_window_state (f, IconicState);
10179
10180 if (!FRAME_VISIBLE_P (f))
10181 {
10182 /* If the frame was withdrawn, before, we must map it. */
10183 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10184 }
10185
10186 f->async_iconified = 1;
10187 f->async_visible = 0;
10188
10189 XFlush (FRAME_X_DISPLAY (f));
10190 UNBLOCK_INPUT;
10191 #endif /* not USE_X_TOOLKIT */
10192 #endif /* MAC_TODO */
10193 }
10194
10195 \f
10196 /* Destroy the X window of frame F. */
10197
10198 void
10199 x_destroy_window (f)
10200 struct frame *f;
10201 {
10202 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10203
10204 BLOCK_INPUT;
10205
10206 DisposeWindow (FRAME_MAC_WINDOW (f));
10207
10208 free_frame_menubar (f);
10209 free_frame_faces (f);
10210
10211 xfree (f->output_data.mac);
10212 f->output_data.mac = 0;
10213 if (f == dpyinfo->x_focus_frame)
10214 dpyinfo->x_focus_frame = 0;
10215 if (f == dpyinfo->x_focus_event_frame)
10216 dpyinfo->x_focus_event_frame = 0;
10217 if (f == dpyinfo->x_highlight_frame)
10218 dpyinfo->x_highlight_frame = 0;
10219
10220 dpyinfo->reference_count--;
10221
10222 if (f == dpyinfo->mouse_face_mouse_frame)
10223 {
10224 dpyinfo->mouse_face_beg_row
10225 = dpyinfo->mouse_face_beg_col = -1;
10226 dpyinfo->mouse_face_end_row
10227 = dpyinfo->mouse_face_end_col = -1;
10228 dpyinfo->mouse_face_window = Qnil;
10229 dpyinfo->mouse_face_deferred_gc = 0;
10230 dpyinfo->mouse_face_mouse_frame = 0;
10231 }
10232
10233 UNBLOCK_INPUT;
10234 }
10235 \f
10236 /* Setting window manager hints. */
10237
10238 /* Set the normal size hints for the window manager, for frame F.
10239 FLAGS is the flags word to use--or 0 meaning preserve the flags
10240 that the window now has.
10241 If USER_POSITION is nonzero, we set the USPosition
10242 flag (this is useful when FLAGS is 0). */
10243 void
10244 x_wm_set_size_hint (f, flags, user_position)
10245 struct frame *f;
10246 long flags;
10247 int user_position;
10248 {
10249 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
10250 XSizeHints size_hints;
10251
10252 #ifdef USE_X_TOOLKIT
10253 Arg al[2];
10254 int ac = 0;
10255 Dimension widget_width, widget_height;
10256 Window window = XtWindow (f->output_data.x->widget);
10257 #else /* not USE_X_TOOLKIT */
10258 Window window = FRAME_X_WINDOW (f);
10259 #endif /* not USE_X_TOOLKIT */
10260
10261 /* Setting PMaxSize caused various problems. */
10262 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10263
10264 size_hints.x = f->output_data.x->left_pos;
10265 size_hints.y = f->output_data.x->top_pos;
10266
10267 #ifdef USE_X_TOOLKIT
10268 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10269 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10270 XtGetValues (f->output_data.x->widget, al, ac);
10271 size_hints.height = widget_height;
10272 size_hints.width = widget_width;
10273 #else /* not USE_X_TOOLKIT */
10274 size_hints.height = PIXEL_HEIGHT (f);
10275 size_hints.width = PIXEL_WIDTH (f);
10276 #endif /* not USE_X_TOOLKIT */
10277
10278 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10279 size_hints.height_inc = f->output_data.x->line_height;
10280 size_hints.max_width
10281 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10282 size_hints.max_height
10283 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10284
10285 /* Calculate the base and minimum sizes.
10286
10287 (When we use the X toolkit, we don't do it here.
10288 Instead we copy the values that the widgets are using, below.) */
10289 #ifndef USE_X_TOOLKIT
10290 {
10291 int base_width, base_height;
10292 int min_rows = 0, min_cols = 0;
10293
10294 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10295 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10296
10297 check_frame_size (f, &min_rows, &min_cols);
10298
10299 /* The window manager uses the base width hints to calculate the
10300 current number of rows and columns in the frame while
10301 resizing; min_width and min_height aren't useful for this
10302 purpose, since they might not give the dimensions for a
10303 zero-row, zero-column frame.
10304
10305 We use the base_width and base_height members if we have
10306 them; otherwise, we set the min_width and min_height members
10307 to the size for a zero x zero frame. */
10308
10309 #ifdef HAVE_X11R4
10310 size_hints.flags |= PBaseSize;
10311 size_hints.base_width = base_width;
10312 size_hints.base_height = base_height;
10313 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10314 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10315 #else
10316 size_hints.min_width = base_width;
10317 size_hints.min_height = base_height;
10318 #endif
10319 }
10320
10321 /* If we don't need the old flags, we don't need the old hint at all. */
10322 if (flags)
10323 {
10324 size_hints.flags |= flags;
10325 goto no_read;
10326 }
10327 #endif /* not USE_X_TOOLKIT */
10328
10329 {
10330 XSizeHints hints; /* Sometimes I hate X Windows... */
10331 long supplied_return;
10332 int value;
10333
10334 #ifdef HAVE_X11R4
10335 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10336 &supplied_return);
10337 #else
10338 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10339 #endif
10340
10341 #ifdef USE_X_TOOLKIT
10342 size_hints.base_height = hints.base_height;
10343 size_hints.base_width = hints.base_width;
10344 size_hints.min_height = hints.min_height;
10345 size_hints.min_width = hints.min_width;
10346 #endif
10347
10348 if (flags)
10349 size_hints.flags |= flags;
10350 else
10351 {
10352 if (value == 0)
10353 hints.flags = 0;
10354 if (hints.flags & PSize)
10355 size_hints.flags |= PSize;
10356 if (hints.flags & PPosition)
10357 size_hints.flags |= PPosition;
10358 if (hints.flags & USPosition)
10359 size_hints.flags |= USPosition;
10360 if (hints.flags & USSize)
10361 size_hints.flags |= USSize;
10362 }
10363 }
10364
10365 #ifndef USE_X_TOOLKIT
10366 no_read:
10367 #endif
10368
10369 #ifdef PWinGravity
10370 size_hints.win_gravity = f->output_data.x->win_gravity;
10371 size_hints.flags |= PWinGravity;
10372
10373 if (user_position)
10374 {
10375 size_hints.flags &= ~ PPosition;
10376 size_hints.flags |= USPosition;
10377 }
10378 #endif /* PWinGravity */
10379
10380 #ifdef HAVE_X11R4
10381 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10382 #else
10383 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10384 #endif
10385 #endif /* MAC_TODO */
10386 }
10387
10388 #if 0 /* MAC_TODO: hide application instead of iconify? */
10389 /* Used for IconicState or NormalState */
10390
10391 void
10392 x_wm_set_window_state (f, state)
10393 struct frame *f;
10394 int state;
10395 {
10396 #ifdef USE_X_TOOLKIT
10397 Arg al[1];
10398
10399 XtSetArg (al[0], XtNinitialState, state);
10400 XtSetValues (f->output_data.x->widget, al, 1);
10401 #else /* not USE_X_TOOLKIT */
10402 Window window = FRAME_X_WINDOW (f);
10403
10404 f->output_data.x->wm_hints.flags |= StateHint;
10405 f->output_data.x->wm_hints.initial_state = state;
10406
10407 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10408 #endif /* not USE_X_TOOLKIT */
10409 }
10410
10411 void
10412 x_wm_set_icon_pixmap (f, pixmap_id)
10413 struct frame *f;
10414 int pixmap_id;
10415 {
10416 Pixmap icon_pixmap;
10417
10418 #ifndef USE_X_TOOLKIT
10419 Window window = FRAME_X_WINDOW (f);
10420 #endif
10421
10422 if (pixmap_id > 0)
10423 {
10424 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10425 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10426 }
10427 else
10428 {
10429 /* It seems there is no way to turn off use of an icon pixmap.
10430 The following line does it, only if no icon has yet been created,
10431 for some window managers. But with mwm it crashes.
10432 Some people say it should clear the IconPixmapHint bit in this case,
10433 but that doesn't work, and the X consortium said it isn't the
10434 right thing at all. Since there is no way to win,
10435 best to explicitly give up. */
10436 #if 0
10437 f->output_data.x->wm_hints.icon_pixmap = None;
10438 #else
10439 return;
10440 #endif
10441 }
10442
10443 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10444
10445 {
10446 Arg al[1];
10447 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10448 XtSetValues (f->output_data.x->widget, al, 1);
10449 }
10450
10451 #else /* not USE_X_TOOLKIT */
10452
10453 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10454 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10455
10456 #endif /* not USE_X_TOOLKIT */
10457 }
10458
10459 #endif /* MAC_TODO */
10460
10461 void
10462 x_wm_set_icon_position (f, icon_x, icon_y)
10463 struct frame *f;
10464 int icon_x, icon_y;
10465 {
10466 #if 0 /* MAC_TODO: no icons on Mac */
10467 #ifdef USE_X_TOOLKIT
10468 Window window = XtWindow (f->output_data.x->widget);
10469 #else
10470 Window window = FRAME_X_WINDOW (f);
10471 #endif
10472
10473 f->output_data.x->wm_hints.flags |= IconPositionHint;
10474 f->output_data.x->wm_hints.icon_x = icon_x;
10475 f->output_data.x->wm_hints.icon_y = icon_y;
10476
10477 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10478 #endif /* MAC_TODO */
10479 }
10480
10481 \f
10482 /***********************************************************************
10483 Fonts
10484 ***********************************************************************/
10485
10486 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10487
10488 struct font_info *
10489 x_get_font_info (f, font_idx)
10490 FRAME_PTR f;
10491 int font_idx;
10492 {
10493 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10494 }
10495
10496 /* the global font name table */
10497 char **font_name_table = NULL;
10498 int font_name_table_size = 0;
10499 int font_name_count = 0;
10500
10501 /* compare two strings ignoring case */
10502 static int
10503 stricmp (const char *s, const char *t)
10504 {
10505 for ( ; tolower (*s) == tolower (*t); s++, t++)
10506 if (*s == '\0')
10507 return 0;
10508 return tolower (*s) - tolower (*t);
10509 }
10510
10511 /* compare two strings ignoring case and handling wildcard */
10512 static int
10513 wildstrieq (char *s1, char *s2)
10514 {
10515 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10516 return true;
10517
10518 return stricmp (s1, s2) == 0;
10519 }
10520
10521 /* Assume parameter 1 is fully qualified, no wildcards. */
10522 static int
10523 mac_font_pattern_match (fontname, pattern)
10524 char * fontname;
10525 char * pattern;
10526 {
10527 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
10528 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10529 char *ptr;
10530
10531 /* Copy fontname so we can modify it during comparison. */
10532 strcpy (font_name_copy, fontname);
10533
10534 ptr = regex;
10535 *ptr++ = '^';
10536
10537 /* Turn pattern into a regexp and do a regexp match. */
10538 for (; *pattern; pattern++)
10539 {
10540 if (*pattern == '?')
10541 *ptr++ = '.';
10542 else if (*pattern == '*')
10543 {
10544 *ptr++ = '.';
10545 *ptr++ = '*';
10546 }
10547 else
10548 *ptr++ = *pattern;
10549 }
10550 *ptr = '$';
10551 *(ptr + 1) = '\0';
10552
10553 return (fast_c_string_match_ignore_case (build_string (regex),
10554 font_name_copy) >= 0);
10555 }
10556
10557 /* Two font specs are considered to match if their foundry, family,
10558 weight, slant, and charset match. */
10559 static int
10560 mac_font_match (char *mf, char *xf)
10561 {
10562 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10563 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10564
10565 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10566 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10567 return mac_font_pattern_match (mf, xf);
10568
10569 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10570 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10571 return mac_font_pattern_match (mf, xf);
10572
10573 return (wildstrieq (m_foundry, x_foundry)
10574 && wildstrieq (m_family, x_family)
10575 && wildstrieq (m_weight, x_weight)
10576 && wildstrieq (m_slant, x_slant)
10577 && wildstrieq (m_charset, x_charset))
10578 || mac_font_pattern_match (mf, xf);
10579 }
10580
10581
10582 static char *
10583 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10584 {
10585 char foundry[32], family[32], cs[32];
10586 char xf[255], *result, *p;
10587
10588 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10589 {
10590 strcpy(foundry, "Apple");
10591 strcpy(family, name);
10592
10593 switch (scriptcode)
10594 {
10595 case smTradChinese:
10596 strcpy(cs, "big5-0");
10597 break;
10598 case smSimpChinese:
10599 strcpy(cs, "gb2312.1980-0");
10600 break;
10601 case smJapanese:
10602 strcpy(cs, "jisx0208.1983-sjis");
10603 break;
10604 case -smJapanese:
10605 /* Each Apple Japanese font is entered into the font table
10606 twice: once as a jisx0208.1983-sjis font and once as a
10607 jisx0201.1976-0 font. The latter can be used to display
10608 the ascii charset and katakana-jisx0201 charset. A
10609 negative script code signals that the name of this latter
10610 font is being built. */
10611 strcpy(cs, "jisx0201.1976-0");
10612 break;
10613 case smKorean:
10614 strcpy(cs, "ksc5601.1989-0");
10615 break;
10616 default:
10617 strcpy(cs, "mac-roman");
10618 break;
10619 }
10620 }
10621
10622 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10623 foundry, family, style & bold ? "bold" : "medium",
10624 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10625
10626 result = (char *) xmalloc (strlen (xf) + 1);
10627 strcpy (result, xf);
10628 for (p = result; *p; p++)
10629 *p = tolower(*p);
10630 return result;
10631 }
10632
10633
10634 /* Convert an X font spec to the corresponding mac font name, which
10635 can then be passed to GetFNum after conversion to a Pascal string.
10636 For ordinary Mac fonts, this should just be their names, like
10637 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10638 collection contain their charset designation in their names, like
10639 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10640 names are handled accordingly. */
10641 static void
10642 x_font_name_to_mac_font_name (char *xf, char *mf)
10643 {
10644 char foundry[32], family[32], weight[20], slant[2], cs[32];
10645
10646 strcpy (mf, "");
10647
10648 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10649 foundry, family, weight, slant, cs) != 5 &&
10650 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10651 foundry, family, weight, slant, cs) != 5)
10652 return;
10653
10654 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
10655 || strcmp (cs, "jisx0208.1983-sjis") == 0
10656 || strcmp (cs, "jisx0201.1976-0") == 0
10657 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
10658 strcpy(mf, family);
10659 else
10660 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10661 }
10662
10663
10664 static void
10665 add_font_name_table_entry (char *font_name)
10666 {
10667 if (font_name_table_size == 0)
10668 {
10669 font_name_table_size = 16;
10670 font_name_table = (char **)
10671 xmalloc (font_name_table_size * sizeof (char *));
10672 }
10673 else if (font_name_count + 1 >= font_name_table_size)
10674 {
10675 font_name_table_size += 16;
10676 font_name_table = (char **)
10677 xrealloc (font_name_table,
10678 font_name_table_size * sizeof (char *));
10679 }
10680
10681 font_name_table[font_name_count++] = font_name;
10682 }
10683
10684 /* Sets up the table font_name_table to contain the list of all fonts
10685 in the system the first time the table is used so that the Resource
10686 Manager need not be accessed every time this information is
10687 needed. */
10688
10689 static void
10690 init_font_name_table ()
10691 {
10692 #if TARGET_API_MAC_CARBON
10693 SInt32 sv;
10694
10695 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10696 {
10697 FMFontFamilyIterator ffi;
10698 FMFontFamilyInstanceIterator ffii;
10699 FMFontFamily ff;
10700
10701 /* Create a dummy instance iterator here to avoid creating and
10702 destroying it in the loop. */
10703 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10704 return;
10705 /* Create an iterator to enumerate the font families. */
10706 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10707 != noErr)
10708 {
10709 FMDisposeFontFamilyInstanceIterator (&ffii);
10710 return;
10711 }
10712
10713 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10714 {
10715 Str255 name;
10716 FMFont font;
10717 FMFontStyle style;
10718 FMFontSize size;
10719 SInt16 sc;
10720
10721 if (FMGetFontFamilyName (ff, name) != noErr)
10722 break;
10723 p2cstr (name);
10724
10725 sc = FontToScript (ff);
10726
10727 /* Point the instance iterator at the current font family. */
10728 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10729 break;
10730
10731 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10732 == noErr)
10733 if (size == 0)
10734 {
10735 add_font_name_table_entry (mac_to_x_fontname (name, size,
10736 style, sc));
10737 add_font_name_table_entry (mac_to_x_fontname (name, size,
10738 italic, sc));
10739 add_font_name_table_entry (mac_to_x_fontname (name, size,
10740 bold, sc));
10741 add_font_name_table_entry (mac_to_x_fontname (name, size,
10742 italic | bold,
10743 sc));
10744 }
10745 else
10746 add_font_name_table_entry (mac_to_x_fontname (name, size, style,
10747 sc));
10748 }
10749
10750 /* Dispose of the iterators. */
10751 FMDisposeFontFamilyIterator (&ffi);
10752 FMDisposeFontFamilyInstanceIterator (&ffii);
10753 }
10754 else
10755 {
10756 #endif /* TARGET_API_MAC_CARBON */
10757 GrafPtr port;
10758 SInt16 fontnum, old_fontnum;
10759 int num_mac_fonts = CountResources('FOND');
10760 int i, j;
10761 Handle font_handle, font_handle_2;
10762 short id, scriptcode;
10763 ResType type;
10764 Str32 name;
10765 struct FontAssoc *fat;
10766 struct AsscEntry *assc_entry;
10767
10768 GetPort (&port); /* save the current font number used */
10769 #if TARGET_API_MAC_CARBON
10770 old_fontnum = GetPortTextFont (port);
10771 #else
10772 old_fontnum = port->txFont;
10773 #endif
10774
10775 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10776 {
10777 font_handle = GetIndResource ('FOND', i);
10778 if (!font_handle)
10779 continue;
10780
10781 GetResInfo (font_handle, &id, &type, name);
10782 GetFNum (name, &fontnum);
10783 p2cstr (name);
10784 if (fontnum == 0)
10785 continue;
10786
10787 TextFont (fontnum);
10788 scriptcode = FontToScript (fontnum);
10789 do
10790 {
10791 HLock (font_handle);
10792
10793 if (GetResourceSizeOnDisk (font_handle)
10794 >= sizeof (struct FamRec))
10795 {
10796 fat = (struct FontAssoc *) (*font_handle
10797 + sizeof (struct FamRec));
10798 assc_entry
10799 = (struct AsscEntry *) (*font_handle
10800 + sizeof (struct FamRec)
10801 + sizeof (struct FontAssoc));
10802
10803 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
10804 {
10805 if (font_name_table_size == 0)
10806 {
10807 font_name_table_size = 16;
10808 font_name_table = (char **)
10809 xmalloc (font_name_table_size * sizeof (char *));
10810 }
10811 else if (font_name_count >= font_name_table_size)
10812 {
10813 font_name_table_size += 16;
10814 font_name_table = (char **)
10815 xrealloc (font_name_table,
10816 font_name_table_size * sizeof (char *));
10817 }
10818 font_name_table[font_name_count++]
10819 = mac_to_x_fontname (name,
10820 assc_entry->fontSize,
10821 assc_entry->fontStyle,
10822 scriptcode);
10823 /* Both jisx0208.1983-sjis and
10824 jisx0201.1976-sjis parts are contained in
10825 Apple Japanese (SJIS) font. */
10826 if (smJapanese == scriptcode)
10827 {
10828 font_name_table[font_name_count++]
10829 = mac_to_x_fontname (name,
10830 assc_entry->fontSize,
10831 assc_entry->fontStyle,
10832 smRoman);
10833 }
10834 }
10835 }
10836
10837 HUnlock (font_handle);
10838 font_handle_2 = GetNextFOND (font_handle);
10839 ReleaseResource (font_handle);
10840 font_handle = font_handle_2;
10841 }
10842 while (ResError () == noErr && font_handle);
10843 }
10844
10845 TextFont (old_fontnum);
10846 #if TARGET_API_MAC_CARBON
10847 }
10848 #endif /* TARGET_API_MAC_CARBON */
10849 }
10850
10851
10852 /* Return a list of at most MAXNAMES font specs matching the one in
10853 PATTERN. Note that each '*' in the PATTERN matches exactly one
10854 field of the font spec, unlike X in which an '*' in a font spec can
10855 match a number of fields. The result is in the Mac implementation
10856 all fonts must be specified by a font spec with all 13 fields
10857 (although many of these can be "*'s"). */
10858
10859 Lisp_Object
10860 x_list_fonts (struct frame *f,
10861 Lisp_Object pattern,
10862 int size,
10863 int maxnames)
10864 {
10865 char *ptnstr;
10866 Lisp_Object newlist = Qnil;
10867 int n_fonts = 0;
10868 int i;
10869 struct gcpro gcpro1, gcpro2;
10870
10871 if (font_name_table == NULL) /* Initialize when first used. */
10872 init_font_name_table ();
10873
10874 ptnstr = XSTRING (pattern)->data;
10875
10876 GCPRO2 (pattern, newlist);
10877
10878 /* Scan and matching bitmap fonts. */
10879 for (i = 0; i < font_name_count; i++)
10880 {
10881 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10882 {
10883 newlist = Fcons (build_string (font_name_table[i]), newlist);
10884
10885 n_fonts++;
10886 if (n_fonts >= maxnames)
10887 break;
10888 }
10889 }
10890
10891 /* MAC_TODO: add code for matching outline fonts here */
10892
10893 UNGCPRO;
10894
10895 return newlist;
10896 }
10897
10898
10899 #if GLYPH_DEBUG
10900
10901 /* Check that FONT is valid on frame F. It is if it can be found in F's
10902 font table. */
10903
10904 static void
10905 x_check_font (f, font)
10906 struct frame *f;
10907 XFontStruct *font;
10908 {
10909 int i;
10910 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10911
10912 xassert (font != NULL);
10913
10914 for (i = 0; i < dpyinfo->n_fonts; i++)
10915 if (dpyinfo->font_table[i].name
10916 && font == dpyinfo->font_table[i].font)
10917 break;
10918
10919 xassert (i < dpyinfo->n_fonts);
10920 }
10921
10922 #endif /* GLYPH_DEBUG != 0 */
10923
10924 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10925 Note: There are (broken) X fonts out there with invalid XFontStruct
10926 min_bounds contents. For example, handa@etl.go.jp reports that
10927 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10928 have font->min_bounds.width == 0. */
10929
10930 static INLINE void
10931 x_font_min_bounds (font, w, h)
10932 MacFontStruct *font;
10933 int *w, *h;
10934 {
10935 /*
10936 * TODO: Windows does not appear to offer min bound, only
10937 * average and maximum width, and maximum height.
10938 */
10939 *h = FONT_HEIGHT (font);
10940 *w = FONT_WIDTH (font);
10941 }
10942
10943
10944 /* Compute the smallest character width and smallest font height over
10945 all fonts available on frame F. Set the members smallest_char_width
10946 and smallest_font_height in F's x_display_info structure to
10947 the values computed. Value is non-zero if smallest_font_height or
10948 smallest_char_width become smaller than they were before. */
10949
10950 int
10951 x_compute_min_glyph_bounds (f)
10952 struct frame *f;
10953 {
10954 int i;
10955 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10956 MacFontStruct *font;
10957 int old_width = dpyinfo->smallest_char_width;
10958 int old_height = dpyinfo->smallest_font_height;
10959
10960 dpyinfo->smallest_font_height = 100000;
10961 dpyinfo->smallest_char_width = 100000;
10962
10963 for (i = 0; i < dpyinfo->n_fonts; ++i)
10964 if (dpyinfo->font_table[i].name)
10965 {
10966 struct font_info *fontp = dpyinfo->font_table + i;
10967 int w, h;
10968
10969 font = (MacFontStruct *) fontp->font;
10970 xassert (font != (MacFontStruct *) ~0);
10971 x_font_min_bounds (font, &w, &h);
10972
10973 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10974 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10975 }
10976
10977 xassert (dpyinfo->smallest_char_width > 0
10978 && dpyinfo->smallest_font_height > 0);
10979
10980 return (dpyinfo->n_fonts == 1
10981 || dpyinfo->smallest_char_width < old_width
10982 || dpyinfo->smallest_font_height < old_height);
10983 }
10984
10985
10986 /* Determine whether given string is a fully-specified XLFD: all 14
10987 fields are present, none is '*'. */
10988
10989 static int
10990 is_fully_specified_xlfd (char *p)
10991 {
10992 int i;
10993 char *q;
10994
10995 if (*p != '-')
10996 return 0;
10997
10998 for (i = 0; i < 13; i++)
10999 {
11000 q = strchr (p + 1, '-');
11001 if (q == NULL)
11002 return 0;
11003 if (q - p == 2 && *(p + 1) == '*')
11004 return 0;
11005 p = q;
11006 }
11007
11008 if (strchr (p + 1, '-') != NULL)
11009 return 0;
11010
11011 if (*(p + 1) == '*' && *(p + 2) == '\0')
11012 return 0;
11013
11014 return 1;
11015 }
11016
11017
11018 const int kDefaultFontSize = 9;
11019
11020
11021 /* XLoadQueryFont creates and returns an internal representation for a
11022 font in a MacFontStruct struct. There is really no concept
11023 corresponding to "loading" a font on the Mac. But we check its
11024 existence and find the font number and all other information for it
11025 and store them in the returned MacFontStruct. */
11026
11027 static MacFontStruct *
11028 XLoadQueryFont (Display *dpy, char *fontname)
11029 {
11030 int i, size, is_two_byte_font, char_width;
11031 char *name;
11032 GrafPtr port;
11033 SInt16 old_fontnum, old_fontsize;
11034 Style old_fontface;
11035 Str32 mfontname;
11036 SInt16 fontnum;
11037 Style fontface = normal;
11038 MacFontStruct *font;
11039 FontInfo the_fontinfo;
11040 char s_weight[7], c_slant;
11041
11042 if (is_fully_specified_xlfd (fontname))
11043 name = fontname;
11044 else
11045 {
11046 for (i = 0; i < font_name_count; i++)
11047 if (mac_font_pattern_match (font_name_table[i], fontname))
11048 break;
11049
11050 if (i >= font_name_count)
11051 return NULL;
11052
11053 name = font_name_table[i];
11054 }
11055
11056 GetPort (&port); /* save the current font number used */
11057 #if TARGET_API_MAC_CARBON
11058 old_fontnum = GetPortTextFont (port);
11059 old_fontsize = GetPortTextSize (port);
11060 old_fontface = GetPortTextFace (port);
11061 #else
11062 old_fontnum = port->txFont;
11063 old_fontsize = port->txSize;
11064 old_fontface = port->txFace;
11065 #endif
11066
11067 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
11068 size = kDefaultFontSize;
11069
11070 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
11071 if (strcmp (s_weight, "bold") == 0)
11072 fontface |= bold;
11073
11074 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
11075 if (c_slant == 'i')
11076 fontface |= italic;
11077
11078 x_font_name_to_mac_font_name (name, mfontname);
11079 c2pstr (mfontname);
11080 GetFNum (mfontname, &fontnum);
11081 if (fontnum == 0)
11082 return NULL;
11083
11084 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
11085
11086 font->fontname = (char *) xmalloc (strlen (name) + 1);
11087 bcopy (name, font->fontname, strlen (name) + 1);
11088
11089 font->mac_fontnum = fontnum;
11090 font->mac_fontsize = size;
11091 font->mac_fontface = fontface;
11092 font->mac_scriptcode = FontToScript (fontnum);
11093
11094 /* Apple Japanese (SJIS) font is listed as both
11095 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
11096 (Roman script) in init_font_name_table (). The latter should be
11097 treated as a one-byte font. */
11098 {
11099 char cs[32];
11100
11101 if (sscanf (name,
11102 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11103 cs) == 1
11104 && 0 == strcmp (cs, "mac-roman"))
11105 font->mac_scriptcode = smRoman;
11106 }
11107
11108 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11109 font->mac_scriptcode == smTradChinese ||
11110 font->mac_scriptcode == smSimpChinese ||
11111 font->mac_scriptcode == smKorean;
11112
11113 TextFont (fontnum);
11114 TextSize (size);
11115 TextFace (fontface);
11116
11117 GetFontInfo (&the_fontinfo);
11118
11119 font->ascent = the_fontinfo.ascent;
11120 font->descent = the_fontinfo.descent;
11121
11122 font->min_byte1 = 0;
11123 if (is_two_byte_font)
11124 font->max_byte1 = 1;
11125 else
11126 font->max_byte1 = 0;
11127 font->min_char_or_byte2 = 0x20;
11128 font->max_char_or_byte2 = 0xff;
11129
11130 if (is_two_byte_font)
11131 {
11132 /* Use the width of an "ideographic space" of that font because
11133 the_fontinfo.widMax returns the wrong width for some fonts. */
11134 switch (font->mac_scriptcode)
11135 {
11136 case smJapanese:
11137 char_width = StringWidth("\p\x81\x40");
11138 break;
11139 case smTradChinese:
11140 char_width = StringWidth("\p\xa1\x40");
11141 break;
11142 case smSimpChinese:
11143 char_width = StringWidth("\p\xa1\xa1");
11144 break;
11145 case smKorean:
11146 char_width = StringWidth("\p\xa1\xa1");
11147 break;
11148 }
11149 }
11150 else
11151 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11152 returns 15 for 12-point Monaco! */
11153 char_width = CharWidth ('m');
11154
11155 font->max_bounds.rbearing = char_width;
11156 font->max_bounds.lbearing = 0;
11157 font->max_bounds.width = char_width;
11158 font->max_bounds.ascent = the_fontinfo.ascent;
11159 font->max_bounds.descent = the_fontinfo.descent;
11160
11161 font->min_bounds = font->max_bounds;
11162
11163 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11164 font->per_char = NULL;
11165 else
11166 {
11167 font->per_char = (XCharStruct *)
11168 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11169 {
11170 int c;
11171
11172 for (c = 0x20; c <= 0xff; c++)
11173 {
11174 font->per_char[c - 0x20] = font->max_bounds;
11175 font->per_char[c - 0x20].width = CharWidth (c);
11176 }
11177 }
11178 }
11179
11180 TextFont (old_fontnum); /* restore previous font number, size and face */
11181 TextSize (old_fontsize);
11182 TextFace (old_fontface);
11183
11184 return font;
11185 }
11186
11187
11188 /* Load font named FONTNAME of the size SIZE for frame F, and return a
11189 pointer to the structure font_info while allocating it dynamically.
11190 If SIZE is 0, load any size of font.
11191 If loading is failed, return NULL. */
11192
11193 struct font_info *
11194 x_load_font (f, fontname, size)
11195 struct frame *f;
11196 register char *fontname;
11197 int size;
11198 {
11199 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11200 Lisp_Object font_names;
11201
11202 /* Get a list of all the fonts that match this name. Once we
11203 have a list of matching fonts, we compare them against the fonts
11204 we already have by comparing names. */
11205 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11206
11207 if (!NILP (font_names))
11208 {
11209 Lisp_Object tail;
11210 int i;
11211
11212 for (i = 0; i < dpyinfo->n_fonts; i++)
11213 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11214 if (dpyinfo->font_table[i].name
11215 && (!strcmp (dpyinfo->font_table[i].name,
11216 XSTRING (XCAR (tail))->data)
11217 || !strcmp (dpyinfo->font_table[i].full_name,
11218 XSTRING (XCAR (tail))->data)))
11219 return (dpyinfo->font_table + i);
11220 }
11221
11222 /* Load the font and add it to the table. */
11223 {
11224 char *full_name;
11225 struct MacFontStruct *font;
11226 struct font_info *fontp;
11227 unsigned long value;
11228 int i;
11229
11230 /* If we have found fonts by x_list_font, load one of them. If
11231 not, we still try to load a font by the name given as FONTNAME
11232 because XListFonts (called in x_list_font) of some X server has
11233 a bug of not finding a font even if the font surely exists and
11234 is loadable by XLoadQueryFont. */
11235 if (size > 0 && !NILP (font_names))
11236 fontname = (char *) XSTRING (XCAR (font_names))->data;
11237
11238 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11239 if (!font)
11240 return NULL;
11241
11242 /* Find a free slot in the font table. */
11243 for (i = 0; i < dpyinfo->n_fonts; ++i)
11244 if (dpyinfo->font_table[i].name == NULL)
11245 break;
11246
11247 /* If no free slot found, maybe enlarge the font table. */
11248 if (i == dpyinfo->n_fonts
11249 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11250 {
11251 int sz;
11252 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11253 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11254 dpyinfo->font_table
11255 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11256 }
11257
11258 fontp = dpyinfo->font_table + i;
11259 if (i == dpyinfo->n_fonts)
11260 ++dpyinfo->n_fonts;
11261
11262 /* Now fill in the slots of *FONTP. */
11263 BLOCK_INPUT;
11264 fontp->font = font;
11265 fontp->font_idx = i;
11266 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11267 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11268
11269 fontp->full_name = fontp->name;
11270
11271 fontp->size = font->max_bounds.width;
11272 fontp->height = FONT_HEIGHT (font);
11273 {
11274 /* For some font, ascent and descent in max_bounds field is
11275 larger than the above value. */
11276 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11277 if (max_height > fontp->height)
11278 fontp->height = max_height;
11279 }
11280
11281 /* The slot `encoding' specifies how to map a character
11282 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11283 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11284 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11285 2:0xA020..0xFF7F). For the moment, we don't know which charset
11286 uses this font. So, we set information in fontp->encoding[1]
11287 which is never used by any charset. If mapping can't be
11288 decided, set FONT_ENCODING_NOT_DECIDED. */
11289 if (font->mac_scriptcode == smJapanese)
11290 fontp->encoding[1] = 4;
11291 else
11292 {
11293 fontp->encoding[1]
11294 = (font->max_byte1 == 0
11295 /* 1-byte font */
11296 ? (font->min_char_or_byte2 < 0x80
11297 ? (font->max_char_or_byte2 < 0x80
11298 ? 0 /* 0x20..0x7F */
11299 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11300 : 1) /* 0xA0..0xFF */
11301 /* 2-byte font */
11302 : (font->min_byte1 < 0x80
11303 ? (font->max_byte1 < 0x80
11304 ? (font->min_char_or_byte2 < 0x80
11305 ? (font->max_char_or_byte2 < 0x80
11306 ? 0 /* 0x2020..0x7F7F */
11307 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11308 : 3) /* 0x20A0..0x7FFF */
11309 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11310 : (font->min_char_or_byte2 < 0x80
11311 ? (font->max_char_or_byte2 < 0x80
11312 ? 2 /* 0xA020..0xFF7F */
11313 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11314 : 1))); /* 0xA0A0..0xFFFF */
11315 }
11316
11317 #if 0 /* MAC_TODO: fill these out with more reasonably values */
11318 fontp->baseline_offset
11319 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11320 ? (long) value : 0);
11321 fontp->relative_compose
11322 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11323 ? (long) value : 0);
11324 fontp->default_ascent
11325 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11326 ? (long) value : 0);
11327 #else
11328 fontp->baseline_offset = 0;
11329 fontp->relative_compose = 0;
11330 fontp->default_ascent = 0;
11331 #endif
11332
11333 /* Set global flag fonts_changed_p to non-zero if the font loaded
11334 has a character with a smaller width than any other character
11335 before, or if the font loaded has a smalle>r height than any
11336 other font loaded before. If this happens, it will make a
11337 glyph matrix reallocation necessary. */
11338 fonts_changed_p = x_compute_min_glyph_bounds (f);
11339 UNBLOCK_INPUT;
11340 return fontp;
11341 }
11342 }
11343
11344
11345 /* Return a pointer to struct font_info of a font named FONTNAME for
11346 frame F. If no such font is loaded, return NULL. */
11347
11348 struct font_info *
11349 x_query_font (f, fontname)
11350 struct frame *f;
11351 register char *fontname;
11352 {
11353 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11354 int i;
11355
11356 for (i = 0; i < dpyinfo->n_fonts; i++)
11357 if (dpyinfo->font_table[i].name
11358 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11359 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11360 return (dpyinfo->font_table + i);
11361 return NULL;
11362 }
11363
11364
11365 /* Find a CCL program for a font specified by FONTP, and set the member
11366 `encoder' of the structure. */
11367
11368 void
11369 x_find_ccl_program (fontp)
11370 struct font_info *fontp;
11371 {
11372 Lisp_Object list, elt;
11373
11374 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11375 {
11376 elt = XCAR (list);
11377 if (CONSP (elt)
11378 && STRINGP (XCAR (elt))
11379 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11380 >= 0))
11381 break;
11382 }
11383 if (! NILP (list))
11384 {
11385 struct ccl_program *ccl
11386 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11387
11388 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11389 xfree (ccl);
11390 else
11391 fontp->font_encoder = ccl;
11392 }
11393 }
11394
11395
11396 \f
11397 /***********************************************************************
11398 Initialization
11399 ***********************************************************************/
11400
11401 #ifdef USE_X_TOOLKIT
11402 static XrmOptionDescRec emacs_options[] = {
11403 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11404 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11405
11406 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11407 XrmoptionSepArg, NULL},
11408 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11409
11410 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11411 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11412 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11413 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11414 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11415 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11416 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11417 };
11418 #endif /* USE_X_TOOLKIT */
11419
11420 static int x_initialized;
11421
11422 #ifdef MULTI_KBOARD
11423 /* Test whether two display-name strings agree up to the dot that separates
11424 the screen number from the server number. */
11425 static int
11426 same_x_server (name1, name2)
11427 char *name1, *name2;
11428 {
11429 int seen_colon = 0;
11430 unsigned char *system_name = XSTRING (Vsystem_name)->data;
11431 int system_name_length = strlen (system_name);
11432 int length_until_period = 0;
11433
11434 while (system_name[length_until_period] != 0
11435 && system_name[length_until_period] != '.')
11436 length_until_period++;
11437
11438 /* Treat `unix' like an empty host name. */
11439 if (! strncmp (name1, "unix:", 5))
11440 name1 += 4;
11441 if (! strncmp (name2, "unix:", 5))
11442 name2 += 4;
11443 /* Treat this host's name like an empty host name. */
11444 if (! strncmp (name1, system_name, system_name_length)
11445 && name1[system_name_length] == ':')
11446 name1 += system_name_length;
11447 if (! strncmp (name2, system_name, system_name_length)
11448 && name2[system_name_length] == ':')
11449 name2 += system_name_length;
11450 /* Treat this host's domainless name like an empty host name. */
11451 if (! strncmp (name1, system_name, length_until_period)
11452 && name1[length_until_period] == ':')
11453 name1 += length_until_period;
11454 if (! strncmp (name2, system_name, length_until_period)
11455 && name2[length_until_period] == ':')
11456 name2 += length_until_period;
11457
11458 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11459 {
11460 if (*name1 == ':')
11461 seen_colon++;
11462 if (seen_colon && *name1 == '.')
11463 return 1;
11464 }
11465 return (seen_colon
11466 && (*name1 == '.' || *name1 == '\0')
11467 && (*name2 == '.' || *name2 == '\0'));
11468 }
11469 #endif
11470
11471
11472 /* The Mac Event loop code */
11473
11474 #ifndef MAC_OSX
11475 #include <Events.h>
11476 #include <Quickdraw.h>
11477 #include <Balloons.h>
11478 #include <Devices.h>
11479 #include <Fonts.h>
11480 #include <Gestalt.h>
11481 #include <Menus.h>
11482 #include <Processes.h>
11483 #include <Sound.h>
11484 #include <ToolUtils.h>
11485 #include <TextUtils.h>
11486 #include <Dialogs.h>
11487 #include <Script.h>
11488 #include <Types.h>
11489 #include <TextEncodingConverter.h>
11490 #include <Resources.h>
11491
11492 #if __MWERKS__
11493 #include <unix.h>
11494 #endif
11495 #endif /* ! MAC_OSX */
11496
11497 #define M_APPLE 128
11498 #define I_ABOUT 1
11499
11500 #define WINDOW_RESOURCE 128
11501 #define TERM_WINDOW_RESOURCE 129
11502
11503 #define DEFAULT_NUM_COLS 80
11504
11505 #define MIN_DOC_SIZE 64
11506 #define MAX_DOC_SIZE 32767
11507
11508 /* sleep time for WaitNextEvent */
11509 #define WNE_SLEEP_AT_SUSPEND 10
11510 #define WNE_SLEEP_AT_RESUME 1
11511
11512 /* true when cannot handle any Mac OS events */
11513 static int handling_window_update = 0;
11514
11515 /* the flag appl_is_suspended is used both for determining the sleep
11516 time to be passed to WaitNextEvent and whether the cursor should be
11517 drawn when updating the display. The cursor is turned off when
11518 Emacs is suspended. Redrawing it is unnecessary and what needs to
11519 be done depends on whether the cursor lies inside or outside the
11520 redraw region. So we might as well skip drawing it when Emacs is
11521 suspended. */
11522 static Boolean app_is_suspended = false;
11523 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11524
11525 #define EXTRA_STACK_ALLOC (256 * 1024)
11526
11527 #define ARGV_STRING_LIST_ID 129
11528 #define ABOUT_ALERT_ID 128
11529 #define RAM_TOO_LARGE_ALERT_ID 129
11530
11531 Boolean terminate_flag = false;
11532
11533 /* true if using command key as meta key */
11534 Lisp_Object Vmac_command_key_is_meta;
11535
11536 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11537 to this text encoding */
11538 int mac_keyboard_text_encoding;
11539 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11540
11541 /* Set in term/mac-win.el to indicate that event loop can now generate
11542 drag and drop events. */
11543 Lisp_Object Qmac_ready_for_drag_n_drop;
11544
11545 Lisp_Object drag_and_drop_file_list;
11546
11547 Point saved_menu_event_location;
11548
11549 /* Apple Events */
11550 static void init_required_apple_events(void);
11551 static pascal OSErr
11552 do_ae_open_application(const AppleEvent *, AppleEvent *, long);
11553 static pascal OSErr
11554 do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
11555 static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
11556 static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
11557
11558 extern void init_emacs_passwd_dir ();
11559 extern int emacs_main (int, char **, char **);
11560 extern void check_alarm ();
11561
11562 extern void initialize_applescript();
11563 extern void terminate_applescript();
11564
11565
11566 static void
11567 do_get_menus (void)
11568 {
11569 Handle menubar_handle;
11570 MenuHandle menu_handle;
11571
11572 menubar_handle = GetNewMBar (128);
11573 if(menubar_handle == NULL)
11574 abort ();
11575 SetMenuBar (menubar_handle);
11576 DrawMenuBar ();
11577
11578 menu_handle = GetMenuHandle (M_APPLE);
11579 if(menu_handle != NULL)
11580 AppendResMenu (menu_handle,'DRVR');
11581 else
11582 abort ();
11583 }
11584
11585
11586 static void
11587 do_init_managers (void)
11588 {
11589 #if !TARGET_API_MAC_CARBON
11590 InitGraf (&qd.thePort);
11591 InitFonts ();
11592 FlushEvents (everyEvent, 0);
11593 InitWindows ();
11594 InitMenus ();
11595 TEInit ();
11596 InitDialogs (NULL);
11597 #endif /* !TARGET_API_MAC_CARBON */
11598 InitCursor ();
11599
11600 #if !TARGET_API_MAC_CARBON
11601 /* set up some extra stack space for use by emacs */
11602 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11603
11604 /* MaxApplZone must be called for AppleScript to execute more
11605 complicated scripts */
11606 MaxApplZone ();
11607 MoreMasters ();
11608 #endif /* !TARGET_API_MAC_CARBON */
11609 }
11610
11611 static void
11612 do_check_ram_size (void)
11613 {
11614 SInt32 physical_ram_size, logical_ram_size;
11615
11616 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11617 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11618 || physical_ram_size > 256 * 1024 * 1024
11619 || logical_ram_size > 256 * 1024 * 1024)
11620 {
11621 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11622 exit (1);
11623 }
11624 }
11625
11626 static void
11627 do_window_update (WindowPtr win)
11628 {
11629 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11630 struct frame *f = mwp->mFP;
11631
11632 if (f)
11633 {
11634 if (f->async_visible == 0)
11635 {
11636 f->async_visible = 1;
11637 f->async_iconified = 0;
11638 SET_FRAME_GARBAGED (f);
11639
11640 /* An update event is equivalent to MapNotify on X, so report
11641 visibility changes properly. */
11642 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11643 /* Force a redisplay sooner or later to update the
11644 frame titles in case this is the second frame. */
11645 record_asynch_buffer_change ();
11646 }
11647 else
11648 {
11649 BeginUpdate (win);
11650 handling_window_update = 1;
11651
11652 expose_frame (f, 0, 0, 0, 0);
11653
11654 handling_window_update = 0;
11655 EndUpdate (win);
11656 }
11657 }
11658 }
11659
11660 static int
11661 is_emacs_window (WindowPtr win)
11662 {
11663 Lisp_Object tail, frame;
11664
11665 if (!win)
11666 return 0;
11667
11668 FOR_EACH_FRAME (tail, frame)
11669 if (FRAME_MAC_P (XFRAME (frame)))
11670 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11671 return 1;
11672
11673 return 0;
11674 }
11675
11676 static void
11677 do_window_activate (WindowPtr win)
11678 {
11679 mac_output *mwp;
11680 struct frame *f;
11681
11682 if (is_emacs_window (win))
11683 {
11684 mwp = (mac_output *) GetWRefCon (win);
11685 f = mwp->mFP;
11686
11687 if (f)
11688 {
11689 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11690 activate_scroll_bars (f);
11691 }
11692 }
11693 }
11694
11695 static void
11696 do_window_deactivate (WindowPtr win)
11697 {
11698 mac_output *mwp;
11699 struct frame *f;
11700
11701 if (is_emacs_window (win))
11702 {
11703 mwp = (mac_output *) GetWRefCon (win);
11704 f = mwp->mFP;
11705
11706 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11707 {
11708 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11709 deactivate_scroll_bars (f);
11710 }
11711 }
11712 }
11713
11714 static void
11715 do_app_resume ()
11716 {
11717 WindowPtr wp;
11718 mac_output *mwp;
11719 struct frame *f;
11720
11721 wp = FrontWindow();
11722 if (is_emacs_window (wp))
11723 {
11724 mwp = (mac_output *) GetWRefCon (wp);
11725 f = mwp->mFP;
11726
11727 if (f)
11728 {
11729 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11730 activate_scroll_bars (f);
11731 }
11732 }
11733
11734 app_is_suspended = false;
11735 app_sleep_time = WNE_SLEEP_AT_RESUME;
11736 }
11737
11738 static void
11739 do_app_suspend ()
11740 {
11741 WindowPtr wp;
11742 mac_output *mwp;
11743 struct frame *f;
11744
11745 wp = FrontWindow();
11746 if (is_emacs_window (wp))
11747 {
11748 mwp = (mac_output *) GetWRefCon (wp);
11749 f = mwp->mFP;
11750
11751 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11752 {
11753 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11754 deactivate_scroll_bars (f);
11755 }
11756 }
11757
11758 app_is_suspended = true;
11759 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11760 }
11761
11762
11763 static void
11764 do_mouse_moved (Point mouse_pos)
11765 {
11766 WindowPtr wp = FrontWindow ();
11767 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11768
11769 #if TARGET_API_MAC_CARBON
11770 SetPort (GetWindowPort (wp));
11771 #else
11772 SetPort (wp);
11773 #endif
11774
11775 GlobalToLocal (&mouse_pos);
11776
11777 note_mouse_movement (f, &mouse_pos);
11778 }
11779
11780
11781 static void
11782 do_os_event (EventRecord *erp)
11783 {
11784 switch((erp->message >> 24) & 0x000000FF)
11785 {
11786 case suspendResumeMessage:
11787 if((erp->message & resumeFlag) == 1)
11788 do_app_resume ();
11789 else
11790 do_app_suspend ();
11791 break;
11792
11793 case mouseMovedMessage:
11794 do_mouse_moved (erp->where);
11795 break;
11796 }
11797 }
11798
11799 static void
11800 do_events (EventRecord *erp)
11801 {
11802 switch (erp->what)
11803 {
11804 case updateEvt:
11805 do_window_update ((WindowPtr) erp->message);
11806 break;
11807
11808 case osEvt:
11809 do_os_event (erp);
11810 break;
11811
11812 case activateEvt:
11813 if ((erp->modifiers & activeFlag) != 0)
11814 do_window_activate ((WindowPtr) erp->message);
11815 else
11816 do_window_deactivate ((WindowPtr) erp->message);
11817 break;
11818 }
11819 }
11820
11821 static void
11822 do_apple_menu (SInt16 menu_item)
11823 {
11824 #if !TARGET_API_MAC_CARBON
11825 Str255 item_name;
11826 SInt16 da_driver_refnum;
11827
11828 if (menu_item == I_ABOUT)
11829 NoteAlert (ABOUT_ALERT_ID, NULL);
11830 else
11831 {
11832 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11833 da_driver_refnum = OpenDeskAcc (item_name);
11834 }
11835 #endif /* !TARGET_API_MAC_CARBON */
11836 }
11837
11838 void
11839 do_menu_choice (SInt32 menu_choice)
11840 {
11841 SInt16 menu_id, menu_item;
11842
11843 menu_id = HiWord (menu_choice);
11844 menu_item = LoWord (menu_choice);
11845
11846 if (menu_id == 0)
11847 return;
11848
11849 switch (menu_id)
11850 {
11851 case M_APPLE:
11852 do_apple_menu (menu_item);
11853 break;
11854
11855 default:
11856 {
11857 WindowPtr wp = FrontWindow ();
11858 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11859 MenuHandle menu = GetMenuHandle (menu_id);
11860 if (menu)
11861 {
11862 UInt32 refcon;
11863
11864 GetMenuItemRefCon (menu, menu_item, &refcon);
11865 menubar_selection_callback (f, refcon);
11866 }
11867 }
11868 }
11869
11870 HiliteMenu (0);
11871 }
11872
11873
11874 /* Handle drags in size box. Based on code contributed by Ben
11875 Mesander and IM - Window Manager A. */
11876
11877 static void
11878 do_grow_window (WindowPtr w, EventRecord *e)
11879 {
11880 long grow_size;
11881 Rect limit_rect;
11882 int rows, columns;
11883 mac_output *mwp = (mac_output *) GetWRefCon (w);
11884 struct frame *f = mwp->mFP;
11885
11886 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11887
11888 grow_size = GrowWindow (w, e->where, &limit_rect);
11889
11890 /* see if it really changed size */
11891 if (grow_size != 0)
11892 {
11893 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11894 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11895
11896 x_set_window_size (f, 0, columns, rows);
11897 }
11898 }
11899
11900
11901 /* Handle clicks in zoom box. Calculation of "standard state" based
11902 on code in IM - Window Manager A and code contributed by Ben
11903 Mesander. The standard state of an Emacs window is 80-characters
11904 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11905
11906 static void
11907 do_zoom_window (WindowPtr w, int zoom_in_or_out)
11908 {
11909 GrafPtr save_port;
11910 Rect zoom_rect, port_rect;
11911 Point top_left;
11912 int w_title_height, columns, rows, width, height, dummy, x, y;
11913 mac_output *mwp = (mac_output *) GetWRefCon (w);
11914 struct frame *f = mwp->mFP;
11915
11916 GetPort (&save_port);
11917
11918 #if TARGET_API_MAC_CARBON
11919 SetPort (GetWindowPort (w));
11920 #else
11921 SetPort (w);
11922 #endif
11923
11924 /* Clear window to avoid flicker. */
11925 #if TARGET_API_MAC_CARBON
11926 {
11927 Rect r;
11928 BitMap bm;
11929
11930 GetWindowPortBounds (w, &r);
11931 EraseRect (&r);
11932
11933 if (zoom_in_or_out == inZoomOut)
11934 {
11935 /* calculate height of window's title bar (hard card it for now). */
11936 w_title_height = 20 + GetMBarHeight ();
11937
11938 /* get maximum height of window into zoom_rect.bottom -
11939 zoom_rect.top */
11940 GetQDGlobalsScreenBits (&bm);
11941 zoom_rect = bm.bounds;
11942 zoom_rect.top += w_title_height;
11943 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11944
11945 zoom_rect.right = zoom_rect.left
11946 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11947
11948 SetWindowStandardState (w, &zoom_rect);
11949 }
11950 }
11951 #else /* not TARGET_API_MAC_CARBON */
11952 EraseRect (&(w->portRect));
11953 if (zoom_in_or_out == inZoomOut)
11954 {
11955 SetPt (&top_left, w->portRect.left, w->portRect.top);
11956 LocalToGlobal (&top_left);
11957
11958 /* calculate height of window's title bar */
11959 w_title_height = top_left.v - 1
11960 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
11961
11962 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
11963 zoom_rect = qd.screenBits.bounds;
11964 zoom_rect.top += w_title_height;
11965 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11966
11967 zoom_rect.right = zoom_rect.left
11968 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11969
11970 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
11971 = zoom_rect;
11972 }
11973 #endif /* not TARGET_API_MAC_CARBON */
11974
11975 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
11976
11977 /* retrieve window size and update application values */
11978 #if TARGET_API_MAC_CARBON
11979 GetWindowPortBounds (w, &port_rect);
11980 #else
11981 port_rect = w->portRect;
11982 #endif
11983 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
11984 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
11985 x_set_window_size (mwp->mFP, 0, columns, rows);
11986
11987 SetPort (save_port);
11988 }
11989
11990
11991 /* Intialize AppleEvent dispatcher table for the required events. */
11992 void
11993 init_required_apple_events ()
11994 {
11995 OSErr err;
11996 long result;
11997
11998 /* Make sure we have apple events before starting. */
11999 err = Gestalt (gestaltAppleEventsAttr, &result);
12000 if (err != noErr)
12001 abort ();
12002
12003 if (!(result & (1 << gestaltAppleEventsPresent)))
12004 abort ();
12005
12006 #if TARGET_API_MAC_CARBON
12007 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12008 NewAEEventHandlerUPP
12009 ((AEEventHandlerProcPtr) do_ae_open_application),
12010 0L, false);
12011 #else
12012 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12013 NewAEEventHandlerProc
12014 ((AEEventHandlerProcPtr) do_ae_open_application),
12015 0L, false);
12016 #endif
12017 if (err != noErr)
12018 abort ();
12019
12020 #if TARGET_API_MAC_CARBON
12021 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12022 NewAEEventHandlerUPP
12023 ((AEEventHandlerProcPtr) do_ae_open_documents),
12024 0L, false);
12025 #else
12026 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12027 NewAEEventHandlerProc
12028 ((AEEventHandlerProcPtr) do_ae_open_documents),
12029 0L, false);
12030 #endif
12031 if (err != noErr)
12032 abort ();
12033
12034 #if TARGET_API_MAC_CARBON
12035 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12036 NewAEEventHandlerUPP
12037 ((AEEventHandlerProcPtr) do_ae_print_documents),
12038 0L, false);
12039 #else
12040 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12041 NewAEEventHandlerProc
12042 ((AEEventHandlerProcPtr) do_ae_print_documents),
12043 0L, false);
12044 #endif
12045 if (err != noErr)
12046 abort ();
12047
12048 #if TARGET_API_MAC_CARBON
12049 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12050 NewAEEventHandlerUPP
12051 ((AEEventHandlerProcPtr) do_ae_quit_application),
12052 0L, false);
12053 #else
12054 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12055 NewAEEventHandlerProc
12056 ((AEEventHandlerProcPtr) do_ae_quit_application),
12057 0L, false);
12058 #endif
12059 if (err != noErr)
12060 abort ();
12061 }
12062
12063
12064 /* Open Application Apple Event */
12065 static pascal OSErr
12066 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12067 {
12068 return noErr;
12069 }
12070
12071
12072 /* Defined in mac.c. */
12073 extern int
12074 path_from_vol_dir_name (char *, int, short, long, char *);
12075
12076
12077 /* Called when we receive an AppleEvent with an ID of
12078 "kAEOpenDocuments". This routine gets the direct parameter,
12079 extracts the FSSpecs in it, and puts their names on a list. */
12080 static pascal OSErr
12081 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12082 {
12083 OSErr err, err2;
12084 AEDesc the_desc;
12085 AEKeyword keyword;
12086 DescType actual_type;
12087 Size actual_size;
12088
12089 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12090 if (err != noErr)
12091 goto descriptor_error_exit;
12092
12093 /* Check to see that we got all of the required parameters from the
12094 event descriptor. For an 'odoc' event this should just be the
12095 file list. */
12096 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
12097 &actual_type, (Ptr) &keyword,
12098 sizeof (keyword), &actual_size);
12099 /* No error means that we found some unused parameters.
12100 errAEDescNotFound means that there are no more parameters. If we
12101 get an error code other than that, flag it. */
12102 if ((err == noErr) || (err != errAEDescNotFound))
12103 {
12104 err = errAEEventNotHandled;
12105 goto error_exit;
12106 }
12107 err = noErr;
12108
12109 /* Got all the parameters we need. Now, go through the direct
12110 object list and parse it up. */
12111 {
12112 long num_files_to_open;
12113
12114 err = AECountItems (&the_desc, &num_files_to_open);
12115 if (err == noErr)
12116 {
12117 int i;
12118
12119 /* AE file list is one based so just use that for indexing here. */
12120 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++) {
12121 FSSpec fs;
12122 Str255 path_name, unix_path_name;
12123
12124 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12125 (Ptr) &fs, sizeof (fs), &actual_size);
12126 if (err != noErr) break;
12127
12128 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12129 fs.name) &&
12130 mac_to_posix_pathname (path_name, unix_path_name, 255))
12131 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12132 drag_and_drop_file_list);
12133 }
12134 }
12135 }
12136
12137 error_exit:
12138 /* Nuke the coerced file list in any case */
12139 err2 = AEDisposeDesc(&the_desc);
12140
12141 descriptor_error_exit:
12142 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12143 return err;
12144 }
12145
12146
12147 /* Print Document Apple Event */
12148 static pascal OSErr
12149 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12150 {
12151 return errAEEventNotHandled;
12152 }
12153
12154
12155 static pascal OSErr
12156 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12157 {
12158 /* FixMe: Do we need an unwind-protect or something here? And what
12159 do we do about unsaved files. Currently just forces quit rather
12160 than doing recursive callback to get user input. */
12161
12162 terminate_flag = true;
12163
12164 /* Fkill_emacs doesn't return. We have to return. (TI) */
12165 return noErr;
12166 }
12167
12168
12169 #if __profile__
12170 void
12171 profiler_exit_proc ()
12172 {
12173 ProfilerDump ("\pEmacs.prof");
12174 ProfilerTerm ();
12175 }
12176 #endif
12177
12178 /* These few functions implement Emacs as a normal Mac application
12179 (almost): set up the heap and the Toolbox, handle necessary
12180 system events plus a few simple menu events. They also set up
12181 Emacs's access to functions defined in the rest of this file.
12182 Emacs uses function hooks to perform all its terminal I/O. A
12183 complete list of these functions appear in termhooks.h. For what
12184 they do, read the comments there and see also w32term.c and
12185 xterm.c. What's noticeably missing here is the event loop, which
12186 is normally present in most Mac application. After performing the
12187 necessary Mac initializations, main passes off control to
12188 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12189 mac_read_socket (defined further below) to read input. This is
12190 where WaitNextEvent is called to process Mac events. This is also
12191 where check_alarm in sysdep.c is called to simulate alarm signals.
12192 This makes the cursor jump back to its correct position after
12193 briefly jumping to that of the matching parenthesis, print useful
12194 hints and prompts in the minibuffer after the user stops typing for
12195 a wait, etc. */
12196
12197 #if !TARGET_API_MAC_CARBON
12198 #undef main
12199 int
12200 main (void)
12201 {
12202 #if __profile__ /* is the profiler on? */
12203 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12204 exit(1);
12205 #endif
12206
12207 #if __MWERKS__
12208 /* set creator and type for files created by MSL */
12209 _fcreator = 'EMAx';
12210 _ftype = 'TEXT';
12211 #endif
12212
12213 do_init_managers ();
12214
12215 do_get_menus ();
12216
12217 do_check_ram_size ();
12218
12219 init_emacs_passwd_dir ();
12220
12221 init_environ ();
12222
12223 initialize_applescript ();
12224
12225 init_required_apple_events ();
12226
12227 {
12228 char **argv;
12229 int argc = 0;
12230
12231 /* set up argv array from STR# resource */
12232 get_string_list (&argv, ARGV_STRING_LIST_ID);
12233 while (argv[argc])
12234 argc++;
12235
12236 /* free up AppleScript resources on exit */
12237 atexit (terminate_applescript);
12238
12239 #if __profile__ /* is the profiler on? */
12240 atexit (profiler_exit_proc);
12241 #endif
12242
12243 /* 3rd param "envp" never used in emacs_main */
12244 (void) emacs_main (argc, argv, 0);
12245 }
12246
12247 /* Never reached - real exit in Fkill_emacs */
12248 return 0;
12249 }
12250 #endif
12251
12252 /* Table for translating Mac keycode to X keysym values. Contributed
12253 by Sudhir Shenoy. */
12254 static unsigned char keycode_to_xkeysym_table[] = {
12255 /* 0x00 - 0x3f */
12256 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12257 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12258 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12259 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12260 /* 0x40 */
12261 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12262 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12263 0, 0, 0, '\xaf' /* kp/ */,
12264 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
12265 /* 0x50 */
12266 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12267 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12268 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12269 '\xb9' /* kp9 */, 0, 0, 0,
12270 /* 0x60 */
12271 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12272 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12273 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12274 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
12275 /* 0x70 */
12276 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12277 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12278 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12279 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
12280 };
12281
12282 static int
12283 keycode_to_xkeysym (int keyCode, int *xKeySym)
12284 {
12285 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12286 return *xKeySym != 0;
12287 }
12288
12289 /* Emacs calls this whenever it wants to read an input event from the
12290 user. */
12291 int
12292 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12293 {
12294 int count = 0;
12295 EventRecord er;
12296 int the_modifiers;
12297 EventMask event_mask;
12298
12299 #if 0
12300 if (interrupt_input_blocked)
12301 {
12302 interrupt_input_pending = 1;
12303 return -1;
12304 }
12305 #endif
12306
12307 interrupt_input_pending = 0;
12308 BLOCK_INPUT;
12309
12310 /* So people can tell when we have read the available input. */
12311 input_signal_count++;
12312
12313 if (numchars <= 0)
12314 abort ();
12315
12316 /* Don't poll for events to process (specifically updateEvt) if
12317 window update currently already in progress. A call to redisplay
12318 (in do_window_update) can be preempted by another call to
12319 redisplay, causing blank regions to be left on the screen and the
12320 cursor to be left at strange places. */
12321 if (handling_window_update)
12322 {
12323 UNBLOCK_INPUT;
12324 return 0;
12325 }
12326
12327 if (terminate_flag)
12328 Fkill_emacs (make_number (1));
12329
12330 /* It is necessary to set this (additional) argument slot of an
12331 event to nil because keyboard.c protects incompletely processed
12332 event from being garbage collected by placing them in the
12333 kbd_buffer_gcpro vector. */
12334 bufp->arg = Qnil;
12335
12336 event_mask = everyEvent;
12337 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
12338 event_mask -= highLevelEventMask;
12339
12340 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
12341 switch (er.what)
12342 {
12343 case mouseDown:
12344 case mouseUp:
12345 {
12346 WindowPtr window_ptr = FrontWindow ();
12347 SInt16 part_code;
12348
12349 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12350 && er.what == mouseUp)
12351 {
12352 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12353 Point mouse_loc = er.where;
12354
12355 /* Convert to local coordinates of new window. */
12356 #if TARGET_API_MAC_CARBON
12357 SetPort (GetWindowPort (window_ptr));
12358 #else
12359 SetPort (window_ptr);
12360 #endif
12361
12362 GlobalToLocal (&mouse_loc);
12363
12364 bufp->code = 0; /* only one mouse button */
12365 bufp->kind = SCROLL_BAR_CLICK_EVENT;
12366 bufp->frame_or_window = tracked_scroll_bar->window;
12367 bufp->part = scroll_bar_handle;
12368 bufp->modifiers = up_modifier;
12369 bufp->timestamp = er.when * (1000 / 60);
12370 /* ticks to milliseconds */
12371
12372 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12373 XSETINT (bufp->y, mouse_loc.v - 24);
12374 tracked_scroll_bar->dragging = Qnil;
12375 mouse_tracking_in_progress = mouse_tracking_none;
12376 tracked_scroll_bar = NULL;
12377 count++;
12378 break;
12379 }
12380
12381 part_code = FindWindow (er.where, &window_ptr);
12382
12383 switch (part_code)
12384 {
12385 case inMenuBar:
12386 {
12387 struct frame *f = ((mac_output *)
12388 GetWRefCon (FrontWindow ()))->mFP;
12389 saved_menu_event_location = er.where;
12390 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
12391 XSETFRAME (bufp->frame_or_window, f);
12392 count++;
12393 }
12394 break;
12395
12396 case inContent:
12397 if (window_ptr != FrontWindow ())
12398 SelectWindow (window_ptr);
12399 else
12400 {
12401 SInt16 control_part_code;
12402 ControlHandle ch;
12403 struct mac_output *mwp = (mac_output *)
12404 GetWRefCon (window_ptr);
12405 Point mouse_loc = er.where;
12406
12407 /* convert to local coordinates of new window */
12408 #if TARGET_API_MAC_CARBON
12409 SetPort (GetWindowPort (window_ptr));
12410 #else
12411 SetPort (window_ptr);
12412 #endif
12413
12414 GlobalToLocal (&mouse_loc);
12415 #if TARGET_API_MAC_CARBON
12416 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12417 &control_part_code);
12418 #else
12419 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
12420 #endif
12421 bufp->code = 0; /* only one mouse button */
12422 XSETINT (bufp->x, mouse_loc.h);
12423 XSETINT (bufp->y, mouse_loc.v);
12424 bufp->timestamp = er.when * (1000 / 60);
12425 /* ticks to milliseconds */
12426
12427 #if TARGET_API_MAC_CARBON
12428 if (ch != 0)
12429 #else
12430 if (control_part_code != 0)
12431 #endif
12432 {
12433 struct scroll_bar *bar = (struct scroll_bar *)
12434 GetControlReference (ch);
12435 x_scroll_bar_handle_click (bar, control_part_code, &er,
12436 bufp);
12437 if (er.what == mouseDown
12438 && control_part_code == kControlIndicatorPart)
12439 {
12440 mouse_tracking_in_progress
12441 = mouse_tracking_scroll_bar;
12442 tracked_scroll_bar = bar;
12443 }
12444 else
12445 {
12446 mouse_tracking_in_progress = mouse_tracking_none;
12447 tracked_scroll_bar = NULL;
12448 }
12449 }
12450 else
12451 {
12452 bufp->kind = MOUSE_CLICK_EVENT;
12453 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12454 if (er.what == mouseDown)
12455 mouse_tracking_in_progress
12456 = mouse_tracking_mouse_movement;
12457 else
12458 mouse_tracking_in_progress = mouse_tracking_none;
12459 }
12460
12461 switch (er.what)
12462 {
12463 case mouseDown:
12464 bufp->modifiers = down_modifier;
12465 break;
12466 case mouseUp:
12467 bufp->modifiers = up_modifier;
12468 break;
12469 }
12470
12471 count++;
12472 }
12473 break;
12474
12475 case inDrag:
12476 #if TARGET_API_MAC_CARBON
12477 {
12478 BitMap bm;
12479
12480 GetQDGlobalsScreenBits (&bm);
12481 DragWindow (window_ptr, er.where, &bm.bounds);
12482 }
12483 #else /* not TARGET_API_MAC_CARBON */
12484 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12485 #endif /* not TARGET_API_MAC_CARBON */
12486 break;
12487
12488 case inGoAway:
12489 if (TrackGoAway (window_ptr, er.where))
12490 {
12491 bufp->kind = DELETE_WINDOW_EVENT;
12492 XSETFRAME (bufp->frame_or_window,
12493 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12494 count++;
12495 }
12496 break;
12497
12498 /* window resize handling added --ben */
12499 case inGrow:
12500 do_grow_window(window_ptr, &er);
12501 break;
12502
12503 /* window zoom handling added --ben */
12504 case inZoomIn:
12505 case inZoomOut:
12506 if (TrackBox (window_ptr, er.where, part_code))
12507 do_zoom_window (window_ptr, part_code);
12508 break;
12509
12510 default:
12511 break;
12512 }
12513 }
12514 break;
12515
12516 case updateEvt:
12517 case osEvt:
12518 case activateEvt:
12519 do_events (&er);
12520 break;
12521
12522 case keyDown:
12523 case autoKey:
12524 {
12525 int keycode = (er.message & keyCodeMask) >> 8;
12526 int xkeysym;
12527
12528 ObscureCursor ();
12529
12530 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12531 {
12532 bufp->code = 0x7f;
12533 bufp->kind = ASCII_KEYSTROKE_EVENT;
12534 }
12535 else if (keycode_to_xkeysym (keycode, &xkeysym))
12536 {
12537 bufp->code = 0xff00 | xkeysym;
12538 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
12539 }
12540 else
12541 {
12542 if (er.modifiers
12543 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12544 {
12545 /* This code comes from Keyboard Resource, Appendix
12546 C of IM - Text. This is necessary since shift is
12547 ignored in KCHR table translation when option or
12548 command is pressed. */
12549 int new_modifiers = er.modifiers & 0xf600;
12550 /* mask off option and command */
12551 int new_keycode = keycode | new_modifiers;
12552 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12553 unsigned long some_state = 0;
12554 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12555 &some_state) & 0xff;
12556 }
12557 else
12558 bufp->code = er.message & charCodeMask;
12559 bufp->kind = ASCII_KEYSTROKE_EVENT;
12560 }
12561 }
12562
12563 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12564 convert non-ASCII characters typed at the Mac keyboard
12565 (presumed to be in the Mac Roman encoding) to iso-latin-1
12566 encoding before they are passed to Emacs. This enables the
12567 Mac keyboard to be used to enter non-ASCII iso-latin-1
12568 characters directly. */
12569 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
12570 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
12571 {
12572 static TECObjectRef converter = NULL;
12573 OSStatus the_err = noErr;
12574 OSStatus convert_status = noErr;
12575
12576 if (converter == NULL)
12577 {
12578 the_err = TECCreateConverter (&converter,
12579 kTextEncodingMacRoman,
12580 mac_keyboard_text_encoding);
12581 current_mac_keyboard_text_encoding
12582 = mac_keyboard_text_encoding;
12583 }
12584 else if (mac_keyboard_text_encoding
12585 != current_mac_keyboard_text_encoding)
12586 {
12587 /* Free the converter for the current encoding before
12588 creating a new one. */
12589 TECDisposeConverter (converter);
12590 the_err = TECCreateConverter (&converter,
12591 kTextEncodingMacRoman,
12592 mac_keyboard_text_encoding);
12593 current_mac_keyboard_text_encoding
12594 = mac_keyboard_text_encoding;
12595 }
12596
12597 if (the_err == noErr)
12598 {
12599 unsigned char ch = bufp->code;
12600 ByteCount actual_input_length, actual_output_length;
12601 unsigned char outch;
12602
12603 convert_status = TECConvertText (converter, &ch, 1,
12604 &actual_input_length,
12605 &outch, 1,
12606 &actual_output_length);
12607 if (convert_status == noErr
12608 && actual_input_length == 1
12609 && actual_output_length == 1)
12610 bufp->code = outch;
12611 }
12612 }
12613
12614 the_modifiers = 0;
12615 if (er.modifiers & shiftKey)
12616 the_modifiers |= shift_modifier;
12617 if (er.modifiers & controlKey)
12618 the_modifiers |= ctrl_modifier;
12619 /* use option or command key as meta depending on value of
12620 mac-command-key-is-meta */
12621 if (er.modifiers
12622 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12623 the_modifiers |= meta_modifier;
12624 bufp->modifiers = the_modifiers;
12625
12626 {
12627 mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
12628 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12629 }
12630
12631 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
12632
12633 count++;
12634 break;
12635
12636 case kHighLevelEvent:
12637 drag_and_drop_file_list = Qnil;
12638
12639 AEProcessAppleEvent(&er);
12640
12641 /* Build a DRAG_N_DROP_EVENT type event as is done in
12642 constuct_drag_n_drop in w32term.c. */
12643 if (!NILP (drag_and_drop_file_list))
12644 {
12645 struct frame *f;
12646 WindowPtr wp;
12647 Lisp_Object frame;
12648
12649 wp = FrontWindow ();
12650 if (!wp)
12651 f = NULL;
12652 else
12653 f = ((mac_output *) GetWRefCon (wp))->mFP;
12654
12655 bufp->kind = DRAG_N_DROP_EVENT;
12656 bufp->code = 0;
12657 bufp->timestamp = er.when * (1000 / 60);
12658 /* ticks to milliseconds */
12659 bufp->modifiers = 0;
12660
12661 XSETINT (bufp->x, 0);
12662 XSETINT (bufp->y, 0);
12663
12664 XSETFRAME (frame, f);
12665 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
12666
12667 /* Regardless of whether Emacs was suspended or in the
12668 foreground, ask it to redraw its entire screen.
12669 Otherwise parts of the screen can be left in an
12670 inconsistent state. */
12671 if (wp)
12672 #if TARGET_API_MAC_CARBON
12673 {
12674 Rect r;
12675
12676 GetWindowPortBounds (wp, &r);
12677 InvalWindowRect (wp, &r);
12678 }
12679 #else /* not TARGET_API_MAC_CARBON */
12680 InvalRect (&(wp->portRect));
12681 #endif /* not TARGET_API_MAC_CARBON */
12682
12683 count++;
12684 }
12685
12686 default:
12687 break;
12688 }
12689
12690 /* If the focus was just given to an autoraising frame,
12691 raise it now. */
12692 /* ??? This ought to be able to handle more than one such frame. */
12693 if (pending_autoraise_frame)
12694 {
12695 x_raise_frame (pending_autoraise_frame);
12696 pending_autoraise_frame = 0;
12697 }
12698
12699 #if !TARGET_API_MAC_CARBON
12700 check_alarm (); /* simulate the handling of a SIGALRM */
12701 #endif
12702
12703 {
12704 static Point old_mouse_pos = { -1, -1 };
12705
12706 if (app_is_suspended)
12707 {
12708 old_mouse_pos.h = -1;
12709 old_mouse_pos.v = -1;
12710 }
12711 else
12712 {
12713 Point mouse_pos;
12714 WindowPtr wp;
12715 struct frame *f;
12716 Lisp_Object bar;
12717 struct scroll_bar *sb;
12718
12719 wp = FrontWindow ();
12720 if (is_emacs_window (wp))
12721 {
12722 f = ((mac_output *) GetWRefCon (wp))->mFP;
12723
12724 #if TARGET_API_MAC_CARBON
12725 SetPort (GetWindowPort (wp));
12726 #else
12727 SetPort (wp);
12728 #endif
12729
12730 GetMouse (&mouse_pos);
12731
12732 if (!EqualPt (mouse_pos, old_mouse_pos))
12733 {
12734 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12735 && tracked_scroll_bar)
12736 x_scroll_bar_note_movement (tracked_scroll_bar,
12737 mouse_pos.v
12738 - XINT (tracked_scroll_bar->top),
12739 TickCount() * (1000 / 60));
12740 else
12741 note_mouse_movement (f, &mouse_pos);
12742
12743 old_mouse_pos = mouse_pos;
12744 }
12745 }
12746 }
12747 }
12748
12749 UNBLOCK_INPUT;
12750
12751 return count;
12752 }
12753
12754
12755 /* Need to override CodeWarrior's input function so no conversion is
12756 done on newlines Otherwise compiled functions in .elc files will be
12757 read incorrectly. Defined in ...:MSL C:MSL
12758 Common:Source:buffer_io.c. */
12759 #ifdef __MWERKS__
12760 void
12761 __convert_to_newlines (unsigned char * p, size_t * n)
12762 {
12763 #pragma unused(p,n)
12764 }
12765
12766 void
12767 __convert_from_newlines (unsigned char * p, size_t * n)
12768 {
12769 #pragma unused(p,n)
12770 }
12771 #endif
12772
12773
12774 /* Initialize the struct pointed to by MW to represent a new COLS x
12775 ROWS Macintosh window, using font with name FONTNAME and size
12776 FONTSIZE. */
12777 void
12778 NewMacWindow (FRAME_PTR fp)
12779 {
12780 mac_output *mwp;
12781 #if TARGET_API_MAC_CARBON
12782 static int making_terminal_window = 0;
12783 #else
12784 static int making_terminal_window = 1;
12785 #endif
12786
12787 mwp = fp->output_data.mac;
12788
12789 if (making_terminal_window)
12790 {
12791 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
12792 (WindowPtr) -1)))
12793 abort ();
12794 making_terminal_window = 0;
12795 }
12796 else
12797 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
12798 abort ();
12799
12800
12801 SetWRefCon (mwp->mWP, (long) mwp);
12802 /* so that update events can find this mac_output struct */
12803 mwp->mFP = fp; /* point back to emacs frame */
12804
12805 #if TARGET_API_MAC_CARBON
12806 SetPort (GetWindowPort (mwp->mWP));
12807 #else
12808 SetPort (mwp->mWP);
12809 #endif
12810
12811 mwp->fontset = -1;
12812
12813 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
12814 ShowWindow (mwp->mWP);
12815
12816 }
12817
12818
12819 void make_mac_frame (struct frame *f)
12820 {
12821 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
12822 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
12823
12824 NewMacWindow(f);
12825 FRAME_BACKGROUND_PIXEL (f) = 0xffffff;
12826 FRAME_FOREGROUND_PIXEL (f) = 0;
12827
12828 f->output_data.mac->cursor_pixel = 0;
12829 f->output_data.mac->border_pixel = 0x00ff00;
12830 f->output_data.mac->mouse_pixel = 0xff00ff;
12831 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
12832
12833 f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
12834
12835 f->output_data.mac->fontset = -1;
12836 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12837 f->output_data.mac->scroll_bar_background_pixel = -1;
12838 f->output_data.mac->left_pos = 4;
12839 f->output_data.mac->top_pos = 4;
12840 f->output_data.mac->border_width = 0;
12841 f->output_data.mac->explicit_parent = 0;
12842
12843 f->output_data.mac->internal_border_width = 0;
12844
12845 f->output_method = output_mac;
12846
12847 f->auto_raise = 1;
12848 f->auto_lower = 1;
12849
12850 f->new_width = 0;
12851 f->new_height = 0;
12852 }
12853
12854 void make_mac_terminal_frame (struct frame *f)
12855 {
12856 Lisp_Object frame;
12857
12858 XSETFRAME (frame, f);
12859
12860 f->output_method = output_mac;
12861 f->output_data.mac = (struct mac_output *)
12862 xmalloc (sizeof (struct mac_output));
12863 bzero (f->output_data.mac, sizeof (struct mac_output));
12864 f->output_data.mac->fontset = -1;
12865 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12866 f->output_data.mac->scroll_bar_background_pixel = -1;
12867
12868 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
12869
12870 f->width = 96;
12871 f->height = 4;
12872
12873 make_mac_frame (f);
12874
12875 x_make_gc (f);
12876
12877 /* Need to be initialized for unshow_buffer in window.c. */
12878 selected_window = f->selected_window;
12879
12880 Fmodify_frame_parameters (frame,
12881 Fcons (Fcons (Qfont,
12882 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
12883 Fmodify_frame_parameters (frame,
12884 Fcons (Fcons (Qforeground_color,
12885 build_string ("black")), Qnil));
12886 Fmodify_frame_parameters (frame,
12887 Fcons (Fcons (Qbackground_color,
12888 build_string ("white")), Qnil));
12889 }
12890
12891 \f
12892 /***********************************************************************
12893 Initialization
12894 ***********************************************************************/
12895
12896 #ifdef USE_X_TOOLKIT
12897 static XrmOptionDescRec emacs_options[] = {
12898 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12899 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12900
12901 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12902 XrmoptionSepArg, NULL},
12903 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12904
12905 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12906 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12907 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12908 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12909 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12910 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12911 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12912 };
12913 #endif /* USE_X_TOOLKIT */
12914
12915 #ifdef MULTI_KBOARD
12916 /* Test whether two display-name strings agree up to the dot that separates
12917 the screen number from the server number. */
12918 static int
12919 same_x_server (name1, name2)
12920 char *name1, *name2;
12921 {
12922 int seen_colon = 0;
12923 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12924 int system_name_length = strlen (system_name);
12925 int length_until_period = 0;
12926
12927 while (system_name[length_until_period] != 0
12928 && system_name[length_until_period] != '.')
12929 length_until_period++;
12930
12931 /* Treat `unix' like an empty host name. */
12932 if (! strncmp (name1, "unix:", 5))
12933 name1 += 4;
12934 if (! strncmp (name2, "unix:", 5))
12935 name2 += 4;
12936 /* Treat this host's name like an empty host name. */
12937 if (! strncmp (name1, system_name, system_name_length)
12938 && name1[system_name_length] == ':')
12939 name1 += system_name_length;
12940 if (! strncmp (name2, system_name, system_name_length)
12941 && name2[system_name_length] == ':')
12942 name2 += system_name_length;
12943 /* Treat this host's domainless name like an empty host name. */
12944 if (! strncmp (name1, system_name, length_until_period)
12945 && name1[length_until_period] == ':')
12946 name1 += length_until_period;
12947 if (! strncmp (name2, system_name, length_until_period)
12948 && name2[length_until_period] == ':')
12949 name2 += length_until_period;
12950
12951 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12952 {
12953 if (*name1 == ':')
12954 seen_colon++;
12955 if (seen_colon && *name1 == '.')
12956 return 1;
12957 }
12958 return (seen_colon
12959 && (*name1 == '.' || *name1 == '\0')
12960 && (*name2 == '.' || *name2 == '\0'));
12961 }
12962 #endif
12963
12964 int mac_initialized = 0;
12965
12966 void
12967 mac_initialize_display_info ()
12968 {
12969 struct mac_display_info *dpyinfo = &one_mac_display_info;
12970 GDHandle main_device_handle;
12971
12972 bzero (dpyinfo, sizeof (*dpyinfo));
12973
12974 /* Put it on x_display_name_list. */
12975 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
12976 x_display_name_list);
12977 dpyinfo->name_list_element = XCAR (x_display_name_list);
12978
12979 #if 0
12980 dpyinfo->mac_id_name
12981 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
12982 + XSTRING (Vsystem_name)->size
12983 + 2);
12984 sprintf (dpyinfo->mac_id_name, "%s@%s",
12985 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
12986 #else
12987 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
12988 strcpy (dpyinfo->mac_id_name, "Mac Display");
12989 #endif
12990
12991 main_device_handle = LMGetMainDevice();
12992
12993 dpyinfo->reference_count = 0;
12994 dpyinfo->resx = 75.0;
12995 dpyinfo->resy = 75.0;
12996 dpyinfo->n_planes = 1;
12997 dpyinfo->n_cbits = 16;
12998 dpyinfo->height = (**main_device_handle).gdRect.bottom;
12999 dpyinfo->width = (**main_device_handle).gdRect.right;
13000 dpyinfo->grabbed = 0;
13001 dpyinfo->root_window = NULL;
13002
13003 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13004 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13005 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13006 dpyinfo->mouse_face_window = Qnil;
13007 }
13008
13009 struct mac_display_info *
13010 mac_term_init (display_name, xrm_option, resource_name)
13011 Lisp_Object display_name;
13012 char *xrm_option;
13013 char *resource_name;
13014 {
13015 struct mac_display_info *dpyinfo;
13016 GDHandle main_device_handle;
13017
13018 if (!mac_initialized)
13019 {
13020 mac_initialize ();
13021 mac_initialized = 1;
13022 }
13023
13024 mac_initialize_display_info (display_name);
13025
13026 dpyinfo = &one_mac_display_info;
13027
13028 main_device_handle = LMGetMainDevice();
13029
13030 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13031 dpyinfo->width = (**main_device_handle).gdRect.right;
13032
13033 return dpyinfo;
13034 }
13035 \f
13036 /* Set up use of X before we make the first connection. */
13037
13038 static struct redisplay_interface x_redisplay_interface =
13039 {
13040 x_produce_glyphs,
13041 x_write_glyphs,
13042 x_insert_glyphs,
13043 x_clear_end_of_line,
13044 x_scroll_run,
13045 x_after_update_window_line,
13046 x_update_window_begin,
13047 x_update_window_end,
13048 XTcursor_to,
13049 x_flush,
13050 x_clear_mouse_face,
13051 x_get_glyph_overhangs,
13052 x_fix_overlapping_area
13053 };
13054
13055 void
13056 mac_initialize ()
13057 {
13058 rif = &x_redisplay_interface;
13059
13060 clear_frame_hook = x_clear_frame;
13061 ins_del_lines_hook = x_ins_del_lines;
13062 delete_glyphs_hook = x_delete_glyphs;
13063 ring_bell_hook = XTring_bell;
13064 reset_terminal_modes_hook = XTreset_terminal_modes;
13065 set_terminal_modes_hook = XTset_terminal_modes;
13066 update_begin_hook = x_update_begin;
13067 update_end_hook = x_update_end;
13068 set_terminal_window_hook = XTset_terminal_window;
13069 read_socket_hook = XTread_socket;
13070 frame_up_to_date_hook = XTframe_up_to_date;
13071 mouse_position_hook = XTmouse_position;
13072 frame_rehighlight_hook = XTframe_rehighlight;
13073 frame_raise_lower_hook = XTframe_raise_lower;
13074
13075 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13076 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13077 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13078 judge_scroll_bars_hook = XTjudge_scroll_bars;
13079
13080 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13081
13082 scroll_region_ok = 1; /* we'll scroll partial frames */
13083 char_ins_del_ok = 1;
13084 line_ins_del_ok = 1; /* we'll just blt 'em */
13085 fast_clear_end_of_line = 1; /* X does this well */
13086 memory_below_frame = 0; /* we don't remember what scrolls
13087 off the bottom */
13088 baud_rate = 19200;
13089
13090 x_noop_count = 0;
13091 last_tool_bar_item = -1;
13092 any_help_event_p = 0;
13093
13094 /* Try to use interrupt input; if we can't, then start polling. */
13095 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13096
13097 #ifdef USE_X_TOOLKIT
13098 XtToolkitInitialize ();
13099 Xt_app_con = XtCreateApplicationContext ();
13100 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13101
13102 /* Install an asynchronous timer that processes Xt timeout events
13103 every 0.1s. This is necessary because some widget sets use
13104 timeouts internally, for example the LessTif menu bar, or the
13105 Xaw3d scroll bar. When Xt timouts aren't processed, these
13106 widgets don't behave normally. */
13107 {
13108 EMACS_TIME interval;
13109 EMACS_SET_SECS_USECS (interval, 0, 100000);
13110 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13111 }
13112 #endif
13113
13114 #if USE_TOOLKIT_SCROLL_BARS
13115 xaw3d_arrow_scroll = False;
13116 xaw3d_pick_top = True;
13117 #endif
13118
13119 #if 0
13120 /* Note that there is no real way portable across R3/R4 to get the
13121 original error handler. */
13122 XSetErrorHandler (x_error_handler);
13123 XSetIOErrorHandler (x_io_error_quitter);
13124
13125 /* Disable Window Change signals; they are handled by X events. */
13126 #ifdef SIGWINCH
13127 signal (SIGWINCH, SIG_DFL);
13128 #endif /* ! defined (SIGWINCH) */
13129
13130 signal (SIGPIPE, x_connection_signal);
13131 #endif
13132
13133 mac_initialize_display_info ();
13134 }
13135
13136
13137 void
13138 syms_of_macterm ()
13139 {
13140 #if 0
13141 staticpro (&x_error_message_string);
13142 x_error_message_string = Qnil;
13143 #endif
13144
13145 staticpro (&x_display_name_list);
13146 x_display_name_list = Qnil;
13147
13148 staticpro (&last_mouse_scroll_bar);
13149 last_mouse_scroll_bar = Qnil;
13150
13151 staticpro (&Qvendor_specific_keysyms);
13152 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13153
13154 staticpro (&last_mouse_press_frame);
13155 last_mouse_press_frame = Qnil;
13156
13157 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13158 staticpro (&Qmac_ready_for_drag_n_drop);
13159
13160 help_echo = Qnil;
13161 staticpro (&help_echo);
13162 help_echo_object = Qnil;
13163 staticpro (&help_echo_object);
13164 help_echo_window = Qnil;
13165 staticpro (&help_echo_window);
13166 previous_help_echo = Qnil;
13167 staticpro (&previous_help_echo);
13168 help_echo_pos = -1;
13169
13170 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13171 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13172 x_autoselect_window_p = 0;
13173
13174 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13175 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13176 For example, if a block cursor is over a tab, it will be drawn as
13177 wide as that tab on the display. */);
13178 x_stretch_cursor_p = 0;
13179
13180 #if 0 /* TODO: Setting underline position from font properties. */
13181 DEFVAR_BOOL ("x-use-underline-position-properties",
13182 &x_use_underline_position_properties,
13183 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13184 nil means ignore them. If you encounter fonts with bogus
13185 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13186 to 4.1, set this to nil. */);
13187 x_use_underline_position_properties = 1;
13188 #endif
13189
13190 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13191 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13192 Vx_toolkit_scroll_bars = Qt;
13193
13194 staticpro (&last_mouse_motion_frame);
13195 last_mouse_motion_frame = Qnil;
13196
13197 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
13198 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13199 Otherwise the option key is used. */);
13200 Vmac_command_key_is_meta = Qt;
13201
13202 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
13203 doc: /* One of the Text Encoding Base constant values defined in the
13204 Basic Text Constants section of Inside Macintosh - Text Encoding
13205 Conversion Manager. Its value determines the encoding characters
13206 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13207 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13208 its default value, no conversion takes place. If it is set to
13209 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13210 characters typed on Mac keyboard are first converted into the
13211 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13212 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13213 command, this enables the Mac keyboard to be used to enter non-ASCII
13214 characters directly. */);
13215 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13216 }