(map_keymap_function_t): More informative prototype.
[emacs.git] / src / macterm.c
blob906f946388c713bf23e6d2a60f9e1cc91f47579b
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
24 #include <config.h>
25 #include <signal.h>
27 #include <stdio.h>
29 #include "lisp.h"
30 #include "blockinput.h"
32 #include "macterm.h"
34 #ifndef MAC_OSX
35 #include <alloca.h>
36 #endif
38 #if !TARGET_API_MAC_CARBON
39 #include <Quickdraw.h>
40 #include <ToolUtils.h>
41 #include <Sound.h>
42 #include <Events.h>
43 #include <Script.h>
44 #include <Resources.h>
45 #include <Fonts.h>
46 #include <TextUtils.h>
47 #include <LowMem.h>
48 #include <Controls.h>
49 #include <Windows.h>
50 #include <Displays.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
53 #endif
55 #if __profile__
56 #include <profiler.h>
57 #endif
58 #endif /* not TARGET_API_MAC_CARBON */
60 #include "systty.h"
61 #include "systime.h"
63 #include <ctype.h>
64 #include <errno.h>
65 #include <setjmp.h>
66 #include <sys/stat.h>
68 #include "charset.h"
69 #include "coding.h"
70 #include "frame.h"
71 #include "dispextern.h"
72 #include "fontset.h"
73 #include "termhooks.h"
74 #include "termopts.h"
75 #include "termchar.h"
76 #include "disptab.h"
77 #include "buffer.h"
78 #include "window.h"
79 #include "keyboard.h"
80 #include "intervals.h"
81 #include "atimer.h"
82 #include "keymap.h"
86 /* Non-nil means Emacs uses toolkit scroll bars. */
88 Lisp_Object Vx_toolkit_scroll_bars;
90 /* If non-zero, the text will be rendered using Core Graphics text
91 rendering which may anti-alias the text. */
92 int mac_use_core_graphics;
95 /* Non-zero means that a HELP_EVENT has been generated since Emacs
96 start. */
98 static int any_help_event_p;
100 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
101 static Lisp_Object last_window;
103 /* Non-zero means make use of UNDERLINE_POSITION font properties.
104 (Not yet supported.) */
105 int x_use_underline_position_properties;
107 /* Non-zero means to draw the underline at the same place as the descent line. */
109 int x_underline_at_descent_line;
111 /* This is a chain of structures for all the X displays currently in
112 use. */
114 struct x_display_info *x_display_list;
116 /* This is a list of cons cells, each of the form (NAME
117 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
118 x_display_list and in the same order. NAME is the name of the
119 frame. FONT-LIST-CACHE records previous values returned by
120 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
121 equivalent, which is implemented with a Lisp object, for the
122 display. */
124 Lisp_Object x_display_name_list;
126 /* This is display since Mac does not support multiple ones. */
127 struct mac_display_info one_mac_display_info;
129 /* Frame being updated by update_frame. This is declared in term.c.
130 This is set by update_begin and looked at by all the XT functions.
131 It is zero while not inside an update. In that case, the XT
132 functions assume that `selected_frame' is the frame to apply to. */
134 extern struct frame *updating_frame;
136 /* This is a frame waiting to be auto-raised, within XTread_socket. */
138 struct frame *pending_autoraise_frame;
140 /* Mouse movement.
142 Formerly, we used PointerMotionHintMask (in standard_event_mask)
143 so that we would have to call XQueryPointer after each MotionNotify
144 event to ask for another such event. However, this made mouse tracking
145 slow, and there was a bug that made it eventually stop.
147 Simply asking for MotionNotify all the time seems to work better.
149 In order to avoid asking for motion events and then throwing most
150 of them away or busy-polling the server for mouse positions, we ask
151 the server for pointer motion hints. This means that we get only
152 one event per group of mouse movements. "Groups" are delimited by
153 other kinds of events (focus changes and button clicks, for
154 example), or by XQueryPointer calls; when one of these happens, we
155 get another MotionNotify event the next time the mouse moves. This
156 is at least as efficient as getting motion events when mouse
157 tracking is on, and I suspect only negligibly worse when tracking
158 is off. */
160 /* Where the mouse was last time we reported a mouse event. */
162 static Rect last_mouse_glyph;
163 static FRAME_PTR last_mouse_glyph_frame;
165 /* The scroll bar in which the last X motion event occurred.
167 If the last X motion event occurred in a scroll bar, we set this so
168 XTmouse_position can know whether to report a scroll bar motion or
169 an ordinary motion.
171 If the last X motion event didn't occur in a scroll bar, we set
172 this to Qnil, to tell XTmouse_position to return an ordinary motion
173 event. */
175 static Lisp_Object last_mouse_scroll_bar;
177 /* This is a hack. We would really prefer that XTmouse_position would
178 return the time associated with the position it returns, but there
179 doesn't seem to be any way to wrest the time-stamp from the server
180 along with the position query. So, we just keep track of the time
181 of the last movement we received, and return that in hopes that
182 it's somewhat accurate. */
184 static Time last_mouse_movement_time;
186 struct scroll_bar *tracked_scroll_bar = NULL;
188 /* Incremented by XTread_socket whenever it really tries to read
189 events. */
191 #ifdef __STDC__
192 static int volatile input_signal_count;
193 #else
194 static int input_signal_count;
195 #endif
197 extern Lisp_Object Vsystem_name;
199 extern Lisp_Object Qeql;
201 /* A mask of extra modifier bits to put into every keyboard char. */
203 extern EMACS_INT extra_keyboard_modifiers;
205 /* The keysyms to use for the various modifiers. */
207 static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
209 extern int inhibit_window_system;
211 #if __MRC__ && !TARGET_API_MAC_CARBON
212 QDGlobals qd; /* QuickDraw global information structure. */
213 #endif
215 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
217 struct mac_display_info *mac_display_info_for_display (Display *);
218 static void x_update_window_end P_ ((struct window *, int, int));
219 int x_catch_errors P_ ((Display *));
220 void x_uncatch_errors P_ ((Display *, int));
221 void x_lower_frame P_ ((struct frame *));
222 void x_scroll_bar_clear P_ ((struct frame *));
223 int x_had_errors_p P_ ((Display *));
224 void x_wm_set_size_hint P_ ((struct frame *, long, int));
225 void x_raise_frame P_ ((struct frame *));
226 void x_set_window_size P_ ((struct frame *, int, int, int));
227 void x_wm_set_window_state P_ ((struct frame *, int));
228 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
229 void mac_initialize P_ ((void));
230 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
231 static int x_compute_min_glyph_bounds P_ ((struct frame *));
232 static void x_update_end P_ ((struct frame *));
233 static void XTframe_up_to_date P_ ((struct frame *));
234 static void XTset_terminal_modes P_ ((void));
235 static void XTreset_terminal_modes P_ ((void));
236 static void x_clear_frame P_ ((void));
237 static void frame_highlight P_ ((struct frame *));
238 static void frame_unhighlight P_ ((struct frame *));
239 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
240 static void mac_focus_changed P_ ((int, struct mac_display_info *,
241 struct frame *, struct input_event *));
242 static void x_detect_focus_change P_ ((struct mac_display_info *,
243 const EventRecord *,
244 struct input_event *));
245 static void XTframe_rehighlight P_ ((struct frame *));
246 static void x_frame_rehighlight P_ ((struct x_display_info *));
247 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
248 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
249 enum text_cursor_kinds));
251 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
252 static void x_flush P_ ((struct frame *f));
253 static void x_update_begin P_ ((struct frame *));
254 static void x_update_window_begin P_ ((struct window *));
255 static void x_after_update_window_line P_ ((struct glyph_row *));
256 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
257 enum scroll_bar_part *,
258 Lisp_Object *, Lisp_Object *,
259 unsigned long *));
261 static int is_emacs_window P_ ((WindowRef));
262 static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
263 static void XSetFont P_ ((Display *, GC, XFontStruct *));
265 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
266 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
267 #define GC_FONT(gc) ((gc)->xgcv.font)
268 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
270 #define CG_SET_FILL_COLOR(context, color) \
271 CGContextSetRGBFillColor (context, \
272 RED_FROM_ULONG (color) / 255.0f, \
273 GREEN_FROM_ULONG (color) / 255.0f, \
274 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
275 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
276 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
277 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
278 do { \
279 if (CGColorGetTypeID != NULL) \
280 CGContextSetFillColorWithColor (context, cg_color); \
281 else \
282 CG_SET_FILL_COLOR (context, color); \
283 } while (0)
284 #else
285 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
286 CGContextSetFillColorWithColor (context, cg_color)
287 #endif
288 #else
289 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
290 CG_SET_FILL_COLOR (context, color)
291 #endif
292 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
293 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
294 (gc)->cg_fore_color)
295 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
296 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
297 (gc)->cg_back_color)
300 #define CG_SET_STROKE_COLOR(context, color) \
301 CGContextSetRGBStrokeColor (context, \
302 RED_FROM_ULONG (color) / 255.0f, \
303 GREEN_FROM_ULONG (color) / 255.0f, \
304 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
305 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
306 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
307 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
308 do { \
309 if (CGColorGetTypeID != NULL) \
310 CGContextSetStrokeColorWithColor (context, cg_color); \
311 else \
312 CG_SET_STROKE_COLOR (context, color); \
313 } while (0)
314 #else
315 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
316 CGContextSetStrokeColorWithColor (context, cg_color)
317 #endif
318 #else
319 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
320 CG_SET_STROKE_COLOR (context, color)
321 #endif
322 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
323 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
324 (gc)->cg_fore_color)
326 #if USE_CG_DRAWING
327 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
329 /* Fringe bitmaps. */
331 static int max_fringe_bmp = 0;
332 static CGImageRef *fringe_bmp = 0;
334 static CGColorSpaceRef mac_cg_color_space_rgb;
335 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
336 static CGColorRef mac_cg_color_black;
337 #endif
339 static void
340 init_cg_color ()
342 mac_cg_color_space_rgb = CGColorSpaceCreateDeviceRGB ();
343 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
344 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
345 /* Don't check the availability of CGColorCreate; this symbol is
346 defined even in Mac OS X 10.1. */
347 if (CGColorGetTypeID != NULL)
348 #endif
350 float rgba[] = {0.0f, 0.0f, 0.0f, 1.0f};
352 mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba);
354 #endif
357 static CGContextRef
358 mac_begin_cg_clip (f, gc)
359 struct frame *f;
360 GC gc;
362 CGContextRef context = FRAME_CG_CONTEXT (f);
364 if (!context)
366 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
367 FRAME_CG_CONTEXT (f) = context;
370 CGContextSaveGState (context);
371 CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
372 CGContextScaleCTM (context, 1, -1);
373 if (gc && gc->n_clip_rects)
374 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
376 return context;
379 static void
380 mac_end_cg_clip (f)
381 struct frame *f;
383 CGContextRestoreGState (FRAME_CG_CONTEXT (f));
386 void
387 mac_prepare_for_quickdraw (f)
388 struct frame *f;
390 if (f == NULL)
392 Lisp_Object rest, frame;
393 FOR_EACH_FRAME (rest, frame)
394 if (FRAME_MAC_P (XFRAME (frame)))
395 mac_prepare_for_quickdraw (XFRAME (frame));
397 else
399 CGContextRef context = FRAME_CG_CONTEXT (f);
401 if (context)
403 CGContextSynchronize (context);
404 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
405 &FRAME_CG_CONTEXT (f));
409 #endif
411 static RgnHandle saved_port_clip_region = NULL;
413 static void
414 mac_begin_clip (f, gc)
415 struct frame *f;
416 GC gc;
418 static RgnHandle new_region = NULL;
420 if (saved_port_clip_region == NULL)
421 saved_port_clip_region = NewRgn ();
422 if (new_region == NULL)
423 new_region = NewRgn ();
425 #if USE_CG_DRAWING
426 mac_prepare_for_quickdraw (f);
427 #endif
428 SetPortWindowPort (FRAME_MAC_WINDOW (f));
430 if (gc->n_clip_rects)
432 GetClip (saved_port_clip_region);
433 SectRgn (saved_port_clip_region, gc->clip_region, new_region);
434 SetClip (new_region);
438 static void
439 mac_end_clip (gc)
440 GC gc;
442 if (gc->n_clip_rects)
443 SetClip (saved_port_clip_region);
447 /* X display function emulation */
449 /* Mac version of XDrawLine. */
451 static void
452 mac_draw_line (f, gc, x1, y1, x2, y2)
453 struct frame *f;
454 GC gc;
455 int x1, y1, x2, y2;
457 #if USE_CG_DRAWING
458 CGContextRef context;
459 float gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
461 if (y1 != y2)
462 gx1 += 0.5f, gx2 += 0.5f;
463 if (x1 != x2)
464 gy1 += 0.5f, gy2 += 0.5f;
466 context = mac_begin_cg_clip (f, gc);
467 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
468 CGContextBeginPath (context);
469 CGContextMoveToPoint (context, gx1, gy1);
470 CGContextAddLineToPoint (context, gx2, gy2);
471 CGContextClosePath (context);
472 CGContextStrokePath (context);
473 mac_end_cg_clip (f);
474 #else
475 if (x1 == x2)
477 if (y1 > y2)
478 y1--;
479 else if (y2 > y1)
480 y2--;
482 else if (y1 == y2)
484 if (x1 > x2)
485 x1--;
486 else
487 x2--;
490 mac_begin_clip (f, gc);
491 RGBForeColor (GC_FORE_COLOR (gc));
492 MoveTo (x1, y1);
493 LineTo (x2, y2);
494 mac_end_clip (gc);
495 #endif
498 /* Mac version of XDrawLine (to Pixmap). */
500 void
501 XDrawLine (display, p, gc, x1, y1, x2, y2)
502 Display *display;
503 Pixmap p;
504 GC gc;
505 int x1, y1, x2, y2;
507 CGrafPtr old_port;
508 GDHandle old_gdh;
510 if (x1 == x2)
512 if (y1 > y2)
513 y1--;
514 else if (y2 > y1)
515 y2--;
517 else if (y1 == y2)
519 if (x1 > x2)
520 x1--;
521 else
522 x2--;
525 GetGWorld (&old_port, &old_gdh);
526 SetGWorld (p, NULL);
528 RGBForeColor (GC_FORE_COLOR (gc));
530 LockPixels (GetGWorldPixMap (p));
531 MoveTo (x1, y1);
532 LineTo (x2, y2);
533 UnlockPixels (GetGWorldPixMap (p));
535 SetGWorld (old_port, old_gdh);
539 static void
540 mac_erase_rectangle (f, gc, x, y, width, height)
541 struct frame *f;
542 GC gc;
543 int x, y;
544 unsigned int width, height;
546 #if USE_CG_DRAWING
548 CGContextRef context;
550 context = mac_begin_cg_clip (f, gc);
551 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
552 CGContextFillRect (context, CGRectMake (x, y, width, height));
553 mac_end_cg_clip (f);
555 #else
557 Rect r;
559 mac_begin_clip (f, gc);
560 RGBBackColor (GC_BACK_COLOR (gc));
561 SetRect (&r, x, y, x + width, y + height);
562 EraseRect (&r);
563 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
564 mac_end_clip (gc);
566 #endif
570 /* Mac version of XClearArea. */
572 void
573 mac_clear_area (f, x, y, width, height)
574 struct frame *f;
575 int x, y;
576 unsigned int width, height;
578 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
581 /* Mac version of XClearWindow. */
583 static void
584 mac_clear_window (f)
585 struct frame *f;
587 #if USE_CG_DRAWING
589 CGContextRef context;
590 GC gc = FRAME_NORMAL_GC (f);
592 context = mac_begin_cg_clip (f, NULL);
593 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
594 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
595 FRAME_PIXEL_HEIGHT (f)));
596 mac_end_cg_clip (f);
598 #else /* !USE_CG_DRAWING */
599 SetPortWindowPort (FRAME_MAC_WINDOW (f));
601 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
603 #if TARGET_API_MAC_CARBON
605 Rect r;
607 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
608 EraseRect (&r);
610 #else /* not TARGET_API_MAC_CARBON */
611 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
612 #endif /* not TARGET_API_MAC_CARBON */
613 #endif
617 /* Mac replacement for XCopyArea. */
619 #if USE_CG_DRAWING
620 static void
621 mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
622 dest_x, dest_y, overlay_p)
623 CGImageRef image;
624 struct frame *f;
625 GC gc;
626 int src_x, src_y;
627 unsigned int width, height;
628 int dest_x, dest_y, overlay_p;
630 CGContextRef context;
631 float port_height = FRAME_PIXEL_HEIGHT (f);
632 CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
634 context = mac_begin_cg_clip (f, gc);
635 if (!overlay_p)
637 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
638 CGContextFillRect (context, dest_rect);
640 CGContextClipToRect (context, dest_rect);
641 CGContextScaleCTM (context, 1, -1);
642 CGContextTranslateCTM (context, 0, -port_height);
643 if (CGImageIsMask (image))
644 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
645 CGContextDrawImage (context,
646 CGRectMake (dest_x - src_x,
647 port_height - (dest_y - src_y
648 + CGImageGetHeight (image)),
649 CGImageGetWidth (image),
650 CGImageGetHeight (image)),
651 image);
652 mac_end_cg_clip (f);
655 #else /* !USE_CG_DRAWING */
657 static void
658 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
659 struct frame *f;
660 GC gc;
661 int x, y, width, height;
662 unsigned short *bits;
663 int overlay_p;
665 BitMap bitmap;
666 Rect r;
668 bitmap.rowBytes = sizeof(unsigned short);
669 bitmap.baseAddr = (char *)bits;
670 SetRect (&(bitmap.bounds), 0, 0, width, height);
672 mac_begin_clip (f, gc);
673 RGBForeColor (GC_FORE_COLOR (gc));
674 RGBBackColor (GC_BACK_COLOR (gc));
675 SetRect (&r, x, y, x + width, y + height);
676 #if TARGET_API_MAC_CARBON
678 CGrafPtr port;
680 GetPort (&port);
681 LockPortBits (port);
682 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
683 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
684 UnlockPortBits (port);
686 #else /* not TARGET_API_MAC_CARBON */
687 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
688 overlay_p ? srcOr : srcCopy, 0);
689 #endif /* not TARGET_API_MAC_CARBON */
690 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
691 mac_end_clip (gc);
693 #endif /* !USE_CG_DRAWING */
696 /* Mac replacement for XCreateBitmapFromBitmapData. */
698 static void
699 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
700 BitMap *bitmap;
701 char *bits;
702 int w, h;
704 static const unsigned char swap_nibble[16]
705 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
706 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
707 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
708 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
709 int i, j, w1;
710 char *p;
712 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
713 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
714 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
715 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
716 for (i = 0; i < h; i++)
718 p = bitmap->baseAddr + i * bitmap->rowBytes;
719 for (j = 0; j < w1; j++)
721 /* Bitswap XBM bytes to match how Mac does things. */
722 unsigned char c = *bits++;
723 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
724 | (swap_nibble[(c>>4) & 0xf]));
728 SetRect (&(bitmap->bounds), 0, 0, w, h);
732 static void
733 mac_free_bitmap (bitmap)
734 BitMap *bitmap;
736 xfree (bitmap->baseAddr);
740 Pixmap
741 XCreatePixmap (display, w, width, height, depth)
742 Display *display;
743 WindowRef w;
744 unsigned int width, height;
745 unsigned int depth;
747 Pixmap pixmap;
748 Rect r;
749 QDErr err;
751 SetPortWindowPort (w);
753 SetRect (&r, 0, 0, width, height);
754 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
755 if (depth == 1)
756 #endif
757 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
758 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
759 else
760 /* CreateCGImageFromPixMaps requires ARGB format. */
761 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
762 #endif
763 if (err != noErr)
764 return NULL;
765 return pixmap;
769 Pixmap
770 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
771 Display *display;
772 WindowRef w;
773 char *data;
774 unsigned int width, height;
775 unsigned long fg, bg;
776 unsigned int depth;
778 Pixmap pixmap;
779 BitMap bitmap;
780 CGrafPtr old_port;
781 GDHandle old_gdh;
782 static GC gc = NULL;
784 if (gc == NULL)
785 gc = XCreateGC (display, w, 0, NULL);
787 pixmap = XCreatePixmap (display, w, width, height, depth);
788 if (pixmap == NULL)
789 return NULL;
791 GetGWorld (&old_port, &old_gdh);
792 SetGWorld (pixmap, NULL);
793 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
794 XSetForeground (display, gc, fg);
795 XSetBackground (display, gc, bg);
796 RGBForeColor (GC_FORE_COLOR (gc));
797 RGBBackColor (GC_BACK_COLOR (gc));
798 LockPixels (GetGWorldPixMap (pixmap));
799 #if TARGET_API_MAC_CARBON
800 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
801 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
802 #else /* not TARGET_API_MAC_CARBON */
803 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
804 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
805 #endif /* not TARGET_API_MAC_CARBON */
806 UnlockPixels (GetGWorldPixMap (pixmap));
807 SetGWorld (old_port, old_gdh);
808 mac_free_bitmap (&bitmap);
810 return pixmap;
814 void
815 XFreePixmap (display, pixmap)
816 Display *display;
817 Pixmap pixmap;
819 DisposeGWorld (pixmap);
823 /* Mac replacement for XFillRectangle. */
825 static void
826 mac_fill_rectangle (f, gc, x, y, width, height)
827 struct frame *f;
828 GC gc;
829 int x, y;
830 unsigned int width, height;
832 #if USE_CG_DRAWING
833 CGContextRef context;
835 context = mac_begin_cg_clip (f, gc);
836 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
837 CGContextFillRect (context, CGRectMake (x, y, width, height));
838 mac_end_cg_clip (f);
839 #else
840 Rect r;
842 mac_begin_clip (f, gc);
843 RGBForeColor (GC_FORE_COLOR (gc));
844 SetRect (&r, x, y, x + width, y + height);
845 PaintRect (&r); /* using foreground color of gc */
846 mac_end_clip (gc);
847 #endif
851 /* Mac replacement for XDrawRectangle: dest is a window. */
853 static void
854 mac_draw_rectangle (f, gc, x, y, width, height)
855 struct frame *f;
856 GC gc;
857 int x, y;
858 unsigned int width, height;
860 #if USE_CG_DRAWING
861 CGContextRef context;
863 context = mac_begin_cg_clip (f, gc);
864 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
865 CGContextStrokeRect (context,
866 CGRectMake (x + 0.5f, y + 0.5f, width, height));
867 mac_end_cg_clip (f);
868 #else
869 Rect r;
871 mac_begin_clip (f, gc);
872 RGBForeColor (GC_FORE_COLOR (gc));
873 SetRect (&r, x, y, x + width + 1, y + height + 1);
874 FrameRect (&r); /* using foreground color of gc */
875 mac_end_clip (gc);
876 #endif
880 static void
881 mac_invert_rectangle (f, x, y, width, height)
882 struct frame *f;
883 int x, y;
884 unsigned int width, height;
886 Rect r;
888 #if USE_CG_DRAWING
889 mac_prepare_for_quickdraw (f);
890 #endif
891 SetPortWindowPort (FRAME_MAC_WINDOW (f));
893 SetRect (&r, x, y, x + width, y + height);
895 InvertRect (&r);
899 #if USE_ATSUI
900 static OSStatus
901 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
902 ConstUniCharArrayPtr text;
903 UniCharCount text_length;
904 ATSUStyle style;
905 ATSUTextLayout *text_layout;
907 OSStatus err;
908 static ATSUTextLayout saved_text_layout = NULL;
910 if (saved_text_layout == NULL)
912 static const UniCharCount lengths[] = {kATSUToTextEnd};
913 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
914 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
915 static ATSLineLayoutOptions line_layout =
916 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
917 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
918 | kATSLineUseQDRendering
919 #else
920 kATSLineIsDisplayOnly | kATSLineFractDisable
921 #endif
923 static const ATSUAttributeValuePtr values[] = {&line_layout};
925 err = ATSUCreateTextLayoutWithTextPtr (text,
926 kATSUFromTextBeginning,
927 kATSUToTextEnd,
928 text_length,
929 1, lengths, &style,
930 &saved_text_layout);
931 if (err == noErr)
932 err = ATSUSetLayoutControls (saved_text_layout,
933 sizeof (tags) / sizeof (tags[0]),
934 tags, sizes, values);
935 if (err == noErr)
936 err = ATSUSetTransientFontMatching (saved_text_layout, true);
938 else
940 err = ATSUSetRunStyle (saved_text_layout, style,
941 kATSUFromTextBeginning, kATSUToTextEnd);
942 if (err == noErr)
943 err = ATSUSetTextPointerLocation (saved_text_layout, text,
944 kATSUFromTextBeginning,
945 kATSUToTextEnd,
946 text_length);
949 if (err == noErr)
950 *text_layout = saved_text_layout;
951 return err;
955 static void
956 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
957 overstrike_p, bytes_per_char)
958 struct frame *f;
959 GC gc;
960 int x, y;
961 char *buf;
962 int nchars, bg_width, overstrike_p, bytes_per_char;
964 OSStatus err;
965 ATSUTextLayout text_layout;
967 xassert (bytes_per_char == 2);
969 #ifndef WORDS_BIG_ENDIAN
971 int i;
972 UniChar *text = (UniChar *)buf;
974 for (i = 0; i < nchars; i++)
975 text[i] = EndianU16_BtoN (text[i]);
977 #endif
978 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
979 nchars,
980 GC_FONT (gc)->mac_style,
981 &text_layout);
982 if (err != noErr)
983 return;
984 #ifdef MAC_OSX
985 if (!mac_use_core_graphics)
987 #endif
988 mac_begin_clip (f, gc);
989 RGBForeColor (GC_FORE_COLOR (gc));
990 if (bg_width)
992 Rect r;
994 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
995 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
996 RGBBackColor (GC_BACK_COLOR (gc));
997 EraseRect (&r);
998 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1000 MoveTo (x, y);
1001 ATSUDrawText (text_layout,
1002 kATSUFromTextBeginning, kATSUToTextEnd,
1003 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1004 if (overstrike_p)
1006 MoveTo (x + 1, y);
1007 ATSUDrawText (text_layout,
1008 kATSUFromTextBeginning, kATSUToTextEnd,
1009 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1011 mac_end_clip (gc);
1012 #ifdef MAC_OSX
1014 else
1016 static CGContextRef context;
1017 float port_height = FRAME_PIXEL_HEIGHT (f);
1018 static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
1019 static const ByteCount sizes[] = {sizeof (CGContextRef)};
1020 static const ATSUAttributeValuePtr values[] = {&context};
1022 #if USE_CG_DRAWING
1023 context = mac_begin_cg_clip (f, gc);
1024 #else
1025 CGrafPtr port;
1027 GetPort (&port);
1028 QDBeginCGContext (port, &context);
1029 if (gc->n_clip_rects || bg_width)
1031 CGContextTranslateCTM (context, 0, port_height);
1032 CGContextScaleCTM (context, 1, -1);
1033 if (gc->n_clip_rects)
1034 CGContextClipToRects (context, gc->clip_rects,
1035 gc->n_clip_rects);
1036 #endif
1037 if (bg_width)
1039 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1040 CGContextFillRect (context,
1041 CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
1042 bg_width,
1043 FONT_HEIGHT (GC_FONT (gc))));
1045 CGContextScaleCTM (context, 1, -1);
1046 CGContextTranslateCTM (context, 0, -port_height);
1047 #if !USE_CG_DRAWING
1049 #endif
1050 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1051 err = ATSUSetLayoutControls (text_layout,
1052 sizeof (tags) / sizeof (tags[0]),
1053 tags, sizes, values);
1054 if (err == noErr)
1056 ATSUDrawText (text_layout,
1057 kATSUFromTextBeginning, kATSUToTextEnd,
1058 Long2Fix (x), Long2Fix (port_height - y));
1059 if (overstrike_p)
1060 ATSUDrawText (text_layout,
1061 kATSUFromTextBeginning, kATSUToTextEnd,
1062 Long2Fix (x + 1), Long2Fix (port_height - y));
1064 #if USE_CG_DRAWING
1065 mac_end_cg_clip (f);
1066 context = NULL;
1067 #else
1068 CGContextSynchronize (context);
1069 QDEndCGContext (port, &context);
1070 #endif
1071 #if 0
1072 /* This doesn't work on Mac OS X 10.1. */
1073 ATSUClearLayoutControls (text_layout,
1074 sizeof (tags) / sizeof (tags[0]), tags);
1075 #else
1076 ATSUSetLayoutControls (text_layout,
1077 sizeof (tags) / sizeof (tags[0]),
1078 tags, sizes, values);
1079 #endif
1081 #endif /* MAC_OSX */
1083 #endif /* USE_ATSUI */
1086 static void
1087 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1088 overstrike_p, bytes_per_char)
1089 struct frame *f;
1090 GC gc;
1091 int x, y;
1092 char *buf;
1093 int nchars, bg_width, overstrike_p, bytes_per_char;
1095 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1096 UInt32 savedFlags;
1097 #endif
1099 mac_begin_clip (f, gc);
1100 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1101 if (mac_use_core_graphics)
1102 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
1103 #endif
1104 RGBForeColor (GC_FORE_COLOR (gc));
1105 #ifdef MAC_OS8
1106 if (bg_width)
1108 RGBBackColor (GC_BACK_COLOR (gc));
1109 TextMode (srcCopy);
1111 else
1112 TextMode (srcOr);
1113 #else
1114 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1115 because:
1116 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1117 into an offscreen graphics world first. So performance gain
1118 cannot be expected.)
1119 - It lowers rendering quality.
1120 - Some fonts leave garbage on cursor movement. */
1121 if (bg_width)
1123 Rect r;
1125 RGBBackColor (GC_BACK_COLOR (gc));
1126 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1127 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1128 EraseRect (&r);
1130 TextMode (srcOr);
1131 #endif
1132 TextFont (GC_FONT (gc)->mac_fontnum);
1133 TextSize (GC_FONT (gc)->mac_fontsize);
1134 TextFace (GC_FONT (gc)->mac_fontface);
1135 MoveTo (x, y);
1136 DrawText (buf, 0, nchars * bytes_per_char);
1137 if (overstrike_p)
1139 TextMode (srcOr);
1140 MoveTo (x + 1, y);
1141 DrawText (buf, 0, nchars * bytes_per_char);
1143 if (bg_width)
1144 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1145 mac_end_clip (gc);
1147 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1148 if (mac_use_core_graphics)
1149 SwapQDTextFlags(savedFlags);
1150 #endif
1154 static INLINE void
1155 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1156 overstrike_p, bytes_per_char)
1157 struct frame *f;
1158 GC gc;
1159 int x, y;
1160 char *buf;
1161 int nchars, bg_width, overstrike_p, bytes_per_char;
1163 #if USE_ATSUI
1164 if (GC_FONT (gc)->mac_style)
1165 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
1166 overstrike_p, bytes_per_char);
1167 else
1168 #endif /* USE_ATSUI */
1169 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1170 overstrike_p, bytes_per_char);
1174 /* Mac replacement for XDrawImageString. */
1176 static void
1177 mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1178 struct frame *f;
1179 GC gc;
1180 int x, y;
1181 char *buf;
1182 int nchars, bg_width, overstrike_p;
1184 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1185 overstrike_p, 1);
1189 /* Mac replacement for XDrawImageString16. */
1191 static void
1192 mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1193 struct frame *f;
1194 GC gc;
1195 int x, y;
1196 XChar2b *buf;
1197 int nchars, bg_width, overstrike_p;
1199 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
1200 overstrike_p, 2);
1204 /* Mac replacement for XQueryTextExtents, but takes a character. If
1205 STYLE is NULL, measurement is done by QuickDraw Text routines for
1206 the font of the current graphics port. If CG_GLYPH is not NULL,
1207 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1209 static OSStatus
1210 mac_query_char_extents (style, c,
1211 font_ascent_return, font_descent_return,
1212 overall_return, cg_glyph)
1213 #if USE_ATSUI
1214 ATSUStyle style;
1215 #else
1216 void *style;
1217 #endif
1218 int c;
1219 int *font_ascent_return, *font_descent_return;
1220 XCharStruct *overall_return;
1221 #if USE_CG_TEXT_DRAWING
1222 CGGlyph *cg_glyph;
1223 #else
1224 void *cg_glyph;
1225 #endif
1227 OSStatus err = noErr;
1228 int width;
1229 Rect char_bounds;
1231 #if USE_ATSUI
1232 if (style)
1234 ATSUTextLayout text_layout;
1235 UniChar ch = c;
1237 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
1238 if (err == noErr
1239 && (font_ascent_return || font_descent_return || overall_return))
1241 ATSTrapezoid glyph_bounds;
1243 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1244 kATSUFromTextBeginning, kATSUToTextEnd,
1245 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1246 kATSUseFractionalOrigins,
1247 #else
1248 kATSUseDeviceOrigins,
1249 #endif
1250 1, &glyph_bounds, NULL);
1251 if (err == noErr)
1253 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1254 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1256 width = Fix2Long (glyph_bounds.upperRight.x
1257 - glyph_bounds.upperLeft.x);
1258 if (font_ascent_return)
1259 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1260 if (font_descent_return)
1261 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1264 if (err == noErr && overall_return)
1266 err = ATSUMeasureTextImage (text_layout,
1267 kATSUFromTextBeginning, kATSUToTextEnd,
1268 0, 0, &char_bounds);
1269 if (err == noErr)
1270 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1271 #if USE_CG_TEXT_DRAWING
1272 if (err == noErr && cg_glyph)
1274 OSStatus err1;
1275 ATSUGlyphInfoArray glyph_info_array;
1276 ByteCount count = sizeof (ATSUGlyphInfoArray);
1278 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1279 kATSUToTextEnd, NULL, NULL, NULL);
1280 if (err1 == noErr)
1281 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1282 kATSUToTextEnd, &count,
1283 &glyph_info_array);
1284 if (err1 == noErr
1285 /* Make sure that we don't have to make layout
1286 adjustments. */
1287 && glyph_info_array.glyphs[0].deltaY == 0.0f
1288 && glyph_info_array.glyphs[0].idealX == 0.0f
1289 && glyph_info_array.glyphs[0].screenX == 0)
1291 xassert (glyph_info_array.glyphs[0].glyphID);
1292 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1294 else
1295 *cg_glyph = 0;
1297 #endif
1300 else
1301 #endif
1303 if (font_ascent_return || font_descent_return)
1305 FontInfo font_info;
1307 GetFontInfo (&font_info);
1308 if (font_ascent_return)
1309 *font_ascent_return = font_info.ascent;
1310 if (font_descent_return)
1311 *font_descent_return = font_info.descent;
1313 if (overall_return)
1315 char ch = c;
1317 width = CharWidth (ch);
1318 QDTextBounds (1, &ch, &char_bounds);
1319 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1323 return err;
1327 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1329 static int
1330 mac_text_extents_16 (font_struct, string, nchars, overall_return)
1331 XFontStruct *font_struct;
1332 XChar2b *string;
1333 int nchars;
1334 XCharStruct *overall_return;
1336 int i;
1337 short width = 0, lbearing = 0, rbearing = 0;
1338 XCharStruct *pcm;
1340 for (i = 0; i < nchars; i++)
1342 pcm = mac_per_char_metric (font_struct, string, 0);
1343 if (pcm == NULL)
1344 width += FONT_WIDTH (font_struct);
1345 else
1347 lbearing = min (lbearing, width + pcm->lbearing);
1348 rbearing = max (rbearing, width + pcm->rbearing);
1349 width += pcm->width;
1351 string++;
1354 overall_return->lbearing = lbearing;
1355 overall_return->rbearing = rbearing;
1356 overall_return->width = width;
1358 /* What's the meaning of the return value of XTextExtents16? */
1362 #if USE_CG_TEXT_DRAWING
1363 static int cg_text_anti_aliasing_threshold = 8;
1365 static void
1366 init_cg_text_anti_aliasing_threshold ()
1368 int threshold;
1369 Boolean valid_p;
1371 threshold =
1372 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1373 kCFPreferencesCurrentApplication,
1374 &valid_p);
1375 if (valid_p)
1376 cg_text_anti_aliasing_threshold = threshold;
1379 static int
1380 mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1381 struct frame *f;
1382 GC gc;
1383 int x, y;
1384 XChar2b *buf;
1385 int nchars, bg_width, overstrike_p;
1387 float port_height, gx, gy;
1388 int i;
1389 CGContextRef context;
1390 CGGlyph *glyphs;
1391 CGSize *advances;
1393 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1394 return 0;
1396 port_height = FRAME_PIXEL_HEIGHT (f);
1397 gx = x;
1398 gy = port_height - y;
1399 glyphs = (CGGlyph *)buf;
1400 advances = alloca (sizeof (CGSize) * nchars);
1401 if (advances == NULL)
1402 return 0;
1403 for (i = 0; i < nchars; i++)
1405 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1407 advances[i].width = pcm->width;
1408 advances[i].height = 0;
1409 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1410 buf++;
1413 #if USE_CG_DRAWING
1414 context = mac_begin_cg_clip (f, gc);
1415 #else
1416 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1417 if (gc->n_clip_rects || bg_width)
1419 CGContextTranslateCTM (context, 0, port_height);
1420 CGContextScaleCTM (context, 1, -1);
1421 if (gc->n_clip_rects)
1422 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1423 #endif
1424 if (bg_width)
1426 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1427 CGContextFillRect
1428 (context,
1429 CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
1430 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1432 CGContextScaleCTM (context, 1, -1);
1433 CGContextTranslateCTM (context, 0, -port_height);
1434 #if !USE_CG_DRAWING
1436 #endif
1437 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1438 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1439 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1440 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1441 CGContextSetShouldAntialias (context, false);
1442 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1443 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1444 if (CGContextShowGlyphsWithAdvances != NULL)
1445 #endif
1447 CGContextSetTextPosition (context, gx, gy);
1448 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1449 if (overstrike_p)
1451 CGContextSetTextPosition (context, gx + 1.0f, gy);
1452 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1455 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1456 else /* CGContextShowGlyphsWithAdvances == NULL */
1457 #endif
1458 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1459 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1461 for (i = 0; i < nchars; i++)
1463 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1464 if (overstrike_p)
1465 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
1466 gx += advances[i].width;
1469 #endif
1470 #if USE_CG_DRAWING
1471 mac_end_cg_clip (f);
1472 #else
1473 CGContextSynchronize (context);
1474 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1475 #endif
1477 return 1;
1479 #endif
1482 #if !USE_CG_DRAWING
1483 /* Mac replacement for XCopyArea: dest must be window. */
1485 static void
1486 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1487 Pixmap src;
1488 struct frame *f;
1489 GC gc;
1490 int src_x, src_y;
1491 unsigned int width, height;
1492 int dest_x, dest_y;
1494 Rect src_r, dest_r;
1496 mac_begin_clip (f, gc);
1498 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1499 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1501 ForeColor (blackColor);
1502 BackColor (whiteColor);
1504 LockPixels (GetGWorldPixMap (src));
1505 #if TARGET_API_MAC_CARBON
1507 CGrafPtr port;
1509 GetPort (&port);
1510 LockPortBits (port);
1511 CopyBits (GetPortBitMapForCopyBits (src),
1512 GetPortBitMapForCopyBits (port),
1513 &src_r, &dest_r, srcCopy, 0);
1514 UnlockPortBits (port);
1516 #else /* not TARGET_API_MAC_CARBON */
1517 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1518 &src_r, &dest_r, srcCopy, 0);
1519 #endif /* not TARGET_API_MAC_CARBON */
1520 UnlockPixels (GetGWorldPixMap (src));
1522 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1524 mac_end_clip (gc);
1528 static void
1529 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1530 width, height, dest_x, dest_y)
1531 Pixmap src, mask;
1532 struct frame *f;
1533 GC gc;
1534 int src_x, src_y;
1535 unsigned int width, height;
1536 int dest_x, dest_y;
1538 Rect src_r, dest_r;
1540 mac_begin_clip (f, gc);
1542 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1543 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1545 ForeColor (blackColor);
1546 BackColor (whiteColor);
1548 LockPixels (GetGWorldPixMap (src));
1549 LockPixels (GetGWorldPixMap (mask));
1550 #if TARGET_API_MAC_CARBON
1552 CGrafPtr port;
1554 GetPort (&port);
1555 LockPortBits (port);
1556 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1557 GetPortBitMapForCopyBits (port),
1558 &src_r, &src_r, &dest_r);
1559 UnlockPortBits (port);
1561 #else /* not TARGET_API_MAC_CARBON */
1562 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1563 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1564 #endif /* not TARGET_API_MAC_CARBON */
1565 UnlockPixels (GetGWorldPixMap (mask));
1566 UnlockPixels (GetGWorldPixMap (src));
1568 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1570 mac_end_clip (gc);
1572 #endif /* !USE_CG_DRAWING */
1575 /* Mac replacement for XCopyArea: used only for scrolling. */
1577 static void
1578 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1579 struct frame *f;
1580 GC gc;
1581 int src_x, src_y;
1582 unsigned int width, height;
1583 int dest_x, dest_y;
1585 #if TARGET_API_MAC_CARBON
1586 Rect src_r;
1587 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
1589 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1590 #if USE_CG_DRAWING
1591 mac_prepare_for_quickdraw (f);
1592 #endif
1593 ScrollWindowRect (FRAME_MAC_WINDOW (f),
1594 &src_r, dest_x - src_x, dest_y - src_y,
1595 kScrollWindowNoOptions, dummy);
1596 DisposeRgn (dummy);
1597 #else /* not TARGET_API_MAC_CARBON */
1598 Rect src_r, dest_r;
1599 WindowRef w = FRAME_MAC_WINDOW (f);
1601 mac_begin_clip (f, gc);
1603 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1604 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1606 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1607 color mapping in CopyBits. Otherwise, it will be slow. */
1608 ForeColor (blackColor);
1609 BackColor (whiteColor);
1610 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1612 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1614 mac_end_clip (gc);
1615 #endif /* not TARGET_API_MAC_CARBON */
1619 /* Mac replacement for XChangeGC. */
1621 static void
1622 XChangeGC (display, gc, mask, xgcv)
1623 Display *display;
1624 GC gc;
1625 unsigned long mask;
1626 XGCValues *xgcv;
1628 if (mask & GCForeground)
1629 XSetForeground (display, gc, xgcv->foreground);
1630 if (mask & GCBackground)
1631 XSetBackground (display, gc, xgcv->background);
1632 if (mask & GCFont)
1633 XSetFont (display, gc, xgcv->font);
1637 /* Mac replacement for XCreateGC. */
1640 XCreateGC (display, d, mask, xgcv)
1641 Display *display;
1642 void *d;
1643 unsigned long mask;
1644 XGCValues *xgcv;
1646 GC gc = xmalloc (sizeof (*gc));
1648 bzero (gc, sizeof (*gc));
1649 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1650 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1651 if (CGColorGetTypeID != NULL)
1652 #endif
1654 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
1655 CGColorRetain (gc->cg_fore_color);
1656 CGColorRetain (gc->cg_back_color);
1658 #endif
1659 XChangeGC (display, gc, mask, xgcv);
1661 return gc;
1665 /* Used in xfaces.c. */
1667 void
1668 XFreeGC (display, gc)
1669 Display *display;
1670 GC gc;
1672 if (gc->clip_region)
1673 DisposeRgn (gc->clip_region);
1674 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1675 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1676 if (CGColorGetTypeID != NULL)
1677 #endif
1679 CGColorRelease (gc->cg_fore_color);
1680 CGColorRelease (gc->cg_back_color);
1682 #endif
1683 xfree (gc);
1687 /* Mac replacement for XGetGCValues. */
1689 static void
1690 XGetGCValues (display, gc, mask, xgcv)
1691 Display *display;
1692 GC gc;
1693 unsigned long mask;
1694 XGCValues *xgcv;
1696 if (mask & GCForeground)
1697 xgcv->foreground = gc->xgcv.foreground;
1698 if (mask & GCBackground)
1699 xgcv->background = gc->xgcv.background;
1700 if (mask & GCFont)
1701 xgcv->font = gc->xgcv.font;
1705 /* Mac replacement for XSetForeground. */
1707 void
1708 XSetForeground (display, gc, color)
1709 Display *display;
1710 GC gc;
1711 unsigned long color;
1713 if (gc->xgcv.foreground != color)
1715 gc->xgcv.foreground = color;
1716 gc->fore_color.red = RED16_FROM_ULONG (color);
1717 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1718 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1719 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1720 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1721 if (CGColorGetTypeID != NULL)
1722 #endif
1724 CGColorRelease (gc->cg_fore_color);
1725 if (color == 0)
1727 gc->cg_fore_color = mac_cg_color_black;
1728 CGColorRetain (gc->cg_fore_color);
1730 else
1732 float rgba[4];
1734 rgba[0] = gc->fore_color.red / 65535.0f;
1735 rgba[1] = gc->fore_color.green / 65535.0f;
1736 rgba[2] = gc->fore_color.blue / 65535.0f;
1737 rgba[3] = 1.0f;
1738 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1741 #endif
1746 /* Mac replacement for XSetBackground. */
1748 void
1749 XSetBackground (display, gc, color)
1750 Display *display;
1751 GC gc;
1752 unsigned long color;
1754 if (gc->xgcv.background != color)
1756 gc->xgcv.background = color;
1757 gc->back_color.red = RED16_FROM_ULONG (color);
1758 gc->back_color.green = GREEN16_FROM_ULONG (color);
1759 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1760 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1761 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1762 if (CGColorGetTypeID != NULL)
1763 #endif
1765 CGColorRelease (gc->cg_back_color);
1766 if (color == 0)
1768 gc->cg_back_color = mac_cg_color_black;
1769 CGColorRetain (gc->cg_back_color);
1771 else
1773 float rgba[4];
1775 rgba[0] = gc->back_color.red / 65535.0f;
1776 rgba[1] = gc->back_color.green / 65535.0f;
1777 rgba[2] = gc->back_color.blue / 65535.0f;
1778 rgba[3] = 1.0f;
1779 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1782 #endif
1787 /* Mac replacement for XSetFont. */
1789 static void
1790 XSetFont (display, gc, font)
1791 Display *display;
1792 GC gc;
1793 XFontStruct *font;
1795 gc->xgcv.font = font;
1799 /* Mac replacement for XSetClipRectangles. */
1801 static void
1802 mac_set_clip_rectangles (display, gc, rectangles, n)
1803 Display *display;
1804 GC gc;
1805 Rect *rectangles;
1806 int n;
1808 int i;
1810 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1812 gc->n_clip_rects = n;
1813 if (n > 0)
1815 if (gc->clip_region == NULL)
1816 gc->clip_region = NewRgn ();
1817 RectRgn (gc->clip_region, rectangles);
1818 if (n > 1)
1820 RgnHandle region = NewRgn ();
1822 for (i = 1; i < n; i++)
1824 RectRgn (region, rectangles + i);
1825 UnionRgn (gc->clip_region, region, gc->clip_region);
1827 DisposeRgn (region);
1830 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1831 for (i = 0; i < n; i++)
1833 Rect *rect = rectangles + i;
1835 gc->clip_rects[i] = CGRectMake (rect->left, rect->top,
1836 rect->right - rect->left,
1837 rect->bottom - rect->top);
1839 #endif
1843 /* Mac replacement for XSetClipMask. */
1845 static INLINE void
1846 mac_reset_clip_rectangles (display, gc)
1847 Display *display;
1848 GC gc;
1850 gc->n_clip_rects = 0;
1854 /* Mac replacement for XSetWindowBackground. */
1856 void
1857 XSetWindowBackground (display, w, color)
1858 Display *display;
1859 WindowRef w;
1860 unsigned long color;
1862 #if !TARGET_API_MAC_CARBON
1863 AuxWinHandle aw_handle;
1864 CTabHandle ctab_handle;
1865 ColorSpecPtr ct_table;
1866 short ct_size;
1867 #endif
1868 RGBColor bg_color;
1870 bg_color.red = RED16_FROM_ULONG (color);
1871 bg_color.green = GREEN16_FROM_ULONG (color);
1872 bg_color.blue = BLUE16_FROM_ULONG (color);
1874 #if TARGET_API_MAC_CARBON
1875 SetWindowContentColor (w, &bg_color);
1876 #else
1877 if (GetAuxWin (w, &aw_handle))
1879 ctab_handle = (*aw_handle)->awCTable;
1880 HandToHand ((Handle *) &ctab_handle);
1881 ct_table = (*ctab_handle)->ctTable;
1882 ct_size = (*ctab_handle)->ctSize;
1883 while (ct_size > -1)
1885 if (ct_table->value == 0)
1887 ct_table->rgb = bg_color;
1888 CTabChanged (ctab_handle);
1889 SetWinColor (w, (WCTabHandle) ctab_handle);
1891 ct_size--;
1894 #endif
1897 /* Flush display of frame F, or of all frames if F is null. */
1899 static void
1900 x_flush (f)
1901 struct frame *f;
1903 #if TARGET_API_MAC_CARBON
1904 BLOCK_INPUT;
1905 #if USE_CG_DRAWING
1906 mac_prepare_for_quickdraw (f);
1907 #endif
1908 if (f)
1909 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1910 else
1911 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1912 UNBLOCK_INPUT;
1913 #endif
1917 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1918 Calls to XFlush should be unnecessary because the X output buffer
1919 is flushed automatically as needed by calls to XPending,
1920 XNextEvent, or XWindowEvent according to the XFlush man page.
1921 XTread_socket calls XPending. Removing XFlush improves
1922 performance. */
1924 #define XFlush(DISPLAY) (void) 0
1926 #if USE_CG_DRAWING
1927 static void
1928 mac_flush_display_optional (f)
1929 struct frame *f;
1931 BLOCK_INPUT;
1932 mac_prepare_for_quickdraw (f);
1933 UNBLOCK_INPUT;
1935 #endif
1937 /***********************************************************************
1938 Starting and ending an update
1939 ***********************************************************************/
1941 /* Start an update of frame F. This function is installed as a hook
1942 for update_begin, i.e. it is called when update_begin is called.
1943 This function is called prior to calls to x_update_window_begin for
1944 each window being updated. */
1946 static void
1947 x_update_begin (f)
1948 struct frame *f;
1950 #if TARGET_API_MAC_CARBON
1951 /* During update of a frame, availability of input events is
1952 periodically checked with ReceiveNextEvent if
1953 redisplay-dont-pause is nil. That normally flushes window buffer
1954 changes for every check, and thus screen update looks waving even
1955 if no input is available. So we disable screen updates during
1956 update of a frame. */
1957 BLOCK_INPUT;
1958 DisableScreenUpdates ();
1959 UNBLOCK_INPUT;
1960 #endif
1964 /* Start update of window W. Set the global variable updated_window
1965 to the window being updated and set output_cursor to the cursor
1966 position of W. */
1968 static void
1969 x_update_window_begin (w)
1970 struct window *w;
1972 struct frame *f = XFRAME (WINDOW_FRAME (w));
1973 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1975 updated_window = w;
1976 set_output_cursor (&w->cursor);
1978 BLOCK_INPUT;
1980 if (f == display_info->mouse_face_mouse_frame)
1982 /* Don't do highlighting for mouse motion during the update. */
1983 display_info->mouse_face_defer = 1;
1985 /* If F needs to be redrawn, simply forget about any prior mouse
1986 highlighting. */
1987 if (FRAME_GARBAGED_P (f))
1988 display_info->mouse_face_window = Qnil;
1990 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1991 their mouse_face_p flag set, which means that they are always
1992 unequal to rows in a desired matrix which never have that
1993 flag set. So, rows containing mouse-face glyphs are never
1994 scrolled, and we don't have to switch the mouse highlight off
1995 here to prevent it from being scrolled. */
1997 /* Can we tell that this update does not affect the window
1998 where the mouse highlight is? If so, no need to turn off.
1999 Likewise, don't do anything if the frame is garbaged;
2000 in that case, the frame's current matrix that we would use
2001 is all wrong, and we will redisplay that line anyway. */
2002 if (!NILP (display_info->mouse_face_window)
2003 && w == XWINDOW (display_info->mouse_face_window))
2005 int i;
2007 for (i = 0; i < w->desired_matrix->nrows; ++i)
2008 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
2009 break;
2011 if (i < w->desired_matrix->nrows)
2012 clear_mouse_face (display_info);
2014 #endif /* 0 */
2017 UNBLOCK_INPUT;
2021 /* Draw a vertical window border from (x,y0) to (x,y1) */
2023 static void
2024 mac_draw_vertical_window_border (w, x, y0, y1)
2025 struct window *w;
2026 int x, y0, y1;
2028 struct frame *f = XFRAME (WINDOW_FRAME (w));
2029 struct face *face;
2031 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
2032 if (face)
2033 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
2034 face->foreground);
2036 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
2039 /* End update of window W (which is equal to updated_window).
2041 Draw vertical borders between horizontally adjacent windows, and
2042 display W's cursor if CURSOR_ON_P is non-zero.
2044 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2045 glyphs in mouse-face were overwritten. In that case we have to
2046 make sure that the mouse-highlight is properly redrawn.
2048 W may be a menu bar pseudo-window in case we don't have X toolkit
2049 support. Such windows don't have a cursor, so don't display it
2050 here. */
2052 static void
2053 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
2054 struct window *w;
2055 int cursor_on_p, mouse_face_overwritten_p;
2057 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
2059 if (!w->pseudo_window_p)
2061 BLOCK_INPUT;
2063 if (cursor_on_p)
2064 display_and_set_cursor (w, 1, output_cursor.hpos,
2065 output_cursor.vpos,
2066 output_cursor.x, output_cursor.y);
2068 if (draw_window_fringes (w, 1))
2069 x_draw_vertical_border (w);
2071 UNBLOCK_INPUT;
2074 /* If a row with mouse-face was overwritten, arrange for
2075 XTframe_up_to_date to redisplay the mouse highlight. */
2076 if (mouse_face_overwritten_p)
2078 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
2079 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
2080 dpyinfo->mouse_face_window = Qnil;
2083 updated_window = NULL;
2087 /* End update of frame F. This function is installed as a hook in
2088 update_end. */
2090 static void
2091 x_update_end (f)
2092 struct frame *f;
2094 /* Mouse highlight may be displayed again. */
2095 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
2097 BLOCK_INPUT;
2098 #if TARGET_API_MAC_CARBON
2099 EnableScreenUpdates ();
2100 #endif
2101 XFlush (FRAME_MAC_DISPLAY (f));
2102 UNBLOCK_INPUT;
2106 /* This function is called from various places in xdisp.c whenever a
2107 complete update has been performed. The global variable
2108 updated_window is not available here. */
2110 static void
2111 XTframe_up_to_date (f)
2112 struct frame *f;
2114 if (FRAME_MAC_P (f))
2116 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2118 if (dpyinfo->mouse_face_deferred_gc
2119 || f == dpyinfo->mouse_face_mouse_frame)
2121 BLOCK_INPUT;
2122 if (dpyinfo->mouse_face_mouse_frame)
2123 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
2124 dpyinfo->mouse_face_mouse_x,
2125 dpyinfo->mouse_face_mouse_y);
2126 dpyinfo->mouse_face_deferred_gc = 0;
2127 UNBLOCK_INPUT;
2133 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2134 arrow bitmaps, or clear the fringes if no bitmaps are required
2135 before DESIRED_ROW is made current. The window being updated is
2136 found in updated_window. This function is called from
2137 update_window_line only if it is known that there are differences
2138 between bitmaps to be drawn between current row and DESIRED_ROW. */
2140 static void
2141 x_after_update_window_line (desired_row)
2142 struct glyph_row *desired_row;
2144 struct window *w = updated_window;
2145 struct frame *f;
2146 int width, height;
2148 xassert (w);
2150 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2151 desired_row->redraw_fringe_bitmaps_p = 1;
2153 /* When a window has disappeared, make sure that no rest of
2154 full-width rows stays visible in the internal border. Could
2155 check here if updated_window is the leftmost/rightmost window,
2156 but I guess it's not worth doing since vertically split windows
2157 are almost never used, internal border is rarely set, and the
2158 overhead is very small. */
2159 if (windows_or_buffers_changed
2160 && desired_row->full_width_p
2161 && (f = XFRAME (w->frame),
2162 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2163 width != 0)
2164 && (height = desired_row->visible_height,
2165 height > 0))
2167 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2169 /* Internal border is drawn below the tool bar. */
2170 if (WINDOWP (f->tool_bar_window)
2171 && w == XWINDOW (f->tool_bar_window))
2172 y -= width;
2174 BLOCK_INPUT;
2175 mac_clear_area (f, 0, y, width, height);
2176 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
2177 UNBLOCK_INPUT;
2182 /* Draw the bitmap WHICH in one of the left or right fringes of
2183 window W. ROW is the glyph row for which to display the bitmap; it
2184 determines the vertical position at which the bitmap has to be
2185 drawn. */
2187 static void
2188 x_draw_fringe_bitmap (w, row, p)
2189 struct window *w;
2190 struct glyph_row *row;
2191 struct draw_fringe_bitmap_params *p;
2193 struct frame *f = XFRAME (WINDOW_FRAME (w));
2194 Display *display = FRAME_MAC_DISPLAY (f);
2195 struct face *face = p->face;
2196 int rowY;
2197 int overlay_p = p->overlay_p;
2199 #ifdef MAC_OSX
2200 if (!overlay_p)
2202 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2204 #if 0 /* MAC_TODO: stipple */
2205 /* In case the same realized face is used for fringes and
2206 for something displayed in the text (e.g. face `region' on
2207 mono-displays, the fill style may have been changed to
2208 FillSolid in x_draw_glyph_string_background. */
2209 if (face->stipple)
2210 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2211 else
2212 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2213 #endif
2215 /* If the fringe is adjacent to the left (right) scroll bar of a
2216 leftmost (rightmost, respectively) window, then extend its
2217 background to the gap between the fringe and the bar. */
2218 if ((WINDOW_LEFTMOST_P (w)
2219 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2220 || (WINDOW_RIGHTMOST_P (w)
2221 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2223 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2225 if (sb_width > 0)
2227 int left = WINDOW_SCROLL_BAR_AREA_X (w);
2228 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2229 * FRAME_COLUMN_WIDTH (f));
2231 if (bx < 0
2232 && (left + width == p->x
2233 || p->x + p->wd == left))
2235 /* Bitmap fills the fringe and we need background
2236 extension. */
2237 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
2239 bx = p->x;
2240 nx = p->wd;
2241 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
2242 row->y));
2243 ny = row->visible_height;
2246 if (bx >= 0)
2248 if (left + width == bx)
2250 bx = left + sb_width;
2251 nx += width - sb_width;
2253 else if (bx + nx == left)
2254 nx += width - sb_width;
2259 if (bx >= 0)
2261 mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
2262 /* The fringe background has already been filled. */
2263 overlay_p = 1;
2266 #if 0 /* MAC_TODO: stipple */
2267 if (!face->stipple)
2268 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2269 #endif
2271 #endif /* MAC_OSX */
2273 /* Must clip because of partially visible lines. */
2274 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2275 if (p->y < rowY)
2277 /* Adjust position of "bottom aligned" bitmap on partially
2278 visible last row. */
2279 int oldY = row->y;
2280 int oldVH = row->visible_height;
2281 row->visible_height = p->h;
2282 row->y -= rowY - p->y;
2283 x_clip_to_row (w, row, -1, face->gc);
2284 row->y = oldY;
2285 row->visible_height = oldVH;
2287 else
2288 x_clip_to_row (w, row, -1, face->gc);
2290 #ifndef MAC_OSX
2291 if (p->bx >= 0 && !p->overlay_p)
2293 #if 0 /* MAC_TODO: stipple */
2294 /* In case the same realized face is used for fringes and
2295 for something displayed in the text (e.g. face `region' on
2296 mono-displays, the fill style may have been changed to
2297 FillSolid in x_draw_glyph_string_background. */
2298 if (face->stipple)
2299 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2300 else
2301 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2302 #endif
2304 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
2306 #if 0 /* MAC_TODO: stipple */
2307 if (!face->stipple)
2308 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2309 #endif
2311 #endif /* !MAC_OSX */
2313 if (p->which
2314 #if USE_CG_DRAWING
2315 && p->which < max_fringe_bmp
2316 #endif
2319 XGCValues gcv;
2321 XGetGCValues (display, face->gc, GCForeground, &gcv);
2322 XSetForeground (display, face->gc,
2323 (p->cursor_p
2324 ? (p->overlay_p ? face->background
2325 : f->output_data.mac->cursor_pixel)
2326 : face->foreground));
2327 #if USE_CG_DRAWING
2328 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
2329 p->wd, p->h, p->x, p->y, overlay_p);
2330 #else
2331 mac_draw_bitmap (f, face->gc, p->x, p->y,
2332 p->wd, p->h, p->bits + p->dh, overlay_p);
2333 #endif
2334 XSetForeground (display, face->gc, gcv.foreground);
2337 mac_reset_clip_rectangles (display, face->gc);
2340 #if USE_CG_DRAWING
2341 static void
2342 mac_define_fringe_bitmap (which, bits, h, wd)
2343 int which;
2344 unsigned short *bits;
2345 int h, wd;
2347 int i;
2348 CGDataProviderRef provider;
2350 if (which >= max_fringe_bmp)
2352 i = max_fringe_bmp;
2353 max_fringe_bmp = which + 20;
2354 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
2355 while (i < max_fringe_bmp)
2356 fringe_bmp[i++] = 0;
2359 for (i = 0; i < h; i++)
2360 bits[i] = ~bits[i];
2361 provider = CGDataProviderCreateWithData (NULL, bits,
2362 sizeof (unsigned short) * h, NULL);
2363 if (provider)
2365 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
2366 sizeof (unsigned short),
2367 provider, NULL, 0);
2368 CGDataProviderRelease (provider);
2372 static void
2373 mac_destroy_fringe_bitmap (which)
2374 int which;
2376 if (which >= max_fringe_bmp)
2377 return;
2379 if (fringe_bmp[which])
2380 CGImageRelease (fringe_bmp[which]);
2381 fringe_bmp[which] = 0;
2383 #endif
2386 /* This is called when starting Emacs and when restarting after
2387 suspend. When starting Emacs, no window is mapped. And nothing
2388 must be done to Emacs's own window if it is suspended (though that
2389 rarely happens). */
2391 static void
2392 XTset_terminal_modes ()
2396 /* This is called when exiting or suspending Emacs. Exiting will make
2397 the windows go away, and suspending requires no action. */
2399 static void
2400 XTreset_terminal_modes ()
2406 /***********************************************************************
2407 Display Iterator
2408 ***********************************************************************/
2410 /* Function prototypes of this page. */
2412 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
2413 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
2416 static void
2417 pcm_init (pcm, count)
2418 XCharStruct *pcm;
2419 int count;
2421 bzero (pcm, sizeof (XCharStruct) * count);
2422 while (--count >= 0)
2424 pcm->descent = PCM_INVALID;
2425 pcm++;
2429 static enum pcm_status
2430 pcm_get_status (pcm)
2431 const XCharStruct *pcm;
2433 int height = pcm->ascent + pcm->descent;
2435 /* Negative height means some special status. */
2436 return height >= 0 ? PCM_VALID : height;
2439 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2440 is not contained in the font. */
2442 static INLINE XCharStruct *
2443 x_per_char_metric (font, char2b)
2444 XFontStruct *font;
2445 XChar2b *char2b;
2447 /* The result metric information. */
2448 XCharStruct *pcm = NULL;
2450 xassert (font && char2b);
2452 #if USE_ATSUI
2453 if (font->mac_style)
2455 XCharStruct **row = font->bounds.rows + char2b->byte1;
2457 if (*row == NULL)
2459 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2460 pcm_init (*row, 0x100);
2462 pcm = *row + char2b->byte2;
2463 if (pcm_get_status (pcm) != PCM_VALID)
2465 BLOCK_INPUT;
2466 mac_query_char_extents (font->mac_style,
2467 (char2b->byte1 << 8) + char2b->byte2,
2468 NULL, NULL, pcm, NULL);
2469 UNBLOCK_INPUT;
2472 else
2474 #endif
2475 if (font->bounds.per_char != NULL)
2477 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2479 /* min_char_or_byte2 specifies the linear character index
2480 corresponding to the first element of the per_char array,
2481 max_char_or_byte2 is the index of the last character. A
2482 character with non-zero CHAR2B->byte1 is not in the font.
2483 A character with byte2 less than min_char_or_byte2 or
2484 greater max_char_or_byte2 is not in the font. */
2485 if (char2b->byte1 == 0
2486 && char2b->byte2 >= font->min_char_or_byte2
2487 && char2b->byte2 <= font->max_char_or_byte2)
2488 pcm = font->bounds.per_char
2489 + (char2b->byte2 - font->min_char_or_byte2);
2491 else
2493 /* If either min_byte1 or max_byte1 are nonzero, both
2494 min_char_or_byte2 and max_char_or_byte2 are less than
2495 256, and the 2-byte character index values corresponding
2496 to the per_char array element N (counting from 0) are:
2498 byte1 = N/D + min_byte1
2499 byte2 = N\D + min_char_or_byte2
2501 where:
2503 D = max_char_or_byte2 - min_char_or_byte2 + 1
2504 / = integer division
2505 \ = integer modulus */
2506 if (char2b->byte1 >= font->min_byte1
2507 && char2b->byte1 <= font->max_byte1
2508 && char2b->byte2 >= font->min_char_or_byte2
2509 && char2b->byte2 <= font->max_char_or_byte2)
2511 pcm = (font->bounds.per_char
2512 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2513 * (char2b->byte1 - font->min_byte1))
2514 + (char2b->byte2 - font->min_char_or_byte2));
2518 else
2520 /* If the per_char pointer is null, all glyphs between the first
2521 and last character indexes inclusive have the same
2522 information, as given by both min_bounds and max_bounds. */
2523 if (char2b->byte2 >= font->min_char_or_byte2
2524 && char2b->byte2 <= font->max_char_or_byte2)
2525 pcm = &font->max_bounds;
2527 #if USE_ATSUI
2529 #endif
2531 return ((pcm == NULL
2532 || (pcm->width == 0
2533 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2534 && (pcm->rbearing - pcm->lbearing) == 0
2535 #endif
2537 ? NULL : pcm);
2540 /* RIF:
2543 static XCharStruct *
2544 mac_per_char_metric (font, char2b, font_type)
2545 XFontStruct *font;
2546 XChar2b *char2b;
2547 int font_type;
2549 return x_per_char_metric (font, char2b);
2552 /* RIF:
2553 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2554 the two-byte form of C. Encoding is returned in *CHAR2B. */
2556 static int
2557 mac_encode_char (c, char2b, font_info, two_byte_p)
2558 int c;
2559 XChar2b *char2b;
2560 struct font_info *font_info;
2561 int *two_byte_p;
2563 int charset = CHAR_CHARSET (c);
2564 XFontStruct *font = font_info->font;
2566 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2567 This may be either a program in a special encoder language or a
2568 fixed encoding. */
2569 if (font_info->font_encoder)
2571 /* It's a program. */
2572 struct ccl_program *ccl = font_info->font_encoder;
2574 check_ccl_update (ccl);
2575 if (CHARSET_DIMENSION (charset) == 1)
2577 ccl->reg[0] = charset;
2578 ccl->reg[1] = char2b->byte2;
2579 ccl->reg[2] = -1;
2581 else
2583 ccl->reg[0] = charset;
2584 ccl->reg[1] = char2b->byte1;
2585 ccl->reg[2] = char2b->byte2;
2588 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2590 /* We assume that MSBs are appropriately set/reset by CCL
2591 program. */
2592 if (font->max_byte1 == 0) /* 1-byte font */
2593 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2594 else
2595 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2597 else if (font_info->encoding[charset])
2599 /* Fixed encoding scheme. See fontset.h for the meaning of the
2600 encoding numbers. */
2601 int enc = font_info->encoding[charset];
2603 if ((enc == 1 || enc == 2)
2604 && CHARSET_DIMENSION (charset) == 2)
2605 char2b->byte1 |= 0x80;
2607 if (enc == 1 || enc == 3)
2608 char2b->byte2 |= 0x80;
2610 if (enc == 4)
2612 int sjis1, sjis2;
2614 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2615 char2b->byte1 = sjis1;
2616 char2b->byte2 = sjis2;
2620 if (two_byte_p)
2621 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2623 return FONT_TYPE_UNKNOWN;
2628 /***********************************************************************
2629 Glyph display
2630 ***********************************************************************/
2634 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2635 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2636 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2637 int));
2638 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2639 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2640 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2641 static void x_draw_glyph_string P_ ((struct glyph_string *));
2642 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2643 static void x_set_cursor_gc P_ ((struct glyph_string *));
2644 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2645 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2646 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2647 unsigned long *, double, int));*/
2648 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2649 double, int, unsigned long));
2650 static void x_setup_relief_colors P_ ((struct glyph_string *));
2651 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2652 static void x_draw_image_relief P_ ((struct glyph_string *));
2653 static void x_draw_image_foreground P_ ((struct glyph_string *));
2654 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2655 int, int, int));
2656 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2657 int, int, int, int, int, int,
2658 Rect *));
2659 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2660 int, int, int, Rect *));
2662 #if GLYPH_DEBUG
2663 static void x_check_font P_ ((struct frame *, XFontStruct *));
2664 #endif
2667 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2668 face. */
2670 static void
2671 x_set_cursor_gc (s)
2672 struct glyph_string *s;
2674 if (s->font == FRAME_FONT (s->f)
2675 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2676 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2677 && !s->cmp)
2678 s->gc = s->f->output_data.mac->cursor_gc;
2679 else
2681 /* Cursor on non-default face: must merge. */
2682 XGCValues xgcv;
2683 unsigned long mask;
2685 xgcv.background = s->f->output_data.mac->cursor_pixel;
2686 xgcv.foreground = s->face->background;
2688 /* If the glyph would be invisible, try a different foreground. */
2689 if (xgcv.foreground == xgcv.background)
2690 xgcv.foreground = s->face->foreground;
2691 if (xgcv.foreground == xgcv.background)
2692 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2693 if (xgcv.foreground == xgcv.background)
2694 xgcv.foreground = s->face->foreground;
2696 /* Make sure the cursor is distinct from text in this face. */
2697 if (xgcv.background == s->face->background
2698 && xgcv.foreground == s->face->foreground)
2700 xgcv.background = s->face->foreground;
2701 xgcv.foreground = s->face->background;
2704 IF_DEBUG (x_check_font (s->f, s->font));
2705 xgcv.font = s->font;
2706 mask = GCForeground | GCBackground | GCFont;
2708 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2709 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2710 mask, &xgcv);
2711 else
2712 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2713 = XCreateGC (s->display, s->window, mask, &xgcv);
2715 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2720 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2722 static void
2723 x_set_mouse_face_gc (s)
2724 struct glyph_string *s;
2726 int face_id;
2727 struct face *face;
2729 /* What face has to be used last for the mouse face? */
2730 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2731 face = FACE_FROM_ID (s->f, face_id);
2732 if (face == NULL)
2733 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2735 if (s->first_glyph->type == CHAR_GLYPH)
2736 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2737 else
2738 face_id = FACE_FOR_CHAR (s->f, face, 0);
2739 s->face = FACE_FROM_ID (s->f, face_id);
2740 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2742 /* If font in this face is same as S->font, use it. */
2743 if (s->font == s->face->font)
2744 s->gc = s->face->gc;
2745 else
2747 /* Otherwise construct scratch_cursor_gc with values from FACE
2748 but font FONT. */
2749 XGCValues xgcv;
2750 unsigned long mask;
2752 xgcv.background = s->face->background;
2753 xgcv.foreground = s->face->foreground;
2754 IF_DEBUG (x_check_font (s->f, s->font));
2755 xgcv.font = s->font;
2756 mask = GCForeground | GCBackground | GCFont;
2758 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2759 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2760 mask, &xgcv);
2761 else
2762 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2763 = XCreateGC (s->display, s->window, mask, &xgcv);
2765 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2768 xassert (s->gc != 0);
2772 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2773 Faces to use in the mode line have already been computed when the
2774 matrix was built, so there isn't much to do, here. */
2776 static INLINE void
2777 x_set_mode_line_face_gc (s)
2778 struct glyph_string *s;
2780 s->gc = s->face->gc;
2784 /* Set S->gc of glyph string S for drawing that glyph string. Set
2785 S->stippled_p to a non-zero value if the face of S has a stipple
2786 pattern. */
2788 static INLINE void
2789 x_set_glyph_string_gc (s)
2790 struct glyph_string *s;
2792 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2794 if (s->hl == DRAW_NORMAL_TEXT)
2796 s->gc = s->face->gc;
2797 s->stippled_p = s->face->stipple != 0;
2799 else if (s->hl == DRAW_INVERSE_VIDEO)
2801 x_set_mode_line_face_gc (s);
2802 s->stippled_p = s->face->stipple != 0;
2804 else if (s->hl == DRAW_CURSOR)
2806 x_set_cursor_gc (s);
2807 s->stippled_p = 0;
2809 else if (s->hl == DRAW_MOUSE_FACE)
2811 x_set_mouse_face_gc (s);
2812 s->stippled_p = s->face->stipple != 0;
2814 else if (s->hl == DRAW_IMAGE_RAISED
2815 || s->hl == DRAW_IMAGE_SUNKEN)
2817 s->gc = s->face->gc;
2818 s->stippled_p = s->face->stipple != 0;
2820 else
2822 s->gc = s->face->gc;
2823 s->stippled_p = s->face->stipple != 0;
2826 /* GC must have been set. */
2827 xassert (s->gc != 0);
2831 /* Set clipping for output of glyph string S. S may be part of a mode
2832 line or menu if we don't have X toolkit support. */
2834 static INLINE void
2835 x_set_glyph_string_clipping (s)
2836 struct glyph_string *s;
2838 Rect rects[MAX_CLIP_RECTS];
2839 int n;
2841 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
2842 mac_set_clip_rectangles (s->display, s->gc, rects, n);
2846 /* RIF:
2847 Compute left and right overhang of glyph string S. If S is a glyph
2848 string for a composition, assume overhangs don't exist. */
2850 static void
2851 mac_compute_glyph_string_overhangs (s)
2852 struct glyph_string *s;
2854 if (!(s->cmp == NULL
2855 && s->first_glyph->type == CHAR_GLYPH))
2856 return;
2858 if (!s->two_byte_p
2859 #if USE_ATSUI
2860 || s->font->mac_style
2861 #endif
2864 XCharStruct cs;
2866 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2867 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2868 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2870 else
2872 Rect r;
2873 MacFontStruct *font = s->font;
2875 #if USE_CG_DRAWING
2876 mac_prepare_for_quickdraw (s->f);
2877 #endif
2878 SetPortWindowPort (FRAME_MAC_WINDOW (s->f));
2880 TextFont (font->mac_fontnum);
2881 TextSize (font->mac_fontsize);
2882 TextFace (font->mac_fontface);
2884 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2886 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2887 s->left_overhang = r.left < 0 ? -r.left : 0;
2892 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2894 static INLINE void
2895 x_clear_glyph_string_rect (s, x, y, w, h)
2896 struct glyph_string *s;
2897 int x, y, w, h;
2899 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
2903 /* Draw the background of glyph_string S. If S->background_filled_p
2904 is non-zero don't draw it. FORCE_P non-zero means draw the
2905 background even if it wouldn't be drawn normally. This is used
2906 when a string preceding S draws into the background of S, or S
2907 contains the first component of a composition. */
2909 static void
2910 x_draw_glyph_string_background (s, force_p)
2911 struct glyph_string *s;
2912 int force_p;
2914 /* Nothing to do if background has already been drawn or if it
2915 shouldn't be drawn in the first place. */
2916 if (!s->background_filled_p)
2918 int box_line_width = max (s->face->box_line_width, 0);
2920 #if 0 /* MAC_TODO: stipple */
2921 if (s->stippled_p)
2923 /* Fill background with a stipple pattern. */
2924 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2925 XFillRectangle (s->display, s->window, s->gc, s->x,
2926 s->y + box_line_width,
2927 s->background_width,
2928 s->height - 2 * box_line_width);
2929 XSetFillStyle (s->display, s->gc, FillSolid);
2930 s->background_filled_p = 1;
2932 else
2933 #endif
2934 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2935 || s->font_not_found_p
2936 || s->extends_to_end_of_line_p
2937 || force_p)
2939 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2940 s->background_width,
2941 s->height - 2 * box_line_width);
2942 s->background_filled_p = 1;
2948 /* Draw the foreground of glyph string S. */
2950 static void
2951 x_draw_glyph_string_foreground (s)
2952 struct glyph_string *s;
2954 int i, x, bg_width;
2956 /* If first glyph of S has a left box line, start drawing the text
2957 of S to the right of that box line. */
2958 if (s->face->box != FACE_NO_BOX
2959 && s->first_glyph->left_box_line_p)
2960 x = s->x + abs (s->face->box_line_width);
2961 else
2962 x = s->x;
2964 /* Draw characters of S as rectangles if S's font could not be
2965 loaded. */
2966 if (s->font_not_found_p)
2968 for (i = 0; i < s->nchars; ++i)
2970 struct glyph *g = s->first_glyph + i;
2971 mac_draw_rectangle (s->f, s->gc, x, s->y,
2972 g->pixel_width - 1, s->height - 1);
2973 x += g->pixel_width;
2976 else
2978 char *char1b = (char *) s->char2b;
2979 int boff = s->font_info->baseline_offset;
2981 if (s->font_info->vertical_centering)
2982 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2984 /* If we can use 8-bit functions, condense S->char2b. */
2985 if (!s->two_byte_p
2986 #if USE_ATSUI
2987 && GC_FONT (s->gc)->mac_style == NULL
2988 #endif
2990 for (i = 0; i < s->nchars; ++i)
2991 char1b[i] = s->char2b[i].byte2;
2993 /* Draw text with XDrawString if background has already been
2994 filled. Otherwise, use XDrawImageString. (Note that
2995 XDrawImageString is usually faster than XDrawString.) Always
2996 use XDrawImageString when drawing the cursor so that there is
2997 no chance that characters under a box cursor are invisible. */
2998 if (s->for_overlaps
2999 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3000 bg_width = 0; /* Corresponds to XDrawString. */
3001 else
3002 bg_width = s->background_width; /* Corresponds to XDrawImageString. */
3004 if (s->two_byte_p
3005 #if USE_ATSUI
3006 || GC_FONT (s->gc)->mac_style
3007 #endif
3009 #if USE_CG_TEXT_DRAWING
3010 if (!s->two_byte_p
3011 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
3012 s->char2b, s->nchars, bg_width,
3013 s->face->overstrike))
3015 else
3016 #endif
3017 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
3018 s->char2b, s->nchars, bg_width,
3019 s->face->overstrike);
3020 else
3021 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
3022 char1b, s->nchars, bg_width,
3023 s->face->overstrike);
3027 /* Draw the foreground of composite glyph string S. */
3029 static void
3030 x_draw_composite_glyph_string_foreground (s)
3031 struct glyph_string *s;
3033 int i, x;
3035 /* If first glyph of S has a left box line, start drawing the text
3036 of S to the right of that box line. */
3037 if (s->face->box != FACE_NO_BOX
3038 && s->first_glyph->left_box_line_p)
3039 x = s->x + abs (s->face->box_line_width);
3040 else
3041 x = s->x;
3043 /* S is a glyph string for a composition. S->gidx is the index of
3044 the first character drawn for glyphs of this composition.
3045 S->gidx == 0 means we are drawing the very first character of
3046 this composition. */
3048 /* Draw a rectangle for the composition if the font for the very
3049 first character of the composition could not be loaded. */
3050 if (s->font_not_found_p)
3052 if (s->gidx == 0)
3053 mac_draw_rectangle (s->f, s->gc, x, s->y,
3054 s->width - 1, s->height - 1);
3056 else
3058 for (i = 0; i < s->nchars; i++, ++s->gidx)
3059 mac_draw_image_string_16 (s->f, s->gc,
3060 x + s->cmp->offsets[s->gidx * 2],
3061 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3062 s->char2b + i, 1, 0, s->face->overstrike);
3067 #ifdef USE_X_TOOLKIT
3069 static struct frame *x_frame_of_widget P_ ((Widget));
3072 /* Return the frame on which widget WIDGET is used.. Abort if frame
3073 cannot be determined. */
3075 static struct frame *
3076 x_frame_of_widget (widget)
3077 Widget widget;
3079 struct x_display_info *dpyinfo;
3080 Lisp_Object tail;
3081 struct frame *f;
3083 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3085 /* Find the top-level shell of the widget. Note that this function
3086 can be called when the widget is not yet realized, so XtWindow
3087 (widget) == 0. That's the reason we can't simply use
3088 x_any_window_to_frame. */
3089 while (!XtIsTopLevelShell (widget))
3090 widget = XtParent (widget);
3092 /* Look for a frame with that top-level widget. Allocate the color
3093 on that frame to get the right gamma correction value. */
3094 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3095 if (GC_FRAMEP (XCAR (tail))
3096 && (f = XFRAME (XCAR (tail)),
3097 (f->output_data.nothing != 1
3098 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3099 && f->output_data.x->widget == widget)
3100 return f;
3102 abort ();
3106 /* Allocate the color COLOR->pixel on the screen and display of
3107 widget WIDGET in colormap CMAP. If an exact match cannot be
3108 allocated, try the nearest color available. Value is non-zero
3109 if successful. This is called from lwlib. */
3112 x_alloc_nearest_color_for_widget (widget, cmap, color)
3113 Widget widget;
3114 Colormap cmap;
3115 XColor *color;
3117 struct frame *f = x_frame_of_widget (widget);
3118 return x_alloc_nearest_color (f, cmap, color);
3122 #endif /* USE_X_TOOLKIT */
3124 #if 0 /* MAC_TODO */
3126 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3127 CMAP. If an exact match can't be allocated, try the nearest color
3128 available. Value is non-zero if successful. Set *COLOR to the
3129 color allocated. */
3132 x_alloc_nearest_color (f, cmap, color)
3133 struct frame *f;
3134 Colormap cmap;
3135 XColor *color;
3137 Display *display = FRAME_X_DISPLAY (f);
3138 Screen *screen = FRAME_X_SCREEN (f);
3139 int rc;
3141 gamma_correct (f, color);
3142 rc = XAllocColor (display, cmap, color);
3143 if (rc == 0)
3145 /* If we got to this point, the colormap is full, so we're going
3146 to try to get the next closest color. The algorithm used is
3147 a least-squares matching, which is what X uses for closest
3148 color matching with StaticColor visuals. */
3149 int nearest, i;
3150 unsigned long nearest_delta = ~0;
3151 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3152 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3154 for (i = 0; i < ncells; ++i)
3155 cells[i].pixel = i;
3156 XQueryColors (display, cmap, cells, ncells);
3158 for (nearest = i = 0; i < ncells; ++i)
3160 long dred = (color->red >> 8) - (cells[i].red >> 8);
3161 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3162 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3163 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3165 if (delta < nearest_delta)
3167 nearest = i;
3168 nearest_delta = delta;
3172 color->red = cells[nearest].red;
3173 color->green = cells[nearest].green;
3174 color->blue = cells[nearest].blue;
3175 rc = XAllocColor (display, cmap, color);
3178 #ifdef DEBUG_X_COLORS
3179 if (rc)
3180 register_color (color->pixel);
3181 #endif /* DEBUG_X_COLORS */
3183 return rc;
3187 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3188 It's necessary to do this instead of just using PIXEL directly to
3189 get color reference counts right. */
3191 unsigned long
3192 x_copy_color (f, pixel)
3193 struct frame *f;
3194 unsigned long pixel;
3196 XColor color;
3198 color.pixel = pixel;
3199 BLOCK_INPUT;
3200 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3201 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3202 UNBLOCK_INPUT;
3203 #ifdef DEBUG_X_COLORS
3204 register_color (pixel);
3205 #endif
3206 return color.pixel;
3210 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3211 It's necessary to do this instead of just using PIXEL directly to
3212 get color reference counts right. */
3214 unsigned long
3215 x_copy_dpy_color (dpy, cmap, pixel)
3216 Display *dpy;
3217 Colormap cmap;
3218 unsigned long pixel;
3220 XColor color;
3222 color.pixel = pixel;
3223 BLOCK_INPUT;
3224 XQueryColor (dpy, cmap, &color);
3225 XAllocColor (dpy, cmap, &color);
3226 UNBLOCK_INPUT;
3227 #ifdef DEBUG_X_COLORS
3228 register_color (pixel);
3229 #endif
3230 return color.pixel;
3233 #endif /* MAC_TODO */
3236 /* Brightness beyond which a color won't have its highlight brightness
3237 boosted.
3239 Nominally, highlight colors for `3d' faces are calculated by
3240 brightening an object's color by a constant scale factor, but this
3241 doesn't yield good results for dark colors, so for colors who's
3242 brightness is less than this value (on a scale of 0-255) have to
3243 use an additional additive factor.
3245 The value here is set so that the default menu-bar/mode-line color
3246 (grey75) will not have its highlights changed at all. */
3247 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3250 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3251 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3252 If this produces the same color as COLOR, try a color where all RGB
3253 values have DELTA added. Return the allocated color in *COLOR.
3254 DISPLAY is the X display, CMAP is the colormap to operate on.
3255 Value is non-zero if successful. */
3257 static int
3258 mac_alloc_lighter_color (f, color, factor, delta)
3259 struct frame *f;
3260 unsigned long *color;
3261 double factor;
3262 int delta;
3264 unsigned long new;
3265 long bright;
3267 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3268 delta /= 256;
3270 /* Change RGB values by specified FACTOR. Avoid overflow! */
3271 xassert (factor >= 0);
3272 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3273 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3274 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3276 /* Calculate brightness of COLOR. */
3277 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
3278 + BLUE_FROM_ULONG (*color)) / 6;
3280 /* We only boost colors that are darker than
3281 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3282 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3283 /* Make an additive adjustment to NEW, because it's dark enough so
3284 that scaling by FACTOR alone isn't enough. */
3286 /* How far below the limit this color is (0 - 1, 1 being darker). */
3287 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3288 /* The additive adjustment. */
3289 int min_delta = delta * dimness * factor / 2;
3291 if (factor < 1)
3292 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
3293 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
3294 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
3295 else
3296 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
3297 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
3298 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
3301 if (new == *color)
3302 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3303 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3304 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3306 /* MAC_TODO: Map to palette and retry with delta if same? */
3307 /* MAC_TODO: Free colors (if using palette)? */
3309 if (new == *color)
3310 return 0;
3312 *color = new;
3314 return 1;
3318 /* Set up the foreground color for drawing relief lines of glyph
3319 string S. RELIEF is a pointer to a struct relief containing the GC
3320 with which lines will be drawn. Use a color that is FACTOR or
3321 DELTA lighter or darker than the relief's background which is found
3322 in S->f->output_data.x->relief_background. If such a color cannot
3323 be allocated, use DEFAULT_PIXEL, instead. */
3325 static void
3326 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3327 struct frame *f;
3328 struct relief *relief;
3329 double factor;
3330 int delta;
3331 unsigned long default_pixel;
3333 XGCValues xgcv;
3334 struct mac_output *di = f->output_data.mac;
3335 unsigned long mask = GCForeground;
3336 unsigned long pixel;
3337 unsigned long background = di->relief_background;
3338 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3340 /* MAC_TODO: Free colors (if using palette)? */
3342 /* Allocate new color. */
3343 xgcv.foreground = default_pixel;
3344 pixel = background;
3345 if (dpyinfo->n_planes != 1
3346 && mac_alloc_lighter_color (f, &pixel, factor, delta))
3348 relief->allocated_p = 1;
3349 xgcv.foreground = relief->pixel = pixel;
3352 if (relief->gc == 0)
3354 #if 0 /* MAC_TODO: stipple */
3355 xgcv.stipple = dpyinfo->gray;
3356 mask |= GCStipple;
3357 #endif
3358 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3360 else
3361 XChangeGC (NULL, relief->gc, mask, &xgcv);
3365 /* Set up colors for the relief lines around glyph string S. */
3367 static void
3368 x_setup_relief_colors (s)
3369 struct glyph_string *s;
3371 struct mac_output *di = s->f->output_data.mac;
3372 unsigned long color;
3374 if (s->face->use_box_color_for_shadows_p)
3375 color = s->face->box_color;
3376 else if (s->first_glyph->type == IMAGE_GLYPH
3377 && s->img->pixmap
3378 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3379 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3380 else
3382 XGCValues xgcv;
3384 /* Get the background color of the face. */
3385 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3386 color = xgcv.background;
3389 if (di->white_relief.gc == 0
3390 || color != di->relief_background)
3392 di->relief_background = color;
3393 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3394 WHITE_PIX_DEFAULT (s->f));
3395 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3396 BLACK_PIX_DEFAULT (s->f));
3401 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3402 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3403 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3404 relief. LEFT_P non-zero means draw a relief on the left side of
3405 the rectangle. RIGHT_P non-zero means draw a relief on the right
3406 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3407 when drawing. */
3409 static void
3410 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3411 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
3412 struct frame *f;
3413 int left_x, top_y, right_x, bottom_y, width;
3414 int top_p, bot_p, left_p, right_p, raised_p;
3415 Rect *clip_rect;
3417 Display *dpy = FRAME_MAC_DISPLAY (f);
3418 int i;
3419 GC gc;
3421 if (raised_p)
3422 gc = f->output_data.mac->white_relief.gc;
3423 else
3424 gc = f->output_data.mac->black_relief.gc;
3425 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3427 /* Top. */
3428 if (top_p)
3429 for (i = 0; i < width; ++i)
3430 mac_draw_line (f, gc,
3431 left_x + i * left_p, top_y + i,
3432 right_x + 1 - i * right_p, top_y + i);
3434 /* Left. */
3435 if (left_p)
3436 for (i = 0; i < width; ++i)
3437 mac_draw_line (f, gc,
3438 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3440 mac_reset_clip_rectangles (dpy, gc);
3441 if (raised_p)
3442 gc = f->output_data.mac->black_relief.gc;
3443 else
3444 gc = f->output_data.mac->white_relief.gc;
3445 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3447 /* Bottom. */
3448 if (bot_p)
3449 for (i = 0; i < width; ++i)
3450 mac_draw_line (f, gc,
3451 left_x + i * left_p, bottom_y - i,
3452 right_x + 1 - i * right_p, bottom_y - i);
3454 /* Right. */
3455 if (right_p)
3456 for (i = 0; i < width; ++i)
3457 mac_draw_line (f, gc,
3458 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3460 mac_reset_clip_rectangles (dpy, gc);
3464 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3465 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3466 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3467 left side of the rectangle. RIGHT_P non-zero means draw a line
3468 on the right side of the rectangle. CLIP_RECT is the clipping
3469 rectangle to use when drawing. */
3471 static void
3472 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3473 left_p, right_p, clip_rect)
3474 struct glyph_string *s;
3475 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3476 Rect *clip_rect;
3478 XGCValues xgcv;
3480 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3481 XSetForeground (s->display, s->gc, s->face->box_color);
3482 mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1);
3484 /* Top. */
3485 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3486 right_x - left_x + 1, width);
3488 /* Left. */
3489 if (left_p)
3490 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3491 width, bottom_y - top_y + 1);
3493 /* Bottom. */
3494 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
3495 right_x - left_x + 1, width);
3497 /* Right. */
3498 if (right_p)
3499 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
3500 top_y, width, bottom_y - top_y + 1);
3502 XSetForeground (s->display, s->gc, xgcv.foreground);
3503 mac_reset_clip_rectangles (s->display, s->gc);
3507 /* Draw a box around glyph string S. */
3509 static void
3510 x_draw_glyph_string_box (s)
3511 struct glyph_string *s;
3513 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3514 int left_p, right_p;
3515 struct glyph *last_glyph;
3516 Rect clip_rect;
3518 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3519 ? WINDOW_RIGHT_EDGE_X (s->w)
3520 : window_box_right (s->w, s->area));
3522 /* The glyph that may have a right box line. */
3523 last_glyph = (s->cmp || s->img
3524 ? s->first_glyph
3525 : s->first_glyph + s->nchars - 1);
3527 width = abs (s->face->box_line_width);
3528 raised_p = s->face->box == FACE_RAISED_BOX;
3529 left_x = s->x;
3530 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3531 ? last_x - 1
3532 : min (last_x, s->x + s->background_width) - 1);
3533 top_y = s->y;
3534 bottom_y = top_y + s->height - 1;
3536 left_p = (s->first_glyph->left_box_line_p
3537 || (s->hl == DRAW_MOUSE_FACE
3538 && (s->prev == NULL
3539 || s->prev->hl != s->hl)));
3540 right_p = (last_glyph->right_box_line_p
3541 || (s->hl == DRAW_MOUSE_FACE
3542 && (s->next == NULL
3543 || s->next->hl != s->hl)));
3545 get_glyph_string_clip_rect (s, &clip_rect);
3547 if (s->face->box == FACE_SIMPLE_BOX)
3548 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3549 left_p, right_p, &clip_rect);
3550 else
3552 x_setup_relief_colors (s);
3553 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3554 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
3559 /* Draw foreground of image glyph string S. */
3561 static void
3562 x_draw_image_foreground (s)
3563 struct glyph_string *s;
3565 int x = s->x;
3566 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3568 /* If first glyph of S has a left box line, start drawing it to the
3569 right of that line. */
3570 if (s->face->box != FACE_NO_BOX
3571 && s->first_glyph->left_box_line_p
3572 && s->slice.x == 0)
3573 x += abs (s->face->box_line_width);
3575 /* If there is a margin around the image, adjust x- and y-position
3576 by that margin. */
3577 if (s->slice.x == 0)
3578 x += s->img->hmargin;
3579 if (s->slice.y == 0)
3580 y += s->img->vmargin;
3582 if (s->img->pixmap)
3584 x_set_glyph_string_clipping (s);
3586 #if USE_CG_DRAWING
3587 mac_draw_cg_image (s->img->data.ptr_val,
3588 s->f, s->gc, s->slice.x, s->slice.y,
3589 s->slice.width, s->slice.height, x, y, 1);
3590 #endif
3591 if (s->img->mask)
3592 #if !USE_CG_DRAWING
3593 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3594 s->f, s->gc, s->slice.x, s->slice.y,
3595 s->slice.width, s->slice.height, x, y);
3596 #else
3598 #endif
3599 else
3601 #if !USE_CG_DRAWING
3602 mac_copy_area (s->img->pixmap,
3603 s->f, s->gc, s->slice.x, s->slice.y,
3604 s->slice.width, s->slice.height, x, y);
3605 #endif
3607 /* When the image has a mask, we can expect that at
3608 least part of a mouse highlight or a block cursor will
3609 be visible. If the image doesn't have a mask, make
3610 a block cursor visible by drawing a rectangle around
3611 the image. I believe it's looking better if we do
3612 nothing here for mouse-face. */
3613 if (s->hl == DRAW_CURSOR)
3615 int r = s->img->relief;
3616 if (r < 0) r = -r;
3617 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
3618 s->slice.width + r*2 - 1,
3619 s->slice.height + r*2 - 1);
3623 else
3624 /* Draw a rectangle if image could not be loaded. */
3625 mac_draw_rectangle (s->f, s->gc, x, y,
3626 s->slice.width - 1, s->slice.height - 1);
3630 /* Draw a relief around the image glyph string S. */
3632 static void
3633 x_draw_image_relief (s)
3634 struct glyph_string *s;
3636 int x0, y0, x1, y1, thick, raised_p;
3637 Rect r;
3638 int x = s->x;
3639 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3641 /* If first glyph of S has a left box line, start drawing it to the
3642 right of that line. */
3643 if (s->face->box != FACE_NO_BOX
3644 && s->first_glyph->left_box_line_p
3645 && s->slice.x == 0)
3646 x += abs (s->face->box_line_width);
3648 /* If there is a margin around the image, adjust x- and y-position
3649 by that margin. */
3650 if (s->slice.x == 0)
3651 x += s->img->hmargin;
3652 if (s->slice.y == 0)
3653 y += s->img->vmargin;
3655 if (s->hl == DRAW_IMAGE_SUNKEN
3656 || s->hl == DRAW_IMAGE_RAISED)
3658 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3659 raised_p = s->hl == DRAW_IMAGE_RAISED;
3661 else
3663 thick = abs (s->img->relief);
3664 raised_p = s->img->relief > 0;
3667 x0 = x - thick;
3668 y0 = y - thick;
3669 x1 = x + s->slice.width + thick - 1;
3670 y1 = y + s->slice.height + thick - 1;
3672 x_setup_relief_colors (s);
3673 get_glyph_string_clip_rect (s, &r);
3674 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3675 s->slice.y == 0,
3676 s->slice.y + s->slice.height == s->img->height,
3677 s->slice.x == 0,
3678 s->slice.x + s->slice.width == s->img->width,
3679 &r);
3683 /* Draw part of the background of glyph string S. X, Y, W, and H
3684 give the rectangle to draw. */
3686 static void
3687 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3688 struct glyph_string *s;
3689 int x, y, w, h;
3691 #if 0 /* MAC_TODO: stipple */
3692 if (s->stippled_p)
3694 /* Fill background with a stipple pattern. */
3695 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3696 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3697 XSetFillStyle (s->display, s->gc, FillSolid);
3699 else
3700 #endif /* MAC_TODO */
3701 x_clear_glyph_string_rect (s, x, y, w, h);
3705 /* Draw image glyph string S.
3707 s->y
3708 s->x +-------------------------
3709 | s->face->box
3711 | +-------------------------
3712 | | s->img->margin
3714 | | +-------------------
3715 | | | the image
3719 static void
3720 x_draw_image_glyph_string (s)
3721 struct glyph_string *s;
3723 int x, y;
3724 int box_line_hwidth = abs (s->face->box_line_width);
3725 int box_line_vwidth = max (s->face->box_line_width, 0);
3726 int height;
3728 height = s->height - 2 * box_line_vwidth;
3731 /* Fill background with face under the image. Do it only if row is
3732 taller than image or if image has a clip mask to reduce
3733 flickering. */
3734 s->stippled_p = s->face->stipple != 0;
3735 if (height > s->slice.height
3736 || s->img->hmargin
3737 || s->img->vmargin
3738 || s->img->mask
3739 || s->img->pixmap == 0
3740 || s->width != s->background_width)
3742 x = s->x;
3743 if (s->first_glyph->left_box_line_p
3744 && s->slice.x == 0)
3745 x += box_line_hwidth;
3747 y = s->y;
3748 if (s->slice.y == 0)
3749 y += box_line_vwidth;
3751 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3753 s->background_filled_p = 1;
3756 /* Draw the foreground. */
3757 x_draw_image_foreground (s);
3759 /* If we must draw a relief around the image, do it. */
3760 if (s->img->relief
3761 || s->hl == DRAW_IMAGE_RAISED
3762 || s->hl == DRAW_IMAGE_SUNKEN)
3763 x_draw_image_relief (s);
3767 /* Draw stretch glyph string S. */
3769 static void
3770 x_draw_stretch_glyph_string (s)
3771 struct glyph_string *s;
3773 xassert (s->first_glyph->type == STRETCH_GLYPH);
3774 s->stippled_p = s->face->stipple != 0;
3776 if (s->hl == DRAW_CURSOR
3777 && !x_stretch_cursor_p)
3779 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3780 as wide as the stretch glyph. */
3781 int width, background_width = s->background_width;
3782 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3784 if (x < left_x)
3786 background_width -= left_x - x;
3787 x = left_x;
3789 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3791 /* Draw cursor. */
3792 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3794 /* Clear rest using the GC of the original non-cursor face. */
3795 if (width < background_width)
3797 int y = s->y;
3798 int w = background_width - width, h = s->height;
3799 Rect r;
3800 GC gc;
3802 x += width;
3803 if (s->row->mouse_face_p
3804 && cursor_in_mouse_face_p (s->w))
3806 x_set_mouse_face_gc (s);
3807 gc = s->gc;
3809 else
3810 gc = s->face->gc;
3812 get_glyph_string_clip_rect (s, &r);
3813 mac_set_clip_rectangles (s->display, gc, &r, 1);
3815 #if 0 /* MAC_TODO: stipple */
3816 if (s->face->stipple)
3818 /* Fill background with a stipple pattern. */
3819 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3820 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3821 XSetFillStyle (s->display, gc, FillSolid);
3823 else
3824 #endif /* MAC_TODO */
3825 mac_erase_rectangle (s->f, gc, x, y, w, h);
3828 else if (!s->background_filled_p)
3830 int background_width = s->background_width;
3831 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3833 /* Don't draw into left margin, fringe or scrollbar area
3834 except for header line and mode line. */
3835 if (x < left_x && !s->row->mode_line_p)
3837 background_width -= left_x - x;
3838 x = left_x;
3840 if (background_width > 0)
3841 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3844 s->background_filled_p = 1;
3848 /* Draw glyph string S. */
3850 static void
3851 x_draw_glyph_string (s)
3852 struct glyph_string *s;
3854 int relief_drawn_p = 0;
3856 /* If S draws into the background of its successor that does not
3857 draw a cursor, draw the background of the successor first so that
3858 S can draw into it. This makes S->next use XDrawString instead
3859 of XDrawImageString. */
3860 if (s->next && s->right_overhang && !s->for_overlaps
3861 && s->next->hl != DRAW_CURSOR)
3863 xassert (s->next->img == NULL);
3864 x_set_glyph_string_gc (s->next);
3865 x_set_glyph_string_clipping (s->next);
3866 x_draw_glyph_string_background (s->next, 1);
3869 /* Set up S->gc, set clipping and draw S. */
3870 x_set_glyph_string_gc (s);
3872 /* Draw relief (if any) in advance for char/composition so that the
3873 glyph string can be drawn over it. */
3874 if (!s->for_overlaps
3875 && s->face->box != FACE_NO_BOX
3876 && (s->first_glyph->type == CHAR_GLYPH
3877 || s->first_glyph->type == COMPOSITE_GLYPH))
3880 x_set_glyph_string_clipping (s);
3881 x_draw_glyph_string_background (s, 1);
3882 x_draw_glyph_string_box (s);
3883 x_set_glyph_string_clipping (s);
3884 relief_drawn_p = 1;
3886 else
3887 x_set_glyph_string_clipping (s);
3889 switch (s->first_glyph->type)
3891 case IMAGE_GLYPH:
3892 x_draw_image_glyph_string (s);
3893 break;
3895 case STRETCH_GLYPH:
3896 x_draw_stretch_glyph_string (s);
3897 break;
3899 case CHAR_GLYPH:
3900 if (s->for_overlaps)
3901 s->background_filled_p = 1;
3902 else
3903 x_draw_glyph_string_background (s, 0);
3904 x_draw_glyph_string_foreground (s);
3905 break;
3907 case COMPOSITE_GLYPH:
3908 if (s->for_overlaps || s->gidx > 0)
3909 s->background_filled_p = 1;
3910 else
3911 x_draw_glyph_string_background (s, 1);
3912 x_draw_composite_glyph_string_foreground (s);
3913 break;
3915 default:
3916 abort ();
3919 if (!s->for_overlaps)
3921 /* Draw underline. */
3922 if (s->face->underline_p)
3924 unsigned long tem, h;
3925 int y;
3927 #if 0
3928 /* Get the underline thickness. Default is 1 pixel. */
3929 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3930 #endif
3931 h = 1;
3933 y = s->y + s->height - h;
3934 if (!x_underline_at_descent_line)
3936 /* Get the underline position. This is the recommended
3937 vertical offset in pixels from the baseline to the top of
3938 the underline. This is a signed value according to the
3939 specs, and its default is
3941 ROUND ((maximum descent) / 2), with
3942 ROUND(x) = floor (x + 0.5) */
3944 #if 0
3945 if (x_use_underline_position_properties
3946 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
3947 y = s->ybase + (long) tem;
3948 else
3949 #endif
3950 if (s->face->font)
3951 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
3954 if (s->face->underline_defaulted_p)
3955 mac_fill_rectangle (s->f, s->gc, s->x, y,
3956 s->background_width, h);
3957 else
3959 XGCValues xgcv;
3960 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3961 XSetForeground (s->display, s->gc, s->face->underline_color);
3962 mac_fill_rectangle (s->f, s->gc, s->x, y,
3963 s->background_width, h);
3964 XSetForeground (s->display, s->gc, xgcv.foreground);
3968 /* Draw overline. */
3969 if (s->face->overline_p)
3971 unsigned long dy = 0, h = 1;
3973 if (s->face->overline_color_defaulted_p)
3974 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3975 s->background_width, h);
3976 else
3978 XGCValues xgcv;
3979 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3980 XSetForeground (s->display, s->gc, s->face->overline_color);
3981 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3982 s->background_width, h);
3983 XSetForeground (s->display, s->gc, xgcv.foreground);
3987 /* Draw strike-through. */
3988 if (s->face->strike_through_p)
3990 unsigned long h = 1;
3991 unsigned long dy = (s->height - h) / 2;
3993 if (s->face->strike_through_color_defaulted_p)
3994 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3995 s->width, h);
3996 else
3998 XGCValues xgcv;
3999 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4000 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4001 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
4002 s->width, h);
4003 XSetForeground (s->display, s->gc, xgcv.foreground);
4007 /* Draw relief if not yet drawn. */
4008 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4009 x_draw_glyph_string_box (s);
4012 /* Reset clipping. */
4013 mac_reset_clip_rectangles (s->display, s->gc);
4016 /* Shift display to make room for inserted glyphs. */
4018 void
4019 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
4020 struct frame *f;
4021 int x, y, width, height, shift_by;
4023 mac_scroll_area (f, f->output_data.mac->normal_gc,
4024 x, y, width, height,
4025 x + shift_by, y);
4028 /* Delete N glyphs at the nominal cursor position. Not implemented
4029 for X frames. */
4031 static void
4032 x_delete_glyphs (n)
4033 register int n;
4035 abort ();
4039 /* Clear entire frame. If updating_frame is non-null, clear that
4040 frame. Otherwise clear the selected frame. */
4042 static void
4043 x_clear_frame ()
4045 struct frame *f;
4047 if (updating_frame)
4048 f = updating_frame;
4049 else
4050 f = SELECTED_FRAME ();
4052 /* Clearing the frame will erase any cursor, so mark them all as no
4053 longer visible. */
4054 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4055 output_cursor.hpos = output_cursor.vpos = 0;
4056 output_cursor.x = -1;
4058 /* We don't set the output cursor here because there will always
4059 follow an explicit cursor_to. */
4060 BLOCK_INPUT;
4061 mac_clear_window (f);
4063 /* We have to clear the scroll bars, too. If we have changed
4064 colors or something like that, then they should be notified. */
4065 x_scroll_bar_clear (f);
4067 XFlush (FRAME_MAC_DISPLAY (f));
4068 UNBLOCK_INPUT;
4073 /* Invert the middle quarter of the frame for .15 sec. */
4075 /* We use the select system call to do the waiting, so we have to make
4076 sure it's available. If it isn't, we just won't do visual bells. */
4078 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4081 /* Subtract the `struct timeval' values X and Y, storing the result in
4082 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4084 static int
4085 timeval_subtract (result, x, y)
4086 struct timeval *result, x, y;
4088 /* Perform the carry for the later subtraction by updating y. This
4089 is safer because on some systems the tv_sec member is unsigned. */
4090 if (x.tv_usec < y.tv_usec)
4092 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4093 y.tv_usec -= 1000000 * nsec;
4094 y.tv_sec += nsec;
4097 if (x.tv_usec - y.tv_usec > 1000000)
4099 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4100 y.tv_usec += 1000000 * nsec;
4101 y.tv_sec -= nsec;
4104 /* Compute the time remaining to wait. tv_usec is certainly
4105 positive. */
4106 result->tv_sec = x.tv_sec - y.tv_sec;
4107 result->tv_usec = x.tv_usec - y.tv_usec;
4109 /* Return indication of whether the result should be considered
4110 negative. */
4111 return x.tv_sec < y.tv_sec;
4114 void
4115 XTflash (f)
4116 struct frame *f;
4118 /* Get the height not including a menu bar widget. */
4119 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
4120 /* Height of each line to flash. */
4121 int flash_height = FRAME_LINE_HEIGHT (f);
4122 /* These will be the left and right margins of the rectangles. */
4123 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4124 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4126 int width;
4128 /* Don't flash the area between a scroll bar and the frame
4129 edge it is next to. */
4130 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4132 case vertical_scroll_bar_left:
4133 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4134 break;
4136 case vertical_scroll_bar_right:
4137 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4138 break;
4140 default:
4141 break;
4144 width = flash_right - flash_left;
4146 BLOCK_INPUT;
4148 /* If window is tall, flash top and bottom line. */
4149 if (height > 3 * FRAME_LINE_HEIGHT (f))
4151 mac_invert_rectangle (f, flash_left,
4152 (FRAME_INTERNAL_BORDER_WIDTH (f)
4153 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4154 width, flash_height);
4155 mac_invert_rectangle (f, flash_left,
4156 (height - flash_height
4157 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4158 width, flash_height);
4160 else
4161 /* If it is short, flash it all. */
4162 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4163 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4165 x_flush (f);
4168 struct timeval wakeup;
4170 EMACS_GET_TIME (wakeup);
4172 /* Compute time to wait until, propagating carry from usecs. */
4173 wakeup.tv_usec += 150000;
4174 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4175 wakeup.tv_usec %= 1000000;
4177 /* Keep waiting until past the time wakeup or any input gets
4178 available. */
4179 while (! detect_input_pending ())
4181 struct timeval current;
4182 struct timeval timeout;
4184 EMACS_GET_TIME (current);
4186 /* Break if result would be negative. */
4187 if (timeval_subtract (&current, wakeup, current))
4188 break;
4190 /* How long `select' should wait. */
4191 timeout.tv_sec = 0;
4192 timeout.tv_usec = 10000;
4194 /* Try to wait that long--but we might wake up sooner. */
4195 select (0, NULL, NULL, NULL, &timeout);
4199 /* If window is tall, flash top and bottom line. */
4200 if (height > 3 * FRAME_LINE_HEIGHT (f))
4202 mac_invert_rectangle (f, flash_left,
4203 (FRAME_INTERNAL_BORDER_WIDTH (f)
4204 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4205 width, flash_height);
4206 mac_invert_rectangle (f, flash_left,
4207 (height - flash_height
4208 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4209 width, flash_height);
4211 else
4212 /* If it is short, flash it all. */
4213 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4214 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4216 x_flush (f);
4218 UNBLOCK_INPUT;
4221 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4224 /* Make audible bell. */
4226 void
4227 XTring_bell ()
4229 struct frame *f = SELECTED_FRAME ();
4231 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4232 if (visible_bell)
4233 XTflash (f);
4234 else
4235 #endif
4237 BLOCK_INPUT;
4238 SysBeep (1);
4239 XFlush (FRAME_MAC_DISPLAY (f));
4240 UNBLOCK_INPUT;
4245 /* Specify how many text lines, from the top of the window,
4246 should be affected by insert-lines and delete-lines operations.
4247 This, and those operations, are used only within an update
4248 that is bounded by calls to x_update_begin and x_update_end. */
4250 static void
4251 XTset_terminal_window (n)
4252 register int n;
4254 /* This function intentionally left blank. */
4259 /***********************************************************************
4260 Line Dance
4261 ***********************************************************************/
4263 /* Perform an insert-lines or delete-lines operation, inserting N
4264 lines or deleting -N lines at vertical position VPOS. */
4266 static void
4267 x_ins_del_lines (vpos, n)
4268 int vpos, n;
4270 abort ();
4274 /* Scroll part of the display as described by RUN. */
4276 static void
4277 x_scroll_run (w, run)
4278 struct window *w;
4279 struct run *run;
4281 struct frame *f = XFRAME (w->frame);
4282 int x, y, width, height, from_y, to_y, bottom_y;
4284 /* Get frame-relative bounding box of the text display area of W,
4285 without mode lines. Include in this box the left and right
4286 fringe of W. */
4287 window_box (w, -1, &x, &y, &width, &height);
4289 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4290 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4291 bottom_y = y + height;
4293 if (to_y < from_y)
4295 /* Scrolling up. Make sure we don't copy part of the mode
4296 line at the bottom. */
4297 if (from_y + run->height > bottom_y)
4298 height = bottom_y - from_y;
4299 else
4300 height = run->height;
4302 else
4304 /* Scolling down. Make sure we don't copy over the mode line.
4305 at the bottom. */
4306 if (to_y + run->height > bottom_y)
4307 height = bottom_y - to_y;
4308 else
4309 height = run->height;
4312 BLOCK_INPUT;
4314 /* Cursor off. Will be switched on again in x_update_window_end. */
4315 updated_window = w;
4316 x_clear_cursor (w);
4318 mac_scroll_area (f, f->output_data.mac->normal_gc,
4319 x, from_y,
4320 width, height,
4321 x, to_y);
4323 UNBLOCK_INPUT;
4328 /***********************************************************************
4329 Exposure Events
4330 ***********************************************************************/
4333 static void
4334 frame_highlight (f)
4335 struct frame *f;
4337 OSErr err;
4338 ControlRef root_control;
4340 BLOCK_INPUT;
4341 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
4342 if (err == noErr)
4343 ActivateControl (root_control);
4344 UNBLOCK_INPUT;
4345 x_update_cursor (f, 1);
4348 static void
4349 frame_unhighlight (f)
4350 struct frame *f;
4352 OSErr err;
4353 ControlRef root_control;
4355 BLOCK_INPUT;
4356 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
4357 if (err == noErr)
4358 DeactivateControl (root_control);
4359 UNBLOCK_INPUT;
4360 x_update_cursor (f, 1);
4363 /* The focus has changed. Update the frames as necessary to reflect
4364 the new situation. Note that we can't change the selected frame
4365 here, because the Lisp code we are interrupting might become confused.
4366 Each event gets marked with the frame in which it occurred, so the
4367 Lisp code can tell when the switch took place by examining the events. */
4369 static void
4370 x_new_focus_frame (dpyinfo, frame)
4371 struct x_display_info *dpyinfo;
4372 struct frame *frame;
4374 struct frame *old_focus = dpyinfo->x_focus_frame;
4376 if (frame != dpyinfo->x_focus_frame)
4378 /* Set this before calling other routines, so that they see
4379 the correct value of x_focus_frame. */
4380 dpyinfo->x_focus_frame = frame;
4382 if (old_focus && old_focus->auto_lower)
4383 x_lower_frame (old_focus);
4385 #if 0
4386 selected_frame = frame;
4387 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
4388 selected_frame);
4389 Fselect_window (selected_frame->selected_window, Qnil);
4390 choose_minibuf_frame ();
4391 #endif /* ! 0 */
4393 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4394 pending_autoraise_frame = dpyinfo->x_focus_frame;
4395 else
4396 pending_autoraise_frame = 0;
4398 #if USE_MAC_FONT_PANEL
4399 if (frame)
4400 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
4401 #endif
4404 x_frame_rehighlight (dpyinfo);
4407 /* Handle FocusIn and FocusOut state changes for FRAME.
4408 If FRAME has focus and there exists more than one frame, puts
4409 a FOCUS_IN_EVENT into *BUFP. */
4411 static void
4412 mac_focus_changed (type, dpyinfo, frame, bufp)
4413 int type;
4414 struct mac_display_info *dpyinfo;
4415 struct frame *frame;
4416 struct input_event *bufp;
4418 if (type == activeFlag)
4420 if (dpyinfo->x_focus_event_frame != frame)
4422 x_new_focus_frame (dpyinfo, frame);
4423 dpyinfo->x_focus_event_frame = frame;
4425 /* Don't stop displaying the initial startup message
4426 for a switch-frame event we don't need. */
4427 if (GC_NILP (Vterminal_frame)
4428 && GC_CONSP (Vframe_list)
4429 && !GC_NILP (XCDR (Vframe_list)))
4431 bufp->kind = FOCUS_IN_EVENT;
4432 XSETFRAME (bufp->frame_or_window, frame);
4436 else
4438 if (dpyinfo->x_focus_event_frame == frame)
4440 dpyinfo->x_focus_event_frame = 0;
4441 x_new_focus_frame (dpyinfo, 0);
4446 /* The focus may have changed. Figure out if it is a real focus change,
4447 by checking both FocusIn/Out and Enter/LeaveNotify events.
4449 Returns FOCUS_IN_EVENT event in *BUFP. */
4451 static void
4452 x_detect_focus_change (dpyinfo, event, bufp)
4453 struct mac_display_info *dpyinfo;
4454 const EventRecord *event;
4455 struct input_event *bufp;
4457 struct frame *frame;
4459 frame = mac_window_to_frame ((WindowRef) event->message);
4460 if (! frame)
4461 return;
4463 /* On Mac, this is only called from focus events, so no switch needed. */
4464 mac_focus_changed ((event->modifiers & activeFlag),
4465 dpyinfo, frame, bufp);
4469 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4471 void
4472 x_mouse_leave (dpyinfo)
4473 struct x_display_info *dpyinfo;
4475 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4478 /* The focus has changed, or we have redirected a frame's focus to
4479 another frame (this happens when a frame uses a surrogate
4480 mini-buffer frame). Shift the highlight as appropriate.
4482 The FRAME argument doesn't necessarily have anything to do with which
4483 frame is being highlighted or un-highlighted; we only use it to find
4484 the appropriate X display info. */
4486 static void
4487 XTframe_rehighlight (frame)
4488 struct frame *frame;
4490 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
4493 static void
4494 x_frame_rehighlight (dpyinfo)
4495 struct x_display_info *dpyinfo;
4497 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4499 if (dpyinfo->x_focus_frame)
4501 dpyinfo->x_highlight_frame
4502 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4503 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4504 : dpyinfo->x_focus_frame);
4505 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4507 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
4508 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4511 else
4512 dpyinfo->x_highlight_frame = 0;
4514 if (dpyinfo->x_highlight_frame != old_highlight)
4516 if (old_highlight)
4517 frame_unhighlight (old_highlight);
4518 if (dpyinfo->x_highlight_frame)
4519 frame_highlight (dpyinfo->x_highlight_frame);
4525 /* Convert a keysym to its name. */
4527 char *
4528 x_get_keysym_name (keysym)
4529 int keysym;
4531 char *value;
4533 BLOCK_INPUT;
4534 #if 0
4535 value = XKeysymToString (keysym);
4536 #else
4537 value = 0;
4538 #endif
4539 UNBLOCK_INPUT;
4541 return value;
4546 /* Function to report a mouse movement to the mainstream Emacs code.
4547 The input handler calls this.
4549 We have received a mouse movement event, which is given in *event.
4550 If the mouse is over a different glyph than it was last time, tell
4551 the mainstream emacs code by setting mouse_moved. If not, ask for
4552 another motion event, so we can check again the next time it moves. */
4554 static Point last_mouse_motion_position;
4555 static Lisp_Object last_mouse_motion_frame;
4557 static int
4558 note_mouse_movement (frame, pos)
4559 FRAME_PTR frame;
4560 Point *pos;
4562 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4563 #if TARGET_API_MAC_CARBON
4564 Rect r;
4565 #endif
4567 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4568 last_mouse_motion_position = *pos;
4569 XSETFRAME (last_mouse_motion_frame, frame);
4571 if (frame == dpyinfo->mouse_face_mouse_frame
4572 #if TARGET_API_MAC_CARBON
4573 && !PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r))
4574 #else
4575 && !PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect)
4576 #endif
4579 /* This case corresponds to LeaveNotify in X11. If we move
4580 outside the frame, then we're certainly no longer on any text
4581 in the frame. */
4582 clear_mouse_face (dpyinfo);
4583 dpyinfo->mouse_face_mouse_frame = 0;
4584 if (!dpyinfo->grabbed)
4585 rif->define_frame_cursor (frame,
4586 frame->output_data.mac->nontext_cursor);
4589 /* Has the mouse moved off the glyph it was on at the last sighting? */
4590 if (frame != last_mouse_glyph_frame
4591 || !PtInRect (*pos, &last_mouse_glyph))
4593 frame->mouse_moved = 1;
4594 last_mouse_scroll_bar = Qnil;
4595 note_mouse_highlight (frame, pos->h, pos->v);
4596 /* Remember which glyph we're now on. */
4597 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
4598 last_mouse_glyph_frame = frame;
4599 return 1;
4602 return 0;
4606 /************************************************************************
4607 Mouse Face
4608 ************************************************************************/
4610 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4612 static void
4613 redo_mouse_highlight ()
4615 if (!NILP (last_mouse_motion_frame)
4616 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4617 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4618 last_mouse_motion_position.h,
4619 last_mouse_motion_position.v);
4623 static struct frame *
4624 mac_focus_frame (dpyinfo)
4625 struct mac_display_info *dpyinfo;
4627 if (dpyinfo->x_focus_frame)
4628 return dpyinfo->x_focus_frame;
4629 else
4630 /* Mac version may get events, such as a menu bar click, even when
4631 all the frames are invisible. In this case, we regard the
4632 event came to the selected frame. */
4633 return SELECTED_FRAME ();
4637 /* Return the current position of the mouse.
4638 *FP should be a frame which indicates which display to ask about.
4640 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4641 and *PART to the frame, window, and scroll bar part that the mouse
4642 is over. Set *X and *Y to the portion and whole of the mouse's
4643 position on the scroll bar.
4645 If the mouse movement started elsewhere, set *FP to the frame the
4646 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4647 the mouse is over.
4649 Set *TIME to the server time-stamp for the time at which the mouse
4650 was at this position.
4652 Don't store anything if we don't have a valid set of values to report.
4654 This clears the mouse_moved flag, so we can wait for the next mouse
4655 movement. */
4657 static void
4658 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4659 FRAME_PTR *fp;
4660 int insist;
4661 Lisp_Object *bar_window;
4662 enum scroll_bar_part *part;
4663 Lisp_Object *x, *y;
4664 unsigned long *time;
4666 FRAME_PTR f1;
4668 BLOCK_INPUT;
4670 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4671 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4672 else
4674 Lisp_Object frame, tail;
4676 /* Clear the mouse-moved flag for every frame on this display. */
4677 FOR_EACH_FRAME (tail, frame)
4678 XFRAME (frame)->mouse_moved = 0;
4680 last_mouse_scroll_bar = Qnil;
4682 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4683 && FRAME_LIVE_P (last_mouse_frame))
4684 f1 = last_mouse_frame;
4685 else
4686 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4688 if (f1)
4690 /* Ok, we found a frame. Store all the values.
4691 last_mouse_glyph is a rectangle used to reduce the
4692 generation of mouse events. To not miss any motion
4693 events, we must divide the frame into rectangles of the
4694 size of the smallest character that could be displayed
4695 on it, i.e. into the same rectangles that matrices on
4696 the frame are divided into. */
4697 Point mouse_pos;
4699 #if TARGET_API_MAC_CARBON
4700 GetGlobalMouse (&mouse_pos);
4701 mouse_pos.h -= f1->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f1);
4702 mouse_pos.v -= f1->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f1);
4703 #else
4704 SetPortWindowPort (FRAME_MAC_WINDOW (f1));
4705 GetMouse (&mouse_pos);
4706 #endif
4707 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4708 &last_mouse_glyph);
4709 last_mouse_glyph_frame = f1;
4711 *bar_window = Qnil;
4712 *part = 0;
4713 *fp = f1;
4714 XSETINT (*x, mouse_pos.h);
4715 XSETINT (*y, mouse_pos.v);
4716 *time = last_mouse_movement_time;
4720 UNBLOCK_INPUT;
4724 /************************************************************************
4725 Toolkit scroll bars
4726 ************************************************************************/
4728 #ifdef USE_TOOLKIT_SCROLL_BARS
4730 static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
4731 static OSStatus install_scroll_bar_timer P_ ((void));
4732 static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
4733 static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
4734 static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
4735 struct input_event *));
4736 static OSStatus get_control_part_bounds P_ ((ControlRef, ControlPartCode,
4737 Rect *));
4738 static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
4739 ControlPartCode, Point,
4740 struct input_event *));
4741 static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
4742 struct input_event *));
4743 static void x_scroll_bar_handle_drag P_ ((WindowRef, struct scroll_bar *,
4744 Point, struct input_event *));
4745 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
4746 int, int, int));
4748 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4750 static int last_scroll_bar_part;
4752 static EventLoopTimerRef scroll_bar_timer;
4754 static int scroll_bar_timer_event_posted_p;
4756 #define SCROLL_BAR_FIRST_DELAY 0.5
4757 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4759 static pascal void
4760 scroll_bar_timer_callback (timer, data)
4761 EventLoopTimerRef timer;
4762 void *data;
4764 OSStatus err;
4766 err = mac_post_mouse_moved_event ();
4767 if (err == noErr)
4768 scroll_bar_timer_event_posted_p = 1;
4771 static OSStatus
4772 install_scroll_bar_timer ()
4774 static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
4776 if (scroll_bar_timer_callbackUPP == NULL)
4777 scroll_bar_timer_callbackUPP =
4778 NewEventLoopTimerUPP (scroll_bar_timer_callback);
4780 if (scroll_bar_timer == NULL)
4781 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4782 kEventDurationForever as delays. */
4783 return
4784 InstallEventLoopTimer (GetCurrentEventLoop (),
4785 kEventDurationForever, kEventDurationForever,
4786 scroll_bar_timer_callbackUPP, NULL,
4787 &scroll_bar_timer);
4790 static OSStatus
4791 set_scroll_bar_timer (delay)
4792 EventTimerInterval delay;
4794 if (scroll_bar_timer == NULL)
4795 install_scroll_bar_timer ();
4797 scroll_bar_timer_event_posted_p = 0;
4799 return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
4802 static int
4803 control_part_code_to_scroll_bar_part (part_code)
4804 ControlPartCode part_code;
4806 switch (part_code)
4808 case kControlUpButtonPart: return scroll_bar_up_arrow;
4809 case kControlDownButtonPart: return scroll_bar_down_arrow;
4810 case kControlPageUpPart: return scroll_bar_above_handle;
4811 case kControlPageDownPart: return scroll_bar_below_handle;
4812 case kControlIndicatorPart: return scroll_bar_handle;
4815 return -1;
4818 static void
4819 construct_scroll_bar_click (bar, part, bufp)
4820 struct scroll_bar *bar;
4821 int part;
4822 struct input_event *bufp;
4824 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4825 bufp->frame_or_window = bar->window;
4826 bufp->arg = Qnil;
4827 bufp->part = part;
4828 bufp->code = 0;
4829 XSETINT (bufp->x, 0);
4830 XSETINT (bufp->y, 0);
4831 bufp->modifiers = 0;
4834 static OSStatus
4835 get_control_part_bounds (ch, part_code, rect)
4836 ControlRef ch;
4837 ControlPartCode part_code;
4838 Rect *rect;
4840 RgnHandle region = NewRgn ();
4841 OSStatus err;
4843 err = GetControlRegion (ch, part_code, region);
4844 if (err == noErr)
4845 GetRegionBounds (region, rect);
4846 DisposeRgn (region);
4848 return err;
4851 static void
4852 x_scroll_bar_handle_press (bar, part_code, mouse_pos, bufp)
4853 struct scroll_bar *bar;
4854 ControlPartCode part_code;
4855 Point mouse_pos;
4856 struct input_event *bufp;
4858 int part = control_part_code_to_scroll_bar_part (part_code);
4860 if (part < 0)
4861 return;
4863 if (part != scroll_bar_handle)
4865 construct_scroll_bar_click (bar, part, bufp);
4866 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), part_code);
4867 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
4868 bar->dragging = Qnil;
4870 else
4872 Rect r;
4874 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar),
4875 kControlIndicatorPart, &r);
4876 XSETINT (bar->dragging, - (mouse_pos.v - r.top) - 1);
4879 last_scroll_bar_part = part;
4880 tracked_scroll_bar = bar;
4883 static void
4884 x_scroll_bar_handle_release (bar, bufp)
4885 struct scroll_bar *bar;
4886 struct input_event *bufp;
4888 if (last_scroll_bar_part != scroll_bar_handle
4889 || (INTEGERP (bar->dragging) && XINT (bar->dragging) >= 0))
4890 construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
4892 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), 0);
4893 set_scroll_bar_timer (kEventDurationForever);
4895 last_scroll_bar_part = -1;
4896 bar->dragging = Qnil;
4897 tracked_scroll_bar = NULL;
4900 static void
4901 x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
4902 WindowRef win;
4903 struct scroll_bar *bar;
4904 Point mouse_pos;
4905 struct input_event *bufp;
4907 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
4909 if (last_scroll_bar_part == scroll_bar_handle)
4911 int top, top_range;
4912 Rect r;
4914 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar),
4915 kControlIndicatorPart, &r);
4917 if (INTEGERP (bar->dragging) && XINT (bar->dragging) < 0)
4918 XSETINT (bar->dragging, - (XINT (bar->dragging) + 1));
4920 top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
4921 top_range = XINT (bar->track_height) - XINT (bar->min_handle);
4923 if (top < 0)
4924 top = 0;
4925 if (top > top_range)
4926 top = top_range;
4928 construct_scroll_bar_click (bar, scroll_bar_handle, bufp);
4929 XSETINT (bufp->x, top);
4930 XSETINT (bufp->y, top_range);
4932 else
4934 ControlPartCode part_code;
4935 int unhilite_p = 0, part;
4937 if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
4938 unhilite_p = 1;
4939 else
4941 part = control_part_code_to_scroll_bar_part (part_code);
4943 switch (last_scroll_bar_part)
4945 case scroll_bar_above_handle:
4946 case scroll_bar_below_handle:
4947 if (part != scroll_bar_above_handle
4948 && part != scroll_bar_below_handle)
4949 unhilite_p = 1;
4950 break;
4952 case scroll_bar_up_arrow:
4953 case scroll_bar_down_arrow:
4954 if (part != scroll_bar_up_arrow
4955 && part != scroll_bar_down_arrow)
4956 unhilite_p = 1;
4957 break;
4961 if (unhilite_p)
4962 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), 0);
4963 else if (part != last_scroll_bar_part
4964 || scroll_bar_timer_event_posted_p)
4966 construct_scroll_bar_click (bar, part, bufp);
4967 last_scroll_bar_part = part;
4968 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), part_code);
4969 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
4974 /* Set the thumb size and position of scroll bar BAR. We are currently
4975 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4977 static void
4978 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4979 struct scroll_bar *bar;
4980 int portion, position, whole;
4982 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
4983 int value, viewsize, maximum;
4985 if (XINT (bar->track_height) == 0)
4986 return;
4988 if (whole <= portion)
4989 value = 0, viewsize = 1, maximum = 0;
4990 else
4992 float scale;
4994 maximum = XINT (bar->track_height) - XINT (bar->min_handle);
4995 scale = (float) maximum / (whole - portion);
4996 value = position * scale + 0.5f;
4997 viewsize = (int) (portion * scale + 0.5f) + XINT (bar->min_handle);
5000 BLOCK_INPUT;
5002 if (GetControlViewSize (ch) != viewsize
5003 || GetControl32BitValue (ch) != value
5004 || GetControl32BitMaximum (ch) != maximum)
5006 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5007 SetControlVisibility (ch, false, false);
5009 SetControl32BitMaximum (ch, maximum);
5010 SetControl32BitValue (ch, value);
5011 SetControlViewSize (ch, viewsize);
5013 SetControlVisibility (ch, true, true);
5016 UNBLOCK_INPUT;
5019 #endif /* USE_TOOLKIT_SCROLL_BARS */
5023 /************************************************************************
5024 Scroll bars, general
5025 ************************************************************************/
5027 /* Create a scroll bar and return the scroll bar vector for it. W is
5028 the Emacs window on which to create the scroll bar. TOP, LEFT,
5029 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5030 scroll bar. */
5032 static struct scroll_bar *
5033 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
5034 struct window *w;
5035 int top, left, width, height, disp_top, disp_height;
5037 struct frame *f = XFRAME (w->frame);
5038 struct scroll_bar *bar
5039 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
5040 Rect r;
5041 ControlRef ch;
5043 BLOCK_INPUT;
5045 r.left = left;
5046 r.top = disp_top;
5047 r.right = left + width;
5048 r.bottom = disp_top + disp_height;
5050 #if USE_CG_DRAWING
5051 mac_prepare_for_quickdraw (f);
5052 #endif
5053 #if TARGET_API_MAC_CARBON
5054 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
5055 #ifdef USE_TOOLKIT_SCROLL_BARS
5056 false,
5057 #else
5058 width < disp_height,
5059 #endif
5060 0, 0, 0, kControlScrollBarProc, (long) bar);
5061 #else
5062 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
5063 0, 0, 0, scrollBarProc, (long) bar);
5064 #endif
5065 SET_SCROLL_BAR_CONTROL_REF (bar, ch);
5067 XSETWINDOW (bar->window, w);
5068 XSETINT (bar->top, top);
5069 XSETINT (bar->left, left);
5070 XSETINT (bar->width, width);
5071 XSETINT (bar->height, height);
5072 XSETINT (bar->start, 0);
5073 XSETINT (bar->end, 0);
5074 bar->dragging = Qnil;
5075 #ifdef MAC_OSX
5076 bar->fringe_extended_p = Qnil;
5077 #endif
5078 #ifdef USE_TOOLKIT_SCROLL_BARS
5079 bar->track_top = Qnil;
5080 bar->track_height = Qnil;
5081 bar->min_handle = Qnil;
5082 #endif
5084 /* Add bar to its frame's list of scroll bars. */
5085 bar->next = FRAME_SCROLL_BARS (f);
5086 bar->prev = Qnil;
5087 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5088 if (!NILP (bar->next))
5089 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5091 UNBLOCK_INPUT;
5092 return bar;
5096 /* Draw BAR's handle in the proper position.
5098 If the handle is already drawn from START to END, don't bother
5099 redrawing it, unless REBUILD is non-zero; in that case, always
5100 redraw it. (REBUILD is handy for drawing the handle after expose
5101 events.)
5103 Normally, we want to constrain the start and end of the handle to
5104 fit inside its rectangle, but if the user is dragging the scroll
5105 bar handle, we want to let them drag it down all the way, so that
5106 the bar's top is as far down as it goes; otherwise, there's no way
5107 to move to the very end of the buffer. */
5109 #ifndef USE_TOOLKIT_SCROLL_BARS
5111 static void
5112 x_scroll_bar_set_handle (bar, start, end, rebuild)
5113 struct scroll_bar *bar;
5114 int start, end;
5115 int rebuild;
5117 int dragging = ! NILP (bar->dragging);
5118 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
5119 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5120 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5121 int length = end - start;
5123 /* If the display is already accurate, do nothing. */
5124 if (! rebuild
5125 && start == XINT (bar->start)
5126 && end == XINT (bar->end))
5127 return;
5129 BLOCK_INPUT;
5131 /* Make sure the values are reasonable, and try to preserve the
5132 distance between start and end. */
5133 if (start < 0)
5134 start = 0;
5135 else if (start > top_range)
5136 start = top_range;
5137 end = start + length;
5139 if (end < start)
5140 end = start;
5141 else if (end > top_range && ! dragging)
5142 end = top_range;
5144 /* Store the adjusted setting in the scroll bar. */
5145 XSETINT (bar->start, start);
5146 XSETINT (bar->end, end);
5148 /* Clip the end position, just for display. */
5149 if (end > top_range)
5150 end = top_range;
5152 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5153 top positions, to make sure the handle is always at least that
5154 many pixels tall. */
5155 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
5157 SetControlMinimum (ch, 0);
5158 /* Don't inadvertently activate deactivated scroll bars */
5159 if (GetControlMaximum (ch) != -1)
5160 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
5161 - (end - start));
5162 SetControlValue (ch, start);
5163 #if TARGET_API_MAC_CARBON
5164 SetControlViewSize (ch, end - start);
5165 #endif
5167 UNBLOCK_INPUT;
5170 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5172 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5173 nil. */
5175 static void
5176 x_scroll_bar_remove (bar)
5177 struct scroll_bar *bar;
5179 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5181 BLOCK_INPUT;
5183 #if USE_CG_DRAWING
5184 mac_prepare_for_quickdraw (f);
5185 #endif
5186 /* Destroy the Mac scroll bar control */
5187 DisposeControl (SCROLL_BAR_CONTROL_REF (bar));
5189 /* Disassociate this scroll bar from its window. */
5190 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5192 UNBLOCK_INPUT;
5196 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5197 that we are displaying PORTION characters out of a total of WHOLE
5198 characters, starting at POSITION. If WINDOW has no scroll bar,
5199 create one. */
5201 static void
5202 XTset_vertical_scroll_bar (w, portion, whole, position)
5203 struct window *w;
5204 int portion, whole, position;
5206 struct frame *f = XFRAME (w->frame);
5207 struct scroll_bar *bar;
5208 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
5209 int window_y, window_height;
5210 #ifdef MAC_OSX
5211 int fringe_extended_p;
5212 #endif
5214 /* Get window dimensions. */
5215 window_box (w, -1, 0, &window_y, 0, &window_height);
5216 top = window_y;
5217 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5218 height = window_height;
5220 /* Compute the left edge of the scroll bar area. */
5221 left = WINDOW_SCROLL_BAR_AREA_X (w);
5223 /* Compute the width of the scroll bar which might be less than
5224 the width of the area reserved for the scroll bar. */
5225 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
5226 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
5227 else
5228 sb_width = width;
5230 /* Compute the left edge of the scroll bar. */
5231 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5232 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
5233 else
5234 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
5236 /* Adjustments according to Inside Macintosh to make it look nice */
5237 disp_top = top;
5238 disp_height = height;
5239 #ifdef MAC_OS8
5240 if (disp_top == 0)
5242 disp_top = -1;
5243 disp_height++;
5245 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
5247 disp_top++;
5248 disp_height--;
5251 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
5252 sb_left++;
5253 #endif
5255 #ifdef MAC_OSX
5256 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
5257 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
5258 && WINDOW_LEFT_FRINGE_WIDTH (w)
5259 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5260 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
5261 else
5262 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
5263 && WINDOW_RIGHT_FRINGE_WIDTH (w)
5264 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5265 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
5266 #endif
5268 /* Does the scroll bar exist yet? */
5269 if (NILP (w->vertical_scroll_bar))
5271 BLOCK_INPUT;
5272 #ifdef MAC_OSX
5273 if (fringe_extended_p)
5274 mac_clear_area (f, sb_left, top, sb_width, height);
5275 else
5276 #endif
5277 mac_clear_area (f, left, top, width, height);
5278 UNBLOCK_INPUT;
5279 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
5280 disp_height);
5281 XSETVECTOR (w->vertical_scroll_bar, bar);
5283 else
5285 /* It may just need to be moved and resized. */
5286 ControlRef ch;
5288 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5289 ch = SCROLL_BAR_CONTROL_REF (bar);
5291 BLOCK_INPUT;
5293 /* If already correctly positioned, do nothing. */
5294 if (!(XINT (bar->left) == sb_left
5295 && XINT (bar->top) == top
5296 && XINT (bar->width) == sb_width
5297 && XINT (bar->height) == height
5298 #ifdef MAC_OSX
5299 && !NILP (bar->fringe_extended_p) == fringe_extended_p
5300 #endif
5303 /* Since toolkit scroll bars are smaller than the space reserved
5304 for them on the frame, we have to clear "under" them. */
5305 #ifdef MAC_OSX
5306 if (fringe_extended_p)
5307 mac_clear_area (f, sb_left, top, sb_width, height);
5308 else
5309 #endif
5310 mac_clear_area (f, left, top, width, height);
5312 #if USE_CG_DRAWING
5313 mac_prepare_for_quickdraw (f);
5314 #endif
5315 HideControl (ch);
5316 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
5317 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5318 disp_height);
5319 #ifndef USE_TOOLKIT_SCROLL_BARS
5320 if (sb_width < disp_height)
5321 ShowControl (ch);
5322 #endif
5324 /* Remember new settings. */
5325 XSETINT (bar->left, sb_left);
5326 XSETINT (bar->top, top);
5327 XSETINT (bar->width, sb_width);
5328 XSETINT (bar->height, height);
5329 #ifdef USE_TOOLKIT_SCROLL_BARS
5330 bar->track_top = Qnil;
5331 bar->track_height = Qnil;
5332 bar->min_handle = Qnil;
5333 #endif
5336 UNBLOCK_INPUT;
5339 #ifdef MAC_OSX
5340 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
5341 #endif
5343 #ifdef USE_TOOLKIT_SCROLL_BARS
5344 if (NILP (bar->track_top))
5346 if (sb_width >= disp_height
5347 #ifdef MAC_OSX
5348 || sb_width < MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5349 #endif
5352 XSETINT (bar->track_top, 0);
5353 XSETINT (bar->track_height, 0);
5354 XSETINT (bar->min_handle, 0);
5356 else
5358 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
5359 Rect r0, r1;
5361 BLOCK_INPUT;
5363 SetControl32BitMinimum (ch, 0);
5364 SetControl32BitMaximum (ch, 1 << 30);
5365 SetControlViewSize (ch, 1);
5367 /* Move the scroll bar thumb to the top. */
5368 SetControl32BitValue (ch, 0);
5369 get_control_part_bounds (ch, kControlIndicatorPart, &r0);
5371 /* Move the scroll bar thumb to the bottom. */
5372 SetControl32BitValue (ch, 1 << 30);
5373 get_control_part_bounds (ch, kControlIndicatorPart, &r1);
5375 UnionRect (&r0, &r1, &r0);
5376 XSETINT (bar->track_top, r0.top);
5377 XSETINT (bar->track_height, r0.bottom - r0.top);
5378 XSETINT (bar->min_handle, r1.bottom - r1.top);
5380 /* Don't show the scroll bar if its height is not enough to
5381 display the scroll bar thumb. */
5382 if (r0.bottom - r0.top > 0)
5383 ShowControl (ch);
5385 UNBLOCK_INPUT;
5389 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5390 #else /* not USE_TOOLKIT_SCROLL_BARS */
5391 /* Set the scroll bar's current state, unless we're currently being
5392 dragged. */
5393 if (NILP (bar->dragging))
5395 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5397 if (whole == 0)
5398 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5399 else
5401 int start = ((double) position * top_range) / whole;
5402 int end = ((double) (position + portion) * top_range) / whole;
5403 x_scroll_bar_set_handle (bar, start, end, 0);
5406 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5410 /* The following three hooks are used when we're doing a thorough
5411 redisplay of the frame. We don't explicitly know which scroll bars
5412 are going to be deleted, because keeping track of when windows go
5413 away is a real pain - "Can you say set-window-configuration, boys
5414 and girls?" Instead, we just assert at the beginning of redisplay
5415 that *all* scroll bars are to be removed, and then save a scroll bar
5416 from the fiery pit when we actually redisplay its window. */
5418 /* Arrange for all scroll bars on FRAME to be removed at the next call
5419 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5420 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5422 static void
5423 XTcondemn_scroll_bars (frame)
5424 FRAME_PTR frame;
5426 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5427 while (! NILP (FRAME_SCROLL_BARS (frame)))
5429 Lisp_Object bar;
5430 bar = FRAME_SCROLL_BARS (frame);
5431 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5432 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5433 XSCROLL_BAR (bar)->prev = Qnil;
5434 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5435 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5436 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5441 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5442 Note that WINDOW isn't necessarily condemned at all. */
5444 static void
5445 XTredeem_scroll_bar (window)
5446 struct window *window;
5448 struct scroll_bar *bar;
5449 struct frame *f;
5451 /* We can't redeem this window's scroll bar if it doesn't have one. */
5452 if (NILP (window->vertical_scroll_bar))
5453 abort ();
5455 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5457 /* Unlink it from the condemned list. */
5458 f = XFRAME (WINDOW_FRAME (window));
5459 if (NILP (bar->prev))
5461 /* If the prev pointer is nil, it must be the first in one of
5462 the lists. */
5463 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5464 /* It's not condemned. Everything's fine. */
5465 return;
5466 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5467 window->vertical_scroll_bar))
5468 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5469 else
5470 /* If its prev pointer is nil, it must be at the front of
5471 one or the other! */
5472 abort ();
5474 else
5475 XSCROLL_BAR (bar->prev)->next = bar->next;
5477 if (! NILP (bar->next))
5478 XSCROLL_BAR (bar->next)->prev = bar->prev;
5480 bar->next = FRAME_SCROLL_BARS (f);
5481 bar->prev = Qnil;
5482 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5483 if (! NILP (bar->next))
5484 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5487 /* Remove all scroll bars on FRAME that haven't been saved since the
5488 last call to `*condemn_scroll_bars_hook'. */
5490 static void
5491 XTjudge_scroll_bars (f)
5492 FRAME_PTR f;
5494 Lisp_Object bar, next;
5496 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5498 /* Clear out the condemned list now so we won't try to process any
5499 more events on the hapless scroll bars. */
5500 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5502 for (; ! NILP (bar); bar = next)
5504 struct scroll_bar *b = XSCROLL_BAR (bar);
5506 x_scroll_bar_remove (b);
5508 next = b->next;
5509 b->next = b->prev = Qnil;
5512 /* Now there should be no references to the condemned scroll bars,
5513 and they should get garbage-collected. */
5517 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5518 is set to something other than NO_EVENT, it is enqueued.
5520 This may be called from a signal handler, so we have to ignore GC
5521 mark bits. */
5523 static void
5524 x_scroll_bar_handle_click (bar, part_code, er, bufp)
5525 struct scroll_bar *bar;
5526 ControlPartCode part_code;
5527 const EventRecord *er;
5528 struct input_event *bufp;
5530 int win_y, top_range;
5532 if (! GC_WINDOWP (bar->window))
5533 abort ();
5535 bufp->kind = SCROLL_BAR_CLICK_EVENT;
5536 bufp->frame_or_window = bar->window;
5537 bufp->arg = Qnil;
5539 bar->dragging = Qnil;
5541 switch (part_code)
5543 case kControlUpButtonPart:
5544 bufp->part = scroll_bar_up_arrow;
5545 break;
5546 case kControlDownButtonPart:
5547 bufp->part = scroll_bar_down_arrow;
5548 break;
5549 case kControlPageUpPart:
5550 bufp->part = scroll_bar_above_handle;
5551 break;
5552 case kControlPageDownPart:
5553 bufp->part = scroll_bar_below_handle;
5554 break;
5555 #if TARGET_API_MAC_CARBON
5556 default:
5557 #else
5558 case kControlIndicatorPart:
5559 #endif
5560 if (er->what == mouseDown)
5561 bar->dragging = make_number (0);
5562 XSETVECTOR (last_mouse_scroll_bar, bar);
5563 bufp->part = scroll_bar_handle;
5564 break;
5567 win_y = XINT (bufp->y) - XINT (bar->top);
5568 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
5570 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5572 win_y -= 24;
5574 if (! NILP (bar->dragging))
5575 win_y -= XINT (bar->dragging);
5577 if (win_y < 0)
5578 win_y = 0;
5579 if (win_y > top_range)
5580 win_y = top_range;
5582 XSETINT (bufp->x, win_y);
5583 XSETINT (bufp->y, top_range);
5586 #ifndef USE_TOOLKIT_SCROLL_BARS
5588 /* Handle some mouse motion while someone is dragging the scroll bar.
5590 This may be called from a signal handler, so we have to ignore GC
5591 mark bits. */
5593 static void
5594 x_scroll_bar_note_movement (bar, y_pos, t)
5595 struct scroll_bar *bar;
5596 int y_pos;
5597 Time t;
5599 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5601 last_mouse_movement_time = t;
5603 f->mouse_moved = 1;
5604 XSETVECTOR (last_mouse_scroll_bar, bar);
5606 /* If we're dragging the bar, display it. */
5607 if (! GC_NILP (bar->dragging))
5609 /* Where should the handle be now? */
5610 int new_start = y_pos - 24;
5612 if (new_start != XINT (bar->start))
5614 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
5616 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5621 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5623 /* Return information to the user about the current position of the mouse
5624 on the scroll bar. */
5626 static void
5627 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
5628 FRAME_PTR *fp;
5629 Lisp_Object *bar_window;
5630 enum scroll_bar_part *part;
5631 Lisp_Object *x, *y;
5632 unsigned long *time;
5634 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5635 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
5636 #if TARGET_API_MAC_CARBON
5637 WindowRef wp = GetControlOwner (ch);
5638 #else
5639 WindowRef wp = (*ch)->contrlOwner;
5640 #endif
5641 Point mouse_pos;
5642 struct frame *f = mac_window_to_frame (wp);
5643 int win_y, top_range;
5645 #if TARGET_API_MAC_CARBON
5646 GetGlobalMouse (&mouse_pos);
5647 mouse_pos.h -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
5648 mouse_pos.v -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
5649 #else
5650 SetPortWindowPort (wp);
5651 GetMouse (&mouse_pos);
5652 #endif
5654 win_y = mouse_pos.v - XINT (bar->top);
5655 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5657 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5659 win_y -= 24;
5661 if (! NILP (bar->dragging))
5662 win_y -= XINT (bar->dragging);
5664 if (win_y < 0)
5665 win_y = 0;
5666 if (win_y > top_range)
5667 win_y = top_range;
5669 *fp = f;
5670 *bar_window = bar->window;
5672 if (! NILP (bar->dragging))
5673 *part = scroll_bar_handle;
5674 else if (win_y < XINT (bar->start))
5675 *part = scroll_bar_above_handle;
5676 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5677 *part = scroll_bar_handle;
5678 else
5679 *part = scroll_bar_below_handle;
5681 XSETINT (*x, win_y);
5682 XSETINT (*y, top_range);
5684 f->mouse_moved = 0;
5685 last_mouse_scroll_bar = Qnil;
5687 *time = last_mouse_movement_time;
5691 /* The screen has been cleared so we may have changed foreground or
5692 background colors, and the scroll bars may need to be redrawn.
5693 Clear out the scroll bars, and ask for expose events, so we can
5694 redraw them. */
5696 void
5697 x_scroll_bar_clear (f)
5698 FRAME_PTR f;
5700 XTcondemn_scroll_bars (f);
5701 XTjudge_scroll_bars (f);
5705 /***********************************************************************
5706 Tool-bars
5707 ***********************************************************************/
5708 #if USE_MAC_TOOLBAR
5710 /* In identifiers such as function/variable names, Emacs tool bar is
5711 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5713 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5714 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5716 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5717 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5718 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5719 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5720 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5721 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5722 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5724 static int mac_event_to_emacs_modifiers P_ ((EventRef));
5725 static void mac_handle_origin_change P_ ((struct frame *));
5726 static OSStatus mac_handle_toolbar_command_event P_ ((EventHandlerCallRef,
5727 EventRef, void *));
5729 static void
5730 mac_move_window_with_gravity (f, win_gravity, left, top)
5731 struct frame *f;
5732 int win_gravity;
5733 short left, top;
5735 Rect inner, outer;
5737 mac_get_window_bounds (f, &inner, &outer);
5739 switch (win_gravity)
5741 case NorthWestGravity:
5742 case WestGravity:
5743 case SouthWestGravity:
5744 left += inner.left - outer.left;
5745 break;
5747 case NorthGravity:
5748 case CenterGravity:
5749 case SouthGravity:
5750 left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
5751 break;
5753 case NorthEastGravity:
5754 case EastGravity:
5755 case SouthEastGravity:
5756 left += inner.right - outer.right;
5757 break;
5760 switch (win_gravity)
5762 case NorthWestGravity:
5763 case NorthGravity:
5764 case NorthEastGravity:
5765 top += inner.top - outer.top;
5766 break;
5768 case WestGravity:
5769 case CenterGravity:
5770 case EastGravity:
5771 top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
5772 break;
5774 case SouthWestGravity:
5775 case SouthGravity:
5776 case SouthEastGravity:
5777 top += inner.bottom - outer.bottom;
5778 break;
5781 MoveWindow (FRAME_MAC_WINDOW (f), left, top, false);
5784 static void
5785 mac_get_window_origin_with_gravity (f, win_gravity, left, top)
5786 struct frame *f;
5787 int win_gravity;
5788 short *left, *top;
5790 Rect inner, outer;
5792 mac_get_window_bounds (f, &inner, &outer);
5794 switch (win_gravity)
5796 case NorthWestGravity:
5797 case WestGravity:
5798 case SouthWestGravity:
5799 *left = outer.left;
5800 break;
5802 case NorthGravity:
5803 case CenterGravity:
5804 case SouthGravity:
5805 *left = outer.left + ((outer.right - outer.left)
5806 - (inner.right - inner.left)) / 2;
5807 break;
5809 case NorthEastGravity:
5810 case EastGravity:
5811 case SouthEastGravity:
5812 *left = outer.right - (inner.right - inner.left);
5813 break;
5816 switch (win_gravity)
5818 case NorthWestGravity:
5819 case NorthGravity:
5820 case NorthEastGravity:
5821 *top = outer.top;
5822 break;
5824 case WestGravity:
5825 case CenterGravity:
5826 case EastGravity:
5827 *top = outer.top + ((outer.bottom - outer.top)
5828 - (inner.bottom - inner.top)) / 2;
5829 break;
5831 case SouthWestGravity:
5832 case SouthGravity:
5833 case SouthEastGravity:
5834 *top = outer.bottom - (inner.bottom - inner.top);
5835 break;
5839 static OSStatus
5840 mac_handle_toolbar_event (next_handler, event, data)
5841 EventHandlerCallRef next_handler;
5842 EventRef event;
5843 void *data;
5845 OSStatus err, result = eventNotHandledErr;
5847 switch (GetEventKind (event))
5849 case kEventToolbarGetDefaultIdentifiers:
5850 result = noErr;
5851 break;
5853 case kEventToolbarGetAllowedIdentifiers:
5855 CFMutableArrayRef array;
5857 GetEventParameter (event, kEventParamMutableArray,
5858 typeCFMutableArrayRef, NULL,
5859 sizeof (CFMutableArrayRef), NULL, &array);
5860 CFArrayAppendValue (array, TOOLBAR_ICON_ITEM_IDENTIFIER);
5861 result = noErr;
5863 break;
5865 case kEventToolbarCreateItemWithIdentifier:
5867 CFStringRef identifier;
5868 HIToolbarItemRef item = NULL;
5870 GetEventParameter (event, kEventParamToolbarItemIdentifier,
5871 typeCFStringRef, NULL,
5872 sizeof (CFStringRef), NULL, &identifier);
5874 if (CFStringCompare (identifier, TOOLBAR_ICON_ITEM_IDENTIFIER, 0)
5875 == kCFCompareEqualTo)
5876 HIToolbarItemCreate (identifier,
5877 kHIToolbarItemAllowDuplicates
5878 | kHIToolbarItemCantBeRemoved, &item);
5880 if (item)
5882 SetEventParameter (event, kEventParamToolbarItem,
5883 typeHIToolbarItemRef,
5884 sizeof (HIToolbarItemRef), &item);
5885 result = noErr;
5888 break;
5890 default:
5891 abort ();
5894 return result;
5897 static CGImageRef
5898 mac_image_spec_to_cg_image (f, image)
5899 struct frame *f;
5900 Lisp_Object image;
5902 if (!valid_image_p (image))
5903 return NULL;
5904 else
5906 int img_id = lookup_image (f, image);
5907 struct image *img = IMAGE_FROM_ID (f, img_id);
5909 prepare_image_for_display (f, img);
5911 return img->data.ptr_val;
5915 /* Create a tool bar for frame F. */
5917 static OSStatus
5918 mac_create_frame_tool_bar (f)
5919 FRAME_PTR f;
5921 OSStatus err;
5922 HIToolbarRef toolbar;
5924 err = HIToolbarCreate (TOOLBAR_IDENTIFIER, kHIToolbarNoAttributes,
5925 &toolbar);
5926 if (err == noErr)
5928 static const EventTypeSpec specs[] =
5929 {{kEventClassToolbar, kEventToolbarGetDefaultIdentifiers},
5930 {kEventClassToolbar, kEventToolbarGetAllowedIdentifiers},
5931 {kEventClassToolbar, kEventToolbarCreateItemWithIdentifier}};
5933 err = InstallEventHandler (HIObjectGetEventTarget (toolbar),
5934 mac_handle_toolbar_event,
5935 GetEventTypeCount (specs), specs,
5936 f, NULL);
5939 if (err == noErr)
5940 err = HIToolbarSetDisplayMode (toolbar, kHIToolbarDisplayModeIconOnly);
5941 if (err == noErr)
5943 static const EventTypeSpec specs[] =
5944 {{kEventClassCommand, kEventCommandProcess}};
5946 err = InstallWindowEventHandler (FRAME_MAC_WINDOW (f),
5947 mac_handle_toolbar_command_event,
5948 GetEventTypeCount (specs),
5949 specs, f, NULL);
5951 if (err == noErr)
5952 err = SetWindowToolbar (FRAME_MAC_WINDOW (f), toolbar);
5954 if (toolbar)
5955 CFRelease (toolbar);
5957 return err;
5960 /* Update the tool bar for frame F. Add new buttons and remove old. */
5962 void
5963 update_frame_tool_bar (f)
5964 FRAME_PTR f;
5966 HIToolbarRef toolbar = NULL;
5967 short left, top;
5968 CFArrayRef old_items = NULL;
5969 CFIndex old_count;
5970 int i, pos, win_gravity = f->output_data.mac->toolbar_win_gravity;
5971 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5973 BLOCK_INPUT;
5975 GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
5976 if (toolbar == NULL)
5978 mac_create_frame_tool_bar (f);
5979 GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
5980 if (toolbar == NULL)
5981 goto out;
5982 if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
5983 mac_get_window_origin_with_gravity (f, win_gravity, &left, &top);
5986 HIToolbarCopyItems (toolbar, &old_items);
5987 if (old_items == NULL)
5988 goto out;
5990 old_count = CFArrayGetCount (old_items);
5991 pos = 0;
5992 for (i = 0; i < f->n_tool_bar_items; ++i)
5994 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5996 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
5997 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
5998 int idx;
5999 Lisp_Object image;
6000 CGImageRef cg_image;
6001 CFStringRef label;
6002 HIToolbarItemRef item;
6004 /* If image is a vector, choose the image according to the
6005 button state. */
6006 image = PROP (TOOL_BAR_ITEM_IMAGES);
6007 if (VECTORP (image))
6009 if (enabled_p)
6010 idx = (selected_p
6011 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6012 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
6013 else
6014 idx = (selected_p
6015 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6016 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
6018 xassert (ASIZE (image) >= idx);
6019 image = AREF (image, idx);
6021 else
6022 idx = -1;
6024 cg_image = mac_image_spec_to_cg_image (f, image);
6025 /* Ignore invalid image specifications. */
6026 if (cg_image == NULL)
6027 continue;
6029 label = cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION));
6030 if (label == NULL)
6031 label = CFSTR ("");
6033 if (pos < old_count)
6035 CGImageRef old_cg_image = NULL;
6036 CFStringRef old_label = NULL;
6037 Boolean old_enabled_p;
6039 item = (HIToolbarItemRef) CFArrayGetValueAtIndex (old_items, pos);
6041 HIToolbarItemCopyImage (item, &old_cg_image);
6042 if (cg_image != old_cg_image)
6043 HIToolbarItemSetImage (item, cg_image);
6044 CGImageRelease (old_cg_image);
6046 HIToolbarItemCopyLabel (item, &old_label);
6047 if (CFStringCompare (label, old_label, 0) != kCFCompareEqualTo)
6048 HIToolbarItemSetLabel (item, label);
6049 CFRelease (old_label);
6051 old_enabled_p = HIToolbarItemIsEnabled (item);
6052 if ((enabled_p || idx >= 0) != old_enabled_p)
6053 HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
6055 else
6057 item = NULL;
6058 HIToolbarCreateItemWithIdentifier (toolbar,
6059 TOOLBAR_ICON_ITEM_IDENTIFIER,
6060 NULL, &item);
6061 if (item)
6063 HIToolbarItemSetImage (item, cg_image);
6064 HIToolbarItemSetLabel (item, label);
6065 HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
6066 HIToolbarAppendItem (toolbar, item);
6067 CFRelease (item);
6071 CFRelease (label);
6072 if (item)
6074 HIToolbarItemSetCommandID (item, TOOLBAR_ITEM_MAKE_COMMAND_ID (i));
6075 pos++;
6079 CFRelease (old_items);
6081 while (pos < old_count)
6082 HIToolbarRemoveItemAtIndex (toolbar, --old_count);
6084 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), true,
6085 !win_gravity && f == mac_focus_frame (dpyinfo));
6086 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6087 toolbar visibility change. */
6088 mac_handle_origin_change (f);
6089 if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
6091 mac_move_window_with_gravity (f, win_gravity, left, top);
6092 /* If the title bar is completely outside the screen, adjust the
6093 position. */
6094 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
6095 kWindowConstrainMoveRegardlessOfFit
6096 | kWindowConstrainAllowPartial, NULL, NULL);
6097 f->output_data.mac->toolbar_win_gravity = 0;
6100 out:
6101 UNBLOCK_INPUT;
6104 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6105 doesn't deallocate the resources. */
6107 void
6108 free_frame_tool_bar (f)
6109 FRAME_PTR f;
6111 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f)))
6113 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6115 BLOCK_INPUT;
6116 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), false,
6117 f == mac_focus_frame (dpyinfo));
6118 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6119 on toolbar visibility change. */
6120 mac_handle_origin_change (f);
6121 UNBLOCK_INPUT;
6125 static void
6126 mac_tool_bar_note_mouse_movement (f, event)
6127 struct frame *f;
6128 EventRef event;
6130 OSStatus err;
6131 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6132 int mouse_down_p;
6133 HIViewRef item_view;
6134 UInt32 command_id;
6136 mouse_down_p = (dpyinfo->grabbed
6137 && f == last_mouse_frame
6138 && FRAME_LIVE_P (f));
6139 if (mouse_down_p)
6140 return;
6142 err = HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f)),
6143 event, &item_view);
6144 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6145 toolbar item view seems to have the same command ID with that of
6146 the toolbar item. */
6147 if (err == noErr)
6148 err = GetControlCommandID (item_view, &command_id);
6149 if (err == noErr && TOOLBAR_ITEM_COMMAND_ID_P (command_id))
6151 int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id);
6153 if (i < f->n_tool_bar_items)
6155 HIRect bounds;
6156 HIViewRef content_view;
6158 err = HIViewGetBounds (item_view, &bounds);
6159 if (err == noErr)
6160 err = HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f)),
6161 kHIViewWindowContentID, &content_view);
6162 if (err == noErr)
6163 err = HIViewConvertRect (&bounds, item_view, content_view);
6164 if (err == noErr)
6165 SetRect (&last_mouse_glyph,
6166 CGRectGetMinX (bounds), CGRectGetMinY (bounds),
6167 CGRectGetMaxX (bounds), CGRectGetMaxY (bounds));
6169 help_echo_object = help_echo_window = Qnil;
6170 help_echo_pos = -1;
6171 help_echo_string = PROP (TOOL_BAR_ITEM_HELP);
6172 if (NILP (help_echo_string))
6173 help_echo_string = PROP (TOOL_BAR_ITEM_CAPTION);
6178 static OSStatus
6179 mac_handle_toolbar_command_event (next_handler, event, data)
6180 EventHandlerCallRef next_handler;
6181 EventRef event;
6182 void *data;
6184 OSStatus err, result = eventNotHandledErr;
6185 struct frame *f = (struct frame *) data;
6186 HICommand command;
6188 err = GetEventParameter (event, kEventParamDirectObject,
6189 typeHICommand, NULL,
6190 sizeof (HICommand), NULL, &command);
6191 if (err != noErr)
6192 return result;
6194 switch (GetEventKind (event))
6196 case kEventCommandProcess:
6197 if (!TOOLBAR_ITEM_COMMAND_ID_P (command.commandID))
6198 result = CallNextEventHandler (next_handler, event);
6199 else
6201 int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command.commandID);
6203 if (i < f->n_tool_bar_items
6204 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)))
6206 Lisp_Object frame;
6207 struct input_event buf;
6209 EVENT_INIT (buf);
6211 XSETFRAME (frame, f);
6212 buf.kind = TOOL_BAR_EVENT;
6213 buf.frame_or_window = frame;
6214 buf.arg = frame;
6215 kbd_buffer_store_event (&buf);
6217 buf.kind = TOOL_BAR_EVENT;
6218 buf.frame_or_window = frame;
6219 buf.arg = PROP (TOOL_BAR_ITEM_KEY);
6220 buf.modifiers = mac_event_to_emacs_modifiers (event);
6221 kbd_buffer_store_event (&buf);
6223 result = noErr;
6226 break;
6228 default:
6229 abort ();
6231 #undef PROP
6233 return result;
6235 #endif /* USE_MAC_TOOLBAR */
6238 /***********************************************************************
6239 Text Cursor
6240 ***********************************************************************/
6242 /* Set clipping for output in glyph row ROW. W is the window in which
6243 we operate. GC is the graphics context to set clipping in.
6245 ROW may be a text row or, e.g., a mode line. Text rows must be
6246 clipped to the interior of the window dedicated to text display,
6247 mode lines must be clipped to the whole window. */
6249 static void
6250 x_clip_to_row (w, row, area, gc)
6251 struct window *w;
6252 struct glyph_row *row;
6253 int area;
6254 GC gc;
6256 struct frame *f = XFRAME (WINDOW_FRAME (w));
6257 Rect clip_rect;
6258 int window_x, window_y, window_width;
6260 window_box (w, area, &window_x, &window_y, &window_width, 0);
6262 clip_rect.left = window_x;
6263 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
6264 clip_rect.top = max (clip_rect.top, window_y);
6265 clip_rect.right = clip_rect.left + window_width;
6266 clip_rect.bottom = clip_rect.top + row->visible_height;
6268 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
6272 /* Draw a hollow box cursor on window W in glyph row ROW. */
6274 static void
6275 x_draw_hollow_cursor (w, row)
6276 struct window *w;
6277 struct glyph_row *row;
6279 struct frame *f = XFRAME (WINDOW_FRAME (w));
6280 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6281 Display *dpy = FRAME_MAC_DISPLAY (f);
6282 int x, y, wd, h;
6283 XGCValues xgcv;
6284 struct glyph *cursor_glyph;
6285 GC gc;
6287 /* Get the glyph the cursor is on. If we can't tell because
6288 the current matrix is invalid or such, give up. */
6289 cursor_glyph = get_phys_cursor_glyph (w);
6290 if (cursor_glyph == NULL)
6291 return;
6293 /* Compute frame-relative coordinates for phys cursor. */
6294 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
6295 wd = w->phys_cursor_width;
6297 /* The foreground of cursor_gc is typically the same as the normal
6298 background color, which can cause the cursor box to be invisible. */
6299 xgcv.foreground = f->output_data.mac->cursor_pixel;
6300 if (dpyinfo->scratch_cursor_gc)
6301 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
6302 else
6303 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
6304 GCForeground, &xgcv);
6305 gc = dpyinfo->scratch_cursor_gc;
6307 /* Set clipping, draw the rectangle, and reset clipping again. */
6308 x_clip_to_row (w, row, TEXT_AREA, gc);
6309 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
6310 mac_reset_clip_rectangles (dpy, gc);
6314 /* Draw a bar cursor on window W in glyph row ROW.
6316 Implementation note: One would like to draw a bar cursor with an
6317 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6318 Unfortunately, I didn't find a font yet that has this property set.
6319 --gerd. */
6321 static void
6322 x_draw_bar_cursor (w, row, width, kind)
6323 struct window *w;
6324 struct glyph_row *row;
6325 int width;
6326 enum text_cursor_kinds kind;
6328 struct frame *f = XFRAME (w->frame);
6329 struct glyph *cursor_glyph;
6331 /* If cursor is out of bounds, don't draw garbage. This can happen
6332 in mini-buffer windows when switching between echo area glyphs
6333 and mini-buffer. */
6334 cursor_glyph = get_phys_cursor_glyph (w);
6335 if (cursor_glyph == NULL)
6336 return;
6338 /* If on an image, draw like a normal cursor. That's usually better
6339 visible than drawing a bar, esp. if the image is large so that
6340 the bar might not be in the window. */
6341 if (cursor_glyph->type == IMAGE_GLYPH)
6343 struct glyph_row *row;
6344 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
6345 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
6347 else
6349 Display *dpy = FRAME_MAC_DISPLAY (f);
6350 Window window = FRAME_MAC_WINDOW (f);
6351 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
6352 unsigned long mask = GCForeground | GCBackground;
6353 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
6354 XGCValues xgcv;
6356 /* If the glyph's background equals the color we normally draw
6357 the bar cursor in, the bar cursor in its normal color is
6358 invisible. Use the glyph's foreground color instead in this
6359 case, on the assumption that the glyph's colors are chosen so
6360 that the glyph is legible. */
6361 if (face->background == f->output_data.mac->cursor_pixel)
6362 xgcv.background = xgcv.foreground = face->foreground;
6363 else
6364 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
6366 if (gc)
6367 XChangeGC (dpy, gc, mask, &xgcv);
6368 else
6370 gc = XCreateGC (dpy, window, mask, &xgcv);
6371 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
6374 if (width < 0)
6375 width = FRAME_CURSOR_WIDTH (f);
6376 width = min (cursor_glyph->pixel_width, width);
6378 w->phys_cursor_width = width;
6379 x_clip_to_row (w, row, TEXT_AREA, gc);
6381 if (kind == BAR_CURSOR)
6382 mac_fill_rectangle (f, gc,
6383 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
6384 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
6385 width, row->height);
6386 else
6387 mac_fill_rectangle (f, gc,
6388 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
6389 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
6390 row->height - width),
6391 cursor_glyph->pixel_width,
6392 width);
6394 mac_reset_clip_rectangles (dpy, gc);
6399 /* RIF: Define cursor CURSOR on frame F. */
6401 static void
6402 mac_define_frame_cursor (f, cursor)
6403 struct frame *f;
6404 Cursor cursor;
6406 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6408 if (dpyinfo->x_focus_frame == f)
6409 SetThemeCursor (cursor);
6413 /* RIF: Clear area on frame F. */
6415 static void
6416 mac_clear_frame_area (f, x, y, width, height)
6417 struct frame *f;
6418 int x, y, width, height;
6420 mac_clear_area (f, x, y, width, height);
6424 /* RIF: Draw cursor on window W. */
6426 static void
6427 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
6428 struct window *w;
6429 struct glyph_row *glyph_row;
6430 int x, y;
6431 int cursor_type, cursor_width;
6432 int on_p, active_p;
6434 if (on_p)
6436 w->phys_cursor_type = cursor_type;
6437 w->phys_cursor_on_p = 1;
6439 if (glyph_row->exact_window_width_line_p
6440 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
6442 glyph_row->cursor_in_fringe_p = 1;
6443 draw_fringe_bitmap (w, glyph_row, 0);
6445 else
6446 switch (cursor_type)
6448 case HOLLOW_BOX_CURSOR:
6449 x_draw_hollow_cursor (w, glyph_row);
6450 break;
6452 case FILLED_BOX_CURSOR:
6453 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
6454 break;
6456 case BAR_CURSOR:
6457 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
6458 break;
6460 case HBAR_CURSOR:
6461 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
6462 break;
6464 case NO_CURSOR:
6465 w->phys_cursor_width = 0;
6466 break;
6468 default:
6469 abort ();
6475 /* Icons. */
6477 #if 0 /* MAC_TODO: no icon support yet. */
6479 x_bitmap_icon (f, icon)
6480 struct frame *f;
6481 Lisp_Object icon;
6483 HANDLE hicon;
6485 if (FRAME_W32_WINDOW (f) == 0)
6486 return 1;
6488 if (NILP (icon))
6489 hicon = LoadIcon (hinst, EMACS_CLASS);
6490 else if (STRINGP (icon))
6491 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
6492 LR_DEFAULTSIZE | LR_LOADFROMFILE);
6493 else if (SYMBOLP (icon))
6495 LPCTSTR name;
6497 if (EQ (icon, intern ("application")))
6498 name = (LPCTSTR) IDI_APPLICATION;
6499 else if (EQ (icon, intern ("hand")))
6500 name = (LPCTSTR) IDI_HAND;
6501 else if (EQ (icon, intern ("question")))
6502 name = (LPCTSTR) IDI_QUESTION;
6503 else if (EQ (icon, intern ("exclamation")))
6504 name = (LPCTSTR) IDI_EXCLAMATION;
6505 else if (EQ (icon, intern ("asterisk")))
6506 name = (LPCTSTR) IDI_ASTERISK;
6507 else if (EQ (icon, intern ("winlogo")))
6508 name = (LPCTSTR) IDI_WINLOGO;
6509 else
6510 return 1;
6512 hicon = LoadIcon (NULL, name);
6514 else
6515 return 1;
6517 if (hicon == NULL)
6518 return 1;
6520 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
6521 (LPARAM) hicon);
6523 return 0;
6525 #endif /* MAC_TODO */
6527 /************************************************************************
6528 Handling X errors
6529 ************************************************************************/
6531 /* Display Error Handling functions not used on W32. Listing them here
6532 helps diff stay in step when comparing w32term.c with xterm.c.
6534 x_error_catcher (display, error)
6535 x_catch_errors (dpy)
6536 x_catch_errors_unwind (old_val)
6537 x_check_errors (dpy, format)
6538 x_had_errors_p (dpy)
6539 x_clear_errors (dpy)
6540 x_uncatch_errors (dpy, count)
6541 x_trace_wire ()
6542 x_connection_signal (signalnum)
6543 x_connection_closed (dpy, error_message)
6544 x_error_quitter (display, error)
6545 x_error_handler (display, error)
6546 x_io_error_quitter (display)
6551 /* Changing the font of the frame. */
6553 /* Give frame F the font named FONTNAME as its default font, and
6554 return the full name of that font. FONTNAME may be a wildcard
6555 pattern; in that case, we choose some font that fits the pattern.
6556 The return value shows which font we chose. */
6558 Lisp_Object
6559 x_new_font (f, fontname)
6560 struct frame *f;
6561 register char *fontname;
6563 struct font_info *fontp
6564 = FS_LOAD_FONT (f, 0, fontname, -1);
6566 if (!fontp)
6567 return Qnil;
6569 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
6570 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
6571 FRAME_FONTSET (f) = -1;
6573 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
6574 FRAME_SPACE_WIDTH (f) = fontp->space_width;
6575 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
6577 compute_fringe_widths (f, 1);
6579 /* Compute the scroll bar width in character columns. */
6580 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
6582 int wid = FRAME_COLUMN_WIDTH (f);
6583 FRAME_CONFIG_SCROLL_BAR_COLS (f)
6584 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
6586 else
6588 int wid = FRAME_COLUMN_WIDTH (f);
6589 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
6592 /* Now make the frame display the given font. */
6593 if (FRAME_MAC_WINDOW (f) != 0)
6595 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
6596 FRAME_FONT (f));
6597 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
6598 FRAME_FONT (f));
6599 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
6600 FRAME_FONT (f));
6602 /* Don't change the size of a tip frame; there's no point in
6603 doing it because it's done in Fx_show_tip, and it leads to
6604 problems because the tip frame has no widget. */
6605 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
6606 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
6609 return build_string (fontp->full_name);
6612 /* Give frame F the fontset named FONTSETNAME as its default font, and
6613 return the full name of that fontset. FONTSETNAME may be a wildcard
6614 pattern; in that case, we choose some fontset that fits the pattern.
6615 The return value shows which fontset we chose. */
6617 Lisp_Object
6618 x_new_fontset (f, fontsetname)
6619 struct frame *f;
6620 char *fontsetname;
6622 int fontset = fs_query_fontset (build_string (fontsetname), 0);
6623 Lisp_Object result;
6625 if (fontset < 0)
6626 return Qnil;
6628 if (FRAME_FONTSET (f) == fontset)
6629 /* This fontset is already set in frame F. There's nothing more
6630 to do. */
6631 return fontset_name (fontset);
6633 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
6635 if (!STRINGP (result))
6636 /* Can't load ASCII font. */
6637 return Qnil;
6639 /* Since x_new_font doesn't update any fontset information, do it now. */
6640 FRAME_FONTSET (f) = fontset;
6642 return build_string (fontsetname);
6646 /***********************************************************************
6647 TODO: W32 Input Methods
6648 ***********************************************************************/
6649 /* Listing missing functions from xterm.c helps diff stay in step.
6651 xim_destroy_callback (xim, client_data, call_data)
6652 xim_open_dpy (dpyinfo, resource_name)
6653 struct xim_inst_t
6654 xim_instantiate_callback (display, client_data, call_data)
6655 xim_initialize (dpyinfo, resource_name)
6656 xim_close_dpy (dpyinfo)
6661 void
6662 mac_get_window_bounds (f, inner, outer)
6663 struct frame *f;
6664 Rect *inner, *outer;
6666 #if TARGET_API_MAC_CARBON
6667 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
6668 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
6669 #else /* not TARGET_API_MAC_CARBON */
6670 RgnHandle region = NewRgn ();
6672 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
6673 *inner = (*region)->rgnBBox;
6674 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
6675 *outer = (*region)->rgnBBox;
6676 DisposeRgn (region);
6677 #endif /* not TARGET_API_MAC_CARBON */
6680 static void
6681 mac_handle_origin_change (f)
6682 struct frame *f;
6684 x_real_positions (f, &f->left_pos, &f->top_pos);
6687 static void
6688 mac_handle_size_change (f, pixelwidth, pixelheight)
6689 struct frame *f;
6690 int pixelwidth, pixelheight;
6692 int cols, rows;
6694 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
6695 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
6697 if (cols != FRAME_COLS (f)
6698 || rows != FRAME_LINES (f)
6699 || pixelwidth != FRAME_PIXEL_WIDTH (f)
6700 || pixelheight != FRAME_PIXEL_HEIGHT (f))
6702 /* We pass 1 for DELAY since we can't run Lisp code inside of
6703 a BLOCK_INPUT. */
6704 change_frame_size (f, rows, cols, 0, 1, 0);
6705 FRAME_PIXEL_WIDTH (f) = pixelwidth;
6706 FRAME_PIXEL_HEIGHT (f) = pixelheight;
6707 SET_FRAME_GARBAGED (f);
6709 /* If cursor was outside the new size, mark it as off. */
6710 mark_window_cursors_off (XWINDOW (f->root_window));
6712 /* Clear out any recollection of where the mouse highlighting
6713 was, since it might be in a place that's outside the new
6714 frame size. Actually checking whether it is outside is a
6715 pain in the neck, so don't try--just let the highlighting be
6716 done afresh with new size. */
6717 cancel_mouse_face (f);
6719 #if TARGET_API_MAC_CARBON
6720 if (f->output_data.mac->hourglass_control)
6722 #if USE_CG_DRAWING
6723 mac_prepare_for_quickdraw (f);
6724 #endif
6725 MoveControl (f->output_data.mac->hourglass_control,
6726 pixelwidth - HOURGLASS_WIDTH, 0);
6728 #endif
6733 /* Calculate the absolute position in frame F
6734 from its current recorded position values and gravity. */
6736 void
6737 x_calc_absolute_position (f)
6738 struct frame *f;
6740 int width_diff = 0, height_diff = 0;
6741 int flags = f->size_hint_flags;
6742 Rect inner, outer;
6744 /* We have nothing to do if the current position
6745 is already for the top-left corner. */
6746 if (! ((flags & XNegative) || (flags & YNegative)))
6747 return;
6749 /* Find the offsets of the outside upper-left corner of
6750 the inner window, with respect to the outer window. */
6751 BLOCK_INPUT;
6752 mac_get_window_bounds (f, &inner, &outer);
6753 UNBLOCK_INPUT;
6755 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
6756 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
6758 /* Treat negative positions as relative to the leftmost bottommost
6759 position that fits on the screen. */
6760 if (flags & XNegative)
6761 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
6762 - width_diff
6763 - FRAME_PIXEL_WIDTH (f)
6764 + f->left_pos);
6766 if (flags & YNegative)
6767 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
6768 - height_diff
6769 - FRAME_PIXEL_HEIGHT (f)
6770 + f->top_pos);
6772 /* The left_pos and top_pos
6773 are now relative to the top and left screen edges,
6774 so the flags should correspond. */
6775 f->size_hint_flags &= ~ (XNegative | YNegative);
6778 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6779 to really change the position, and 0 when calling from
6780 x_make_frame_visible (in that case, XOFF and YOFF are the current
6781 position values). It is -1 when calling from x_set_frame_parameters,
6782 which means, do adjust for borders but don't change the gravity. */
6784 void
6785 x_set_offset (f, xoff, yoff, change_gravity)
6786 struct frame *f;
6787 register int xoff, yoff;
6788 int change_gravity;
6790 if (change_gravity > 0)
6792 f->top_pos = yoff;
6793 f->left_pos = xoff;
6794 f->size_hint_flags &= ~ (XNegative | YNegative);
6795 if (xoff < 0)
6796 f->size_hint_flags |= XNegative;
6797 if (yoff < 0)
6798 f->size_hint_flags |= YNegative;
6799 f->win_gravity = NorthWestGravity;
6801 x_calc_absolute_position (f);
6803 BLOCK_INPUT;
6804 x_wm_set_size_hint (f, (long) 0, 0);
6806 #if TARGET_API_MAC_CARBON
6807 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
6808 /* If the title bar is completely outside the screen, adjust the
6809 position. */
6810 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
6811 kWindowConstrainMoveRegardlessOfFit
6812 | kWindowConstrainAllowPartial, NULL, NULL);
6813 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
6814 mac_handle_origin_change (f);
6815 #else
6817 Rect inner, outer, screen_rect, dummy;
6818 RgnHandle region = NewRgn ();
6820 mac_get_window_bounds (f, &inner, &outer);
6821 f->x_pixels_diff = inner.left - outer.left;
6822 f->y_pixels_diff = inner.top - outer.top;
6823 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6824 f->top_pos + f->y_pixels_diff, false);
6826 /* If the title bar is completely outside the screen, adjust the
6827 position. The variable `outer' holds the title bar rectangle.
6828 The variable `inner' holds slightly smaller one than `outer',
6829 so that the calculation of overlapping may not become too
6830 strict. */
6831 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
6832 outer = (*region)->rgnBBox;
6833 DisposeRgn (region);
6834 inner = outer;
6835 InsetRect (&inner, 8, 8);
6836 screen_rect = qd.screenBits.bounds;
6837 screen_rect.top += GetMBarHeight ();
6839 if (!SectRect (&inner, &screen_rect, &dummy))
6841 if (inner.right <= screen_rect.left)
6842 f->left_pos = screen_rect.left;
6843 else if (inner.left >= screen_rect.right)
6844 f->left_pos = screen_rect.right - (outer.right - outer.left);
6846 if (inner.bottom <= screen_rect.top)
6847 f->top_pos = screen_rect.top;
6848 else if (inner.top >= screen_rect.bottom)
6849 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
6851 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6852 f->top_pos + f->y_pixels_diff, false);
6855 #endif
6857 UNBLOCK_INPUT;
6860 /* Call this to change the size of frame F's x-window.
6861 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6862 for this size change and subsequent size changes.
6863 Otherwise we leave the window gravity unchanged. */
6865 void
6866 x_set_window_size (f, change_gravity, cols, rows)
6867 struct frame *f;
6868 int change_gravity;
6869 int cols, rows;
6871 int pixelwidth, pixelheight;
6873 BLOCK_INPUT;
6875 check_frame_size (f, &rows, &cols);
6876 f->scroll_bar_actual_width
6877 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
6879 compute_fringe_widths (f, 0);
6881 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
6882 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
6884 f->win_gravity = NorthWestGravity;
6885 x_wm_set_size_hint (f, (long) 0, 0);
6887 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
6889 #if TARGET_API_MAC_CARBON
6890 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
6891 #endif
6892 mac_handle_size_change (f, pixelwidth, pixelheight);
6894 if (f->output_data.mac->internal_border_width
6895 != FRAME_INTERNAL_BORDER_WIDTH (f))
6897 mac_clear_window (f);
6898 f->output_data.mac->internal_border_width
6899 = FRAME_INTERNAL_BORDER_WIDTH (f);
6902 SET_FRAME_GARBAGED (f);
6904 UNBLOCK_INPUT;
6907 /* Mouse warping. */
6909 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
6911 void
6912 x_set_mouse_position (f, x, y)
6913 struct frame *f;
6914 int x, y;
6916 int pix_x, pix_y;
6918 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
6919 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
6921 if (pix_x < 0) pix_x = 0;
6922 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
6924 if (pix_y < 0) pix_y = 0;
6925 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
6927 x_set_mouse_pixel_position (f, pix_x, pix_y);
6930 void
6931 x_set_mouse_pixel_position (f, pix_x, pix_y)
6932 struct frame *f;
6933 int pix_x, pix_y;
6935 #ifdef MAC_OSX
6936 pix_x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
6937 pix_y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
6939 BLOCK_INPUT;
6940 CGWarpMouseCursorPosition (CGPointMake (pix_x, pix_y));
6941 UNBLOCK_INPUT;
6942 #else
6943 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6944 BLOCK_INPUT;
6946 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
6947 0, 0, 0, 0, pix_x, pix_y);
6948 UNBLOCK_INPUT;
6949 #endif
6950 #endif
6953 /* focus shifting, raising and lowering. */
6955 void
6956 x_focus_on_frame (f)
6957 struct frame *f;
6959 #if 0 /* This proves to be unpleasant. */
6960 x_raise_frame (f);
6961 #endif
6962 #if 0
6963 /* I don't think that the ICCCM allows programs to do things like this
6964 without the interaction of the window manager. Whatever you end up
6965 doing with this code, do it to x_unfocus_frame too. */
6966 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6967 RevertToPointerRoot, CurrentTime);
6968 #endif /* ! 0 */
6971 void
6972 x_unfocus_frame (f)
6973 struct frame *f;
6977 /* Raise frame F. */
6979 void
6980 x_raise_frame (f)
6981 struct frame *f;
6983 if (f->async_visible)
6985 BLOCK_INPUT;
6986 BringToFront (FRAME_MAC_WINDOW (f));
6987 UNBLOCK_INPUT;
6991 /* Lower frame F. */
6993 void
6994 x_lower_frame (f)
6995 struct frame *f;
6997 if (f->async_visible)
6999 BLOCK_INPUT;
7000 SendBehind (FRAME_MAC_WINDOW (f), NULL);
7001 UNBLOCK_INPUT;
7005 static void
7006 XTframe_raise_lower (f, raise_flag)
7007 FRAME_PTR f;
7008 int raise_flag;
7010 if (raise_flag)
7011 x_raise_frame (f);
7012 else
7013 x_lower_frame (f);
7016 /* Change of visibility. */
7018 static void
7019 mac_handle_visibility_change (f)
7020 struct frame *f;
7022 WindowRef wp = FRAME_MAC_WINDOW (f);
7023 int visible = 0, iconified = 0;
7024 struct input_event buf;
7026 if (IsWindowVisible (wp))
7028 if (IsWindowCollapsed (wp))
7029 iconified = 1;
7030 else
7031 visible = 1;
7034 if (!f->async_visible && visible)
7036 if (f->iconified)
7038 /* wait_reading_process_output will notice this and update
7039 the frame's display structures. If we were made
7040 invisible, we should not set garbaged, because that stops
7041 redrawing on Update events. */
7042 SET_FRAME_GARBAGED (f);
7044 EVENT_INIT (buf);
7045 buf.kind = DEICONIFY_EVENT;
7046 XSETFRAME (buf.frame_or_window, f);
7047 buf.arg = Qnil;
7048 kbd_buffer_store_event (&buf);
7050 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
7051 /* Force a redisplay sooner or later to update the
7052 frame titles in case this is the second frame. */
7053 record_asynch_buffer_change ();
7055 else if (f->async_visible && !visible)
7056 if (iconified)
7058 EVENT_INIT (buf);
7059 buf.kind = ICONIFY_EVENT;
7060 XSETFRAME (buf.frame_or_window, f);
7061 buf.arg = Qnil;
7062 kbd_buffer_store_event (&buf);
7065 f->async_visible = visible;
7066 f->async_iconified = iconified;
7069 /* This tries to wait until the frame is really visible.
7070 However, if the window manager asks the user where to position
7071 the frame, this will return before the user finishes doing that.
7072 The frame will not actually be visible at that time,
7073 but it will become visible later when the window manager
7074 finishes with it. */
7076 void
7077 x_make_frame_visible (f)
7078 struct frame *f;
7080 BLOCK_INPUT;
7082 if (! FRAME_VISIBLE_P (f))
7084 /* We test FRAME_GARBAGED_P here to make sure we don't
7085 call x_set_offset a second time
7086 if we get to x_make_frame_visible a second time
7087 before the window gets really visible. */
7088 if (! FRAME_ICONIFIED_P (f)
7089 && ! f->output_data.mac->asked_for_visible)
7090 x_set_offset (f, f->left_pos, f->top_pos, 0);
7092 f->output_data.mac->asked_for_visible = 1;
7094 CollapseWindow (FRAME_MAC_WINDOW (f), false);
7095 ShowWindow (FRAME_MAC_WINDOW (f));
7098 XFlush (FRAME_MAC_DISPLAY (f));
7100 /* Synchronize to ensure Emacs knows the frame is visible
7101 before we do anything else. We do this loop with input not blocked
7102 so that incoming events are handled. */
7104 Lisp_Object frame;
7105 int count;
7107 /* This must come after we set COUNT. */
7108 UNBLOCK_INPUT;
7110 XSETFRAME (frame, f);
7112 /* Wait until the frame is visible. Process X events until a
7113 MapNotify event has been seen, or until we think we won't get a
7114 MapNotify at all.. */
7115 for (count = input_signal_count + 10;
7116 input_signal_count < count && !FRAME_VISIBLE_P (f);)
7118 /* Force processing of queued events. */
7119 x_sync (f);
7121 /* Machines that do polling rather than SIGIO have been
7122 observed to go into a busy-wait here. So we'll fake an
7123 alarm signal to let the handler know that there's something
7124 to be read. We used to raise a real alarm, but it seems
7125 that the handler isn't always enabled here. This is
7126 probably a bug. */
7127 if (input_polling_used ())
7129 /* It could be confusing if a real alarm arrives while
7130 processing the fake one. Turn it off and let the
7131 handler reset it. */
7132 extern void poll_for_input_1 P_ ((void));
7133 int old_poll_suppress_count = poll_suppress_count;
7134 poll_suppress_count = 1;
7135 poll_for_input_1 ();
7136 poll_suppress_count = old_poll_suppress_count;
7139 /* See if a MapNotify event has been processed. */
7140 FRAME_SAMPLE_VISIBILITY (f);
7145 /* Change from mapped state to withdrawn state. */
7147 /* Make the frame visible (mapped and not iconified). */
7149 void
7150 x_make_frame_invisible (f)
7151 struct frame *f;
7153 /* A deactivate event does not occur when the last visible frame is
7154 made invisible. So if we clear the highlight here, it will not
7155 be rehighlighted when it is made visible. */
7156 #if 0
7157 /* Don't keep the highlight on an invisible frame. */
7158 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
7159 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
7160 #endif
7162 BLOCK_INPUT;
7164 #if !TARGET_API_MAC_CARBON
7165 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7166 that the current position of the window is user-specified, rather than
7167 program-specified, so that when the window is mapped again, it will be
7168 placed at the same location, without forcing the user to position it
7169 by hand again (they have already done that once for this window.) */
7170 x_wm_set_size_hint (f, (long) 0, 1);
7171 #endif
7173 HideWindow (FRAME_MAC_WINDOW (f));
7175 UNBLOCK_INPUT;
7177 #if !TARGET_API_MAC_CARBON
7178 mac_handle_visibility_change (f);
7179 #endif
7182 /* Change window state from mapped to iconified. */
7184 void
7185 x_iconify_frame (f)
7186 struct frame *f;
7188 OSStatus err;
7190 /* A deactivate event does not occur when the last visible frame is
7191 iconified. So if we clear the highlight here, it will not be
7192 rehighlighted when it is deiconified. */
7193 #if 0
7194 /* Don't keep the highlight on an invisible frame. */
7195 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
7196 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
7197 #endif
7199 if (f->async_iconified)
7200 return;
7202 BLOCK_INPUT;
7204 FRAME_SAMPLE_VISIBILITY (f);
7206 if (! FRAME_VISIBLE_P (f))
7207 ShowWindow (FRAME_MAC_WINDOW (f));
7209 err = CollapseWindow (FRAME_MAC_WINDOW (f), true);
7211 UNBLOCK_INPUT;
7213 if (err != noErr)
7214 error ("Can't notify window manager of iconification");
7216 #if !TARGET_API_MAC_CARBON
7217 mac_handle_visibility_change (f);
7218 #endif
7222 /* Free X resources of frame F. */
7224 void
7225 x_free_frame_resources (f)
7226 struct frame *f;
7228 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7229 WindowRef wp = FRAME_MAC_WINDOW (f);
7231 BLOCK_INPUT;
7233 if (wp != tip_window)
7234 remove_window_handler (wp);
7236 #if USE_CG_DRAWING
7237 mac_prepare_for_quickdraw (f);
7238 #endif
7239 DisposeWindow (wp);
7240 if (wp == tip_window)
7241 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7242 closed' event. So we reset tip_window here. */
7243 tip_window = NULL;
7245 free_frame_menubar (f);
7247 if (FRAME_FACE_CACHE (f))
7248 free_frame_faces (f);
7250 x_free_gcs (f);
7252 if (FRAME_SIZE_HINTS (f))
7253 xfree (FRAME_SIZE_HINTS (f));
7255 xfree (f->output_data.mac);
7256 f->output_data.mac = NULL;
7258 if (f == dpyinfo->x_focus_frame)
7260 dpyinfo->x_focus_frame = 0;
7261 #if USE_MAC_FONT_PANEL
7262 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
7263 #endif
7265 if (f == dpyinfo->x_focus_event_frame)
7266 dpyinfo->x_focus_event_frame = 0;
7267 if (f == dpyinfo->x_highlight_frame)
7268 dpyinfo->x_highlight_frame = 0;
7270 if (f == dpyinfo->mouse_face_mouse_frame)
7272 dpyinfo->mouse_face_beg_row
7273 = dpyinfo->mouse_face_beg_col = -1;
7274 dpyinfo->mouse_face_end_row
7275 = dpyinfo->mouse_face_end_col = -1;
7276 dpyinfo->mouse_face_window = Qnil;
7277 dpyinfo->mouse_face_deferred_gc = 0;
7278 dpyinfo->mouse_face_mouse_frame = 0;
7281 UNBLOCK_INPUT;
7285 /* Destroy the X window of frame F. */
7287 void
7288 x_destroy_window (f)
7289 struct frame *f;
7291 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7293 x_free_frame_resources (f);
7295 dpyinfo->reference_count--;
7299 /* Setting window manager hints. */
7301 /* Set the normal size hints for the window manager, for frame F.
7302 FLAGS is the flags word to use--or 0 meaning preserve the flags
7303 that the window now has.
7304 If USER_POSITION is nonzero, we set the USPosition
7305 flag (this is useful when FLAGS is 0). */
7306 void
7307 x_wm_set_size_hint (f, flags, user_position)
7308 struct frame *f;
7309 long flags;
7310 int user_position;
7312 int base_width, base_height, width_inc, height_inc;
7313 int min_rows = 0, min_cols = 0;
7314 XSizeHints *size_hints;
7316 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
7317 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
7318 width_inc = FRAME_COLUMN_WIDTH (f);
7319 height_inc = FRAME_LINE_HEIGHT (f);
7321 check_frame_size (f, &min_rows, &min_cols);
7323 size_hints = FRAME_SIZE_HINTS (f);
7324 if (size_hints == NULL)
7326 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
7327 bzero (size_hints, sizeof (XSizeHints));
7330 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
7331 size_hints->width_inc = width_inc;
7332 size_hints->height_inc = height_inc;
7333 size_hints->min_width = base_width + min_cols * width_inc;
7334 size_hints->min_height = base_height + min_rows * height_inc;
7335 size_hints->base_width = base_width;
7336 size_hints->base_height = base_height;
7338 if (flags)
7339 size_hints->flags = flags;
7340 else if (user_position)
7342 size_hints->flags &= ~ PPosition;
7343 size_hints->flags |= USPosition;
7347 #if 0 /* MAC_TODO: hide application instead of iconify? */
7348 /* Used for IconicState or NormalState */
7350 void
7351 x_wm_set_window_state (f, state)
7352 struct frame *f;
7353 int state;
7355 #ifdef USE_X_TOOLKIT
7356 Arg al[1];
7358 XtSetArg (al[0], XtNinitialState, state);
7359 XtSetValues (f->output_data.x->widget, al, 1);
7360 #else /* not USE_X_TOOLKIT */
7361 Window window = FRAME_X_WINDOW (f);
7363 f->output_data.x->wm_hints.flags |= StateHint;
7364 f->output_data.x->wm_hints.initial_state = state;
7366 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
7367 #endif /* not USE_X_TOOLKIT */
7370 void
7371 x_wm_set_icon_pixmap (f, pixmap_id)
7372 struct frame *f;
7373 int pixmap_id;
7375 Pixmap icon_pixmap;
7377 #ifndef USE_X_TOOLKIT
7378 Window window = FRAME_X_WINDOW (f);
7379 #endif
7381 if (pixmap_id > 0)
7383 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7384 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
7386 else
7388 /* It seems there is no way to turn off use of an icon pixmap.
7389 The following line does it, only if no icon has yet been created,
7390 for some window managers. But with mwm it crashes.
7391 Some people say it should clear the IconPixmapHint bit in this case,
7392 but that doesn't work, and the X consortium said it isn't the
7393 right thing at all. Since there is no way to win,
7394 best to explicitly give up. */
7395 #if 0
7396 f->output_data.x->wm_hints.icon_pixmap = None;
7397 #else
7398 return;
7399 #endif
7402 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7405 Arg al[1];
7406 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
7407 XtSetValues (f->output_data.x->widget, al, 1);
7410 #else /* not USE_X_TOOLKIT */
7412 f->output_data.x->wm_hints.flags |= IconPixmapHint;
7413 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
7415 #endif /* not USE_X_TOOLKIT */
7418 #endif /* MAC_TODO */
7420 void
7421 x_wm_set_icon_position (f, icon_x, icon_y)
7422 struct frame *f;
7423 int icon_x, icon_y;
7425 #if 0 /* MAC_TODO: no icons on Mac */
7426 #ifdef USE_X_TOOLKIT
7427 Window window = XtWindow (f->output_data.x->widget);
7428 #else
7429 Window window = FRAME_X_WINDOW (f);
7430 #endif
7432 f->output_data.x->wm_hints.flags |= IconPositionHint;
7433 f->output_data.x->wm_hints.icon_x = icon_x;
7434 f->output_data.x->wm_hints.icon_y = icon_y;
7436 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
7437 #endif /* MAC_TODO */
7441 /***********************************************************************
7442 XLFD Pattern Match
7443 ***********************************************************************/
7445 /* An XLFD pattern is divided into blocks delimited by '*'. This
7446 structure holds information for each block. */
7447 struct xlfdpat_block
7449 /* Length of the pattern string in this block. Non-zero except for
7450 the first and the last blocks. */
7451 int len;
7453 /* Pattern string except the last character in this block. The last
7454 character is replaced with NUL in order to use it as a
7455 sentinel. */
7456 unsigned char *pattern;
7458 /* Last character of the pattern string. Must not be '?'. */
7459 unsigned char last_char;
7461 /* One of the tables for the Boyer-Moore string search. It
7462 specifies the number of positions to proceed for each character
7463 with which the match fails. */
7464 int skip[256];
7466 /* The skip value for the last character in the above `skip' is
7467 assigned to `infinity' in order to simplify a loop condition.
7468 The original value is saved here. */
7469 int last_char_skip;
7472 struct xlfdpat
7474 /* Normalized pattern string. "Normalized" means that capital
7475 letters are lowered, blocks are not empty except the first and
7476 the last ones, and trailing '?'s in a block that is not the last
7477 one are moved to the next one. The last character in each block
7478 is replaced with NUL. */
7479 unsigned char *buf;
7481 /* Number of characters except '*'s and trailing '?'s in the
7482 normalized pattern string. */
7483 int nchars;
7485 /* Number of trailing '?'s in the normalized pattern string. */
7486 int trailing_anychars;
7488 /* Number of blocks and information for each block. The latter is
7489 NULL if the pattern is exact (no '*' or '?' in it). */
7490 int nblocks;
7491 struct xlfdpat_block *blocks;
7494 static void
7495 xlfdpat_destroy (pat)
7496 struct xlfdpat *pat;
7498 if (pat)
7500 if (pat->buf)
7502 if (pat->blocks)
7503 xfree (pat->blocks);
7504 xfree (pat->buf);
7506 xfree (pat);
7510 static struct xlfdpat *
7511 xlfdpat_create (pattern)
7512 const char *pattern;
7514 struct xlfdpat *pat;
7515 int nblocks, i, skip;
7516 unsigned char last_char, *p, *q, *anychar_head;
7517 const unsigned char *ptr;
7518 struct xlfdpat_block *blk;
7520 pat = xmalloc (sizeof (struct xlfdpat));
7521 pat->buf = xmalloc (strlen (pattern) + 1);
7523 /* Normalize the pattern string and store it to `pat->buf'. */
7524 nblocks = 0;
7525 anychar_head = NULL;
7526 q = pat->buf;
7527 last_char = '\0';
7528 for (ptr = pattern; *ptr; ptr++)
7530 unsigned char c = *ptr;
7532 if (c == '*')
7533 if (last_char == '*')
7534 /* ...a** -> ...a* */
7535 continue;
7536 else
7538 if (last_char == '?')
7540 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
7541 /* ...*??* -> ...*?? */
7542 continue;
7543 else
7544 /* ...a??* -> ...a*?? */
7546 *anychar_head++ = '*';
7547 c = '?';
7550 nblocks++;
7552 else if (c == '?')
7554 if (last_char != '?')
7555 anychar_head = q;
7557 else
7558 /* On Mac OS X 10.3, tolower also converts non-ASCII
7559 characters for some locales. */
7560 if (isascii (c))
7561 c = tolower (c);
7563 *q++ = last_char = c;
7565 *q = '\0';
7566 nblocks++;
7567 pat->nblocks = nblocks;
7568 if (last_char != '?')
7569 pat->trailing_anychars = 0;
7570 else
7572 pat->trailing_anychars = q - anychar_head;
7573 q = anychar_head;
7575 pat->nchars = q - pat->buf - (nblocks - 1);
7577 if (anychar_head == NULL && nblocks == 1)
7579 /* The pattern is exact. */
7580 pat->blocks = NULL;
7581 return pat;
7584 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
7586 /* Divide the normalized pattern into blocks. */
7587 p = pat->buf;
7588 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
7590 blk->pattern = p;
7591 while (*p != '*')
7592 p++;
7593 blk->len = p - blk->pattern;
7594 p++;
7596 blk->pattern = p;
7597 blk->len = q - blk->pattern;
7599 /* Setup a table for the Boyer-Moore string search. */
7600 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
7601 if (blk->len != 0)
7603 blk->last_char = blk->pattern[blk->len - 1];
7604 blk->pattern[blk->len - 1] = '\0';
7606 for (skip = 1; skip < blk->len; skip++)
7607 if (blk->pattern[blk->len - skip - 1] == '?')
7608 break;
7610 for (i = 0; i < 256; i++)
7611 blk->skip[i] = skip;
7613 p = blk->pattern + (blk->len - skip);
7614 while (--skip > 0)
7615 blk->skip[*p++] = skip;
7617 blk->last_char_skip = blk->skip[blk->last_char];
7620 return pat;
7623 static INLINE int
7624 xlfdpat_exact_p (pat)
7625 struct xlfdpat *pat;
7627 return pat->blocks == NULL;
7630 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7631 that the pattern in *BLK matches with its prefix. Return NULL
7632 there is no such strings. STRING must be lowered in advance. */
7634 static const char *
7635 xlfdpat_block_match_1 (blk, string, start_max)
7636 struct xlfdpat_block *blk;
7637 const unsigned char *string;
7638 int start_max;
7640 int start, infinity;
7641 unsigned char *p;
7642 const unsigned char *s;
7644 xassert (blk->len > 0);
7645 xassert (start_max + blk->len <= strlen (string));
7646 xassert (blk->last_char != '?');
7648 /* See the comments in the function `boyer_moore' (search.c) for the
7649 use of `infinity'. */
7650 infinity = start_max + blk->len + 1;
7651 blk->skip[blk->last_char] = infinity;
7653 start = 0;
7656 /* Check the last character of the pattern. */
7657 s = string + blk->len - 1;
7660 start += blk->skip[*(s + start)];
7662 while (start <= start_max);
7664 if (start < infinity)
7665 /* Couldn't find the last character. */
7666 return NULL;
7668 /* No less than `infinity' means we could find the last
7669 character at `s[start - infinity]'. */
7670 start -= infinity;
7672 /* Check the remaining characters. We prefer making no-'?'
7673 cases faster because the use of '?' is really rare. */
7674 p = blk->pattern;
7675 s = string + start;
7678 while (*p++ == *s++)
7681 while (*(p - 1) == '?');
7683 if (*(p - 1) == '\0')
7684 /* Matched. */
7685 return string + start;
7687 /* Didn't match. */
7688 start += blk->last_char_skip;
7690 while (start <= start_max);
7692 return NULL;
7695 #define xlfdpat_block_match(b, s, m) \
7696 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7697 : xlfdpat_block_match_1 (b, s, m))
7699 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7700 matches with STRING. STRING must be lowered in advance. */
7702 static int
7703 xlfdpat_match (pat, string)
7704 struct xlfdpat *pat;
7705 const unsigned char *string;
7707 int str_len, nblocks, i, start_max;
7708 struct xlfdpat_block *blk;
7709 const unsigned char *s;
7711 xassert (pat->nblocks > 0);
7713 if (xlfdpat_exact_p (pat))
7714 return strcmp (pat->buf, string) == 0;
7716 /* The number of the characters in the string must not be smaller
7717 than that in the pattern. */
7718 str_len = strlen (string);
7719 if (str_len < pat->nchars + pat->trailing_anychars)
7720 return 0;
7722 /* Chop off the trailing '?'s. */
7723 str_len -= pat->trailing_anychars;
7725 /* The last block. When it is non-empty, it must match at the end
7726 of the string. */
7727 nblocks = pat->nblocks;
7728 blk = pat->blocks + (nblocks - 1);
7729 if (nblocks == 1)
7730 /* The last block is also the first one. */
7731 return (str_len == blk->len
7732 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
7733 else if (blk->len != 0)
7734 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
7735 return 0;
7737 /* The first block. When it is non-empty, it must match at the
7738 beginning of the string. */
7739 blk = pat->blocks;
7740 if (blk->len != 0)
7742 s = xlfdpat_block_match (blk, string, 0);
7743 if (s == NULL)
7744 return 0;
7745 string = s + blk->len;
7748 /* The rest of the blocks. */
7749 start_max = str_len - pat->nchars;
7750 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
7752 s = xlfdpat_block_match (blk, string, start_max);
7753 if (s == NULL)
7754 return 0;
7755 start_max -= s - string;
7756 string = s + blk->len;
7759 return 1;
7763 /***********************************************************************
7764 Fonts
7765 ***********************************************************************/
7767 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7769 struct font_info *
7770 x_get_font_info (f, font_idx)
7771 FRAME_PTR f;
7772 int font_idx;
7774 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
7777 /* the global font name table */
7778 static char **font_name_table = NULL;
7779 static int font_name_table_size = 0;
7780 static int font_name_count = 0;
7782 /* Alist linking font family names to Font Manager font family
7783 references (which can also be used as QuickDraw font IDs). We use
7784 an alist because hash tables are not ready when the terminal frame
7785 for Mac OS Classic is created. */
7786 static Lisp_Object fm_font_family_alist;
7787 #if USE_ATSUI
7788 /* Hash table linking font family names to ATSU font IDs. */
7789 static Lisp_Object atsu_font_id_hash;
7790 /* Alist linking Font Manager style to face attributes. */
7791 static Lisp_Object fm_style_face_attributes_alist;
7792 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
7793 #endif
7795 /* Alist linking character set strings to Mac text encoding and Emacs
7796 coding system. */
7797 static Lisp_Object Vmac_charset_info_alist;
7799 static Lisp_Object
7800 create_text_encoding_info_alist ()
7802 Lisp_Object result = Qnil, rest;
7804 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
7806 Lisp_Object charset_info = XCAR (rest);
7807 Lisp_Object charset, coding_system, text_encoding;
7808 Lisp_Object existing_info;
7810 if (!(CONSP (charset_info)
7811 && (charset = XCAR (charset_info),
7812 STRINGP (charset))
7813 && CONSP (XCDR (charset_info))
7814 && (text_encoding = XCAR (XCDR (charset_info)),
7815 INTEGERP (text_encoding))
7816 && CONSP (XCDR (XCDR (charset_info)))
7817 && (coding_system = XCAR (XCDR (XCDR (charset_info))),
7818 SYMBOLP (coding_system))))
7819 continue;
7821 existing_info = assq_no_quit (text_encoding, result);
7822 if (NILP (existing_info))
7823 result = Fcons (list3 (text_encoding, coding_system, charset),
7824 result);
7825 else
7826 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
7827 XSETCDR (XCDR (existing_info),
7828 Fcons (charset, XCDR (XCDR (existing_info))));
7831 return result;
7835 static void
7836 decode_mac_font_name (name, size, coding_system)
7837 char *name;
7838 int size;
7839 Lisp_Object coding_system;
7841 struct coding_system coding;
7842 char *buf, *p;
7844 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
7846 for (p = name; *p; p++)
7847 if (!isascii (*p) || iscntrl (*p))
7848 break;
7850 if (*p)
7852 setup_coding_system (coding_system, &coding);
7853 coding.src_multibyte = 0;
7854 coding.dst_multibyte = 1;
7855 coding.mode |= CODING_MODE_LAST_BLOCK;
7856 coding.composing = COMPOSITION_DISABLED;
7857 buf = (char *) alloca (size);
7859 decode_coding (&coding, name, buf, strlen (name), size - 1);
7860 bcopy (buf, name, coding.produced);
7861 name[coding.produced] = '\0';
7865 /* If there's just one occurrence of '-' in the family name, it is
7866 replaced with '_'. (More than one occurrence of '-' means a
7867 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7868 p = strchr (name, '-');
7869 if (p && strchr (p + 1, '-') == NULL)
7870 *p = '_';
7872 for (p = name; *p; p++)
7873 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7874 for some locales. */
7875 if (isascii (*p))
7876 *p = tolower (*p);
7880 static char *
7881 mac_to_x_fontname (name, size, style, charset)
7882 const char *name;
7883 int size;
7884 Style style;
7885 char *charset;
7887 Str31 foundry, cs;
7888 Str255 family;
7889 char xf[256], *result;
7890 unsigned char *p;
7892 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
7893 charset = cs;
7894 else
7896 strcpy(foundry, "Apple");
7897 strcpy(family, name);
7900 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7901 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
7902 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
7904 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
7905 sprintf (result, "-%s-%s-%s", foundry, family, xf);
7906 for (p = result; *p; p++)
7907 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7908 for some locales. */
7909 if (isascii (*p))
7910 *p = tolower (*p);
7911 return result;
7915 /* Parse fully-specified and instantiated X11 font spec XF, and store
7916 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7917 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7918 caller must allocate at least 256 and 32 bytes respectively. For
7919 ordinary Mac fonts, the value stored to FAMILY should just be their
7920 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7921 intlfonts collection contain their charset designation in their
7922 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7923 types of font names are handled accordingly. */
7925 const int kDefaultFontSize = 12;
7927 static int
7928 parse_x_font_name (xf, family, size, style, charset)
7929 const char *xf;
7930 char *family;
7931 int *size;
7932 Style *style;
7933 char *charset;
7935 Str31 foundry, weight;
7936 int point_size, avgwidth;
7937 char slant[2], *p;
7939 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7940 foundry, family, weight, slant, size,
7941 &point_size, &avgwidth, charset) != 8
7942 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7943 foundry, family, weight, slant, size,
7944 &point_size, &avgwidth, charset) != 8)
7945 return 0;
7947 if (*size == 0)
7949 if (point_size > 0)
7950 *size = point_size / 10;
7951 else if (avgwidth > 0)
7952 *size = avgwidth / 10;
7954 if (*size == 0)
7955 *size = kDefaultFontSize;
7957 *style = normal;
7958 if (strcmp (weight, "bold") == 0)
7959 *style |= bold;
7960 if (*slant == 'i')
7961 *style |= italic;
7963 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
7965 int foundry_len = strlen (foundry), family_len = strlen (family);
7967 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
7969 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7970 but take overlap into account. */
7971 memmove (family + foundry_len + 1, family, family_len);
7972 memcpy (family, foundry, foundry_len);
7973 family[foundry_len] = '-';
7974 family[foundry_len + 1 + family_len] = '-';
7975 strcpy (family + foundry_len + 1 + family_len + 1, charset);
7977 else
7978 return 0;
7981 for (p = family; *p; p++)
7982 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7983 for some locales. */
7984 if (isascii (*p))
7985 *p = tolower (*p);
7987 return 1;
7991 static void
7992 add_font_name_table_entry (char *font_name)
7994 if (font_name_table_size == 0)
7996 font_name_table_size = 256;
7997 font_name_table = (char **)
7998 xmalloc (font_name_table_size * sizeof (char *));
8000 else if (font_name_count + 1 >= font_name_table_size)
8002 font_name_table_size *= 2;
8003 font_name_table = (char **)
8004 xrealloc (font_name_table,
8005 font_name_table_size * sizeof (char *));
8008 font_name_table[font_name_count++] = font_name;
8011 static void
8012 add_mac_font_name (name, size, style, charset)
8013 const char *name;
8014 int size;
8015 Style style;
8016 const char *charset;
8018 if (size > 0)
8019 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
8020 else
8022 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
8023 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
8024 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
8025 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
8026 charset));
8030 #if USE_ATSUI
8031 static FMFontStyle
8032 fm_get_style_from_font (font)
8033 FMFont font;
8035 OSStatus err;
8036 FMFontStyle style = normal;
8037 ByteCount len;
8038 UInt16 mac_style;
8039 FMFontFamily font_family;
8040 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8042 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8043 some font (e.g., Optima) even if it is `bold'. */
8044 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
8045 sizeof (mac_style), &mac_style, &len);
8046 if (err == noErr
8047 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
8048 style = EndianU16_BtoN (mac_style);
8049 else
8050 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
8052 return style;
8055 static ATSUFontID
8056 atsu_find_font_from_family_name (family)
8057 const char *family;
8059 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
8060 unsigned hash_code;
8061 int i;
8062 Lisp_Object rest, best;
8063 FMFontStyle min_style, style;
8065 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
8066 &hash_code);
8067 if (i < 0)
8068 return kATSUInvalidFontID;
8070 rest = HASH_VALUE (h, i);
8071 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
8072 return cons_to_long (rest);
8074 rest = Fnreverse (rest);
8075 best = XCAR (rest);
8076 rest = XCDR (rest);
8077 if (!NILP (rest)
8078 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
8081 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
8082 if (style < min_style)
8084 best = XCAR (rest);
8085 if (style == normal)
8086 break;
8087 else
8088 min_style = style;
8090 rest = XCDR (rest);
8092 while (!NILP (rest));
8094 HASH_VALUE (h, i) = best;
8095 return cons_to_long (best);
8098 static Lisp_Object
8099 fm_style_to_face_attributes (fm_style)
8100 FMFontStyle fm_style;
8102 Lisp_Object tem;
8104 fm_style &= (bold | italic);
8105 tem = assq_no_quit (make_number (fm_style),
8106 fm_style_face_attributes_alist);
8107 if (!NILP (tem))
8108 return XCDR (tem);
8110 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
8111 QCslant, fm_style & italic ? Qitalic : Qnormal);
8112 fm_style_face_attributes_alist =
8113 Fcons (Fcons (make_number (fm_style), tem),
8114 fm_style_face_attributes_alist);
8116 return tem;
8119 static Lisp_Object
8120 atsu_find_font_family_name (font_id)
8121 ATSUFontID font_id;
8123 OSStatus err;
8124 ByteCount len;
8125 Lisp_Object family = Qnil;
8127 err = ATSUFindFontName (font_id, kFontFamilyName,
8128 kFontMacintoshPlatform, kFontNoScript,
8129 kFontNoLanguage, 0, NULL, &len, NULL);
8130 if (err == noErr)
8132 family = make_uninit_string (len);
8133 err = ATSUFindFontName (font_id, kFontFamilyName,
8134 kFontMacintoshPlatform, kFontNoScript,
8135 kFontNoLanguage, len, SDATA (family),
8136 NULL, NULL);
8138 if (err == noErr)
8139 decode_mac_font_name (SDATA (family), len + 1, Qnil);
8141 return family;
8144 Lisp_Object
8145 mac_atsu_font_face_attributes (font_id)
8146 ATSUFontID font_id;
8148 Lisp_Object family, style_attrs;
8150 family = atsu_find_font_family_name (font_id);
8151 if (NILP (family))
8152 return Qnil;
8153 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
8154 return Fcons (QCfamily, Fcons (family, style_attrs));
8156 #endif
8158 /* Sets up the table font_name_table to contain the list of all fonts
8159 in the system the first time the table is used so that the Resource
8160 Manager need not be accessed every time this information is
8161 needed. */
8163 static void
8164 init_font_name_table ()
8166 #if TARGET_API_MAC_CARBON
8167 FMFontFamilyIterator ffi;
8168 FMFontFamilyInstanceIterator ffii;
8169 FMFontFamily ff;
8170 Lisp_Object text_encoding_info_alist;
8171 struct gcpro gcpro1;
8173 text_encoding_info_alist = create_text_encoding_info_alist ();
8175 #if USE_ATSUI
8176 #if USE_CG_TEXT_DRAWING
8177 init_cg_text_anti_aliasing_threshold ();
8178 #endif
8179 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
8180 text_encoding_info_alist)))
8182 OSStatus err;
8183 struct Lisp_Hash_Table *h;
8184 unsigned hash_code;
8185 ItemCount nfonts, i;
8186 ATSUFontID *font_ids = NULL;
8187 Lisp_Object prev_family = Qnil;
8188 int j;
8190 atsu_font_id_hash =
8191 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
8192 make_float (DEFAULT_REHASH_SIZE),
8193 make_float (DEFAULT_REHASH_THRESHOLD),
8194 Qnil, Qnil, Qnil);
8195 h = XHASH_TABLE (atsu_font_id_hash);
8197 err = ATSUFontCount (&nfonts);
8198 if (err == noErr)
8200 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
8201 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
8203 if (err == noErr)
8204 for (i = 0; i < nfonts; i++)
8206 Lisp_Object family;
8208 family = atsu_find_font_family_name (font_ids[i]);
8209 if (NILP (family) || SREF (family, 0) == '.')
8210 continue;
8211 if (!NILP (Fequal (prev_family, family)))
8212 family = prev_family;
8213 else
8214 j = hash_lookup (h, family, &hash_code);
8215 if (j < 0)
8217 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
8218 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
8219 Qnil), hash_code);
8221 else if (EQ (prev_family, family))
8222 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
8223 HASH_VALUE (h, j));
8224 prev_family = family;
8226 if (font_ids)
8227 xfree (font_ids);
8229 #endif
8231 /* Create a dummy instance iterator here to avoid creating and
8232 destroying it in the loop. */
8233 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
8234 return;
8235 /* Create an iterator to enumerate the font families. */
8236 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
8237 != noErr)
8239 FMDisposeFontFamilyInstanceIterator (&ffii);
8240 return;
8243 GCPRO1 (text_encoding_info_alist);
8245 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
8247 Str255 name;
8248 FMFont font;
8249 FMFontStyle style;
8250 FMFontSize size;
8251 TextEncoding encoding;
8252 TextEncodingBase sc;
8253 Lisp_Object text_encoding_info, family;
8255 if (FMGetFontFamilyName (ff, name) != noErr)
8256 continue;
8257 p2cstr (name);
8258 if (*name == '.')
8259 continue;
8261 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
8262 continue;
8263 sc = GetTextEncodingBase (encoding);
8264 text_encoding_info = assq_no_quit (make_number (sc),
8265 text_encoding_info_alist);
8266 if (NILP (text_encoding_info))
8267 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
8268 text_encoding_info_alist);
8269 decode_mac_font_name (name, sizeof (name),
8270 XCAR (XCDR (text_encoding_info)));
8271 family = build_string (name);
8272 if (!NILP (Fassoc (family, fm_font_family_alist)))
8273 continue;
8274 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
8275 fm_font_family_alist);
8277 /* Point the instance iterator at the current font family. */
8278 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
8279 continue;
8281 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
8282 == noErr)
8284 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
8286 if (size > 0 || style == normal)
8287 for (; !NILP (rest); rest = XCDR (rest))
8288 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
8292 UNGCPRO;
8294 /* Dispose of the iterators. */
8295 FMDisposeFontFamilyIterator (&ffi);
8296 FMDisposeFontFamilyInstanceIterator (&ffii);
8297 #else /* !TARGET_API_MAC_CARBON */
8298 GrafPtr port;
8299 SInt16 fontnum, old_fontnum;
8300 int num_mac_fonts = CountResources('FOND');
8301 int i, j;
8302 Handle font_handle, font_handle_2;
8303 short id, scriptcode;
8304 ResType type;
8305 Str255 name;
8306 struct FontAssoc *fat;
8307 struct AsscEntry *assc_entry;
8308 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
8309 struct gcpro gcpro1;
8311 GetPort (&port); /* save the current font number used */
8312 old_fontnum = port->txFont;
8314 text_encoding_info_alist = create_text_encoding_info_alist ();
8316 GCPRO1 (text_encoding_info_alist);
8318 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
8320 font_handle = GetIndResource ('FOND', i);
8321 if (!font_handle)
8322 continue;
8324 GetResInfo (font_handle, &id, &type, name);
8325 GetFNum (name, &fontnum);
8326 p2cstr (name);
8327 if (fontnum == 0 || *name == '.')
8328 continue;
8330 TextFont (fontnum);
8331 scriptcode = FontToScript (fontnum);
8332 text_encoding_info = assq_no_quit (make_number (scriptcode),
8333 text_encoding_info_alist);
8334 if (NILP (text_encoding_info))
8335 text_encoding_info = assq_no_quit (make_number (smRoman),
8336 text_encoding_info_alist);
8337 decode_mac_font_name (name, sizeof (name),
8338 XCAR (XCDR (text_encoding_info)));
8339 family = build_string (name);
8340 if (!NILP (Fassoc (family, fm_font_family_alist)))
8341 continue;
8342 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
8343 fm_font_family_alist);
8346 HLock (font_handle);
8348 if (GetResourceSizeOnDisk (font_handle)
8349 >= sizeof (struct FamRec))
8351 fat = (struct FontAssoc *) (*font_handle
8352 + sizeof (struct FamRec));
8353 assc_entry
8354 = (struct AsscEntry *) (*font_handle
8355 + sizeof (struct FamRec)
8356 + sizeof (struct FontAssoc));
8358 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
8360 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
8362 for (; !NILP (rest); rest = XCDR (rest))
8363 add_mac_font_name (name, assc_entry->fontSize,
8364 assc_entry->fontStyle,
8365 SDATA (XCAR (rest)));
8369 HUnlock (font_handle);
8370 font_handle_2 = GetNextFOND (font_handle);
8371 ReleaseResource (font_handle);
8372 font_handle = font_handle_2;
8374 while (ResError () == noErr && font_handle);
8377 UNGCPRO;
8379 TextFont (old_fontnum);
8380 #endif /* !TARGET_API_MAC_CARBON */
8384 void
8385 mac_clear_font_name_table ()
8387 int i;
8389 for (i = 0; i < font_name_count; i++)
8390 xfree (font_name_table[i]);
8391 xfree (font_name_table);
8392 font_name_table = NULL;
8393 font_name_table_size = font_name_count = 0;
8394 fm_font_family_alist = Qnil;
8398 enum xlfd_scalable_field_index
8400 XLFD_SCL_PIXEL_SIZE,
8401 XLFD_SCL_POINT_SIZE,
8402 XLFD_SCL_AVGWIDTH,
8403 XLFD_SCL_LAST
8406 static const int xlfd_scalable_fields[] =
8408 6, /* PIXEL_SIZE */
8409 7, /* POINT_SIZE */
8410 11, /* AVGWIDTH */
8414 static Lisp_Object
8415 mac_do_list_fonts (pattern, maxnames)
8416 const char *pattern;
8417 int maxnames;
8419 int i, n_fonts = 0;
8420 Lisp_Object font_list = Qnil;
8421 struct xlfdpat *pat;
8422 char *scaled;
8423 const char *ptr;
8424 int scl_val[XLFD_SCL_LAST], *val;
8425 const int *field;
8426 int exact;
8428 if (font_name_table == NULL) /* Initialize when first used. */
8429 init_font_name_table ();
8431 for (i = 0; i < XLFD_SCL_LAST; i++)
8432 scl_val[i] = -1;
8434 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8435 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8436 fonts are scaled according to the specified size. */
8437 ptr = pattern;
8438 i = 0;
8439 field = xlfd_scalable_fields;
8440 val = scl_val;
8441 if (*ptr == '-')
8444 ptr++;
8445 if (i == *field)
8447 if ('0' <= *ptr && *ptr <= '9')
8449 *val = *ptr++ - '0';
8450 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
8451 *val = *val * 10 + *ptr++ - '0';
8452 if (*ptr != '-')
8453 *val = -1;
8455 field++;
8456 val++;
8458 ptr = strchr (ptr, '-');
8459 i++;
8461 while (ptr && i < 14);
8463 if (i == 14 && ptr == NULL)
8465 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
8466 scl_val[XLFD_SCL_PIXEL_SIZE] =
8467 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
8468 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
8469 : -1));
8470 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
8471 scl_val[XLFD_SCL_POINT_SIZE] =
8472 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
8473 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
8474 : -1));
8475 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
8476 scl_val[XLFD_SCL_AVGWIDTH] =
8477 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
8478 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
8479 : -1));
8481 else
8482 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
8484 pat = xlfdpat_create (pattern);
8485 if (pat == NULL)
8486 return Qnil;
8488 exact = xlfdpat_exact_p (pat);
8490 for (i = 0; i < font_name_count; i++)
8492 if (xlfdpat_match (pat, font_name_table[i]))
8494 font_list = Fcons (build_string (font_name_table[i]), font_list);
8495 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
8496 break;
8498 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
8499 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
8501 int former_len = ptr - font_name_table[i];
8503 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
8504 memcpy (scaled, font_name_table[i], former_len);
8505 sprintf (scaled + former_len,
8506 "-%d-%d-72-72-m-%d-%s",
8507 scl_val[XLFD_SCL_PIXEL_SIZE],
8508 scl_val[XLFD_SCL_POINT_SIZE],
8509 scl_val[XLFD_SCL_AVGWIDTH],
8510 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
8512 if (xlfdpat_match (pat, scaled))
8514 font_list = Fcons (build_string (scaled), font_list);
8515 xfree (scaled);
8516 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
8517 break;
8519 else
8520 xfree (scaled);
8524 xlfdpat_destroy (pat);
8526 return font_list;
8529 /* Return a list of names of available fonts matching PATTERN on frame F.
8531 Frame F null means we have not yet created any frame on Mac, and
8532 consult the first display in x_display_list. MAXNAMES sets a limit
8533 on how many fonts to match. */
8535 Lisp_Object
8536 x_list_fonts (f, pattern, size, maxnames)
8537 struct frame *f;
8538 Lisp_Object pattern;
8539 int size, maxnames;
8541 Lisp_Object list = Qnil, patterns, tem, key;
8542 struct mac_display_info *dpyinfo
8543 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
8545 xassert (size <= 0);
8547 patterns = Fassoc (pattern, Valternate_fontname_alist);
8548 if (NILP (patterns))
8549 patterns = Fcons (pattern, Qnil);
8551 for (; CONSP (patterns); patterns = XCDR (patterns))
8553 pattern = XCAR (patterns);
8555 if (!STRINGP (pattern))
8556 continue;
8558 tem = XCAR (XCDR (dpyinfo->name_list_element));
8559 key = Fcons (pattern, make_number (maxnames));
8561 list = Fassoc (key, tem);
8562 if (!NILP (list))
8564 list = Fcdr_safe (list);
8565 /* We have a cashed list. Don't have to get the list again. */
8566 goto label_cached;
8569 BLOCK_INPUT;
8570 list = mac_do_list_fonts (SDATA (pattern), maxnames);
8571 UNBLOCK_INPUT;
8573 /* MAC_TODO: add code for matching outline fonts here */
8575 /* Now store the result in the cache. */
8576 XSETCAR (XCDR (dpyinfo->name_list_element),
8577 Fcons (Fcons (key, list),
8578 XCAR (XCDR (dpyinfo->name_list_element))));
8580 label_cached:
8581 if (NILP (list)) continue; /* Try the remaining alternatives. */
8584 return list;
8588 #if GLYPH_DEBUG
8590 /* Check that FONT is valid on frame F. It is if it can be found in F's
8591 font table. */
8593 static void
8594 x_check_font (f, font)
8595 struct frame *f;
8596 XFontStruct *font;
8598 int i;
8599 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8601 xassert (font != NULL);
8603 for (i = 0; i < dpyinfo->n_fonts; i++)
8604 if (dpyinfo->font_table[i].name
8605 && font == dpyinfo->font_table[i].font)
8606 break;
8608 xassert (i < dpyinfo->n_fonts);
8611 #endif /* GLYPH_DEBUG != 0 */
8613 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8614 Note: There are (broken) X fonts out there with invalid XFontStruct
8615 min_bounds contents. For example, handa@etl.go.jp reports that
8616 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8617 have font->min_bounds.width == 0. */
8619 static INLINE void
8620 x_font_min_bounds (font, w, h)
8621 MacFontStruct *font;
8622 int *w, *h;
8624 *h = FONT_HEIGHT (font);
8625 *w = font->min_bounds.width;
8629 /* Compute the smallest character width and smallest font height over
8630 all fonts available on frame F. Set the members smallest_char_width
8631 and smallest_font_height in F's x_display_info structure to
8632 the values computed. Value is non-zero if smallest_font_height or
8633 smallest_char_width become smaller than they were before. */
8635 static int
8636 x_compute_min_glyph_bounds (f)
8637 struct frame *f;
8639 int i;
8640 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8641 MacFontStruct *font;
8642 int old_width = dpyinfo->smallest_char_width;
8643 int old_height = dpyinfo->smallest_font_height;
8645 dpyinfo->smallest_font_height = 100000;
8646 dpyinfo->smallest_char_width = 100000;
8648 for (i = 0; i < dpyinfo->n_fonts; ++i)
8649 if (dpyinfo->font_table[i].name)
8651 struct font_info *fontp = dpyinfo->font_table + i;
8652 int w, h;
8654 font = (MacFontStruct *) fontp->font;
8655 xassert (font != (MacFontStruct *) ~0);
8656 x_font_min_bounds (font, &w, &h);
8658 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8659 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8662 xassert (dpyinfo->smallest_char_width > 0
8663 && dpyinfo->smallest_font_height > 0);
8665 return (dpyinfo->n_fonts == 1
8666 || dpyinfo->smallest_char_width < old_width
8667 || dpyinfo->smallest_font_height < old_height);
8671 /* Determine whether given string is a fully-specified XLFD: all 14
8672 fields are present, none is '*'. */
8674 static int
8675 is_fully_specified_xlfd (p)
8676 const char *p;
8678 int i;
8679 char *q;
8681 if (*p != '-')
8682 return 0;
8684 for (i = 0; i < 13; i++)
8686 q = strchr (p + 1, '-');
8687 if (q == NULL)
8688 return 0;
8689 if (q - p == 2 && *(p + 1) == '*')
8690 return 0;
8691 p = q;
8694 if (strchr (p + 1, '-') != NULL)
8695 return 0;
8697 if (*(p + 1) == '*' && *(p + 2) == '\0')
8698 return 0;
8700 return 1;
8704 /* mac_load_query_font creates and returns an internal representation
8705 for a font in a MacFontStruct struct. There is really no concept
8706 corresponding to "loading" a font on the Mac. But we check its
8707 existence and find the font number and all other information for it
8708 and store them in the returned MacFontStruct. */
8710 static MacFontStruct *
8711 mac_load_query_font (f, fontname)
8712 struct frame *f;
8713 char *fontname;
8715 int size;
8716 char *name;
8717 Str255 family;
8718 Str31 charset;
8719 SInt16 fontnum;
8720 #if USE_ATSUI
8721 static ATSUFontID font_id;
8722 ATSUStyle mac_style = NULL;
8723 #endif
8724 Style fontface;
8725 #if TARGET_API_MAC_CARBON
8726 TextEncoding encoding;
8727 int scriptcode;
8728 #else
8729 short scriptcode;
8730 #endif
8731 MacFontStruct *font;
8732 XCharStruct *space_bounds = NULL, *pcm;
8734 if (is_fully_specified_xlfd (fontname))
8735 name = fontname;
8736 else
8738 Lisp_Object matched_fonts;
8740 matched_fonts = mac_do_list_fonts (fontname, 1);
8741 if (NILP (matched_fonts))
8742 return NULL;
8743 name = SDATA (XCAR (matched_fonts));
8746 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
8747 return NULL;
8749 #if USE_ATSUI
8750 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
8752 OSStatus err;
8753 static const ATSUAttributeTag tags[] =
8754 {kATSUFontTag, kATSUSizeTag,
8755 kATSUQDBoldfaceTag, kATSUQDItalicTag};
8756 static const ByteCount sizes[] =
8757 {sizeof (ATSUFontID), sizeof (Fixed),
8758 sizeof (Boolean), sizeof (Boolean)};
8759 static Fixed size_fixed;
8760 static Boolean bold_p, italic_p;
8761 static const ATSUAttributeValuePtr values[] =
8762 {&font_id, &size_fixed,
8763 &bold_p, &italic_p};
8764 static const ATSUFontFeatureType types[] =
8765 {kAllTypographicFeaturesType, kDiacriticsType};
8766 static const ATSUFontFeatureSelector selectors[] =
8767 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
8768 FMFontStyle style;
8770 font_id = atsu_find_font_from_family_name (family);
8771 if (font_id == kATSUInvalidFontID)
8772 return;
8773 size_fixed = Long2Fix (size);
8774 bold_p = (fontface & bold) != 0;
8775 italic_p = (fontface & italic) != 0;
8776 err = ATSUCreateStyle (&mac_style);
8777 if (err != noErr)
8778 return NULL;
8779 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
8780 types, selectors);
8781 if (err != noErr)
8782 return NULL;
8783 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
8784 tags, sizes, values);
8785 if (err != noErr)
8786 return NULL;
8787 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
8788 if (err != noErr)
8789 fontnum = -1;
8790 scriptcode = kTextEncodingMacUnicode;
8792 else
8793 #endif
8795 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
8797 if (NILP (tmp))
8798 return NULL;
8799 fontnum = XINT (XCDR (tmp));
8800 #if TARGET_API_MAC_CARBON
8801 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
8802 return NULL;
8803 scriptcode = GetTextEncodingBase (encoding);
8804 #else
8805 scriptcode = FontToScript (fontnum);
8806 #endif
8809 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
8811 font->mac_fontnum = fontnum;
8812 font->mac_fontsize = size;
8813 font->mac_fontface = fontface;
8814 font->mac_scriptcode = scriptcode;
8815 #if USE_ATSUI
8816 font->mac_style = mac_style;
8817 #if USE_CG_TEXT_DRAWING
8818 font->cg_font = NULL;
8819 font->cg_glyphs = NULL;
8820 #endif
8821 #endif
8823 /* Apple Japanese (SJIS) font is listed as both
8824 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8825 (Roman script) in init_font_name_table (). The latter should be
8826 treated as a one-byte font. */
8827 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
8828 font->mac_scriptcode = smRoman;
8830 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
8832 #if USE_ATSUI
8833 if (font->mac_style)
8835 OSStatus err;
8836 UniChar c;
8838 font->min_byte1 = 0;
8839 font->max_byte1 = 0xff;
8840 font->min_char_or_byte2 = 0;
8841 font->max_char_or_byte2 = 0xff;
8843 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
8844 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
8845 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
8846 pcm_init (font->bounds.rows[0], 0x100);
8848 #if USE_CG_TEXT_DRAWING
8849 if (fontnum != -1)
8851 FMFontStyle style;
8852 ATSFontRef ats_font;
8854 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
8855 &font_id, &style);
8856 /* Use CG text drawing if italic/bold is not synthesized. */
8857 if (err == noErr && style == fontface)
8859 ats_font = FMGetATSFontRefFromFont (font_id);
8860 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
8864 if (font->cg_font)
8866 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
8867 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
8869 #endif
8870 space_bounds = font->bounds.rows[0] + 0x20;
8871 err = mac_query_char_extents (font->mac_style, 0x20,
8872 &font->ascent, &font->descent,
8873 space_bounds,
8874 #if USE_CG_TEXT_DRAWING
8875 (font->cg_glyphs ? font->cg_glyphs + 0x20
8876 : NULL)
8877 #else
8878 NULL
8879 #endif
8881 if (err != noErr
8882 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
8884 mac_unload_font (&one_mac_display_info, font);
8885 return NULL;
8888 pcm = font->bounds.rows[0];
8889 for (c = 0x21; c <= 0xff; c++)
8891 if (c == 0xad)
8892 /* Soft hyphen is not supported in ATSUI. */
8893 continue;
8894 else if (c == 0x7f)
8896 #if USE_CG_TEXT_DRAWING
8897 if (font->cg_glyphs)
8899 c = 0x9f;
8900 pcm = NULL;
8901 continue;
8903 #endif
8904 break;
8907 mac_query_char_extents (font->mac_style, c, NULL, NULL,
8908 pcm ? pcm + c : NULL,
8909 #if USE_CG_TEXT_DRAWING
8910 (font->cg_glyphs ? font->cg_glyphs + c
8911 : NULL)
8912 #else
8913 NULL
8914 #endif
8917 #if USE_CG_TEXT_DRAWING
8918 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
8920 /* Don't use CG text drawing if font substitution occurs in
8921 ASCII or Latin-1 characters. */
8922 CGFontRelease (font->cg_font);
8923 font->cg_font = NULL;
8924 xfree (font->cg_glyphs);
8925 font->cg_glyphs = NULL;
8926 if (pcm == NULL)
8927 break;
8929 #endif
8932 else
8933 #endif
8935 OSStatus err;
8936 FontInfo the_fontinfo;
8937 int is_two_byte_font;
8939 #if USE_CG_DRAWING
8940 mac_prepare_for_quickdraw (f);
8941 #endif
8942 SetPortWindowPort (FRAME_MAC_WINDOW (f));
8944 TextFont (fontnum);
8945 TextSize (size);
8946 TextFace (fontface);
8948 GetFontInfo (&the_fontinfo);
8950 font->ascent = the_fontinfo.ascent;
8951 font->descent = the_fontinfo.descent;
8953 is_two_byte_font = (font->mac_scriptcode == smJapanese
8954 || font->mac_scriptcode == smTradChinese
8955 || font->mac_scriptcode == smSimpChinese
8956 || font->mac_scriptcode == smKorean);
8958 if (is_two_byte_font)
8960 int char_width;
8962 font->min_byte1 = 0xa1;
8963 font->max_byte1 = 0xfe;
8964 font->min_char_or_byte2 = 0xa1;
8965 font->max_char_or_byte2 = 0xfe;
8967 /* Use the width of an "ideographic space" of that font
8968 because the_fontinfo.widMax returns the wrong width for
8969 some fonts. */
8970 switch (font->mac_scriptcode)
8972 case smJapanese:
8973 font->min_byte1 = 0x81;
8974 font->max_byte1 = 0xfc;
8975 font->min_char_or_byte2 = 0x40;
8976 font->max_char_or_byte2 = 0xfc;
8977 char_width = StringWidth("\p\x81\x40");
8978 break;
8979 case smTradChinese:
8980 font->min_char_or_byte2 = 0x40;
8981 char_width = StringWidth("\p\xa1\x40");
8982 break;
8983 case smSimpChinese:
8984 char_width = StringWidth("\p\xa1\xa1");
8985 break;
8986 case smKorean:
8987 char_width = StringWidth("\p\xa1\xa1");
8988 break;
8991 font->bounds.per_char = NULL;
8993 if (fontface & italic)
8994 font->max_bounds.rbearing = char_width + 1;
8995 else
8996 font->max_bounds.rbearing = char_width;
8997 font->max_bounds.lbearing = 0;
8998 font->max_bounds.width = char_width;
8999 font->max_bounds.ascent = the_fontinfo.ascent;
9000 font->max_bounds.descent = the_fontinfo.descent;
9002 font->min_bounds = font->max_bounds;
9004 else
9006 int c;
9008 font->min_byte1 = font->max_byte1 = 0;
9009 font->min_char_or_byte2 = 0x20;
9010 font->max_char_or_byte2 = 0xff;
9012 font->bounds.per_char =
9013 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
9014 bzero (font->bounds.per_char,
9015 sizeof (XCharStruct) * (0xff - 0x20 + 1));
9017 space_bounds = font->bounds.per_char;
9018 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
9019 &font->descent, space_bounds, NULL);
9020 if (err != noErr || space_bounds->width <= 0)
9022 mac_unload_font (&one_mac_display_info, font);
9023 return NULL;
9026 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
9027 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
9031 if (space_bounds)
9033 int c;
9035 font->min_bounds = font->max_bounds = *space_bounds;
9036 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
9037 if (pcm->width > 0)
9039 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
9040 pcm->lbearing);
9041 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
9042 pcm->rbearing);
9043 font->min_bounds.width = min (font->min_bounds.width,
9044 pcm->width);
9045 font->min_bounds.ascent = min (font->min_bounds.ascent,
9046 pcm->ascent);
9047 font->min_bounds.descent = min (font->min_bounds.descent,
9048 pcm->descent);
9050 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
9051 pcm->lbearing);
9052 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
9053 pcm->rbearing);
9054 font->max_bounds.width = max (font->max_bounds.width,
9055 pcm->width);
9056 font->max_bounds.ascent = max (font->max_bounds.ascent,
9057 pcm->ascent);
9058 font->max_bounds.descent = max (font->max_bounds.descent,
9059 pcm->descent);
9061 if (
9062 #if USE_ATSUI
9063 font->mac_style == NULL &&
9064 #endif
9065 font->max_bounds.width == font->min_bounds.width
9066 && font->min_bounds.lbearing >= 0
9067 && font->max_bounds.rbearing <= font->max_bounds.width)
9069 /* Fixed width and no overhangs. */
9070 xfree (font->bounds.per_char);
9071 font->bounds.per_char = NULL;
9075 #if !defined (MAC_OS8) || USE_ATSUI
9076 /* AppKit and WebKit do some adjustment to the heights of Courier,
9077 Helvetica, and Times. This only works on the environments where
9078 srcCopy text transfer mode is never used. */
9079 if (
9080 #ifdef MAC_OS8 /* implies USE_ATSUI */
9081 font->mac_style &&
9082 #endif
9083 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
9084 || strcmp (family, "times") == 0))
9085 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
9086 #endif
9088 return font;
9092 void
9093 mac_unload_font (dpyinfo, font)
9094 struct mac_display_info *dpyinfo;
9095 XFontStruct *font;
9097 xfree (font->full_name);
9098 #if USE_ATSUI
9099 if (font->mac_style)
9101 int i;
9103 for (i = font->min_byte1; i <= font->max_byte1; i++)
9104 if (font->bounds.rows[i])
9105 xfree (font->bounds.rows[i]);
9106 xfree (font->bounds.rows);
9107 ATSUDisposeStyle (font->mac_style);
9109 else
9110 #endif
9111 if (font->bounds.per_char)
9112 xfree (font->bounds.per_char);
9113 #if USE_CG_TEXT_DRAWING
9114 if (font->cg_font)
9115 CGFontRelease (font->cg_font);
9116 if (font->cg_glyphs)
9117 xfree (font->cg_glyphs);
9118 #endif
9119 xfree (font);
9123 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9124 pointer to the structure font_info while allocating it dynamically.
9125 If SIZE is 0, load any size of font.
9126 If loading is failed, return NULL. */
9128 struct font_info *
9129 x_load_font (f, fontname, size)
9130 struct frame *f;
9131 register char *fontname;
9132 int size;
9134 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9135 Lisp_Object font_names;
9137 /* Get a list of all the fonts that match this name. Once we
9138 have a list of matching fonts, we compare them against the fonts
9139 we already have by comparing names. */
9140 font_names = x_list_fonts (f, build_string (fontname), size, 1);
9142 if (!NILP (font_names))
9144 Lisp_Object tail;
9145 int i;
9147 for (i = 0; i < dpyinfo->n_fonts; i++)
9148 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
9149 if (dpyinfo->font_table[i].name
9150 && (!strcmp (dpyinfo->font_table[i].name,
9151 SDATA (XCAR (tail)))
9152 || !strcmp (dpyinfo->font_table[i].full_name,
9153 SDATA (XCAR (tail)))))
9154 return (dpyinfo->font_table + i);
9156 else
9157 return NULL;
9159 /* Load the font and add it to the table. */
9161 struct MacFontStruct *font;
9162 struct font_info *fontp;
9163 int i;
9165 fontname = (char *) SDATA (XCAR (font_names));
9167 BLOCK_INPUT;
9168 font = mac_load_query_font (f, fontname);
9169 UNBLOCK_INPUT;
9170 if (!font)
9171 return NULL;
9173 /* Find a free slot in the font table. */
9174 for (i = 0; i < dpyinfo->n_fonts; ++i)
9175 if (dpyinfo->font_table[i].name == NULL)
9176 break;
9178 /* If no free slot found, maybe enlarge the font table. */
9179 if (i == dpyinfo->n_fonts
9180 && dpyinfo->n_fonts == dpyinfo->font_table_size)
9182 int sz;
9183 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
9184 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
9185 dpyinfo->font_table
9186 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
9189 fontp = dpyinfo->font_table + i;
9190 if (i == dpyinfo->n_fonts)
9191 ++dpyinfo->n_fonts;
9193 /* Now fill in the slots of *FONTP. */
9194 BLOCK_INPUT;
9195 bzero (fontp, sizeof (*fontp));
9196 fontp->font = font;
9197 fontp->font_idx = i;
9198 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
9199 bcopy (fontname, fontp->name, strlen (fontname) + 1);
9201 if (font->min_bounds.width == font->max_bounds.width)
9203 /* Fixed width font. */
9204 fontp->average_width = fontp->space_width = font->min_bounds.width;
9206 else
9208 XChar2b char2b;
9209 XCharStruct *pcm;
9211 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
9212 pcm = mac_per_char_metric (font, &char2b, 0);
9213 if (pcm)
9214 fontp->space_width = pcm->width;
9215 else
9216 fontp->space_width = FONT_WIDTH (font);
9218 if (pcm)
9220 int width = pcm->width;
9221 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
9222 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
9223 width += pcm->width;
9224 fontp->average_width = width / 95;
9226 else
9227 fontp->average_width = FONT_WIDTH (font);
9230 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
9231 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
9233 fontp->size = font->max_bounds.width;
9234 fontp->height = FONT_HEIGHT (font);
9236 /* For some font, ascent and descent in max_bounds field is
9237 larger than the above value. */
9238 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
9239 if (max_height > fontp->height)
9240 fontp->height = max_height;
9243 /* The slot `encoding' specifies how to map a character
9244 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9245 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9246 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9247 2:0xA020..0xFF7F). For the moment, we don't know which charset
9248 uses this font. So, we set information in fontp->encoding[1]
9249 which is never used by any charset. If mapping can't be
9250 decided, set FONT_ENCODING_NOT_DECIDED. */
9251 if (font->mac_scriptcode == smJapanese)
9252 fontp->encoding[1] = 4;
9253 else
9255 fontp->encoding[1]
9256 = (font->max_byte1 == 0
9257 /* 1-byte font */
9258 ? (font->min_char_or_byte2 < 0x80
9259 ? (font->max_char_or_byte2 < 0x80
9260 ? 0 /* 0x20..0x7F */
9261 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
9262 : 1) /* 0xA0..0xFF */
9263 /* 2-byte font */
9264 : (font->min_byte1 < 0x80
9265 ? (font->max_byte1 < 0x80
9266 ? (font->min_char_or_byte2 < 0x80
9267 ? (font->max_char_or_byte2 < 0x80
9268 ? 0 /* 0x2020..0x7F7F */
9269 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
9270 : 3) /* 0x20A0..0x7FFF */
9271 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
9272 : (font->min_char_or_byte2 < 0x80
9273 ? (font->max_char_or_byte2 < 0x80
9274 ? 2 /* 0xA020..0xFF7F */
9275 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
9276 : 1))); /* 0xA0A0..0xFFFF */
9279 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9280 fontp->baseline_offset
9281 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
9282 ? (long) value : 0);
9283 fontp->relative_compose
9284 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
9285 ? (long) value : 0);
9286 fontp->default_ascent
9287 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
9288 ? (long) value : 0);
9289 #else
9290 fontp->baseline_offset = 0;
9291 fontp->relative_compose = 0;
9292 fontp->default_ascent = 0;
9293 #endif
9295 /* Set global flag fonts_changed_p to non-zero if the font loaded
9296 has a character with a smaller width than any other character
9297 before, or if the font loaded has a smaller height than any
9298 other font loaded before. If this happens, it will make a
9299 glyph matrix reallocation necessary. */
9300 fonts_changed_p |= x_compute_min_glyph_bounds (f);
9301 UNBLOCK_INPUT;
9302 return fontp;
9307 /* Return a pointer to struct font_info of a font named FONTNAME for
9308 frame F. If no such font is loaded, return NULL. */
9310 struct font_info *
9311 x_query_font (f, fontname)
9312 struct frame *f;
9313 register char *fontname;
9315 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9316 int i;
9318 for (i = 0; i < dpyinfo->n_fonts; i++)
9319 if (dpyinfo->font_table[i].name
9320 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
9321 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
9322 return (dpyinfo->font_table + i);
9323 return NULL;
9327 /* Find a CCL program for a font specified by FONTP, and set the member
9328 `encoder' of the structure. */
9330 void
9331 x_find_ccl_program (fontp)
9332 struct font_info *fontp;
9334 Lisp_Object list, elt;
9336 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
9338 elt = XCAR (list);
9339 if (CONSP (elt)
9340 && STRINGP (XCAR (elt))
9341 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
9342 >= 0))
9343 break;
9345 if (! NILP (list))
9347 struct ccl_program *ccl
9348 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
9350 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
9351 xfree (ccl);
9352 else
9353 fontp->font_encoder = ccl;
9357 #if USE_MAC_FONT_PANEL
9358 /* Whether Font Panel has been shown before. The first call to font
9359 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9360 slow. This variable is used for deferring such a call as much as
9361 possible. */
9362 static int font_panel_shown_p = 0;
9364 extern Lisp_Object Qfont;
9365 static Lisp_Object Qpanel_closed, Qselection;
9367 static OSStatus mac_store_event_ref_as_apple_event P_ ((AEEventClass, AEEventID,
9368 Lisp_Object,
9369 Lisp_Object,
9370 EventRef, UInt32,
9371 const EventParamName *,
9372 const EventParamType *));
9375 mac_font_panel_visible_p ()
9377 return font_panel_shown_p && FPIsFontPanelVisible ();
9380 static pascal OSStatus
9381 mac_handle_font_event (next_handler, event, data)
9382 EventHandlerCallRef next_handler;
9383 EventRef event;
9384 void *data;
9386 OSStatus result, err;
9387 Lisp_Object id_key;
9388 int num_params;
9389 const EventParamName *names;
9390 const EventParamType *types;
9391 static const EventParamName names_sel[] = {kEventParamATSUFontID,
9392 kEventParamATSUFontSize,
9393 kEventParamFMFontFamily,
9394 kEventParamFMFontSize,
9395 kEventParamFontColor};
9396 static const EventParamType types_sel[] = {typeATSUFontID,
9397 typeATSUSize,
9398 typeFMFontFamily,
9399 typeFMFontSize,
9400 typeFontColor};
9402 result = CallNextEventHandler (next_handler, event);
9403 if (result != eventNotHandledErr)
9404 return result;
9406 switch (GetEventKind (event))
9408 case kEventFontPanelClosed:
9409 id_key = Qpanel_closed;
9410 num_params = 0;
9411 names = NULL;
9412 types = NULL;
9413 break;
9415 case kEventFontSelection:
9416 id_key = Qselection;
9417 num_params = sizeof (names_sel) / sizeof (names_sel[0]);
9418 names = names_sel;
9419 types = types_sel;
9420 break;
9423 err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
9424 event, num_params,
9425 names, types);
9426 if (err == noErr)
9427 result = noErr;
9429 return result;
9432 OSStatus
9433 mac_show_hide_font_panel ()
9435 if (!font_panel_shown_p)
9437 OSStatus err;
9439 static const EventTypeSpec specs[] =
9440 {{kEventClassFont, kEventFontPanelClosed},
9441 {kEventClassFont, kEventFontSelection}};
9443 err = InstallApplicationEventHandler (mac_handle_font_event,
9444 GetEventTypeCount (specs),
9445 specs, NULL, NULL);
9446 if (err != noErr)
9447 return err;
9449 font_panel_shown_p = 1;
9452 return FPShowHideFontPanel ();
9455 OSStatus
9456 mac_set_font_info_for_selection (f, face_id, c)
9457 struct frame *f;
9458 int face_id, c;
9460 OSStatus err;
9461 EventTargetRef target = NULL;
9462 XFontStruct *font = NULL;
9464 if (!mac_font_panel_visible_p ())
9465 return noErr;
9467 if (f)
9469 target = GetWindowEventTarget (FRAME_MAC_WINDOW (f));
9471 if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0))
9473 struct face *face;
9475 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
9476 face = FACE_FROM_ID (f, face_id);
9477 font = face->font;
9481 if (font == NULL)
9482 err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target);
9483 else
9485 if (font->mac_fontnum != -1)
9487 FontSelectionQDStyle qd_style;
9489 qd_style.version = kFontSelectionQDStyleVersionZero;
9490 qd_style.instance.fontFamily = font->mac_fontnum;
9491 qd_style.instance.fontStyle = font->mac_fontface;
9492 qd_style.size = font->mac_fontsize;
9493 qd_style.hasColor = false;
9495 err = SetFontInfoForSelection (kFontSelectionQDType,
9496 1, &qd_style, target);
9498 else
9499 err = SetFontInfoForSelection (kFontSelectionATSUIType,
9500 1, &font->mac_style, target);
9503 return err;
9505 #endif
9508 /* The Mac Event loop code */
9510 #if !TARGET_API_MAC_CARBON
9511 #include <Events.h>
9512 #include <Quickdraw.h>
9513 #include <Balloons.h>
9514 #include <Devices.h>
9515 #include <Fonts.h>
9516 #include <Gestalt.h>
9517 #include <Menus.h>
9518 #include <Processes.h>
9519 #include <Sound.h>
9520 #include <ToolUtils.h>
9521 #include <TextUtils.h>
9522 #include <Dialogs.h>
9523 #include <Script.h>
9524 #include <Types.h>
9525 #include <Resources.h>
9527 #if __MWERKS__
9528 #include <unix.h>
9529 #endif
9530 #endif /* ! TARGET_API_MAC_CARBON */
9532 #define M_APPLE 234
9533 #define I_ABOUT 1
9535 #define DEFAULT_NUM_COLS 80
9537 #define MIN_DOC_SIZE 64
9538 #define MAX_DOC_SIZE 32767
9540 #define EXTRA_STACK_ALLOC (256 * 1024)
9542 #define ARGV_STRING_LIST_ID 129
9543 #define ABOUT_ALERT_ID 128
9544 #define RAM_TOO_LARGE_ALERT_ID 129
9546 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9547 Lisp_Object Qreverse;
9550 /* Modifier associated with the control key, or nil to ignore. */
9551 Lisp_Object Vmac_control_modifier;
9553 /* Modifier associated with the option key, or nil to ignore. */
9554 Lisp_Object Vmac_option_modifier;
9556 /* Modifier associated with the command key, or nil to ignore. */
9557 Lisp_Object Vmac_command_modifier;
9559 /* Modifier associated with the function key, or nil to ignore. */
9560 Lisp_Object Vmac_function_modifier;
9562 /* True if the option and command modifiers should be used to emulate
9563 a three button mouse */
9564 Lisp_Object Vmac_emulate_three_button_mouse;
9566 #if TARGET_API_MAC_CARBON
9567 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9568 mouse-2, instead of mouse-3. */
9569 int mac_wheel_button_is_mouse_2;
9571 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9572 for processing before Emacs sees it. */
9573 int mac_pass_command_to_system;
9575 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9576 for processing before Emacs sees it. */
9577 int mac_pass_control_to_system;
9578 #endif
9580 /* Points to the variable `inev' in the function XTread_socket. It is
9581 used for passing an input event to the function back from
9582 Carbon/Apple event handlers. */
9583 static struct input_event *read_socket_inev = NULL;
9585 /* Whether or not the screen configuration has changed. */
9586 static int mac_screen_config_changed = 0;
9588 Point saved_menu_event_location;
9590 /* Apple Events */
9591 #if TARGET_API_MAC_CARBON
9592 static Lisp_Object Qhi_command;
9593 #ifdef MAC_OSX
9594 extern Lisp_Object Qwindow;
9595 static Lisp_Object Qtoolbar_switch_mode;
9596 #endif
9597 #if USE_MAC_TSM
9598 static TSMDocumentID tsm_document_id;
9599 static Lisp_Object Qtext_input;
9600 static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
9601 static Lisp_Object Vmac_ts_active_input_overlay;
9602 extern Lisp_Object Qbefore_string;
9603 static Lisp_Object Vmac_ts_script_language_on_focus;
9604 static Lisp_Object saved_ts_script_language_on_focus;
9605 static ScriptLanguageRecord saved_ts_language;
9606 static Component saved_ts_component;
9607 #endif
9608 #endif /* TARGET_API_MAC_CARBON */
9609 extern int mac_ready_for_apple_events;
9610 extern Lisp_Object Qundefined;
9611 extern void init_apple_event_handler P_ ((void));
9612 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
9613 Lisp_Object *, Lisp_Object *,
9614 Lisp_Object *));
9615 extern OSErr init_coercion_handler P_ ((void));
9617 /* Drag and Drop */
9618 extern OSErr install_drag_handler P_ ((WindowRef));
9619 extern void remove_drag_handler P_ ((WindowRef));
9621 #if TARGET_API_MAC_CARBON
9622 /* Showing help echo string during menu tracking */
9623 extern OSStatus install_menu_target_item_handler P_ ((void));
9625 #ifdef MAC_OSX
9626 extern OSStatus install_service_handler ();
9627 static Lisp_Object Qservice, Qpaste, Qperform;
9628 #endif
9629 #endif
9631 extern void init_emacs_passwd_dir ();
9632 extern int emacs_main (int, char **, char **);
9634 extern void initialize_applescript();
9635 extern void terminate_applescript();
9637 /* Table for translating Mac keycode to X keysym values. Contributed
9638 by Sudhir Shenoy.
9639 Mapping for special keys is now identical to that in Apple X11
9640 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9641 on the right of the Cmd key on laptops, and fn + `enter' (->
9642 <linefeed>). */
9643 static const unsigned char keycode_to_xkeysym_table[] = {
9644 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9645 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9646 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9648 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9649 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9650 /*0x38*/ 0, 0, 0, 0,
9651 /*0x3C*/ 0, 0, 0, 0,
9653 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9654 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9655 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9656 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9658 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9659 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9660 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9661 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9663 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9664 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9665 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9666 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9668 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9669 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9670 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9671 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9674 #ifdef MAC_OSX
9675 /* Table for translating Mac keycode with the laptop `fn' key to that
9676 without it. Destination symbols in comments are keys on US
9677 keyboard, and they may not be the same on other types of keyboards.
9678 If the destination is identical to the source (f1 ... f12), it
9679 doesn't map `fn' key to a modifier. */
9680 static const unsigned char fn_keycode_to_keycode_table[] = {
9681 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9682 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9683 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9685 /*0x30*/ 0, 0, 0, 0,
9686 /*0x34*/ 0, 0, 0, 0,
9687 /*0x38*/ 0, 0, 0, 0,
9688 /*0x3C*/ 0, 0, 0, 0,
9690 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9691 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9692 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9693 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9695 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9696 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9697 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9698 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9700 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9701 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9702 /*0x68*/ 0, 0, 0, 0,
9703 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9705 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9706 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9707 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9708 /*0x7C*/ 0, 0, 0, 0
9710 #endif /* MAC_OSX */
9712 static int
9713 #if TARGET_API_MAC_CARBON
9714 mac_to_emacs_modifiers (UInt32 mods)
9715 #else
9716 mac_to_emacs_modifiers (EventModifiers mods)
9717 #endif
9719 unsigned int result = 0;
9720 if (mods & shiftKey)
9721 result |= shift_modifier;
9723 /* Deactivated to simplify configuration:
9724 if Vmac_option_modifier is non-NIL, we fully process the Option
9725 key. Otherwise, we only process it if an additional Ctrl or Command
9726 is pressed. That way the system may convert the character to a
9727 composed one.
9728 if ((mods & optionKey) &&
9729 (( !NILP(Vmac_option_modifier) ||
9730 ((mods & cmdKey) || (mods & controlKey))))) */
9732 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
9733 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
9734 if (INTEGERP(val))
9735 result |= XUINT(val);
9737 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
9738 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
9739 if (INTEGERP(val))
9740 result |= XUINT(val);
9742 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
9743 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
9744 if (INTEGERP(val))
9745 result |= XUINT(val);
9748 #ifdef MAC_OSX
9749 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
9750 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
9751 if (INTEGERP(val))
9752 result |= XUINT(val);
9754 #endif
9756 return result;
9759 static UInt32
9760 mac_mapped_modifiers (modifiers)
9761 UInt32 modifiers;
9763 UInt32 mapped_modifiers_all =
9764 (NILP (Vmac_control_modifier) ? 0 : controlKey)
9765 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
9766 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
9768 #ifdef MAC_OSX
9769 mapped_modifiers_all |=
9770 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
9771 #endif
9773 return mapped_modifiers_all & modifiers;
9776 static int
9777 mac_get_emulated_btn ( UInt32 modifiers )
9779 int result = 0;
9780 if (!NILP (Vmac_emulate_three_button_mouse)) {
9781 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
9782 if (modifiers & cmdKey)
9783 result = cmdIs3 ? 2 : 1;
9784 else if (modifiers & optionKey)
9785 result = cmdIs3 ? 1 : 2;
9787 return result;
9790 #if TARGET_API_MAC_CARBON
9791 /***** Code to handle C-g testing *****/
9792 extern int quit_char;
9793 extern int make_ctrl_char P_ ((int));
9796 mac_quit_char_key_p (modifiers, key_code)
9797 UInt32 modifiers, key_code;
9799 UInt32 char_code;
9800 unsigned long some_state = 0;
9801 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9802 int c, emacs_modifiers;
9804 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9805 key_code |= (modifiers & ~(mac_mapped_modifiers (modifiers)));
9806 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
9807 if (char_code & ~0xff)
9808 return 0;
9810 emacs_modifiers = mac_to_emacs_modifiers (modifiers);
9811 if (emacs_modifiers & ctrl_modifier)
9812 c = make_ctrl_char (char_code);
9814 c |= (emacs_modifiers
9815 & (meta_modifier | alt_modifier
9816 | hyper_modifier | super_modifier));
9818 return c == quit_char;
9820 #endif
9822 #if TARGET_API_MAC_CARBON
9823 /* Obtains the event modifiers from the event ref and then calls
9824 mac_to_emacs_modifiers. */
9825 static int
9826 mac_event_to_emacs_modifiers (EventRef eventRef)
9828 UInt32 mods = 0, class;
9830 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
9831 sizeof (UInt32), NULL, &mods);
9832 class = GetEventClass (eventRef);
9833 if (!NILP (Vmac_emulate_three_button_mouse) &&
9834 (class == kEventClassMouse || class == kEventClassCommand))
9836 mods &= ~(optionKey | cmdKey);
9838 return mac_to_emacs_modifiers (mods);
9841 /* Given an event ref, return the code to use for the mouse button
9842 code in the emacs input_event. */
9843 static int
9844 mac_get_mouse_btn (EventRef ref)
9846 EventMouseButton result = kEventMouseButtonPrimary;
9847 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
9848 sizeof (EventMouseButton), NULL, &result);
9849 switch (result)
9851 case kEventMouseButtonPrimary:
9852 if (NILP (Vmac_emulate_three_button_mouse))
9853 return 0;
9854 else {
9855 UInt32 mods = 0;
9856 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
9857 sizeof (UInt32), NULL, &mods);
9858 return mac_get_emulated_btn(mods);
9860 case kEventMouseButtonSecondary:
9861 return mac_wheel_button_is_mouse_2 ? 2 : 1;
9862 case kEventMouseButtonTertiary:
9863 case 4: /* 4 is the number for the mouse wheel button */
9864 return mac_wheel_button_is_mouse_2 ? 1 : 2;
9865 default:
9866 return 0;
9870 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9871 events. However the click of the mouse wheel is not converted to a
9872 mouseDown or mouseUp event. Likewise for dead key events. This
9873 calls ConvertEventRefToEventRecord, but then checks to see if it is
9874 a mouse up/down, or a dead key Carbon event that has not been
9875 converted, and if so, converts it by hand (to be picked up in the
9876 XTread_socket loop). */
9877 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
9879 OSStatus err;
9880 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
9881 EventKind action;
9883 if (result)
9884 return result;
9886 switch (GetEventClass (eventRef))
9888 case kEventClassMouse:
9889 switch (GetEventKind (eventRef))
9891 case kEventMouseDown:
9892 eventRec->what = mouseDown;
9893 result = 1;
9894 break;
9896 case kEventMouseUp:
9897 eventRec->what = mouseUp;
9898 result = 1;
9899 break;
9901 default:
9902 break;
9904 break;
9906 case kEventClassKeyboard:
9907 switch (GetEventKind (eventRef))
9909 case kEventRawKeyDown:
9910 action = keyDown;
9911 goto keystroke_common;
9912 case kEventRawKeyRepeat:
9913 action = autoKey;
9914 goto keystroke_common;
9915 case kEventRawKeyUp:
9916 action = keyUp;
9917 keystroke_common:
9919 unsigned char char_codes;
9920 UInt32 key_code;
9922 err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes,
9923 typeChar, NULL, sizeof (char),
9924 NULL, &char_codes);
9925 if (err == noErr)
9926 err = GetEventParameter (eventRef, kEventParamKeyCode,
9927 typeUInt32, NULL, sizeof (UInt32),
9928 NULL, &key_code);
9929 if (err == noErr)
9931 eventRec->what = action;
9932 eventRec->message = char_codes | ((key_code & 0xff) << 8);
9933 result = 1;
9936 break;
9938 default:
9939 break;
9941 break;
9943 default:
9944 break;
9947 if (result)
9949 /* Need where and when. */
9950 UInt32 mods = 0;
9952 GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
9953 NULL, sizeof (Point), NULL, &eventRec->where);
9954 /* Use two step process because new event modifiers are 32-bit
9955 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9956 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
9957 NULL, sizeof (UInt32), NULL, &mods);
9958 eventRec->modifiers = mods;
9960 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
9963 return result;
9966 #endif
9968 #ifdef MAC_OS8
9969 static void
9970 do_get_menus (void)
9972 Handle menubar_handle;
9973 MenuRef menu;
9975 menubar_handle = GetNewMBar (128);
9976 if(menubar_handle == NULL)
9977 abort ();
9978 SetMenuBar (menubar_handle);
9979 DrawMenuBar ();
9981 #if !TARGET_API_MAC_CARBON
9982 menu = GetMenuRef (M_APPLE);
9983 if (menu != NULL)
9984 AppendResMenu (menu, 'DRVR');
9985 else
9986 abort ();
9987 #endif
9991 static void
9992 do_init_managers (void)
9994 #if !TARGET_API_MAC_CARBON
9995 InitGraf (&qd.thePort);
9996 InitFonts ();
9997 FlushEvents (everyEvent, 0);
9998 InitWindows ();
9999 InitMenus ();
10000 TEInit ();
10001 InitDialogs (NULL);
10002 #endif /* !TARGET_API_MAC_CARBON */
10003 InitCursor ();
10005 #if !TARGET_API_MAC_CARBON
10006 /* set up some extra stack space for use by emacs */
10007 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
10009 /* MaxApplZone must be called for AppleScript to execute more
10010 complicated scripts */
10011 MaxApplZone ();
10012 MoreMasters ();
10013 #endif /* !TARGET_API_MAC_CARBON */
10016 static void
10017 do_check_ram_size (void)
10019 SInt32 physical_ram_size, logical_ram_size;
10021 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
10022 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
10023 || physical_ram_size > (1 << VALBITS)
10024 || logical_ram_size > (1 << VALBITS))
10026 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
10027 exit (1);
10030 #endif /* MAC_OS8 */
10032 static void
10033 do_window_update (WindowRef win)
10035 struct frame *f = mac_window_to_frame (win);
10037 BeginUpdate (win);
10039 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10040 below. */
10041 if (win != tip_window)
10043 if (f->async_visible == 0)
10045 /* Update events may occur when a frame gets iconified. */
10046 #if 0
10047 f->async_visible = 1;
10048 f->async_iconified = 0;
10049 SET_FRAME_GARBAGED (f);
10050 #endif
10052 else
10054 Rect r;
10055 #if TARGET_API_MAC_CARBON
10056 RgnHandle region = NewRgn ();
10058 GetPortVisibleRegion (GetWindowPort (win), region);
10059 GetRegionBounds (region, &r);
10060 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
10061 #if USE_CG_DRAWING
10062 mac_prepare_for_quickdraw (f);
10063 #endif
10064 UpdateControls (win, region);
10065 DisposeRgn (region);
10066 #else
10067 r = (*win->visRgn)->rgnBBox;
10068 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
10069 UpdateControls (win, win->visRgn);
10070 #endif
10074 EndUpdate (win);
10077 static int
10078 is_emacs_window (WindowRef win)
10080 Lisp_Object tail, frame;
10082 if (!win)
10083 return 0;
10085 FOR_EACH_FRAME (tail, frame)
10086 if (FRAME_MAC_P (XFRAME (frame)))
10087 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
10088 return 1;
10090 return 0;
10093 #if USE_MAC_TSM
10094 static OSStatus
10095 mac_tsm_resume ()
10097 OSStatus err;
10098 ScriptLanguageRecord slrec, *slptr = NULL;
10100 err = ActivateTSMDocument (tsm_document_id);
10102 if (err == noErr)
10104 if (EQ (Vmac_ts_script_language_on_focus, Qt)
10105 && EQ (saved_ts_script_language_on_focus, Qt))
10106 slptr = &saved_ts_language;
10107 else if (CONSP (Vmac_ts_script_language_on_focus)
10108 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
10109 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
10110 && CONSP (saved_ts_script_language_on_focus)
10111 && EQ (XCAR (saved_ts_script_language_on_focus),
10112 XCAR (Vmac_ts_script_language_on_focus))
10113 && EQ (XCDR (saved_ts_script_language_on_focus),
10114 XCDR (Vmac_ts_script_language_on_focus)))
10116 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
10117 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
10118 slptr = &slrec;
10122 if (slptr)
10124 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10125 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
10126 kKeyboardInputMethodClass);
10127 #else
10128 err = SetDefaultInputMethod (saved_ts_component, slptr);
10129 #endif
10130 if (err == noErr)
10131 err = SetTextServiceLanguage (slptr);
10133 /* Seems to be needed on Mac OS X 10.2. */
10134 if (err == noErr)
10135 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
10138 return err;
10141 static OSStatus
10142 mac_tsm_suspend ()
10144 OSStatus err;
10145 ScriptLanguageRecord slrec, *slptr = NULL;
10147 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
10149 if (EQ (Vmac_ts_script_language_on_focus, Qt))
10151 err = GetTextServiceLanguage (&saved_ts_language);
10152 if (err == noErr)
10153 slptr = &saved_ts_language;
10155 else if (CONSP (Vmac_ts_script_language_on_focus)
10156 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
10157 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
10159 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
10160 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
10161 slptr = &slrec;
10164 if (slptr)
10166 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10167 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
10168 kKeyboardInputMethodClass);
10169 #else
10170 GetDefaultInputMethod (&saved_ts_component, slptr);
10171 #endif
10174 err = DeactivateTSMDocument (tsm_document_id);
10176 return err;
10178 #endif
10180 #if !TARGET_API_MAC_CARBON
10181 void
10182 do_apple_menu (SInt16 menu_item)
10184 Str255 item_name;
10185 SInt16 da_driver_refnum;
10187 if (menu_item == I_ABOUT)
10188 NoteAlert (ABOUT_ALERT_ID, NULL);
10189 else
10191 GetMenuItemText (GetMenuRef (M_APPLE), menu_item, item_name);
10192 da_driver_refnum = OpenDeskAcc (item_name);
10195 #endif /* !TARGET_API_MAC_CARBON */
10197 /* Handle drags in size box. Based on code contributed by Ben
10198 Mesander and IM - Window Manager A. */
10200 static void
10201 do_grow_window (w, e)
10202 WindowRef w;
10203 const EventRecord *e;
10205 Rect limit_rect;
10206 int rows, columns, width, height;
10207 struct frame *f = mac_window_to_frame (w);
10208 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
10209 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
10210 #if TARGET_API_MAC_CARBON
10211 Rect new_rect;
10212 #else
10213 long grow_size;
10214 #endif
10216 if (size_hints->flags & PMinSize)
10218 min_width = size_hints->min_width;
10219 min_height = size_hints->min_height;
10221 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
10223 #if TARGET_API_MAC_CARBON
10224 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
10225 return;
10226 height = new_rect.bottom - new_rect.top;
10227 width = new_rect.right - new_rect.left;
10228 #else
10229 grow_size = GrowWindow (w, e->where, &limit_rect);
10230 /* see if it really changed size */
10231 if (grow_size == 0)
10232 return;
10233 height = HiWord (grow_size);
10234 width = LoWord (grow_size);
10235 #endif
10237 if (width != FRAME_PIXEL_WIDTH (f)
10238 || height != FRAME_PIXEL_HEIGHT (f))
10240 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
10241 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
10243 x_set_window_size (f, 0, columns, rows);
10248 #if TARGET_API_MAC_CARBON
10249 static Point
10250 mac_get_ideal_size (f)
10251 struct frame *f;
10253 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10254 WindowRef w = FRAME_MAC_WINDOW (f);
10255 Point ideal_size;
10256 Rect standard_rect;
10257 int height, width, columns, rows;
10259 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
10260 ideal_size.v = dpyinfo->height;
10261 IsWindowInStandardState (w, &ideal_size, &standard_rect);
10262 /* Adjust the standard size according to character boundaries. */
10263 width = standard_rect.right - standard_rect.left;
10264 height = standard_rect.bottom - standard_rect.top;
10265 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
10266 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
10267 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
10268 ideal_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
10270 return ideal_size;
10272 #endif
10274 /* Handle clicks in zoom box. Calculation of "standard state" based
10275 on code in IM - Window Manager A and code contributed by Ben
10276 Mesander. The standard state of an Emacs window is 80-characters
10277 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10279 static void
10280 do_zoom_window (WindowRef w, int zoom_in_or_out)
10282 Rect zoom_rect, port_rect;
10283 int width, height;
10284 struct frame *f = mac_window_to_frame (w);
10285 #if TARGET_API_MAC_CARBON
10286 Point ideal_size = mac_get_ideal_size (f);
10288 GetWindowBounds (w, kWindowContentRgn, &port_rect);
10289 if (IsWindowInStandardState (w, &ideal_size, &zoom_rect)
10290 && port_rect.left == zoom_rect.left
10291 && port_rect.top == zoom_rect.top)
10292 zoom_in_or_out = inZoomIn;
10293 else
10294 zoom_in_or_out = inZoomOut;
10296 #ifdef MAC_OS8
10297 mac_clear_window (f);
10298 #endif
10299 ZoomWindowIdeal (w, zoom_in_or_out, &ideal_size);
10300 #else /* not TARGET_API_MAC_CARBON */
10301 GrafPtr save_port;
10302 Point top_left;
10303 int w_title_height, rows;
10304 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10306 GetPort (&save_port);
10308 SetPortWindowPort (w);
10310 /* Clear window to avoid flicker. */
10311 EraseRect (&(w->portRect));
10312 if (zoom_in_or_out == inZoomOut)
10314 SetPt (&top_left, w->portRect.left, w->portRect.top);
10315 LocalToGlobal (&top_left);
10317 /* calculate height of window's title bar */
10318 w_title_height = top_left.v - 1
10319 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
10321 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10322 zoom_rect = qd.screenBits.bounds;
10323 zoom_rect.top += w_title_height;
10324 InsetRect (&zoom_rect, 8, 4); /* not too tight */
10326 zoom_rect.right = zoom_rect.left
10327 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
10329 /* Adjust the standard size according to character boundaries. */
10330 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
10331 zoom_rect.bottom =
10332 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
10334 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
10335 = zoom_rect;
10338 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
10340 SetPort (save_port);
10341 #endif /* not TARGET_API_MAC_CARBON */
10343 #if !TARGET_API_MAC_CARBON
10344 /* retrieve window size and update application values */
10345 port_rect = w->portRect;
10346 height = port_rect.bottom - port_rect.top;
10347 width = port_rect.right - port_rect.left;
10349 mac_handle_size_change (f, width, height);
10350 mac_handle_origin_change (f);
10351 #endif
10354 static void
10355 mac_set_unicode_keystroke_event (code, buf)
10356 UniChar code;
10357 struct input_event *buf;
10359 int charset_id, c1, c2;
10361 if (code < 0x80)
10363 buf->kind = ASCII_KEYSTROKE_EVENT;
10364 buf->code = code;
10366 else if (code < 0x100)
10368 if (code < 0xA0)
10369 charset_id = CHARSET_8_BIT_CONTROL;
10370 else
10371 charset_id = charset_latin_iso8859_1;
10372 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10373 buf->code = MAKE_CHAR (charset_id, code, 0);
10375 else
10377 if (code < 0x2500)
10378 charset_id = charset_mule_unicode_0100_24ff,
10379 code -= 0x100;
10380 else if (code < 0x33FF)
10381 charset_id = charset_mule_unicode_2500_33ff,
10382 code -= 0x2500;
10383 else if (code >= 0xE000)
10384 charset_id = charset_mule_unicode_e000_ffff,
10385 code -= 0xE000;
10386 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
10387 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10388 buf->code = MAKE_CHAR (charset_id, c1, c2);
10392 static void
10393 do_keystroke (action, char_code, key_code, modifiers, timestamp, buf)
10394 EventKind action;
10395 unsigned char char_code;
10396 UInt32 key_code, modifiers;
10397 unsigned long timestamp;
10398 struct input_event *buf;
10400 static SInt16 last_key_script = -1;
10401 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
10402 UInt32 mapped_modifiers = mac_mapped_modifiers (modifiers);
10404 #ifdef MAC_OSX
10405 if (mapped_modifiers & kEventKeyModifierFnMask
10406 && key_code <= 0x7f
10407 && fn_keycode_to_keycode_table[key_code])
10408 key_code = fn_keycode_to_keycode_table[key_code];
10409 #endif
10411 if (key_code <= 0x7f && keycode_to_xkeysym_table[key_code])
10413 buf->kind = NON_ASCII_KEYSTROKE_EVENT;
10414 buf->code = 0xff00 | keycode_to_xkeysym_table[key_code];
10415 #ifdef MAC_OSX
10416 if (modifiers & kEventKeyModifierFnMask
10417 && key_code <= 0x7f
10418 && fn_keycode_to_keycode_table[key_code] == key_code)
10419 modifiers &= ~kEventKeyModifierFnMask;
10420 #endif
10422 else if (mapped_modifiers)
10424 /* translate the keycode back to determine the original key */
10425 #ifdef MAC_OSX
10426 UCKeyboardLayout *uchr_ptr = NULL;
10427 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10428 OSStatus err;
10429 KeyboardLayoutRef layout;
10431 err = KLGetCurrentKeyboardLayout (&layout);
10432 if (err == noErr)
10433 err = KLGetKeyboardLayoutProperty (layout, kKLuchrData,
10434 (const void **) &uchr_ptr);
10435 #else
10436 static SInt16 last_key_layout_id = 0;
10437 static Handle uchr_handle = (Handle)-1;
10438 SInt16 current_key_layout_id =
10439 GetScriptVariable (current_key_script, smScriptKeys);
10441 if (uchr_handle == (Handle)-1
10442 || last_key_layout_id != current_key_layout_id)
10444 uchr_handle = GetResource ('uchr', current_key_layout_id);
10445 last_key_layout_id = current_key_layout_id;
10447 if (uchr_handle)
10448 uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
10449 #endif
10451 if (uchr_ptr)
10453 OSStatus status;
10454 UInt16 key_action = action - keyDown;
10455 UInt32 modifier_key_state = (modifiers & ~mapped_modifiers) >> 8;
10456 UInt32 keyboard_type = LMGetKbdType ();
10457 SInt32 dead_key_state = 0;
10458 UniChar code;
10459 UniCharCount actual_length;
10461 status = UCKeyTranslate (uchr_ptr, key_code, key_action,
10462 modifier_key_state, keyboard_type,
10463 kUCKeyTranslateNoDeadKeysMask,
10464 &dead_key_state,
10465 1, &actual_length, &code);
10466 if (status == noErr && actual_length == 1)
10467 mac_set_unicode_keystroke_event (code, buf);
10469 #endif /* MAC_OSX */
10471 if (buf->kind == NO_EVENT)
10473 /* This code comes from Keyboard Resource, Appendix C of IM
10474 - Text. This is necessary since shift is ignored in KCHR
10475 table translation when option or command is pressed. It
10476 also does not translate correctly control-shift chars
10477 like C-% so mask off shift here also. */
10478 /* Mask off modifier keys that are mapped to some Emacs
10479 modifiers. */
10480 int new_modifiers = modifiers & ~mapped_modifiers;
10481 /* set high byte of keycode to modifier high byte*/
10482 int new_key_code = key_code | new_modifiers;
10483 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
10484 unsigned long some_state = 0;
10485 UInt32 new_char_code;
10487 new_char_code = KeyTranslate (kchr_ptr, new_key_code, &some_state);
10488 if (new_char_code == 0)
10489 /* Seems like a dead key. Append up-stroke. */
10490 new_char_code = KeyTranslate (kchr_ptr, new_key_code | 0x80,
10491 &some_state);
10492 if (new_char_code)
10494 buf->kind = ASCII_KEYSTROKE_EVENT;
10495 buf->code = new_char_code & 0xff;
10500 if (buf->kind == NO_EVENT)
10502 buf->kind = ASCII_KEYSTROKE_EVENT;
10503 buf->code = char_code;
10506 buf->modifiers = mac_to_emacs_modifiers (modifiers);
10507 buf->modifiers |= (extra_keyboard_modifiers
10508 & (meta_modifier | alt_modifier
10509 | hyper_modifier | super_modifier));
10511 #if TARGET_API_MAC_CARBON
10512 if (buf->kind == ASCII_KEYSTROKE_EVENT
10513 && buf->code >= 0x80 && buf->modifiers)
10515 OSStatus err;
10516 TextEncoding encoding = kTextEncodingMacRoman;
10517 TextToUnicodeInfo ttu_info;
10519 UpgradeScriptInfoToTextEncoding (current_key_script,
10520 kTextLanguageDontCare,
10521 kTextRegionDontCare,
10522 NULL, &encoding);
10523 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
10524 if (err == noErr)
10526 UniChar code;
10527 Str255 pstr;
10528 ByteCount unicode_len;
10530 pstr[0] = 1;
10531 pstr[1] = buf->code;
10532 err = ConvertFromPStringToUnicode (ttu_info, pstr,
10533 sizeof (UniChar),
10534 &unicode_len, &code);
10535 if (err == noErr && unicode_len == sizeof (UniChar))
10536 mac_set_unicode_keystroke_event (code, buf);
10537 DisposeTextToUnicodeInfo (&ttu_info);
10540 #endif
10542 if (buf->kind == ASCII_KEYSTROKE_EVENT
10543 && buf->code >= 0x80
10544 && last_key_script != current_key_script)
10546 struct input_event event;
10548 EVENT_INIT (event);
10549 event.kind = LANGUAGE_CHANGE_EVENT;
10550 event.arg = Qnil;
10551 event.code = current_key_script;
10552 event.timestamp = timestamp;
10553 kbd_buffer_store_event (&event);
10554 last_key_script = current_key_script;
10558 void
10559 mac_store_apple_event (class, id, desc)
10560 Lisp_Object class, id;
10561 const AEDesc *desc;
10563 struct input_event buf;
10565 EVENT_INIT (buf);
10567 buf.kind = MAC_APPLE_EVENT;
10568 buf.x = class;
10569 buf.y = id;
10570 XSETFRAME (buf.frame_or_window,
10571 mac_focus_frame (&one_mac_display_info));
10572 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10573 is safe to use them during read_socket_hook. */
10574 buf.arg = mac_aedesc_to_lisp (desc);
10575 kbd_buffer_store_event (&buf);
10578 #if TARGET_API_MAC_CARBON
10579 static OSStatus
10580 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
10581 event, num_params, names, types)
10582 AEEventClass class;
10583 AEEventID id;
10584 Lisp_Object class_key, id_key;
10585 EventRef event;
10586 UInt32 num_params;
10587 const EventParamName *names;
10588 const EventParamType *types;
10590 OSStatus err = eventNotHandledErr;
10591 Lisp_Object binding;
10593 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
10594 if (!NILP (binding) && !EQ (binding, Qundefined))
10596 if (INTEGERP (binding))
10597 err = XINT (binding);
10598 else
10600 AppleEvent apple_event;
10601 err = create_apple_event_from_event_ref (event, num_params,
10602 names, types,
10603 &apple_event);
10604 if (err == noErr)
10606 mac_store_apple_event (class_key, id_key, &apple_event);
10607 AEDisposeDesc (&apple_event);
10608 mac_wakeup_from_rne ();
10613 return err;
10616 void
10617 mac_store_drag_event (window, mouse_pos, modifiers, desc)
10618 WindowRef window;
10619 Point mouse_pos;
10620 SInt16 modifiers;
10621 const AEDesc *desc;
10623 struct input_event buf;
10625 EVENT_INIT (buf);
10627 buf.kind = DRAG_N_DROP_EVENT;
10628 buf.modifiers = mac_to_emacs_modifiers (modifiers);
10629 buf.timestamp = TickCount () * (1000 / 60);
10630 XSETINT (buf.x, mouse_pos.h);
10631 XSETINT (buf.y, mouse_pos.v);
10632 XSETFRAME (buf.frame_or_window, mac_window_to_frame (window));
10633 buf.arg = mac_aedesc_to_lisp (desc);
10634 kbd_buffer_store_event (&buf);
10637 #ifdef MAC_OSX
10638 OSStatus
10639 mac_store_service_event (event)
10640 EventRef event;
10642 OSStatus err;
10643 Lisp_Object id_key;
10644 int num_params;
10645 const EventParamName *names;
10646 const EventParamType *types;
10647 static const EventParamName names_pfm[] =
10648 {kEventParamServiceMessageName, kEventParamServiceUserData};
10649 static const EventParamType types_pfm[] =
10650 {typeCFStringRef, typeCFStringRef};
10652 switch (GetEventKind (event))
10654 case kEventServicePaste:
10655 id_key = Qpaste;
10656 num_params = 0;
10657 names = NULL;
10658 types = NULL;
10659 break;
10661 case kEventServicePerform:
10662 id_key = Qperform;
10663 num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
10664 names = names_pfm;
10665 types = types_pfm;
10666 break;
10668 default:
10669 abort ();
10672 err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
10673 event, num_params,
10674 names, types);
10676 return err;
10678 #endif /* MAC_OSX */
10680 static pascal OSStatus
10681 mac_handle_window_event (next_handler, event, data)
10682 EventHandlerCallRef next_handler;
10683 EventRef event;
10684 void *data;
10686 WindowRef wp;
10687 OSStatus err, result = eventNotHandledErr;
10688 struct frame *f;
10689 UInt32 attributes;
10690 XSizeHints *size_hints;
10692 err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
10693 NULL, sizeof (WindowRef), NULL, &wp);
10694 if (err != noErr)
10695 return eventNotHandledErr;
10697 f = mac_window_to_frame (wp);
10698 switch (GetEventKind (event))
10700 /* -- window refresh events -- */
10702 case kEventWindowUpdate:
10703 result = CallNextEventHandler (next_handler, event);
10704 if (result != eventNotHandledErr)
10705 break;
10707 do_window_update (wp);
10708 result = noErr;
10709 break;
10711 /* -- window state change events -- */
10713 case kEventWindowShowing:
10714 size_hints = FRAME_SIZE_HINTS (f);
10715 if (!(size_hints->flags & (USPosition | PPosition)))
10717 struct frame *sf = SELECTED_FRAME ();
10719 if (!(FRAME_MAC_P (sf)))
10720 RepositionWindow (wp, NULL, kWindowCenterOnMainScreen);
10721 else
10723 RepositionWindow (wp, FRAME_MAC_WINDOW (sf),
10724 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10725 kWindowCascadeStartAtParentWindowScreen
10726 #else
10727 kWindowCascadeOnParentWindowScreen
10728 #endif
10730 #if USE_MAC_TOOLBAR
10731 /* This is a workaround. RepositionWindow fails to put
10732 a window at the cascading position when its parent
10733 window has a Carbon HIToolbar. */
10734 if (f->top_pos == sf->top_pos && f->left_pos == sf->left_pos)
10735 MoveWindowStructure (wp, f->left_pos + 10, f->top_pos + 32);
10736 #endif
10738 result = noErr;
10740 break;
10742 case kEventWindowHiding:
10743 /* Before unmapping the window, update the WM_SIZE_HINTS
10744 property to claim that the current position of the window is
10745 user-specified, rather than program-specified, so that when
10746 the window is mapped again, it will be placed at the same
10747 location, without forcing the user to position it by hand
10748 again (they have already done that once for this window.) */
10749 x_wm_set_size_hint (f, (long) 0, 1);
10750 result = noErr;
10751 break;
10753 case kEventWindowShown:
10754 case kEventWindowHidden:
10755 case kEventWindowCollapsed:
10756 case kEventWindowExpanded:
10757 mac_handle_visibility_change (f);
10758 result = noErr;
10759 break;
10761 case kEventWindowBoundsChanging:
10762 result = CallNextEventHandler (next_handler, event);
10763 if (result != eventNotHandledErr)
10764 break;
10766 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
10767 NULL, sizeof (UInt32), NULL, &attributes);
10768 if (err != noErr)
10769 break;
10771 size_hints = FRAME_SIZE_HINTS (f);
10772 if ((attributes & kWindowBoundsChangeUserResize)
10773 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
10774 == (PResizeInc | PBaseSize | PMinSize)))
10776 Rect bounds;
10777 int width, height;
10779 err = GetEventParameter (event, kEventParamCurrentBounds,
10780 typeQDRectangle, NULL, sizeof (Rect),
10781 NULL, &bounds);
10782 if (err != noErr)
10783 break;
10785 width = bounds.right - bounds.left;
10786 height = bounds.bottom - bounds.top;
10788 if (width < size_hints->min_width)
10789 width = size_hints->min_width;
10790 else
10791 width = size_hints->base_width
10792 + (int) ((width - size_hints->base_width)
10793 / (float) size_hints->width_inc + .5)
10794 * size_hints->width_inc;
10796 if (height < size_hints->min_height)
10797 height = size_hints->min_height;
10798 else
10799 height = size_hints->base_height
10800 + (int) ((height - size_hints->base_height)
10801 / (float) size_hints->height_inc + .5)
10802 * size_hints->height_inc;
10804 bounds.right = bounds.left + width;
10805 bounds.bottom = bounds.top + height;
10806 SetEventParameter (event, kEventParamCurrentBounds,
10807 typeQDRectangle, sizeof (Rect), &bounds);
10808 result = noErr;
10810 break;
10812 case kEventWindowBoundsChanged:
10813 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
10814 NULL, sizeof (UInt32), NULL, &attributes);
10815 if (err != noErr)
10816 break;
10818 if (attributes & kWindowBoundsChangeSizeChanged)
10820 Rect bounds;
10822 err = GetEventParameter (event, kEventParamCurrentBounds,
10823 typeQDRectangle, NULL, sizeof (Rect),
10824 NULL, &bounds);
10825 if (err == noErr)
10827 int width, height;
10829 width = bounds.right - bounds.left;
10830 height = bounds.bottom - bounds.top;
10831 mac_handle_size_change (f, width, height);
10832 mac_wakeup_from_rne ();
10836 if (attributes & kWindowBoundsChangeOriginChanged)
10837 mac_handle_origin_change (f);
10839 result = noErr;
10840 break;
10842 /* -- window action events -- */
10844 case kEventWindowClose:
10846 struct input_event buf;
10848 EVENT_INIT (buf);
10849 buf.kind = DELETE_WINDOW_EVENT;
10850 XSETFRAME (buf.frame_or_window, f);
10851 buf.arg = Qnil;
10852 kbd_buffer_store_event (&buf);
10854 result = noErr;
10855 break;
10857 case kEventWindowGetIdealSize:
10858 result = CallNextEventHandler (next_handler, event);
10859 if (result != eventNotHandledErr)
10860 break;
10863 Point ideal_size = mac_get_ideal_size (f);
10865 err = SetEventParameter (event, kEventParamDimensions,
10866 typeQDPoint, sizeof (Point), &ideal_size);
10867 if (err == noErr)
10868 result = noErr;
10870 break;
10872 #ifdef MAC_OSX
10873 case kEventWindowToolbarSwitchMode:
10875 static const EventParamName names[] = {kEventParamDirectObject,
10876 kEventParamWindowMouseLocation,
10877 kEventParamKeyModifiers,
10878 kEventParamMouseButton,
10879 kEventParamClickCount,
10880 kEventParamMouseChord};
10881 static const EventParamType types[] = {typeWindowRef,
10882 typeQDPoint,
10883 typeUInt32,
10884 typeMouseButton,
10885 typeUInt32,
10886 typeUInt32};
10887 int num_params = sizeof (names) / sizeof (names[0]);
10889 err = mac_store_event_ref_as_apple_event (0, 0,
10890 Qwindow,
10891 Qtoolbar_switch_mode,
10892 event, num_params,
10893 names, types);
10895 if (err == noErr)
10896 result = noErr;
10897 break;
10898 #endif
10900 #if USE_MAC_TSM
10901 /* -- window focus events -- */
10903 case kEventWindowFocusAcquired:
10904 err = mac_tsm_resume ();
10905 if (err == noErr)
10906 result = noErr;
10907 break;
10909 case kEventWindowFocusRelinquish:
10910 err = mac_tsm_suspend ();
10911 if (err == noErr)
10912 result = noErr;
10913 break;
10914 #endif
10916 default:
10917 abort ();
10920 return result;
10923 static pascal OSStatus
10924 mac_handle_application_event (next_handler, event, data)
10925 EventHandlerCallRef next_handler;
10926 EventRef event;
10927 void *data;
10929 OSStatus err, result = eventNotHandledErr;
10931 switch (GetEventKind (event))
10933 #if USE_MAC_TSM
10934 case kEventAppActivated:
10935 err = mac_tsm_resume ();
10936 break;
10938 case kEventAppDeactivated:
10939 err = mac_tsm_suspend ();
10940 break;
10941 #endif
10943 default:
10944 abort ();
10947 if (err == noErr)
10948 result = noErr;
10950 return result;
10953 static pascal OSStatus
10954 mac_handle_keyboard_event (next_handler, event, data)
10955 EventHandlerCallRef next_handler;
10956 EventRef event;
10957 void *data;
10959 OSStatus err, result = eventNotHandledErr;
10960 UInt32 event_kind, key_code, modifiers, mapped_modifiers;
10961 unsigned char char_code;
10963 event_kind = GetEventKind (event);
10964 switch (event_kind)
10966 case kEventRawKeyDown:
10967 case kEventRawKeyRepeat:
10968 case kEventRawKeyUp:
10969 if (read_socket_inev == NULL)
10971 result = CallNextEventHandler (next_handler, event);
10972 break;
10975 err = GetEventParameter (event, kEventParamKeyModifiers,
10976 typeUInt32, NULL,
10977 sizeof (UInt32), NULL, &modifiers);
10978 if (err != noErr)
10979 break;
10981 mapped_modifiers = mac_mapped_modifiers (modifiers);
10983 /* When using Carbon Events, we need to pass raw keyboard events
10984 to the TSM ourselves. If TSM handles it, it will pass back
10985 noErr, otherwise it will pass back "eventNotHandledErr" and
10986 we can process it normally. */
10987 if (!(mapped_modifiers
10988 & ~(mac_pass_command_to_system ? cmdKey : 0)
10989 & ~(mac_pass_control_to_system ? controlKey : 0)))
10991 result = CallNextEventHandler (next_handler, event);
10992 if (result != eventNotHandledErr)
10993 break;
10996 #if USE_MAC_TSM
10997 if (read_socket_inev->kind != NO_EVENT)
10999 result = noErr;
11000 break;
11002 #endif
11004 if (event_kind == kEventRawKeyUp)
11005 break;
11007 err = GetEventParameter (event, kEventParamKeyMacCharCodes,
11008 typeChar, NULL,
11009 sizeof (char), NULL, &char_code);
11010 if (err != noErr)
11011 break;
11013 err = GetEventParameter (event, kEventParamKeyCode,
11014 typeUInt32, NULL,
11015 sizeof (UInt32), NULL, &key_code);
11016 if (err != noErr)
11017 break;
11019 do_keystroke ((event_kind == kEventRawKeyDown ? keyDown : autoKey),
11020 char_code, key_code, modifiers,
11021 ((unsigned long)
11022 (GetEventTime (event) / kEventDurationMillisecond)),
11023 read_socket_inev);
11024 result = noErr;
11025 break;
11027 default:
11028 abort ();
11031 return result;
11034 static pascal OSStatus
11035 mac_handle_command_event (next_handler, event, data)
11036 EventHandlerCallRef next_handler;
11037 EventRef event;
11038 void *data;
11040 OSStatus err, result = eventNotHandledErr;
11041 HICommand command;
11042 static const EventParamName names[] =
11043 {kEventParamDirectObject, kEventParamKeyModifiers};
11044 static const EventParamType types[] =
11045 {typeHICommand, typeUInt32};
11046 int num_params = sizeof (names) / sizeof (names[0]);
11048 err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
11049 NULL, sizeof (HICommand), NULL, &command);
11050 if (err != noErr)
11051 return eventNotHandledErr;
11053 switch (GetEventKind (event))
11055 case kEventCommandProcess:
11056 result = CallNextEventHandler (next_handler, event);
11057 if (result != eventNotHandledErr)
11058 break;
11060 err = GetEventParameter (event, kEventParamDirectObject,
11061 typeHICommand, NULL,
11062 sizeof (HICommand), NULL, &command);
11064 if (err != noErr || command.commandID == 0)
11065 break;
11067 /* A HI command event is mapped to an Apple event whose event
11068 class symbol is `hi-command' and event ID is its command
11069 ID. */
11070 err = mac_store_event_ref_as_apple_event (0, command.commandID,
11071 Qhi_command, Qnil,
11072 event, num_params,
11073 names, types);
11074 if (err == noErr)
11075 result = noErr;
11076 break;
11078 default:
11079 abort ();
11082 return result;
11085 static pascal OSStatus
11086 mac_handle_mouse_event (next_handler, event, data)
11087 EventHandlerCallRef next_handler;
11088 EventRef event;
11089 void *data;
11091 OSStatus err, result = eventNotHandledErr;
11093 switch (GetEventKind (event))
11095 case kEventMouseWheelMoved:
11097 WindowRef wp;
11098 struct frame *f;
11099 EventMouseWheelAxis axis;
11100 SInt32 delta;
11101 Point point;
11103 result = CallNextEventHandler (next_handler, event);
11104 if (result != eventNotHandledErr || read_socket_inev == NULL)
11105 break;
11107 f = mac_focus_frame (&one_mac_display_info);
11109 err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
11110 NULL, sizeof (WindowRef), NULL, &wp);
11111 if (err != noErr
11112 || wp != FRAME_MAC_WINDOW (f))
11113 break;
11115 err = GetEventParameter (event, kEventParamMouseWheelAxis,
11116 typeMouseWheelAxis, NULL,
11117 sizeof (EventMouseWheelAxis), NULL, &axis);
11118 if (err != noErr || axis != kEventMouseWheelAxisY)
11119 break;
11121 err = GetEventParameter (event, kEventParamMouseLocation,
11122 typeQDPoint, NULL, sizeof (Point),
11123 NULL, &point);
11124 if (err != noErr)
11125 break;
11127 point.h -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
11128 point.v -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
11129 if (point.h < 0 || point.v < 0
11130 || EQ (window_from_coordinates (f, point.h, point.v, 0, 0, 0, 1),
11131 f->tool_bar_window))
11132 break;
11134 err = GetEventParameter (event, kEventParamMouseWheelDelta,
11135 typeSInt32, NULL, sizeof (SInt32),
11136 NULL, &delta);
11137 if (err != noErr)
11138 break;
11140 read_socket_inev->kind = WHEEL_EVENT;
11141 read_socket_inev->code = 0;
11142 read_socket_inev->modifiers =
11143 (mac_event_to_emacs_modifiers (event)
11144 | ((delta < 0) ? down_modifier : up_modifier));
11145 XSETINT (read_socket_inev->x, point.h);
11146 XSETINT (read_socket_inev->y, point.v);
11147 XSETFRAME (read_socket_inev->frame_or_window, f);
11149 result = noErr;
11151 break;
11153 default:
11154 abort ();
11157 return result;
11160 #if USE_MAC_TSM
11161 static pascal OSStatus
11162 mac_handle_text_input_event (next_handler, event, data)
11163 EventHandlerCallRef next_handler;
11164 EventRef event;
11165 void *data;
11167 OSStatus err, result;
11168 Lisp_Object id_key = Qnil;
11169 int num_params;
11170 const EventParamName *names;
11171 const EventParamType *types;
11172 static UInt32 seqno_uaia = 0;
11173 static const EventParamName names_uaia[] =
11174 {kEventParamTextInputSendComponentInstance,
11175 kEventParamTextInputSendRefCon,
11176 kEventParamTextInputSendSLRec,
11177 kEventParamTextInputSendFixLen,
11178 kEventParamTextInputSendText,
11179 kEventParamTextInputSendUpdateRng,
11180 kEventParamTextInputSendHiliteRng,
11181 kEventParamTextInputSendClauseRng,
11182 kEventParamTextInputSendPinRng,
11183 kEventParamTextInputSendTextServiceEncoding,
11184 kEventParamTextInputSendTextServiceMacEncoding,
11185 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
11186 static const EventParamType types_uaia[] =
11187 {typeComponentInstance,
11188 typeLongInteger,
11189 typeIntlWritingCode,
11190 typeLongInteger,
11191 #ifdef MAC_OSX
11192 typeUnicodeText,
11193 #else
11194 typeChar,
11195 #endif
11196 typeTextRangeArray,
11197 typeTextRangeArray,
11198 typeOffsetArray,
11199 typeTextRange,
11200 typeUInt32,
11201 typeUInt32,
11202 typeUInt32};
11203 static const EventParamName names_ufke[] =
11204 {kEventParamTextInputSendComponentInstance,
11205 kEventParamTextInputSendRefCon,
11206 kEventParamTextInputSendSLRec,
11207 kEventParamTextInputSendText};
11208 static const EventParamType types_ufke[] =
11209 {typeComponentInstance,
11210 typeLongInteger,
11211 typeIntlWritingCode,
11212 typeUnicodeText};
11214 result = CallNextEventHandler (next_handler, event);
11215 if (result != eventNotHandledErr)
11216 return result;
11218 switch (GetEventKind (event))
11220 case kEventTextInputUpdateActiveInputArea:
11221 id_key = Qupdate_active_input_area;
11222 num_params = sizeof (names_uaia) / sizeof (names_uaia[0]);
11223 names = names_uaia;
11224 types = types_uaia;
11225 SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
11226 typeUInt32, sizeof (UInt32), &seqno_uaia);
11227 seqno_uaia++;
11228 result = noErr;
11229 break;
11231 case kEventTextInputUnicodeForKeyEvent:
11233 EventRef kbd_event;
11234 UInt32 actual_size, modifiers;
11236 err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent,
11237 typeEventRef, NULL, sizeof (EventRef), NULL,
11238 &kbd_event);
11239 if (err == noErr)
11240 err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
11241 typeUInt32, NULL,
11242 sizeof (UInt32), NULL, &modifiers);
11243 if (err == noErr && mac_mapped_modifiers (modifiers))
11244 /* There're mapped modifier keys. Process it in
11245 do_keystroke. */
11246 break;
11247 if (err == noErr)
11248 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
11249 typeUnicodeText, NULL, 0, &actual_size,
11250 NULL);
11251 if (err == noErr && actual_size == sizeof (UniChar))
11253 UniChar code;
11255 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
11256 typeUnicodeText, NULL,
11257 sizeof (UniChar), NULL, &code);
11258 if (err == noErr && code < 0x80)
11260 /* ASCII character. Process it in do_keystroke. */
11261 if (read_socket_inev && code >= 0x20 && code <= 0x7e)
11263 UInt32 key_code;
11265 err = GetEventParameter (kbd_event, kEventParamKeyCode,
11266 typeUInt32, NULL, sizeof (UInt32),
11267 NULL, &key_code);
11268 if (!(err == noErr && key_code <= 0x7f
11269 && keycode_to_xkeysym_table [key_code]))
11271 struct frame *f =
11272 mac_focus_frame (&one_mac_display_info);
11274 read_socket_inev->kind = ASCII_KEYSTROKE_EVENT;
11275 read_socket_inev->code = code;
11276 read_socket_inev->modifiers =
11277 mac_to_emacs_modifiers (modifiers);
11278 read_socket_inev->modifiers |=
11279 (extra_keyboard_modifiers
11280 & (meta_modifier | alt_modifier
11281 | hyper_modifier | super_modifier));
11282 XSETFRAME (read_socket_inev->frame_or_window, f);
11285 break;
11288 if (err == noErr)
11290 /* Non-ASCII keystrokes without mapped modifiers are
11291 processed at the Lisp level. */
11292 id_key = Qunicode_for_key_event;
11293 num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
11294 names = names_ufke;
11295 types = types_ufke;
11296 result = noErr;
11299 break;
11301 case kEventTextInputOffsetToPos:
11303 struct frame *f;
11304 struct window *w;
11305 Point p;
11307 if (!OVERLAYP (Vmac_ts_active_input_overlay))
11308 break;
11310 /* Strictly speaking, this is not always correct because
11311 previous events may change some states about display. */
11312 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
11314 /* Active input area is displayed around the current point. */
11315 f = SELECTED_FRAME ();
11316 w = XWINDOW (f->selected_window);
11318 else if (WINDOWP (echo_area_window))
11320 /* Active input area is displayed in the echo area. */
11321 w = XWINDOW (echo_area_window);
11322 f = WINDOW_XFRAME (w);
11324 else
11325 break;
11327 p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
11328 + WINDOW_LEFT_FRINGE_WIDTH (w)
11329 + f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f));
11330 p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
11331 + FONT_BASE (FRAME_FONT (f))
11332 + f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f));
11333 err = SetEventParameter (event, kEventParamTextInputReplyPoint,
11334 typeQDPoint, sizeof (typeQDPoint), &p);
11335 if (err == noErr)
11336 result = noErr;
11338 break;
11340 default:
11341 abort ();
11344 if (!NILP (id_key))
11345 err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
11346 event, num_params,
11347 names, types);
11348 return result;
11350 #endif
11351 #endif /* TARGET_API_MAC_CARBON */
11354 OSStatus
11355 install_window_handler (window)
11356 WindowRef window;
11358 OSStatus err = noErr;
11360 #if TARGET_API_MAC_CARBON
11361 if (err == noErr)
11363 static const EventTypeSpec specs[] =
11365 /* -- window refresh events -- */
11366 {kEventClassWindow, kEventWindowUpdate},
11367 /* -- window state change events -- */
11368 {kEventClassWindow, kEventWindowShowing},
11369 {kEventClassWindow, kEventWindowHiding},
11370 {kEventClassWindow, kEventWindowShown},
11371 {kEventClassWindow, kEventWindowHidden},
11372 {kEventClassWindow, kEventWindowCollapsed},
11373 {kEventClassWindow, kEventWindowExpanded},
11374 {kEventClassWindow, kEventWindowBoundsChanging},
11375 {kEventClassWindow, kEventWindowBoundsChanged},
11376 /* -- window action events -- */
11377 {kEventClassWindow, kEventWindowClose},
11378 {kEventClassWindow, kEventWindowGetIdealSize},
11379 #ifdef MAC_OSX
11380 {kEventClassWindow, kEventWindowToolbarSwitchMode},
11381 #endif
11382 #if USE_MAC_TSM
11383 /* -- window focus events -- */
11384 {kEventClassWindow, kEventWindowFocusAcquired},
11385 {kEventClassWindow, kEventWindowFocusRelinquish},
11386 #endif
11388 static EventHandlerUPP handle_window_eventUPP = NULL;
11390 if (handle_window_eventUPP == NULL)
11391 handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
11393 err = InstallWindowEventHandler (window, handle_window_eventUPP,
11394 GetEventTypeCount (specs),
11395 specs, NULL, NULL);
11397 #endif
11399 if (err == noErr)
11400 err = install_drag_handler (window);
11402 return err;
11405 void
11406 remove_window_handler (window)
11407 WindowRef window;
11409 remove_drag_handler (window);
11412 #if TARGET_API_MAC_CARBON
11413 static OSStatus
11414 install_application_handler ()
11416 OSStatus err = noErr;
11418 if (err == noErr)
11420 static const EventTypeSpec specs[] = {
11421 #if USE_MAC_TSM
11422 {kEventClassApplication, kEventAppActivated},
11423 {kEventClassApplication, kEventAppDeactivated},
11424 #endif
11427 err = InstallApplicationEventHandler (NewEventHandlerUPP
11428 (mac_handle_application_event),
11429 GetEventTypeCount (specs),
11430 specs, NULL, NULL);
11433 if (err == noErr)
11435 static const EventTypeSpec specs[] =
11436 {{kEventClassKeyboard, kEventRawKeyDown},
11437 {kEventClassKeyboard, kEventRawKeyRepeat},
11438 {kEventClassKeyboard, kEventRawKeyUp}};
11440 err = InstallApplicationEventHandler (NewEventHandlerUPP
11441 (mac_handle_keyboard_event),
11442 GetEventTypeCount (specs),
11443 specs, NULL, NULL);
11446 if (err == noErr)
11448 static const EventTypeSpec specs[] =
11449 {{kEventClassCommand, kEventCommandProcess}};
11451 err = InstallApplicationEventHandler (NewEventHandlerUPP
11452 (mac_handle_command_event),
11453 GetEventTypeCount (specs),
11454 specs, NULL, NULL);
11457 if (err == noErr)
11459 static const EventTypeSpec specs[] =
11460 {{kEventClassMouse, kEventMouseWheelMoved}};
11462 err = InstallApplicationEventHandler (NewEventHandlerUPP
11463 (mac_handle_mouse_event),
11464 GetEventTypeCount (specs),
11465 specs, NULL, NULL);
11468 #if USE_MAC_TSM
11469 if (err == noErr)
11471 static const EventTypeSpec spec[] =
11472 {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
11473 {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
11474 {kEventClassTextInput, kEventTextInputOffsetToPos}};
11476 err = InstallApplicationEventHandler (NewEventHandlerUPP
11477 (mac_handle_text_input_event),
11478 GetEventTypeCount (spec),
11479 spec, NULL, NULL);
11481 #endif
11483 if (err == noErr)
11484 err = install_menu_target_item_handler ();
11486 #ifdef MAC_OSX
11487 if (err == noErr)
11488 err = install_service_handler ();
11489 #endif
11491 return err;
11493 #endif
11495 static pascal void
11496 mac_handle_dm_notification (event)
11497 AppleEvent *event;
11499 mac_screen_config_changed = 1;
11502 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11503 static void
11504 mac_handle_cg_display_reconfig (display, flags, user_info)
11505 CGDirectDisplayID display;
11506 CGDisplayChangeSummaryFlags flags;
11507 void *user_info;
11509 mac_screen_config_changed = 1;
11511 #endif
11513 static OSErr
11514 init_dm_notification_handler ()
11516 OSErr err = noErr;
11518 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11519 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11520 if (CGDisplayRegisterReconfigurationCallback != NULL)
11521 #endif
11523 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig,
11524 NULL);
11526 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11527 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11528 #endif
11529 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11530 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11532 static DMNotificationUPP handle_dm_notificationUPP = NULL;
11533 ProcessSerialNumber psn;
11535 if (handle_dm_notificationUPP == NULL)
11536 handle_dm_notificationUPP =
11537 NewDMNotificationUPP (mac_handle_dm_notification);
11539 err = GetCurrentProcess (&psn);
11540 if (err == noErr)
11541 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
11543 #endif
11545 return err;
11548 static void
11549 mac_get_screen_info (dpyinfo)
11550 struct mac_display_info *dpyinfo;
11552 #ifdef MAC_OSX
11553 /* HasDepth returns true if it is possible to have a 32 bit display,
11554 but this may not be what is actually used. Mac OSX can do better. */
11555 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
11556 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
11558 CGDisplayErr err;
11559 CGDisplayCount ndisps;
11560 CGDirectDisplayID *displays;
11562 err = CGGetActiveDisplayList (0, NULL, &ndisps);
11563 if (err == noErr)
11565 displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
11566 err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
11568 if (err == noErr)
11570 CGRect bounds = CGRectZero;
11572 while (ndisps-- > 0)
11573 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
11574 dpyinfo->height = CGRectGetHeight (bounds);
11575 dpyinfo->width = CGRectGetWidth (bounds);
11577 else
11579 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
11580 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
11583 #else /* !MAC_OSX */
11585 GDHandle gdh = GetMainDevice ();
11586 Rect rect = (**gdh).gdRect;
11588 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
11589 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
11590 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
11591 break;
11593 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
11594 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
11595 UnionRect (&rect, &(**gdh).gdRect, &rect);
11597 dpyinfo->height = rect.bottom - rect.top;
11598 dpyinfo->width = rect.right - rect.left;
11600 #endif /* !MAC_OSX */
11604 #if __profile__
11605 void
11606 profiler_exit_proc ()
11608 ProfilerDump ("\pEmacs.prof");
11609 ProfilerTerm ();
11611 #endif
11613 /* These few functions implement Emacs as a normal Mac application
11614 (almost): set up the heap and the Toolbox, handle necessary system
11615 events plus a few simple menu events. They also set up Emacs's
11616 access to functions defined in the rest of this file. Emacs uses
11617 function hooks to perform all its terminal I/O. A complete list of
11618 these functions appear in termhooks.h. For what they do, read the
11619 comments there and see also w32term.c and xterm.c. What's
11620 noticeably missing here is the event loop, which is normally
11621 present in most Mac application. After performing the necessary
11622 Mac initializations, main passes off control to emacs_main
11623 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11624 (defined further below) to read input. This is where
11625 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11627 #ifdef MAC_OS8
11628 #undef main
11630 main (void)
11632 #if __profile__ /* is the profiler on? */
11633 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
11634 exit(1);
11635 #endif
11637 #if __MWERKS__
11638 /* set creator and type for files created by MSL */
11639 _fcreator = MAC_EMACS_CREATOR_CODE;
11640 _ftype = 'TEXT';
11641 #endif
11643 do_init_managers ();
11645 do_get_menus ();
11647 #ifndef USE_LSB_TAG
11648 do_check_ram_size ();
11649 #endif
11651 init_emacs_passwd_dir ();
11653 init_environ ();
11655 init_coercion_handler ();
11657 initialize_applescript ();
11659 init_apple_event_handler ();
11661 init_dm_notification_handler ();
11664 char **argv;
11665 int argc = 0;
11667 /* set up argv array from STR# resource */
11668 get_string_list (&argv, ARGV_STRING_LIST_ID);
11669 while (argv[argc])
11670 argc++;
11672 /* free up AppleScript resources on exit */
11673 atexit (terminate_applescript);
11675 #if __profile__ /* is the profiler on? */
11676 atexit (profiler_exit_proc);
11677 #endif
11679 /* 3rd param "envp" never used in emacs_main */
11680 (void) emacs_main (argc, argv, 0);
11683 /* Never reached - real exit in Fkill_emacs */
11684 return 0;
11686 #endif
11688 #if !TARGET_API_MAC_CARBON
11689 static RgnHandle mouse_region = NULL;
11691 Boolean
11692 mac_wait_next_event (er, sleep_time, dequeue)
11693 EventRecord *er;
11694 UInt32 sleep_time;
11695 Boolean dequeue;
11697 static EventRecord er_buf = {nullEvent};
11698 UInt32 target_tick, current_tick;
11699 EventMask event_mask;
11701 if (mouse_region == NULL)
11702 mouse_region = NewRgn ();
11704 event_mask = everyEvent;
11705 if (!mac_ready_for_apple_events)
11706 event_mask -= highLevelEventMask;
11708 current_tick = TickCount ();
11709 target_tick = current_tick + sleep_time;
11711 if (er_buf.what == nullEvent)
11712 while (!WaitNextEvent (event_mask, &er_buf,
11713 target_tick - current_tick, mouse_region))
11715 current_tick = TickCount ();
11716 if (target_tick <= current_tick)
11717 return false;
11720 *er = er_buf;
11721 if (dequeue)
11722 er_buf.what = nullEvent;
11723 return true;
11725 #endif /* not TARGET_API_MAC_CARBON */
11727 #if TARGET_API_MAC_CARBON
11728 OSStatus
11729 mac_post_mouse_moved_event ()
11731 EventRef event = NULL;
11732 OSStatus err;
11734 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
11735 kEventAttributeNone, &event);
11736 if (err == noErr)
11738 Point mouse_pos;
11740 GetGlobalMouse (&mouse_pos);
11741 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
11742 sizeof (Point), &mouse_pos);
11744 if (err == noErr)
11746 UInt32 modifiers = GetCurrentKeyModifiers ();
11748 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
11749 sizeof (UInt32), &modifiers);
11751 if (err == noErr)
11752 err = PostEventToQueue (GetCurrentEventQueue (), event,
11753 kEventPriorityStandard);
11754 if (event)
11755 ReleaseEvent (event);
11757 return err;
11759 #endif
11761 /* Emacs calls this whenever it wants to read an input event from the
11762 user. */
11764 XTread_socket (sd, expected, hold_quit)
11765 int sd, expected;
11766 struct input_event *hold_quit;
11768 struct input_event inev;
11769 int count = 0;
11770 #if TARGET_API_MAC_CARBON
11771 EventRef eventRef;
11772 EventTargetRef toolbox_dispatcher;
11773 #endif
11774 EventRecord er;
11775 struct mac_display_info *dpyinfo = &one_mac_display_info;
11777 if (interrupt_input_blocked)
11779 interrupt_input_pending = 1;
11780 return -1;
11783 interrupt_input_pending = 0;
11784 BLOCK_INPUT;
11786 /* So people can tell when we have read the available input. */
11787 input_signal_count++;
11789 ++handling_signal;
11791 #if TARGET_API_MAC_CARBON
11792 toolbox_dispatcher = GetEventDispatcherTarget ();
11794 while (
11795 #if USE_CG_DRAWING
11796 mac_prepare_for_quickdraw (NULL),
11797 #endif
11798 !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
11799 kEventRemoveFromQueue, &eventRef))
11800 #else /* !TARGET_API_MAC_CARBON */
11801 while (mac_wait_next_event (&er, 0, true))
11802 #endif /* !TARGET_API_MAC_CARBON */
11804 int do_help = 0;
11805 struct frame *f;
11806 unsigned long timestamp;
11808 EVENT_INIT (inev);
11809 inev.kind = NO_EVENT;
11810 inev.arg = Qnil;
11812 #if TARGET_API_MAC_CARBON
11813 timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
11815 if (!mac_convert_event_ref (eventRef, &er))
11816 goto OTHER;
11817 #else /* !TARGET_API_MAC_CARBON */
11818 timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
11819 #endif /* !TARGET_API_MAC_CARBON */
11821 switch (er.what)
11823 case mouseDown:
11824 case mouseUp:
11826 WindowRef window_ptr;
11827 ControlPartCode part_code;
11828 int tool_bar_p = 0;
11830 #if TARGET_API_MAC_CARBON
11831 OSStatus err;
11833 /* This is needed to send mouse events like aqua window
11834 buttons to the correct handler. */
11835 read_socket_inev = &inev;
11836 err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
11837 read_socket_inev = NULL;
11838 if (err != eventNotHandledErr)
11839 break;
11840 #endif
11841 last_mouse_glyph_frame = 0;
11843 if (dpyinfo->grabbed && last_mouse_frame
11844 && FRAME_LIVE_P (last_mouse_frame))
11846 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
11847 part_code = inContent;
11849 else
11851 part_code = FindWindow (er.where, &window_ptr);
11852 if (tip_window && window_ptr == tip_window)
11854 HideWindow (tip_window);
11855 part_code = FindWindow (er.where, &window_ptr);
11859 if (er.what != mouseDown &&
11860 (part_code != inContent || dpyinfo->grabbed == 0))
11861 break;
11863 switch (part_code)
11865 case inMenuBar:
11866 f = mac_focus_frame (dpyinfo);
11867 saved_menu_event_location = er.where;
11868 inev.kind = MENU_BAR_ACTIVATE_EVENT;
11869 XSETFRAME (inev.frame_or_window, f);
11870 break;
11872 case inContent:
11873 if (
11874 #if TARGET_API_MAC_CARBON
11875 FrontNonFloatingWindow ()
11876 #else
11877 FrontWindow ()
11878 #endif
11879 != window_ptr
11880 || (mac_window_to_frame (window_ptr)
11881 != dpyinfo->x_focus_frame))
11882 SelectWindow (window_ptr);
11883 else
11885 ControlPartCode control_part_code;
11886 ControlRef ch;
11887 Point mouse_loc;
11888 #ifdef MAC_OSX
11889 ControlKind control_kind;
11890 #endif
11892 f = mac_window_to_frame (window_ptr);
11893 /* convert to local coordinates of new window */
11894 mouse_loc.h = (er.where.h
11895 - (f->left_pos
11896 + FRAME_OUTER_TO_INNER_DIFF_X (f)));
11897 mouse_loc.v = (er.where.v
11898 - (f->top_pos
11899 + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
11900 #if TARGET_API_MAC_CARBON
11901 ch = FindControlUnderMouse (mouse_loc, window_ptr,
11902 &control_part_code);
11903 #ifdef MAC_OSX
11904 if (ch)
11905 GetControlKind (ch, &control_kind);
11906 #endif
11907 #else
11908 control_part_code = FindControl (mouse_loc, window_ptr,
11909 &ch);
11910 #endif
11912 #if TARGET_API_MAC_CARBON
11913 inev.code = mac_get_mouse_btn (eventRef);
11914 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
11915 #else
11916 inev.code = mac_get_emulated_btn (er.modifiers);
11917 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
11918 #endif
11919 XSETINT (inev.x, mouse_loc.h);
11920 XSETINT (inev.y, mouse_loc.v);
11922 if ((dpyinfo->grabbed && tracked_scroll_bar)
11923 || (ch != 0
11924 #ifndef USE_TOOLKIT_SCROLL_BARS
11925 /* control_part_code becomes kControlNoPart if
11926 a progress indicator is clicked. */
11927 && control_part_code != kControlNoPart
11928 #else /* USE_TOOLKIT_SCROLL_BARS */
11929 #ifdef MAC_OSX
11930 && control_kind.kind == kControlKindScrollBar
11931 #endif /* MAC_OSX */
11932 #endif /* USE_TOOLKIT_SCROLL_BARS */
11935 struct scroll_bar *bar;
11937 if (dpyinfo->grabbed && tracked_scroll_bar)
11939 bar = tracked_scroll_bar;
11940 #ifndef USE_TOOLKIT_SCROLL_BARS
11941 control_part_code = kControlIndicatorPart;
11942 #endif
11944 else
11945 bar = (struct scroll_bar *) GetControlReference (ch);
11946 #ifdef USE_TOOLKIT_SCROLL_BARS
11947 /* Make the "Ctrl-Mouse-2 splits window" work
11948 for toolkit scroll bars. */
11949 if (inev.modifiers & ctrl_modifier)
11950 x_scroll_bar_handle_click (bar, control_part_code,
11951 &er, &inev);
11952 else if (er.what == mouseDown)
11953 x_scroll_bar_handle_press (bar, control_part_code,
11954 mouse_loc, &inev);
11955 else
11956 x_scroll_bar_handle_release (bar, &inev);
11957 #else /* not USE_TOOLKIT_SCROLL_BARS */
11958 x_scroll_bar_handle_click (bar, control_part_code,
11959 &er, &inev);
11960 if (er.what == mouseDown
11961 && control_part_code == kControlIndicatorPart)
11962 tracked_scroll_bar = bar;
11963 else
11964 tracked_scroll_bar = NULL;
11965 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11967 else
11969 Lisp_Object window;
11970 int x = mouse_loc.h;
11971 int y = mouse_loc.v;
11973 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
11974 if (EQ (window, f->tool_bar_window))
11976 if (er.what == mouseDown)
11977 handle_tool_bar_click (f, x, y, 1, 0);
11978 else
11979 handle_tool_bar_click (f, x, y, 0,
11980 inev.modifiers);
11981 tool_bar_p = 1;
11983 else
11985 XSETFRAME (inev.frame_or_window, f);
11986 inev.kind = MOUSE_CLICK_EVENT;
11990 if (er.what == mouseDown)
11992 dpyinfo->grabbed |= (1 << inev.code);
11993 last_mouse_frame = f;
11995 if (!tool_bar_p)
11996 last_tool_bar_item = -1;
11998 else
12000 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
12001 /* If a button is released though it was not
12002 previously pressed, that would be because
12003 of multi-button emulation. */
12004 dpyinfo->grabbed = 0;
12005 else
12006 dpyinfo->grabbed &= ~(1 << inev.code);
12009 /* Ignore any mouse motion that happened before
12010 this event; any subsequent mouse-movement Emacs
12011 events should reflect only motion after the
12012 ButtonPress. */
12013 if (f != 0)
12014 f->mouse_moved = 0;
12016 #ifdef USE_TOOLKIT_SCROLL_BARS
12017 if (inev.kind == MOUSE_CLICK_EVENT
12018 || (inev.kind == SCROLL_BAR_CLICK_EVENT
12019 && (inev.modifiers & ctrl_modifier)))
12020 #endif
12021 switch (er.what)
12023 case mouseDown:
12024 inev.modifiers |= down_modifier;
12025 break;
12026 case mouseUp:
12027 inev.modifiers |= up_modifier;
12028 break;
12031 break;
12033 case inDrag:
12034 #if TARGET_API_MAC_CARBON
12035 case inProxyIcon:
12036 if (IsWindowPathSelectClick (window_ptr, &er))
12038 WindowPathSelect (window_ptr, NULL, NULL);
12039 break;
12041 if (part_code == inProxyIcon
12042 && (TrackWindowProxyDrag (window_ptr, er.where)
12043 != errUserWantsToDragWindow))
12044 break;
12045 DragWindow (window_ptr, er.where, NULL);
12046 #else /* not TARGET_API_MAC_CARBON */
12047 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12048 /* Update the frame parameters. */
12050 struct frame *f = mac_window_to_frame (window_ptr);
12052 if (f && !f->async_iconified)
12053 mac_handle_origin_change (f);
12055 #endif /* not TARGET_API_MAC_CARBON */
12056 break;
12058 case inGoAway:
12059 if (TrackGoAway (window_ptr, er.where))
12061 inev.kind = DELETE_WINDOW_EVENT;
12062 XSETFRAME (inev.frame_or_window,
12063 mac_window_to_frame (window_ptr));
12065 break;
12067 /* window resize handling added --ben */
12068 case inGrow:
12069 do_grow_window (window_ptr, &er);
12070 break;
12072 /* window zoom handling added --ben */
12073 case inZoomIn:
12074 case inZoomOut:
12075 if (TrackBox (window_ptr, er.where, part_code))
12076 do_zoom_window (window_ptr, part_code);
12077 break;
12079 #if USE_MAC_TOOLBAR
12080 case inStructure:
12082 OSStatus err;
12083 HIViewRef ch;
12085 err = HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr),
12086 eventRef, &ch);
12087 /* This doesn't work on Mac OS X 10.2. */
12088 if (err == noErr)
12089 HIViewClick (ch, eventRef);
12091 break;
12092 #endif /* USE_MAC_TOOLBAR */
12094 default:
12095 break;
12098 break;
12100 #if !TARGET_API_MAC_CARBON
12101 case updateEvt:
12102 do_window_update ((WindowRef) er.message);
12103 break;
12104 #endif
12106 case osEvt:
12107 switch ((er.message >> 24) & 0x000000FF)
12109 case mouseMovedMessage:
12110 #if !TARGET_API_MAC_CARBON
12111 SetRectRgn (mouse_region, er.where.h, er.where.v,
12112 er.where.h + 1, er.where.v + 1);
12113 #endif
12114 previous_help_echo_string = help_echo_string;
12115 help_echo_string = Qnil;
12117 if (dpyinfo->grabbed && last_mouse_frame
12118 && FRAME_LIVE_P (last_mouse_frame))
12119 f = last_mouse_frame;
12120 else
12121 f = dpyinfo->x_focus_frame;
12123 if (dpyinfo->mouse_face_hidden)
12125 dpyinfo->mouse_face_hidden = 0;
12126 clear_mouse_face (dpyinfo);
12129 if (f)
12131 WindowRef wp = FRAME_MAC_WINDOW (f);
12132 Point mouse_pos;
12134 mouse_pos.h = (er.where.h
12135 - (f->left_pos
12136 + FRAME_OUTER_TO_INNER_DIFF_X (f)));
12137 mouse_pos.v = (er.where.v
12138 - (f->top_pos
12139 + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
12140 if (dpyinfo->grabbed && tracked_scroll_bar)
12141 #ifdef USE_TOOLKIT_SCROLL_BARS
12142 x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
12143 mouse_pos, &inev);
12144 #else /* not USE_TOOLKIT_SCROLL_BARS */
12145 x_scroll_bar_note_movement (tracked_scroll_bar,
12146 mouse_pos.v
12147 - XINT (tracked_scroll_bar->top),
12148 er.when * (1000 / 60));
12149 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12150 else
12152 /* Generate SELECT_WINDOW_EVENTs when needed. */
12153 if (!NILP (Vmouse_autoselect_window))
12155 Lisp_Object window;
12157 window = window_from_coordinates (f,
12158 mouse_pos.h,
12159 mouse_pos.v,
12160 0, 0, 0, 0);
12162 /* Window will be selected only when it is
12163 not selected now and last mouse movement
12164 event was not in it. Minibuffer window
12165 will be selected iff it is active. */
12166 if (WINDOWP (window)
12167 && !EQ (window, last_window)
12168 && !EQ (window, selected_window))
12170 inev.kind = SELECT_WINDOW_EVENT;
12171 inev.frame_or_window = window;
12174 last_window=window;
12176 if (!note_mouse_movement (f, &mouse_pos))
12177 help_echo_string = previous_help_echo_string;
12178 #if USE_MAC_TOOLBAR
12179 else
12180 mac_tool_bar_note_mouse_movement (f, eventRef);
12181 #endif
12185 /* If the contents of the global variable
12186 help_echo_string has changed, generate a
12187 HELP_EVENT. */
12188 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
12189 do_help = 1;
12190 break;
12192 default:
12193 goto OTHER;
12195 break;
12197 case activateEvt:
12199 WindowRef window_ptr = (WindowRef) er.message;
12201 if (window_ptr == tip_window)
12203 HideWindow (tip_window);
12204 break;
12207 if (!is_emacs_window (window_ptr))
12208 goto OTHER;
12210 f = mac_window_to_frame (window_ptr);
12212 if ((er.modifiers & activeFlag) != 0)
12214 /* A window has been activated */
12215 Point mouse_loc;
12217 x_detect_focus_change (dpyinfo, &er, &inev);
12219 mouse_loc.h = (er.where.h
12220 - (f->left_pos
12221 + FRAME_OUTER_TO_INNER_DIFF_X (f)));
12222 mouse_loc.v = (er.where.v
12223 - (f->top_pos
12224 + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
12225 /* Window-activated event counts as mouse movement,
12226 so update things that depend on mouse position. */
12227 note_mouse_movement (f, &mouse_loc);
12229 else
12231 /* A window has been deactivated */
12232 #ifdef USE_TOOLKIT_SCROLL_BARS
12233 if (dpyinfo->grabbed && tracked_scroll_bar)
12235 struct input_event event;
12237 EVENT_INIT (event);
12238 event.kind = NO_EVENT;
12239 x_scroll_bar_handle_release (tracked_scroll_bar, &event);
12240 if (event.kind != NO_EVENT)
12242 event.timestamp = timestamp;
12243 kbd_buffer_store_event_hold (&event, hold_quit);
12244 count++;
12247 #endif
12248 dpyinfo->grabbed = 0;
12250 x_detect_focus_change (dpyinfo, &er, &inev);
12252 if (f == dpyinfo->mouse_face_mouse_frame)
12254 /* If we move outside the frame, then we're
12255 certainly no longer on any text in the
12256 frame. */
12257 clear_mouse_face (dpyinfo);
12258 dpyinfo->mouse_face_mouse_frame = 0;
12261 /* Generate a nil HELP_EVENT to cancel a help-echo.
12262 Do it only if there's something to cancel.
12263 Otherwise, the startup message is cleared when the
12264 mouse leaves the frame. */
12265 if (any_help_event_p)
12266 do_help = -1;
12269 break;
12271 case keyDown:
12272 case keyUp:
12273 case autoKey:
12274 ObscureCursor ();
12276 f = mac_focus_frame (dpyinfo);
12277 XSETFRAME (inev.frame_or_window, f);
12279 /* If mouse-highlight is an integer, input clears out mouse
12280 highlighting. */
12281 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
12282 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
12284 clear_mouse_face (dpyinfo);
12285 dpyinfo->mouse_face_hidden = 1;
12287 #if TARGET_API_MAC_CARBON
12288 goto OTHER;
12289 #else
12290 do_keystroke (er.what, er.message & charCodeMask,
12291 (er.message & keyCodeMask) >> 8,
12292 er.modifiers, timestamp, &inev);
12293 #endif
12294 break;
12296 case kHighLevelEvent:
12297 AEProcessAppleEvent (&er);
12298 break;
12300 default:
12301 OTHER:
12302 #if TARGET_API_MAC_CARBON
12304 OSStatus err;
12306 read_socket_inev = &inev;
12307 err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
12308 read_socket_inev = NULL;
12310 #endif
12311 break;
12313 #if TARGET_API_MAC_CARBON
12314 ReleaseEvent (eventRef);
12315 #endif
12317 if (inev.kind != NO_EVENT)
12319 inev.timestamp = timestamp;
12320 kbd_buffer_store_event_hold (&inev, hold_quit);
12321 count++;
12324 if (do_help
12325 && !(hold_quit && hold_quit->kind != NO_EVENT))
12327 Lisp_Object frame;
12329 if (f)
12330 XSETFRAME (frame, f);
12331 else
12332 frame = Qnil;
12334 if (do_help > 0)
12336 any_help_event_p = 1;
12337 gen_help_event (help_echo_string, frame, help_echo_window,
12338 help_echo_object, help_echo_pos);
12340 else
12342 help_echo_string = Qnil;
12343 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
12345 count++;
12350 /* If the focus was just given to an autoraising frame,
12351 raise it now. */
12352 /* ??? This ought to be able to handle more than one such frame. */
12353 if (pending_autoraise_frame)
12355 x_raise_frame (pending_autoraise_frame);
12356 pending_autoraise_frame = 0;
12359 if (mac_screen_config_changed)
12361 mac_get_screen_info (dpyinfo);
12362 mac_screen_config_changed = 0;
12365 #if !TARGET_API_MAC_CARBON
12366 /* Check which frames are still visible. We do this here because
12367 there doesn't seem to be any direct notification from the Window
12368 Manager that the visibility of a window has changed (at least,
12369 not in all cases). */
12371 Lisp_Object tail, frame;
12373 FOR_EACH_FRAME (tail, frame)
12375 struct frame *f = XFRAME (frame);
12377 /* The tooltip has been drawn already. Avoid the
12378 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12379 if (EQ (frame, tip_frame))
12380 continue;
12382 if (FRAME_MAC_P (f))
12383 mac_handle_visibility_change (f);
12386 #endif
12388 --handling_signal;
12389 UNBLOCK_INPUT;
12390 return count;
12394 /* Need to override CodeWarrior's input function so no conversion is
12395 done on newlines Otherwise compiled functions in .elc files will be
12396 read incorrectly. Defined in ...:MSL C:MSL
12397 Common:Source:buffer_io.c. */
12398 #ifdef __MWERKS__
12399 void
12400 __convert_to_newlines (unsigned char * p, size_t * n)
12402 #pragma unused(p,n)
12405 void
12406 __convert_from_newlines (unsigned char * p, size_t * n)
12408 #pragma unused(p,n)
12410 #endif
12412 #ifdef MAC_OS8
12413 void
12414 make_mac_terminal_frame (struct frame *f)
12416 Lisp_Object frame;
12417 Rect r;
12419 XSETFRAME (frame, f);
12421 f->output_method = output_mac;
12422 f->output_data.mac = (struct mac_output *)
12423 xmalloc (sizeof (struct mac_output));
12424 bzero (f->output_data.mac, sizeof (struct mac_output));
12426 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
12428 FRAME_COLS (f) = 96;
12429 FRAME_LINES (f) = 4;
12431 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
12432 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
12434 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
12436 f->output_data.mac->cursor_pixel = 0;
12437 f->output_data.mac->border_pixel = 0x00ff00;
12438 f->output_data.mac->mouse_pixel = 0xff00ff;
12439 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
12441 f->output_data.mac->text_cursor = kThemeIBeamCursor;
12442 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
12443 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
12444 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
12445 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
12446 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
12448 FRAME_FONTSET (f) = -1;
12449 f->output_data.mac->explicit_parent = 0;
12450 f->left_pos = 8;
12451 f->top_pos = 32;
12452 f->border_width = 0;
12454 f->internal_border_width = 0;
12456 f->auto_raise = 1;
12457 f->auto_lower = 1;
12459 f->new_text_cols = 0;
12460 f->new_text_lines = 0;
12462 SetRect (&r, f->left_pos, f->top_pos,
12463 f->left_pos + FRAME_PIXEL_WIDTH (f),
12464 f->top_pos + FRAME_PIXEL_HEIGHT (f));
12466 BLOCK_INPUT;
12468 if (!(FRAME_MAC_WINDOW (f) =
12469 NewCWindow (NULL, &r, "\p", true, dBoxProc,
12470 (WindowRef) -1, 1, (long) f->output_data.mac)))
12471 abort ();
12472 /* so that update events can find this mac_output struct */
12473 f->output_data.mac->mFP = f; /* point back to emacs frame */
12475 UNBLOCK_INPUT;
12477 x_make_gc (f);
12479 /* Need to be initialized for unshow_buffer in window.c. */
12480 selected_window = f->selected_window;
12482 Fmodify_frame_parameters (frame,
12483 Fcons (Fcons (Qfont,
12484 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
12485 Fmodify_frame_parameters (frame,
12486 Fcons (Fcons (Qforeground_color,
12487 build_string ("black")), Qnil));
12488 Fmodify_frame_parameters (frame,
12489 Fcons (Fcons (Qbackground_color,
12490 build_string ("white")), Qnil));
12492 #endif
12495 /***********************************************************************
12496 Initialization
12497 ***********************************************************************/
12499 static int mac_initialized = 0;
12501 static XrmDatabase
12502 mac_make_rdb (xrm_option)
12503 const char *xrm_option;
12505 XrmDatabase database;
12507 database = xrm_get_preference_database (NULL);
12508 if (xrm_option)
12509 xrm_merge_string_database (database, xrm_option);
12511 return database;
12514 struct mac_display_info *
12515 mac_term_init (display_name, xrm_option, resource_name)
12516 Lisp_Object display_name;
12517 char *xrm_option;
12518 char *resource_name;
12520 struct mac_display_info *dpyinfo;
12522 BLOCK_INPUT;
12524 if (!mac_initialized)
12526 mac_initialize ();
12527 mac_initialized = 1;
12530 if (x_display_list)
12531 error ("Sorry, this version can only handle one display");
12533 dpyinfo = &one_mac_display_info;
12534 bzero (dpyinfo, sizeof (*dpyinfo));
12536 #ifdef MAC_OSX
12537 dpyinfo->mac_id_name
12538 = (char *) xmalloc (SCHARS (Vinvocation_name)
12539 + SCHARS (Vsystem_name)
12540 + 2);
12541 sprintf (dpyinfo->mac_id_name, "%s@%s",
12542 SDATA (Vinvocation_name), SDATA (Vsystem_name));
12543 #else
12544 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
12545 strcpy (dpyinfo->mac_id_name, "Mac Display");
12546 #endif
12548 dpyinfo->reference_count = 0;
12549 dpyinfo->resx = 72.0;
12550 dpyinfo->resy = 72.0;
12552 mac_get_screen_info (dpyinfo);
12554 dpyinfo->grabbed = 0;
12555 dpyinfo->root_window = NULL;
12556 dpyinfo->image_cache = make_image_cache ();
12558 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
12559 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
12560 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
12561 dpyinfo->mouse_face_window = Qnil;
12562 dpyinfo->mouse_face_overlay = Qnil;
12563 dpyinfo->mouse_face_hidden = 0;
12565 dpyinfo->xrdb = mac_make_rdb (xrm_option);
12567 /* Put this display on the chain. */
12568 dpyinfo->next = x_display_list;
12569 x_display_list = dpyinfo;
12571 /* Put it on x_display_name_list. */
12572 x_display_name_list = Fcons (Fcons (display_name,
12573 Fcons (Qnil, dpyinfo->xrdb)),
12574 x_display_name_list);
12575 dpyinfo->name_list_element = XCAR (x_display_name_list);
12577 UNBLOCK_INPUT;
12579 return dpyinfo;
12582 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12584 void
12585 x_delete_display (dpyinfo)
12586 struct mac_display_info *dpyinfo;
12588 int i;
12590 /* Discard this display from x_display_name_list and x_display_list.
12591 We can't use Fdelq because that can quit. */
12592 if (! NILP (x_display_name_list)
12593 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
12594 x_display_name_list = XCDR (x_display_name_list);
12595 else
12597 Lisp_Object tail;
12599 tail = x_display_name_list;
12600 while (CONSP (tail) && CONSP (XCDR (tail)))
12602 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
12604 XSETCDR (tail, XCDR (XCDR (tail)));
12605 break;
12607 tail = XCDR (tail);
12611 if (x_display_list == dpyinfo)
12612 x_display_list = dpyinfo->next;
12613 else
12615 struct x_display_info *tail;
12617 for (tail = x_display_list; tail; tail = tail->next)
12618 if (tail->next == dpyinfo)
12619 tail->next = tail->next->next;
12622 /* Free the font names in the font table. */
12623 for (i = 0; i < dpyinfo->n_fonts; i++)
12624 if (dpyinfo->font_table[i].name)
12626 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
12627 xfree (dpyinfo->font_table[i].full_name);
12628 xfree (dpyinfo->font_table[i].name);
12631 if (dpyinfo->font_table)
12633 if (dpyinfo->font_table->font_encoder)
12634 xfree (dpyinfo->font_table->font_encoder);
12635 xfree (dpyinfo->font_table);
12637 if (dpyinfo->mac_id_name)
12638 xfree (dpyinfo->mac_id_name);
12640 if (x_display_list == 0)
12642 mac_clear_font_name_table ();
12643 bzero (dpyinfo, sizeof (*dpyinfo));
12648 static void
12649 init_menu_bar ()
12651 #ifdef MAC_OSX
12652 OSStatus err;
12653 MenuRef menu;
12654 MenuItemIndex menu_index;
12656 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
12657 &menu, &menu_index);
12658 if (err == noErr)
12659 SetMenuItemCommandKey (menu, menu_index, false, 0);
12660 EnableMenuCommand (NULL, kHICommandPreferences);
12661 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
12662 &menu, &menu_index);
12663 if (err == noErr)
12665 SetMenuItemCommandKey (menu, menu_index, false, 0);
12666 InsertMenuItemTextWithCFString (menu, NULL,
12667 0, kMenuItemAttrSeparator, 0);
12668 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
12669 0, 0, kHICommandAbout);
12671 #else /* !MAC_OSX */
12672 #if TARGET_API_MAC_CARBON
12673 SetMenuItemCommandID (GetMenuRef (M_APPLE), I_ABOUT, kHICommandAbout);
12674 #endif
12675 #endif
12678 #if USE_MAC_TSM
12679 static void
12680 init_tsm ()
12682 #ifdef MAC_OSX
12683 static InterfaceTypeList types = {kUnicodeDocument};
12684 #else
12685 static InterfaceTypeList types = {kTextService};
12686 #endif
12688 NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
12689 &tsm_document_id, 0);
12691 #endif
12693 /* Set up use of X before we make the first connection. */
12695 extern frame_parm_handler mac_frame_parm_handlers[];
12697 static struct redisplay_interface x_redisplay_interface =
12699 mac_frame_parm_handlers,
12700 x_produce_glyphs,
12701 x_write_glyphs,
12702 x_insert_glyphs,
12703 x_clear_end_of_line,
12704 x_scroll_run,
12705 x_after_update_window_line,
12706 x_update_window_begin,
12707 x_update_window_end,
12708 x_cursor_to,
12709 x_flush,
12710 #if USE_CG_DRAWING
12711 mac_flush_display_optional,
12712 #else
12713 0, /* flush_display_optional */
12714 #endif
12715 x_clear_window_mouse_face,
12716 x_get_glyph_overhangs,
12717 x_fix_overlapping_area,
12718 x_draw_fringe_bitmap,
12719 #if USE_CG_DRAWING
12720 mac_define_fringe_bitmap,
12721 mac_destroy_fringe_bitmap,
12722 #else
12723 0, /* define_fringe_bitmap */
12724 0, /* destroy_fringe_bitmap */
12725 #endif
12726 mac_per_char_metric,
12727 mac_encode_char,
12728 mac_compute_glyph_string_overhangs,
12729 x_draw_glyph_string,
12730 mac_define_frame_cursor,
12731 mac_clear_frame_area,
12732 mac_draw_window_cursor,
12733 mac_draw_vertical_window_border,
12734 mac_shift_glyphs_for_insert
12737 void
12738 mac_initialize ()
12740 rif = &x_redisplay_interface;
12742 clear_frame_hook = x_clear_frame;
12743 ins_del_lines_hook = x_ins_del_lines;
12744 delete_glyphs_hook = x_delete_glyphs;
12745 ring_bell_hook = XTring_bell;
12746 reset_terminal_modes_hook = XTreset_terminal_modes;
12747 set_terminal_modes_hook = XTset_terminal_modes;
12748 update_begin_hook = x_update_begin;
12749 update_end_hook = x_update_end;
12750 set_terminal_window_hook = XTset_terminal_window;
12751 read_socket_hook = XTread_socket;
12752 frame_up_to_date_hook = XTframe_up_to_date;
12753 mouse_position_hook = XTmouse_position;
12754 frame_rehighlight_hook = XTframe_rehighlight;
12755 frame_raise_lower_hook = XTframe_raise_lower;
12757 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
12758 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
12759 redeem_scroll_bar_hook = XTredeem_scroll_bar;
12760 judge_scroll_bars_hook = XTjudge_scroll_bars;
12762 scroll_region_ok = 1; /* we'll scroll partial frames */
12763 char_ins_del_ok = 1;
12764 line_ins_del_ok = 1; /* we'll just blt 'em */
12765 fast_clear_end_of_line = 1; /* X does this well */
12766 memory_below_frame = 0; /* we don't remember what scrolls
12767 off the bottom */
12768 baud_rate = 19200;
12770 last_tool_bar_item = -1;
12771 any_help_event_p = 0;
12773 /* Try to use interrupt input; if we can't, then start polling. */
12774 Fset_input_mode (Qt, Qnil, Qt, Qnil);
12776 BLOCK_INPUT;
12778 #if TARGET_API_MAC_CARBON
12780 install_application_handler ();
12782 init_menu_bar ();
12784 #if USE_MAC_TSM
12785 init_tsm ();
12786 #endif
12788 #ifdef MAC_OSX
12789 init_coercion_handler ();
12791 init_apple_event_handler ();
12793 init_dm_notification_handler ();
12795 if (!inhibit_window_system)
12797 static const ProcessSerialNumber psn = {0, kCurrentProcess};
12799 SetFrontProcess (&psn);
12801 #endif
12802 #endif
12804 #if USE_CG_DRAWING
12805 init_cg_color ();
12807 mac_init_fringe ();
12808 #endif
12810 UNBLOCK_INPUT;
12814 void
12815 syms_of_macterm ()
12817 #if 0
12818 staticpro (&x_error_message_string);
12819 x_error_message_string = Qnil;
12820 #endif
12822 Qcontrol = intern ("control"); staticpro (&Qcontrol);
12823 Qmeta = intern ("meta"); staticpro (&Qmeta);
12824 Qalt = intern ("alt"); staticpro (&Qalt);
12825 Qhyper = intern ("hyper"); staticpro (&Qhyper);
12826 Qsuper = intern ("super"); staticpro (&Qsuper);
12827 Qmodifier_value = intern ("modifier-value");
12828 staticpro (&Qmodifier_value);
12830 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
12831 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
12832 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
12833 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
12834 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
12836 #if TARGET_API_MAC_CARBON
12837 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
12838 #ifdef MAC_OSX
12839 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
12840 staticpro (&Qtoolbar_switch_mode);
12841 #if USE_MAC_FONT_PANEL
12842 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
12843 Qselection = intern ("selection"); staticpro (&Qselection);
12844 #endif
12846 Qservice = intern ("service"); staticpro (&Qservice);
12847 Qpaste = intern ("paste"); staticpro (&Qpaste);
12848 Qperform = intern ("perform"); staticpro (&Qperform);
12849 #endif
12850 #if USE_MAC_TSM
12851 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
12852 Qupdate_active_input_area = intern ("update-active-input-area");
12853 staticpro (&Qupdate_active_input_area);
12854 Qunicode_for_key_event = intern ("unicode-for-key-event");
12855 staticpro (&Qunicode_for_key_event);
12856 #endif
12857 #endif
12859 #ifdef MAC_OSX
12860 Fprovide (intern ("mac-carbon"), Qnil);
12861 #endif
12863 staticpro (&Qreverse);
12864 Qreverse = intern ("reverse");
12866 staticpro (&x_display_name_list);
12867 x_display_name_list = Qnil;
12869 staticpro (&last_mouse_scroll_bar);
12870 last_mouse_scroll_bar = Qnil;
12872 staticpro (&fm_font_family_alist);
12873 fm_font_family_alist = Qnil;
12875 #if USE_ATSUI
12876 staticpro (&atsu_font_id_hash);
12877 atsu_font_id_hash = Qnil;
12879 staticpro (&fm_style_face_attributes_alist);
12880 fm_style_face_attributes_alist = Qnil;
12881 #endif
12883 #if USE_MAC_TSM
12884 staticpro (&saved_ts_script_language_on_focus);
12885 saved_ts_script_language_on_focus = Qnil;
12886 #endif
12888 /* We don't yet support this, but defining this here avoids whining
12889 from cus-start.el and other places, like "M-x set-variable". */
12890 DEFVAR_BOOL ("x-use-underline-position-properties",
12891 &x_use_underline_position_properties,
12892 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12893 A value of nil means ignore them. If you encounter fonts with bogus
12894 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12895 to 4.1, set this to nil.
12897 NOTE: Not supported on Mac yet. */);
12898 x_use_underline_position_properties = 0;
12900 DEFVAR_BOOL ("x-underline-at-descent-line",
12901 &x_underline_at_descent_line,
12902 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
12903 A value of nil means to draw the underline according to the value of the
12904 variable `x-use-underline-position-properties', which is usually at the
12905 baseline level. The default value is nil. */);
12906 x_underline_at_descent_line = 0;
12908 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
12909 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
12910 #ifdef USE_TOOLKIT_SCROLL_BARS
12911 Vx_toolkit_scroll_bars = Qt;
12912 #else
12913 Vx_toolkit_scroll_bars = Qnil;
12914 #endif
12916 staticpro (&last_mouse_motion_frame);
12917 last_mouse_motion_frame = Qnil;
12919 /* Variables to configure modifier key assignment. */
12921 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
12922 doc: /* *Modifier key assumed when the Mac control key is pressed.
12923 The value can be `control', `meta', `alt', `hyper', or `super' for the
12924 respective modifier. The default is `control'. */);
12925 Vmac_control_modifier = Qcontrol;
12927 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
12928 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
12929 The value can be `control', `meta', `alt', `hyper', or `super' for the
12930 respective modifier. If the value is nil then the key will act as the
12931 normal Mac control modifier, and the option key can be used to compose
12932 characters depending on the chosen Mac keyboard setting. */);
12933 Vmac_option_modifier = Qnil;
12935 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
12936 doc: /* *Modifier key assumed when the Mac command key is pressed.
12937 The value can be `control', `meta', `alt', `hyper', or `super' for the
12938 respective modifier. The default is `meta'. */);
12939 Vmac_command_modifier = Qmeta;
12941 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
12942 doc: /* *Modifier key assumed when the Mac function key is pressed.
12943 The value can be `control', `meta', `alt', `hyper', or `super' for the
12944 respective modifier. Note that remapping the function key may lead to
12945 unexpected results for some keys on non-US/GB keyboards. */);
12946 Vmac_function_modifier = Qnil;
12948 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12949 &Vmac_emulate_three_button_mouse,
12950 doc: /* *Specify a way of three button mouse emulation.
12951 The value can be nil, t, or the symbol `reverse'.
12952 A value of nil means that no emulation should be done and the modifiers
12953 should be placed on the mouse-1 event.
12954 t means that when the option-key is held down while pressing the mouse
12955 button, the click will register as mouse-2 and while the command-key
12956 is held down, the click will register as mouse-3.
12957 The symbol `reverse' means that the option-key will register for
12958 mouse-3 and the command-key will register for mouse-2. */);
12959 Vmac_emulate_three_button_mouse = Qnil;
12961 #if TARGET_API_MAC_CARBON
12962 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
12963 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12964 Otherwise, the right click will be treated as mouse-2 and the wheel
12965 button will be mouse-3. */);
12966 mac_wheel_button_is_mouse_2 = 1;
12968 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
12969 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12970 mac_pass_command_to_system = 1;
12972 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
12973 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12974 mac_pass_control_to_system = 1;
12976 #endif
12978 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
12979 doc: /* *If non-nil, allow anti-aliasing.
12980 The text will be rendered using Core Graphics text rendering which
12981 may anti-alias the text. */);
12982 #if USE_CG_DRAWING
12983 mac_use_core_graphics = 1;
12984 #else
12985 mac_use_core_graphics = 0;
12986 #endif
12988 /* Register an entry for `mac-roman' so that it can be used when
12989 creating the terminal frame on Mac OS 9 before loading
12990 term/mac-win.elc. */
12991 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
12992 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
12993 Each entry should be of the form:
12995 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12997 where CHARSET-NAME is a string used in font names to identify the
12998 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12999 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13000 Vmac_charset_info_alist =
13001 Fcons (list3 (build_string ("mac-roman"),
13002 make_number (smRoman), Qnil), Qnil);
13004 #if USE_MAC_TSM
13005 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
13006 doc: /* Overlay used to display Mac TSM active input area. */);
13007 Vmac_ts_active_input_overlay = Qnil;
13009 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
13010 doc: /* *How to change Mac TSM script/language when a frame gets focus.
13011 If the value is t, the input script and language are restored to those
13012 used in the last focus frame. If the value is a pair of integers, the
13013 input script and language codes, which are defined in the Script
13014 Manager, are set to its car and cdr parts, respectively. Otherwise,
13015 Emacs doesn't set them and thus follows the system default behavior. */);
13016 Vmac_ts_script_language_on_focus = Qnil;
13017 #endif
13020 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13021 (do not change this comment) */