]> code.delx.au - gnu-emacs/blob - src/macterm.c
Rename enum event_kind items.
[gnu-emacs] / src / macterm.c
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
22
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "lisp.h"
28 #include "charset.h"
29 #include "blockinput.h"
30
31 #include "macterm.h"
32
33 #ifndef MAC_OSX
34 #include <alloca.h>
35 #endif
36
37 #ifdef MAC_OSX
38 #undef mktime
39 #undef DEBUG
40 #undef free
41 #undef malloc
42 #undef realloc
43 /* Macros max and min defined in lisp.h conflict with those in
44 precompiled header Carbon.h. */
45 #undef max
46 #undef min
47 #include <Carbon/Carbon.h>
48 #undef free
49 #define free unexec_free
50 #undef malloc
51 #define malloc unexec_malloc
52 #undef realloc
53 #define realloc unexec_realloc
54 #undef min
55 #define min(a, b) ((a) < (b) ? (a) : (b))
56 #undef max
57 #define max(a, b) ((a) > (b) ? (a) : (b))
58 #else /* not MAC_OSX */
59 #include <Quickdraw.h>
60 #include <ToolUtils.h>
61 #include <Sound.h>
62 #include <Events.h>
63 #include <Script.h>
64 #include <Resources.h>
65 #include <Fonts.h>
66 #include <TextUtils.h>
67 #include <LowMem.h>
68 #include <Controls.h>
69 #if defined (__MRC__) || (__MSL__ >= 0x6000)
70 #include <ControlDefinitions.h>
71 #endif
72 #include <Gestalt.h>
73
74 #if __profile__
75 #include <profiler.h>
76 #endif
77 #endif /* not MAC_OSX */
78
79 #include "systty.h"
80 #include "systime.h"
81 #include "atimer.h"
82 #include "keymap.h"
83
84 #include <ctype.h>
85 #include <errno.h>
86 #include <setjmp.h>
87 #include <sys/stat.h>
88
89 #include "keyboard.h"
90 #include "frame.h"
91 #include "dispextern.h"
92 #include "fontset.h"
93 #include "termhooks.h"
94 #include "termopts.h"
95 #include "termchar.h"
96 #include "gnu.h"
97 #include "disptab.h"
98 #include "buffer.h"
99 #include "window.h"
100 #include "intervals.h"
101 #include "composite.h"
102 #include "coding.h"
103
104 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
105
106 \f
107 /* Fringe bitmaps. */
108
109 enum fringe_bitmap_type
110 {
111 NO_FRINGE_BITMAP,
112 LEFT_TRUNCATION_BITMAP,
113 RIGHT_TRUNCATION_BITMAP,
114 OVERLAY_ARROW_BITMAP,
115 CONTINUED_LINE_BITMAP,
116 CONTINUATION_LINE_BITMAP,
117 ZV_LINE_BITMAP
118 };
119
120 /* Bitmap drawn to indicate lines not displaying text if
121 `indicate-empty-lines' is non-nil. */
122
123 #define zv_width 8
124 #define zv_height 72
125 #define zv_period 3
126 static unsigned char zv_bits[] = {
127 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
128 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
129 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
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
136 /* An arrow like this: `<-'. */
137
138 #define left_width 8
139 #define left_height 8
140 static unsigned char left_bits[] = {
141 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
142
143 /* Right truncation arrow bitmap `->'. */
144
145 #define right_width 8
146 #define right_height 8
147 static unsigned char right_bits[] = {
148 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
149
150 /* Marker for continued lines. */
151
152 #define continued_width 8
153 #define continued_height 8
154 static unsigned char continued_bits[] = {
155 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
156
157 /* Marker for continuation lines. */
158
159 #define continuation_width 8
160 #define continuation_height 8
161 static unsigned char continuation_bits[] = {
162 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
163
164 /* Overlay arrow bitmap. */
165
166 #if 0
167 /* A bomb. */
168 #define ov_width 8
169 #define ov_height 8
170 static unsigned char ov_bits[] = {
171 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
172 #else
173 /* A triangular arrow. */
174 #define ov_width 8
175 #define ov_height 8
176 static unsigned char ov_bits[] = {
177 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
178 #endif
179
180 extern Lisp_Object Qhelp_echo;
181
182 \f
183 /* Non-nil means Emacs uses toolkit scroll bars. */
184
185 Lisp_Object Vx_toolkit_scroll_bars;
186
187 /* If a string, XTread_socket generates an event to display that string.
188 (The display is done in read_char.) */
189
190 static Lisp_Object help_echo;
191 static Lisp_Object help_echo_window;
192 static Lisp_Object help_echo_object;
193 static int help_echo_pos;
194
195 /* Temporary variable for XTread_socket. */
196
197 static Lisp_Object previous_help_echo;
198
199 /* Non-zero means that a HELP_EVENT has been generated since Emacs
200 start. */
201
202 static int any_help_event_p;
203
204 /* Non-zero means autoselect window with the mouse cursor. */
205
206 int x_autoselect_window_p;
207
208 /* Non-zero means draw block and hollow cursor as wide as the glyph
209 under it. For example, if a block cursor is over a tab, it will be
210 drawn as wide as that tab on the display. */
211
212 int x_stretch_cursor_p;
213
214 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
215
216 int x_use_underline_position_properties;
217
218 /* This is a chain of structures for all the X displays currently in
219 use. */
220
221 struct x_display_info *x_display_list;
222
223 /* This is a list of cons cells, each of the form (NAME
224 . FONT-LIST-CACHE), one for each element of x_display_list and in
225 the same order. NAME is the name of the frame. FONT-LIST-CACHE
226 records previous values returned by x-list-fonts. */
227
228 Lisp_Object x_display_name_list;
229
230 /* This is display since Mac does not support multiple ones. */
231 struct mac_display_info one_mac_display_info;
232
233 /* Frame being updated by update_frame. This is declared in term.c.
234 This is set by update_begin and looked at by all the XT functions.
235 It is zero while not inside an update. In that case, the XT
236 functions assume that `selected_frame' is the frame to apply to. */
237
238 extern struct frame *updating_frame;
239
240 extern int waiting_for_input;
241
242 /* This is a frame waiting to be auto-raised, within XTread_socket. */
243
244 struct frame *pending_autoraise_frame;
245
246 /* Nominal cursor position -- where to draw output.
247 HPOS and VPOS are window relative glyph matrix coordinates.
248 X and Y are window relative pixel coordinates. */
249
250 struct cursor_pos output_cursor;
251
252 /* Non-zero means user is interacting with a toolkit scroll bar. */
253
254 static int toolkit_scroll_bar_interaction;
255
256 /* Mouse movement.
257
258 Formerly, we used PointerMotionHintMask (in standard_event_mask)
259 so that we would have to call XQueryPointer after each MotionNotify
260 event to ask for another such event. However, this made mouse tracking
261 slow, and there was a bug that made it eventually stop.
262
263 Simply asking for MotionNotify all the time seems to work better.
264
265 In order to avoid asking for motion events and then throwing most
266 of them away or busy-polling the server for mouse positions, we ask
267 the server for pointer motion hints. This means that we get only
268 one event per group of mouse movements. "Groups" are delimited by
269 other kinds of events (focus changes and button clicks, for
270 example), or by XQueryPointer calls; when one of these happens, we
271 get another MotionNotify event the next time the mouse moves. This
272 is at least as efficient as getting motion events when mouse
273 tracking is on, and I suspect only negligibly worse when tracking
274 is off. */
275
276 /* Where the mouse was last time we reported a mouse event. */
277
278 FRAME_PTR last_mouse_frame;
279 static Rect last_mouse_glyph;
280 static Lisp_Object last_mouse_press_frame;
281
282 /* The scroll bar in which the last X motion event occurred.
283
284 If the last X motion event occurred in a scroll bar, we set this so
285 XTmouse_position can know whether to report a scroll bar motion or
286 an ordinary motion.
287
288 If the last X motion event didn't occur in a scroll bar, we set
289 this to Qnil, to tell XTmouse_position to return an ordinary motion
290 event. */
291
292 static Lisp_Object last_mouse_scroll_bar;
293
294 /* This is a hack. We would really prefer that XTmouse_position would
295 return the time associated with the position it returns, but there
296 doesn't seem to be any way to wrest the time-stamp from the server
297 along with the position query. So, we just keep track of the time
298 of the last movement we received, and return that in hopes that
299 it's somewhat accurate. */
300
301 static Time last_mouse_movement_time;
302
303 enum mouse_tracking_type {
304 mouse_tracking_none,
305 mouse_tracking_mouse_movement,
306 mouse_tracking_scroll_bar
307 };
308
309 enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
310
311 struct scroll_bar *tracked_scroll_bar = NULL;
312
313 /* Incremented by XTread_socket whenever it really tries to read
314 events. */
315
316 #ifdef __STDC__
317 static int volatile input_signal_count;
318 #else
319 static int input_signal_count;
320 #endif
321
322 /* Used locally within XTread_socket. */
323
324 static int x_noop_count;
325
326 /* Initial values of argv and argc. */
327
328 extern char **initial_argv;
329 extern int initial_argc;
330
331 extern Lisp_Object Vcommand_line_args, Vsystem_name;
332
333 /* Tells if a window manager is present or not. */
334
335 extern Lisp_Object Vx_no_window_manager;
336
337 extern Lisp_Object Qface, Qmouse_face;
338
339 extern int errno;
340
341 /* A mask of extra modifier bits to put into every keyboard char. */
342
343 extern int extra_keyboard_modifiers;
344
345 static Lisp_Object Qvendor_specific_keysyms;
346
347 #if 0
348 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
349 #endif
350
351 extern Lisp_Object x_icon_type P_ ((struct frame *));
352
353
354 #if __MRC__
355 QDGlobals qd; /* QuickDraw global information structure. */
356 #endif
357
358
359 /* Enumeration for overriding/changing the face to use for drawing
360 glyphs in x_draw_glyphs. */
361
362 enum draw_glyphs_face
363 {
364 DRAW_NORMAL_TEXT,
365 DRAW_INVERSE_VIDEO,
366 DRAW_CURSOR,
367 DRAW_MOUSE_FACE,
368 DRAW_IMAGE_RAISED,
369 DRAW_IMAGE_SUNKEN
370 };
371
372 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
373 struct mac_display_info *mac_display_info_for_display (Display *);
374 static void x_update_window_end P_ ((struct window *, int, int));
375 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
376 static int fast_find_position P_ ((struct window *, int, int *, int *,
377 int *, int *, Lisp_Object));
378 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
379 int *, int *, int *, int *, int));
380 static void set_output_cursor P_ ((struct cursor_pos *));
381 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
382 int *, int *, int *, int));
383 static void note_mode_line_highlight P_ ((struct window *, int, int));
384 static void note_mouse_highlight P_ ((struct frame *, int, int));
385 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
386 static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
387 static void show_mouse_face P_ ((struct x_display_info *,
388 enum draw_glyphs_face));
389 static int cursor_in_mouse_face_p P_ ((struct window *));
390 static int clear_mouse_face P_ ((struct mac_display_info *));
391 static int x_io_error_quitter P_ ((Display *));
392 int x_catch_errors P_ ((Display *));
393 void x_uncatch_errors P_ ((Display *, int));
394 void x_lower_frame P_ ((struct frame *));
395 void x_scroll_bar_clear P_ ((struct frame *));
396 int x_had_errors_p P_ ((Display *));
397 void x_wm_set_size_hint P_ ((struct frame *, long, int));
398 void x_raise_frame P_ ((struct frame *));
399 void x_set_window_size P_ ((struct frame *, int, int, int));
400 void x_wm_set_window_state P_ ((struct frame *, int));
401 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
402 void mac_initialize P_ ((void));
403 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
404 static int x_compute_min_glyph_bounds P_ ((struct frame *));
405 enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
406 static void x_draw_phys_cursor_glyph P_ ((struct window *,
407 struct glyph_row *,
408 enum draw_glyphs_face));
409 static void x_update_end P_ ((struct frame *));
410 static void XTframe_up_to_date P_ ((struct frame *));
411 static void XTreassert_line_highlight P_ ((int, int));
412 static void x_change_line_highlight P_ ((int, int, int, int));
413 static void XTset_terminal_modes P_ ((void));
414 static void XTreset_terminal_modes P_ ((void));
415 static void XTcursor_to P_ ((int, int, int, int));
416 static void x_write_glyphs P_ ((struct glyph *, int));
417 static void x_clear_end_of_line P_ ((int));
418 static void x_clear_frame P_ ((void));
419 static void x_clear_cursor P_ ((struct window *));
420 static void frame_highlight P_ ((struct frame *));
421 static void frame_unhighlight P_ ((struct frame *));
422 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
423 static void XTframe_rehighlight P_ ((struct frame *));
424 static void x_frame_rehighlight P_ ((struct x_display_info *));
425 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
426 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
427 static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
428 static void expose_frame P_ ((struct frame *, int, int, int, int));
429 static int expose_window_tree P_ ((struct window *, Rect *));
430 static int expose_window P_ ((struct window *, Rect *));
431 static void expose_area P_ ((struct window *, struct glyph_row *,
432 Rect *, enum glyph_row_area));
433 static int expose_line P_ ((struct window *, struct glyph_row *,
434 Rect *));
435 void x_display_cursor (struct window *, int, int, int, int, int);
436 void x_update_cursor P_ ((struct frame *, int));
437 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
438 static void x_update_window_cursor P_ ((struct window *, int));
439 static void x_erase_phys_cursor P_ ((struct window *));
440 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
441 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
442 enum fringe_bitmap_type, int left_p));
443 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
444 GC, int));
445 static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
446 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
447 static void notice_overwritten_cursor P_ ((struct window *,
448 enum glyph_row_area,
449 int, int, int, int));
450 static void x_flush P_ ((struct frame *f));
451 static void x_update_begin P_ ((struct frame *));
452 static void x_update_window_begin P_ ((struct window *));
453 static void x_draw_vertical_border P_ ((struct window *));
454 static void x_after_update_window_line P_ ((struct glyph_row *));
455 static INLINE void take_vertical_position_into_account P_ ((struct it *));
456 static void x_produce_stretch_glyph P_ ((struct it *));
457
458 static void activate_scroll_bars (FRAME_PTR);
459 static void deactivate_scroll_bars (FRAME_PTR);
460
461 extern int image_ascent (struct image *, struct face *);
462 void x_set_offset (struct frame *, int, int, int);
463 int x_bitmap_icon (struct frame *, Lisp_Object);
464 void x_make_frame_visible (struct frame *);
465
466 extern void window_scroll (Lisp_Object, int, int, int);
467
468 /* Defined in macmenu.h. */
469 extern void menubar_selection_callback (FRAME_PTR, int);
470 extern void set_frame_menubar (FRAME_PTR, int, int);
471
472 /* X display function emulation */
473
474 /* Structure borrowed from Xlib.h to represent two-byte characters in
475 dumpglyphs. */
476
477 typedef struct {
478 unsigned char byte1;
479 unsigned char byte2;
480 } XChar2b;
481
482 static void
483 XFreePixmap (display, pixmap)
484 Display *display;
485 Pixmap pixmap;
486 {
487 PixMap *p = (PixMap *) pixmap;
488
489 xfree (p->baseAddr);
490 xfree (p);
491 }
492
493
494 /* Set foreground color for subsequent QuickDraw commands. Assume
495 graphic port has already been set. */
496
497 static void
498 mac_set_forecolor (unsigned long color)
499 {
500 RGBColor fg_color;
501
502 fg_color.red = RED_FROM_ULONG (color) * 256;
503 fg_color.green = GREEN_FROM_ULONG (color) * 256;
504 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
505
506 RGBForeColor (&fg_color);
507 }
508
509
510 /* Set background color for subsequent QuickDraw commands. Assume
511 graphic port has already been set. */
512
513 static void
514 mac_set_backcolor (unsigned long color)
515 {
516 RGBColor bg_color;
517
518 bg_color.red = RED_FROM_ULONG (color) * 256;
519 bg_color.green = GREEN_FROM_ULONG (color) * 256;
520 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
521
522 RGBBackColor (&bg_color);
523 }
524
525 /* Set foreground and background color for subsequent QuickDraw
526 commands. Assume that the graphic port has already been set. */
527
528 static void
529 mac_set_colors (GC gc)
530 {
531 mac_set_forecolor (gc->foreground);
532 mac_set_backcolor (gc->background);
533 }
534
535 /* Mac version of XDrawLine. */
536
537 static void
538 XDrawLine (display, w, gc, x1, y1, x2, y2)
539 Display *display;
540 WindowPtr w;
541 GC gc;
542 int x1, y1, x2, y2;
543 {
544 #if TARGET_API_MAC_CARBON
545 SetPort (GetWindowPort (w));
546 #else
547 SetPort (w);
548 #endif
549
550 mac_set_colors (gc);
551
552 MoveTo (x1, y1);
553 LineTo (x2, y2);
554 }
555
556 /* Mac version of XClearArea. */
557
558 void
559 XClearArea (display, w, x, y, width, height, exposures)
560 Display *display;
561 WindowPtr w;
562 int x, y;
563 unsigned int width, height;
564 int exposures;
565 {
566 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
567 Rect r;
568 XGCValues xgc;
569
570 xgc.foreground = mwp->x_compatible.foreground_pixel;
571 xgc.background = mwp->x_compatible.background_pixel;
572
573 #if TARGET_API_MAC_CARBON
574 SetPort (GetWindowPort (w));
575 #else
576 SetPort (w);
577 #endif
578
579 mac_set_colors (&xgc);
580 SetRect (&r, x, y, x + width, y + height);
581
582 EraseRect (&r);
583 }
584
585 /* Mac version of XClearWindow. */
586
587 static void
588 XClearWindow (display, w)
589 Display *display;
590 WindowPtr w;
591 {
592 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
593 XGCValues xgc;
594
595 xgc.foreground = mwp->x_compatible.foreground_pixel;
596 xgc.background = mwp->x_compatible.background_pixel;
597
598 #if TARGET_API_MAC_CARBON
599 SetPort (GetWindowPort (w));
600 #else
601 SetPort (w);
602 #endif
603
604 mac_set_colors (&xgc);
605
606 #if TARGET_API_MAC_CARBON
607 {
608 Rect r;
609
610 GetWindowPortBounds (w, &r);
611 EraseRect (&r);
612 }
613 #else /* not TARGET_API_MAC_CARBON */
614 EraseRect (&(w->portRect));
615 #endif /* not TARGET_API_MAC_CARBON */
616 }
617
618
619 /* Mac replacement for XCopyArea. */
620
621 static void
622 mac_draw_bitmap (display, w, gc, x, y, bitmap)
623 Display *display;
624 WindowPtr w;
625 GC gc;
626 int x, y;
627 BitMap *bitmap;
628 {
629 Rect r;
630
631 #if TARGET_API_MAC_CARBON
632 SetPort (GetWindowPort (w));
633 #else
634 SetPort (w);
635 #endif
636
637 mac_set_colors (gc);
638 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
639
640 #if TARGET_API_MAC_CARBON
641 {
642 PixMapHandle pmh;
643
644 LockPortBits (GetWindowPort (w));
645 pmh = GetPortPixMap (GetWindowPort (w));
646 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
647 UnlockPortBits (GetWindowPort (w));
648 }
649 #else /* not TARGET_API_MAC_CARBON */
650 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
651 #endif /* not TARGET_API_MAC_CARBON */
652 }
653
654
655 /* Mac replacement for XSetClipRectangles. */
656
657 static void
658 mac_set_clip_rectangle (display, w, r)
659 Display *display;
660 WindowPtr w;
661 Rect *r;
662 {
663 #if TARGET_API_MAC_CARBON
664 SetPort (GetWindowPort (w));
665 #else
666 SetPort (w);
667 #endif
668
669 ClipRect (r);
670 }
671
672
673 /* Mac replacement for XSetClipMask. */
674
675 static void
676 mac_reset_clipping (display, w)
677 Display *display;
678 WindowPtr w;
679 {
680 Rect r;
681
682 #if TARGET_API_MAC_CARBON
683 SetPort (GetWindowPort (w));
684 #else
685 SetPort (w);
686 #endif
687
688 SetRect (&r, -32767, -32767, 32767, 32767);
689 ClipRect (&r);
690 }
691
692
693 /* Mac replacement for XCreateBitmapFromBitmapData. */
694
695 static void
696 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
697 BitMap *bitmap;
698 char *bits;
699 int w, h;
700 {
701 int bytes_per_row, i, j;
702
703 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
704 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
705 if (!bitmap->baseAddr)
706 abort ();
707
708 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
709 for (i = 0; i < h; i++)
710 for (j = 0; j < w; j++)
711 if (BitTst (bits, i * w + j))
712 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
713
714 SetRect (&(bitmap->bounds), 0, 0, w, h);
715 }
716
717
718 static void
719 mac_free_bitmap (bitmap)
720 BitMap *bitmap;
721 {
722 xfree (bitmap->baseAddr);
723 }
724
725 /* Mac replacement for XFillRectangle. */
726
727 static void
728 XFillRectangle (display, w, gc, x, y, width, height)
729 Display *display;
730 WindowPtr w;
731 GC gc;
732 int x, y;
733 unsigned int width, height;
734 {
735 Rect r;
736
737 #if TARGET_API_MAC_CARBON
738 SetPort (GetWindowPort (w));
739 #else
740 SetPort (w);
741 #endif
742
743 mac_set_colors (gc);
744 SetRect (&r, x, y, x + width, y + height);
745
746 PaintRect (&r); /* using foreground color of gc */
747 }
748
749
750 /* Mac replacement for XDrawRectangle: dest is a window. */
751
752 static void
753 mac_draw_rectangle (display, w, gc, x, y, width, height)
754 Display *display;
755 WindowPtr w;
756 GC gc;
757 int x, y;
758 unsigned int width, height;
759 {
760 Rect r;
761
762 #if TARGET_API_MAC_CARBON
763 SetPort (GetWindowPort (w));
764 #else
765 SetPort (w);
766 #endif
767
768 mac_set_colors (gc);
769 SetRect (&r, x, y, x + width + 1, y + height + 1);
770
771 FrameRect (&r); /* using foreground color of gc */
772 }
773
774
775 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
776
777 static void
778 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
779 Display *display;
780 Pixmap p;
781 GC gc;
782 int x, y;
783 unsigned int width, height;
784 {
785 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
786 Rect r;
787
788 #if TARGET_API_MAC_CARBON
789 SetPort (GetWindowPort (w));
790 #else
791 SetPort (w);
792 #endif
793
794 mac_set_colors (gc);
795 SetRect (&r, x, y, x + width, y + height);
796
797 FrameRect (&r); /* using foreground color of gc */
798 #endif /* 0 */
799 }
800
801
802 static void
803 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
804 bytes_per_char)
805 Display *display;
806 WindowPtr w;
807 GC gc;
808 int x, y;
809 char *buf;
810 int nchars, mode, bytes_per_char;
811 {
812 #if TARGET_API_MAC_CARBON
813 SetPort (GetWindowPort (w));
814 #else
815 SetPort (w);
816 #endif
817
818 mac_set_colors (gc);
819
820 TextFont (gc->font->mac_fontnum);
821 TextSize (gc->font->mac_fontsize);
822 TextFace (gc->font->mac_fontface);
823 TextMode (mode);
824
825 MoveTo (x, y);
826 DrawText (buf, 0, nchars * bytes_per_char);
827 }
828
829
830 /* Mac replacement for XDrawString. */
831
832 static void
833 XDrawString (display, w, gc, x, y, buf, nchars)
834 Display *display;
835 WindowPtr w;
836 GC gc;
837 int x, y;
838 char *buf;
839 int nchars;
840 {
841 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
842 }
843
844
845 /* Mac replacement for XDrawString16. */
846
847 static void
848 XDrawString16 (display, w, gc, x, y, buf, nchars)
849 Display *display;
850 WindowPtr w;
851 GC gc;
852 int x, y;
853 XChar2b *buf;
854 int nchars;
855 {
856 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
857 2);
858 }
859
860
861 /* Mac replacement for XDrawImageString. */
862
863 static void
864 XDrawImageString (display, w, gc, x, y, buf, nchars)
865 Display *display;
866 WindowPtr w;
867 GC gc;
868 int x, y;
869 char *buf;
870 int nchars;
871 {
872 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
873 }
874
875
876 /* Mac replacement for XDrawString16. */
877
878 static void
879 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
880 Display *display;
881 WindowPtr w;
882 GC gc;
883 int x, y;
884 XChar2b *buf;
885 int nchars;
886 {
887 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
888 2);
889 }
890
891
892 /* Mac replacement for XCopyArea: dest must be window. */
893
894 static void
895 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
896 dest_y)
897 Display *display;
898 Pixmap src;
899 WindowPtr dest;
900 GC gc;
901 int src_x, src_y;
902 unsigned int width, height;
903 int dest_x, dest_y;
904 {
905 Rect src_r, dest_r;
906
907 #if TARGET_API_MAC_CARBON
908 SetPort (GetWindowPort (dest));
909 #else
910 SetPort (dest);
911 #endif
912
913 mac_set_colors (gc);
914
915 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
916 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
917
918 #if TARGET_API_MAC_CARBON
919 {
920 PixMapHandle pmh;
921
922 LockPortBits (GetWindowPort (dest));
923 pmh = GetPortPixMap (GetWindowPort (dest));
924 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
925 UnlockPortBits (GetWindowPort (dest));
926 }
927 #else /* not TARGET_API_MAC_CARBON */
928 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
929 #endif /* not TARGET_API_MAC_CARBON */
930 }
931
932
933 #if 0
934 /* Convert a pair of local coordinates to global (screen) coordinates.
935 Assume graphic port has been properly set. */
936 static void
937 local_to_global_coord (short *h, short *v)
938 {
939 Point p;
940
941 p.h = *h;
942 p.v = *v;
943
944 LocalToGlobal (&p);
945
946 *h = p.h;
947 *v = p.v;
948 }
949 #endif
950
951 /* Mac replacement for XCopyArea: used only for scrolling. */
952
953 static void
954 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
955 Display *display;
956 WindowPtr w;
957 GC gc;
958 int src_x, src_y;
959 unsigned int width, height;
960 int dest_x, dest_y;
961 {
962 #if TARGET_API_MAC_CARBON
963 Rect gw_r, src_r, dest_r;
964 PixMapHandle pmh;
965
966 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
967 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
968
969 SetPort (GetWindowPort (w));
970 mac_set_colors (gc);
971
972 LockPortBits (GetWindowPort (w));
973 pmh = GetPortPixMap (GetWindowPort (w));
974 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
975 UnlockPortBits (GetWindowPort (w));
976 #else /* not TARGET_API_MAC_CARBON */
977 Rect src_r, dest_r;
978
979 SetPort (w);
980 #if 0
981 mac_set_colors (gc);
982 #endif
983
984 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
985 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
986
987 #if 0
988 /* Need to use global coordinates and screenBits since src and dest
989 areas overlap in general. */
990 local_to_global_coord (&src_r.left, &src_r.top);
991 local_to_global_coord (&src_r.right, &src_r.bottom);
992 local_to_global_coord (&dest_r.left, &dest_r.top);
993 local_to_global_coord (&dest_r.right, &dest_r.bottom);
994
995 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
996 #else
997 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
998 color mapping in CopyBits. Otherwise, it will be slow. */
999 ForeColor (blackColor);
1000 BackColor (whiteColor);
1001 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1002
1003 mac_set_colors (gc);
1004 #endif
1005 #endif /* not TARGET_API_MAC_CARBON */
1006 }
1007
1008
1009 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1010
1011 static void
1012 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
1013 dest_x, dest_y)
1014 Display *display;
1015 Pixmap src;
1016 Pixmap dest;
1017 GC gc;
1018 int src_x, src_y;
1019 unsigned int width, height;
1020 int dest_x, dest_y;
1021 {
1022 Rect src_r, dest_r;
1023 int src_right = ((PixMap *) src)->bounds.right;
1024 int src_bottom = ((PixMap *) src)->bounds.bottom;
1025 int w = src_right - src_x;
1026 int h = src_bottom - src_y;
1027
1028 mac_set_colors (gc);
1029
1030 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
1031 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
1032
1033 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
1034 }
1035
1036
1037 /* Mac replacement for XChangeGC. */
1038
1039 static void
1040 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1041 XGCValues *xgcv)
1042 {
1043 if (mask & GCForeground)
1044 gc->foreground = xgcv->foreground;
1045 if (mask & GCBackground)
1046 gc->background = xgcv->background;
1047 if (mask & GCFont)
1048 gc->font = xgcv->font;
1049 }
1050
1051
1052 /* Mac replacement for XCreateGC. */
1053
1054 XGCValues *
1055 XCreateGC (void * ignore, Window window, unsigned long mask,
1056 XGCValues *xgcv)
1057 {
1058 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1059 bzero (gc, sizeof (XGCValues));
1060
1061 XChangeGC (ignore, gc, mask, xgcv);
1062
1063 return gc;
1064 }
1065
1066
1067 /* Used in xfaces.c. */
1068
1069 void
1070 XFreeGC (display, gc)
1071 Display *display;
1072 GC gc;
1073 {
1074 xfree (gc);
1075 }
1076
1077
1078 /* Mac replacement for XGetGCValues. */
1079
1080 static void
1081 XGetGCValues (void* ignore, XGCValues *gc,
1082 unsigned long mask, XGCValues *xgcv)
1083 {
1084 XChangeGC (ignore, xgcv, mask, gc);
1085 }
1086
1087
1088 /* Mac replacement for XSetForeground. */
1089
1090 static void
1091 XSetForeground (display, gc, color)
1092 Display *display;
1093 GC gc;
1094 unsigned long color;
1095 {
1096 gc->foreground = color;
1097 }
1098
1099
1100 /* Mac replacement for XSetFont. */
1101
1102 static void
1103 XSetFont (display, gc, font)
1104 Display *display;
1105 GC gc;
1106 XFontStruct *font;
1107 {
1108 gc->font = font;
1109 }
1110
1111
1112 static void
1113 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1114 int *direction,int *font_ascent,
1115 int *font_descent, XCharStruct *cs)
1116 {
1117 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1118 }
1119
1120
1121 /* x_sync is a no-op on Mac. */
1122 void
1123 x_sync (f)
1124 void *f;
1125 {
1126 }
1127
1128
1129 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1130 Calls to XFlush should be unnecessary because the X output buffer
1131 is flushed automatically as needed by calls to XPending,
1132 XNextEvent, or XWindowEvent according to the XFlush man page.
1133 XTread_socket calls XPending. Removing XFlush improves
1134 performance. */
1135
1136 #if TARGET_API_MAC_CARBON
1137 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1138 #else
1139 #define XFlush(DISPLAY) (void) 0
1140 #endif
1141
1142 /* Flush display of frame F, or of all frames if F is null. */
1143
1144 void
1145 x_flush (f)
1146 struct frame *f;
1147 {
1148 #if TARGET_API_MAC_CARBON
1149 BLOCK_INPUT;
1150 if (f == NULL)
1151 {
1152 Lisp_Object rest, frame;
1153 FOR_EACH_FRAME (rest, frame)
1154 x_flush (XFRAME (frame));
1155 }
1156 else if (FRAME_X_P (f))
1157 XFlush (FRAME_MAC_DISPLAY (f));
1158 UNBLOCK_INPUT;
1159 #endif /* TARGET_API_MAC_CARBON */
1160 }
1161
1162
1163 \f
1164 /* Return the struct mac_display_info corresponding to DPY. There's
1165 only one. */
1166
1167 struct mac_display_info *
1168 mac_display_info_for_display (dpy)
1169 Display *dpy;
1170 {
1171 return &one_mac_display_info;
1172 }
1173
1174
1175 \f
1176 /***********************************************************************
1177 Starting and ending an update
1178 ***********************************************************************/
1179
1180 /* Start an update of frame F. This function is installed as a hook
1181 for update_begin, i.e. it is called when update_begin is called.
1182 This function is called prior to calls to x_update_window_begin for
1183 each window being updated. */
1184
1185 static void
1186 x_update_begin (f)
1187 struct frame *f;
1188 {
1189 /* Nothing to do. */
1190 }
1191
1192
1193 /* Start update of window W. Set the global variable updated_window
1194 to the window being updated and set output_cursor to the cursor
1195 position of W. */
1196
1197 static void
1198 x_update_window_begin (w)
1199 struct window *w;
1200 {
1201 struct frame *f = XFRAME (WINDOW_FRAME (w));
1202 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1203
1204 updated_window = w;
1205 set_output_cursor (&w->cursor);
1206
1207 BLOCK_INPUT;
1208
1209 if (f == display_info->mouse_face_mouse_frame)
1210 {
1211 /* Don't do highlighting for mouse motion during the update. */
1212 display_info->mouse_face_defer = 1;
1213
1214 /* If F needs to be redrawn, simply forget about any prior mouse
1215 highlighting. */
1216 if (FRAME_GARBAGED_P (f))
1217 display_info->mouse_face_window = Qnil;
1218
1219 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1220 their mouse_face_p flag set, which means that they are always
1221 unequal to rows in a desired matrix which never have that
1222 flag set. So, rows containing mouse-face glyphs are never
1223 scrolled, and we don't have to switch the mouse highlight off
1224 here to prevent it from being scrolled. */
1225
1226 /* Can we tell that this update does not affect the window
1227 where the mouse highlight is? If so, no need to turn off.
1228 Likewise, don't do anything if the frame is garbaged;
1229 in that case, the frame's current matrix that we would use
1230 is all wrong, and we will redisplay that line anyway. */
1231 if (!NILP (display_info->mouse_face_window)
1232 && w == XWINDOW (display_info->mouse_face_window))
1233 {
1234 int i;
1235
1236 for (i = 0; i < w->desired_matrix->nrows; ++i)
1237 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1238 break;
1239
1240 if (i < w->desired_matrix->nrows)
1241 clear_mouse_face (display_info);
1242 }
1243 #endif /* 0 */
1244 }
1245
1246 UNBLOCK_INPUT;
1247 }
1248
1249
1250 /* Draw a vertical window border to the right of window W if W doesn't
1251 have vertical scroll bars. */
1252
1253 static void
1254 x_draw_vertical_border (w)
1255 struct window *w;
1256 {
1257 struct frame *f = XFRAME (WINDOW_FRAME (w));
1258
1259 /* Redraw borders between horizontally adjacent windows. Don't
1260 do it for frames with vertical scroll bars because either the
1261 right scroll bar of a window, or the left scroll bar of its
1262 neighbor will suffice as a border. */
1263 if (!WINDOW_RIGHTMOST_P (w)
1264 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1265 {
1266 int x0, x1, y0, y1;
1267
1268 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
1269 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
1270 y1 -= 1;
1271
1272 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1273 f->output_data.mac->normal_gc, x1, y0, x1, y1);
1274 }
1275 }
1276
1277
1278 /* End update of window W (which is equal to updated_window).
1279
1280 Draw vertical borders between horizontally adjacent windows, and
1281 display W's cursor if CURSOR_ON_P is non-zero.
1282
1283 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1284 glyphs in mouse-face were overwritten. In that case we have to
1285 make sure that the mouse-highlight is properly redrawn.
1286
1287 W may be a menu bar pseudo-window in case we don't have X toolkit
1288 support. Such windows don't have a cursor, so don't display it
1289 here. */
1290
1291 static void
1292 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1293 struct window *w;
1294 int cursor_on_p, mouse_face_overwritten_p;
1295 {
1296 struct mac_display_info *dpyinfo
1297 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1298
1299 if (!w->pseudo_window_p)
1300 {
1301 BLOCK_INPUT;
1302
1303 if (cursor_on_p)
1304 x_display_and_set_cursor (w, 1, output_cursor.hpos,
1305 output_cursor.vpos,
1306 output_cursor.x, output_cursor.y);
1307
1308 x_draw_vertical_border (w);
1309 UNBLOCK_INPUT;
1310 }
1311
1312 /* If a row with mouse-face was overwritten, arrange for
1313 XTframe_up_to_date to redisplay the mouse highlight. */
1314 if (mouse_face_overwritten_p)
1315 {
1316 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1317 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1318 dpyinfo->mouse_face_window = Qnil;
1319 }
1320
1321 #if 0
1322 /* Unhide the caret. This won't actually show the cursor, unless it
1323 was visible before the corresponding call to HideCaret in
1324 x_update_window_begin. */
1325 if (w32_use_visible_system_caret)
1326 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1327 #endif
1328
1329 updated_window = NULL;
1330 }
1331
1332
1333 /* End update of frame F. This function is installed as a hook in
1334 update_end. */
1335
1336 static void
1337 x_update_end (f)
1338 struct frame *f;
1339 {
1340 /* Reset the background color of Mac OS Window to that of the frame after
1341 update so that it is used by Mac Toolbox to clear the update region before
1342 an update event is generated. */
1343 #if TARGET_API_MAC_CARBON
1344 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1345 #else
1346 SetPort (FRAME_MAC_WINDOW (f));
1347 #endif
1348
1349 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1350
1351 /* Mouse highlight may be displayed again. */
1352 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1353
1354 BLOCK_INPUT;
1355 XFlush (FRAME_MAC_DISPLAY (f));
1356 UNBLOCK_INPUT;
1357 }
1358
1359
1360 /* This function is called from various places in xdisp.c whenever a
1361 complete update has been performed. The global variable
1362 updated_window is not available here. */
1363
1364 static void
1365 XTframe_up_to_date (f)
1366 struct frame *f;
1367 {
1368 if (FRAME_X_P (f))
1369 {
1370 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1371
1372 if (dpyinfo->mouse_face_deferred_gc
1373 || f == dpyinfo->mouse_face_mouse_frame)
1374 {
1375 BLOCK_INPUT;
1376 if (dpyinfo->mouse_face_mouse_frame)
1377 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1378 dpyinfo->mouse_face_mouse_x,
1379 dpyinfo->mouse_face_mouse_y);
1380 dpyinfo->mouse_face_deferred_gc = 0;
1381 UNBLOCK_INPUT;
1382 }
1383 }
1384 }
1385
1386
1387 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1388 arrow bitmaps, or clear the fringes if no bitmaps are required
1389 before DESIRED_ROW is made current. The window being updated is
1390 found in updated_window. This function is called from
1391 update_window_line only if it is known that there are differences
1392 between bitmaps to be drawn between current row and DESIRED_ROW. */
1393
1394 static void
1395 x_after_update_window_line (desired_row)
1396 struct glyph_row *desired_row;
1397 {
1398 struct window *w = updated_window;
1399 struct frame *f;
1400 int width, height;
1401
1402 xassert (w);
1403
1404 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1405 {
1406 BLOCK_INPUT;
1407 x_draw_row_fringe_bitmaps (w, desired_row);
1408 UNBLOCK_INPUT;
1409 }
1410
1411 /* When a window has disappeared, make sure that no rest of
1412 full-width rows stays visible in the internal border. Could
1413 check here if updated_window is the leftmost/rightmost window,
1414 but I guess it's not worth doing since vertically split windows
1415 are almost never used, internal border is rarely set, and the
1416 overhead is very small. */
1417 if (windows_or_buffers_changed
1418 && desired_row->full_width_p
1419 && (f = XFRAME (w->frame),
1420 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1421 width != 0)
1422 && (height = desired_row->visible_height,
1423 height > 0))
1424 {
1425 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1426 /* Internal border is drawn below the tool bar. */
1427 if (WINDOWP (f->tool_bar_window)
1428 && w == XWINDOW (f->tool_bar_window))
1429 y -= width;
1430
1431 BLOCK_INPUT;
1432
1433 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1434 0, y, width, height, 0);
1435 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1436 f->output_data.mac->pixel_width - width, y,
1437 width, height, 0);
1438
1439 UNBLOCK_INPUT;
1440 }
1441 }
1442
1443
1444 /* Draw the bitmap WHICH in one of the left or right fringes of
1445 window W. ROW is the glyph row for which to display the bitmap; it
1446 determines the vertical position at which the bitmap has to be
1447 drawn. */
1448
1449 static void
1450 x_draw_fringe_bitmap (w, row, which, left_p)
1451 struct window *w;
1452 struct glyph_row *row;
1453 enum fringe_bitmap_type which;
1454 int left_p;
1455 {
1456 struct frame *f = XFRAME (WINDOW_FRAME (w));
1457 Display *display = FRAME_MAC_DISPLAY (f);
1458 WindowPtr window = FRAME_MAC_WINDOW (f);
1459 int x, y, wd, h, dy;
1460 int b1, b2;
1461 unsigned char *bits;
1462 BitMap bitmap;
1463 XGCValues gcv;
1464 GC gc = f->output_data.mac->normal_gc;
1465 struct face *face;
1466
1467 /* Must clip because of partially visible lines. */
1468 x_clip_to_row (w, row, gc, 1);
1469
1470 /* Convert row to frame coordinates. */
1471 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1472
1473 switch (which)
1474 {
1475 case NO_FRINGE_BITMAP:
1476 wd = 0;
1477 h = 0;
1478 break;
1479
1480 case LEFT_TRUNCATION_BITMAP:
1481 wd = left_width;
1482 h = left_height;
1483 bits = left_bits;
1484 break;
1485
1486 case OVERLAY_ARROW_BITMAP:
1487 wd = ov_width;
1488 h = ov_height;
1489 bits = ov_bits;
1490 break;
1491
1492 case RIGHT_TRUNCATION_BITMAP:
1493 wd = right_width;
1494 h = right_height;
1495 bits = right_bits;
1496 break;
1497
1498 case CONTINUED_LINE_BITMAP:
1499 wd = continued_width;
1500 h = continued_height;
1501 bits = continued_bits;
1502 break;
1503
1504 case CONTINUATION_LINE_BITMAP:
1505 wd = continuation_width;
1506 h = continuation_height;
1507 bits = continuation_bits;
1508 break;
1509
1510 case ZV_LINE_BITMAP:
1511 wd = zv_width;
1512 h = zv_height - (y % zv_period);
1513 bits = zv_bits + (y % zv_period);
1514 break;
1515
1516 default:
1517 abort ();
1518 }
1519
1520 /* Clip bitmap if too high. */
1521 if (h > row->height)
1522 h = row->height;
1523
1524 /* Set dy to the offset in the row to start drawing the bitmap. */
1525 dy = (row->height - h) / 2;
1526
1527 /* Draw the bitmap. */
1528 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
1529 PREPARE_FACE_FOR_DISPLAY (f, face);
1530
1531 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
1532 the fringe. */
1533 b1 = -1;
1534 if (left_p)
1535 {
1536 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
1537 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
1538 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
1539 - wd
1540 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
1541 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
1542 {
1543 /* If W has a vertical border to its left, don't draw over it. */
1544 int border = ((XFASTINT (w->left) > 0
1545 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1546 ? 1 : 0);
1547 b1 = (window_box_left (w, -1)
1548 - FRAME_X_LEFT_FRINGE_WIDTH (f)
1549 + border);
1550 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
1551 }
1552 }
1553 else
1554 {
1555 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
1556 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1557 x = (window_box_right (w, -1)
1558 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
1559 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1560 the fringe. */
1561 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
1562 {
1563 b1 = window_box_right (w, -1);
1564 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
1565 }
1566 }
1567
1568 if (b1 >= 0)
1569 {
1570 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1571 XGCValues gcv;
1572 gcv.foreground = face->background;
1573
1574 #if 0 /* MAC_TODO: stipple */
1575 /* In case the same realized face is used for fringes and
1576 for something displayed in the text (e.g. face `region' on
1577 mono-displays, the fill style may have been changed to
1578 FillSolid in x_draw_glyph_string_background. */
1579 if (face->stipple)
1580 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1581 else
1582 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1583 #endif
1584
1585 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1586 &gcv,
1587 b1,
1588 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1589 row->y)),
1590 b2,
1591 row->visible_height);
1592
1593 #if 0 /* MAC_TODO: stipple */
1594 if (!face->stipple)
1595 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1596 #endif
1597 }
1598
1599 if (which == NO_FRINGE_BITMAP)
1600 {
1601 mac_reset_clipping (display, window);
1602 return;
1603 }
1604
1605 mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
1606 gcv.foreground = face->foreground;
1607 gcv.background = face->background;
1608
1609 mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
1610
1611 mac_free_bitmap (&bitmap);
1612 mac_reset_clipping (display, window);
1613 }
1614
1615
1616 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1617 function with input blocked. */
1618
1619 static void
1620 x_draw_row_fringe_bitmaps (w, row)
1621 struct window *w;
1622 struct glyph_row *row;
1623 {
1624 struct frame *f = XFRAME (w->frame);
1625 enum fringe_bitmap_type bitmap;
1626
1627 xassert (interrupt_input_blocked);
1628
1629 /* If row is completely invisible, because of vscrolling, we
1630 don't have to draw anything. */
1631 if (row->visible_height <= 0)
1632 return;
1633
1634 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1635 {
1636 /* Decide which bitmap to draw in the left fringe. */
1637 if (row->overlay_arrow_p)
1638 bitmap = OVERLAY_ARROW_BITMAP;
1639 else if (row->truncated_on_left_p)
1640 bitmap = LEFT_TRUNCATION_BITMAP;
1641 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1642 bitmap = CONTINUATION_LINE_BITMAP;
1643 else if (row->indicate_empty_line_p)
1644 bitmap = ZV_LINE_BITMAP;
1645 else
1646 bitmap = NO_FRINGE_BITMAP;
1647
1648 x_draw_fringe_bitmap (w, row, bitmap, 1);
1649 }
1650
1651 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1652 {
1653 /* Decide which bitmap to draw in the right fringe. */
1654 if (row->truncated_on_right_p)
1655 bitmap = RIGHT_TRUNCATION_BITMAP;
1656 else if (row->continued_p)
1657 bitmap = CONTINUED_LINE_BITMAP;
1658 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1659 bitmap = ZV_LINE_BITMAP;
1660 else
1661 bitmap = NO_FRINGE_BITMAP;
1662
1663 x_draw_fringe_bitmap (w, row, bitmap, 0);
1664 }
1665 }
1666
1667 \f
1668 /* This is called when starting Emacs and when restarting after
1669 suspend. When starting Emacs, no window is mapped. And nothing
1670 must be done to Emacs's own window if it is suspended (though that
1671 rarely happens). */
1672
1673 static void
1674 XTset_terminal_modes ()
1675 {
1676 }
1677
1678 /* This is called when exiting or suspending Emacs. Exiting will make
1679 the windows go away, and suspending requires no action. */
1680
1681 static void
1682 XTreset_terminal_modes ()
1683 {
1684 }
1685
1686
1687 \f
1688 /***********************************************************************
1689 Output Cursor
1690 ***********************************************************************/
1691
1692 /* Set the global variable output_cursor to CURSOR. All cursor
1693 positions are relative to updated_window. */
1694
1695 static void
1696 set_output_cursor (cursor)
1697 struct cursor_pos *cursor;
1698 {
1699 output_cursor.hpos = cursor->hpos;
1700 output_cursor.vpos = cursor->vpos;
1701 output_cursor.x = cursor->x;
1702 output_cursor.y = cursor->y;
1703 }
1704
1705
1706 /* Set a nominal cursor position.
1707
1708 HPOS and VPOS are column/row positions in a window glyph matrix. X
1709 and Y are window text area relative pixel positions.
1710
1711 If this is done during an update, updated_window will contain the
1712 window that is being updated and the position is the future output
1713 cursor position for that window. If updated_window is null, use
1714 selected_window and display the cursor at the given position. */
1715
1716 static void
1717 XTcursor_to (vpos, hpos, y, x)
1718 int vpos, hpos, y, x;
1719 {
1720 struct window *w;
1721
1722 /* If updated_window is not set, work on selected_window. */
1723 if (updated_window)
1724 w = updated_window;
1725 else
1726 w = XWINDOW (selected_window);
1727
1728 /* Set the output cursor. */
1729 output_cursor.hpos = hpos;
1730 output_cursor.vpos = vpos;
1731 output_cursor.x = x;
1732 output_cursor.y = y;
1733
1734 /* If not called as part of an update, really display the cursor.
1735 This will also set the cursor position of W. */
1736 if (updated_window == NULL)
1737 {
1738 BLOCK_INPUT;
1739 x_display_cursor (w, 1, hpos, vpos, x, y);
1740 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1741 UNBLOCK_INPUT;
1742 }
1743 }
1744
1745
1746 \f
1747 /***********************************************************************
1748 Display Iterator
1749 ***********************************************************************/
1750
1751 /* Function prototypes of this page. */
1752
1753 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1754 struct glyph *,
1755 XChar2b *,
1756 int *));
1757 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1758 int, XChar2b *, int));
1759 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1760 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1761 static void x_append_glyph P_ ((struct it *));
1762 static void x_append_composite_glyph P_ ((struct it *));
1763 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1764 int, int, double));
1765 static void x_produce_glyphs P_ ((struct it *));
1766 static void x_produce_image_glyph P_ ((struct it *it));
1767
1768
1769 /* Return a pointer to per-char metric information in FONT of a
1770 character pointed by B which is a pointer to an XChar2b. */
1771
1772 #define PER_CHAR_METRIC(font, b) \
1773 ((font)->per_char \
1774 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1775 + (((font)->min_byte1 || (font)->max_byte1) \
1776 ? (((b)->byte1 - (font)->min_byte1) \
1777 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1778 : 0)) \
1779 : &((font)->max_bounds))
1780
1781
1782 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1783 is not contained in the font. */
1784
1785 static INLINE XCharStruct *
1786 x_per_char_metric (font, char2b)
1787 XFontStruct *font;
1788 XChar2b *char2b;
1789 {
1790 /* The result metric information. */
1791 XCharStruct *pcm = NULL;
1792
1793 xassert (font && char2b);
1794
1795 if (font->per_char != NULL)
1796 {
1797 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1798 {
1799 /* min_char_or_byte2 specifies the linear character index
1800 corresponding to the first element of the per_char array,
1801 max_char_or_byte2 is the index of the last character. A
1802 character with non-zero CHAR2B->byte1 is not in the font.
1803 A character with byte2 less than min_char_or_byte2 or
1804 greater max_char_or_byte2 is not in the font. */
1805 if (char2b->byte1 == 0
1806 && char2b->byte2 >= font->min_char_or_byte2
1807 && char2b->byte2 <= font->max_char_or_byte2)
1808 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1809 }
1810 else
1811 {
1812 /* If either min_byte1 or max_byte1 are nonzero, both
1813 min_char_or_byte2 and max_char_or_byte2 are less than
1814 256, and the 2-byte character index values corresponding
1815 to the per_char array element N (counting from 0) are:
1816
1817 byte1 = N/D + min_byte1
1818 byte2 = N\D + min_char_or_byte2
1819
1820 where:
1821
1822 D = max_char_or_byte2 - min_char_or_byte2 + 1
1823 / = integer division
1824 \ = integer modulus */
1825 if (char2b->byte1 >= font->min_byte1
1826 && char2b->byte1 <= font->max_byte1
1827 && char2b->byte2 >= font->min_char_or_byte2
1828 && char2b->byte2 <= font->max_char_or_byte2)
1829 {
1830 pcm = (font->per_char
1831 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1832 * (char2b->byte1 - font->min_byte1))
1833 + (char2b->byte2 - font->min_char_or_byte2));
1834 }
1835 }
1836 }
1837 else
1838 {
1839 /* If the per_char pointer is null, all glyphs between the first
1840 and last character indexes inclusive have the same
1841 information, as given by both min_bounds and max_bounds. */
1842 if (char2b->byte2 >= font->min_char_or_byte2
1843 && char2b->byte2 <= font->max_char_or_byte2)
1844 pcm = &font->max_bounds;
1845 }
1846
1847 return ((pcm == NULL
1848 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1849 ? NULL : pcm);
1850 }
1851
1852
1853 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1854 the two-byte form of C. Encoding is returned in *CHAR2B. */
1855
1856 static INLINE void
1857 x_encode_char (c, char2b, font_info)
1858 int c;
1859 XChar2b *char2b;
1860 struct font_info *font_info;
1861 {
1862 int charset = CHAR_CHARSET (c);
1863 XFontStruct *font = font_info->font;
1864
1865 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1866 This may be either a program in a special encoder language or a
1867 fixed encoding. */
1868 if (font_info->font_encoder)
1869 {
1870 /* It's a program. */
1871 struct ccl_program *ccl = font_info->font_encoder;
1872
1873 if (CHARSET_DIMENSION (charset) == 1)
1874 {
1875 ccl->reg[0] = charset;
1876 ccl->reg[1] = char2b->byte2;
1877 }
1878 else
1879 {
1880 ccl->reg[0] = charset;
1881 ccl->reg[1] = char2b->byte1;
1882 ccl->reg[2] = char2b->byte2;
1883 }
1884
1885 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1886
1887 /* We assume that MSBs are appropriately set/reset by CCL
1888 program. */
1889 if (font->max_byte1 == 0) /* 1-byte font */
1890 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1891 else
1892 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1893 }
1894 else if (font_info->encoding[charset])
1895 {
1896 /* Fixed encoding scheme. See fontset.h for the meaning of the
1897 encoding numbers. */
1898 int enc = font_info->encoding[charset];
1899
1900 if ((enc == 1 || enc == 2)
1901 && CHARSET_DIMENSION (charset) == 2)
1902 char2b->byte1 |= 0x80;
1903
1904 if (enc == 1 || enc == 3)
1905 char2b->byte2 |= 0x80;
1906
1907 if (enc == 4)
1908 {
1909 int sjis1, sjis2;
1910
1911 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1912 char2b->byte1 = sjis1;
1913 char2b->byte2 = sjis2;
1914 }
1915 }
1916 }
1917
1918
1919 /* Get face and two-byte form of character C in face FACE_ID on frame
1920 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1921 means we want to display multibyte text. Value is a pointer to a
1922 realized face that is ready for display. */
1923
1924 static INLINE struct face *
1925 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1926 struct frame *f;
1927 int c, face_id;
1928 XChar2b *char2b;
1929 int multibyte_p;
1930 {
1931 struct face *face = FACE_FROM_ID (f, face_id);
1932
1933 if (!multibyte_p)
1934 {
1935 /* Unibyte case. We don't have to encode, but we have to make
1936 sure to use a face suitable for unibyte. */
1937 char2b->byte1 = 0;
1938 char2b->byte2 = c;
1939 face_id = FACE_FOR_CHAR (f, face, c);
1940 face = FACE_FROM_ID (f, face_id);
1941 }
1942 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1943 {
1944 /* Case of ASCII in a face known to fit ASCII. */
1945 char2b->byte1 = 0;
1946 char2b->byte2 = c;
1947 }
1948 else
1949 {
1950 int c1, c2, charset;
1951
1952 /* Split characters into bytes. If c2 is -1 afterwards, C is
1953 really a one-byte character so that byte1 is zero. */
1954 SPLIT_CHAR (c, charset, c1, c2);
1955 if (c2 > 0)
1956 char2b->byte1 = c1, char2b->byte2 = c2;
1957 else
1958 char2b->byte1 = 0, char2b->byte2 = c1;
1959
1960 /* Maybe encode the character in *CHAR2B. */
1961 if (face->font != NULL)
1962 {
1963 struct font_info *font_info
1964 = FONT_INFO_FROM_ID (f, face->font_info_id);
1965 if (font_info)
1966 x_encode_char (c, char2b, font_info);
1967 }
1968 }
1969
1970 /* Make sure X resources of the face are allocated. */
1971 xassert (face != NULL);
1972 PREPARE_FACE_FOR_DISPLAY (f, face);
1973
1974 return face;
1975 }
1976
1977
1978 /* Get face and two-byte form of character glyph GLYPH on frame F.
1979 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1980 a pointer to a realized face that is ready for display. */
1981
1982 static INLINE struct face *
1983 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1984 struct frame *f;
1985 struct glyph *glyph;
1986 XChar2b *char2b;
1987 int *two_byte_p;
1988 {
1989 struct face *face;
1990
1991 xassert (glyph->type == CHAR_GLYPH);
1992 face = FACE_FROM_ID (f, glyph->face_id);
1993
1994 if (two_byte_p)
1995 *two_byte_p = 0;
1996
1997 if (!glyph->multibyte_p)
1998 {
1999 /* Unibyte case. We don't have to encode, but we have to make
2000 sure to use a face suitable for unibyte. */
2001 char2b->byte1 = 0;
2002 char2b->byte2 = glyph->u.ch;
2003 }
2004 else if (glyph->u.ch < 128
2005 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
2006 {
2007 /* Case of ASCII in a face known to fit ASCII. */
2008 char2b->byte1 = 0;
2009 char2b->byte2 = glyph->u.ch;
2010 }
2011 else
2012 {
2013 int c1, c2, charset;
2014
2015 /* Split characters into bytes. If c2 is -1 afterwards, C is
2016 really a one-byte character so that byte1 is zero. */
2017 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
2018 if (c2 > 0)
2019 char2b->byte1 = c1, char2b->byte2 = c2;
2020 else
2021 char2b->byte1 = 0, char2b->byte2 = c1;
2022
2023 /* Maybe encode the character in *CHAR2B. */
2024 if (charset != CHARSET_ASCII)
2025 {
2026 struct font_info *font_info
2027 = FONT_INFO_FROM_ID (f, face->font_info_id);
2028 if (font_info)
2029 {
2030 x_encode_char (glyph->u.ch, char2b, font_info);
2031 if (two_byte_p)
2032 *two_byte_p
2033 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2034 }
2035 }
2036 }
2037
2038 /* Make sure X resources of the face are allocated. */
2039 xassert (face != NULL);
2040 PREPARE_FACE_FOR_DISPLAY (f, face);
2041 return face;
2042 }
2043
2044
2045 /* Store one glyph for IT->char_to_display in IT->glyph_row.
2046 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2047
2048 static INLINE void
2049 x_append_glyph (it)
2050 struct it *it;
2051 {
2052 struct glyph *glyph;
2053 enum glyph_row_area area = it->area;
2054
2055 xassert (it->glyph_row);
2056 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
2057
2058 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2059 if (glyph < it->glyph_row->glyphs[area + 1])
2060 {
2061 glyph->charpos = CHARPOS (it->position);
2062 glyph->object = it->object;
2063 glyph->pixel_width = it->pixel_width;
2064 glyph->voffset = it->voffset;
2065 glyph->type = CHAR_GLYPH;
2066 glyph->multibyte_p = it->multibyte_p;
2067 glyph->left_box_line_p = it->start_of_box_run_p;
2068 glyph->right_box_line_p = it->end_of_box_run_p;
2069 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2070 || it->phys_descent > it->descent);
2071 glyph->padding_p = 0;
2072 glyph->glyph_not_available_p = it->glyph_not_available_p;
2073 glyph->face_id = it->face_id;
2074 glyph->u.ch = it->char_to_display;
2075 ++it->glyph_row->used[area];
2076 }
2077 }
2078
2079 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
2080 Called from x_produce_glyphs when IT->glyph_row is non-null. */
2081
2082 static INLINE void
2083 x_append_composite_glyph (it)
2084 struct it *it;
2085 {
2086 struct glyph *glyph;
2087 enum glyph_row_area area = it->area;
2088
2089 xassert (it->glyph_row);
2090
2091 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2092 if (glyph < it->glyph_row->glyphs[area + 1])
2093 {
2094 glyph->charpos = CHARPOS (it->position);
2095 glyph->object = it->object;
2096 glyph->pixel_width = it->pixel_width;
2097 glyph->voffset = it->voffset;
2098 glyph->type = COMPOSITE_GLYPH;
2099 glyph->multibyte_p = it->multibyte_p;
2100 glyph->left_box_line_p = it->start_of_box_run_p;
2101 glyph->right_box_line_p = it->end_of_box_run_p;
2102 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
2103 || it->phys_descent > it->descent);
2104 glyph->padding_p = 0;
2105 glyph->glyph_not_available_p = 0;
2106 glyph->face_id = it->face_id;
2107 glyph->u.cmp_id = it->cmp_id;
2108 ++it->glyph_row->used[area];
2109 }
2110 }
2111
2112
2113 /* Change IT->ascent and IT->height according to the setting of
2114 IT->voffset. */
2115
2116 static INLINE void
2117 take_vertical_position_into_account (it)
2118 struct it *it;
2119 {
2120 if (it->voffset)
2121 {
2122 if (it->voffset < 0)
2123 /* Increase the ascent so that we can display the text higher
2124 in the line. */
2125 it->ascent += abs (it->voffset);
2126 else
2127 /* Increase the descent so that we can display the text lower
2128 in the line. */
2129 it->descent += it->voffset;
2130 }
2131 }
2132
2133
2134 /* Produce glyphs/get display metrics for the image IT is loaded with.
2135 See the description of struct display_iterator in dispextern.h for
2136 an overview of struct display_iterator. */
2137
2138 static void
2139 x_produce_image_glyph (it)
2140 struct it *it;
2141 {
2142 struct image *img;
2143 struct face *face;
2144
2145 xassert (it->what == IT_IMAGE);
2146
2147 face = FACE_FROM_ID (it->f, it->face_id);
2148 img = IMAGE_FROM_ID (it->f, it->image_id);
2149 xassert (img);
2150
2151 /* Make sure X resources of the face and image are loaded. */
2152 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2153 prepare_image_for_display (it->f, img);
2154
2155 it->ascent = it->phys_ascent = image_ascent (img, face);
2156 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
2157 it->pixel_width = img->width + 2 * img->hmargin;
2158
2159 it->nglyphs = 1;
2160
2161 if (face->box != FACE_NO_BOX)
2162 {
2163 if (face->box_line_width > 0)
2164 {
2165 it->ascent += face->box_line_width;
2166 it->descent += face->box_line_width;
2167 }
2168
2169 if (it->start_of_box_run_p)
2170 it->pixel_width += abs (face->box_line_width);
2171 if (it->end_of_box_run_p)
2172 it->pixel_width += abs (face->box_line_width);
2173 }
2174
2175 take_vertical_position_into_account (it);
2176
2177 if (it->glyph_row)
2178 {
2179 struct glyph *glyph;
2180 enum glyph_row_area area = it->area;
2181
2182 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2183 if (glyph < it->glyph_row->glyphs[area + 1])
2184 {
2185 glyph->charpos = CHARPOS (it->position);
2186 glyph->object = it->object;
2187 glyph->pixel_width = it->pixel_width;
2188 glyph->voffset = it->voffset;
2189 glyph->type = IMAGE_GLYPH;
2190 glyph->multibyte_p = it->multibyte_p;
2191 glyph->left_box_line_p = it->start_of_box_run_p;
2192 glyph->right_box_line_p = it->end_of_box_run_p;
2193 glyph->overlaps_vertically_p = 0;
2194 glyph->padding_p = 0;
2195 glyph->glyph_not_available_p = 0;
2196 glyph->face_id = it->face_id;
2197 glyph->u.img_id = img->id;
2198 ++it->glyph_row->used[area];
2199 }
2200 }
2201 }
2202
2203
2204 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
2205 of the glyph, WIDTH and HEIGHT are the width and height of the
2206 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
2207 ascent of the glyph (0 <= ASCENT <= 1). */
2208
2209 static void
2210 x_append_stretch_glyph (it, object, width, height, ascent)
2211 struct it *it;
2212 Lisp_Object object;
2213 int width, height;
2214 double ascent;
2215 {
2216 struct glyph *glyph;
2217 enum glyph_row_area area = it->area;
2218
2219 xassert (ascent >= 0 && ascent <= 1);
2220
2221 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
2222 if (glyph < it->glyph_row->glyphs[area + 1])
2223 {
2224 glyph->charpos = CHARPOS (it->position);
2225 glyph->object = object;
2226 glyph->pixel_width = width;
2227 glyph->voffset = it->voffset;
2228 glyph->type = STRETCH_GLYPH;
2229 glyph->multibyte_p = it->multibyte_p;
2230 glyph->left_box_line_p = it->start_of_box_run_p;
2231 glyph->right_box_line_p = it->end_of_box_run_p;
2232 glyph->overlaps_vertically_p = 0;
2233 glyph->padding_p = 0;
2234 glyph->glyph_not_available_p = 0;
2235 glyph->face_id = it->face_id;
2236 glyph->u.stretch.ascent = height * ascent;
2237 glyph->u.stretch.height = height;
2238 ++it->glyph_row->used[area];
2239 }
2240 }
2241
2242
2243 /* Produce a stretch glyph for iterator IT. IT->object is the value
2244 of the glyph property displayed. The value must be a list
2245 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
2246 being recognized:
2247
2248 1. `:width WIDTH' specifies that the space should be WIDTH *
2249 canonical char width wide. WIDTH may be an integer or floating
2250 point number.
2251
2252 2. `:relative-width FACTOR' specifies that the width of the stretch
2253 should be computed from the width of the first character having the
2254 `glyph' property, and should be FACTOR times that width.
2255
2256 3. `:align-to HPOS' specifies that the space should be wide enough
2257 to reach HPOS, a value in canonical character units.
2258
2259 Exactly one of the above pairs must be present.
2260
2261 4. `:height HEIGHT' specifies that the height of the stretch produced
2262 should be HEIGHT, measured in canonical character units.
2263
2264 5. `:relative-height FACTOR' specifies that the height of the
2265 stretch should be FACTOR times the height of the characters having
2266 the glyph property.
2267
2268 Either none or exactly one of 4 or 5 must be present.
2269
2270 6. `:ascent ASCENT' specifies that ASCENT percent of the height
2271 of the stretch should be used for the ascent of the stretch.
2272 ASCENT must be in the range 0 <= ASCENT <= 100. */
2273
2274 #define NUMVAL(X) \
2275 ((INTEGERP (X) || FLOATP (X)) \
2276 ? XFLOATINT (X) \
2277 : - 1)
2278
2279
2280 static void
2281 x_produce_stretch_glyph (it)
2282 struct it *it;
2283 {
2284 /* (space :width WIDTH :height HEIGHT. */
2285 #if GLYPH_DEBUG
2286 extern Lisp_Object Qspace;
2287 #endif
2288 extern Lisp_Object QCwidth, QCheight, QCascent;
2289 extern Lisp_Object QCrelative_width, QCrelative_height;
2290 extern Lisp_Object QCalign_to;
2291 Lisp_Object prop, plist;
2292 double width = 0, height = 0, ascent = 0;
2293 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2294 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
2295
2296 PREPARE_FACE_FOR_DISPLAY (it->f, face);
2297
2298 /* List should start with `space'. */
2299 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
2300 plist = XCDR (it->object);
2301
2302 /* Compute the width of the stretch. */
2303 if (prop = Fplist_get (plist, QCwidth),
2304 NUMVAL (prop) > 0)
2305 /* Absolute width `:width WIDTH' specified and valid. */
2306 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
2307 else if (prop = Fplist_get (plist, QCrelative_width),
2308 NUMVAL (prop) > 0)
2309 {
2310 /* Relative width `:relative-width FACTOR' specified and valid.
2311 Compute the width of the characters having the `glyph'
2312 property. */
2313 struct it it2;
2314 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
2315
2316 it2 = *it;
2317 if (it->multibyte_p)
2318 {
2319 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
2320 - IT_BYTEPOS (*it));
2321 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
2322 }
2323 else
2324 it2.c = *p, it2.len = 1;
2325
2326 it2.glyph_row = NULL;
2327 it2.what = IT_CHARACTER;
2328 x_produce_glyphs (&it2);
2329 width = NUMVAL (prop) * it2.pixel_width;
2330 }
2331 else if (prop = Fplist_get (plist, QCalign_to),
2332 NUMVAL (prop) > 0)
2333 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
2334 else
2335 /* Nothing specified -> width defaults to canonical char width. */
2336 width = CANON_X_UNIT (it->f);
2337
2338 /* Compute height. */
2339 if (prop = Fplist_get (plist, QCheight),
2340 NUMVAL (prop) > 0)
2341 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
2342 else if (prop = Fplist_get (plist, QCrelative_height),
2343 NUMVAL (prop) > 0)
2344 height = FONT_HEIGHT (font) * NUMVAL (prop);
2345 else
2346 height = FONT_HEIGHT (font);
2347
2348 /* Compute percentage of height used for ascent. If
2349 `:ascent ASCENT' is present and valid, use that. Otherwise,
2350 derive the ascent from the font in use. */
2351 if (prop = Fplist_get (plist, QCascent),
2352 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
2353 ascent = NUMVAL (prop) / 100.0;
2354 else
2355 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
2356
2357 if (width <= 0)
2358 width = 1;
2359 if (height <= 0)
2360 height = 1;
2361
2362 if (it->glyph_row)
2363 {
2364 Lisp_Object object = it->stack[it->sp - 1].string;
2365 if (!STRINGP (object))
2366 object = it->w->buffer;
2367 x_append_stretch_glyph (it, object, width, height, ascent);
2368 }
2369
2370 it->pixel_width = width;
2371 it->ascent = it->phys_ascent = height * ascent;
2372 it->descent = it->phys_descent = height - it->ascent;
2373 it->nglyphs = 1;
2374
2375 if (face->box != FACE_NO_BOX)
2376 {
2377 if (face->box_line_width > 0)
2378 {
2379 it->ascent += face->box_line_width;
2380 it->descent += face->box_line_width;
2381 }
2382
2383 if (it->start_of_box_run_p)
2384 it->pixel_width += abs (face->box_line_width);
2385 if (it->end_of_box_run_p)
2386 it->pixel_width += abs (face->box_line_width);
2387 }
2388
2389 take_vertical_position_into_account (it);
2390 }
2391
2392 /* Return proper value to be used as baseline offset of font that has
2393 ASCENT and DESCENT to draw characters by the font at the vertical
2394 center of the line of frame F.
2395
2396 Here, out task is to find the value of BOFF in the following figure;
2397
2398 -------------------------+-----------+-
2399 -+-+---------+-+ | |
2400 | | | | | |
2401 | | | | F_ASCENT F_HEIGHT
2402 | | | ASCENT | |
2403 HEIGHT | | | | |
2404 | | |-|-+------+-----------|------- baseline
2405 | | | | BOFF | |
2406 | |---------|-+-+ | |
2407 | | | DESCENT | |
2408 -+-+---------+-+ F_DESCENT |
2409 -------------------------+-----------+-
2410
2411 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2412 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2413 DESCENT = FONT->descent
2414 HEIGHT = FONT_HEIGHT (FONT)
2415 F_DESCENT = (F->output_data.x->font->descent
2416 - F->output_data.x->baseline_offset)
2417 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2418 */
2419
2420 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2421 (FONT_DESCENT (FONT) \
2422 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2423 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2424 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2425
2426 /* Produce glyphs/get display metrics for the display element IT is
2427 loaded with. See the description of struct display_iterator in
2428 dispextern.h for an overview of struct display_iterator. */
2429
2430 static void
2431 x_produce_glyphs (it)
2432 struct it *it;
2433 {
2434 it->glyph_not_available_p = 0;
2435
2436 if (it->what == IT_CHARACTER)
2437 {
2438 XChar2b char2b;
2439 XFontStruct *font;
2440 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2441 XCharStruct *pcm;
2442 int font_not_found_p;
2443 struct font_info *font_info;
2444 int boff; /* baseline offset */
2445 /* We may change it->multibyte_p upon unibyte<->multibyte
2446 conversion. So, save the current value now and restore it
2447 later.
2448
2449 Note: It seems that we don't have to record multibyte_p in
2450 struct glyph because the character code itself tells if or
2451 not the character is multibyte. Thus, in the future, we must
2452 consider eliminating the field `multibyte_p' in the struct
2453 glyph.
2454 */
2455 int saved_multibyte_p = it->multibyte_p;
2456
2457 /* Maybe translate single-byte characters to multibyte, or the
2458 other way. */
2459 it->char_to_display = it->c;
2460 if (!ASCII_BYTE_P (it->c))
2461 {
2462 if (unibyte_display_via_language_environment
2463 && SINGLE_BYTE_CHAR_P (it->c)
2464 && (it->c >= 0240
2465 || !NILP (Vnonascii_translation_table)))
2466 {
2467 it->char_to_display = unibyte_char_to_multibyte (it->c);
2468 it->multibyte_p = 1;
2469 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2470 face = FACE_FROM_ID (it->f, it->face_id);
2471 }
2472 else if (!SINGLE_BYTE_CHAR_P (it->c)
2473 && !it->multibyte_p)
2474 {
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 }
2480
2481 /* Get font to use. Encode IT->char_to_display. */
2482 x_get_char_face_and_encoding (it->f, it->char_to_display,
2483 it->face_id, &char2b,
2484 it->multibyte_p);
2485 font = face->font;
2486
2487 /* When no suitable font found, use the default font. */
2488 font_not_found_p = font == NULL;
2489 if (font_not_found_p)
2490 {
2491 font = FRAME_FONT (it->f);
2492 boff = it->f->output_data.mac->baseline_offset;
2493 font_info = NULL;
2494 }
2495 else
2496 {
2497 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2498 boff = font_info->baseline_offset;
2499 if (font_info->vertical_centering)
2500 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2501 }
2502
2503 if (it->char_to_display >= ' '
2504 && (!it->multibyte_p || it->char_to_display < 128))
2505 {
2506 /* Either unibyte or ASCII. */
2507 int stretched_p;
2508
2509 it->nglyphs = 1;
2510
2511 pcm = x_per_char_metric (font, &char2b);
2512 it->ascent = FONT_BASE (font) + boff;
2513 it->descent = FONT_DESCENT (font) - boff;
2514
2515 if (pcm)
2516 {
2517 it->phys_ascent = pcm->ascent + boff;
2518 it->phys_descent = pcm->descent - boff;
2519 it->pixel_width = pcm->width;
2520 }
2521 else
2522 {
2523 it->glyph_not_available_p = 1;
2524 it->phys_ascent = FONT_BASE (font) + boff;
2525 it->phys_descent = FONT_DESCENT (font) - boff;
2526 it->pixel_width = FONT_WIDTH (font);
2527 }
2528
2529 /* If this is a space inside a region of text with
2530 `space-width' property, change its width. */
2531 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2532 if (stretched_p)
2533 it->pixel_width *= XFLOATINT (it->space_width);
2534
2535 /* If face has a box, add the box thickness to the character
2536 height. If character has a box line to the left and/or
2537 right, add the box line width to the character's width. */
2538 if (face->box != FACE_NO_BOX)
2539 {
2540 int thick = face->box_line_width;
2541
2542 if (thick > 0)
2543 {
2544 it->ascent += thick;
2545 it->descent += thick;
2546 }
2547 else
2548 thick = -thick;
2549
2550 if (it->start_of_box_run_p)
2551 it->pixel_width += thick;
2552 if (it->end_of_box_run_p)
2553 it->pixel_width += thick;
2554 }
2555
2556 /* If face has an overline, add the height of the overline
2557 (1 pixel) and a 1 pixel margin to the character height. */
2558 if (face->overline_p)
2559 it->ascent += 2;
2560
2561 take_vertical_position_into_account (it);
2562
2563 /* If we have to actually produce glyphs, do it. */
2564 if (it->glyph_row)
2565 {
2566 if (stretched_p)
2567 {
2568 /* Translate a space with a `space-width' property
2569 into a stretch glyph. */
2570 double ascent = (double) FONT_BASE (font)
2571 / FONT_HEIGHT (font);
2572 x_append_stretch_glyph (it, it->object, it->pixel_width,
2573 it->ascent + it->descent, ascent);
2574 }
2575 else
2576 x_append_glyph (it);
2577
2578 /* If characters with lbearing or rbearing are displayed
2579 in this line, record that fact in a flag of the
2580 glyph row. This is used to optimize X output code. */
2581 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2582 it->glyph_row->contains_overlapping_glyphs_p = 1;
2583 }
2584 }
2585 else if (it->char_to_display == '\n')
2586 {
2587 /* A newline has no width but we need the height of the line. */
2588 it->pixel_width = 0;
2589 it->nglyphs = 0;
2590 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2591 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2592
2593 if (face->box != FACE_NO_BOX
2594 && face->box_line_width > 0)
2595 {
2596 it->ascent += face->box_line_width;
2597 it->descent += face->box_line_width;
2598 }
2599 }
2600 else if (it->char_to_display == '\t')
2601 {
2602 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2603 int x = it->current_x + it->continuation_lines_width;
2604 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2605
2606 /* If the distance from the current position to the next tab
2607 stop is less than a canonical character width, use the
2608 tab stop after that. */
2609 if (next_tab_x - x < CANON_X_UNIT (it->f))
2610 next_tab_x += tab_width;
2611
2612 it->pixel_width = next_tab_x - x;
2613 it->nglyphs = 1;
2614 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2615 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2616
2617 if (it->glyph_row)
2618 {
2619 double ascent = (double) it->ascent / (it->ascent + it->descent);
2620 x_append_stretch_glyph (it, it->object, it->pixel_width,
2621 it->ascent + it->descent, ascent);
2622 }
2623 }
2624 else
2625 {
2626 /* A multi-byte character. Assume that the display width of the
2627 character is the width of the character multiplied by the
2628 width of the font. */
2629
2630 /* If we found a font, this font should give us the right
2631 metrics. If we didn't find a font, use the frame's
2632 default font and calculate the width of the character
2633 from the charset width; this is what old redisplay code
2634 did. */
2635 pcm = x_per_char_metric (font, &char2b);
2636 if (font_not_found_p || !pcm)
2637 {
2638 int charset = CHAR_CHARSET (it->char_to_display);
2639
2640 it->glyph_not_available_p = 1;
2641 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2642 * CHARSET_WIDTH (charset));
2643 it->phys_ascent = FONT_BASE (font) + boff;
2644 it->phys_descent = FONT_DESCENT (font) - boff;
2645 }
2646 else
2647 {
2648 it->pixel_width = pcm->width;
2649 it->phys_ascent = pcm->ascent + boff;
2650 it->phys_descent = pcm->descent - boff;
2651 if (it->glyph_row
2652 && (pcm->lbearing < 0
2653 || pcm->rbearing > pcm->width))
2654 it->glyph_row->contains_overlapping_glyphs_p = 1;
2655 }
2656 it->nglyphs = 1;
2657 it->ascent = FONT_BASE (font) + boff;
2658 it->descent = FONT_DESCENT (font) - boff;
2659 if (face->box != FACE_NO_BOX)
2660 {
2661 int thick = face->box_line_width;
2662
2663 if (thick > 0)
2664 {
2665 it->ascent += thick;
2666 it->descent += thick;
2667 }
2668 else
2669 thick = - thick;
2670
2671 if (it->start_of_box_run_p)
2672 it->pixel_width += thick;
2673 if (it->end_of_box_run_p)
2674 it->pixel_width += thick;
2675 }
2676
2677 /* If face has an overline, add the height of the overline
2678 (1 pixel) and a 1 pixel margin to the character height. */
2679 if (face->overline_p)
2680 it->ascent += 2;
2681
2682 take_vertical_position_into_account (it);
2683
2684 if (it->glyph_row)
2685 x_append_glyph (it);
2686 }
2687 it->multibyte_p = saved_multibyte_p;
2688 }
2689 else if (it->what == IT_COMPOSITION)
2690 {
2691 /* Note: A composition is represented as one glyph in the
2692 glyph matrix. There are no padding glyphs. */
2693 XChar2b char2b;
2694 XFontStruct *font;
2695 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2696 XCharStruct *pcm;
2697 int font_not_found_p;
2698 struct font_info *font_info;
2699 int boff; /* baseline offset */
2700 struct composition *cmp = composition_table[it->cmp_id];
2701
2702 /* Maybe translate single-byte characters to multibyte. */
2703 it->char_to_display = it->c;
2704 if (unibyte_display_via_language_environment
2705 && SINGLE_BYTE_CHAR_P (it->c)
2706 && (it->c >= 0240
2707 || (it->c >= 0200
2708 && !NILP (Vnonascii_translation_table))))
2709 {
2710 it->char_to_display = unibyte_char_to_multibyte (it->c);
2711 }
2712
2713 /* Get face and font to use. Encode IT->char_to_display. */
2714 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2715 face = FACE_FROM_ID (it->f, it->face_id);
2716 x_get_char_face_and_encoding (it->f, it->char_to_display,
2717 it->face_id, &char2b, it->multibyte_p);
2718 font = face->font;
2719
2720 /* When no suitable font found, use the default font. */
2721 font_not_found_p = font == NULL;
2722 if (font_not_found_p)
2723 {
2724 font = FRAME_FONT (it->f);
2725 boff = it->f->output_data.mac->baseline_offset;
2726 font_info = NULL;
2727 }
2728 else
2729 {
2730 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2731 boff = font_info->baseline_offset;
2732 if (font_info->vertical_centering)
2733 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2734 }
2735
2736 /* There are no padding glyphs, so there is only one glyph to
2737 produce for the composition. Important is that pixel_width,
2738 ascent and descent are the values of what is drawn by
2739 draw_glyphs (i.e. the values of the overall glyphs composed). */
2740 it->nglyphs = 1;
2741
2742 /* If we have not yet calculated pixel size data of glyphs of
2743 the composition for the current face font, calculate them
2744 now. Theoretically, we have to check all fonts for the
2745 glyphs, but that requires much time and memory space. So,
2746 here we check only the font of the first glyph. This leads
2747 to incorrect display very rarely, and C-l (recenter) can
2748 correct the display anyway. */
2749 if (cmp->font != (void *) font)
2750 {
2751 /* Ascent and descent of the font of the first character of
2752 this composition (adjusted by baseline offset). Ascent
2753 and descent of overall glyphs should not be less than
2754 them respectively. */
2755 int font_ascent = FONT_BASE (font) + boff;
2756 int font_descent = FONT_DESCENT (font) - boff;
2757 /* Bounding box of the overall glyphs. */
2758 int leftmost, rightmost, lowest, highest;
2759 int i, width, ascent, descent;
2760
2761 cmp->font = (void *) font;
2762
2763 /* Initialize the bounding box. */
2764 pcm = x_per_char_metric (font, &char2b);
2765 if (pcm)
2766 {
2767 width = pcm->width;
2768 ascent = pcm->ascent;
2769 descent = pcm->descent;
2770 }
2771 else
2772 {
2773 width = FONT_WIDTH (font);
2774 ascent = FONT_BASE (font);
2775 descent = FONT_DESCENT (font);
2776 }
2777
2778 rightmost = width;
2779 lowest = - descent + boff;
2780 highest = ascent + boff;
2781 leftmost = 0;
2782
2783 if (font_info
2784 && font_info->default_ascent
2785 && CHAR_TABLE_P (Vuse_default_ascent)
2786 && !NILP (Faref (Vuse_default_ascent,
2787 make_number (it->char_to_display))))
2788 highest = font_info->default_ascent + boff;
2789
2790 /* Draw the first glyph at the normal position. It may be
2791 shifted to right later if some other glyphs are drawn at
2792 the left. */
2793 cmp->offsets[0] = 0;
2794 cmp->offsets[1] = boff;
2795
2796 /* Set cmp->offsets for the remaining glyphs. */
2797 for (i = 1; i < cmp->glyph_len; i++)
2798 {
2799 int left, right, btm, top;
2800 int ch = COMPOSITION_GLYPH (cmp, i);
2801 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2802
2803 face = FACE_FROM_ID (it->f, face_id);
2804 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2805 it->multibyte_p);
2806 font = face->font;
2807 if (font == NULL)
2808 {
2809 font = FRAME_FONT (it->f);
2810 boff = it->f->output_data.mac->baseline_offset;
2811 font_info = NULL;
2812 }
2813 else
2814 {
2815 font_info
2816 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2817 boff = font_info->baseline_offset;
2818 if (font_info->vertical_centering)
2819 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2820 }
2821
2822 pcm = x_per_char_metric (font, &char2b);
2823 if (pcm)
2824 {
2825 width = pcm->width;
2826 ascent = pcm->ascent;
2827 descent = pcm->descent;
2828 }
2829 else
2830 {
2831 width = FONT_WIDTH (font);
2832 ascent = 1;
2833 descent = 0;
2834 }
2835
2836 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2837 {
2838 /* Relative composition with or without
2839 alternate chars. */
2840 left = (leftmost + rightmost - width) / 2;
2841 btm = - descent + boff;
2842 if (font_info && font_info->relative_compose
2843 && (! CHAR_TABLE_P (Vignore_relative_composition)
2844 || NILP (Faref (Vignore_relative_composition,
2845 make_number (ch)))))
2846 {
2847
2848 if (- descent >= font_info->relative_compose)
2849 /* One extra pixel between two glyphs. */
2850 btm = highest + 1;
2851 else if (ascent <= 0)
2852 /* One extra pixel between two glyphs. */
2853 btm = lowest - 1 - ascent - descent;
2854 }
2855 }
2856 else
2857 {
2858 /* A composition rule is specified by an integer
2859 value that encodes global and new reference
2860 points (GREF and NREF). GREF and NREF are
2861 specified by numbers as below:
2862
2863 0---1---2 -- ascent
2864 | |
2865 | |
2866 | |
2867 9--10--11 -- center
2868 | |
2869 ---3---4---5--- baseline
2870 | |
2871 6---7---8 -- descent
2872 */
2873 int rule = COMPOSITION_RULE (cmp, i);
2874 int gref, nref, grefx, grefy, nrefx, nrefy;
2875
2876 COMPOSITION_DECODE_RULE (rule, gref, nref);
2877 grefx = gref % 3, nrefx = nref % 3;
2878 grefy = gref / 3, nrefy = nref / 3;
2879
2880 left = (leftmost
2881 + grefx * (rightmost - leftmost) / 2
2882 - nrefx * width / 2);
2883 btm = ((grefy == 0 ? highest
2884 : grefy == 1 ? 0
2885 : grefy == 2 ? lowest
2886 : (highest + lowest) / 2)
2887 - (nrefy == 0 ? ascent + descent
2888 : nrefy == 1 ? descent - boff
2889 : nrefy == 2 ? 0
2890 : (ascent + descent) / 2));
2891 }
2892
2893 cmp->offsets[i * 2] = left;
2894 cmp->offsets[i * 2 + 1] = btm + descent;
2895
2896 /* Update the bounding box of the overall glyphs. */
2897 right = left + width;
2898 top = btm + descent + ascent;
2899 if (left < leftmost)
2900 leftmost = left;
2901 if (right > rightmost)
2902 rightmost = right;
2903 if (top > highest)
2904 highest = top;
2905 if (btm < lowest)
2906 lowest = btm;
2907 }
2908
2909 /* If there are glyphs whose x-offsets are negative,
2910 shift all glyphs to the right and make all x-offsets
2911 non-negative. */
2912 if (leftmost < 0)
2913 {
2914 for (i = 0; i < cmp->glyph_len; i++)
2915 cmp->offsets[i * 2] -= leftmost;
2916 rightmost -= leftmost;
2917 }
2918
2919 cmp->pixel_width = rightmost;
2920 cmp->ascent = highest;
2921 cmp->descent = - lowest;
2922 if (cmp->ascent < font_ascent)
2923 cmp->ascent = font_ascent;
2924 if (cmp->descent < font_descent)
2925 cmp->descent = font_descent;
2926 }
2927
2928 it->pixel_width = cmp->pixel_width;
2929 it->ascent = it->phys_ascent = cmp->ascent;
2930 it->descent = it->phys_descent = cmp->descent;
2931
2932 if (face->box != FACE_NO_BOX)
2933 {
2934 int thick = face->box_line_width;
2935
2936 if (thick > 0)
2937 {
2938 it->ascent += thick;
2939 it->descent += thick;
2940 }
2941 else
2942 thick = - thick;
2943
2944 if (it->start_of_box_run_p)
2945 it->pixel_width += thick;
2946 if (it->end_of_box_run_p)
2947 it->pixel_width += thick;
2948 }
2949
2950 /* If face has an overline, add the height of the overline
2951 (1 pixel) and a 1 pixel margin to the character height. */
2952 if (face->overline_p)
2953 it->ascent += 2;
2954
2955 take_vertical_position_into_account (it);
2956
2957 if (it->glyph_row)
2958 x_append_composite_glyph (it);
2959 }
2960 else if (it->what == IT_IMAGE)
2961 x_produce_image_glyph (it);
2962 else if (it->what == IT_STRETCH)
2963 x_produce_stretch_glyph (it);
2964
2965 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2966 because this isn't true for images with `:ascent 100'. */
2967 xassert (it->ascent >= 0 && it->descent >= 0);
2968 if (it->area == TEXT_AREA)
2969 it->current_x += it->pixel_width;
2970
2971 it->descent += it->extra_line_spacing;
2972
2973 it->max_ascent = max (it->max_ascent, it->ascent);
2974 it->max_descent = max (it->max_descent, it->descent);
2975 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2976 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2977 }
2978
2979
2980 /* Estimate the pixel height of the mode or top line on frame F.
2981 FACE_ID specifies what line's height to estimate. */
2982
2983 int
2984 x_estimate_mode_line_height (f, face_id)
2985 struct frame *f;
2986 enum face_id face_id;
2987 {
2988 int height = FONT_HEIGHT (FRAME_FONT (f));
2989
2990 /* This function is called so early when Emacs starts that the face
2991 cache and mode line face are not yet initialized. */
2992 if (FRAME_FACE_CACHE (f))
2993 {
2994 struct face *face = FACE_FROM_ID (f, face_id);
2995 if (face)
2996 {
2997 if (face->font)
2998 height = FONT_HEIGHT (face->font);
2999 if (face->box_line_width > 0)
3000 height += 2 * face->box_line_width;
3001 }
3002 }
3003
3004 return height;
3005 }
3006
3007 \f
3008 /***********************************************************************
3009 Glyph display
3010 ***********************************************************************/
3011
3012 /* A sequence of glyphs to be drawn in the same face.
3013
3014 This data structure is not really completely X specific, so it
3015 could possibly, at least partially, be useful for other systems. It
3016 is currently not part of the external redisplay interface because
3017 it's not clear what other systems will need. */
3018
3019 struct glyph_string
3020 {
3021 /* X-origin of the string. */
3022 int x;
3023
3024 /* Y-origin and y-position of the base line of this string. */
3025 int y, ybase;
3026
3027 /* The width of the string, not including a face extension. */
3028 int width;
3029
3030 /* The width of the string, including a face extension. */
3031 int background_width;
3032
3033 /* The height of this string. This is the height of the line this
3034 string is drawn in, and can be different from the height of the
3035 font the string is drawn in. */
3036 int height;
3037
3038 /* Number of pixels this string overwrites in front of its x-origin.
3039 This number is zero if the string has an lbearing >= 0; it is
3040 -lbearing, if the string has an lbearing < 0. */
3041 int left_overhang;
3042
3043 /* Number of pixels this string overwrites past its right-most
3044 nominal x-position, i.e. x + width. Zero if the string's
3045 rbearing is <= its nominal width, rbearing - width otherwise. */
3046 int right_overhang;
3047
3048 /* The frame on which the glyph string is drawn. */
3049 struct frame *f;
3050
3051 /* The window on which the glyph string is drawn. */
3052 struct window *w;
3053
3054 /* X display and window for convenience. */
3055 Display *display;
3056 Window window;
3057
3058 /* The glyph row for which this string was built. It determines the
3059 y-origin and height of the string. */
3060 struct glyph_row *row;
3061
3062 /* The area within row. */
3063 enum glyph_row_area area;
3064
3065 /* Characters to be drawn, and number of characters. */
3066 XChar2b *char2b;
3067 int nchars;
3068
3069 /* A face-override for drawing cursors, mouse face and similar. */
3070 enum draw_glyphs_face hl;
3071
3072 /* Face in which this string is to be drawn. */
3073 struct face *face;
3074
3075 /* Font in which this string is to be drawn. */
3076 XFontStruct *font;
3077
3078 /* Font info for this string. */
3079 struct font_info *font_info;
3080
3081 /* Non-null means this string describes (part of) a composition.
3082 All characters from char2b are drawn composed. */
3083 struct composition *cmp;
3084
3085 /* Index of this glyph string's first character in the glyph
3086 definition of CMP. If this is zero, this glyph string describes
3087 the first character of a composition. */
3088 int gidx;
3089
3090 /* 1 means this glyph strings face has to be drawn to the right end
3091 of the window's drawing area. */
3092 unsigned extends_to_end_of_line_p : 1;
3093
3094 /* 1 means the background of this string has been drawn. */
3095 unsigned background_filled_p : 1;
3096
3097 /* 1 means glyph string must be drawn with 16-bit functions. */
3098 unsigned two_byte_p : 1;
3099
3100 /* 1 means that the original font determined for drawing this glyph
3101 string could not be loaded. The member `font' has been set to
3102 the frame's default font in this case. */
3103 unsigned font_not_found_p : 1;
3104
3105 /* 1 means that the face in which this glyph string is drawn has a
3106 stipple pattern. */
3107 unsigned stippled_p : 1;
3108
3109 /* 1 means only the foreground of this glyph string must be drawn,
3110 and we should use the physical height of the line this glyph
3111 string appears in as clip rect. */
3112 unsigned for_overlaps_p : 1;
3113
3114 /* The GC to use for drawing this glyph string. */
3115 GC gc;
3116
3117 /* A pointer to the first glyph in the string. This glyph
3118 corresponds to char2b[0]. Needed to draw rectangles if
3119 font_not_found_p is 1. */
3120 struct glyph *first_glyph;
3121
3122 /* Image, if any. */
3123 struct image *img;
3124
3125 struct glyph_string *next, *prev;
3126 };
3127
3128
3129 #if 0
3130
3131 static void
3132 x_dump_glyph_string (s)
3133 struct glyph_string *s;
3134 {
3135 fprintf (stderr, "glyph string\n");
3136 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
3137 s->x, s->y, s->width, s->height);
3138 fprintf (stderr, " ybase = %d\n", s->ybase);
3139 fprintf (stderr, " hl = %d\n", s->hl);
3140 fprintf (stderr, " left overhang = %d, right = %d\n",
3141 s->left_overhang, s->right_overhang);
3142 fprintf (stderr, " nchars = %d\n", s->nchars);
3143 fprintf (stderr, " extends to end of line = %d\n",
3144 s->extends_to_end_of_line_p);
3145 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
3146 fprintf (stderr, " bg width = %d\n", s->background_width);
3147 }
3148
3149 #endif /* GLYPH_DEBUG */
3150
3151
3152
3153 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
3154 struct glyph_string **,
3155 struct glyph_string *,
3156 struct glyph_string *));
3157 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
3158 struct glyph_string **,
3159 struct glyph_string *,
3160 struct glyph_string *));
3161 static void x_append_glyph_string P_ ((struct glyph_string **,
3162 struct glyph_string **,
3163 struct glyph_string *));
3164 static int x_left_overwritten P_ ((struct glyph_string *));
3165 static int x_left_overwriting P_ ((struct glyph_string *));
3166 static int x_right_overwritten P_ ((struct glyph_string *));
3167 static int x_right_overwriting P_ ((struct glyph_string *));
3168 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
3169 int));
3170 static void x_init_glyph_string P_ ((struct glyph_string *,
3171 XChar2b *, struct window *,
3172 struct glyph_row *,
3173 enum glyph_row_area, int,
3174 enum draw_glyphs_face));
3175 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
3176 enum glyph_row_area, int, int,
3177 enum draw_glyphs_face, int));
3178 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
3179 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
3180 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
3181 int));
3182 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
3183 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
3184 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
3185 static void x_draw_glyph_string P_ ((struct glyph_string *));
3186 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
3187 static void x_set_cursor_gc P_ ((struct glyph_string *));
3188 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
3189 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
3190 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
3191 int *, int *));
3192 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
3193 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
3194 unsigned long *, double, int));*/
3195 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
3196 double, int, unsigned long));
3197 static void x_setup_relief_colors P_ ((struct glyph_string *));
3198 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
3199 static void x_draw_image_relief P_ ((struct glyph_string *));
3200 static void x_draw_image_foreground P_ ((struct glyph_string *));
3201 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
3202 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
3203 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
3204 int, int, int));
3205 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
3206 int, int, int, int, Rect *));
3207 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
3208 int, int, int, Rect *));
3209 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
3210 enum glyph_row_area));
3211 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
3212 struct glyph_row *,
3213 enum glyph_row_area, int, int));
3214
3215 #if GLYPH_DEBUG
3216 static void x_check_font P_ ((struct frame *, XFontStruct *));
3217 #endif
3218
3219
3220 /* Append the list of glyph strings with head H and tail T to the list
3221 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
3222
3223 static INLINE void
3224 x_append_glyph_string_lists (head, tail, h, t)
3225 struct glyph_string **head, **tail;
3226 struct glyph_string *h, *t;
3227 {
3228 if (h)
3229 {
3230 if (*head)
3231 (*tail)->next = h;
3232 else
3233 *head = h;
3234 h->prev = *tail;
3235 *tail = t;
3236 }
3237 }
3238
3239
3240 /* Prepend the list of glyph strings with head H and tail T to the
3241 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
3242 result. */
3243
3244 static INLINE void
3245 x_prepend_glyph_string_lists (head, tail, h, t)
3246 struct glyph_string **head, **tail;
3247 struct glyph_string *h, *t;
3248 {
3249 if (h)
3250 {
3251 if (*head)
3252 (*head)->prev = t;
3253 else
3254 *tail = t;
3255 t->next = *head;
3256 *head = h;
3257 }
3258 }
3259
3260
3261 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
3262 Set *HEAD and *TAIL to the resulting list. */
3263
3264 static INLINE void
3265 x_append_glyph_string (head, tail, s)
3266 struct glyph_string **head, **tail;
3267 struct glyph_string *s;
3268 {
3269 s->next = s->prev = NULL;
3270 x_append_glyph_string_lists (head, tail, s, s);
3271 }
3272
3273
3274 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
3275 face. */
3276
3277 static void
3278 x_set_cursor_gc (s)
3279 struct glyph_string *s;
3280 {
3281 if (s->font == FRAME_FONT (s->f)
3282 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
3283 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
3284 && !s->cmp)
3285 s->gc = s->f->output_data.mac->cursor_gc;
3286 else
3287 {
3288 /* Cursor on non-default face: must merge. */
3289 XGCValues xgcv;
3290 unsigned long mask;
3291
3292 xgcv.background = s->f->output_data.mac->cursor_pixel;
3293 xgcv.foreground = s->face->background;
3294
3295 /* If the glyph would be invisible, try a different foreground. */
3296 if (xgcv.foreground == xgcv.background)
3297 xgcv.foreground = s->face->foreground;
3298 if (xgcv.foreground == xgcv.background)
3299 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
3300 if (xgcv.foreground == xgcv.background)
3301 xgcv.foreground = s->face->foreground;
3302
3303 /* Make sure the cursor is distinct from text in this face. */
3304 if (xgcv.background == s->face->background
3305 && xgcv.foreground == s->face->foreground)
3306 {
3307 xgcv.background = s->face->foreground;
3308 xgcv.foreground = s->face->background;
3309 }
3310
3311 IF_DEBUG (x_check_font (s->f, s->font));
3312 xgcv.font = s->font;
3313 mask = GCForeground | GCBackground | GCFont;
3314
3315 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3316 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3317 mask, &xgcv);
3318 else
3319 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3320 = XCreateGC (s->display, s->window, mask, &xgcv);
3321
3322 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3323 }
3324 }
3325
3326
3327 /* Set up S->gc of glyph string S for drawing text in mouse face. */
3328
3329 static void
3330 x_set_mouse_face_gc (s)
3331 struct glyph_string *s;
3332 {
3333 int face_id;
3334 struct face *face;
3335
3336 /* What face has to be used last for the mouse face? */
3337 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
3338 face = FACE_FROM_ID (s->f, face_id);
3339 if (face == NULL)
3340 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
3341
3342 if (s->first_glyph->type == CHAR_GLYPH)
3343 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
3344 else
3345 face_id = FACE_FOR_CHAR (s->f, face, 0);
3346 s->face = FACE_FROM_ID (s->f, face_id);
3347 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3348
3349 /* If font in this face is same as S->font, use it. */
3350 if (s->font == s->face->font)
3351 s->gc = s->face->gc;
3352 else
3353 {
3354 /* Otherwise construct scratch_cursor_gc with values from FACE
3355 but font FONT. */
3356 XGCValues xgcv;
3357 unsigned long mask;
3358
3359 xgcv.background = s->face->background;
3360 xgcv.foreground = s->face->foreground;
3361 IF_DEBUG (x_check_font (s->f, s->font));
3362 xgcv.font = s->font;
3363 mask = GCForeground | GCBackground | GCFont;
3364
3365 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3366 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3367 mask, &xgcv);
3368 else
3369 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
3370 = XCreateGC (s->display, s->window, mask, &xgcv);
3371
3372 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3373 }
3374
3375 xassert (s->gc != 0);
3376 }
3377
3378
3379 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3380 Faces to use in the mode line have already been computed when the
3381 matrix was built, so there isn't much to do, here. */
3382
3383 static INLINE void
3384 x_set_mode_line_face_gc (s)
3385 struct glyph_string *s;
3386 {
3387 s->gc = s->face->gc;
3388 }
3389
3390
3391 /* Set S->gc of glyph string S for drawing that glyph string. Set
3392 S->stippled_p to a non-zero value if the face of S has a stipple
3393 pattern. */
3394
3395 static INLINE void
3396 x_set_glyph_string_gc (s)
3397 struct glyph_string *s;
3398 {
3399 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3400
3401 if (s->hl == DRAW_NORMAL_TEXT)
3402 {
3403 s->gc = s->face->gc;
3404 s->stippled_p = s->face->stipple != 0;
3405 }
3406 else if (s->hl == DRAW_INVERSE_VIDEO)
3407 {
3408 x_set_mode_line_face_gc (s);
3409 s->stippled_p = s->face->stipple != 0;
3410 }
3411 else if (s->hl == DRAW_CURSOR)
3412 {
3413 x_set_cursor_gc (s);
3414 s->stippled_p = 0;
3415 }
3416 else if (s->hl == DRAW_MOUSE_FACE)
3417 {
3418 x_set_mouse_face_gc (s);
3419 s->stippled_p = s->face->stipple != 0;
3420 }
3421 else if (s->hl == DRAW_IMAGE_RAISED
3422 || s->hl == DRAW_IMAGE_SUNKEN)
3423 {
3424 s->gc = s->face->gc;
3425 s->stippled_p = s->face->stipple != 0;
3426 }
3427 else
3428 {
3429 s->gc = s->face->gc;
3430 s->stippled_p = s->face->stipple != 0;
3431 }
3432
3433 /* GC must have been set. */
3434 xassert (s->gc != 0);
3435 }
3436
3437
3438 /* Return in *R the clipping rectangle for glyph string S. */
3439
3440 static void
3441 x_get_glyph_string_clip_rect (s, r)
3442 struct glyph_string *s;
3443 Rect *r;
3444 {
3445 int r_height, r_width;
3446
3447 if (s->row->full_width_p)
3448 {
3449 /* Draw full-width. X coordinates are relative to S->w->left. */
3450 int canon_x = CANON_X_UNIT (s->f);
3451
3452 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3453 r_width = XFASTINT (s->w->width) * canon_x;
3454
3455 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3456 {
3457 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3458 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3459 r->left -= width;
3460 }
3461
3462 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3463
3464 /* Unless displaying a mode or menu bar line, which are always
3465 fully visible, clip to the visible part of the row. */
3466 if (s->w->pseudo_window_p)
3467 r_height = s->row->visible_height;
3468 else
3469 r_height = s->height;
3470 }
3471 else
3472 {
3473 /* This is a text line that may be partially visible. */
3474 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3475 r_width = window_box_width (s->w, s->area);
3476 r_height = s->row->visible_height;
3477 }
3478
3479 /* If S draws overlapping rows, it's sufficient to use the top and
3480 bottom of the window for clipping because this glyph string
3481 intentionally draws over other lines. */
3482 if (s->for_overlaps_p)
3483 {
3484 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3485 r_height = window_text_bottom_y (s->w) - r->top;
3486 }
3487 else
3488 {
3489 /* Don't use S->y for clipping because it doesn't take partially
3490 visible lines into account. For example, it can be negative for
3491 partially visible lines at the top of a window. */
3492 if (!s->row->full_width_p
3493 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3494 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3495 else
3496 r->top = max (0, s->row->y);
3497
3498 /* If drawing a tool-bar window, draw it over the internal border
3499 at the top of the window. */
3500 if (s->w == XWINDOW (s->f->tool_bar_window))
3501 r->top -= s->f->output_data.mac->internal_border_width;
3502 }
3503
3504 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3505
3506 r->bottom = r->top + r_height;
3507 r->right = r->left + r_width;
3508 }
3509
3510
3511 /* Set clipping for output of glyph string S. S may be part of a mode
3512 line or menu if we don't have X toolkit support. */
3513
3514 static INLINE void
3515 x_set_glyph_string_clipping (s)
3516 struct glyph_string *s;
3517 {
3518 Rect r;
3519 x_get_glyph_string_clip_rect (s, &r);
3520 mac_set_clip_rectangle (s->display, s->window, &r);
3521 }
3522
3523
3524 /* Compute left and right overhang of glyph string S. If S is a glyph
3525 string for a composition, assume overhangs don't exist. */
3526
3527 static INLINE void
3528 x_compute_glyph_string_overhangs (s)
3529 struct glyph_string *s;
3530 {
3531 if (s->cmp == NULL
3532 && s->first_glyph->type == CHAR_GLYPH)
3533 {
3534 XCharStruct cs;
3535 int direction, font_ascent, font_descent;
3536 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
3537 &font_ascent, &font_descent, &cs);
3538 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
3539 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
3540 }
3541 }
3542
3543
3544 /* Compute overhangs and x-positions for glyph string S and its
3545 predecessors, or successors. X is the starting x-position for S.
3546 BACKWARD_P non-zero means process predecessors. */
3547
3548 static void
3549 x_compute_overhangs_and_x (s, x, backward_p)
3550 struct glyph_string *s;
3551 int x;
3552 int backward_p;
3553 {
3554 if (backward_p)
3555 {
3556 while (s)
3557 {
3558 x_compute_glyph_string_overhangs (s);
3559 x -= s->width;
3560 s->x = x;
3561 s = s->prev;
3562 }
3563 }
3564 else
3565 {
3566 while (s)
3567 {
3568 x_compute_glyph_string_overhangs (s);
3569 s->x = x;
3570 x += s->width;
3571 s = s->next;
3572 }
3573 }
3574 }
3575
3576
3577 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3578 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3579 assumed to be zero. */
3580
3581 void
3582 x_get_glyph_overhangs (glyph, f, left, right)
3583 struct glyph *glyph;
3584 struct frame *f;
3585 int *left, *right;
3586 {
3587 *left = *right = 0;
3588
3589 if (glyph->type == CHAR_GLYPH)
3590 {
3591 XFontStruct *font;
3592 struct face *face;
3593 struct font_info *font_info;
3594 XChar2b char2b;
3595 XCharStruct *pcm;
3596
3597 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3598 font = face->font;
3599 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
3600 if (font
3601 && (pcm = x_per_char_metric (font, &char2b)))
3602 {
3603 if (pcm->rbearing > pcm->width)
3604 *right = pcm->rbearing - pcm->width;
3605 if (pcm->lbearing < 0)
3606 *left = -pcm->lbearing;
3607 }
3608 }
3609 }
3610
3611
3612 /* Return the index of the first glyph preceding glyph string S that
3613 is overwritten by S because of S's left overhang. Value is -1
3614 if no glyphs are overwritten. */
3615
3616 static int
3617 x_left_overwritten (s)
3618 struct glyph_string *s;
3619 {
3620 int k;
3621
3622 if (s->left_overhang)
3623 {
3624 int x = 0, i;
3625 struct glyph *glyphs = s->row->glyphs[s->area];
3626 int first = s->first_glyph - glyphs;
3627
3628 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3629 x -= glyphs[i].pixel_width;
3630
3631 k = i + 1;
3632 }
3633 else
3634 k = -1;
3635
3636 return k;
3637 }
3638
3639
3640 /* Return the index of the first glyph preceding glyph string S that
3641 is overwriting S because of its right overhang. Value is -1 if no
3642 glyph in front of S overwrites S. */
3643
3644 static int
3645 x_left_overwriting (s)
3646 struct glyph_string *s;
3647 {
3648 int i, k, x;
3649 struct glyph *glyphs = s->row->glyphs[s->area];
3650 int first = s->first_glyph - glyphs;
3651
3652 k = -1;
3653 x = 0;
3654 for (i = first - 1; i >= 0; --i)
3655 {
3656 int left, right;
3657 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3658 if (x + right > 0)
3659 k = i;
3660 x -= glyphs[i].pixel_width;
3661 }
3662
3663 return k;
3664 }
3665
3666
3667 /* Return the index of the last glyph following glyph string S that is
3668 not overwritten by S because of S's right overhang. Value is -1 if
3669 no such glyph is found. */
3670
3671 static int
3672 x_right_overwritten (s)
3673 struct glyph_string *s;
3674 {
3675 int k = -1;
3676
3677 if (s->right_overhang)
3678 {
3679 int x = 0, i;
3680 struct glyph *glyphs = s->row->glyphs[s->area];
3681 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3682 int end = s->row->used[s->area];
3683
3684 for (i = first; i < end && s->right_overhang > x; ++i)
3685 x += glyphs[i].pixel_width;
3686
3687 k = i;
3688 }
3689
3690 return k;
3691 }
3692
3693
3694 /* Return the index of the last glyph following glyph string S that
3695 overwrites S because of its left overhang. Value is negative
3696 if no such glyph is found. */
3697
3698 static int
3699 x_right_overwriting (s)
3700 struct glyph_string *s;
3701 {
3702 int i, k, x;
3703 int end = s->row->used[s->area];
3704 struct glyph *glyphs = s->row->glyphs[s->area];
3705 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3706
3707 k = -1;
3708 x = 0;
3709 for (i = first; i < end; ++i)
3710 {
3711 int left, right;
3712 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3713 if (x - left < 0)
3714 k = i;
3715 x += glyphs[i].pixel_width;
3716 }
3717
3718 return k;
3719 }
3720
3721
3722 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3723
3724 static INLINE void
3725 x_clear_glyph_string_rect (s, x, y, w, h)
3726 struct glyph_string *s;
3727 int x, y, w, h;
3728 {
3729 XGCValues xgcv;
3730
3731 xgcv.foreground = s->gc->background;
3732 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
3733 }
3734
3735
3736 /* Draw the background of glyph_string S. If S->background_filled_p
3737 is non-zero don't draw it. FORCE_P non-zero means draw the
3738 background even if it wouldn't be drawn normally. This is used
3739 when a string preceding S draws into the background of S, or S
3740 contains the first component of a composition. */
3741
3742 static void
3743 x_draw_glyph_string_background (s, force_p)
3744 struct glyph_string *s;
3745 int force_p;
3746 {
3747 /* Nothing to do if background has already been drawn or if it
3748 shouldn't be drawn in the first place. */
3749 if (!s->background_filled_p)
3750 {
3751 int box_line_width = max (s->face->box_line_width, 0);
3752
3753 #if 0 /* MAC_TODO: stipple */
3754 if (s->stippled_p)
3755 {
3756 /* Fill background with a stipple pattern. */
3757 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3758 XFillRectangle (s->display, s->window, s->gc, s->x,
3759 s->y + box_line_width,
3760 s->background_width,
3761 s->height - 2 * box_line_width);
3762 XSetFillStyle (s->display, s->gc, FillSolid);
3763 s->background_filled_p = 1;
3764 }
3765 else
3766 #endif
3767 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3768 || s->font_not_found_p
3769 || s->extends_to_end_of_line_p
3770 || force_p)
3771 {
3772 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3773 s->background_width,
3774 s->height - 2 * box_line_width);
3775 s->background_filled_p = 1;
3776 }
3777 }
3778 }
3779
3780
3781 /* Draw the foreground of glyph string S. */
3782
3783 static void
3784 x_draw_glyph_string_foreground (s)
3785 struct glyph_string *s;
3786 {
3787 int i, x;
3788
3789 /* If first glyph of S has a left box line, start drawing the text
3790 of S to the right of that box line. */
3791 if (s->face->box != FACE_NO_BOX
3792 && s->first_glyph->left_box_line_p)
3793 x = s->x + abs (s->face->box_line_width);
3794 else
3795 x = s->x;
3796
3797 /* Draw characters of S as rectangles if S's font could not be
3798 loaded. */
3799 if (s->font_not_found_p)
3800 {
3801 for (i = 0; i < s->nchars; ++i)
3802 {
3803 struct glyph *g = s->first_glyph + i;
3804 mac_draw_rectangle (s->display, s->window,
3805 s->gc, x, s->y, g->pixel_width - 1,
3806 s->height - 1);
3807 x += g->pixel_width;
3808 }
3809 }
3810 else
3811 {
3812 char *char1b = (char *) s->char2b;
3813 int boff = s->font_info->baseline_offset;
3814
3815 if (s->font_info->vertical_centering)
3816 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3817
3818 /* If we can use 8-bit functions, condense S->char2b. */
3819 if (!s->two_byte_p)
3820 for (i = 0; i < s->nchars; ++i)
3821 char1b[i] = s->char2b[i].byte2;
3822
3823 /* Draw text with XDrawString if background has already been
3824 filled. Otherwise, use XDrawImageString. (Note that
3825 XDrawImageString is usually faster than XDrawString.) Always
3826 use XDrawImageString when drawing the cursor so that there is
3827 no chance that characters under a box cursor are invisible. */
3828 if (s->for_overlaps_p
3829 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3830 {
3831 /* Draw characters with 16-bit or 8-bit functions. */
3832 if (s->two_byte_p)
3833 XDrawString16 (s->display, s->window, s->gc, x,
3834 s->ybase - boff, s->char2b, s->nchars);
3835 else
3836 XDrawString (s->display, s->window, s->gc, x,
3837 s->ybase - boff, char1b, s->nchars);
3838 }
3839 else
3840 {
3841 if (s->two_byte_p)
3842 XDrawImageString16 (s->display, s->window, s->gc, x,
3843 s->ybase - boff, s->char2b, s->nchars);
3844 else
3845 XDrawImageString (s->display, s->window, s->gc, x,
3846 s->ybase - boff, char1b, s->nchars);
3847 }
3848 }
3849 }
3850
3851 /* Draw the foreground of composite glyph string S. */
3852
3853 static void
3854 x_draw_composite_glyph_string_foreground (s)
3855 struct glyph_string *s;
3856 {
3857 int i, x;
3858
3859 /* If first glyph of S has a left box line, start drawing the text
3860 of S to the right of that box line. */
3861 if (s->face->box != FACE_NO_BOX
3862 && s->first_glyph->left_box_line_p)
3863 x = s->x + abs (s->face->box_line_width);
3864 else
3865 x = s->x;
3866
3867 /* S is a glyph string for a composition. S->gidx is the index of
3868 the first character drawn for glyphs of this composition.
3869 S->gidx == 0 means we are drawing the very first character of
3870 this composition. */
3871
3872 /* Draw a rectangle for the composition if the font for the very
3873 first character of the composition could not be loaded. */
3874 if (s->font_not_found_p)
3875 {
3876 if (s->gidx == 0)
3877 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
3878 s->width - 1, s->height - 1);
3879 }
3880 else
3881 {
3882 for (i = 0; i < s->nchars; i++, ++s->gidx)
3883 XDrawString16 (s->display, s->window, s->gc,
3884 x + s->cmp->offsets[s->gidx * 2],
3885 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3886 s->char2b + i, 1);
3887 }
3888 }
3889
3890
3891 #ifdef USE_X_TOOLKIT
3892
3893 static struct frame *x_frame_of_widget P_ ((Widget));
3894
3895
3896 /* Return the frame on which widget WIDGET is used.. Abort if frame
3897 cannot be determined. */
3898
3899 static struct frame *
3900 x_frame_of_widget (widget)
3901 Widget widget;
3902 {
3903 struct x_display_info *dpyinfo;
3904 Lisp_Object tail;
3905 struct frame *f;
3906
3907 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3908
3909 /* Find the top-level shell of the widget. Note that this function
3910 can be called when the widget is not yet realized, so XtWindow
3911 (widget) == 0. That's the reason we can't simply use
3912 x_any_window_to_frame. */
3913 while (!XtIsTopLevelShell (widget))
3914 widget = XtParent (widget);
3915
3916 /* Look for a frame with that top-level widget. Allocate the color
3917 on that frame to get the right gamma correction value. */
3918 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3919 if (GC_FRAMEP (XCAR (tail))
3920 && (f = XFRAME (XCAR (tail)),
3921 (f->output_data.nothing != 1
3922 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3923 && f->output_data.x->widget == widget)
3924 return f;
3925
3926 abort ();
3927 }
3928
3929
3930 /* Allocate the color COLOR->pixel on the screen and display of
3931 widget WIDGET in colormap CMAP. If an exact match cannot be
3932 allocated, try the nearest color available. Value is non-zero
3933 if successful. This is called from lwlib. */
3934
3935 int
3936 x_alloc_nearest_color_for_widget (widget, cmap, color)
3937 Widget widget;
3938 Colormap cmap;
3939 XColor *color;
3940 {
3941 struct frame *f = x_frame_of_widget (widget);
3942 return x_alloc_nearest_color (f, cmap, color);
3943 }
3944
3945
3946 #endif /* USE_X_TOOLKIT */
3947
3948 #if 0 /* MAC_TODO */
3949
3950 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3951 CMAP. If an exact match can't be allocated, try the nearest color
3952 available. Value is non-zero if successful. Set *COLOR to the
3953 color allocated. */
3954
3955 int
3956 x_alloc_nearest_color (f, cmap, color)
3957 struct frame *f;
3958 Colormap cmap;
3959 XColor *color;
3960 {
3961 Display *display = FRAME_X_DISPLAY (f);
3962 Screen *screen = FRAME_X_SCREEN (f);
3963 int rc;
3964
3965 gamma_correct (f, color);
3966 rc = XAllocColor (display, cmap, color);
3967 if (rc == 0)
3968 {
3969 /* If we got to this point, the colormap is full, so we're going
3970 to try to get the next closest color. The algorithm used is
3971 a least-squares matching, which is what X uses for closest
3972 color matching with StaticColor visuals. */
3973 int nearest, i;
3974 unsigned long nearest_delta = ~0;
3975 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3976 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3977
3978 for (i = 0; i < ncells; ++i)
3979 cells[i].pixel = i;
3980 XQueryColors (display, cmap, cells, ncells);
3981
3982 for (nearest = i = 0; i < ncells; ++i)
3983 {
3984 long dred = (color->red >> 8) - (cells[i].red >> 8);
3985 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3986 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3987 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3988
3989 if (delta < nearest_delta)
3990 {
3991 nearest = i;
3992 nearest_delta = delta;
3993 }
3994 }
3995
3996 color->red = cells[nearest].red;
3997 color->green = cells[nearest].green;
3998 color->blue = cells[nearest].blue;
3999 rc = XAllocColor (display, cmap, color);
4000 }
4001
4002 #ifdef DEBUG_X_COLORS
4003 if (rc)
4004 register_color (color->pixel);
4005 #endif /* DEBUG_X_COLORS */
4006
4007 return rc;
4008 }
4009
4010
4011 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
4012 It's necessary to do this instead of just using PIXEL directly to
4013 get color reference counts right. */
4014
4015 unsigned long
4016 x_copy_color (f, pixel)
4017 struct frame *f;
4018 unsigned long pixel;
4019 {
4020 XColor color;
4021
4022 color.pixel = pixel;
4023 BLOCK_INPUT;
4024 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4025 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
4026 UNBLOCK_INPUT;
4027 #ifdef DEBUG_X_COLORS
4028 register_color (pixel);
4029 #endif
4030 return color.pixel;
4031 }
4032
4033
4034 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
4035 It's necessary to do this instead of just using PIXEL directly to
4036 get color reference counts right. */
4037
4038 unsigned long
4039 x_copy_dpy_color (dpy, cmap, pixel)
4040 Display *dpy;
4041 Colormap cmap;
4042 unsigned long pixel;
4043 {
4044 XColor color;
4045
4046 color.pixel = pixel;
4047 BLOCK_INPUT;
4048 XQueryColor (dpy, cmap, &color);
4049 XAllocColor (dpy, cmap, &color);
4050 UNBLOCK_INPUT;
4051 #ifdef DEBUG_X_COLORS
4052 register_color (pixel);
4053 #endif
4054 return color.pixel;
4055 }
4056
4057 #endif /* MAC_TODO */
4058
4059 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
4060 or DELTA. Try a color with RGB values multiplied by FACTOR first.
4061 If this produces the same color as COLOR, try a color where all RGB
4062 values have DELTA added. Return the allocated color in *COLOR.
4063 DISPLAY is the X display, CMAP is the colormap to operate on.
4064 Value is non-zero if successful. */
4065
4066 static int
4067 mac_alloc_lighter_color (f, color, factor, delta)
4068 struct frame *f;
4069 unsigned long *color;
4070 double factor;
4071 int delta;
4072 {
4073 unsigned long new;
4074
4075 /* Change RGB values by specified FACTOR. Avoid overflow! */
4076 xassert (factor >= 0);
4077 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
4078 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
4079 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
4080 if (new == *color)
4081 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
4082 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
4083 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
4084
4085 /* MAC_TODO: Map to palette and retry with delta if same? */
4086 /* MAC_TODO: Free colors (if using palette)? */
4087
4088 if (new == *color)
4089 return 0;
4090
4091 *color = new;
4092
4093 return 1;
4094 }
4095
4096
4097 /* Set up the foreground color for drawing relief lines of glyph
4098 string S. RELIEF is a pointer to a struct relief containing the GC
4099 with which lines will be drawn. Use a color that is FACTOR or
4100 DELTA lighter or darker than the relief's background which is found
4101 in S->f->output_data.x->relief_background. If such a color cannot
4102 be allocated, use DEFAULT_PIXEL, instead. */
4103
4104 static void
4105 x_setup_relief_color (f, relief, factor, delta, default_pixel)
4106 struct frame *f;
4107 struct relief *relief;
4108 double factor;
4109 int delta;
4110 unsigned long default_pixel;
4111 {
4112 XGCValues xgcv;
4113 struct mac_output *di = f->output_data.mac;
4114 unsigned long mask = GCForeground;
4115 unsigned long pixel;
4116 unsigned long background = di->relief_background;
4117 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4118
4119 /* MAC_TODO: Free colors (if using palette)? */
4120
4121 /* Allocate new color. */
4122 xgcv.foreground = default_pixel;
4123 pixel = background;
4124 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
4125 {
4126 relief->allocated_p = 1;
4127 xgcv.foreground = relief->pixel = pixel;
4128 }
4129
4130 if (relief->gc == 0)
4131 {
4132 #if 0 /* MAC_TODO: stipple */
4133 xgcv.stipple = dpyinfo->gray;
4134 mask |= GCStipple;
4135 #endif
4136 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
4137 }
4138 else
4139 XChangeGC (NULL, relief->gc, mask, &xgcv);
4140 }
4141
4142
4143 /* Set up colors for the relief lines around glyph string S. */
4144
4145 static void
4146 x_setup_relief_colors (s)
4147 struct glyph_string *s;
4148 {
4149 struct mac_output *di = s->f->output_data.mac;
4150 unsigned long color;
4151
4152 if (s->face->use_box_color_for_shadows_p)
4153 color = s->face->box_color;
4154 else
4155 {
4156 XGCValues xgcv;
4157
4158 /* Get the background color of the face. */
4159 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
4160 color = xgcv.background;
4161 }
4162
4163 if (di->white_relief.gc == 0
4164 || color != di->relief_background)
4165 {
4166 di->relief_background = color;
4167 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
4168 WHITE_PIX_DEFAULT (s->f));
4169 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
4170 BLACK_PIX_DEFAULT (s->f));
4171 }
4172 }
4173
4174
4175 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
4176 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
4177 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
4178 relief. LEFT_P non-zero means draw a relief on the left side of
4179 the rectangle. RIGHT_P non-zero means draw a relief on the right
4180 side of the rectangle. CLIP_RECT is the clipping rectangle to use
4181 when drawing. */
4182
4183 static void
4184 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
4185 raised_p, left_p, right_p, clip_rect)
4186 struct frame *f;
4187 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
4188 Rect *clip_rect;
4189 {
4190 int i;
4191 GC gc;
4192
4193 if (raised_p)
4194 gc = f->output_data.mac->white_relief.gc;
4195 else
4196 gc = f->output_data.mac->black_relief.gc;
4197 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
4198
4199 /* Top. */
4200 for (i = 0; i < width; ++i)
4201 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4202 left_x + i * left_p, top_y + i,
4203 right_x + 1 - i * right_p, top_y + i);
4204
4205 /* Left. */
4206 if (left_p)
4207 for (i = 0; i < width; ++i)
4208 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4209 left_x + i, top_y + i, left_x + i, bottom_y - i);
4210
4211 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4212 if (raised_p)
4213 gc = f->output_data.mac->black_relief.gc;
4214 else
4215 gc = f->output_data.mac->white_relief.gc;
4216 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4217 clip_rect);
4218
4219 /* Bottom. */
4220 for (i = 0; i < width; ++i)
4221 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4222 left_x + i * left_p, bottom_y - i,
4223 right_x + 1 - i * right_p, bottom_y - i);
4224
4225 /* Right. */
4226 if (right_p)
4227 for (i = 0; i < width; ++i)
4228 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
4229 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
4230
4231 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
4232 }
4233
4234
4235 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
4236 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
4237 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
4238 left side of the rectangle. RIGHT_P non-zero means draw a line
4239 on the right side of the rectangle. CLIP_RECT is the clipping
4240 rectangle to use when drawing. */
4241
4242 static void
4243 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4244 left_p, right_p, clip_rect)
4245 struct glyph_string *s;
4246 int left_x, top_y, right_x, bottom_y, left_p, right_p;
4247 Rect *clip_rect;
4248 {
4249 XGCValues xgcv;
4250
4251 xgcv.foreground = s->face->box_color;
4252 mac_set_clip_rectangle (s->display, s->window, clip_rect);
4253
4254 /* Top. */
4255 XFillRectangle (s->display, s->window, &xgcv,
4256 left_x, top_y, right_x - left_x, width);
4257
4258 /* Left. */
4259 if (left_p)
4260 XFillRectangle (s->display, s->window, &xgcv,
4261 left_x, top_y, width, bottom_y - top_y);
4262
4263 /* Bottom. */
4264 XFillRectangle (s->display, s->window, &xgcv,
4265 left_x, bottom_y - width, right_x - left_x, width);
4266
4267 /* Right. */
4268 if (right_p)
4269 XFillRectangle (s->display, s->window, &xgcv,
4270 right_x - width, top_y, width, bottom_y - top_y);
4271
4272 mac_reset_clipping (s->display, s->window);
4273 }
4274
4275
4276 /* Draw a box around glyph string S. */
4277
4278 static void
4279 x_draw_glyph_string_box (s)
4280 struct glyph_string *s;
4281 {
4282 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4283 int left_p, right_p;
4284 struct glyph *last_glyph;
4285 Rect clip_rect;
4286
4287 last_x = window_box_right (s->w, s->area);
4288 if (s->row->full_width_p
4289 && !s->w->pseudo_window_p)
4290 {
4291 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4292 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4293 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4294 }
4295
4296 /* The glyph that may have a right box line. */
4297 last_glyph = (s->cmp || s->img
4298 ? s->first_glyph
4299 : s->first_glyph + s->nchars - 1);
4300
4301 width = abs (s->face->box_line_width);
4302 raised_p = s->face->box == FACE_RAISED_BOX;
4303 left_x = s->x;
4304 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
4305 ? last_x - 1
4306 : min (last_x, s->x + s->background_width) - 1));
4307 top_y = s->y;
4308 bottom_y = top_y + s->height - 1;
4309
4310 left_p = (s->first_glyph->left_box_line_p
4311 || (s->hl == DRAW_MOUSE_FACE
4312 && (s->prev == NULL
4313 || s->prev->hl != s->hl)));
4314 right_p = (last_glyph->right_box_line_p
4315 || (s->hl == DRAW_MOUSE_FACE
4316 && (s->next == NULL
4317 || s->next->hl != s->hl)));
4318
4319 x_get_glyph_string_clip_rect (s, &clip_rect);
4320
4321 if (s->face->box == FACE_SIMPLE_BOX)
4322 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4323 left_p, right_p, &clip_rect);
4324 else
4325 {
4326 x_setup_relief_colors (s);
4327 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4328 width, raised_p, left_p, right_p, &clip_rect);
4329 }
4330 }
4331
4332
4333 /* Draw foreground of image glyph string S. */
4334
4335 static void
4336 x_draw_image_foreground (s)
4337 struct glyph_string *s;
4338 {
4339 int x;
4340 int y = s->ybase - image_ascent (s->img, s->face);
4341
4342 /* If first glyph of S has a left box line, start drawing it to the
4343 right of that line. */
4344 if (s->face->box != FACE_NO_BOX
4345 && s->first_glyph->left_box_line_p)
4346 x = s->x + abs (s->face->box_line_width);
4347 else
4348 x = s->x;
4349
4350 /* If there is a margin around the image, adjust x- and y-position
4351 by that margin. */
4352 x += s->img->hmargin;
4353 y += s->img->vmargin;
4354
4355 if (s->img->pixmap)
4356 {
4357 #if 0 /* MAC_TODO: image mask */
4358 if (s->img->mask)
4359 {
4360 /* We can't set both a clip mask and use XSetClipRectangles
4361 because the latter also sets a clip mask. We also can't
4362 trust on the shape extension to be available
4363 (XShapeCombineRegion). So, compute the rectangle to draw
4364 manually. */
4365 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4366 | GCFunction);
4367 XGCValues xgcv;
4368 XRectangle clip_rect, image_rect, r;
4369
4370 xgcv.clip_mask = s->img->mask;
4371 xgcv.clip_x_origin = x;
4372 xgcv.clip_y_origin = y;
4373 xgcv.function = GXcopy;
4374 XChangeGC (s->display, s->gc, mask, &xgcv);
4375
4376 x_get_glyph_string_clip_rect (s, &clip_rect);
4377 image_rect.x = x;
4378 image_rect.y = y;
4379 image_rect.width = s->img->width;
4380 image_rect.height = s->img->height;
4381 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4382 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4383 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4384 }
4385 else
4386 #endif /* MAC_TODO */
4387 {
4388 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
4389 0, 0, s->img->width, s->img->height, x, y);
4390
4391 /* When the image has a mask, we can expect that at
4392 least part of a mouse highlight or a block cursor will
4393 be visible. If the image doesn't have a mask, make
4394 a block cursor visible by drawing a rectangle around
4395 the image. I believe it's looking better if we do
4396 nothing here for mouse-face. */
4397 if (s->hl == DRAW_CURSOR)
4398 {
4399 int r = s->img->relief;
4400 if (r < 0) r = -r;
4401 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
4402 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4403 }
4404 }
4405 }
4406 else
4407 /* Draw a rectangle if image could not be loaded. */
4408 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
4409 s->img->width - 1, s->img->height - 1);
4410 }
4411
4412
4413
4414 /* Draw a relief around the image glyph string S. */
4415
4416 static void
4417 x_draw_image_relief (s)
4418 struct glyph_string *s;
4419 {
4420 int x0, y0, x1, y1, thick, raised_p;
4421 Rect r;
4422 int x;
4423 int y = s->ybase - image_ascent (s->img, s->face);
4424
4425 /* If first glyph of S has a left box line, start drawing it to the
4426 right of that line. */
4427 if (s->face->box != FACE_NO_BOX
4428 && s->first_glyph->left_box_line_p)
4429 x = s->x + abs (s->face->box_line_width);
4430 else
4431 x = s->x;
4432
4433 /* If there is a margin around the image, adjust x- and y-position
4434 by that margin. */
4435 x += s->img->hmargin;
4436 y += s->img->vmargin;
4437
4438 if (s->hl == DRAW_IMAGE_SUNKEN
4439 || s->hl == DRAW_IMAGE_RAISED)
4440 {
4441 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4442 raised_p = s->hl == DRAW_IMAGE_RAISED;
4443 }
4444 else
4445 {
4446 thick = abs (s->img->relief);
4447 raised_p = s->img->relief > 0;
4448 }
4449
4450 x0 = x - thick;
4451 y0 = y - thick;
4452 x1 = x + s->img->width + thick - 1;
4453 y1 = y + s->img->height + thick - 1;
4454
4455 x_setup_relief_colors (s);
4456 x_get_glyph_string_clip_rect (s, &r);
4457 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4458 }
4459
4460
4461 /* Draw the foreground of image glyph string S to PIXMAP. */
4462
4463 static void
4464 x_draw_image_foreground_1 (s, pixmap)
4465 struct glyph_string *s;
4466 Pixmap pixmap;
4467 {
4468 int x;
4469 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4470
4471 /* If first glyph of S has a left box line, start drawing it to the
4472 right of that line. */
4473 if (s->face->box != FACE_NO_BOX
4474 && s->first_glyph->left_box_line_p)
4475 x = abs (s->face->box_line_width);
4476 else
4477 x = 0;
4478
4479 /* If there is a margin around the image, adjust x- and y-position
4480 by that margin. */
4481 x += s->img->hmargin;
4482 y += s->img->vmargin;
4483
4484 if (s->img->pixmap)
4485 {
4486 #if 0 /* MAC_TODO: image mask */
4487 if (s->img->mask)
4488 {
4489 /* We can't set both a clip mask and use XSetClipRectangles
4490 because the latter also sets a clip mask. We also can't
4491 trust on the shape extension to be available
4492 (XShapeCombineRegion). So, compute the rectangle to draw
4493 manually. */
4494 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4495 | GCFunction);
4496 XGCValues xgcv;
4497
4498 xgcv.clip_mask = s->img->mask;
4499 xgcv.clip_x_origin = x;
4500 xgcv.clip_y_origin = y;
4501 xgcv.function = GXcopy;
4502 XChangeGC (s->display, s->gc, mask, &xgcv);
4503
4504 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4505 0, 0, s->img->width, s->img->height, x, y);
4506 XSetClipMask (s->display, s->gc, None);
4507 }
4508 else
4509 #endif /* MAC_TODO */
4510 {
4511 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
4512 0, 0, s->img->width, s->img->height, x, y);
4513
4514 /* When the image has a mask, we can expect that at
4515 least part of a mouse highlight or a block cursor will
4516 be visible. If the image doesn't have a mask, make
4517 a block cursor visible by drawing a rectangle around
4518 the image. I believe it's looking better if we do
4519 nothing here for mouse-face. */
4520 if (s->hl == DRAW_CURSOR)
4521 {
4522 int r = s->img->relief;
4523 if (r < 0) r = -r;
4524 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
4525 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4526 }
4527 }
4528 }
4529 else
4530 /* Draw a rectangle if image could not be loaded. */
4531 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
4532 s->img->width - 1, s->img->height - 1);
4533 }
4534
4535
4536 /* Draw part of the background of glyph string S. X, Y, W, and H
4537 give the rectangle to draw. */
4538
4539 static void
4540 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4541 struct glyph_string *s;
4542 int x, y, w, h;
4543 {
4544 #if 0 /* MAC_TODO: stipple */
4545 if (s->stippled_p)
4546 {
4547 /* Fill background with a stipple pattern. */
4548 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4549 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4550 XSetFillStyle (s->display, s->gc, FillSolid);
4551 }
4552 else
4553 #endif /* MAC_TODO */
4554 x_clear_glyph_string_rect (s, x, y, w, h);
4555 }
4556
4557
4558 /* Draw image glyph string S.
4559
4560 s->y
4561 s->x +-------------------------
4562 | s->face->box
4563 |
4564 | +-------------------------
4565 | | s->img->vmargin
4566 | |
4567 | | +-------------------
4568 | | | the image
4569
4570 */
4571
4572 static void
4573 x_draw_image_glyph_string (s)
4574 struct glyph_string *s;
4575 {
4576 int x, y;
4577 int box_line_hwidth = abs (s->face->box_line_width);
4578 int box_line_vwidth = max (s->face->box_line_width, 0);
4579 int height;
4580 Pixmap pixmap = 0;
4581
4582 height = s->height - 2 * box_line_vwidth;
4583
4584 /* Fill background with face under the image. Do it only if row is
4585 taller than image or if image has a clip mask to reduce
4586 flickering. */
4587 s->stippled_p = s->face->stipple != 0;
4588 if (height > s->img->height
4589 || s->img->hmargin
4590 || s->img->vmargin
4591 #if 0 /* TODO: image mask */
4592 || s->img->mask
4593 #endif
4594 || s->img->pixmap == 0
4595 || s->width != s->background_width)
4596 {
4597 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4598 x = s->x + box_line_hwidth;
4599 else
4600 x = s->x;
4601
4602 y = s->y + box_line_vwidth;
4603 #if 0 /* TODO: image mask */
4604 if (s->img->mask)
4605 {
4606 /* Create a pixmap as large as the glyph string. Fill it
4607 with the background color. Copy the image to it, using
4608 its mask. Copy the temporary pixmap to the display. */
4609 Screen *screen = FRAME_X_SCREEN (s->f);
4610 int depth = DefaultDepthOfScreen (screen);
4611
4612 /* Create a pixmap as large as the glyph string. */
4613 pixmap = XCreatePixmap (s->display, s->window,
4614 s->background_width,
4615 s->height, depth);
4616
4617 /* Don't clip in the following because we're working on the
4618 pixmap. */
4619 XSetClipMask (s->display, s->gc, None);
4620
4621 /* Fill the pixmap with the background color/stipple. */
4622 if (s->stippled_p)
4623 {
4624 /* Fill background with a stipple pattern. */
4625 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4626 XFillRectangle (s->display, pixmap, s->gc,
4627 0, 0, s->background_width, s->height);
4628 XSetFillStyle (s->display, s->gc, FillSolid);
4629 }
4630 else
4631 {
4632 XGCValues xgcv;
4633 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4634 &xgcv);
4635 XSetForeground (s->display, s->gc, xgcv.background);
4636 XFillRectangle (s->display, pixmap, s->gc,
4637 0, 0, s->background_width, s->height);
4638 XSetForeground (s->display, s->gc, xgcv.foreground);
4639 }
4640 }
4641 else
4642 #endif
4643 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4644
4645 s->background_filled_p = 1;
4646 }
4647
4648 /* Draw the foreground. */
4649 if (pixmap != 0)
4650 {
4651 x_draw_image_foreground_1 (s, pixmap);
4652 x_set_glyph_string_clipping (s);
4653 mac_copy_area (s->display, pixmap, s->window, s->gc,
4654 0, 0, s->background_width, s->height, s->x, s->y);
4655 mac_reset_clipping (s->display, s->window);
4656 XFreePixmap (s->display, pixmap);
4657 }
4658 else
4659 x_draw_image_foreground (s);
4660
4661 /* If we must draw a relief around the image, do it. */
4662 if (s->img->relief
4663 || s->hl == DRAW_IMAGE_RAISED
4664 || s->hl == DRAW_IMAGE_SUNKEN)
4665 x_draw_image_relief (s);
4666 }
4667
4668
4669 /* Draw stretch glyph string S. */
4670
4671 static void
4672 x_draw_stretch_glyph_string (s)
4673 struct glyph_string *s;
4674 {
4675 xassert (s->first_glyph->type == STRETCH_GLYPH);
4676 s->stippled_p = s->face->stipple != 0;
4677
4678 if (s->hl == DRAW_CURSOR
4679 && !x_stretch_cursor_p)
4680 {
4681 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4682 as wide as the stretch glyph. */
4683 int width = min (CANON_X_UNIT (s->f), s->background_width);
4684
4685 /* Draw cursor. */
4686 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4687
4688 /* Clear rest using the GC of the original non-cursor face. */
4689 if (width < s->background_width)
4690 {
4691 GC gc = s->face->gc;
4692 int x = s->x + width, y = s->y;
4693 int w = s->background_width - width, h = s->height;
4694 Rect r;
4695
4696 if (s->row->mouse_face_p
4697 && cursor_in_mouse_face_p (s->w))
4698 {
4699 x_set_mouse_face_gc (s);
4700 gc = s->gc;
4701 }
4702 else
4703 gc = s->face->gc;
4704
4705 x_get_glyph_string_clip_rect (s, &r);
4706 mac_set_clip_rectangle (s->display, s->window, &r);
4707
4708 #if 0 /* MAC_TODO: stipple */
4709 if (s->face->stipple)
4710 {
4711 /* Fill background with a stipple pattern. */
4712 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4713 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4714 XSetFillStyle (s->display, gc, FillSolid);
4715 }
4716 else
4717 #endif /* MAC_TODO */
4718 {
4719 XGCValues xgcv;
4720 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4721 XSetForeground (s->display, gc, xgcv.background);
4722 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4723 XSetForeground (s->display, gc, xgcv.foreground);
4724 }
4725
4726 mac_reset_clipping (s->display, s->window);
4727 }
4728 }
4729 else if (!s->background_filled_p)
4730 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4731 s->height);
4732
4733 s->background_filled_p = 1;
4734 }
4735
4736
4737 /* Draw glyph string S. */
4738
4739 static void
4740 x_draw_glyph_string (s)
4741 struct glyph_string *s;
4742 {
4743 int relief_drawn_p = 0;
4744
4745 /* If S draws into the background of its successor, draw the
4746 background of the successor first so that S can draw into it.
4747 This makes S->next use XDrawString instead of XDrawImageString. */
4748 if (s->next && s->right_overhang && !s->for_overlaps_p)
4749 {
4750 xassert (s->next->img == NULL);
4751 x_set_glyph_string_gc (s->next);
4752 x_set_glyph_string_clipping (s->next);
4753 x_draw_glyph_string_background (s->next, 1);
4754
4755 }
4756
4757 /* Set up S->gc, set clipping and draw S. */
4758 x_set_glyph_string_gc (s);
4759
4760 /* Draw relief (if any) in advance for char/composition so that the
4761 glyph string can be drawn over it. */
4762 if (!s->for_overlaps_p
4763 && s->face->box != FACE_NO_BOX
4764 && (s->first_glyph->type == CHAR_GLYPH
4765 || s->first_glyph->type == COMPOSITE_GLYPH))
4766
4767 {
4768 x_set_glyph_string_clipping (s);
4769 x_draw_glyph_string_background (s, 1);
4770 x_draw_glyph_string_box (s);
4771 x_set_glyph_string_clipping (s);
4772 relief_drawn_p = 1;
4773 }
4774 else
4775 x_set_glyph_string_clipping (s);
4776
4777 switch (s->first_glyph->type)
4778 {
4779 case IMAGE_GLYPH:
4780 x_draw_image_glyph_string (s);
4781 break;
4782
4783 case STRETCH_GLYPH:
4784 x_draw_stretch_glyph_string (s);
4785 break;
4786
4787 case CHAR_GLYPH:
4788 if (s->for_overlaps_p)
4789 s->background_filled_p = 1;
4790 else
4791 x_draw_glyph_string_background (s, 0);
4792 x_draw_glyph_string_foreground (s);
4793 break;
4794
4795 case COMPOSITE_GLYPH:
4796 if (s->for_overlaps_p || s->gidx > 0)
4797 s->background_filled_p = 1;
4798 else
4799 x_draw_glyph_string_background (s, 1);
4800 x_draw_composite_glyph_string_foreground (s);
4801 break;
4802
4803 default:
4804 abort ();
4805 }
4806
4807 if (!s->for_overlaps_p)
4808 {
4809 /* Draw underline. */
4810 if (s->face->underline_p)
4811 {
4812 unsigned long h = 1;
4813 unsigned long dy = s->height - h;
4814
4815 if (s->face->underline_defaulted_p)
4816 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4817 s->width, h);
4818 else
4819 {
4820 XGCValues xgcv;
4821 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4822 XSetForeground (s->display, s->gc, s->face->underline_color);
4823 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4824 s->width, h);
4825 XSetForeground (s->display, s->gc, xgcv.foreground);
4826 }
4827 }
4828
4829 /* Draw overline. */
4830 if (s->face->overline_p)
4831 {
4832 unsigned long dy = 0, h = 1;
4833
4834 if (s->face->overline_color_defaulted_p)
4835 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4836 s->width, h);
4837 else
4838 {
4839 XGCValues xgcv;
4840 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4841 XSetForeground (s->display, s->gc, s->face->overline_color);
4842 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4843 s->width, h);
4844 XSetForeground (s->display, s->gc, xgcv.foreground);
4845 }
4846 }
4847
4848 /* Draw strike-through. */
4849 if (s->face->strike_through_p)
4850 {
4851 unsigned long h = 1;
4852 unsigned long dy = (s->height - h) / 2;
4853
4854 if (s->face->strike_through_color_defaulted_p)
4855 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4856 s->width, h);
4857 else
4858 {
4859 XGCValues xgcv;
4860 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4861 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4862 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4863 s->width, h);
4864 XSetForeground (s->display, s->gc, xgcv.foreground);
4865 }
4866 }
4867
4868 /* Draw relief. */
4869 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4870 x_draw_glyph_string_box (s);
4871 }
4872
4873 /* Reset clipping. */
4874 mac_reset_clipping (s->display, s->window);
4875 }
4876
4877
4878 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4879 struct face **, int));
4880
4881
4882 /* Fill glyph string S with composition components specified by S->cmp.
4883
4884 FACES is an array of faces for all components of this composition.
4885 S->gidx is the index of the first component for S.
4886 OVERLAPS_P non-zero means S should draw the foreground only, and
4887 use its physical height for clipping.
4888
4889 Value is the index of a component not in S. */
4890
4891 static int
4892 x_fill_composite_glyph_string (s, faces, overlaps_p)
4893 struct glyph_string *s;
4894 struct face **faces;
4895 int overlaps_p;
4896 {
4897 int i;
4898
4899 xassert (s);
4900
4901 s->for_overlaps_p = overlaps_p;
4902
4903 s->face = faces[s->gidx];
4904 s->font = s->face->font;
4905 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4906
4907 /* For all glyphs of this composition, starting at the offset
4908 S->gidx, until we reach the end of the definition or encounter a
4909 glyph that requires the different face, add it to S. */
4910 ++s->nchars;
4911 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4912 ++s->nchars;
4913
4914 /* All glyph strings for the same composition has the same width,
4915 i.e. the width set for the first component of the composition. */
4916
4917 s->width = s->first_glyph->pixel_width;
4918
4919 /* If the specified font could not be loaded, use the frame's
4920 default font, but record the fact that we couldn't load it in
4921 the glyph string so that we can draw rectangles for the
4922 characters of the glyph string. */
4923 if (s->font == NULL)
4924 {
4925 s->font_not_found_p = 1;
4926 s->font = FRAME_FONT (s->f);
4927 }
4928
4929 /* Adjust base line for subscript/superscript text. */
4930 s->ybase += s->first_glyph->voffset;
4931
4932 xassert (s->face && s->face->gc);
4933
4934 /* This glyph string must always be drawn with 16-bit functions. */
4935 s->two_byte_p = 1;
4936
4937 return s->gidx + s->nchars;
4938 }
4939
4940
4941 /* Fill glyph string S from a sequence of character glyphs.
4942
4943 FACE_ID is the face id of the string. START is the index of the
4944 first glyph to consider, END is the index of the last + 1.
4945 OVERLAPS_P non-zero means S should draw the foreground only, and
4946 use its physical height for clipping.
4947
4948 Value is the index of the first glyph not in S. */
4949
4950 static int
4951 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4952 struct glyph_string *s;
4953 int face_id;
4954 int start, end, overlaps_p;
4955 {
4956 struct glyph *glyph, *last;
4957 int voffset;
4958 int glyph_not_available_p;
4959
4960 xassert (s->f == XFRAME (s->w->frame));
4961 xassert (s->nchars == 0);
4962 xassert (start >= 0 && end > start);
4963
4964 s->for_overlaps_p = overlaps_p;
4965 glyph = s->row->glyphs[s->area] + start;
4966 last = s->row->glyphs[s->area] + end;
4967 voffset = glyph->voffset;
4968
4969 glyph_not_available_p = glyph->glyph_not_available_p;
4970
4971 while (glyph < last
4972 && glyph->type == CHAR_GLYPH
4973 && glyph->voffset == voffset
4974 /* Same face id implies same font, nowadays. */
4975 && glyph->face_id == face_id
4976 && glyph->glyph_not_available_p == glyph_not_available_p)
4977 {
4978 int two_byte_p;
4979
4980 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4981 s->char2b + s->nchars,
4982 &two_byte_p);
4983 s->two_byte_p = two_byte_p;
4984 ++s->nchars;
4985 xassert (s->nchars <= end - start);
4986 s->width += glyph->pixel_width;
4987 ++glyph;
4988 }
4989
4990 s->font = s->face->font;
4991 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4992
4993 /* If the specified font could not be loaded, use the frame's font,
4994 but record the fact that we couldn't load it in
4995 S->font_not_found_p so that we can draw rectangles for the
4996 characters of the glyph string. */
4997 if (s->font == NULL || glyph_not_available_p)
4998 {
4999 s->font_not_found_p = 1;
5000 s->font = FRAME_FONT (s->f);
5001 }
5002
5003 /* Adjust base line for subscript/superscript text. */
5004 s->ybase += voffset;
5005
5006 xassert (s->face && s->face->gc);
5007 return glyph - s->row->glyphs[s->area];
5008 }
5009
5010
5011 /* Fill glyph string S from image glyph S->first_glyph. */
5012
5013 static void
5014 x_fill_image_glyph_string (s)
5015 struct glyph_string *s;
5016 {
5017 xassert (s->first_glyph->type == IMAGE_GLYPH);
5018 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
5019 xassert (s->img);
5020 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
5021 s->font = s->face->font;
5022 s->width = s->first_glyph->pixel_width;
5023
5024 /* Adjust base line for subscript/superscript text. */
5025 s->ybase += s->first_glyph->voffset;
5026 }
5027
5028
5029 /* Fill glyph string S from a sequence of stretch glyphs.
5030
5031 ROW is the glyph row in which the glyphs are found, AREA is the
5032 area within the row. START is the index of the first glyph to
5033 consider, END is the index of the last + 1.
5034
5035 Value is the index of the first glyph not in S. */
5036
5037 static int
5038 x_fill_stretch_glyph_string (s, row, area, start, end)
5039 struct glyph_string *s;
5040 struct glyph_row *row;
5041 enum glyph_row_area area;
5042 int start, end;
5043 {
5044 struct glyph *glyph, *last;
5045 int voffset, face_id;
5046
5047 xassert (s->first_glyph->type == STRETCH_GLYPH);
5048
5049 glyph = s->row->glyphs[s->area] + start;
5050 last = s->row->glyphs[s->area] + end;
5051 face_id = glyph->face_id;
5052 s->face = FACE_FROM_ID (s->f, face_id);
5053 s->font = s->face->font;
5054 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
5055 s->width = glyph->pixel_width;
5056 voffset = glyph->voffset;
5057
5058 for (++glyph;
5059 (glyph < last
5060 && glyph->type == STRETCH_GLYPH
5061 && glyph->voffset == voffset
5062 && glyph->face_id == face_id);
5063 ++glyph)
5064 s->width += glyph->pixel_width;
5065
5066 /* Adjust base line for subscript/superscript text. */
5067 s->ybase += voffset;
5068
5069 xassert (s->face);
5070 return glyph - s->row->glyphs[s->area];
5071 }
5072
5073
5074 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
5075 of XChar2b structures for S; it can't be allocated in
5076 x_init_glyph_string because it must be allocated via `alloca'. W
5077 is the window on which S is drawn. ROW and AREA are the glyph row
5078 and area within the row from which S is constructed. START is the
5079 index of the first glyph structure covered by S. HL is a
5080 face-override for drawing S. */
5081
5082 static void
5083 x_init_glyph_string (s, char2b, w, row, area, start, hl)
5084 struct glyph_string *s;
5085 XChar2b *char2b;
5086 struct window *w;
5087 struct glyph_row *row;
5088 enum glyph_row_area area;
5089 int start;
5090 enum draw_glyphs_face hl;
5091 {
5092 bzero (s, sizeof *s);
5093 s->w = w;
5094 s->f = XFRAME (w->frame);
5095 s->display = FRAME_MAC_DISPLAY (s->f);
5096 s->window = FRAME_MAC_WINDOW (s->f);
5097 s->char2b = char2b;
5098 s->hl = hl;
5099 s->row = row;
5100 s->area = area;
5101 s->first_glyph = row->glyphs[area] + start;
5102 s->height = row->height;
5103 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5104
5105 /* Display the internal border below the tool-bar window. */
5106 if (s->w == XWINDOW (s->f->tool_bar_window))
5107 s->y -= s->f->output_data.mac->internal_border_width;
5108
5109 s->ybase = s->y + row->ascent;
5110 }
5111
5112
5113 /* Set background width of glyph string S. START is the index of the
5114 first glyph following S. LAST_X is the right-most x-position + 1
5115 in the drawing area. */
5116
5117 static INLINE void
5118 x_set_glyph_string_background_width (s, start, last_x)
5119 struct glyph_string *s;
5120 int start;
5121 int last_x;
5122 {
5123 /* If the face of this glyph string has to be drawn to the end of
5124 the drawing area, set S->extends_to_end_of_line_p. */
5125 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
5126
5127 if (start == s->row->used[s->area]
5128 && s->area == TEXT_AREA
5129 && ((s->hl == DRAW_NORMAL_TEXT
5130 && (s->row->fill_line_p
5131 || s->face->background != default_face->background
5132 || s->face->stipple != default_face->stipple
5133 || s->row->mouse_face_p))
5134 || s->hl == DRAW_MOUSE_FACE
5135 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
5136 && s->row->fill_line_p)))
5137 s->extends_to_end_of_line_p = 1;
5138
5139 /* If S extends its face to the end of the line, set its
5140 background_width to the distance to the right edge of the drawing
5141 area. */
5142 if (s->extends_to_end_of_line_p)
5143 s->background_width = last_x - s->x + 1;
5144 else
5145 s->background_width = s->width;
5146 }
5147
5148
5149 /* Add a glyph string for a stretch glyph to the list of strings
5150 between HEAD and TAIL. START is the index of the stretch glyph in
5151 row area AREA of glyph row ROW. END is the index of the last glyph
5152 in that glyph row area. X is the current output position assigned
5153 to the new glyph string constructed. HL overrides that face of the
5154 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5155 is the right-most x-position of the drawing area. */
5156
5157 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
5158 and below -- keep them on one line. */
5159 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5160 do \
5161 { \
5162 s = (struct glyph_string *) alloca (sizeof *s); \
5163 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5164 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
5165 x_append_glyph_string (&HEAD, &TAIL, s); \
5166 s->x = (X); \
5167 } \
5168 while (0)
5169
5170
5171 /* Add a glyph string for an image glyph to the list of strings
5172 between HEAD and TAIL. START is the index of the image glyph in
5173 row area AREA of glyph row ROW. END is the index of the last glyph
5174 in that glyph row area. X is the current output position assigned
5175 to the new glyph string constructed. HL overrides that face of the
5176 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
5177 is the right-most x-position of the drawing area. */
5178
5179 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
5180 do \
5181 { \
5182 s = (struct glyph_string *) alloca (sizeof *s); \
5183 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
5184 x_fill_image_glyph_string (s); \
5185 x_append_glyph_string (&HEAD, &TAIL, s); \
5186 ++START; \
5187 s->x = (X); \
5188 } \
5189 while (0)
5190
5191
5192 /* Add a glyph string for a sequence of character glyphs to the list
5193 of strings between HEAD and TAIL. START is the index of the first
5194 glyph in row area AREA of glyph row ROW that is part of the new
5195 glyph string. END is the index of the last glyph in that glyph row
5196 area. X is the current output position assigned to the new glyph
5197 string constructed. HL overrides that face of the glyph; e.g. it
5198 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
5199 right-most x-position of the drawing area. */
5200
5201 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5202 do \
5203 { \
5204 int c, face_id; \
5205 XChar2b *char2b; \
5206 \
5207 c = (ROW)->glyphs[AREA][START].u.ch; \
5208 face_id = (ROW)->glyphs[AREA][START].face_id; \
5209 \
5210 s = (struct glyph_string *) alloca (sizeof *s); \
5211 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
5212 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
5213 x_append_glyph_string (&HEAD, &TAIL, s); \
5214 s->x = (X); \
5215 START = x_fill_glyph_string (s, face_id, START, END, \
5216 OVERLAPS_P); \
5217 } \
5218 while (0)
5219
5220
5221 /* Add a glyph string for a composite sequence to the list of strings
5222 between HEAD and TAIL. START is the index of the first glyph in
5223 row area AREA of glyph row ROW that is part of the new glyph
5224 string. END is the index of the last glyph in that glyph row area.
5225 X is the current output position assigned to the new glyph string
5226 constructed. HL overrides that face of the glyph; e.g. it is
5227 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
5228 x-position of the drawing area. */
5229
5230 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5231 do { \
5232 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
5233 int face_id = (ROW)->glyphs[AREA][START].face_id; \
5234 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
5235 struct composition *cmp = composition_table[cmp_id]; \
5236 int glyph_len = cmp->glyph_len; \
5237 XChar2b *char2b; \
5238 struct face **faces; \
5239 struct glyph_string *first_s = NULL; \
5240 int n; \
5241 \
5242 base_face = base_face->ascii_face; \
5243 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5244 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5245 /* At first, fill in `char2b' and `faces'. */ \
5246 for (n = 0; n < glyph_len; n++) \
5247 { \
5248 int c = COMPOSITION_GLYPH (cmp, n); \
5249 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5250 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5251 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5252 this_face_id, char2b + n, 1); \
5253 } \
5254 \
5255 /* Make glyph_strings for each glyph sequence that is drawable by \
5256 the same face, and append them to HEAD/TAIL. */ \
5257 for (n = 0; n < cmp->glyph_len;) \
5258 { \
5259 s = (struct glyph_string *) alloca (sizeof *s); \
5260 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5261 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5262 s->cmp = cmp; \
5263 s->gidx = n; \
5264 s->x = (X); \
5265 \
5266 if (n == 0) \
5267 first_s = s; \
5268 \
5269 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5270 } \
5271 \
5272 ++START; \
5273 s = first_s; \
5274 } while (0)
5275
5276
5277 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5278 of AREA of glyph row ROW on window W between indices START and END.
5279 HL overrides the face for drawing glyph strings, e.g. it is
5280 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5281 x-positions of the drawing area.
5282
5283 This is an ugly monster macro construct because we must use alloca
5284 to allocate glyph strings (because x_draw_glyphs can be called
5285 asynchronously). */
5286
5287 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5288 do \
5289 { \
5290 HEAD = TAIL = NULL; \
5291 while (START < END) \
5292 { \
5293 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5294 switch (first_glyph->type) \
5295 { \
5296 case CHAR_GLYPH: \
5297 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5298 TAIL, HL, X, LAST_X, \
5299 OVERLAPS_P); \
5300 break; \
5301 \
5302 case COMPOSITE_GLYPH: \
5303 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5304 HEAD, TAIL, HL, X, LAST_X,\
5305 OVERLAPS_P); \
5306 break; \
5307 \
5308 case STRETCH_GLYPH: \
5309 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5310 HEAD, TAIL, HL, X, LAST_X); \
5311 break; \
5312 \
5313 case IMAGE_GLYPH: \
5314 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5315 TAIL, HL, X, LAST_X); \
5316 break; \
5317 \
5318 default: \
5319 abort (); \
5320 } \
5321 \
5322 x_set_glyph_string_background_width (s, START, LAST_X); \
5323 (X) += s->width; \
5324 } \
5325 } \
5326 while (0)
5327
5328
5329 /* Draw glyphs between START and END in AREA of ROW on window W,
5330 starting at x-position X. X is relative to AREA in W. HL is a
5331 face-override with the following meaning:
5332
5333 DRAW_NORMAL_TEXT draw normally
5334 DRAW_CURSOR draw in cursor face
5335 DRAW_MOUSE_FACE draw in mouse face.
5336 DRAW_INVERSE_VIDEO draw in mode line face
5337 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5338 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5339
5340 If OVERLAPS_P is non-zero, draw only the foreground of characters
5341 and clip to the physical height of ROW.
5342
5343 Value is the x-position reached, relative to AREA of W. */
5344
5345 static int
5346 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5347 struct window *w;
5348 int x;
5349 struct glyph_row *row;
5350 enum glyph_row_area area;
5351 int start, end;
5352 enum draw_glyphs_face hl;
5353 int overlaps_p;
5354 {
5355 struct glyph_string *head, *tail;
5356 struct glyph_string *s;
5357 int last_x, area_width;
5358 int x_reached;
5359 int i, j;
5360
5361 /* Let's rather be paranoid than getting a SEGV. */
5362 end = min (end, row->used[area]);
5363 start = max (0, start);
5364 start = min (end, start);
5365
5366 /* Translate X to frame coordinates. Set last_x to the right
5367 end of the drawing area. */
5368 if (row->full_width_p)
5369 {
5370 /* X is relative to the left edge of W, without scroll bars
5371 or fringes. */
5372 struct frame *f = XFRAME (WINDOW_FRAME (w));
5373 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5374
5375 x += window_left_x;
5376 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5377 last_x = window_left_x + area_width;
5378
5379 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5380 {
5381 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5382 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5383 last_x += width;
5384 else
5385 x -= width;
5386 }
5387
5388 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5389 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
5390 }
5391 else
5392 {
5393 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5394 area_width = window_box_width (w, area);
5395 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5396 }
5397
5398 /* Build a doubly-linked list of glyph_string structures between
5399 head and tail from what we have to draw. Note that the macro
5400 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5401 the reason we use a separate variable `i'. */
5402 i = start;
5403 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5404 overlaps_p);
5405 if (tail)
5406 x_reached = tail->x + tail->background_width;
5407 else
5408 x_reached = x;
5409
5410 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5411 the row, redraw some glyphs in front or following the glyph
5412 strings built above. */
5413 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5414 {
5415 int dummy_x = 0;
5416 struct glyph_string *h, *t;
5417
5418 /* Compute overhangs for all glyph strings. */
5419 for (s = head; s; s = s->next)
5420 x_compute_glyph_string_overhangs (s);
5421
5422 /* Prepend glyph strings for glyphs in front of the first glyph
5423 string that are overwritten because of the first glyph
5424 string's left overhang. The background of all strings
5425 prepended must be drawn because the first glyph string
5426 draws over it. */
5427 i = x_left_overwritten (head);
5428 if (i >= 0)
5429 {
5430 j = i;
5431 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5432 DRAW_NORMAL_TEXT, dummy_x, last_x,
5433 overlaps_p);
5434 start = i;
5435 x_compute_overhangs_and_x (t, head->x, 1);
5436 x_prepend_glyph_string_lists (&head, &tail, h, t);
5437 }
5438
5439 /* Prepend glyph strings for glyphs in front of the first glyph
5440 string that overwrite that glyph string because of their
5441 right overhang. For these strings, only the foreground must
5442 be drawn, because it draws over the glyph string at `head'.
5443 The background must not be drawn because this would overwrite
5444 right overhangs of preceding glyphs for which no glyph
5445 strings exist. */
5446 i = x_left_overwriting (head);
5447 if (i >= 0)
5448 {
5449 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5450 DRAW_NORMAL_TEXT, dummy_x, last_x,
5451 overlaps_p);
5452 for (s = h; s; s = s->next)
5453 s->background_filled_p = 1;
5454 x_compute_overhangs_and_x (t, head->x, 1);
5455 x_prepend_glyph_string_lists (&head, &tail, h, t);
5456 }
5457
5458 /* Append glyphs strings for glyphs following the last glyph
5459 string tail that are overwritten by tail. The background of
5460 these strings has to be drawn because tail's foreground draws
5461 over it. */
5462 i = x_right_overwritten (tail);
5463 if (i >= 0)
5464 {
5465 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5466 DRAW_NORMAL_TEXT, x, last_x,
5467 overlaps_p);
5468 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5469 x_append_glyph_string_lists (&head, &tail, h, t);
5470 }
5471
5472 /* Append glyph strings for glyphs following the last glyph
5473 string tail that overwrite tail. The foreground of such
5474 glyphs has to be drawn because it writes into the background
5475 of tail. The background must not be drawn because it could
5476 paint over the foreground of following glyphs. */
5477 i = x_right_overwriting (tail);
5478 if (i >= 0)
5479 {
5480 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5481 DRAW_NORMAL_TEXT, x, last_x,
5482 overlaps_p);
5483 for (s = h; s; s = s->next)
5484 s->background_filled_p = 1;
5485 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5486 x_append_glyph_string_lists (&head, &tail, h, t);
5487 }
5488 }
5489
5490 /* Draw all strings. */
5491 for (s = head; s; s = s->next)
5492 x_draw_glyph_string (s);
5493
5494 if (area == TEXT_AREA
5495 && !row->full_width_p
5496 /* When drawing overlapping rows, only the glyph strings'
5497 foreground is drawn, which doesn't erase a cursor
5498 completely. */
5499 && !overlaps_p)
5500 {
5501 int x0 = head ? head->x : x;
5502 int x1 = tail ? tail->x + tail->background_width : x;
5503
5504 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5505 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5506
5507 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5508 {
5509 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5510 x0 -= left_area_width;
5511 x1 -= left_area_width;
5512 }
5513
5514 notice_overwritten_cursor (w, area, x0, x1,
5515 row->y, MATRIX_ROW_BOTTOM_Y (row));
5516 }
5517
5518 /* Value is the x-position up to which drawn, relative to AREA of W.
5519 This doesn't include parts drawn because of overhangs. */
5520 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5521 if (!row->full_width_p)
5522 {
5523 if (area > LEFT_MARGIN_AREA)
5524 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5525 if (area > TEXT_AREA)
5526 x_reached -= window_box_width (w, TEXT_AREA);
5527 }
5528
5529 return x_reached;
5530 }
5531
5532
5533 /* Fix the display of area AREA of overlapping row ROW in window W. */
5534
5535 static void
5536 x_fix_overlapping_area (w, row, area)
5537 struct window *w;
5538 struct glyph_row *row;
5539 enum glyph_row_area area;
5540 {
5541 int i, x;
5542
5543 BLOCK_INPUT;
5544
5545 if (area == LEFT_MARGIN_AREA)
5546 x = 0;
5547 else if (area == TEXT_AREA)
5548 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5549 else
5550 x = (window_box_width (w, LEFT_MARGIN_AREA)
5551 + window_box_width (w, TEXT_AREA));
5552
5553 for (i = 0; i < row->used[area];)
5554 {
5555 if (row->glyphs[area][i].overlaps_vertically_p)
5556 {
5557 int start = i, start_x = x;
5558
5559 do
5560 {
5561 x += row->glyphs[area][i].pixel_width;
5562 ++i;
5563 }
5564 while (i < row->used[area]
5565 && row->glyphs[area][i].overlaps_vertically_p);
5566
5567 x_draw_glyphs (w, start_x, row, area, start, i,
5568 DRAW_NORMAL_TEXT, 1);
5569 }
5570 else
5571 {
5572 x += row->glyphs[area][i].pixel_width;
5573 ++i;
5574 }
5575 }
5576
5577 UNBLOCK_INPUT;
5578 }
5579
5580
5581 /* Output LEN glyphs starting at START at the nominal cursor position.
5582 Advance the nominal cursor over the text. The global variable
5583 updated_window contains the window being updated, updated_row is
5584 the glyph row being updated, and updated_area is the area of that
5585 row being updated. */
5586
5587 static void
5588 x_write_glyphs (start, len)
5589 struct glyph *start;
5590 int len;
5591 {
5592 int x, hpos;
5593
5594 xassert (updated_window && updated_row);
5595 BLOCK_INPUT;
5596
5597 /* Write glyphs. */
5598
5599 hpos = start - updated_row->glyphs[updated_area];
5600 x = x_draw_glyphs (updated_window, output_cursor.x,
5601 updated_row, updated_area,
5602 hpos, hpos + len,
5603 DRAW_NORMAL_TEXT, 0);
5604
5605 UNBLOCK_INPUT;
5606
5607 /* Advance the output cursor. */
5608 output_cursor.hpos += len;
5609 output_cursor.x = x;
5610 }
5611
5612
5613 /* Insert LEN glyphs from START at the nominal cursor position. */
5614
5615 static void
5616 x_insert_glyphs (start, len)
5617 struct glyph *start;
5618 register int len;
5619 {
5620 struct frame *f;
5621 struct window *w;
5622 int line_height, shift_by_width, shifted_region_width;
5623 struct glyph_row *row;
5624 struct glyph *glyph;
5625 int frame_x, frame_y, hpos;
5626
5627 xassert (updated_window && updated_row);
5628 BLOCK_INPUT;
5629 w = updated_window;
5630 f = XFRAME (WINDOW_FRAME (w));
5631
5632 /* Get the height of the line we are in. */
5633 row = updated_row;
5634 line_height = row->height;
5635
5636 /* Get the width of the glyphs to insert. */
5637 shift_by_width = 0;
5638 for (glyph = start; glyph < start + len; ++glyph)
5639 shift_by_width += glyph->pixel_width;
5640
5641 /* Get the width of the region to shift right. */
5642 shifted_region_width = (window_box_width (w, updated_area)
5643 - output_cursor.x
5644 - shift_by_width);
5645
5646 /* Shift right. */
5647 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5648 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5649
5650 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5651 f->output_data.mac->normal_gc,
5652 frame_x, frame_y,
5653 shifted_region_width, line_height,
5654 frame_x + shift_by_width, frame_y);
5655
5656 /* Write the glyphs. */
5657 hpos = start - row->glyphs[updated_area];
5658 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5659 DRAW_NORMAL_TEXT, 0);
5660
5661 /* Advance the output cursor. */
5662 output_cursor.hpos += len;
5663 output_cursor.x += shift_by_width;
5664 UNBLOCK_INPUT;
5665 }
5666
5667
5668 /* Delete N glyphs at the nominal cursor position. Not implemented
5669 for X frames. */
5670
5671 static void
5672 x_delete_glyphs (n)
5673 register int n;
5674 {
5675 abort ();
5676 }
5677
5678
5679 /* Erase the current text line from the nominal cursor position
5680 (inclusive) to pixel column TO_X (exclusive). The idea is that
5681 everything from TO_X onward is already erased.
5682
5683 TO_X is a pixel position relative to updated_area of
5684 updated_window. TO_X == -1 means clear to the end of this area. */
5685
5686 static void
5687 x_clear_end_of_line (to_x)
5688 int to_x;
5689 {
5690 struct frame *f;
5691 struct window *w = updated_window;
5692 int max_x, min_y, max_y;
5693 int from_x, from_y, to_y;
5694
5695 xassert (updated_window && updated_row);
5696 f = XFRAME (w->frame);
5697
5698 if (updated_row->full_width_p)
5699 {
5700 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5701 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5702 && !w->pseudo_window_p)
5703 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5704 }
5705 else
5706 max_x = window_box_width (w, updated_area);
5707 max_y = window_text_bottom_y (w);
5708
5709 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5710 of window. For TO_X > 0, truncate to end of drawing area. */
5711 if (to_x == 0)
5712 return;
5713 else if (to_x < 0)
5714 to_x = max_x;
5715 else
5716 to_x = min (to_x, max_x);
5717
5718 to_y = min (max_y, output_cursor.y + updated_row->height);
5719
5720 /* Notice if the cursor will be cleared by this operation. */
5721 if (!updated_row->full_width_p)
5722 notice_overwritten_cursor (w, updated_area,
5723 output_cursor.x, -1,
5724 updated_row->y,
5725 MATRIX_ROW_BOTTOM_Y (updated_row));
5726
5727 from_x = output_cursor.x;
5728
5729 /* Translate to frame coordinates. */
5730 if (updated_row->full_width_p)
5731 {
5732 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5733 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5734 }
5735 else
5736 {
5737 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5738 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5739 }
5740
5741 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5742 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5743 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5744
5745 /* Prevent inadvertently clearing to end of the X window. */
5746 if (to_x > from_x && to_y > from_y)
5747 {
5748 BLOCK_INPUT;
5749 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5750 from_x, from_y, to_x - from_x, to_y - from_y,
5751 0);
5752 UNBLOCK_INPUT;
5753 }
5754 }
5755
5756
5757 /* Clear entire frame. If updating_frame is non-null, clear that
5758 frame. Otherwise clear the selected frame. */
5759
5760 static void
5761 x_clear_frame ()
5762 {
5763 struct frame *f;
5764
5765 if (updating_frame)
5766 f = updating_frame;
5767 else
5768 f = SELECTED_FRAME ();
5769
5770 /* Clearing the frame will erase any cursor, so mark them all as no
5771 longer visible. */
5772 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5773 output_cursor.hpos = output_cursor.vpos = 0;
5774 output_cursor.x = -1;
5775
5776 /* We don't set the output cursor here because there will always
5777 follow an explicit cursor_to. */
5778 BLOCK_INPUT;
5779 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
5780
5781 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
5782 /* We have to clear the scroll bars, too. If we have changed
5783 colors or something like that, then they should be notified. */
5784 x_scroll_bar_clear (f);
5785 #endif
5786
5787 XFlush (FRAME_MAC_DISPLAY (f));
5788 UNBLOCK_INPUT;
5789 }
5790
5791
5792 \f
5793 /* Invert the middle quarter of the frame for .15 sec. */
5794
5795 /* We use the select system call to do the waiting, so we have to make
5796 sure it's available. If it isn't, we just won't do visual bells. */
5797
5798 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5799
5800 /* Subtract the `struct timeval' values X and Y, storing the result in
5801 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5802
5803 static int
5804 timeval_subtract (result, x, y)
5805 struct timeval *result, x, y;
5806 {
5807 /* Perform the carry for the later subtraction by updating y. This
5808 is safer because on some systems the tv_sec member is unsigned. */
5809 if (x.tv_usec < y.tv_usec)
5810 {
5811 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5812 y.tv_usec -= 1000000 * nsec;
5813 y.tv_sec += nsec;
5814 }
5815
5816 if (x.tv_usec - y.tv_usec > 1000000)
5817 {
5818 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5819 y.tv_usec += 1000000 * nsec;
5820 y.tv_sec -= nsec;
5821 }
5822
5823 /* Compute the time remaining to wait. tv_usec is certainly
5824 positive. */
5825 result->tv_sec = x.tv_sec - y.tv_sec;
5826 result->tv_usec = x.tv_usec - y.tv_usec;
5827
5828 /* Return indication of whether the result should be considered
5829 negative. */
5830 return x.tv_sec < y.tv_sec;
5831 }
5832
5833 void
5834 XTflash (f)
5835 struct frame *f;
5836 {
5837 BLOCK_INPUT;
5838
5839 FlashMenuBar (0);
5840
5841 {
5842 struct timeval wakeup;
5843
5844 EMACS_GET_TIME (wakeup);
5845
5846 /* Compute time to wait until, propagating carry from usecs. */
5847 wakeup.tv_usec += 150000;
5848 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5849 wakeup.tv_usec %= 1000000;
5850
5851 /* Keep waiting until past the time wakeup. */
5852 while (1)
5853 {
5854 struct timeval timeout;
5855
5856 EMACS_GET_TIME (timeout);
5857
5858 /* In effect, timeout = wakeup - timeout.
5859 Break if result would be negative. */
5860 if (timeval_subtract (&timeout, wakeup, timeout))
5861 break;
5862
5863 /* Try to wait that long--but we might wake up sooner. */
5864 select (0, NULL, NULL, NULL, &timeout);
5865 }
5866 }
5867
5868 FlashMenuBar (0);
5869
5870 UNBLOCK_INPUT;
5871 }
5872
5873 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5874
5875
5876 /* Make audible bell. */
5877
5878 void
5879 XTring_bell ()
5880 {
5881 struct frame *f = SELECTED_FRAME ();
5882
5883 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5884 if (visible_bell)
5885 XTflash (f);
5886 else
5887 #endif
5888 {
5889 BLOCK_INPUT;
5890 SysBeep (1);
5891 XFlush (FRAME_MAC_DISPLAY (f));
5892 UNBLOCK_INPUT;
5893 }
5894 }
5895
5896
5897 \f
5898 /* Specify how many text lines, from the top of the window,
5899 should be affected by insert-lines and delete-lines operations.
5900 This, and those operations, are used only within an update
5901 that is bounded by calls to x_update_begin and x_update_end. */
5902
5903 void
5904 XTset_terminal_window (n)
5905 register int n;
5906 {
5907 /* This function intentionally left blank. */
5908 }
5909
5910
5911 \f
5912 /***********************************************************************
5913 Line Dance
5914 ***********************************************************************/
5915
5916 /* Perform an insert-lines or delete-lines operation, inserting N
5917 lines or deleting -N lines at vertical position VPOS. */
5918
5919 static void
5920 x_ins_del_lines (vpos, n)
5921 int vpos, n;
5922 {
5923 abort ();
5924 }
5925
5926
5927 /* Scroll part of the display as described by RUN. */
5928
5929 static void
5930 x_scroll_run (w, run)
5931 struct window *w;
5932 struct run *run;
5933 {
5934 struct frame *f = XFRAME (w->frame);
5935 int x, y, width, height, from_y, to_y, bottom_y;
5936
5937 /* Get frame-relative bounding box of the text display area of W,
5938 without mode lines. Include in this box the left and right
5939 fringes of W. */
5940 window_box (w, -1, &x, &y, &width, &height);
5941 width += FRAME_X_FRINGE_WIDTH (f);
5942 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5943
5944 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5945 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5946 bottom_y = y + height;
5947
5948 if (to_y < from_y)
5949 {
5950 /* Scrolling up. Make sure we don't copy part of the mode
5951 line at the bottom. */
5952 if (from_y + run->height > bottom_y)
5953 height = bottom_y - from_y;
5954 else
5955 height = run->height;
5956 }
5957 else
5958 {
5959 /* Scolling down. Make sure we don't copy over the mode line.
5960 at the bottom. */
5961 if (to_y + run->height > bottom_y)
5962 height = bottom_y - to_y;
5963 else
5964 height = run->height;
5965 }
5966
5967 BLOCK_INPUT;
5968
5969 /* Cursor off. Will be switched on again in x_update_window_end. */
5970 updated_window = w;
5971 x_clear_cursor (w);
5972
5973 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5974 f->output_data.mac->normal_gc,
5975 x, from_y,
5976 width, height,
5977 x, to_y);
5978
5979 UNBLOCK_INPUT;
5980 }
5981
5982
5983 \f
5984 /***********************************************************************
5985 Exposure Events
5986 ***********************************************************************/
5987
5988 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5989 corner of the exposed rectangle. W and H are width and height of
5990 the exposed area. All are pixel values. W or H zero means redraw
5991 the entire frame. */
5992
5993 static void
5994 expose_frame (f, x, y, w, h)
5995 struct frame *f;
5996 int x, y, w, h;
5997 {
5998 Rect r;
5999 int mouse_face_overwritten_p = 0;
6000
6001 TRACE ((stderr, "expose_frame "));
6002
6003 /* No need to redraw if frame will be redrawn soon. */
6004 if (FRAME_GARBAGED_P (f))
6005 {
6006 TRACE ((stderr, " garbaged\n"));
6007 return;
6008 }
6009
6010 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
6011 or deactivated here, for unknown reasons, activated scroll bars
6012 are shown in deactivated frames in some instances. */
6013 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6014 activate_scroll_bars (f);
6015 else
6016 deactivate_scroll_bars (f);
6017
6018 /* If basic faces haven't been realized yet, there is no point in
6019 trying to redraw anything. This can happen when we get an expose
6020 event while Emacs is starting, e.g. by moving another window. */
6021 if (FRAME_FACE_CACHE (f) == NULL
6022 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
6023 {
6024 TRACE ((stderr, " no faces\n"));
6025 return;
6026 }
6027
6028 if (w == 0 || h == 0)
6029 {
6030 r.left = r.top = 0;
6031 r.right = CANON_X_UNIT (f) * f->width;
6032 r.bottom = CANON_Y_UNIT (f) * f->height;
6033 }
6034 else
6035 {
6036 r.left = x;
6037 r.top = y;
6038 r.right = x + w;
6039 r.bottom = y + h;
6040 }
6041
6042 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
6043 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
6044
6045 if (WINDOWP (f->tool_bar_window))
6046 mouse_face_overwritten_p
6047 |= expose_window (XWINDOW (f->tool_bar_window), &r);
6048
6049 /* Some window managers support a focus-follows-mouse style with
6050 delayed raising of frames. Imagine a partially obscured frame,
6051 and moving the mouse into partially obscured mouse-face on that
6052 frame. The visible part of the mouse-face will be highlighted,
6053 then the WM raises the obscured frame. With at least one WM, KDE
6054 2.1, Emacs is not getting any event for the raising of the frame
6055 (even tried with SubstructureRedirectMask), only Expose events.
6056 These expose events will draw text normally, i.e. not
6057 highlighted. Which means we must redo the highlight here.
6058 Subsume it under ``we love X''. --gerd 2001-08-15 */
6059 /* Included in Windows version because Windows most likely does not
6060 do the right thing if any third party tool offers
6061 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
6062 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
6063 {
6064 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6065 if (f == dpyinfo->mouse_face_mouse_frame)
6066 {
6067 int x = dpyinfo->mouse_face_mouse_x;
6068 int y = dpyinfo->mouse_face_mouse_y;
6069 clear_mouse_face (dpyinfo);
6070 note_mouse_highlight (f, x, y);
6071 }
6072 }
6073 }
6074
6075
6076 /* Redraw (parts) of all windows in the window tree rooted at W that
6077 intersect R. R contains frame pixel coordinates. */
6078
6079 static int
6080 expose_window_tree (w, r)
6081 struct window *w;
6082 Rect *r;
6083 {
6084 struct frame *f = XFRAME (w->frame);
6085 int mouse_face_overwritten_p = 0;
6086
6087 while (w && !FRAME_GARBAGED_P (f))
6088 {
6089 if (!NILP (w->hchild))
6090 mouse_face_overwritten_p
6091 |= expose_window_tree (XWINDOW (w->hchild), r);
6092 else if (!NILP (w->vchild))
6093 mouse_face_overwritten_p
6094 |= expose_window_tree (XWINDOW (w->vchild), r);
6095 else
6096 mouse_face_overwritten_p |= expose_window (w, r);
6097
6098 w = NILP (w->next) ? NULL : XWINDOW (w->next);
6099 }
6100
6101 return mouse_face_overwritten_p;
6102 }
6103
6104
6105 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
6106 which intersects rectangle R. R is in window-relative coordinates. */
6107
6108 static void
6109 expose_area (w, row, r, area)
6110 struct window *w;
6111 struct glyph_row *row;
6112 Rect *r;
6113 enum glyph_row_area area;
6114 {
6115 struct glyph *first = row->glyphs[area];
6116 struct glyph *end = row->glyphs[area] + row->used[area];
6117 struct glyph *last;
6118 int first_x, start_x, x;
6119
6120 if (area == TEXT_AREA && row->fill_line_p)
6121 /* If row extends face to end of line write the whole line. */
6122 x_draw_glyphs (w, 0, row, area,
6123 0, row->used[area],
6124 DRAW_NORMAL_TEXT, 0);
6125 else
6126 {
6127 /* Set START_X to the window-relative start position for drawing glyphs of
6128 AREA. The first glyph of the text area can be partially visible.
6129 The first glyphs of other areas cannot. */
6130 if (area == LEFT_MARGIN_AREA)
6131 start_x = 0;
6132 else if (area == TEXT_AREA)
6133 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6134 else
6135 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6136 + window_box_width (w, TEXT_AREA));
6137 x = start_x;
6138
6139 /* Find the first glyph that must be redrawn. */
6140 while (first < end
6141 && x + first->pixel_width < r->left)
6142 {
6143 x += first->pixel_width;
6144 ++first;
6145 }
6146
6147 /* Find the last one. */
6148 last = first;
6149 first_x = x;
6150 while (last < end
6151 && x < r->right)
6152 {
6153 x += last->pixel_width;
6154 ++last;
6155 }
6156
6157 /* Repaint. */
6158 if (last > first)
6159 x_draw_glyphs (w, first_x - start_x, row, area,
6160 first - row->glyphs[area],
6161 last - row->glyphs[area],
6162 DRAW_NORMAL_TEXT, 0);
6163 }
6164 }
6165
6166
6167 /* Redraw the parts of the glyph row ROW on window W intersecting
6168 rectangle R. R is in window-relative coordinates. Value is
6169 non-zero if mouse face was overwritten. */
6170
6171 static int
6172 expose_line (w, row, r)
6173 struct window *w;
6174 struct glyph_row *row;
6175 Rect *r;
6176 {
6177 xassert (row->enabled_p);
6178
6179 if (row->mode_line_p || w->pseudo_window_p)
6180 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6181 DRAW_NORMAL_TEXT, 0);
6182 else
6183 {
6184 if (row->used[LEFT_MARGIN_AREA])
6185 expose_area (w, row, r, LEFT_MARGIN_AREA);
6186 if (row->used[TEXT_AREA])
6187 expose_area (w, row, r, TEXT_AREA);
6188 if (row->used[RIGHT_MARGIN_AREA])
6189 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6190 x_draw_row_fringe_bitmaps (w, row);
6191 }
6192
6193 return row->mouse_face_p;
6194 }
6195
6196
6197 /* Return non-zero if W's cursor intersects rectangle R. */
6198
6199 static int
6200 x_phys_cursor_in_rect_p (w, r)
6201 struct window *w;
6202 Rect *r;
6203 {
6204 Rect cr, result;
6205 struct glyph *cursor_glyph;
6206
6207 cursor_glyph = get_phys_cursor_glyph (w);
6208 if (cursor_glyph)
6209 {
6210 cr.left = w->phys_cursor.x;
6211 cr.top = w->phys_cursor.y;
6212 cr.right = cr.left + cursor_glyph->pixel_width;
6213 cr.bottom = cr.top + w->phys_cursor_height;
6214 return x_intersect_rectangles (&cr, r, &result);
6215 }
6216 else
6217 return 0;
6218 }
6219
6220
6221 /* Redraw the part of window W intersection rectagle FR. Pixel
6222 coordinates in FR are frame relative. Call this function with
6223 input blocked. Value is non-zero if the exposure overwrites
6224 mouse-face. */
6225
6226 static int
6227 expose_window (w, fr)
6228 struct window *w;
6229 Rect *fr;
6230 {
6231 struct frame *f = XFRAME (w->frame);
6232 Rect wr, r;
6233 int mouse_face_overwritten_p = 0;
6234
6235 /* If window is not yet fully initialized, do nothing. This can
6236 happen when toolkit scroll bars are used and a window is split.
6237 Reconfiguring the scroll bar will generate an expose for a newly
6238 created window. */
6239 if (w->current_matrix == NULL)
6240 return 0;
6241
6242 /* When we're currently updating the window, display and current
6243 matrix usually don't agree. Arrange for a thorough display
6244 later. */
6245 if (w == updated_window)
6246 {
6247 SET_FRAME_GARBAGED (f);
6248 return 0;
6249 }
6250
6251 /* Frame-relative pixel rectangle of W. */
6252 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
6253 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
6254 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
6255 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
6256
6257 if (x_intersect_rectangles (fr, &wr, &r))
6258 {
6259 int yb = window_text_bottom_y (w);
6260 struct glyph_row *row;
6261 int cursor_cleared_p;
6262
6263 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6264 r.left, r.top, r.right, r.bottom));
6265
6266 /* Convert to window coordinates. */
6267 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
6268 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
6269 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
6270 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
6271
6272 /* Turn off the cursor. */
6273 if (!w->pseudo_window_p
6274 && x_phys_cursor_in_rect_p (w, &r))
6275 {
6276 x_clear_cursor (w);
6277 cursor_cleared_p = 1;
6278 }
6279 else
6280 cursor_cleared_p = 0;
6281
6282 /* Find the first row intersecting the rectangle R. */
6283 for (row = w->current_matrix->rows;
6284 row->enabled_p;
6285 ++row)
6286 {
6287 int y0 = row->y;
6288 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6289
6290 if ((y0 >= r.top && y0 < r.bottom)
6291 || (y1 > r.top && y1 < r.bottom)
6292 || (r.top >= y0 && r.top < y1)
6293 || (r.bottom > y0 && r.bottom < y1))
6294 {
6295 if (expose_line (w, row, &r))
6296 mouse_face_overwritten_p = 1;
6297 }
6298
6299 if (y1 >= yb)
6300 break;
6301 }
6302
6303 /* Display the mode line if there is one. */
6304 if (WINDOW_WANTS_MODELINE_P (w)
6305 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6306 row->enabled_p)
6307 && row->y < r.bottom)
6308 {
6309 if (expose_line (w, row, &r))
6310 mouse_face_overwritten_p = 1;
6311 }
6312
6313 if (!w->pseudo_window_p)
6314 {
6315 /* Draw border between windows. */
6316 x_draw_vertical_border (w);
6317
6318 /* Turn the cursor on again. */
6319 if (cursor_cleared_p)
6320 x_update_window_cursor (w, 1);
6321 }
6322 }
6323
6324 /* Display scroll bar for this window. */
6325 if (!NILP (w->vertical_scroll_bar))
6326 {
6327 ControlHandle ch
6328 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
6329
6330 Draw1Control (ch);
6331 }
6332
6333 return mouse_face_overwritten_p;
6334 }
6335
6336 static int
6337 x_intersect_rectangles (r1, r2, result)
6338 Rect *r1, *r2, *result;
6339 {
6340 Rect *left, *right;
6341 Rect *upper, *lower;
6342 int intersection_p = 0;
6343
6344 /* Rerrange so that R1 is the left-most rectangle. */
6345 if (r1->left < r2->left)
6346 left = r1, right = r2;
6347 else
6348 left = r2, right = r1;
6349
6350 /* X0 of the intersection is right.x0, if this is inside R1,
6351 otherwise there is no intersection. */
6352 if (right->left <= left->right)
6353 {
6354 result->left = right->left;
6355
6356 /* The right end of the intersection is the minimum of the
6357 the right ends of left and right. */
6358 result->right = min (left->right, right->right);
6359
6360 /* Same game for Y. */
6361 if (r1->top < r2->top)
6362 upper = r1, lower = r2;
6363 else
6364 upper = r2, lower = r1;
6365
6366 /* The upper end of the intersection is lower.y0, if this is inside
6367 of upper. Otherwise, there is no intersection. */
6368 if (lower->top <= upper->bottom)
6369 {
6370 result->top = lower->top;
6371
6372 /* The lower end of the intersection is the minimum of the lower
6373 ends of upper and lower. */
6374 result->bottom = min (lower->bottom, upper->bottom);
6375 intersection_p = 1;
6376 }
6377 }
6378
6379 return intersection_p;
6380 }
6381
6382
6383
6384
6385 \f
6386 static void
6387 frame_highlight (f)
6388 struct frame *f;
6389 {
6390 x_update_cursor (f, 1);
6391 }
6392
6393 static void
6394 frame_unhighlight (f)
6395 struct frame *f;
6396 {
6397 x_update_cursor (f, 1);
6398 }
6399
6400 /* The focus has changed. Update the frames as necessary to reflect
6401 the new situation. Note that we can't change the selected frame
6402 here, because the Lisp code we are interrupting might become confused.
6403 Each event gets marked with the frame in which it occurred, so the
6404 Lisp code can tell when the switch took place by examining the events. */
6405
6406 static void
6407 x_new_focus_frame (dpyinfo, frame)
6408 struct x_display_info *dpyinfo;
6409 struct frame *frame;
6410 {
6411 struct frame *old_focus = dpyinfo->x_focus_frame;
6412
6413 if (frame != dpyinfo->x_focus_frame)
6414 {
6415 /* Set this before calling other routines, so that they see
6416 the correct value of x_focus_frame. */
6417 dpyinfo->x_focus_frame = frame;
6418
6419 if (old_focus && old_focus->auto_lower)
6420 x_lower_frame (old_focus);
6421
6422 #if 0
6423 selected_frame = frame;
6424 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6425 selected_frame);
6426 Fselect_window (selected_frame->selected_window);
6427 choose_minibuf_frame ();
6428 #endif /* ! 0 */
6429
6430 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6431 pending_autoraise_frame = dpyinfo->x_focus_frame;
6432 else
6433 pending_autoraise_frame = 0;
6434 }
6435
6436 x_frame_rehighlight (dpyinfo);
6437 }
6438
6439 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6440
6441 void
6442 x_mouse_leave (dpyinfo)
6443 struct x_display_info *dpyinfo;
6444 {
6445 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6446 }
6447
6448 /* The focus has changed, or we have redirected a frame's focus to
6449 another frame (this happens when a frame uses a surrogate
6450 mini-buffer frame). Shift the highlight as appropriate.
6451
6452 The FRAME argument doesn't necessarily have anything to do with which
6453 frame is being highlighted or un-highlighted; we only use it to find
6454 the appropriate X display info. */
6455
6456 static void
6457 XTframe_rehighlight (frame)
6458 struct frame *frame;
6459 {
6460 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6461 }
6462
6463 static void
6464 x_frame_rehighlight (dpyinfo)
6465 struct x_display_info *dpyinfo;
6466 {
6467 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6468
6469 if (dpyinfo->x_focus_frame)
6470 {
6471 dpyinfo->x_highlight_frame
6472 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6473 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6474 : dpyinfo->x_focus_frame);
6475 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6476 {
6477 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6478 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6479 }
6480 }
6481 else
6482 dpyinfo->x_highlight_frame = 0;
6483
6484 if (dpyinfo->x_highlight_frame != old_highlight)
6485 {
6486 if (old_highlight)
6487 frame_unhighlight (old_highlight);
6488 if (dpyinfo->x_highlight_frame)
6489 frame_highlight (dpyinfo->x_highlight_frame);
6490 }
6491 }
6492
6493
6494 \f
6495 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6496
6497 #if 0 /* MAC_TODO */
6498 /* Initialize mode_switch_bit and modifier_meaning. */
6499 static void
6500 x_find_modifier_meanings (dpyinfo)
6501 struct x_display_info *dpyinfo;
6502 {
6503 int min_code, max_code;
6504 KeySym *syms;
6505 int syms_per_code;
6506 XModifierKeymap *mods;
6507
6508 dpyinfo->meta_mod_mask = 0;
6509 dpyinfo->shift_lock_mask = 0;
6510 dpyinfo->alt_mod_mask = 0;
6511 dpyinfo->super_mod_mask = 0;
6512 dpyinfo->hyper_mod_mask = 0;
6513
6514 #ifdef HAVE_X11R4
6515 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6516 #else
6517 min_code = dpyinfo->display->min_keycode;
6518 max_code = dpyinfo->display->max_keycode;
6519 #endif
6520
6521 syms = XGetKeyboardMapping (dpyinfo->display,
6522 min_code, max_code - min_code + 1,
6523 &syms_per_code);
6524 mods = XGetModifierMapping (dpyinfo->display);
6525
6526 /* Scan the modifier table to see which modifier bits the Meta and
6527 Alt keysyms are on. */
6528 {
6529 int row, col; /* The row and column in the modifier table. */
6530
6531 for (row = 3; row < 8; row++)
6532 for (col = 0; col < mods->max_keypermod; col++)
6533 {
6534 KeyCode code
6535 = mods->modifiermap[(row * mods->max_keypermod) + col];
6536
6537 /* Zeroes are used for filler. Skip them. */
6538 if (code == 0)
6539 continue;
6540
6541 /* Are any of this keycode's keysyms a meta key? */
6542 {
6543 int code_col;
6544
6545 for (code_col = 0; code_col < syms_per_code; code_col++)
6546 {
6547 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6548
6549 switch (sym)
6550 {
6551 case XK_Meta_L:
6552 case XK_Meta_R:
6553 dpyinfo->meta_mod_mask |= (1 << row);
6554 break;
6555
6556 case XK_Alt_L:
6557 case XK_Alt_R:
6558 dpyinfo->alt_mod_mask |= (1 << row);
6559 break;
6560
6561 case XK_Hyper_L:
6562 case XK_Hyper_R:
6563 dpyinfo->hyper_mod_mask |= (1 << row);
6564 break;
6565
6566 case XK_Super_L:
6567 case XK_Super_R:
6568 dpyinfo->super_mod_mask |= (1 << row);
6569 break;
6570
6571 case XK_Shift_Lock:
6572 /* Ignore this if it's not on the lock modifier. */
6573 if ((1 << row) == LockMask)
6574 dpyinfo->shift_lock_mask = LockMask;
6575 break;
6576 }
6577 }
6578 }
6579 }
6580 }
6581
6582 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6583 if (! dpyinfo->meta_mod_mask)
6584 {
6585 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6586 dpyinfo->alt_mod_mask = 0;
6587 }
6588
6589 /* If some keys are both alt and meta,
6590 make them just meta, not alt. */
6591 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6592 {
6593 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6594 }
6595
6596 XFree ((char *) syms);
6597 XFreeModifiermap (mods);
6598 }
6599
6600 #endif /* MAC_TODO */
6601
6602 /* Convert between the modifier bits X uses and the modifier bits
6603 Emacs uses. */
6604
6605 static unsigned int
6606 x_mac_to_emacs_modifiers (dpyinfo, state)
6607 struct x_display_info *dpyinfo;
6608 unsigned short state;
6609 {
6610 return (((state & shiftKey) ? shift_modifier : 0)
6611 | ((state & controlKey) ? ctrl_modifier : 0)
6612 | ((state & cmdKey) ? meta_modifier : 0)
6613 | ((state & optionKey) ? alt_modifier : 0));
6614 }
6615
6616 #if 0 /* MAC_TODO */
6617 static unsigned short
6618 x_emacs_to_x_modifiers (dpyinfo, state)
6619 struct x_display_info *dpyinfo;
6620 unsigned int state;
6621 {
6622 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6623 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6624 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6625 | ((state & shift_modifier) ? ShiftMask : 0)
6626 | ((state & ctrl_modifier) ? ControlMask : 0)
6627 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6628 }
6629 #endif /* MAC_TODO */
6630
6631 /* Convert a keysym to its name. */
6632
6633 char *
6634 x_get_keysym_name (keysym)
6635 int keysym;
6636 {
6637 char *value;
6638
6639 BLOCK_INPUT;
6640 #if 0
6641 value = XKeysymToString (keysym);
6642 #else
6643 value = 0;
6644 #endif
6645 UNBLOCK_INPUT;
6646
6647 return value;
6648 }
6649
6650
6651 \f
6652 /* Mouse clicks and mouse movement. Rah. */
6653
6654 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6655 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6656 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6657 not force the value into range. */
6658
6659 void
6660 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6661 FRAME_PTR f;
6662 register int pix_x, pix_y;
6663 register int *x, *y;
6664 Rect *bounds;
6665 int noclip;
6666 {
6667 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6668 if (NILP (Vwindow_system))
6669 {
6670 *x = pix_x;
6671 *y = pix_y;
6672 return;
6673 }
6674
6675 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6676 even for negative values. */
6677 if (pix_x < 0)
6678 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
6679 if (pix_y < 0)
6680 pix_y -= (f)->output_data.mac->line_height - 1;
6681
6682 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6683 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6684
6685 if (bounds)
6686 {
6687 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6688 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
6689 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6690 bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
6691 }
6692
6693 if (!noclip)
6694 {
6695 if (pix_x < 0)
6696 pix_x = 0;
6697 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6698 pix_x = FRAME_WINDOW_WIDTH (f);
6699
6700 if (pix_y < 0)
6701 pix_y = 0;
6702 else if (pix_y > f->height)
6703 pix_y = f->height;
6704 }
6705
6706 *x = pix_x;
6707 *y = pix_y;
6708 }
6709
6710
6711 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6712 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6713 can't tell the positions because W's display is not up to date,
6714 return 0. */
6715
6716 int
6717 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6718 struct window *w;
6719 int hpos, vpos;
6720 int *frame_x, *frame_y;
6721 {
6722 int success_p;
6723
6724 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6725 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6726
6727 if (display_completed)
6728 {
6729 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6730 struct glyph *glyph = row->glyphs[TEXT_AREA];
6731 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6732
6733 *frame_y = row->y;
6734 *frame_x = row->x;
6735 while (glyph < end)
6736 {
6737 *frame_x += glyph->pixel_width;
6738 ++glyph;
6739 }
6740
6741 success_p = 1;
6742 }
6743 else
6744 {
6745 *frame_y = *frame_x = 0;
6746 success_p = 0;
6747 }
6748
6749 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6750 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6751 return success_p;
6752 }
6753
6754
6755 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6756
6757 If the event is a button press, then note that we have grabbed
6758 the mouse. */
6759
6760 static Lisp_Object
6761 construct_mouse_click (result, event, f)
6762 struct input_event *result;
6763 EventRecord *event;
6764 struct frame *f;
6765 {
6766 Point mouseLoc;
6767
6768 result->kind = MOUSE_CLICK_EVENT;
6769 result->code = 0; /* only one mouse button */
6770 result->timestamp = event->when;
6771 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
6772
6773 mouseLoc = event->where;
6774
6775 #if TARGET_API_MAC_CARBON
6776 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
6777 #else
6778 SetPort (FRAME_MAC_WINDOW (f));
6779 #endif
6780
6781 GlobalToLocal (&mouseLoc);
6782 XSETINT (result->x, mouseLoc.h);
6783 XSETINT (result->y, mouseLoc.v);
6784
6785 XSETFRAME (result->frame_or_window, f);
6786
6787 result->arg = Qnil;
6788 return Qnil;
6789 }
6790
6791 \f
6792 /* Function to report a mouse movement to the mainstream Emacs code.
6793 The input handler calls this.
6794
6795 We have received a mouse movement event, which is given in *event.
6796 If the mouse is over a different glyph than it was last time, tell
6797 the mainstream emacs code by setting mouse_moved. If not, ask for
6798 another motion event, so we can check again the next time it moves. */
6799
6800 static Point last_mouse_motion_position;
6801 static Lisp_Object last_mouse_motion_frame;
6802
6803 static void
6804 note_mouse_movement (frame, pos)
6805 FRAME_PTR frame;
6806 Point *pos;
6807 {
6808 #if TARGET_API_MAC_CARBON
6809 Rect r;
6810 #endif
6811
6812 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
6813 last_mouse_motion_position = *pos;
6814 XSETFRAME (last_mouse_motion_frame, frame);
6815
6816 #if TARGET_API_MAC_CARBON
6817 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
6818 #else
6819 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
6820 #endif
6821 {
6822 frame->mouse_moved = 1;
6823 last_mouse_scroll_bar = Qnil;
6824 note_mouse_highlight (frame, -1, -1);
6825 }
6826 /* Has the mouse moved off the glyph it was on at the last sighting? */
6827 else if (pos->h < last_mouse_glyph.left
6828 || pos->h >= last_mouse_glyph.right
6829 || pos->v < last_mouse_glyph.top
6830 || pos->v >= last_mouse_glyph.bottom)
6831 {
6832 frame->mouse_moved = 1;
6833 last_mouse_scroll_bar = Qnil;
6834 note_mouse_highlight (frame, pos->h, pos->v);
6835 }
6836 }
6837
6838 /* This is used for debugging, to turn off note_mouse_highlight. */
6839
6840 int disable_mouse_highlight;
6841
6842
6843 \f
6844 /************************************************************************
6845 Mouse Face
6846 ************************************************************************/
6847
6848 /* Find the glyph under window-relative coordinates X/Y in window W.
6849 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6850 strings. Return in *HPOS and *VPOS the row and column number of
6851 the glyph found. Return in *AREA the glyph area containing X.
6852 Value is a pointer to the glyph found or null if X/Y is not on
6853 text, or we can't tell because W's current matrix is not up to
6854 date. */
6855
6856 static struct glyph *
6857 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6858 struct window *w;
6859 int x, y;
6860 int *hpos, *vpos, *area;
6861 int buffer_only_p;
6862 {
6863 struct glyph *glyph, *end;
6864 struct glyph_row *row = NULL;
6865 int x0, i, left_area_width;
6866
6867 /* Find row containing Y. Give up if some row is not enabled. */
6868 for (i = 0; i < w->current_matrix->nrows; ++i)
6869 {
6870 row = MATRIX_ROW (w->current_matrix, i);
6871 if (!row->enabled_p)
6872 return NULL;
6873 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6874 break;
6875 }
6876
6877 *vpos = i;
6878 *hpos = 0;
6879
6880 /* Give up if Y is not in the window. */
6881 if (i == w->current_matrix->nrows)
6882 return NULL;
6883
6884 /* Get the glyph area containing X. */
6885 if (w->pseudo_window_p)
6886 {
6887 *area = TEXT_AREA;
6888 x0 = 0;
6889 }
6890 else
6891 {
6892 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6893 if (x < left_area_width)
6894 {
6895 *area = LEFT_MARGIN_AREA;
6896 x0 = 0;
6897 }
6898 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6899 {
6900 *area = TEXT_AREA;
6901 x0 = row->x + left_area_width;
6902 }
6903 else
6904 {
6905 *area = RIGHT_MARGIN_AREA;
6906 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6907 }
6908 }
6909
6910 /* Find glyph containing X. */
6911 glyph = row->glyphs[*area];
6912 end = glyph + row->used[*area];
6913 while (glyph < end)
6914 {
6915 if (x < x0 + glyph->pixel_width)
6916 {
6917 if (w->pseudo_window_p)
6918 break;
6919 else if (!buffer_only_p || BUFFERP (glyph->object))
6920 break;
6921 }
6922
6923 x0 += glyph->pixel_width;
6924 ++glyph;
6925 }
6926
6927 if (glyph == end)
6928 return NULL;
6929
6930 *hpos = glyph - row->glyphs[*area];
6931 return glyph;
6932 }
6933
6934
6935 /* Convert frame-relative x/y to coordinates relative to window W.
6936 Takes pseudo-windows into account. */
6937
6938 static void
6939 frame_to_window_pixel_xy (w, x, y)
6940 struct window *w;
6941 int *x, *y;
6942 {
6943 if (w->pseudo_window_p)
6944 {
6945 /* A pseudo-window is always full-width, and starts at the
6946 left edge of the frame, plus a frame border. */
6947 struct frame *f = XFRAME (w->frame);
6948 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6949 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6950 }
6951 else
6952 {
6953 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6954 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6955 }
6956 }
6957
6958
6959 /* Take proper action when mouse has moved to the mode or header line of
6960 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6961 mode line. X is relative to the start of the text display area of
6962 W, so the width of fringes and scroll bars must be subtracted
6963 to get a position relative to the start of the mode line. */
6964
6965 static void
6966 note_mode_line_highlight (w, x, mode_line_p)
6967 struct window *w;
6968 int x, mode_line_p;
6969 {
6970 struct frame *f = XFRAME (w->frame);
6971 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6972 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
6973 struct glyph_row *row;
6974
6975 if (mode_line_p)
6976 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6977 else
6978 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6979
6980 if (row->enabled_p)
6981 {
6982 struct glyph *glyph, *end;
6983 Lisp_Object help, map;
6984 int x0;
6985
6986 /* Find the glyph under X. */
6987 glyph = row->glyphs[TEXT_AREA];
6988 end = glyph + row->used[TEXT_AREA];
6989 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6990 + FRAME_X_LEFT_FRINGE_WIDTH (f));
6991
6992 while (glyph < end
6993 && x >= x0 + glyph->pixel_width)
6994 {
6995 x0 += glyph->pixel_width;
6996 ++glyph;
6997 }
6998
6999 if (glyph < end
7000 && STRINGP (glyph->object)
7001 && XSTRING (glyph->object)->intervals
7002 && glyph->charpos >= 0
7003 && glyph->charpos < XSTRING (glyph->object)->size)
7004 {
7005 /* If we're on a string with `help-echo' text property,
7006 arrange for the help to be displayed. This is done by
7007 setting the global variable help_echo to the help string. */
7008 help = Fget_text_property (make_number (glyph->charpos),
7009 Qhelp_echo, glyph->object);
7010 if (!NILP (help))
7011 {
7012 help_echo = help;
7013 XSETWINDOW (help_echo_window, w);
7014 help_echo_object = glyph->object;
7015 help_echo_pos = glyph->charpos;
7016 }
7017
7018 /* Change the mouse pointer according to what is under X/Y. */
7019 map = Fget_text_property (make_number (glyph->charpos),
7020 Qlocal_map, glyph->object);
7021 if (KEYMAPP (map))
7022 cursor = f->output_data.mac->nontext_cursor;
7023 else
7024 {
7025 map = Fget_text_property (make_number (glyph->charpos),
7026 Qkeymap, glyph->object);
7027 if (KEYMAPP (map))
7028 cursor = f->output_data.mac->nontext_cursor;
7029 }
7030 }
7031 }
7032
7033 #if 0 /* MAC_TODO: mouse cursor */
7034 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7035 #endif
7036 }
7037
7038
7039 /* Take proper action when the mouse has moved to position X, Y on
7040 frame F as regards highlighting characters that have mouse-face
7041 properties. Also de-highlighting chars where the mouse was before.
7042 X and Y can be negative or out of range. */
7043
7044 static void
7045 note_mouse_highlight (f, x, y)
7046 struct frame *f;
7047 int x, y;
7048 {
7049 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7050 int portion;
7051 Lisp_Object window;
7052 struct window *w;
7053 struct buffer *b;
7054
7055 #if 0
7056 /* When a menu is active, don't highlight because this looks odd. */
7057 if (popup_activated ())
7058 return;
7059 #endif
7060
7061 if (NILP (Vmouse_highlight)
7062 || !f->glyphs_initialized_p)
7063 return;
7064
7065 dpyinfo->mouse_face_mouse_x = x;
7066 dpyinfo->mouse_face_mouse_y = y;
7067 dpyinfo->mouse_face_mouse_frame = f;
7068
7069 if (dpyinfo->mouse_face_defer)
7070 return;
7071
7072 if (gc_in_progress)
7073 {
7074 dpyinfo->mouse_face_deferred_gc = 1;
7075 return;
7076 }
7077
7078 /* Which window is that in? */
7079 window = window_from_coordinates (f, x, y, &portion, 1);
7080
7081 /* If we were displaying active text in another window, clear that. */
7082 if (! EQ (window, dpyinfo->mouse_face_window))
7083 clear_mouse_face (dpyinfo);
7084
7085 /* Not on a window -> return. */
7086 if (!WINDOWP (window))
7087 return;
7088
7089 /* Reset help_echo. It will get recomputed below. */
7090 help_echo = Qnil;
7091
7092 /* Convert to window-relative pixel coordinates. */
7093 w = XWINDOW (window);
7094 frame_to_window_pixel_xy (w, &x, &y);
7095
7096 /* Handle tool-bar window differently since it doesn't display a
7097 buffer. */
7098 if (EQ (window, f->tool_bar_window))
7099 {
7100 note_tool_bar_highlight (f, x, y);
7101 return;
7102 }
7103
7104 /* Mouse is on the mode or header line? */
7105 if (portion == 1 || portion == 3)
7106 {
7107 note_mode_line_highlight (w, x, portion == 1);
7108 return;
7109 }
7110 #if 0 /* TODO: mouse cursor */
7111 if (portion == 2)
7112 cursor = f->output_data.x->horizontal_drag_cursor;
7113 else
7114 cursor = f->output_data.x->text_cursor;
7115 #endif
7116 /* Are we in a window whose display is up to date?
7117 And verify the buffer's text has not changed. */
7118 b = XBUFFER (w->buffer);
7119 if (/* Within text portion of the window. */
7120 portion == 0
7121 && EQ (w->window_end_valid, w->buffer)
7122 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7123 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
7124 {
7125 int hpos, vpos, pos, i, area;
7126 struct glyph *glyph;
7127 Lisp_Object object;
7128 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7129 Lisp_Object *overlay_vec = NULL;
7130 int len, noverlays;
7131 struct buffer *obuf;
7132 int obegv, ozv, same_region;
7133
7134 /* Find the glyph under X/Y. */
7135 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
7136
7137 /* Clear mouse face if X/Y not over text. */
7138 if (glyph == NULL
7139 || area != TEXT_AREA
7140 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7141 {
7142 clear_mouse_face (dpyinfo);
7143 /* TODO: mouse cursor */
7144 goto set_cursor;
7145 }
7146
7147 pos = glyph->charpos;
7148 object = glyph->object;
7149 if (!STRINGP (object) && !BUFFERP (object))
7150 goto set_cursor;
7151
7152 /* If we get an out-of-range value, return now; avoid an error. */
7153 if (BUFFERP (object) && pos > BUF_Z (b))
7154 goto set_cursor;
7155
7156 /* Make the window's buffer temporarily current for
7157 overlays_at and compute_char_face. */
7158 obuf = current_buffer;
7159 current_buffer = b;
7160 obegv = BEGV;
7161 ozv = ZV;
7162 BEGV = BEG;
7163 ZV = Z;
7164
7165 /* Is this char mouse-active or does it have help-echo? */
7166 position = make_number (pos);
7167
7168 if (BUFFERP (object))
7169 {
7170 /* Put all the overlays we want in a vector in overlay_vec.
7171 Store the length in len. If there are more than 10, make
7172 enough space for all, and try again. */
7173 len = 10;
7174 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7175 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7176 if (noverlays > len)
7177 {
7178 len = noverlays;
7179 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7180 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7181 }
7182
7183 /* Sort overlays into increasing priority order. */
7184 noverlays = sort_overlays (overlay_vec, noverlays, w);
7185 }
7186 else
7187 noverlays = 0;
7188
7189 same_region = (EQ (window, dpyinfo->mouse_face_window)
7190 && vpos >= dpyinfo->mouse_face_beg_row
7191 && vpos <= dpyinfo->mouse_face_end_row
7192 && (vpos > dpyinfo->mouse_face_beg_row
7193 || hpos >= dpyinfo->mouse_face_beg_col)
7194 && (vpos < dpyinfo->mouse_face_end_row
7195 || hpos < dpyinfo->mouse_face_end_col
7196 || dpyinfo->mouse_face_past_end));
7197
7198 /* TODO: if (same_region)
7199 mouse cursor */
7200
7201 /* Check mouse-face highlighting. */
7202 if (! same_region
7203 /* If there exists an overlay with mouse-face overlapping
7204 the one we are currently highlighting, we have to
7205 check if we enter the overlapping overlay, and then
7206 highlight that. */
7207 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7208 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7209 {
7210 /* Find the highest priority overlay that has a mouse-face
7211 property. */
7212 overlay = Qnil;
7213 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7214 {
7215 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7216 if (!NILP (mouse_face))
7217 overlay = overlay_vec[i];
7218 }
7219
7220 /* If we're actually highlighting the same overlay as
7221 before, there's no need to do that again. */
7222 if (!NILP (overlay)
7223 && EQ (overlay, dpyinfo->mouse_face_overlay))
7224 goto check_help_echo;
7225
7226 dpyinfo->mouse_face_overlay = overlay;
7227
7228 /* Clear the display of the old active region, if any. */
7229 clear_mouse_face (dpyinfo);
7230 /* TODO: mouse cursor changes. */
7231
7232 /* If no overlay applies, get a text property. */
7233 if (NILP (overlay))
7234 mouse_face = Fget_text_property (position, Qmouse_face, object);
7235
7236 /* Handle the overlay case. */
7237 if (!NILP (overlay))
7238 {
7239 /* Find the range of text around this char that
7240 should be active. */
7241 Lisp_Object before, after;
7242 int ignore;
7243
7244 before = Foverlay_start (overlay);
7245 after = Foverlay_end (overlay);
7246 /* Record this as the current active region. */
7247 fast_find_position (w, XFASTINT (before),
7248 &dpyinfo->mouse_face_beg_col,
7249 &dpyinfo->mouse_face_beg_row,
7250 &dpyinfo->mouse_face_beg_x,
7251 &dpyinfo->mouse_face_beg_y, Qnil);
7252
7253 dpyinfo->mouse_face_past_end
7254 = !fast_find_position (w, XFASTINT (after),
7255 &dpyinfo->mouse_face_end_col,
7256 &dpyinfo->mouse_face_end_row,
7257 &dpyinfo->mouse_face_end_x,
7258 &dpyinfo->mouse_face_end_y, Qnil);
7259 dpyinfo->mouse_face_window = window;
7260
7261 dpyinfo->mouse_face_face_id
7262 = face_at_buffer_position (w, pos, 0, 0,
7263 &ignore, pos + 1, 1);
7264
7265 /* Display it as active. */
7266 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7267 /* TODO: mouse cursor changes. */
7268 }
7269 /* Handle the text property case. */
7270 else if (! NILP (mouse_face) && BUFFERP (object))
7271 {
7272 /* Find the range of text around this char that
7273 should be active. */
7274 Lisp_Object before, after, beginning, end;
7275 int ignore;
7276
7277 beginning = Fmarker_position (w->start);
7278 end = make_number (BUF_Z (XBUFFER (object))
7279 - XFASTINT (w->window_end_pos));
7280 before
7281 = Fprevious_single_property_change (make_number (pos + 1),
7282 Qmouse_face,
7283 object, beginning);
7284 after
7285 = Fnext_single_property_change (position, Qmouse_face,
7286 object, end);
7287
7288 /* Record this as the current active region. */
7289 fast_find_position (w, XFASTINT (before),
7290 &dpyinfo->mouse_face_beg_col,
7291 &dpyinfo->mouse_face_beg_row,
7292 &dpyinfo->mouse_face_beg_x,
7293 &dpyinfo->mouse_face_beg_y, Qnil);
7294 dpyinfo->mouse_face_past_end
7295 = !fast_find_position (w, XFASTINT (after),
7296 &dpyinfo->mouse_face_end_col,
7297 &dpyinfo->mouse_face_end_row,
7298 &dpyinfo->mouse_face_end_x,
7299 &dpyinfo->mouse_face_end_y, Qnil);
7300 dpyinfo->mouse_face_window = window;
7301
7302 if (BUFFERP (object))
7303 dpyinfo->mouse_face_face_id
7304 = face_at_buffer_position (w, pos, 0, 0,
7305 &ignore, pos + 1, 1);
7306
7307 /* Display it as active. */
7308 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7309 /* TODO: mouse cursor changes. */
7310 }
7311 else if (!NILP (mouse_face) && STRINGP (object))
7312 {
7313 Lisp_Object b, e;
7314 int ignore;
7315
7316 b = Fprevious_single_property_change (make_number (pos + 1),
7317 Qmouse_face,
7318 object, Qnil);
7319 e = Fnext_single_property_change (position, Qmouse_face,
7320 object, Qnil);
7321 if (NILP (b))
7322 b = make_number (0);
7323 if (NILP (e))
7324 e = make_number (XSTRING (object)->size - 1);
7325 fast_find_string_pos (w, XINT (b), object,
7326 &dpyinfo->mouse_face_beg_col,
7327 &dpyinfo->mouse_face_beg_row,
7328 &dpyinfo->mouse_face_beg_x,
7329 &dpyinfo->mouse_face_beg_y, 0);
7330 fast_find_string_pos (w, XINT (e), object,
7331 &dpyinfo->mouse_face_end_col,
7332 &dpyinfo->mouse_face_end_row,
7333 &dpyinfo->mouse_face_end_x,
7334 &dpyinfo->mouse_face_end_y, 1);
7335 dpyinfo->mouse_face_past_end = 0;
7336 dpyinfo->mouse_face_window = window;
7337 dpyinfo->mouse_face_face_id
7338 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7339 glyph->face_id, 1);
7340 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7341 /* TODO: mouse cursor changes. */
7342 }
7343 else if (STRINGP (object) && NILP (mouse_face))
7344 {
7345 /* A string which doesn't have mouse-face, but
7346 the text ``under'' it might have. */
7347 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7348 int start = MATRIX_ROW_START_CHARPOS (r);
7349
7350 pos = string_buffer_position (w, object, start);
7351 if (pos > 0)
7352 mouse_face = get_char_property_and_overlay (make_number (pos),
7353 Qmouse_face,
7354 w->buffer,
7355 &overlay);
7356 if (!NILP (mouse_face) && !NILP (overlay))
7357 {
7358 Lisp_Object before = Foverlay_start (overlay);
7359 Lisp_Object after = Foverlay_end (overlay);
7360 int ignore;
7361
7362 /* Note that we might not be able to find position
7363 BEFORE in the glyph matrix if the overlay is
7364 entirely covered by a `display' property. In
7365 this case, we overshoot. So let's stop in
7366 the glyph matrix before glyphs for OBJECT. */
7367 fast_find_position (w, XFASTINT (before),
7368 &dpyinfo->mouse_face_beg_col,
7369 &dpyinfo->mouse_face_beg_row,
7370 &dpyinfo->mouse_face_beg_x,
7371 &dpyinfo->mouse_face_beg_y,
7372 object);
7373
7374 dpyinfo->mouse_face_past_end
7375 = !fast_find_position (w, XFASTINT (after),
7376 &dpyinfo->mouse_face_end_col,
7377 &dpyinfo->mouse_face_end_row,
7378 &dpyinfo->mouse_face_end_x,
7379 &dpyinfo->mouse_face_end_y,
7380 Qnil);
7381 dpyinfo->mouse_face_window = window;
7382 dpyinfo->mouse_face_face_id
7383 = face_at_buffer_position (w, pos, 0, 0,
7384 &ignore, pos + 1, 1);
7385
7386 /* Display it as active. */
7387 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7388 /* TODO: mouse cursor changes. */
7389 }
7390 }
7391 }
7392
7393 check_help_echo:
7394
7395 /* Look for a `help-echo' property. */
7396 {
7397 Lisp_Object help, overlay;
7398
7399 /* Check overlays first. */
7400 help = overlay = Qnil;
7401 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7402 {
7403 overlay = overlay_vec[i];
7404 help = Foverlay_get (overlay, Qhelp_echo);
7405 }
7406
7407 if (!NILP (help))
7408 {
7409 help_echo = help;
7410 help_echo_window = window;
7411 help_echo_object = overlay;
7412 help_echo_pos = pos;
7413 }
7414 else
7415 {
7416 Lisp_Object object = glyph->object;
7417 int charpos = glyph->charpos;
7418
7419 /* Try text properties. */
7420 if (STRINGP (object)
7421 && charpos >= 0
7422 && charpos < XSTRING (object)->size)
7423 {
7424 help = Fget_text_property (make_number (charpos),
7425 Qhelp_echo, object);
7426 if (NILP (help))
7427 {
7428 /* If the string itself doesn't specify a help-echo,
7429 see if the buffer text ``under'' it does. */
7430 struct glyph_row *r
7431 = MATRIX_ROW (w->current_matrix, vpos);
7432 int start = MATRIX_ROW_START_CHARPOS (r);
7433 int pos = string_buffer_position (w, object, start);
7434 if (pos > 0)
7435 {
7436 help = Fget_char_property (make_number (pos),
7437 Qhelp_echo, w->buffer);
7438 if (!NILP (help))
7439 {
7440 charpos = pos;
7441 object = w->buffer;
7442 }
7443 }
7444 }
7445 }
7446 else if (BUFFERP (object)
7447 && charpos >= BEGV
7448 && charpos < ZV)
7449 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7450 object);
7451
7452 if (!NILP (help))
7453 {
7454 help_echo = help;
7455 help_echo_window = window;
7456 help_echo_object = object;
7457 help_echo_pos = charpos;
7458 }
7459 }
7460 }
7461
7462 BEGV = obegv;
7463 ZV = ozv;
7464 current_buffer = obuf;
7465 }
7466
7467 set_cursor:
7468 /* TODO: mouse cursor changes. */
7469 ;
7470 }
7471
7472 static void
7473 redo_mouse_highlight ()
7474 {
7475 if (!NILP (last_mouse_motion_frame)
7476 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7477 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7478 last_mouse_motion_position.h,
7479 last_mouse_motion_position.v);
7480 }
7481
7482
7483 \f
7484 /***********************************************************************
7485 Tool-bars
7486 ***********************************************************************/
7487
7488 static int x_tool_bar_item P_ ((struct frame *, int, int,
7489 struct glyph **, int *, int *, int *));
7490
7491 /* Tool-bar item index of the item on which a mouse button was pressed
7492 or -1. */
7493
7494 static int last_tool_bar_item;
7495
7496
7497 /* Get information about the tool-bar item at position X/Y on frame F.
7498 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7499 the current matrix of the tool-bar window of F, or NULL if not
7500 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7501 item in F->current_tool_bar_items. Value is
7502
7503 -1 if X/Y is not on a tool-bar item
7504 0 if X/Y is on the same item that was highlighted before.
7505 1 otherwise. */
7506
7507 static int
7508 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7509 struct frame *f;
7510 int x, y;
7511 struct glyph **glyph;
7512 int *hpos, *vpos, *prop_idx;
7513 {
7514 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7515 struct window *w = XWINDOW (f->tool_bar_window);
7516 int area;
7517
7518 /* Find the glyph under X/Y. */
7519 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7520 if (*glyph == NULL)
7521 return -1;
7522
7523 /* Get the start of this tool-bar item's properties in
7524 f->current_tool_bar_items. */
7525 if (!tool_bar_item_info (f, *glyph, prop_idx))
7526 return -1;
7527
7528 /* Is mouse on the highlighted item? */
7529 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7530 && *vpos >= dpyinfo->mouse_face_beg_row
7531 && *vpos <= dpyinfo->mouse_face_end_row
7532 && (*vpos > dpyinfo->mouse_face_beg_row
7533 || *hpos >= dpyinfo->mouse_face_beg_col)
7534 && (*vpos < dpyinfo->mouse_face_end_row
7535 || *hpos < dpyinfo->mouse_face_end_col
7536 || dpyinfo->mouse_face_past_end))
7537 return 0;
7538
7539 return 1;
7540 }
7541
7542
7543 /* Handle mouse button event on the tool-bar of frame F, at
7544 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7545 or ButtonRelase. */
7546
7547 static void
7548 x_handle_tool_bar_click (f, button_event)
7549 struct frame *f;
7550 EventRecord *button_event;
7551 {
7552 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7553 struct window *w = XWINDOW (f->tool_bar_window);
7554 int hpos, vpos, prop_idx;
7555 struct glyph *glyph;
7556 Lisp_Object enabled_p;
7557 int x = button_event->where.h;
7558 int y = button_event->where.v;
7559
7560 /* If not on the highlighted tool-bar item, return. */
7561 frame_to_window_pixel_xy (w, &x, &y);
7562 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7563 return;
7564
7565 /* If item is disabled, do nothing. */
7566 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7567 if (NILP (enabled_p))
7568 return;
7569
7570 if (button_event->what == mouseDown)
7571 {
7572 /* Show item in pressed state. */
7573 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7574 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7575 last_tool_bar_item = prop_idx;
7576 }
7577 else
7578 {
7579 Lisp_Object key, frame;
7580 struct input_event event;
7581
7582 /* Show item in released state. */
7583 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7584 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7585
7586 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7587
7588 XSETFRAME (frame, f);
7589 event.kind = TOOL_BAR_EVENT;
7590 event.frame_or_window = frame;
7591 event.arg = frame;
7592 kbd_buffer_store_event (&event);
7593
7594 event.kind = TOOL_BAR_EVENT;
7595 event.frame_or_window = frame;
7596 event.arg = key;
7597 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7598 button_event->modifiers);
7599 kbd_buffer_store_event (&event);
7600 last_tool_bar_item = -1;
7601 }
7602 }
7603
7604
7605 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7606 tool-bar window-relative coordinates X/Y. Called from
7607 note_mouse_highlight. */
7608
7609 static void
7610 note_tool_bar_highlight (f, x, y)
7611 struct frame *f;
7612 int x, y;
7613 {
7614 Lisp_Object window = f->tool_bar_window;
7615 struct window *w = XWINDOW (window);
7616 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7617 int hpos, vpos;
7618 struct glyph *glyph;
7619 struct glyph_row *row;
7620 int i;
7621 Lisp_Object enabled_p;
7622 int prop_idx;
7623 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7624 int mouse_down_p, rc;
7625
7626 /* Function note_mouse_highlight is called with negative x(y
7627 values when mouse moves outside of the frame. */
7628 if (x <= 0 || y <= 0)
7629 {
7630 clear_mouse_face (dpyinfo);
7631 return;
7632 }
7633
7634 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7635 if (rc < 0)
7636 {
7637 /* Not on tool-bar item. */
7638 clear_mouse_face (dpyinfo);
7639 return;
7640 }
7641 else if (rc == 0)
7642 /* On same tool-bar item as before. */
7643 goto set_help_echo;
7644
7645 clear_mouse_face (dpyinfo);
7646
7647 /* Mouse is down, but on different tool-bar item? */
7648 mouse_down_p = (dpyinfo->grabbed
7649 && f == last_mouse_frame
7650 && FRAME_LIVE_P (f));
7651 if (mouse_down_p
7652 && last_tool_bar_item != prop_idx)
7653 return;
7654
7655 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7656 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7657
7658 /* If tool-bar item is not enabled, don't highlight it. */
7659 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7660 if (!NILP (enabled_p))
7661 {
7662 /* Compute the x-position of the glyph. In front and past the
7663 image is a space. We include this is the highlighted area. */
7664 row = MATRIX_ROW (w->current_matrix, vpos);
7665 for (i = x = 0; i < hpos; ++i)
7666 x += row->glyphs[TEXT_AREA][i].pixel_width;
7667
7668 /* Record this as the current active region. */
7669 dpyinfo->mouse_face_beg_col = hpos;
7670 dpyinfo->mouse_face_beg_row = vpos;
7671 dpyinfo->mouse_face_beg_x = x;
7672 dpyinfo->mouse_face_beg_y = row->y;
7673 dpyinfo->mouse_face_past_end = 0;
7674
7675 dpyinfo->mouse_face_end_col = hpos + 1;
7676 dpyinfo->mouse_face_end_row = vpos;
7677 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7678 dpyinfo->mouse_face_end_y = row->y;
7679 dpyinfo->mouse_face_window = window;
7680 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7681
7682 /* Display it as active. */
7683 show_mouse_face (dpyinfo, draw);
7684 dpyinfo->mouse_face_image_state = draw;
7685 }
7686
7687 set_help_echo:
7688
7689 /* Set help_echo to a help string.to display for this tool-bar item.
7690 XTread_socket does the rest. */
7691 help_echo_object = help_echo_window = Qnil;
7692 help_echo_pos = -1;
7693 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7694 if (NILP (help_echo))
7695 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7696 }
7697
7698
7699 \f
7700 /* Find the glyph matrix position of buffer position CHARPOS in window
7701 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7702 current glyphs must be up to date. If CHARPOS is above window
7703 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7704 of last line in W. In the row containing CHARPOS, stop before glyphs
7705 having STOP as object. */
7706
7707 #if 0 /* This is a version of fast_find_position that's more correct
7708 in the presence of hscrolling, for example. I didn't install
7709 it right away because the problem fixed is minor, it failed
7710 in 20.x as well, and I think it's too risky to install
7711 so near the release of 21.1. 2001-09-25 gerd. */
7712
7713 static int
7714 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7715 struct window *w;
7716 int charpos;
7717 int *hpos, *vpos, *x, *y;
7718 Lisp_Object stop;
7719 {
7720 struct glyph_row *row, *first;
7721 struct glyph *glyph, *end;
7722 int i, past_end = 0;
7723
7724 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7725 row = row_containing_pos (w, charpos, first, NULL, 0);
7726 if (row == NULL)
7727 {
7728 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7729 {
7730 *x = *y = *hpos = *vpos = 0;
7731 return 0;
7732 }
7733 else
7734 {
7735 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7736 past_end = 1;
7737 }
7738 }
7739
7740 *x = row->x;
7741 *y = row->y;
7742 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7743
7744 glyph = row->glyphs[TEXT_AREA];
7745 end = glyph + row->used[TEXT_AREA];
7746
7747 /* Skip over glyphs not having an object at the start of the row.
7748 These are special glyphs like truncation marks on terminal
7749 frames. */
7750 if (row->displays_text_p)
7751 while (glyph < end
7752 && INTEGERP (glyph->object)
7753 && !EQ (stop, glyph->object)
7754 && glyph->charpos < 0)
7755 {
7756 *x += glyph->pixel_width;
7757 ++glyph;
7758 }
7759
7760 while (glyph < end
7761 && !INTEGERP (glyph->object)
7762 && !EQ (stop, glyph->object)
7763 && (!BUFFERP (glyph->object)
7764 || glyph->charpos < charpos))
7765 {
7766 *x += glyph->pixel_width;
7767 ++glyph;
7768 }
7769
7770 *hpos = glyph - row->glyphs[TEXT_AREA];
7771 return past_end;
7772 }
7773
7774 #else /* not 0 */
7775
7776 static int
7777 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7778 struct window *w;
7779 int pos;
7780 int *hpos, *vpos, *x, *y;
7781 Lisp_Object stop;
7782 {
7783 int i;
7784 int lastcol;
7785 int maybe_next_line_p = 0;
7786 int line_start_position;
7787 int yb = window_text_bottom_y (w);
7788 struct glyph_row *row, *best_row;
7789 int row_vpos, best_row_vpos;
7790 int current_x;
7791
7792 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7793 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7794
7795 while (row->y < yb)
7796 {
7797 if (row->used[TEXT_AREA])
7798 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7799 else
7800 line_start_position = 0;
7801
7802 if (line_start_position > pos)
7803 break;
7804 /* If the position sought is the end of the buffer,
7805 don't include the blank lines at the bottom of the window. */
7806 else if (line_start_position == pos
7807 && pos == BUF_ZV (XBUFFER (w->buffer)))
7808 {
7809 maybe_next_line_p = 1;
7810 break;
7811 }
7812 else if (line_start_position > 0)
7813 {
7814 best_row = row;
7815 best_row_vpos = row_vpos;
7816 }
7817
7818 if (row->y + row->height >= yb)
7819 break;
7820
7821 ++row;
7822 ++row_vpos;
7823 }
7824
7825 /* Find the right column within BEST_ROW. */
7826 lastcol = 0;
7827 current_x = best_row->x;
7828 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7829 {
7830 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7831 int charpos = glyph->charpos;
7832
7833 if (BUFFERP (glyph->object))
7834 {
7835 if (charpos == pos)
7836 {
7837 *hpos = i;
7838 *vpos = best_row_vpos;
7839 *x = current_x;
7840 *y = best_row->y;
7841 return 1;
7842 }
7843 else if (charpos > pos)
7844 break;
7845 }
7846 else if (EQ (glyph->object, stop))
7847 break;
7848
7849 if (charpos > 0)
7850 lastcol = i;
7851 current_x += glyph->pixel_width;
7852 }
7853
7854 /* If we're looking for the end of the buffer,
7855 and we didn't find it in the line we scanned,
7856 use the start of the following line. */
7857 if (maybe_next_line_p)
7858 {
7859 ++best_row;
7860 ++best_row_vpos;
7861 lastcol = 0;
7862 current_x = best_row->x;
7863 }
7864
7865 *vpos = best_row_vpos;
7866 *hpos = lastcol + 1;
7867 *x = current_x;
7868 *y = best_row->y;
7869 return 0;
7870 }
7871
7872 #endif /* not 0 */
7873
7874
7875 /* Find the position of the glyph for position POS in OBJECT in
7876 window W's current matrix, and return in *X/*Y the pixel
7877 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7878
7879 RIGHT_P non-zero means return the position of the right edge of the
7880 glyph, RIGHT_P zero means return the left edge position.
7881
7882 If no glyph for POS exists in the matrix, return the position of
7883 the glyph with the next smaller position that is in the matrix, if
7884 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7885 exists in the matrix, return the position of the glyph with the
7886 next larger position in OBJECT.
7887
7888 Value is non-zero if a glyph was found. */
7889
7890 static int
7891 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7892 struct window *w;
7893 int pos;
7894 Lisp_Object object;
7895 int *hpos, *vpos, *x, *y;
7896 int right_p;
7897 {
7898 int yb = window_text_bottom_y (w);
7899 struct glyph_row *r;
7900 struct glyph *best_glyph = NULL;
7901 struct glyph_row *best_row = NULL;
7902 int best_x = 0;
7903
7904 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7905 r->enabled_p && r->y < yb;
7906 ++r)
7907 {
7908 struct glyph *g = r->glyphs[TEXT_AREA];
7909 struct glyph *e = g + r->used[TEXT_AREA];
7910 int gx;
7911
7912 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7913 if (EQ (g->object, object))
7914 {
7915 if (g->charpos == pos)
7916 {
7917 best_glyph = g;
7918 best_x = gx;
7919 best_row = r;
7920 goto found;
7921 }
7922 else if (best_glyph == NULL
7923 || ((abs (g->charpos - pos)
7924 < abs (best_glyph->charpos - pos))
7925 && (right_p
7926 ? g->charpos < pos
7927 : g->charpos > pos)))
7928 {
7929 best_glyph = g;
7930 best_x = gx;
7931 best_row = r;
7932 }
7933 }
7934 }
7935
7936 found:
7937
7938 if (best_glyph)
7939 {
7940 *x = best_x;
7941 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7942
7943 if (right_p)
7944 {
7945 *x += best_glyph->pixel_width;
7946 ++*hpos;
7947 }
7948
7949 *y = best_row->y;
7950 *vpos = best_row - w->current_matrix->rows;
7951 }
7952
7953 return best_glyph != NULL;
7954 }
7955
7956
7957 /* Display the active region described by mouse_face_*
7958 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7959
7960 static void
7961 show_mouse_face (dpyinfo, draw)
7962 struct mac_display_info *dpyinfo;
7963 enum draw_glyphs_face draw;
7964 {
7965 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7966 struct frame *f = XFRAME (WINDOW_FRAME (w));
7967
7968 if (/* If window is in the process of being destroyed, don't bother
7969 to do anything. */
7970 w->current_matrix != NULL
7971 /* Don't update mouse highlight if hidden */
7972 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7973 /* Recognize when we are called to operate on rows that don't exist
7974 anymore. This can happen when a window is split. */
7975 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7976 {
7977 int phys_cursor_on_p = w->phys_cursor_on_p;
7978 struct glyph_row *row, *first, *last;
7979
7980 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7981 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7982
7983 for (row = first; row <= last && row->enabled_p; ++row)
7984 {
7985 int start_hpos, end_hpos, start_x;
7986
7987 /* For all but the first row, the highlight starts at column 0. */
7988 if (row == first)
7989 {
7990 start_hpos = dpyinfo->mouse_face_beg_col;
7991 start_x = dpyinfo->mouse_face_beg_x;
7992 }
7993 else
7994 {
7995 start_hpos = 0;
7996 start_x = 0;
7997 }
7998
7999 if (row == last)
8000 end_hpos = dpyinfo->mouse_face_end_col;
8001 else
8002 end_hpos = row->used[TEXT_AREA];
8003
8004 if (end_hpos > start_hpos)
8005 {
8006 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8007 start_hpos, end_hpos, draw, 0);
8008
8009 row->mouse_face_p
8010 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8011 }
8012 }
8013
8014 /* When we've written over the cursor, arrange for it to
8015 be displayed again. */
8016 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8017 x_display_cursor (w, 1,
8018 w->phys_cursor.hpos, w->phys_cursor.vpos,
8019 w->phys_cursor.x, w->phys_cursor.y);
8020 }
8021
8022 #if 0 /* MAC_TODO: mouse cursor */
8023 /* Change the mouse cursor. */
8024 if (draw == DRAW_NORMAL_TEXT)
8025 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8026 f->output_data.x->text_cursor);
8027 else if (draw == DRAW_MOUSE_FACE)
8028 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8029 f->output_data.x->cross_cursor);
8030 else
8031 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8032 f->output_data.x->nontext_cursor);
8033 #endif
8034 }
8035
8036 /* Clear out the mouse-highlighted active region.
8037 Redraw it un-highlighted first. */
8038
8039 static int
8040 clear_mouse_face (dpyinfo)
8041 struct mac_display_info *dpyinfo;
8042 {
8043 int cleared = 0;
8044
8045 if (! NILP (dpyinfo->mouse_face_window))
8046 {
8047 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8048 cleared = 1;
8049 }
8050
8051 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8052 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8053 dpyinfo->mouse_face_window = Qnil;
8054 dpyinfo->mouse_face_overlay = Qnil;
8055 return cleared;
8056 }
8057
8058
8059 /* Clear any mouse-face on window W. This function is part of the
8060 redisplay interface, and is called from try_window_id and similar
8061 functions to ensure the mouse-highlight is off. */
8062
8063 static void
8064 x_clear_mouse_face (w)
8065 struct window *w;
8066 {
8067 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
8068 Lisp_Object window;
8069
8070 BLOCK_INPUT;
8071 XSETWINDOW (window, w);
8072 if (EQ (window, dpyinfo->mouse_face_window))
8073 clear_mouse_face (dpyinfo);
8074 UNBLOCK_INPUT;
8075 }
8076
8077
8078 /* Just discard the mouse face information for frame F, if any.
8079 This is used when the size of F is changed. */
8080
8081 void
8082 cancel_mouse_face (f)
8083 FRAME_PTR f;
8084 {
8085 Lisp_Object window;
8086 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8087
8088 window = dpyinfo->mouse_face_window;
8089 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8090 {
8091 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8092 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8093 dpyinfo->mouse_face_window = Qnil;
8094 }
8095 }
8096 \f
8097 static struct scroll_bar *x_window_to_scroll_bar ();
8098 static void x_scroll_bar_report_motion ();
8099 static void x_check_fullscreen P_ ((struct frame *));
8100 static void x_check_fullscreen_move P_ ((struct frame *));
8101 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
8102
8103
8104 /* Try to determine frame pixel position and size of the glyph under
8105 frame pixel coordinates X/Y on frame F . Return the position and
8106 size in *RECT. Value is non-zero if we could compute these
8107 values. */
8108
8109 static int
8110 glyph_rect (f, x, y, rect)
8111 struct frame *f;
8112 int x, y;
8113 Rect *rect;
8114 {
8115 Lisp_Object window;
8116 int part;
8117
8118 window = window_from_coordinates (f, x, y, &part, 0);
8119 if (!NILP (window))
8120 {
8121 struct window *w = XWINDOW (window);
8122 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8123 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8124
8125 frame_to_window_pixel_xy (w, &x, &y);
8126
8127 for (; r < end && r->enabled_p; ++r)
8128 if (r->y <= y && r->y + r->height > y)
8129 {
8130 /* Found the row at y. */
8131 struct glyph *g = r->glyphs[TEXT_AREA];
8132 struct glyph *end = g + r->used[TEXT_AREA];
8133 int gx;
8134
8135 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8136 rect->bottom = rect->top + r->height;
8137
8138 if (x < r->x)
8139 {
8140 /* x is to the left of the first glyph in the row. */
8141 rect->left = XINT (w->left);
8142 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
8143 return 1;
8144 }
8145
8146 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
8147 if (gx <= x && gx + g->pixel_width > x)
8148 {
8149 /* x is on a glyph. */
8150 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8151 rect->right = rect->left + g->pixel_width;
8152 return 1;
8153 }
8154
8155 /* x is to the right of the last glyph in the row. */
8156 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8157 rect->right = XINT (w->left) + XINT (w->width);
8158 return 1;
8159 }
8160 }
8161
8162 /* The y is not on any row. */
8163 return 0;
8164 }
8165
8166 /* Record the position of the mouse in last_mouse_glyph. */
8167 static void
8168 remember_mouse_glyph (f1, gx, gy)
8169 struct frame * f1;
8170 int gx, gy;
8171 {
8172 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
8173 {
8174 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8175 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8176
8177 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8178 round down even for negative values. */
8179 if (gx < 0)
8180 gx -= width - 1;
8181 if (gy < 0)
8182 gy -= height - 1;
8183 #if 0
8184 /* This was the original code from XTmouse_position, but it seems
8185 to give the position of the glyph diagonally next to the one
8186 the mouse is over. */
8187 gx = (gx + width - 1) / width * width;
8188 gy = (gy + height - 1) / height * height;
8189 #else
8190 gx = gx / width * width;
8191 gy = gy / height * height;
8192 #endif
8193
8194 last_mouse_glyph.left = gx;
8195 last_mouse_glyph.top = gy;
8196 last_mouse_glyph.right = gx + width;
8197 last_mouse_glyph.bottom = gy + height;
8198 }
8199 }
8200
8201 /* Return the current position of the mouse.
8202 *fp should be a frame which indicates which display to ask about.
8203
8204 If the mouse movement started in a scroll bar, set *fp, *bar_window,
8205 and *part to the frame, window, and scroll bar part that the mouse
8206 is over. Set *x and *y to the portion and whole of the mouse's
8207 position on the scroll bar.
8208
8209 If the mouse movement started elsewhere, set *fp to the frame the
8210 mouse is on, *bar_window to nil, and *x and *y to the character cell
8211 the mouse is over.
8212
8213 Set *time to the server time-stamp for the time at which the mouse
8214 was at this position.
8215
8216 Don't store anything if we don't have a valid set of values to report.
8217
8218 This clears the mouse_moved flag, so we can wait for the next mouse
8219 movement. */
8220
8221 static void
8222 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8223 FRAME_PTR *fp;
8224 int insist;
8225 Lisp_Object *bar_window;
8226 enum scroll_bar_part *part;
8227 Lisp_Object *x, *y;
8228 unsigned long *time;
8229 {
8230 Point mouse_pos;
8231 int ignore1, ignore2;
8232 WindowPtr wp = FrontWindow ();
8233 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8234 Lisp_Object frame, tail;
8235
8236 BLOCK_INPUT;
8237
8238 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8239 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8240 else
8241 {
8242 /* Clear the mouse-moved flag for every frame on this display. */
8243 FOR_EACH_FRAME (tail, frame)
8244 XFRAME (frame)->mouse_moved = 0;
8245
8246 last_mouse_scroll_bar = Qnil;
8247
8248 #if TARGET_API_MAC_CARBON
8249 SetPort (GetWindowPort (wp));
8250 #else
8251 SetPort (wp);
8252 #endif
8253
8254 GetMouse (&mouse_pos);
8255
8256 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
8257 &last_mouse_glyph, insist);
8258
8259 *bar_window = Qnil;
8260 *part = scroll_bar_handle;
8261 *fp = f;
8262 XSETINT (*x, mouse_pos.h);
8263 XSETINT (*y, mouse_pos.v);
8264 *time = last_mouse_movement_time;
8265 }
8266
8267 UNBLOCK_INPUT;
8268 }
8269
8270 \f
8271 /************************************************************************
8272 Scroll bars, general
8273 ************************************************************************/
8274
8275 /* Create a scroll bar and return the scroll bar vector for it. W is
8276 the Emacs window on which to create the scroll bar. TOP, LEFT,
8277 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
8278 scroll bar. */
8279
8280 static struct scroll_bar *
8281 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
8282 struct window *w;
8283 int top, left, width, height, disp_top, disp_height;
8284 {
8285 struct frame *f = XFRAME (w->frame);
8286 struct scroll_bar *bar
8287 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8288 Rect r;
8289 ControlHandle ch;
8290
8291 BLOCK_INPUT;
8292
8293 r.left = left;
8294 r.top = disp_top;
8295 r.right = left + width;
8296 r.bottom = disp_top + disp_height;
8297
8298 #ifdef TARGET_API_MAC_CARBON
8299 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
8300 kControlScrollBarProc, 0L);
8301 #else
8302 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
8303 0L);
8304 #endif
8305 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
8306 SetControlReference (ch, (long) bar);
8307
8308 XSETWINDOW (bar->window, w);
8309 XSETINT (bar->top, top);
8310 XSETINT (bar->left, left);
8311 XSETINT (bar->width, width);
8312 XSETINT (bar->height, height);
8313 XSETINT (bar->start, 0);
8314 XSETINT (bar->end, 0);
8315 bar->dragging = Qnil;
8316
8317 /* Add bar to its frame's list of scroll bars. */
8318 bar->next = FRAME_SCROLL_BARS (f);
8319 bar->prev = Qnil;
8320 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8321 if (!NILP (bar->next))
8322 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8323
8324 UNBLOCK_INPUT;
8325 return bar;
8326 }
8327
8328
8329 /* Draw BAR's handle in the proper position.
8330
8331 If the handle is already drawn from START to END, don't bother
8332 redrawing it, unless REBUILD is non-zero; in that case, always
8333 redraw it. (REBUILD is handy for drawing the handle after expose
8334 events.)
8335
8336 Normally, we want to constrain the start and end of the handle to
8337 fit inside its rectangle, but if the user is dragging the scroll
8338 bar handle, we want to let them drag it down all the way, so that
8339 the bar's top is as far down as it goes; otherwise, there's no way
8340 to move to the very end of the buffer. */
8341
8342 static void
8343 x_scroll_bar_set_handle (bar, start, end, rebuild)
8344 struct scroll_bar *bar;
8345 int start, end;
8346 int rebuild;
8347 {
8348 int dragging = ! NILP (bar->dragging);
8349 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8350 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8351 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8352 int length = end - start;
8353
8354 /* If the display is already accurate, do nothing. */
8355 if (! rebuild
8356 && start == XINT (bar->start)
8357 && end == XINT (bar->end))
8358 return;
8359
8360 BLOCK_INPUT;
8361
8362 /* Make sure the values are reasonable, and try to preserve the
8363 distance between start and end. */
8364 if (start < 0)
8365 start = 0;
8366 else if (start > top_range)
8367 start = top_range;
8368 end = start + length;
8369
8370 if (end < start)
8371 end = start;
8372 else if (end > top_range && ! dragging)
8373 end = top_range;
8374
8375 /* Store the adjusted setting in the scroll bar. */
8376 XSETINT (bar->start, start);
8377 XSETINT (bar->end, end);
8378
8379 /* Clip the end position, just for display. */
8380 if (end > top_range)
8381 end = top_range;
8382
8383 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
8384 top positions, to make sure the handle is always at least that
8385 many pixels tall. */
8386 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8387
8388 SetControlMinimum (ch, 0);
8389 /* Don't inadvertently activate deactivated scroll bars */
8390 if (GetControlMaximum (ch) != -1)
8391 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
8392 - (end - start));
8393 SetControlValue (ch, start);
8394 #if TARGET_API_MAC_CARBON
8395 SetControlViewSize (ch, end - start);
8396 #endif
8397
8398 UNBLOCK_INPUT;
8399 }
8400
8401
8402 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8403 nil. */
8404
8405 static void
8406 x_scroll_bar_remove (bar)
8407 struct scroll_bar *bar;
8408 {
8409 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8410
8411 BLOCK_INPUT;
8412
8413 /* Destroy the Mac scroll bar control */
8414 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
8415
8416 /* Disassociate this scroll bar from its window. */
8417 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8418
8419 UNBLOCK_INPUT;
8420 }
8421
8422 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8423 that we are displaying PORTION characters out of a total of WHOLE
8424 characters, starting at POSITION. If WINDOW has no scroll bar,
8425 create one. */
8426 static void
8427 XTset_vertical_scroll_bar (w, portion, whole, position)
8428 struct window *w;
8429 int portion, whole, position;
8430 {
8431 struct frame *f = XFRAME (w->frame);
8432 struct scroll_bar *bar;
8433 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
8434 int window_x, window_y, window_width, window_height;
8435
8436 /* Get window dimensions. */
8437 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8438 top = window_y;
8439 #ifdef MAC_OSX
8440 width = 16;
8441 #else
8442 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8443 #endif
8444 height = window_height;
8445
8446 /* Compute the left edge of the scroll bar area. */
8447 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8448 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8449 else
8450 left = XFASTINT (w->left);
8451 left *= CANON_X_UNIT (f);
8452 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8453
8454 /* Compute the width of the scroll bar which might be less than
8455 the width of the area reserved for the scroll bar. */
8456 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8457 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8458 else
8459 sb_width = width;
8460
8461 /* Compute the left edge of the scroll bar. */
8462 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8463 sb_left = left + width - sb_width - (width - sb_width) / 2;
8464 else
8465 sb_left = left + (width - sb_width) / 2;
8466
8467 /* Adjustments according to Inside Macintosh to make it look nice */
8468 disp_top = top;
8469 disp_height = height;
8470 if (disp_top == 0)
8471 {
8472 disp_top = -1;
8473 disp_height++;
8474 }
8475 else if (disp_top == PIXEL_HEIGHT (f) - 16)
8476 {
8477 disp_top++;
8478 disp_height--;
8479 }
8480
8481 if (sb_left + sb_width == PIXEL_WIDTH (f))
8482 sb_left++;
8483
8484 /* Does the scroll bar exist yet? */
8485 if (NILP (w->vertical_scroll_bar))
8486 {
8487 BLOCK_INPUT;
8488 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8489 left, top, width, height, 0);
8490 UNBLOCK_INPUT;
8491 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
8492 disp_height);
8493 XSETVECTOR (w->vertical_scroll_bar, bar);
8494 }
8495 else
8496 {
8497 /* It may just need to be moved and resized. */
8498 ControlHandle ch;
8499
8500 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8501 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
8502
8503 BLOCK_INPUT;
8504
8505 /* If already correctly positioned, do nothing. */
8506 if (XINT (bar->left) == sb_left
8507 && XINT (bar->top) == top
8508 && XINT (bar->width) == sb_width
8509 && XINT (bar->height) == height)
8510 Draw1Control (ch);
8511 else
8512 {
8513 /* Clear areas not covered by the scroll bar because it's not as
8514 wide as the area reserved for it . This makes sure a
8515 previous mode line display is cleared after C-x 2 C-x 1, for
8516 example. */
8517 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8518 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8519 left, top, area_width, height, 0);
8520
8521 #if 0
8522 if (sb_left + sb_width >= PIXEL_WIDTH (f))
8523 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
8524 sb_left - 1, top, 1, height, 0);
8525 #endif
8526
8527 HideControl (ch);
8528 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
8529 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8530 disp_height);
8531 ShowControl (ch);
8532
8533 /* Remember new settings. */
8534 XSETINT (bar->left, sb_left);
8535 XSETINT (bar->top, top);
8536 XSETINT (bar->width, sb_width);
8537 XSETINT (bar->height, height);
8538 }
8539
8540 UNBLOCK_INPUT;
8541 }
8542
8543 /* Set the scroll bar's current state, unless we're currently being
8544 dragged. */
8545 if (NILP (bar->dragging))
8546 {
8547 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8548
8549 if (whole == 0)
8550 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8551 else
8552 {
8553 int start = ((double) position * top_range) / whole;
8554 int end = ((double) (position + portion) * top_range) / whole;
8555 x_scroll_bar_set_handle (bar, start, end, 0);
8556 }
8557 }
8558 }
8559
8560
8561 /* The following three hooks are used when we're doing a thorough
8562 redisplay of the frame. We don't explicitly know which scroll bars
8563 are going to be deleted, because keeping track of when windows go
8564 away is a real pain - "Can you say set-window-configuration, boys
8565 and girls?" Instead, we just assert at the beginning of redisplay
8566 that *all* scroll bars are to be removed, and then save a scroll bar
8567 from the fiery pit when we actually redisplay its window. */
8568
8569 /* Arrange for all scroll bars on FRAME to be removed at the next call
8570 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8571 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8572
8573 static void
8574 XTcondemn_scroll_bars (frame)
8575 FRAME_PTR frame;
8576 {
8577 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8578 while (! NILP (FRAME_SCROLL_BARS (frame)))
8579 {
8580 Lisp_Object bar;
8581 bar = FRAME_SCROLL_BARS (frame);
8582 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8583 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8584 XSCROLL_BAR (bar)->prev = Qnil;
8585 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8586 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8587 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8588 }
8589 }
8590
8591
8592 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8593 Note that WINDOW isn't necessarily condemned at all. */
8594
8595 static void
8596 XTredeem_scroll_bar (window)
8597 struct window *window;
8598 {
8599 struct scroll_bar *bar;
8600
8601 /* We can't redeem this window's scroll bar if it doesn't have one. */
8602 if (NILP (window->vertical_scroll_bar))
8603 abort ();
8604
8605 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8606
8607 /* Unlink it from the condemned list. */
8608 {
8609 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8610
8611 if (NILP (bar->prev))
8612 {
8613 /* If the prev pointer is nil, it must be the first in one of
8614 the lists. */
8615 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8616 /* It's not condemned. Everything's fine. */
8617 return;
8618 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8619 window->vertical_scroll_bar))
8620 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8621 else
8622 /* If its prev pointer is nil, it must be at the front of
8623 one or the other! */
8624 abort ();
8625 }
8626 else
8627 XSCROLL_BAR (bar->prev)->next = bar->next;
8628
8629 if (! NILP (bar->next))
8630 XSCROLL_BAR (bar->next)->prev = bar->prev;
8631
8632 bar->next = FRAME_SCROLL_BARS (f);
8633 bar->prev = Qnil;
8634 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8635 if (! NILP (bar->next))
8636 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8637 }
8638 }
8639
8640 /* Remove all scroll bars on FRAME that haven't been saved since the
8641 last call to `*condemn_scroll_bars_hook'. */
8642
8643 static void
8644 XTjudge_scroll_bars (f)
8645 FRAME_PTR f;
8646 {
8647 Lisp_Object bar, next;
8648
8649 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8650
8651 /* Clear out the condemned list now so we won't try to process any
8652 more events on the hapless scroll bars. */
8653 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8654
8655 for (; ! NILP (bar); bar = next)
8656 {
8657 struct scroll_bar *b = XSCROLL_BAR (bar);
8658
8659 x_scroll_bar_remove (b);
8660
8661 next = b->next;
8662 b->next = b->prev = Qnil;
8663 }
8664
8665 /* Now there should be no references to the condemned scroll bars,
8666 and they should get garbage-collected. */
8667 }
8668
8669
8670 static void
8671 activate_scroll_bars (frame)
8672 FRAME_PTR frame;
8673 {
8674 Lisp_Object bar;
8675 ControlHandle ch;
8676
8677 bar = FRAME_SCROLL_BARS (frame);
8678 while (! NILP (bar))
8679 {
8680 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8681 #ifdef TARGET_API_MAC_CARBON
8682 ActivateControl (ch);
8683 #else
8684 SetControlMaximum (ch,
8685 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
8686 XINT (XSCROLL_BAR (bar)
8687 ->height)) - 1);
8688 #endif
8689 bar = XSCROLL_BAR (bar)->next;
8690 }
8691 }
8692
8693
8694 static void
8695 deactivate_scroll_bars (frame)
8696 FRAME_PTR frame;
8697 {
8698 Lisp_Object bar;
8699 ControlHandle ch;
8700
8701 bar = FRAME_SCROLL_BARS (frame);
8702 while (! NILP (bar))
8703 {
8704 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
8705 #ifdef TARGET_API_MAC_CARBON
8706 DeactivateControl (ch);
8707 #else
8708 SetControlMaximum (ch, XINT (-1));
8709 #endif
8710 bar = XSCROLL_BAR (bar)->next;
8711 }
8712 }
8713
8714 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8715 is set to something other than NO_EVENT, it is enqueued.
8716
8717 This may be called from a signal handler, so we have to ignore GC
8718 mark bits. */
8719
8720 static void
8721 x_scroll_bar_handle_click (bar, part_code, er, bufp)
8722 struct scroll_bar *bar;
8723 int part_code;
8724 EventRecord *er;
8725 struct input_event *bufp;
8726 {
8727 if (! GC_WINDOWP (bar->window))
8728 abort ();
8729
8730 bufp->kind = SCROLL_BAR_CLICK_EVENT;
8731 bufp->frame_or_window = bar->window;
8732 bufp->arg = Qnil;
8733
8734 bar->dragging = Qnil;
8735
8736 switch (part_code)
8737 {
8738 case kControlUpButtonPart:
8739 bufp->part = scroll_bar_up_arrow;
8740 break;
8741 case kControlDownButtonPart:
8742 bufp->part = scroll_bar_down_arrow;
8743 break;
8744 case kControlPageUpPart:
8745 bufp->part = scroll_bar_above_handle;
8746 break;
8747 case kControlPageDownPart:
8748 bufp->part = scroll_bar_below_handle;
8749 break;
8750 #ifdef TARGET_API_MAC_CARBON
8751 default:
8752 #else
8753 case kControlIndicatorPart:
8754 #endif
8755 if (er->what == mouseDown)
8756 bar->dragging = make_number (0);
8757 XSETVECTOR (last_mouse_scroll_bar, bar);
8758 bufp->part = scroll_bar_handle;
8759 break;
8760 }
8761 }
8762
8763
8764 /* Handle some mouse motion while someone is dragging the scroll bar.
8765
8766 This may be called from a signal handler, so we have to ignore GC
8767 mark bits. */
8768
8769 static void
8770 x_scroll_bar_note_movement (bar, y_pos, t)
8771 struct scroll_bar *bar;
8772 int y_pos;
8773 Time t;
8774 {
8775 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8776
8777 last_mouse_movement_time = t;
8778
8779 f->mouse_moved = 1;
8780 XSETVECTOR (last_mouse_scroll_bar, bar);
8781
8782 /* If we're dragging the bar, display it. */
8783 if (! GC_NILP (bar->dragging))
8784 {
8785 /* Where should the handle be now? */
8786 int new_start = y_pos - 24;
8787
8788 if (new_start != XINT (bar->start))
8789 {
8790 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8791
8792 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8793 }
8794 }
8795 }
8796
8797
8798 /* Return information to the user about the current position of the
8799 mouse on the scroll bar. */
8800
8801 static void
8802 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8803 FRAME_PTR *fp;
8804 Lisp_Object *bar_window;
8805 enum scroll_bar_part *part;
8806 Lisp_Object *x, *y;
8807 unsigned long *time;
8808 {
8809 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8810 WindowPtr wp = FrontWindow ();
8811 Point mouse_pos;
8812 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
8813 int win_y, top_range;
8814
8815 #if TARGET_API_MAC_CARBON
8816 SetPort (GetWindowPort (wp));
8817 #else
8818 SetPort (wp);
8819 #endif
8820
8821 GetMouse (&mouse_pos);
8822
8823 win_y = mouse_pos.v - XINT (bar->top);
8824 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8825
8826 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8827
8828 win_y -= 24;
8829
8830 if (! NILP (bar->dragging))
8831 win_y -= XINT (bar->dragging);
8832
8833 if (win_y < 0)
8834 win_y = 0;
8835 if (win_y > top_range)
8836 win_y = top_range;
8837
8838 *fp = f;
8839 *bar_window = bar->window;
8840
8841 if (! NILP (bar->dragging))
8842 *part = scroll_bar_handle;
8843 else if (win_y < XINT (bar->start))
8844 *part = scroll_bar_above_handle;
8845 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8846 *part = scroll_bar_handle;
8847 else
8848 *part = scroll_bar_below_handle;
8849
8850 XSETINT (*x, win_y);
8851 XSETINT (*y, top_range);
8852
8853 f->mouse_moved = 0;
8854 last_mouse_scroll_bar = Qnil;
8855
8856 *time = last_mouse_movement_time;
8857 }
8858 \f
8859 /***********************************************************************
8860 Text Cursor
8861 ***********************************************************************/
8862
8863 /* Notice if the text cursor of window W has been overwritten by a
8864 drawing operation that outputs glyphs starting at START_X and
8865 ending at END_X in the line given by output_cursor.vpos.
8866 Coordinates are area-relative. END_X < 0 means all the rest
8867 of the line after START_X has been written. */
8868
8869 static void
8870 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
8871 struct window *w;
8872 enum glyph_row_area area;
8873 int x0, x1, y0, y1;
8874 {
8875 if (area == TEXT_AREA
8876 && w->phys_cursor_on_p
8877 && y0 <= w->phys_cursor.y
8878 && y1 >= w->phys_cursor.y + w->phys_cursor_height
8879 && x0 <= w->phys_cursor.x
8880 && (x1 < 0 || x1 > w->phys_cursor.x))
8881 w->phys_cursor_on_p = 0;
8882 }
8883
8884
8885 /* Set clipping for output in glyph row ROW. W is the window in which
8886 we operate. GC is the graphics context to set clipping in.
8887 WHOLE_LINE_P non-zero means include the areas used for truncation
8888 mark display and alike in the clipping rectangle.
8889
8890 ROW may be a text row or, e.g., a mode line. Text rows must be
8891 clipped to the interior of the window dedicated to text display,
8892 mode lines must be clipped to the whole window. */
8893
8894 static void
8895 x_clip_to_row (w, row, gc, whole_line_p)
8896 struct window *w;
8897 struct glyph_row *row;
8898 GC gc;
8899 int whole_line_p;
8900 {
8901 struct frame *f = XFRAME (WINDOW_FRAME (w));
8902 Rect clip_rect;
8903 int window_x, window_y, window_width, window_height;
8904
8905 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8906
8907 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8908 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8909 clip_rect.top = max (clip_rect.top, window_y);
8910 clip_rect.right = clip_rect.left + window_width;
8911 clip_rect.bottom = clip_rect.top + row->visible_height;
8912
8913 /* If clipping to the whole line, including trunc marks, extend
8914 the rectangle to the left and increase its width. */
8915 if (whole_line_p)
8916 {
8917 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
8918 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
8919 }
8920
8921 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
8922 }
8923
8924
8925 /* Draw a hollow box cursor on window W in glyph row ROW. */
8926
8927 static void
8928 x_draw_hollow_cursor (w, row)
8929 struct window *w;
8930 struct glyph_row *row;
8931 {
8932 struct frame *f = XFRAME (WINDOW_FRAME (w));
8933 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8934 Display *dpy = FRAME_MAC_DISPLAY (f);
8935 int x, y, wd, h;
8936 XGCValues xgcv;
8937 struct glyph *cursor_glyph;
8938 GC gc;
8939
8940 /* Compute frame-relative coordinates from window-relative
8941 coordinates. */
8942 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8943 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8944 + row->ascent - w->phys_cursor_ascent);
8945 h = row->height - 1;
8946
8947 /* Get the glyph the cursor is on. If we can't tell because
8948 the current matrix is invalid or such, give up. */
8949 cursor_glyph = get_phys_cursor_glyph (w);
8950 if (cursor_glyph == NULL)
8951 return;
8952
8953 /* Compute the width of the rectangle to draw. If on a stretch
8954 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8955 rectangle as wide as the glyph, but use a canonical character
8956 width instead. */
8957 wd = cursor_glyph->pixel_width - 1;
8958 if (cursor_glyph->type == STRETCH_GLYPH
8959 && !x_stretch_cursor_p)
8960 wd = min (CANON_X_UNIT (f), wd);
8961
8962 /* The foreground of cursor_gc is typically the same as the normal
8963 background color, which can cause the cursor box to be invisible. */
8964 xgcv.foreground = f->output_data.mac->cursor_pixel;
8965 if (dpyinfo->scratch_cursor_gc)
8966 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
8967 else
8968 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
8969 GCForeground, &xgcv);
8970 gc = dpyinfo->scratch_cursor_gc;
8971
8972 /* Set clipping, draw the rectangle, and reset clipping again. */
8973 x_clip_to_row (w, row, gc, 0);
8974 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
8975 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
8976 }
8977
8978
8979 /* Draw a bar cursor on window W in glyph row ROW.
8980
8981 Implementation note: One would like to draw a bar cursor with an
8982 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8983 Unfortunately, I didn't find a font yet that has this property set.
8984 --gerd. */
8985
8986 static void
8987 x_draw_bar_cursor (w, row, width)
8988 struct window *w;
8989 struct glyph_row *row;
8990 int width;
8991 {
8992 /* If cursor hpos is out of bounds, don't draw garbage. This can
8993 happen in mini-buffer windows when switching between echo area
8994 glyphs and mini-buffer. */
8995 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8996 {
8997 struct frame *f = XFRAME (w->frame);
8998 struct glyph *cursor_glyph;
8999 GC gc;
9000 int x;
9001 unsigned long mask;
9002 XGCValues xgcv;
9003 Display *dpy;
9004 Window window;
9005
9006 cursor_glyph = get_phys_cursor_glyph (w);
9007 if (cursor_glyph == NULL)
9008 return;
9009
9010 xgcv.background = f->output_data.mac->cursor_pixel;
9011 xgcv.foreground = f->output_data.mac->cursor_pixel;
9012 mask = GCForeground | GCBackground;
9013 dpy = FRAME_MAC_DISPLAY (f);
9014 window = FRAME_MAC_WINDOW (f);
9015 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9016
9017 if (gc)
9018 XChangeGC (dpy, gc, mask, &xgcv);
9019 else
9020 {
9021 gc = XCreateGC (dpy, window, mask, &xgcv);
9022 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9023 }
9024
9025 if (width < 0)
9026 width = f->output_data.mac->cursor_width;
9027
9028 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9029 x_clip_to_row (w, row, gc, 0);
9030 XFillRectangle (dpy, window, gc,
9031 x,
9032 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9033 min (cursor_glyph->pixel_width, width),
9034 row->height);
9035 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
9036 }
9037 }
9038
9039
9040 /* Clear the cursor of window W to background color, and mark the
9041 cursor as not shown. This is used when the text where the cursor
9042 is is about to be rewritten. */
9043
9044 static void
9045 x_clear_cursor (w)
9046 struct window *w;
9047 {
9048 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9049 x_update_window_cursor (w, 0);
9050 }
9051
9052
9053 /* Draw the cursor glyph of window W in glyph row ROW. See the
9054 comment of x_draw_glyphs for the meaning of HL. */
9055
9056 static void
9057 x_draw_phys_cursor_glyph (w, row, hl)
9058 struct window *w;
9059 struct glyph_row *row;
9060 enum draw_glyphs_face hl;
9061 {
9062 /* If cursor hpos is out of bounds, don't draw garbage. This can
9063 happen in mini-buffer windows when switching between echo area
9064 glyphs and mini-buffer. */
9065 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9066 {
9067 int on_p = w->phys_cursor_on_p;
9068 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9069 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9070 hl, 0);
9071 w->phys_cursor_on_p = on_p;
9072
9073 /* When we erase the cursor, and ROW is overlapped by other
9074 rows, make sure that these overlapping parts of other rows
9075 are redrawn. */
9076 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9077 {
9078 if (row > w->current_matrix->rows
9079 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9080 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9081
9082 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9083 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9084 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9085 }
9086 }
9087 }
9088
9089
9090 /* Erase the image of a cursor of window W from the screen. */
9091
9092 static void
9093 x_erase_phys_cursor (w)
9094 struct window *w;
9095 {
9096 struct frame *f = XFRAME (w->frame);
9097 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9098 int hpos = w->phys_cursor.hpos;
9099 int vpos = w->phys_cursor.vpos;
9100 int mouse_face_here_p = 0;
9101 struct glyph_matrix *active_glyphs = w->current_matrix;
9102 struct glyph_row *cursor_row;
9103 struct glyph *cursor_glyph;
9104 enum draw_glyphs_face hl;
9105
9106 /* No cursor displayed or row invalidated => nothing to do on the
9107 screen. */
9108 if (w->phys_cursor_type == NO_CURSOR)
9109 goto mark_cursor_off;
9110
9111 /* VPOS >= active_glyphs->nrows means that window has been resized.
9112 Don't bother to erase the cursor. */
9113 if (vpos >= active_glyphs->nrows)
9114 goto mark_cursor_off;
9115
9116 /* If row containing cursor is marked invalid, there is nothing we
9117 can do. */
9118 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9119 if (!cursor_row->enabled_p)
9120 goto mark_cursor_off;
9121
9122 /* If row is completely invisible, don't attempt to delete a cursor which
9123 isn't there. This may happen if cursor is at top of window, and
9124 we switch to a buffer with a header line in that window. */
9125 if (cursor_row->visible_height <= 0)
9126 goto mark_cursor_off;
9127
9128 /* This can happen when the new row is shorter than the old one.
9129 In this case, either x_draw_glyphs or clear_end_of_line
9130 should have cleared the cursor. Note that we wouldn't be
9131 able to erase the cursor in this case because we don't have a
9132 cursor glyph at hand. */
9133 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9134 goto mark_cursor_off;
9135
9136 /* If the cursor is in the mouse face area, redisplay that when
9137 we clear the cursor. */
9138 if (! NILP (dpyinfo->mouse_face_window)
9139 && w == XWINDOW (dpyinfo->mouse_face_window)
9140 && (vpos > dpyinfo->mouse_face_beg_row
9141 || (vpos == dpyinfo->mouse_face_beg_row
9142 && hpos >= dpyinfo->mouse_face_beg_col))
9143 && (vpos < dpyinfo->mouse_face_end_row
9144 || (vpos == dpyinfo->mouse_face_end_row
9145 && hpos < dpyinfo->mouse_face_end_col))
9146 /* Don't redraw the cursor's spot in mouse face if it is at the
9147 end of a line (on a newline). The cursor appears there, but
9148 mouse highlighting does not. */
9149 && cursor_row->used[TEXT_AREA] > hpos)
9150 mouse_face_here_p = 1;
9151
9152 /* Maybe clear the display under the cursor. */
9153 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9154 {
9155 int x;
9156 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9157
9158 cursor_glyph = get_phys_cursor_glyph (w);
9159 if (cursor_glyph == NULL)
9160 goto mark_cursor_off;
9161
9162 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9163
9164 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
9165 x,
9166 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9167 cursor_row->y)),
9168 cursor_glyph->pixel_width,
9169 cursor_row->visible_height,
9170 0);
9171 }
9172
9173 /* Erase the cursor by redrawing the character underneath it. */
9174 if (mouse_face_here_p)
9175 hl = DRAW_MOUSE_FACE;
9176 else
9177 hl = DRAW_NORMAL_TEXT;
9178 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9179
9180 mark_cursor_off:
9181 w->phys_cursor_on_p = 0;
9182 w->phys_cursor_type = NO_CURSOR;
9183 }
9184
9185
9186 /* Non-zero if physical cursor of window W is within mouse face. */
9187
9188 static int
9189 cursor_in_mouse_face_p (w)
9190 struct window *w;
9191 {
9192 struct mac_display_info *dpyinfo
9193 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
9194 int in_mouse_face = 0;
9195
9196 if (WINDOWP (dpyinfo->mouse_face_window)
9197 && XWINDOW (dpyinfo->mouse_face_window) == w)
9198 {
9199 int hpos = w->phys_cursor.hpos;
9200 int vpos = w->phys_cursor.vpos;
9201
9202 if (vpos >= dpyinfo->mouse_face_beg_row
9203 && vpos <= dpyinfo->mouse_face_end_row
9204 && (vpos > dpyinfo->mouse_face_beg_row
9205 || hpos >= dpyinfo->mouse_face_beg_col)
9206 && (vpos < dpyinfo->mouse_face_end_row
9207 || hpos < dpyinfo->mouse_face_end_col
9208 || dpyinfo->mouse_face_past_end))
9209 in_mouse_face = 1;
9210 }
9211
9212 return in_mouse_face;
9213 }
9214
9215
9216 /* Display or clear cursor of window W. If ON is zero, clear the
9217 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9218 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9219
9220 void
9221 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9222 struct window *w;
9223 int on, hpos, vpos, x, y;
9224 {
9225 struct frame *f = XFRAME (w->frame);
9226 int new_cursor_type;
9227 int new_cursor_width;
9228 struct glyph_matrix *current_glyphs;
9229 struct glyph_row *glyph_row;
9230 struct glyph *glyph;
9231 int cursor_non_selected;
9232 int active_cursor = 1;
9233
9234 /* This is pointless on invisible frames, and dangerous on garbaged
9235 windows and frames; in the latter case, the frame or window may
9236 be in the midst of changing its size, and x and y may be off the
9237 window. */
9238 if (! FRAME_VISIBLE_P (f)
9239 || FRAME_GARBAGED_P (f)
9240 || vpos >= w->current_matrix->nrows
9241 || hpos >= w->current_matrix->matrix_w)
9242 return;
9243
9244 /* If cursor is off and we want it off, return quickly. */
9245 if (!on && !w->phys_cursor_on_p)
9246 return;
9247
9248 current_glyphs = w->current_matrix;
9249 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9250 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9251
9252 /* If cursor row is not enabled, we don't really know where to
9253 display the cursor. */
9254 if (!glyph_row->enabled_p)
9255 {
9256 w->phys_cursor_on_p = 0;
9257 return;
9258 }
9259
9260 xassert (interrupt_input_blocked);
9261
9262 /* Set new_cursor_type to the cursor we want to be displayed. In a
9263 mini-buffer window, we want the cursor only to appear if we are
9264 reading input from this window. For the selected window, we want
9265 the cursor type given by the frame parameter. If explicitly
9266 marked off, draw no cursor. In all other cases, we want a hollow
9267 box cursor. */
9268 cursor_non_selected
9269 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
9270 w->buffer));
9271 new_cursor_width = -1;
9272 if (cursor_in_echo_area
9273 && FRAME_HAS_MINIBUF_P (f)
9274 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
9275 {
9276 if (w == XWINDOW (echo_area_window))
9277 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9278 else
9279 {
9280 if (cursor_non_selected)
9281 new_cursor_type = HOLLOW_BOX_CURSOR;
9282 else
9283 new_cursor_type = NO_CURSOR;
9284 active_cursor = 0;
9285 }
9286 }
9287 else
9288 {
9289 if (f != FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame
9290 || w != XWINDOW (f->selected_window))
9291 {
9292 active_cursor = 0;
9293
9294 if (MINI_WINDOW_P (w)
9295 || !cursor_non_selected
9296 || NILP (XBUFFER (w->buffer)->cursor_type))
9297 new_cursor_type = NO_CURSOR;
9298 else
9299 new_cursor_type = HOLLOW_BOX_CURSOR;
9300 }
9301 else
9302 {
9303 struct buffer *b = XBUFFER (w->buffer);
9304
9305 if (EQ (b->cursor_type, Qt))
9306 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9307 else
9308 new_cursor_type = x_specified_cursor_type (b->cursor_type,
9309 &new_cursor_width);
9310 if (w->cursor_off_p)
9311 {
9312 if (new_cursor_type == FILLED_BOX_CURSOR)
9313 new_cursor_type = HOLLOW_BOX_CURSOR;
9314 else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
9315 new_cursor_width = 1;
9316 else
9317 new_cursor_type = NO_CURSOR;
9318 }
9319 }
9320 }
9321
9322 /* If cursor is currently being shown and we don't want it to be or
9323 it is in the wrong place, or the cursor type is not what we want,
9324 erase it. */
9325 if (w->phys_cursor_on_p
9326 && (!on
9327 || w->phys_cursor.x != x
9328 || w->phys_cursor.y != y
9329 || new_cursor_type != w->phys_cursor_type
9330 || (new_cursor_type == BAR_CURSOR
9331 && new_cursor_width != w->phys_cursor_width)))
9332 x_erase_phys_cursor (w);
9333
9334 /* If the cursor is now invisible and we want it to be visible,
9335 display it. */
9336 if (on && !w->phys_cursor_on_p)
9337 {
9338 w->phys_cursor_ascent = glyph_row->ascent;
9339 w->phys_cursor_height = glyph_row->height;
9340
9341 /* Set phys_cursor_.* before x_draw_.* is called because some
9342 of them may need the information. */
9343 w->phys_cursor.x = x;
9344 w->phys_cursor.y = glyph_row->y;
9345 w->phys_cursor.hpos = hpos;
9346 w->phys_cursor.vpos = vpos;
9347 w->phys_cursor_type = new_cursor_type;
9348 w->phys_cursor_width = new_cursor_width;
9349 w->phys_cursor_on_p = 1;
9350
9351 switch (new_cursor_type)
9352 {
9353 case HOLLOW_BOX_CURSOR:
9354 x_draw_hollow_cursor (w, glyph_row);
9355 break;
9356
9357 case FILLED_BOX_CURSOR:
9358 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9359 break;
9360
9361 case BAR_CURSOR:
9362 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9363 break;
9364
9365 case NO_CURSOR:
9366 break;
9367
9368 default:
9369 abort ();
9370 }
9371 }
9372 }
9373
9374
9375 /* Display the cursor on window W, or clear it. X and Y are window
9376 relative pixel coordinates. HPOS and VPOS are glyph matrix
9377 positions. If W is not the selected window, display a hollow
9378 cursor. ON non-zero means display the cursor at X, Y which
9379 correspond to HPOS, VPOS, otherwise it is cleared. */
9380
9381 void
9382 x_display_cursor (w, on, hpos, vpos, x, y)
9383 struct window *w;
9384 int on, hpos, vpos, x, y;
9385 {
9386 BLOCK_INPUT;
9387 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9388 UNBLOCK_INPUT;
9389 }
9390
9391
9392 /* Display the cursor on window W, or clear it, according to ON_P.
9393 Don't change the cursor's position. */
9394
9395 void
9396 x_update_cursor (f, on_p)
9397 struct frame *f;
9398 int on_p;
9399 {
9400 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9401 }
9402
9403
9404 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9405 in the window tree rooted at W. */
9406
9407 static void
9408 x_update_cursor_in_window_tree (w, on_p)
9409 struct window *w;
9410 int on_p;
9411 {
9412 while (w)
9413 {
9414 if (!NILP (w->hchild))
9415 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9416 else if (!NILP (w->vchild))
9417 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9418 else
9419 x_update_window_cursor (w, on_p);
9420
9421 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9422 }
9423 }
9424
9425
9426 /* Switch the display of W's cursor on or off, according to the value
9427 of ON. */
9428
9429 static void
9430 x_update_window_cursor (w, on)
9431 struct window *w;
9432 int on;
9433 {
9434 /* Don't update cursor in windows whose frame is in the process
9435 of being deleted. */
9436 if (w->current_matrix)
9437 {
9438 BLOCK_INPUT;
9439 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9440 w->phys_cursor.vpos, w->phys_cursor.x,
9441 w->phys_cursor.y);
9442 UNBLOCK_INPUT;
9443 }
9444 }
9445
9446
9447
9448 \f
9449 /* Icons. */
9450
9451 #if 0 /* MAC_TODO: no icon support yet. */
9452 int
9453 x_bitmap_icon (f, icon)
9454 struct frame *f;
9455 Lisp_Object icon;
9456 {
9457 HANDLE hicon;
9458
9459 if (FRAME_W32_WINDOW (f) == 0)
9460 return 1;
9461
9462 if (NILP (icon))
9463 hicon = LoadIcon (hinst, EMACS_CLASS);
9464 else if (STRINGP (icon))
9465 hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
9466 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9467 else if (SYMBOLP (icon))
9468 {
9469 LPCTSTR name;
9470
9471 if (EQ (icon, intern ("application")))
9472 name = (LPCTSTR) IDI_APPLICATION;
9473 else if (EQ (icon, intern ("hand")))
9474 name = (LPCTSTR) IDI_HAND;
9475 else if (EQ (icon, intern ("question")))
9476 name = (LPCTSTR) IDI_QUESTION;
9477 else if (EQ (icon, intern ("exclamation")))
9478 name = (LPCTSTR) IDI_EXCLAMATION;
9479 else if (EQ (icon, intern ("asterisk")))
9480 name = (LPCTSTR) IDI_ASTERISK;
9481 else if (EQ (icon, intern ("winlogo")))
9482 name = (LPCTSTR) IDI_WINLOGO;
9483 else
9484 return 1;
9485
9486 hicon = LoadIcon (NULL, name);
9487 }
9488 else
9489 return 1;
9490
9491 if (hicon == NULL)
9492 return 1;
9493
9494 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9495 (LPARAM) hicon);
9496
9497 return 0;
9498 }
9499 #endif /* MAC_TODO */
9500 \f
9501 /************************************************************************
9502 Handling X errors
9503 ************************************************************************/
9504
9505 /* Display Error Handling functions not used on W32. Listing them here
9506 helps diff stay in step when comparing w32term.c with xterm.c.
9507
9508 x_error_catcher (display, error)
9509 x_catch_errors (dpy)
9510 x_catch_errors_unwind (old_val)
9511 x_check_errors (dpy, format)
9512 x_had_errors_p (dpy)
9513 x_clear_errors (dpy)
9514 x_uncatch_errors (dpy, count)
9515 x_trace_wire ()
9516 x_connection_signal (signalnum)
9517 x_connection_closed (dpy, error_message)
9518 x_error_quitter (display, error)
9519 x_error_handler (display, error)
9520 x_io_error_quitter (display)
9521
9522 */
9523
9524 \f
9525 /* Changing the font of the frame. */
9526
9527 /* Give frame F the font named FONTNAME as its default font, and
9528 return the full name of that font. FONTNAME may be a wildcard
9529 pattern; in that case, we choose some font that fits the pattern.
9530 The return value shows which font we chose. */
9531
9532 Lisp_Object
9533 x_new_font (f, fontname)
9534 struct frame *f;
9535 register char *fontname;
9536 {
9537 struct font_info *fontp
9538 = FS_LOAD_FONT (f, 0, fontname, -1);
9539
9540 if (!fontp)
9541 return Qnil;
9542
9543 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9544 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9545 FRAME_FONTSET (f) = -1;
9546
9547 /* Compute the scroll bar width in character columns. */
9548 if (f->scroll_bar_pixel_width > 0)
9549 {
9550 int wid = FONT_WIDTH (FRAME_FONT (f));
9551 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9552 }
9553 else
9554 {
9555 int wid = FONT_WIDTH (FRAME_FONT (f));
9556 f->scroll_bar_cols = (14 + wid - 1) / wid;
9557 }
9558
9559 /* Now make the frame display the given font. */
9560 if (FRAME_MAC_WINDOW (f) != 0)
9561 {
9562 frame_update_line_height (f);
9563 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9564 x_set_window_size (f, 0, f->width, f->height);
9565 }
9566 else
9567 /* If we are setting a new frame's font for the first time,
9568 there are no faces yet, so this font's height is the line height. */
9569 f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
9570
9571 return build_string (fontp->full_name);
9572 }
9573 \f
9574 /* Give frame F the fontset named FONTSETNAME as its default font, and
9575 return the full name of that fontset. FONTSETNAME may be a wildcard
9576 pattern; in that case, we choose some fontset that fits the pattern.
9577 The return value shows which fontset we chose. */
9578
9579 Lisp_Object
9580 x_new_fontset (f, fontsetname)
9581 struct frame *f;
9582 char *fontsetname;
9583 {
9584 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9585 Lisp_Object result;
9586
9587 if (fontset < 0)
9588 return Qnil;
9589
9590 if (FRAME_FONTSET (f) == fontset)
9591 /* This fontset is already set in frame F. There's nothing more
9592 to do. */
9593 return fontset_name (fontset);
9594
9595 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
9596
9597 if (!STRINGP (result))
9598 /* Can't load ASCII font. */
9599 return Qnil;
9600
9601 /* Since x_new_font doesn't update any fontset information, do it now. */
9602 FRAME_FONTSET(f) = fontset;
9603
9604 return build_string (fontsetname);
9605 }
9606
9607 /* Compute actual fringe widths */
9608
9609 void
9610 x_compute_fringe_widths (f, redraw)
9611 struct frame *f;
9612 int redraw;
9613 {
9614 int o_left = f->output_data.mac->left_fringe_width;
9615 int o_right = f->output_data.mac->right_fringe_width;
9616 int o_cols = f->output_data.mac->fringe_cols;
9617
9618 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9619 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9620 int left_fringe_width, right_fringe_width;
9621
9622 if (!NILP (left_fringe))
9623 left_fringe = Fcdr (left_fringe);
9624 if (!NILP (right_fringe))
9625 right_fringe = Fcdr (right_fringe);
9626
9627 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9628 XINT (left_fringe));
9629 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9630 XINT (right_fringe));
9631
9632 if (left_fringe_width || right_fringe_width)
9633 {
9634 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9635 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9636 int conf_wid = left_wid + right_wid;
9637 int font_wid = FONT_WIDTH (f->output_data.mac->font);
9638 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9639 int real_wid = cols * font_wid;
9640 if (left_wid && right_wid)
9641 {
9642 if (left_fringe_width < 0)
9643 {
9644 /* Left fringe width is fixed, adjust right fringe if necessary */
9645 f->output_data.mac->left_fringe_width = left_wid;
9646 f->output_data.mac->right_fringe_width = real_wid - left_wid;
9647 }
9648 else if (right_fringe_width < 0)
9649 {
9650 /* Right fringe width is fixed, adjust left fringe if necessary */
9651 f->output_data.mac->left_fringe_width = real_wid - right_wid;
9652 f->output_data.mac->right_fringe_width = right_wid;
9653 }
9654 else
9655 {
9656 /* Adjust both fringes with an equal amount.
9657 Note that we are doing integer arithmetic here, so don't
9658 lose a pixel if the total width is an odd number. */
9659 int fill = real_wid - conf_wid;
9660 f->output_data.mac->left_fringe_width = left_wid + fill/2;
9661 f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
9662 }
9663 }
9664 else if (left_fringe_width)
9665 {
9666 f->output_data.mac->left_fringe_width = real_wid;
9667 f->output_data.mac->right_fringe_width = 0;
9668 }
9669 else
9670 {
9671 f->output_data.mac->left_fringe_width = 0;
9672 f->output_data.mac->right_fringe_width = real_wid;
9673 }
9674 f->output_data.mac->fringe_cols = cols;
9675 f->output_data.mac->fringes_extra = real_wid;
9676 }
9677 else
9678 {
9679 f->output_data.mac->left_fringe_width = 0;
9680 f->output_data.mac->right_fringe_width = 0;
9681 f->output_data.mac->fringe_cols = 0;
9682 f->output_data.mac->fringes_extra = 0;
9683 }
9684
9685 if (redraw && FRAME_VISIBLE_P (f))
9686 if (o_left != f->output_data.mac->left_fringe_width ||
9687 o_right != f->output_data.mac->right_fringe_width ||
9688 o_cols != f->output_data.mac->fringe_cols)
9689 redraw_frame (f);
9690 }
9691 \f
9692 /***********************************************************************
9693 TODO: W32 Input Methods
9694 ***********************************************************************/
9695 /* Listing missing functions from xterm.c helps diff stay in step.
9696
9697 xim_destroy_callback (xim, client_data, call_data)
9698 xim_open_dpy (dpyinfo, resource_name)
9699 struct xim_inst_t
9700 xim_instantiate_callback (display, client_data, call_data)
9701 xim_initialize (dpyinfo, resource_name)
9702 xim_close_dpy (dpyinfo)
9703
9704 */
9705
9706 \f
9707 /* Calculate the absolute position in frame F
9708 from its current recorded position values and gravity. */
9709
9710 void
9711 x_calc_absolute_position (f)
9712 struct frame *f;
9713 {
9714 Point pt;
9715 int flags = f->output_data.mac->size_hint_flags;
9716
9717 pt.h = pt.v = 0;
9718
9719 /* Find the position of the outside upper-left corner of
9720 the inner window, with respect to the outer window. */
9721 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
9722 {
9723 GrafPtr savePort;
9724 GetPort (&savePort);
9725
9726 #if TARGET_API_MAC_CARBON
9727 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
9728 #else
9729 SetPort (FRAME_MAC_WINDOW (f));
9730 #endif
9731
9732 #if TARGET_API_MAC_CARBON
9733 {
9734 Rect r;
9735
9736 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
9737 SetPt(&pt, r.left, r.top);
9738 }
9739 #else /* not TARGET_API_MAC_CARBON */
9740 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
9741 #endif /* not TARGET_API_MAC_CARBON */
9742 LocalToGlobal (&pt);
9743 SetPort (savePort);
9744 }
9745
9746 /* Treat negative positions as relative to the leftmost bottommost
9747 position that fits on the screen. */
9748 if (flags & XNegative)
9749 f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
9750 - 2 * f->output_data.mac->border_width - pt.h
9751 - PIXEL_WIDTH (f)
9752 + f->output_data.mac->left_pos);
9753 /* NTEMACS_TODO: Subtract menubar height? */
9754 if (flags & YNegative)
9755 f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
9756 - 2 * f->output_data.mac->border_width - pt.v
9757 - PIXEL_HEIGHT (f)
9758 + f->output_data.mac->top_pos);
9759 /* The left_pos and top_pos
9760 are now relative to the top and left screen edges,
9761 so the flags should correspond. */
9762 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9763 }
9764
9765 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9766 to really change the position, and 0 when calling from
9767 x_make_frame_visible (in that case, XOFF and YOFF are the current
9768 position values). It is -1 when calling from x_set_frame_parameters,
9769 which means, do adjust for borders but don't change the gravity. */
9770
9771 void
9772 x_set_offset (f, xoff, yoff, change_gravity)
9773 struct frame *f;
9774 register int xoff, yoff;
9775 int change_gravity;
9776 {
9777 int modified_top, modified_left;
9778
9779 if (change_gravity > 0)
9780 {
9781 f->output_data.mac->top_pos = yoff;
9782 f->output_data.mac->left_pos = xoff;
9783 f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
9784 if (xoff < 0)
9785 f->output_data.mac->size_hint_flags |= XNegative;
9786 if (yoff < 0)
9787 f->output_data.mac->size_hint_flags |= YNegative;
9788 f->output_data.mac->win_gravity = NorthWestGravity;
9789 }
9790 x_calc_absolute_position (f);
9791
9792 BLOCK_INPUT;
9793 x_wm_set_size_hint (f, (long) 0, 0);
9794
9795 modified_left = f->output_data.mac->left_pos;
9796 modified_top = f->output_data.mac->top_pos;
9797
9798 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
9799 modified_top + 42, false);
9800
9801 UNBLOCK_INPUT;
9802 }
9803
9804 /* Call this to change the size of frame F's x-window.
9805 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9806 for this size change and subsequent size changes.
9807 Otherwise we leave the window gravity unchanged. */
9808
9809 void
9810 x_set_window_size (f, change_gravity, cols, rows)
9811 struct frame *f;
9812 int change_gravity;
9813 int cols, rows;
9814 {
9815 int pixelwidth, pixelheight;
9816
9817 BLOCK_INPUT;
9818
9819 check_frame_size (f, &rows, &cols);
9820 f->output_data.mac->vertical_scroll_bar_extra
9821 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9822 ? 0
9823 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
9824
9825 x_compute_fringe_widths (f, 0);
9826
9827 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9828 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9829
9830 f->output_data.mac->win_gravity = NorthWestGravity;
9831 x_wm_set_size_hint (f, (long) 0, 0);
9832
9833 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
9834
9835 /* Now, strictly speaking, we can't be sure that this is accurate,
9836 but the window manager will get around to dealing with the size
9837 change request eventually, and we'll hear how it went when the
9838 ConfigureNotify event gets here.
9839
9840 We could just not bother storing any of this information here,
9841 and let the ConfigureNotify event set everything up, but that
9842 might be kind of confusing to the Lisp code, since size changes
9843 wouldn't be reported in the frame parameters until some random
9844 point in the future when the ConfigureNotify event arrives.
9845
9846 We pass 1 for DELAY since we can't run Lisp code inside of
9847 a BLOCK_INPUT. */
9848 change_frame_size (f, rows, cols, 0, 1, 0);
9849 PIXEL_WIDTH (f) = pixelwidth;
9850 PIXEL_HEIGHT (f) = pixelheight;
9851
9852 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9853 receive in the ConfigureNotify event; if we get what we asked
9854 for, then the event won't cause the screen to become garbaged, so
9855 we have to make sure to do it here. */
9856 SET_FRAME_GARBAGED (f);
9857
9858 XFlush (FRAME_X_DISPLAY (f));
9859
9860 /* If cursor was outside the new size, mark it as off. */
9861 mark_window_cursors_off (XWINDOW (f->root_window));
9862
9863 /* Clear out any recollection of where the mouse highlighting was,
9864 since it might be in a place that's outside the new frame size.
9865 Actually checking whether it is outside is a pain in the neck,
9866 so don't try--just let the highlighting be done afresh with new size. */
9867 cancel_mouse_face (f);
9868
9869 UNBLOCK_INPUT;
9870 }
9871 \f
9872 /* Mouse warping. */
9873
9874 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9875
9876 void
9877 x_set_mouse_position (f, x, y)
9878 struct frame *f;
9879 int x, y;
9880 {
9881 int pix_x, pix_y;
9882
9883 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
9884 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
9885
9886 if (pix_x < 0) pix_x = 0;
9887 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9888
9889 if (pix_y < 0) pix_y = 0;
9890 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9891
9892 x_set_mouse_pixel_position (f, pix_x, pix_y);
9893 }
9894
9895 void
9896 x_set_mouse_pixel_position (f, pix_x, pix_y)
9897 struct frame *f;
9898 int pix_x, pix_y;
9899 {
9900 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
9901 BLOCK_INPUT;
9902
9903 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
9904 0, 0, 0, 0, pix_x, pix_y);
9905 UNBLOCK_INPUT;
9906 #endif
9907 }
9908
9909 \f
9910 /* focus shifting, raising and lowering. */
9911
9912 void
9913 x_focus_on_frame (f)
9914 struct frame *f;
9915 {
9916 #if 0 /* This proves to be unpleasant. */
9917 x_raise_frame (f);
9918 #endif
9919 #if 0
9920 /* I don't think that the ICCCM allows programs to do things like this
9921 without the interaction of the window manager. Whatever you end up
9922 doing with this code, do it to x_unfocus_frame too. */
9923 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9924 RevertToPointerRoot, CurrentTime);
9925 #endif /* ! 0 */
9926 }
9927
9928 void
9929 x_unfocus_frame (f)
9930 struct frame *f;
9931 {
9932 }
9933
9934 /* Raise frame F. */
9935 void
9936 x_raise_frame (f)
9937 struct frame *f;
9938 {
9939 if (f->async_visible)
9940 SelectWindow (FRAME_MAC_WINDOW (f));
9941 }
9942
9943 /* Lower frame F. */
9944 void
9945 x_lower_frame (f)
9946 struct frame *f;
9947 {
9948 if (f->async_visible)
9949 SendBehind (FRAME_MAC_WINDOW (f), nil);
9950 }
9951
9952 static void
9953 XTframe_raise_lower (f, raise_flag)
9954 FRAME_PTR f;
9955 int raise_flag;
9956 {
9957 if (raise_flag)
9958 x_raise_frame (f);
9959 else
9960 x_lower_frame (f);
9961 }
9962 \f
9963 /* Change of visibility. */
9964
9965 /* This tries to wait until the frame is really visible.
9966 However, if the window manager asks the user where to position
9967 the frame, this will return before the user finishes doing that.
9968 The frame will not actually be visible at that time,
9969 but it will become visible later when the window manager
9970 finishes with it. */
9971
9972 void
9973 x_make_frame_visible (f)
9974 struct frame *f;
9975 {
9976 Lisp_Object type;
9977 int original_top, original_left;
9978
9979 BLOCK_INPUT;
9980
9981 if (! FRAME_VISIBLE_P (f))
9982 {
9983 /* We test FRAME_GARBAGED_P here to make sure we don't
9984 call x_set_offset a second time
9985 if we get to x_make_frame_visible a second time
9986 before the window gets really visible. */
9987 if (! FRAME_ICONIFIED_P (f)
9988 && ! f->output_data.mac->asked_for_visible)
9989 x_set_offset (f, f->output_data.mac->left_pos,
9990 f->output_data.mac->top_pos, 0);
9991
9992 f->output_data.mac->asked_for_visible = 1;
9993
9994 ShowWindow (FRAME_MAC_WINDOW (f));
9995 }
9996
9997 XFlush (FRAME_MAC_DISPLAY (f));
9998
9999 #if 0 /* MAC_TODO */
10000 /* Synchronize to ensure Emacs knows the frame is visible
10001 before we do anything else. We do this loop with input not blocked
10002 so that incoming events are handled. */
10003 {
10004 Lisp_Object frame;
10005 int count;
10006
10007 /* This must come after we set COUNT. */
10008 UNBLOCK_INPUT;
10009
10010 XSETFRAME (frame, f);
10011
10012 /* Wait until the frame is visible. Process X events until a
10013 MapNotify event has been seen, or until we think we won't get a
10014 MapNotify at all.. */
10015 for (count = input_signal_count + 10;
10016 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10017 {
10018 /* Force processing of queued events. */
10019 x_sync (f);
10020
10021 /* Machines that do polling rather than SIGIO have been
10022 observed to go into a busy-wait here. So we'll fake an
10023 alarm signal to let the handler know that there's something
10024 to be read. We used to raise a real alarm, but it seems
10025 that the handler isn't always enabled here. This is
10026 probably a bug. */
10027 if (input_polling_used ())
10028 {
10029 /* It could be confusing if a real alarm arrives while
10030 processing the fake one. Turn it off and let the
10031 handler reset it. */
10032 extern void poll_for_input_1 P_ ((void));
10033 int old_poll_suppress_count = poll_suppress_count;
10034 poll_suppress_count = 1;
10035 poll_for_input_1 ();
10036 poll_suppress_count = old_poll_suppress_count;
10037 }
10038
10039 /* See if a MapNotify event has been processed. */
10040 FRAME_SAMPLE_VISIBILITY (f);
10041 }
10042 }
10043 #endif /* MAC_TODO */
10044 }
10045
10046 /* Change from mapped state to withdrawn state. */
10047
10048 /* Make the frame visible (mapped and not iconified). */
10049
10050 void
10051 x_make_frame_invisible (f)
10052 struct frame *f;
10053 {
10054 /* Don't keep the highlight on an invisible frame. */
10055 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
10056 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
10057
10058 BLOCK_INPUT;
10059
10060 HideWindow (FRAME_MAC_WINDOW (f));
10061
10062 /* We can't distinguish this from iconification
10063 just by the event that we get from the server.
10064 So we can't win using the usual strategy of letting
10065 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10066 and synchronize with the server to make sure we agree. */
10067 f->visible = 0;
10068 FRAME_ICONIFIED_P (f) = 0;
10069 f->async_visible = 0;
10070 f->async_iconified = 0;
10071
10072 UNBLOCK_INPUT;
10073 }
10074
10075 /* Change window state from mapped to iconified. */
10076
10077 void
10078 x_iconify_frame (f)
10079 struct frame *f;
10080 {
10081 #if 0 /* MAC_TODO: really no iconify on Mac */
10082 int result;
10083 Lisp_Object type;
10084
10085 /* Don't keep the highlight on an invisible frame. */
10086 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
10087 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
10088
10089 if (f->async_iconified)
10090 return;
10091
10092 BLOCK_INPUT;
10093
10094 FRAME_SAMPLE_VISIBILITY (f);
10095
10096 type = x_icon_type (f);
10097 if (!NILP (type))
10098 x_bitmap_icon (f, type);
10099
10100 #ifdef USE_X_TOOLKIT
10101
10102 if (! FRAME_VISIBLE_P (f))
10103 {
10104 if (! EQ (Vx_no_window_manager, Qt))
10105 x_wm_set_window_state (f, IconicState);
10106 /* This was XtPopup, but that did nothing for an iconified frame. */
10107 XtMapWidget (f->output_data.x->widget);
10108 /* The server won't give us any event to indicate
10109 that an invisible frame was changed to an icon,
10110 so we have to record it here. */
10111 f->iconified = 1;
10112 f->visible = 1;
10113 f->async_iconified = 1;
10114 f->async_visible = 0;
10115 UNBLOCK_INPUT;
10116 return;
10117 }
10118
10119 result = XIconifyWindow (FRAME_X_DISPLAY (f),
10120 XtWindow (f->output_data.x->widget),
10121 DefaultScreen (FRAME_X_DISPLAY (f)));
10122 UNBLOCK_INPUT;
10123
10124 if (!result)
10125 error ("Can't notify window manager of iconification");
10126
10127 f->async_iconified = 1;
10128 f->async_visible = 0;
10129
10130
10131 BLOCK_INPUT;
10132 XFlush (FRAME_X_DISPLAY (f));
10133 UNBLOCK_INPUT;
10134 #else /* not USE_X_TOOLKIT */
10135
10136 /* Make sure the X server knows where the window should be positioned,
10137 in case the user deiconifies with the window manager. */
10138 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
10139 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
10140
10141 /* Since we don't know which revision of X we're running, we'll use both
10142 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
10143
10144 /* X11R4: send a ClientMessage to the window manager using the
10145 WM_CHANGE_STATE type. */
10146 {
10147 XEvent message;
10148
10149 message.xclient.window = FRAME_X_WINDOW (f);
10150 message.xclient.type = ClientMessage;
10151 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
10152 message.xclient.format = 32;
10153 message.xclient.data.l[0] = IconicState;
10154
10155 if (! XSendEvent (FRAME_X_DISPLAY (f),
10156 DefaultRootWindow (FRAME_X_DISPLAY (f)),
10157 False,
10158 SubstructureRedirectMask | SubstructureNotifyMask,
10159 &message))
10160 {
10161 UNBLOCK_INPUT_RESIGNAL;
10162 error ("Can't notify window manager of iconification");
10163 }
10164 }
10165
10166 /* X11R3: set the initial_state field of the window manager hints to
10167 IconicState. */
10168 x_wm_set_window_state (f, IconicState);
10169
10170 if (!FRAME_VISIBLE_P (f))
10171 {
10172 /* If the frame was withdrawn, before, we must map it. */
10173 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
10174 }
10175
10176 f->async_iconified = 1;
10177 f->async_visible = 0;
10178
10179 XFlush (FRAME_X_DISPLAY (f));
10180 UNBLOCK_INPUT;
10181 #endif /* not USE_X_TOOLKIT */
10182 #endif /* MAC_TODO */
10183 }
10184
10185 \f
10186 /* Destroy the X window of frame F. */
10187
10188 void
10189 x_destroy_window (f)
10190 struct frame *f;
10191 {
10192 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10193
10194 BLOCK_INPUT;
10195
10196 DisposeWindow (FRAME_MAC_WINDOW (f));
10197
10198 free_frame_menubar (f);
10199 free_frame_faces (f);
10200
10201 xfree (f->output_data.mac);
10202 f->output_data.mac = 0;
10203 if (f == dpyinfo->x_focus_frame)
10204 dpyinfo->x_focus_frame = 0;
10205 if (f == dpyinfo->x_focus_event_frame)
10206 dpyinfo->x_focus_event_frame = 0;
10207 if (f == dpyinfo->x_highlight_frame)
10208 dpyinfo->x_highlight_frame = 0;
10209
10210 dpyinfo->reference_count--;
10211
10212 if (f == dpyinfo->mouse_face_mouse_frame)
10213 {
10214 dpyinfo->mouse_face_beg_row
10215 = dpyinfo->mouse_face_beg_col = -1;
10216 dpyinfo->mouse_face_end_row
10217 = dpyinfo->mouse_face_end_col = -1;
10218 dpyinfo->mouse_face_window = Qnil;
10219 dpyinfo->mouse_face_deferred_gc = 0;
10220 dpyinfo->mouse_face_mouse_frame = 0;
10221 }
10222
10223 UNBLOCK_INPUT;
10224 }
10225 \f
10226 /* Setting window manager hints. */
10227
10228 /* Set the normal size hints for the window manager, for frame F.
10229 FLAGS is the flags word to use--or 0 meaning preserve the flags
10230 that the window now has.
10231 If USER_POSITION is nonzero, we set the USPosition
10232 flag (this is useful when FLAGS is 0). */
10233 void
10234 x_wm_set_size_hint (f, flags, user_position)
10235 struct frame *f;
10236 long flags;
10237 int user_position;
10238 {
10239 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
10240 XSizeHints size_hints;
10241
10242 #ifdef USE_X_TOOLKIT
10243 Arg al[2];
10244 int ac = 0;
10245 Dimension widget_width, widget_height;
10246 Window window = XtWindow (f->output_data.x->widget);
10247 #else /* not USE_X_TOOLKIT */
10248 Window window = FRAME_X_WINDOW (f);
10249 #endif /* not USE_X_TOOLKIT */
10250
10251 /* Setting PMaxSize caused various problems. */
10252 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
10253
10254 size_hints.x = f->output_data.x->left_pos;
10255 size_hints.y = f->output_data.x->top_pos;
10256
10257 #ifdef USE_X_TOOLKIT
10258 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
10259 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
10260 XtGetValues (f->output_data.x->widget, al, ac);
10261 size_hints.height = widget_height;
10262 size_hints.width = widget_width;
10263 #else /* not USE_X_TOOLKIT */
10264 size_hints.height = PIXEL_HEIGHT (f);
10265 size_hints.width = PIXEL_WIDTH (f);
10266 #endif /* not USE_X_TOOLKIT */
10267
10268 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
10269 size_hints.height_inc = f->output_data.x->line_height;
10270 size_hints.max_width
10271 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
10272 size_hints.max_height
10273 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
10274
10275 /* Calculate the base and minimum sizes.
10276
10277 (When we use the X toolkit, we don't do it here.
10278 Instead we copy the values that the widgets are using, below.) */
10279 #ifndef USE_X_TOOLKIT
10280 {
10281 int base_width, base_height;
10282 int min_rows = 0, min_cols = 0;
10283
10284 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
10285 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
10286
10287 check_frame_size (f, &min_rows, &min_cols);
10288
10289 /* The window manager uses the base width hints to calculate the
10290 current number of rows and columns in the frame while
10291 resizing; min_width and min_height aren't useful for this
10292 purpose, since they might not give the dimensions for a
10293 zero-row, zero-column frame.
10294
10295 We use the base_width and base_height members if we have
10296 them; otherwise, we set the min_width and min_height members
10297 to the size for a zero x zero frame. */
10298
10299 #ifdef HAVE_X11R4
10300 size_hints.flags |= PBaseSize;
10301 size_hints.base_width = base_width;
10302 size_hints.base_height = base_height;
10303 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
10304 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
10305 #else
10306 size_hints.min_width = base_width;
10307 size_hints.min_height = base_height;
10308 #endif
10309 }
10310
10311 /* If we don't need the old flags, we don't need the old hint at all. */
10312 if (flags)
10313 {
10314 size_hints.flags |= flags;
10315 goto no_read;
10316 }
10317 #endif /* not USE_X_TOOLKIT */
10318
10319 {
10320 XSizeHints hints; /* Sometimes I hate X Windows... */
10321 long supplied_return;
10322 int value;
10323
10324 #ifdef HAVE_X11R4
10325 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
10326 &supplied_return);
10327 #else
10328 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
10329 #endif
10330
10331 #ifdef USE_X_TOOLKIT
10332 size_hints.base_height = hints.base_height;
10333 size_hints.base_width = hints.base_width;
10334 size_hints.min_height = hints.min_height;
10335 size_hints.min_width = hints.min_width;
10336 #endif
10337
10338 if (flags)
10339 size_hints.flags |= flags;
10340 else
10341 {
10342 if (value == 0)
10343 hints.flags = 0;
10344 if (hints.flags & PSize)
10345 size_hints.flags |= PSize;
10346 if (hints.flags & PPosition)
10347 size_hints.flags |= PPosition;
10348 if (hints.flags & USPosition)
10349 size_hints.flags |= USPosition;
10350 if (hints.flags & USSize)
10351 size_hints.flags |= USSize;
10352 }
10353 }
10354
10355 #ifndef USE_X_TOOLKIT
10356 no_read:
10357 #endif
10358
10359 #ifdef PWinGravity
10360 size_hints.win_gravity = f->output_data.x->win_gravity;
10361 size_hints.flags |= PWinGravity;
10362
10363 if (user_position)
10364 {
10365 size_hints.flags &= ~ PPosition;
10366 size_hints.flags |= USPosition;
10367 }
10368 #endif /* PWinGravity */
10369
10370 #ifdef HAVE_X11R4
10371 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10372 #else
10373 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
10374 #endif
10375 #endif /* MAC_TODO */
10376 }
10377
10378 #if 0 /* MAC_TODO: hide application instead of iconify? */
10379 /* Used for IconicState or NormalState */
10380
10381 void
10382 x_wm_set_window_state (f, state)
10383 struct frame *f;
10384 int state;
10385 {
10386 #ifdef USE_X_TOOLKIT
10387 Arg al[1];
10388
10389 XtSetArg (al[0], XtNinitialState, state);
10390 XtSetValues (f->output_data.x->widget, al, 1);
10391 #else /* not USE_X_TOOLKIT */
10392 Window window = FRAME_X_WINDOW (f);
10393
10394 f->output_data.x->wm_hints.flags |= StateHint;
10395 f->output_data.x->wm_hints.initial_state = state;
10396
10397 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10398 #endif /* not USE_X_TOOLKIT */
10399 }
10400
10401 void
10402 x_wm_set_icon_pixmap (f, pixmap_id)
10403 struct frame *f;
10404 int pixmap_id;
10405 {
10406 Pixmap icon_pixmap;
10407
10408 #ifndef USE_X_TOOLKIT
10409 Window window = FRAME_X_WINDOW (f);
10410 #endif
10411
10412 if (pixmap_id > 0)
10413 {
10414 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
10415 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
10416 }
10417 else
10418 {
10419 /* It seems there is no way to turn off use of an icon pixmap.
10420 The following line does it, only if no icon has yet been created,
10421 for some window managers. But with mwm it crashes.
10422 Some people say it should clear the IconPixmapHint bit in this case,
10423 but that doesn't work, and the X consortium said it isn't the
10424 right thing at all. Since there is no way to win,
10425 best to explicitly give up. */
10426 #if 0
10427 f->output_data.x->wm_hints.icon_pixmap = None;
10428 #else
10429 return;
10430 #endif
10431 }
10432
10433 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
10434
10435 {
10436 Arg al[1];
10437 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
10438 XtSetValues (f->output_data.x->widget, al, 1);
10439 }
10440
10441 #else /* not USE_X_TOOLKIT */
10442
10443 f->output_data.x->wm_hints.flags |= IconPixmapHint;
10444 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10445
10446 #endif /* not USE_X_TOOLKIT */
10447 }
10448
10449 #endif /* MAC_TODO */
10450
10451 void
10452 x_wm_set_icon_position (f, icon_x, icon_y)
10453 struct frame *f;
10454 int icon_x, icon_y;
10455 {
10456 #if 0 /* MAC_TODO: no icons on Mac */
10457 #ifdef USE_X_TOOLKIT
10458 Window window = XtWindow (f->output_data.x->widget);
10459 #else
10460 Window window = FRAME_X_WINDOW (f);
10461 #endif
10462
10463 f->output_data.x->wm_hints.flags |= IconPositionHint;
10464 f->output_data.x->wm_hints.icon_x = icon_x;
10465 f->output_data.x->wm_hints.icon_y = icon_y;
10466
10467 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
10468 #endif /* MAC_TODO */
10469 }
10470
10471 \f
10472 /***********************************************************************
10473 Fonts
10474 ***********************************************************************/
10475
10476 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
10477
10478 struct font_info *
10479 x_get_font_info (f, font_idx)
10480 FRAME_PTR f;
10481 int font_idx;
10482 {
10483 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
10484 }
10485
10486 /* the global font name table */
10487 char **font_name_table = NULL;
10488 int font_name_table_size = 0;
10489 int font_name_count = 0;
10490
10491 /* compare two strings ignoring case */
10492 static int
10493 stricmp (const char *s, const char *t)
10494 {
10495 for ( ; tolower (*s) == tolower (*t); s++, t++)
10496 if (*s == '\0')
10497 return 0;
10498 return tolower (*s) - tolower (*t);
10499 }
10500
10501 /* compare two strings ignoring case and handling wildcard */
10502 static int
10503 wildstrieq (char *s1, char *s2)
10504 {
10505 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
10506 return true;
10507
10508 return stricmp (s1, s2) == 0;
10509 }
10510
10511 /* Assume parameter 1 is fully qualified, no wildcards. */
10512 static int
10513 mac_font_pattern_match (fontname, pattern)
10514 char * fontname;
10515 char * pattern;
10516 {
10517 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
10518 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
10519 char *ptr;
10520
10521 /* Copy fontname so we can modify it during comparison. */
10522 strcpy (font_name_copy, fontname);
10523
10524 ptr = regex;
10525 *ptr++ = '^';
10526
10527 /* Turn pattern into a regexp and do a regexp match. */
10528 for (; *pattern; pattern++)
10529 {
10530 if (*pattern == '?')
10531 *ptr++ = '.';
10532 else if (*pattern == '*')
10533 {
10534 *ptr++ = '.';
10535 *ptr++ = '*';
10536 }
10537 else
10538 *ptr++ = *pattern;
10539 }
10540 *ptr = '$';
10541 *(ptr + 1) = '\0';
10542
10543 return (fast_c_string_match_ignore_case (build_string (regex),
10544 font_name_copy) >= 0);
10545 }
10546
10547 /* Two font specs are considered to match if their foundry, family,
10548 weight, slant, and charset match. */
10549 static int
10550 mac_font_match (char *mf, char *xf)
10551 {
10552 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
10553 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
10554
10555 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10556 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
10557 return mac_font_pattern_match (mf, xf);
10558
10559 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
10560 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
10561 return mac_font_pattern_match (mf, xf);
10562
10563 return (wildstrieq (m_foundry, x_foundry)
10564 && wildstrieq (m_family, x_family)
10565 && wildstrieq (m_weight, x_weight)
10566 && wildstrieq (m_slant, x_slant)
10567 && wildstrieq (m_charset, x_charset))
10568 || mac_font_pattern_match (mf, xf);
10569 }
10570
10571
10572 static char *
10573 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
10574 {
10575 char foundry[32], family[32], cs[32];
10576 char xf[255], *result, *p;
10577
10578 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
10579 {
10580 strcpy(foundry, "Apple");
10581 strcpy(family, name);
10582
10583 switch (scriptcode)
10584 {
10585 case smTradChinese:
10586 strcpy(cs, "big5-0");
10587 break;
10588 case smSimpChinese:
10589 strcpy(cs, "gb2312.1980-0");
10590 break;
10591 case smJapanese:
10592 strcpy(cs, "jisx0208.1983-sjis");
10593 break;
10594 case -smJapanese:
10595 /* Each Apple Japanese font is entered into the font table
10596 twice: once as a jisx0208.1983-sjis font and once as a
10597 jisx0201.1976-0 font. The latter can be used to display
10598 the ascii charset and katakana-jisx0201 charset. A
10599 negative script code signals that the name of this latter
10600 font is being built. */
10601 strcpy(cs, "jisx0201.1976-0");
10602 break;
10603 case smKorean:
10604 strcpy(cs, "ksc5601.1989-0");
10605 break;
10606 default:
10607 strcpy(cs, "mac-roman");
10608 break;
10609 }
10610 }
10611
10612 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
10613 foundry, family, style & bold ? "bold" : "medium",
10614 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
10615
10616 result = (char *) xmalloc (strlen (xf) + 1);
10617 strcpy (result, xf);
10618 for (p = result; *p; p++)
10619 *p = tolower(*p);
10620 return result;
10621 }
10622
10623
10624 /* Convert an X font spec to the corresponding mac font name, which
10625 can then be passed to GetFNum after conversion to a Pascal string.
10626 For ordinary Mac fonts, this should just be their names, like
10627 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
10628 collection contain their charset designation in their names, like
10629 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
10630 names are handled accordingly. */
10631 static void
10632 x_font_name_to_mac_font_name (char *xf, char *mf)
10633 {
10634 char foundry[32], family[32], weight[20], slant[2], cs[32];
10635
10636 strcpy (mf, "");
10637
10638 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10639 foundry, family, weight, slant, cs) != 5 &&
10640 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
10641 foundry, family, weight, slant, cs) != 5)
10642 return;
10643
10644 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
10645 || strcmp (cs, "jisx0208.1983-sjis") == 0
10646 || strcmp (cs, "jisx0201.1976-0") == 0
10647 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
10648 strcpy(mf, family);
10649 else
10650 sprintf(mf, "%s-%s-%s", foundry, family, cs);
10651 }
10652
10653
10654 /* Sets up the table font_name_table to contain the list of all
10655 monospace fonts in the system the first time the table is used so
10656 that the Resource Manager need not be accessed every time this
10657 information is needed. */
10658
10659 static void
10660 init_font_name_table ()
10661 {
10662 #if TARGET_API_MAC_CARBON
10663 SInt32 sv;
10664
10665 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
10666 {
10667 FMFontFamilyIterator ffi;
10668 FMFontFamilyInstanceIterator ffii;
10669 FMFontFamily ff;
10670
10671 /* Create a dummy instance iterator here to avoid creating and
10672 destroying it in the loop. */
10673 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
10674 return;
10675 /* Create an iterator to enumerate the font families. */
10676 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
10677 != noErr)
10678 {
10679 FMDisposeFontFamilyInstanceIterator (&ffii);
10680 return;
10681 }
10682
10683 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
10684 {
10685 Str255 name;
10686 FMFont font;
10687 FMFontStyle style;
10688 FMFontSize size;
10689 SInt16 sc;
10690
10691 if (FMGetFontFamilyName (ff, name) != noErr)
10692 break;
10693 p2cstr (name);
10694
10695 sc = FontToScript (ff);
10696
10697 /* Point the instance iterator at the current font family. */
10698 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
10699 break;
10700
10701 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
10702 == noErr)
10703 {
10704 if (font_name_table_size == 0)
10705 {
10706 font_name_table_size = 16;
10707 font_name_table = (char **)
10708 xmalloc (font_name_table_size * sizeof (char *));
10709 }
10710 else if (font_name_count + 1 >= font_name_table_size)
10711 {
10712 font_name_table_size += 16;
10713 font_name_table = (char **)
10714 xrealloc (font_name_table,
10715 font_name_table_size * sizeof (char *));
10716 }
10717 font_name_table[font_name_count++]
10718 = mac_to_x_fontname (name, size, style, sc);
10719 }
10720 }
10721
10722 /* Dispose of the iterators. */
10723 FMDisposeFontFamilyIterator (&ffi);
10724 FMDisposeFontFamilyInstanceIterator (&ffii);
10725 }
10726 else
10727 {
10728 #endif /* TARGET_API_MAC_CARBON */
10729 GrafPtr port;
10730 SInt16 fontnum, old_fontnum;
10731 int num_mac_fonts = CountResources('FOND');
10732 int i, j;
10733 Handle font_handle, font_handle_2;
10734 short id, scriptcode;
10735 ResType type;
10736 Str32 name;
10737 struct FontAssoc *fat;
10738 struct AsscEntry *assc_entry;
10739
10740 GetPort (&port); /* save the current font number used */
10741 #if TARGET_API_MAC_CARBON
10742 old_fontnum = GetPortTextFont (port);
10743 #else
10744 old_fontnum = port->txFont;
10745 #endif
10746
10747 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
10748 {
10749 font_handle = GetIndResource ('FOND', i);
10750 if (!font_handle)
10751 continue;
10752
10753 GetResInfo (font_handle, &id, &type, name);
10754 GetFNum (name, &fontnum);
10755 p2cstr (name);
10756 if (fontnum == 0)
10757 continue;
10758
10759 TextFont (fontnum);
10760 scriptcode = FontToScript (fontnum);
10761 do
10762 {
10763 HLock (font_handle);
10764
10765 if (GetResourceSizeOnDisk (font_handle)
10766 >= sizeof (struct FamRec))
10767 {
10768 fat = (struct FontAssoc *) (*font_handle
10769 + sizeof (struct FamRec));
10770 assc_entry
10771 = (struct AsscEntry *) (*font_handle
10772 + sizeof (struct FamRec)
10773 + sizeof (struct FontAssoc));
10774
10775 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
10776 {
10777 if (font_name_table_size == 0)
10778 {
10779 font_name_table_size = 16;
10780 font_name_table = (char **)
10781 xmalloc (font_name_table_size * sizeof (char *));
10782 }
10783 else if (font_name_count >= font_name_table_size)
10784 {
10785 font_name_table_size += 16;
10786 font_name_table = (char **)
10787 xrealloc (font_name_table,
10788 font_name_table_size * sizeof (char *));
10789 }
10790 font_name_table[font_name_count++]
10791 = mac_to_x_fontname (name,
10792 assc_entry->fontSize,
10793 assc_entry->fontStyle,
10794 scriptcode);
10795 /* Both jisx0208.1983-sjis and
10796 jisx0201.1976-sjis parts are contained in
10797 Apple Japanese (SJIS) font. */
10798 if (smJapanese == scriptcode)
10799 {
10800 font_name_table[font_name_count++]
10801 = mac_to_x_fontname (name,
10802 assc_entry->fontSize,
10803 assc_entry->fontStyle,
10804 smRoman);
10805 }
10806 }
10807 }
10808
10809 HUnlock (font_handle);
10810 font_handle_2 = GetNextFOND (font_handle);
10811 ReleaseResource (font_handle);
10812 font_handle = font_handle_2;
10813 }
10814 while (ResError () == noErr && font_handle);
10815 }
10816
10817 TextFont (old_fontnum);
10818 #if TARGET_API_MAC_CARBON
10819 }
10820 #endif /* TARGET_API_MAC_CARBON */
10821 }
10822
10823
10824 /* Return a list of at most MAXNAMES font specs matching the one in
10825 PATTERN. Note that each '*' in the PATTERN matches exactly one
10826 field of the font spec, unlike X in which an '*' in a font spec can
10827 match a number of fields. The result is in the Mac implementation
10828 all fonts must be specified by a font spec with all 13 fields
10829 (although many of these can be "*'s"). */
10830
10831 Lisp_Object
10832 x_list_fonts (struct frame *f,
10833 Lisp_Object pattern,
10834 int size,
10835 int maxnames)
10836 {
10837 char *ptnstr;
10838 Lisp_Object newlist = Qnil;
10839 int n_fonts = 0;
10840 int i;
10841 struct gcpro gcpro1, gcpro2;
10842
10843 if (font_name_table == NULL) /* Initialize when first used. */
10844 init_font_name_table ();
10845
10846 ptnstr = XSTRING (pattern)->data;
10847
10848 GCPRO2 (pattern, newlist);
10849
10850 /* Scan and matching bitmap fonts. */
10851 for (i = 0; i < font_name_count; i++)
10852 {
10853 if (mac_font_pattern_match (font_name_table[i], ptnstr))
10854 {
10855 newlist = Fcons (build_string (font_name_table[i]), newlist);
10856
10857 n_fonts++;
10858 if (n_fonts >= maxnames)
10859 break;
10860 }
10861 }
10862
10863 /* MAC_TODO: add code for matching outline fonts here */
10864
10865 UNGCPRO;
10866
10867 return newlist;
10868 }
10869
10870
10871 #if GLYPH_DEBUG
10872
10873 /* Check that FONT is valid on frame F. It is if it can be found in F's
10874 font table. */
10875
10876 static void
10877 x_check_font (f, font)
10878 struct frame *f;
10879 XFontStruct *font;
10880 {
10881 int i;
10882 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10883
10884 xassert (font != NULL);
10885
10886 for (i = 0; i < dpyinfo->n_fonts; i++)
10887 if (dpyinfo->font_table[i].name
10888 && font == dpyinfo->font_table[i].font)
10889 break;
10890
10891 xassert (i < dpyinfo->n_fonts);
10892 }
10893
10894 #endif /* GLYPH_DEBUG != 0 */
10895
10896 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10897 Note: There are (broken) X fonts out there with invalid XFontStruct
10898 min_bounds contents. For example, handa@etl.go.jp reports that
10899 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10900 have font->min_bounds.width == 0. */
10901
10902 static INLINE void
10903 x_font_min_bounds (font, w, h)
10904 MacFontStruct *font;
10905 int *w, *h;
10906 {
10907 /*
10908 * TODO: Windows does not appear to offer min bound, only
10909 * average and maximum width, and maximum height.
10910 */
10911 *h = FONT_HEIGHT (font);
10912 *w = FONT_WIDTH (font);
10913 }
10914
10915
10916 /* Compute the smallest character width and smallest font height over
10917 all fonts available on frame F. Set the members smallest_char_width
10918 and smallest_font_height in F's x_display_info structure to
10919 the values computed. Value is non-zero if smallest_font_height or
10920 smallest_char_width become smaller than they were before. */
10921
10922 int
10923 x_compute_min_glyph_bounds (f)
10924 struct frame *f;
10925 {
10926 int i;
10927 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10928 MacFontStruct *font;
10929 int old_width = dpyinfo->smallest_char_width;
10930 int old_height = dpyinfo->smallest_font_height;
10931
10932 dpyinfo->smallest_font_height = 100000;
10933 dpyinfo->smallest_char_width = 100000;
10934
10935 for (i = 0; i < dpyinfo->n_fonts; ++i)
10936 if (dpyinfo->font_table[i].name)
10937 {
10938 struct font_info *fontp = dpyinfo->font_table + i;
10939 int w, h;
10940
10941 font = (MacFontStruct *) fontp->font;
10942 xassert (font != (MacFontStruct *) ~0);
10943 x_font_min_bounds (font, &w, &h);
10944
10945 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10946 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10947 }
10948
10949 xassert (dpyinfo->smallest_char_width > 0
10950 && dpyinfo->smallest_font_height > 0);
10951
10952 return (dpyinfo->n_fonts == 1
10953 || dpyinfo->smallest_char_width < old_width
10954 || dpyinfo->smallest_font_height < old_height);
10955 }
10956
10957
10958 /* Determine whether given string is a fully-specified XLFD: all 14
10959 fields are present, none is '*'. */
10960
10961 static int
10962 is_fully_specified_xlfd (char *p)
10963 {
10964 int i;
10965 char *q;
10966
10967 if (*p != '-')
10968 return 0;
10969
10970 for (i = 0; i < 13; i++)
10971 {
10972 q = strchr (p + 1, '-');
10973 if (q == NULL)
10974 return 0;
10975 if (q - p == 2 && *(p + 1) == '*')
10976 return 0;
10977 p = q;
10978 }
10979
10980 if (strchr (p + 1, '-') != NULL)
10981 return 0;
10982
10983 if (*(p + 1) == '*' && *(p + 2) == '\0')
10984 return 0;
10985
10986 return 1;
10987 }
10988
10989
10990 const int kDefaultFontSize = 9;
10991
10992
10993 /* XLoadQueryFont creates and returns an internal representation for a
10994 font in a MacFontStruct struct. There is really no concept
10995 corresponding to "loading" a font on the Mac. But we check its
10996 existence and find the font number and all other information for it
10997 and store them in the returned MacFontStruct. */
10998
10999 static MacFontStruct *
11000 XLoadQueryFont (Display *dpy, char *fontname)
11001 {
11002 int i, size, is_two_byte_font, char_width;
11003 char *name;
11004 GrafPtr port;
11005 SInt16 old_fontnum, old_fontsize;
11006 Style old_fontface;
11007 Str32 mfontname;
11008 SInt16 fontnum;
11009 Style fontface = normal;
11010 MacFontStruct *font;
11011 FontInfo the_fontinfo;
11012 char s_weight[7], c_slant;
11013
11014 if (is_fully_specified_xlfd (fontname))
11015 name = fontname;
11016 else
11017 {
11018 for (i = 0; i < font_name_count; i++)
11019 if (mac_font_pattern_match (font_name_table[i], fontname))
11020 break;
11021
11022 if (i >= font_name_count)
11023 return NULL;
11024
11025 name = font_name_table[i];
11026 }
11027
11028 GetPort (&port); /* save the current font number used */
11029 #if TARGET_API_MAC_CARBON
11030 old_fontnum = GetPortTextFont (port);
11031 old_fontsize = GetPortTextSize (port);
11032 old_fontface = GetPortTextFace (port);
11033 #else
11034 old_fontnum = port->txFont;
11035 old_fontsize = port->txSize;
11036 old_fontface = port->txFace;
11037 #endif
11038
11039 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
11040 size = kDefaultFontSize;
11041
11042 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
11043 if (strcmp (s_weight, "bold") == 0)
11044 fontface |= bold;
11045
11046 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
11047 if (c_slant == 'i')
11048 fontface |= italic;
11049
11050 x_font_name_to_mac_font_name (name, mfontname);
11051 c2pstr (mfontname);
11052 GetFNum (mfontname, &fontnum);
11053 if (fontnum == 0)
11054 return NULL;
11055
11056 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
11057
11058 font->fontname = (char *) xmalloc (strlen (name) + 1);
11059 bcopy (name, font->fontname, strlen (name) + 1);
11060
11061 font->mac_fontnum = fontnum;
11062 font->mac_fontsize = size;
11063 font->mac_fontface = fontface;
11064 font->mac_scriptcode = FontToScript (fontnum);
11065
11066 /* Apple Japanese (SJIS) font is listed as both
11067 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
11068 (Roman script) in init_font_name_table (). The latter should be
11069 treated as a one-byte font. */
11070 {
11071 char cs[32];
11072
11073 if (sscanf (name,
11074 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
11075 cs) == 1
11076 && 0 == strcmp (cs, "mac-roman"))
11077 font->mac_scriptcode = smRoman;
11078 }
11079
11080 is_two_byte_font = font->mac_scriptcode == smJapanese ||
11081 font->mac_scriptcode == smTradChinese ||
11082 font->mac_scriptcode == smSimpChinese ||
11083 font->mac_scriptcode == smKorean;
11084
11085 TextFont (fontnum);
11086 TextSize (size);
11087 TextFace (fontface);
11088
11089 GetFontInfo (&the_fontinfo);
11090
11091 font->ascent = the_fontinfo.ascent;
11092 font->descent = the_fontinfo.descent;
11093
11094 font->min_byte1 = 0;
11095 if (is_two_byte_font)
11096 font->max_byte1 = 1;
11097 else
11098 font->max_byte1 = 0;
11099 font->min_char_or_byte2 = 0x20;
11100 font->max_char_or_byte2 = 0xff;
11101
11102 if (is_two_byte_font)
11103 {
11104 /* Use the width of an "ideographic space" of that font because
11105 the_fontinfo.widMax returns the wrong width for some fonts. */
11106 switch (font->mac_scriptcode)
11107 {
11108 case smJapanese:
11109 char_width = StringWidth("\p\x81\x40");
11110 break;
11111 case smTradChinese:
11112 char_width = StringWidth("\p\xa1\x40");
11113 break;
11114 case smSimpChinese:
11115 char_width = StringWidth("\p\xa1\xa1");
11116 break;
11117 case smKorean:
11118 char_width = StringWidth("\p\xa1\xa1");
11119 break;
11120 }
11121 }
11122 else
11123 /* Do this instead of use the_fontinfo.widMax, which incorrectly
11124 returns 15 for 12-point Monaco! */
11125 char_width = CharWidth ('m');
11126
11127 font->max_bounds.rbearing = char_width;
11128 font->max_bounds.lbearing = 0;
11129 font->max_bounds.width = char_width;
11130 font->max_bounds.ascent = the_fontinfo.ascent;
11131 font->max_bounds.descent = the_fontinfo.descent;
11132
11133 font->min_bounds = font->max_bounds;
11134
11135 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
11136 font->per_char = NULL;
11137 else
11138 {
11139 font->per_char = (XCharStruct *)
11140 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
11141 {
11142 int c;
11143
11144 for (c = 0x20; c <= 0xff; c++)
11145 {
11146 font->per_char[c - 0x20] = font->max_bounds;
11147 font->per_char[c - 0x20].width = CharWidth (c);
11148 }
11149 }
11150 }
11151
11152 TextFont (old_fontnum); /* restore previous font number, size and face */
11153 TextSize (old_fontsize);
11154 TextFace (old_fontface);
11155
11156 return font;
11157 }
11158
11159
11160 /* Load font named FONTNAME of the size SIZE for frame F, and return a
11161 pointer to the structure font_info while allocating it dynamically.
11162 If SIZE is 0, load any size of font.
11163 If loading is failed, return NULL. */
11164
11165 struct font_info *
11166 x_load_font (f, fontname, size)
11167 struct frame *f;
11168 register char *fontname;
11169 int size;
11170 {
11171 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11172 Lisp_Object font_names;
11173
11174 /* Get a list of all the fonts that match this name. Once we
11175 have a list of matching fonts, we compare them against the fonts
11176 we already have by comparing names. */
11177 font_names = x_list_fonts (f, build_string (fontname), size, 1);
11178
11179 if (!NILP (font_names))
11180 {
11181 Lisp_Object tail;
11182 int i;
11183
11184 for (i = 0; i < dpyinfo->n_fonts; i++)
11185 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
11186 if (dpyinfo->font_table[i].name
11187 && (!strcmp (dpyinfo->font_table[i].name,
11188 XSTRING (XCAR (tail))->data)
11189 || !strcmp (dpyinfo->font_table[i].full_name,
11190 XSTRING (XCAR (tail))->data)))
11191 return (dpyinfo->font_table + i);
11192 }
11193
11194 /* Load the font and add it to the table. */
11195 {
11196 char *full_name;
11197 struct MacFontStruct *font;
11198 struct font_info *fontp;
11199 unsigned long value;
11200 int i;
11201
11202 /* If we have found fonts by x_list_font, load one of them. If
11203 not, we still try to load a font by the name given as FONTNAME
11204 because XListFonts (called in x_list_font) of some X server has
11205 a bug of not finding a font even if the font surely exists and
11206 is loadable by XLoadQueryFont. */
11207 if (size > 0 && !NILP (font_names))
11208 fontname = (char *) XSTRING (XCAR (font_names))->data;
11209
11210 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
11211 if (!font)
11212 return NULL;
11213
11214 /* Find a free slot in the font table. */
11215 for (i = 0; i < dpyinfo->n_fonts; ++i)
11216 if (dpyinfo->font_table[i].name == NULL)
11217 break;
11218
11219 /* If no free slot found, maybe enlarge the font table. */
11220 if (i == dpyinfo->n_fonts
11221 && dpyinfo->n_fonts == dpyinfo->font_table_size)
11222 {
11223 int sz;
11224 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11225 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
11226 dpyinfo->font_table
11227 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
11228 }
11229
11230 fontp = dpyinfo->font_table + i;
11231 if (i == dpyinfo->n_fonts)
11232 ++dpyinfo->n_fonts;
11233
11234 /* Now fill in the slots of *FONTP. */
11235 BLOCK_INPUT;
11236 fontp->font = font;
11237 fontp->font_idx = i;
11238 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
11239 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
11240
11241 fontp->full_name = fontp->name;
11242
11243 fontp->size = font->max_bounds.width;
11244 fontp->height = FONT_HEIGHT (font);
11245 {
11246 /* For some font, ascent and descent in max_bounds field is
11247 larger than the above value. */
11248 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11249 if (max_height > fontp->height)
11250 fontp->height = max_height;
11251 }
11252
11253 /* The slot `encoding' specifies how to map a character
11254 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
11255 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
11256 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
11257 2:0xA020..0xFF7F). For the moment, we don't know which charset
11258 uses this font. So, we set information in fontp->encoding[1]
11259 which is never used by any charset. If mapping can't be
11260 decided, set FONT_ENCODING_NOT_DECIDED. */
11261 if (font->mac_scriptcode == smJapanese)
11262 fontp->encoding[1] = 4;
11263 else
11264 {
11265 fontp->encoding[1]
11266 = (font->max_byte1 == 0
11267 /* 1-byte font */
11268 ? (font->min_char_or_byte2 < 0x80
11269 ? (font->max_char_or_byte2 < 0x80
11270 ? 0 /* 0x20..0x7F */
11271 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
11272 : 1) /* 0xA0..0xFF */
11273 /* 2-byte font */
11274 : (font->min_byte1 < 0x80
11275 ? (font->max_byte1 < 0x80
11276 ? (font->min_char_or_byte2 < 0x80
11277 ? (font->max_char_or_byte2 < 0x80
11278 ? 0 /* 0x2020..0x7F7F */
11279 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
11280 : 3) /* 0x20A0..0x7FFF */
11281 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
11282 : (font->min_char_or_byte2 < 0x80
11283 ? (font->max_char_or_byte2 < 0x80
11284 ? 2 /* 0xA020..0xFF7F */
11285 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
11286 : 1))); /* 0xA0A0..0xFFFF */
11287 }
11288
11289 #if 0 /* MAC_TODO: fill these out with more reasonably values */
11290 fontp->baseline_offset
11291 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
11292 ? (long) value : 0);
11293 fontp->relative_compose
11294 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
11295 ? (long) value : 0);
11296 fontp->default_ascent
11297 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
11298 ? (long) value : 0);
11299 #else
11300 fontp->baseline_offset = 0;
11301 fontp->relative_compose = 0;
11302 fontp->default_ascent = 0;
11303 #endif
11304
11305 /* Set global flag fonts_changed_p to non-zero if the font loaded
11306 has a character with a smaller width than any other character
11307 before, or if the font loaded has a smalle>r height than any
11308 other font loaded before. If this happens, it will make a
11309 glyph matrix reallocation necessary. */
11310 fonts_changed_p = x_compute_min_glyph_bounds (f);
11311 UNBLOCK_INPUT;
11312 return fontp;
11313 }
11314 }
11315
11316
11317 /* Return a pointer to struct font_info of a font named FONTNAME for
11318 frame F. If no such font is loaded, return NULL. */
11319
11320 struct font_info *
11321 x_query_font (f, fontname)
11322 struct frame *f;
11323 register char *fontname;
11324 {
11325 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
11326 int i;
11327
11328 for (i = 0; i < dpyinfo->n_fonts; i++)
11329 if (dpyinfo->font_table[i].name
11330 && (!strcmp (dpyinfo->font_table[i].name, fontname)
11331 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
11332 return (dpyinfo->font_table + i);
11333 return NULL;
11334 }
11335
11336
11337 /* Find a CCL program for a font specified by FONTP, and set the member
11338 `encoder' of the structure. */
11339
11340 void
11341 x_find_ccl_program (fontp)
11342 struct font_info *fontp;
11343 {
11344 Lisp_Object list, elt;
11345
11346 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
11347 {
11348 elt = XCAR (list);
11349 if (CONSP (elt)
11350 && STRINGP (XCAR (elt))
11351 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
11352 >= 0))
11353 break;
11354 }
11355 if (! NILP (list))
11356 {
11357 struct ccl_program *ccl
11358 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
11359
11360 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
11361 xfree (ccl);
11362 else
11363 fontp->font_encoder = ccl;
11364 }
11365 }
11366
11367
11368 \f
11369 /***********************************************************************
11370 Initialization
11371 ***********************************************************************/
11372
11373 #ifdef USE_X_TOOLKIT
11374 static XrmOptionDescRec emacs_options[] = {
11375 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
11376 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
11377
11378 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
11379 XrmoptionSepArg, NULL},
11380 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
11381
11382 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11383 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11384 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
11385 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11386 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
11387 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
11388 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
11389 };
11390 #endif /* USE_X_TOOLKIT */
11391
11392 static int x_initialized;
11393
11394 #ifdef MULTI_KBOARD
11395 /* Test whether two display-name strings agree up to the dot that separates
11396 the screen number from the server number. */
11397 static int
11398 same_x_server (name1, name2)
11399 char *name1, *name2;
11400 {
11401 int seen_colon = 0;
11402 unsigned char *system_name = XSTRING (Vsystem_name)->data;
11403 int system_name_length = strlen (system_name);
11404 int length_until_period = 0;
11405
11406 while (system_name[length_until_period] != 0
11407 && system_name[length_until_period] != '.')
11408 length_until_period++;
11409
11410 /* Treat `unix' like an empty host name. */
11411 if (! strncmp (name1, "unix:", 5))
11412 name1 += 4;
11413 if (! strncmp (name2, "unix:", 5))
11414 name2 += 4;
11415 /* Treat this host's name like an empty host name. */
11416 if (! strncmp (name1, system_name, system_name_length)
11417 && name1[system_name_length] == ':')
11418 name1 += system_name_length;
11419 if (! strncmp (name2, system_name, system_name_length)
11420 && name2[system_name_length] == ':')
11421 name2 += system_name_length;
11422 /* Treat this host's domainless name like an empty host name. */
11423 if (! strncmp (name1, system_name, length_until_period)
11424 && name1[length_until_period] == ':')
11425 name1 += length_until_period;
11426 if (! strncmp (name2, system_name, length_until_period)
11427 && name2[length_until_period] == ':')
11428 name2 += length_until_period;
11429
11430 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
11431 {
11432 if (*name1 == ':')
11433 seen_colon++;
11434 if (seen_colon && *name1 == '.')
11435 return 1;
11436 }
11437 return (seen_colon
11438 && (*name1 == '.' || *name1 == '\0')
11439 && (*name2 == '.' || *name2 == '\0'));
11440 }
11441 #endif
11442
11443
11444 /* The Mac Event loop code */
11445
11446 #ifndef MAC_OSX
11447 #include <Events.h>
11448 #include <Quickdraw.h>
11449 #include <Balloons.h>
11450 #include <Devices.h>
11451 #include <Fonts.h>
11452 #include <Gestalt.h>
11453 #include <Menus.h>
11454 #include <Processes.h>
11455 #include <Sound.h>
11456 #include <ToolUtils.h>
11457 #include <TextUtils.h>
11458 #include <Dialogs.h>
11459 #include <Script.h>
11460 #include <Types.h>
11461 #include <TextEncodingConverter.h>
11462 #include <Resources.h>
11463
11464 #if __MWERKS__
11465 #include <unix.h>
11466 #endif
11467 #endif /* ! MAC_OSX */
11468
11469 #define M_APPLE 128
11470 #define I_ABOUT 1
11471
11472 #define WINDOW_RESOURCE 128
11473 #define TERM_WINDOW_RESOURCE 129
11474
11475 #define DEFAULT_NUM_COLS 80
11476
11477 #define MIN_DOC_SIZE 64
11478 #define MAX_DOC_SIZE 32767
11479
11480 /* sleep time for WaitNextEvent */
11481 #define WNE_SLEEP_AT_SUSPEND 10
11482 #define WNE_SLEEP_AT_RESUME 1
11483
11484 /* true when cannot handle any Mac OS events */
11485 static int handling_window_update = 0;
11486
11487 /* the flag appl_is_suspended is used both for determining the sleep
11488 time to be passed to WaitNextEvent and whether the cursor should be
11489 drawn when updating the display. The cursor is turned off when
11490 Emacs is suspended. Redrawing it is unnecessary and what needs to
11491 be done depends on whether the cursor lies inside or outside the
11492 redraw region. So we might as well skip drawing it when Emacs is
11493 suspended. */
11494 static Boolean app_is_suspended = false;
11495 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
11496
11497 #define EXTRA_STACK_ALLOC (256 * 1024)
11498
11499 #define ARGV_STRING_LIST_ID 129
11500 #define ABOUT_ALERT_ID 128
11501 #define RAM_TOO_LARGE_ALERT_ID 129
11502
11503 Boolean terminate_flag = false;
11504
11505 /* true if using command key as meta key */
11506 Lisp_Object Vmac_command_key_is_meta;
11507
11508 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
11509 to this text encoding */
11510 int mac_keyboard_text_encoding;
11511 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
11512
11513 /* Set in term/mac-win.el to indicate that event loop can now generate
11514 drag and drop events. */
11515 Lisp_Object Qmac_ready_for_drag_n_drop;
11516
11517 Lisp_Object drag_and_drop_file_list;
11518
11519 Point saved_menu_event_location;
11520
11521 /* Apple Events */
11522 static void init_required_apple_events(void);
11523 static pascal OSErr
11524 do_ae_open_application(const AppleEvent *, AppleEvent *, long);
11525 static pascal OSErr
11526 do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
11527 static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
11528 static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
11529
11530 extern void init_emacs_passwd_dir ();
11531 extern int emacs_main (int, char **, char **);
11532 extern void check_alarm ();
11533
11534 extern void initialize_applescript();
11535 extern void terminate_applescript();
11536
11537
11538 static void
11539 do_get_menus (void)
11540 {
11541 Handle menubar_handle;
11542 MenuHandle menu_handle;
11543
11544 menubar_handle = GetNewMBar (128);
11545 if(menubar_handle == NULL)
11546 abort ();
11547 SetMenuBar (menubar_handle);
11548 DrawMenuBar ();
11549
11550 menu_handle = GetMenuHandle (M_APPLE);
11551 if(menu_handle != NULL)
11552 AppendResMenu (menu_handle,'DRVR');
11553 else
11554 abort ();
11555 }
11556
11557
11558 static void
11559 do_init_managers (void)
11560 {
11561 #if !TARGET_API_MAC_CARBON
11562 InitGraf (&qd.thePort);
11563 InitFonts ();
11564 FlushEvents (everyEvent, 0);
11565 InitWindows ();
11566 InitMenus ();
11567 TEInit ();
11568 InitDialogs (NULL);
11569 #endif /* !TARGET_API_MAC_CARBON */
11570 InitCursor ();
11571
11572 #if !TARGET_API_MAC_CARBON
11573 /* set up some extra stack space for use by emacs */
11574 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
11575
11576 /* MaxApplZone must be called for AppleScript to execute more
11577 complicated scripts */
11578 MaxApplZone ();
11579 MoreMasters ();
11580 #endif /* !TARGET_API_MAC_CARBON */
11581 }
11582
11583 static void
11584 do_check_ram_size (void)
11585 {
11586 SInt32 physical_ram_size, logical_ram_size;
11587
11588 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
11589 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
11590 || physical_ram_size > 256 * 1024 * 1024
11591 || logical_ram_size > 256 * 1024 * 1024)
11592 {
11593 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
11594 exit (1);
11595 }
11596 }
11597
11598 static void
11599 do_window_update (WindowPtr win)
11600 {
11601 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
11602 struct frame *f = mwp->mFP;
11603
11604 if (f)
11605 {
11606 if (f->async_visible == 0)
11607 {
11608 f->async_visible = 1;
11609 f->async_iconified = 0;
11610 SET_FRAME_GARBAGED (f);
11611
11612 /* An update event is equivalent to MapNotify on X, so report
11613 visibility changes properly. */
11614 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
11615 /* Force a redisplay sooner or later to update the
11616 frame titles in case this is the second frame. */
11617 record_asynch_buffer_change ();
11618 }
11619 else
11620 {
11621 BeginUpdate (win);
11622 handling_window_update = 1;
11623
11624 expose_frame (f, 0, 0, 0, 0);
11625
11626 handling_window_update = 0;
11627 EndUpdate (win);
11628 }
11629 }
11630 }
11631
11632 static int
11633 is_emacs_window (WindowPtr win)
11634 {
11635 Lisp_Object tail, frame;
11636
11637 if (!win)
11638 return 0;
11639
11640 FOR_EACH_FRAME (tail, frame)
11641 if (FRAME_MAC_P (XFRAME (frame)))
11642 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
11643 return 1;
11644
11645 return 0;
11646 }
11647
11648 static void
11649 do_window_activate (WindowPtr win)
11650 {
11651 mac_output *mwp;
11652 struct frame *f;
11653
11654 if (is_emacs_window (win))
11655 {
11656 mwp = (mac_output *) GetWRefCon (win);
11657 f = mwp->mFP;
11658
11659 if (f)
11660 {
11661 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11662 activate_scroll_bars (f);
11663 }
11664 }
11665 }
11666
11667 static void
11668 do_window_deactivate (WindowPtr win)
11669 {
11670 mac_output *mwp;
11671 struct frame *f;
11672
11673 if (is_emacs_window (win))
11674 {
11675 mwp = (mac_output *) GetWRefCon (win);
11676 f = mwp->mFP;
11677
11678 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11679 {
11680 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11681 deactivate_scroll_bars (f);
11682 }
11683 }
11684 }
11685
11686 static void
11687 do_app_resume ()
11688 {
11689 WindowPtr wp;
11690 mac_output *mwp;
11691 struct frame *f;
11692
11693 wp = FrontWindow();
11694 if (is_emacs_window (wp))
11695 {
11696 mwp = (mac_output *) GetWRefCon (wp);
11697 f = mwp->mFP;
11698
11699 if (f)
11700 {
11701 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
11702 activate_scroll_bars (f);
11703 }
11704 }
11705
11706 app_is_suspended = false;
11707 app_sleep_time = WNE_SLEEP_AT_RESUME;
11708 }
11709
11710 static void
11711 do_app_suspend ()
11712 {
11713 WindowPtr wp;
11714 mac_output *mwp;
11715 struct frame *f;
11716
11717 wp = FrontWindow();
11718 if (is_emacs_window (wp))
11719 {
11720 mwp = (mac_output *) GetWRefCon (wp);
11721 f = mwp->mFP;
11722
11723 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
11724 {
11725 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
11726 deactivate_scroll_bars (f);
11727 }
11728 }
11729
11730 app_is_suspended = true;
11731 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
11732 }
11733
11734
11735 static void
11736 do_mouse_moved (Point mouse_pos)
11737 {
11738 WindowPtr wp = FrontWindow ();
11739 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11740
11741 #if TARGET_API_MAC_CARBON
11742 SetPort (GetWindowPort (wp));
11743 #else
11744 SetPort (wp);
11745 #endif
11746
11747 GlobalToLocal (&mouse_pos);
11748
11749 note_mouse_movement (f, &mouse_pos);
11750 }
11751
11752
11753 static void
11754 do_os_event (EventRecord *erp)
11755 {
11756 switch((erp->message >> 24) & 0x000000FF)
11757 {
11758 case suspendResumeMessage:
11759 if((erp->message & resumeFlag) == 1)
11760 do_app_resume ();
11761 else
11762 do_app_suspend ();
11763 break;
11764
11765 case mouseMovedMessage:
11766 do_mouse_moved (erp->where);
11767 break;
11768 }
11769 }
11770
11771 static void
11772 do_events (EventRecord *erp)
11773 {
11774 switch (erp->what)
11775 {
11776 case updateEvt:
11777 do_window_update ((WindowPtr) erp->message);
11778 break;
11779
11780 case osEvt:
11781 do_os_event (erp);
11782 break;
11783
11784 case activateEvt:
11785 if ((erp->modifiers & activeFlag) != 0)
11786 do_window_activate ((WindowPtr) erp->message);
11787 else
11788 do_window_deactivate ((WindowPtr) erp->message);
11789 break;
11790 }
11791 }
11792
11793 static void
11794 do_apple_menu (SInt16 menu_item)
11795 {
11796 #if !TARGET_API_MAC_CARBON
11797 Str255 item_name;
11798 SInt16 da_driver_refnum;
11799
11800 if (menu_item == I_ABOUT)
11801 NoteAlert (ABOUT_ALERT_ID, NULL);
11802 else
11803 {
11804 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
11805 da_driver_refnum = OpenDeskAcc (item_name);
11806 }
11807 #endif /* !TARGET_API_MAC_CARBON */
11808 }
11809
11810 void
11811 do_menu_choice (SInt32 menu_choice)
11812 {
11813 SInt16 menu_id, menu_item;
11814
11815 menu_id = HiWord (menu_choice);
11816 menu_item = LoWord (menu_choice);
11817
11818 if (menu_id == 0)
11819 return;
11820
11821 switch (menu_id)
11822 {
11823 case M_APPLE:
11824 do_apple_menu (menu_item);
11825 break;
11826
11827 default:
11828 {
11829 WindowPtr wp = FrontWindow ();
11830 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
11831 MenuHandle menu = GetMenuHandle (menu_id);
11832 if (menu)
11833 {
11834 UInt32 refcon;
11835
11836 GetMenuItemRefCon (menu, menu_item, &refcon);
11837 menubar_selection_callback (f, refcon);
11838 }
11839 }
11840 }
11841
11842 HiliteMenu (0);
11843 }
11844
11845
11846 /* Handle drags in size box. Based on code contributed by Ben
11847 Mesander and IM - Window Manager A. */
11848
11849 static void
11850 do_grow_window (WindowPtr w, EventRecord *e)
11851 {
11852 long grow_size;
11853 Rect limit_rect;
11854 int rows, columns;
11855 mac_output *mwp = (mac_output *) GetWRefCon (w);
11856 struct frame *f = mwp->mFP;
11857
11858 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
11859
11860 grow_size = GrowWindow (w, e->where, &limit_rect);
11861
11862 /* see if it really changed size */
11863 if (grow_size != 0)
11864 {
11865 rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
11866 columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
11867
11868 x_set_window_size (f, 0, columns, rows);
11869 }
11870 }
11871
11872
11873 /* Handle clicks in zoom box. Calculation of "standard state" based
11874 on code in IM - Window Manager A and code contributed by Ben
11875 Mesander. The standard state of an Emacs window is 80-characters
11876 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
11877
11878 static void
11879 do_zoom_window (WindowPtr w, int zoom_in_or_out)
11880 {
11881 GrafPtr save_port;
11882 Rect zoom_rect, port_rect;
11883 Point top_left;
11884 int w_title_height, columns, rows, width, height, dummy, x, y;
11885 mac_output *mwp = (mac_output *) GetWRefCon (w);
11886 struct frame *f = mwp->mFP;
11887
11888 GetPort (&save_port);
11889
11890 #if TARGET_API_MAC_CARBON
11891 SetPort (GetWindowPort (w));
11892 #else
11893 SetPort (w);
11894 #endif
11895
11896 /* Clear window to avoid flicker. */
11897 #if TARGET_API_MAC_CARBON
11898 {
11899 Rect r;
11900 BitMap bm;
11901
11902 GetWindowPortBounds (w, &r);
11903 EraseRect (&r);
11904
11905 if (zoom_in_or_out == inZoomOut)
11906 {
11907 /* calculate height of window's title bar (hard card it for now). */
11908 w_title_height = 20 + GetMBarHeight ();
11909
11910 /* get maximum height of window into zoom_rect.bottom -
11911 zoom_rect.top */
11912 GetQDGlobalsScreenBits (&bm);
11913 zoom_rect = bm.bounds;
11914 zoom_rect.top += w_title_height;
11915 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11916
11917 zoom_rect.right = zoom_rect.left
11918 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11919
11920 SetWindowStandardState (w, &zoom_rect);
11921 }
11922 }
11923 #else /* not TARGET_API_MAC_CARBON */
11924 EraseRect (&(w->portRect));
11925 if (zoom_in_or_out == inZoomOut)
11926 {
11927 SetPt (&top_left, w->portRect.left, w->portRect.top);
11928 LocalToGlobal (&top_left);
11929
11930 /* calculate height of window's title bar */
11931 w_title_height = top_left.v - 1
11932 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
11933
11934 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
11935 zoom_rect = qd.screenBits.bounds;
11936 zoom_rect.top += w_title_height;
11937 InsetRect (&zoom_rect, 8, 4); /* not too tight */
11938
11939 zoom_rect.right = zoom_rect.left
11940 + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
11941
11942 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
11943 = zoom_rect;
11944 }
11945 #endif /* not TARGET_API_MAC_CARBON */
11946
11947 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
11948
11949 /* retrieve window size and update application values */
11950 #if TARGET_API_MAC_CARBON
11951 GetWindowPortBounds (w, &port_rect);
11952 #else
11953 port_rect = w->portRect;
11954 #endif
11955 rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
11956 columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
11957 x_set_window_size (mwp->mFP, 0, columns, rows);
11958
11959 SetPort (save_port);
11960 }
11961
11962
11963 /* Intialize AppleEvent dispatcher table for the required events. */
11964 void
11965 init_required_apple_events ()
11966 {
11967 OSErr err;
11968 long result;
11969
11970 /* Make sure we have apple events before starting. */
11971 err = Gestalt (gestaltAppleEventsAttr, &result);
11972 if (err != noErr)
11973 abort ();
11974
11975 if (!(result & (1 << gestaltAppleEventsPresent)))
11976 abort ();
11977
11978 #if TARGET_API_MAC_CARBON
11979 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
11980 NewAEEventHandlerUPP
11981 ((AEEventHandlerProcPtr) do_ae_open_application),
11982 0L, false);
11983 #else
11984 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
11985 NewAEEventHandlerProc
11986 ((AEEventHandlerProcPtr) do_ae_open_application),
11987 0L, false);
11988 #endif
11989 if (err != noErr)
11990 abort ();
11991
11992 #if TARGET_API_MAC_CARBON
11993 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
11994 NewAEEventHandlerUPP
11995 ((AEEventHandlerProcPtr) do_ae_open_documents),
11996 0L, false);
11997 #else
11998 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
11999 NewAEEventHandlerProc
12000 ((AEEventHandlerProcPtr) do_ae_open_documents),
12001 0L, false);
12002 #endif
12003 if (err != noErr)
12004 abort ();
12005
12006 #if TARGET_API_MAC_CARBON
12007 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12008 NewAEEventHandlerUPP
12009 ((AEEventHandlerProcPtr) do_ae_print_documents),
12010 0L, false);
12011 #else
12012 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
12013 NewAEEventHandlerProc
12014 ((AEEventHandlerProcPtr) do_ae_print_documents),
12015 0L, false);
12016 #endif
12017 if (err != noErr)
12018 abort ();
12019
12020 #if TARGET_API_MAC_CARBON
12021 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12022 NewAEEventHandlerUPP
12023 ((AEEventHandlerProcPtr) do_ae_quit_application),
12024 0L, false);
12025 #else
12026 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
12027 NewAEEventHandlerProc
12028 ((AEEventHandlerProcPtr) do_ae_quit_application),
12029 0L, false);
12030 #endif
12031 if (err != noErr)
12032 abort ();
12033 }
12034
12035
12036 /* Open Application Apple Event */
12037 static pascal OSErr
12038 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
12039 {
12040 return noErr;
12041 }
12042
12043
12044 /* Defined in mac.c. */
12045 extern int
12046 path_from_vol_dir_name (char *, int, short, long, char *);
12047
12048
12049 /* Called when we receive an AppleEvent with an ID of
12050 "kAEOpenDocuments". This routine gets the direct parameter,
12051 extracts the FSSpecs in it, and puts their names on a list. */
12052 static pascal OSErr
12053 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
12054 {
12055 OSErr err, err2;
12056 AEDesc the_desc;
12057 AEKeyword keyword;
12058 DescType actual_type;
12059 Size actual_size;
12060
12061 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
12062 if (err != noErr)
12063 goto descriptor_error_exit;
12064
12065 /* Check to see that we got all of the required parameters from the
12066 event descriptor. For an 'odoc' event this should just be the
12067 file list. */
12068 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
12069 &actual_type, (Ptr) &keyword,
12070 sizeof (keyword), &actual_size);
12071 /* No error means that we found some unused parameters.
12072 errAEDescNotFound means that there are no more parameters. If we
12073 get an error code other than that, flag it. */
12074 if ((err == noErr) || (err != errAEDescNotFound))
12075 {
12076 err = errAEEventNotHandled;
12077 goto error_exit;
12078 }
12079 err = noErr;
12080
12081 /* Got all the parameters we need. Now, go through the direct
12082 object list and parse it up. */
12083 {
12084 long num_files_to_open;
12085
12086 err = AECountItems (&the_desc, &num_files_to_open);
12087 if (err == noErr)
12088 {
12089 int i;
12090
12091 /* AE file list is one based so just use that for indexing here. */
12092 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++) {
12093 FSSpec fs;
12094 Str255 path_name, unix_path_name;
12095
12096 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
12097 (Ptr) &fs, sizeof (fs), &actual_size);
12098 if (err != noErr) break;
12099
12100 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
12101 fs.name) &&
12102 mac_to_posix_pathname (path_name, unix_path_name, 255))
12103 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
12104 drag_and_drop_file_list);
12105 }
12106 }
12107 }
12108
12109 error_exit:
12110 /* Nuke the coerced file list in any case */
12111 err2 = AEDisposeDesc(&the_desc);
12112
12113 descriptor_error_exit:
12114 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
12115 return err;
12116 }
12117
12118
12119 /* Print Document Apple Event */
12120 static pascal OSErr
12121 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
12122 {
12123 return errAEEventNotHandled;
12124 }
12125
12126
12127 static pascal OSErr
12128 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
12129 {
12130 /* FixMe: Do we need an unwind-protect or something here? And what
12131 do we do about unsaved files. Currently just forces quit rather
12132 than doing recursive callback to get user input. */
12133
12134 terminate_flag = true;
12135
12136 /* Fkill_emacs doesn't return. We have to return. (TI) */
12137 return noErr;
12138 }
12139
12140
12141 #if __profile__
12142 void
12143 profiler_exit_proc ()
12144 {
12145 ProfilerDump ("\pEmacs.prof");
12146 ProfilerTerm ();
12147 }
12148 #endif
12149
12150 /* These few functions implement Emacs as a normal Mac application
12151 (almost): set up the heap and the Toolbox, handle necessary
12152 system events plus a few simple menu events. They also set up
12153 Emacs's access to functions defined in the rest of this file.
12154 Emacs uses function hooks to perform all its terminal I/O. A
12155 complete list of these functions appear in termhooks.h. For what
12156 they do, read the comments there and see also w32term.c and
12157 xterm.c. What's noticeably missing here is the event loop, which
12158 is normally present in most Mac application. After performing the
12159 necessary Mac initializations, main passes off control to
12160 emacs_main (corresponding to main in emacs.c). Emacs_main calls
12161 mac_read_socket (defined further below) to read input. This is
12162 where WaitNextEvent is called to process Mac events. This is also
12163 where check_alarm in sysdep.c is called to simulate alarm signals.
12164 This makes the cursor jump back to its correct position after
12165 briefly jumping to that of the matching parenthesis, print useful
12166 hints and prompts in the minibuffer after the user stops typing for
12167 a wait, etc. */
12168
12169 #if !TARGET_API_MAC_CARBON
12170 #undef main
12171 int
12172 main (void)
12173 {
12174 #if __profile__ /* is the profiler on? */
12175 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
12176 exit(1);
12177 #endif
12178
12179 #if __MWERKS__
12180 /* set creator and type for files created by MSL */
12181 _fcreator = 'EMAx';
12182 _ftype = 'TEXT';
12183 #endif
12184
12185 do_init_managers ();
12186
12187 do_get_menus ();
12188
12189 do_check_ram_size ();
12190
12191 init_emacs_passwd_dir ();
12192
12193 init_environ ();
12194
12195 initialize_applescript ();
12196
12197 init_required_apple_events ();
12198
12199 {
12200 char **argv;
12201 int argc = 0;
12202
12203 /* set up argv array from STR# resource */
12204 get_string_list (&argv, ARGV_STRING_LIST_ID);
12205 while (argv[argc])
12206 argc++;
12207
12208 /* free up AppleScript resources on exit */
12209 atexit (terminate_applescript);
12210
12211 #if __profile__ /* is the profiler on? */
12212 atexit (profiler_exit_proc);
12213 #endif
12214
12215 /* 3rd param "envp" never used in emacs_main */
12216 (void) emacs_main (argc, argv, 0);
12217 }
12218
12219 /* Never reached - real exit in Fkill_emacs */
12220 return 0;
12221 }
12222 #endif
12223
12224 /* Table for translating Mac keycode to X keysym values. Contributed
12225 by Sudhir Shenoy. */
12226 static unsigned char keycode_to_xkeysym_table[] = {
12227 /* 0x00 - 0x3f */
12228 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12230 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12231 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12232 /* 0x40 */
12233 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
12234 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
12235 0, 0, 0, '\xaf' /* kp/ */,
12236 '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
12237 /* 0x50 */
12238 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
12239 '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
12240 '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
12241 '\xb9' /* kp9 */, 0, 0, 0,
12242 /* 0x60 */
12243 '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
12244 '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
12245 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
12246 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
12247 /* 0x70 */
12248 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
12249 '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
12250 '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
12251 '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
12252 };
12253
12254 static int
12255 keycode_to_xkeysym (int keyCode, int *xKeySym)
12256 {
12257 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
12258 return *xKeySym != 0;
12259 }
12260
12261 /* Emacs calls this whenever it wants to read an input event from the
12262 user. */
12263 int
12264 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
12265 {
12266 int count = 0;
12267 EventRecord er;
12268 int the_modifiers;
12269 EventMask event_mask;
12270
12271 #if 0
12272 if (interrupt_input_blocked)
12273 {
12274 interrupt_input_pending = 1;
12275 return -1;
12276 }
12277 #endif
12278
12279 interrupt_input_pending = 0;
12280 BLOCK_INPUT;
12281
12282 /* So people can tell when we have read the available input. */
12283 input_signal_count++;
12284
12285 if (numchars <= 0)
12286 abort ();
12287
12288 /* Don't poll for events to process (specifically updateEvt) if
12289 window update currently already in progress. A call to redisplay
12290 (in do_window_update) can be preempted by another call to
12291 redisplay, causing blank regions to be left on the screen and the
12292 cursor to be left at strange places. */
12293 if (handling_window_update)
12294 {
12295 UNBLOCK_INPUT;
12296 return 0;
12297 }
12298
12299 if (terminate_flag)
12300 Fkill_emacs (make_number (1));
12301
12302 /* It is necessary to set this (additional) argument slot of an
12303 event to nil because keyboard.c protects incompletely processed
12304 event from being garbage collected by placing them in the
12305 kbd_buffer_gcpro vector. */
12306 bufp->arg = Qnil;
12307
12308 event_mask = everyEvent;
12309 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
12310 event_mask -= highLevelEventMask;
12311
12312 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
12313 switch (er.what)
12314 {
12315 case mouseDown:
12316 case mouseUp:
12317 {
12318 WindowPtr window_ptr = FrontWindow ();
12319 SInt16 part_code;
12320
12321 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12322 && er.what == mouseUp)
12323 {
12324 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
12325 Point mouse_loc = er.where;
12326
12327 /* Convert to local coordinates of new window. */
12328 #if TARGET_API_MAC_CARBON
12329 SetPort (GetWindowPort (window_ptr));
12330 #else
12331 SetPort (window_ptr);
12332 #endif
12333
12334 GlobalToLocal (&mouse_loc);
12335
12336 bufp->code = 0; /* only one mouse button */
12337 bufp->kind = SCROLL_BAR_CLICK_EVENT;
12338 bufp->frame_or_window = tracked_scroll_bar->window;
12339 bufp->part = scroll_bar_handle;
12340 bufp->modifiers = up_modifier;
12341 bufp->timestamp = er.when * (1000 / 60);
12342 /* ticks to milliseconds */
12343
12344 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
12345 XSETINT (bufp->y, mouse_loc.v - 24);
12346 tracked_scroll_bar->dragging = Qnil;
12347 mouse_tracking_in_progress = mouse_tracking_none;
12348 tracked_scroll_bar = NULL;
12349 count++;
12350 break;
12351 }
12352
12353 part_code = FindWindow (er.where, &window_ptr);
12354
12355 switch (part_code)
12356 {
12357 case inMenuBar:
12358 {
12359 struct frame *f = ((mac_output *)
12360 GetWRefCon (FrontWindow ()))->mFP;
12361 saved_menu_event_location = er.where;
12362 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
12363 XSETFRAME (bufp->frame_or_window, f);
12364 count++;
12365 }
12366 break;
12367
12368 case inContent:
12369 if (window_ptr != FrontWindow ())
12370 SelectWindow (window_ptr);
12371 else
12372 {
12373 SInt16 control_part_code;
12374 ControlHandle ch;
12375 struct mac_output *mwp = (mac_output *)
12376 GetWRefCon (window_ptr);
12377 Point mouse_loc = er.where;
12378
12379 /* convert to local coordinates of new window */
12380 #if TARGET_API_MAC_CARBON
12381 SetPort (GetWindowPort (window_ptr));
12382 #else
12383 SetPort (window_ptr);
12384 #endif
12385
12386 GlobalToLocal (&mouse_loc);
12387 #if TARGET_API_MAC_CARBON
12388 ch = FindControlUnderMouse (mouse_loc, window_ptr,
12389 &control_part_code);
12390 #else
12391 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
12392 #endif
12393 bufp->code = 0; /* only one mouse button */
12394 XSETINT (bufp->x, mouse_loc.h);
12395 XSETINT (bufp->y, mouse_loc.v);
12396 bufp->timestamp = er.when * (1000 / 60);
12397 /* ticks to milliseconds */
12398
12399 #if TARGET_API_MAC_CARBON
12400 if (ch != 0)
12401 #else
12402 if (control_part_code != 0)
12403 #endif
12404 {
12405 struct scroll_bar *bar = (struct scroll_bar *)
12406 GetControlReference (ch);
12407 x_scroll_bar_handle_click (bar, control_part_code, &er,
12408 bufp);
12409 if (er.what == mouseDown
12410 && control_part_code == kControlIndicatorPart)
12411 {
12412 mouse_tracking_in_progress
12413 = mouse_tracking_scroll_bar;
12414 tracked_scroll_bar = bar;
12415 }
12416 else
12417 {
12418 mouse_tracking_in_progress = mouse_tracking_none;
12419 tracked_scroll_bar = NULL;
12420 }
12421 }
12422 else
12423 {
12424 bufp->kind = MOUSE_CLICK_EVENT;
12425 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12426 if (er.what == mouseDown)
12427 mouse_tracking_in_progress
12428 = mouse_tracking_mouse_movement;
12429 else
12430 mouse_tracking_in_progress = mouse_tracking_none;
12431 }
12432
12433 switch (er.what)
12434 {
12435 case mouseDown:
12436 bufp->modifiers = down_modifier;
12437 break;
12438 case mouseUp:
12439 bufp->modifiers = up_modifier;
12440 break;
12441 }
12442
12443 count++;
12444 }
12445 break;
12446
12447 case inDrag:
12448 #if TARGET_API_MAC_CARBON
12449 {
12450 BitMap bm;
12451
12452 GetQDGlobalsScreenBits (&bm);
12453 DragWindow (window_ptr, er.where, &bm.bounds);
12454 }
12455 #else /* not TARGET_API_MAC_CARBON */
12456 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12457 #endif /* not TARGET_API_MAC_CARBON */
12458 break;
12459
12460 case inGoAway:
12461 if (TrackGoAway (window_ptr, er.where))
12462 {
12463 bufp->kind = DELETE_WINDOW_EVENT;
12464 XSETFRAME (bufp->frame_or_window,
12465 ((mac_output *) GetWRefCon (window_ptr))->mFP);
12466 count++;
12467 }
12468 break;
12469
12470 /* window resize handling added --ben */
12471 case inGrow:
12472 do_grow_window(window_ptr, &er);
12473 break;
12474
12475 /* window zoom handling added --ben */
12476 case inZoomIn:
12477 case inZoomOut:
12478 if (TrackBox (window_ptr, er.where, part_code))
12479 do_zoom_window (window_ptr, part_code);
12480 break;
12481
12482 default:
12483 break;
12484 }
12485 }
12486 break;
12487
12488 case updateEvt:
12489 case osEvt:
12490 case activateEvt:
12491 do_events (&er);
12492 break;
12493
12494 case keyDown:
12495 case autoKey:
12496 {
12497 int keycode = (er.message & keyCodeMask) >> 8;
12498 int xkeysym;
12499
12500 ObscureCursor ();
12501
12502 if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
12503 {
12504 bufp->code = 0x7f;
12505 bufp->kind = ASCII_KEYSTROKE_EVENT;
12506 }
12507 else if (keycode_to_xkeysym (keycode, &xkeysym))
12508 {
12509 bufp->code = 0xff00 | xkeysym;
12510 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
12511 }
12512 else
12513 {
12514 if (er.modifiers
12515 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12516 {
12517 /* This code comes from Keyboard Resource, Appendix
12518 C of IM - Text. This is necessary since shift is
12519 ignored in KCHR table translation when option or
12520 command is pressed. */
12521 int new_modifiers = er.modifiers & 0xf600;
12522 /* mask off option and command */
12523 int new_keycode = keycode | new_modifiers;
12524 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
12525 unsigned long some_state = 0;
12526 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
12527 &some_state) & 0xff;
12528 }
12529 else
12530 bufp->code = er.message & charCodeMask;
12531 bufp->kind = ASCII_KEYSTROKE_EVENT;
12532 }
12533 }
12534
12535 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
12536 convert non-ASCII characters typed at the Mac keyboard
12537 (presumed to be in the Mac Roman encoding) to iso-latin-1
12538 encoding before they are passed to Emacs. This enables the
12539 Mac keyboard to be used to enter non-ASCII iso-latin-1
12540 characters directly. */
12541 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
12542 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
12543 {
12544 static TECObjectRef converter = NULL;
12545 OSStatus the_err = noErr;
12546 OSStatus convert_status = noErr;
12547
12548 if (converter == NULL)
12549 {
12550 the_err = TECCreateConverter (&converter,
12551 kTextEncodingMacRoman,
12552 mac_keyboard_text_encoding);
12553 current_mac_keyboard_text_encoding
12554 = mac_keyboard_text_encoding;
12555 }
12556 else if (mac_keyboard_text_encoding
12557 != current_mac_keyboard_text_encoding)
12558 {
12559 /* Free the converter for the current encoding before
12560 creating a new one. */
12561 TECDisposeConverter (converter);
12562 the_err = TECCreateConverter (&converter,
12563 kTextEncodingMacRoman,
12564 mac_keyboard_text_encoding);
12565 current_mac_keyboard_text_encoding
12566 = mac_keyboard_text_encoding;
12567 }
12568
12569 if (the_err == noErr)
12570 {
12571 unsigned char ch = bufp->code;
12572 ByteCount actual_input_length, actual_output_length;
12573 unsigned char outch;
12574
12575 convert_status = TECConvertText (converter, &ch, 1,
12576 &actual_input_length,
12577 &outch, 1,
12578 &actual_output_length);
12579 if (convert_status == noErr
12580 && actual_input_length == 1
12581 && actual_output_length == 1)
12582 bufp->code = outch;
12583 }
12584 }
12585
12586 the_modifiers = 0;
12587 if (er.modifiers & shiftKey)
12588 the_modifiers |= shift_modifier;
12589 if (er.modifiers & controlKey)
12590 the_modifiers |= ctrl_modifier;
12591 /* use option or command key as meta depending on value of
12592 mac-command-key-is-meta */
12593 if (er.modifiers
12594 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
12595 the_modifiers |= meta_modifier;
12596 bufp->modifiers = the_modifiers;
12597
12598 {
12599 mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
12600 XSETFRAME (bufp->frame_or_window, mwp->mFP);
12601 }
12602
12603 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
12604
12605 count++;
12606 break;
12607
12608 case kHighLevelEvent:
12609 drag_and_drop_file_list = Qnil;
12610
12611 AEProcessAppleEvent(&er);
12612
12613 /* Build a DRAG_N_DROP_EVENT type event as is done in
12614 constuct_drag_n_drop in w32term.c. */
12615 if (!NILP (drag_and_drop_file_list))
12616 {
12617 struct frame *f;
12618 WindowPtr wp;
12619 Lisp_Object frame;
12620
12621 wp = FrontWindow ();
12622 if (!wp)
12623 f = NULL;
12624 else
12625 f = ((mac_output *) GetWRefCon (wp))->mFP;
12626
12627 bufp->kind = DRAG_N_DROP_EVENT;
12628 bufp->code = 0;
12629 bufp->timestamp = er.when * (1000 / 60);
12630 /* ticks to milliseconds */
12631 bufp->modifiers = 0;
12632
12633 XSETINT (bufp->x, 0);
12634 XSETINT (bufp->y, 0);
12635
12636 XSETFRAME (frame, f);
12637 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
12638
12639 /* Regardless of whether Emacs was suspended or in the
12640 foreground, ask it to redraw its entire screen.
12641 Otherwise parts of the screen can be left in an
12642 inconsistent state. */
12643 if (wp)
12644 #if TARGET_API_MAC_CARBON
12645 {
12646 Rect r;
12647
12648 GetWindowPortBounds (wp, &r);
12649 InvalWindowRect (wp, &r);
12650 }
12651 #else /* not TARGET_API_MAC_CARBON */
12652 InvalRect (&(wp->portRect));
12653 #endif /* not TARGET_API_MAC_CARBON */
12654
12655 count++;
12656 }
12657
12658 default:
12659 break;
12660 }
12661
12662 /* If the focus was just given to an autoraising frame,
12663 raise it now. */
12664 /* ??? This ought to be able to handle more than one such frame. */
12665 if (pending_autoraise_frame)
12666 {
12667 x_raise_frame (pending_autoraise_frame);
12668 pending_autoraise_frame = 0;
12669 }
12670
12671 #if !TARGET_API_MAC_CARBON
12672 check_alarm (); /* simulate the handling of a SIGALRM */
12673 #endif
12674
12675 {
12676 static Point old_mouse_pos = { -1, -1 };
12677
12678 if (app_is_suspended)
12679 {
12680 old_mouse_pos.h = -1;
12681 old_mouse_pos.v = -1;
12682 }
12683 else
12684 {
12685 Point mouse_pos;
12686 WindowPtr wp;
12687 struct frame *f;
12688 Lisp_Object bar;
12689 struct scroll_bar *sb;
12690
12691 wp = FrontWindow ();
12692 if (is_emacs_window (wp))
12693 {
12694 f = ((mac_output *) GetWRefCon (wp))->mFP;
12695
12696 #if TARGET_API_MAC_CARBON
12697 SetPort (GetWindowPort (wp));
12698 #else
12699 SetPort (wp);
12700 #endif
12701
12702 GetMouse (&mouse_pos);
12703
12704 if (!EqualPt (mouse_pos, old_mouse_pos))
12705 {
12706 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
12707 && tracked_scroll_bar)
12708 x_scroll_bar_note_movement (tracked_scroll_bar,
12709 mouse_pos.v
12710 - XINT (tracked_scroll_bar->top),
12711 TickCount() * (1000 / 60));
12712 else
12713 note_mouse_movement (f, &mouse_pos);
12714
12715 old_mouse_pos = mouse_pos;
12716 }
12717 }
12718 }
12719 }
12720
12721 UNBLOCK_INPUT;
12722
12723 return count;
12724 }
12725
12726
12727 /* Need to override CodeWarrior's input function so no conversion is
12728 done on newlines Otherwise compiled functions in .elc files will be
12729 read incorrectly. Defined in ...:MSL C:MSL
12730 Common:Source:buffer_io.c. */
12731 #ifdef __MWERKS__
12732 void
12733 __convert_to_newlines (unsigned char * p, size_t * n)
12734 {
12735 #pragma unused(p,n)
12736 }
12737
12738 void
12739 __convert_from_newlines (unsigned char * p, size_t * n)
12740 {
12741 #pragma unused(p,n)
12742 }
12743 #endif
12744
12745
12746 /* Initialize the struct pointed to by MW to represent a new COLS x
12747 ROWS Macintosh window, using font with name FONTNAME and size
12748 FONTSIZE. */
12749 void
12750 NewMacWindow (FRAME_PTR fp)
12751 {
12752 mac_output *mwp;
12753 #if TARGET_API_MAC_CARBON
12754 static int making_terminal_window = 0;
12755 #else
12756 static int making_terminal_window = 1;
12757 #endif
12758
12759 mwp = fp->output_data.mac;
12760
12761 if (making_terminal_window)
12762 {
12763 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
12764 (WindowPtr) -1)))
12765 abort ();
12766 making_terminal_window = 0;
12767 }
12768 else
12769 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
12770 abort ();
12771
12772
12773 SetWRefCon (mwp->mWP, (long) mwp);
12774 /* so that update events can find this mac_output struct */
12775 mwp->mFP = fp; /* point back to emacs frame */
12776
12777 #if TARGET_API_MAC_CARBON
12778 SetPort (GetWindowPort (mwp->mWP));
12779 #else
12780 SetPort (mwp->mWP);
12781 #endif
12782
12783 mwp->fontset = -1;
12784
12785 SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
12786 ShowWindow (mwp->mWP);
12787
12788 }
12789
12790
12791 void make_mac_frame (struct frame *f)
12792 {
12793 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
12794 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
12795
12796 NewMacWindow(f);
12797 FRAME_BACKGROUND_PIXEL (f) = 0xffffff;
12798 FRAME_FOREGROUND_PIXEL (f) = 0;
12799
12800 f->output_data.mac->cursor_pixel = 0;
12801 f->output_data.mac->border_pixel = 0x00ff00;
12802 f->output_data.mac->mouse_pixel = 0xff00ff;
12803 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
12804
12805 f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
12806
12807 f->output_data.mac->fontset = -1;
12808 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12809 f->output_data.mac->scroll_bar_background_pixel = -1;
12810 f->output_data.mac->left_pos = 4;
12811 f->output_data.mac->top_pos = 4;
12812 f->output_data.mac->border_width = 0;
12813 f->output_data.mac->explicit_parent = 0;
12814
12815 f->output_data.mac->internal_border_width = 0;
12816
12817 f->output_method = output_mac;
12818
12819 f->auto_raise = 1;
12820 f->auto_lower = 1;
12821
12822 f->new_width = 0;
12823 f->new_height = 0;
12824 }
12825
12826 void make_mac_terminal_frame (struct frame *f)
12827 {
12828 Lisp_Object frame;
12829
12830 XSETFRAME (frame, f);
12831
12832 f->output_method = output_mac;
12833 f->output_data.mac = (struct mac_output *)
12834 xmalloc (sizeof (struct mac_output));
12835 bzero (f->output_data.mac, sizeof (struct mac_output));
12836 f->output_data.mac->fontset = -1;
12837 f->output_data.mac->scroll_bar_foreground_pixel = -1;
12838 f->output_data.mac->scroll_bar_background_pixel = -1;
12839
12840 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
12841
12842 f->width = 96;
12843 f->height = 4;
12844
12845 make_mac_frame (f);
12846
12847 x_make_gc (f);
12848
12849 /* Need to be initialized for unshow_buffer in window.c. */
12850 selected_window = f->selected_window;
12851
12852 Fmodify_frame_parameters (frame,
12853 Fcons (Fcons (Qfont,
12854 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
12855 Fmodify_frame_parameters (frame,
12856 Fcons (Fcons (Qforeground_color,
12857 build_string ("black")), Qnil));
12858 Fmodify_frame_parameters (frame,
12859 Fcons (Fcons (Qbackground_color,
12860 build_string ("white")), Qnil));
12861 }
12862
12863 \f
12864 /***********************************************************************
12865 Initialization
12866 ***********************************************************************/
12867
12868 #ifdef USE_X_TOOLKIT
12869 static XrmOptionDescRec emacs_options[] = {
12870 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12871 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12872
12873 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12874 XrmoptionSepArg, NULL},
12875 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12876
12877 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12878 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12879 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12880 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12881 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12882 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12883 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12884 };
12885 #endif /* USE_X_TOOLKIT */
12886
12887 #ifdef MULTI_KBOARD
12888 /* Test whether two display-name strings agree up to the dot that separates
12889 the screen number from the server number. */
12890 static int
12891 same_x_server (name1, name2)
12892 char *name1, *name2;
12893 {
12894 int seen_colon = 0;
12895 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12896 int system_name_length = strlen (system_name);
12897 int length_until_period = 0;
12898
12899 while (system_name[length_until_period] != 0
12900 && system_name[length_until_period] != '.')
12901 length_until_period++;
12902
12903 /* Treat `unix' like an empty host name. */
12904 if (! strncmp (name1, "unix:", 5))
12905 name1 += 4;
12906 if (! strncmp (name2, "unix:", 5))
12907 name2 += 4;
12908 /* Treat this host's name like an empty host name. */
12909 if (! strncmp (name1, system_name, system_name_length)
12910 && name1[system_name_length] == ':')
12911 name1 += system_name_length;
12912 if (! strncmp (name2, system_name, system_name_length)
12913 && name2[system_name_length] == ':')
12914 name2 += system_name_length;
12915 /* Treat this host's domainless name like an empty host name. */
12916 if (! strncmp (name1, system_name, length_until_period)
12917 && name1[length_until_period] == ':')
12918 name1 += length_until_period;
12919 if (! strncmp (name2, system_name, length_until_period)
12920 && name2[length_until_period] == ':')
12921 name2 += length_until_period;
12922
12923 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12924 {
12925 if (*name1 == ':')
12926 seen_colon++;
12927 if (seen_colon && *name1 == '.')
12928 return 1;
12929 }
12930 return (seen_colon
12931 && (*name1 == '.' || *name1 == '\0')
12932 && (*name2 == '.' || *name2 == '\0'));
12933 }
12934 #endif
12935
12936 int mac_initialized = 0;
12937
12938 void
12939 mac_initialize_display_info ()
12940 {
12941 struct mac_display_info *dpyinfo = &one_mac_display_info;
12942 GDHandle main_device_handle;
12943
12944 bzero (dpyinfo, sizeof (*dpyinfo));
12945
12946 /* Put it on x_display_name_list. */
12947 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
12948 x_display_name_list);
12949 dpyinfo->name_list_element = XCAR (x_display_name_list);
12950
12951 #if 0
12952 dpyinfo->mac_id_name
12953 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
12954 + XSTRING (Vsystem_name)->size
12955 + 2);
12956 sprintf (dpyinfo->mac_id_name, "%s@%s",
12957 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
12958 #else
12959 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
12960 strcpy (dpyinfo->mac_id_name, "Mac Display");
12961 #endif
12962
12963 main_device_handle = LMGetMainDevice();
12964
12965 dpyinfo->reference_count = 0;
12966 dpyinfo->resx = 75.0;
12967 dpyinfo->resy = 75.0;
12968 dpyinfo->n_planes = 1;
12969 dpyinfo->n_cbits = 16;
12970 dpyinfo->height = (**main_device_handle).gdRect.bottom;
12971 dpyinfo->width = (**main_device_handle).gdRect.right;
12972 dpyinfo->grabbed = 0;
12973 dpyinfo->root_window = NULL;
12974
12975 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
12976 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
12977 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
12978 dpyinfo->mouse_face_window = Qnil;
12979 }
12980
12981 struct mac_display_info *
12982 mac_term_init (display_name, xrm_option, resource_name)
12983 Lisp_Object display_name;
12984 char *xrm_option;
12985 char *resource_name;
12986 {
12987 struct mac_display_info *dpyinfo;
12988 GDHandle main_device_handle;
12989
12990 if (!mac_initialized)
12991 {
12992 mac_initialize ();
12993 mac_initialized = 1;
12994 }
12995
12996 mac_initialize_display_info (display_name);
12997
12998 dpyinfo = &one_mac_display_info;
12999
13000 main_device_handle = LMGetMainDevice();
13001
13002 dpyinfo->height = (**main_device_handle).gdRect.bottom;
13003 dpyinfo->width = (**main_device_handle).gdRect.right;
13004
13005 return dpyinfo;
13006 }
13007 \f
13008 /* Set up use of X before we make the first connection. */
13009
13010 static struct redisplay_interface x_redisplay_interface =
13011 {
13012 x_produce_glyphs,
13013 x_write_glyphs,
13014 x_insert_glyphs,
13015 x_clear_end_of_line,
13016 x_scroll_run,
13017 x_after_update_window_line,
13018 x_update_window_begin,
13019 x_update_window_end,
13020 XTcursor_to,
13021 x_flush,
13022 x_clear_mouse_face,
13023 x_get_glyph_overhangs,
13024 x_fix_overlapping_area
13025 };
13026
13027 void
13028 mac_initialize ()
13029 {
13030 rif = &x_redisplay_interface;
13031
13032 clear_frame_hook = x_clear_frame;
13033 ins_del_lines_hook = x_ins_del_lines;
13034 delete_glyphs_hook = x_delete_glyphs;
13035 ring_bell_hook = XTring_bell;
13036 reset_terminal_modes_hook = XTreset_terminal_modes;
13037 set_terminal_modes_hook = XTset_terminal_modes;
13038 update_begin_hook = x_update_begin;
13039 update_end_hook = x_update_end;
13040 set_terminal_window_hook = XTset_terminal_window;
13041 read_socket_hook = XTread_socket;
13042 frame_up_to_date_hook = XTframe_up_to_date;
13043 mouse_position_hook = XTmouse_position;
13044 frame_rehighlight_hook = XTframe_rehighlight;
13045 frame_raise_lower_hook = XTframe_raise_lower;
13046
13047 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13048 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13049 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13050 judge_scroll_bars_hook = XTjudge_scroll_bars;
13051
13052 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13053
13054 scroll_region_ok = 1; /* we'll scroll partial frames */
13055 char_ins_del_ok = 1;
13056 line_ins_del_ok = 1; /* we'll just blt 'em */
13057 fast_clear_end_of_line = 1; /* X does this well */
13058 memory_below_frame = 0; /* we don't remember what scrolls
13059 off the bottom */
13060 baud_rate = 19200;
13061
13062 x_noop_count = 0;
13063 last_tool_bar_item = -1;
13064 any_help_event_p = 0;
13065
13066 /* Try to use interrupt input; if we can't, then start polling. */
13067 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13068
13069 #ifdef USE_X_TOOLKIT
13070 XtToolkitInitialize ();
13071 Xt_app_con = XtCreateApplicationContext ();
13072 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13073
13074 /* Install an asynchronous timer that processes Xt timeout events
13075 every 0.1s. This is necessary because some widget sets use
13076 timeouts internally, for example the LessTif menu bar, or the
13077 Xaw3d scroll bar. When Xt timouts aren't processed, these
13078 widgets don't behave normally. */
13079 {
13080 EMACS_TIME interval;
13081 EMACS_SET_SECS_USECS (interval, 0, 100000);
13082 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13083 }
13084 #endif
13085
13086 #if USE_TOOLKIT_SCROLL_BARS
13087 xaw3d_arrow_scroll = False;
13088 xaw3d_pick_top = True;
13089 #endif
13090
13091 #if 0
13092 /* Note that there is no real way portable across R3/R4 to get the
13093 original error handler. */
13094 XSetErrorHandler (x_error_handler);
13095 XSetIOErrorHandler (x_io_error_quitter);
13096
13097 /* Disable Window Change signals; they are handled by X events. */
13098 #ifdef SIGWINCH
13099 signal (SIGWINCH, SIG_DFL);
13100 #endif /* ! defined (SIGWINCH) */
13101
13102 signal (SIGPIPE, x_connection_signal);
13103 #endif
13104
13105 mac_initialize_display_info ();
13106 }
13107
13108
13109 void
13110 syms_of_macterm ()
13111 {
13112 #if 0
13113 staticpro (&x_error_message_string);
13114 x_error_message_string = Qnil;
13115 #endif
13116
13117 staticpro (&x_display_name_list);
13118 x_display_name_list = Qnil;
13119
13120 staticpro (&last_mouse_scroll_bar);
13121 last_mouse_scroll_bar = Qnil;
13122
13123 staticpro (&Qvendor_specific_keysyms);
13124 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13125
13126 staticpro (&last_mouse_press_frame);
13127 last_mouse_press_frame = Qnil;
13128
13129 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
13130 staticpro (&Qmac_ready_for_drag_n_drop);
13131
13132 help_echo = Qnil;
13133 staticpro (&help_echo);
13134 help_echo_object = Qnil;
13135 staticpro (&help_echo_object);
13136 help_echo_window = Qnil;
13137 staticpro (&help_echo_window);
13138 previous_help_echo = Qnil;
13139 staticpro (&previous_help_echo);
13140 help_echo_pos = -1;
13141
13142 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
13143 doc: /* *Non-nil means autoselect window with mouse pointer. */);
13144 x_autoselect_window_p = 0;
13145
13146 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13147 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
13148 For example, if a block cursor is over a tab, it will be drawn as
13149 wide as that tab on the display. */);
13150 x_stretch_cursor_p = 0;
13151
13152 #if 0 /* TODO: Setting underline position from font properties. */
13153 DEFVAR_BOOL ("x-use-underline-position-properties",
13154 &x_use_underline_position_properties,
13155 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
13156 nil means ignore them. If you encounter fonts with bogus
13157 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
13158 to 4.1, set this to nil. */);
13159 x_use_underline_position_properties = 1;
13160 #endif
13161
13162 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
13163 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
13164 Vx_toolkit_scroll_bars = Qt;
13165
13166 staticpro (&last_mouse_motion_frame);
13167 last_mouse_motion_frame = Qnil;
13168
13169 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
13170 doc: /* Non-nil means that the command key is used as the Emacs meta key.
13171 Otherwise the option key is used. */);
13172 Vmac_command_key_is_meta = Qt;
13173
13174 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
13175 doc: /* One of the Text Encoding Base constant values defined in the
13176 Basic Text Constants section of Inside Macintosh - Text Encoding
13177 Conversion Manager. Its value determines the encoding characters
13178 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
13179 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
13180 its default value, no conversion takes place. If it is set to
13181 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
13182 characters typed on Mac keyboard are first converted into the
13183 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
13184 passed to Emacs. Together with Emacs's set-keyboard-coding-system
13185 command, this enables the Mac keyboard to be used to enter non-ASCII
13186 characters directly. */);
13187 mac_keyboard_text_encoding = kTextEncodingMacRoman;
13188 }