Most uses of XSTRING combined with STRING_BYTES or indirection changed to
[bpt/emacs.git] / 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
974 ForeColor (blackColor);
975 BackColor (whiteColor);
976
977 LockPortBits (GetWindowPort (w));
978 pmh = GetPortPixMap (GetWindowPort (w));
979 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
980 UnlockPortBits (GetWindowPort (w));
981
982 mac_set_colors (gc);
983 #else /* not TARGET_API_MAC_CARBON */
984 Rect src_r, dest_r;
985
986 SetPort (w);
987 #if 0
988 mac_set_colors (gc);
989 #endif
990
991 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
992 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
993
994 #if 0
995 /* Need to use global coordinates and screenBits since src and dest
996 areas overlap in general. */
997 local_to_global_coord (&src_r.left, &src_r.top);
998 local_to_global_coord (&src_r.right, &src_r.bottom);
999 local_to_global_coord (&dest_r.left, &dest_r.top);
1000 local_to_global_coord (&dest_r.right, &dest_r.bottom);
1001
1002 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
1003 #else
1004 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1005 color mapping in CopyBits. Otherwise, it will be slow. */
1006 ForeColor (blackColor);
1007 BackColor (whiteColor);
1008 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1009
1010 mac_set_colors (gc);
1011 #endif
1012 #endif /* not TARGET_API_MAC_CARBON */
1013 }
1014
1015
1016 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1017
1018 static void
1019 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1020 dest_x, dest_y)
1021 Display *display;
1022 Pixmap src;
1023 Pixmap dest;
1024 GC gc;
1025 int src_x, src_y;
1026 unsigned int width, height;
1027 int dest_x, dest_y;
1028 {
1029 Rect src_r, dest_r;
1030 int src_right = ((PixMap *) src)->bounds.right;
1031 int src_bottom = ((PixMap *) src)->bounds.bottom;
1032 int w = src_right - src_x;
1033 int h = src_bottom - src_y;
1034
1035 mac_set_colors (gc);
1036
1037 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
1038 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
1039
1040 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
1041 }
1042
1043
1044 /* Mac replacement for XChangeGC. */
1045
1046 static void
1047 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1048 XGCValues *xgcv)
1049 {
1050 if (mask & GCForeground)
1051 gc->foreground = xgcv->foreground;
1052 if (mask & GCBackground)
1053 gc->background = xgcv->background;
1054 if (mask & GCFont)
1055 gc->font = xgcv->font;
1056 }
1057
1058
1059 /* Mac replacement for XCreateGC. */
1060
1061 XGCValues *
1062 XCreateGC (void * ignore, Window window, unsigned long mask,
1063 XGCValues *xgcv)
1064 {
1065 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1066 bzero (gc, sizeof (XGCValues));
1067
1068 XChangeGC (ignore, gc, mask, xgcv);
1069
1070 return gc;
1071 }
1072
1073
1074 /* Used in xfaces.c. */
1075
1076 void
1077 XFreeGC (display, gc)
1078 Display *display;
1079 GC gc;
1080 {
1081 xfree (gc);
1082 }
1083
1084
1085 /* Mac replacement for XGetGCValues. */
1086
1087 static void
1088 XGetGCValues (void* ignore, XGCValues *gc,
1089 unsigned long mask, XGCValues *xgcv)
1090 {
1091 XChangeGC (ignore, xgcv, mask, gc);
1092 }
1093
1094
1095 /* Mac replacement for XSetForeground. */
1096
1097 static void
1098 XSetForeground (display, gc, color)
1099 Display *display;
1100 GC gc;
1101 unsigned long color;
1102 {
1103 gc->foreground = color;
1104 }
1105
1106
1107 /* Mac replacement for XSetFont. */
1108
1109 static void
1110 XSetFont (display, gc, font)
1111 Display *display;
1112 GC gc;
1113 XFontStruct *font;
1114 {
1115 gc->font = font;
1116 }
1117
1118
1119 static void
1120 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1121 int *direction,int *font_ascent,
1122 int *font_descent, XCharStruct *cs)
1123 {
1124 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1125 }
1126
1127
1128 /* x_sync is a no-op on Mac. */
1129 void
1130 x_sync (f)
1131 void *f;
1132 {
1133 }
1134
1135
1136 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1137 Calls to XFlush should be unnecessary because the X output buffer
1138 is flushed automatically as needed by calls to XPending,
1139 XNextEvent, or XWindowEvent according to the XFlush man page.
1140 XTread_socket calls XPending. Removing XFlush improves
1141 performance. */
1142
1143 #if TARGET_API_MAC_CARBON
1144 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1145 #else
1146 #define XFlush(DISPLAY) (void) 0
1147 #endif
1148
1149 /* Flush display of frame F, or of all frames if F is null. */
1150
1151 void
1152 x_flush (f)
1153 struct frame *f;
1154 {
1155 #if TARGET_API_MAC_CARBON
1156 BLOCK_INPUT;
1157 if (f == NULL)
1158 {
1159 Lisp_Object rest, frame;
1160 FOR_EACH_FRAME (rest, frame)
1161 x_flush (XFRAME (frame));
1162 }
1163 else if (FRAME_X_P (f))
1164 XFlush (FRAME_MAC_DISPLAY (f));
1165 UNBLOCK_INPUT;
1166 #endif /* TARGET_API_MAC_CARBON */
1167 }
1168
1169
1170 \f
1171 /* Return the struct mac_display_info corresponding to DPY. There's
1172 only one. */
1173
1174 struct mac_display_info *
1175 mac_display_info_for_display (dpy)
1176 Display *dpy;
1177 {
1178 return &one_mac_display_info;
1179 }
1180
1181
1182 \f
1183 /***********************************************************************
1184 Starting and ending an update
1185 ***********************************************************************/
1186
1187 /* Start an update of frame F. This function is installed as a hook
1188 for update_begin, i.e. it is called when update_begin is called.
1189 This function is called prior to calls to x_update_window_begin for
1190 each window being updated. */
1191
1192 static void
1193 x_update_begin (f)
1194 struct frame *f;
1195 {
1196 /* Nothing to do. */
1197 }
1198
1199
1200 /* Start update of window W. Set the global variable updated_window
1201 to the window being updated and set output_cursor to the cursor
1202 position of W. */
1203
1204 static void
1205 x_update_window_begin (w)
1206 struct window *w;
1207 {
1208 struct frame *f = XFRAME (WINDOW_FRAME (w));
1209 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1210
1211 updated_window = w;
1212 set_output_cursor (&w->cursor);
1213
1214 BLOCK_INPUT;
1215
1216 if (f == display_info->mouse_face_mouse_frame)
1217 {
1218 /* Don't do highlighting for mouse motion during the update. */
1219 display_info->mouse_face_defer = 1;
1220
1221 /* If F needs to be redrawn, simply forget about any prior mouse
1222 highlighting. */
1223 if (FRAME_GARBAGED_P (f))
1224 display_info->mouse_face_window = Qnil;
1225
1226 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1227 their mouse_face_p flag set, which means that they are always
1228 unequal to rows in a desired matrix which never have that
1229 flag set. So, rows containing mouse-face glyphs are never
1230 scrolled, and we don't have to switch the mouse highlight off
1231 here to prevent it from being scrolled. */
1232
1233 /* Can we tell that this update does not affect the window
1234 where the mouse highlight is? If so, no need to turn off.
1235 Likewise, don't do anything if the frame is garbaged;
1236 in that case, the frame's current matrix that we would use
1237 is all wrong, and we will redisplay that line anyway. */
1238 if (!NILP (display_info->mouse_face_window)
1239 && w == XWINDOW (display_info->mouse_face_window))
1240 {
1241 int i;
1242
1243 for (i = 0; i < w->desired_matrix->nrows; ++i)
1244 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1245 break;
1246
1247 if (i < w->desired_matrix->nrows)
1248 clear_mouse_face (display_info);
1249 }
1250 #endif /* 0 */
1251 }
1252
1253 UNBLOCK_INPUT;
1254 }
1255
1256
1257 /* Draw a vertical window border to the right of window W if W doesn't
1258 have vertical scroll bars. */
1259
1260 static void
1261 x_draw_vertical_border (w)
1262 struct window *w;
1263 {
1264 struct frame *f = XFRAME (WINDOW_FRAME (w));
1265
1266 /* Redraw borders between horizontally adjacent windows. Don't
1267 do it for frames with vertical scroll bars because either the
1268 right scroll bar of a window, or the left scroll bar of its
1269 neighbor will suffice as a border. */
1270 if (!WINDOW_RIGHTMOST_P (w)
1271 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1272 {
1273 int x0, x1, y0, y1;
1274
1275 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
1276 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1277 y1 -= 1;
1278
1279 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1280 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1281 }
1282 }
1283
1284
1285 /* End update of window W (which is equal to updated_window).
1286
1287 Draw vertical borders between horizontally adjacent windows, and
1288 display W's cursor if CURSOR_ON_P is non-zero.
1289
1290 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1291 glyphs in mouse-face were overwritten. In that case we have to
1292 make sure that the mouse-highlight is properly redrawn.
1293
1294 W may be a menu bar pseudo-window in case we don't have X toolkit
1295 support. Such windows don't have a cursor, so don't display it
1296 here. */
1297
1298 static void
1299 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1300 struct window *w;
1301 int cursor_on_p, mouse_face_overwritten_p;
1302 {
1303 struct mac_display_info *dpyinfo
1304 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1305
1306 if (!w->pseudo_window_p)
1307 {
1308 BLOCK_INPUT;
1309
1310 if (cursor_on_p)
1311 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1312 output_cursor.vpos,
1313 output_cursor.x, output_cursor.y);
1314
1315 x_draw_vertical_border (w);
1316 UNBLOCK_INPUT;
1317 }
1318
1319 /* If a row with mouse-face was overwritten, arrange for
1320 XTframe_up_to_date to redisplay the mouse highlight. */
1321 if (mouse_face_overwritten_p)
1322 {
1323 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1324 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1325 dpyinfo->mouse_face_window = Qnil;
1326 }
1327
1328 #if 0
1329 /* Unhide the caret. This won't actually show the cursor, unless it
1330 was visible before the corresponding call to HideCaret in
1331 x_update_window_begin. */
1332 if (w32_use_visible_system_caret)
1333 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1334 #endif
1335
1336 updated_window = NULL;
1337 }
1338
1339
1340 /* End update of frame F. This function is installed as a hook in
1341 update_end. */
1342
1343 static void
1344 x_update_end (f)
1345 struct frame *f;
1346 {
1347 /* Reset the background color of Mac OS Window to that of the frame after
1348 update so that it is used by Mac Toolbox to clear the update region before
1349 an update event is generated. */
1350 #if TARGET_API_MAC_CARBON
1351 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1352 #else
1353 SetPort (FRAME_MAC_WINDOW (f));
1354 #endif
1355
1356 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1357
1358 /* Mouse highlight may be displayed again. */
1359 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1360
1361 BLOCK_INPUT;
1362 XFlush (FRAME_MAC_DISPLAY (f));
1363 UNBLOCK_INPUT;
1364 }
1365
1366
1367 /* This function is called from various places in xdisp.c whenever a
1368 complete update has been performed. The global variable
1369 updated_window is not available here. */
1370
1371 static void
1372 XTframe_up_to_date (f)
1373 struct frame *f;
1374 {
1375 if (FRAME_X_P (f))
1376 {
1377 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1378
1379 if (dpyinfo->mouse_face_deferred_gc
1380 || f == dpyinfo->mouse_face_mouse_frame)
1381 {
1382 BLOCK_INPUT;
1383 if (dpyinfo->mouse_face_mouse_frame)
1384 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1385 dpyinfo->mouse_face_mouse_x,
1386 dpyinfo->mouse_face_mouse_y);
1387 dpyinfo->mouse_face_deferred_gc = 0;
1388 UNBLOCK_INPUT;
1389 }
1390 }
1391 }
1392
1393
1394 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1395 arrow bitmaps, or clear the fringes if no bitmaps are required
1396 before DESIRED_ROW is made current. The window being updated is
1397 found in updated_window. This function is called from
1398 update_window_line only if it is known that there are differences
1399 between bitmaps to be drawn between current row and DESIRED_ROW. */
1400
1401 static void
1402 x_after_update_window_line (desired_row)
1403 struct glyph_row *desired_row;
1404 {
1405 struct window *w = updated_window;
1406 struct frame *f;
1407 int width, height;
1408
1409 xassert (w);
1410
1411 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1412 {
1413 BLOCK_INPUT;
1414 x_draw_row_fringe_bitmaps (w, desired_row);
1415 UNBLOCK_INPUT;
1416 }
1417
1418 /* When a window has disappeared, make sure that no rest of
1419 full-width rows stays visible in the internal border. Could
1420 check here if updated_window is the leftmost/rightmost window,
1421 but I guess it's not worth doing since vertically split windows
1422 are almost never used, internal border is rarely set, and the
1423 overhead is very small. */
1424 if (windows_or_buffers_changed
1425 && desired_row->full_width_p
1426 && (f = XFRAME (w->frame),
1427 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1428 width != 0)
1429 && (height = desired_row->visible_height,
1430 height > 0))
1431 {
1432 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1433 /* Internal border is drawn below the tool bar. */
1434 if (WINDOWP (f->tool_bar_window)
1435 && w == XWINDOW (f->tool_bar_window))
1436 y -= width;
1437
1438 BLOCK_INPUT;
1439
1440 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1441 0, y, width, height, 0);
1442 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1443 f->output_data.mac->pixel_width - width, y,
1444 width, height, 0);
1445
1446 UNBLOCK_INPUT;
1447 }
1448 }
1449
1450
1451 /* Draw the bitmap WHICH in one of the left or right fringes of
1452 window W. ROW is the glyph row for which to display the bitmap; it
1453 determines the vertical position at which the bitmap has to be
1454 drawn. */
1455
1456 static void
1457 x_draw_fringe_bitmap (w, row, which, left_p)
1458 struct window *w;
1459 struct glyph_row *row;
1460 enum fringe_bitmap_type which;
1461 int left_p;
1462 {
1463 struct frame *f = XFRAME (WINDOW_FRAME (w));
1464 Display *display = FRAME_MAC_DISPLAY (f);
1465 WindowPtr window = FRAME_MAC_WINDOW (f);
1466 int x, y, wd, h, dy;
1467 int b1, b2;
1468 unsigned char *bits;
1469 BitMap bitmap;
1470 XGCValues gcv;
1471 GC gc = f->output_data.mac->normal_gc;
1472 struct face *face;
1473
1474 /* Must clip because of partially visible lines. */
1475 x_clip_to_row (w, row, gc, 1);
1476
1477 /* Convert row to frame coordinates. */
1478 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1479
1480 switch (which)
1481 {
1482 case NO_FRINGE_BITMAP:
1483 wd = 0;
1484 h = 0;
1485 break;
1486
1487 case LEFT_TRUNCATION_BITMAP:
1488 wd = left_width;
1489 h = left_height;
1490 bits = left_bits;
1491 break;
1492
1493 case OVERLAY_ARROW_BITMAP:
1494 wd = ov_width;
1495 h = ov_height;
1496 bits = ov_bits;
1497 break;
1498
1499 case RIGHT_TRUNCATION_BITMAP:
1500 wd = right_width;
1501 h = right_height;
1502 bits = right_bits;
1503 break;
1504
1505 case CONTINUED_LINE_BITMAP:
1506 wd = continued_width;
1507 h = continued_height;
1508 bits = continued_bits;
1509 break;
1510
1511 case CONTINUATION_LINE_BITMAP:
1512 wd = continuation_width;
1513 h = continuation_height;
1514 bits = continuation_bits;
1515 break;
1516
1517 case ZV_LINE_BITMAP:
1518 wd = zv_width;
1519 h = zv_height - (y % zv_period);
1520 bits = zv_bits + (y % zv_period);
1521 break;
1522
1523 default:
1524 abort ();
1525 }
1526
1527 /* Clip bitmap if too high. */
1528 if (h > row->height)
1529 h = row->height;
1530
1531 /* Set dy to the offset in the row to start drawing the bitmap. */
1532 dy = (row->height - h) / 2;
1533
1534 /* Draw the bitmap. */
1535 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
1536 PREPARE_FACE_FOR_DISPLAY (f, face);
1537
1538 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1539 the fringe. */
1540 b1 = -1;
1541 if (left_p)
1542 {
1543 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
1544 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
1545 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1546 - wd
1547 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
1548 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
1549 {
1550 /* If W has a vertical border to its left, don't draw over it. */
1551 int border = ((XFASTINT (w->left) > 0
1552 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1553 ? 1 : 0);
1554 b1 = (window_box_left (w, -1)
1555 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1556 + border);
1557 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1558 }
1559 }
1560 else
1561 {
1562 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
1563 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1564 x = (window_box_right (w, -1)
1565 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
1566 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1567 the fringe. */
1568 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
1569 {
1570 b1 = window_box_right (w, -1);
1571 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1572 }
1573 }
1574
1575 if (b1 >= 0)
1576 {
1577 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1578 XGCValues gcv;
1579 gcv.foreground = face->background;
1580
1581 #if 0 /* MAC_TODO: stipple */
1582 /* In case the same realized face is used for fringes and
1583 for something displayed in the text (e.g. face `region' on
1584 mono-displays, the fill style may have been changed to
1585 FillSolid in x_draw_glyph_string_background. */
1586 if (face->stipple)
1587 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1588 else
1589 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1590 #endif
1591
1592 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1593 &gcv,
1594 b1,
1595 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1596 row->y)),
1597 b2,
1598 row->visible_height);
1599
1600 #if 0 /* MAC_TODO: stipple */
1601 if (!face->stipple)
1602 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1603 #endif
1604 }
1605
1606 if (which == NO_FRINGE_BITMAP)
1607 {
1608 mac_reset_clipping (display, window);
1609 return;
1610 }
1611
1612 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1613 gcv.foreground = face->foreground;
1614 gcv.background = face->background;
1615
1616 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1617
1618 mac_free_bitmap (&bitmap);
1619 mac_reset_clipping (display, window);
1620 }
1621
1622
1623 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1624 function with input blocked. */
1625
1626 static void
1627 x_draw_row_fringe_bitmaps (w, row)
1628 struct window *w;
1629 struct glyph_row *row;
1630 {
1631 struct frame *f = XFRAME (w->frame);
1632 enum fringe_bitmap_type bitmap;
1633
1634 xassert (interrupt_input_blocked);
1635
1636 /* If row is completely invisible, because of vscrolling, we
1637 don't have to draw anything. */
1638 if (row->visible_height <= 0)
1639 return;
1640
1641 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1642 {
1643 /* Decide which bitmap to draw in the left fringe. */
1644 if (row->overlay_arrow_p)
1645 bitmap = OVERLAY_ARROW_BITMAP;
1646 else if (row->truncated_on_left_p)
1647 bitmap = LEFT_TRUNCATION_BITMAP;
1648 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1649 bitmap = CONTINUATION_LINE_BITMAP;
1650 else if (row->indicate_empty_line_p)
1651 bitmap = ZV_LINE_BITMAP;
1652 else
1653 bitmap = NO_FRINGE_BITMAP;
1654
1655 x_draw_fringe_bitmap (w, row, bitmap, 1);
1656 }
1657
1658 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1659 {
1660 /* Decide which bitmap to draw in the right fringe. */
1661 if (row->truncated_on_right_p)
1662 bitmap = RIGHT_TRUNCATION_BITMAP;
1663 else if (row->continued_p)
1664 bitmap = CONTINUED_LINE_BITMAP;
1665 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1666 bitmap = ZV_LINE_BITMAP;
1667 else
1668 bitmap = NO_FRINGE_BITMAP;
1669
1670 x_draw_fringe_bitmap (w, row, bitmap, 0);
1671 }
1672 }
1673
1674 \f
1675 /* This is called when starting Emacs and when restarting after
1676 suspend. When starting Emacs, no window is mapped. And nothing
1677 must be done to Emacs's own window if it is suspended (though that
1678 rarely happens). */
1679
1680 static void
1681 XTset_terminal_modes ()
1682 {
1683 }
1684
1685 /* This is called when exiting or suspending Emacs. Exiting will make
1686 the windows go away, and suspending requires no action. */
1687
1688 static void
1689 XTreset_terminal_modes ()
1690 {
1691 }
1692
1693
1694 \f
1695 /***********************************************************************
1696 Output Cursor
1697 ***********************************************************************/
1698
1699 /* Set the global variable output_cursor to CURSOR. All cursor
1700 positions are relative to updated_window. */
1701
1702 static void
1703 set_output_cursor (cursor)
1704 struct cursor_pos *cursor;
1705 {
1706 output_cursor.hpos = cursor->hpos;
1707 output_cursor.vpos = cursor->vpos;
1708 output_cursor.x = cursor->x;
1709 output_cursor.y = cursor->y;
1710 }
1711
1712
1713 /* Set a nominal cursor position.
1714
1715 HPOS and VPOS are column/row positions in a window glyph matrix. X
1716 and Y are window text area relative pixel positions.
1717
1718 If this is done during an update, updated_window will contain the
1719 window that is being updated and the position is the future output
1720 cursor position for that window. If updated_window is null, use
1721 selected_window and display the cursor at the given position. */
1722
1723 static void
1724 XTcursor_to (vpos, hpos, y, x)
1725 int vpos, hpos, y, x;
1726 {
1727 struct window *w;
1728
1729 /* If updated_window is not set, work on selected_window. */
1730 if (updated_window)
1731 w = updated_window;
1732 else
1733 w = XWINDOW (selected_window);
1734
1735 /* Set the output cursor. */
1736 output_cursor.hpos = hpos;
1737 output_cursor.vpos = vpos;
1738 output_cursor.x = x;
1739 output_cursor.y = y;
1740
1741 /* If not called as part of an update, really display the cursor.
1742 This will also set the cursor position of W. */
1743 if (updated_window == NULL)
1744 {
1745 BLOCK_INPUT;
1746 x_display_cursor (w, 1, hpos, vpos, x, y);
1747 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1748 UNBLOCK_INPUT;
1749 }
1750 }
1751
1752
1753 \f
1754 /***********************************************************************
1755 Display Iterator
1756 ***********************************************************************/
1757
1758 /* Function prototypes of this page. */
1759
1760 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1761 struct glyph *,
1762 XChar2b *,
1763 int *));
1764 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1765 int, XChar2b *, int));
1766 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1767 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1768 static void x_append_glyph P_ ((struct it *));
1769 static void x_append_composite_glyph P_ ((struct it *));
1770 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1771 int, int, double));
1772 static void x_produce_glyphs P_ ((struct it *));
1773 static void x_produce_image_glyph P_ ((struct it *it));
1774
1775
1776 /* Return a pointer to per-char metric information in FONT of a
1777 character pointed by B which is a pointer to an XChar2b. */
1778
1779 #define PER_CHAR_METRIC(font, b) \
1780 ((font)->per_char \
1781 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1782 + (((font)->min_byte1 || (font)->max_byte1) \
1783 ? (((b)->byte1 - (font)->min_byte1) \
1784 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1785 : 0)) \
1786 : &((font)->max_bounds))
1787
1788
1789 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1790 is not contained in the font. */
1791
1792 static INLINE XCharStruct *
1793 x_per_char_metric (font, char2b)
1794 XFontStruct *font;
1795 XChar2b *char2b;
1796 {
1797 /* The result metric information. */
1798 XCharStruct *pcm = NULL;
1799
1800 xassert (font && char2b);
1801
1802 if (font->per_char != NULL)
1803 {
1804 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1805 {
1806 /* min_char_or_byte2 specifies the linear character index
1807 corresponding to the first element of the per_char array,
1808 max_char_or_byte2 is the index of the last character. A
1809 character with non-zero CHAR2B->byte1 is not in the font.
1810 A character with byte2 less than min_char_or_byte2 or
1811 greater max_char_or_byte2 is not in the font. */
1812 if (char2b->byte1 == 0
1813 && char2b->byte2 >= font->min_char_or_byte2
1814 && char2b->byte2 <= font->max_char_or_byte2)
1815 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1816 }
1817 else
1818 {
1819 /* If either min_byte1 or max_byte1 are nonzero, both
1820 min_char_or_byte2 and max_char_or_byte2 are less than
1821 256, and the 2-byte character index values corresponding
1822 to the per_char array element N (counting from 0) are:
1823
1824 byte1 = N/D + min_byte1
1825 byte2 = N\D + min_char_or_byte2
1826
1827 where:
1828
1829 D = max_char_or_byte2 - min_char_or_byte2 + 1
1830 / = integer division
1831 \ = integer modulus */
1832 if (char2b->byte1 >= font->min_byte1
1833 && char2b->byte1 <= font->max_byte1
1834 && char2b->byte2 >= font->min_char_or_byte2
1835 && char2b->byte2 <= font->max_char_or_byte2)
1836 {
1837 pcm = (font->per_char
1838 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1839 * (char2b->byte1 - font->min_byte1))
1840 + (char2b->byte2 - font->min_char_or_byte2));
1841 }
1842 }
1843 }
1844 else
1845 {
1846 /* If the per_char pointer is null, all glyphs between the first
1847 and last character indexes inclusive have the same
1848 information, as given by both min_bounds and max_bounds. */
1849 if (char2b->byte2 >= font->min_char_or_byte2
1850 && char2b->byte2 <= font->max_char_or_byte2)
1851 pcm = &font->max_bounds;
1852 }
1853
1854 return ((pcm == NULL
1855 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1856 ? NULL : pcm);
1857 }
1858
1859
1860 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1861 the two-byte form of C. Encoding is returned in *CHAR2B. */
1862
1863 static INLINE void
1864 x_encode_char (c, char2b, font_info)
1865 int c;
1866 XChar2b *char2b;
1867 struct font_info *font_info;
1868 {
1869 int charset = CHAR_CHARSET (c);
1870 XFontStruct *font = font_info->font;
1871
1872 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1873 This may be either a program in a special encoder language or a
1874 fixed encoding. */
1875 if (font_info->font_encoder)
1876 {
1877 /* It's a program. */
1878 struct ccl_program *ccl = font_info->font_encoder;
1879
1880 if (CHARSET_DIMENSION (charset) == 1)
1881 {
1882 ccl->reg[0] = charset;
1883 ccl->reg[1] = char2b->byte2;
1884 }
1885 else
1886 {
1887 ccl->reg[0] = charset;
1888 ccl->reg[1] = char2b->byte1;
1889 ccl->reg[2] = char2b->byte2;
1890 }
1891
1892 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1893
1894 /* We assume that MSBs are appropriately set/reset by CCL
1895 program. */
1896 if (font->max_byte1 == 0) /* 1-byte font */
1897 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1898 else
1899 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1900 }
1901 else if (font_info->encoding[charset])
1902 {
1903 /* Fixed encoding scheme. See fontset.h for the meaning of the
1904 encoding numbers. */
1905 int enc = font_info->encoding[charset];
1906
1907 if ((enc == 1 || enc == 2)
1908 && CHARSET_DIMENSION (charset) == 2)
1909 char2b->byte1 |= 0x80;
1910
1911 if (enc == 1 || enc == 3)
1912 char2b->byte2 |= 0x80;
1913
1914 if (enc == 4)
1915 {
1916 int sjis1, sjis2;
1917
1918 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1919 char2b->byte1 = sjis1;
1920 char2b->byte2 = sjis2;
1921 }
1922 }
1923 }
1924
1925
1926 /* Get face and two-byte form of character C in face FACE_ID on frame
1927 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1928 means we want to display multibyte text. Value is a pointer to a
1929 realized face that is ready for display. */
1930
1931 static INLINE struct face *
1932 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1933 struct frame *f;
1934 int c, face_id;
1935 XChar2b *char2b;
1936 int multibyte_p;
1937 {
1938 struct face *face = FACE_FROM_ID (f, face_id);
1939
1940 if (!multibyte_p)
1941 {
1942 /* Unibyte case. We don't have to encode, but we have to make
1943 sure to use a face suitable for unibyte. */
1944 char2b->byte1 = 0;
1945 char2b->byte2 = c;
1946 face_id = FACE_FOR_CHAR (f, face, c);
1947 face = FACE_FROM_ID (f, face_id);
1948 }
1949 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1950 {
1951 /* Case of ASCII in a face known to fit ASCII. */
1952 char2b->byte1 = 0;
1953 char2b->byte2 = c;
1954 }
1955 else
1956 {
1957 int c1, c2, charset;
1958
1959 /* Split characters into bytes. If c2 is -1 afterwards, C is
1960 really a one-byte character so that byte1 is zero. */
1961 SPLIT_CHAR (c, charset, c1, c2);
1962 if (c2 > 0)
1963 char2b->byte1 = c1, char2b->byte2 = c2;
1964 else
1965 char2b->byte1 = 0, char2b->byte2 = c1;
1966
1967 /* Maybe encode the character in *CHAR2B. */
1968 if (face->font != NULL)
1969 {
1970 struct font_info *font_info
1971 = FONT_INFO_FROM_ID (f, face->font_info_id);
1972 if (font_info)
1973 x_encode_char (c, char2b, font_info);
1974 }
1975 }
1976
1977 /* Make sure X resources of the face are allocated. */
1978 xassert (face != NULL);
1979 PREPARE_FACE_FOR_DISPLAY (f, face);
1980
1981 return face;
1982 }
1983
1984
1985 /* Get face and two-byte form of character glyph GLYPH on frame F.
1986 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1987 a pointer to a realized face that is ready for display. */
1988
1989 static INLINE struct face *
1990 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1991 struct frame *f;
1992 struct glyph *glyph;
1993 XChar2b *char2b;
1994 int *two_byte_p;
1995 {
1996 struct face *face;
1997
1998 xassert (glyph->type == CHAR_GLYPH);
1999 face = FACE_FROM_ID (f, glyph->face_id);
2000
2001 if (two_byte_p)
2002 *two_byte_p = 0;
2003
2004 if (!glyph->multibyte_p)
2005 {
2006 /* Unibyte case. We don't have to encode, but we have to make
2007 sure to use a face suitable for unibyte. */
2008 char2b->byte1 = 0;
2009 char2b->byte2 = glyph->u.ch;
2010 }
2011 else if (glyph->u.ch < 128
2012 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
2013 {
2014 /* Case of ASCII in a face known to fit ASCII. */
2015 char2b->byte1 = 0;
2016 char2b->byte2 = glyph->u.ch;
2017 }
2018 else
2019 {
2020 int c1, c2, charset;
2021
2022 /* Split characters into bytes. If c2 is -1 afterwards, C is
2023 really a one-byte character so that byte1 is zero. */
2024 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
2025 if (c2 > 0)
2026 char2b->byte1 = c1, char2b->byte2 = c2;
2027 else
2028 char2b->byte1 = 0, char2b->byte2 = c1;
2029
2030 /* Maybe encode the character in *CHAR2B. */
2031 if (charset != CHARSET_ASCII)
2032 {
2033 struct font_info *font_info
2034 = FONT_INFO_FROM_ID (f, face->font_info_id);
2035 if (font_info)
2036 {
2037 x_encode_char (glyph->u.ch, char2b, font_info);
2038 if (two_byte_p)
2039 *two_byte_p
2040 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2041 }
2042 }
2043 }
2044
2045 /* Make sure X resources of the face are allocated. */
2046 xassert (face != NULL);
2047 PREPARE_FACE_FOR_DISPLAY (f, face);
2048 return face;
2049 }
2050
2051
2052 /* Store one glyph for IT->char_to_display in IT->glyph_row.
2053 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2054
2055 static INLINE void
2056 x_append_glyph (it)
2057 struct it *it;
2058 {
2059 struct glyph *glyph;
2060 enum glyph_row_area area = it->area;
2061
2062 xassert (it->glyph_row);
2063 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
2064
2065 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2066 if (glyph < it->glyph_row->glyphs[area + 1])
2067 {
2068 glyph->charpos = CHARPOS (it->position);
2069 glyph->object = it->object;
2070 glyph->pixel_width = it->pixel_width;
2071 glyph->voffset = it->voffset;
2072 glyph->type = CHAR_GLYPH;
2073 glyph->multibyte_p = it->multibyte_p;
2074 glyph->left_box_line_p = it->start_of_box_run_p;
2075 glyph->right_box_line_p = it->end_of_box_run_p;
2076 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2077 || it->phys_descent > it->descent);
2078 glyph->padding_p = 0;
2079 glyph->glyph_not_available_p = it->glyph_not_available_p;
2080 glyph->face_id = it->face_id;
2081 glyph->u.ch = it->char_to_display;
2082 ++it->glyph_row->used[area];
2083 }
2084 }
2085
2086 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2087 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2088
2089 static INLINE void
2090 x_append_composite_glyph (it)
2091 struct it *it;
2092 {
2093 struct glyph *glyph;
2094 enum glyph_row_area area = it->area;
2095
2096 xassert (it->glyph_row);
2097
2098 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2099 if (glyph < it->glyph_row->glyphs[area + 1])
2100 {
2101 glyph->charpos = CHARPOS (it->position);
2102 glyph->object = it->object;
2103 glyph->pixel_width = it->pixel_width;
2104 glyph->voffset = it->voffset;
2105 glyph->type = COMPOSITE_GLYPH;
2106 glyph->multibyte_p = it->multibyte_p;
2107 glyph->left_box_line_p = it->start_of_box_run_p;
2108 glyph->right_box_line_p = it->end_of_box_run_p;
2109 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2110 || it->phys_descent > it->descent);
2111 glyph->padding_p = 0;
2112 glyph->glyph_not_available_p = 0;
2113 glyph->face_id = it->face_id;
2114 glyph->u.cmp_id = it->cmp_id;
2115 ++it->glyph_row->used[area];
2116 }
2117 }
2118
2119
2120 /* Change IT->ascent and IT->height according to the setting of
2121 IT->voffset. */
2122
2123 static INLINE void
2124 take_vertical_position_into_account (it)
2125 struct it *it;
2126 {
2127 if (it->voffset)
2128 {
2129 if (it->voffset < 0)
2130 /* Increase the ascent so that we can display the text higher
2131 in the line. */
2132 it->ascent += abs (it->voffset);
2133 else
2134 /* Increase the descent so that we can display the text lower
2135 in the line. */
2136 it->descent += it->voffset;
2137 }
2138 }
2139
2140
2141 /* Produce glyphs/get display metrics for the image IT is loaded with.
2142 See the description of struct display_iterator in dispextern.h for
2143 an overview of struct display_iterator. */
2144
2145 static void
2146 x_produce_image_glyph (it)
2147 struct it *it;
2148 {
2149 struct image *img;
2150 struct face *face;
2151
2152 xassert (it->what == IT_IMAGE);
2153
2154 face = FACE_FROM_ID (it->f, it->face_id);
2155 img = IMAGE_FROM_ID (it->f, it->image_id);
2156 xassert (img);
2157
2158 /* Make sure X resources of the face and image are loaded. */
2159 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2160 prepare_image_for_display (it->f, img);
2161
2162 it->ascent = it->phys_ascent = image_ascent (img, face);
2163 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
2164 it->pixel_width = img->width + 2 * img->hmargin;
2165
2166 it->nglyphs = 1;
2167
2168 if (face->box != FACE_NO_BOX)
2169 {
2170 if (face->box_line_width > 0)
2171 {
2172 it->ascent += face->box_line_width;
2173 it->descent += face->box_line_width;
2174 }
2175
2176 if (it->start_of_box_run_p)
2177 it->pixel_width += abs (face->box_line_width);
2178 if (it->end_of_box_run_p)
2179 it->pixel_width += abs (face->box_line_width);
2180 }
2181
2182 take_vertical_position_into_account (it);
2183
2184 if (it->glyph_row)
2185 {
2186 struct glyph *glyph;
2187 enum glyph_row_area area = it->area;
2188
2189 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2190 if (glyph < it->glyph_row->glyphs[area + 1])
2191 {
2192 glyph->charpos = CHARPOS (it->position);
2193 glyph->object = it->object;
2194 glyph->pixel_width = it->pixel_width;
2195 glyph->voffset = it->voffset;
2196 glyph->type = IMAGE_GLYPH;
2197 glyph->multibyte_p = it->multibyte_p;
2198 glyph->left_box_line_p = it->start_of_box_run_p;
2199 glyph->right_box_line_p = it->end_of_box_run_p;
2200 glyph->overlaps_vertically_p = 0;
2201 glyph->padding_p = 0;
2202 glyph->glyph_not_available_p = 0;
2203 glyph->face_id = it->face_id;
2204 glyph->u.img_id = img->id;
2205 ++it->glyph_row->used[area];
2206 }
2207 }
2208 }
2209
2210
2211 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2212 of the glyph, WIDTH and HEIGHT are the width and height of the
2213 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2214 ascent of the glyph (0 <= ASCENT <= 1). */
2215
2216 static void
2217 x_append_stretch_glyph (it, object, width, height, ascent)
2218 struct it *it;
2219 Lisp_Object object;
2220 int width, height;
2221 double ascent;
2222 {
2223 struct glyph *glyph;
2224 enum glyph_row_area area = it->area;
2225
2226 xassert (ascent >= 0 && ascent <= 1);
2227
2228 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2229 if (glyph < it->glyph_row->glyphs[area + 1])
2230 {
2231 glyph->charpos = CHARPOS (it->position);
2232 glyph->object = object;
2233 glyph->pixel_width = width;
2234 glyph->voffset = it->voffset;
2235 glyph->type = STRETCH_GLYPH;
2236 glyph->multibyte_p = it->multibyte_p;
2237 glyph->left_box_line_p = it->start_of_box_run_p;
2238 glyph->right_box_line_p = it->end_of_box_run_p;
2239 glyph->overlaps_vertically_p = 0;
2240 glyph->padding_p = 0;
2241 glyph->glyph_not_available_p = 0;
2242 glyph->face_id = it->face_id;
2243 glyph->u.stretch.ascent = height * ascent;
2244 glyph->u.stretch.height = height;
2245 ++it->glyph_row->used[area];
2246 }
2247 }
2248
2249
2250 /* Produce a stretch glyph for iterator IT. IT->object is the value
2251 of the glyph property displayed. The value must be a list
2252 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2253 being recognized:
2254
2255 1. `:width WIDTH' specifies that the space should be WIDTH *
2256 canonical char width wide. WIDTH may be an integer or floating
2257 point number.
2258
2259 2. `:relative-width FACTOR' specifies that the width of the stretch
2260 should be computed from the width of the first character having the
2261 `glyph' property, and should be FACTOR times that width.
2262
2263 3. `:align-to HPOS' specifies that the space should be wide enough
2264 to reach HPOS, a value in canonical character units.
2265
2266 Exactly one of the above pairs must be present.
2267
2268 4. `:height HEIGHT' specifies that the height of the stretch produced
2269 should be HEIGHT, measured in canonical character units.
2270
2271 5. `:relative-height FACTOR' specifies that the height of the
2272 stretch should be FACTOR times the height of the characters having
2273 the glyph property.
2274
2275 Either none or exactly one of 4 or 5 must be present.
2276
2277 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2278 of the stretch should be used for the ascent of the stretch.
2279 ASCENT must be in the range 0 <= ASCENT <= 100. */
2280
2281 #define NUMVAL(X) \
2282 ((INTEGERP (X) || FLOATP (X)) \
2283 ? XFLOATINT (X) \
2284 : - 1)
2285
2286
2287 static void
2288 x_produce_stretch_glyph (it)
2289 struct it *it;
2290 {
2291 /* (space :width WIDTH :height HEIGHT. */
2292 #if GLYPH_DEBUG
2293 extern Lisp_Object Qspace;
2294 #endif
2295 extern Lisp_Object QCwidth, QCheight, QCascent;
2296 extern Lisp_Object QCrelative_width, QCrelative_height;
2297 extern Lisp_Object QCalign_to;
2298 Lisp_Object prop, plist;
2299 double width = 0, height = 0, ascent = 0;
2300 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2301 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2302
2303 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2304
2305 /* List should start with `space'. */
2306 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2307 plist = XCDR (it->object);
2308
2309 /* Compute the width of the stretch. */
2310 if (prop = Fplist_get (plist, QCwidth),
2311 NUMVAL (prop) > 0)
2312 /* Absolute width `:width WIDTH' specified and valid. */
2313 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2314 else if (prop = Fplist_get (plist, QCrelative_width),
2315 NUMVAL (prop) > 0)
2316 {
2317 /* Relative width `:relative-width FACTOR' specified and valid.
2318 Compute the width of the characters having the `glyph'
2319 property. */
2320 struct it it2;
2321 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2322
2323 it2 = *it;
2324 if (it->multibyte_p)
2325 {
2326 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2327 - IT_BYTEPOS (*it));
2328 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2329 }
2330 else
2331 it2.c = *p, it2.len = 1;
2332
2333 it2.glyph_row = NULL;
2334 it2.what = IT_CHARACTER;
2335 x_produce_glyphs (&it2);
2336 width = NUMVAL (prop) * it2.pixel_width;
2337 }
2338 else if (prop = Fplist_get (plist, QCalign_to),
2339 NUMVAL (prop) > 0)
2340 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2341 else
2342 /* Nothing specified -> width defaults to canonical char width. */
2343 width = CANON_X_UNIT (it->f);
2344
2345 /* Compute height. */
2346 if (prop = Fplist_get (plist, QCheight),
2347 NUMVAL (prop) > 0)
2348 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2349 else if (prop = Fplist_get (plist, QCrelative_height),
2350 NUMVAL (prop) > 0)
2351 height = FONT_HEIGHT (font) * NUMVAL (prop);
2352 else
2353 height = FONT_HEIGHT (font);
2354
2355 /* Compute percentage of height used for ascent. If
2356 `:ascent ASCENT' is present and valid, use that. Otherwise,
2357 derive the ascent from the font in use. */
2358 if (prop = Fplist_get (plist, QCascent),
2359 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2360 ascent = NUMVAL (prop) / 100.0;
2361 else
2362 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
2363
2364 if (width <= 0)
2365 width = 1;
2366 if (height <= 0)
2367 height = 1;
2368
2369 if (it->glyph_row)
2370 {
2371 Lisp_Object object = it->stack[it->sp - 1].string;
2372 if (!STRINGP (object))
2373 object = it->w->buffer;
2374 x_append_stretch_glyph (it, object, width, height, ascent);
2375 }
2376
2377 it->pixel_width = width;
2378 it->ascent = it->phys_ascent = height * ascent;
2379 it->descent = it->phys_descent = height - it->ascent;
2380 it->nglyphs = 1;
2381
2382 if (face->box != FACE_NO_BOX)
2383 {
2384 if (face->box_line_width > 0)
2385 {
2386 it->ascent += face->box_line_width;
2387 it->descent += face->box_line_width;
2388 }
2389
2390 if (it->start_of_box_run_p)
2391 it->pixel_width += abs (face->box_line_width);
2392 if (it->end_of_box_run_p)
2393 it->pixel_width += abs (face->box_line_width);
2394 }
2395
2396 take_vertical_position_into_account (it);
2397 }
2398
2399 /* Return proper value to be used as baseline offset of font that has
2400 ASCENT and DESCENT to draw characters by the font at the vertical
2401 center of the line of frame F.
2402
2403 Here, out task is to find the value of BOFF in the following figure;
2404
2405 -------------------------+-----------+-
2406 -+-+---------+-+ | |
2407 | | | | | |
2408 | | | | F_ASCENT F_HEIGHT
2409 | | | ASCENT | |
2410 HEIGHT | | | | |
2411 | | |-|-+------+-----------|------- baseline
2412 | | | | BOFF | |
2413 | |---------|-+-+ | |
2414 | | | DESCENT | |
2415 -+-+---------+-+ F_DESCENT |
2416 -------------------------+-----------+-
2417
2418 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2419 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2420 DESCENT = FONT->descent
2421 HEIGHT = FONT_HEIGHT (FONT)
2422 F_DESCENT = (F->output_data.x->font->descent
2423 - F->output_data.x->baseline_offset)
2424 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2425 */
2426
2427 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2428 (FONT_DESCENT (FONT) \
2429 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2430 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2431 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2432
2433 /* Produce glyphs/get display metrics for the display element IT is
2434 loaded with. See the description of struct display_iterator in
2435 dispextern.h for an overview of struct display_iterator. */
2436
2437 static void
2438 x_produce_glyphs (it)
2439 struct it *it;
2440 {
2441 it->glyph_not_available_p = 0;
2442
2443 if (it->what == IT_CHARACTER)
2444 {
2445 XChar2b char2b;
2446 XFontStruct *font;
2447 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2448 XCharStruct *pcm;
2449 int font_not_found_p;
2450 struct font_info *font_info;
2451 int boff; /* baseline offset */
2452 /* We may change it->multibyte_p upon unibyte<->multibyte
2453 conversion. So, save the current value now and restore it
2454 later.
2455
2456 Note: It seems that we don't have to record multibyte_p in
2457 struct glyph because the character code itself tells if or
2458 not the character is multibyte. Thus, in the future, we must
2459 consider eliminating the field `multibyte_p' in the struct
2460 glyph.
2461 */
2462 int saved_multibyte_p = it->multibyte_p;
2463
2464 /* Maybe translate single-byte characters to multibyte, or the
2465 other way. */
2466 it->char_to_display = it->c;
2467 if (!ASCII_BYTE_P (it->c))
2468 {
2469 if (unibyte_display_via_language_environment
2470 && SINGLE_BYTE_CHAR_P (it->c)
2471 && (it->c >= 0240
2472 || !NILP (Vnonascii_translation_table)))
2473 {
2474 it->char_to_display = unibyte_char_to_multibyte (it->c);
2475 it->multibyte_p = 1;
2476 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2477 face = FACE_FROM_ID (it->f, it->face_id);
2478 }
2479 else if (!SINGLE_BYTE_CHAR_P (it->c)
2480 && !it->multibyte_p)
2481 {
2482 it->multibyte_p = 1;
2483 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2484 face = FACE_FROM_ID (it->f, it->face_id);
2485 }
2486 }
2487
2488 /* Get font to use. Encode IT->char_to_display. */
2489 x_get_char_face_and_encoding (it->f, it->char_to_display,
2490 it->face_id, &char2b,
2491 it->multibyte_p);
2492 font = face->font;
2493
2494 /* When no suitable font found, use the default font. */
2495 font_not_found_p = font == NULL;
2496 if (font_not_found_p)
2497 {
2498 font = FRAME_FONT (it->f);
2499 boff = it->f->output_data.mac->baseline_offset;
2500 font_info = NULL;
2501 }
2502 else
2503 {
2504 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2505 boff = font_info->baseline_offset;
2506 if (font_info->vertical_centering)
2507 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2508 }
2509
2510 if (it->char_to_display >= ' '
2511 && (!it->multibyte_p || it->char_to_display < 128))
2512 {
2513 /* Either unibyte or ASCII. */
2514 int stretched_p;
2515
2516 it->nglyphs = 1;
2517
2518 pcm = x_per_char_metric (font, &char2b);
2519 it->ascent = FONT_BASE (font) + boff;
2520 it->descent = FONT_DESCENT (font) - boff;
2521
2522 if (pcm)
2523 {
2524 it->phys_ascent = pcm->ascent + boff;
2525 it->phys_descent = pcm->descent - boff;
2526 it->pixel_width = pcm->width;
2527 }
2528 else
2529 {
2530 it->glyph_not_available_p = 1;
2531 it->phys_ascent = FONT_BASE (font) + boff;
2532 it->phys_descent = FONT_DESCENT (font) - boff;
2533 it->pixel_width = FONT_WIDTH (font);
2534 }
2535
2536 /* If this is a space inside a region of text with
2537 `space-width' property, change its width. */
2538 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2539 if (stretched_p)
2540 it->pixel_width *= XFLOATINT (it->space_width);
2541
2542 /* If face has a box, add the box thickness to the character
2543 height. If character has a box line to the left and/or
2544 right, add the box line width to the character's width. */
2545 if (face->box != FACE_NO_BOX)
2546 {
2547 int thick = face->box_line_width;
2548
2549 if (thick > 0)
2550 {
2551 it->ascent += thick;
2552 it->descent += thick;
2553 }
2554 else
2555 thick = -thick;
2556
2557 if (it->start_of_box_run_p)
2558 it->pixel_width += thick;
2559 if (it->end_of_box_run_p)
2560 it->pixel_width += thick;
2561 }
2562
2563 /* If face has an overline, add the height of the overline
2564 (1 pixel) and a 1 pixel margin to the character height. */
2565 if (face->overline_p)
2566 it->ascent += 2;
2567
2568 take_vertical_position_into_account (it);
2569
2570 /* If we have to actually produce glyphs, do it. */
2571 if (it->glyph_row)
2572 {
2573 if (stretched_p)
2574 {
2575 /* Translate a space with a `space-width' property
2576 into a stretch glyph. */
2577 double ascent = (double) FONT_BASE (font)
2578 / FONT_HEIGHT (font);
2579 x_append_stretch_glyph (it, it->object, it->pixel_width,
2580 it->ascent + it->descent, ascent);
2581 }
2582 else
2583 x_append_glyph (it);
2584
2585 /* If characters with lbearing or rbearing are displayed
2586 in this line, record that fact in a flag of the
2587 glyph row. This is used to optimize X output code. */
2588 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2589 it->glyph_row->contains_overlapping_glyphs_p = 1;
2590 }
2591 }
2592 else if (it->char_to_display == '\n')
2593 {
2594 /* A newline has no width but we need the height of the line. */
2595 it->pixel_width = 0;
2596 it->nglyphs = 0;
2597 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2598 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2599
2600 if (face->box != FACE_NO_BOX
2601 && face->box_line_width > 0)
2602 {
2603 it->ascent += face->box_line_width;
2604 it->descent += face->box_line_width;
2605 }
2606 }
2607 else if (it->char_to_display == '\t')
2608 {
2609 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2610 int x = it->current_x + it->continuation_lines_width;
2611 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2612
2613 /* If the distance from the current position to the next tab
2614 stop is less than a canonical character width, use the
2615 tab stop after that. */
2616 if (next_tab_x - x < CANON_X_UNIT (it->f))
2617 next_tab_x += tab_width;
2618
2619 it->pixel_width = next_tab_x - x;
2620 it->nglyphs = 1;
2621 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2622 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2623
2624 if (it->glyph_row)
2625 {
2626 double ascent = (double) it->ascent / (it->ascent + it->descent);
2627 x_append_stretch_glyph (it, it->object, it->pixel_width,
2628 it->ascent + it->descent, ascent);
2629 }
2630 }
2631 else
2632 {
2633 /* A multi-byte character. Assume that the display width of the
2634 character is the width of the character multiplied by the
2635 width of the font. */
2636
2637 /* If we found a font, this font should give us the right
2638 metrics. If we didn't find a font, use the frame's
2639 default font and calculate the width of the character
2640 from the charset width; this is what old redisplay code
2641 did. */
2642 pcm = x_per_char_metric (font, &char2b);
2643 if (font_not_found_p || !pcm)
2644 {
2645 int charset = CHAR_CHARSET (it->char_to_display);
2646
2647 it->glyph_not_available_p = 1;
2648 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2649 * CHARSET_WIDTH (charset));
2650 it->phys_ascent = FONT_BASE (font) + boff;
2651 it->phys_descent = FONT_DESCENT (font) - boff;
2652 }
2653 else
2654 {
2655 it->pixel_width = pcm->width;
2656 it->phys_ascent = pcm->ascent + boff;
2657 it->phys_descent = pcm->descent - boff;
2658 if (it->glyph_row
2659 && (pcm->lbearing < 0
2660 || pcm->rbearing > pcm->width))
2661 it->glyph_row->contains_overlapping_glyphs_p = 1;
2662 }
2663 it->nglyphs = 1;
2664 it->ascent = FONT_BASE (font) + boff;
2665 it->descent = FONT_DESCENT (font) - boff;
2666 if (face->box != FACE_NO_BOX)
2667 {
2668 int thick = face->box_line_width;
2669
2670 if (thick > 0)
2671 {
2672 it->ascent += thick;
2673 it->descent += thick;
2674 }
2675 else
2676 thick = - thick;
2677
2678 if (it->start_of_box_run_p)
2679 it->pixel_width += thick;
2680 if (it->end_of_box_run_p)
2681 it->pixel_width += thick;
2682 }
2683
2684 /* If face has an overline, add the height of the overline
2685 (1 pixel) and a 1 pixel margin to the character height. */
2686 if (face->overline_p)
2687 it->ascent += 2;
2688
2689 take_vertical_position_into_account (it);
2690
2691 if (it->glyph_row)
2692 x_append_glyph (it);
2693 }
2694 it->multibyte_p = saved_multibyte_p;
2695 }
2696 else if (it->what == IT_COMPOSITION)
2697 {
2698 /* Note: A composition is represented as one glyph in the
2699 glyph matrix. There are no padding glyphs. */
2700 XChar2b char2b;
2701 XFontStruct *font;
2702 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2703 XCharStruct *pcm;
2704 int font_not_found_p;
2705 struct font_info *font_info;
2706 int boff; /* baseline offset */
2707 struct composition *cmp = composition_table[it->cmp_id];
2708
2709 /* Maybe translate single-byte characters to multibyte. */
2710 it->char_to_display = it->c;
2711 if (unibyte_display_via_language_environment
2712 && SINGLE_BYTE_CHAR_P (it->c)
2713 && (it->c >= 0240
2714 || (it->c >= 0200
2715 && !NILP (Vnonascii_translation_table))))
2716 {
2717 it->char_to_display = unibyte_char_to_multibyte (it->c);
2718 }
2719
2720 /* Get face and font to use. Encode IT->char_to_display. */
2721 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2722 face = FACE_FROM_ID (it->f, it->face_id);
2723 x_get_char_face_and_encoding (it->f, it->char_to_display,
2724 it->face_id, &char2b, it->multibyte_p);
2725 font = face->font;
2726
2727 /* When no suitable font found, use the default font. */
2728 font_not_found_p = font == NULL;
2729 if (font_not_found_p)
2730 {
2731 font = FRAME_FONT (it->f);
2732 boff = it->f->output_data.mac->baseline_offset;
2733 font_info = NULL;
2734 }
2735 else
2736 {
2737 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2738 boff = font_info->baseline_offset;
2739 if (font_info->vertical_centering)
2740 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2741 }
2742
2743 /* There are no padding glyphs, so there is only one glyph to
2744 produce for the composition. Important is that pixel_width,
2745 ascent and descent are the values of what is drawn by
2746 draw_glyphs (i.e. the values of the overall glyphs composed). */
2747 it->nglyphs = 1;
2748
2749 /* If we have not yet calculated pixel size data of glyphs of
2750 the composition for the current face font, calculate them
2751 now. Theoretically, we have to check all fonts for the
2752 glyphs, but that requires much time and memory space. So,
2753 here we check only the font of the first glyph. This leads
2754 to incorrect display very rarely, and C-l (recenter) can
2755 correct the display anyway. */
2756 if (cmp->font != (void *) font)
2757 {
2758 /* Ascent and descent of the font of the first character of
2759 this composition (adjusted by baseline offset). Ascent
2760 and descent of overall glyphs should not be less than
2761 them respectively. */
2762 int font_ascent = FONT_BASE (font) + boff;
2763 int font_descent = FONT_DESCENT (font) - boff;
2764 /* Bounding box of the overall glyphs. */
2765 int leftmost, rightmost, lowest, highest;
2766 int i, width, ascent, descent;
2767
2768 cmp->font = (void *) font;
2769
2770 /* Initialize the bounding box. */
2771 pcm = x_per_char_metric (font, &char2b);
2772 if (pcm)
2773 {
2774 width = pcm->width;
2775 ascent = pcm->ascent;
2776 descent = pcm->descent;
2777 }
2778 else
2779 {
2780 width = FONT_WIDTH (font);
2781 ascent = FONT_BASE (font);
2782 descent = FONT_DESCENT (font);
2783 }
2784
2785 rightmost = width;
2786 lowest = - descent + boff;
2787 highest = ascent + boff;
2788 leftmost = 0;
2789
2790 if (font_info
2791 && font_info->default_ascent
2792 && CHAR_TABLE_P (Vuse_default_ascent)
2793 && !NILP (Faref (Vuse_default_ascent,
2794 make_number (it->char_to_display))))
2795 highest = font_info->default_ascent + boff;
2796
2797 /* Draw the first glyph at the normal position. It may be
2798 shifted to right later if some other glyphs are drawn at
2799 the left. */
2800 cmp->offsets[0] = 0;
2801 cmp->offsets[1] = boff;
2802
2803 /* Set cmp->offsets for the remaining glyphs. */
2804 for (i = 1; i < cmp->glyph_len; i++)
2805 {
2806 int left, right, btm, top;
2807 int ch = COMPOSITION_GLYPH (cmp, i);
2808 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2809
2810 face = FACE_FROM_ID (it->f, face_id);
2811 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2812 it->multibyte_p);
2813 font = face->font;
2814 if (font == NULL)
2815 {
2816 font = FRAME_FONT (it->f);
2817 boff = it->f->output_data.mac->baseline_offset;
2818 font_info = NULL;
2819 }
2820 else
2821 {
2822 font_info
2823 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2824 boff = font_info->baseline_offset;
2825 if (font_info->vertical_centering)
2826 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2827 }
2828
2829 pcm = x_per_char_metric (font, &char2b);
2830 if (pcm)
2831 {
2832 width = pcm->width;
2833 ascent = pcm->ascent;
2834 descent = pcm->descent;
2835 }
2836 else
2837 {
2838 width = FONT_WIDTH (font);
2839 ascent = 1;
2840 descent = 0;
2841 }
2842
2843 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2844 {
2845 /* Relative composition with or without
2846 alternate chars. */
2847 left = (leftmost + rightmost - width) / 2;
2848 btm = - descent + boff;
2849 if (font_info && font_info->relative_compose
2850 && (! CHAR_TABLE_P (Vignore_relative_composition)
2851 || NILP (Faref (Vignore_relative_composition,
2852 make_number (ch)))))
2853 {
2854
2855 if (- descent >= font_info->relative_compose)
2856 /* One extra pixel between two glyphs. */
2857 btm = highest + 1;
2858 else if (ascent <= 0)
2859 /* One extra pixel between two glyphs. */
2860 btm = lowest - 1 - ascent - descent;
2861 }
2862 }
2863 else
2864 {
2865 /* A composition rule is specified by an integer
2866 value that encodes global and new reference
2867 points (GREF and NREF). GREF and NREF are
2868 specified by numbers as below:
2869
2870 0---1---2 -- ascent
2871 | |
2872 | |
2873 | |
2874 9--10--11 -- center
2875 | |
2876 ---3---4---5--- baseline
2877 | |
2878 6---7---8 -- descent
2879 */
2880 int rule = COMPOSITION_RULE (cmp, i);
2881 int gref, nref, grefx, grefy, nrefx, nrefy;
2882
2883 COMPOSITION_DECODE_RULE (rule, gref, nref);
2884 grefx = gref % 3, nrefx = nref % 3;
2885 grefy = gref / 3, nrefy = nref / 3;
2886
2887 left = (leftmost
2888 + grefx * (rightmost - leftmost) / 2
2889 - nrefx * width / 2);
2890 btm = ((grefy == 0 ? highest
2891 : grefy == 1 ? 0
2892 : grefy == 2 ? lowest
2893 : (highest + lowest) / 2)
2894 - (nrefy == 0 ? ascent + descent
2895 : nrefy == 1 ? descent - boff
2896 : nrefy == 2 ? 0
2897 : (ascent + descent) / 2));
2898 }
2899
2900 cmp->offsets[i * 2] = left;
2901 cmp->offsets[i * 2 + 1] = btm + descent;
2902
2903 /* Update the bounding box of the overall glyphs. */
2904 right = left + width;
2905 top = btm + descent + ascent;
2906 if (left < leftmost)
2907 leftmost = left;
2908 if (right > rightmost)
2909 rightmost = right;
2910 if (top > highest)
2911 highest = top;
2912 if (btm < lowest)
2913 lowest = btm;
2914 }
2915
2916 /* If there are glyphs whose x-offsets are negative,
2917 shift all glyphs to the right and make all x-offsets
2918 non-negative. */
2919 if (leftmost < 0)
2920 {
2921 for (i = 0; i < cmp->glyph_len; i++)
2922 cmp->offsets[i * 2] -= leftmost;
2923 rightmost -= leftmost;
2924 }
2925
2926 cmp->pixel_width = rightmost;
2927 cmp->ascent = highest;
2928 cmp->descent = - lowest;
2929 if (cmp->ascent < font_ascent)
2930 cmp->ascent = font_ascent;
2931 if (cmp->descent < font_descent)
2932 cmp->descent = font_descent;
2933 }
2934
2935 it->pixel_width = cmp->pixel_width;
2936 it->ascent = it->phys_ascent = cmp->ascent;
2937 it->descent = it->phys_descent = cmp->descent;
2938
2939 if (face->box != FACE_NO_BOX)
2940 {
2941 int thick = face->box_line_width;
2942
2943 if (thick > 0)
2944 {
2945 it->ascent += thick;
2946 it->descent += thick;
2947 }
2948 else
2949 thick = - thick;
2950
2951 if (it->start_of_box_run_p)
2952 it->pixel_width += thick;
2953 if (it->end_of_box_run_p)
2954 it->pixel_width += thick;
2955 }
2956
2957 /* If face has an overline, add the height of the overline
2958 (1 pixel) and a 1 pixel margin to the character height. */
2959 if (face->overline_p)
2960 it->ascent += 2;
2961
2962 take_vertical_position_into_account (it);
2963
2964 if (it->glyph_row)
2965 x_append_composite_glyph (it);
2966 }
2967 else if (it->what == IT_IMAGE)
2968 x_produce_image_glyph (it);
2969 else if (it->what == IT_STRETCH)
2970 x_produce_stretch_glyph (it);
2971
2972 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2973 because this isn't true for images with `:ascent 100'. */
2974 xassert (it->ascent >= 0 && it->descent >= 0);
2975 if (it->area == TEXT_AREA)
2976 it->current_x += it->pixel_width;
2977
2978 it->descent += it->extra_line_spacing;
2979
2980 it->max_ascent = max (it->max_ascent, it->ascent);
2981 it->max_descent = max (it->max_descent, it->descent);
2982 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2983 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2984 }
2985
2986
2987 /* Estimate the pixel height of the mode or top line on frame F.
2988 FACE_ID specifies what line's height to estimate. */
2989
2990 int
2991 x_estimate_mode_line_height (f, face_id)
2992 struct frame *f;
2993 enum face_id face_id;
2994 {
2995 int height = FONT_HEIGHT (FRAME_FONT (f));
2996
2997 /* This function is called so early when Emacs starts that the face
2998 cache and mode line face are not yet initialized. */
2999 if (FRAME_FACE_CACHE (f))
3000 {
3001 struct face *face = FACE_FROM_ID (f, face_id);
3002 if (face)
3003 {
3004 if (face->font)
3005 height = FONT_HEIGHT (face->font);
3006 if (face->box_line_width > 0)
3007 height += 2 * face->box_line_width;
3008 }
3009 }
3010
3011 return height;
3012 }
3013
3014 \f
3015 /***********************************************************************
3016 Glyph display
3017 ***********************************************************************/
3018
3019 /* A sequence of glyphs to be drawn in the same face.
3020
3021 This data structure is not really completely X specific, so it
3022 could possibly, at least partially, be useful for other systems. It
3023 is currently not part of the external redisplay interface because
3024 it's not clear what other systems will need. */
3025
3026 struct glyph_string
3027 {
3028 /* X-origin of the string. */
3029 int x;
3030
3031 /* Y-origin and y-position of the base line of this string. */
3032 int y, ybase;
3033
3034 /* The width of the string, not including a face extension. */
3035 int width;
3036
3037 /* The width of the string, including a face extension. */
3038 int background_width;
3039
3040 /* The height of this string. This is the height of the line this
3041 string is drawn in, and can be different from the height of the
3042 font the string is drawn in. */
3043 int height;
3044
3045 /* Number of pixels this string overwrites in front of its x-origin.
3046 This number is zero if the string has an lbearing >= 0; it is
3047 -lbearing, if the string has an lbearing < 0. */
3048 int left_overhang;
3049
3050 /* Number of pixels this string overwrites past its right-most
3051 nominal x-position, i.e. x + width. Zero if the string's
3052 rbearing is <= its nominal width, rbearing - width otherwise. */
3053 int right_overhang;
3054
3055 /* The frame on which the glyph string is drawn. */
3056 struct frame *f;
3057
3058 /* The window on which the glyph string is drawn. */
3059 struct window *w;
3060
3061 /* X display and window for convenience. */
3062 Display *display;
3063 Window window;
3064
3065 /* The glyph row for which this string was built. It determines the
3066 y-origin and height of the string. */
3067 struct glyph_row *row;
3068
3069 /* The area within row. */
3070 enum glyph_row_area area;
3071
3072 /* Characters to be drawn, and number of characters. */
3073 XChar2b *char2b;
3074 int nchars;
3075
3076 /* A face-override for drawing cursors, mouse face and similar. */
3077 enum draw_glyphs_face hl;
3078
3079 /* Face in which this string is to be drawn. */
3080 struct face *face;
3081
3082 /* Font in which this string is to be drawn. */
3083 XFontStruct *font;
3084
3085 /* Font info for this string. */
3086 struct font_info *font_info;
3087
3088 /* Non-null means this string describes (part of) a composition.
3089 All characters from char2b are drawn composed. */
3090 struct composition *cmp;
3091
3092 /* Index of this glyph string's first character in the glyph
3093 definition of CMP. If this is zero, this glyph string describes
3094 the first character of a composition. */
3095 int gidx;
3096
3097 /* 1 means this glyph strings face has to be drawn to the right end
3098 of the window's drawing area. */
3099 unsigned extends_to_end_of_line_p : 1;
3100
3101 /* 1 means the background of this string has been drawn. */
3102 unsigned background_filled_p : 1;
3103
3104 /* 1 means glyph string must be drawn with 16-bit functions. */
3105 unsigned two_byte_p : 1;
3106
3107 /* 1 means that the original font determined for drawing this glyph
3108 string could not be loaded. The member `font' has been set to
3109 the frame's default font in this case. */
3110 unsigned font_not_found_p : 1;
3111
3112 /* 1 means that the face in which this glyph string is drawn has a
3113 stipple pattern. */
3114 unsigned stippled_p : 1;
3115
3116 /* 1 means only the foreground of this glyph string must be drawn,
3117 and we should use the physical height of the line this glyph
3118 string appears in as clip rect. */
3119 unsigned for_overlaps_p : 1;
3120
3121 /* The GC to use for drawing this glyph string. */
3122 GC gc;
3123
3124 /* A pointer to the first glyph in the string. This glyph
3125 corresponds to char2b[0]. Needed to draw rectangles if
3126 font_not_found_p is 1. */
3127 struct glyph *first_glyph;
3128
3129 /* Image, if any. */
3130 struct image *img;
3131
3132 struct glyph_string *next, *prev;
3133 };
3134
3135
3136 #if 0
3137
3138 static void
3139 x_dump_glyph_string (s)
3140 struct glyph_string *s;
3141 {
3142 fprintf (stderr, "glyph string\n");
3143 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
3144 s->x, s->y, s->width, s->height);
3145 fprintf (stderr, " ybase = %d\n", s->ybase);
3146 fprintf (stderr, " hl = %d\n", s->hl);
3147 fprintf (stderr, " left overhang = %d, right = %d\n",
3148 s->left_overhang, s->right_overhang);
3149 fprintf (stderr, " nchars = %d\n", s->nchars);
3150 fprintf (stderr, " extends to end of line = %d\n",
3151 s->extends_to_end_of_line_p);
3152 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
3153 fprintf (stderr, " bg width = %d\n", s->background_width);
3154 }
3155
3156 #endif /* GLYPH_DEBUG */
3157
3158
3159
3160 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3161 struct glyph_string **,
3162 struct glyph_string *,
3163 struct glyph_string *));
3164 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3165 struct glyph_string **,
3166 struct glyph_string *,
3167 struct glyph_string *));
3168 static void x_append_glyph_string P_ ((struct glyph_string **,
3169 struct glyph_string **,
3170 struct glyph_string *));
3171 static int x_left_overwritten P_ ((struct glyph_string *));
3172 static int x_left_overwriting P_ ((struct glyph_string *));
3173 static int x_right_overwritten P_ ((struct glyph_string *));
3174 static int x_right_overwriting P_ ((struct glyph_string *));
3175 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3176 int));
3177 static void x_init_glyph_string P_ ((struct glyph_string *,
3178 XChar2b *, struct window *,
3179 struct glyph_row *,
3180 enum glyph_row_area, int,
3181 enum draw_glyphs_face));
3182 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3183 enum glyph_row_area, int, int,
3184 enum draw_glyphs_face, int));
3185 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3186 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3187 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3188 int));
3189 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3190 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3191 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3192 static void x_draw_glyph_string P_ ((struct glyph_string *));
3193 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3194 static void x_set_cursor_gc P_ ((struct glyph_string *));
3195 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3196 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3197 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3198 int *, int *));
3199 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
3200 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3201 unsigned long *, double, int));*/
3202 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3203 double, int, unsigned long));
3204 static void x_setup_relief_colors P_ ((struct glyph_string *));
3205 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3206 static void x_draw_image_relief P_ ((struct glyph_string *));
3207 static void x_draw_image_foreground P_ ((struct glyph_string *));
3208 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3209 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3210 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3211 int, int, int));
3212 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
3213 int, int, int, int, Rect *));
3214 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
3215 int, int, int, Rect *));
3216 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3217 enum glyph_row_area));
3218 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3219 struct glyph_row *,
3220 enum glyph_row_area, int, int));
3221
3222 #if GLYPH_DEBUG
3223 static void x_check_font P_ ((struct frame *, XFontStruct *));
3224 #endif
3225
3226
3227 /* Append the list of glyph strings with head H and tail T to the list
3228 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3229
3230 static INLINE void
3231 x_append_glyph_string_lists (head, tail, h, t)
3232 struct glyph_string **head, **tail;
3233 struct glyph_string *h, *t;
3234 {
3235 if (h)
3236 {
3237 if (*head)
3238 (*tail)->next = h;
3239 else
3240 *head = h;
3241 h->prev = *tail;
3242 *tail = t;
3243 }
3244 }
3245
3246
3247 /* Prepend the list of glyph strings with head H and tail T to the
3248 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3249 result. */
3250
3251 static INLINE void
3252 x_prepend_glyph_string_lists (head, tail, h, t)
3253 struct glyph_string **head, **tail;
3254 struct glyph_string *h, *t;
3255 {
3256 if (h)
3257 {
3258 if (*head)
3259 (*head)->prev = t;
3260 else
3261 *tail = t;
3262 t->next = *head;
3263 *head = h;
3264 }
3265 }
3266
3267
3268 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3269 Set *HEAD and *TAIL to the resulting list. */
3270
3271 static INLINE void
3272 x_append_glyph_string (head, tail, s)
3273 struct glyph_string **head, **tail;
3274 struct glyph_string *s;
3275 {
3276 s->next = s->prev = NULL;
3277 x_append_glyph_string_lists (head, tail, s, s);
3278 }
3279
3280
3281 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3282 face. */
3283
3284 static void
3285 x_set_cursor_gc (s)
3286 struct glyph_string *s;
3287 {
3288 if (s->font == FRAME_FONT (s->f)
3289 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3290 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3291 && !s->cmp)
3292 s->gc = s->f->output_data.mac->cursor_gc;
3293 else
3294 {
3295 /* Cursor on non-default face: must merge. */
3296 XGCValues xgcv;
3297 unsigned long mask;
3298
3299 xgcv.background = s->f->output_data.mac->cursor_pixel;
3300 xgcv.foreground = s->face->background;
3301
3302 /* If the glyph would be invisible, try a different foreground. */
3303 if (xgcv.foreground == xgcv.background)
3304 xgcv.foreground = s->face->foreground;
3305 if (xgcv.foreground == xgcv.background)
3306 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3307 if (xgcv.foreground == xgcv.background)
3308 xgcv.foreground = s->face->foreground;
3309
3310 /* Make sure the cursor is distinct from text in this face. */
3311 if (xgcv.background == s->face->background
3312 && xgcv.foreground == s->face->foreground)
3313 {
3314 xgcv.background = s->face->foreground;
3315 xgcv.foreground = s->face->background;
3316 }
3317
3318 IF_DEBUG (x_check_font (s->f, s->font));
3319 xgcv.font = s->font;
3320 mask = GCForeground | GCBackground | GCFont;
3321
3322 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3323 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3324 mask, &xgcv);
3325 else
3326 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3327 = XCreateGC (s->display, s->window, mask, &xgcv);
3328
3329 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3330 }
3331 }
3332
3333
3334 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3335
3336 static void
3337 x_set_mouse_face_gc (s)
3338 struct glyph_string *s;
3339 {
3340 int face_id;
3341 struct face *face;
3342
3343 /* What face has to be used last for the mouse face? */
3344 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3345 face = FACE_FROM_ID (s->f, face_id);
3346 if (face == NULL)
3347 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3348
3349 if (s->first_glyph->type == CHAR_GLYPH)
3350 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3351 else
3352 face_id = FACE_FOR_CHAR (s->f, face, 0);
3353 s->face = FACE_FROM_ID (s->f, face_id);
3354 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3355
3356 /* If font in this face is same as S->font, use it. */
3357 if (s->font == s->face->font)
3358 s->gc = s->face->gc;
3359 else
3360 {
3361 /* Otherwise construct scratch_cursor_gc with values from FACE
3362 but font FONT. */
3363 XGCValues xgcv;
3364 unsigned long mask;
3365
3366 xgcv.background = s->face->background;
3367 xgcv.foreground = s->face->foreground;
3368 IF_DEBUG (x_check_font (s->f, s->font));
3369 xgcv.font = s->font;
3370 mask = GCForeground | GCBackground | GCFont;
3371
3372 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3373 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3374 mask, &xgcv);
3375 else
3376 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3377 = XCreateGC (s->display, s->window, mask, &xgcv);
3378
3379 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3380 }
3381
3382 xassert (s->gc != 0);
3383 }
3384
3385
3386 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3387 Faces to use in the mode line have already been computed when the
3388 matrix was built, so there isn't much to do, here. */
3389
3390 static INLINE void
3391 x_set_mode_line_face_gc (s)
3392 struct glyph_string *s;
3393 {
3394 s->gc = s->face->gc;
3395 }
3396
3397
3398 /* Set S->gc of glyph string S for drawing that glyph string. Set
3399 S->stippled_p to a non-zero value if the face of S has a stipple
3400 pattern. */
3401
3402 static INLINE void
3403 x_set_glyph_string_gc (s)
3404 struct glyph_string *s;
3405 {
3406 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3407
3408 if (s->hl == DRAW_NORMAL_TEXT)
3409 {
3410 s->gc = s->face->gc;
3411 s->stippled_p = s->face->stipple != 0;
3412 }
3413 else if (s->hl == DRAW_INVERSE_VIDEO)
3414 {
3415 x_set_mode_line_face_gc (s);
3416 s->stippled_p = s->face->stipple != 0;
3417 }
3418 else if (s->hl == DRAW_CURSOR)
3419 {
3420 x_set_cursor_gc (s);
3421 s->stippled_p = 0;
3422 }
3423 else if (s->hl == DRAW_MOUSE_FACE)
3424 {
3425 x_set_mouse_face_gc (s);
3426 s->stippled_p = s->face->stipple != 0;
3427 }
3428 else if (s->hl == DRAW_IMAGE_RAISED
3429 || s->hl == DRAW_IMAGE_SUNKEN)
3430 {
3431 s->gc = s->face->gc;
3432 s->stippled_p = s->face->stipple != 0;
3433 }
3434 else
3435 {
3436 s->gc = s->face->gc;
3437 s->stippled_p = s->face->stipple != 0;
3438 }
3439
3440 /* GC must have been set. */
3441 xassert (s->gc != 0);
3442 }
3443
3444
3445 /* Return in *R the clipping rectangle for glyph string S. */
3446
3447 static void
3448 x_get_glyph_string_clip_rect (s, r)
3449 struct glyph_string *s;
3450 Rect *r;
3451 {
3452 int r_height, r_width;
3453
3454 if (s->row->full_width_p)
3455 {
3456 /* Draw full-width. X coordinates are relative to S->w->left. */
3457 int canon_x = CANON_X_UNIT (s->f);
3458
3459 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3460 r_width = XFASTINT (s->w->width) * canon_x;
3461
3462 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3463 {
3464 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3465 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3466 r->left -= width;
3467 }
3468
3469 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3470
3471 /* Unless displaying a mode or menu bar line, which are always
3472 fully visible, clip to the visible part of the row. */
3473 if (s->w->pseudo_window_p)
3474 r_height = s->row->visible_height;
3475 else
3476 r_height = s->height;
3477 }
3478 else
3479 {
3480 /* This is a text line that may be partially visible. */
3481 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3482 r_width = window_box_width (s->w, s->area);
3483 r_height = s->row->visible_height;
3484 }
3485
3486 /* If S draws overlapping rows, it's sufficient to use the top and
3487 bottom of the window for clipping because this glyph string
3488 intentionally draws over other lines. */
3489 if (s->for_overlaps_p)
3490 {
3491 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3492 r_height = window_text_bottom_y (s->w) - r->top;
3493 }
3494 else
3495 {
3496 /* Don't use S->y for clipping because it doesn't take partially
3497 visible lines into account. For example, it can be negative for
3498 partially visible lines at the top of a window. */
3499 if (!s->row->full_width_p
3500 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3501 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3502 else
3503 r->top = max (0, s->row->y);
3504
3505 /* If drawing a tool-bar window, draw it over the internal border
3506 at the top of the window. */
3507 if (s->w == XWINDOW (s->f->tool_bar_window))
3508 r->top -= s->f->output_data.mac->internal_border_width;
3509 }
3510
3511 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3512
3513 r->bottom = r->top + r_height;
3514 r->right = r->left + r_width;
3515 }
3516
3517
3518 /* Set clipping for output of glyph string S. S may be part of a mode
3519 line or menu if we don't have X toolkit support. */
3520
3521 static INLINE void
3522 x_set_glyph_string_clipping (s)
3523 struct glyph_string *s;
3524 {
3525 Rect r;
3526 x_get_glyph_string_clip_rect (s, &r);
3527 mac_set_clip_rectangle (s->display, s->window, &r);
3528 }
3529
3530
3531 /* Compute left and right overhang of glyph string S. If S is a glyph
3532 string for a composition, assume overhangs don't exist. */
3533
3534 static INLINE void
3535 x_compute_glyph_string_overhangs (s)
3536 struct glyph_string *s;
3537 {
3538 if (s->cmp == NULL
3539 && s->first_glyph->type == CHAR_GLYPH)
3540 {
3541 XCharStruct cs;
3542 int direction, font_ascent, font_descent;
3543 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3544 &font_ascent, &font_descent, &cs);
3545 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3546 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3547 }
3548 }
3549
3550
3551 /* Compute overhangs and x-positions for glyph string S and its
3552 predecessors, or successors. X is the starting x-position for S.
3553 BACKWARD_P non-zero means process predecessors. */
3554
3555 static void
3556 x_compute_overhangs_and_x (s, x, backward_p)
3557 struct glyph_string *s;
3558 int x;
3559 int backward_p;
3560 {
3561 if (backward_p)
3562 {
3563 while (s)
3564 {
3565 x_compute_glyph_string_overhangs (s);
3566 x -= s->width;
3567 s->x = x;
3568 s = s->prev;
3569 }
3570 }
3571 else
3572 {
3573 while (s)
3574 {
3575 x_compute_glyph_string_overhangs (s);
3576 s->x = x;
3577 x += s->width;
3578 s = s->next;
3579 }
3580 }
3581 }
3582
3583
3584 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3585 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3586 assumed to be zero. */
3587
3588 void
3589 x_get_glyph_overhangs (glyph, f, left, right)
3590 struct glyph *glyph;
3591 struct frame *f;
3592 int *left, *right;
3593 {
3594 *left = *right = 0;
3595
3596 if (glyph->type == CHAR_GLYPH)
3597 {
3598 XFontStruct *font;
3599 struct face *face;
3600 struct font_info *font_info;
3601 XChar2b char2b;
3602 XCharStruct *pcm;
3603
3604 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3605 font = face->font;
3606 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3607 if (font
3608 && (pcm = x_per_char_metric (font, &char2b)))
3609 {
3610 if (pcm->rbearing > pcm->width)
3611 *right = pcm->rbearing - pcm->width;
3612 if (pcm->lbearing < 0)
3613 *left = -pcm->lbearing;
3614 }
3615 }
3616 }
3617
3618
3619 /* Return the index of the first glyph preceding glyph string S that
3620 is overwritten by S because of S's left overhang. Value is -1
3621 if no glyphs are overwritten. */
3622
3623 static int
3624 x_left_overwritten (s)
3625 struct glyph_string *s;
3626 {
3627 int k;
3628
3629 if (s->left_overhang)
3630 {
3631 int x = 0, i;
3632 struct glyph *glyphs = s->row->glyphs[s->area];
3633 int first = s->first_glyph - glyphs;
3634
3635 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3636 x -= glyphs[i].pixel_width;
3637
3638 k = i + 1;
3639 }
3640 else
3641 k = -1;
3642
3643 return k;
3644 }
3645
3646
3647 /* Return the index of the first glyph preceding glyph string S that
3648 is overwriting S because of its right overhang. Value is -1 if no
3649 glyph in front of S overwrites S. */
3650
3651 static int
3652 x_left_overwriting (s)
3653 struct glyph_string *s;
3654 {
3655 int i, k, x;
3656 struct glyph *glyphs = s->row->glyphs[s->area];
3657 int first = s->first_glyph - glyphs;
3658
3659 k = -1;
3660 x = 0;
3661 for (i = first - 1; i >= 0; --i)
3662 {
3663 int left, right;
3664 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3665 if (x + right > 0)
3666 k = i;
3667 x -= glyphs[i].pixel_width;
3668 }
3669
3670 return k;
3671 }
3672
3673
3674 /* Return the index of the last glyph following glyph string S that is
3675 not overwritten by S because of S's right overhang. Value is -1 if
3676 no such glyph is found. */
3677
3678 static int
3679 x_right_overwritten (s)
3680 struct glyph_string *s;
3681 {
3682 int k = -1;
3683
3684 if (s->right_overhang)
3685 {
3686 int x = 0, i;
3687 struct glyph *glyphs = s->row->glyphs[s->area];
3688 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3689 int end = s->row->used[s->area];
3690
3691 for (i = first; i < end && s->right_overhang > x; ++i)
3692 x += glyphs[i].pixel_width;
3693
3694 k = i;
3695 }
3696
3697 return k;
3698 }
3699
3700
3701 /* Return the index of the last glyph following glyph string S that
3702 overwrites S because of its left overhang. Value is negative
3703 if no such glyph is found. */
3704
3705 static int
3706 x_right_overwriting (s)
3707 struct glyph_string *s;
3708 {
3709 int i, k, x;
3710 int end = s->row->used[s->area];
3711 struct glyph *glyphs = s->row->glyphs[s->area];
3712 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3713
3714 k = -1;
3715 x = 0;
3716 for (i = first; i < end; ++i)
3717 {
3718 int left, right;
3719 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3720 if (x - left < 0)
3721 k = i;
3722 x += glyphs[i].pixel_width;
3723 }
3724
3725 return k;
3726 }
3727
3728
3729 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3730
3731 static INLINE void
3732 x_clear_glyph_string_rect (s, x, y, w, h)
3733 struct glyph_string *s;
3734 int x, y, w, h;
3735 {
3736 XGCValues xgcv;
3737
3738 xgcv.foreground = s->gc->background;
3739 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3740 }
3741
3742
3743 /* Draw the background of glyph_string S. If S->background_filled_p
3744 is non-zero don't draw it. FORCE_P non-zero means draw the
3745 background even if it wouldn't be drawn normally. This is used
3746 when a string preceding S draws into the background of S, or S
3747 contains the first component of a composition. */
3748
3749 static void
3750 x_draw_glyph_string_background (s, force_p)
3751 struct glyph_string *s;
3752 int force_p;
3753 {
3754 /* Nothing to do if background has already been drawn or if it
3755 shouldn't be drawn in the first place. */
3756 if (!s->background_filled_p)
3757 {
3758 int box_line_width = max (s->face->box_line_width, 0);
3759
3760 #if 0 /* MAC_TODO: stipple */
3761 if (s->stippled_p)
3762 {
3763 /* Fill background with a stipple pattern. */
3764 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3765 XFillRectangle (s->display, s->window, s->gc, s->x,
3766 s->y + box_line_width,
3767 s->background_width,
3768 s->height - 2 * box_line_width);
3769 XSetFillStyle (s->display, s->gc, FillSolid);
3770 s->background_filled_p = 1;
3771 }
3772 else
3773 #endif
3774 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3775 || s->font_not_found_p
3776 || s->extends_to_end_of_line_p
3777 || force_p)
3778 {
3779 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3780 s->background_width,
3781 s->height - 2 * box_line_width);
3782 s->background_filled_p = 1;
3783 }
3784 }
3785 }
3786
3787
3788 /* Draw the foreground of glyph string S. */
3789
3790 static void
3791 x_draw_glyph_string_foreground (s)
3792 struct glyph_string *s;
3793 {
3794 int i, x;
3795
3796 /* If first glyph of S has a left box line, start drawing the text
3797 of S to the right of that box line. */
3798 if (s->face->box != FACE_NO_BOX
3799 && s->first_glyph->left_box_line_p)
3800 x = s->x + abs (s->face->box_line_width);
3801 else
3802 x = s->x;
3803
3804 /* Draw characters of S as rectangles if S's font could not be
3805 loaded. */
3806 if (s->font_not_found_p)
3807 {
3808 for (i = 0; i < s->nchars; ++i)
3809 {
3810 struct glyph *g = s->first_glyph + i;
3811 mac_draw_rectangle (s->display, s->window,
3812 s->gc, x, s->y, g->pixel_width - 1,
3813 s->height - 1);
3814 x += g->pixel_width;
3815 }
3816 }
3817 else
3818 {
3819 char *char1b = (char *) s->char2b;
3820 int boff = s->font_info->baseline_offset;
3821
3822 if (s->font_info->vertical_centering)
3823 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3824
3825 /* If we can use 8-bit functions, condense S->char2b. */
3826 if (!s->two_byte_p)
3827 for (i = 0; i < s->nchars; ++i)
3828 char1b[i] = s->char2b[i].byte2;
3829
3830 /* Draw text with XDrawString if background has already been
3831 filled. Otherwise, use XDrawImageString. (Note that
3832 XDrawImageString is usually faster than XDrawString.) Always
3833 use XDrawImageString when drawing the cursor so that there is
3834 no chance that characters under a box cursor are invisible. */
3835 if (s->for_overlaps_p
3836 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3837 {
3838 /* Draw characters with 16-bit or 8-bit functions. */
3839 if (s->two_byte_p)
3840 XDrawString16 (s->display, s->window, s->gc, x,
3841 s->ybase - boff, s->char2b, s->nchars);
3842 else
3843 XDrawString (s->display, s->window, s->gc, x,
3844 s->ybase - boff, char1b, s->nchars);
3845 }
3846 else
3847 {
3848 if (s->two_byte_p)
3849 XDrawImageString16 (s->display, s->window, s->gc, x,
3850 s->ybase - boff, s->char2b, s->nchars);
3851 else
3852 XDrawImageString (s->display, s->window, s->gc, x,
3853 s->ybase - boff, char1b, s->nchars);
3854 }
3855 }
3856 }
3857
3858 /* Draw the foreground of composite glyph string S. */
3859
3860 static void
3861 x_draw_composite_glyph_string_foreground (s)
3862 struct glyph_string *s;
3863 {
3864 int i, x;
3865
3866 /* If first glyph of S has a left box line, start drawing the text
3867 of S to the right of that box line. */
3868 if (s->face->box != FACE_NO_BOX
3869 && s->first_glyph->left_box_line_p)
3870 x = s->x + abs (s->face->box_line_width);
3871 else
3872 x = s->x;
3873
3874 /* S is a glyph string for a composition. S->gidx is the index of
3875 the first character drawn for glyphs of this composition.
3876 S->gidx == 0 means we are drawing the very first character of
3877 this composition. */
3878
3879 /* Draw a rectangle for the composition if the font for the very
3880 first character of the composition could not be loaded. */
3881 if (s->font_not_found_p)
3882 {
3883 if (s->gidx == 0)
3884 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3885 s->width - 1, s->height - 1);
3886 }
3887 else
3888 {
3889 for (i = 0; i < s->nchars; i++, ++s->gidx)
3890 XDrawString16 (s->display, s->window, s->gc,
3891 x + s->cmp->offsets[s->gidx * 2],
3892 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3893 s->char2b + i, 1);
3894 }
3895 }
3896
3897
3898 #ifdef USE_X_TOOLKIT
3899
3900 static struct frame *x_frame_of_widget P_ ((Widget));
3901
3902
3903 /* Return the frame on which widget WIDGET is used.. Abort if frame
3904 cannot be determined. */
3905
3906 static struct frame *
3907 x_frame_of_widget (widget)
3908 Widget widget;
3909 {
3910 struct x_display_info *dpyinfo;
3911 Lisp_Object tail;
3912 struct frame *f;
3913
3914 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3915
3916 /* Find the top-level shell of the widget. Note that this function
3917 can be called when the widget is not yet realized, so XtWindow
3918 (widget) == 0. That's the reason we can't simply use
3919 x_any_window_to_frame. */
3920 while (!XtIsTopLevelShell (widget))
3921 widget = XtParent (widget);
3922
3923 /* Look for a frame with that top-level widget. Allocate the color
3924 on that frame to get the right gamma correction value. */
3925 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3926 if (GC_FRAMEP (XCAR (tail))
3927 && (f = XFRAME (XCAR (tail)),
3928 (f->output_data.nothing != 1
3929 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3930 && f->output_data.x->widget == widget)
3931 return f;
3932
3933 abort ();
3934 }
3935
3936
3937 /* Allocate the color COLOR->pixel on the screen and display of
3938 widget WIDGET in colormap CMAP. If an exact match cannot be
3939 allocated, try the nearest color available. Value is non-zero
3940 if successful. This is called from lwlib. */
3941
3942 int
3943 x_alloc_nearest_color_for_widget (widget, cmap, color)
3944 Widget widget;
3945 Colormap cmap;
3946 XColor *color;
3947 {
3948 struct frame *f = x_frame_of_widget (widget);
3949 return x_alloc_nearest_color (f, cmap, color);
3950 }
3951
3952
3953 #endif /* USE_X_TOOLKIT */
3954
3955 #if 0 /* MAC_TODO */
3956
3957 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3958 CMAP. If an exact match can't be allocated, try the nearest color
3959 available. Value is non-zero if successful. Set *COLOR to the
3960 color allocated. */
3961
3962 int
3963 x_alloc_nearest_color (f, cmap, color)
3964 struct frame *f;
3965 Colormap cmap;
3966 XColor *color;
3967 {
3968 Display *display = FRAME_X_DISPLAY (f);
3969 Screen *screen = FRAME_X_SCREEN (f);
3970 int rc;
3971
3972 gamma_correct (f, color);
3973 rc = XAllocColor (display, cmap, color);
3974 if (rc == 0)
3975 {
3976 /* If we got to this point, the colormap is full, so we're going
3977 to try to get the next closest color. The algorithm used is
3978 a least-squares matching, which is what X uses for closest
3979 color matching with StaticColor visuals. */
3980 int nearest, i;
3981 unsigned long nearest_delta = ~0;
3982 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3983 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3984
3985 for (i = 0; i < ncells; ++i)
3986 cells[i].pixel = i;
3987 XQueryColors (display, cmap, cells, ncells);
3988
3989 for (nearest = i = 0; i < ncells; ++i)
3990 {
3991 long dred = (color->red >> 8) - (cells[i].red >> 8);
3992 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3993 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3994 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3995
3996 if (delta < nearest_delta)
3997 {
3998 nearest = i;
3999 nearest_delta = delta;
4000 }
4001 }
4002
4003 color->red = cells[nearest].red;
4004 color->green = cells[nearest].green;
4005 color->blue = cells[nearest].blue;
4006 rc = XAllocColor (display, cmap, color);
4007 }
4008
4009 #ifdef DEBUG_X_COLORS
4010 if (rc)
4011 register_color (color->pixel);
4012 #endif /* DEBUG_X_COLORS */
4013
4014 return rc;
4015 }
4016
4017
4018 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4019 It's necessary to do this instead of just using PIXEL directly to
4020 get color reference counts right. */
4021
4022 unsigned long
4023 x_copy_color (f, pixel)
4024 struct frame *f;
4025 unsigned long pixel;
4026 {
4027 XColor color;
4028
4029 color.pixel = pixel;
4030 BLOCK_INPUT;
4031 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4032 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4033 UNBLOCK_INPUT;
4034 #ifdef DEBUG_X_COLORS
4035 register_color (pixel);
4036 #endif
4037 return color.pixel;
4038 }
4039
4040
4041 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4042 It's necessary to do this instead of just using PIXEL directly to
4043 get color reference counts right. */
4044
4045 unsigned long
4046 x_copy_dpy_color (dpy, cmap, pixel)
4047 Display *dpy;
4048 Colormap cmap;
4049 unsigned long pixel;
4050 {
4051 XColor color;
4052
4053 color.pixel = pixel;
4054 BLOCK_INPUT;
4055 XQueryColor (dpy, cmap, &color);
4056 XAllocColor (dpy, cmap, &color);
4057 UNBLOCK_INPUT;
4058 #ifdef DEBUG_X_COLORS
4059 register_color (pixel);
4060 #endif
4061 return color.pixel;
4062 }
4063
4064 #endif /* MAC_TODO */
4065
4066 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
4067 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4068 If this produces the same color as COLOR, try a color where all RGB
4069 values have DELTA added. Return the allocated color in *COLOR.
4070 DISPLAY is the X display, CMAP is the colormap to operate on.
4071 Value is non-zero if successful. */
4072
4073 static int
4074 mac_alloc_lighter_color (f, color, factor, delta)
4075 struct frame *f;
4076 unsigned long *color;
4077 double factor;
4078 int delta;
4079 {
4080 unsigned long new;
4081
4082 /* Change RGB values by specified FACTOR. Avoid overflow! */
4083 xassert (factor >= 0);
4084 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
4085 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
4086 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
4087 if (new == *color)
4088 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
4089 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
4090 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
4091
4092 /* MAC_TODO: Map to palette and retry with delta if same? */
4093 /* MAC_TODO: Free colors (if using palette)? */
4094
4095 if (new == *color)
4096 return 0;
4097
4098 *color = new;
4099
4100 return 1;
4101 }
4102
4103
4104 /* Set up the foreground color for drawing relief lines of glyph
4105 string S. RELIEF is a pointer to a struct relief containing the GC
4106 with which lines will be drawn. Use a color that is FACTOR or
4107 DELTA lighter or darker than the relief's background which is found
4108 in S->f->output_data.x->relief_background. If such a color cannot
4109 be allocated, use DEFAULT_PIXEL, instead. */
4110
4111 static void
4112 x_setup_relief_color (f, relief, factor, delta, default_pixel)
4113 struct frame *f;
4114 struct relief *relief;
4115 double factor;
4116 int delta;
4117 unsigned long default_pixel;
4118 {
4119 XGCValues xgcv;
4120 struct mac_output *di = f->output_data.mac;
4121 unsigned long mask = GCForeground;
4122 unsigned long pixel;
4123 unsigned long background = di->relief_background;
4124 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4125
4126 /* MAC_TODO: Free colors (if using palette)? */
4127
4128 /* Allocate new color. */
4129 xgcv.foreground = default_pixel;
4130 pixel = background;
4131 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
4132 {
4133 relief->allocated_p = 1;
4134 xgcv.foreground = relief->pixel = pixel;
4135 }
4136
4137 if (relief->gc == 0)
4138 {
4139 #if 0 /* MAC_TODO: stipple */
4140 xgcv.stipple = dpyinfo->gray;
4141 mask |= GCStipple;
4142 #endif
4143 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4144 }
4145 else
4146 XChangeGC (NULL, relief->gc, mask, &xgcv);
4147 }
4148
4149
4150 /* Set up colors for the relief lines around glyph string S. */
4151
4152 static void
4153 x_setup_relief_colors (s)
4154 struct glyph_string *s;
4155 {
4156 struct mac_output *di = s->f->output_data.mac;
4157 unsigned long color;
4158
4159 if (s->face->use_box_color_for_shadows_p)
4160 color = s->face->box_color;
4161 else
4162 {
4163 XGCValues xgcv;
4164
4165 /* Get the background color of the face. */
4166 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4167 color = xgcv.background;
4168 }
4169
4170 if (di->white_relief.gc == 0
4171 || color != di->relief_background)
4172 {
4173 di->relief_background = color;
4174 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4175 WHITE_PIX_DEFAULT (s->f));
4176 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4177 BLACK_PIX_DEFAULT (s->f));
4178 }
4179 }
4180
4181
4182 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
4183 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4184 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4185 relief. LEFT_P non-zero means draw a relief on the left side of
4186 the rectangle. RIGHT_P non-zero means draw a relief on the right
4187 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4188 when drawing. */
4189
4190 static void
4191 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4192 raised_p, left_p, right_p, clip_rect)
4193 struct frame *f;
4194 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4195 Rect *clip_rect;
4196 {
4197 int i;
4198 GC gc;
4199
4200 if (raised_p)
4201 gc = f->output_data.mac->white_relief.gc;
4202 else
4203 gc = f->output_data.mac->black_relief.gc;
4204 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4205
4206 /* Top. */
4207 for (i = 0; i < width; ++i)
4208 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4209 left_x + i * left_p, top_y + i,
4210 right_x + 1 - i * right_p, top_y + i);
4211
4212 /* Left. */
4213 if (left_p)
4214 for (i = 0; i < width; ++i)
4215 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4216 left_x + i, top_y + i, left_x + i, bottom_y - i);
4217
4218 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4219 if (raised_p)
4220 gc = f->output_data.mac->black_relief.gc;
4221 else
4222 gc = f->output_data.mac->white_relief.gc;
4223 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4224 clip_rect);
4225
4226 /* Bottom. */
4227 for (i = 0; i < width; ++i)
4228 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4229 left_x + i * left_p, bottom_y - i,
4230 right_x + 1 - i * right_p, bottom_y - i);
4231
4232 /* Right. */
4233 if (right_p)
4234 for (i = 0; i < width; ++i)
4235 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4236 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4237
4238 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4239 }
4240
4241
4242 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4243 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4244 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4245 left side of the rectangle. RIGHT_P non-zero means draw a line
4246 on the right side of the rectangle. CLIP_RECT is the clipping
4247 rectangle to use when drawing. */
4248
4249 static void
4250 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4251 left_p, right_p, clip_rect)
4252 struct glyph_string *s;
4253 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4254 Rect *clip_rect;
4255 {
4256 XGCValues xgcv;
4257
4258 xgcv.foreground = s->face->box_color;
4259 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4260
4261 /* Top. */
4262 XFillRectangle (s->display, s->window, &xgcv,
4263 left_x, top_y, right_x - left_x, width);
4264
4265 /* Left. */
4266 if (left_p)
4267 XFillRectangle (s->display, s->window, &xgcv,
4268 left_x, top_y, width, bottom_y - top_y);
4269
4270 /* Bottom. */
4271 XFillRectangle (s->display, s->window, &xgcv,
4272 left_x, bottom_y - width, right_x - left_x, width);
4273
4274 /* Right. */
4275 if (right_p)
4276 XFillRectangle (s->display, s->window, &xgcv,
4277 right_x - width, top_y, width, bottom_y - top_y);
4278
4279 mac_reset_clipping (s->display, s->window);
4280 }
4281
4282
4283 /* Draw a box around glyph string S. */
4284
4285 static void
4286 x_draw_glyph_string_box (s)
4287 struct glyph_string *s;
4288 {
4289 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4290 int left_p, right_p;
4291 struct glyph *last_glyph;
4292 Rect clip_rect;
4293
4294 last_x = window_box_right (s->w, s->area);
4295 if (s->row->full_width_p
4296 && !s->w->pseudo_window_p)
4297 {
4298 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4299 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4300 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4301 }
4302
4303 /* The glyph that may have a right box line. */
4304 last_glyph = (s->cmp || s->img
4305 ? s->first_glyph
4306 : s->first_glyph + s->nchars - 1);
4307
4308 width = abs (s->face->box_line_width);
4309 raised_p = s->face->box == FACE_RAISED_BOX;
4310 left_x = s->x;
4311 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
4312 ? last_x - 1
4313 : min (last_x, s->x + s->background_width) - 1));
4314 top_y = s->y;
4315 bottom_y = top_y + s->height - 1;
4316
4317 left_p = (s->first_glyph->left_box_line_p
4318 || (s->hl == DRAW_MOUSE_FACE
4319 && (s->prev == NULL
4320 || s->prev->hl != s->hl)));
4321 right_p = (last_glyph->right_box_line_p
4322 || (s->hl == DRAW_MOUSE_FACE
4323 && (s->next == NULL
4324 || s->next->hl != s->hl)));
4325
4326 x_get_glyph_string_clip_rect (s, &clip_rect);
4327
4328 if (s->face->box == FACE_SIMPLE_BOX)
4329 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4330 left_p, right_p, &clip_rect);
4331 else
4332 {
4333 x_setup_relief_colors (s);
4334 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4335 width, raised_p, left_p, right_p, &clip_rect);
4336 }
4337 }
4338
4339
4340 /* Draw foreground of image glyph string S. */
4341
4342 static void
4343 x_draw_image_foreground (s)
4344 struct glyph_string *s;
4345 {
4346 int x;
4347 int y = s->ybase - image_ascent (s->img, s->face);
4348
4349 /* If first glyph of S has a left box line, start drawing it to the
4350 right of that line. */
4351 if (s->face->box != FACE_NO_BOX
4352 && s->first_glyph->left_box_line_p)
4353 x = s->x + abs (s->face->box_line_width);
4354 else
4355 x = s->x;
4356
4357 /* If there is a margin around the image, adjust x- and y-position
4358 by that margin. */
4359 x += s->img->hmargin;
4360 y += s->img->vmargin;
4361
4362 if (s->img->pixmap)
4363 {
4364 #if 0 /* MAC_TODO: image mask */
4365 if (s->img->mask)
4366 {
4367 /* We can't set both a clip mask and use XSetClipRectangles
4368 because the latter also sets a clip mask. We also can't
4369 trust on the shape extension to be available
4370 (XShapeCombineRegion). So, compute the rectangle to draw
4371 manually. */
4372 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4373 | GCFunction);
4374 XGCValues xgcv;
4375 XRectangle clip_rect, image_rect, r;
4376
4377 xgcv.clip_mask = s->img->mask;
4378 xgcv.clip_x_origin = x;
4379 xgcv.clip_y_origin = y;
4380 xgcv.function = GXcopy;
4381 XChangeGC (s->display, s->gc, mask, &xgcv);
4382
4383 x_get_glyph_string_clip_rect (s, &clip_rect);
4384 image_rect.x = x;
4385 image_rect.y = y;
4386 image_rect.width = s->img->width;
4387 image_rect.height = s->img->height;
4388 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4389 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4390 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4391 }
4392 else
4393 #endif /* MAC_TODO */
4394 {
4395 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4396 0, 0, s->img->width, s->img->height, x, y);
4397
4398 /* When the image has a mask, we can expect that at
4399 least part of a mouse highlight or a block cursor will
4400 be visible. If the image doesn't have a mask, make
4401 a block cursor visible by drawing a rectangle around
4402 the image. I believe it's looking better if we do
4403 nothing here for mouse-face. */
4404 if (s->hl == DRAW_CURSOR)
4405 {
4406 int r = s->img->relief;
4407 if (r < 0) r = -r;
4408 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
4409 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4410 }
4411 }
4412 }
4413 else
4414 /* Draw a rectangle if image could not be loaded. */
4415 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4416 s->img->width - 1, s->img->height - 1);
4417 }
4418
4419
4420
4421 /* Draw a relief around the image glyph string S. */
4422
4423 static void
4424 x_draw_image_relief (s)
4425 struct glyph_string *s;
4426 {
4427 int x0, y0, x1, y1, thick, raised_p;
4428 Rect r;
4429 int x;
4430 int y = s->ybase - image_ascent (s->img, s->face);
4431
4432 /* If first glyph of S has a left box line, start drawing it to the
4433 right of that line. */
4434 if (s->face->box != FACE_NO_BOX
4435 && s->first_glyph->left_box_line_p)
4436 x = s->x + abs (s->face->box_line_width);
4437 else
4438 x = s->x;
4439
4440 /* If there is a margin around the image, adjust x- and y-position
4441 by that margin. */
4442 x += s->img->hmargin;
4443 y += s->img->vmargin;
4444
4445 if (s->hl == DRAW_IMAGE_SUNKEN
4446 || s->hl == DRAW_IMAGE_RAISED)
4447 {
4448 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4449 raised_p = s->hl == DRAW_IMAGE_RAISED;
4450 }
4451 else
4452 {
4453 thick = abs (s->img->relief);
4454 raised_p = s->img->relief > 0;
4455 }
4456
4457 x0 = x - thick;
4458 y0 = y - thick;
4459 x1 = x + s->img->width + thick - 1;
4460 y1 = y + s->img->height + thick - 1;
4461
4462 x_setup_relief_colors (s);
4463 x_get_glyph_string_clip_rect (s, &r);
4464 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4465 }
4466
4467
4468 /* Draw the foreground of image glyph string S to PIXMAP. */
4469
4470 static void
4471 x_draw_image_foreground_1 (s, pixmap)
4472 struct glyph_string *s;
4473 Pixmap pixmap;
4474 {
4475 int x;
4476 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4477
4478 /* If first glyph of S has a left box line, start drawing it to the
4479 right of that line. */
4480 if (s->face->box != FACE_NO_BOX
4481 && s->first_glyph->left_box_line_p)
4482 x = abs (s->face->box_line_width);
4483 else
4484 x = 0;
4485
4486 /* If there is a margin around the image, adjust x- and y-position
4487 by that margin. */
4488 x += s->img->hmargin;
4489 y += s->img->vmargin;
4490
4491 if (s->img->pixmap)
4492 {
4493 #if 0 /* MAC_TODO: image mask */
4494 if (s->img->mask)
4495 {
4496 /* We can't set both a clip mask and use XSetClipRectangles
4497 because the latter also sets a clip mask. We also can't
4498 trust on the shape extension to be available
4499 (XShapeCombineRegion). So, compute the rectangle to draw
4500 manually. */
4501 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4502 | GCFunction);
4503 XGCValues xgcv;
4504
4505 xgcv.clip_mask = s->img->mask;
4506 xgcv.clip_x_origin = x;
4507 xgcv.clip_y_origin = y;
4508 xgcv.function = GXcopy;
4509 XChangeGC (s->display, s->gc, mask, &xgcv);
4510
4511 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4512 0, 0, s->img->width, s->img->height, x, y);
4513 XSetClipMask (s->display, s->gc, None);
4514 }
4515 else
4516 #endif /* MAC_TODO */
4517 {
4518 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4519 0, 0, s->img->width, s->img->height, x, y);
4520
4521 /* When the image has a mask, we can expect that at
4522 least part of a mouse highlight or a block cursor will
4523 be visible. If the image doesn't have a mask, make
4524 a block cursor visible by drawing a rectangle around
4525 the image. I believe it's looking better if we do
4526 nothing here for mouse-face. */
4527 if (s->hl == DRAW_CURSOR)
4528 {
4529 int r = s->img->relief;
4530 if (r < 0) r = -r;
4531 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
4532 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4533 }
4534 }
4535 }
4536 else
4537 /* Draw a rectangle if image could not be loaded. */
4538 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4539 s->img->width - 1, s->img->height - 1);
4540 }
4541
4542
4543 /* Draw part of the background of glyph string S. X, Y, W, and H
4544 give the rectangle to draw. */
4545
4546 static void
4547 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4548 struct glyph_string *s;
4549 int x, y, w, h;
4550 {
4551 #if 0 /* MAC_TODO: stipple */
4552 if (s->stippled_p)
4553 {
4554 /* Fill background with a stipple pattern. */
4555 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4556 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4557 XSetFillStyle (s->display, s->gc, FillSolid);
4558 }
4559 else
4560 #endif /* MAC_TODO */
4561 x_clear_glyph_string_rect (s, x, y, w, h);
4562 }
4563
4564
4565 /* Draw image glyph string S.
4566
4567 s->y
4568 s->x +-------------------------
4569 | s->face->box
4570 |
4571 | +-------------------------
4572 | | s->img->vmargin
4573 | |
4574 | | +-------------------
4575 | | | the image
4576
4577 */
4578
4579 static void
4580 x_draw_image_glyph_string (s)
4581 struct glyph_string *s;
4582 {
4583 int x, y;
4584 int box_line_hwidth = abs (s->face->box_line_width);
4585 int box_line_vwidth = max (s->face->box_line_width, 0);
4586 int height;
4587 Pixmap pixmap = 0;
4588
4589 height = s->height - 2 * box_line_vwidth;
4590
4591 /* Fill background with face under the image. Do it only if row is
4592 taller than image or if image has a clip mask to reduce
4593 flickering. */
4594 s->stippled_p = s->face->stipple != 0;
4595 if (height > s->img->height
4596 || s->img->hmargin
4597 || s->img->vmargin
4598 #if 0 /* TODO: image mask */
4599 || s->img->mask
4600 #endif
4601 || s->img->pixmap == 0
4602 || s->width != s->background_width)
4603 {
4604 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4605 x = s->x + box_line_hwidth;
4606 else
4607 x = s->x;
4608
4609 y = s->y + box_line_vwidth;
4610 #if 0 /* TODO: image mask */
4611 if (s->img->mask)
4612 {
4613 /* Create a pixmap as large as the glyph string. Fill it
4614 with the background color. Copy the image to it, using
4615 its mask. Copy the temporary pixmap to the display. */
4616 Screen *screen = FRAME_X_SCREEN (s->f);
4617 int depth = DefaultDepthOfScreen (screen);
4618
4619 /* Create a pixmap as large as the glyph string. */
4620 pixmap = XCreatePixmap (s->display, s->window,
4621 s->background_width,
4622 s->height, depth);
4623
4624 /* Don't clip in the following because we're working on the
4625 pixmap. */
4626 XSetClipMask (s->display, s->gc, None);
4627
4628 /* Fill the pixmap with the background color/stipple. */
4629 if (s->stippled_p)
4630 {
4631 /* Fill background with a stipple pattern. */
4632 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4633 XFillRectangle (s->display, pixmap, s->gc,
4634 0, 0, s->background_width, s->height);
4635 XSetFillStyle (s->display, s->gc, FillSolid);
4636 }
4637 else
4638 {
4639 XGCValues xgcv;
4640 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4641 &xgcv);
4642 XSetForeground (s->display, s->gc, xgcv.background);
4643 XFillRectangle (s->display, pixmap, s->gc,
4644 0, 0, s->background_width, s->height);
4645 XSetForeground (s->display, s->gc, xgcv.foreground);
4646 }
4647 }
4648 else
4649 #endif
4650 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4651
4652 s->background_filled_p = 1;
4653 }
4654
4655 /* Draw the foreground. */
4656 if (pixmap != 0)
4657 {
4658 x_draw_image_foreground_1 (s, pixmap);
4659 x_set_glyph_string_clipping (s);
4660 mac_copy_area (s->display, pixmap, s->window, s->gc,
4661 0, 0, s->background_width, s->height, s->x, s->y);
4662 mac_reset_clipping (s->display, s->window);
4663 XFreePixmap (s->display, pixmap);
4664 }
4665 else
4666 x_draw_image_foreground (s);
4667
4668 /* If we must draw a relief around the image, do it. */
4669 if (s->img->relief
4670 || s->hl == DRAW_IMAGE_RAISED
4671 || s->hl == DRAW_IMAGE_SUNKEN)
4672 x_draw_image_relief (s);
4673 }
4674
4675
4676 /* Draw stretch glyph string S. */
4677
4678 static void
4679 x_draw_stretch_glyph_string (s)
4680 struct glyph_string *s;
4681 {
4682 xassert (s->first_glyph->type == STRETCH_GLYPH);
4683 s->stippled_p = s->face->stipple != 0;
4684
4685 if (s->hl == DRAW_CURSOR
4686 && !x_stretch_cursor_p)
4687 {
4688 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4689 as wide as the stretch glyph. */
4690 int width = min (CANON_X_UNIT (s->f), s->background_width);
4691
4692 /* Draw cursor. */
4693 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4694
4695 /* Clear rest using the GC of the original non-cursor face. */
4696 if (width < s->background_width)
4697 {
4698 GC gc = s->face->gc;
4699 int x = s->x + width, y = s->y;
4700 int w = s->background_width - width, h = s->height;
4701 Rect r;
4702
4703 if (s->row->mouse_face_p
4704 && cursor_in_mouse_face_p (s->w))
4705 {
4706 x_set_mouse_face_gc (s);
4707 gc = s->gc;
4708 }
4709 else
4710 gc = s->face->gc;
4711
4712 x_get_glyph_string_clip_rect (s, &r);
4713 mac_set_clip_rectangle (s->display, s->window, &r);
4714
4715 #if 0 /* MAC_TODO: stipple */
4716 if (s->face->stipple)
4717 {
4718 /* Fill background with a stipple pattern. */
4719 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4720 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4721 XSetFillStyle (s->display, gc, FillSolid);
4722 }
4723 else
4724 #endif /* MAC_TODO */
4725 {
4726 XGCValues xgcv;
4727 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4728 XSetForeground (s->display, gc, xgcv.background);
4729 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4730 XSetForeground (s->display, gc, xgcv.foreground);
4731 }
4732
4733 mac_reset_clipping (s->display, s->window);
4734 }
4735 }
4736 else if (!s->background_filled_p)
4737 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4738 s->height);
4739
4740 s->background_filled_p = 1;
4741 }
4742
4743
4744 /* Draw glyph string S. */
4745
4746 static void
4747 x_draw_glyph_string (s)
4748 struct glyph_string *s;
4749 {
4750 int relief_drawn_p = 0;
4751
4752 /* If S draws into the background of its successor, draw the
4753 background of the successor first so that S can draw into it.
4754 This makes S->next use XDrawString instead of XDrawImageString. */
4755 if (s->next && s->right_overhang && !s->for_overlaps_p)
4756 {
4757 xassert (s->next->img == NULL);
4758 x_set_glyph_string_gc (s->next);
4759 x_set_glyph_string_clipping (s->next);
4760 x_draw_glyph_string_background (s->next, 1);
4761
4762 }
4763
4764 /* Set up S->gc, set clipping and draw S. */
4765 x_set_glyph_string_gc (s);
4766
4767 /* Draw relief (if any) in advance for char/composition so that the
4768 glyph string can be drawn over it. */
4769 if (!s->for_overlaps_p
4770 && s->face->box != FACE_NO_BOX
4771 && (s->first_glyph->type == CHAR_GLYPH
4772 || s->first_glyph->type == COMPOSITE_GLYPH))
4773
4774 {
4775 x_set_glyph_string_clipping (s);
4776 x_draw_glyph_string_background (s, 1);
4777 x_draw_glyph_string_box (s);
4778 x_set_glyph_string_clipping (s);
4779 relief_drawn_p = 1;
4780 }
4781 else
4782 x_set_glyph_string_clipping (s);
4783
4784 switch (s->first_glyph->type)
4785 {
4786 case IMAGE_GLYPH:
4787 x_draw_image_glyph_string (s);
4788 break;
4789
4790 case STRETCH_GLYPH:
4791 x_draw_stretch_glyph_string (s);
4792 break;
4793
4794 case CHAR_GLYPH:
4795 if (s->for_overlaps_p)
4796 s->background_filled_p = 1;
4797 else
4798 x_draw_glyph_string_background (s, 0);
4799 x_draw_glyph_string_foreground (s);
4800 break;
4801
4802 case COMPOSITE_GLYPH:
4803 if (s->for_overlaps_p || s->gidx > 0)
4804 s->background_filled_p = 1;
4805 else
4806 x_draw_glyph_string_background (s, 1);
4807 x_draw_composite_glyph_string_foreground (s);
4808 break;
4809
4810 default:
4811 abort ();
4812 }
4813
4814 if (!s->for_overlaps_p)
4815 {
4816 /* Draw underline. */
4817 if (s->face->underline_p)
4818 {
4819 unsigned long h = 1;
4820 unsigned long dy = s->height - h;
4821
4822 if (s->face->underline_defaulted_p)
4823 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4824 s->width, h);
4825 else
4826 {
4827 XGCValues xgcv;
4828 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4829 XSetForeground (s->display, s->gc, s->face->underline_color);
4830 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4831 s->width, h);
4832 XSetForeground (s->display, s->gc, xgcv.foreground);
4833 }
4834 }
4835
4836 /* Draw overline. */
4837 if (s->face->overline_p)
4838 {
4839 unsigned long dy = 0, h = 1;
4840
4841 if (s->face->overline_color_defaulted_p)
4842 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4843 s->width, h);
4844 else
4845 {
4846 XGCValues xgcv;
4847 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4848 XSetForeground (s->display, s->gc, s->face->overline_color);
4849 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4850 s->width, h);
4851 XSetForeground (s->display, s->gc, xgcv.foreground);
4852 }
4853 }
4854
4855 /* Draw strike-through. */
4856 if (s->face->strike_through_p)
4857 {
4858 unsigned long h = 1;
4859 unsigned long dy = (s->height - h) / 2;
4860
4861 if (s->face->strike_through_color_defaulted_p)
4862 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4863 s->width, h);
4864 else
4865 {
4866 XGCValues xgcv;
4867 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4868 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4869 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4870 s->width, h);
4871 XSetForeground (s->display, s->gc, xgcv.foreground);
4872 }
4873 }
4874
4875 /* Draw relief. */
4876 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4877 x_draw_glyph_string_box (s);
4878 }
4879
4880 /* Reset clipping. */
4881 mac_reset_clipping (s->display, s->window);
4882 }
4883
4884
4885 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4886 struct face **, int));
4887
4888
4889 /* Fill glyph string S with composition components specified by S->cmp.
4890
4891 FACES is an array of faces for all components of this composition.
4892 S->gidx is the index of the first component for S.
4893 OVERLAPS_P non-zero means S should draw the foreground only, and
4894 use its physical height for clipping.
4895
4896 Value is the index of a component not in S. */
4897
4898 static int
4899 x_fill_composite_glyph_string (s, faces, overlaps_p)
4900 struct glyph_string *s;
4901 struct face **faces;
4902 int overlaps_p;
4903 {
4904 int i;
4905
4906 xassert (s);
4907
4908 s->for_overlaps_p = overlaps_p;
4909
4910 s->face = faces[s->gidx];
4911 s->font = s->face->font;
4912 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4913
4914 /* For all glyphs of this composition, starting at the offset
4915 S->gidx, until we reach the end of the definition or encounter a
4916 glyph that requires the different face, add it to S. */
4917 ++s->nchars;
4918 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4919 ++s->nchars;
4920
4921 /* All glyph strings for the same composition has the same width,
4922 i.e. the width set for the first component of the composition. */
4923
4924 s->width = s->first_glyph->pixel_width;
4925
4926 /* If the specified font could not be loaded, use the frame's
4927 default font, but record the fact that we couldn't load it in
4928 the glyph string so that we can draw rectangles for the
4929 characters of the glyph string. */
4930 if (s->font == NULL)
4931 {
4932 s->font_not_found_p = 1;
4933 s->font = FRAME_FONT (s->f);
4934 }
4935
4936 /* Adjust base line for subscript/superscript text. */
4937 s->ybase += s->first_glyph->voffset;
4938
4939 xassert (s->face && s->face->gc);
4940
4941 /* This glyph string must always be drawn with 16-bit functions. */
4942 s->two_byte_p = 1;
4943
4944 return s->gidx + s->nchars;
4945 }
4946
4947
4948 /* Fill glyph string S from a sequence of character glyphs.
4949
4950 FACE_ID is the face id of the string. START is the index of the
4951 first glyph to consider, END is the index of the last + 1.
4952 OVERLAPS_P non-zero means S should draw the foreground only, and
4953 use its physical height for clipping.
4954
4955 Value is the index of the first glyph not in S. */
4956
4957 static int
4958 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4959 struct glyph_string *s;
4960 int face_id;
4961 int start, end, overlaps_p;
4962 {
4963 struct glyph *glyph, *last;
4964 int voffset;
4965 int glyph_not_available_p;
4966
4967 xassert (s->f == XFRAME (s->w->frame));
4968 xassert (s->nchars == 0);
4969 xassert (start >= 0 && end > start);
4970
4971 s->for_overlaps_p = overlaps_p;
4972 glyph = s->row->glyphs[s->area] + start;
4973 last = s->row->glyphs[s->area] + end;
4974 voffset = glyph->voffset;
4975
4976 glyph_not_available_p = glyph->glyph_not_available_p;
4977
4978 while (glyph < last
4979 && glyph->type == CHAR_GLYPH
4980 && glyph->voffset == voffset
4981 /* Same face id implies same font, nowadays. */
4982 && glyph->face_id == face_id
4983 && glyph->glyph_not_available_p == glyph_not_available_p)
4984 {
4985 int two_byte_p;
4986
4987 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4988 s->char2b + s->nchars,
4989 &two_byte_p);
4990 s->two_byte_p = two_byte_p;
4991 ++s->nchars;
4992 xassert (s->nchars <= end - start);
4993 s->width += glyph->pixel_width;
4994 ++glyph;
4995 }
4996
4997 s->font = s->face->font;
4998 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4999
5000 /* If the specified font could not be loaded, use the frame's font,
5001 but record the fact that we couldn't load it in
5002 S->font_not_found_p so that we can draw rectangles for the
5003 characters of the glyph string. */
5004 if (s->font == NULL || glyph_not_available_p)
5005 {
5006 s->font_not_found_p = 1;
5007 s->font = FRAME_FONT (s->f);
5008 }
5009
5010 /* Adjust base line for subscript/superscript text. */
5011 s->ybase += voffset;
5012
5013 xassert (s->face && s->face->gc);
5014 return glyph - s->row->glyphs[s->area];
5015 }
5016
5017
5018 /* Fill glyph string S from image glyph S->first_glyph. */
5019
5020 static void
5021 x_fill_image_glyph_string (s)
5022 struct glyph_string *s;
5023 {
5024 xassert (s->first_glyph->type == IMAGE_GLYPH);
5025 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
5026 xassert (s->img);
5027 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
5028 s->font = s->face->font;
5029 s->width = s->first_glyph->pixel_width;
5030
5031 /* Adjust base line for subscript/superscript text. */
5032 s->ybase += s->first_glyph->voffset;
5033 }
5034
5035
5036 /* Fill glyph string S from a sequence of stretch glyphs.
5037
5038 ROW is the glyph row in which the glyphs are found, AREA is the
5039 area within the row. START is the index of the first glyph to
5040 consider, END is the index of the last + 1.
5041
5042 Value is the index of the first glyph not in S. */
5043
5044 static int
5045 x_fill_stretch_glyph_string (s, row, area, start, end)
5046 struct glyph_string *s;
5047 struct glyph_row *row;
5048 enum glyph_row_area area;
5049 int start, end;
5050 {
5051 struct glyph *glyph, *last;
5052 int voffset, face_id;
5053
5054 xassert (s->first_glyph->type == STRETCH_GLYPH);
5055
5056 glyph = s->row->glyphs[s->area] + start;
5057 last = s->row->glyphs[s->area] + end;
5058 face_id = glyph->face_id;
5059 s->face = FACE_FROM_ID (s->f, face_id);
5060 s->font = s->face->font;
5061 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5062 s->width = glyph->pixel_width;
5063 voffset = glyph->voffset;
5064
5065 for (++glyph;
5066 (glyph < last
5067 && glyph->type == STRETCH_GLYPH
5068 && glyph->voffset == voffset
5069 && glyph->face_id == face_id);
5070 ++glyph)
5071 s->width += glyph->pixel_width;
5072
5073 /* Adjust base line for subscript/superscript text. */
5074 s->ybase += voffset;
5075
5076 xassert (s->face);
5077 return glyph - s->row->glyphs[s->area];
5078 }
5079
5080
5081 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
5082 of XChar2b structures for S; it can't be allocated in
5083 x_init_glyph_string because it must be allocated via `alloca'. W
5084 is the window on which S is drawn. ROW and AREA are the glyph row
5085 and area within the row from which S is constructed. START is the
5086 index of the first glyph structure covered by S. HL is a
5087 face-override for drawing S. */
5088
5089 static void
5090 x_init_glyph_string (s, char2b, w, row, area, start, hl)
5091 struct glyph_string *s;
5092 XChar2b *char2b;
5093 struct window *w;
5094 struct glyph_row *row;
5095 enum glyph_row_area area;
5096 int start;
5097 enum draw_glyphs_face hl;
5098 {
5099 bzero (s, sizeof *s);
5100 s->w = w;
5101 s->f = XFRAME (w->frame);
5102 s->display = FRAME_MAC_DISPLAY (s->f);
5103 s->window = FRAME_MAC_WINDOW (s->f);
5104 s->char2b = char2b;
5105 s->hl = hl;
5106 s->row = row;
5107 s->area = area;
5108 s->first_glyph = row->glyphs[area] + start;
5109 s->height = row->height;
5110 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5111
5112 /* Display the internal border below the tool-bar window. */
5113 if (s->w == XWINDOW (s->f->tool_bar_window))
5114 s->y -= s->f->output_data.mac->internal_border_width;
5115
5116 s->ybase = s->y + row->ascent;
5117 }
5118
5119
5120 /* Set background width of glyph string S. START is the index of the
5121 first glyph following S. LAST_X is the right-most x-position + 1
5122 in the drawing area. */
5123
5124 static INLINE void
5125 x_set_glyph_string_background_width (s, start, last_x)
5126 struct glyph_string *s;
5127 int start;
5128 int last_x;
5129 {
5130 /* If the face of this glyph string has to be drawn to the end of
5131 the drawing area, set S->extends_to_end_of_line_p. */
5132 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
5133
5134 if (start == s->row->used[s->area]
5135 && s->area == TEXT_AREA
5136 && ((s->hl == DRAW_NORMAL_TEXT
5137 && (s->row->fill_line_p
5138 || s->face->background != default_face->background
5139 || s->face->stipple != default_face->stipple
5140 || s->row->mouse_face_p))
5141 || s->hl == DRAW_MOUSE_FACE
5142 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
5143 && s->row->fill_line_p)))
5144 s->extends_to_end_of_line_p = 1;
5145
5146 /* If S extends its face to the end of the line, set its
5147 background_width to the distance to the right edge of the drawing
5148 area. */
5149 if (s->extends_to_end_of_line_p)
5150 s->background_width = last_x - s->x + 1;
5151 else
5152 s->background_width = s->width;
5153 }
5154
5155
5156 /* Add a glyph string for a stretch glyph to the list of strings
5157 between HEAD and TAIL. START is the index of the stretch glyph in
5158 row area AREA of glyph row ROW. END is the index of the last glyph
5159 in that glyph row area. X is the current output position assigned
5160 to the new glyph string constructed. HL overrides that face of the
5161 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5162 is the right-most x-position of the drawing area. */
5163
5164 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5165 and below -- keep them on one line. */
5166 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5167 do \
5168 { \
5169 s = (struct glyph_string *) alloca (sizeof *s); \
5170 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5171 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5172 x_append_glyph_string (&HEAD, &TAIL, s); \
5173 s->x = (X); \
5174 } \
5175 while (0)
5176
5177
5178 /* Add a glyph string for an image glyph to the list of strings
5179 between HEAD and TAIL. START is the index of the image glyph in
5180 row area AREA of glyph row ROW. END is the index of the last glyph
5181 in that glyph row area. X is the current output position assigned
5182 to the new glyph string constructed. HL overrides that face of the
5183 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5184 is the right-most x-position of the drawing area. */
5185
5186 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5187 do \
5188 { \
5189 s = (struct glyph_string *) alloca (sizeof *s); \
5190 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5191 x_fill_image_glyph_string (s); \
5192 x_append_glyph_string (&HEAD, &TAIL, s); \
5193 ++START; \
5194 s->x = (X); \
5195 } \
5196 while (0)
5197
5198
5199 /* Add a glyph string for a sequence of character glyphs to the list
5200 of strings between HEAD and TAIL. START is the index of the first
5201 glyph in row area AREA of glyph row ROW that is part of the new
5202 glyph string. END is the index of the last glyph in that glyph row
5203 area. X is the current output position assigned to the new glyph
5204 string constructed. HL overrides that face of the glyph; e.g. it
5205 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5206 right-most x-position of the drawing area. */
5207
5208 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5209 do \
5210 { \
5211 int c, face_id; \
5212 XChar2b *char2b; \
5213 \
5214 c = (ROW)->glyphs[AREA][START].u.ch; \
5215 face_id = (ROW)->glyphs[AREA][START].face_id; \
5216 \
5217 s = (struct glyph_string *) alloca (sizeof *s); \
5218 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5219 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5220 x_append_glyph_string (&HEAD, &TAIL, s); \
5221 s->x = (X); \
5222 START = x_fill_glyph_string (s, face_id, START, END, \
5223 OVERLAPS_P); \
5224 } \
5225 while (0)
5226
5227
5228 /* Add a glyph string for a composite sequence to the list of strings
5229 between HEAD and TAIL. START is the index of the first glyph in
5230 row area AREA of glyph row ROW that is part of the new glyph
5231 string. END is the index of the last glyph in that glyph row area.
5232 X is the current output position assigned to the new glyph string
5233 constructed. HL overrides that face of the glyph; e.g. it is
5234 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5235 x-position of the drawing area. */
5236
5237 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5238 do { \
5239 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5240 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5241 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5242 struct composition *cmp = composition_table[cmp_id]; \
5243 int glyph_len = cmp->glyph_len; \
5244 XChar2b *char2b; \
5245 struct face **faces; \
5246 struct glyph_string *first_s = NULL; \
5247 int n; \
5248 \
5249 base_face = base_face->ascii_face; \
5250 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5251 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5252 /* At first, fill in `char2b' and `faces'. */ \
5253 for (n = 0; n < glyph_len; n++) \
5254 { \
5255 int c = COMPOSITION_GLYPH (cmp, n); \
5256 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5257 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5258 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5259 this_face_id, char2b + n, 1); \
5260 } \
5261 \
5262 /* Make glyph_strings for each glyph sequence that is drawable by \
5263 the same face, and append them to HEAD/TAIL. */ \
5264 for (n = 0; n < cmp->glyph_len;) \
5265 { \
5266 s = (struct glyph_string *) alloca (sizeof *s); \
5267 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5268 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5269 s->cmp = cmp; \
5270 s->gidx = n; \
5271 s->x = (X); \
5272 \
5273 if (n == 0) \
5274 first_s = s; \
5275 \
5276 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5277 } \
5278 \
5279 ++START; \
5280 s = first_s; \
5281 } while (0)
5282
5283
5284 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5285 of AREA of glyph row ROW on window W between indices START and END.
5286 HL overrides the face for drawing glyph strings, e.g. it is
5287 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5288 x-positions of the drawing area.
5289
5290 This is an ugly monster macro construct because we must use alloca
5291 to allocate glyph strings (because x_draw_glyphs can be called
5292 asynchronously). */
5293
5294 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5295 do \
5296 { \
5297 HEAD = TAIL = NULL; \
5298 while (START < END) \
5299 { \
5300 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5301 switch (first_glyph->type) \
5302 { \
5303 case CHAR_GLYPH: \
5304 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5305 TAIL, HL, X, LAST_X, \
5306 OVERLAPS_P); \
5307 break; \
5308 \
5309 case COMPOSITE_GLYPH: \
5310 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5311 HEAD, TAIL, HL, X, LAST_X,\
5312 OVERLAPS_P); \
5313 break; \
5314 \
5315 case STRETCH_GLYPH: \
5316 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5317 HEAD, TAIL, HL, X, LAST_X); \
5318 break; \
5319 \
5320 case IMAGE_GLYPH: \
5321 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5322 TAIL, HL, X, LAST_X); \
5323 break; \
5324 \
5325 default: \
5326 abort (); \
5327 } \
5328 \
5329 x_set_glyph_string_background_width (s, START, LAST_X); \
5330 (X) += s->width; \
5331 } \
5332 } \
5333 while (0)
5334
5335
5336 /* Draw glyphs between START and END in AREA of ROW on window W,
5337 starting at x-position X. X is relative to AREA in W. HL is a
5338 face-override with the following meaning:
5339
5340 DRAW_NORMAL_TEXT draw normally
5341 DRAW_CURSOR draw in cursor face
5342 DRAW_MOUSE_FACE draw in mouse face.
5343 DRAW_INVERSE_VIDEO draw in mode line face
5344 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5345 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5346
5347 If OVERLAPS_P is non-zero, draw only the foreground of characters
5348 and clip to the physical height of ROW.
5349
5350 Value is the x-position reached, relative to AREA of W. */
5351
5352 static int
5353 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5354 struct window *w;
5355 int x;
5356 struct glyph_row *row;
5357 enum glyph_row_area area;
5358 int start, end;
5359 enum draw_glyphs_face hl;
5360 int overlaps_p;
5361 {
5362 struct glyph_string *head, *tail;
5363 struct glyph_string *s;
5364 int last_x, area_width;
5365 int x_reached;
5366 int i, j;
5367
5368 /* Let's rather be paranoid than getting a SEGV. */
5369 end = min (end, row->used[area]);
5370 start = max (0, start);
5371 start = min (end, start);
5372
5373 /* Translate X to frame coordinates. Set last_x to the right
5374 end of the drawing area. */
5375 if (row->full_width_p)
5376 {
5377 /* X is relative to the left edge of W, without scroll bars
5378 or fringes. */
5379 struct frame *f = XFRAME (WINDOW_FRAME (w));
5380 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5381
5382 x += window_left_x;
5383 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5384 last_x = window_left_x + area_width;
5385
5386 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5387 {
5388 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5389 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5390 last_x += width;
5391 else
5392 x -= width;
5393 }
5394
5395 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5396 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5397 }
5398 else
5399 {
5400 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5401 area_width = window_box_width (w, area);
5402 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5403 }
5404
5405 /* Build a doubly-linked list of glyph_string structures between
5406 head and tail from what we have to draw. Note that the macro
5407 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5408 the reason we use a separate variable `i'. */
5409 i = start;
5410 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5411 overlaps_p);
5412 if (tail)
5413 x_reached = tail->x + tail->background_width;
5414 else
5415 x_reached = x;
5416
5417 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5418 the row, redraw some glyphs in front or following the glyph
5419 strings built above. */
5420 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5421 {
5422 int dummy_x = 0;
5423 struct glyph_string *h, *t;
5424
5425 /* Compute overhangs for all glyph strings. */
5426 for (s = head; s; s = s->next)
5427 x_compute_glyph_string_overhangs (s);
5428
5429 /* Prepend glyph strings for glyphs in front of the first glyph
5430 string that are overwritten because of the first glyph
5431 string's left overhang. The background of all strings
5432 prepended must be drawn because the first glyph string
5433 draws over it. */
5434 i = x_left_overwritten (head);
5435 if (i >= 0)
5436 {
5437 j = i;
5438 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5439 DRAW_NORMAL_TEXT, dummy_x, last_x,
5440 overlaps_p);
5441 start = i;
5442 x_compute_overhangs_and_x (t, head->x, 1);
5443 x_prepend_glyph_string_lists (&head, &tail, h, t);
5444 }
5445
5446 /* Prepend glyph strings for glyphs in front of the first glyph
5447 string that overwrite that glyph string because of their
5448 right overhang. For these strings, only the foreground must
5449 be drawn, because it draws over the glyph string at `head'.
5450 The background must not be drawn because this would overwrite
5451 right overhangs of preceding glyphs for which no glyph
5452 strings exist. */
5453 i = x_left_overwriting (head);
5454 if (i >= 0)
5455 {
5456 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5457 DRAW_NORMAL_TEXT, dummy_x, last_x,
5458 overlaps_p);
5459 for (s = h; s; s = s->next)
5460 s->background_filled_p = 1;
5461 x_compute_overhangs_and_x (t, head->x, 1);
5462 x_prepend_glyph_string_lists (&head, &tail, h, t);
5463 }
5464
5465 /* Append glyphs strings for glyphs following the last glyph
5466 string tail that are overwritten by tail. The background of
5467 these strings has to be drawn because tail's foreground draws
5468 over it. */
5469 i = x_right_overwritten (tail);
5470 if (i >= 0)
5471 {
5472 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5473 DRAW_NORMAL_TEXT, x, last_x,
5474 overlaps_p);
5475 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5476 x_append_glyph_string_lists (&head, &tail, h, t);
5477 }
5478
5479 /* Append glyph strings for glyphs following the last glyph
5480 string tail that overwrite tail. The foreground of such
5481 glyphs has to be drawn because it writes into the background
5482 of tail. The background must not be drawn because it could
5483 paint over the foreground of following glyphs. */
5484 i = x_right_overwriting (tail);
5485 if (i >= 0)
5486 {
5487 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5488 DRAW_NORMAL_TEXT, x, last_x,
5489 overlaps_p);
5490 for (s = h; s; s = s->next)
5491 s->background_filled_p = 1;
5492 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5493 x_append_glyph_string_lists (&head, &tail, h, t);
5494 }
5495 }
5496
5497 /* Draw all strings. */
5498 for (s = head; s; s = s->next)
5499 x_draw_glyph_string (s);
5500
5501 if (area == TEXT_AREA
5502 && !row->full_width_p
5503 /* When drawing overlapping rows, only the glyph strings'
5504 foreground is drawn, which doesn't erase a cursor
5505 completely. */
5506 && !overlaps_p)
5507 {
5508 int x0 = head ? head->x : x;
5509 int x1 = tail ? tail->x + tail->background_width : x;
5510
5511 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5512 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5513
5514 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5515 {
5516 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5517 x0 -= left_area_width;
5518 x1 -= left_area_width;
5519 }
5520
5521 notice_overwritten_cursor (w, area, x0, x1,
5522 row->y, MATRIX_ROW_BOTTOM_Y (row));
5523 }
5524
5525 /* Value is the x-position up to which drawn, relative to AREA of W.
5526 This doesn't include parts drawn because of overhangs. */
5527 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5528 if (!row->full_width_p)
5529 {
5530 if (area > LEFT_MARGIN_AREA)
5531 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5532 if (area > TEXT_AREA)
5533 x_reached -= window_box_width (w, TEXT_AREA);
5534 }
5535
5536 return x_reached;
5537 }
5538
5539
5540 /* Fix the display of area AREA of overlapping row ROW in window W. */
5541
5542 static void
5543 x_fix_overlapping_area (w, row, area)
5544 struct window *w;
5545 struct glyph_row *row;
5546 enum glyph_row_area area;
5547 {
5548 int i, x;
5549
5550 BLOCK_INPUT;
5551
5552 if (area == LEFT_MARGIN_AREA)
5553 x = 0;
5554 else if (area == TEXT_AREA)
5555 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5556 else
5557 x = (window_box_width (w, LEFT_MARGIN_AREA)
5558 + window_box_width (w, TEXT_AREA));
5559
5560 for (i = 0; i < row->used[area];)
5561 {
5562 if (row->glyphs[area][i].overlaps_vertically_p)
5563 {
5564 int start = i, start_x = x;
5565
5566 do
5567 {
5568 x += row->glyphs[area][i].pixel_width;
5569 ++i;
5570 }
5571 while (i < row->used[area]
5572 && row->glyphs[area][i].overlaps_vertically_p);
5573
5574 x_draw_glyphs (w, start_x, row, area, start, i,
5575 DRAW_NORMAL_TEXT, 1);
5576 }
5577 else
5578 {
5579 x += row->glyphs[area][i].pixel_width;
5580 ++i;
5581 }
5582 }
5583
5584 UNBLOCK_INPUT;
5585 }
5586
5587
5588 /* Output LEN glyphs starting at START at the nominal cursor position.
5589 Advance the nominal cursor over the text. The global variable
5590 updated_window contains the window being updated, updated_row is
5591 the glyph row being updated, and updated_area is the area of that
5592 row being updated. */
5593
5594 static void
5595 x_write_glyphs (start, len)
5596 struct glyph *start;
5597 int len;
5598 {
5599 int x, hpos;
5600
5601 xassert (updated_window && updated_row);
5602 BLOCK_INPUT;
5603
5604 /* Write glyphs. */
5605
5606 hpos = start - updated_row->glyphs[updated_area];
5607 x = x_draw_glyphs (updated_window, output_cursor.x,
5608 updated_row, updated_area,
5609 hpos, hpos + len,
5610 DRAW_NORMAL_TEXT, 0);
5611
5612 UNBLOCK_INPUT;
5613
5614 /* Advance the output cursor. */
5615 output_cursor.hpos += len;
5616 output_cursor.x = x;
5617 }
5618
5619
5620 /* Insert LEN glyphs from START at the nominal cursor position. */
5621
5622 static void
5623 x_insert_glyphs (start, len)
5624 struct glyph *start;
5625 register int len;
5626 {
5627 struct frame *f;
5628 struct window *w;
5629 int line_height, shift_by_width, shifted_region_width;
5630 struct glyph_row *row;
5631 struct glyph *glyph;
5632 int frame_x, frame_y, hpos;
5633
5634 xassert (updated_window && updated_row);
5635 BLOCK_INPUT;
5636 w = updated_window;
5637 f = XFRAME (WINDOW_FRAME (w));
5638
5639 /* Get the height of the line we are in. */
5640 row = updated_row;
5641 line_height = row->height;
5642
5643 /* Get the width of the glyphs to insert. */
5644 shift_by_width = 0;
5645 for (glyph = start; glyph < start + len; ++glyph)
5646 shift_by_width += glyph->pixel_width;
5647
5648 /* Get the width of the region to shift right. */
5649 shifted_region_width = (window_box_width (w, updated_area)
5650 - output_cursor.x
5651 - shift_by_width);
5652
5653 /* Shift right. */
5654 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5655 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5656
5657 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5658 f->output_data.mac->normal_gc,
5659 frame_x, frame_y,
5660 shifted_region_width, line_height,
5661 frame_x + shift_by_width, frame_y);
5662
5663 /* Write the glyphs. */
5664 hpos = start - row->glyphs[updated_area];
5665 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5666 DRAW_NORMAL_TEXT, 0);
5667
5668 /* Advance the output cursor. */
5669 output_cursor.hpos += len;
5670 output_cursor.x += shift_by_width;
5671 UNBLOCK_INPUT;
5672 }
5673
5674
5675 /* Delete N glyphs at the nominal cursor position. Not implemented
5676 for X frames. */
5677
5678 static void
5679 x_delete_glyphs (n)
5680 register int n;
5681 {
5682 abort ();
5683 }
5684
5685
5686 /* Erase the current text line from the nominal cursor position
5687 (inclusive) to pixel column TO_X (exclusive). The idea is that
5688 everything from TO_X onward is already erased.
5689
5690 TO_X is a pixel position relative to updated_area of
5691 updated_window. TO_X == -1 means clear to the end of this area. */
5692
5693 static void
5694 x_clear_end_of_line (to_x)
5695 int to_x;
5696 {
5697 struct frame *f;
5698 struct window *w = updated_window;
5699 int max_x, min_y, max_y;
5700 int from_x, from_y, to_y;
5701
5702 xassert (updated_window && updated_row);
5703 f = XFRAME (w->frame);
5704
5705 if (updated_row->full_width_p)
5706 {
5707 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5708 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5709 && !w->pseudo_window_p)
5710 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5711 }
5712 else
5713 max_x = window_box_width (w, updated_area);
5714 max_y = window_text_bottom_y (w);
5715
5716 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5717 of window. For TO_X > 0, truncate to end of drawing area. */
5718 if (to_x == 0)
5719 return;
5720 else if (to_x < 0)
5721 to_x = max_x;
5722 else
5723 to_x = min (to_x, max_x);
5724
5725 to_y = min (max_y, output_cursor.y + updated_row->height);
5726
5727 /* Notice if the cursor will be cleared by this operation. */
5728 if (!updated_row->full_width_p)
5729 notice_overwritten_cursor (w, updated_area,
5730 output_cursor.x, -1,
5731 updated_row->y,
5732 MATRIX_ROW_BOTTOM_Y (updated_row));
5733
5734 from_x = output_cursor.x;
5735
5736 /* Translate to frame coordinates. */
5737 if (updated_row->full_width_p)
5738 {
5739 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5740 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5741 }
5742 else
5743 {
5744 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5745 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5746 }
5747
5748 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5749 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5750 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5751
5752 /* Prevent inadvertently clearing to end of the X window. */
5753 if (to_x > from_x && to_y > from_y)
5754 {
5755 BLOCK_INPUT;
5756 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5757 from_x, from_y, to_x - from_x, to_y - from_y,
5758 0);
5759 UNBLOCK_INPUT;
5760 }
5761 }
5762
5763
5764 /* Clear entire frame. If updating_frame is non-null, clear that
5765 frame. Otherwise clear the selected frame. */
5766
5767 static void
5768 x_clear_frame ()
5769 {
5770 struct frame *f;
5771
5772 if (updating_frame)
5773 f = updating_frame;
5774 else
5775 f = SELECTED_FRAME ();
5776
5777 /* Clearing the frame will erase any cursor, so mark them all as no
5778 longer visible. */
5779 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5780 output_cursor.hpos = output_cursor.vpos = 0;
5781 output_cursor.x = -1;
5782
5783 /* We don't set the output cursor here because there will always
5784 follow an explicit cursor_to. */
5785 BLOCK_INPUT;
5786 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5787
5788 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5789 /* We have to clear the scroll bars, too. If we have changed
5790 colors or something like that, then they should be notified. */
5791 x_scroll_bar_clear (f);
5792 #endif
5793
5794 XFlush (FRAME_MAC_DISPLAY (f));
5795 UNBLOCK_INPUT;
5796 }
5797
5798
5799 \f
5800 /* Invert the middle quarter of the frame for .15 sec. */
5801
5802 /* We use the select system call to do the waiting, so we have to make
5803 sure it's available. If it isn't, we just won't do visual bells. */
5804
5805 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5806
5807 /* Subtract the `struct timeval' values X and Y, storing the result in
5808 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5809
5810 static int
5811 timeval_subtract (result, x, y)
5812 struct timeval *result, x, y;
5813 {
5814 /* Perform the carry for the later subtraction by updating y. This
5815 is safer because on some systems the tv_sec member is unsigned. */
5816 if (x.tv_usec < y.tv_usec)
5817 {
5818 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5819 y.tv_usec -= 1000000 * nsec;
5820 y.tv_sec += nsec;
5821 }
5822
5823 if (x.tv_usec - y.tv_usec > 1000000)
5824 {
5825 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5826 y.tv_usec += 1000000 * nsec;
5827 y.tv_sec -= nsec;
5828 }
5829
5830 /* Compute the time remaining to wait. tv_usec is certainly
5831 positive. */
5832 result->tv_sec = x.tv_sec - y.tv_sec;
5833 result->tv_usec = x.tv_usec - y.tv_usec;
5834
5835 /* Return indication of whether the result should be considered
5836 negative. */
5837 return x.tv_sec < y.tv_sec;
5838 }
5839
5840 void
5841 XTflash (f)
5842 struct frame *f;
5843 {
5844 BLOCK_INPUT;
5845
5846 FlashMenuBar (0);
5847
5848 {
5849 struct timeval wakeup;
5850
5851 EMACS_GET_TIME (wakeup);
5852
5853 /* Compute time to wait until, propagating carry from usecs. */
5854 wakeup.tv_usec += 150000;
5855 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5856 wakeup.tv_usec %= 1000000;
5857
5858 /* Keep waiting until past the time wakeup. */
5859 while (1)
5860 {
5861 struct timeval timeout;
5862
5863 EMACS_GET_TIME (timeout);
5864
5865 /* In effect, timeout = wakeup - timeout.
5866 Break if result would be negative. */
5867 if (timeval_subtract (&timeout, wakeup, timeout))
5868 break;
5869
5870 /* Try to wait that long--but we might wake up sooner. */
5871 select (0, NULL, NULL, NULL, &timeout);
5872 }
5873 }
5874
5875 FlashMenuBar (0);
5876
5877 UNBLOCK_INPUT;
5878 }
5879
5880 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5881
5882
5883 /* Make audible bell. */
5884
5885 void
5886 XTring_bell ()
5887 {
5888 struct frame *f = SELECTED_FRAME ();
5889
5890 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5891 if (visible_bell)
5892 XTflash (f);
5893 else
5894 #endif
5895 {
5896 BLOCK_INPUT;
5897 SysBeep (1);
5898 XFlush (FRAME_MAC_DISPLAY (f));
5899 UNBLOCK_INPUT;
5900 }
5901 }
5902
5903
5904 \f
5905 /* Specify how many text lines, from the top of the window,
5906 should be affected by insert-lines and delete-lines operations.
5907 This, and those operations, are used only within an update
5908 that is bounded by calls to x_update_begin and x_update_end. */
5909
5910 void
5911 XTset_terminal_window (n)
5912 register int n;
5913 {
5914 /* This function intentionally left blank. */
5915 }
5916
5917
5918 \f
5919 /***********************************************************************
5920 Line Dance
5921 ***********************************************************************/
5922
5923 /* Perform an insert-lines or delete-lines operation, inserting N
5924 lines or deleting -N lines at vertical position VPOS. */
5925
5926 static void
5927 x_ins_del_lines (vpos, n)
5928 int vpos, n;
5929 {
5930 abort ();
5931 }
5932
5933
5934 /* Scroll part of the display as described by RUN. */
5935
5936 static void
5937 x_scroll_run (w, run)
5938 struct window *w;
5939 struct run *run;
5940 {
5941 struct frame *f = XFRAME (w->frame);
5942 int x, y, width, height, from_y, to_y, bottom_y;
5943
5944 /* Get frame-relative bounding box of the text display area of W,
5945 without mode lines. Include in this box the left and right
5946 fringes of W. */
5947 window_box (w, -1, &x, &y, &width, &height);
5948 width += FRAME_X_FRINGE_WIDTH (f);
5949 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5950
5951 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5952 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5953 bottom_y = y + height;
5954
5955 if (to_y < from_y)
5956 {
5957 /* Scrolling up. Make sure we don't copy part of the mode
5958 line at the bottom. */
5959 if (from_y + run->height > bottom_y)
5960 height = bottom_y - from_y;
5961 else
5962 height = run->height;
5963 }
5964 else
5965 {
5966 /* Scolling down. Make sure we don't copy over the mode line.
5967 at the bottom. */
5968 if (to_y + run->height > bottom_y)
5969 height = bottom_y - to_y;
5970 else
5971 height = run->height;
5972 }
5973
5974 BLOCK_INPUT;
5975
5976 /* Cursor off. Will be switched on again in x_update_window_end. */
5977 updated_window = w;
5978 x_clear_cursor (w);
5979
5980 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5981 f->output_data.mac->normal_gc,
5982 x, from_y,
5983 width, height,
5984 x, to_y);
5985
5986 UNBLOCK_INPUT;
5987 }
5988
5989
5990 \f
5991 /***********************************************************************
5992 Exposure Events
5993 ***********************************************************************/
5994
5995 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5996 corner of the exposed rectangle. W and H are width and height of
5997 the exposed area. All are pixel values. W or H zero means redraw
5998 the entire frame. */
5999
6000 static void
6001 expose_frame (f, x, y, w, h)
6002 struct frame *f;
6003 int x, y, w, h;
6004 {
6005 Rect r;
6006 int mouse_face_overwritten_p = 0;
6007
6008 TRACE ((stderr, "expose_frame "));
6009
6010 /* No need to redraw if frame will be redrawn soon. */
6011 if (FRAME_GARBAGED_P (f))
6012 {
6013 TRACE ((stderr, " garbaged\n"));
6014 return;
6015 }
6016
6017 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6018 or deactivated here, for unknown reasons, activated scroll bars
6019 are shown in deactivated frames in some instances. */
6020 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6021 activate_scroll_bars (f);
6022 else
6023 deactivate_scroll_bars (f);
6024
6025 /* If basic faces haven't been realized yet, there is no point in
6026 trying to redraw anything. This can happen when we get an expose
6027 event while Emacs is starting, e.g. by moving another window. */
6028 if (FRAME_FACE_CACHE (f) == NULL
6029 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
6030 {
6031 TRACE ((stderr, " no faces\n"));
6032 return;
6033 }
6034
6035 if (w == 0 || h == 0)
6036 {
6037 r.left = r.top = 0;
6038 r.right = CANON_X_UNIT (f) * f->width;
6039 r.bottom = CANON_Y_UNIT (f) * f->height;
6040 }
6041 else
6042 {
6043 r.left = x;
6044 r.top = y;
6045 r.right = x + w;
6046 r.bottom = y + h;
6047 }
6048
6049 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
6050 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
6051
6052 if (WINDOWP (f->tool_bar_window))
6053 mouse_face_overwritten_p
6054 |= expose_window (XWINDOW (f->tool_bar_window), &r);
6055
6056 /* Some window managers support a focus-follows-mouse style with
6057 delayed raising of frames. Imagine a partially obscured frame,
6058 and moving the mouse into partially obscured mouse-face on that
6059 frame. The visible part of the mouse-face will be highlighted,
6060 then the WM raises the obscured frame. With at least one WM, KDE
6061 2.1, Emacs is not getting any event for the raising of the frame
6062 (even tried with SubstructureRedirectMask), only Expose events.
6063 These expose events will draw text normally, i.e. not
6064 highlighted. Which means we must redo the highlight here.
6065 Subsume it under ``we love X''. --gerd 2001-08-15 */
6066 /* Included in Windows version because Windows most likely does not
6067 do the right thing if any third party tool offers
6068 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6069 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
6070 {
6071 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6072 if (f == dpyinfo->mouse_face_mouse_frame)
6073 {
6074 int x = dpyinfo->mouse_face_mouse_x;
6075 int y = dpyinfo->mouse_face_mouse_y;
6076 clear_mouse_face (dpyinfo);
6077 note_mouse_highlight (f, x, y);
6078 }
6079 }
6080 }
6081
6082
6083 /* Redraw (parts) of all windows in the window tree rooted at W that
6084 intersect R. R contains frame pixel coordinates. */
6085
6086 static int
6087 expose_window_tree (w, r)
6088 struct window *w;
6089 Rect *r;
6090 {
6091 struct frame *f = XFRAME (w->frame);
6092 int mouse_face_overwritten_p = 0;
6093
6094 while (w && !FRAME_GARBAGED_P (f))
6095 {
6096 if (!NILP (w->hchild))
6097 mouse_face_overwritten_p
6098 |= expose_window_tree (XWINDOW (w->hchild), r);
6099 else if (!NILP (w->vchild))
6100 mouse_face_overwritten_p
6101 |= expose_window_tree (XWINDOW (w->vchild), r);
6102 else
6103 mouse_face_overwritten_p |= expose_window (w, r);
6104
6105 w = NILP (w->next) ? NULL : XWINDOW (w->next);
6106 }
6107
6108 return mouse_face_overwritten_p;
6109 }
6110
6111
6112 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
6113 which intersects rectangle R. R is in window-relative coordinates. */
6114
6115 static void
6116 expose_area (w, row, r, area)
6117 struct window *w;
6118 struct glyph_row *row;
6119 Rect *r;
6120 enum glyph_row_area area;
6121 {
6122 struct glyph *first = row->glyphs[area];
6123 struct glyph *end = row->glyphs[area] + row->used[area];
6124 struct glyph *last;
6125 int first_x, start_x, x;
6126
6127 if (area == TEXT_AREA && row->fill_line_p)
6128 /* If row extends face to end of line write the whole line. */
6129 x_draw_glyphs (w, 0, row, area,
6130 0, row->used[area],
6131 DRAW_NORMAL_TEXT, 0);
6132 else
6133 {
6134 /* Set START_X to the window-relative start position for drawing glyphs of
6135 AREA. The first glyph of the text area can be partially visible.
6136 The first glyphs of other areas cannot. */
6137 if (area == LEFT_MARGIN_AREA)
6138 start_x = 0;
6139 else if (area == TEXT_AREA)
6140 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6141 else
6142 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6143 + window_box_width (w, TEXT_AREA));
6144 x = start_x;
6145
6146 /* Find the first glyph that must be redrawn. */
6147 while (first < end
6148 && x + first->pixel_width < r->left)
6149 {
6150 x += first->pixel_width;
6151 ++first;
6152 }
6153
6154 /* Find the last one. */
6155 last = first;
6156 first_x = x;
6157 while (last < end
6158 && x < r->right)
6159 {
6160 x += last->pixel_width;
6161 ++last;
6162 }
6163
6164 /* Repaint. */
6165 if (last > first)
6166 x_draw_glyphs (w, first_x - start_x, row, area,
6167 first - row->glyphs[area],
6168 last - row->glyphs[area],
6169 DRAW_NORMAL_TEXT, 0);
6170 }
6171 }
6172
6173
6174 /* Redraw the parts of the glyph row ROW on window W intersecting
6175 rectangle R. R is in window-relative coordinates. Value is
6176 non-zero if mouse face was overwritten. */
6177
6178 static int
6179 expose_line (w, row, r)
6180 struct window *w;
6181 struct glyph_row *row;
6182 Rect *r;
6183 {
6184 xassert (row->enabled_p);
6185
6186 if (row->mode_line_p || w->pseudo_window_p)
6187 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6188 DRAW_NORMAL_TEXT, 0);
6189 else
6190 {
6191 if (row->used[LEFT_MARGIN_AREA])
6192 expose_area (w, row, r, LEFT_MARGIN_AREA);
6193 if (row->used[TEXT_AREA])
6194 expose_area (w, row, r, TEXT_AREA);
6195 if (row->used[RIGHT_MARGIN_AREA])
6196 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6197 x_draw_row_fringe_bitmaps (w, row);
6198 }
6199
6200 return row->mouse_face_p;
6201 }
6202
6203
6204 /* Return non-zero if W's cursor intersects rectangle R. */
6205
6206 static int
6207 x_phys_cursor_in_rect_p (w, r)
6208 struct window *w;
6209 Rect *r;
6210 {
6211 Rect cr, result;
6212 struct glyph *cursor_glyph;
6213
6214 cursor_glyph = get_phys_cursor_glyph (w);
6215 if (cursor_glyph)
6216 {
6217 cr.left = w->phys_cursor.x;
6218 cr.top = w->phys_cursor.y;
6219 cr.right = cr.left + cursor_glyph->pixel_width;
6220 cr.bottom = cr.top + w->phys_cursor_height;
6221 return x_intersect_rectangles (&cr, r, &result);
6222 }
6223 else
6224 return 0;
6225 }
6226
6227
6228 /* Redraw the part of window W intersection rectagle FR. Pixel
6229 coordinates in FR are frame relative. Call this function with
6230 input blocked. Value is non-zero if the exposure overwrites
6231 mouse-face. */
6232
6233 static int
6234 expose_window (w, fr)
6235 struct window *w;
6236 Rect *fr;
6237 {
6238 struct frame *f = XFRAME (w->frame);
6239 Rect wr, r;
6240 int mouse_face_overwritten_p = 0;
6241
6242 /* If window is not yet fully initialized, do nothing. This can
6243 happen when toolkit scroll bars are used and a window is split.
6244 Reconfiguring the scroll bar will generate an expose for a newly
6245 created window. */
6246 if (w->current_matrix == NULL)
6247 return 0;
6248
6249 /* When we're currently updating the window, display and current
6250 matrix usually don't agree. Arrange for a thorough display
6251 later. */
6252 if (w == updated_window)
6253 {
6254 SET_FRAME_GARBAGED (f);
6255 return 0;
6256 }
6257
6258 /* Frame-relative pixel rectangle of W. */
6259 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6260 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6261 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6262 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6263
6264 if (x_intersect_rectangles (fr, &wr, &r))
6265 {
6266 int yb = window_text_bottom_y (w);
6267 struct glyph_row *row;
6268 int cursor_cleared_p;
6269
6270 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6271 r.left, r.top, r.right, r.bottom));
6272
6273 /* Convert to window coordinates. */
6274 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6275 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6276 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6277 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6278
6279 /* Turn off the cursor. */
6280 if (!w->pseudo_window_p
6281 && x_phys_cursor_in_rect_p (w, &r))
6282 {
6283 x_clear_cursor (w);
6284 cursor_cleared_p = 1;
6285 }
6286 else
6287 cursor_cleared_p = 0;
6288
6289 /* Find the first row intersecting the rectangle R. */
6290 for (row = w->current_matrix->rows;
6291 row->enabled_p;
6292 ++row)
6293 {
6294 int y0 = row->y;
6295 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6296
6297 if ((y0 >= r.top && y0 < r.bottom)
6298 || (y1 > r.top && y1 < r.bottom)
6299 || (r.top >= y0 && r.top < y1)
6300 || (r.bottom > y0 && r.bottom < y1))
6301 {
6302 if (expose_line (w, row, &r))
6303 mouse_face_overwritten_p = 1;
6304 }
6305
6306 if (y1 >= yb)
6307 break;
6308 }
6309
6310 /* Display the mode line if there is one. */
6311 if (WINDOW_WANTS_MODELINE_P (w)
6312 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6313 row->enabled_p)
6314 && row->y < r.bottom)
6315 {
6316 if (expose_line (w, row, &r))
6317 mouse_face_overwritten_p = 1;
6318 }
6319
6320 if (!w->pseudo_window_p)
6321 {
6322 /* Draw border between windows. */
6323 x_draw_vertical_border (w);
6324
6325 /* Turn the cursor on again. */
6326 if (cursor_cleared_p)
6327 x_update_window_cursor (w, 1);
6328 }
6329 }
6330
6331 /* Display scroll bar for this window. */
6332 if (!NILP (w->vertical_scroll_bar))
6333 {
6334 ControlHandle ch
6335 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
6336
6337 Draw1Control (ch);
6338 }
6339
6340 return mouse_face_overwritten_p;
6341 }
6342
6343 static int
6344 x_intersect_rectangles (r1, r2, result)
6345 Rect *r1, *r2, *result;
6346 {
6347 Rect *left, *right;
6348 Rect *upper, *lower;
6349 int intersection_p = 0;
6350
6351 /* Rerrange so that R1 is the left-most rectangle. */
6352 if (r1->left < r2->left)
6353 left = r1, right = r2;
6354 else
6355 left = r2, right = r1;
6356
6357 /* X0 of the intersection is right.x0, if this is inside R1,
6358 otherwise there is no intersection. */
6359 if (right->left <= left->right)
6360 {
6361 result->left = right->left;
6362
6363 /* The right end of the intersection is the minimum of the
6364 the right ends of left and right. */
6365 result->right = min (left->right, right->right);
6366
6367 /* Same game for Y. */
6368 if (r1->top < r2->top)
6369 upper = r1, lower = r2;
6370 else
6371 upper = r2, lower = r1;
6372
6373 /* The upper end of the intersection is lower.y0, if this is inside
6374 of upper. Otherwise, there is no intersection. */
6375 if (lower->top <= upper->bottom)
6376 {
6377 result->top = lower->top;
6378
6379 /* The lower end of the intersection is the minimum of the lower
6380 ends of upper and lower. */
6381 result->bottom = min (lower->bottom, upper->bottom);
6382 intersection_p = 1;
6383 }
6384 }
6385
6386 return intersection_p;
6387 }
6388
6389
6390
6391
6392 \f
6393 static void
6394 frame_highlight (f)
6395 struct frame *f;
6396 {
6397 x_update_cursor (f, 1);
6398 }
6399
6400 static void
6401 frame_unhighlight (f)
6402 struct frame *f;
6403 {
6404 x_update_cursor (f, 1);
6405 }
6406
6407 /* The focus has changed. Update the frames as necessary to reflect
6408 the new situation. Note that we can't change the selected frame
6409 here, because the Lisp code we are interrupting might become confused.
6410 Each event gets marked with the frame in which it occurred, so the
6411 Lisp code can tell when the switch took place by examining the events. */
6412
6413 static void
6414 x_new_focus_frame (dpyinfo, frame)
6415 struct x_display_info *dpyinfo;
6416 struct frame *frame;
6417 {
6418 struct frame *old_focus = dpyinfo->x_focus_frame;
6419
6420 if (frame != dpyinfo->x_focus_frame)
6421 {
6422 /* Set this before calling other routines, so that they see
6423 the correct value of x_focus_frame. */
6424 dpyinfo->x_focus_frame = frame;
6425
6426 if (old_focus && old_focus->auto_lower)
6427 x_lower_frame (old_focus);
6428
6429 #if 0
6430 selected_frame = frame;
6431 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6432 selected_frame);
6433 Fselect_window (selected_frame->selected_window);
6434 choose_minibuf_frame ();
6435 #endif /* ! 0 */
6436
6437 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6438 pending_autoraise_frame = dpyinfo->x_focus_frame;
6439 else
6440 pending_autoraise_frame = 0;
6441 }
6442
6443 x_frame_rehighlight (dpyinfo);
6444 }
6445
6446 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6447
6448 void
6449 x_mouse_leave (dpyinfo)
6450 struct x_display_info *dpyinfo;
6451 {
6452 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6453 }
6454
6455 /* The focus has changed, or we have redirected a frame's focus to
6456 another frame (this happens when a frame uses a surrogate
6457 mini-buffer frame). Shift the highlight as appropriate.
6458
6459 The FRAME argument doesn't necessarily have anything to do with which
6460 frame is being highlighted or un-highlighted; we only use it to find
6461 the appropriate X display info. */
6462
6463 static void
6464 XTframe_rehighlight (frame)
6465 struct frame *frame;
6466 {
6467 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6468 }
6469
6470 static void
6471 x_frame_rehighlight (dpyinfo)
6472 struct x_display_info *dpyinfo;
6473 {
6474 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6475
6476 if (dpyinfo->x_focus_frame)
6477 {
6478 dpyinfo->x_highlight_frame
6479 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6480 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6481 : dpyinfo->x_focus_frame);
6482 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6483 {
6484 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6485 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6486 }
6487 }
6488 else
6489 dpyinfo->x_highlight_frame = 0;
6490
6491 if (dpyinfo->x_highlight_frame != old_highlight)
6492 {
6493 if (old_highlight)
6494 frame_unhighlight (old_highlight);
6495 if (dpyinfo->x_highlight_frame)
6496 frame_highlight (dpyinfo->x_highlight_frame);
6497 }
6498 }
6499
6500
6501 \f
6502 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6503
6504 #if 0 /* MAC_TODO */
6505 /* Initialize mode_switch_bit and modifier_meaning. */
6506 static void
6507 x_find_modifier_meanings (dpyinfo)
6508 struct x_display_info *dpyinfo;
6509 {
6510 int min_code, max_code;
6511 KeySym *syms;
6512 int syms_per_code;
6513 XModifierKeymap *mods;
6514
6515 dpyinfo->meta_mod_mask = 0;
6516 dpyinfo->shift_lock_mask = 0;
6517 dpyinfo->alt_mod_mask = 0;
6518 dpyinfo->super_mod_mask = 0;
6519 dpyinfo->hyper_mod_mask = 0;
6520
6521 #ifdef HAVE_X11R4
6522 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6523 #else
6524 min_code = dpyinfo->display->min_keycode;
6525 max_code = dpyinfo->display->max_keycode;
6526 #endif
6527
6528 syms = XGetKeyboardMapping (dpyinfo->display,
6529 min_code, max_code - min_code + 1,
6530 &syms_per_code);
6531 mods = XGetModifierMapping (dpyinfo->display);
6532
6533 /* Scan the modifier table to see which modifier bits the Meta and
6534 Alt keysyms are on. */
6535 {
6536 int row, col; /* The row and column in the modifier table. */
6537
6538 for (row = 3; row < 8; row++)
6539 for (col = 0; col < mods->max_keypermod; col++)
6540 {
6541 KeyCode code
6542 = mods->modifiermap[(row * mods->max_keypermod) + col];
6543
6544 /* Zeroes are used for filler. Skip them. */
6545 if (code == 0)
6546 continue;
6547
6548 /* Are any of this keycode's keysyms a meta key? */
6549 {
6550 int code_col;
6551
6552 for (code_col = 0; code_col < syms_per_code; code_col++)
6553 {
6554 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6555
6556 switch (sym)
6557 {
6558 case XK_Meta_L:
6559 case XK_Meta_R:
6560 dpyinfo->meta_mod_mask |= (1 << row);
6561 break;
6562
6563 case XK_Alt_L:
6564 case XK_Alt_R:
6565 dpyinfo->alt_mod_mask |= (1 << row);
6566 break;
6567
6568 case XK_Hyper_L:
6569 case XK_Hyper_R:
6570 dpyinfo->hyper_mod_mask |= (1 << row);
6571 break;
6572
6573 case XK_Super_L:
6574 case XK_Super_R:
6575 dpyinfo->super_mod_mask |= (1 << row);
6576 break;
6577
6578 case XK_Shift_Lock:
6579 /* Ignore this if it's not on the lock modifier. */
6580 if ((1 << row) == LockMask)
6581 dpyinfo->shift_lock_mask = LockMask;
6582 break;
6583 }
6584 }
6585 }
6586 }
6587 }
6588
6589 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6590 if (! dpyinfo->meta_mod_mask)
6591 {
6592 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6593 dpyinfo->alt_mod_mask = 0;
6594 }
6595
6596 /* If some keys are both alt and meta,
6597 make them just meta, not alt. */
6598 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6599 {
6600 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6601 }
6602
6603 XFree ((char *) syms);
6604 XFreeModifiermap (mods);
6605 }
6606
6607 #endif /* MAC_TODO */
6608
6609 /* Convert between the modifier bits X uses and the modifier bits
6610 Emacs uses. */
6611
6612 static unsigned int
6613 x_mac_to_emacs_modifiers (dpyinfo, state)
6614 struct x_display_info *dpyinfo;
6615 unsigned short state;
6616 {
6617 return (((state & shiftKey) ? shift_modifier : 0)
6618 | ((state & controlKey) ? ctrl_modifier : 0)
6619 | ((state & cmdKey) ? meta_modifier : 0)
6620 | ((state & optionKey) ? alt_modifier : 0));
6621 }
6622
6623 #if 0 /* MAC_TODO */
6624 static unsigned short
6625 x_emacs_to_x_modifiers (dpyinfo, state)
6626 struct x_display_info *dpyinfo;
6627 unsigned int state;
6628 {
6629 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6630 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6631 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6632 | ((state & shift_modifier) ? ShiftMask : 0)
6633 | ((state & ctrl_modifier) ? ControlMask : 0)
6634 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6635 }
6636 #endif /* MAC_TODO */
6637
6638 /* Convert a keysym to its name. */
6639
6640 char *
6641 x_get_keysym_name (keysym)
6642 int keysym;
6643 {
6644 char *value;
6645
6646 BLOCK_INPUT;
6647 #if 0
6648 value = XKeysymToString (keysym);
6649 #else
6650 value = 0;
6651 #endif
6652 UNBLOCK_INPUT;
6653
6654 return value;
6655 }
6656
6657
6658 \f
6659 /* Mouse clicks and mouse movement. Rah. */
6660
6661 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6662 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6663 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6664 not force the value into range. */
6665
6666 void
6667 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6668 FRAME_PTR f;
6669 register int pix_x, pix_y;
6670 register int *x, *y;
6671 Rect *bounds;
6672 int noclip;
6673 {
6674 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6675 if (NILP (Vwindow_system))
6676 {
6677 *x = pix_x;
6678 *y = pix_y;
6679 return;
6680 }
6681
6682 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6683 even for negative values. */
6684 if (pix_x < 0)
6685 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
6686 if (pix_y < 0)
6687 pix_y -= (f)->output_data.mac->line_height - 1;
6688
6689 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6690 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6691
6692 if (bounds)
6693 {
6694 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6695 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
6696 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6697 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
6698 }
6699
6700 if (!noclip)
6701 {
6702 if (pix_x < 0)
6703 pix_x = 0;
6704 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6705 pix_x = FRAME_WINDOW_WIDTH (f);
6706
6707 if (pix_y < 0)
6708 pix_y = 0;
6709 else if (pix_y > f->height)
6710 pix_y = f->height;
6711 }
6712
6713 *x = pix_x;
6714 *y = pix_y;
6715 }
6716
6717
6718 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6719 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6720 can't tell the positions because W's display is not up to date,
6721 return 0. */
6722
6723 int
6724 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6725 struct window *w;
6726 int hpos, vpos;
6727 int *frame_x, *frame_y;
6728 {
6729 int success_p;
6730
6731 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6732 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6733
6734 if (display_completed)
6735 {
6736 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6737 struct glyph *glyph = row->glyphs[TEXT_AREA];
6738 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6739
6740 *frame_y = row->y;
6741 *frame_x = row->x;
6742 while (glyph < end)
6743 {
6744 *frame_x += glyph->pixel_width;
6745 ++glyph;
6746 }
6747
6748 success_p = 1;
6749 }
6750 else
6751 {
6752 *frame_y = *frame_x = 0;
6753 success_p = 0;
6754 }
6755
6756 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6757 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6758 return success_p;
6759 }
6760
6761
6762 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6763
6764 If the event is a button press, then note that we have grabbed
6765 the mouse. */
6766
6767 static Lisp_Object
6768 construct_mouse_click (result, event, f)
6769 struct input_event *result;
6770 EventRecord *event;
6771 struct frame *f;
6772 {
6773 Point mouseLoc;
6774
6775 result->kind = MOUSE_CLICK_EVENT;
6776 result->code = 0; /* only one mouse button */
6777 result->timestamp = event->when;
6778 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6779
6780 mouseLoc = event->where;
6781
6782 #if TARGET_API_MAC_CARBON
6783 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6784 #else
6785 SetPort (FRAME_MAC_WINDOW (f));
6786 #endif
6787
6788 GlobalToLocal (&mouseLoc);
6789 XSETINT (result->x, mouseLoc.h);
6790 XSETINT (result->y, mouseLoc.v);
6791
6792 XSETFRAME (result->frame_or_window, f);
6793
6794 result->arg = Qnil;
6795 return Qnil;
6796 }
6797
6798 \f
6799 /* Function to report a mouse movement to the mainstream Emacs code.
6800 The input handler calls this.
6801
6802 We have received a mouse movement event, which is given in *event.
6803 If the mouse is over a different glyph than it was last time, tell
6804 the mainstream emacs code by setting mouse_moved. If not, ask for
6805 another motion event, so we can check again the next time it moves. */
6806
6807 static Point last_mouse_motion_position;
6808 static Lisp_Object last_mouse_motion_frame;
6809
6810 static void
6811 note_mouse_movement (frame, pos)
6812 FRAME_PTR frame;
6813 Point *pos;
6814 {
6815 #if TARGET_API_MAC_CARBON
6816 Rect r;
6817 #endif
6818
6819 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6820 last_mouse_motion_position = *pos;
6821 XSETFRAME (last_mouse_motion_frame, frame);
6822
6823 #if TARGET_API_MAC_CARBON
6824 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6825 #else
6826 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
6827 #endif
6828 {
6829 frame->mouse_moved = 1;
6830 last_mouse_scroll_bar = Qnil;
6831 note_mouse_highlight (frame, -1, -1);
6832 }
6833 /* Has the mouse moved off the glyph it was on at the last sighting? */
6834 else if (pos->h < last_mouse_glyph.left
6835 || pos->h >= last_mouse_glyph.right
6836 || pos->v < last_mouse_glyph.top
6837 || pos->v >= last_mouse_glyph.bottom)
6838 {
6839 frame->mouse_moved = 1;
6840 last_mouse_scroll_bar = Qnil;
6841 note_mouse_highlight (frame, pos->h, pos->v);
6842 }
6843 }
6844
6845 /* This is used for debugging, to turn off note_mouse_highlight. */
6846
6847 int disable_mouse_highlight;
6848
6849
6850 \f
6851 /************************************************************************
6852 Mouse Face
6853 ************************************************************************/
6854
6855 /* Find the glyph under window-relative coordinates X/Y in window W.
6856 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6857 strings. Return in *HPOS and *VPOS the row and column number of
6858 the glyph found. Return in *AREA the glyph area containing X.
6859 Value is a pointer to the glyph found or null if X/Y is not on
6860 text, or we can't tell because W's current matrix is not up to
6861 date. */
6862
6863 static struct glyph *
6864 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6865 struct window *w;
6866 int x, y;
6867 int *hpos, *vpos, *area;
6868 int buffer_only_p;
6869 {
6870 struct glyph *glyph, *end;
6871 struct glyph_row *row = NULL;
6872 int x0, i, left_area_width;
6873
6874 /* Find row containing Y. Give up if some row is not enabled. */
6875 for (i = 0; i < w->current_matrix->nrows; ++i)
6876 {
6877 row = MATRIX_ROW (w->current_matrix, i);
6878 if (!row->enabled_p)
6879 return NULL;
6880 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6881 break;
6882 }
6883
6884 *vpos = i;
6885 *hpos = 0;
6886
6887 /* Give up if Y is not in the window. */
6888 if (i == w->current_matrix->nrows)
6889 return NULL;
6890
6891 /* Get the glyph area containing X. */
6892 if (w->pseudo_window_p)
6893 {
6894 *area = TEXT_AREA;
6895 x0 = 0;
6896 }
6897 else
6898 {
6899 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6900 if (x < left_area_width)
6901 {
6902 *area = LEFT_MARGIN_AREA;
6903 x0 = 0;
6904 }
6905 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6906 {
6907 *area = TEXT_AREA;
6908 x0 = row->x + left_area_width;
6909 }
6910 else
6911 {
6912 *area = RIGHT_MARGIN_AREA;
6913 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6914 }
6915 }
6916
6917 /* Find glyph containing X. */
6918 glyph = row->glyphs[*area];
6919 end = glyph + row->used[*area];
6920 while (glyph < end)
6921 {
6922 if (x < x0 + glyph->pixel_width)
6923 {
6924 if (w->pseudo_window_p)
6925 break;
6926 else if (!buffer_only_p || BUFFERP (glyph->object))
6927 break;
6928 }
6929
6930 x0 += glyph->pixel_width;
6931 ++glyph;
6932 }
6933
6934 if (glyph == end)
6935 return NULL;
6936
6937 *hpos = glyph - row->glyphs[*area];
6938 return glyph;
6939 }
6940
6941
6942 /* Convert frame-relative x/y to coordinates relative to window W.
6943 Takes pseudo-windows into account. */
6944
6945 static void
6946 frame_to_window_pixel_xy (w, x, y)
6947 struct window *w;
6948 int *x, *y;
6949 {
6950 if (w->pseudo_window_p)
6951 {
6952 /* A pseudo-window is always full-width, and starts at the
6953 left edge of the frame, plus a frame border. */
6954 struct frame *f = XFRAME (w->frame);
6955 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6956 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6957 }
6958 else
6959 {
6960 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6961 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6962 }
6963 }
6964
6965
6966 /* Take proper action when mouse has moved to the mode or header line of
6967 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6968 mode line. X is relative to the start of the text display area of
6969 W, so the width of fringes and scroll bars must be subtracted
6970 to get a position relative to the start of the mode line. */
6971
6972 static void
6973 note_mode_line_highlight (w, x, mode_line_p)
6974 struct window *w;
6975 int x, mode_line_p;
6976 {
6977 struct frame *f = XFRAME (w->frame);
6978 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6979 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
6980 struct glyph_row *row;
6981
6982 if (mode_line_p)
6983 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6984 else
6985 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6986
6987 if (row->enabled_p)
6988 {
6989 struct glyph *glyph, *end;
6990 Lisp_Object help, map;
6991 int x0;
6992
6993 /* Find the glyph under X. */
6994 glyph = row->glyphs[TEXT_AREA];
6995 end = glyph + row->used[TEXT_AREA];
6996 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6997 + FRAME_X_LEFT_FRINGE_WIDTH (f));
6998
6999 while (glyph < end
7000 && x >= x0 + glyph->pixel_width)
7001 {
7002 x0 += glyph->pixel_width;
7003 ++glyph;
7004 }
7005
7006 if (glyph < end
7007 && STRINGP (glyph->object)
7008 && STRING_INTERVALS (glyph->object)
7009 && glyph->charpos >= 0
7010 && glyph->charpos < SCHARS (glyph->object))
7011 {
7012 /* If we're on a string with `help-echo' text property,
7013 arrange for the help to be displayed. This is done by
7014 setting the global variable help_echo to the help string. */
7015 help = Fget_text_property (make_number (glyph->charpos),
7016 Qhelp_echo, glyph->object);
7017 if (!NILP (help))
7018 {
7019 help_echo = help;
7020 XSETWINDOW (help_echo_window, w);
7021 help_echo_object = glyph->object;
7022 help_echo_pos = glyph->charpos;
7023 }
7024
7025 /* Change the mouse pointer according to what is under X/Y. */
7026 map = Fget_text_property (make_number (glyph->charpos),
7027 Qlocal_map, glyph->object);
7028 if (KEYMAPP (map))
7029 cursor = f->output_data.mac->nontext_cursor;
7030 else
7031 {
7032 map = Fget_text_property (make_number (glyph->charpos),
7033 Qkeymap, glyph->object);
7034 if (KEYMAPP (map))
7035 cursor = f->output_data.mac->nontext_cursor;
7036 }
7037 }
7038 }
7039
7040 #if 0 /* MAC_TODO: mouse cursor */
7041 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7042 #endif
7043 }
7044
7045
7046 /* Take proper action when the mouse has moved to position X, Y on
7047 frame F as regards highlighting characters that have mouse-face
7048 properties. Also de-highlighting chars where the mouse was before.
7049 X and Y can be negative or out of range. */
7050
7051 static void
7052 note_mouse_highlight (f, x, y)
7053 struct frame *f;
7054 int x, y;
7055 {
7056 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7057 int portion;
7058 Lisp_Object window;
7059 struct window *w;
7060 struct buffer *b;
7061
7062 #if 0
7063 /* When a menu is active, don't highlight because this looks odd. */
7064 if (popup_activated ())
7065 return;
7066 #endif
7067
7068 if (NILP (Vmouse_highlight)
7069 || !f->glyphs_initialized_p)
7070 return;
7071
7072 dpyinfo->mouse_face_mouse_x = x;
7073 dpyinfo->mouse_face_mouse_y = y;
7074 dpyinfo->mouse_face_mouse_frame = f;
7075
7076 if (dpyinfo->mouse_face_defer)
7077 return;
7078
7079 if (gc_in_progress)
7080 {
7081 dpyinfo->mouse_face_deferred_gc = 1;
7082 return;
7083 }
7084
7085 /* Which window is that in? */
7086 window = window_from_coordinates (f, x, y, &portion, 1);
7087
7088 /* If we were displaying active text in another window, clear that. */
7089 if (! EQ (window, dpyinfo->mouse_face_window))
7090 clear_mouse_face (dpyinfo);
7091
7092 /* Not on a window -> return. */
7093 if (!WINDOWP (window))
7094 return;
7095
7096 /* Reset help_echo. It will get recomputed below. */
7097 help_echo = Qnil;
7098
7099 /* Convert to window-relative pixel coordinates. */
7100 w = XWINDOW (window);
7101 frame_to_window_pixel_xy (w, &x, &y);
7102
7103 /* Handle tool-bar window differently since it doesn't display a
7104 buffer. */
7105 if (EQ (window, f->tool_bar_window))
7106 {
7107 note_tool_bar_highlight (f, x, y);
7108 return;
7109 }
7110
7111 /* Mouse is on the mode or header line? */
7112 if (portion == 1 || portion == 3)
7113 {
7114 note_mode_line_highlight (w, x, portion == 1);
7115 return;
7116 }
7117 #if 0 /* TODO: mouse cursor */
7118 if (portion == 2)
7119 cursor = f->output_data.x->horizontal_drag_cursor;
7120 else
7121 cursor = f->output_data.x->text_cursor;
7122 #endif
7123 /* Are we in a window whose display is up to date?
7124 And verify the buffer's text has not changed. */
7125 b = XBUFFER (w->buffer);
7126 if (/* Within text portion of the window. */
7127 portion == 0
7128 && EQ (w->window_end_valid, w->buffer)
7129 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7130 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
7131 {
7132 int hpos, vpos, pos, i, area;
7133 struct glyph *glyph;
7134 Lisp_Object object;
7135 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7136 Lisp_Object *overlay_vec = NULL;
7137 int len, noverlays;
7138 struct buffer *obuf;
7139 int obegv, ozv, same_region;
7140
7141 /* Find the glyph under X/Y. */
7142 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
7143
7144 /* Clear mouse face if X/Y not over text. */
7145 if (glyph == NULL
7146 || area != TEXT_AREA
7147 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7148 {
7149 clear_mouse_face (dpyinfo);
7150 /* TODO: mouse cursor */
7151 goto set_cursor;
7152 }
7153
7154 pos = glyph->charpos;
7155 object = glyph->object;
7156 if (!STRINGP (object) && !BUFFERP (object))
7157 goto set_cursor;
7158
7159 /* If we get an out-of-range value, return now; avoid an error. */
7160 if (BUFFERP (object) && pos > BUF_Z (b))
7161 goto set_cursor;
7162
7163 /* Make the window's buffer temporarily current for
7164 overlays_at and compute_char_face. */
7165 obuf = current_buffer;
7166 current_buffer = b;
7167 obegv = BEGV;
7168 ozv = ZV;
7169 BEGV = BEG;
7170 ZV = Z;
7171
7172 /* Is this char mouse-active or does it have help-echo? */
7173 position = make_number (pos);
7174
7175 if (BUFFERP (object))
7176 {
7177 /* Put all the overlays we want in a vector in overlay_vec.
7178 Store the length in len. If there are more than 10, make
7179 enough space for all, and try again. */
7180 len = 10;
7181 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7182 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7183 if (noverlays > len)
7184 {
7185 len = noverlays;
7186 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7187 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7188 }
7189
7190 /* Sort overlays into increasing priority order. */
7191 noverlays = sort_overlays (overlay_vec, noverlays, w);
7192 }
7193 else
7194 noverlays = 0;
7195
7196 same_region = (EQ (window, dpyinfo->mouse_face_window)
7197 && vpos >= dpyinfo->mouse_face_beg_row
7198 && vpos <= dpyinfo->mouse_face_end_row
7199 && (vpos > dpyinfo->mouse_face_beg_row
7200 || hpos >= dpyinfo->mouse_face_beg_col)
7201 && (vpos < dpyinfo->mouse_face_end_row
7202 || hpos < dpyinfo->mouse_face_end_col
7203 || dpyinfo->mouse_face_past_end));
7204
7205 /* TODO: if (same_region)
7206 mouse cursor */
7207
7208 /* Check mouse-face highlighting. */
7209 if (! same_region
7210 /* If there exists an overlay with mouse-face overlapping
7211 the one we are currently highlighting, we have to
7212 check if we enter the overlapping overlay, and then
7213 highlight that. */
7214 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7215 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7216 {
7217 /* Find the highest priority overlay that has a mouse-face
7218 property. */
7219 overlay = Qnil;
7220 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7221 {
7222 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7223 if (!NILP (mouse_face))
7224 overlay = overlay_vec[i];
7225 }
7226
7227 /* If we're actually highlighting the same overlay as
7228 before, there's no need to do that again. */
7229 if (!NILP (overlay)
7230 && EQ (overlay, dpyinfo->mouse_face_overlay))
7231 goto check_help_echo;
7232
7233 dpyinfo->mouse_face_overlay = overlay;
7234
7235 /* Clear the display of the old active region, if any. */
7236 clear_mouse_face (dpyinfo);
7237 /* TODO: mouse cursor changes. */
7238
7239 /* If no overlay applies, get a text property. */
7240 if (NILP (overlay))
7241 mouse_face = Fget_text_property (position, Qmouse_face, object);
7242
7243 /* Handle the overlay case. */
7244 if (!NILP (overlay))
7245 {
7246 /* Find the range of text around this char that
7247 should be active. */
7248 Lisp_Object before, after;
7249 int ignore;
7250
7251 before = Foverlay_start (overlay);
7252 after = Foverlay_end (overlay);
7253 /* Record this as the current active region. */
7254 fast_find_position (w, XFASTINT (before),
7255 &dpyinfo->mouse_face_beg_col,
7256 &dpyinfo->mouse_face_beg_row,
7257 &dpyinfo->mouse_face_beg_x,
7258 &dpyinfo->mouse_face_beg_y, Qnil);
7259
7260 dpyinfo->mouse_face_past_end
7261 = !fast_find_position (w, XFASTINT (after),
7262 &dpyinfo->mouse_face_end_col,
7263 &dpyinfo->mouse_face_end_row,
7264 &dpyinfo->mouse_face_end_x,
7265 &dpyinfo->mouse_face_end_y, Qnil);
7266 dpyinfo->mouse_face_window = window;
7267
7268 dpyinfo->mouse_face_face_id
7269 = face_at_buffer_position (w, pos, 0, 0,
7270 &ignore, pos + 1, 1);
7271
7272 /* Display it as active. */
7273 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7274 /* TODO: mouse cursor changes. */
7275 }
7276 /* Handle the text property case. */
7277 else if (! NILP (mouse_face) && BUFFERP (object))
7278 {
7279 /* Find the range of text around this char that
7280 should be active. */
7281 Lisp_Object before, after, beginning, end;
7282 int ignore;
7283
7284 beginning = Fmarker_position (w->start);
7285 end = make_number (BUF_Z (XBUFFER (object))
7286 - XFASTINT (w->window_end_pos));
7287 before
7288 = Fprevious_single_property_change (make_number (pos + 1),
7289 Qmouse_face,
7290 object, beginning);
7291 after
7292 = Fnext_single_property_change (position, Qmouse_face,
7293 object, end);
7294
7295 /* Record this as the current active region. */
7296 fast_find_position (w, XFASTINT (before),
7297 &dpyinfo->mouse_face_beg_col,
7298 &dpyinfo->mouse_face_beg_row,
7299 &dpyinfo->mouse_face_beg_x,
7300 &dpyinfo->mouse_face_beg_y, Qnil);
7301 dpyinfo->mouse_face_past_end
7302 = !fast_find_position (w, XFASTINT (after),
7303 &dpyinfo->mouse_face_end_col,
7304 &dpyinfo->mouse_face_end_row,
7305 &dpyinfo->mouse_face_end_x,
7306 &dpyinfo->mouse_face_end_y, Qnil);
7307 dpyinfo->mouse_face_window = window;
7308
7309 if (BUFFERP (object))
7310 dpyinfo->mouse_face_face_id
7311 = face_at_buffer_position (w, pos, 0, 0,
7312 &ignore, pos + 1, 1);
7313
7314 /* Display it as active. */
7315 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7316 /* TODO: mouse cursor changes. */
7317 }
7318 else if (!NILP (mouse_face) && STRINGP (object))
7319 {
7320 Lisp_Object b, e;
7321 int ignore;
7322
7323 b = Fprevious_single_property_change (make_number (pos + 1),
7324 Qmouse_face,
7325 object, Qnil);
7326 e = Fnext_single_property_change (position, Qmouse_face,
7327 object, Qnil);
7328 if (NILP (b))
7329 b = make_number (0);
7330 if (NILP (e))
7331 e = make_number (SCHARS (object) - 1);
7332 fast_find_string_pos (w, XINT (b), object,
7333 &dpyinfo->mouse_face_beg_col,
7334 &dpyinfo->mouse_face_beg_row,
7335 &dpyinfo->mouse_face_beg_x,
7336 &dpyinfo->mouse_face_beg_y, 0);
7337 fast_find_string_pos (w, XINT (e), object,
7338 &dpyinfo->mouse_face_end_col,
7339 &dpyinfo->mouse_face_end_row,
7340 &dpyinfo->mouse_face_end_x,
7341 &dpyinfo->mouse_face_end_y, 1);
7342 dpyinfo->mouse_face_past_end = 0;
7343 dpyinfo->mouse_face_window = window;
7344 dpyinfo->mouse_face_face_id
7345 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7346 glyph->face_id, 1);
7347 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7348 /* TODO: mouse cursor changes. */
7349 }
7350 else if (STRINGP (object) && NILP (mouse_face))
7351 {
7352 /* A string which doesn't have mouse-face, but
7353 the text ``under'' it might have. */
7354 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7355 int start = MATRIX_ROW_START_CHARPOS (r);
7356
7357 pos = string_buffer_position (w, object, start);
7358 if (pos > 0)
7359 mouse_face = get_char_property_and_overlay (make_number (pos),
7360 Qmouse_face,
7361 w->buffer,
7362 &overlay);
7363 if (!NILP (mouse_face) && !NILP (overlay))
7364 {
7365 Lisp_Object before = Foverlay_start (overlay);
7366 Lisp_Object after = Foverlay_end (overlay);
7367 int ignore;
7368
7369 /* Note that we might not be able to find position
7370 BEFORE in the glyph matrix if the overlay is
7371 entirely covered by a `display' property. In
7372 this case, we overshoot. So let's stop in
7373 the glyph matrix before glyphs for OBJECT. */
7374 fast_find_position (w, XFASTINT (before),
7375 &dpyinfo->mouse_face_beg_col,
7376 &dpyinfo->mouse_face_beg_row,
7377 &dpyinfo->mouse_face_beg_x,
7378 &dpyinfo->mouse_face_beg_y,
7379 object);
7380
7381 dpyinfo->mouse_face_past_end
7382 = !fast_find_position (w, XFASTINT (after),
7383 &dpyinfo->mouse_face_end_col,
7384 &dpyinfo->mouse_face_end_row,
7385 &dpyinfo->mouse_face_end_x,
7386 &dpyinfo->mouse_face_end_y,
7387 Qnil);
7388 dpyinfo->mouse_face_window = window;
7389 dpyinfo->mouse_face_face_id
7390 = face_at_buffer_position (w, pos, 0, 0,
7391 &ignore, pos + 1, 1);
7392
7393 /* Display it as active. */
7394 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7395 /* TODO: mouse cursor changes. */
7396 }
7397 }
7398 }
7399
7400 check_help_echo:
7401
7402 /* Look for a `help-echo' property. */
7403 {
7404 Lisp_Object help, overlay;
7405
7406 /* Check overlays first. */
7407 help = overlay = Qnil;
7408 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7409 {
7410 overlay = overlay_vec[i];
7411 help = Foverlay_get (overlay, Qhelp_echo);
7412 }
7413
7414 if (!NILP (help))
7415 {
7416 help_echo = help;
7417 help_echo_window = window;
7418 help_echo_object = overlay;
7419 help_echo_pos = pos;
7420 }
7421 else
7422 {
7423 Lisp_Object object = glyph->object;
7424 int charpos = glyph->charpos;
7425
7426 /* Try text properties. */
7427 if (STRINGP (object)
7428 && charpos >= 0
7429 && charpos < SCHARS (object))
7430 {
7431 help = Fget_text_property (make_number (charpos),
7432 Qhelp_echo, object);
7433 if (NILP (help))
7434 {
7435 /* If the string itself doesn't specify a help-echo,
7436 see if the buffer text ``under'' it does. */
7437 struct glyph_row *r
7438 = MATRIX_ROW (w->current_matrix, vpos);
7439 int start = MATRIX_ROW_START_CHARPOS (r);
7440 int pos = string_buffer_position (w, object, start);
7441 if (pos > 0)
7442 {
7443 help = Fget_char_property (make_number (pos),
7444 Qhelp_echo, w->buffer);
7445 if (!NILP (help))
7446 {
7447 charpos = pos;
7448 object = w->buffer;
7449 }
7450 }
7451 }
7452 }
7453 else if (BUFFERP (object)
7454 && charpos >= BEGV
7455 && charpos < ZV)
7456 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7457 object);
7458
7459 if (!NILP (help))
7460 {
7461 help_echo = help;
7462 help_echo_window = window;
7463 help_echo_object = object;
7464 help_echo_pos = charpos;
7465 }
7466 }
7467 }
7468
7469 BEGV = obegv;
7470 ZV = ozv;
7471 current_buffer = obuf;
7472 }
7473
7474 set_cursor:
7475 /* TODO: mouse cursor changes. */
7476 ;
7477 }
7478
7479 static void
7480 redo_mouse_highlight ()
7481 {
7482 if (!NILP (last_mouse_motion_frame)
7483 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7484 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7485 last_mouse_motion_position.h,
7486 last_mouse_motion_position.v);
7487 }
7488
7489
7490 \f
7491 /***********************************************************************
7492 Tool-bars
7493 ***********************************************************************/
7494
7495 static int x_tool_bar_item P_ ((struct frame *, int, int,
7496 struct glyph **, int *, int *, int *));
7497
7498 /* Tool-bar item index of the item on which a mouse button was pressed
7499 or -1. */
7500
7501 static int last_tool_bar_item;
7502
7503
7504 /* Get information about the tool-bar item at position X/Y on frame F.
7505 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7506 the current matrix of the tool-bar window of F, or NULL if not
7507 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7508 item in F->current_tool_bar_items. Value is
7509
7510 -1 if X/Y is not on a tool-bar item
7511 0 if X/Y is on the same item that was highlighted before.
7512 1 otherwise. */
7513
7514 static int
7515 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7516 struct frame *f;
7517 int x, y;
7518 struct glyph **glyph;
7519 int *hpos, *vpos, *prop_idx;
7520 {
7521 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7522 struct window *w = XWINDOW (f->tool_bar_window);
7523 int area;
7524
7525 /* Find the glyph under X/Y. */
7526 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7527 if (*glyph == NULL)
7528 return -1;
7529
7530 /* Get the start of this tool-bar item's properties in
7531 f->current_tool_bar_items. */
7532 if (!tool_bar_item_info (f, *glyph, prop_idx))
7533 return -1;
7534
7535 /* Is mouse on the highlighted item? */
7536 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7537 && *vpos >= dpyinfo->mouse_face_beg_row
7538 && *vpos <= dpyinfo->mouse_face_end_row
7539 && (*vpos > dpyinfo->mouse_face_beg_row
7540 || *hpos >= dpyinfo->mouse_face_beg_col)
7541 && (*vpos < dpyinfo->mouse_face_end_row
7542 || *hpos < dpyinfo->mouse_face_end_col
7543 || dpyinfo->mouse_face_past_end))
7544 return 0;
7545
7546 return 1;
7547 }
7548
7549
7550 /* Handle mouse button event on the tool-bar of frame F, at
7551 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7552 or ButtonRelase. */
7553
7554 static void
7555 x_handle_tool_bar_click (f, button_event)
7556 struct frame *f;
7557 EventRecord *button_event;
7558 {
7559 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7560 struct window *w = XWINDOW (f->tool_bar_window);
7561 int hpos, vpos, prop_idx;
7562 struct glyph *glyph;
7563 Lisp_Object enabled_p;
7564 int x = button_event->where.h;
7565 int y = button_event->where.v;
7566
7567 /* If not on the highlighted tool-bar item, return. */
7568 frame_to_window_pixel_xy (w, &x, &y);
7569 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7570 return;
7571
7572 /* If item is disabled, do nothing. */
7573 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7574 if (NILP (enabled_p))
7575 return;
7576
7577 if (button_event->what == mouseDown)
7578 {
7579 /* Show item in pressed state. */
7580 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7581 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7582 last_tool_bar_item = prop_idx;
7583 }
7584 else
7585 {
7586 Lisp_Object key, frame;
7587 struct input_event event;
7588
7589 /* Show item in released state. */
7590 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7591 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7592
7593 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7594
7595 XSETFRAME (frame, f);
7596 event.kind = TOOL_BAR_EVENT;
7597 event.frame_or_window = frame;
7598 event.arg = frame;
7599 kbd_buffer_store_event (&event);
7600
7601 event.kind = TOOL_BAR_EVENT;
7602 event.frame_or_window = frame;
7603 event.arg = key;
7604 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7605 button_event->modifiers);
7606 kbd_buffer_store_event (&event);
7607 last_tool_bar_item = -1;
7608 }
7609 }
7610
7611
7612 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7613 tool-bar window-relative coordinates X/Y. Called from
7614 note_mouse_highlight. */
7615
7616 static void
7617 note_tool_bar_highlight (f, x, y)
7618 struct frame *f;
7619 int x, y;
7620 {
7621 Lisp_Object window = f->tool_bar_window;
7622 struct window *w = XWINDOW (window);
7623 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7624 int hpos, vpos;
7625 struct glyph *glyph;
7626 struct glyph_row *row;
7627 int i;
7628 Lisp_Object enabled_p;
7629 int prop_idx;
7630 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7631 int mouse_down_p, rc;
7632
7633 /* Function note_mouse_highlight is called with negative x(y
7634 values when mouse moves outside of the frame. */
7635 if (x <= 0 || y <= 0)
7636 {
7637 clear_mouse_face (dpyinfo);
7638 return;
7639 }
7640
7641 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7642 if (rc < 0)
7643 {
7644 /* Not on tool-bar item. */
7645 clear_mouse_face (dpyinfo);
7646 return;
7647 }
7648 else if (rc == 0)
7649 /* On same tool-bar item as before. */
7650 goto set_help_echo;
7651
7652 clear_mouse_face (dpyinfo);
7653
7654 /* Mouse is down, but on different tool-bar item? */
7655 mouse_down_p = (dpyinfo->grabbed
7656 && f == last_mouse_frame
7657 && FRAME_LIVE_P (f));
7658 if (mouse_down_p
7659 && last_tool_bar_item != prop_idx)
7660 return;
7661
7662 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7663 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7664
7665 /* If tool-bar item is not enabled, don't highlight it. */
7666 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7667 if (!NILP (enabled_p))
7668 {
7669 /* Compute the x-position of the glyph. In front and past the
7670 image is a space. We include this is the highlighted area. */
7671 row = MATRIX_ROW (w->current_matrix, vpos);
7672 for (i = x = 0; i < hpos; ++i)
7673 x += row->glyphs[TEXT_AREA][i].pixel_width;
7674
7675 /* Record this as the current active region. */
7676 dpyinfo->mouse_face_beg_col = hpos;
7677 dpyinfo->mouse_face_beg_row = vpos;
7678 dpyinfo->mouse_face_beg_x = x;
7679 dpyinfo->mouse_face_beg_y = row->y;
7680 dpyinfo->mouse_face_past_end = 0;
7681
7682 dpyinfo->mouse_face_end_col = hpos + 1;
7683 dpyinfo->mouse_face_end_row = vpos;
7684 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7685 dpyinfo->mouse_face_end_y = row->y;
7686 dpyinfo->mouse_face_window = window;
7687 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7688
7689 /* Display it as active. */
7690 show_mouse_face (dpyinfo, draw);
7691 dpyinfo->mouse_face_image_state = draw;
7692 }
7693
7694 set_help_echo:
7695
7696 /* Set help_echo to a help string.to display for this tool-bar item.
7697 XTread_socket does the rest. */
7698 help_echo_object = help_echo_window = Qnil;
7699 help_echo_pos = -1;
7700 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7701 if (NILP (help_echo))
7702 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7703 }
7704
7705
7706 \f
7707 /* Find the glyph matrix position of buffer position CHARPOS in window
7708 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7709 current glyphs must be up to date. If CHARPOS is above window
7710 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7711 of last line in W. In the row containing CHARPOS, stop before glyphs
7712 having STOP as object. */
7713
7714 #if 0 /* This is a version of fast_find_position that's more correct
7715 in the presence of hscrolling, for example. I didn't install
7716 it right away because the problem fixed is minor, it failed
7717 in 20.x as well, and I think it's too risky to install
7718 so near the release of 21.1. 2001-09-25 gerd. */
7719
7720 static int
7721 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7722 struct window *w;
7723 int charpos;
7724 int *hpos, *vpos, *x, *y;
7725 Lisp_Object stop;
7726 {
7727 struct glyph_row *row, *first;
7728 struct glyph *glyph, *end;
7729 int i, past_end = 0;
7730
7731 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7732 row = row_containing_pos (w, charpos, first, NULL, 0);
7733 if (row == NULL)
7734 {
7735 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7736 {
7737 *x = *y = *hpos = *vpos = 0;
7738 return 0;
7739 }
7740 else
7741 {
7742 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7743 past_end = 1;
7744 }
7745 }
7746
7747 *x = row->x;
7748 *y = row->y;
7749 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7750
7751 glyph = row->glyphs[TEXT_AREA];
7752 end = glyph + row->used[TEXT_AREA];
7753
7754 /* Skip over glyphs not having an object at the start of the row.
7755 These are special glyphs like truncation marks on terminal
7756 frames. */
7757 if (row->displays_text_p)
7758 while (glyph < end
7759 && INTEGERP (glyph->object)
7760 && !EQ (stop, glyph->object)
7761 && glyph->charpos < 0)
7762 {
7763 *x += glyph->pixel_width;
7764 ++glyph;
7765 }
7766
7767 while (glyph < end
7768 && !INTEGERP (glyph->object)
7769 && !EQ (stop, glyph->object)
7770 && (!BUFFERP (glyph->object)
7771 || glyph->charpos < charpos))
7772 {
7773 *x += glyph->pixel_width;
7774 ++glyph;
7775 }
7776
7777 *hpos = glyph - row->glyphs[TEXT_AREA];
7778 return past_end;
7779 }
7780
7781 #else /* not 0 */
7782
7783 static int
7784 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7785 struct window *w;
7786 int pos;
7787 int *hpos, *vpos, *x, *y;
7788 Lisp_Object stop;
7789 {
7790 int i;
7791 int lastcol;
7792 int maybe_next_line_p = 0;
7793 int line_start_position;
7794 int yb = window_text_bottom_y (w);
7795 struct glyph_row *row, *best_row;
7796 int row_vpos, best_row_vpos;
7797 int current_x;
7798
7799 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7800 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7801
7802 while (row->y < yb)
7803 {
7804 if (row->used[TEXT_AREA])
7805 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7806 else
7807 line_start_position = 0;
7808
7809 if (line_start_position > pos)
7810 break;
7811 /* If the position sought is the end of the buffer,
7812 don't include the blank lines at the bottom of the window. */
7813 else if (line_start_position == pos
7814 && pos == BUF_ZV (XBUFFER (w->buffer)))
7815 {
7816 maybe_next_line_p = 1;
7817 break;
7818 }
7819 else if (line_start_position > 0)
7820 {
7821 best_row = row;
7822 best_row_vpos = row_vpos;
7823 }
7824
7825 if (row->y + row->height >= yb)
7826 break;
7827
7828 ++row;
7829 ++row_vpos;
7830 }
7831
7832 /* Find the right column within BEST_ROW. */
7833 lastcol = 0;
7834 current_x = best_row->x;
7835 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7836 {
7837 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7838 int charpos = glyph->charpos;
7839
7840 if (BUFFERP (glyph->object))
7841 {
7842 if (charpos == pos)
7843 {
7844 *hpos = i;
7845 *vpos = best_row_vpos;
7846 *x = current_x;
7847 *y = best_row->y;
7848 return 1;
7849 }
7850 else if (charpos > pos)
7851 break;
7852 }
7853 else if (EQ (glyph->object, stop))
7854 break;
7855
7856 if (charpos > 0)
7857 lastcol = i;
7858 current_x += glyph->pixel_width;
7859 }
7860
7861 /* If we're looking for the end of the buffer,
7862 and we didn't find it in the line we scanned,
7863 use the start of the following line. */
7864 if (maybe_next_line_p)
7865 {
7866 ++best_row;
7867 ++best_row_vpos;
7868 lastcol = 0;
7869 current_x = best_row->x;
7870 }
7871
7872 *vpos = best_row_vpos;
7873 *hpos = lastcol + 1;
7874 *x = current_x;
7875 *y = best_row->y;
7876 return 0;
7877 }
7878
7879 #endif /* not 0 */
7880
7881
7882 /* Find the position of the glyph for position POS in OBJECT in
7883 window W's current matrix, and return in *X/*Y the pixel
7884 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7885
7886 RIGHT_P non-zero means return the position of the right edge of the
7887 glyph, RIGHT_P zero means return the left edge position.
7888
7889 If no glyph for POS exists in the matrix, return the position of
7890 the glyph with the next smaller position that is in the matrix, if
7891 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7892 exists in the matrix, return the position of the glyph with the
7893 next larger position in OBJECT.
7894
7895 Value is non-zero if a glyph was found. */
7896
7897 static int
7898 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7899 struct window *w;
7900 int pos;
7901 Lisp_Object object;
7902 int *hpos, *vpos, *x, *y;
7903 int right_p;
7904 {
7905 int yb = window_text_bottom_y (w);
7906 struct glyph_row *r;
7907 struct glyph *best_glyph = NULL;
7908 struct glyph_row *best_row = NULL;
7909 int best_x = 0;
7910
7911 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7912 r->enabled_p && r->y < yb;
7913 ++r)
7914 {
7915 struct glyph *g = r->glyphs[TEXT_AREA];
7916 struct glyph *e = g + r->used[TEXT_AREA];
7917 int gx;
7918
7919 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7920 if (EQ (g->object, object))
7921 {
7922 if (g->charpos == pos)
7923 {
7924 best_glyph = g;
7925 best_x = gx;
7926 best_row = r;
7927 goto found;
7928 }
7929 else if (best_glyph == NULL
7930 || ((abs (g->charpos - pos)
7931 < abs (best_glyph->charpos - pos))
7932 && (right_p
7933 ? g->charpos < pos
7934 : g->charpos > pos)))
7935 {
7936 best_glyph = g;
7937 best_x = gx;
7938 best_row = r;
7939 }
7940 }
7941 }
7942
7943 found:
7944
7945 if (best_glyph)
7946 {
7947 *x = best_x;
7948 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7949
7950 if (right_p)
7951 {
7952 *x += best_glyph->pixel_width;
7953 ++*hpos;
7954 }
7955
7956 *y = best_row->y;
7957 *vpos = best_row - w->current_matrix->rows;
7958 }
7959
7960 return best_glyph != NULL;
7961 }
7962
7963
7964 /* Display the active region described by mouse_face_*
7965 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7966
7967 static void
7968 show_mouse_face (dpyinfo, draw)
7969 struct mac_display_info *dpyinfo;
7970 enum draw_glyphs_face draw;
7971 {
7972 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7973 struct frame *f = XFRAME (WINDOW_FRAME (w));
7974
7975 if (/* If window is in the process of being destroyed, don't bother
7976 to do anything. */
7977 w->current_matrix != NULL
7978 /* Don't update mouse highlight if hidden */
7979 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7980 /* Recognize when we are called to operate on rows that don't exist
7981 anymore. This can happen when a window is split. */
7982 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7983 {
7984 int phys_cursor_on_p = w->phys_cursor_on_p;
7985 struct glyph_row *row, *first, *last;
7986
7987 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7988 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7989
7990 for (row = first; row <= last && row->enabled_p; ++row)
7991 {
7992 int start_hpos, end_hpos, start_x;
7993
7994 /* For all but the first row, the highlight starts at column 0. */
7995 if (row == first)
7996 {
7997 start_hpos = dpyinfo->mouse_face_beg_col;
7998 start_x = dpyinfo->mouse_face_beg_x;
7999 }
8000 else
8001 {
8002 start_hpos = 0;
8003 start_x = 0;
8004 }
8005
8006 if (row == last)
8007 end_hpos = dpyinfo->mouse_face_end_col;
8008 else
8009 end_hpos = row->used[TEXT_AREA];
8010
8011 if (end_hpos > start_hpos)
8012 {
8013 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8014 start_hpos, end_hpos, draw, 0);
8015
8016 row->mouse_face_p
8017 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8018 }
8019 }
8020
8021 /* When we've written over the cursor, arrange for it to
8022 be displayed again. */
8023 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8024 x_display_cursor (w, 1,
8025 w->phys_cursor.hpos, w->phys_cursor.vpos,
8026 w->phys_cursor.x, w->phys_cursor.y);
8027 }
8028
8029 #if 0 /* MAC_TODO: mouse cursor */
8030 /* Change the mouse cursor. */
8031 if (draw == DRAW_NORMAL_TEXT)
8032 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8033 f->output_data.x->text_cursor);
8034 else if (draw == DRAW_MOUSE_FACE)
8035 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8036 f->output_data.x->cross_cursor);
8037 else
8038 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8039 f->output_data.x->nontext_cursor);
8040 #endif
8041 }
8042
8043 /* Clear out the mouse-highlighted active region.
8044 Redraw it un-highlighted first. */
8045
8046 static int
8047 clear_mouse_face (dpyinfo)
8048 struct mac_display_info *dpyinfo;
8049 {
8050 int cleared = 0;
8051
8052 if (! NILP (dpyinfo->mouse_face_window))
8053 {
8054 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8055 cleared = 1;
8056 }
8057
8058 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8059 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8060 dpyinfo->mouse_face_window = Qnil;
8061 dpyinfo->mouse_face_overlay = Qnil;
8062 return cleared;
8063 }
8064
8065
8066 /* Clear any mouse-face on window W. This function is part of the
8067 redisplay interface, and is called from try_window_id and similar
8068 functions to ensure the mouse-highlight is off. */
8069
8070 static void
8071 x_clear_mouse_face (w)
8072 struct window *w;
8073 {
8074 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8075 Lisp_Object window;
8076
8077 BLOCK_INPUT;
8078 XSETWINDOW (window, w);
8079 if (EQ (window, dpyinfo->mouse_face_window))
8080 clear_mouse_face (dpyinfo);
8081 UNBLOCK_INPUT;
8082 }
8083
8084
8085 /* Just discard the mouse face information for frame F, if any.
8086 This is used when the size of F is changed. */
8087
8088 void
8089 cancel_mouse_face (f)
8090 FRAME_PTR f;
8091 {
8092 Lisp_Object window;
8093 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8094
8095 window = dpyinfo->mouse_face_window;
8096 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8097 {
8098 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8099 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8100 dpyinfo->mouse_face_window = Qnil;
8101 }
8102 }
8103 \f
8104 static struct scroll_bar *x_window_to_scroll_bar ();
8105 static void x_scroll_bar_report_motion ();
8106 static void x_check_fullscreen P_ ((struct frame *));
8107 static void x_check_fullscreen_move P_ ((struct frame *));
8108 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8109
8110
8111 /* Try to determine frame pixel position and size of the glyph under
8112 frame pixel coordinates X/Y on frame F . Return the position and
8113 size in *RECT. Value is non-zero if we could compute these
8114 values. */
8115
8116 static int
8117 glyph_rect (f, x, y, rect)
8118 struct frame *f;
8119 int x, y;
8120 Rect *rect;
8121 {
8122 Lisp_Object window;
8123 int part;
8124
8125 window = window_from_coordinates (f, x, y, &part, 0);
8126 if (!NILP (window))
8127 {
8128 struct window *w = XWINDOW (window);
8129 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8130 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8131
8132 frame_to_window_pixel_xy (w, &x, &y);
8133
8134 for (; r < end && r->enabled_p; ++r)
8135 if (r->y <= y && r->y + r->height > y)
8136 {
8137 /* Found the row at y. */
8138 struct glyph *g = r->glyphs[TEXT_AREA];
8139 struct glyph *end = g + r->used[TEXT_AREA];
8140 int gx;
8141
8142 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8143 rect->bottom = rect->top + r->height;
8144
8145 if (x < r->x)
8146 {
8147 /* x is to the left of the first glyph in the row. */
8148 rect->left = XINT (w->left);
8149 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8150 return 1;
8151 }
8152
8153 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8154 if (gx <= x && gx + g->pixel_width > x)
8155 {
8156 /* x is on a glyph. */
8157 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8158 rect->right = rect->left + g->pixel_width;
8159 return 1;
8160 }
8161
8162 /* x is to the right of the last glyph in the row. */
8163 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8164 rect->right = XINT (w->left) + XINT (w->width);
8165 return 1;
8166 }
8167 }
8168
8169 /* The y is not on any row. */
8170 return 0;
8171 }
8172
8173 /* Record the position of the mouse in last_mouse_glyph. */
8174 static void
8175 remember_mouse_glyph (f1, gx, gy)
8176 struct frame * f1;
8177 int gx, gy;
8178 {
8179 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8180 {
8181 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8182 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8183
8184 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8185 round down even for negative values. */
8186 if (gx < 0)
8187 gx -= width - 1;
8188 if (gy < 0)
8189 gy -= height - 1;
8190 #if 0
8191 /* This was the original code from XTmouse_position, but it seems
8192 to give the position of the glyph diagonally next to the one
8193 the mouse is over. */
8194 gx = (gx + width - 1) / width * width;
8195 gy = (gy + height - 1) / height * height;
8196 #else
8197 gx = gx / width * width;
8198 gy = gy / height * height;
8199 #endif
8200
8201 last_mouse_glyph.left = gx;
8202 last_mouse_glyph.top = gy;
8203 last_mouse_glyph.right = gx + width;
8204 last_mouse_glyph.bottom = gy + height;
8205 }
8206 }
8207
8208 /* Return the current position of the mouse.
8209 *fp should be a frame which indicates which display to ask about.
8210
8211 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8212 and *part to the frame, window, and scroll bar part that the mouse
8213 is over. Set *x and *y to the portion and whole of the mouse's
8214 position on the scroll bar.
8215
8216 If the mouse movement started elsewhere, set *fp to the frame the
8217 mouse is on, *bar_window to nil, and *x and *y to the character cell
8218 the mouse is over.
8219
8220 Set *time to the server time-stamp for the time at which the mouse
8221 was at this position.
8222
8223 Don't store anything if we don't have a valid set of values to report.
8224
8225 This clears the mouse_moved flag, so we can wait for the next mouse
8226 movement. */
8227
8228 static void
8229 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8230 FRAME_PTR *fp;
8231 int insist;
8232 Lisp_Object *bar_window;
8233 enum scroll_bar_part *part;
8234 Lisp_Object *x, *y;
8235 unsigned long *time;
8236 {
8237 Point mouse_pos;
8238 int ignore1, ignore2;
8239 WindowPtr wp = FrontWindow ();
8240 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8241 Lisp_Object frame, tail;
8242
8243 BLOCK_INPUT;
8244
8245 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8246 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8247 else
8248 {
8249 /* Clear the mouse-moved flag for every frame on this display. */
8250 FOR_EACH_FRAME (tail, frame)
8251 XFRAME (frame)->mouse_moved = 0;
8252
8253 last_mouse_scroll_bar = Qnil;
8254
8255 #if TARGET_API_MAC_CARBON
8256 SetPort (GetWindowPort (wp));
8257 #else
8258 SetPort (wp);
8259 #endif
8260
8261 GetMouse (&mouse_pos);
8262
8263 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8264 &last_mouse_glyph, insist);
8265
8266 *bar_window = Qnil;
8267 *part = scroll_bar_handle;
8268 *fp = f;
8269 XSETINT (*x, mouse_pos.h);
8270 XSETINT (*y, mouse_pos.v);
8271 *time = last_mouse_movement_time;
8272 }
8273
8274 UNBLOCK_INPUT;
8275 }
8276
8277 \f
8278 /************************************************************************
8279 Scroll bars, general
8280 ************************************************************************/
8281
8282 /* Create a scroll bar and return the scroll bar vector for it. W is
8283 the Emacs window on which to create the scroll bar. TOP, LEFT,
8284 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
8285 scroll bar. */
8286
8287 static struct scroll_bar *
8288 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8289 struct window *w;
8290 int top, left, width, height, disp_top, disp_height;
8291 {
8292 struct frame *f = XFRAME (w->frame);
8293 struct scroll_bar *bar
8294 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8295 Rect r;
8296 ControlHandle ch;
8297
8298 BLOCK_INPUT;
8299
8300 r.left = left;
8301 r.top = disp_top;
8302 r.right = left + width;
8303 r.bottom = disp_top + disp_height;
8304
8305 #ifdef TARGET_API_MAC_CARBON
8306 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8307 kControlScrollBarProc, 0L);
8308 #else
8309 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8310 0L);
8311 #endif
8312 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8313 SetControlReference (ch, (long) bar);
8314
8315 XSETWINDOW (bar->window, w);
8316 XSETINT (bar->top, top);
8317 XSETINT (bar->left, left);
8318 XSETINT (bar->width, width);
8319 XSETINT (bar->height, height);
8320 XSETINT (bar->start, 0);
8321 XSETINT (bar->end, 0);
8322 bar->dragging = Qnil;
8323
8324 /* Add bar to its frame's list of scroll bars. */
8325 bar->next = FRAME_SCROLL_BARS (f);
8326 bar->prev = Qnil;
8327 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8328 if (!NILP (bar->next))
8329 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8330
8331 UNBLOCK_INPUT;
8332 return bar;
8333 }
8334
8335
8336 /* Draw BAR's handle in the proper position.
8337
8338 If the handle is already drawn from START to END, don't bother
8339 redrawing it, unless REBUILD is non-zero; in that case, always
8340 redraw it. (REBUILD is handy for drawing the handle after expose
8341 events.)
8342
8343 Normally, we want to constrain the start and end of the handle to
8344 fit inside its rectangle, but if the user is dragging the scroll
8345 bar handle, we want to let them drag it down all the way, so that
8346 the bar's top is as far down as it goes; otherwise, there's no way
8347 to move to the very end of the buffer. */
8348
8349 static void
8350 x_scroll_bar_set_handle (bar, start, end, rebuild)
8351 struct scroll_bar *bar;
8352 int start, end;
8353 int rebuild;
8354 {
8355 int dragging = ! NILP (bar->dragging);
8356 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8357 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8358 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8359 int length = end - start;
8360
8361 /* If the display is already accurate, do nothing. */
8362 if (! rebuild
8363 && start == XINT (bar->start)
8364 && end == XINT (bar->end))
8365 return;
8366
8367 BLOCK_INPUT;
8368
8369 /* Make sure the values are reasonable, and try to preserve the
8370 distance between start and end. */
8371 if (start < 0)
8372 start = 0;
8373 else if (start > top_range)
8374 start = top_range;
8375 end = start + length;
8376
8377 if (end < start)
8378 end = start;
8379 else if (end > top_range && ! dragging)
8380 end = top_range;
8381
8382 /* Store the adjusted setting in the scroll bar. */
8383 XSETINT (bar->start, start);
8384 XSETINT (bar->end, end);
8385
8386 /* Clip the end position, just for display. */
8387 if (end > top_range)
8388 end = top_range;
8389
8390 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8391 top positions, to make sure the handle is always at least that
8392 many pixels tall. */
8393 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8394
8395 SetControlMinimum (ch, 0);
8396 /* Don't inadvertently activate deactivated scroll bars */
8397 if (GetControlMaximum (ch) != -1)
8398 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8399 - (end - start));
8400 SetControlValue (ch, start);
8401 #if TARGET_API_MAC_CARBON
8402 SetControlViewSize (ch, end - start);
8403 #endif
8404
8405 UNBLOCK_INPUT;
8406 }
8407
8408
8409 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8410 nil. */
8411
8412 static void
8413 x_scroll_bar_remove (bar)
8414 struct scroll_bar *bar;
8415 {
8416 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8417
8418 BLOCK_INPUT;
8419
8420 /* Destroy the Mac scroll bar control */
8421 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8422
8423 /* Disassociate this scroll bar from its window. */
8424 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8425
8426 UNBLOCK_INPUT;
8427 }
8428
8429 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8430 that we are displaying PORTION characters out of a total of WHOLE
8431 characters, starting at POSITION. If WINDOW has no scroll bar,
8432 create one. */
8433 static void
8434 XTset_vertical_scroll_bar (w, portion, whole, position)
8435 struct window *w;
8436 int portion, whole, position;
8437 {
8438 struct frame *f = XFRAME (w->frame);
8439 struct scroll_bar *bar;
8440 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8441 int window_x, window_y, window_width, window_height;
8442
8443 /* Get window dimensions. */
8444 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8445 top = window_y;
8446 #ifdef MAC_OSX
8447 width = 16;
8448 #else
8449 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8450 #endif
8451 height = window_height;
8452
8453 /* Compute the left edge of the scroll bar area. */
8454 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8455 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8456 else
8457 left = XFASTINT (w->left);
8458 left *= CANON_X_UNIT (f);
8459 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8460
8461 /* Compute the width of the scroll bar which might be less than
8462 the width of the area reserved for the scroll bar. */
8463 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8464 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8465 else
8466 sb_width = width;
8467
8468 /* Compute the left edge of the scroll bar. */
8469 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8470 sb_left = left + width - sb_width - (width - sb_width) / 2;
8471 else
8472 sb_left = left + (width - sb_width) / 2;
8473
8474 /* Adjustments according to Inside Macintosh to make it look nice */
8475 disp_top = top;
8476 disp_height = height;
8477 if (disp_top == 0)
8478 {
8479 disp_top = -1;
8480 disp_height++;
8481 }
8482 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8483 {
8484 disp_top++;
8485 disp_height--;
8486 }
8487
8488 if (sb_left + sb_width == PIXEL_WIDTH (f))
8489 sb_left++;
8490
8491 /* Does the scroll bar exist yet? */
8492 if (NILP (w->vertical_scroll_bar))
8493 {
8494 BLOCK_INPUT;
8495 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8496 left, top, width, height, 0);
8497 UNBLOCK_INPUT;
8498 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8499 disp_height);
8500 XSETVECTOR (w->vertical_scroll_bar, bar);
8501 }
8502 else
8503 {
8504 /* It may just need to be moved and resized. */
8505 ControlHandle ch;
8506
8507 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8508 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8509
8510 BLOCK_INPUT;
8511
8512 /* If already correctly positioned, do nothing. */
8513 if (XINT (bar->left) == sb_left
8514 && XINT (bar->top) == top
8515 && XINT (bar->width) == sb_width
8516 && XINT (bar->height) == height)
8517 Draw1Control (ch);
8518 else
8519 {
8520 /* Clear areas not covered by the scroll bar because it's not as
8521 wide as the area reserved for it . This makes sure a
8522 previous mode line display is cleared after C-x 2 C-x 1, for
8523 example. */
8524 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8525 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8526 left, top, area_width, height, 0);
8527
8528 #if 0
8529 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8530 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8531 sb_left - 1, top, 1, height, 0);
8532 #endif
8533
8534 HideControl (ch);
8535 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8536 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8537 disp_height);
8538 ShowControl (ch);
8539
8540 /* Remember new settings. */
8541 XSETINT (bar->left, sb_left);
8542 XSETINT (bar->top, top);
8543 XSETINT (bar->width, sb_width);
8544 XSETINT (bar->height, height);
8545 }
8546
8547 UNBLOCK_INPUT;
8548 }
8549
8550 /* Set the scroll bar's current state, unless we're currently being
8551 dragged. */
8552 if (NILP (bar->dragging))
8553 {
8554 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8555
8556 if (whole == 0)
8557 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8558 else
8559 {
8560 int start = ((double) position * top_range) / whole;
8561 int end = ((double) (position + portion) * top_range) / whole;
8562 x_scroll_bar_set_handle (bar, start, end, 0);
8563 }
8564 }
8565 }
8566
8567
8568 /* The following three hooks are used when we're doing a thorough
8569 redisplay of the frame. We don't explicitly know which scroll bars
8570 are going to be deleted, because keeping track of when windows go
8571 away is a real pain - "Can you say set-window-configuration, boys
8572 and girls?" Instead, we just assert at the beginning of redisplay
8573 that *all* scroll bars are to be removed, and then save a scroll bar
8574 from the fiery pit when we actually redisplay its window. */
8575
8576 /* Arrange for all scroll bars on FRAME to be removed at the next call
8577 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8578 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8579
8580 static void
8581 XTcondemn_scroll_bars (frame)
8582 FRAME_PTR frame;
8583 {
8584 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8585 while (! NILP (FRAME_SCROLL_BARS (frame)))
8586 {
8587 Lisp_Object bar;
8588 bar = FRAME_SCROLL_BARS (frame);
8589 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8590 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8591 XSCROLL_BAR (bar)->prev = Qnil;
8592 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8593 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8594 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8595 }
8596 }
8597
8598
8599 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8600 Note that WINDOW isn't necessarily condemned at all. */
8601
8602 static void
8603 XTredeem_scroll_bar (window)
8604 struct window *window;
8605 {
8606 struct scroll_bar *bar;
8607
8608 /* We can't redeem this window's scroll bar if it doesn't have one. */
8609 if (NILP (window->vertical_scroll_bar))
8610 abort ();
8611
8612 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8613
8614 /* Unlink it from the condemned list. */
8615 {
8616 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8617
8618 if (NILP (bar->prev))
8619 {
8620 /* If the prev pointer is nil, it must be the first in one of
8621 the lists. */
8622 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8623 /* It's not condemned. Everything's fine. */
8624 return;
8625 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8626 window->vertical_scroll_bar))
8627 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8628 else
8629 /* If its prev pointer is nil, it must be at the front of
8630 one or the other! */
8631 abort ();
8632 }
8633 else
8634 XSCROLL_BAR (bar->prev)->next = bar->next;
8635
8636 if (! NILP (bar->next))
8637 XSCROLL_BAR (bar->next)->prev = bar->prev;
8638
8639 bar->next = FRAME_SCROLL_BARS (f);
8640 bar->prev = Qnil;
8641 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8642 if (! NILP (bar->next))
8643 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8644 }
8645 }
8646
8647 /* Remove all scroll bars on FRAME that haven't been saved since the
8648 last call to `*condemn_scroll_bars_hook'. */
8649
8650 static void
8651 XTjudge_scroll_bars (f)
8652 FRAME_PTR f;
8653 {
8654 Lisp_Object bar, next;
8655
8656 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8657
8658 /* Clear out the condemned list now so we won't try to process any
8659 more events on the hapless scroll bars. */
8660 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8661
8662 for (; ! NILP (bar); bar = next)
8663 {
8664 struct scroll_bar *b = XSCROLL_BAR (bar);
8665
8666 x_scroll_bar_remove (b);
8667
8668 next = b->next;
8669 b->next = b->prev = Qnil;
8670 }
8671
8672 /* Now there should be no references to the condemned scroll bars,
8673 and they should get garbage-collected. */
8674 }
8675
8676
8677 static void
8678 activate_scroll_bars (frame)
8679 FRAME_PTR frame;
8680 {
8681 Lisp_Object bar;
8682 ControlHandle ch;
8683
8684 bar = FRAME_SCROLL_BARS (frame);
8685 while (! NILP (bar))
8686 {
8687 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8688 #ifdef TARGET_API_MAC_CARBON
8689 ActivateControl (ch);
8690 #else
8691 SetControlMaximum (ch,
8692 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8693 XINT (XSCROLL_BAR (bar)
8694 ->height)) - 1);
8695 #endif
8696 bar = XSCROLL_BAR (bar)->next;
8697 }
8698 }
8699
8700
8701 static void
8702 deactivate_scroll_bars (frame)
8703 FRAME_PTR frame;
8704 {
8705 Lisp_Object bar;
8706 ControlHandle ch;
8707
8708 bar = FRAME_SCROLL_BARS (frame);
8709 while (! NILP (bar))
8710 {
8711 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8712 #ifdef TARGET_API_MAC_CARBON
8713 DeactivateControl (ch);
8714 #else
8715 SetControlMaximum (ch, XINT (-1));
8716 #endif
8717 bar = XSCROLL_BAR (bar)->next;
8718 }
8719 }
8720
8721 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8722 is set to something other than NO_EVENT, it is enqueued.
8723
8724 This may be called from a signal handler, so we have to ignore GC
8725 mark bits. */
8726
8727 static void
8728 x_scroll_bar_handle_click (bar, part_code, er, bufp)
8729 struct scroll_bar *bar;
8730 int part_code;
8731 EventRecord *er;
8732 struct input_event *bufp;
8733 {
8734 if (! GC_WINDOWP (bar->window))
8735 abort ();
8736
8737 bufp->kind = SCROLL_BAR_CLICK_EVENT;
8738 bufp->frame_or_window = bar->window;
8739 bufp->arg = Qnil;
8740
8741 bar->dragging = Qnil;
8742
8743 switch (part_code)
8744 {
8745 case kControlUpButtonPart:
8746 bufp->part = scroll_bar_up_arrow;
8747 break;
8748 case kControlDownButtonPart:
8749 bufp->part = scroll_bar_down_arrow;
8750 break;
8751 case kControlPageUpPart:
8752 bufp->part = scroll_bar_above_handle;
8753 break;
8754 case kControlPageDownPart:
8755 bufp->part = scroll_bar_below_handle;
8756 break;
8757 #ifdef TARGET_API_MAC_CARBON
8758 default:
8759 #else
8760 case kControlIndicatorPart:
8761 #endif
8762 if (er->what == mouseDown)
8763 bar->dragging = make_number (0);
8764 XSETVECTOR (last_mouse_scroll_bar, bar);
8765 bufp->part = scroll_bar_handle;
8766 break;
8767 }
8768 }
8769
8770
8771 /* Handle some mouse motion while someone is dragging the scroll bar.
8772
8773 This may be called from a signal handler, so we have to ignore GC
8774 mark bits. */
8775
8776 static void
8777 x_scroll_bar_note_movement (bar, y_pos, t)
8778 struct scroll_bar *bar;
8779 int y_pos;
8780 Time t;
8781 {
8782 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8783
8784 last_mouse_movement_time = t;
8785
8786 f->mouse_moved = 1;
8787 XSETVECTOR (last_mouse_scroll_bar, bar);
8788
8789 /* If we're dragging the bar, display it. */
8790 if (! GC_NILP (bar->dragging))
8791 {
8792 /* Where should the handle be now? */
8793 int new_start = y_pos - 24;
8794
8795 if (new_start != XINT (bar->start))
8796 {
8797 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8798
8799 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8800 }
8801 }
8802 }
8803
8804
8805 /* Return information to the user about the current position of the
8806 mouse on the scroll bar. */
8807
8808 static void
8809 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8810 FRAME_PTR *fp;
8811 Lisp_Object *bar_window;
8812 enum scroll_bar_part *part;
8813 Lisp_Object *x, *y;
8814 unsigned long *time;
8815 {
8816 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8817 WindowPtr wp = FrontWindow ();
8818 Point mouse_pos;
8819 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8820 int win_y, top_range;
8821
8822 #if TARGET_API_MAC_CARBON
8823 SetPort (GetWindowPort (wp));
8824 #else
8825 SetPort (wp);
8826 #endif
8827
8828 GetMouse (&mouse_pos);
8829
8830 win_y = mouse_pos.v - XINT (bar->top);
8831 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8832
8833 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8834
8835 win_y -= 24;
8836
8837 if (! NILP (bar->dragging))
8838 win_y -= XINT (bar->dragging);
8839
8840 if (win_y < 0)
8841 win_y = 0;
8842 if (win_y > top_range)
8843 win_y = top_range;
8844
8845 *fp = f;
8846 *bar_window = bar->window;
8847
8848 if (! NILP (bar->dragging))
8849 *part = scroll_bar_handle;
8850 else if (win_y < XINT (bar->start))
8851 *part = scroll_bar_above_handle;
8852 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8853 *part = scroll_bar_handle;
8854 else
8855 *part = scroll_bar_below_handle;
8856
8857 XSETINT (*x, win_y);
8858 XSETINT (*y, top_range);
8859
8860 f->mouse_moved = 0;
8861 last_mouse_scroll_bar = Qnil;
8862
8863 *time = last_mouse_movement_time;
8864 }
8865 \f
8866 /***********************************************************************
8867 Text Cursor
8868 ***********************************************************************/
8869
8870 /* Notice if the text cursor of window W has been overwritten by a
8871 drawing operation that outputs glyphs starting at START_X and
8872 ending at END_X in the line given by output_cursor.vpos.
8873 Coordinates are area-relative. END_X < 0 means all the rest
8874 of the line after START_X has been written. */
8875
8876 static void
8877 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
8878 struct window *w;
8879 enum glyph_row_area area;
8880 int x0, x1, y0, y1;
8881 {
8882 if (area == TEXT_AREA
8883 && w->phys_cursor_on_p
8884 && y0 <= w->phys_cursor.y
8885 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8886 && x0 <= w->phys_cursor.x
8887 && (x1 < 0 || x1 > w->phys_cursor.x))
8888 w->phys_cursor_on_p = 0;
8889 }
8890
8891
8892 /* Set clipping for output in glyph row ROW. W is the window in which
8893 we operate. GC is the graphics context to set clipping in.
8894 WHOLE_LINE_P non-zero means include the areas used for truncation
8895 mark display and alike in the clipping rectangle.
8896
8897 ROW may be a text row or, e.g., a mode line. Text rows must be
8898 clipped to the interior of the window dedicated to text display,
8899 mode lines must be clipped to the whole window. */
8900
8901 static void
8902 x_clip_to_row (w, row, gc, whole_line_p)
8903 struct window *w;
8904 struct glyph_row *row;
8905 GC gc;
8906 int whole_line_p;
8907 {
8908 struct frame *f = XFRAME (WINDOW_FRAME (w));
8909 Rect clip_rect;
8910 int window_x, window_y, window_width, window_height;
8911
8912 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8913
8914 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8915 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8916 clip_rect.top = max (clip_rect.top, window_y);
8917 clip_rect.right = clip_rect.left + window_width;
8918 clip_rect.bottom = clip_rect.top + row->visible_height;
8919
8920 /* If clipping to the whole line, including trunc marks, extend
8921 the rectangle to the left and increase its width. */
8922 if (whole_line_p)
8923 {
8924 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8925 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
8926 }
8927
8928 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8929 }
8930
8931
8932 /* Draw a hollow box cursor on window W in glyph row ROW. */
8933
8934 static void
8935 x_draw_hollow_cursor (w, row)
8936 struct window *w;
8937 struct glyph_row *row;
8938 {
8939 struct frame *f = XFRAME (WINDOW_FRAME (w));
8940 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8941 Display *dpy = FRAME_MAC_DISPLAY (f);
8942 int x, y, wd, h;
8943 XGCValues xgcv;
8944 struct glyph *cursor_glyph;
8945 GC gc;
8946
8947 /* Compute frame-relative coordinates from window-relative
8948 coordinates. */
8949 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8950 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8951 + row->ascent - w->phys_cursor_ascent);
8952 h = row->height - 1;
8953
8954 /* Get the glyph the cursor is on. If we can't tell because
8955 the current matrix is invalid or such, give up. */
8956 cursor_glyph = get_phys_cursor_glyph (w);
8957 if (cursor_glyph == NULL)
8958 return;
8959
8960 /* Compute the width of the rectangle to draw. If on a stretch
8961 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8962 rectangle as wide as the glyph, but use a canonical character
8963 width instead. */
8964 wd = cursor_glyph->pixel_width - 1;
8965 if (cursor_glyph->type == STRETCH_GLYPH
8966 && !x_stretch_cursor_p)
8967 wd = min (CANON_X_UNIT (f), wd);
8968
8969 /* The foreground of cursor_gc is typically the same as the normal
8970 background color, which can cause the cursor box to be invisible. */
8971 xgcv.foreground = f->output_data.mac->cursor_pixel;
8972 if (dpyinfo->scratch_cursor_gc)
8973 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8974 else
8975 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
8976 GCForeground, &xgcv);
8977 gc = dpyinfo->scratch_cursor_gc;
8978
8979 /* Set clipping, draw the rectangle, and reset clipping again. */
8980 x_clip_to_row (w, row, gc, 0);
8981 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
8982 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8983 }
8984
8985
8986 /* Draw a bar cursor on window W in glyph row ROW.
8987
8988 Implementation note: One would like to draw a bar cursor with an
8989 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8990 Unfortunately, I didn't find a font yet that has this property set.
8991 --gerd. */
8992
8993 static void
8994 x_draw_bar_cursor (w, row, width)
8995 struct window *w;
8996 struct glyph_row *row;
8997 int width;
8998 {
8999 /* If cursor hpos is out of bounds, don't draw garbage. This can
9000 happen in mini-buffer windows when switching between echo area
9001 glyphs and mini-buffer. */
9002 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9003 {
9004 struct frame *f = XFRAME (w->frame);
9005 struct glyph *cursor_glyph;
9006 GC gc;
9007 int x;
9008 unsigned long mask;
9009 XGCValues xgcv;
9010 Display *dpy;
9011 Window window;
9012
9013 cursor_glyph = get_phys_cursor_glyph (w);
9014 if (cursor_glyph == NULL)
9015 return;
9016
9017 xgcv.background = f->output_data.mac->cursor_pixel;
9018 xgcv.foreground = f->output_data.mac->cursor_pixel;
9019 mask = GCForeground | GCBackground;
9020 dpy = FRAME_MAC_DISPLAY (f);
9021 window = FRAME_MAC_WINDOW (f);
9022 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9023
9024 if (gc)
9025 XChangeGC (dpy, gc, mask, &xgcv);
9026 else
9027 {
9028 gc = XCreateGC (dpy, window, mask, &xgcv);
9029 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9030 }
9031
9032 if (width < 0)
9033 width = f->output_data.mac->cursor_width;
9034
9035 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9036 x_clip_to_row (w, row, gc, 0);
9037 XFillRectangle (dpy, window, gc,
9038 x,
9039 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9040 min (cursor_glyph->pixel_width, width),
9041 row->height);
9042 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9043 }
9044 }
9045
9046
9047 /* Clear the cursor of window W to background color, and mark the
9048 cursor as not shown. This is used when the text where the cursor
9049 is is about to be rewritten. */
9050
9051 static void
9052 x_clear_cursor (w)
9053 struct window *w;
9054 {
9055 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9056 x_update_window_cursor (w, 0);
9057 }
9058
9059
9060 /* Draw the cursor glyph of window W in glyph row ROW. See the
9061 comment of x_draw_glyphs for the meaning of HL. */
9062
9063 static void
9064 x_draw_phys_cursor_glyph (w, row, hl)
9065 struct window *w;
9066 struct glyph_row *row;
9067 enum draw_glyphs_face hl;
9068 {
9069 /* If cursor hpos is out of bounds, don't draw garbage. This can
9070 happen in mini-buffer windows when switching between echo area
9071 glyphs and mini-buffer. */
9072 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9073 {
9074 int on_p = w->phys_cursor_on_p;
9075 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9076 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9077 hl, 0);
9078 w->phys_cursor_on_p = on_p;
9079
9080 /* When we erase the cursor, and ROW is overlapped by other
9081 rows, make sure that these overlapping parts of other rows
9082 are redrawn. */
9083 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9084 {
9085 if (row > w->current_matrix->rows
9086 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9087 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9088
9089 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9090 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9091 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9092 }
9093 }
9094 }
9095
9096
9097 /* Erase the image of a cursor of window W from the screen. */
9098
9099 static void
9100 x_erase_phys_cursor (w)
9101 struct window *w;
9102 {
9103 struct frame *f = XFRAME (w->frame);
9104 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9105 int hpos = w->phys_cursor.hpos;
9106 int vpos = w->phys_cursor.vpos;
9107 int mouse_face_here_p = 0;
9108 struct glyph_matrix *active_glyphs = w->current_matrix;
9109 struct glyph_row *cursor_row;
9110 struct glyph *cursor_glyph;
9111 enum draw_glyphs_face hl;
9112
9113 /* No cursor displayed or row invalidated => nothing to do on the
9114 screen. */
9115 if (w->phys_cursor_type == NO_CURSOR)
9116 goto mark_cursor_off;
9117
9118 /* VPOS >= active_glyphs->nrows means that window has been resized.
9119 Don't bother to erase the cursor. */
9120 if (vpos >= active_glyphs->nrows)
9121 goto mark_cursor_off;
9122
9123 /* If row containing cursor is marked invalid, there is nothing we
9124 can do. */
9125 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9126 if (!cursor_row->enabled_p)
9127 goto mark_cursor_off;
9128
9129 /* If row is completely invisible, don't attempt to delete a cursor which
9130 isn't there. This may happen if cursor is at top of window, and
9131 we switch to a buffer with a header line in that window. */
9132 if (cursor_row->visible_height <= 0)
9133 goto mark_cursor_off;
9134
9135 /* This can happen when the new row is shorter than the old one.
9136 In this case, either x_draw_glyphs or clear_end_of_line
9137 should have cleared the cursor. Note that we wouldn't be
9138 able to erase the cursor in this case because we don't have a
9139 cursor glyph at hand. */
9140 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9141 goto mark_cursor_off;
9142
9143 /* If the cursor is in the mouse face area, redisplay that when
9144 we clear the cursor. */
9145 if (! NILP (dpyinfo->mouse_face_window)
9146 && w == XWINDOW (dpyinfo->mouse_face_window)
9147 && (vpos > dpyinfo->mouse_face_beg_row
9148 || (vpos == dpyinfo->mouse_face_beg_row
9149 && hpos >= dpyinfo->mouse_face_beg_col))
9150 && (vpos < dpyinfo->mouse_face_end_row
9151 || (vpos == dpyinfo->mouse_face_end_row
9152 && hpos < dpyinfo->mouse_face_end_col))
9153 /* Don't redraw the cursor's spot in mouse face if it is at the
9154 end of a line (on a newline). The cursor appears there, but
9155 mouse highlighting does not. */
9156 && cursor_row->used[TEXT_AREA] > hpos)
9157 mouse_face_here_p = 1;
9158
9159 /* Maybe clear the display under the cursor. */
9160 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9161 {
9162 int x;
9163 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9164
9165 cursor_glyph = get_phys_cursor_glyph (w);
9166 if (cursor_glyph == NULL)
9167 goto mark_cursor_off;
9168
9169 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9170
9171 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9172 x,
9173 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9174 cursor_row->y)),
9175 cursor_glyph->pixel_width,
9176 cursor_row->visible_height,
9177 0);
9178 }
9179
9180 /* Erase the cursor by redrawing the character underneath it. */
9181 if (mouse_face_here_p)
9182 hl = DRAW_MOUSE_FACE;
9183 else
9184 hl = DRAW_NORMAL_TEXT;
9185 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9186
9187 mark_cursor_off:
9188 w->phys_cursor_on_p = 0;
9189 w->phys_cursor_type = NO_CURSOR;
9190 }
9191
9192
9193 /* Non-zero if physical cursor of window W is within mouse face. */
9194
9195 static int
9196 cursor_in_mouse_face_p (w)
9197 struct window *w;
9198 {
9199 struct mac_display_info *dpyinfo
9200 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9201 int in_mouse_face = 0;
9202
9203 if (WINDOWP (dpyinfo->mouse_face_window)
9204 && XWINDOW (dpyinfo->mouse_face_window) == w)
9205 {
9206 int hpos = w->phys_cursor.hpos;
9207 int vpos = w->phys_cursor.vpos;
9208
9209 if (vpos >= dpyinfo->mouse_face_beg_row
9210 && vpos <= dpyinfo->mouse_face_end_row
9211 && (vpos > dpyinfo->mouse_face_beg_row
9212 || hpos >= dpyinfo->mouse_face_beg_col)
9213 && (vpos < dpyinfo->mouse_face_end_row
9214 || hpos < dpyinfo->mouse_face_end_col
9215 || dpyinfo->mouse_face_past_end))
9216 in_mouse_face = 1;
9217 }
9218
9219 return in_mouse_face;
9220 }
9221
9222
9223 /* Display or clear cursor of window W. If ON is zero, clear the
9224 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9225 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9226
9227 void
9228 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9229 struct window *w;
9230 int on, hpos, vpos, x, y;
9231 {
9232 struct frame *f = XFRAME (w->frame);
9233 int new_cursor_type;
9234 int new_cursor_width;
9235 struct glyph_matrix *current_glyphs;
9236 struct glyph_row *glyph_row;
9237 struct glyph *glyph;
9238 int cursor_non_selected;
9239 int active_cursor = 1;
9240
9241 /* This is pointless on invisible frames, and dangerous on garbaged
9242 windows and frames; in the latter case, the frame or window may
9243 be in the midst of changing its size, and x and y may be off the
9244 window. */
9245 if (! FRAME_VISIBLE_P (f)
9246 || FRAME_GARBAGED_P (f)
9247 || vpos >= w->current_matrix->nrows
9248 || hpos >= w->current_matrix->matrix_w)
9249 return;
9250
9251 /* If cursor is off and we want it off, return quickly. */
9252 if (!on && !w->phys_cursor_on_p)
9253 return;
9254
9255 current_glyphs = w->current_matrix;
9256 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9257 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9258
9259 /* If cursor row is not enabled, we don't really know where to
9260 display the cursor. */
9261 if (!glyph_row->enabled_p)
9262 {
9263 w->phys_cursor_on_p = 0;
9264 return;
9265 }
9266
9267 xassert (interrupt_input_blocked);
9268
9269 /* Set new_cursor_type to the cursor we want to be displayed. In a
9270 mini-buffer window, we want the cursor only to appear if we are
9271 reading input from this window. For the selected window, we want
9272 the cursor type given by the frame parameter. If explicitly
9273 marked off, draw no cursor. In all other cases, we want a hollow
9274 box cursor. */
9275 cursor_non_selected
9276 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
9277 w->buffer));
9278 new_cursor_width = -1;
9279 if (cursor_in_echo_area
9280 && FRAME_HAS_MINIBUF_P (f)
9281 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
9282 {
9283 if (w == XWINDOW (echo_area_window))
9284 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9285 else
9286 {
9287 if (cursor_non_selected)
9288 new_cursor_type = HOLLOW_BOX_CURSOR;
9289 else
9290 new_cursor_type = NO_CURSOR;
9291 active_cursor = 0;
9292 }
9293 }
9294 else
9295 {
9296 if (f != FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame
9297 || w != XWINDOW (f->selected_window))
9298 {
9299 active_cursor = 0;
9300
9301 if (MINI_WINDOW_P (w)
9302 || !cursor_non_selected
9303 || NILP (XBUFFER (w->buffer)->cursor_type))
9304 new_cursor_type = NO_CURSOR;
9305 else
9306 new_cursor_type = HOLLOW_BOX_CURSOR;
9307 }
9308 else
9309 {
9310 struct buffer *b = XBUFFER (w->buffer);
9311
9312 if (EQ (b->cursor_type, Qt))
9313 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9314 else
9315 new_cursor_type = x_specified_cursor_type (b->cursor_type,
9316 &new_cursor_width);
9317 if (w->cursor_off_p)
9318 {
9319 if (new_cursor_type == FILLED_BOX_CURSOR)
9320 new_cursor_type = HOLLOW_BOX_CURSOR;
9321 else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
9322 new_cursor_width = 1;
9323 else
9324 new_cursor_type = NO_CURSOR;
9325 }
9326 }
9327 }
9328
9329 /* If cursor is currently being shown and we don't want it to be or
9330 it is in the wrong place, or the cursor type is not what we want,
9331 erase it. */
9332 if (w->phys_cursor_on_p
9333 && (!on
9334 || w->phys_cursor.x != x
9335 || w->phys_cursor.y != y
9336 || new_cursor_type != w->phys_cursor_type
9337 || (new_cursor_type == BAR_CURSOR
9338 && new_cursor_width != w->phys_cursor_width)))
9339 x_erase_phys_cursor (w);
9340
9341 /* If the cursor is now invisible and we want it to be visible,
9342 display it. */
9343 if (on && !w->phys_cursor_on_p)
9344 {
9345 w->phys_cursor_ascent = glyph_row->ascent;
9346 w->phys_cursor_height = glyph_row->height;
9347
9348 /* Set phys_cursor_.* before x_draw_.* is called because some
9349 of them may need the information. */
9350 w->phys_cursor.x = x;
9351 w->phys_cursor.y = glyph_row->y;
9352 w->phys_cursor.hpos = hpos;
9353 w->phys_cursor.vpos = vpos;
9354 w->phys_cursor_type = new_cursor_type;
9355 w->phys_cursor_width = new_cursor_width;
9356 w->phys_cursor_on_p = 1;
9357
9358 switch (new_cursor_type)
9359 {
9360 case HOLLOW_BOX_CURSOR:
9361 x_draw_hollow_cursor (w, glyph_row);
9362 break;
9363
9364 case FILLED_BOX_CURSOR:
9365 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9366 break;
9367
9368 case BAR_CURSOR:
9369 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9370 break;
9371
9372 case NO_CURSOR:
9373 break;
9374
9375 default:
9376 abort ();
9377 }
9378 }
9379 }
9380
9381
9382 /* Display the cursor on window W, or clear it. X and Y are window
9383 relative pixel coordinates. HPOS and VPOS are glyph matrix
9384 positions. If W is not the selected window, display a hollow
9385 cursor. ON non-zero means display the cursor at X, Y which
9386 correspond to HPOS, VPOS, otherwise it is cleared. */
9387
9388 void
9389 x_display_cursor (w, on, hpos, vpos, x, y)
9390 struct window *w;
9391 int on, hpos, vpos, x, y;
9392 {
9393 BLOCK_INPUT;
9394 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9395 UNBLOCK_INPUT;
9396 }
9397
9398
9399 /* Display the cursor on window W, or clear it, according to ON_P.
9400 Don't change the cursor's position. */
9401
9402 void
9403 x_update_cursor (f, on_p)
9404 struct frame *f;
9405 int on_p;
9406 {
9407 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9408 }
9409
9410
9411 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9412 in the window tree rooted at W. */
9413
9414 static void
9415 x_update_cursor_in_window_tree (w, on_p)
9416 struct window *w;
9417 int on_p;
9418 {
9419 while (w)
9420 {
9421 if (!NILP (w->hchild))
9422 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9423 else if (!NILP (w->vchild))
9424 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9425 else
9426 x_update_window_cursor (w, on_p);
9427
9428 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9429 }
9430 }
9431
9432
9433 /* Switch the display of W's cursor on or off, according to the value
9434 of ON. */
9435
9436 static void
9437 x_update_window_cursor (w, on)
9438 struct window *w;
9439 int on;
9440 {
9441 /* Don't update cursor in windows whose frame is in the process
9442 of being deleted. */
9443 if (w->current_matrix)
9444 {
9445 BLOCK_INPUT;
9446 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9447 w->phys_cursor.vpos, w->phys_cursor.x,
9448 w->phys_cursor.y);
9449 UNBLOCK_INPUT;
9450 }
9451 }
9452
9453
9454
9455 \f
9456 /* Icons. */
9457
9458 #if 0 /* MAC_TODO: no icon support yet. */
9459 int
9460 x_bitmap_icon (f, icon)
9461 struct frame *f;
9462 Lisp_Object icon;
9463 {
9464 HANDLE hicon;
9465
9466 if (FRAME_W32_WINDOW (f) == 0)
9467 return 1;
9468
9469 if (NILP (icon))
9470 hicon = LoadIcon (hinst, EMACS_CLASS);
9471 else if (STRINGP (icon))
9472 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
9473 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9474 else if (SYMBOLP (icon))
9475 {
9476 LPCTSTR name;
9477
9478 if (EQ (icon, intern ("application")))
9479 name = (LPCTSTR) IDI_APPLICATION;
9480 else if (EQ (icon, intern ("hand")))
9481 name = (LPCTSTR) IDI_HAND;
9482 else if (EQ (icon, intern ("question")))
9483 name = (LPCTSTR) IDI_QUESTION;
9484 else if (EQ (icon, intern ("exclamation")))
9485 name = (LPCTSTR) IDI_EXCLAMATION;
9486 else if (EQ (icon, intern ("asterisk")))
9487 name = (LPCTSTR) IDI_ASTERISK;
9488 else if (EQ (icon, intern ("winlogo")))
9489 name = (LPCTSTR) IDI_WINLOGO;
9490 else
9491 return 1;
9492
9493 hicon = LoadIcon (NULL, name);
9494 }
9495 else
9496 return 1;
9497
9498 if (hicon == NULL)
9499 return 1;
9500
9501 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9502 (LPARAM) hicon);
9503
9504 return 0;
9505 }
9506 #endif /* MAC_TODO */
9507 \f
9508 /************************************************************************
9509 Handling X errors
9510 ************************************************************************/
9511
9512 /* Display Error Handling functions not used on W32. Listing them here
9513 helps diff stay in step when comparing w32term.c with xterm.c.
9514
9515 x_error_catcher (display, error)
9516 x_catch_errors (dpy)
9517 x_catch_errors_unwind (old_val)
9518 x_check_errors (dpy, format)
9519 x_had_errors_p (dpy)
9520 x_clear_errors (dpy)
9521 x_uncatch_errors (dpy, count)
9522 x_trace_wire ()
9523 x_connection_signal (signalnum)
9524 x_connection_closed (dpy, error_message)
9525 x_error_quitter (display, error)
9526 x_error_handler (display, error)
9527 x_io_error_quitter (display)
9528
9529 */
9530
9531 \f
9532 /* Changing the font of the frame. */
9533
9534 /* Give frame F the font named FONTNAME as its default font, and
9535 return the full name of that font. FONTNAME may be a wildcard
9536 pattern; in that case, we choose some font that fits the pattern.
9537 The return value shows which font we chose. */
9538
9539 Lisp_Object
9540 x_new_font (f, fontname)
9541 struct frame *f;
9542 register char *fontname;
9543 {
9544 struct font_info *fontp
9545 = FS_LOAD_FONT (f, 0, fontname, -1);
9546
9547 if (!fontp)
9548 return Qnil;
9549
9550 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9551 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9552 FRAME_FONTSET (f) = -1;
9553
9554 /* Compute the scroll bar width in character columns. */
9555 if (f->scroll_bar_pixel_width > 0)
9556 {
9557 int wid = FONT_WIDTH (FRAME_FONT (f));
9558 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9559 }
9560 else
9561 {
9562 int wid = FONT_WIDTH (FRAME_FONT (f));
9563 f->scroll_bar_cols = (14 + wid - 1) / wid;
9564 }
9565
9566 /* Now make the frame display the given font. */
9567 if (FRAME_MAC_WINDOW (f) != 0)
9568 {
9569 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
9570 f->output_data.mac->font);
9571 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
9572 f->output_data.mac->font);
9573 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
9574 f->output_data.mac->font);
9575
9576 frame_update_line_height (f);
9577 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9578 x_set_window_size (f, 0, f->width, f->height);
9579 }
9580 else
9581 /* If we are setting a new frame's font for the first time,
9582 there are no faces yet, so this font's height is the line height. */
9583 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
9584
9585 return build_string (fontp->full_name);
9586 }
9587 \f
9588 /* Give frame F the fontset named FONTSETNAME as its default font, and
9589 return the full name of that fontset. FONTSETNAME may be a wildcard
9590 pattern; in that case, we choose some fontset that fits the pattern.
9591 The return value shows which fontset we chose. */
9592
9593 Lisp_Object
9594 x_new_fontset (f, fontsetname)
9595 struct frame *f;
9596 char *fontsetname;
9597 {
9598 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9599 Lisp_Object result;
9600
9601 if (fontset < 0)
9602 return Qnil;
9603
9604 if (FRAME_FONTSET (f) == fontset)
9605 /* This fontset is already set in frame F. There's nothing more
9606 to do. */
9607 return fontset_name (fontset);
9608
9609 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
9610
9611 if (!STRINGP (result))
9612 /* Can't load ASCII font. */
9613 return Qnil;
9614
9615 /* Since x_new_font doesn't update any fontset information, do it now. */
9616 FRAME_FONTSET(f) = fontset;
9617
9618 return build_string (fontsetname);
9619 }
9620
9621 /* Compute actual fringe widths */
9622
9623 void
9624 x_compute_fringe_widths (f, redraw)
9625 struct frame *f;
9626 int redraw;
9627 {
9628 int o_left = f->output_data.mac->left_fringe_width;
9629 int o_right = f->output_data.mac->right_fringe_width;
9630 int o_cols = f->output_data.mac->fringe_cols;
9631
9632 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9633 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9634 int left_fringe_width, right_fringe_width;
9635
9636 if (!NILP (left_fringe))
9637 left_fringe = Fcdr (left_fringe);
9638 if (!NILP (right_fringe))
9639 right_fringe = Fcdr (right_fringe);
9640
9641 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9642 XINT (left_fringe));
9643 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9644 XINT (right_fringe));
9645
9646 if (left_fringe_width || right_fringe_width)
9647 {
9648 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9649 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9650 int conf_wid = left_wid + right_wid;
9651 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9652 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9653 int real_wid = cols * font_wid;
9654 if (left_wid && right_wid)
9655 {
9656 if (left_fringe_width < 0)
9657 {
9658 /* Left fringe width is fixed, adjust right fringe if necessary */
9659 f->output_data.mac->left_fringe_width = left_wid;
9660 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9661 }
9662 else if (right_fringe_width < 0)
9663 {
9664 /* Right fringe width is fixed, adjust left fringe if necessary */
9665 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9666 f->output_data.mac->right_fringe_width = right_wid;
9667 }
9668 else
9669 {
9670 /* Adjust both fringes with an equal amount.
9671 Note that we are doing integer arithmetic here, so don't
9672 lose a pixel if the total width is an odd number. */
9673 int fill = real_wid - conf_wid;
9674 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9675 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9676 }
9677 }
9678 else if (left_fringe_width)
9679 {
9680 f->output_data.mac->left_fringe_width = real_wid;
9681 f->output_data.mac->right_fringe_width = 0;
9682 }
9683 else
9684 {
9685 f->output_data.mac->left_fringe_width = 0;
9686 f->output_data.mac->right_fringe_width = real_wid;
9687 }
9688 f->output_data.mac->fringe_cols = cols;
9689 f->output_data.mac->fringes_extra = real_wid;
9690 }
9691 else
9692 {
9693 f->output_data.mac->left_fringe_width = 0;
9694 f->output_data.mac->right_fringe_width = 0;
9695 f->output_data.mac->fringe_cols = 0;
9696 f->output_data.mac->fringes_extra = 0;
9697 }
9698
9699 if (redraw && FRAME_VISIBLE_P (f))
9700 if (o_left != f->output_data.mac->left_fringe_width ||
9701 o_right != f->output_data.mac->right_fringe_width ||
9702 o_cols != f->output_data.mac->fringe_cols)
9703 redraw_frame (f);
9704 }
9705 \f
9706 /***********************************************************************
9707 TODO: W32 Input Methods
9708 ***********************************************************************/
9709 /* Listing missing functions from xterm.c helps diff stay in step.
9710
9711 xim_destroy_callback (xim, client_data, call_data)
9712 xim_open_dpy (dpyinfo, resource_name)
9713 struct xim_inst_t
9714 xim_instantiate_callback (display, client_data, call_data)
9715 xim_initialize (dpyinfo, resource_name)
9716 xim_close_dpy (dpyinfo)
9717
9718 */
9719
9720 \f
9721 /* Calculate the absolute position in frame F
9722 from its current recorded position values and gravity. */
9723
9724 void
9725 x_calc_absolute_position (f)
9726 struct frame *f;
9727 {
9728 Point pt;
9729 int flags = f->output_data.mac->size_hint_flags;
9730
9731 pt.h = pt.v = 0;
9732
9733 /* Find the position of the outside upper-left corner of
9734 the inner window, with respect to the outer window. */
9735 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9736 {
9737 GrafPtr savePort;
9738 GetPort (&savePort);
9739
9740 #if TARGET_API_MAC_CARBON
9741 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9742 #else
9743 SetPort (FRAME_MAC_WINDOW (f));
9744 #endif
9745
9746 #if TARGET_API_MAC_CARBON
9747 {
9748 Rect r;
9749
9750 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9751 SetPt(&pt, r.left, r.top);
9752 }
9753 #else /* not TARGET_API_MAC_CARBON */
9754 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
9755 #endif /* not TARGET_API_MAC_CARBON */
9756 LocalToGlobal (&pt);
9757 SetPort (savePort);
9758 }
9759
9760 /* Treat negative positions as relative to the leftmost bottommost
9761 position that fits on the screen. */
9762 if (flags & XNegative)
9763 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9764 - 2 * f->output_data.mac->border_width - pt.h
9765 - PIXEL_WIDTH (f)
9766 + f->output_data.mac->left_pos);
9767 /* NTEMACS_TODO: Subtract menubar height? */
9768 if (flags & YNegative)
9769 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9770 - 2 * f->output_data.mac->border_width - pt.v
9771 - PIXEL_HEIGHT (f)
9772 + f->output_data.mac->top_pos);
9773 /* The left_pos and top_pos
9774 are now relative to the top and left screen edges,
9775 so the flags should correspond. */
9776 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9777 }
9778
9779 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9780 to really change the position, and 0 when calling from
9781 x_make_frame_visible (in that case, XOFF and YOFF are the current
9782 position values). It is -1 when calling from x_set_frame_parameters,
9783 which means, do adjust for borders but don't change the gravity. */
9784
9785 void
9786 x_set_offset (f, xoff, yoff, change_gravity)
9787 struct frame *f;
9788 register int xoff, yoff;
9789 int change_gravity;
9790 {
9791 int modified_top, modified_left;
9792
9793 if (change_gravity > 0)
9794 {
9795 f->output_data.mac->top_pos = yoff;
9796 f->output_data.mac->left_pos = xoff;
9797 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9798 if (xoff < 0)
9799 f->output_data.mac->size_hint_flags |= XNegative;
9800 if (yoff < 0)
9801 f->output_data.mac->size_hint_flags |= YNegative;
9802 f->output_data.mac->win_gravity = NorthWestGravity;
9803 }
9804 x_calc_absolute_position (f);
9805
9806 BLOCK_INPUT;
9807 x_wm_set_size_hint (f, (long) 0, 0);
9808
9809 modified_left = f->output_data.mac->left_pos;
9810 modified_top = f->output_data.mac->top_pos;
9811
9812 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9813 modified_top + 42, false);
9814
9815 UNBLOCK_INPUT;
9816 }
9817
9818 /* Call this to change the size of frame F's x-window.
9819 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9820 for this size change and subsequent size changes.
9821 Otherwise we leave the window gravity unchanged. */
9822
9823 void
9824 x_set_window_size (f, change_gravity, cols, rows)
9825 struct frame *f;
9826 int change_gravity;
9827 int cols, rows;
9828 {
9829 int pixelwidth, pixelheight;
9830
9831 BLOCK_INPUT;
9832
9833 check_frame_size (f, &rows, &cols);
9834 f->output_data.mac->vertical_scroll_bar_extra
9835 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9836 ? 0
9837 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
9838
9839 x_compute_fringe_widths (f, 0);
9840
9841 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9842 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9843
9844 f->output_data.mac->win_gravity = NorthWestGravity;
9845 x_wm_set_size_hint (f, (long) 0, 0);
9846
9847 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9848
9849 /* Now, strictly speaking, we can't be sure that this is accurate,
9850 but the window manager will get around to dealing with the size
9851 change request eventually, and we'll hear how it went when the
9852 ConfigureNotify event gets here.
9853
9854 We could just not bother storing any of this information here,
9855 and let the ConfigureNotify event set everything up, but that
9856 might be kind of confusing to the Lisp code, since size changes
9857 wouldn't be reported in the frame parameters until some random
9858 point in the future when the ConfigureNotify event arrives.
9859
9860 We pass 1 for DELAY since we can't run Lisp code inside of
9861 a BLOCK_INPUT. */
9862 change_frame_size (f, rows, cols, 0, 1, 0);
9863 PIXEL_WIDTH (f) = pixelwidth;
9864 PIXEL_HEIGHT (f) = pixelheight;
9865
9866 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9867 receive in the ConfigureNotify event; if we get what we asked
9868 for, then the event won't cause the screen to become garbaged, so
9869 we have to make sure to do it here. */
9870 SET_FRAME_GARBAGED (f);
9871
9872 XFlush (FRAME_X_DISPLAY (f));
9873
9874 /* If cursor was outside the new size, mark it as off. */
9875 mark_window_cursors_off (XWINDOW (f->root_window));
9876
9877 /* Clear out any recollection of where the mouse highlighting was,
9878 since it might be in a place that's outside the new frame size.
9879 Actually checking whether it is outside is a pain in the neck,
9880 so don't try--just let the highlighting be done afresh with new size. */
9881 cancel_mouse_face (f);
9882
9883 UNBLOCK_INPUT;
9884 }
9885 \f
9886 /* Mouse warping. */
9887
9888 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9889
9890 void
9891 x_set_mouse_position (f, x, y)
9892 struct frame *f;
9893 int x, y;
9894 {
9895 int pix_x, pix_y;
9896
9897 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9898 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9899
9900 if (pix_x < 0) pix_x = 0;
9901 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9902
9903 if (pix_y < 0) pix_y = 0;
9904 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9905
9906 x_set_mouse_pixel_position (f, pix_x, pix_y);
9907 }
9908
9909 void
9910 x_set_mouse_pixel_position (f, pix_x, pix_y)
9911 struct frame *f;
9912 int pix_x, pix_y;
9913 {
9914 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9915 BLOCK_INPUT;
9916
9917 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9918 0, 0, 0, 0, pix_x, pix_y);
9919 UNBLOCK_INPUT;
9920 #endif
9921 }
9922
9923 \f
9924 /* focus shifting, raising and lowering. */
9925
9926 void
9927 x_focus_on_frame (f)
9928 struct frame *f;
9929 {
9930 #if 0 /* This proves to be unpleasant. */
9931 x_raise_frame (f);
9932 #endif
9933 #if 0
9934 /* I don't think that the ICCCM allows programs to do things like this
9935 without the interaction of the window manager. Whatever you end up
9936 doing with this code, do it to x_unfocus_frame too. */
9937 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9938 RevertToPointerRoot, CurrentTime);
9939 #endif /* ! 0 */
9940 }
9941
9942 void
9943 x_unfocus_frame (f)
9944 struct frame *f;
9945 {
9946 }
9947
9948 /* Raise frame F. */
9949 void
9950 x_raise_frame (f)
9951 struct frame *f;
9952 {
9953 if (f->async_visible)
9954 SelectWindow (FRAME_MAC_WINDOW (f));
9955 }
9956
9957 /* Lower frame F. */
9958 void
9959 x_lower_frame (f)
9960 struct frame *f;
9961 {
9962 if (f->async_visible)
9963 SendBehind (FRAME_MAC_WINDOW (f), nil);
9964 }
9965
9966 static void
9967 XTframe_raise_lower (f, raise_flag)
9968 FRAME_PTR f;
9969 int raise_flag;
9970 {
9971 if (raise_flag)
9972 x_raise_frame (f);
9973 else
9974 x_lower_frame (f);
9975 }
9976 \f
9977 /* Change of visibility. */
9978
9979 /* This tries to wait until the frame is really visible.
9980 However, if the window manager asks the user where to position
9981 the frame, this will return before the user finishes doing that.
9982 The frame will not actually be visible at that time,
9983 but it will become visible later when the window manager
9984 finishes with it. */
9985
9986 void
9987 x_make_frame_visible (f)
9988 struct frame *f;
9989 {
9990 Lisp_Object type;
9991 int original_top, original_left;
9992
9993 BLOCK_INPUT;
9994
9995 if (! FRAME_VISIBLE_P (f))
9996 {
9997 /* We test FRAME_GARBAGED_P here to make sure we don't
9998 call x_set_offset a second time
9999 if we get to x_make_frame_visible a second time
10000 before the window gets really visible. */
10001 if (! FRAME_ICONIFIED_P (f)
10002 && ! f->output_data.mac->asked_for_visible)
10003 x_set_offset (f, f->output_data.mac->left_pos,
10004 f->output_data.mac->top_pos, 0);
10005
10006 f->output_data.mac->asked_for_visible = 1;
10007
10008 ShowWindow (FRAME_MAC_WINDOW (f));
10009 }
10010
10011 XFlush (FRAME_MAC_DISPLAY (f));
10012
10013 #if 0 /* MAC_TODO */
10014 /* Synchronize to ensure Emacs knows the frame is visible
10015 before we do anything else. We do this loop with input not blocked
10016 so that incoming events are handled. */
10017 {
10018 Lisp_Object frame;
10019 int count;
10020
10021 /* This must come after we set COUNT. */
10022 UNBLOCK_INPUT;
10023
10024 XSETFRAME (frame, f);
10025
10026 /* Wait until the frame is visible. Process X events until a
10027 MapNotify event has been seen, or until we think we won't get a
10028 MapNotify at all.. */
10029 for (count = input_signal_count + 10;
10030 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10031 {
10032 /* Force processing of queued events. */
10033 x_sync (f);
10034
10035 /* Machines that do polling rather than SIGIO have been
10036 observed to go into a busy-wait here. So we'll fake an
10037 alarm signal to let the handler know that there's something
10038 to be read. We used to raise a real alarm, but it seems
10039 that the handler isn't always enabled here. This is
10040 probably a bug. */
10041 if (input_polling_used ())
10042 {
10043 /* It could be confusing if a real alarm arrives while
10044 processing the fake one. Turn it off and let the
10045 handler reset it. */
10046 extern void poll_for_input_1 P_ ((void));
10047 int old_poll_suppress_count = poll_suppress_count;
10048 poll_suppress_count = 1;
10049 poll_for_input_1 ();
10050 poll_suppress_count = old_poll_suppress_count;
10051 }
10052
10053 /* See if a MapNotify event has been processed. */
10054 FRAME_SAMPLE_VISIBILITY (f);
10055 }
10056 }
10057 #endif /* MAC_TODO */
10058 }
10059
10060 /* Change from mapped state to withdrawn state. */
10061
10062 /* Make the frame visible (mapped and not iconified). */
10063
10064 void
10065 x_make_frame_invisible (f)
10066 struct frame *f;
10067 {
10068 /* Don't keep the highlight on an invisible frame. */
10069 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10070 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10071
10072 BLOCK_INPUT;
10073
10074 HideWindow (FRAME_MAC_WINDOW (f));
10075
10076 /* We can't distinguish this from iconification
10077 just by the event that we get from the server.
10078 So we can't win using the usual strategy of letting
10079 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10080 and synchronize with the server to make sure we agree. */
10081 f->visible = 0;
10082 FRAME_ICONIFIED_P (f) = 0;
10083 f->async_visible = 0;
10084 f->async_iconified = 0;
10085
10086 UNBLOCK_INPUT;
10087 }
10088
10089 /* Change window state from mapped to iconified. */
10090
10091 void
10092 x_iconify_frame (f)
10093 struct frame *f;
10094 {
10095 #if 0 /* MAC_TODO: really no iconify on Mac */
10096 int result;
10097 Lisp_Object type;
10098
10099 /* Don't keep the highlight on an invisible frame. */
10100 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
10101 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
10102
10103 if (f->async_iconified)
10104 return;
10105
10106 BLOCK_INPUT;
10107
10108 FRAME_SAMPLE_VISIBILITY (f);
10109
10110 type = x_icon_type (f);
10111 if (!NILP (type))
10112 x_bitmap_icon (f, type);
10113
10114 #ifdef USE_X_TOOLKIT
10115
10116 if (! FRAME_VISIBLE_P (f))
10117 {
10118 if (! EQ (Vx_no_window_manager, Qt))
10119 x_wm_set_window_state (f, IconicState);
10120 /* This was XtPopup, but that did nothing for an iconified frame. */
10121 XtMapWidget (f->output_data.x->widget);
10122 /* The server won't give us any event to indicate
10123 that an invisible frame was changed to an icon,
10124 so we have to record it here. */
10125 f->iconified = 1;
10126 f->visible = 1;
10127 f->async_iconified = 1;
10128 f->async_visible = 0;
10129 UNBLOCK_INPUT;
10130 return;
10131 }
10132
10133 result = XIconifyWindow (FRAME_X_DISPLAY (f),
10134 XtWindow (f->output_data.x->widget),
10135 DefaultScreen (FRAME_X_DISPLAY (f)));
10136 UNBLOCK_INPUT;
10137
10138 if (!result)
10139 error ("Can't notify window manager of iconification");
10140
10141 f->async_iconified = 1;
10142 f->async_visible = 0;
10143
10144
10145 BLOCK_INPUT;
10146 XFlush (FRAME_X_DISPLAY (f));
10147 UNBLOCK_INPUT;
10148 #else /* not USE_X_TOOLKIT */
10149
10150 /* Make sure the X server knows where the window should be positioned,
10151 in case the user deiconifies with the window manager. */
10152 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
10153 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
10154
10155 /* Since we don't know which revision of X we're running, we'll use both
10156 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
10157
10158 /* X11R4: send a ClientMessage to the window manager using the
10159 WM_CHANGE_STATE type. */
10160 {
10161 XEvent message;
10162
10163 message.xclient.window = FRAME_X_WINDOW (f);
10164 message.xclient.type = ClientMessage;
10165 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
10166 message.xclient.format = 32;
10167 message.xclient.data.l[0] = IconicState;
10168
10169 if (! XSendEvent (FRAME_X_DISPLAY (f),
10170 DefaultRootWindow (FRAME_X_DISPLAY (f)),
10171 False,
10172 SubstructureRedirectMask | SubstructureNotifyMask,
10173 &message))
10174 {
10175 UNBLOCK_INPUT_RESIGNAL;
10176 error ("Can't notify window manager of iconification");
10177 }
10178 }
10179
10180 /* X11R3: set the initial_state field of the window manager hints to
10181 IconicState. */
10182 x_wm_set_window_state (f, IconicState);
10183
10184 if (!FRAME_VISIBLE_P (f))
10185 {
10186 /* If the frame was withdrawn, before, we must map it. */
10187 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10188 }
10189
10190 f->async_iconified = 1;
10191 f->async_visible = 0;
10192
10193 XFlush (FRAME_X_DISPLAY (f));
10194 UNBLOCK_INPUT;
10195 #endif /* not USE_X_TOOLKIT */
10196 #endif /* MAC_TODO */
10197 }
10198
10199 \f
10200 /* Destroy the X window of frame F. */
10201
10202 void
10203 x_destroy_window (f)
10204 struct frame *f;
10205 {
10206 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10207
10208 BLOCK_INPUT;
10209
10210 DisposeWindow (FRAME_MAC_WINDOW (f));
10211
10212 free_frame_menubar (f);
10213 free_frame_faces (f);
10214
10215 xfree (f->output_data.mac);
10216 f->output_data.mac = 0;
10217 if (f == dpyinfo->x_focus_frame)
10218 dpyinfo->x_focus_frame = 0;
10219 if (f == dpyinfo->x_focus_event_frame)
10220 dpyinfo->x_focus_event_frame = 0;
10221 if (f == dpyinfo->x_highlight_frame)
10222 dpyinfo->x_highlight_frame = 0;
10223
10224 dpyinfo->reference_count--;
10225
10226 if (f == dpyinfo->mouse_face_mouse_frame)
10227 {
10228 dpyinfo->mouse_face_beg_row
10229 = dpyinfo->mouse_face_beg_col = -1;
10230 dpyinfo->mouse_face_end_row
10231 = dpyinfo->mouse_face_end_col = -1;
10232 dpyinfo->mouse_face_window = Qnil;
10233 dpyinfo->mouse_face_deferred_gc = 0;
10234 dpyinfo->mouse_face_mouse_frame = 0;
10235 }
10236
10237 UNBLOCK_INPUT;
10238 }
10239 \f
10240 /* Setting window manager hints. */
10241
10242 /* Set the normal size hints for the window manager, for frame F.
10243 FLAGS is the flags word to use--or 0 meaning preserve the flags
10244 that the window now has.
10245 If USER_POSITION is nonzero, we set the USPosition
10246 flag (this is useful when FLAGS is 0). */
10247 void
10248 x_wm_set_size_hint (f, flags, user_position)
10249 struct frame *f;
10250 long flags;
10251 int user_position;
10252 {
10253 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
10254 XSizeHints size_hints;
10255
10256 #ifdef USE_X_TOOLKIT
10257 Arg al[2];
10258 int ac = 0;
10259 Dimension widget_width, widget_height;
10260 Window window = XtWindow (f->output_data.x->widget);
10261 #else /* not USE_X_TOOLKIT */
10262 Window window = FRAME_X_WINDOW (f);
10263 #endif /* not USE_X_TOOLKIT */
10264
10265 /* Setting PMaxSize caused various problems. */
10266 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10267
10268 size_hints.x = f->output_data.x->left_pos;
10269 size_hints.y = f->output_data.x->top_pos;
10270
10271 #ifdef USE_X_TOOLKIT
10272 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10273 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10274 XtGetValues (f->output_data.x->widget, al, ac);
10275 size_hints.height = widget_height;
10276 size_hints.width = widget_width;
10277 #else /* not USE_X_TOOLKIT */
10278 size_hints.height = PIXEL_HEIGHT (f);
10279 size_hints.width = PIXEL_WIDTH (f);
10280 #endif /* not USE_X_TOOLKIT */
10281
10282 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10283 size_hints.height_inc = f->output_data.x->line_height;
10284 size_hints.max_width
10285 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10286 size_hints.max_height
10287 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10288
10289 /* Calculate the base and minimum sizes.
10290
10291 (When we use the X toolkit, we don't do it here.
10292 Instead we copy the values that the widgets are using, below.) */
10293 #ifndef USE_X_TOOLKIT
10294 {
10295 int base_width, base_height;
10296 int min_rows = 0, min_cols = 0;
10297
10298 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10299 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10300
10301 check_frame_size (f, &min_rows, &min_cols);
10302
10303 /* The window manager uses the base width hints to calculate the
10304 current number of rows and columns in the frame while
10305 resizing; min_width and min_height aren't useful for this
10306 purpose, since they might not give the dimensions for a
10307 zero-row, zero-column frame.
10308
10309 We use the base_width and base_height members if we have
10310 them; otherwise, we set the min_width and min_height members
10311 to the size for a zero x zero frame. */
10312
10313 #ifdef HAVE_X11R4
10314 size_hints.flags |= PBaseSize;
10315 size_hints.base_width = base_width;
10316 size_hints.base_height = base_height;
10317 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10318 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10319 #else
10320 size_hints.min_width = base_width;
10321 size_hints.min_height = base_height;
10322 #endif
10323 }
10324
10325 /* If we don't need the old flags, we don't need the old hint at all. */
10326 if (flags)
10327 {
10328 size_hints.flags |= flags;
10329 goto no_read;
10330 }
10331 #endif /* not USE_X_TOOLKIT */
10332
10333 {
10334 XSizeHints hints; /* Sometimes I hate X Windows... */
10335 long supplied_return;
10336 int value;
10337
10338 #ifdef HAVE_X11R4
10339 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10340 &supplied_return);
10341 #else
10342 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10343 #endif
10344
10345 #ifdef USE_X_TOOLKIT
10346 size_hints.base_height = hints.base_height;
10347 size_hints.base_width = hints.base_width;
10348 size_hints.min_height = hints.min_height;
10349 size_hints.min_width = hints.min_width;
10350 #endif
10351
10352 if (flags)
10353 size_hints.flags |= flags;
10354 else
10355 {
10356 if (value == 0)
10357 hints.flags = 0;
10358 if (hints.flags & PSize)
10359 size_hints.flags |= PSize;
10360 if (hints.flags & PPosition)
10361 size_hints.flags |= PPosition;
10362 if (hints.flags & USPosition)
10363 size_hints.flags |= USPosition;
10364 if (hints.flags & USSize)
10365 size_hints.flags |= USSize;
10366 }
10367 }
10368
10369 #ifndef USE_X_TOOLKIT
10370 no_read:
10371 #endif
10372
10373 #ifdef PWinGravity
10374 size_hints.win_gravity = f->output_data.x->win_gravity;
10375 size_hints.flags |= PWinGravity;
10376
10377 if (user_position)
10378 {
10379 size_hints.flags &= ~ PPosition;
10380 size_hints.flags |= USPosition;
10381 }
10382 #endif /* PWinGravity */
10383
10384 #ifdef HAVE_X11R4
10385 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10386 #else
10387 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10388 #endif
10389 #endif /* MAC_TODO */
10390 }
10391
10392 #if 0 /* MAC_TODO: hide application instead of iconify? */
10393 /* Used for IconicState or NormalState */
10394
10395 void
10396 x_wm_set_window_state (f, state)
10397 struct frame *f;
10398 int state;
10399 {
10400 #ifdef USE_X_TOOLKIT
10401 Arg al[1];
10402
10403 XtSetArg (al[0], XtNinitialState, state);
10404 XtSetValues (f->output_data.x->widget, al, 1);
10405 #else /* not USE_X_TOOLKIT */
10406 Window window = FRAME_X_WINDOW (f);
10407
10408 f->output_data.x->wm_hints.flags |= StateHint;
10409 f->output_data.x->wm_hints.initial_state = state;
10410
10411 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10412 #endif /* not USE_X_TOOLKIT */
10413 }
10414
10415 void
10416 x_wm_set_icon_pixmap (f, pixmap_id)
10417 struct frame *f;
10418 int pixmap_id;
10419 {
10420 Pixmap icon_pixmap;
10421
10422 #ifndef USE_X_TOOLKIT
10423 Window window = FRAME_X_WINDOW (f);
10424 #endif
10425
10426 if (pixmap_id > 0)
10427 {
10428 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10429 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10430 }
10431 else
10432 {
10433 /* It seems there is no way to turn off use of an icon pixmap.
10434 The following line does it, only if no icon has yet been created,
10435 for some window managers. But with mwm it crashes.
10436 Some people say it should clear the IconPixmapHint bit in this case,
10437 but that doesn't work, and the X consortium said it isn't the
10438 right thing at all. Since there is no way to win,
10439 best to explicitly give up. */
10440 #if 0
10441 f->output_data.x->wm_hints.icon_pixmap = None;
10442 #else
10443 return;
10444 #endif
10445 }
10446
10447 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10448
10449 {
10450 Arg al[1];
10451 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10452 XtSetValues (f->output_data.x->widget, al, 1);
10453 }
10454
10455 #else /* not USE_X_TOOLKIT */
10456
10457 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10458 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10459
10460 #endif /* not USE_X_TOOLKIT */
10461 }
10462
10463 #endif /* MAC_TODO */
10464
10465 void
10466 x_wm_set_icon_position (f, icon_x, icon_y)
10467 struct frame *f;
10468 int icon_x, icon_y;
10469 {
10470 #if 0 /* MAC_TODO: no icons on Mac */
10471 #ifdef USE_X_TOOLKIT
10472 Window window = XtWindow (f->output_data.x->widget);
10473 #else
10474 Window window = FRAME_X_WINDOW (f);
10475 #endif
10476
10477 f->output_data.x->wm_hints.flags |= IconPositionHint;
10478 f->output_data.x->wm_hints.icon_x = icon_x;
10479 f->output_data.x->wm_hints.icon_y = icon_y;
10480
10481 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10482 #endif /* MAC_TODO */
10483 }
10484
10485 \f
10486 /***********************************************************************
10487 Fonts
10488 ***********************************************************************/
10489
10490 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10491
10492 struct font_info *
10493 x_get_font_info (f, font_idx)
10494 FRAME_PTR f;
10495 int font_idx;
10496 {
10497 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10498 }
10499
10500 /* the global font name table */
10501 char **font_name_table = NULL;
10502 int font_name_table_size = 0;
10503 int font_name_count = 0;
10504
10505 /* compare two strings ignoring case */
10506 static int
10507 stricmp (const char *s, const char *t)
10508 {
10509 for ( ; tolower (*s) == tolower (*t); s++, t++)
10510 if (*s == '\0')
10511 return 0;
10512 return tolower (*s) - tolower (*t);
10513 }
10514
10515 /* compare two strings ignoring case and handling wildcard */
10516 static int
10517 wildstrieq (char *s1, char *s2)
10518 {
10519 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10520 return true;
10521
10522 return stricmp (s1, s2) == 0;
10523 }
10524
10525 /* Assume parameter 1 is fully qualified, no wildcards. */
10526 static int
10527 mac_font_pattern_match (fontname, pattern)
10528 char * fontname;
10529 char * pattern;
10530 {
10531 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
10532 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10533 char *ptr;
10534
10535 /* Copy fontname so we can modify it during comparison. */
10536 strcpy (font_name_copy, fontname);
10537
10538 ptr = regex;
10539 *ptr++ = '^';
10540
10541 /* Turn pattern into a regexp and do a regexp match. */
10542 for (; *pattern; pattern++)
10543 {
10544 if (*pattern == '?')
10545 *ptr++ = '.';
10546 else if (*pattern == '*')
10547 {
10548 *ptr++ = '.';
10549 *ptr++ = '*';
10550 }
10551 else
10552 *ptr++ = *pattern;
10553 }
10554 *ptr = '$';
10555 *(ptr + 1) = '\0';
10556
10557 return (fast_c_string_match_ignore_case (build_string (regex),
10558 font_name_copy) >= 0);
10559 }
10560
10561 /* Two font specs are considered to match if their foundry, family,
10562 weight, slant, and charset match. */
10563 static int
10564 mac_font_match (char *mf, char *xf)
10565 {
10566 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10567 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10568
10569 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10570 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10571 return mac_font_pattern_match (mf, xf);
10572
10573 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10574 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10575 return mac_font_pattern_match (mf, xf);
10576
10577 return (wildstrieq (m_foundry, x_foundry)
10578 && wildstrieq (m_family, x_family)
10579 && wildstrieq (m_weight, x_weight)
10580 && wildstrieq (m_slant, x_slant)
10581 && wildstrieq (m_charset, x_charset))
10582 || mac_font_pattern_match (mf, xf);
10583 }
10584
10585
10586 static char *
10587 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10588 {
10589 char foundry[32], family[32], cs[32];
10590 char xf[255], *result, *p;
10591
10592 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10593 {
10594 strcpy(foundry, "Apple");
10595 strcpy(family, name);
10596
10597 switch (scriptcode)
10598 {
10599 case smTradChinese:
10600 strcpy(cs, "big5-0");
10601 break;
10602 case smSimpChinese:
10603 strcpy(cs, "gb2312.1980-0");
10604 break;
10605 case smJapanese:
10606 strcpy(cs, "jisx0208.1983-sjis");
10607 break;
10608 case -smJapanese:
10609 /* Each Apple Japanese font is entered into the font table
10610 twice: once as a jisx0208.1983-sjis font and once as a
10611 jisx0201.1976-0 font. The latter can be used to display
10612 the ascii charset and katakana-jisx0201 charset. A
10613 negative script code signals that the name of this latter
10614 font is being built. */
10615 strcpy(cs, "jisx0201.1976-0");
10616 break;
10617 case smKorean:
10618 strcpy(cs, "ksc5601.1989-0");
10619 break;
10620 default:
10621 strcpy(cs, "mac-roman");
10622 break;
10623 }
10624 }
10625
10626 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10627 foundry, family, style & bold ? "bold" : "medium",
10628 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10629
10630 result = (char *) xmalloc (strlen (xf) + 1);
10631 strcpy (result, xf);
10632 for (p = result; *p; p++)
10633 *p = tolower(*p);
10634 return result;
10635 }
10636
10637
10638 /* Convert an X font spec to the corresponding mac font name, which
10639 can then be passed to GetFNum after conversion to a Pascal string.
10640 For ordinary Mac fonts, this should just be their names, like
10641 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10642 collection contain their charset designation in their names, like
10643 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10644 names are handled accordingly. */
10645 static void
10646 x_font_name_to_mac_font_name (char *xf, char *mf)
10647 {
10648 char foundry[32], family[32], weight[20], slant[2], cs[32];
10649
10650 strcpy (mf, "");
10651
10652 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10653 foundry, family, weight, slant, cs) != 5 &&
10654 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10655 foundry, family, weight, slant, cs) != 5)
10656 return;
10657
10658 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
10659 || strcmp (cs, "jisx0208.1983-sjis") == 0
10660 || strcmp (cs, "jisx0201.1976-0") == 0
10661 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
10662 strcpy(mf, family);
10663 else
10664 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10665 }
10666
10667
10668 static void
10669 add_font_name_table_entry (char *font_name)
10670 {
10671 if (font_name_table_size == 0)
10672 {
10673 font_name_table_size = 16;
10674 font_name_table = (char **)
10675 xmalloc (font_name_table_size * sizeof (char *));
10676 }
10677 else if (font_name_count + 1 >= font_name_table_size)
10678 {
10679 font_name_table_size += 16;
10680 font_name_table = (char **)
10681 xrealloc (font_name_table,
10682 font_name_table_size * sizeof (char *));
10683 }
10684
10685 font_name_table[font_name_count++] = font_name;
10686 }
10687
10688 /* Sets up the table font_name_table to contain the list of all fonts
10689 in the system the first time the table is used so that the Resource
10690 Manager need not be accessed every time this information is
10691 needed. */
10692
10693 static void
10694 init_font_name_table ()
10695 {
10696 #if TARGET_API_MAC_CARBON
10697 SInt32 sv;
10698
10699 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10700 {
10701 FMFontFamilyIterator ffi;
10702 FMFontFamilyInstanceIterator ffii;
10703 FMFontFamily ff;
10704
10705 /* Create a dummy instance iterator here to avoid creating and
10706 destroying it in the loop. */
10707 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10708 return;
10709 /* Create an iterator to enumerate the font families. */
10710 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10711 != noErr)
10712 {
10713 FMDisposeFontFamilyInstanceIterator (&ffii);
10714 return;
10715 }
10716
10717 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10718 {
10719 Str255 name;
10720 FMFont font;
10721 FMFontStyle style;
10722 FMFontSize size;
10723 SInt16 sc;
10724
10725 if (FMGetFontFamilyName (ff, name) != noErr)
10726 break;
10727 p2cstr (name);
10728
10729 sc = FontToScript (ff);
10730
10731 /* Point the instance iterator at the current font family. */
10732 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10733 break;
10734
10735 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10736 == noErr)
10737 if (size == 0)
10738 {
10739 add_font_name_table_entry (mac_to_x_fontname (name, size,
10740 style, sc));
10741 add_font_name_table_entry (mac_to_x_fontname (name, size,
10742 italic, sc));
10743 add_font_name_table_entry (mac_to_x_fontname (name, size,
10744 bold, sc));
10745 add_font_name_table_entry (mac_to_x_fontname (name, size,
10746 italic | bold,
10747 sc));
10748 }
10749 else
10750 {
10751 add_font_name_table_entry (mac_to_x_fontname (name, size,
10752 style, sc));
10753 if (smJapanese == sc)
10754 add_font_name_table_entry (mac_to_x_fontname (name, size,
10755 style,
10756 -smJapanese));
10757 }
10758 }
10759
10760 /* Dispose of the iterators. */
10761 FMDisposeFontFamilyIterator (&ffi);
10762 FMDisposeFontFamilyInstanceIterator (&ffii);
10763 }
10764 else
10765 {
10766 #endif /* TARGET_API_MAC_CARBON */
10767 GrafPtr port;
10768 SInt16 fontnum, old_fontnum;
10769 int num_mac_fonts = CountResources('FOND');
10770 int i, j;
10771 Handle font_handle, font_handle_2;
10772 short id, scriptcode;
10773 ResType type;
10774 Str32 name;
10775 struct FontAssoc *fat;
10776 struct AsscEntry *assc_entry;
10777
10778 GetPort (&port); /* save the current font number used */
10779 #if TARGET_API_MAC_CARBON
10780 old_fontnum = GetPortTextFont (port);
10781 #else
10782 old_fontnum = port->txFont;
10783 #endif
10784
10785 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10786 {
10787 font_handle = GetIndResource ('FOND', i);
10788 if (!font_handle)
10789 continue;
10790
10791 GetResInfo (font_handle, &id, &type, name);
10792 GetFNum (name, &fontnum);
10793 p2cstr (name);
10794 if (fontnum == 0)
10795 continue;
10796
10797 TextFont (fontnum);
10798 scriptcode = FontToScript (fontnum);
10799 do
10800 {
10801 HLock (font_handle);
10802
10803 if (GetResourceSizeOnDisk (font_handle)
10804 >= sizeof (struct FamRec))
10805 {
10806 fat = (struct FontAssoc *) (*font_handle
10807 + sizeof (struct FamRec));
10808 assc_entry
10809 = (struct AsscEntry *) (*font_handle
10810 + sizeof (struct FamRec)
10811 + sizeof (struct FontAssoc));
10812
10813 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
10814 {
10815 if (font_name_table_size == 0)
10816 {
10817 font_name_table_size = 16;
10818 font_name_table = (char **)
10819 xmalloc (font_name_table_size * sizeof (char *));
10820 }
10821 else if (font_name_count >= font_name_table_size)
10822 {
10823 font_name_table_size += 16;
10824 font_name_table = (char **)
10825 xrealloc (font_name_table,
10826 font_name_table_size * sizeof (char *));
10827 }
10828 font_name_table[font_name_count++]
10829 = mac_to_x_fontname (name,
10830 assc_entry->fontSize,
10831 assc_entry->fontStyle,
10832 scriptcode);
10833 /* Both jisx0208.1983-sjis and
10834 jisx0201.1976-sjis parts are contained in
10835 Apple Japanese (SJIS) font. */
10836 if (smJapanese == scriptcode)
10837 {
10838 font_name_table[font_name_count++]
10839 = mac_to_x_fontname (name,
10840 assc_entry->fontSize,
10841 assc_entry->fontStyle,
10842 -smJapanese);
10843 }
10844 }
10845 }
10846
10847 HUnlock (font_handle);
10848 font_handle_2 = GetNextFOND (font_handle);
10849 ReleaseResource (font_handle);
10850 font_handle = font_handle_2;
10851 }
10852 while (ResError () == noErr && font_handle);
10853 }
10854
10855 TextFont (old_fontnum);
10856 #if TARGET_API_MAC_CARBON
10857 }
10858 #endif /* TARGET_API_MAC_CARBON */
10859 }
10860
10861
10862 /* Return a list of at most MAXNAMES font specs matching the one in
10863 PATTERN. Cache matching fonts for patterns in
10864 dpyinfo->name_list_element to avoid looking them up again by
10865 calling mac_font_pattern_match (slow). */
10866
10867 Lisp_Object
10868 x_list_fonts (struct frame *f,
10869 Lisp_Object pattern,
10870 int size,
10871 int maxnames)
10872 {
10873 char *ptnstr;
10874 Lisp_Object newlist = Qnil, tem, key;
10875 int n_fonts = 0;
10876 int i;
10877 struct gcpro gcpro1, gcpro2;
10878 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
10879
10880 if (font_name_table == NULL) /* Initialize when first used. */
10881 init_font_name_table ();
10882
10883 if (dpyinfo)
10884 {
10885 tem = XCDR (dpyinfo->name_list_element);
10886 key = Fcons (pattern, make_number (maxnames));
10887
10888 newlist = Fassoc (key, tem);
10889 if (!NILP (newlist))
10890 {
10891 newlist = Fcdr_safe (newlist);
10892 goto label_cached;
10893 }
10894 }
10895
10896 ptnstr = SDATA (pattern);
10897
10898 GCPRO2 (pattern, newlist);
10899
10900 /* Scan and matching bitmap fonts. */
10901 for (i = 0; i < font_name_count; i++)
10902 {
10903 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10904 {
10905 newlist = Fcons (build_string (font_name_table[i]), newlist);
10906
10907 n_fonts++;
10908 if (n_fonts >= maxnames)
10909 break;
10910 }
10911 }
10912
10913 /* MAC_TODO: add code for matching outline fonts here */
10914
10915 UNGCPRO;
10916
10917 if (dpyinfo)
10918 {
10919 XSETCDR (dpyinfo->name_list_element,
10920 Fcons (Fcons (key, newlist),
10921 XCDR (dpyinfo->name_list_element)));
10922 }
10923 label_cached:
10924
10925 return newlist;
10926 }
10927
10928
10929 #if GLYPH_DEBUG
10930
10931 /* Check that FONT is valid on frame F. It is if it can be found in F's
10932 font table. */
10933
10934 static void
10935 x_check_font (f, font)
10936 struct frame *f;
10937 XFontStruct *font;
10938 {
10939 int i;
10940 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10941
10942 xassert (font != NULL);
10943
10944 for (i = 0; i < dpyinfo->n_fonts; i++)
10945 if (dpyinfo->font_table[i].name
10946 && font == dpyinfo->font_table[i].font)
10947 break;
10948
10949 xassert (i < dpyinfo->n_fonts);
10950 }
10951
10952 #endif /* GLYPH_DEBUG != 0 */
10953
10954 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10955 Note: There are (broken) X fonts out there with invalid XFontStruct
10956 min_bounds contents. For example, handa@etl.go.jp reports that
10957 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10958 have font->min_bounds.width == 0. */
10959
10960 static INLINE void
10961 x_font_min_bounds (font, w, h)
10962 MacFontStruct *font;
10963 int *w, *h;
10964 {
10965 /*
10966 * TODO: Windows does not appear to offer min bound, only
10967 * average and maximum width, and maximum height.
10968 */
10969 *h = FONT_HEIGHT (font);
10970 *w = FONT_WIDTH (font);
10971 }
10972
10973
10974 /* Compute the smallest character width and smallest font height over
10975 all fonts available on frame F. Set the members smallest_char_width
10976 and smallest_font_height in F's x_display_info structure to
10977 the values computed. Value is non-zero if smallest_font_height or
10978 smallest_char_width become smaller than they were before. */
10979
10980 int
10981 x_compute_min_glyph_bounds (f)
10982 struct frame *f;
10983 {
10984 int i;
10985 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10986 MacFontStruct *font;
10987 int old_width = dpyinfo->smallest_char_width;
10988 int old_height = dpyinfo->smallest_font_height;
10989
10990 dpyinfo->smallest_font_height = 100000;
10991 dpyinfo->smallest_char_width = 100000;
10992
10993 for (i = 0; i < dpyinfo->n_fonts; ++i)
10994 if (dpyinfo->font_table[i].name)
10995 {
10996 struct font_info *fontp = dpyinfo->font_table + i;
10997 int w, h;
10998
10999 font = (MacFontStruct *) fontp->font;
11000 xassert (font != (MacFontStruct *) ~0);
11001 x_font_min_bounds (font, &w, &h);
11002
11003 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
11004 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
11005 }
11006
11007 xassert (dpyinfo->smallest_char_width > 0
11008 && dpyinfo->smallest_font_height > 0);
11009
11010 return (dpyinfo->n_fonts == 1
11011 || dpyinfo->smallest_char_width < old_width
11012 || dpyinfo->smallest_font_height < old_height);
11013 }
11014
11015
11016 /* Determine whether given string is a fully-specified XLFD: all 14
11017 fields are present, none is '*'. */
11018
11019 static int
11020 is_fully_specified_xlfd (char *p)
11021 {
11022 int i;
11023 char *q;
11024
11025 if (*p != '-')
11026 return 0;
11027
11028 for (i = 0; i < 13; i++)
11029 {
11030 q = strchr (p + 1, '-');
11031 if (q == NULL)
11032 return 0;
11033 if (q - p == 2 && *(p + 1) == '*')
11034 return 0;
11035 p = q;
11036 }
11037
11038 if (strchr (p + 1, '-') != NULL)
11039 return 0;
11040
11041 if (*(p + 1) == '*' && *(p + 2) == '\0')
11042 return 0;
11043
11044 return 1;
11045 }
11046
11047
11048 const int kDefaultFontSize = 9;
11049
11050
11051 /* XLoadQueryFont creates and returns an internal representation for a
11052 font in a MacFontStruct struct. There is really no concept
11053 corresponding to "loading" a font on the Mac. But we check its
11054 existence and find the font number and all other information for it
11055 and store them in the returned MacFontStruct. */
11056
11057 static MacFontStruct *
11058 XLoadQueryFont (Display *dpy, char *fontname)
11059 {
11060 int i, size, is_two_byte_font, char_width;
11061 char *name;
11062 GrafPtr port;
11063 SInt16 old_fontnum, old_fontsize;
11064 Style old_fontface;
11065 Str32 mfontname;
11066 SInt16 fontnum;
11067 Style fontface = normal;
11068 MacFontStruct *font;
11069 FontInfo the_fontinfo;
11070 char s_weight[7], c_slant;
11071
11072 if (is_fully_specified_xlfd (fontname))
11073 name = fontname;
11074 else
11075 {
11076 for (i = 0; i < font_name_count; i++)
11077 if (mac_font_pattern_match (font_name_table[i], fontname))
11078 break;
11079
11080 if (i >= font_name_count)
11081 return NULL;
11082
11083 name = font_name_table[i];
11084 }
11085
11086 GetPort (&port); /* save the current font number used */
11087 #if TARGET_API_MAC_CARBON
11088 old_fontnum = GetPortTextFont (port);
11089 old_fontsize = GetPortTextSize (port);
11090 old_fontface = GetPortTextFace (port);
11091 #else
11092 old_fontnum = port->txFont;
11093 old_fontsize = port->txSize;
11094 old_fontface = port->txFace;
11095 #endif
11096
11097 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
11098 size = kDefaultFontSize;
11099
11100 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
11101 if (strcmp (s_weight, "bold") == 0)
11102 fontface |= bold;
11103
11104 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
11105 if (c_slant == 'i')
11106 fontface |= italic;
11107
11108 x_font_name_to_mac_font_name (name, mfontname);
11109 c2pstr (mfontname);
11110 GetFNum (mfontname, &fontnum);
11111 if (fontnum == 0)
11112 return NULL;
11113
11114 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
11115
11116 font->fontname = (char *) xmalloc (strlen (name) + 1);
11117 bcopy (name, font->fontname, strlen (name) + 1);
11118
11119 font->mac_fontnum = fontnum;
11120 font->mac_fontsize = size;
11121 font->mac_fontface = fontface;
11122 font->mac_scriptcode = FontToScript (fontnum);
11123
11124 /* Apple Japanese (SJIS) font is listed as both
11125 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
11126 (Roman script) in init_font_name_table (). The latter should be
11127 treated as a one-byte font. */
11128 {
11129 char cs[32];
11130
11131 if (sscanf (name,
11132 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11133 cs) == 1
11134 && 0 == strcmp (cs, "jisx0201.1976-0"))
11135 font->mac_scriptcode = smRoman;
11136 }
11137
11138 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11139 font->mac_scriptcode == smTradChinese ||
11140 font->mac_scriptcode == smSimpChinese ||
11141 font->mac_scriptcode == smKorean;
11142
11143 TextFont (fontnum);
11144 TextSize (size);
11145 TextFace (fontface);
11146
11147 GetFontInfo (&the_fontinfo);
11148
11149 font->ascent = the_fontinfo.ascent;
11150 font->descent = the_fontinfo.descent;
11151
11152 font->min_byte1 = 0;
11153 if (is_two_byte_font)
11154 font->max_byte1 = 1;
11155 else
11156 font->max_byte1 = 0;
11157 font->min_char_or_byte2 = 0x20;
11158 font->max_char_or_byte2 = 0xff;
11159
11160 if (is_two_byte_font)
11161 {
11162 /* Use the width of an "ideographic space" of that font because
11163 the_fontinfo.widMax returns the wrong width for some fonts. */
11164 switch (font->mac_scriptcode)
11165 {
11166 case smJapanese:
11167 char_width = StringWidth("\p\x81\x40");
11168 break;
11169 case smTradChinese:
11170 char_width = StringWidth("\p\xa1\x40");
11171 break;
11172 case smSimpChinese:
11173 char_width = StringWidth("\p\xa1\xa1");
11174 break;
11175 case smKorean:
11176 char_width = StringWidth("\p\xa1\xa1");
11177 break;
11178 }
11179 }
11180 else
11181 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11182 returns 15 for 12-point Monaco! */
11183 char_width = CharWidth ('m');
11184
11185 font->max_bounds.rbearing = char_width;
11186 font->max_bounds.lbearing = 0;
11187 font->max_bounds.width = char_width;
11188 font->max_bounds.ascent = the_fontinfo.ascent;
11189 font->max_bounds.descent = the_fontinfo.descent;
11190
11191 font->min_bounds = font->max_bounds;
11192
11193 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11194 font->per_char = NULL;
11195 else
11196 {
11197 font->per_char = (XCharStruct *)
11198 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11199 {
11200 int c;
11201
11202 for (c = 0x20; c <= 0xff; c++)
11203 {
11204 font->per_char[c - 0x20] = font->max_bounds;
11205 font->per_char[c - 0x20].width = CharWidth (c);
11206 }
11207 }
11208 }
11209
11210 TextFont (old_fontnum); /* restore previous font number, size and face */
11211 TextSize (old_fontsize);
11212 TextFace (old_fontface);
11213
11214 return font;
11215 }
11216
11217
11218 /* Load font named FONTNAME of the size SIZE for frame F, and return a
11219 pointer to the structure font_info while allocating it dynamically.
11220 If SIZE is 0, load any size of font.
11221 If loading is failed, return NULL. */
11222
11223 struct font_info *
11224 x_load_font (f, fontname, size)
11225 struct frame *f;
11226 register char *fontname;
11227 int size;
11228 {
11229 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11230 Lisp_Object font_names;
11231
11232 /* Get a list of all the fonts that match this name. Once we
11233 have a list of matching fonts, we compare them against the fonts
11234 we already have by comparing names. */
11235 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11236
11237 if (!NILP (font_names))
11238 {
11239 Lisp_Object tail;
11240 int i;
11241
11242 for (i = 0; i < dpyinfo->n_fonts; i++)
11243 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11244 if (dpyinfo->font_table[i].name
11245 && (!strcmp (dpyinfo->font_table[i].name,
11246 SDATA (XCAR (tail)))
11247 || !strcmp (dpyinfo->font_table[i].full_name,
11248 SDATA (XCAR (tail)))))
11249 return (dpyinfo->font_table + i);
11250 }
11251
11252 /* Load the font and add it to the table. */
11253 {
11254 char *full_name;
11255 struct MacFontStruct *font;
11256 struct font_info *fontp;
11257 unsigned long value;
11258 int i;
11259
11260 /* If we have found fonts by x_list_font, load one of them. If
11261 not, we still try to load a font by the name given as FONTNAME
11262 because XListFonts (called in x_list_font) of some X server has
11263 a bug of not finding a font even if the font surely exists and
11264 is loadable by XLoadQueryFont. */
11265 if (size > 0 && !NILP (font_names))
11266 fontname = (char *) SDATA (XCAR (font_names));
11267
11268 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11269 if (!font)
11270 return NULL;
11271
11272 /* Find a free slot in the font table. */
11273 for (i = 0; i < dpyinfo->n_fonts; ++i)
11274 if (dpyinfo->font_table[i].name == NULL)
11275 break;
11276
11277 /* If no free slot found, maybe enlarge the font table. */
11278 if (i == dpyinfo->n_fonts
11279 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11280 {
11281 int sz;
11282 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11283 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11284 dpyinfo->font_table
11285 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11286 }
11287
11288 fontp = dpyinfo->font_table + i;
11289 if (i == dpyinfo->n_fonts)
11290 ++dpyinfo->n_fonts;
11291
11292 /* Now fill in the slots of *FONTP. */
11293 BLOCK_INPUT;
11294 fontp->font = font;
11295 fontp->font_idx = i;
11296 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11297 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11298
11299 fontp->full_name = fontp->name;
11300
11301 fontp->size = font->max_bounds.width;
11302 fontp->height = FONT_HEIGHT (font);
11303 {
11304 /* For some font, ascent and descent in max_bounds field is
11305 larger than the above value. */
11306 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11307 if (max_height > fontp->height)
11308 fontp->height = max_height;
11309 }
11310
11311 /* The slot `encoding' specifies how to map a character
11312 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11313 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11314 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11315 2:0xA020..0xFF7F). For the moment, we don't know which charset
11316 uses this font. So, we set information in fontp->encoding[1]
11317 which is never used by any charset. If mapping can't be
11318 decided, set FONT_ENCODING_NOT_DECIDED. */
11319 if (font->mac_scriptcode == smJapanese)
11320 fontp->encoding[1] = 4;
11321 else
11322 {
11323 fontp->encoding[1]
11324 = (font->max_byte1 == 0
11325 /* 1-byte font */
11326 ? (font->min_char_or_byte2 < 0x80
11327 ? (font->max_char_or_byte2 < 0x80
11328 ? 0 /* 0x20..0x7F */
11329 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11330 : 1) /* 0xA0..0xFF */
11331 /* 2-byte font */
11332 : (font->min_byte1 < 0x80
11333 ? (font->max_byte1 < 0x80
11334 ? (font->min_char_or_byte2 < 0x80
11335 ? (font->max_char_or_byte2 < 0x80
11336 ? 0 /* 0x2020..0x7F7F */
11337 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11338 : 3) /* 0x20A0..0x7FFF */
11339 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11340 : (font->min_char_or_byte2 < 0x80
11341 ? (font->max_char_or_byte2 < 0x80
11342 ? 2 /* 0xA020..0xFF7F */
11343 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11344 : 1))); /* 0xA0A0..0xFFFF */
11345 }
11346
11347 #if 0 /* MAC_TODO: fill these out with more reasonably values */
11348 fontp->baseline_offset
11349 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11350 ? (long) value : 0);
11351 fontp->relative_compose
11352 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11353 ? (long) value : 0);
11354 fontp->default_ascent
11355 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11356 ? (long) value : 0);
11357 #else
11358 fontp->baseline_offset = 0;
11359 fontp->relative_compose = 0;
11360 fontp->default_ascent = 0;
11361 #endif
11362
11363 /* Set global flag fonts_changed_p to non-zero if the font loaded
11364 has a character with a smaller width than any other character
11365 before, or if the font loaded has a smalle>r height than any
11366 other font loaded before. If this happens, it will make a
11367 glyph matrix reallocation necessary. */
11368 fonts_changed_p = x_compute_min_glyph_bounds (f);
11369 UNBLOCK_INPUT;
11370 return fontp;
11371 }
11372 }
11373
11374
11375 /* Return a pointer to struct font_info of a font named FONTNAME for
11376 frame F. If no such font is loaded, return NULL. */
11377
11378 struct font_info *
11379 x_query_font (f, fontname)
11380 struct frame *f;
11381 register char *fontname;
11382 {
11383 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11384 int i;
11385
11386 for (i = 0; i < dpyinfo->n_fonts; i++)
11387 if (dpyinfo->font_table[i].name
11388 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11389 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11390 return (dpyinfo->font_table + i);
11391 return NULL;
11392 }
11393
11394
11395 /* Find a CCL program for a font specified by FONTP, and set the member
11396 `encoder' of the structure. */
11397
11398 void
11399 x_find_ccl_program (fontp)
11400 struct font_info *fontp;
11401 {
11402 Lisp_Object list, elt;
11403
11404 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11405 {
11406 elt = XCAR (list);
11407 if (CONSP (elt)
11408 && STRINGP (XCAR (elt))
11409 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11410 >= 0))
11411 break;
11412 }
11413 if (! NILP (list))
11414 {
11415 struct ccl_program *ccl
11416 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11417
11418 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11419 xfree (ccl);
11420 else
11421 fontp->font_encoder = ccl;
11422 }
11423 }
11424
11425
11426 \f
11427 /***********************************************************************
11428 Initialization
11429 ***********************************************************************/
11430
11431 #ifdef USE_X_TOOLKIT
11432 static XrmOptionDescRec emacs_options[] = {
11433 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11434 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11435
11436 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11437 XrmoptionSepArg, NULL},
11438 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11439
11440 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11441 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11442 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11443 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11444 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11445 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11446 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11447 };
11448 #endif /* USE_X_TOOLKIT */
11449
11450 static int x_initialized;
11451
11452 #ifdef MULTI_KBOARD
11453 /* Test whether two display-name strings agree up to the dot that separates
11454 the screen number from the server number. */
11455 static int
11456 same_x_server (name1, name2)
11457 char *name1, *name2;
11458 {
11459 int seen_colon = 0;
11460 unsigned char *system_name = SDATA (Vsystem_name);
11461 int system_name_length = strlen (system_name);
11462 int length_until_period = 0;
11463
11464 while (system_name[length_until_period] != 0
11465 && system_name[length_until_period] != '.')
11466 length_until_period++;
11467
11468 /* Treat `unix' like an empty host name. */
11469 if (! strncmp (name1, "unix:", 5))
11470 name1 += 4;
11471 if (! strncmp (name2, "unix:", 5))
11472 name2 += 4;
11473 /* Treat this host's name like an empty host name. */
11474 if (! strncmp (name1, system_name, system_name_length)
11475 && name1[system_name_length] == ':')
11476 name1 += system_name_length;
11477 if (! strncmp (name2, system_name, system_name_length)
11478 && name2[system_name_length] == ':')
11479 name2 += system_name_length;
11480 /* Treat this host's domainless name like an empty host name. */
11481 if (! strncmp (name1, system_name, length_until_period)
11482 && name1[length_until_period] == ':')
11483 name1 += length_until_period;
11484 if (! strncmp (name2, system_name, length_until_period)
11485 && name2[length_until_period] == ':')
11486 name2 += length_until_period;
11487
11488 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11489 {
11490 if (*name1 == ':')
11491 seen_colon++;
11492 if (seen_colon && *name1 == '.')
11493 return 1;
11494 }
11495 return (seen_colon
11496 && (*name1 == '.' || *name1 == '\0')
11497 && (*name2 == '.' || *name2 == '\0'));
11498 }
11499 #endif
11500
11501
11502 /* The Mac Event loop code */
11503
11504 #ifndef MAC_OSX
11505 #include <Events.h>
11506 #include <Quickdraw.h>
11507 #include <Balloons.h>
11508 #include <Devices.h>
11509 #include <Fonts.h>
11510 #include <Gestalt.h>
11511 #include <Menus.h>
11512 #include <Processes.h>
11513 #include <Sound.h>
11514 #include <ToolUtils.h>
11515 #include <TextUtils.h>
11516 #include <Dialogs.h>
11517 #include <Script.h>
11518 #include <Types.h>
11519 #include <TextEncodingConverter.h>
11520 #include <Resources.h>
11521
11522 #if __MWERKS__
11523 #include <unix.h>
11524 #endif
11525 #endif /* ! MAC_OSX */
11526
11527 #define M_APPLE 128
11528 #define I_ABOUT 1
11529
11530 #define WINDOW_RESOURCE 128
11531 #define TERM_WINDOW_RESOURCE 129
11532
11533 #define DEFAULT_NUM_COLS 80
11534
11535 #define MIN_DOC_SIZE 64
11536 #define MAX_DOC_SIZE 32767
11537
11538 /* sleep time for WaitNextEvent */
11539 #define WNE_SLEEP_AT_SUSPEND 10
11540 #define WNE_SLEEP_AT_RESUME 1
11541
11542 /* true when cannot handle any Mac OS events */
11543 static int handling_window_update = 0;
11544
11545 /* the flag appl_is_suspended is used both for determining the sleep
11546 time to be passed to WaitNextEvent and whether the cursor should be
11547 drawn when updating the display. The cursor is turned off when
11548 Emacs is suspended. Redrawing it is unnecessary and what needs to
11549 be done depends on whether the cursor lies inside or outside the
11550 redraw region. So we might as well skip drawing it when Emacs is
11551 suspended. */
11552 static Boolean app_is_suspended = false;
11553 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11554
11555 #define EXTRA_STACK_ALLOC (256 * 1024)
11556
11557 #define ARGV_STRING_LIST_ID 129
11558 #define ABOUT_ALERT_ID 128
11559 #define RAM_TOO_LARGE_ALERT_ID 129
11560
11561 Boolean terminate_flag = false;
11562
11563 /* true if using command key as meta key */
11564 Lisp_Object Vmac_command_key_is_meta;
11565
11566 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11567 to this text encoding */
11568 int mac_keyboard_text_encoding;
11569 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11570
11571 /* Set in term/mac-win.el to indicate that event loop can now generate
11572 drag and drop events. */
11573 Lisp_Object Qmac_ready_for_drag_n_drop;
11574
11575 Lisp_Object drag_and_drop_file_list;
11576
11577 Point saved_menu_event_location;
11578
11579 /* Apple Events */
11580 static void init_required_apple_events(void);
11581 static pascal OSErr
11582 do_ae_open_application(const AppleEvent *, AppleEvent *, long);
11583 static pascal OSErr
11584 do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
11585 static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
11586 static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
11587
11588 extern void init_emacs_passwd_dir ();
11589 extern int emacs_main (int, char **, char **);
11590 extern void check_alarm ();
11591
11592 extern void initialize_applescript();
11593 extern void terminate_applescript();
11594
11595
11596 static void
11597 do_get_menus (void)
11598 {
11599 Handle menubar_handle;
11600 MenuHandle menu_handle;
11601
11602 menubar_handle = GetNewMBar (128);
11603 if(menubar_handle == NULL)
11604 abort ();
11605 SetMenuBar (menubar_handle);
11606 DrawMenuBar ();
11607
11608 menu_handle = GetMenuHandle (M_APPLE);
11609 if(menu_handle != NULL)
11610 AppendResMenu (menu_handle,'DRVR');
11611 else
11612 abort ();
11613 }
11614
11615
11616 static void
11617 do_init_managers (void)
11618 {
11619 #if !TARGET_API_MAC_CARBON
11620 InitGraf (&qd.thePort);
11621 InitFonts ();
11622 FlushEvents (everyEvent, 0);
11623 InitWindows ();
11624 InitMenus ();
11625 TEInit ();
11626 InitDialogs (NULL);
11627 #endif /* !TARGET_API_MAC_CARBON */
11628 InitCursor ();
11629
11630 #if !TARGET_API_MAC_CARBON
11631 /* set up some extra stack space for use by emacs */
11632 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11633
11634 /* MaxApplZone must be called for AppleScript to execute more
11635 complicated scripts */
11636 MaxApplZone ();
11637 MoreMasters ();
11638 #endif /* !TARGET_API_MAC_CARBON */
11639 }
11640
11641 static void
11642 do_check_ram_size (void)
11643 {
11644 SInt32 physical_ram_size, logical_ram_size;
11645
11646 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11647 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11648 || physical_ram_size > 256 * 1024 * 1024
11649 || logical_ram_size > 256 * 1024 * 1024)
11650 {
11651 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11652 exit (1);
11653 }
11654 }
11655
11656 static void
11657 do_window_update (WindowPtr win)
11658 {
11659 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11660 struct frame *f = mwp->mFP;
11661
11662 if (f)
11663 {
11664 if (f->async_visible == 0)
11665 {
11666 f->async_visible = 1;
11667 f->async_iconified = 0;
11668 SET_FRAME_GARBAGED (f);
11669
11670 /* An update event is equivalent to MapNotify on X, so report
11671 visibility changes properly. */
11672 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11673 /* Force a redisplay sooner or later to update the
11674 frame titles in case this is the second frame. */
11675 record_asynch_buffer_change ();
11676 }
11677 else
11678 {
11679 BeginUpdate (win);
11680 handling_window_update = 1;
11681
11682 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
11683
11684 expose_frame (f, 0, 0, 0, 0);
11685
11686 handling_window_update = 0;
11687 EndUpdate (win);
11688 }
11689 }
11690 }
11691
11692 static int
11693 is_emacs_window (WindowPtr win)
11694 {
11695 Lisp_Object tail, frame;
11696
11697 if (!win)
11698 return 0;
11699
11700 FOR_EACH_FRAME (tail, frame)
11701 if (FRAME_MAC_P (XFRAME (frame)))
11702 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11703 return 1;
11704
11705 return 0;
11706 }
11707
11708 static void
11709 do_window_activate (WindowPtr win)
11710 {
11711 mac_output *mwp;
11712 struct frame *f;
11713
11714 if (is_emacs_window (win))
11715 {
11716 mwp = (mac_output *) GetWRefCon (win);
11717 f = mwp->mFP;
11718
11719 if (f)
11720 {
11721 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11722 activate_scroll_bars (f);
11723 }
11724 }
11725 }
11726
11727 static void
11728 do_window_deactivate (WindowPtr win)
11729 {
11730 mac_output *mwp;
11731 struct frame *f;
11732
11733 if (is_emacs_window (win))
11734 {
11735 mwp = (mac_output *) GetWRefCon (win);
11736 f = mwp->mFP;
11737
11738 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11739 {
11740 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11741 deactivate_scroll_bars (f);
11742 }
11743 }
11744 }
11745
11746 static void
11747 do_app_resume ()
11748 {
11749 WindowPtr wp;
11750 mac_output *mwp;
11751 struct frame *f;
11752
11753 wp = FrontWindow();
11754 if (is_emacs_window (wp))
11755 {
11756 mwp = (mac_output *) GetWRefCon (wp);
11757 f = mwp->mFP;
11758
11759 if (f)
11760 {
11761 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11762 activate_scroll_bars (f);
11763 }
11764 }
11765
11766 app_is_suspended = false;
11767 app_sleep_time = WNE_SLEEP_AT_RESUME;
11768 }
11769
11770 static void
11771 do_app_suspend ()
11772 {
11773 WindowPtr wp;
11774 mac_output *mwp;
11775 struct frame *f;
11776
11777 wp = FrontWindow();
11778 if (is_emacs_window (wp))
11779 {
11780 mwp = (mac_output *) GetWRefCon (wp);
11781 f = mwp->mFP;
11782
11783 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11784 {
11785 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11786 deactivate_scroll_bars (f);
11787 }
11788 }
11789
11790 app_is_suspended = true;
11791 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11792 }
11793
11794
11795 static void
11796 do_mouse_moved (Point mouse_pos)
11797 {
11798 WindowPtr wp = FrontWindow ();
11799 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11800
11801 #if TARGET_API_MAC_CARBON
11802 SetPort (GetWindowPort (wp));
11803 #else
11804 SetPort (wp);
11805 #endif
11806
11807 GlobalToLocal (&mouse_pos);
11808
11809 note_mouse_movement (f, &mouse_pos);
11810 }
11811
11812
11813 static void
11814 do_os_event (EventRecord *erp)
11815 {
11816 switch((erp->message >> 24) & 0x000000FF)
11817 {
11818 case suspendResumeMessage:
11819 if((erp->message & resumeFlag) == 1)
11820 do_app_resume ();
11821 else
11822 do_app_suspend ();
11823 break;
11824
11825 case mouseMovedMessage:
11826 do_mouse_moved (erp->where);
11827 break;
11828 }
11829 }
11830
11831 static void
11832 do_events (EventRecord *erp)
11833 {
11834 switch (erp->what)
11835 {
11836 case updateEvt:
11837 do_window_update ((WindowPtr) erp->message);
11838 break;
11839
11840 case osEvt:
11841 do_os_event (erp);
11842 break;
11843
11844 case activateEvt:
11845 if ((erp->modifiers & activeFlag) != 0)
11846 do_window_activate ((WindowPtr) erp->message);
11847 else
11848 do_window_deactivate ((WindowPtr) erp->message);
11849 break;
11850 }
11851 }
11852
11853 static void
11854 do_apple_menu (SInt16 menu_item)
11855 {
11856 #if !TARGET_API_MAC_CARBON
11857 Str255 item_name;
11858 SInt16 da_driver_refnum;
11859
11860 if (menu_item == I_ABOUT)
11861 NoteAlert (ABOUT_ALERT_ID, NULL);
11862 else
11863 {
11864 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11865 da_driver_refnum = OpenDeskAcc (item_name);
11866 }
11867 #endif /* !TARGET_API_MAC_CARBON */
11868 }
11869
11870 void
11871 do_menu_choice (SInt32 menu_choice)
11872 {
11873 SInt16 menu_id, menu_item;
11874
11875 menu_id = HiWord (menu_choice);
11876 menu_item = LoWord (menu_choice);
11877
11878 if (menu_id == 0)
11879 return;
11880
11881 switch (menu_id)
11882 {
11883 case M_APPLE:
11884 do_apple_menu (menu_item);
11885 break;
11886
11887 default:
11888 {
11889 WindowPtr wp = FrontWindow ();
11890 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11891 MenuHandle menu = GetMenuHandle (menu_id);
11892 if (menu)
11893 {
11894 UInt32 refcon;
11895
11896 GetMenuItemRefCon (menu, menu_item, &refcon);
11897 menubar_selection_callback (f, refcon);
11898 }
11899 }
11900 }
11901
11902 HiliteMenu (0);
11903 }
11904
11905
11906 /* Handle drags in size box. Based on code contributed by Ben
11907 Mesander and IM - Window Manager A. */
11908
11909 static void
11910 do_grow_window (WindowPtr w, EventRecord *e)
11911 {
11912 long grow_size;
11913 Rect limit_rect;
11914 int rows, columns;
11915 mac_output *mwp = (mac_output *) GetWRefCon (w);
11916 struct frame *f = mwp->mFP;
11917
11918 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11919
11920 grow_size = GrowWindow (w, e->where, &limit_rect);
11921
11922 /* see if it really changed size */
11923 if (grow_size != 0)
11924 {
11925 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11926 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11927
11928 x_set_window_size (f, 0, columns, rows);
11929 }
11930 }
11931
11932
11933 /* Handle clicks in zoom box. Calculation of "standard state" based
11934 on code in IM - Window Manager A and code contributed by Ben
11935 Mesander. The standard state of an Emacs window is 80-characters
11936 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11937
11938 static void
11939 do_zoom_window (WindowPtr w, int zoom_in_or_out)
11940 {
11941 GrafPtr save_port;
11942 Rect zoom_rect, port_rect;
11943 Point top_left;
11944 int w_title_height, columns, rows, width, height, dummy, x, y;
11945 mac_output *mwp = (mac_output *) GetWRefCon (w);
11946 struct frame *f = mwp->mFP;
11947
11948 GetPort (&save_port);
11949
11950 #if TARGET_API_MAC_CARBON
11951 SetPort (GetWindowPort (w));
11952 #else
11953 SetPort (w);
11954 #endif
11955
11956 /* Clear window to avoid flicker. */
11957 #if TARGET_API_MAC_CARBON
11958 {
11959 Rect r;
11960 BitMap bm;
11961
11962 GetWindowPortBounds (w, &r);
11963 EraseRect (&r);
11964
11965 if (zoom_in_or_out == inZoomOut)
11966 {
11967 /* calculate height of window's title bar (hard card it for now). */
11968 w_title_height = 20 + GetMBarHeight ();
11969
11970 /* get maximum height of window into zoom_rect.bottom -
11971 zoom_rect.top */
11972 GetQDGlobalsScreenBits (&bm);
11973 zoom_rect = bm.bounds;
11974 zoom_rect.top += w_title_height;
11975 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11976
11977 zoom_rect.right = zoom_rect.left
11978 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11979
11980 SetWindowStandardState (w, &zoom_rect);
11981 }
11982 }
11983 #else /* not TARGET_API_MAC_CARBON */
11984 EraseRect (&(w->portRect));
11985 if (zoom_in_or_out == inZoomOut)
11986 {
11987 SetPt (&top_left, w->portRect.left, w->portRect.top);
11988 LocalToGlobal (&top_left);
11989
11990 /* calculate height of window's title bar */
11991 w_title_height = top_left.v - 1
11992 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
11993
11994 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
11995 zoom_rect = qd.screenBits.bounds;
11996 zoom_rect.top += w_title_height;
11997 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11998
11999 zoom_rect.right = zoom_rect.left
12000 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
12001
12002 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
12003 = zoom_rect;
12004 }
12005 #endif /* not TARGET_API_MAC_CARBON */
12006
12007 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
12008
12009 /* retrieve window size and update application values */
12010 #if TARGET_API_MAC_CARBON
12011 GetWindowPortBounds (w, &port_rect);
12012 #else
12013 port_rect = w->portRect;
12014 #endif
12015 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
12016 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
12017 x_set_window_size (mwp->mFP, 0, columns, rows);
12018
12019 SetPort (save_port);
12020 }
12021
12022
12023 /* Intialize AppleEvent dispatcher table for the required events. */
12024 void
12025 init_required_apple_events ()
12026 {
12027 OSErr err;
12028 long result;
12029
12030 /* Make sure we have apple events before starting. */
12031 err = Gestalt (gestaltAppleEventsAttr, &result);
12032 if (err != noErr)
12033 abort ();
12034
12035 if (!(result & (1 << gestaltAppleEventsPresent)))
12036 abort ();
12037
12038 #if TARGET_API_MAC_CARBON
12039 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12040 NewAEEventHandlerUPP
12041 ((AEEventHandlerProcPtr) do_ae_open_application),
12042 0L, false);
12043 #else
12044 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
12045 NewAEEventHandlerProc
12046 ((AEEventHandlerProcPtr) do_ae_open_application),
12047 0L, false);
12048 #endif
12049 if (err != noErr)
12050 abort ();
12051
12052 #if TARGET_API_MAC_CARBON
12053 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12054 NewAEEventHandlerUPP
12055 ((AEEventHandlerProcPtr) do_ae_open_documents),
12056 0L, false);
12057 #else
12058 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
12059 NewAEEventHandlerProc
12060 ((AEEventHandlerProcPtr) do_ae_open_documents),
12061 0L, false);
12062 #endif
12063 if (err != noErr)
12064 abort ();
12065
12066 #if TARGET_API_MAC_CARBON
12067 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12068 NewAEEventHandlerUPP
12069 ((AEEventHandlerProcPtr) do_ae_print_documents),
12070 0L, false);
12071 #else
12072 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12073 NewAEEventHandlerProc
12074 ((AEEventHandlerProcPtr) do_ae_print_documents),
12075 0L, false);
12076 #endif
12077 if (err != noErr)
12078 abort ();
12079
12080 #if TARGET_API_MAC_CARBON
12081 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12082 NewAEEventHandlerUPP
12083 ((AEEventHandlerProcPtr) do_ae_quit_application),
12084 0L, false);
12085 #else
12086 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12087 NewAEEventHandlerProc
12088 ((AEEventHandlerProcPtr) do_ae_quit_application),
12089 0L, false);
12090 #endif
12091 if (err != noErr)
12092 abort ();
12093 }
12094
12095
12096 /* Open Application Apple Event */
12097 static pascal OSErr
12098 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12099 {
12100 return noErr;
12101 }
12102
12103
12104 /* Defined in mac.c. */
12105 extern int
12106 path_from_vol_dir_name (char *, int, short, long, char *);
12107
12108
12109 /* Called when we receive an AppleEvent with an ID of
12110 "kAEOpenDocuments". This routine gets the direct parameter,
12111 extracts the FSSpecs in it, and puts their names on a list. */
12112 static pascal OSErr
12113 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12114 {
12115 OSErr err, err2;
12116 AEDesc the_desc;
12117 AEKeyword keyword;
12118 DescType actual_type;
12119 Size actual_size;
12120
12121 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12122 if (err != noErr)
12123 goto descriptor_error_exit;
12124
12125 /* Check to see that we got all of the required parameters from the
12126 event descriptor. For an 'odoc' event this should just be the
12127 file list. */
12128 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
12129 &actual_type, (Ptr) &keyword,
12130 sizeof (keyword), &actual_size);
12131 /* No error means that we found some unused parameters.
12132 errAEDescNotFound means that there are no more parameters. If we
12133 get an error code other than that, flag it. */
12134 if ((err == noErr) || (err != errAEDescNotFound))
12135 {
12136 err = errAEEventNotHandled;
12137 goto error_exit;
12138 }
12139 err = noErr;
12140
12141 /* Got all the parameters we need. Now, go through the direct
12142 object list and parse it up. */
12143 {
12144 long num_files_to_open;
12145
12146 err = AECountItems (&the_desc, &num_files_to_open);
12147 if (err == noErr)
12148 {
12149 int i;
12150
12151 /* AE file list is one based so just use that for indexing here. */
12152 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
12153 {
12154 FSSpec fs;
12155 Str255 path_name, unix_path_name;
12156 #ifdef MAC_OSX
12157 FSRef fref;
12158 #endif
12159
12160 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12161 (Ptr) &fs, sizeof (fs), &actual_size);
12162 if (err != noErr) break;
12163
12164 #ifdef MAC_OSX
12165 err = FSpMakeFSRef (&fs, &fref);
12166 if (err != noErr) break;
12167
12168 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
12169 #else
12170 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12171 fs.name) &&
12172 mac_to_posix_pathname (path_name, unix_path_name, 255))
12173 #endif
12174 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12175 drag_and_drop_file_list);
12176 }
12177 }
12178 }
12179
12180 error_exit:
12181 /* Nuke the coerced file list in any case */
12182 err2 = AEDisposeDesc(&the_desc);
12183
12184 descriptor_error_exit:
12185 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12186 return err;
12187 }
12188
12189
12190 /* Print Document Apple Event */
12191 static pascal OSErr
12192 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12193 {
12194 return errAEEventNotHandled;
12195 }
12196
12197
12198 static pascal OSErr
12199 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12200 {
12201 /* FixMe: Do we need an unwind-protect or something here? And what
12202 do we do about unsaved files. Currently just forces quit rather
12203 than doing recursive callback to get user input. */
12204
12205 terminate_flag = true;
12206
12207 /* Fkill_emacs doesn't return. We have to return. (TI) */
12208 return noErr;
12209 }
12210
12211
12212 #if __profile__
12213 void
12214 profiler_exit_proc ()
12215 {
12216 ProfilerDump ("\pEmacs.prof");
12217 ProfilerTerm ();
12218 }
12219 #endif
12220
12221 /* These few functions implement Emacs as a normal Mac application
12222 (almost): set up the heap and the Toolbox, handle necessary
12223 system events plus a few simple menu events. They also set up
12224 Emacs's access to functions defined in the rest of this file.
12225 Emacs uses function hooks to perform all its terminal I/O. A
12226 complete list of these functions appear in termhooks.h. For what
12227 they do, read the comments there and see also w32term.c and
12228 xterm.c. What's noticeably missing here is the event loop, which
12229 is normally present in most Mac application. After performing the
12230 necessary Mac initializations, main passes off control to
12231 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12232 mac_read_socket (defined further below) to read input. This is
12233 where WaitNextEvent is called to process Mac events. This is also
12234 where check_alarm in sysdep.c is called to simulate alarm signals.
12235 This makes the cursor jump back to its correct position after
12236 briefly jumping to that of the matching parenthesis, print useful
12237 hints and prompts in the minibuffer after the user stops typing for
12238 a wait, etc. */
12239
12240 #if !TARGET_API_MAC_CARBON
12241 #undef main
12242 int
12243 main (void)
12244 {
12245 #if __profile__ /* is the profiler on? */
12246 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12247 exit(1);
12248 #endif
12249
12250 #if __MWERKS__
12251 /* set creator and type for files created by MSL */
12252 _fcreator = 'EMAx';
12253 _ftype = 'TEXT';
12254 #endif
12255
12256 do_init_managers ();
12257
12258 do_get_menus ();
12259
12260 do_check_ram_size ();
12261
12262 init_emacs_passwd_dir ();
12263
12264 init_environ ();
12265
12266 initialize_applescript ();
12267
12268 init_required_apple_events ();
12269
12270 {
12271 char **argv;
12272 int argc = 0;
12273
12274 /* set up argv array from STR# resource */
12275 get_string_list (&argv, ARGV_STRING_LIST_ID);
12276 while (argv[argc])
12277 argc++;
12278
12279 /* free up AppleScript resources on exit */
12280 atexit (terminate_applescript);
12281
12282 #if __profile__ /* is the profiler on? */
12283 atexit (profiler_exit_proc);
12284 #endif
12285
12286 /* 3rd param "envp" never used in emacs_main */
12287 (void) emacs_main (argc, argv, 0);
12288 }
12289
12290 /* Never reached - real exit in Fkill_emacs */
12291 return 0;
12292 }
12293 #endif
12294
12295 /* Table for translating Mac keycode to X keysym values. Contributed
12296 by Sudhir Shenoy. */
12297 static unsigned char keycode_to_xkeysym_table[] = {
12298 /* 0x00 - 0x3f */
12299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12302 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12303 /* 0x40 */
12304 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12305 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12306 0, 0, 0, '\xaf' /* kp/ */,
12307 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
12308 /* 0x50 */
12309 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12310 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12311 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12312 '\xb9' /* kp9 */, 0, 0, 0,
12313 /* 0x60 */
12314 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12315 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12316 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12317 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
12318 /* 0x70 */
12319 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12320 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12321 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12322 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
12323 };
12324
12325 static int
12326 keycode_to_xkeysym (int keyCode, int *xKeySym)
12327 {
12328 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12329 return *xKeySym != 0;
12330 }
12331
12332 /* Emacs calls this whenever it wants to read an input event from the
12333 user. */
12334 int
12335 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12336 {
12337 int count = 0;
12338 EventRecord er;
12339 int the_modifiers;
12340 EventMask event_mask;
12341
12342 #if 0
12343 if (interrupt_input_blocked)
12344 {
12345 interrupt_input_pending = 1;
12346 return -1;
12347 }
12348 #endif
12349
12350 interrupt_input_pending = 0;
12351 BLOCK_INPUT;
12352
12353 /* So people can tell when we have read the available input. */
12354 input_signal_count++;
12355
12356 if (numchars <= 0)
12357 abort ();
12358
12359 /* Don't poll for events to process (specifically updateEvt) if
12360 window update currently already in progress. A call to redisplay
12361 (in do_window_update) can be preempted by another call to
12362 redisplay, causing blank regions to be left on the screen and the
12363 cursor to be left at strange places. */
12364 if (handling_window_update)
12365 {
12366 UNBLOCK_INPUT;
12367 return 0;
12368 }
12369
12370 if (terminate_flag)
12371 Fkill_emacs (make_number (1));
12372
12373 /* It is necessary to set this (additional) argument slot of an
12374 event to nil because keyboard.c protects incompletely processed
12375 event from being garbage collected by placing them in the
12376 kbd_buffer_gcpro vector. */
12377 bufp->arg = Qnil;
12378
12379 event_mask = everyEvent;
12380 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
12381 event_mask -= highLevelEventMask;
12382
12383 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
12384 switch (er.what)
12385 {
12386 case mouseDown:
12387 case mouseUp:
12388 {
12389 WindowPtr window_ptr = FrontWindow ();
12390 SInt16 part_code;
12391
12392 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12393 && er.what == mouseUp)
12394 {
12395 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12396 Point mouse_loc = er.where;
12397
12398 /* Convert to local coordinates of new window. */
12399 #if TARGET_API_MAC_CARBON
12400 SetPort (GetWindowPort (window_ptr));
12401 #else
12402 SetPort (window_ptr);
12403 #endif
12404
12405 GlobalToLocal (&mouse_loc);
12406
12407 bufp->code = 0; /* only one mouse button */
12408 bufp->kind = SCROLL_BAR_CLICK_EVENT;
12409 bufp->frame_or_window = tracked_scroll_bar->window;
12410 bufp->part = scroll_bar_handle;
12411 bufp->modifiers = up_modifier;
12412 bufp->timestamp = er.when * (1000 / 60);
12413 /* ticks to milliseconds */
12414
12415 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12416 XSETINT (bufp->y, mouse_loc.v - 24);
12417 tracked_scroll_bar->dragging = Qnil;
12418 mouse_tracking_in_progress = mouse_tracking_none;
12419 tracked_scroll_bar = NULL;
12420 count++;
12421 break;
12422 }
12423
12424 part_code = FindWindow (er.where, &window_ptr);
12425
12426 switch (part_code)
12427 {
12428 case inMenuBar:
12429 {
12430 struct frame *f = ((mac_output *)
12431 GetWRefCon (FrontWindow ()))->mFP;
12432 saved_menu_event_location = er.where;
12433 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
12434 XSETFRAME (bufp->frame_or_window, f);
12435 count++;
12436 }
12437 break;
12438
12439 case inContent:
12440 if (window_ptr != FrontWindow ())
12441 SelectWindow (window_ptr);
12442 else
12443 {
12444 SInt16 control_part_code;
12445 ControlHandle ch;
12446 struct mac_output *mwp = (mac_output *)
12447 GetWRefCon (window_ptr);
12448 Point mouse_loc = er.where;
12449
12450 /* convert to local coordinates of new window */
12451 #if TARGET_API_MAC_CARBON
12452 SetPort (GetWindowPort (window_ptr));
12453 #else
12454 SetPort (window_ptr);
12455 #endif
12456
12457 GlobalToLocal (&mouse_loc);
12458 #if TARGET_API_MAC_CARBON
12459 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12460 &control_part_code);
12461 #else
12462 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
12463 #endif
12464 bufp->code = 0; /* only one mouse button */
12465 XSETINT (bufp->x, mouse_loc.h);
12466 XSETINT (bufp->y, mouse_loc.v);
12467 bufp->timestamp = er.when * (1000 / 60);
12468 /* ticks to milliseconds */
12469
12470 #if TARGET_API_MAC_CARBON
12471 if (ch != 0)
12472 #else
12473 if (control_part_code != 0)
12474 #endif
12475 {
12476 struct scroll_bar *bar = (struct scroll_bar *)
12477 GetControlReference (ch);
12478 x_scroll_bar_handle_click (bar, control_part_code, &er,
12479 bufp);
12480 if (er.what == mouseDown
12481 && control_part_code == kControlIndicatorPart)
12482 {
12483 mouse_tracking_in_progress
12484 = mouse_tracking_scroll_bar;
12485 tracked_scroll_bar = bar;
12486 }
12487 else
12488 {
12489 mouse_tracking_in_progress = mouse_tracking_none;
12490 tracked_scroll_bar = NULL;
12491 }
12492 }
12493 else
12494 {
12495 bufp->kind = MOUSE_CLICK_EVENT;
12496 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12497 if (er.what == mouseDown)
12498 mouse_tracking_in_progress
12499 = mouse_tracking_mouse_movement;
12500 else
12501 mouse_tracking_in_progress = mouse_tracking_none;
12502 }
12503
12504 switch (er.what)
12505 {
12506 case mouseDown:
12507 bufp->modifiers = down_modifier;
12508 break;
12509 case mouseUp:
12510 bufp->modifiers = up_modifier;
12511 break;
12512 }
12513
12514 count++;
12515 }
12516 break;
12517
12518 case inDrag:
12519 #if TARGET_API_MAC_CARBON
12520 {
12521 BitMap bm;
12522
12523 GetQDGlobalsScreenBits (&bm);
12524 DragWindow (window_ptr, er.where, &bm.bounds);
12525 }
12526 #else /* not TARGET_API_MAC_CARBON */
12527 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12528 #endif /* not TARGET_API_MAC_CARBON */
12529 break;
12530
12531 case inGoAway:
12532 if (TrackGoAway (window_ptr, er.where))
12533 {
12534 bufp->kind = DELETE_WINDOW_EVENT;
12535 XSETFRAME (bufp->frame_or_window,
12536 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12537 count++;
12538 }
12539 break;
12540
12541 /* window resize handling added --ben */
12542 case inGrow:
12543 do_grow_window(window_ptr, &er);
12544 break;
12545
12546 /* window zoom handling added --ben */
12547 case inZoomIn:
12548 case inZoomOut:
12549 if (TrackBox (window_ptr, er.where, part_code))
12550 do_zoom_window (window_ptr, part_code);
12551 break;
12552
12553 default:
12554 break;
12555 }
12556 }
12557 break;
12558
12559 case updateEvt:
12560 case osEvt:
12561 case activateEvt:
12562 do_events (&er);
12563 break;
12564
12565 case keyDown:
12566 case autoKey:
12567 {
12568 int keycode = (er.message & keyCodeMask) >> 8;
12569 int xkeysym;
12570
12571 ObscureCursor ();
12572
12573 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12574 {
12575 bufp->code = 0x7f;
12576 bufp->kind = ASCII_KEYSTROKE_EVENT;
12577 }
12578 else if (keycode_to_xkeysym (keycode, &xkeysym))
12579 {
12580 bufp->code = 0xff00 | xkeysym;
12581 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
12582 }
12583 else
12584 {
12585 if (er.modifiers
12586 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12587 {
12588 /* This code comes from Keyboard Resource, Appendix
12589 C of IM - Text. This is necessary since shift is
12590 ignored in KCHR table translation when option or
12591 command is pressed. */
12592 int new_modifiers = er.modifiers & 0xf600;
12593 /* mask off option and command */
12594 int new_keycode = keycode | new_modifiers;
12595 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12596 unsigned long some_state = 0;
12597 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12598 &some_state) & 0xff;
12599 }
12600 else
12601 bufp->code = er.message & charCodeMask;
12602 bufp->kind = ASCII_KEYSTROKE_EVENT;
12603 }
12604 }
12605
12606 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12607 convert non-ASCII characters typed at the Mac keyboard
12608 (presumed to be in the Mac Roman encoding) to iso-latin-1
12609 encoding before they are passed to Emacs. This enables the
12610 Mac keyboard to be used to enter non-ASCII iso-latin-1
12611 characters directly. */
12612 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
12613 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
12614 {
12615 static TECObjectRef converter = NULL;
12616 OSStatus the_err = noErr;
12617 OSStatus convert_status = noErr;
12618
12619 if (converter == NULL)
12620 {
12621 the_err = TECCreateConverter (&converter,
12622 kTextEncodingMacRoman,
12623 mac_keyboard_text_encoding);
12624 current_mac_keyboard_text_encoding
12625 = mac_keyboard_text_encoding;
12626 }
12627 else if (mac_keyboard_text_encoding
12628 != current_mac_keyboard_text_encoding)
12629 {
12630 /* Free the converter for the current encoding before
12631 creating a new one. */
12632 TECDisposeConverter (converter);
12633 the_err = TECCreateConverter (&converter,
12634 kTextEncodingMacRoman,
12635 mac_keyboard_text_encoding);
12636 current_mac_keyboard_text_encoding
12637 = mac_keyboard_text_encoding;
12638 }
12639
12640 if (the_err == noErr)
12641 {
12642 unsigned char ch = bufp->code;
12643 ByteCount actual_input_length, actual_output_length;
12644 unsigned char outch;
12645
12646 convert_status = TECConvertText (converter, &ch, 1,
12647 &actual_input_length,
12648 &outch, 1,
12649 &actual_output_length);
12650 if (convert_status == noErr
12651 && actual_input_length == 1
12652 && actual_output_length == 1)
12653 bufp->code = outch;
12654 }
12655 }
12656
12657 the_modifiers = 0;
12658 if (er.modifiers & shiftKey)
12659 the_modifiers |= shift_modifier;
12660 if (er.modifiers & controlKey)
12661 the_modifiers |= ctrl_modifier;
12662 /* Use option or command key as meta depending on value of
12663 mac-command-key-is-meta. */
12664 if (er.modifiers
12665 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12666 the_modifiers |= meta_modifier;
12667
12668 /* If the Mac option key is meta, then make Emacs recognize
12669 the Mac command key as alt. */
12670 if (NILP (Vmac_command_key_is_meta) && (er.modifiers & cmdKey))
12671 the_modifiers |= alt_modifier;
12672
12673 bufp->modifiers = the_modifiers;
12674
12675 {
12676 mac_output *mwp
12677 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
12678 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12679 }
12680
12681 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
12682
12683 count++;
12684 break;
12685
12686 case kHighLevelEvent:
12687 drag_and_drop_file_list = Qnil;
12688
12689 AEProcessAppleEvent(&er);
12690
12691 /* Build a DRAG_N_DROP_EVENT type event as is done in
12692 constuct_drag_n_drop in w32term.c. */
12693 if (!NILP (drag_and_drop_file_list))
12694 {
12695 struct frame *f;
12696 WindowPtr wp;
12697 Lisp_Object frame;
12698
12699 wp = FrontWindow ();
12700 if (!wp)
12701 f = NULL;
12702 else
12703 f = ((mac_output *) GetWRefCon (wp))->mFP;
12704
12705 bufp->kind = DRAG_N_DROP_EVENT;
12706 bufp->code = 0;
12707 bufp->timestamp = er.when * (1000 / 60);
12708 /* ticks to milliseconds */
12709 bufp->modifiers = 0;
12710
12711 XSETINT (bufp->x, 0);
12712 XSETINT (bufp->y, 0);
12713
12714 XSETFRAME (frame, f);
12715 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
12716
12717 /* Regardless of whether Emacs was suspended or in the
12718 foreground, ask it to redraw its entire screen.
12719 Otherwise parts of the screen can be left in an
12720 inconsistent state. */
12721 if (wp)
12722 #if TARGET_API_MAC_CARBON
12723 {
12724 Rect r;
12725
12726 GetWindowPortBounds (wp, &r);
12727 InvalWindowRect (wp, &r);
12728 }
12729 #else /* not TARGET_API_MAC_CARBON */
12730 InvalRect (&(wp->portRect));
12731 #endif /* not TARGET_API_MAC_CARBON */
12732
12733 count++;
12734 }
12735
12736 default:
12737 break;
12738 }
12739
12740 /* If the focus was just given to an autoraising frame,
12741 raise it now. */
12742 /* ??? This ought to be able to handle more than one such frame. */
12743 if (pending_autoraise_frame)
12744 {
12745 x_raise_frame (pending_autoraise_frame);
12746 pending_autoraise_frame = 0;
12747 }
12748
12749 #if !TARGET_API_MAC_CARBON
12750 check_alarm (); /* simulate the handling of a SIGALRM */
12751 #endif
12752
12753 {
12754 static Point old_mouse_pos = { -1, -1 };
12755
12756 if (app_is_suspended)
12757 {
12758 old_mouse_pos.h = -1;
12759 old_mouse_pos.v = -1;
12760 }
12761 else
12762 {
12763 Point mouse_pos;
12764 WindowPtr wp;
12765 struct frame *f;
12766 Lisp_Object bar;
12767 struct scroll_bar *sb;
12768
12769 wp = FrontWindow ();
12770 if (is_emacs_window (wp))
12771 {
12772 f = ((mac_output *) GetWRefCon (wp))->mFP;
12773
12774 #if TARGET_API_MAC_CARBON
12775 SetPort (GetWindowPort (wp));
12776 #else
12777 SetPort (wp);
12778 #endif
12779
12780 GetMouse (&mouse_pos);
12781
12782 if (!EqualPt (mouse_pos, old_mouse_pos))
12783 {
12784 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12785 && tracked_scroll_bar)
12786 x_scroll_bar_note_movement (tracked_scroll_bar,
12787 mouse_pos.v
12788 - XINT (tracked_scroll_bar->top),
12789 TickCount() * (1000 / 60));
12790 else
12791 note_mouse_movement (f, &mouse_pos);
12792
12793 old_mouse_pos = mouse_pos;
12794 }
12795 }
12796 }
12797 }
12798
12799 UNBLOCK_INPUT;
12800
12801 return count;
12802 }
12803
12804
12805 /* Need to override CodeWarrior's input function so no conversion is
12806 done on newlines Otherwise compiled functions in .elc files will be
12807 read incorrectly. Defined in ...:MSL C:MSL
12808 Common:Source:buffer_io.c. */
12809 #ifdef __MWERKS__
12810 void
12811 __convert_to_newlines (unsigned char * p, size_t * n)
12812 {
12813 #pragma unused(p,n)
12814 }
12815
12816 void
12817 __convert_from_newlines (unsigned char * p, size_t * n)
12818 {
12819 #pragma unused(p,n)
12820 }
12821 #endif
12822
12823
12824 /* Initialize the struct pointed to by MW to represent a new COLS x
12825 ROWS Macintosh window, using font with name FONTNAME and size
12826 FONTSIZE. */
12827 void
12828 NewMacWindow (FRAME_PTR fp)
12829 {
12830 mac_output *mwp;
12831 #if TARGET_API_MAC_CARBON
12832 static int making_terminal_window = 0;
12833 #else
12834 static int making_terminal_window = 1;
12835 #endif
12836
12837 mwp = fp->output_data.mac;
12838
12839 if (making_terminal_window)
12840 {
12841 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
12842 (WindowPtr) -1)))
12843 abort ();
12844 making_terminal_window = 0;
12845 }
12846 else
12847 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
12848 abort ();
12849
12850
12851 SetWRefCon (mwp->mWP, (long) mwp);
12852 /* so that update events can find this mac_output struct */
12853 mwp->mFP = fp; /* point back to emacs frame */
12854
12855 #if TARGET_API_MAC_CARBON
12856 SetPort (GetWindowPort (mwp->mWP));
12857 #else
12858 SetPort (mwp->mWP);
12859 #endif
12860
12861 mwp->fontset = -1;
12862
12863 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
12864 ShowWindow (mwp->mWP);
12865
12866 }
12867
12868
12869 void make_mac_frame (struct frame *f)
12870 {
12871 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
12872 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
12873
12874 NewMacWindow(f);
12875
12876 f->output_data.mac->cursor_pixel = 0;
12877 f->output_data.mac->border_pixel = 0x00ff00;
12878 f->output_data.mac->mouse_pixel = 0xff00ff;
12879 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
12880
12881 f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
12882
12883 f->output_data.mac->fontset = -1;
12884 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12885 f->output_data.mac->scroll_bar_background_pixel = -1;
12886 f->output_data.mac->left_pos = 4;
12887 f->output_data.mac->top_pos = 4;
12888 f->output_data.mac->border_width = 0;
12889 f->output_data.mac->explicit_parent = 0;
12890
12891 f->output_data.mac->internal_border_width = 0;
12892
12893 f->output_method = output_mac;
12894
12895 f->auto_raise = 1;
12896 f->auto_lower = 1;
12897
12898 f->new_width = 0;
12899 f->new_height = 0;
12900 }
12901
12902 void make_mac_terminal_frame (struct frame *f)
12903 {
12904 Lisp_Object frame;
12905
12906 XSETFRAME (frame, f);
12907
12908 f->output_method = output_mac;
12909 f->output_data.mac = (struct mac_output *)
12910 xmalloc (sizeof (struct mac_output));
12911 bzero (f->output_data.mac, sizeof (struct mac_output));
12912 f->output_data.mac->fontset = -1;
12913 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12914 f->output_data.mac->scroll_bar_background_pixel = -1;
12915
12916 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
12917
12918 f->width = 96;
12919 f->height = 4;
12920
12921 make_mac_frame (f);
12922
12923 x_make_gc (f);
12924
12925 /* Need to be initialized for unshow_buffer in window.c. */
12926 selected_window = f->selected_window;
12927
12928 Fmodify_frame_parameters (frame,
12929 Fcons (Fcons (Qfont,
12930 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
12931 Fmodify_frame_parameters (frame,
12932 Fcons (Fcons (Qforeground_color,
12933 build_string ("black")), Qnil));
12934 Fmodify_frame_parameters (frame,
12935 Fcons (Fcons (Qbackground_color,
12936 build_string ("white")), Qnil));
12937 }
12938
12939 \f
12940 /***********************************************************************
12941 Initialization
12942 ***********************************************************************/
12943
12944 #ifdef USE_X_TOOLKIT
12945 static XrmOptionDescRec emacs_options[] = {
12946 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12947 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12948
12949 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12950 XrmoptionSepArg, NULL},
12951 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12952
12953 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12954 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12955 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12956 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12957 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12958 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12959 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12960 };
12961 #endif /* USE_X_TOOLKIT */
12962
12963 #ifdef MULTI_KBOARD
12964 /* Test whether two display-name strings agree up to the dot that separates
12965 the screen number from the server number. */
12966 static int
12967 same_x_server (name1, name2)
12968 char *name1, *name2;
12969 {
12970 int seen_colon = 0;
12971 unsigned char *system_name = SDATA (Vsystem_name);
12972 int system_name_length = strlen (system_name);
12973 int length_until_period = 0;
12974
12975 while (system_name[length_until_period] != 0
12976 && system_name[length_until_period] != '.')
12977 length_until_period++;
12978
12979 /* Treat `unix' like an empty host name. */
12980 if (! strncmp (name1, "unix:", 5))
12981 name1 += 4;
12982 if (! strncmp (name2, "unix:", 5))
12983 name2 += 4;
12984 /* Treat this host's name like an empty host name. */
12985 if (! strncmp (name1, system_name, system_name_length)
12986 && name1[system_name_length] == ':')
12987 name1 += system_name_length;
12988 if (! strncmp (name2, system_name, system_name_length)
12989 && name2[system_name_length] == ':')
12990 name2 += system_name_length;
12991 /* Treat this host's domainless name like an empty host name. */
12992 if (! strncmp (name1, system_name, length_until_period)
12993 && name1[length_until_period] == ':')
12994 name1 += length_until_period;
12995 if (! strncmp (name2, system_name, length_until_period)
12996 && name2[length_until_period] == ':')
12997 name2 += length_until_period;
12998
12999 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13000 {
13001 if (*name1 == ':')
13002 seen_colon++;
13003 if (seen_colon && *name1 == '.')
13004 return 1;
13005 }
13006 return (seen_colon
13007 && (*name1 == '.' || *name1 == '\0')
13008 && (*name2 == '.' || *name2 == '\0'));
13009 }
13010 #endif
13011
13012 int mac_initialized = 0;
13013
13014 void
13015 mac_initialize_display_info ()
13016 {
13017 struct mac_display_info *dpyinfo = &one_mac_display_info;
13018 GDHandle main_device_handle;
13019
13020 bzero (dpyinfo, sizeof (*dpyinfo));
13021
13022 /* Put it on x_display_name_list. */
13023 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
13024 x_display_name_list);
13025 dpyinfo->name_list_element = XCAR (x_display_name_list);
13026
13027 #if 0
13028 dpyinfo->mac_id_name
13029 = (char *) xmalloc (SCHARS (Vinvocation_name)
13030 + SCHARS (Vsystem_name)
13031 + 2);
13032 sprintf (dpyinfo->mac_id_name, "%s@%s",
13033 SDATA (Vinvocation_name), SDATA (Vsystem_name));
13034 #else
13035 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
13036 strcpy (dpyinfo->mac_id_name, "Mac Display");
13037 #endif
13038
13039 main_device_handle = LMGetMainDevice();
13040
13041 dpyinfo->reference_count = 0;
13042 dpyinfo->resx = 75.0;
13043 dpyinfo->resy = 75.0;
13044 dpyinfo->n_planes = 1;
13045 dpyinfo->n_cbits = 16;
13046 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13047 dpyinfo->width = (**main_device_handle).gdRect.right;
13048 dpyinfo->grabbed = 0;
13049 dpyinfo->root_window = NULL;
13050
13051 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13052 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13053 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13054 dpyinfo->mouse_face_window = Qnil;
13055 }
13056
13057 struct mac_display_info *
13058 mac_term_init (display_name, xrm_option, resource_name)
13059 Lisp_Object display_name;
13060 char *xrm_option;
13061 char *resource_name;
13062 {
13063 struct mac_display_info *dpyinfo;
13064 GDHandle main_device_handle;
13065
13066 if (!mac_initialized)
13067 {
13068 mac_initialize ();
13069 mac_initialized = 1;
13070 }
13071
13072 mac_initialize_display_info (display_name);
13073
13074 dpyinfo = &one_mac_display_info;
13075
13076 main_device_handle = LMGetMainDevice();
13077
13078 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13079 dpyinfo->width = (**main_device_handle).gdRect.right;
13080
13081 return dpyinfo;
13082 }
13083 \f
13084 /* Set up use of X before we make the first connection. */
13085
13086 static struct redisplay_interface x_redisplay_interface =
13087 {
13088 x_produce_glyphs,
13089 x_write_glyphs,
13090 x_insert_glyphs,
13091 x_clear_end_of_line,
13092 x_scroll_run,
13093 x_after_update_window_line,
13094 x_update_window_begin,
13095 x_update_window_end,
13096 XTcursor_to,
13097 x_flush,
13098 x_clear_mouse_face,
13099 x_get_glyph_overhangs,
13100 x_fix_overlapping_area
13101 };
13102
13103 void
13104 mac_initialize ()
13105 {
13106 rif = &x_redisplay_interface;
13107
13108 clear_frame_hook = x_clear_frame;
13109 ins_del_lines_hook = x_ins_del_lines;
13110 delete_glyphs_hook = x_delete_glyphs;
13111 ring_bell_hook = XTring_bell;
13112 reset_terminal_modes_hook = XTreset_terminal_modes;
13113 set_terminal_modes_hook = XTset_terminal_modes;
13114 update_begin_hook = x_update_begin;
13115 update_end_hook = x_update_end;
13116 set_terminal_window_hook = XTset_terminal_window;
13117 read_socket_hook = XTread_socket;
13118 frame_up_to_date_hook = XTframe_up_to_date;
13119 mouse_position_hook = XTmouse_position;
13120 frame_rehighlight_hook = XTframe_rehighlight;
13121 frame_raise_lower_hook = XTframe_raise_lower;
13122
13123 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13124 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13125 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13126 judge_scroll_bars_hook = XTjudge_scroll_bars;
13127
13128 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13129
13130 scroll_region_ok = 1; /* we'll scroll partial frames */
13131 char_ins_del_ok = 1;
13132 line_ins_del_ok = 1; /* we'll just blt 'em */
13133 fast_clear_end_of_line = 1; /* X does this well */
13134 memory_below_frame = 0; /* we don't remember what scrolls
13135 off the bottom */
13136 baud_rate = 19200;
13137
13138 x_noop_count = 0;
13139 last_tool_bar_item = -1;
13140 any_help_event_p = 0;
13141
13142 /* Try to use interrupt input; if we can't, then start polling. */
13143 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13144
13145 #ifdef USE_X_TOOLKIT
13146 XtToolkitInitialize ();
13147 Xt_app_con = XtCreateApplicationContext ();
13148 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13149
13150 /* Install an asynchronous timer that processes Xt timeout events
13151 every 0.1s. This is necessary because some widget sets use
13152 timeouts internally, for example the LessTif menu bar, or the
13153 Xaw3d scroll bar. When Xt timouts aren't processed, these
13154 widgets don't behave normally. */
13155 {
13156 EMACS_TIME interval;
13157 EMACS_SET_SECS_USECS (interval, 0, 100000);
13158 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13159 }
13160 #endif
13161
13162 #if USE_TOOLKIT_SCROLL_BARS
13163 xaw3d_arrow_scroll = False;
13164 xaw3d_pick_top = True;
13165 #endif
13166
13167 #if 0
13168 /* Note that there is no real way portable across R3/R4 to get the
13169 original error handler. */
13170 XSetErrorHandler (x_error_handler);
13171 XSetIOErrorHandler (x_io_error_quitter);
13172
13173 /* Disable Window Change signals; they are handled by X events. */
13174 #ifdef SIGWINCH
13175 signal (SIGWINCH, SIG_DFL);
13176 #endif /* ! defined (SIGWINCH) */
13177
13178 signal (SIGPIPE, x_connection_signal);
13179 #endif
13180
13181 mac_initialize_display_info ();
13182
13183 #if TARGET_API_MAC_CARBON
13184 init_required_apple_events ();
13185
13186 DisableMenuCommand (NULL, kHICommandQuit);
13187 #endif
13188 }
13189
13190
13191 void
13192 syms_of_macterm ()
13193 {
13194 #if 0
13195 staticpro (&x_error_message_string);
13196 x_error_message_string = Qnil;
13197 #endif
13198
13199 staticpro (&x_display_name_list);
13200 x_display_name_list = Qnil;
13201
13202 staticpro (&last_mouse_scroll_bar);
13203 last_mouse_scroll_bar = Qnil;
13204
13205 staticpro (&Qvendor_specific_keysyms);
13206 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13207
13208 staticpro (&last_mouse_press_frame);
13209 last_mouse_press_frame = Qnil;
13210
13211 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13212 staticpro (&Qmac_ready_for_drag_n_drop);
13213
13214 help_echo = Qnil;
13215 staticpro (&help_echo);
13216 help_echo_object = Qnil;
13217 staticpro (&help_echo_object);
13218 help_echo_window = Qnil;
13219 staticpro (&help_echo_window);
13220 previous_help_echo = Qnil;
13221 staticpro (&previous_help_echo);
13222 help_echo_pos = -1;
13223
13224 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13225 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13226 x_autoselect_window_p = 0;
13227
13228 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13229 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13230 For example, if a block cursor is over a tab, it will be drawn as
13231 wide as that tab on the display. */);
13232 x_stretch_cursor_p = 0;
13233
13234 #if 0 /* TODO: Setting underline position from font properties. */
13235 DEFVAR_BOOL ("x-use-underline-position-properties",
13236 &x_use_underline_position_properties,
13237 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13238 nil means ignore them. If you encounter fonts with bogus
13239 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13240 to 4.1, set this to nil. */);
13241 x_use_underline_position_properties = 1;
13242 #endif
13243
13244 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13245 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13246 Vx_toolkit_scroll_bars = Qt;
13247
13248 staticpro (&last_mouse_motion_frame);
13249 last_mouse_motion_frame = Qnil;
13250
13251 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
13252 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13253 Otherwise the option key is used. */);
13254 Vmac_command_key_is_meta = Qt;
13255
13256 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
13257 doc: /* One of the Text Encoding Base constant values defined in the
13258 Basic Text Constants section of Inside Macintosh - Text Encoding
13259 Conversion Manager. Its value determines the encoding characters
13260 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13261 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13262 its default value, no conversion takes place. If it is set to
13263 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13264 characters typed on Mac keyboard are first converted into the
13265 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13266 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13267 command, this enables the Mac keyboard to be used to enter non-ASCII
13268 characters directly. */);
13269 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13270 }