(easy-menu-avoid-duplicate-keys): New var.
[emacs.git] / src / macterm.c
blob3fbdcc2f822ea250d923d8e076f6f750cbd51672
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008 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 3, 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 static 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_ ((struct terminal *));
235 static void XTreset_terminal_modes P_ ((struct terminal *));
236 static void x_clear_frame P_ ((struct frame *));
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 *));
264 static struct terminal *mac_create_terminal P_ ((struct mac_display_info *dpyinfo));
267 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
268 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
269 #define GC_FONT(gc) ((gc)->xgcv.font)
270 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
272 #define CG_SET_FILL_COLOR(context, color) \
273 CGContextSetRGBFillColor (context, \
274 RED_FROM_ULONG (color) / 255.0f, \
275 GREEN_FROM_ULONG (color) / 255.0f, \
276 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
277 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
278 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
279 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
280 do { \
281 if (CGColorGetTypeID != NULL) \
282 CGContextSetFillColorWithColor (context, cg_color); \
283 else \
284 CG_SET_FILL_COLOR (context, color); \
285 } while (0)
286 #else
287 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
288 CGContextSetFillColorWithColor (context, cg_color)
289 #endif
290 #else
291 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
292 CG_SET_FILL_COLOR (context, color)
293 #endif
294 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
295 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
296 (gc)->cg_fore_color)
297 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
298 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
299 (gc)->cg_back_color)
302 #define CG_SET_STROKE_COLOR(context, color) \
303 CGContextSetRGBStrokeColor (context, \
304 RED_FROM_ULONG (color) / 255.0f, \
305 GREEN_FROM_ULONG (color) / 255.0f, \
306 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
307 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
308 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
309 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
310 do { \
311 if (CGColorGetTypeID != NULL) \
312 CGContextSetStrokeColorWithColor (context, cg_color); \
313 else \
314 CG_SET_STROKE_COLOR (context, color); \
315 } while (0)
316 #else
317 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
318 CGContextSetStrokeColorWithColor (context, cg_color)
319 #endif
320 #else
321 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
322 CG_SET_STROKE_COLOR (context, color)
323 #endif
324 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
325 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
326 (gc)->cg_fore_color)
328 #if USE_CG_DRAWING
329 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
331 /* Fringe bitmaps. */
333 static int max_fringe_bmp = 0;
334 static CGImageRef *fringe_bmp = 0;
336 static CGColorSpaceRef mac_cg_color_space_rgb;
337 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
338 static CGColorRef mac_cg_color_black;
339 #endif
341 static void
342 init_cg_color ()
344 mac_cg_color_space_rgb = CGColorSpaceCreateDeviceRGB ();
345 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
346 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
347 /* Don't check the availability of CGColorCreate; this symbol is
348 defined even in Mac OS X 10.1. */
349 if (CGColorGetTypeID != NULL)
350 #endif
352 float rgba[] = {0.0f, 0.0f, 0.0f, 1.0f};
354 mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba);
356 #endif
359 static CGContextRef
360 mac_begin_cg_clip (f, gc)
361 struct frame *f;
362 GC gc;
364 CGContextRef context = FRAME_CG_CONTEXT (f);
366 if (!context)
368 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
369 FRAME_CG_CONTEXT (f) = context;
372 CGContextSaveGState (context);
373 CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
374 CGContextScaleCTM (context, 1, -1);
375 if (gc && gc->n_clip_rects)
376 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
378 return context;
381 static void
382 mac_end_cg_clip (f)
383 struct frame *f;
385 CGContextRestoreGState (FRAME_CG_CONTEXT (f));
388 void
389 mac_prepare_for_quickdraw (f)
390 struct frame *f;
392 if (f == NULL)
394 Lisp_Object rest, frame;
395 FOR_EACH_FRAME (rest, frame)
396 if (FRAME_MAC_P (XFRAME (frame)))
397 mac_prepare_for_quickdraw (XFRAME (frame));
399 else
401 CGContextRef context = FRAME_CG_CONTEXT (f);
403 if (context)
405 CGContextSynchronize (context);
406 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
407 &FRAME_CG_CONTEXT (f));
411 #endif
413 static RgnHandle saved_port_clip_region = NULL;
415 static void
416 mac_begin_clip (f, gc)
417 struct frame *f;
418 GC gc;
420 static RgnHandle new_region = NULL;
422 if (saved_port_clip_region == NULL)
423 saved_port_clip_region = NewRgn ();
424 if (new_region == NULL)
425 new_region = NewRgn ();
427 #if USE_CG_DRAWING
428 mac_prepare_for_quickdraw (f);
429 #endif
430 SetPortWindowPort (FRAME_MAC_WINDOW (f));
432 if (gc->n_clip_rects)
434 GetClip (saved_port_clip_region);
435 SectRgn (saved_port_clip_region, gc->clip_region, new_region);
436 SetClip (new_region);
440 static void
441 mac_end_clip (gc)
442 GC gc;
444 if (gc->n_clip_rects)
445 SetClip (saved_port_clip_region);
449 /* X display function emulation */
451 /* Mac version of XDrawLine. */
453 static void
454 mac_draw_line (f, gc, x1, y1, x2, y2)
455 struct frame *f;
456 GC gc;
457 int x1, y1, x2, y2;
459 #if USE_CG_DRAWING
460 CGContextRef context;
461 float gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
463 if (y1 != y2)
464 gx1 += 0.5f, gx2 += 0.5f;
465 if (x1 != x2)
466 gy1 += 0.5f, gy2 += 0.5f;
468 context = mac_begin_cg_clip (f, gc);
469 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
470 CGContextBeginPath (context);
471 CGContextMoveToPoint (context, gx1, gy1);
472 CGContextAddLineToPoint (context, gx2, gy2);
473 CGContextClosePath (context);
474 CGContextStrokePath (context);
475 mac_end_cg_clip (f);
476 #else
477 if (x1 == x2)
479 if (y1 > y2)
480 y1--;
481 else if (y2 > y1)
482 y2--;
484 else if (y1 == y2)
486 if (x1 > x2)
487 x1--;
488 else
489 x2--;
492 mac_begin_clip (f, gc);
493 RGBForeColor (GC_FORE_COLOR (gc));
494 MoveTo (x1, y1);
495 LineTo (x2, y2);
496 mac_end_clip (gc);
497 #endif
500 /* Mac version of XDrawLine (to Pixmap). */
502 void
503 XDrawLine (display, p, gc, x1, y1, x2, y2)
504 Display *display;
505 Pixmap p;
506 GC gc;
507 int x1, y1, x2, y2;
509 CGrafPtr old_port;
510 GDHandle old_gdh;
512 if (x1 == x2)
514 if (y1 > y2)
515 y1--;
516 else if (y2 > y1)
517 y2--;
519 else if (y1 == y2)
521 if (x1 > x2)
522 x1--;
523 else
524 x2--;
527 GetGWorld (&old_port, &old_gdh);
528 SetGWorld (p, NULL);
530 RGBForeColor (GC_FORE_COLOR (gc));
532 LockPixels (GetGWorldPixMap (p));
533 MoveTo (x1, y1);
534 LineTo (x2, y2);
535 UnlockPixels (GetGWorldPixMap (p));
537 SetGWorld (old_port, old_gdh);
541 static void
542 mac_erase_rectangle (f, gc, x, y, width, height)
543 struct frame *f;
544 GC gc;
545 int x, y;
546 unsigned int width, height;
548 #if USE_CG_DRAWING
550 CGContextRef context;
552 context = mac_begin_cg_clip (f, gc);
553 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
554 CGContextFillRect (context, CGRectMake (x, y, width, height));
555 mac_end_cg_clip (f);
557 #else
559 Rect r;
561 mac_begin_clip (f, gc);
562 RGBBackColor (GC_BACK_COLOR (gc));
563 SetRect (&r, x, y, x + width, y + height);
564 EraseRect (&r);
565 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
566 mac_end_clip (gc);
568 #endif
572 /* Mac version of XClearArea. */
574 void
575 mac_clear_area (f, x, y, width, height)
576 struct frame *f;
577 int x, y;
578 unsigned int width, height;
580 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
583 /* Mac version of XClearWindow. */
585 static void
586 mac_clear_window (f)
587 struct frame *f;
589 #if USE_CG_DRAWING
591 CGContextRef context;
592 GC gc = FRAME_NORMAL_GC (f);
594 context = mac_begin_cg_clip (f, NULL);
595 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
596 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
597 FRAME_PIXEL_HEIGHT (f)));
598 mac_end_cg_clip (f);
600 #else /* !USE_CG_DRAWING */
601 SetPortWindowPort (FRAME_MAC_WINDOW (f));
603 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
605 #if TARGET_API_MAC_CARBON
607 Rect r;
609 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
610 EraseRect (&r);
612 #else /* not TARGET_API_MAC_CARBON */
613 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
614 #endif /* not TARGET_API_MAC_CARBON */
615 #endif
619 /* Mac replacement for XCopyArea. */
621 #if USE_CG_DRAWING
622 static void
623 mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
624 dest_x, dest_y, overlay_p)
625 CGImageRef image;
626 struct frame *f;
627 GC gc;
628 int src_x, src_y;
629 unsigned int width, height;
630 int dest_x, dest_y, overlay_p;
632 CGContextRef context;
633 float port_height = FRAME_PIXEL_HEIGHT (f);
634 CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
636 context = mac_begin_cg_clip (f, gc);
637 if (!overlay_p)
639 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
640 CGContextFillRect (context, dest_rect);
642 CGContextClipToRect (context, dest_rect);
643 CGContextScaleCTM (context, 1, -1);
644 CGContextTranslateCTM (context, 0, -port_height);
645 if (CGImageIsMask (image))
646 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
647 CGContextDrawImage (context,
648 CGRectMake (dest_x - src_x,
649 port_height - (dest_y - src_y
650 + CGImageGetHeight (image)),
651 CGImageGetWidth (image),
652 CGImageGetHeight (image)),
653 image);
654 mac_end_cg_clip (f);
657 #else /* !USE_CG_DRAWING */
659 static void
660 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
661 struct frame *f;
662 GC gc;
663 int x, y, width, height;
664 unsigned short *bits;
665 int overlay_p;
667 BitMap bitmap;
668 Rect r;
670 bitmap.rowBytes = sizeof(unsigned short);
671 bitmap.baseAddr = (char *)bits;
672 SetRect (&(bitmap.bounds), 0, 0, width, height);
674 mac_begin_clip (f, gc);
675 RGBForeColor (GC_FORE_COLOR (gc));
676 RGBBackColor (GC_BACK_COLOR (gc));
677 SetRect (&r, x, y, x + width, y + height);
678 #if TARGET_API_MAC_CARBON
680 CGrafPtr port;
682 GetPort (&port);
683 LockPortBits (port);
684 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
685 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
686 UnlockPortBits (port);
688 #else /* not TARGET_API_MAC_CARBON */
689 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
690 overlay_p ? srcOr : srcCopy, 0);
691 #endif /* not TARGET_API_MAC_CARBON */
692 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
693 mac_end_clip (gc);
695 #endif /* !USE_CG_DRAWING */
698 /* Mac replacement for XCreateBitmapFromBitmapData. */
700 static void
701 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
702 BitMap *bitmap;
703 char *bits;
704 int w, h;
706 static const unsigned char swap_nibble[16]
707 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
708 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
709 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
710 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
711 int i, j, w1;
712 char *p;
714 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
715 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
716 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
717 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
718 for (i = 0; i < h; i++)
720 p = bitmap->baseAddr + i * bitmap->rowBytes;
721 for (j = 0; j < w1; j++)
723 /* Bitswap XBM bytes to match how Mac does things. */
724 unsigned char c = *bits++;
725 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
726 | (swap_nibble[(c>>4) & 0xf]));
730 SetRect (&(bitmap->bounds), 0, 0, w, h);
734 static void
735 mac_free_bitmap (bitmap)
736 BitMap *bitmap;
738 xfree (bitmap->baseAddr);
742 Pixmap
743 XCreatePixmap (display, w, width, height, depth)
744 Display *display;
745 WindowRef w;
746 unsigned int width, height;
747 unsigned int depth;
749 Pixmap pixmap;
750 Rect r;
751 QDErr err;
753 SetPortWindowPort (w);
755 SetRect (&r, 0, 0, width, height);
756 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
757 if (depth == 1)
758 #endif
759 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
760 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
761 else
762 /* CreateCGImageFromPixMaps requires ARGB format. */
763 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
764 #endif
765 if (err != noErr)
766 return NULL;
767 return pixmap;
771 Pixmap
772 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
773 Display *display;
774 WindowRef w;
775 char *data;
776 unsigned int width, height;
777 unsigned long fg, bg;
778 unsigned int depth;
780 Pixmap pixmap;
781 BitMap bitmap;
782 CGrafPtr old_port;
783 GDHandle old_gdh;
784 static GC gc = NULL;
786 if (gc == NULL)
787 gc = XCreateGC (display, w, 0, NULL);
789 pixmap = XCreatePixmap (display, w, width, height, depth);
790 if (pixmap == NULL)
791 return NULL;
793 GetGWorld (&old_port, &old_gdh);
794 SetGWorld (pixmap, NULL);
795 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
796 XSetForeground (display, gc, fg);
797 XSetBackground (display, gc, bg);
798 RGBForeColor (GC_FORE_COLOR (gc));
799 RGBBackColor (GC_BACK_COLOR (gc));
800 LockPixels (GetGWorldPixMap (pixmap));
801 #if TARGET_API_MAC_CARBON
802 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
803 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
804 #else /* not TARGET_API_MAC_CARBON */
805 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
806 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
807 #endif /* not TARGET_API_MAC_CARBON */
808 UnlockPixels (GetGWorldPixMap (pixmap));
809 SetGWorld (old_port, old_gdh);
810 mac_free_bitmap (&bitmap);
812 return pixmap;
816 void
817 XFreePixmap (display, pixmap)
818 Display *display;
819 Pixmap pixmap;
821 DisposeGWorld (pixmap);
825 /* Mac replacement for XFillRectangle. */
827 static void
828 mac_fill_rectangle (f, gc, x, y, width, height)
829 struct frame *f;
830 GC gc;
831 int x, y;
832 unsigned int width, height;
834 #if USE_CG_DRAWING
835 CGContextRef context;
837 context = mac_begin_cg_clip (f, gc);
838 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
839 CGContextFillRect (context, CGRectMake (x, y, width, height));
840 mac_end_cg_clip (f);
841 #else
842 Rect r;
844 mac_begin_clip (f, gc);
845 RGBForeColor (GC_FORE_COLOR (gc));
846 SetRect (&r, x, y, x + width, y + height);
847 PaintRect (&r); /* using foreground color of gc */
848 mac_end_clip (gc);
849 #endif
853 /* Mac replacement for XDrawRectangle: dest is a window. */
855 static void
856 mac_draw_rectangle (f, gc, x, y, width, height)
857 struct frame *f;
858 GC gc;
859 int x, y;
860 unsigned int width, height;
862 #if USE_CG_DRAWING
863 CGContextRef context;
865 context = mac_begin_cg_clip (f, gc);
866 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
867 CGContextStrokeRect (context,
868 CGRectMake (x + 0.5f, y + 0.5f, width, height));
869 mac_end_cg_clip (f);
870 #else
871 Rect r;
873 mac_begin_clip (f, gc);
874 RGBForeColor (GC_FORE_COLOR (gc));
875 SetRect (&r, x, y, x + width + 1, y + height + 1);
876 FrameRect (&r); /* using foreground color of gc */
877 mac_end_clip (gc);
878 #endif
882 static void
883 mac_invert_rectangle (f, x, y, width, height)
884 struct frame *f;
885 int x, y;
886 unsigned int width, height;
888 Rect r;
890 #if USE_CG_DRAWING
891 mac_prepare_for_quickdraw (f);
892 #endif
893 SetPortWindowPort (FRAME_MAC_WINDOW (f));
895 SetRect (&r, x, y, x + width, y + height);
897 InvertRect (&r);
901 #if USE_ATSUI
902 static OSStatus
903 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
904 ConstUniCharArrayPtr text;
905 UniCharCount text_length;
906 ATSUStyle style;
907 ATSUTextLayout *text_layout;
909 OSStatus err;
910 static ATSUTextLayout saved_text_layout = NULL;
912 if (saved_text_layout == NULL)
914 static const UniCharCount lengths[] = {kATSUToTextEnd};
915 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
916 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
917 static ATSLineLayoutOptions line_layout =
918 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
919 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
920 | kATSLineUseQDRendering
921 #else
922 kATSLineIsDisplayOnly | kATSLineFractDisable
923 #endif
925 static const ATSUAttributeValuePtr values[] = {&line_layout};
927 err = ATSUCreateTextLayoutWithTextPtr (text,
928 kATSUFromTextBeginning,
929 kATSUToTextEnd,
930 text_length,
931 1, lengths, &style,
932 &saved_text_layout);
933 if (err == noErr)
934 err = ATSUSetLayoutControls (saved_text_layout,
935 sizeof (tags) / sizeof (tags[0]),
936 tags, sizes, values);
937 if (err == noErr)
938 err = ATSUSetTransientFontMatching (saved_text_layout, true);
940 else
942 err = ATSUSetRunStyle (saved_text_layout, style,
943 kATSUFromTextBeginning, kATSUToTextEnd);
944 if (err == noErr)
945 err = ATSUSetTextPointerLocation (saved_text_layout, text,
946 kATSUFromTextBeginning,
947 kATSUToTextEnd,
948 text_length);
951 if (err == noErr)
952 *text_layout = saved_text_layout;
953 return err;
957 static void
958 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
959 overstrike_p, bytes_per_char)
960 struct frame *f;
961 GC gc;
962 int x, y;
963 char *buf;
964 int nchars, bg_width, overstrike_p, bytes_per_char;
966 OSStatus err;
967 ATSUTextLayout text_layout;
969 xassert (bytes_per_char == 2);
971 #ifndef WORDS_BIG_ENDIAN
973 int i;
974 UniChar *text = (UniChar *)buf;
976 for (i = 0; i < nchars; i++)
977 text[i] = EndianU16_BtoN (text[i]);
979 #endif
980 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
981 nchars,
982 GC_FONT (gc)->mac_style,
983 &text_layout);
984 if (err != noErr)
985 return;
986 #ifdef MAC_OSX
987 if (!mac_use_core_graphics)
989 #endif
990 mac_begin_clip (f, gc);
991 RGBForeColor (GC_FORE_COLOR (gc));
992 if (bg_width)
994 Rect r;
996 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
997 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
998 RGBBackColor (GC_BACK_COLOR (gc));
999 EraseRect (&r);
1000 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1002 MoveTo (x, y);
1003 ATSUDrawText (text_layout,
1004 kATSUFromTextBeginning, kATSUToTextEnd,
1005 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1006 if (overstrike_p)
1008 MoveTo (x + 1, y);
1009 ATSUDrawText (text_layout,
1010 kATSUFromTextBeginning, kATSUToTextEnd,
1011 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1013 mac_end_clip (gc);
1014 #ifdef MAC_OSX
1016 else
1018 static CGContextRef context;
1019 float port_height = FRAME_PIXEL_HEIGHT (f);
1020 static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
1021 static const ByteCount sizes[] = {sizeof (CGContextRef)};
1022 static const ATSUAttributeValuePtr values[] = {&context};
1024 #if USE_CG_DRAWING
1025 context = mac_begin_cg_clip (f, gc);
1026 #else
1027 CGrafPtr port;
1029 GetPort (&port);
1030 QDBeginCGContext (port, &context);
1031 if (gc->n_clip_rects || bg_width)
1033 CGContextTranslateCTM (context, 0, port_height);
1034 CGContextScaleCTM (context, 1, -1);
1035 if (gc->n_clip_rects)
1036 CGContextClipToRects (context, gc->clip_rects,
1037 gc->n_clip_rects);
1038 #endif
1039 if (bg_width)
1041 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1042 CGContextFillRect (context,
1043 CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
1044 bg_width,
1045 FONT_HEIGHT (GC_FONT (gc))));
1047 CGContextScaleCTM (context, 1, -1);
1048 CGContextTranslateCTM (context, 0, -port_height);
1049 #if !USE_CG_DRAWING
1051 #endif
1052 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1053 err = ATSUSetLayoutControls (text_layout,
1054 sizeof (tags) / sizeof (tags[0]),
1055 tags, sizes, values);
1056 if (err == noErr)
1058 ATSUDrawText (text_layout,
1059 kATSUFromTextBeginning, kATSUToTextEnd,
1060 Long2Fix (x), Long2Fix (port_height - y));
1061 if (overstrike_p)
1062 ATSUDrawText (text_layout,
1063 kATSUFromTextBeginning, kATSUToTextEnd,
1064 Long2Fix (x + 1), Long2Fix (port_height - y));
1066 #if USE_CG_DRAWING
1067 mac_end_cg_clip (f);
1068 context = NULL;
1069 #else
1070 CGContextSynchronize (context);
1071 QDEndCGContext (port, &context);
1072 #endif
1073 #if 0
1074 /* This doesn't work on Mac OS X 10.1. */
1075 ATSUClearLayoutControls (text_layout,
1076 sizeof (tags) / sizeof (tags[0]), tags);
1077 #else
1078 ATSUSetLayoutControls (text_layout,
1079 sizeof (tags) / sizeof (tags[0]),
1080 tags, sizes, values);
1081 #endif
1083 #endif /* MAC_OSX */
1085 #endif /* USE_ATSUI */
1088 static void
1089 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1090 overstrike_p, bytes_per_char)
1091 struct frame *f;
1092 GC gc;
1093 int x, y;
1094 char *buf;
1095 int nchars, bg_width, overstrike_p, bytes_per_char;
1097 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1098 UInt32 savedFlags;
1099 #endif
1101 mac_begin_clip (f, gc);
1102 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1103 if (mac_use_core_graphics)
1104 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
1105 #endif
1106 RGBForeColor (GC_FORE_COLOR (gc));
1107 #ifdef MAC_OS8
1108 if (bg_width)
1110 RGBBackColor (GC_BACK_COLOR (gc));
1111 TextMode (srcCopy);
1113 else
1114 TextMode (srcOr);
1115 #else
1116 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1117 because:
1118 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1119 into an offscreen graphics world first. So performance gain
1120 cannot be expected.)
1121 - It lowers rendering quality.
1122 - Some fonts leave garbage on cursor movement. */
1123 if (bg_width)
1125 Rect r;
1127 RGBBackColor (GC_BACK_COLOR (gc));
1128 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1129 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1130 EraseRect (&r);
1132 TextMode (srcOr);
1133 #endif
1134 TextFont (GC_FONT (gc)->mac_fontnum);
1135 TextSize (GC_FONT (gc)->mac_fontsize);
1136 TextFace (GC_FONT (gc)->mac_fontface);
1137 MoveTo (x, y);
1138 DrawText (buf, 0, nchars * bytes_per_char);
1139 if (overstrike_p)
1141 TextMode (srcOr);
1142 MoveTo (x + 1, y);
1143 DrawText (buf, 0, nchars * bytes_per_char);
1145 if (bg_width)
1146 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1147 mac_end_clip (gc);
1149 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1150 if (mac_use_core_graphics)
1151 SwapQDTextFlags(savedFlags);
1152 #endif
1156 static INLINE void
1157 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1158 overstrike_p, bytes_per_char)
1159 struct frame *f;
1160 GC gc;
1161 int x, y;
1162 char *buf;
1163 int nchars, bg_width, overstrike_p, bytes_per_char;
1165 #if USE_ATSUI
1166 if (GC_FONT (gc)->mac_style)
1167 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
1168 overstrike_p, bytes_per_char);
1169 else
1170 #endif /* USE_ATSUI */
1171 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1172 overstrike_p, bytes_per_char);
1176 /* Mac replacement for XDrawImageString. */
1178 static void
1179 mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1180 struct frame *f;
1181 GC gc;
1182 int x, y;
1183 char *buf;
1184 int nchars, bg_width, overstrike_p;
1186 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1187 overstrike_p, 1);
1191 /* Mac replacement for XDrawImageString16. */
1193 static void
1194 mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1195 struct frame *f;
1196 GC gc;
1197 int x, y;
1198 XChar2b *buf;
1199 int nchars, bg_width, overstrike_p;
1201 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
1202 overstrike_p, 2);
1206 /* Mac replacement for XQueryTextExtents, but takes a character. If
1207 STYLE is NULL, measurement is done by QuickDraw Text routines for
1208 the font of the current graphics port. If CG_GLYPH is not NULL,
1209 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1211 static OSStatus
1212 mac_query_char_extents (style, c,
1213 font_ascent_return, font_descent_return,
1214 overall_return, cg_glyph)
1215 #if USE_ATSUI
1216 ATSUStyle style;
1217 #else
1218 void *style;
1219 #endif
1220 int c;
1221 int *font_ascent_return, *font_descent_return;
1222 XCharStruct *overall_return;
1223 #if USE_CG_TEXT_DRAWING
1224 CGGlyph *cg_glyph;
1225 #else
1226 void *cg_glyph;
1227 #endif
1229 OSStatus err = noErr;
1230 int width;
1231 Rect char_bounds;
1233 #if USE_ATSUI
1234 if (style)
1236 ATSUTextLayout text_layout;
1237 UniChar ch = c;
1239 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
1240 if (err == noErr
1241 && (font_ascent_return || font_descent_return || overall_return))
1243 ATSTrapezoid glyph_bounds;
1245 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1246 kATSUFromTextBeginning, kATSUToTextEnd,
1247 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1248 kATSUseFractionalOrigins,
1249 #else
1250 kATSUseDeviceOrigins,
1251 #endif
1252 1, &glyph_bounds, NULL);
1253 if (err == noErr)
1255 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1256 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1258 width = Fix2Long (glyph_bounds.upperRight.x
1259 - glyph_bounds.upperLeft.x);
1260 if (font_ascent_return)
1261 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1262 if (font_descent_return)
1263 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1266 if (err == noErr && overall_return)
1268 err = ATSUMeasureTextImage (text_layout,
1269 kATSUFromTextBeginning, kATSUToTextEnd,
1270 0, 0, &char_bounds);
1271 if (err == noErr)
1272 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1273 #if USE_CG_TEXT_DRAWING
1274 if (err == noErr && cg_glyph)
1276 OSStatus err1;
1277 ATSUGlyphInfoArray glyph_info_array;
1278 ByteCount count = sizeof (ATSUGlyphInfoArray);
1280 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1281 kATSUToTextEnd, NULL, NULL, NULL);
1282 if (err1 == noErr)
1283 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1284 kATSUToTextEnd, &count,
1285 &glyph_info_array);
1286 if (err1 == noErr
1287 /* Make sure that we don't have to make layout
1288 adjustments. */
1289 && glyph_info_array.glyphs[0].deltaY == 0.0f
1290 && glyph_info_array.glyphs[0].idealX == 0.0f
1291 && glyph_info_array.glyphs[0].screenX == 0)
1293 xassert (glyph_info_array.glyphs[0].glyphID);
1294 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1296 else
1297 *cg_glyph = 0;
1299 #endif
1302 else
1303 #endif
1305 if (font_ascent_return || font_descent_return)
1307 FontInfo font_info;
1309 GetFontInfo (&font_info);
1310 if (font_ascent_return)
1311 *font_ascent_return = font_info.ascent;
1312 if (font_descent_return)
1313 *font_descent_return = font_info.descent;
1315 if (overall_return)
1317 char ch = c;
1319 width = CharWidth (ch);
1320 QDTextBounds (1, &ch, &char_bounds);
1321 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1325 return err;
1329 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1331 static int
1332 mac_text_extents_16 (font_struct, string, nchars, overall_return)
1333 XFontStruct *font_struct;
1334 XChar2b *string;
1335 int nchars;
1336 XCharStruct *overall_return;
1338 int i;
1339 short width = 0, lbearing = 0, rbearing = 0;
1340 XCharStruct *pcm;
1342 for (i = 0; i < nchars; i++)
1344 pcm = mac_per_char_metric (font_struct, string, 0);
1345 if (pcm == NULL)
1346 width += FONT_WIDTH (font_struct);
1347 else
1349 lbearing = min (lbearing, width + pcm->lbearing);
1350 rbearing = max (rbearing, width + pcm->rbearing);
1351 width += pcm->width;
1353 string++;
1356 overall_return->lbearing = lbearing;
1357 overall_return->rbearing = rbearing;
1358 overall_return->width = width;
1360 /* What's the meaning of the return value of XTextExtents16? */
1364 #if USE_CG_TEXT_DRAWING
1365 static int cg_text_anti_aliasing_threshold = 8;
1367 static void
1368 init_cg_text_anti_aliasing_threshold ()
1370 int threshold;
1371 Boolean valid_p;
1373 threshold =
1374 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1375 kCFPreferencesCurrentApplication,
1376 &valid_p);
1377 if (valid_p)
1378 cg_text_anti_aliasing_threshold = threshold;
1381 static int
1382 mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1383 struct frame *f;
1384 GC gc;
1385 int x, y;
1386 XChar2b *buf;
1387 int nchars, bg_width, overstrike_p;
1389 float port_height, gx, gy;
1390 int i;
1391 CGContextRef context;
1392 CGGlyph *glyphs;
1393 CGSize *advances;
1395 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1396 return 0;
1398 port_height = FRAME_PIXEL_HEIGHT (f);
1399 gx = x;
1400 gy = port_height - y;
1401 glyphs = (CGGlyph *)buf;
1402 advances = alloca (sizeof (CGSize) * nchars);
1403 if (advances == NULL)
1404 return 0;
1405 for (i = 0; i < nchars; i++)
1407 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1409 advances[i].width = pcm->width;
1410 advances[i].height = 0;
1411 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1412 buf++;
1415 #if USE_CG_DRAWING
1416 context = mac_begin_cg_clip (f, gc);
1417 #else
1418 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1419 if (gc->n_clip_rects || bg_width)
1421 CGContextTranslateCTM (context, 0, port_height);
1422 CGContextScaleCTM (context, 1, -1);
1423 if (gc->n_clip_rects)
1424 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1425 #endif
1426 if (bg_width)
1428 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1429 CGContextFillRect
1430 (context,
1431 CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
1432 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1434 CGContextScaleCTM (context, 1, -1);
1435 CGContextTranslateCTM (context, 0, -port_height);
1436 #if !USE_CG_DRAWING
1438 #endif
1439 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1440 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1441 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1442 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1443 CGContextSetShouldAntialias (context, false);
1444 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1445 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1446 if (CGContextShowGlyphsWithAdvances != NULL)
1447 #endif
1449 CGContextSetTextPosition (context, gx, gy);
1450 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1451 if (overstrike_p)
1453 CGContextSetTextPosition (context, gx + 1.0f, gy);
1454 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1457 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1458 else /* CGContextShowGlyphsWithAdvances == NULL */
1459 #endif
1460 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1461 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1463 for (i = 0; i < nchars; i++)
1465 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1466 if (overstrike_p)
1467 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
1468 gx += advances[i].width;
1471 #endif
1472 #if USE_CG_DRAWING
1473 mac_end_cg_clip (f);
1474 #else
1475 CGContextSynchronize (context);
1476 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1477 #endif
1479 return 1;
1481 #endif
1484 #if !USE_CG_DRAWING
1485 /* Mac replacement for XCopyArea: dest must be window. */
1487 static void
1488 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1489 Pixmap src;
1490 struct frame *f;
1491 GC gc;
1492 int src_x, src_y;
1493 unsigned int width, height;
1494 int dest_x, dest_y;
1496 Rect src_r, dest_r;
1498 mac_begin_clip (f, gc);
1500 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1501 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1503 ForeColor (blackColor);
1504 BackColor (whiteColor);
1506 LockPixels (GetGWorldPixMap (src));
1507 #if TARGET_API_MAC_CARBON
1509 CGrafPtr port;
1511 GetPort (&port);
1512 LockPortBits (port);
1513 CopyBits (GetPortBitMapForCopyBits (src),
1514 GetPortBitMapForCopyBits (port),
1515 &src_r, &dest_r, srcCopy, 0);
1516 UnlockPortBits (port);
1518 #else /* not TARGET_API_MAC_CARBON */
1519 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1520 &src_r, &dest_r, srcCopy, 0);
1521 #endif /* not TARGET_API_MAC_CARBON */
1522 UnlockPixels (GetGWorldPixMap (src));
1524 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1526 mac_end_clip (gc);
1530 static void
1531 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1532 width, height, dest_x, dest_y)
1533 Pixmap src, mask;
1534 struct frame *f;
1535 GC gc;
1536 int src_x, src_y;
1537 unsigned int width, height;
1538 int dest_x, dest_y;
1540 Rect src_r, dest_r;
1542 mac_begin_clip (f, gc);
1544 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1545 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1547 ForeColor (blackColor);
1548 BackColor (whiteColor);
1550 LockPixels (GetGWorldPixMap (src));
1551 LockPixels (GetGWorldPixMap (mask));
1552 #if TARGET_API_MAC_CARBON
1554 CGrafPtr port;
1556 GetPort (&port);
1557 LockPortBits (port);
1558 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1559 GetPortBitMapForCopyBits (port),
1560 &src_r, &src_r, &dest_r);
1561 UnlockPortBits (port);
1563 #else /* not TARGET_API_MAC_CARBON */
1564 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1565 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1566 #endif /* not TARGET_API_MAC_CARBON */
1567 UnlockPixels (GetGWorldPixMap (mask));
1568 UnlockPixels (GetGWorldPixMap (src));
1570 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1572 mac_end_clip (gc);
1574 #endif /* !USE_CG_DRAWING */
1577 /* Mac replacement for XCopyArea: used only for scrolling. */
1579 static void
1580 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1581 struct frame *f;
1582 GC gc;
1583 int src_x, src_y;
1584 unsigned int width, height;
1585 int dest_x, dest_y;
1587 #if TARGET_API_MAC_CARBON
1588 Rect src_r;
1589 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
1591 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1592 #if USE_CG_DRAWING
1593 mac_prepare_for_quickdraw (f);
1594 #endif
1595 ScrollWindowRect (FRAME_MAC_WINDOW (f),
1596 &src_r, dest_x - src_x, dest_y - src_y,
1597 kScrollWindowNoOptions, dummy);
1598 DisposeRgn (dummy);
1599 #else /* not TARGET_API_MAC_CARBON */
1600 Rect src_r, dest_r;
1601 WindowRef w = FRAME_MAC_WINDOW (f);
1603 mac_begin_clip (f, gc);
1605 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1606 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1608 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1609 color mapping in CopyBits. Otherwise, it will be slow. */
1610 ForeColor (blackColor);
1611 BackColor (whiteColor);
1612 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1614 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1616 mac_end_clip (gc);
1617 #endif /* not TARGET_API_MAC_CARBON */
1621 /* Mac replacement for XChangeGC. */
1623 static void
1624 XChangeGC (display, gc, mask, xgcv)
1625 Display *display;
1626 GC gc;
1627 unsigned long mask;
1628 XGCValues *xgcv;
1630 if (mask & GCForeground)
1631 XSetForeground (display, gc, xgcv->foreground);
1632 if (mask & GCBackground)
1633 XSetBackground (display, gc, xgcv->background);
1634 if (mask & GCFont)
1635 XSetFont (display, gc, xgcv->font);
1639 /* Mac replacement for XCreateGC. */
1642 XCreateGC (display, d, mask, xgcv)
1643 Display *display;
1644 void *d;
1645 unsigned long mask;
1646 XGCValues *xgcv;
1648 GC gc = xmalloc (sizeof (*gc));
1650 bzero (gc, sizeof (*gc));
1651 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1652 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1653 if (CGColorGetTypeID != NULL)
1654 #endif
1656 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
1657 CGColorRetain (gc->cg_fore_color);
1658 CGColorRetain (gc->cg_back_color);
1660 #endif
1661 XChangeGC (display, gc, mask, xgcv);
1663 return gc;
1667 /* Used in xfaces.c. */
1669 void
1670 XFreeGC (display, gc)
1671 Display *display;
1672 GC gc;
1674 if (gc->clip_region)
1675 DisposeRgn (gc->clip_region);
1676 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1677 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1678 if (CGColorGetTypeID != NULL)
1679 #endif
1681 CGColorRelease (gc->cg_fore_color);
1682 CGColorRelease (gc->cg_back_color);
1684 #endif
1685 xfree (gc);
1689 /* Mac replacement for XGetGCValues. */
1691 static void
1692 XGetGCValues (display, gc, mask, xgcv)
1693 Display *display;
1694 GC gc;
1695 unsigned long mask;
1696 XGCValues *xgcv;
1698 if (mask & GCForeground)
1699 xgcv->foreground = gc->xgcv.foreground;
1700 if (mask & GCBackground)
1701 xgcv->background = gc->xgcv.background;
1702 if (mask & GCFont)
1703 xgcv->font = gc->xgcv.font;
1707 /* Mac replacement for XSetForeground. */
1709 void
1710 XSetForeground (display, gc, color)
1711 Display *display;
1712 GC gc;
1713 unsigned long color;
1715 if (gc->xgcv.foreground != color)
1717 gc->xgcv.foreground = color;
1718 gc->fore_color.red = RED16_FROM_ULONG (color);
1719 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1720 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1721 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1722 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1723 if (CGColorGetTypeID != NULL)
1724 #endif
1726 CGColorRelease (gc->cg_fore_color);
1727 if (color == 0)
1729 gc->cg_fore_color = mac_cg_color_black;
1730 CGColorRetain (gc->cg_fore_color);
1732 else
1734 float rgba[4];
1736 rgba[0] = gc->fore_color.red / 65535.0f;
1737 rgba[1] = gc->fore_color.green / 65535.0f;
1738 rgba[2] = gc->fore_color.blue / 65535.0f;
1739 rgba[3] = 1.0f;
1740 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1743 #endif
1748 /* Mac replacement for XSetBackground. */
1750 void
1751 XSetBackground (display, gc, color)
1752 Display *display;
1753 GC gc;
1754 unsigned long color;
1756 if (gc->xgcv.background != color)
1758 gc->xgcv.background = color;
1759 gc->back_color.red = RED16_FROM_ULONG (color);
1760 gc->back_color.green = GREEN16_FROM_ULONG (color);
1761 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1762 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1763 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1764 if (CGColorGetTypeID != NULL)
1765 #endif
1767 CGColorRelease (gc->cg_back_color);
1768 if (color == 0)
1770 gc->cg_back_color = mac_cg_color_black;
1771 CGColorRetain (gc->cg_back_color);
1773 else
1775 float rgba[4];
1777 rgba[0] = gc->back_color.red / 65535.0f;
1778 rgba[1] = gc->back_color.green / 65535.0f;
1779 rgba[2] = gc->back_color.blue / 65535.0f;
1780 rgba[3] = 1.0f;
1781 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1784 #endif
1789 /* Mac replacement for XSetFont. */
1791 static void
1792 XSetFont (display, gc, font)
1793 Display *display;
1794 GC gc;
1795 XFontStruct *font;
1797 gc->xgcv.font = font;
1801 /* Mac replacement for XSetClipRectangles. */
1803 static void
1804 mac_set_clip_rectangles (display, gc, rectangles, n)
1805 Display *display;
1806 GC gc;
1807 Rect *rectangles;
1808 int n;
1810 int i;
1812 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1814 gc->n_clip_rects = n;
1815 if (n > 0)
1817 if (gc->clip_region == NULL)
1818 gc->clip_region = NewRgn ();
1819 RectRgn (gc->clip_region, rectangles);
1820 if (n > 1)
1822 RgnHandle region = NewRgn ();
1824 for (i = 1; i < n; i++)
1826 RectRgn (region, rectangles + i);
1827 UnionRgn (gc->clip_region, region, gc->clip_region);
1829 DisposeRgn (region);
1832 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1833 for (i = 0; i < n; i++)
1835 Rect *rect = rectangles + i;
1837 gc->clip_rects[i] = CGRectMake (rect->left, rect->top,
1838 rect->right - rect->left,
1839 rect->bottom - rect->top);
1841 #endif
1845 /* Mac replacement for XSetClipMask. */
1847 static INLINE void
1848 mac_reset_clip_rectangles (display, gc)
1849 Display *display;
1850 GC gc;
1852 gc->n_clip_rects = 0;
1856 /* Mac replacement for XSetWindowBackground. */
1858 void
1859 XSetWindowBackground (display, w, color)
1860 Display *display;
1861 WindowRef w;
1862 unsigned long color;
1864 #if !TARGET_API_MAC_CARBON
1865 AuxWinHandle aw_handle;
1866 CTabHandle ctab_handle;
1867 ColorSpecPtr ct_table;
1868 short ct_size;
1869 #endif
1870 RGBColor bg_color;
1872 bg_color.red = RED16_FROM_ULONG (color);
1873 bg_color.green = GREEN16_FROM_ULONG (color);
1874 bg_color.blue = BLUE16_FROM_ULONG (color);
1876 #if TARGET_API_MAC_CARBON
1877 SetWindowContentColor (w, &bg_color);
1878 #else
1879 if (GetAuxWin (w, &aw_handle))
1881 ctab_handle = (*aw_handle)->awCTable;
1882 HandToHand ((Handle *) &ctab_handle);
1883 ct_table = (*ctab_handle)->ctTable;
1884 ct_size = (*ctab_handle)->ctSize;
1885 while (ct_size > -1)
1887 if (ct_table->value == 0)
1889 ct_table->rgb = bg_color;
1890 CTabChanged (ctab_handle);
1891 SetWinColor (w, (WCTabHandle) ctab_handle);
1893 ct_size--;
1896 #endif
1899 /* Flush display of frame F, or of all frames if F is null. */
1901 static void
1902 x_flush (f)
1903 struct frame *f;
1905 #if TARGET_API_MAC_CARBON
1906 BLOCK_INPUT;
1907 #if USE_CG_DRAWING
1908 mac_prepare_for_quickdraw (f);
1909 #endif
1910 if (f)
1911 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1912 else
1913 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1914 UNBLOCK_INPUT;
1915 #endif
1919 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1920 Calls to XFlush should be unnecessary because the X output buffer
1921 is flushed automatically as needed by calls to XPending,
1922 XNextEvent, or XWindowEvent according to the XFlush man page.
1923 XTread_socket calls XPending. Removing XFlush improves
1924 performance. */
1926 #define XFlush(DISPLAY) (void) 0
1928 #if USE_CG_DRAWING
1929 static void
1930 mac_flush_display_optional (f)
1931 struct frame *f;
1933 BLOCK_INPUT;
1934 mac_prepare_for_quickdraw (f);
1935 UNBLOCK_INPUT;
1937 #endif
1939 /***********************************************************************
1940 Starting and ending an update
1941 ***********************************************************************/
1943 /* Start an update of frame F. This function is installed as a hook
1944 for update_begin, i.e. it is called when update_begin is called.
1945 This function is called prior to calls to x_update_window_begin for
1946 each window being updated. */
1948 static void
1949 x_update_begin (f)
1950 struct frame *f;
1952 #if TARGET_API_MAC_CARBON
1953 /* During update of a frame, availability of input events is
1954 periodically checked with ReceiveNextEvent if
1955 redisplay-dont-pause is nil. That normally flushes window buffer
1956 changes for every check, and thus screen update looks waving even
1957 if no input is available. So we disable screen updates during
1958 update of a frame. */
1959 BLOCK_INPUT;
1960 DisableScreenUpdates ();
1961 UNBLOCK_INPUT;
1962 #endif
1966 /* Start update of window W. Set the global variable updated_window
1967 to the window being updated and set output_cursor to the cursor
1968 position of W. */
1970 static void
1971 x_update_window_begin (w)
1972 struct window *w;
1974 struct frame *f = XFRAME (WINDOW_FRAME (w));
1975 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1977 updated_window = w;
1978 set_output_cursor (&w->cursor);
1980 BLOCK_INPUT;
1982 if (f == display_info->mouse_face_mouse_frame)
1984 /* Don't do highlighting for mouse motion during the update. */
1985 display_info->mouse_face_defer = 1;
1987 /* If F needs to be redrawn, simply forget about any prior mouse
1988 highlighting. */
1989 if (FRAME_GARBAGED_P (f))
1990 display_info->mouse_face_window = Qnil;
1992 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1993 their mouse_face_p flag set, which means that they are always
1994 unequal to rows in a desired matrix which never have that
1995 flag set. So, rows containing mouse-face glyphs are never
1996 scrolled, and we don't have to switch the mouse highlight off
1997 here to prevent it from being scrolled. */
1999 /* Can we tell that this update does not affect the window
2000 where the mouse highlight is? If so, no need to turn off.
2001 Likewise, don't do anything if the frame is garbaged;
2002 in that case, the frame's current matrix that we would use
2003 is all wrong, and we will redisplay that line anyway. */
2004 if (!NILP (display_info->mouse_face_window)
2005 && w == XWINDOW (display_info->mouse_face_window))
2007 int i;
2009 for (i = 0; i < w->desired_matrix->nrows; ++i)
2010 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
2011 break;
2013 if (i < w->desired_matrix->nrows)
2014 clear_mouse_face (display_info);
2016 #endif /* 0 */
2019 UNBLOCK_INPUT;
2023 /* Draw a vertical window border from (x,y0) to (x,y1) */
2025 static void
2026 mac_draw_vertical_window_border (w, x, y0, y1)
2027 struct window *w;
2028 int x, y0, y1;
2030 struct frame *f = XFRAME (WINDOW_FRAME (w));
2031 struct face *face;
2033 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
2034 if (face)
2035 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
2036 face->foreground);
2038 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
2041 /* End update of window W (which is equal to updated_window).
2043 Draw vertical borders between horizontally adjacent windows, and
2044 display W's cursor if CURSOR_ON_P is non-zero.
2046 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2047 glyphs in mouse-face were overwritten. In that case we have to
2048 make sure that the mouse-highlight is properly redrawn.
2050 W may be a menu bar pseudo-window in case we don't have X toolkit
2051 support. Such windows don't have a cursor, so don't display it
2052 here. */
2054 static void
2055 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
2056 struct window *w;
2057 int cursor_on_p, mouse_face_overwritten_p;
2059 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
2061 if (!w->pseudo_window_p)
2063 BLOCK_INPUT;
2065 if (cursor_on_p)
2066 display_and_set_cursor (w, 1, output_cursor.hpos,
2067 output_cursor.vpos,
2068 output_cursor.x, output_cursor.y);
2070 if (draw_window_fringes (w, 1))
2071 x_draw_vertical_border (w);
2073 UNBLOCK_INPUT;
2076 /* If a row with mouse-face was overwritten, arrange for
2077 XTframe_up_to_date to redisplay the mouse highlight. */
2078 if (mouse_face_overwritten_p)
2080 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
2081 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
2082 dpyinfo->mouse_face_window = Qnil;
2085 updated_window = NULL;
2089 /* End update of frame F. This function is installed as a hook in
2090 update_end. */
2092 static void
2093 x_update_end (f)
2094 struct frame *f;
2096 /* Mouse highlight may be displayed again. */
2097 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
2099 BLOCK_INPUT;
2100 #if TARGET_API_MAC_CARBON
2101 EnableScreenUpdates ();
2102 #endif
2103 XFlush (FRAME_MAC_DISPLAY (f));
2104 UNBLOCK_INPUT;
2108 /* This function is called from various places in xdisp.c whenever a
2109 complete update has been performed. The global variable
2110 updated_window is not available here. */
2112 static void
2113 XTframe_up_to_date (f)
2114 struct frame *f;
2116 if (FRAME_MAC_P (f))
2118 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2120 if (dpyinfo->mouse_face_deferred_gc
2121 || f == dpyinfo->mouse_face_mouse_frame)
2123 BLOCK_INPUT;
2124 if (dpyinfo->mouse_face_mouse_frame)
2125 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
2126 dpyinfo->mouse_face_mouse_x,
2127 dpyinfo->mouse_face_mouse_y);
2128 dpyinfo->mouse_face_deferred_gc = 0;
2129 UNBLOCK_INPUT;
2135 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2136 arrow bitmaps, or clear the fringes if no bitmaps are required
2137 before DESIRED_ROW is made current. The window being updated is
2138 found in updated_window. This function is called from
2139 update_window_line only if it is known that there are differences
2140 between bitmaps to be drawn between current row and DESIRED_ROW. */
2142 static void
2143 x_after_update_window_line (desired_row)
2144 struct glyph_row *desired_row;
2146 struct window *w = updated_window;
2147 struct frame *f;
2148 int width, height;
2150 xassert (w);
2152 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2153 desired_row->redraw_fringe_bitmaps_p = 1;
2155 /* When a window has disappeared, make sure that no rest of
2156 full-width rows stays visible in the internal border. Could
2157 check here if updated_window is the leftmost/rightmost window,
2158 but I guess it's not worth doing since vertically split windows
2159 are almost never used, internal border is rarely set, and the
2160 overhead is very small. */
2161 if (windows_or_buffers_changed
2162 && desired_row->full_width_p
2163 && (f = XFRAME (w->frame),
2164 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2165 width != 0)
2166 && (height = desired_row->visible_height,
2167 height > 0))
2169 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2171 /* Internal border is drawn below the tool bar. */
2172 if (WINDOWP (f->tool_bar_window)
2173 && w == XWINDOW (f->tool_bar_window))
2174 y -= width;
2176 BLOCK_INPUT;
2177 mac_clear_area (f, 0, y, width, height);
2178 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
2179 UNBLOCK_INPUT;
2184 /* Draw the bitmap WHICH in one of the left or right fringes of
2185 window W. ROW is the glyph row for which to display the bitmap; it
2186 determines the vertical position at which the bitmap has to be
2187 drawn. */
2189 static void
2190 x_draw_fringe_bitmap (w, row, p)
2191 struct window *w;
2192 struct glyph_row *row;
2193 struct draw_fringe_bitmap_params *p;
2195 struct frame *f = XFRAME (WINDOW_FRAME (w));
2196 Display *display = FRAME_MAC_DISPLAY (f);
2197 struct face *face = p->face;
2198 int rowY;
2199 int overlay_p = p->overlay_p;
2201 #ifdef MAC_OSX
2202 if (!overlay_p)
2204 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2206 #if 0 /* MAC_TODO: stipple */
2207 /* In case the same realized face is used for fringes and
2208 for something displayed in the text (e.g. face `region' on
2209 mono-displays, the fill style may have been changed to
2210 FillSolid in x_draw_glyph_string_background. */
2211 if (face->stipple)
2212 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2213 else
2214 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2215 #endif
2217 /* If the fringe is adjacent to the left (right) scroll bar of a
2218 leftmost (rightmost, respectively) window, then extend its
2219 background to the gap between the fringe and the bar. */
2220 if ((WINDOW_LEFTMOST_P (w)
2221 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2222 || (WINDOW_RIGHTMOST_P (w)
2223 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2225 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2227 if (sb_width > 0)
2229 int left = WINDOW_SCROLL_BAR_AREA_X (w);
2230 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2231 * FRAME_COLUMN_WIDTH (f));
2233 if (bx < 0
2234 && (left + width == p->x
2235 || p->x + p->wd == left))
2237 /* Bitmap fills the fringe and we need background
2238 extension. */
2239 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
2241 bx = p->x;
2242 nx = p->wd;
2243 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
2244 row->y));
2245 ny = row->visible_height;
2248 if (bx >= 0)
2250 if (left + width == bx)
2252 bx = left + sb_width;
2253 nx += width - sb_width;
2255 else if (bx + nx == left)
2256 nx += width - sb_width;
2261 if (bx >= 0)
2263 mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
2264 /* The fringe background has already been filled. */
2265 overlay_p = 1;
2268 #if 0 /* MAC_TODO: stipple */
2269 if (!face->stipple)
2270 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2271 #endif
2273 #endif /* MAC_OSX */
2275 /* Must clip because of partially visible lines. */
2276 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2277 if (p->y < rowY)
2279 /* Adjust position of "bottom aligned" bitmap on partially
2280 visible last row. */
2281 int oldY = row->y;
2282 int oldVH = row->visible_height;
2283 row->visible_height = p->h;
2284 row->y -= rowY - p->y;
2285 x_clip_to_row (w, row, -1, face->gc);
2286 row->y = oldY;
2287 row->visible_height = oldVH;
2289 else
2290 x_clip_to_row (w, row, -1, face->gc);
2292 #ifndef MAC_OSX
2293 if (p->bx >= 0 && !p->overlay_p)
2295 #if 0 /* MAC_TODO: stipple */
2296 /* In case the same realized face is used for fringes and
2297 for something displayed in the text (e.g. face `region' on
2298 mono-displays, the fill style may have been changed to
2299 FillSolid in x_draw_glyph_string_background. */
2300 if (face->stipple)
2301 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2302 else
2303 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2304 #endif
2306 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
2308 #if 0 /* MAC_TODO: stipple */
2309 if (!face->stipple)
2310 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2311 #endif
2313 #endif /* !MAC_OSX */
2315 if (p->which
2316 #if USE_CG_DRAWING
2317 && p->which < max_fringe_bmp
2318 #endif
2321 XGCValues gcv;
2323 XGetGCValues (display, face->gc, GCForeground, &gcv);
2324 XSetForeground (display, face->gc,
2325 (p->cursor_p
2326 ? (p->overlay_p ? face->background
2327 : f->output_data.mac->cursor_pixel)
2328 : face->foreground));
2329 #if USE_CG_DRAWING
2330 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
2331 p->wd, p->h, p->x, p->y, overlay_p);
2332 #else
2333 mac_draw_bitmap (f, face->gc, p->x, p->y,
2334 p->wd, p->h, p->bits + p->dh, overlay_p);
2335 #endif
2336 XSetForeground (display, face->gc, gcv.foreground);
2339 mac_reset_clip_rectangles (display, face->gc);
2342 #if USE_CG_DRAWING
2343 static void
2344 mac_define_fringe_bitmap (which, bits, h, wd)
2345 int which;
2346 unsigned short *bits;
2347 int h, wd;
2349 int i;
2350 CGDataProviderRef provider;
2352 if (which >= max_fringe_bmp)
2354 i = max_fringe_bmp;
2355 max_fringe_bmp = which + 20;
2356 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
2357 while (i < max_fringe_bmp)
2358 fringe_bmp[i++] = 0;
2361 for (i = 0; i < h; i++)
2362 bits[i] = ~bits[i];
2364 BLOCK_INPUT;
2366 provider = CGDataProviderCreateWithData (NULL, bits,
2367 sizeof (unsigned short) * h, NULL);
2368 if (provider)
2370 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
2371 sizeof (unsigned short),
2372 provider, NULL, 0);
2373 CGDataProviderRelease (provider);
2376 UNBLOCK_INPUT;
2379 static void
2380 mac_destroy_fringe_bitmap (which)
2381 int which;
2383 if (which >= max_fringe_bmp)
2384 return;
2386 if (fringe_bmp[which])
2388 BLOCK_INPUT;
2389 CGImageRelease (fringe_bmp[which]);
2390 UNBLOCK_INPUT;
2392 fringe_bmp[which] = 0;
2394 #endif
2397 /* This is called when starting Emacs and when restarting after
2398 suspend. When starting Emacs, no window is mapped. And nothing
2399 must be done to Emacs's own window if it is suspended (though that
2400 rarely happens). */
2402 static void
2403 XTset_terminal_modes (struct terminal *t)
2407 /* This is called when exiting or suspending Emacs. Exiting will make
2408 the windows go away, and suspending requires no action. */
2410 static void
2411 XTreset_terminal_modes (struct terminal *t)
2417 /***********************************************************************
2418 Display Iterator
2419 ***********************************************************************/
2421 /* Function prototypes of this page. */
2423 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
2424 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
2427 static void
2428 pcm_init (pcm, count)
2429 XCharStruct *pcm;
2430 int count;
2432 bzero (pcm, sizeof (XCharStruct) * count);
2433 while (--count >= 0)
2435 pcm->descent = PCM_INVALID;
2436 pcm++;
2440 static enum pcm_status
2441 pcm_get_status (pcm)
2442 const XCharStruct *pcm;
2444 int height = pcm->ascent + pcm->descent;
2446 /* Negative height means some special status. */
2447 return height >= 0 ? PCM_VALID : height;
2450 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2451 is not contained in the font. */
2453 static INLINE XCharStruct *
2454 x_per_char_metric (font, char2b)
2455 XFontStruct *font;
2456 XChar2b *char2b;
2458 /* The result metric information. */
2459 XCharStruct *pcm = NULL;
2461 xassert (font && char2b);
2463 #if USE_ATSUI
2464 if (font->mac_style)
2466 XCharStruct **row = font->bounds.rows + char2b->byte1;
2468 if (*row == NULL)
2470 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2471 pcm_init (*row, 0x100);
2473 pcm = *row + char2b->byte2;
2474 if (pcm_get_status (pcm) != PCM_VALID)
2476 BLOCK_INPUT;
2477 mac_query_char_extents (font->mac_style,
2478 (char2b->byte1 << 8) + char2b->byte2,
2479 NULL, NULL, pcm, NULL);
2480 UNBLOCK_INPUT;
2483 else
2485 #endif
2486 if (font->bounds.per_char != NULL)
2488 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2490 /* min_char_or_byte2 specifies the linear character index
2491 corresponding to the first element of the per_char array,
2492 max_char_or_byte2 is the index of the last character. A
2493 character with non-zero CHAR2B->byte1 is not in the font.
2494 A character with byte2 less than min_char_or_byte2 or
2495 greater max_char_or_byte2 is not in the font. */
2496 if (char2b->byte1 == 0
2497 && char2b->byte2 >= font->min_char_or_byte2
2498 && char2b->byte2 <= font->max_char_or_byte2)
2499 pcm = font->bounds.per_char
2500 + (char2b->byte2 - font->min_char_or_byte2);
2502 else
2504 /* If either min_byte1 or max_byte1 are nonzero, both
2505 min_char_or_byte2 and max_char_or_byte2 are less than
2506 256, and the 2-byte character index values corresponding
2507 to the per_char array element N (counting from 0) are:
2509 byte1 = N/D + min_byte1
2510 byte2 = N\D + min_char_or_byte2
2512 where:
2514 D = max_char_or_byte2 - min_char_or_byte2 + 1
2515 / = integer division
2516 \ = integer modulus */
2517 if (char2b->byte1 >= font->min_byte1
2518 && char2b->byte1 <= font->max_byte1
2519 && char2b->byte2 >= font->min_char_or_byte2
2520 && char2b->byte2 <= font->max_char_or_byte2)
2522 pcm = (font->bounds.per_char
2523 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2524 * (char2b->byte1 - font->min_byte1))
2525 + (char2b->byte2 - font->min_char_or_byte2));
2529 else
2531 /* If the per_char pointer is null, all glyphs between the first
2532 and last character indexes inclusive have the same
2533 information, as given by both min_bounds and max_bounds. */
2534 if (char2b->byte2 >= font->min_char_or_byte2
2535 && char2b->byte2 <= font->max_char_or_byte2)
2536 pcm = &font->max_bounds;
2538 #if USE_ATSUI
2540 #endif
2542 return ((pcm == NULL
2543 || (pcm->width == 0
2544 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2545 && (pcm->rbearing - pcm->lbearing) == 0
2546 #endif
2548 ? NULL : pcm);
2551 /* RIF:
2554 static XCharStruct *
2555 mac_per_char_metric (font, char2b, font_type)
2556 XFontStruct *font;
2557 XChar2b *char2b;
2558 int font_type;
2560 return x_per_char_metric (font, char2b);
2563 /* RIF:
2564 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2565 the two-byte form of C. Encoding is returned in *CHAR2B. */
2567 static int
2568 mac_encode_char (c, char2b, font_info, two_byte_p)
2569 int c;
2570 XChar2b *char2b;
2571 struct font_info *font_info;
2572 int *two_byte_p;
2574 int charset = CHAR_CHARSET (c);
2575 XFontStruct *font = font_info->font;
2577 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2578 This may be either a program in a special encoder language or a
2579 fixed encoding. */
2580 if (font_info->font_encoder)
2582 /* It's a program. */
2583 struct ccl_program *ccl = font_info->font_encoder;
2585 check_ccl_update (ccl);
2586 if (CHARSET_DIMENSION (charset) == 1)
2588 ccl->reg[0] = charset;
2589 ccl->reg[1] = char2b->byte2;
2590 ccl->reg[2] = -1;
2592 else
2594 ccl->reg[0] = charset;
2595 ccl->reg[1] = char2b->byte1;
2596 ccl->reg[2] = char2b->byte2;
2599 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2601 /* We assume that MSBs are appropriately set/reset by CCL
2602 program. */
2603 if (font->max_byte1 == 0) /* 1-byte font */
2604 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2605 else
2606 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2608 else if (font_info->encoding[charset])
2610 /* Fixed encoding scheme. See fontset.h for the meaning of the
2611 encoding numbers. */
2612 int enc = font_info->encoding[charset];
2614 if ((enc == 1 || enc == 2)
2615 && CHARSET_DIMENSION (charset) == 2)
2616 char2b->byte1 |= 0x80;
2618 if (enc == 1 || enc == 3)
2619 char2b->byte2 |= 0x80;
2621 if (enc == 4)
2623 int sjis1, sjis2;
2625 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2626 char2b->byte1 = sjis1;
2627 char2b->byte2 = sjis2;
2631 if (two_byte_p)
2632 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2634 return FONT_TYPE_UNKNOWN;
2639 /***********************************************************************
2640 Glyph display
2641 ***********************************************************************/
2645 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2646 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2647 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2648 int));
2649 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2650 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2651 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2652 static void x_draw_glyph_string P_ ((struct glyph_string *));
2653 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2654 static void x_set_cursor_gc P_ ((struct glyph_string *));
2655 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2656 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2657 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2658 unsigned long *, double, int));*/
2659 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2660 double, int, unsigned long));
2661 static void x_setup_relief_colors P_ ((struct glyph_string *));
2662 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2663 static void x_draw_image_relief P_ ((struct glyph_string *));
2664 static void x_draw_image_foreground P_ ((struct glyph_string *));
2665 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2666 int, int, int));
2667 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2668 int, int, int, int, int, int,
2669 Rect *));
2670 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2671 int, int, int, Rect *));
2673 #if GLYPH_DEBUG
2674 static void x_check_font P_ ((struct frame *, XFontStruct *));
2675 #endif
2678 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2679 face. */
2681 static void
2682 x_set_cursor_gc (s)
2683 struct glyph_string *s;
2685 if (s->font == FRAME_FONT (s->f)
2686 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2687 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2688 && !s->cmp)
2689 s->gc = s->f->output_data.mac->cursor_gc;
2690 else
2692 /* Cursor on non-default face: must merge. */
2693 XGCValues xgcv;
2694 unsigned long mask;
2696 xgcv.background = s->f->output_data.mac->cursor_pixel;
2697 xgcv.foreground = s->face->background;
2699 /* If the glyph would be invisible, try a different foreground. */
2700 if (xgcv.foreground == xgcv.background)
2701 xgcv.foreground = s->face->foreground;
2702 if (xgcv.foreground == xgcv.background)
2703 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2704 if (xgcv.foreground == xgcv.background)
2705 xgcv.foreground = s->face->foreground;
2707 /* Make sure the cursor is distinct from text in this face. */
2708 if (xgcv.background == s->face->background
2709 && xgcv.foreground == s->face->foreground)
2711 xgcv.background = s->face->foreground;
2712 xgcv.foreground = s->face->background;
2715 IF_DEBUG (x_check_font (s->f, s->font));
2716 xgcv.font = s->font;
2717 mask = GCForeground | GCBackground | GCFont;
2719 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2720 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2721 mask, &xgcv);
2722 else
2723 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2724 = XCreateGC (s->display, s->window, mask, &xgcv);
2726 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2731 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2733 static void
2734 x_set_mouse_face_gc (s)
2735 struct glyph_string *s;
2737 int face_id;
2738 struct face *face;
2740 /* What face has to be used last for the mouse face? */
2741 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2742 face = FACE_FROM_ID (s->f, face_id);
2743 if (face == NULL)
2744 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2746 if (s->first_glyph->type == CHAR_GLYPH)
2747 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2748 else
2749 face_id = FACE_FOR_CHAR (s->f, face, 0);
2750 s->face = FACE_FROM_ID (s->f, face_id);
2751 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2753 /* If font in this face is same as S->font, use it. */
2754 if (s->font == s->face->font)
2755 s->gc = s->face->gc;
2756 else
2758 /* Otherwise construct scratch_cursor_gc with values from FACE
2759 but font FONT. */
2760 XGCValues xgcv;
2761 unsigned long mask;
2763 xgcv.background = s->face->background;
2764 xgcv.foreground = s->face->foreground;
2765 IF_DEBUG (x_check_font (s->f, s->font));
2766 xgcv.font = s->font;
2767 mask = GCForeground | GCBackground | GCFont;
2769 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2770 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2771 mask, &xgcv);
2772 else
2773 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2774 = XCreateGC (s->display, s->window, mask, &xgcv);
2776 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2779 xassert (s->gc != 0);
2783 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2784 Faces to use in the mode line have already been computed when the
2785 matrix was built, so there isn't much to do, here. */
2787 static INLINE void
2788 x_set_mode_line_face_gc (s)
2789 struct glyph_string *s;
2791 s->gc = s->face->gc;
2795 /* Set S->gc of glyph string S for drawing that glyph string. Set
2796 S->stippled_p to a non-zero value if the face of S has a stipple
2797 pattern. */
2799 static INLINE void
2800 x_set_glyph_string_gc (s)
2801 struct glyph_string *s;
2803 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2805 if (s->hl == DRAW_NORMAL_TEXT)
2807 s->gc = s->face->gc;
2808 s->stippled_p = s->face->stipple != 0;
2810 else if (s->hl == DRAW_INVERSE_VIDEO)
2812 x_set_mode_line_face_gc (s);
2813 s->stippled_p = s->face->stipple != 0;
2815 else if (s->hl == DRAW_CURSOR)
2817 x_set_cursor_gc (s);
2818 s->stippled_p = 0;
2820 else if (s->hl == DRAW_MOUSE_FACE)
2822 x_set_mouse_face_gc (s);
2823 s->stippled_p = s->face->stipple != 0;
2825 else if (s->hl == DRAW_IMAGE_RAISED
2826 || s->hl == DRAW_IMAGE_SUNKEN)
2828 s->gc = s->face->gc;
2829 s->stippled_p = s->face->stipple != 0;
2831 else
2833 s->gc = s->face->gc;
2834 s->stippled_p = s->face->stipple != 0;
2837 /* GC must have been set. */
2838 xassert (s->gc != 0);
2842 /* Set clipping for output of glyph string S. S may be part of a mode
2843 line or menu if we don't have X toolkit support. */
2845 static INLINE void
2846 x_set_glyph_string_clipping (s)
2847 struct glyph_string *s;
2849 Rect rects[MAX_CLIP_RECTS];
2850 int n;
2852 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
2853 mac_set_clip_rectangles (s->display, s->gc, rects, n);
2857 /* RIF:
2858 Compute left and right overhang of glyph string S. If S is a glyph
2859 string for a composition, assume overhangs don't exist. */
2861 static void
2862 mac_compute_glyph_string_overhangs (s)
2863 struct glyph_string *s;
2865 if (!(s->cmp == NULL
2866 && s->first_glyph->type == CHAR_GLYPH))
2867 return;
2869 if (!s->two_byte_p
2870 #if USE_ATSUI
2871 || s->font->mac_style
2872 #endif
2875 XCharStruct cs;
2877 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2878 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2879 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2881 else
2883 Rect r;
2884 MacFontStruct *font = s->font;
2886 #if USE_CG_DRAWING
2887 mac_prepare_for_quickdraw (s->f);
2888 #endif
2889 SetPortWindowPort (FRAME_MAC_WINDOW (s->f));
2891 TextFont (font->mac_fontnum);
2892 TextSize (font->mac_fontsize);
2893 TextFace (font->mac_fontface);
2895 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2897 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2898 s->left_overhang = r.left < 0 ? -r.left : 0;
2903 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2905 static INLINE void
2906 x_clear_glyph_string_rect (s, x, y, w, h)
2907 struct glyph_string *s;
2908 int x, y, w, h;
2910 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
2914 /* Draw the background of glyph_string S. If S->background_filled_p
2915 is non-zero don't draw it. FORCE_P non-zero means draw the
2916 background even if it wouldn't be drawn normally. This is used
2917 when a string preceding S draws into the background of S, or S
2918 contains the first component of a composition. */
2920 static void
2921 x_draw_glyph_string_background (s, force_p)
2922 struct glyph_string *s;
2923 int force_p;
2925 /* Nothing to do if background has already been drawn or if it
2926 shouldn't be drawn in the first place. */
2927 if (!s->background_filled_p)
2929 int box_line_width = max (s->face->box_line_width, 0);
2931 #if 0 /* MAC_TODO: stipple */
2932 if (s->stippled_p)
2934 /* Fill background with a stipple pattern. */
2935 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2936 XFillRectangle (s->display, s->window, s->gc, s->x,
2937 s->y + box_line_width,
2938 s->background_width,
2939 s->height - 2 * box_line_width);
2940 XSetFillStyle (s->display, s->gc, FillSolid);
2941 s->background_filled_p = 1;
2943 else
2944 #endif
2945 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2946 || s->font_not_found_p
2947 || s->extends_to_end_of_line_p
2948 || force_p)
2950 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2951 s->background_width,
2952 s->height - 2 * box_line_width);
2953 s->background_filled_p = 1;
2959 /* Draw the foreground of glyph string S. */
2961 static void
2962 x_draw_glyph_string_foreground (s)
2963 struct glyph_string *s;
2965 int i, x, bg_width;
2967 /* If first glyph of S has a left box line, start drawing the text
2968 of S to the right of that box line. */
2969 if (s->face->box != FACE_NO_BOX
2970 && s->first_glyph->left_box_line_p)
2971 x = s->x + eabs (s->face->box_line_width);
2972 else
2973 x = s->x;
2975 /* Draw characters of S as rectangles if S's font could not be
2976 loaded. */
2977 if (s->font_not_found_p)
2979 for (i = 0; i < s->nchars; ++i)
2981 struct glyph *g = s->first_glyph + i;
2982 mac_draw_rectangle (s->f, s->gc, x, s->y,
2983 g->pixel_width - 1, s->height - 1);
2984 x += g->pixel_width;
2987 else
2989 char *char1b = (char *) s->char2b;
2990 int boff = s->font_info->baseline_offset;
2992 if (s->font_info->vertical_centering)
2993 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2995 /* If we can use 8-bit functions, condense S->char2b. */
2996 if (!s->two_byte_p
2997 #if USE_ATSUI
2998 && GC_FONT (s->gc)->mac_style == NULL
2999 #endif
3001 for (i = 0; i < s->nchars; ++i)
3002 char1b[i] = s->char2b[i].byte2;
3004 /* Draw text with XDrawString if background has already been
3005 filled. Otherwise, use XDrawImageString. (Note that
3006 XDrawImageString is usually faster than XDrawString.) Always
3007 use XDrawImageString when drawing the cursor so that there is
3008 no chance that characters under a box cursor are invisible. */
3009 if (s->for_overlaps
3010 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3011 bg_width = 0; /* Corresponds to XDrawString. */
3012 else
3013 bg_width = s->background_width; /* Corresponds to XDrawImageString. */
3015 if (s->two_byte_p
3016 #if USE_ATSUI
3017 || GC_FONT (s->gc)->mac_style
3018 #endif
3020 #if USE_CG_TEXT_DRAWING
3021 if (!s->two_byte_p
3022 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
3023 s->char2b, s->nchars, bg_width,
3024 s->face->overstrike))
3026 else
3027 #endif
3028 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
3029 s->char2b, s->nchars, bg_width,
3030 s->face->overstrike);
3031 else
3032 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
3033 char1b, s->nchars, bg_width,
3034 s->face->overstrike);
3038 /* Draw the foreground of composite glyph string S. */
3040 static void
3041 x_draw_composite_glyph_string_foreground (s)
3042 struct glyph_string *s;
3044 int i, x;
3046 /* If first glyph of S has a left box line, start drawing the text
3047 of S to the right of that box line. */
3048 if (s->face->box != FACE_NO_BOX
3049 && s->first_glyph->left_box_line_p)
3050 x = s->x + eabs (s->face->box_line_width);
3051 else
3052 x = s->x;
3054 /* S is a glyph string for a composition. S->gidx is the index of
3055 the first character drawn for glyphs of this composition.
3056 S->gidx == 0 means we are drawing the very first character of
3057 this composition. */
3059 /* Draw a rectangle for the composition if the font for the very
3060 first character of the composition could not be loaded. */
3061 if (s->font_not_found_p)
3063 if (s->gidx == 0)
3064 mac_draw_rectangle (s->f, s->gc, x, s->y,
3065 s->width - 1, s->height - 1);
3067 else
3069 for (i = 0; i < s->nchars; i++, ++s->gidx)
3070 if (mac_per_char_metric (GC_FONT (s->gc), s->char2b + i, 0) == NULL)
3071 /* This is a nonexistent or zero-width glyph such as a
3072 combining diacritic. Draw a rectangle. */
3073 mac_draw_rectangle (s->f, s->gc,
3074 x + s->cmp->offsets[s->gidx * 2], s->y,
3075 FONT_WIDTH (GC_FONT (s->gc)) - 1, s->height - 1);
3076 else
3077 mac_draw_image_string_16 (s->f, s->gc,
3078 x + s->cmp->offsets[s->gidx * 2],
3079 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3080 s->char2b + i, 1, 0, s->face->overstrike);
3085 #ifdef USE_X_TOOLKIT
3087 static struct frame *x_frame_of_widget P_ ((Widget));
3090 /* Return the frame on which widget WIDGET is used.. Abort if frame
3091 cannot be determined. */
3093 static struct frame *
3094 x_frame_of_widget (widget)
3095 Widget widget;
3097 struct x_display_info *dpyinfo;
3098 Lisp_Object tail;
3099 struct frame *f;
3101 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3103 /* Find the top-level shell of the widget. Note that this function
3104 can be called when the widget is not yet realized, so XtWindow
3105 (widget) == 0. That's the reason we can't simply use
3106 x_any_window_to_frame. */
3107 while (!XtIsTopLevelShell (widget))
3108 widget = XtParent (widget);
3110 /* Look for a frame with that top-level widget. Allocate the color
3111 on that frame to get the right gamma correction value. */
3112 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3113 if (GC_FRAMEP (XCAR (tail))
3114 && (f = XFRAME (XCAR (tail)),
3115 (f->output_data.nothing != 1
3116 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3117 && f->output_data.x->widget == widget)
3118 return f;
3120 abort ();
3124 /* Allocate the color COLOR->pixel on the screen and display of
3125 widget WIDGET in colormap CMAP. If an exact match cannot be
3126 allocated, try the nearest color available. Value is non-zero
3127 if successful. This is called from lwlib. */
3130 x_alloc_nearest_color_for_widget (widget, cmap, color)
3131 Widget widget;
3132 Colormap cmap;
3133 XColor *color;
3135 struct frame *f = x_frame_of_widget (widget);
3136 return x_alloc_nearest_color (f, cmap, color);
3140 #endif /* USE_X_TOOLKIT */
3142 #if 0 /* MAC_TODO */
3144 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3145 CMAP. If an exact match can't be allocated, try the nearest color
3146 available. Value is non-zero if successful. Set *COLOR to the
3147 color allocated. */
3150 x_alloc_nearest_color (f, cmap, color)
3151 struct frame *f;
3152 Colormap cmap;
3153 XColor *color;
3155 Display *display = FRAME_X_DISPLAY (f);
3156 Screen *screen = FRAME_X_SCREEN (f);
3157 int rc;
3159 gamma_correct (f, color);
3160 rc = XAllocColor (display, cmap, color);
3161 if (rc == 0)
3163 /* If we got to this point, the colormap is full, so we're going
3164 to try to get the next closest color. The algorithm used is
3165 a least-squares matching, which is what X uses for closest
3166 color matching with StaticColor visuals. */
3167 int nearest, i;
3168 unsigned long nearest_delta = ~0;
3169 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3170 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3172 for (i = 0; i < ncells; ++i)
3173 cells[i].pixel = i;
3174 XQueryColors (display, cmap, cells, ncells);
3176 for (nearest = i = 0; i < ncells; ++i)
3178 long dred = (color->red >> 8) - (cells[i].red >> 8);
3179 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3180 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3181 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3183 if (delta < nearest_delta)
3185 nearest = i;
3186 nearest_delta = delta;
3190 color->red = cells[nearest].red;
3191 color->green = cells[nearest].green;
3192 color->blue = cells[nearest].blue;
3193 rc = XAllocColor (display, cmap, color);
3196 #ifdef DEBUG_X_COLORS
3197 if (rc)
3198 register_color (color->pixel);
3199 #endif /* DEBUG_X_COLORS */
3201 return rc;
3205 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3206 It's necessary to do this instead of just using PIXEL directly to
3207 get color reference counts right. */
3209 unsigned long
3210 x_copy_color (f, pixel)
3211 struct frame *f;
3212 unsigned long pixel;
3214 XColor color;
3216 color.pixel = pixel;
3217 BLOCK_INPUT;
3218 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3219 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3220 UNBLOCK_INPUT;
3221 #ifdef DEBUG_X_COLORS
3222 register_color (pixel);
3223 #endif
3224 return color.pixel;
3228 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3229 It's necessary to do this instead of just using PIXEL directly to
3230 get color reference counts right. */
3232 unsigned long
3233 x_copy_dpy_color (dpy, cmap, pixel)
3234 Display *dpy;
3235 Colormap cmap;
3236 unsigned long pixel;
3238 XColor color;
3240 color.pixel = pixel;
3241 BLOCK_INPUT;
3242 XQueryColor (dpy, cmap, &color);
3243 XAllocColor (dpy, cmap, &color);
3244 UNBLOCK_INPUT;
3245 #ifdef DEBUG_X_COLORS
3246 register_color (pixel);
3247 #endif
3248 return color.pixel;
3251 #endif /* MAC_TODO */
3254 /* Brightness beyond which a color won't have its highlight brightness
3255 boosted.
3257 Nominally, highlight colors for `3d' faces are calculated by
3258 brightening an object's color by a constant scale factor, but this
3259 doesn't yield good results for dark colors, so for colors who's
3260 brightness is less than this value (on a scale of 0-255) have to
3261 use an additional additive factor.
3263 The value here is set so that the default menu-bar/mode-line color
3264 (grey75) will not have its highlights changed at all. */
3265 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3268 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3269 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3270 If this produces the same color as COLOR, try a color where all RGB
3271 values have DELTA added. Return the allocated color in *COLOR.
3272 DISPLAY is the X display, CMAP is the colormap to operate on.
3273 Value is non-zero if successful. */
3275 static int
3276 mac_alloc_lighter_color (f, color, factor, delta)
3277 struct frame *f;
3278 unsigned long *color;
3279 double factor;
3280 int delta;
3282 unsigned long new;
3283 long bright;
3285 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3286 delta /= 256;
3288 /* Change RGB values by specified FACTOR. Avoid overflow! */
3289 xassert (factor >= 0);
3290 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3291 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3292 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3294 /* Calculate brightness of COLOR. */
3295 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
3296 + BLUE_FROM_ULONG (*color)) / 6;
3298 /* We only boost colors that are darker than
3299 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3300 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3301 /* Make an additive adjustment to NEW, because it's dark enough so
3302 that scaling by FACTOR alone isn't enough. */
3304 /* How far below the limit this color is (0 - 1, 1 being darker). */
3305 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3306 /* The additive adjustment. */
3307 int min_delta = delta * dimness * factor / 2;
3309 if (factor < 1)
3310 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
3311 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
3312 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
3313 else
3314 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
3315 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
3316 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
3319 if (new == *color)
3320 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3321 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3322 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3324 /* MAC_TODO: Map to palette and retry with delta if same? */
3325 /* MAC_TODO: Free colors (if using palette)? */
3327 if (new == *color)
3328 return 0;
3330 *color = new;
3332 return 1;
3336 /* Set up the foreground color for drawing relief lines of glyph
3337 string S. RELIEF is a pointer to a struct relief containing the GC
3338 with which lines will be drawn. Use a color that is FACTOR or
3339 DELTA lighter or darker than the relief's background which is found
3340 in S->f->output_data.x->relief_background. If such a color cannot
3341 be allocated, use DEFAULT_PIXEL, instead. */
3343 static void
3344 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3345 struct frame *f;
3346 struct relief *relief;
3347 double factor;
3348 int delta;
3349 unsigned long default_pixel;
3351 XGCValues xgcv;
3352 struct mac_output *di = f->output_data.mac;
3353 unsigned long mask = GCForeground;
3354 unsigned long pixel;
3355 unsigned long background = di->relief_background;
3356 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3358 /* MAC_TODO: Free colors (if using palette)? */
3360 /* Allocate new color. */
3361 xgcv.foreground = default_pixel;
3362 pixel = background;
3363 if (dpyinfo->n_planes != 1
3364 && mac_alloc_lighter_color (f, &pixel, factor, delta))
3366 relief->allocated_p = 1;
3367 xgcv.foreground = relief->pixel = pixel;
3370 if (relief->gc == 0)
3372 #if 0 /* MAC_TODO: stipple */
3373 xgcv.stipple = dpyinfo->gray;
3374 mask |= GCStipple;
3375 #endif
3376 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3378 else
3379 XChangeGC (NULL, relief->gc, mask, &xgcv);
3383 /* Set up colors for the relief lines around glyph string S. */
3385 static void
3386 x_setup_relief_colors (s)
3387 struct glyph_string *s;
3389 struct mac_output *di = s->f->output_data.mac;
3390 unsigned long color;
3392 if (s->face->use_box_color_for_shadows_p)
3393 color = s->face->box_color;
3394 else if (s->first_glyph->type == IMAGE_GLYPH
3395 && s->img->pixmap
3396 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3397 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3398 else
3400 XGCValues xgcv;
3402 /* Get the background color of the face. */
3403 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3404 color = xgcv.background;
3407 if (di->white_relief.gc == 0
3408 || color != di->relief_background)
3410 di->relief_background = color;
3411 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3412 WHITE_PIX_DEFAULT (s->f));
3413 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3414 BLACK_PIX_DEFAULT (s->f));
3419 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3420 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3421 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3422 relief. LEFT_P non-zero means draw a relief on the left side of
3423 the rectangle. RIGHT_P non-zero means draw a relief on the right
3424 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3425 when drawing. */
3427 static void
3428 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3429 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
3430 struct frame *f;
3431 int left_x, top_y, right_x, bottom_y, width;
3432 int top_p, bot_p, left_p, right_p, raised_p;
3433 Rect *clip_rect;
3435 Display *dpy = FRAME_MAC_DISPLAY (f);
3436 int i;
3437 GC gc;
3439 if (raised_p)
3440 gc = f->output_data.mac->white_relief.gc;
3441 else
3442 gc = f->output_data.mac->black_relief.gc;
3443 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3445 /* Top. */
3446 if (top_p)
3447 for (i = 0; i < width; ++i)
3448 mac_draw_line (f, gc,
3449 left_x + i * left_p, top_y + i,
3450 right_x + 1 - i * right_p, top_y + i);
3452 /* Left. */
3453 if (left_p)
3454 for (i = 0; i < width; ++i)
3455 mac_draw_line (f, gc,
3456 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3458 mac_reset_clip_rectangles (dpy, gc);
3459 if (raised_p)
3460 gc = f->output_data.mac->black_relief.gc;
3461 else
3462 gc = f->output_data.mac->white_relief.gc;
3463 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3465 /* Bottom. */
3466 if (bot_p)
3467 for (i = 0; i < width; ++i)
3468 mac_draw_line (f, gc,
3469 left_x + i * left_p, bottom_y - i,
3470 right_x + 1 - i * right_p, bottom_y - i);
3472 /* Right. */
3473 if (right_p)
3474 for (i = 0; i < width; ++i)
3475 mac_draw_line (f, gc,
3476 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3478 mac_reset_clip_rectangles (dpy, gc);
3482 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3483 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3484 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3485 left side of the rectangle. RIGHT_P non-zero means draw a line
3486 on the right side of the rectangle. CLIP_RECT is the clipping
3487 rectangle to use when drawing. */
3489 static void
3490 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3491 left_p, right_p, clip_rect)
3492 struct glyph_string *s;
3493 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3494 Rect *clip_rect;
3496 XGCValues xgcv;
3498 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3499 XSetForeground (s->display, s->gc, s->face->box_color);
3500 mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1);
3502 /* Top. */
3503 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3504 right_x - left_x + 1, width);
3506 /* Left. */
3507 if (left_p)
3508 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3509 width, bottom_y - top_y + 1);
3511 /* Bottom. */
3512 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
3513 right_x - left_x + 1, width);
3515 /* Right. */
3516 if (right_p)
3517 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
3518 top_y, width, bottom_y - top_y + 1);
3520 XSetForeground (s->display, s->gc, xgcv.foreground);
3521 mac_reset_clip_rectangles (s->display, s->gc);
3525 /* Draw a box around glyph string S. */
3527 static void
3528 x_draw_glyph_string_box (s)
3529 struct glyph_string *s;
3531 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3532 int left_p, right_p;
3533 struct glyph *last_glyph;
3534 Rect clip_rect;
3536 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3537 ? WINDOW_RIGHT_EDGE_X (s->w)
3538 : window_box_right (s->w, s->area));
3540 /* The glyph that may have a right box line. */
3541 last_glyph = (s->cmp || s->img
3542 ? s->first_glyph
3543 : s->first_glyph + s->nchars - 1);
3545 width = eabs (s->face->box_line_width);
3546 raised_p = s->face->box == FACE_RAISED_BOX;
3547 left_x = s->x;
3548 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3549 ? last_x - 1
3550 : min (last_x, s->x + s->background_width) - 1);
3551 top_y = s->y;
3552 bottom_y = top_y + s->height - 1;
3554 left_p = (s->first_glyph->left_box_line_p
3555 || (s->hl == DRAW_MOUSE_FACE
3556 && (s->prev == NULL
3557 || s->prev->hl != s->hl)));
3558 right_p = (last_glyph->right_box_line_p
3559 || (s->hl == DRAW_MOUSE_FACE
3560 && (s->next == NULL
3561 || s->next->hl != s->hl)));
3563 get_glyph_string_clip_rect (s, &clip_rect);
3565 if (s->face->box == FACE_SIMPLE_BOX)
3566 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3567 left_p, right_p, &clip_rect);
3568 else
3570 x_setup_relief_colors (s);
3571 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3572 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
3577 /* Draw foreground of image glyph string S. */
3579 static void
3580 x_draw_image_foreground (s)
3581 struct glyph_string *s;
3583 int x = s->x;
3584 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3586 /* If first glyph of S has a left box line, start drawing it to the
3587 right of that line. */
3588 if (s->face->box != FACE_NO_BOX
3589 && s->first_glyph->left_box_line_p
3590 && s->slice.x == 0)
3591 x += eabs (s->face->box_line_width);
3593 /* If there is a margin around the image, adjust x- and y-position
3594 by that margin. */
3595 if (s->slice.x == 0)
3596 x += s->img->hmargin;
3597 if (s->slice.y == 0)
3598 y += s->img->vmargin;
3600 if (s->img->pixmap)
3602 x_set_glyph_string_clipping (s);
3604 #if USE_CG_DRAWING
3605 mac_draw_cg_image (s->img->data.ptr_val,
3606 s->f, s->gc, s->slice.x, s->slice.y,
3607 s->slice.width, s->slice.height, x, y, 1);
3608 #endif
3609 if (s->img->mask)
3610 #if !USE_CG_DRAWING
3611 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3612 s->f, s->gc, s->slice.x, s->slice.y,
3613 s->slice.width, s->slice.height, x, y);
3614 #else
3616 #endif
3617 else
3619 #if !USE_CG_DRAWING
3620 mac_copy_area (s->img->pixmap,
3621 s->f, s->gc, s->slice.x, s->slice.y,
3622 s->slice.width, s->slice.height, x, y);
3623 #endif
3625 /* When the image has a mask, we can expect that at
3626 least part of a mouse highlight or a block cursor will
3627 be visible. If the image doesn't have a mask, make
3628 a block cursor visible by drawing a rectangle around
3629 the image. I believe it's looking better if we do
3630 nothing here for mouse-face. */
3631 if (s->hl == DRAW_CURSOR)
3633 int r = s->img->relief;
3634 if (r < 0) r = -r;
3635 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
3636 s->slice.width + r*2 - 1,
3637 s->slice.height + r*2 - 1);
3641 else
3642 /* Draw a rectangle if image could not be loaded. */
3643 mac_draw_rectangle (s->f, s->gc, x, y,
3644 s->slice.width - 1, s->slice.height - 1);
3648 /* Draw a relief around the image glyph string S. */
3650 static void
3651 x_draw_image_relief (s)
3652 struct glyph_string *s;
3654 int x0, y0, x1, y1, thick, raised_p;
3655 Rect r;
3656 int x = s->x;
3657 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3659 /* If first glyph of S has a left box line, start drawing it to the
3660 right of that line. */
3661 if (s->face->box != FACE_NO_BOX
3662 && s->first_glyph->left_box_line_p
3663 && s->slice.x == 0)
3664 x += eabs (s->face->box_line_width);
3666 /* If there is a margin around the image, adjust x- and y-position
3667 by that margin. */
3668 if (s->slice.x == 0)
3669 x += s->img->hmargin;
3670 if (s->slice.y == 0)
3671 y += s->img->vmargin;
3673 if (s->hl == DRAW_IMAGE_SUNKEN
3674 || s->hl == DRAW_IMAGE_RAISED)
3676 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3677 raised_p = s->hl == DRAW_IMAGE_RAISED;
3679 else
3681 thick = eabs (s->img->relief);
3682 raised_p = s->img->relief > 0;
3685 x0 = x - thick;
3686 y0 = y - thick;
3687 x1 = x + s->slice.width + thick - 1;
3688 y1 = y + s->slice.height + thick - 1;
3690 x_setup_relief_colors (s);
3691 get_glyph_string_clip_rect (s, &r);
3692 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3693 s->slice.y == 0,
3694 s->slice.y + s->slice.height == s->img->height,
3695 s->slice.x == 0,
3696 s->slice.x + s->slice.width == s->img->width,
3697 &r);
3701 /* Draw part of the background of glyph string S. X, Y, W, and H
3702 give the rectangle to draw. */
3704 static void
3705 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3706 struct glyph_string *s;
3707 int x, y, w, h;
3709 #if 0 /* MAC_TODO: stipple */
3710 if (s->stippled_p)
3712 /* Fill background with a stipple pattern. */
3713 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3714 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3715 XSetFillStyle (s->display, s->gc, FillSolid);
3717 else
3718 #endif /* MAC_TODO */
3719 x_clear_glyph_string_rect (s, x, y, w, h);
3723 /* Draw image glyph string S.
3725 s->y
3726 s->x +-------------------------
3727 | s->face->box
3729 | +-------------------------
3730 | | s->img->margin
3732 | | +-------------------
3733 | | | the image
3737 static void
3738 x_draw_image_glyph_string (s)
3739 struct glyph_string *s;
3741 int x, y;
3742 int box_line_hwidth = eabs (s->face->box_line_width);
3743 int box_line_vwidth = max (s->face->box_line_width, 0);
3744 int height;
3746 height = s->height - 2 * box_line_vwidth;
3749 /* Fill background with face under the image. Do it only if row is
3750 taller than image or if image has a clip mask to reduce
3751 flickering. */
3752 s->stippled_p = s->face->stipple != 0;
3753 if (height > s->slice.height
3754 || s->img->hmargin
3755 || s->img->vmargin
3756 || s->img->mask
3757 || s->img->pixmap == 0
3758 || s->width != s->background_width)
3760 x = s->x;
3761 if (s->first_glyph->left_box_line_p
3762 && s->slice.x == 0)
3763 x += box_line_hwidth;
3765 y = s->y;
3766 if (s->slice.y == 0)
3767 y += box_line_vwidth;
3769 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3771 s->background_filled_p = 1;
3774 /* Draw the foreground. */
3775 x_draw_image_foreground (s);
3777 /* If we must draw a relief around the image, do it. */
3778 if (s->img->relief
3779 || s->hl == DRAW_IMAGE_RAISED
3780 || s->hl == DRAW_IMAGE_SUNKEN)
3781 x_draw_image_relief (s);
3785 /* Draw stretch glyph string S. */
3787 static void
3788 x_draw_stretch_glyph_string (s)
3789 struct glyph_string *s;
3791 xassert (s->first_glyph->type == STRETCH_GLYPH);
3793 if (s->hl == DRAW_CURSOR
3794 && !x_stretch_cursor_p)
3796 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3797 as wide as the stretch glyph. */
3798 int width, background_width = s->background_width;
3799 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3801 if (x < left_x)
3803 background_width -= left_x - x;
3804 x = left_x;
3806 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3808 /* Draw cursor. */
3809 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3811 /* Clear rest using the GC of the original non-cursor face. */
3812 if (width < background_width)
3814 int y = s->y;
3815 int w = background_width - width, h = s->height;
3816 Rect r;
3817 GC gc;
3819 x += width;
3820 if (s->row->mouse_face_p
3821 && cursor_in_mouse_face_p (s->w))
3823 x_set_mouse_face_gc (s);
3824 gc = s->gc;
3826 else
3827 gc = s->face->gc;
3829 get_glyph_string_clip_rect (s, &r);
3830 mac_set_clip_rectangles (s->display, gc, &r, 1);
3832 #if 0 /* MAC_TODO: stipple */
3833 if (s->face->stipple)
3835 /* Fill background with a stipple pattern. */
3836 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3837 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3838 XSetFillStyle (s->display, gc, FillSolid);
3840 else
3841 #endif /* MAC_TODO */
3842 mac_erase_rectangle (s->f, gc, x, y, w, h);
3845 else if (!s->background_filled_p)
3847 int background_width = s->background_width;
3848 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3850 /* Don't draw into left margin, fringe or scrollbar area
3851 except for header line and mode line. */
3852 if (x < left_x && !s->row->mode_line_p)
3854 background_width -= left_x - x;
3855 x = left_x;
3857 if (background_width > 0)
3858 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3861 s->background_filled_p = 1;
3865 /* Draw glyph string S. */
3867 static void
3868 x_draw_glyph_string (s)
3869 struct glyph_string *s;
3871 int relief_drawn_p = 0;
3873 /* If S draws into the background of its successor that does not
3874 draw a cursor, draw the background of the successor first so that
3875 S can draw into it. This makes S->next use XDrawString instead
3876 of XDrawImageString. */
3877 if (s->next && s->right_overhang && !s->for_overlaps
3878 && s->next->hl != DRAW_CURSOR)
3880 xassert (s->next->img == NULL);
3881 x_set_glyph_string_gc (s->next);
3882 x_set_glyph_string_clipping (s->next);
3883 x_draw_glyph_string_background (s->next, 1);
3886 /* Set up S->gc, set clipping and draw S. */
3887 x_set_glyph_string_gc (s);
3889 /* Draw relief (if any) in advance for char/composition so that the
3890 glyph string can be drawn over it. */
3891 if (!s->for_overlaps
3892 && s->face->box != FACE_NO_BOX
3893 && (s->first_glyph->type == CHAR_GLYPH
3894 || s->first_glyph->type == COMPOSITE_GLYPH))
3897 x_set_glyph_string_clipping (s);
3898 x_draw_glyph_string_background (s, 1);
3899 x_draw_glyph_string_box (s);
3900 x_set_glyph_string_clipping (s);
3901 relief_drawn_p = 1;
3903 else
3904 x_set_glyph_string_clipping (s);
3906 switch (s->first_glyph->type)
3908 case IMAGE_GLYPH:
3909 x_draw_image_glyph_string (s);
3910 break;
3912 case STRETCH_GLYPH:
3913 x_draw_stretch_glyph_string (s);
3914 break;
3916 case CHAR_GLYPH:
3917 if (s->for_overlaps)
3918 s->background_filled_p = 1;
3919 else
3920 x_draw_glyph_string_background (s, 0);
3921 x_draw_glyph_string_foreground (s);
3922 break;
3924 case COMPOSITE_GLYPH:
3925 if (s->for_overlaps || s->gidx > 0)
3926 s->background_filled_p = 1;
3927 else
3928 x_draw_glyph_string_background (s, 1);
3929 x_draw_composite_glyph_string_foreground (s);
3930 break;
3932 default:
3933 abort ();
3936 if (!s->for_overlaps)
3938 /* Draw underline. */
3939 if (s->face->underline_p)
3941 unsigned long tem, h;
3942 int y;
3944 #if 0
3945 /* Get the underline thickness. Default is 1 pixel. */
3946 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3947 #endif
3948 h = 1;
3950 y = s->y + s->height - h;
3951 if (!x_underline_at_descent_line)
3953 /* Get the underline position. This is the recommended
3954 vertical offset in pixels from the baseline to the top of
3955 the underline. This is a signed value according to the
3956 specs, and its default is
3958 ROUND ((maximum descent) / 2), with
3959 ROUND(x) = floor (x + 0.5) */
3961 #if 0
3962 if (x_use_underline_position_properties
3963 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
3964 y = s->ybase + (long) tem;
3965 else
3966 #endif
3967 if (s->face->font)
3968 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
3971 if (s->face->underline_defaulted_p)
3972 mac_fill_rectangle (s->f, s->gc, s->x, y,
3973 s->background_width, h);
3974 else
3976 XGCValues xgcv;
3977 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3978 XSetForeground (s->display, s->gc, s->face->underline_color);
3979 mac_fill_rectangle (s->f, s->gc, s->x, y,
3980 s->background_width, h);
3981 XSetForeground (s->display, s->gc, xgcv.foreground);
3985 /* Draw overline. */
3986 if (s->face->overline_p)
3988 unsigned long dy = 0, h = 1;
3990 if (s->face->overline_color_defaulted_p)
3991 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3992 s->background_width, h);
3993 else
3995 XGCValues xgcv;
3996 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3997 XSetForeground (s->display, s->gc, s->face->overline_color);
3998 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3999 s->background_width, h);
4000 XSetForeground (s->display, s->gc, xgcv.foreground);
4004 /* Draw strike-through. */
4005 if (s->face->strike_through_p)
4007 unsigned long h = 1;
4008 unsigned long dy = (s->height - h) / 2;
4010 if (s->face->strike_through_color_defaulted_p)
4011 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
4012 s->width, h);
4013 else
4015 XGCValues xgcv;
4016 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4017 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4018 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
4019 s->width, h);
4020 XSetForeground (s->display, s->gc, xgcv.foreground);
4024 /* Draw relief if not yet drawn. */
4025 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4026 x_draw_glyph_string_box (s);
4029 /* Reset clipping. */
4030 mac_reset_clip_rectangles (s->display, s->gc);
4033 /* Shift display to make room for inserted glyphs. */
4035 void
4036 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
4037 struct frame *f;
4038 int x, y, width, height, shift_by;
4040 mac_scroll_area (f, f->output_data.mac->normal_gc,
4041 x, y, width, height,
4042 x + shift_by, y);
4045 /* Delete N glyphs at the nominal cursor position. Not implemented
4046 for X frames. */
4048 static void
4049 x_delete_glyphs (n)
4050 register int n;
4052 abort ();
4056 /* Clear entire frame. If updating_frame is non-null, clear that
4057 frame. Otherwise clear the selected frame. */
4059 static void
4060 x_clear_frame (struct frame *f)
4062 /* Clearing the frame will erase any cursor, so mark them all as no
4063 longer visible. */
4064 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4065 output_cursor.hpos = output_cursor.vpos = 0;
4066 output_cursor.x = -1;
4068 /* We don't set the output cursor here because there will always
4069 follow an explicit cursor_to. */
4070 BLOCK_INPUT;
4071 mac_clear_window (f);
4073 /* We have to clear the scroll bars, too. If we have changed
4074 colors or something like that, then they should be notified. */
4075 x_scroll_bar_clear (f);
4077 XFlush (FRAME_MAC_DISPLAY (f));
4078 UNBLOCK_INPUT;
4083 /* Invert the middle quarter of the frame for .15 sec. */
4085 /* We use the select system call to do the waiting, so we have to make
4086 sure it's available. If it isn't, we just won't do visual bells. */
4088 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4091 /* Subtract the `struct timeval' values X and Y, storing the result in
4092 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4094 static int
4095 timeval_subtract (result, x, y)
4096 struct timeval *result, x, y;
4098 /* Perform the carry for the later subtraction by updating y. This
4099 is safer because on some systems the tv_sec member is unsigned. */
4100 if (x.tv_usec < y.tv_usec)
4102 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4103 y.tv_usec -= 1000000 * nsec;
4104 y.tv_sec += nsec;
4107 if (x.tv_usec - y.tv_usec > 1000000)
4109 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4110 y.tv_usec += 1000000 * nsec;
4111 y.tv_sec -= nsec;
4114 /* Compute the time remaining to wait. tv_usec is certainly
4115 positive. */
4116 result->tv_sec = x.tv_sec - y.tv_sec;
4117 result->tv_usec = x.tv_usec - y.tv_usec;
4119 /* Return indication of whether the result should be considered
4120 negative. */
4121 return x.tv_sec < y.tv_sec;
4124 void
4125 XTflash (f)
4126 struct frame *f;
4128 /* Get the height not including a menu bar widget. */
4129 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
4130 /* Height of each line to flash. */
4131 int flash_height = FRAME_LINE_HEIGHT (f);
4132 /* These will be the left and right margins of the rectangles. */
4133 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4134 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4136 int width;
4138 /* Don't flash the area between a scroll bar and the frame
4139 edge it is next to. */
4140 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4142 case vertical_scroll_bar_left:
4143 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4144 break;
4146 case vertical_scroll_bar_right:
4147 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4148 break;
4150 default:
4151 break;
4154 width = flash_right - flash_left;
4156 BLOCK_INPUT;
4158 /* If window is tall, flash top and bottom line. */
4159 if (height > 3 * FRAME_LINE_HEIGHT (f))
4161 mac_invert_rectangle (f, flash_left,
4162 (FRAME_INTERNAL_BORDER_WIDTH (f)
4163 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4164 width, flash_height);
4165 mac_invert_rectangle (f, flash_left,
4166 (height - flash_height
4167 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4168 width, flash_height);
4170 else
4171 /* If it is short, flash it all. */
4172 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4173 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4175 x_flush (f);
4178 struct timeval wakeup;
4180 EMACS_GET_TIME (wakeup);
4182 /* Compute time to wait until, propagating carry from usecs. */
4183 wakeup.tv_usec += 150000;
4184 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4185 wakeup.tv_usec %= 1000000;
4187 /* Keep waiting until past the time wakeup or any input gets
4188 available. */
4189 while (! detect_input_pending ())
4191 struct timeval current;
4192 struct timeval timeout;
4194 EMACS_GET_TIME (current);
4196 /* Break if result would be negative. */
4197 if (timeval_subtract (&current, wakeup, current))
4198 break;
4200 /* How long `select' should wait. */
4201 timeout.tv_sec = 0;
4202 timeout.tv_usec = 10000;
4204 /* Try to wait that long--but we might wake up sooner. */
4205 select (0, NULL, NULL, NULL, &timeout);
4209 /* If window is tall, flash top and bottom line. */
4210 if (height > 3 * FRAME_LINE_HEIGHT (f))
4212 mac_invert_rectangle (f, flash_left,
4213 (FRAME_INTERNAL_BORDER_WIDTH (f)
4214 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4215 width, flash_height);
4216 mac_invert_rectangle (f, flash_left,
4217 (height - flash_height
4218 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4219 width, flash_height);
4221 else
4222 /* If it is short, flash it all. */
4223 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4224 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4226 x_flush (f);
4228 UNBLOCK_INPUT;
4231 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4234 /* Make audible bell. */
4236 void
4237 XTring_bell ()
4239 struct frame *f = SELECTED_FRAME ();
4241 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4242 if (visible_bell)
4243 XTflash (f);
4244 else
4245 #endif
4247 BLOCK_INPUT;
4248 SysBeep (1);
4249 XFlush (FRAME_MAC_DISPLAY (f));
4250 UNBLOCK_INPUT;
4255 /* Specify how many text lines, from the top of the window,
4256 should be affected by insert-lines and delete-lines operations.
4257 This, and those operations, are used only within an update
4258 that is bounded by calls to x_update_begin and x_update_end. */
4260 static void
4261 XTset_terminal_window (n)
4262 register int n;
4264 /* This function intentionally left blank. */
4269 /***********************************************************************
4270 Line Dance
4271 ***********************************************************************/
4273 /* Perform an insert-lines or delete-lines operation, inserting N
4274 lines or deleting -N lines at vertical position VPOS. */
4276 static void
4277 x_ins_del_lines (vpos, n)
4278 int vpos, n;
4280 abort ();
4284 /* Scroll part of the display as described by RUN. */
4286 static void
4287 x_scroll_run (w, run)
4288 struct window *w;
4289 struct run *run;
4291 struct frame *f = XFRAME (w->frame);
4292 int x, y, width, height, from_y, to_y, bottom_y;
4294 /* Get frame-relative bounding box of the text display area of W,
4295 without mode lines. Include in this box the left and right
4296 fringe of W. */
4297 window_box (w, -1, &x, &y, &width, &height);
4299 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4300 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4301 bottom_y = y + height;
4303 if (to_y < from_y)
4305 /* Scrolling up. Make sure we don't copy part of the mode
4306 line at the bottom. */
4307 if (from_y + run->height > bottom_y)
4308 height = bottom_y - from_y;
4309 else
4310 height = run->height;
4312 else
4314 /* Scolling down. Make sure we don't copy over the mode line.
4315 at the bottom. */
4316 if (to_y + run->height > bottom_y)
4317 height = bottom_y - to_y;
4318 else
4319 height = run->height;
4322 BLOCK_INPUT;
4324 /* Cursor off. Will be switched on again in x_update_window_end. */
4325 updated_window = w;
4326 x_clear_cursor (w);
4328 mac_scroll_area (f, f->output_data.mac->normal_gc,
4329 x, from_y,
4330 width, height,
4331 x, to_y);
4333 UNBLOCK_INPUT;
4338 /***********************************************************************
4339 Exposure Events
4340 ***********************************************************************/
4343 static void
4344 frame_highlight (f)
4345 struct frame *f;
4347 x_update_cursor (f, 1);
4350 static void
4351 frame_unhighlight (f)
4352 struct frame *f;
4354 x_update_cursor (f, 1);
4357 /* The focus has changed. Update the frames as necessary to reflect
4358 the new situation. Note that we can't change the selected frame
4359 here, because the Lisp code we are interrupting might become confused.
4360 Each event gets marked with the frame in which it occurred, so the
4361 Lisp code can tell when the switch took place by examining the events. */
4363 static void
4364 x_new_focus_frame (dpyinfo, frame)
4365 struct x_display_info *dpyinfo;
4366 struct frame *frame;
4368 struct frame *old_focus = dpyinfo->x_focus_frame;
4370 if (frame != dpyinfo->x_focus_frame)
4372 /* Set this before calling other routines, so that they see
4373 the correct value of x_focus_frame. */
4374 dpyinfo->x_focus_frame = frame;
4376 if (old_focus && old_focus->auto_lower)
4377 x_lower_frame (old_focus);
4379 #if 0
4380 selected_frame = frame;
4381 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
4382 selected_frame);
4383 Fselect_window (selected_frame->selected_window, Qnil);
4384 choose_minibuf_frame ();
4385 #endif /* ! 0 */
4387 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4388 pending_autoraise_frame = dpyinfo->x_focus_frame;
4389 else
4390 pending_autoraise_frame = 0;
4392 #if USE_MAC_FONT_PANEL
4393 if (frame)
4394 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
4395 #endif
4398 x_frame_rehighlight (dpyinfo);
4401 /* Handle FocusIn and FocusOut state changes for FRAME.
4402 If FRAME has focus and there exists more than one frame, puts
4403 a FOCUS_IN_EVENT into *BUFP. */
4405 static void
4406 mac_focus_changed (type, dpyinfo, frame, bufp)
4407 int type;
4408 struct mac_display_info *dpyinfo;
4409 struct frame *frame;
4410 struct input_event *bufp;
4412 if (type == activeFlag)
4414 if (dpyinfo->x_focus_event_frame != frame)
4416 x_new_focus_frame (dpyinfo, frame);
4417 dpyinfo->x_focus_event_frame = frame;
4419 /* Don't stop displaying the initial startup message
4420 for a switch-frame event we don't need. */
4421 if (GC_NILP (Vterminal_frame)
4422 && GC_CONSP (Vframe_list)
4423 && !GC_NILP (XCDR (Vframe_list)))
4425 bufp->kind = FOCUS_IN_EVENT;
4426 XSETFRAME (bufp->frame_or_window, frame);
4430 else
4432 if (dpyinfo->x_focus_event_frame == frame)
4434 dpyinfo->x_focus_event_frame = 0;
4435 x_new_focus_frame (dpyinfo, 0);
4440 /* The focus may have changed. Figure out if it is a real focus change,
4441 by checking both FocusIn/Out and Enter/LeaveNotify events.
4443 Returns FOCUS_IN_EVENT event in *BUFP. */
4445 static void
4446 x_detect_focus_change (dpyinfo, event, bufp)
4447 struct mac_display_info *dpyinfo;
4448 const EventRecord *event;
4449 struct input_event *bufp;
4451 struct frame *frame;
4453 frame = mac_window_to_frame ((WindowRef) event->message);
4454 if (! frame)
4455 return;
4457 /* On Mac, this is only called from focus events, so no switch needed. */
4458 mac_focus_changed ((event->modifiers & activeFlag),
4459 dpyinfo, frame, bufp);
4463 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4465 void
4466 x_mouse_leave (dpyinfo)
4467 struct x_display_info *dpyinfo;
4469 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4472 /* The focus has changed, or we have redirected a frame's focus to
4473 another frame (this happens when a frame uses a surrogate
4474 mini-buffer frame). Shift the highlight as appropriate.
4476 The FRAME argument doesn't necessarily have anything to do with which
4477 frame is being highlighted or un-highlighted; we only use it to find
4478 the appropriate X display info. */
4480 static void
4481 XTframe_rehighlight (frame)
4482 struct frame *frame;
4484 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
4487 static void
4488 x_frame_rehighlight (dpyinfo)
4489 struct x_display_info *dpyinfo;
4491 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4493 if (dpyinfo->x_focus_frame)
4495 dpyinfo->x_highlight_frame
4496 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4497 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4498 : dpyinfo->x_focus_frame);
4499 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4501 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
4502 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4505 else
4506 dpyinfo->x_highlight_frame = 0;
4508 if (dpyinfo->x_highlight_frame != old_highlight)
4510 if (old_highlight)
4511 frame_unhighlight (old_highlight);
4512 if (dpyinfo->x_highlight_frame)
4513 frame_highlight (dpyinfo->x_highlight_frame);
4519 /* Convert a keysym to its name. */
4521 char *
4522 x_get_keysym_name (keysym)
4523 int keysym;
4525 char *value;
4527 BLOCK_INPUT;
4528 #if 0
4529 value = XKeysymToString (keysym);
4530 #else
4531 value = 0;
4532 #endif
4533 UNBLOCK_INPUT;
4535 return value;
4540 /* Function to report a mouse movement to the mainstream Emacs code.
4541 The input handler calls this.
4543 We have received a mouse movement event, which is given in *event.
4544 If the mouse is over a different glyph than it was last time, tell
4545 the mainstream emacs code by setting mouse_moved. If not, ask for
4546 another motion event, so we can check again the next time it moves. */
4548 static Point last_mouse_motion_position;
4549 static Lisp_Object last_mouse_motion_frame;
4551 static int
4552 note_mouse_movement (frame, pos)
4553 FRAME_PTR frame;
4554 Point *pos;
4556 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4557 #if TARGET_API_MAC_CARBON
4558 Rect r;
4559 #endif
4561 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4562 last_mouse_motion_position = *pos;
4563 XSETFRAME (last_mouse_motion_frame, frame);
4565 if (frame == dpyinfo->mouse_face_mouse_frame
4566 #if TARGET_API_MAC_CARBON
4567 && !PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r))
4568 #else
4569 && !PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect)
4570 #endif
4573 /* This case corresponds to LeaveNotify in X11. If we move
4574 outside the frame, then we're certainly no longer on any text
4575 in the frame. */
4576 clear_mouse_face (dpyinfo);
4577 dpyinfo->mouse_face_mouse_frame = 0;
4578 if (!dpyinfo->grabbed)
4579 FRAME_RIF (frame)->define_frame_cursor (frame,
4580 frame->output_data.mac->nontext_cursor);
4583 /* Has the mouse moved off the glyph it was on at the last sighting? */
4584 if (frame != last_mouse_glyph_frame
4585 || !PtInRect (*pos, &last_mouse_glyph))
4587 frame->mouse_moved = 1;
4588 last_mouse_scroll_bar = Qnil;
4589 note_mouse_highlight (frame, pos->h, pos->v);
4590 /* Remember which glyph we're now on. */
4591 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
4592 last_mouse_glyph_frame = frame;
4593 return 1;
4596 return 0;
4600 /************************************************************************
4601 Mouse Face
4602 ************************************************************************/
4604 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4606 static void
4607 redo_mouse_highlight ()
4609 if (!NILP (last_mouse_motion_frame)
4610 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4611 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4612 last_mouse_motion_position.h,
4613 last_mouse_motion_position.v);
4617 static struct frame *
4618 mac_focus_frame (dpyinfo)
4619 struct mac_display_info *dpyinfo;
4621 if (dpyinfo->x_focus_frame)
4622 return dpyinfo->x_focus_frame;
4623 else
4624 /* Mac version may get events, such as a menu bar click, even when
4625 all the frames are invisible. In this case, we regard the
4626 event came to the selected frame. */
4627 return SELECTED_FRAME ();
4631 /* Return the current position of the mouse.
4632 *FP should be a frame which indicates which display to ask about.
4634 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4635 and *PART to the frame, window, and scroll bar part that the mouse
4636 is over. Set *X and *Y to the portion and whole of the mouse's
4637 position on the scroll bar.
4639 If the mouse movement started elsewhere, set *FP to the frame the
4640 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4641 the mouse is over.
4643 Set *TIME to the server time-stamp for the time at which the mouse
4644 was at this position.
4646 Don't store anything if we don't have a valid set of values to report.
4648 This clears the mouse_moved flag, so we can wait for the next mouse
4649 movement. */
4651 static void
4652 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4653 FRAME_PTR *fp;
4654 int insist;
4655 Lisp_Object *bar_window;
4656 enum scroll_bar_part *part;
4657 Lisp_Object *x, *y;
4658 unsigned long *time;
4660 FRAME_PTR f1;
4662 BLOCK_INPUT;
4664 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4665 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4666 else
4668 Lisp_Object frame, tail;
4670 /* Clear the mouse-moved flag for every frame on this display. */
4671 FOR_EACH_FRAME (tail, frame)
4672 XFRAME (frame)->mouse_moved = 0;
4674 last_mouse_scroll_bar = Qnil;
4676 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4677 && FRAME_LIVE_P (last_mouse_frame))
4678 f1 = last_mouse_frame;
4679 else
4680 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4682 if (f1)
4684 /* Ok, we found a frame. Store all the values.
4685 last_mouse_glyph is a rectangle used to reduce the
4686 generation of mouse events. To not miss any motion
4687 events, we must divide the frame into rectangles of the
4688 size of the smallest character that could be displayed
4689 on it, i.e. into the same rectangles that matrices on
4690 the frame are divided into. */
4691 Point mouse_pos;
4693 #if TARGET_API_MAC_CARBON
4694 GetGlobalMouse (&mouse_pos);
4695 mouse_pos.h -= f1->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f1);
4696 mouse_pos.v -= f1->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f1);
4697 #else
4698 SetPortWindowPort (FRAME_MAC_WINDOW (f1));
4699 GetMouse (&mouse_pos);
4700 #endif
4701 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4702 &last_mouse_glyph);
4703 last_mouse_glyph_frame = f1;
4705 *bar_window = Qnil;
4706 *part = 0;
4707 *fp = f1;
4708 XSETINT (*x, mouse_pos.h);
4709 XSETINT (*y, mouse_pos.v);
4710 *time = last_mouse_movement_time;
4714 UNBLOCK_INPUT;
4718 /************************************************************************
4719 Toolkit scroll bars
4720 ************************************************************************/
4722 #ifdef USE_TOOLKIT_SCROLL_BARS
4724 static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
4725 static OSStatus install_scroll_bar_timer P_ ((void));
4726 static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
4727 static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
4728 static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
4729 struct input_event *));
4730 static OSStatus get_control_part_bounds P_ ((ControlRef, ControlPartCode,
4731 Rect *));
4732 static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
4733 ControlPartCode, Point,
4734 struct input_event *));
4735 static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
4736 struct input_event *));
4737 static void x_scroll_bar_handle_drag P_ ((WindowRef, struct scroll_bar *,
4738 Point, struct input_event *));
4739 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
4740 int, int, int));
4742 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4744 static int last_scroll_bar_part;
4746 static EventLoopTimerRef scroll_bar_timer;
4748 static int scroll_bar_timer_event_posted_p;
4750 #define SCROLL_BAR_FIRST_DELAY 0.5
4751 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4753 static pascal void
4754 scroll_bar_timer_callback (timer, data)
4755 EventLoopTimerRef timer;
4756 void *data;
4758 OSStatus err;
4760 err = mac_post_mouse_moved_event ();
4761 if (err == noErr)
4762 scroll_bar_timer_event_posted_p = 1;
4765 static OSStatus
4766 install_scroll_bar_timer ()
4768 static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
4770 if (scroll_bar_timer_callbackUPP == NULL)
4771 scroll_bar_timer_callbackUPP =
4772 NewEventLoopTimerUPP (scroll_bar_timer_callback);
4774 if (scroll_bar_timer == NULL)
4775 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4776 kEventDurationForever as delays. */
4777 return
4778 InstallEventLoopTimer (GetCurrentEventLoop (),
4779 kEventDurationForever, kEventDurationForever,
4780 scroll_bar_timer_callbackUPP, NULL,
4781 &scroll_bar_timer);
4784 static OSStatus
4785 set_scroll_bar_timer (delay)
4786 EventTimerInterval delay;
4788 if (scroll_bar_timer == NULL)
4789 install_scroll_bar_timer ();
4791 scroll_bar_timer_event_posted_p = 0;
4793 return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
4796 static int
4797 control_part_code_to_scroll_bar_part (part_code)
4798 ControlPartCode part_code;
4800 switch (part_code)
4802 case kControlUpButtonPart: return scroll_bar_up_arrow;
4803 case kControlDownButtonPart: return scroll_bar_down_arrow;
4804 case kControlPageUpPart: return scroll_bar_above_handle;
4805 case kControlPageDownPart: return scroll_bar_below_handle;
4806 case kControlIndicatorPart: return scroll_bar_handle;
4809 return -1;
4812 static void
4813 construct_scroll_bar_click (bar, part, bufp)
4814 struct scroll_bar *bar;
4815 int part;
4816 struct input_event *bufp;
4818 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4819 bufp->frame_or_window = bar->window;
4820 bufp->arg = Qnil;
4821 bufp->part = part;
4822 bufp->code = 0;
4823 XSETINT (bufp->x, 0);
4824 XSETINT (bufp->y, 0);
4825 bufp->modifiers = 0;
4828 static OSStatus
4829 get_control_part_bounds (ch, part_code, rect)
4830 ControlRef ch;
4831 ControlPartCode part_code;
4832 Rect *rect;
4834 RgnHandle region = NewRgn ();
4835 OSStatus err;
4837 err = GetControlRegion (ch, part_code, region);
4838 if (err == noErr)
4839 GetRegionBounds (region, rect);
4840 DisposeRgn (region);
4842 return err;
4845 static void
4846 x_scroll_bar_handle_press (bar, part_code, mouse_pos, bufp)
4847 struct scroll_bar *bar;
4848 ControlPartCode part_code;
4849 Point mouse_pos;
4850 struct input_event *bufp;
4852 int part = control_part_code_to_scroll_bar_part (part_code);
4854 if (part < 0)
4855 return;
4857 if (part != scroll_bar_handle)
4859 construct_scroll_bar_click (bar, part, bufp);
4860 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), part_code);
4861 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
4862 bar->dragging = Qnil;
4864 else
4866 Rect r;
4868 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar),
4869 kControlIndicatorPart, &r);
4870 XSETINT (bar->dragging, - (mouse_pos.v - r.top) - 1);
4873 last_scroll_bar_part = part;
4874 tracked_scroll_bar = bar;
4877 static void
4878 x_scroll_bar_handle_release (bar, bufp)
4879 struct scroll_bar *bar;
4880 struct input_event *bufp;
4882 if (last_scroll_bar_part != scroll_bar_handle
4883 || (INTEGERP (bar->dragging) && XINT (bar->dragging) >= 0))
4884 construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
4886 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), 0);
4887 set_scroll_bar_timer (kEventDurationForever);
4889 last_scroll_bar_part = -1;
4890 bar->dragging = Qnil;
4891 tracked_scroll_bar = NULL;
4894 static void
4895 x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
4896 WindowRef win;
4897 struct scroll_bar *bar;
4898 Point mouse_pos;
4899 struct input_event *bufp;
4901 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
4903 if (last_scroll_bar_part == scroll_bar_handle)
4905 int top, top_range;
4906 Rect r;
4908 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar),
4909 kControlIndicatorPart, &r);
4911 if (INTEGERP (bar->dragging) && XINT (bar->dragging) < 0)
4912 XSETINT (bar->dragging, - (XINT (bar->dragging) + 1));
4914 top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
4915 top_range = XINT (bar->track_height) - XINT (bar->min_handle);
4917 if (top < 0)
4918 top = 0;
4919 if (top > top_range)
4920 top = top_range;
4922 construct_scroll_bar_click (bar, scroll_bar_handle, bufp);
4923 XSETINT (bufp->x, top);
4924 XSETINT (bufp->y, top_range);
4926 else
4928 ControlPartCode part_code;
4929 int unhilite_p = 0, part;
4931 if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
4932 unhilite_p = 1;
4933 else
4935 part = control_part_code_to_scroll_bar_part (part_code);
4937 switch (last_scroll_bar_part)
4939 case scroll_bar_above_handle:
4940 case scroll_bar_below_handle:
4941 if (part != scroll_bar_above_handle
4942 && part != scroll_bar_below_handle)
4943 unhilite_p = 1;
4944 break;
4946 case scroll_bar_up_arrow:
4947 case scroll_bar_down_arrow:
4948 if (part != scroll_bar_up_arrow
4949 && part != scroll_bar_down_arrow)
4950 unhilite_p = 1;
4951 break;
4955 if (unhilite_p)
4956 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), 0);
4957 else if (part != last_scroll_bar_part
4958 || scroll_bar_timer_event_posted_p)
4960 construct_scroll_bar_click (bar, part, bufp);
4961 last_scroll_bar_part = part;
4962 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), part_code);
4963 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
4968 /* Set the thumb size and position of scroll bar BAR. We are currently
4969 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4971 static void
4972 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4973 struct scroll_bar *bar;
4974 int portion, position, whole;
4976 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
4977 int value, viewsize, maximum;
4979 if (XINT (bar->track_height) == 0)
4980 return;
4982 if (whole <= portion)
4983 value = 0, viewsize = 1, maximum = 0;
4984 else
4986 float scale;
4988 maximum = XINT (bar->track_height) - XINT (bar->min_handle);
4989 scale = (float) maximum / (whole - portion);
4990 value = position * scale + 0.5f;
4991 viewsize = (int) (portion * scale + 0.5f) + XINT (bar->min_handle);
4994 BLOCK_INPUT;
4996 if (GetControlViewSize (ch) != viewsize
4997 || GetControl32BitValue (ch) != value
4998 || GetControl32BitMaximum (ch) != maximum)
5000 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5001 SetControlVisibility (ch, false, false);
5003 SetControl32BitMaximum (ch, maximum);
5004 SetControl32BitValue (ch, value);
5005 SetControlViewSize (ch, viewsize);
5007 SetControlVisibility (ch, true, true);
5010 UNBLOCK_INPUT;
5013 #endif /* USE_TOOLKIT_SCROLL_BARS */
5017 /************************************************************************
5018 Scroll bars, general
5019 ************************************************************************/
5021 /* Create a scroll bar and return the scroll bar vector for it. W is
5022 the Emacs window on which to create the scroll bar. TOP, LEFT,
5023 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5024 scroll bar. */
5026 static struct scroll_bar *
5027 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
5028 struct window *w;
5029 int top, left, width, height, disp_top, disp_height;
5031 struct frame *f = XFRAME (w->frame);
5032 struct scroll_bar *bar
5033 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
5034 Rect r;
5035 ControlRef ch;
5037 BLOCK_INPUT;
5039 r.left = left;
5040 r.top = disp_top;
5041 r.right = left + width;
5042 r.bottom = disp_top + disp_height;
5044 #if USE_CG_DRAWING
5045 mac_prepare_for_quickdraw (f);
5046 #endif
5047 #if TARGET_API_MAC_CARBON
5048 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
5049 #ifdef USE_TOOLKIT_SCROLL_BARS
5050 false,
5051 #else
5052 width < disp_height,
5053 #endif
5054 0, 0, 0, kControlScrollBarProc, (long) bar);
5055 #else
5056 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
5057 0, 0, 0, scrollBarProc, (long) bar);
5058 #endif
5059 SET_SCROLL_BAR_CONTROL_REF (bar, ch);
5061 XSETWINDOW (bar->window, w);
5062 XSETINT (bar->top, top);
5063 XSETINT (bar->left, left);
5064 XSETINT (bar->width, width);
5065 XSETINT (bar->height, height);
5066 XSETINT (bar->start, 0);
5067 XSETINT (bar->end, 0);
5068 bar->dragging = Qnil;
5069 #ifdef MAC_OSX
5070 bar->fringe_extended_p = Qnil;
5071 #endif
5072 #ifdef USE_TOOLKIT_SCROLL_BARS
5073 bar->track_top = Qnil;
5074 bar->track_height = Qnil;
5075 bar->min_handle = Qnil;
5076 #endif
5078 /* Add bar to its frame's list of scroll bars. */
5079 bar->next = FRAME_SCROLL_BARS (f);
5080 bar->prev = Qnil;
5081 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5082 if (!NILP (bar->next))
5083 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5085 UNBLOCK_INPUT;
5086 return bar;
5090 /* Draw BAR's handle in the proper position.
5092 If the handle is already drawn from START to END, don't bother
5093 redrawing it, unless REBUILD is non-zero; in that case, always
5094 redraw it. (REBUILD is handy for drawing the handle after expose
5095 events.)
5097 Normally, we want to constrain the start and end of the handle to
5098 fit inside its rectangle, but if the user is dragging the scroll
5099 bar handle, we want to let them drag it down all the way, so that
5100 the bar's top is as far down as it goes; otherwise, there's no way
5101 to move to the very end of the buffer. */
5103 #ifndef USE_TOOLKIT_SCROLL_BARS
5105 static void
5106 x_scroll_bar_set_handle (bar, start, end, rebuild)
5107 struct scroll_bar *bar;
5108 int start, end;
5109 int rebuild;
5111 int dragging = ! NILP (bar->dragging);
5112 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
5113 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5114 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5115 int length = end - start;
5117 /* If the display is already accurate, do nothing. */
5118 if (! rebuild
5119 && start == XINT (bar->start)
5120 && end == XINT (bar->end))
5121 return;
5123 BLOCK_INPUT;
5125 /* Make sure the values are reasonable, and try to preserve the
5126 distance between start and end. */
5127 if (start < 0)
5128 start = 0;
5129 else if (start > top_range)
5130 start = top_range;
5131 end = start + length;
5133 if (end < start)
5134 end = start;
5135 else if (end > top_range && ! dragging)
5136 end = top_range;
5138 /* Store the adjusted setting in the scroll bar. */
5139 XSETINT (bar->start, start);
5140 XSETINT (bar->end, end);
5142 /* Clip the end position, just for display. */
5143 if (end > top_range)
5144 end = top_range;
5146 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5147 top positions, to make sure the handle is always at least that
5148 many pixels tall. */
5149 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
5151 SetControlMinimum (ch, 0);
5152 /* Don't inadvertently activate deactivated scroll bars */
5153 if (GetControlMaximum (ch) != -1)
5154 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
5155 - (end - start));
5156 SetControlValue (ch, start);
5157 #if TARGET_API_MAC_CARBON
5158 SetControlViewSize (ch, end - start);
5159 #endif
5161 UNBLOCK_INPUT;
5164 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5166 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5167 nil. */
5169 static void
5170 x_scroll_bar_remove (bar)
5171 struct scroll_bar *bar;
5173 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5175 BLOCK_INPUT;
5177 #if USE_CG_DRAWING
5178 mac_prepare_for_quickdraw (f);
5179 #endif
5180 /* Destroy the Mac scroll bar control */
5181 DisposeControl (SCROLL_BAR_CONTROL_REF (bar));
5183 /* Disassociate this scroll bar from its window. */
5184 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5186 UNBLOCK_INPUT;
5190 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5191 that we are displaying PORTION characters out of a total of WHOLE
5192 characters, starting at POSITION. If WINDOW has no scroll bar,
5193 create one. */
5195 static void
5196 XTset_vertical_scroll_bar (w, portion, whole, position)
5197 struct window *w;
5198 int portion, whole, position;
5200 struct frame *f = XFRAME (w->frame);
5201 struct scroll_bar *bar;
5202 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
5203 int window_y, window_height;
5204 #ifdef MAC_OSX
5205 int fringe_extended_p;
5206 #endif
5208 /* Get window dimensions. */
5209 window_box (w, -1, 0, &window_y, 0, &window_height);
5210 top = window_y;
5211 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5212 height = window_height;
5214 /* Compute the left edge of the scroll bar area. */
5215 left = WINDOW_SCROLL_BAR_AREA_X (w);
5217 /* Compute the width of the scroll bar which might be less than
5218 the width of the area reserved for the scroll bar. */
5219 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
5220 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
5221 else
5222 sb_width = width;
5224 /* Compute the left edge of the scroll bar. */
5225 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5226 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
5227 else
5228 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
5230 /* Adjustments according to Inside Macintosh to make it look nice */
5231 disp_top = top;
5232 disp_height = height;
5233 #ifdef MAC_OS8
5234 if (disp_top == 0)
5236 disp_top = -1;
5237 disp_height++;
5239 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
5241 disp_top++;
5242 disp_height--;
5245 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
5246 sb_left++;
5247 #endif
5249 #ifdef MAC_OSX
5250 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
5251 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
5252 && WINDOW_LEFT_FRINGE_WIDTH (w)
5253 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5254 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
5255 else
5256 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
5257 && WINDOW_RIGHT_FRINGE_WIDTH (w)
5258 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5259 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
5260 #endif
5262 /* Does the scroll bar exist yet? */
5263 if (NILP (w->vertical_scroll_bar))
5265 BLOCK_INPUT;
5266 #ifdef MAC_OSX
5267 if (fringe_extended_p)
5268 mac_clear_area (f, sb_left, top, sb_width, height);
5269 else
5270 #endif
5271 mac_clear_area (f, left, top, width, height);
5272 UNBLOCK_INPUT;
5273 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
5274 disp_height);
5275 XSETVECTOR (w->vertical_scroll_bar, bar);
5277 else
5279 /* It may just need to be moved and resized. */
5280 ControlRef ch;
5282 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5283 ch = SCROLL_BAR_CONTROL_REF (bar);
5285 BLOCK_INPUT;
5287 /* If already correctly positioned, do nothing. */
5288 if (!(XINT (bar->left) == sb_left
5289 && XINT (bar->top) == top
5290 && XINT (bar->width) == sb_width
5291 && XINT (bar->height) == height
5292 #ifdef MAC_OSX
5293 && !NILP (bar->fringe_extended_p) == fringe_extended_p
5294 #endif
5297 /* Since toolkit scroll bars are smaller than the space reserved
5298 for them on the frame, we have to clear "under" them. */
5299 #ifdef MAC_OSX
5300 if (fringe_extended_p)
5301 mac_clear_area (f, sb_left, top, sb_width, height);
5302 else
5303 #endif
5304 mac_clear_area (f, left, top, width, height);
5306 #if USE_CG_DRAWING
5307 mac_prepare_for_quickdraw (f);
5308 #endif
5309 HideControl (ch);
5310 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
5311 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5312 disp_height);
5313 #ifndef USE_TOOLKIT_SCROLL_BARS
5314 if (sb_width < disp_height)
5315 ShowControl (ch);
5316 #endif
5318 /* Remember new settings. */
5319 XSETINT (bar->left, sb_left);
5320 XSETINT (bar->top, top);
5321 XSETINT (bar->width, sb_width);
5322 XSETINT (bar->height, height);
5323 #ifdef USE_TOOLKIT_SCROLL_BARS
5324 bar->track_top = Qnil;
5325 bar->track_height = Qnil;
5326 bar->min_handle = Qnil;
5327 #endif
5330 UNBLOCK_INPUT;
5333 #ifdef MAC_OSX
5334 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
5335 #endif
5337 #ifdef USE_TOOLKIT_SCROLL_BARS
5338 if (NILP (bar->track_top))
5340 if (sb_width >= disp_height
5341 #ifdef MAC_OSX
5342 || sb_width < MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5343 #endif
5346 XSETINT (bar->track_top, 0);
5347 XSETINT (bar->track_height, 0);
5348 XSETINT (bar->min_handle, 0);
5350 else
5352 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
5353 Rect r0, r1;
5355 BLOCK_INPUT;
5357 SetControl32BitMinimum (ch, 0);
5358 SetControl32BitMaximum (ch, 1 << 30);
5359 SetControlViewSize (ch, 1);
5361 /* Move the scroll bar thumb to the top. */
5362 SetControl32BitValue (ch, 0);
5363 get_control_part_bounds (ch, kControlIndicatorPart, &r0);
5365 /* Move the scroll bar thumb to the bottom. */
5366 SetControl32BitValue (ch, 1 << 30);
5367 get_control_part_bounds (ch, kControlIndicatorPart, &r1);
5369 UnionRect (&r0, &r1, &r0);
5370 XSETINT (bar->track_top, r0.top);
5371 XSETINT (bar->track_height, r0.bottom - r0.top);
5372 XSETINT (bar->min_handle, r1.bottom - r1.top);
5374 /* Don't show the scroll bar if its height is not enough to
5375 display the scroll bar thumb. */
5376 if (r0.bottom - r0.top > 0)
5377 ShowControl (ch);
5379 UNBLOCK_INPUT;
5383 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5384 #else /* not USE_TOOLKIT_SCROLL_BARS */
5385 /* Set the scroll bar's current state, unless we're currently being
5386 dragged. */
5387 if (NILP (bar->dragging))
5389 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5391 if (whole == 0)
5392 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5393 else
5395 int start = ((double) position * top_range) / whole;
5396 int end = ((double) (position + portion) * top_range) / whole;
5397 x_scroll_bar_set_handle (bar, start, end, 0);
5400 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5404 /* The following three hooks are used when we're doing a thorough
5405 redisplay of the frame. We don't explicitly know which scroll bars
5406 are going to be deleted, because keeping track of when windows go
5407 away is a real pain - "Can you say set-window-configuration, boys
5408 and girls?" Instead, we just assert at the beginning of redisplay
5409 that *all* scroll bars are to be removed, and then save a scroll bar
5410 from the fiery pit when we actually redisplay its window. */
5412 /* Arrange for all scroll bars on FRAME to be removed at the next call
5413 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5414 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5416 static void
5417 XTcondemn_scroll_bars (frame)
5418 FRAME_PTR frame;
5420 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5421 while (! NILP (FRAME_SCROLL_BARS (frame)))
5423 Lisp_Object bar;
5424 bar = FRAME_SCROLL_BARS (frame);
5425 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5426 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5427 XSCROLL_BAR (bar)->prev = Qnil;
5428 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5429 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5430 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5435 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5436 Note that WINDOW isn't necessarily condemned at all. */
5438 static void
5439 XTredeem_scroll_bar (window)
5440 struct window *window;
5442 struct scroll_bar *bar;
5443 struct frame *f;
5445 /* We can't redeem this window's scroll bar if it doesn't have one. */
5446 if (NILP (window->vertical_scroll_bar))
5447 abort ();
5449 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5451 /* Unlink it from the condemned list. */
5452 f = XFRAME (WINDOW_FRAME (window));
5453 if (NILP (bar->prev))
5455 /* If the prev pointer is nil, it must be the first in one of
5456 the lists. */
5457 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5458 /* It's not condemned. Everything's fine. */
5459 return;
5460 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5461 window->vertical_scroll_bar))
5462 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5463 else
5464 /* If its prev pointer is nil, it must be at the front of
5465 one or the other! */
5466 abort ();
5468 else
5469 XSCROLL_BAR (bar->prev)->next = bar->next;
5471 if (! NILP (bar->next))
5472 XSCROLL_BAR (bar->next)->prev = bar->prev;
5474 bar->next = FRAME_SCROLL_BARS (f);
5475 bar->prev = Qnil;
5476 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5477 if (! NILP (bar->next))
5478 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5481 /* Remove all scroll bars on FRAME that haven't been saved since the
5482 last call to `*condemn_scroll_bars_hook'. */
5484 static void
5485 XTjudge_scroll_bars (f)
5486 FRAME_PTR f;
5488 Lisp_Object bar, next;
5490 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5492 /* Clear out the condemned list now so we won't try to process any
5493 more events on the hapless scroll bars. */
5494 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5496 for (; ! NILP (bar); bar = next)
5498 struct scroll_bar *b = XSCROLL_BAR (bar);
5500 x_scroll_bar_remove (b);
5502 next = b->next;
5503 b->next = b->prev = Qnil;
5506 /* Now there should be no references to the condemned scroll bars,
5507 and they should get garbage-collected. */
5511 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5512 is set to something other than NO_EVENT, it is enqueued.
5514 This may be called from a signal handler, so we have to ignore GC
5515 mark bits. */
5517 static void
5518 x_scroll_bar_handle_click (bar, part_code, er, bufp)
5519 struct scroll_bar *bar;
5520 ControlPartCode part_code;
5521 const EventRecord *er;
5522 struct input_event *bufp;
5524 int win_y, top_range;
5526 if (! GC_WINDOWP (bar->window))
5527 abort ();
5529 bufp->kind = SCROLL_BAR_CLICK_EVENT;
5530 bufp->frame_or_window = bar->window;
5531 bufp->arg = Qnil;
5533 bar->dragging = Qnil;
5535 switch (part_code)
5537 case kControlUpButtonPart:
5538 bufp->part = scroll_bar_up_arrow;
5539 break;
5540 case kControlDownButtonPart:
5541 bufp->part = scroll_bar_down_arrow;
5542 break;
5543 case kControlPageUpPart:
5544 bufp->part = scroll_bar_above_handle;
5545 break;
5546 case kControlPageDownPart:
5547 bufp->part = scroll_bar_below_handle;
5548 break;
5549 #if TARGET_API_MAC_CARBON
5550 default:
5551 #else
5552 case kControlIndicatorPart:
5553 #endif
5554 if (er->what == mouseDown)
5555 bar->dragging = make_number (0);
5556 XSETVECTOR (last_mouse_scroll_bar, bar);
5557 bufp->part = scroll_bar_handle;
5558 break;
5561 win_y = XINT (bufp->y) - XINT (bar->top);
5562 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
5564 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5566 win_y -= 24;
5568 if (! NILP (bar->dragging))
5569 win_y -= XINT (bar->dragging);
5571 if (win_y < 0)
5572 win_y = 0;
5573 if (win_y > top_range)
5574 win_y = top_range;
5576 XSETINT (bufp->x, win_y);
5577 XSETINT (bufp->y, top_range);
5580 #ifndef USE_TOOLKIT_SCROLL_BARS
5582 /* Handle some mouse motion while someone is dragging the scroll bar.
5584 This may be called from a signal handler, so we have to ignore GC
5585 mark bits. */
5587 static void
5588 x_scroll_bar_note_movement (bar, y_pos, t)
5589 struct scroll_bar *bar;
5590 int y_pos;
5591 Time t;
5593 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5595 last_mouse_movement_time = t;
5597 f->mouse_moved = 1;
5598 XSETVECTOR (last_mouse_scroll_bar, bar);
5600 /* If we're dragging the bar, display it. */
5601 if (! GC_NILP (bar->dragging))
5603 /* Where should the handle be now? */
5604 int new_start = y_pos - 24;
5606 if (new_start != XINT (bar->start))
5608 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
5610 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5615 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5617 /* Return information to the user about the current position of the mouse
5618 on the scroll bar. */
5620 static void
5621 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
5622 FRAME_PTR *fp;
5623 Lisp_Object *bar_window;
5624 enum scroll_bar_part *part;
5625 Lisp_Object *x, *y;
5626 unsigned long *time;
5628 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5629 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
5630 #if TARGET_API_MAC_CARBON
5631 WindowRef wp = GetControlOwner (ch);
5632 #else
5633 WindowRef wp = (*ch)->contrlOwner;
5634 #endif
5635 Point mouse_pos;
5636 struct frame *f = mac_window_to_frame (wp);
5637 int win_y, top_range;
5639 #if TARGET_API_MAC_CARBON
5640 GetGlobalMouse (&mouse_pos);
5641 mouse_pos.h -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
5642 mouse_pos.v -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
5643 #else
5644 SetPortWindowPort (wp);
5645 GetMouse (&mouse_pos);
5646 #endif
5648 win_y = mouse_pos.v - XINT (bar->top);
5649 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5651 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5653 win_y -= 24;
5655 if (! NILP (bar->dragging))
5656 win_y -= XINT (bar->dragging);
5658 if (win_y < 0)
5659 win_y = 0;
5660 if (win_y > top_range)
5661 win_y = top_range;
5663 *fp = f;
5664 *bar_window = bar->window;
5666 if (! NILP (bar->dragging))
5667 *part = scroll_bar_handle;
5668 else if (win_y < XINT (bar->start))
5669 *part = scroll_bar_above_handle;
5670 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5671 *part = scroll_bar_handle;
5672 else
5673 *part = scroll_bar_below_handle;
5675 XSETINT (*x, win_y);
5676 XSETINT (*y, top_range);
5678 f->mouse_moved = 0;
5679 last_mouse_scroll_bar = Qnil;
5681 *time = last_mouse_movement_time;
5685 /* The screen has been cleared so we may have changed foreground or
5686 background colors, and the scroll bars may need to be redrawn.
5687 Clear out the scroll bars, and ask for expose events, so we can
5688 redraw them. */
5690 void
5691 x_scroll_bar_clear (f)
5692 FRAME_PTR f;
5694 XTcondemn_scroll_bars (f);
5695 XTjudge_scroll_bars (f);
5699 /***********************************************************************
5700 Tool-bars
5701 ***********************************************************************/
5702 #if USE_MAC_TOOLBAR
5704 /* In identifiers such as function/variable names, Emacs tool bar is
5705 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5707 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5708 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5710 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5711 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5712 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5713 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5714 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5715 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5716 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5718 static int mac_event_to_emacs_modifiers P_ ((EventRef));
5719 static void mac_handle_origin_change P_ ((struct frame *));
5720 static OSStatus mac_handle_toolbar_command_event P_ ((EventHandlerCallRef,
5721 EventRef, void *));
5723 static void
5724 mac_move_window_with_gravity (f, win_gravity, left, top)
5725 struct frame *f;
5726 int win_gravity;
5727 short left, top;
5729 Rect inner, outer;
5731 mac_get_window_bounds (f, &inner, &outer);
5733 switch (win_gravity)
5735 case NorthWestGravity:
5736 case WestGravity:
5737 case SouthWestGravity:
5738 left += inner.left - outer.left;
5739 break;
5741 case NorthGravity:
5742 case CenterGravity:
5743 case SouthGravity:
5744 left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
5745 break;
5747 case NorthEastGravity:
5748 case EastGravity:
5749 case SouthEastGravity:
5750 left += inner.right - outer.right;
5751 break;
5754 switch (win_gravity)
5756 case NorthWestGravity:
5757 case NorthGravity:
5758 case NorthEastGravity:
5759 top += inner.top - outer.top;
5760 break;
5762 case WestGravity:
5763 case CenterGravity:
5764 case EastGravity:
5765 top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
5766 break;
5768 case SouthWestGravity:
5769 case SouthGravity:
5770 case SouthEastGravity:
5771 top += inner.bottom - outer.bottom;
5772 break;
5775 MoveWindow (FRAME_MAC_WINDOW (f), left, top, false);
5778 static void
5779 mac_get_window_origin_with_gravity (f, win_gravity, left, top)
5780 struct frame *f;
5781 int win_gravity;
5782 short *left, *top;
5784 Rect inner, outer;
5786 mac_get_window_bounds (f, &inner, &outer);
5788 switch (win_gravity)
5790 case NorthWestGravity:
5791 case WestGravity:
5792 case SouthWestGravity:
5793 *left = outer.left;
5794 break;
5796 case NorthGravity:
5797 case CenterGravity:
5798 case SouthGravity:
5799 *left = outer.left + ((outer.right - outer.left)
5800 - (inner.right - inner.left)) / 2;
5801 break;
5803 case NorthEastGravity:
5804 case EastGravity:
5805 case SouthEastGravity:
5806 *left = outer.right - (inner.right - inner.left);
5807 break;
5810 switch (win_gravity)
5812 case NorthWestGravity:
5813 case NorthGravity:
5814 case NorthEastGravity:
5815 *top = outer.top;
5816 break;
5818 case WestGravity:
5819 case CenterGravity:
5820 case EastGravity:
5821 *top = outer.top + ((outer.bottom - outer.top)
5822 - (inner.bottom - inner.top)) / 2;
5823 break;
5825 case SouthWestGravity:
5826 case SouthGravity:
5827 case SouthEastGravity:
5828 *top = outer.bottom - (inner.bottom - inner.top);
5829 break;
5833 static OSStatus
5834 mac_handle_toolbar_event (next_handler, event, data)
5835 EventHandlerCallRef next_handler;
5836 EventRef event;
5837 void *data;
5839 OSStatus err, result = eventNotHandledErr;
5841 switch (GetEventKind (event))
5843 case kEventToolbarGetDefaultIdentifiers:
5844 result = noErr;
5845 break;
5847 case kEventToolbarGetAllowedIdentifiers:
5849 CFMutableArrayRef array;
5851 GetEventParameter (event, kEventParamMutableArray,
5852 typeCFMutableArrayRef, NULL,
5853 sizeof (CFMutableArrayRef), NULL, &array);
5854 CFArrayAppendValue (array, TOOLBAR_ICON_ITEM_IDENTIFIER);
5855 result = noErr;
5857 break;
5859 case kEventToolbarCreateItemWithIdentifier:
5861 CFStringRef identifier;
5862 HIToolbarItemRef item = NULL;
5864 GetEventParameter (event, kEventParamToolbarItemIdentifier,
5865 typeCFStringRef, NULL,
5866 sizeof (CFStringRef), NULL, &identifier);
5868 if (CFStringCompare (identifier, TOOLBAR_ICON_ITEM_IDENTIFIER, 0)
5869 == kCFCompareEqualTo)
5870 HIToolbarItemCreate (identifier,
5871 kHIToolbarItemAllowDuplicates
5872 | kHIToolbarItemCantBeRemoved, &item);
5874 if (item)
5876 SetEventParameter (event, kEventParamToolbarItem,
5877 typeHIToolbarItemRef,
5878 sizeof (HIToolbarItemRef), &item);
5879 result = noErr;
5882 break;
5884 default:
5885 abort ();
5888 return result;
5891 static CGImageRef
5892 mac_image_spec_to_cg_image (f, image)
5893 struct frame *f;
5894 Lisp_Object image;
5896 if (!valid_image_p (image))
5897 return NULL;
5898 else
5900 int img_id = lookup_image (f, image);
5901 struct image *img = IMAGE_FROM_ID (f, img_id);
5903 prepare_image_for_display (f, img);
5905 return img->data.ptr_val;
5909 /* Create a tool bar for frame F. */
5911 static OSStatus
5912 mac_create_frame_tool_bar (f)
5913 FRAME_PTR f;
5915 OSStatus err;
5916 HIToolbarRef toolbar;
5918 err = HIToolbarCreate (TOOLBAR_IDENTIFIER, kHIToolbarNoAttributes,
5919 &toolbar);
5920 if (err == noErr)
5922 static const EventTypeSpec specs[] =
5923 {{kEventClassToolbar, kEventToolbarGetDefaultIdentifiers},
5924 {kEventClassToolbar, kEventToolbarGetAllowedIdentifiers},
5925 {kEventClassToolbar, kEventToolbarCreateItemWithIdentifier}};
5927 err = InstallEventHandler (HIObjectGetEventTarget (toolbar),
5928 mac_handle_toolbar_event,
5929 GetEventTypeCount (specs), specs,
5930 f, NULL);
5933 if (err == noErr)
5934 err = HIToolbarSetDisplayMode (toolbar, kHIToolbarDisplayModeIconOnly);
5935 if (err == noErr)
5937 static const EventTypeSpec specs[] =
5938 {{kEventClassCommand, kEventCommandProcess}};
5940 err = InstallWindowEventHandler (FRAME_MAC_WINDOW (f),
5941 mac_handle_toolbar_command_event,
5942 GetEventTypeCount (specs),
5943 specs, f, NULL);
5945 if (err == noErr)
5946 err = SetWindowToolbar (FRAME_MAC_WINDOW (f), toolbar);
5948 if (toolbar)
5949 CFRelease (toolbar);
5951 return err;
5954 /* Update the tool bar for frame F. Add new buttons and remove old. */
5956 void
5957 update_frame_tool_bar (f)
5958 FRAME_PTR f;
5960 HIToolbarRef toolbar = NULL;
5961 short left, top;
5962 CFArrayRef old_items = NULL;
5963 CFIndex old_count;
5964 int i, pos, win_gravity = f->output_data.mac->toolbar_win_gravity;
5965 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5967 BLOCK_INPUT;
5969 GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
5970 if (toolbar == NULL)
5972 mac_create_frame_tool_bar (f);
5973 GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
5974 if (toolbar == NULL)
5975 goto out;
5976 if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
5977 mac_get_window_origin_with_gravity (f, win_gravity, &left, &top);
5980 HIToolbarCopyItems (toolbar, &old_items);
5981 if (old_items == NULL)
5982 goto out;
5984 old_count = CFArrayGetCount (old_items);
5985 pos = 0;
5986 for (i = 0; i < f->n_tool_bar_items; ++i)
5988 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5990 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
5991 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
5992 int idx;
5993 Lisp_Object image;
5994 CGImageRef cg_image;
5995 CFStringRef label;
5996 HIToolbarItemRef item;
5998 /* If image is a vector, choose the image according to the
5999 button state. */
6000 image = PROP (TOOL_BAR_ITEM_IMAGES);
6001 if (VECTORP (image))
6003 if (enabled_p)
6004 idx = (selected_p
6005 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6006 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
6007 else
6008 idx = (selected_p
6009 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6010 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
6012 xassert (ASIZE (image) >= idx);
6013 image = AREF (image, idx);
6015 else
6016 idx = -1;
6018 cg_image = mac_image_spec_to_cg_image (f, image);
6019 /* Ignore invalid image specifications. */
6020 if (cg_image == NULL)
6021 continue;
6023 label = cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION));
6024 if (label == NULL)
6025 label = CFSTR ("");
6027 if (pos < old_count)
6029 CGImageRef old_cg_image = NULL;
6030 CFStringRef old_label = NULL;
6031 Boolean old_enabled_p;
6033 item = (HIToolbarItemRef) CFArrayGetValueAtIndex (old_items, pos);
6035 HIToolbarItemCopyImage (item, &old_cg_image);
6036 if (cg_image != old_cg_image)
6037 HIToolbarItemSetImage (item, cg_image);
6038 CGImageRelease (old_cg_image);
6040 HIToolbarItemCopyLabel (item, &old_label);
6041 if (CFStringCompare (label, old_label, 0) != kCFCompareEqualTo)
6042 HIToolbarItemSetLabel (item, label);
6043 CFRelease (old_label);
6045 old_enabled_p = HIToolbarItemIsEnabled (item);
6046 if ((enabled_p || idx >= 0) != old_enabled_p)
6047 HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
6049 else
6051 item = NULL;
6052 HIToolbarCreateItemWithIdentifier (toolbar,
6053 TOOLBAR_ICON_ITEM_IDENTIFIER,
6054 NULL, &item);
6055 if (item)
6057 HIToolbarItemSetImage (item, cg_image);
6058 HIToolbarItemSetLabel (item, label);
6059 HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
6060 HIToolbarAppendItem (toolbar, item);
6061 CFRelease (item);
6065 CFRelease (label);
6066 if (item)
6068 HIToolbarItemSetCommandID (item, TOOLBAR_ITEM_MAKE_COMMAND_ID (i));
6069 pos++;
6073 CFRelease (old_items);
6075 while (pos < old_count)
6076 HIToolbarRemoveItemAtIndex (toolbar, --old_count);
6078 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), true,
6079 !win_gravity && f == mac_focus_frame (dpyinfo));
6080 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6081 toolbar visibility change. */
6082 mac_handle_origin_change (f);
6083 if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
6085 mac_move_window_with_gravity (f, win_gravity, left, top);
6086 /* If the title bar is completely outside the screen, adjust the
6087 position. */
6088 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
6089 kWindowConstrainMoveRegardlessOfFit
6090 | kWindowConstrainAllowPartial, NULL, NULL);
6091 f->output_data.mac->toolbar_win_gravity = 0;
6094 out:
6095 UNBLOCK_INPUT;
6098 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6099 doesn't deallocate the resources. */
6101 void
6102 free_frame_tool_bar (f)
6103 FRAME_PTR f;
6105 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f)))
6107 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6109 BLOCK_INPUT;
6110 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), false,
6111 (NILP (Fsymbol_value
6112 (intern ("frame-notice-user-settings")))
6113 && f == mac_focus_frame (dpyinfo)));
6114 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6115 on toolbar visibility change. */
6116 mac_handle_origin_change (f);
6117 UNBLOCK_INPUT;
6121 static void
6122 mac_tool_bar_note_mouse_movement (f, event)
6123 struct frame *f;
6124 EventRef event;
6126 OSStatus err;
6127 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6128 int mouse_down_p;
6129 HIViewRef item_view;
6130 UInt32 command_id;
6132 mouse_down_p = (dpyinfo->grabbed
6133 && f == last_mouse_frame
6134 && FRAME_LIVE_P (f));
6135 if (mouse_down_p)
6136 return;
6138 err = HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f)),
6139 event, &item_view);
6140 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6141 toolbar item view seems to have the same command ID with that of
6142 the toolbar item. */
6143 if (err == noErr)
6144 err = GetControlCommandID (item_view, &command_id);
6145 if (err == noErr && TOOLBAR_ITEM_COMMAND_ID_P (command_id))
6147 int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id);
6149 if (i < f->n_tool_bar_items)
6151 HIRect bounds;
6152 HIViewRef content_view;
6154 err = HIViewGetBounds (item_view, &bounds);
6155 if (err == noErr)
6156 err = HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f)),
6157 kHIViewWindowContentID, &content_view);
6158 if (err == noErr)
6159 err = HIViewConvertRect (&bounds, item_view, content_view);
6160 if (err == noErr)
6161 SetRect (&last_mouse_glyph,
6162 CGRectGetMinX (bounds), CGRectGetMinY (bounds),
6163 CGRectGetMaxX (bounds), CGRectGetMaxY (bounds));
6165 help_echo_object = help_echo_window = Qnil;
6166 help_echo_pos = -1;
6167 help_echo_string = PROP (TOOL_BAR_ITEM_HELP);
6168 if (NILP (help_echo_string))
6169 help_echo_string = PROP (TOOL_BAR_ITEM_CAPTION);
6174 static OSStatus
6175 mac_handle_toolbar_command_event (next_handler, event, data)
6176 EventHandlerCallRef next_handler;
6177 EventRef event;
6178 void *data;
6180 OSStatus err, result = eventNotHandledErr;
6181 struct frame *f = (struct frame *) data;
6182 HICommand command;
6184 err = GetEventParameter (event, kEventParamDirectObject,
6185 typeHICommand, NULL,
6186 sizeof (HICommand), NULL, &command);
6187 if (err != noErr)
6188 return result;
6190 switch (GetEventKind (event))
6192 case kEventCommandProcess:
6193 if (!TOOLBAR_ITEM_COMMAND_ID_P (command.commandID))
6194 result = CallNextEventHandler (next_handler, event);
6195 else
6197 int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command.commandID);
6199 if (i < f->n_tool_bar_items
6200 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)))
6202 Lisp_Object frame;
6203 struct input_event buf;
6205 EVENT_INIT (buf);
6207 XSETFRAME (frame, f);
6208 buf.kind = TOOL_BAR_EVENT;
6209 buf.frame_or_window = frame;
6210 buf.arg = frame;
6211 kbd_buffer_store_event (&buf);
6213 buf.kind = TOOL_BAR_EVENT;
6214 buf.frame_or_window = frame;
6215 buf.arg = PROP (TOOL_BAR_ITEM_KEY);
6216 buf.modifiers = mac_event_to_emacs_modifiers (event);
6217 kbd_buffer_store_event (&buf);
6219 result = noErr;
6222 break;
6224 default:
6225 abort ();
6227 #undef PROP
6229 return result;
6231 #endif /* USE_MAC_TOOLBAR */
6234 /***********************************************************************
6235 Text Cursor
6236 ***********************************************************************/
6238 /* Set clipping for output in glyph row ROW. W is the window in which
6239 we operate. GC is the graphics context to set clipping in.
6241 ROW may be a text row or, e.g., a mode line. Text rows must be
6242 clipped to the interior of the window dedicated to text display,
6243 mode lines must be clipped to the whole window. */
6245 static void
6246 x_clip_to_row (w, row, area, gc)
6247 struct window *w;
6248 struct glyph_row *row;
6249 int area;
6250 GC gc;
6252 struct frame *f = XFRAME (WINDOW_FRAME (w));
6253 Rect clip_rect;
6254 int window_x, window_y, window_width;
6256 window_box (w, area, &window_x, &window_y, &window_width, 0);
6258 clip_rect.left = window_x;
6259 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
6260 clip_rect.top = max (clip_rect.top, window_y);
6261 clip_rect.right = clip_rect.left + window_width;
6262 clip_rect.bottom = clip_rect.top + row->visible_height;
6264 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
6268 /* Draw a hollow box cursor on window W in glyph row ROW. */
6270 static void
6271 x_draw_hollow_cursor (w, row)
6272 struct window *w;
6273 struct glyph_row *row;
6275 struct frame *f = XFRAME (WINDOW_FRAME (w));
6276 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6277 Display *dpy = FRAME_MAC_DISPLAY (f);
6278 int x, y, wd, h;
6279 XGCValues xgcv;
6280 struct glyph *cursor_glyph;
6281 GC gc;
6283 /* Get the glyph the cursor is on. If we can't tell because
6284 the current matrix is invalid or such, give up. */
6285 cursor_glyph = get_phys_cursor_glyph (w);
6286 if (cursor_glyph == NULL)
6287 return;
6289 /* Compute frame-relative coordinates for phys cursor. */
6290 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
6291 wd = w->phys_cursor_width;
6293 /* The foreground of cursor_gc is typically the same as the normal
6294 background color, which can cause the cursor box to be invisible. */
6295 xgcv.foreground = f->output_data.mac->cursor_pixel;
6296 if (dpyinfo->scratch_cursor_gc)
6297 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
6298 else
6299 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
6300 GCForeground, &xgcv);
6301 gc = dpyinfo->scratch_cursor_gc;
6303 /* Set clipping, draw the rectangle, and reset clipping again. */
6304 x_clip_to_row (w, row, TEXT_AREA, gc);
6305 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
6306 mac_reset_clip_rectangles (dpy, gc);
6310 /* Draw a bar cursor on window W in glyph row ROW.
6312 Implementation note: One would like to draw a bar cursor with an
6313 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6314 Unfortunately, I didn't find a font yet that has this property set.
6315 --gerd. */
6317 static void
6318 x_draw_bar_cursor (w, row, width, kind)
6319 struct window *w;
6320 struct glyph_row *row;
6321 int width;
6322 enum text_cursor_kinds kind;
6324 struct frame *f = XFRAME (w->frame);
6325 struct glyph *cursor_glyph;
6327 /* If cursor is out of bounds, don't draw garbage. This can happen
6328 in mini-buffer windows when switching between echo area glyphs
6329 and mini-buffer. */
6330 cursor_glyph = get_phys_cursor_glyph (w);
6331 if (cursor_glyph == NULL)
6332 return;
6334 /* If on an image, draw like a normal cursor. That's usually better
6335 visible than drawing a bar, esp. if the image is large so that
6336 the bar might not be in the window. */
6337 if (cursor_glyph->type == IMAGE_GLYPH)
6339 struct glyph_row *row;
6340 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
6341 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
6343 else
6345 Display *dpy = FRAME_MAC_DISPLAY (f);
6346 Window window = FRAME_MAC_WINDOW (f);
6347 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
6348 unsigned long mask = GCForeground | GCBackground;
6349 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
6350 XGCValues xgcv;
6352 /* If the glyph's background equals the color we normally draw
6353 the bar cursor in, the bar cursor in its normal color is
6354 invisible. Use the glyph's foreground color instead in this
6355 case, on the assumption that the glyph's colors are chosen so
6356 that the glyph is legible. */
6357 if (face->background == f->output_data.mac->cursor_pixel)
6358 xgcv.background = xgcv.foreground = face->foreground;
6359 else
6360 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
6362 if (gc)
6363 XChangeGC (dpy, gc, mask, &xgcv);
6364 else
6366 gc = XCreateGC (dpy, window, mask, &xgcv);
6367 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
6370 if (width < 0)
6371 width = FRAME_CURSOR_WIDTH (f);
6372 width = min (cursor_glyph->pixel_width, width);
6374 w->phys_cursor_width = width;
6375 x_clip_to_row (w, row, TEXT_AREA, gc);
6377 if (kind == BAR_CURSOR)
6378 mac_fill_rectangle (f, gc,
6379 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
6380 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
6381 width, row->height);
6382 else
6383 mac_fill_rectangle (f, gc,
6384 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
6385 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
6386 row->height - width),
6387 cursor_glyph->pixel_width,
6388 width);
6390 mac_reset_clip_rectangles (dpy, gc);
6395 /* RIF: Define cursor CURSOR on frame F. */
6397 static void
6398 mac_define_frame_cursor (f, cursor)
6399 struct frame *f;
6400 Cursor cursor;
6402 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6404 if (dpyinfo->x_focus_frame == f)
6405 SetThemeCursor (cursor);
6409 /* RIF: Clear area on frame F. */
6411 static void
6412 mac_clear_frame_area (f, x, y, width, height)
6413 struct frame *f;
6414 int x, y, width, height;
6416 mac_clear_area (f, x, y, width, height);
6420 /* RIF: Draw cursor on window W. */
6422 static void
6423 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
6424 struct window *w;
6425 struct glyph_row *glyph_row;
6426 int x, y;
6427 int cursor_type, cursor_width;
6428 int on_p, active_p;
6430 if (on_p)
6432 w->phys_cursor_type = cursor_type;
6433 w->phys_cursor_on_p = 1;
6435 if (glyph_row->exact_window_width_line_p
6436 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
6438 glyph_row->cursor_in_fringe_p = 1;
6439 draw_fringe_bitmap (w, glyph_row, 0);
6441 else
6442 switch (cursor_type)
6444 case HOLLOW_BOX_CURSOR:
6445 x_draw_hollow_cursor (w, glyph_row);
6446 break;
6448 case FILLED_BOX_CURSOR:
6449 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
6450 break;
6452 case BAR_CURSOR:
6453 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
6454 break;
6456 case HBAR_CURSOR:
6457 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
6458 break;
6460 case NO_CURSOR:
6461 w->phys_cursor_width = 0;
6462 break;
6464 default:
6465 abort ();
6471 /* Icons. */
6473 #if 0 /* MAC_TODO: no icon support yet. */
6475 x_bitmap_icon (f, icon)
6476 struct frame *f;
6477 Lisp_Object icon;
6479 HANDLE hicon;
6481 if (FRAME_W32_WINDOW (f) == 0)
6482 return 1;
6484 if (NILP (icon))
6485 hicon = LoadIcon (hinst, EMACS_CLASS);
6486 else if (STRINGP (icon))
6487 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
6488 LR_DEFAULTSIZE | LR_LOADFROMFILE);
6489 else if (SYMBOLP (icon))
6491 LPCTSTR name;
6493 if (EQ (icon, intern ("application")))
6494 name = (LPCTSTR) IDI_APPLICATION;
6495 else if (EQ (icon, intern ("hand")))
6496 name = (LPCTSTR) IDI_HAND;
6497 else if (EQ (icon, intern ("question")))
6498 name = (LPCTSTR) IDI_QUESTION;
6499 else if (EQ (icon, intern ("exclamation")))
6500 name = (LPCTSTR) IDI_EXCLAMATION;
6501 else if (EQ (icon, intern ("asterisk")))
6502 name = (LPCTSTR) IDI_ASTERISK;
6503 else if (EQ (icon, intern ("winlogo")))
6504 name = (LPCTSTR) IDI_WINLOGO;
6505 else
6506 return 1;
6508 hicon = LoadIcon (NULL, name);
6510 else
6511 return 1;
6513 if (hicon == NULL)
6514 return 1;
6516 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
6517 (LPARAM) hicon);
6519 return 0;
6521 #endif /* MAC_TODO */
6523 /************************************************************************
6524 Handling X errors
6525 ************************************************************************/
6527 /* Display Error Handling functions not used on W32. Listing them here
6528 helps diff stay in step when comparing w32term.c with xterm.c.
6530 x_error_catcher (display, error)
6531 x_catch_errors (dpy)
6532 x_catch_errors_unwind (old_val)
6533 x_check_errors (dpy, format)
6534 x_had_errors_p (dpy)
6535 x_clear_errors (dpy)
6536 x_uncatch_errors (dpy, count)
6537 x_trace_wire ()
6538 x_connection_signal (signalnum)
6539 x_connection_closed (dpy, error_message)
6540 x_error_quitter (display, error)
6541 x_error_handler (display, error)
6542 x_io_error_quitter (display)
6547 /* Changing the font of the frame. */
6549 /* Give frame F the font named FONTNAME as its default font, and
6550 return the full name of that font. FONTNAME may be a wildcard
6551 pattern; in that case, we choose some font that fits the pattern.
6552 The return value shows which font we chose. */
6554 Lisp_Object
6555 x_new_font (f, fontname)
6556 struct frame *f;
6557 register char *fontname;
6559 struct font_info *fontp
6560 = FS_LOAD_FONT (f, 0, fontname, -1);
6562 if (!fontp)
6563 return Qnil;
6565 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
6566 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
6567 FRAME_FONTSET (f) = -1;
6569 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
6570 FRAME_SPACE_WIDTH (f) = fontp->space_width;
6571 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
6573 compute_fringe_widths (f, 1);
6575 /* Compute the scroll bar width in character columns. */
6576 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
6578 int wid = FRAME_COLUMN_WIDTH (f);
6579 FRAME_CONFIG_SCROLL_BAR_COLS (f)
6580 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
6582 else
6584 int wid = FRAME_COLUMN_WIDTH (f);
6585 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
6588 /* Now make the frame display the given font. */
6589 if (FRAME_MAC_WINDOW (f) != 0)
6591 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
6592 FRAME_FONT (f));
6593 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
6594 FRAME_FONT (f));
6595 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
6596 FRAME_FONT (f));
6598 /* Don't change the size of a tip frame; there's no point in
6599 doing it because it's done in Fx_show_tip, and it leads to
6600 problems because the tip frame has no widget. */
6601 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
6602 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
6605 return build_string (fontp->full_name);
6608 /* Give frame F the fontset named FONTSETNAME as its default font, and
6609 return the full name of that fontset. FONTSETNAME may be a wildcard
6610 pattern; in that case, we choose some fontset that fits the pattern.
6611 The return value shows which fontset we chose. */
6613 Lisp_Object
6614 x_new_fontset (f, fontsetname)
6615 struct frame *f;
6616 char *fontsetname;
6618 int fontset = fs_query_fontset (build_string (fontsetname), 0);
6619 Lisp_Object result;
6621 if (fontset < 0)
6622 return Qnil;
6624 if (FRAME_FONTSET (f) == fontset)
6625 /* This fontset is already set in frame F. There's nothing more
6626 to do. */
6627 return fontset_name (fontset);
6629 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
6631 if (!STRINGP (result))
6632 /* Can't load ASCII font. */
6633 return Qnil;
6635 /* Since x_new_font doesn't update any fontset information, do it now. */
6636 FRAME_FONTSET (f) = fontset;
6638 return build_string (fontsetname);
6642 /***********************************************************************
6643 TODO: W32 Input Methods
6644 ***********************************************************************/
6645 /* Listing missing functions from xterm.c helps diff stay in step.
6647 xim_destroy_callback (xim, client_data, call_data)
6648 xim_open_dpy (dpyinfo, resource_name)
6649 struct xim_inst_t
6650 xim_instantiate_callback (display, client_data, call_data)
6651 xim_initialize (dpyinfo, resource_name)
6652 xim_close_dpy (dpyinfo)
6657 void
6658 mac_get_window_bounds (f, inner, outer)
6659 struct frame *f;
6660 Rect *inner, *outer;
6662 #if TARGET_API_MAC_CARBON
6663 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
6664 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
6665 #else /* not TARGET_API_MAC_CARBON */
6666 RgnHandle region = NewRgn ();
6668 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
6669 *inner = (*region)->rgnBBox;
6670 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
6671 *outer = (*region)->rgnBBox;
6672 DisposeRgn (region);
6673 #endif /* not TARGET_API_MAC_CARBON */
6676 static void
6677 mac_handle_origin_change (f)
6678 struct frame *f;
6680 x_real_positions (f, &f->left_pos, &f->top_pos);
6683 static void
6684 mac_handle_size_change (f, pixelwidth, pixelheight)
6685 struct frame *f;
6686 int pixelwidth, pixelheight;
6688 int cols, rows;
6690 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
6691 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
6693 if (cols != FRAME_COLS (f)
6694 || rows != FRAME_LINES (f)
6695 || pixelwidth != FRAME_PIXEL_WIDTH (f)
6696 || pixelheight != FRAME_PIXEL_HEIGHT (f))
6698 /* We pass 1 for DELAY since we can't run Lisp code inside of
6699 a BLOCK_INPUT. */
6700 change_frame_size (f, rows, cols, 0, 1, 0);
6701 FRAME_PIXEL_WIDTH (f) = pixelwidth;
6702 FRAME_PIXEL_HEIGHT (f) = pixelheight;
6703 SET_FRAME_GARBAGED (f);
6705 /* If cursor was outside the new size, mark it as off. */
6706 mark_window_cursors_off (XWINDOW (f->root_window));
6708 /* Clear out any recollection of where the mouse highlighting
6709 was, since it might be in a place that's outside the new
6710 frame size. Actually checking whether it is outside is a
6711 pain in the neck, so don't try--just let the highlighting be
6712 done afresh with new size. */
6713 cancel_mouse_face (f);
6715 #if TARGET_API_MAC_CARBON
6716 if (f->output_data.mac->hourglass_control)
6718 #if USE_CG_DRAWING
6719 mac_prepare_for_quickdraw (f);
6720 #endif
6721 MoveControl (f->output_data.mac->hourglass_control,
6722 pixelwidth - HOURGLASS_WIDTH, 0);
6724 #endif
6729 /* Calculate the absolute position in frame F
6730 from its current recorded position values and gravity. */
6732 void
6733 x_calc_absolute_position (f)
6734 struct frame *f;
6736 int width_diff = 0, height_diff = 0;
6737 int flags = f->size_hint_flags;
6738 Rect inner, outer;
6740 /* We have nothing to do if the current position
6741 is already for the top-left corner. */
6742 if (! ((flags & XNegative) || (flags & YNegative)))
6743 return;
6745 /* Find the offsets of the outside upper-left corner of
6746 the inner window, with respect to the outer window. */
6747 BLOCK_INPUT;
6748 mac_get_window_bounds (f, &inner, &outer);
6749 UNBLOCK_INPUT;
6751 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
6752 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
6754 /* Treat negative positions as relative to the leftmost bottommost
6755 position that fits on the screen. */
6756 if (flags & XNegative)
6757 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
6758 - width_diff
6759 - FRAME_PIXEL_WIDTH (f)
6760 + f->left_pos);
6762 if (flags & YNegative)
6763 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
6764 - height_diff
6765 - FRAME_PIXEL_HEIGHT (f)
6766 + f->top_pos);
6768 /* The left_pos and top_pos
6769 are now relative to the top and left screen edges,
6770 so the flags should correspond. */
6771 f->size_hint_flags &= ~ (XNegative | YNegative);
6774 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6775 to really change the position, and 0 when calling from
6776 x_make_frame_visible (in that case, XOFF and YOFF are the current
6777 position values). It is -1 when calling from x_set_frame_parameters,
6778 which means, do adjust for borders but don't change the gravity. */
6780 void
6781 x_set_offset (f, xoff, yoff, change_gravity)
6782 struct frame *f;
6783 register int xoff, yoff;
6784 int change_gravity;
6786 if (change_gravity > 0)
6788 f->top_pos = yoff;
6789 f->left_pos = xoff;
6790 f->size_hint_flags &= ~ (XNegative | YNegative);
6791 if (xoff < 0)
6792 f->size_hint_flags |= XNegative;
6793 if (yoff < 0)
6794 f->size_hint_flags |= YNegative;
6795 f->win_gravity = NorthWestGravity;
6797 x_calc_absolute_position (f);
6799 BLOCK_INPUT;
6800 x_wm_set_size_hint (f, (long) 0, 0);
6802 #if TARGET_API_MAC_CARBON
6803 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
6804 /* If the title bar is completely outside the screen, adjust the
6805 position. */
6806 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
6807 kWindowConstrainMoveRegardlessOfFit
6808 | kWindowConstrainAllowPartial, NULL, NULL);
6809 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
6810 mac_handle_origin_change (f);
6811 #else
6813 Rect inner, outer, screen_rect, dummy;
6814 RgnHandle region = NewRgn ();
6816 mac_get_window_bounds (f, &inner, &outer);
6817 f->x_pixels_diff = inner.left - outer.left;
6818 f->y_pixels_diff = inner.top - outer.top;
6819 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6820 f->top_pos + f->y_pixels_diff, false);
6822 /* If the title bar is completely outside the screen, adjust the
6823 position. The variable `outer' holds the title bar rectangle.
6824 The variable `inner' holds slightly smaller one than `outer',
6825 so that the calculation of overlapping may not become too
6826 strict. */
6827 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
6828 outer = (*region)->rgnBBox;
6829 DisposeRgn (region);
6830 inner = outer;
6831 InsetRect (&inner, 8, 8);
6832 screen_rect = qd.screenBits.bounds;
6833 screen_rect.top += GetMBarHeight ();
6835 if (!SectRect (&inner, &screen_rect, &dummy))
6837 if (inner.right <= screen_rect.left)
6838 f->left_pos = screen_rect.left;
6839 else if (inner.left >= screen_rect.right)
6840 f->left_pos = screen_rect.right - (outer.right - outer.left);
6842 if (inner.bottom <= screen_rect.top)
6843 f->top_pos = screen_rect.top;
6844 else if (inner.top >= screen_rect.bottom)
6845 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
6847 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6848 f->top_pos + f->y_pixels_diff, false);
6851 #endif
6853 UNBLOCK_INPUT;
6856 /* Call this to change the size of frame F's x-window.
6857 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6858 for this size change and subsequent size changes.
6859 Otherwise we leave the window gravity unchanged. */
6861 void
6862 x_set_window_size (f, change_gravity, cols, rows)
6863 struct frame *f;
6864 int change_gravity;
6865 int cols, rows;
6867 int pixelwidth, pixelheight;
6869 BLOCK_INPUT;
6871 check_frame_size (f, &rows, &cols);
6872 f->scroll_bar_actual_width
6873 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
6875 compute_fringe_widths (f, 0);
6877 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
6878 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
6880 f->win_gravity = NorthWestGravity;
6881 x_wm_set_size_hint (f, (long) 0, 0);
6883 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
6885 #if TARGET_API_MAC_CARBON
6886 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
6887 #endif
6888 mac_handle_size_change (f, pixelwidth, pixelheight);
6890 if (f->output_data.mac->internal_border_width
6891 != FRAME_INTERNAL_BORDER_WIDTH (f))
6893 mac_clear_window (f);
6894 f->output_data.mac->internal_border_width
6895 = FRAME_INTERNAL_BORDER_WIDTH (f);
6898 SET_FRAME_GARBAGED (f);
6900 UNBLOCK_INPUT;
6903 /* Mouse warping. */
6905 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
6907 void
6908 x_set_mouse_position (f, x, y)
6909 struct frame *f;
6910 int x, y;
6912 int pix_x, pix_y;
6914 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
6915 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
6917 if (pix_x < 0) pix_x = 0;
6918 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
6920 if (pix_y < 0) pix_y = 0;
6921 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
6923 x_set_mouse_pixel_position (f, pix_x, pix_y);
6926 void
6927 x_set_mouse_pixel_position (f, pix_x, pix_y)
6928 struct frame *f;
6929 int pix_x, pix_y;
6931 #ifdef MAC_OSX
6932 pix_x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
6933 pix_y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
6935 BLOCK_INPUT;
6936 CGWarpMouseCursorPosition (CGPointMake (pix_x, pix_y));
6937 UNBLOCK_INPUT;
6938 #else
6939 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6940 BLOCK_INPUT;
6942 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
6943 0, 0, 0, 0, pix_x, pix_y);
6944 UNBLOCK_INPUT;
6945 #endif
6946 #endif
6949 /* focus shifting, raising and lowering. */
6951 void
6952 x_focus_on_frame (f)
6953 struct frame *f;
6955 #if 0 /* This proves to be unpleasant. */
6956 x_raise_frame (f);
6957 #endif
6958 #if 0
6959 /* I don't think that the ICCCM allows programs to do things like this
6960 without the interaction of the window manager. Whatever you end up
6961 doing with this code, do it to x_unfocus_frame too. */
6962 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6963 RevertToPointerRoot, CurrentTime);
6964 #endif /* ! 0 */
6967 void
6968 x_unfocus_frame (f)
6969 struct frame *f;
6973 /* Raise frame F. */
6975 void
6976 x_raise_frame (f)
6977 struct frame *f;
6979 if (f->async_visible)
6981 BLOCK_INPUT;
6982 BringToFront (FRAME_MAC_WINDOW (f));
6983 UNBLOCK_INPUT;
6987 /* Lower frame F. */
6989 void
6990 x_lower_frame (f)
6991 struct frame *f;
6993 if (f->async_visible)
6995 BLOCK_INPUT;
6996 SendBehind (FRAME_MAC_WINDOW (f), NULL);
6997 UNBLOCK_INPUT;
7001 static void
7002 XTframe_raise_lower (f, raise_flag)
7003 FRAME_PTR f;
7004 int raise_flag;
7006 if (raise_flag)
7007 x_raise_frame (f);
7008 else
7009 x_lower_frame (f);
7012 /* Change of visibility. */
7014 static void
7015 mac_handle_visibility_change (f)
7016 struct frame *f;
7018 WindowRef wp = FRAME_MAC_WINDOW (f);
7019 int visible = 0, iconified = 0;
7020 struct input_event buf;
7022 if (IsWindowVisible (wp))
7024 if (IsWindowCollapsed (wp))
7025 iconified = 1;
7026 else
7027 visible = 1;
7030 if (!f->async_visible && visible)
7032 if (f->iconified)
7034 /* wait_reading_process_output will notice this and update
7035 the frame's display structures. If we were made
7036 invisible, we should not set garbaged, because that stops
7037 redrawing on Update events. */
7038 SET_FRAME_GARBAGED (f);
7040 EVENT_INIT (buf);
7041 buf.kind = DEICONIFY_EVENT;
7042 XSETFRAME (buf.frame_or_window, f);
7043 buf.arg = Qnil;
7044 kbd_buffer_store_event (&buf);
7046 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
7047 /* Force a redisplay sooner or later to update the
7048 frame titles in case this is the second frame. */
7049 record_asynch_buffer_change ();
7051 else if (f->async_visible && !visible)
7052 if (iconified)
7054 EVENT_INIT (buf);
7055 buf.kind = ICONIFY_EVENT;
7056 XSETFRAME (buf.frame_or_window, f);
7057 buf.arg = Qnil;
7058 kbd_buffer_store_event (&buf);
7061 f->async_visible = visible;
7062 f->async_iconified = iconified;
7065 /* This tries to wait until the frame is really visible.
7066 However, if the window manager asks the user where to position
7067 the frame, this will return before the user finishes doing that.
7068 The frame will not actually be visible at that time,
7069 but it will become visible later when the window manager
7070 finishes with it. */
7072 void
7073 x_make_frame_visible (f)
7074 struct frame *f;
7076 BLOCK_INPUT;
7078 if (! FRAME_VISIBLE_P (f))
7080 /* We test FRAME_GARBAGED_P here to make sure we don't
7081 call x_set_offset a second time
7082 if we get to x_make_frame_visible a second time
7083 before the window gets really visible. */
7084 if (! FRAME_ICONIFIED_P (f)
7085 && ! f->output_data.mac->asked_for_visible)
7086 x_set_offset (f, f->left_pos, f->top_pos, 0);
7088 f->output_data.mac->asked_for_visible = 1;
7090 CollapseWindow (FRAME_MAC_WINDOW (f), false);
7091 ShowWindow (FRAME_MAC_WINDOW (f));
7094 XFlush (FRAME_MAC_DISPLAY (f));
7096 /* Synchronize to ensure Emacs knows the frame is visible
7097 before we do anything else. We do this loop with input not blocked
7098 so that incoming events are handled. */
7100 Lisp_Object frame;
7101 int count;
7103 /* This must come after we set COUNT. */
7104 UNBLOCK_INPUT;
7106 XSETFRAME (frame, f);
7108 /* Wait until the frame is visible. Process X events until a
7109 MapNotify event has been seen, or until we think we won't get a
7110 MapNotify at all.. */
7111 for (count = input_signal_count + 10;
7112 input_signal_count < count && !FRAME_VISIBLE_P (f);)
7114 /* Force processing of queued events. */
7115 x_sync (f);
7117 /* Machines that do polling rather than SIGIO have been
7118 observed to go into a busy-wait here. So we'll fake an
7119 alarm signal to let the handler know that there's something
7120 to be read. We used to raise a real alarm, but it seems
7121 that the handler isn't always enabled here. This is
7122 probably a bug. */
7123 if (input_polling_used ())
7125 /* It could be confusing if a real alarm arrives while
7126 processing the fake one. Turn it off and let the
7127 handler reset it. */
7128 extern void poll_for_input_1 P_ ((void));
7129 int old_poll_suppress_count = poll_suppress_count;
7130 poll_suppress_count = 1;
7131 poll_for_input_1 ();
7132 poll_suppress_count = old_poll_suppress_count;
7135 /* See if a MapNotify event has been processed. */
7136 FRAME_SAMPLE_VISIBILITY (f);
7141 /* Change from mapped state to withdrawn state. */
7143 /* Make the frame visible (mapped and not iconified). */
7145 void
7146 x_make_frame_invisible (f)
7147 struct frame *f;
7149 /* A deactivate event does not occur when the last visible frame is
7150 made invisible. So if we clear the highlight here, it will not
7151 be rehighlighted when it is made visible. */
7152 #if 0
7153 /* Don't keep the highlight on an invisible frame. */
7154 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
7155 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
7156 #endif
7158 BLOCK_INPUT;
7160 #if !TARGET_API_MAC_CARBON
7161 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7162 that the current position of the window is user-specified, rather than
7163 program-specified, so that when the window is mapped again, it will be
7164 placed at the same location, without forcing the user to position it
7165 by hand again (they have already done that once for this window.) */
7166 x_wm_set_size_hint (f, (long) 0, 1);
7167 #endif
7169 HideWindow (FRAME_MAC_WINDOW (f));
7171 UNBLOCK_INPUT;
7173 #if !TARGET_API_MAC_CARBON
7174 mac_handle_visibility_change (f);
7175 #endif
7178 /* Change window state from mapped to iconified. */
7180 void
7181 x_iconify_frame (f)
7182 struct frame *f;
7184 OSStatus err;
7186 /* A deactivate event does not occur when the last visible frame is
7187 iconified. So if we clear the highlight here, it will not be
7188 rehighlighted when it is deiconified. */
7189 #if 0
7190 /* Don't keep the highlight on an invisible frame. */
7191 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
7192 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
7193 #endif
7195 if (f->async_iconified)
7196 return;
7198 BLOCK_INPUT;
7200 FRAME_SAMPLE_VISIBILITY (f);
7202 if (! FRAME_VISIBLE_P (f))
7203 ShowWindow (FRAME_MAC_WINDOW (f));
7205 err = CollapseWindow (FRAME_MAC_WINDOW (f), true);
7207 UNBLOCK_INPUT;
7209 if (err != noErr)
7210 error ("Can't notify window manager of iconification");
7212 #if !TARGET_API_MAC_CARBON
7213 mac_handle_visibility_change (f);
7214 #endif
7218 /* Free X resources of frame F. */
7220 void
7221 x_free_frame_resources (f)
7222 struct frame *f;
7224 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7225 WindowRef wp = FRAME_MAC_WINDOW (f);
7227 BLOCK_INPUT;
7229 if (wp != tip_window)
7230 remove_window_handler (wp);
7232 #if USE_CG_DRAWING
7233 mac_prepare_for_quickdraw (f);
7234 #endif
7235 DisposeWindow (wp);
7236 if (wp == tip_window)
7237 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7238 closed' event. So we reset tip_window here. */
7239 tip_window = NULL;
7241 free_frame_menubar (f);
7243 if (FRAME_FACE_CACHE (f))
7244 free_frame_faces (f);
7246 x_free_gcs (f);
7248 if (FRAME_SIZE_HINTS (f))
7249 xfree (FRAME_SIZE_HINTS (f));
7251 xfree (f->output_data.mac);
7252 f->output_data.mac = NULL;
7254 if (f == dpyinfo->x_focus_frame)
7256 dpyinfo->x_focus_frame = 0;
7257 #if USE_MAC_FONT_PANEL
7258 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
7259 #endif
7261 if (f == dpyinfo->x_focus_event_frame)
7262 dpyinfo->x_focus_event_frame = 0;
7263 if (f == dpyinfo->x_highlight_frame)
7264 dpyinfo->x_highlight_frame = 0;
7266 if (f == dpyinfo->mouse_face_mouse_frame)
7268 dpyinfo->mouse_face_beg_row
7269 = dpyinfo->mouse_face_beg_col = -1;
7270 dpyinfo->mouse_face_end_row
7271 = dpyinfo->mouse_face_end_col = -1;
7272 dpyinfo->mouse_face_window = Qnil;
7273 dpyinfo->mouse_face_deferred_gc = 0;
7274 dpyinfo->mouse_face_mouse_frame = 0;
7277 UNBLOCK_INPUT;
7281 /* Destroy the X window of frame F. */
7283 void
7284 x_destroy_window (f)
7285 struct frame *f;
7287 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7289 x_free_frame_resources (f);
7291 dpyinfo->reference_count--;
7295 /* Setting window manager hints. */
7297 /* Set the normal size hints for the window manager, for frame F.
7298 FLAGS is the flags word to use--or 0 meaning preserve the flags
7299 that the window now has.
7300 If USER_POSITION is nonzero, we set the USPosition
7301 flag (this is useful when FLAGS is 0). */
7302 void
7303 x_wm_set_size_hint (f, flags, user_position)
7304 struct frame *f;
7305 long flags;
7306 int user_position;
7308 int base_width, base_height, width_inc, height_inc;
7309 int min_rows = 0, min_cols = 0;
7310 XSizeHints *size_hints;
7312 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
7313 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
7314 width_inc = FRAME_COLUMN_WIDTH (f);
7315 height_inc = FRAME_LINE_HEIGHT (f);
7317 check_frame_size (f, &min_rows, &min_cols);
7319 size_hints = FRAME_SIZE_HINTS (f);
7320 if (size_hints == NULL)
7322 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
7323 bzero (size_hints, sizeof (XSizeHints));
7326 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
7327 size_hints->width_inc = width_inc;
7328 size_hints->height_inc = height_inc;
7329 size_hints->min_width = base_width + min_cols * width_inc;
7330 size_hints->min_height = base_height + min_rows * height_inc;
7331 size_hints->base_width = base_width;
7332 size_hints->base_height = base_height;
7334 if (flags)
7335 size_hints->flags = flags;
7336 else if (user_position)
7338 size_hints->flags &= ~ PPosition;
7339 size_hints->flags |= USPosition;
7343 #if 0 /* MAC_TODO: hide application instead of iconify? */
7344 /* Used for IconicState or NormalState */
7346 void
7347 x_wm_set_window_state (f, state)
7348 struct frame *f;
7349 int state;
7351 #ifdef USE_X_TOOLKIT
7352 Arg al[1];
7354 XtSetArg (al[0], XtNinitialState, state);
7355 XtSetValues (f->output_data.x->widget, al, 1);
7356 #else /* not USE_X_TOOLKIT */
7357 Window window = FRAME_X_WINDOW (f);
7359 f->output_data.x->wm_hints.flags |= StateHint;
7360 f->output_data.x->wm_hints.initial_state = state;
7362 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
7363 #endif /* not USE_X_TOOLKIT */
7366 void
7367 x_wm_set_icon_pixmap (f, pixmap_id)
7368 struct frame *f;
7369 int pixmap_id;
7371 Pixmap icon_pixmap;
7373 #ifndef USE_X_TOOLKIT
7374 Window window = FRAME_X_WINDOW (f);
7375 #endif
7377 if (pixmap_id > 0)
7379 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7380 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
7382 else
7384 /* It seems there is no way to turn off use of an icon pixmap.
7385 The following line does it, only if no icon has yet been created,
7386 for some window managers. But with mwm it crashes.
7387 Some people say it should clear the IconPixmapHint bit in this case,
7388 but that doesn't work, and the X consortium said it isn't the
7389 right thing at all. Since there is no way to win,
7390 best to explicitly give up. */
7391 #if 0
7392 f->output_data.x->wm_hints.icon_pixmap = None;
7393 #else
7394 return;
7395 #endif
7398 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7401 Arg al[1];
7402 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
7403 XtSetValues (f->output_data.x->widget, al, 1);
7406 #else /* not USE_X_TOOLKIT */
7408 f->output_data.x->wm_hints.flags |= IconPixmapHint;
7409 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
7411 #endif /* not USE_X_TOOLKIT */
7414 #endif /* MAC_TODO */
7416 void
7417 x_wm_set_icon_position (f, icon_x, icon_y)
7418 struct frame *f;
7419 int icon_x, icon_y;
7421 #if 0 /* MAC_TODO: no icons on Mac */
7422 #ifdef USE_X_TOOLKIT
7423 Window window = XtWindow (f->output_data.x->widget);
7424 #else
7425 Window window = FRAME_X_WINDOW (f);
7426 #endif
7428 f->output_data.x->wm_hints.flags |= IconPositionHint;
7429 f->output_data.x->wm_hints.icon_x = icon_x;
7430 f->output_data.x->wm_hints.icon_y = icon_y;
7432 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
7433 #endif /* MAC_TODO */
7437 /***********************************************************************
7438 XLFD Pattern Match
7439 ***********************************************************************/
7441 /* An XLFD pattern is divided into blocks delimited by '*'. This
7442 structure holds information for each block. */
7443 struct xlfdpat_block
7445 /* Length of the pattern string in this block. Non-zero except for
7446 the first and the last blocks. */
7447 int len;
7449 /* Pattern string except the last character in this block. The last
7450 character is replaced with NUL in order to use it as a
7451 sentinel. */
7452 unsigned char *pattern;
7454 /* Last character of the pattern string. Must not be '?'. */
7455 unsigned char last_char;
7457 /* One of the tables for the Boyer-Moore string search. It
7458 specifies the number of positions to proceed for each character
7459 with which the match fails. */
7460 int skip[256];
7462 /* The skip value for the last character in the above `skip' is
7463 assigned to `infinity' in order to simplify a loop condition.
7464 The original value is saved here. */
7465 int last_char_skip;
7468 struct xlfdpat
7470 /* Normalized pattern string. "Normalized" means that capital
7471 letters are lowered, blocks are not empty except the first and
7472 the last ones, and trailing '?'s in a block that is not the last
7473 one are moved to the next one. The last character in each block
7474 is replaced with NUL. */
7475 unsigned char *buf;
7477 /* Number of characters except '*'s and trailing '?'s in the
7478 normalized pattern string. */
7479 int nchars;
7481 /* Number of trailing '?'s in the normalized pattern string. */
7482 int trailing_anychars;
7484 /* Number of blocks and information for each block. The latter is
7485 NULL if the pattern is exact (no '*' or '?' in it). */
7486 int nblocks;
7487 struct xlfdpat_block *blocks;
7490 static void
7491 xlfdpat_destroy (pat)
7492 struct xlfdpat *pat;
7494 if (pat)
7496 if (pat->buf)
7498 if (pat->blocks)
7499 xfree (pat->blocks);
7500 xfree (pat->buf);
7502 xfree (pat);
7506 static struct xlfdpat *
7507 xlfdpat_create (pattern)
7508 const char *pattern;
7510 struct xlfdpat *pat;
7511 int nblocks, i, skip;
7512 unsigned char last_char, *p, *q, *anychar_head;
7513 const unsigned char *ptr;
7514 struct xlfdpat_block *blk;
7516 pat = xmalloc (sizeof (struct xlfdpat));
7517 pat->buf = xmalloc (strlen (pattern) + 1);
7519 /* Normalize the pattern string and store it to `pat->buf'. */
7520 nblocks = 0;
7521 anychar_head = NULL;
7522 q = pat->buf;
7523 last_char = '\0';
7524 for (ptr = pattern; *ptr; ptr++)
7526 unsigned char c = *ptr;
7528 if (c == '*')
7529 if (last_char == '*')
7530 /* ...a** -> ...a* */
7531 continue;
7532 else
7534 if (last_char == '?')
7536 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
7537 /* ...*??* -> ...*?? */
7538 continue;
7539 else
7540 /* ...a??* -> ...a*?? */
7542 *anychar_head++ = '*';
7543 c = '?';
7546 nblocks++;
7548 else if (c == '?')
7550 if (last_char != '?')
7551 anychar_head = q;
7553 else
7554 /* On Mac OS X 10.3, tolower also converts non-ASCII
7555 characters for some locales. */
7556 if (isascii (c))
7557 c = tolower (c);
7559 *q++ = last_char = c;
7561 *q = '\0';
7562 nblocks++;
7563 pat->nblocks = nblocks;
7564 if (last_char != '?')
7565 pat->trailing_anychars = 0;
7566 else
7568 pat->trailing_anychars = q - anychar_head;
7569 q = anychar_head;
7571 pat->nchars = q - pat->buf - (nblocks - 1);
7573 if (anychar_head == NULL && nblocks == 1)
7575 /* The pattern is exact. */
7576 pat->blocks = NULL;
7577 return pat;
7580 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
7582 /* Divide the normalized pattern into blocks. */
7583 p = pat->buf;
7584 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
7586 blk->pattern = p;
7587 while (*p != '*')
7588 p++;
7589 blk->len = p - blk->pattern;
7590 p++;
7592 blk->pattern = p;
7593 blk->len = q - blk->pattern;
7595 /* Setup a table for the Boyer-Moore string search. */
7596 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
7597 if (blk->len != 0)
7599 blk->last_char = blk->pattern[blk->len - 1];
7600 blk->pattern[blk->len - 1] = '\0';
7602 for (skip = 1; skip < blk->len; skip++)
7603 if (blk->pattern[blk->len - skip - 1] == '?')
7604 break;
7606 for (i = 0; i < 256; i++)
7607 blk->skip[i] = skip;
7609 p = blk->pattern + (blk->len - skip);
7610 while (--skip > 0)
7611 blk->skip[*p++] = skip;
7613 blk->last_char_skip = blk->skip[blk->last_char];
7616 return pat;
7619 static INLINE int
7620 xlfdpat_exact_p (pat)
7621 struct xlfdpat *pat;
7623 return pat->blocks == NULL;
7626 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7627 that the pattern in *BLK matches with its prefix. Return NULL
7628 there is no such strings. STRING must be lowered in advance. */
7630 static const char *
7631 xlfdpat_block_match_1 (blk, string, start_max)
7632 struct xlfdpat_block *blk;
7633 const unsigned char *string;
7634 int start_max;
7636 int start, infinity;
7637 unsigned char *p;
7638 const unsigned char *s;
7640 xassert (blk->len > 0);
7641 xassert (start_max + blk->len <= strlen (string));
7642 xassert (blk->last_char != '?');
7644 /* See the comments in the function `boyer_moore' (search.c) for the
7645 use of `infinity'. */
7646 infinity = start_max + blk->len + 1;
7647 blk->skip[blk->last_char] = infinity;
7649 start = 0;
7652 /* Check the last character of the pattern. */
7653 s = string + blk->len - 1;
7656 start += blk->skip[*(s + start)];
7658 while (start <= start_max);
7660 if (start < infinity)
7661 /* Couldn't find the last character. */
7662 return NULL;
7664 /* No less than `infinity' means we could find the last
7665 character at `s[start - infinity]'. */
7666 start -= infinity;
7668 /* Check the remaining characters. We prefer making no-'?'
7669 cases faster because the use of '?' is really rare. */
7670 p = blk->pattern;
7671 s = string + start;
7674 while (*p++ == *s++)
7677 while (*(p - 1) == '?');
7679 if (*(p - 1) == '\0')
7680 /* Matched. */
7681 return string + start;
7683 /* Didn't match. */
7684 start += blk->last_char_skip;
7686 while (start <= start_max);
7688 return NULL;
7691 #define xlfdpat_block_match(b, s, m) \
7692 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7693 : xlfdpat_block_match_1 (b, s, m))
7695 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7696 matches with STRING. STRING must be lowered in advance. */
7698 static int
7699 xlfdpat_match (pat, string)
7700 struct xlfdpat *pat;
7701 const unsigned char *string;
7703 int str_len, nblocks, i, start_max;
7704 struct xlfdpat_block *blk;
7705 const unsigned char *s;
7707 xassert (pat->nblocks > 0);
7709 if (xlfdpat_exact_p (pat))
7710 return strcmp (pat->buf, string) == 0;
7712 /* The number of the characters in the string must not be smaller
7713 than that in the pattern. */
7714 str_len = strlen (string);
7715 if (str_len < pat->nchars + pat->trailing_anychars)
7716 return 0;
7718 /* Chop off the trailing '?'s. */
7719 str_len -= pat->trailing_anychars;
7721 /* The last block. When it is non-empty, it must match at the end
7722 of the string. */
7723 nblocks = pat->nblocks;
7724 blk = pat->blocks + (nblocks - 1);
7725 if (nblocks == 1)
7726 /* The last block is also the first one. */
7727 return (str_len == blk->len
7728 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
7729 else if (blk->len != 0)
7730 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
7731 return 0;
7733 /* The first block. When it is non-empty, it must match at the
7734 beginning of the string. */
7735 blk = pat->blocks;
7736 if (blk->len != 0)
7738 s = xlfdpat_block_match (blk, string, 0);
7739 if (s == NULL)
7740 return 0;
7741 string = s + blk->len;
7744 /* The rest of the blocks. */
7745 start_max = str_len - pat->nchars;
7746 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
7748 s = xlfdpat_block_match (blk, string, start_max);
7749 if (s == NULL)
7750 return 0;
7751 start_max -= s - string;
7752 string = s + blk->len;
7755 return 1;
7759 /***********************************************************************
7760 Fonts
7761 ***********************************************************************/
7763 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7765 struct font_info *
7766 x_get_font_info (f, font_idx)
7767 FRAME_PTR f;
7768 int font_idx;
7770 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
7773 /* the global font name table */
7774 static char **font_name_table = NULL;
7775 static int font_name_table_size = 0;
7776 static int font_name_count = 0;
7778 /* Alist linking font family names to Font Manager font family
7779 references (which can also be used as QuickDraw font IDs). We use
7780 an alist because hash tables are not ready when the terminal frame
7781 for Mac OS Classic is created. */
7782 static Lisp_Object fm_font_family_alist;
7783 #if USE_ATSUI
7784 /* Hash table linking font family names to ATSU font IDs. */
7785 static Lisp_Object atsu_font_id_hash;
7786 /* Alist linking Font Manager style to face attributes. */
7787 static Lisp_Object fm_style_face_attributes_alist;
7788 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
7789 #endif
7791 /* Alist linking character set strings to Mac text encoding and Emacs
7792 coding system. */
7793 static Lisp_Object Vmac_charset_info_alist;
7795 static Lisp_Object
7796 create_text_encoding_info_alist ()
7798 Lisp_Object result = Qnil, rest;
7800 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
7802 Lisp_Object charset_info = XCAR (rest);
7803 Lisp_Object charset, coding_system, text_encoding;
7804 Lisp_Object existing_info;
7806 if (!(CONSP (charset_info)
7807 && (charset = XCAR (charset_info),
7808 STRINGP (charset))
7809 && CONSP (XCDR (charset_info))
7810 && (text_encoding = XCAR (XCDR (charset_info)),
7811 INTEGERP (text_encoding))
7812 && CONSP (XCDR (XCDR (charset_info)))
7813 && (coding_system = XCAR (XCDR (XCDR (charset_info))),
7814 SYMBOLP (coding_system))))
7815 continue;
7817 existing_info = assq_no_quit (text_encoding, result);
7818 if (NILP (existing_info))
7819 result = Fcons (list3 (text_encoding, coding_system, charset),
7820 result);
7821 else
7822 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
7823 XSETCDR (XCDR (existing_info),
7824 Fcons (charset, XCDR (XCDR (existing_info))));
7827 return result;
7831 static void
7832 decode_mac_font_name (name, size, coding_system)
7833 char *name;
7834 int size;
7835 Lisp_Object coding_system;
7837 struct coding_system coding;
7838 char *buf, *p;
7840 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
7842 for (p = name; *p; p++)
7843 if (!isascii (*p) || iscntrl (*p))
7844 break;
7846 if (*p)
7848 setup_coding_system (coding_system, &coding);
7849 coding.src_multibyte = 0;
7850 coding.dst_multibyte = 1;
7851 coding.mode |= CODING_MODE_LAST_BLOCK;
7852 coding.composing = COMPOSITION_DISABLED;
7853 buf = (char *) alloca (size);
7855 decode_coding (&coding, name, buf, strlen (name), size - 1);
7856 bcopy (buf, name, coding.produced);
7857 name[coding.produced] = '\0';
7861 /* If there's just one occurrence of '-' in the family name, it is
7862 replaced with '_'. (More than one occurrence of '-' means a
7863 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7864 p = strchr (name, '-');
7865 if (p && strchr (p + 1, '-') == NULL)
7866 *p = '_';
7868 for (p = name; *p; p++)
7869 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7870 for some locales. */
7871 if (isascii (*p))
7872 *p = tolower (*p);
7876 static char *
7877 mac_to_x_fontname (name, size, style, charset)
7878 const char *name;
7879 int size;
7880 Style style;
7881 char *charset;
7883 Str31 foundry, cs;
7884 Str255 family;
7885 char xf[256], *result;
7886 unsigned char *p;
7888 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
7889 charset = cs;
7890 else
7892 strcpy(foundry, "Apple");
7893 strcpy(family, name);
7896 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7897 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
7898 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
7900 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
7901 sprintf (result, "-%s-%s-%s", foundry, family, xf);
7902 for (p = result; *p; p++)
7903 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7904 for some locales. */
7905 if (isascii (*p))
7906 *p = tolower (*p);
7907 return result;
7911 /* Parse fully-specified and instantiated X11 font spec XF, and store
7912 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7913 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7914 caller must allocate at least 256 and 32 bytes respectively. For
7915 ordinary Mac fonts, the value stored to FAMILY should just be their
7916 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7917 intlfonts collection contain their charset designation in their
7918 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7919 types of font names are handled accordingly. */
7921 const int kDefaultFontSize = 12;
7923 static int
7924 parse_x_font_name (xf, family, size, style, charset)
7925 const char *xf;
7926 char *family;
7927 int *size;
7928 Style *style;
7929 char *charset;
7931 Str31 foundry, weight;
7932 int point_size, avgwidth;
7933 char slant[2], *p;
7935 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7936 foundry, family, weight, slant, size,
7937 &point_size, &avgwidth, charset) != 8
7938 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7939 foundry, family, weight, slant, size,
7940 &point_size, &avgwidth, charset) != 8)
7941 return 0;
7943 if (*size == 0)
7945 if (point_size > 0)
7946 *size = point_size / 10;
7947 else if (avgwidth > 0)
7948 *size = avgwidth / 10;
7950 if (*size == 0)
7951 *size = kDefaultFontSize;
7953 *style = normal;
7954 if (strcmp (weight, "bold") == 0)
7955 *style |= bold;
7956 if (*slant == 'i')
7957 *style |= italic;
7959 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
7961 int foundry_len = strlen (foundry), family_len = strlen (family);
7963 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
7965 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7966 but take overlap into account. */
7967 memmove (family + foundry_len + 1, family, family_len);
7968 memcpy (family, foundry, foundry_len);
7969 family[foundry_len] = '-';
7970 family[foundry_len + 1 + family_len] = '-';
7971 strcpy (family + foundry_len + 1 + family_len + 1, charset);
7973 else
7974 return 0;
7977 for (p = family; *p; p++)
7978 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7979 for some locales. */
7980 if (isascii (*p))
7981 *p = tolower (*p);
7983 return 1;
7987 static void
7988 add_font_name_table_entry (char *font_name)
7990 if (font_name_table_size == 0)
7992 font_name_table_size = 256;
7993 font_name_table = (char **)
7994 xmalloc (font_name_table_size * sizeof (char *));
7996 else if (font_name_count + 1 >= font_name_table_size)
7998 font_name_table_size *= 2;
7999 font_name_table = (char **)
8000 xrealloc (font_name_table,
8001 font_name_table_size * sizeof (char *));
8004 font_name_table[font_name_count++] = font_name;
8007 static void
8008 add_mac_font_name (name, size, style, charset)
8009 const char *name;
8010 int size;
8011 Style style;
8012 const char *charset;
8014 if (size > 0)
8015 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
8016 else
8018 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
8019 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
8020 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
8021 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
8022 charset));
8026 #if USE_ATSUI
8027 static FMFontStyle
8028 fm_get_style_from_font (font)
8029 FMFont font;
8031 OSStatus err;
8032 FMFontStyle style = normal;
8033 ByteCount len;
8034 UInt16 mac_style;
8035 FMFontFamily font_family;
8036 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8038 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8039 some font (e.g., Optima) even if it is `bold'. */
8040 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
8041 sizeof (mac_style), &mac_style, &len);
8042 if (err == noErr
8043 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
8044 style = EndianU16_BtoN (mac_style);
8045 else
8046 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
8048 return style;
8051 static ATSUFontID
8052 atsu_find_font_from_family_name (family)
8053 const char *family;
8055 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
8056 unsigned hash_code;
8057 int i;
8058 Lisp_Object rest, best;
8059 FMFontStyle min_style, style;
8061 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
8062 &hash_code);
8063 if (i < 0)
8064 return kATSUInvalidFontID;
8066 rest = HASH_VALUE (h, i);
8067 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
8068 return cons_to_long (rest);
8070 rest = Fnreverse (rest);
8071 best = XCAR (rest);
8072 rest = XCDR (rest);
8073 if (!NILP (rest)
8074 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
8077 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
8078 if (style < min_style)
8080 best = XCAR (rest);
8081 if (style == normal)
8082 break;
8083 else
8084 min_style = style;
8086 rest = XCDR (rest);
8088 while (!NILP (rest));
8090 HASH_VALUE (h, i) = best;
8091 return cons_to_long (best);
8094 static Lisp_Object
8095 fm_style_to_face_attributes (fm_style)
8096 FMFontStyle fm_style;
8098 Lisp_Object tem;
8100 fm_style &= (bold | italic);
8101 tem = assq_no_quit (make_number (fm_style),
8102 fm_style_face_attributes_alist);
8103 if (!NILP (tem))
8104 return XCDR (tem);
8106 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
8107 QCslant, fm_style & italic ? Qitalic : Qnormal);
8108 fm_style_face_attributes_alist =
8109 Fcons (Fcons (make_number (fm_style), tem),
8110 fm_style_face_attributes_alist);
8112 return tem;
8115 static Lisp_Object
8116 atsu_find_font_family_name (font_id)
8117 ATSUFontID font_id;
8119 OSStatus err;
8120 ByteCount len;
8121 Lisp_Object family = Qnil;
8123 err = ATSUFindFontName (font_id, kFontFamilyName,
8124 kFontMacintoshPlatform, kFontNoScript,
8125 kFontNoLanguage, 0, NULL, &len, NULL);
8126 if (err == noErr)
8128 family = make_uninit_string (len);
8129 err = ATSUFindFontName (font_id, kFontFamilyName,
8130 kFontMacintoshPlatform, kFontNoScript,
8131 kFontNoLanguage, len, SDATA (family),
8132 NULL, NULL);
8134 if (err == noErr)
8135 decode_mac_font_name (SDATA (family), len + 1, Qnil);
8137 return family;
8140 Lisp_Object
8141 mac_atsu_font_face_attributes (font_id)
8142 ATSUFontID font_id;
8144 Lisp_Object family, style_attrs;
8146 family = atsu_find_font_family_name (font_id);
8147 if (NILP (family))
8148 return Qnil;
8149 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
8150 return Fcons (QCfamily, Fcons (family, style_attrs));
8152 #endif
8154 /* Sets up the table font_name_table to contain the list of all fonts
8155 in the system the first time the table is used so that the Resource
8156 Manager need not be accessed every time this information is
8157 needed. */
8159 static void
8160 init_font_name_table ()
8162 #if TARGET_API_MAC_CARBON
8163 FMFontFamilyIterator ffi;
8164 FMFontFamilyInstanceIterator ffii;
8165 FMFontFamily ff;
8166 Lisp_Object text_encoding_info_alist;
8167 struct gcpro gcpro1;
8169 text_encoding_info_alist = create_text_encoding_info_alist ();
8171 #if USE_ATSUI
8172 #if USE_CG_TEXT_DRAWING
8173 init_cg_text_anti_aliasing_threshold ();
8174 #endif
8175 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
8176 text_encoding_info_alist)))
8178 OSStatus err;
8179 struct Lisp_Hash_Table *h;
8180 unsigned hash_code;
8181 ItemCount nfonts, i;
8182 ATSUFontID *font_ids = NULL;
8183 Lisp_Object prev_family = Qnil;
8184 int j;
8186 atsu_font_id_hash =
8187 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
8188 make_float (DEFAULT_REHASH_SIZE),
8189 make_float (DEFAULT_REHASH_THRESHOLD),
8190 Qnil, Qnil, Qnil);
8191 h = XHASH_TABLE (atsu_font_id_hash);
8193 err = ATSUFontCount (&nfonts);
8194 if (err == noErr)
8196 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
8197 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
8199 if (err == noErr)
8200 for (i = 0; i < nfonts; i++)
8202 Lisp_Object family;
8204 family = atsu_find_font_family_name (font_ids[i]);
8205 if (NILP (family) || SREF (family, 0) == '.')
8206 continue;
8207 if (!NILP (Fequal (prev_family, family)))
8208 family = prev_family;
8209 else
8210 j = hash_lookup (h, family, &hash_code);
8211 if (j < 0)
8213 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
8214 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
8215 Qnil), hash_code);
8217 else if (EQ (prev_family, family))
8218 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
8219 HASH_VALUE (h, j));
8220 prev_family = family;
8222 if (font_ids)
8223 xfree (font_ids);
8225 #endif
8227 /* Create a dummy instance iterator here to avoid creating and
8228 destroying it in the loop. */
8229 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
8230 return;
8231 /* Create an iterator to enumerate the font families. */
8232 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
8233 != noErr)
8235 FMDisposeFontFamilyInstanceIterator (&ffii);
8236 return;
8239 GCPRO1 (text_encoding_info_alist);
8241 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
8243 Str255 name;
8244 FMFont font;
8245 FMFontStyle style;
8246 FMFontSize size;
8247 TextEncoding encoding;
8248 TextEncodingBase sc;
8249 Lisp_Object text_encoding_info, family;
8251 if (FMGetFontFamilyName (ff, name) != noErr)
8252 continue;
8253 p2cstr (name);
8254 if (*name == '.')
8255 continue;
8257 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
8258 continue;
8259 sc = GetTextEncodingBase (encoding);
8260 text_encoding_info = assq_no_quit (make_number (sc),
8261 text_encoding_info_alist);
8262 if (NILP (text_encoding_info))
8263 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
8264 text_encoding_info_alist);
8265 decode_mac_font_name (name, sizeof (name),
8266 XCAR (XCDR (text_encoding_info)));
8267 family = build_string (name);
8268 if (!NILP (Fassoc (family, fm_font_family_alist)))
8269 continue;
8270 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
8271 fm_font_family_alist);
8273 /* Point the instance iterator at the current font family. */
8274 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
8275 continue;
8277 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
8278 == noErr)
8280 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
8282 if (size > 0 || style == normal)
8283 for (; CONSP (rest); rest = XCDR (rest))
8284 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
8288 UNGCPRO;
8290 /* Dispose of the iterators. */
8291 FMDisposeFontFamilyIterator (&ffi);
8292 FMDisposeFontFamilyInstanceIterator (&ffii);
8293 #else /* !TARGET_API_MAC_CARBON */
8294 GrafPtr port;
8295 SInt16 fontnum, old_fontnum;
8296 int num_mac_fonts = CountResources('FOND');
8297 int i, j;
8298 Handle font_handle, font_handle_2;
8299 short id, scriptcode;
8300 ResType type;
8301 Str255 name;
8302 struct FontAssoc *fat;
8303 struct AsscEntry *assc_entry;
8304 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
8305 struct gcpro gcpro1;
8307 GetPort (&port); /* save the current font number used */
8308 old_fontnum = port->txFont;
8310 text_encoding_info_alist = create_text_encoding_info_alist ();
8312 GCPRO1 (text_encoding_info_alist);
8314 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
8316 font_handle = GetIndResource ('FOND', i);
8317 if (!font_handle)
8318 continue;
8320 GetResInfo (font_handle, &id, &type, name);
8321 GetFNum (name, &fontnum);
8322 p2cstr (name);
8323 if (fontnum == 0 || *name == '.')
8324 continue;
8326 TextFont (fontnum);
8327 scriptcode = FontToScript (fontnum);
8328 text_encoding_info = assq_no_quit (make_number (scriptcode),
8329 text_encoding_info_alist);
8330 if (NILP (text_encoding_info))
8331 text_encoding_info = assq_no_quit (make_number (smRoman),
8332 text_encoding_info_alist);
8333 decode_mac_font_name (name, sizeof (name),
8334 XCAR (XCDR (text_encoding_info)));
8335 family = build_string (name);
8336 if (!NILP (Fassoc (family, fm_font_family_alist)))
8337 continue;
8338 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
8339 fm_font_family_alist);
8342 HLock (font_handle);
8344 if (GetResourceSizeOnDisk (font_handle)
8345 >= sizeof (struct FamRec))
8347 fat = (struct FontAssoc *) (*font_handle
8348 + sizeof (struct FamRec));
8349 assc_entry
8350 = (struct AsscEntry *) (*font_handle
8351 + sizeof (struct FamRec)
8352 + sizeof (struct FontAssoc));
8354 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
8356 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
8358 for (; CONSP (rest); rest = XCDR (rest))
8359 add_mac_font_name (name, assc_entry->fontSize,
8360 assc_entry->fontStyle,
8361 SDATA (XCAR (rest)));
8365 HUnlock (font_handle);
8366 font_handle_2 = GetNextFOND (font_handle);
8367 ReleaseResource (font_handle);
8368 font_handle = font_handle_2;
8370 while (ResError () == noErr && font_handle);
8373 UNGCPRO;
8375 TextFont (old_fontnum);
8376 #endif /* !TARGET_API_MAC_CARBON */
8380 void
8381 mac_clear_font_name_table ()
8383 int i;
8385 for (i = 0; i < font_name_count; i++)
8386 xfree (font_name_table[i]);
8387 xfree (font_name_table);
8388 font_name_table = NULL;
8389 font_name_table_size = font_name_count = 0;
8390 fm_font_family_alist = Qnil;
8394 enum xlfd_scalable_field_index
8396 XLFD_SCL_PIXEL_SIZE,
8397 XLFD_SCL_POINT_SIZE,
8398 XLFD_SCL_AVGWIDTH,
8399 XLFD_SCL_LAST
8402 static const int xlfd_scalable_fields[] =
8404 6, /* PIXEL_SIZE */
8405 7, /* POINT_SIZE */
8406 11, /* AVGWIDTH */
8410 static Lisp_Object
8411 mac_do_list_fonts (pattern, maxnames)
8412 const char *pattern;
8413 int maxnames;
8415 int i, n_fonts = 0;
8416 Lisp_Object font_list = Qnil;
8417 struct xlfdpat *pat;
8418 char *scaled;
8419 const char *ptr;
8420 int scl_val[XLFD_SCL_LAST], *val;
8421 const int *field;
8422 int exact;
8424 if (font_name_table == NULL) /* Initialize when first used. */
8425 init_font_name_table ();
8427 for (i = 0; i < XLFD_SCL_LAST; i++)
8428 scl_val[i] = -1;
8430 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8431 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8432 fonts are scaled according to the specified size. */
8433 ptr = pattern;
8434 i = 0;
8435 field = xlfd_scalable_fields;
8436 val = scl_val;
8437 if (*ptr == '-')
8440 ptr++;
8441 if (i == *field)
8443 if ('0' <= *ptr && *ptr <= '9')
8445 *val = *ptr++ - '0';
8446 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
8447 *val = *val * 10 + *ptr++ - '0';
8448 if (*ptr != '-')
8449 *val = -1;
8451 field++;
8452 val++;
8454 ptr = strchr (ptr, '-');
8455 i++;
8457 while (ptr && i < 14);
8459 if (i == 14 && ptr == NULL)
8461 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
8462 scl_val[XLFD_SCL_PIXEL_SIZE] =
8463 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
8464 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
8465 : -1));
8466 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
8467 scl_val[XLFD_SCL_POINT_SIZE] =
8468 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
8469 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
8470 : -1));
8471 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
8472 scl_val[XLFD_SCL_AVGWIDTH] =
8473 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
8474 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
8475 : -1));
8477 else
8478 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
8480 pat = xlfdpat_create (pattern);
8481 if (pat == NULL)
8482 return Qnil;
8484 exact = xlfdpat_exact_p (pat);
8486 for (i = 0; i < font_name_count; i++)
8488 if (xlfdpat_match (pat, font_name_table[i]))
8490 font_list = Fcons (build_string (font_name_table[i]), font_list);
8491 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
8492 break;
8494 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
8495 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
8497 int former_len = ptr - font_name_table[i];
8499 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
8500 memcpy (scaled, font_name_table[i], former_len);
8501 sprintf (scaled + former_len,
8502 "-%d-%d-72-72-m-%d-%s",
8503 scl_val[XLFD_SCL_PIXEL_SIZE],
8504 scl_val[XLFD_SCL_POINT_SIZE],
8505 scl_val[XLFD_SCL_AVGWIDTH],
8506 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
8508 if (xlfdpat_match (pat, scaled))
8510 font_list = Fcons (build_string (scaled), font_list);
8511 xfree (scaled);
8512 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
8513 break;
8515 else
8516 xfree (scaled);
8520 xlfdpat_destroy (pat);
8522 return font_list;
8525 /* Return a list of names of available fonts matching PATTERN on frame F.
8527 Frame F null means we have not yet created any frame on Mac, and
8528 consult the first display in x_display_list. MAXNAMES sets a limit
8529 on how many fonts to match. */
8531 Lisp_Object
8532 x_list_fonts (f, pattern, size, maxnames)
8533 struct frame *f;
8534 Lisp_Object pattern;
8535 int size, maxnames;
8537 Lisp_Object list = Qnil, patterns, tem, key;
8538 struct mac_display_info *dpyinfo
8539 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
8541 xassert (size <= 0);
8543 patterns = Fassoc (pattern, Valternate_fontname_alist);
8544 if (NILP (patterns))
8545 patterns = Fcons (pattern, Qnil);
8547 for (; CONSP (patterns); patterns = XCDR (patterns))
8549 pattern = XCAR (patterns);
8551 if (!STRINGP (pattern))
8552 continue;
8554 tem = XCAR (XCDR (dpyinfo->name_list_element));
8555 key = Fcons (pattern, make_number (maxnames));
8557 list = Fassoc (key, tem);
8558 if (!NILP (list))
8560 list = Fcdr_safe (list);
8561 /* We have a cashed list. Don't have to get the list again. */
8562 goto label_cached;
8565 BLOCK_INPUT;
8566 list = mac_do_list_fonts (SDATA (pattern), maxnames);
8567 UNBLOCK_INPUT;
8569 /* MAC_TODO: add code for matching outline fonts here */
8571 /* Now store the result in the cache. */
8572 XSETCAR (XCDR (dpyinfo->name_list_element),
8573 Fcons (Fcons (key, list),
8574 XCAR (XCDR (dpyinfo->name_list_element))));
8576 label_cached:
8577 if (NILP (list)) continue; /* Try the remaining alternatives. */
8580 return list;
8584 #if GLYPH_DEBUG
8586 /* Check that FONT is valid on frame F. It is if it can be found in F's
8587 font table. */
8589 static void
8590 x_check_font (f, font)
8591 struct frame *f;
8592 XFontStruct *font;
8594 int i;
8595 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8597 xassert (font != NULL);
8599 for (i = 0; i < dpyinfo->n_fonts; i++)
8600 if (dpyinfo->font_table[i].name
8601 && font == dpyinfo->font_table[i].font)
8602 break;
8604 xassert (i < dpyinfo->n_fonts);
8607 #endif /* GLYPH_DEBUG != 0 */
8609 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8610 Note: There are (broken) X fonts out there with invalid XFontStruct
8611 min_bounds contents. For example, handa@etl.go.jp reports that
8612 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8613 have font->min_bounds.width == 0. */
8615 static INLINE void
8616 x_font_min_bounds (font, w, h)
8617 MacFontStruct *font;
8618 int *w, *h;
8620 *h = FONT_HEIGHT (font);
8621 *w = font->min_bounds.width;
8625 /* Compute the smallest character width and smallest font height over
8626 all fonts available on frame F. Set the members smallest_char_width
8627 and smallest_font_height in F's x_display_info structure to
8628 the values computed. Value is non-zero if smallest_font_height or
8629 smallest_char_width become smaller than they were before. */
8631 static int
8632 x_compute_min_glyph_bounds (f)
8633 struct frame *f;
8635 int i;
8636 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8637 MacFontStruct *font;
8638 int old_width = dpyinfo->smallest_char_width;
8639 int old_height = dpyinfo->smallest_font_height;
8641 dpyinfo->smallest_font_height = 100000;
8642 dpyinfo->smallest_char_width = 100000;
8644 for (i = 0; i < dpyinfo->n_fonts; ++i)
8645 if (dpyinfo->font_table[i].name)
8647 struct font_info *fontp = dpyinfo->font_table + i;
8648 int w, h;
8650 font = (MacFontStruct *) fontp->font;
8651 xassert (font != (MacFontStruct *) ~0);
8652 x_font_min_bounds (font, &w, &h);
8654 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8655 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8658 xassert (dpyinfo->smallest_char_width > 0
8659 && dpyinfo->smallest_font_height > 0);
8661 return (dpyinfo->n_fonts == 1
8662 || dpyinfo->smallest_char_width < old_width
8663 || dpyinfo->smallest_font_height < old_height);
8667 /* Determine whether given string is a fully-specified XLFD: all 14
8668 fields are present, none is '*'. */
8670 static int
8671 is_fully_specified_xlfd (p)
8672 const char *p;
8674 int i;
8675 char *q;
8677 if (*p != '-')
8678 return 0;
8680 for (i = 0; i < 13; i++)
8682 q = strchr (p + 1, '-');
8683 if (q == NULL)
8684 return 0;
8685 if (q - p == 2 && *(p + 1) == '*')
8686 return 0;
8687 p = q;
8690 if (strchr (p + 1, '-') != NULL)
8691 return 0;
8693 if (*(p + 1) == '*' && *(p + 2) == '\0')
8694 return 0;
8696 return 1;
8700 /* mac_load_query_font creates and returns an internal representation
8701 for a font in a MacFontStruct struct. There is really no concept
8702 corresponding to "loading" a font on the Mac. But we check its
8703 existence and find the font number and all other information for it
8704 and store them in the returned MacFontStruct. */
8706 static MacFontStruct *
8707 mac_load_query_font (f, fontname)
8708 struct frame *f;
8709 char *fontname;
8711 int size;
8712 char *name;
8713 Str255 family;
8714 Str31 charset;
8715 SInt16 fontnum;
8716 #if USE_ATSUI
8717 static ATSUFontID font_id;
8718 ATSUStyle mac_style = NULL;
8719 #endif
8720 Style fontface;
8721 #if TARGET_API_MAC_CARBON
8722 TextEncoding encoding;
8723 int scriptcode;
8724 #else
8725 short scriptcode;
8726 #endif
8727 MacFontStruct *font;
8728 XCharStruct *space_bounds = NULL, *pcm;
8730 if (is_fully_specified_xlfd (fontname))
8731 name = fontname;
8732 else
8734 Lisp_Object matched_fonts;
8736 matched_fonts = mac_do_list_fonts (fontname, 1);
8737 if (NILP (matched_fonts))
8738 return NULL;
8739 name = SDATA (XCAR (matched_fonts));
8742 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
8743 return NULL;
8745 #if USE_ATSUI
8746 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
8748 OSStatus err;
8749 static const ATSUAttributeTag tags[] =
8750 {kATSUFontTag, kATSUSizeTag,
8751 kATSUQDBoldfaceTag, kATSUQDItalicTag};
8752 static const ByteCount sizes[] =
8753 {sizeof (ATSUFontID), sizeof (Fixed),
8754 sizeof (Boolean), sizeof (Boolean)};
8755 static Fixed size_fixed;
8756 static Boolean bold_p, italic_p;
8757 static const ATSUAttributeValuePtr values[] =
8758 {&font_id, &size_fixed,
8759 &bold_p, &italic_p};
8760 static const ATSUFontFeatureType types[] =
8761 {kAllTypographicFeaturesType, kDiacriticsType};
8762 static const ATSUFontFeatureSelector selectors[] =
8763 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
8764 FMFontStyle style;
8766 font_id = atsu_find_font_from_family_name (family);
8767 if (font_id == kATSUInvalidFontID)
8768 return NULL;
8769 size_fixed = Long2Fix (size);
8770 bold_p = (fontface & bold) != 0;
8771 italic_p = (fontface & italic) != 0;
8772 err = ATSUCreateStyle (&mac_style);
8773 if (err != noErr)
8774 return NULL;
8775 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
8776 types, selectors);
8777 if (err != noErr)
8778 return NULL;
8779 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
8780 tags, sizes, values);
8781 if (err != noErr)
8782 return NULL;
8783 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
8784 if (err != noErr)
8785 fontnum = -1;
8786 scriptcode = kTextEncodingMacUnicode;
8788 else
8789 #endif
8791 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
8793 if (NILP (tmp))
8794 return NULL;
8795 fontnum = XINT (XCDR (tmp));
8796 #if TARGET_API_MAC_CARBON
8797 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
8798 return NULL;
8799 scriptcode = GetTextEncodingBase (encoding);
8800 #else
8801 scriptcode = FontToScript (fontnum);
8802 #endif
8805 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
8807 font->mac_fontnum = fontnum;
8808 font->mac_fontsize = size;
8809 font->mac_fontface = fontface;
8810 font->mac_scriptcode = scriptcode;
8811 #if USE_ATSUI
8812 font->mac_style = mac_style;
8813 #if USE_CG_TEXT_DRAWING
8814 font->cg_font = NULL;
8815 font->cg_glyphs = NULL;
8816 #endif
8817 #endif
8819 /* Apple Japanese (SJIS) font is listed as both
8820 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8821 (Roman script) in init_font_name_table (). The latter should be
8822 treated as a one-byte font. */
8823 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
8824 font->mac_scriptcode = smRoman;
8826 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
8828 #if USE_ATSUI
8829 if (font->mac_style)
8831 OSStatus err;
8832 UniChar c;
8834 font->min_byte1 = 0;
8835 font->max_byte1 = 0xff;
8836 font->min_char_or_byte2 = 0;
8837 font->max_char_or_byte2 = 0xff;
8839 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
8840 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
8841 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
8842 pcm_init (font->bounds.rows[0], 0x100);
8844 #if USE_CG_TEXT_DRAWING
8845 if (fontnum != -1)
8847 FMFontStyle style;
8848 ATSFontRef ats_font;
8850 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
8851 &font_id, &style);
8852 /* Use CG text drawing if italic/bold is not synthesized. */
8853 if (err == noErr && style == fontface)
8855 ats_font = FMGetATSFontRefFromFont (font_id);
8856 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
8860 if (font->cg_font)
8862 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
8863 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
8865 #endif
8866 space_bounds = font->bounds.rows[0] + 0x20;
8867 err = mac_query_char_extents (font->mac_style, 0x20,
8868 &font->ascent, &font->descent,
8869 space_bounds,
8870 #if USE_CG_TEXT_DRAWING
8871 (font->cg_glyphs ? font->cg_glyphs + 0x20
8872 : NULL)
8873 #else
8874 NULL
8875 #endif
8877 if (err != noErr
8878 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
8880 mac_unload_font (&one_mac_display_info, font);
8881 return NULL;
8884 pcm = font->bounds.rows[0];
8885 for (c = 0x21; c <= 0xff; c++)
8887 if (c == 0xad)
8888 /* Soft hyphen is not supported in ATSUI. */
8889 continue;
8890 else if (c == 0x7f)
8892 #if USE_CG_TEXT_DRAWING
8893 if (font->cg_glyphs)
8895 c = 0x9f;
8896 pcm = NULL;
8897 continue;
8899 #endif
8900 break;
8903 mac_query_char_extents (font->mac_style, c, NULL, NULL,
8904 pcm ? pcm + c : NULL,
8905 #if USE_CG_TEXT_DRAWING
8906 (font->cg_glyphs ? font->cg_glyphs + c
8907 : NULL)
8908 #else
8909 NULL
8910 #endif
8913 #if USE_CG_TEXT_DRAWING
8914 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
8916 /* Don't use CG text drawing if font substitution occurs in
8917 ASCII or Latin-1 characters. */
8918 CGFontRelease (font->cg_font);
8919 font->cg_font = NULL;
8920 xfree (font->cg_glyphs);
8921 font->cg_glyphs = NULL;
8922 if (pcm == NULL)
8923 break;
8925 #endif
8928 else
8929 #endif
8931 OSStatus err;
8932 FontInfo the_fontinfo;
8933 int is_two_byte_font;
8935 #if USE_CG_DRAWING
8936 mac_prepare_for_quickdraw (f);
8937 #endif
8938 SetPortWindowPort (FRAME_MAC_WINDOW (f));
8940 TextFont (fontnum);
8941 TextSize (size);
8942 TextFace (fontface);
8944 GetFontInfo (&the_fontinfo);
8946 font->ascent = the_fontinfo.ascent;
8947 font->descent = the_fontinfo.descent;
8949 is_two_byte_font = (font->mac_scriptcode == smJapanese
8950 || font->mac_scriptcode == smTradChinese
8951 || font->mac_scriptcode == smSimpChinese
8952 || font->mac_scriptcode == smKorean);
8954 if (is_two_byte_font)
8956 int char_width;
8958 font->min_byte1 = 0xa1;
8959 font->max_byte1 = 0xfe;
8960 font->min_char_or_byte2 = 0xa1;
8961 font->max_char_or_byte2 = 0xfe;
8963 /* Use the width of an "ideographic space" of that font
8964 because the_fontinfo.widMax returns the wrong width for
8965 some fonts. */
8966 switch (font->mac_scriptcode)
8968 case smJapanese:
8969 font->min_byte1 = 0x81;
8970 font->max_byte1 = 0xfc;
8971 font->min_char_or_byte2 = 0x40;
8972 font->max_char_or_byte2 = 0xfc;
8973 char_width = StringWidth("\p\x81\x40");
8974 break;
8975 case smTradChinese:
8976 font->min_char_or_byte2 = 0x40;
8977 char_width = StringWidth("\p\xa1\x40");
8978 break;
8979 case smSimpChinese:
8980 char_width = StringWidth("\p\xa1\xa1");
8981 break;
8982 case smKorean:
8983 char_width = StringWidth("\p\xa1\xa1");
8984 break;
8987 font->bounds.per_char = NULL;
8989 if (fontface & italic)
8990 font->max_bounds.rbearing = char_width + 1;
8991 else
8992 font->max_bounds.rbearing = char_width;
8993 font->max_bounds.lbearing = 0;
8994 font->max_bounds.width = char_width;
8995 font->max_bounds.ascent = the_fontinfo.ascent;
8996 font->max_bounds.descent = the_fontinfo.descent;
8998 font->min_bounds = font->max_bounds;
9000 else
9002 int c;
9004 font->min_byte1 = font->max_byte1 = 0;
9005 font->min_char_or_byte2 = 0x20;
9006 font->max_char_or_byte2 = 0xff;
9008 font->bounds.per_char =
9009 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
9010 bzero (font->bounds.per_char,
9011 sizeof (XCharStruct) * (0xff - 0x20 + 1));
9013 space_bounds = font->bounds.per_char;
9014 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
9015 &font->descent, space_bounds, NULL);
9016 if (err != noErr || space_bounds->width <= 0)
9018 mac_unload_font (&one_mac_display_info, font);
9019 return NULL;
9022 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
9023 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
9027 if (space_bounds)
9029 int c;
9031 font->min_bounds = font->max_bounds = *space_bounds;
9032 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
9033 if (pcm->width > 0)
9035 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
9036 pcm->lbearing);
9037 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
9038 pcm->rbearing);
9039 font->min_bounds.width = min (font->min_bounds.width,
9040 pcm->width);
9041 font->min_bounds.ascent = min (font->min_bounds.ascent,
9042 pcm->ascent);
9043 font->min_bounds.descent = min (font->min_bounds.descent,
9044 pcm->descent);
9046 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
9047 pcm->lbearing);
9048 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
9049 pcm->rbearing);
9050 font->max_bounds.width = max (font->max_bounds.width,
9051 pcm->width);
9052 font->max_bounds.ascent = max (font->max_bounds.ascent,
9053 pcm->ascent);
9054 font->max_bounds.descent = max (font->max_bounds.descent,
9055 pcm->descent);
9057 if (
9058 #if USE_ATSUI
9059 font->mac_style == NULL &&
9060 #endif
9061 font->max_bounds.width == font->min_bounds.width
9062 && font->min_bounds.lbearing >= 0
9063 && font->max_bounds.rbearing <= font->max_bounds.width)
9065 /* Fixed width and no overhangs. */
9066 xfree (font->bounds.per_char);
9067 font->bounds.per_char = NULL;
9071 #if !defined (MAC_OS8) || USE_ATSUI
9072 /* AppKit and WebKit do some adjustment to the heights of Courier,
9073 Helvetica, and Times. This only works on the environments where
9074 srcCopy text transfer mode is never used. */
9075 if (
9076 #ifdef MAC_OS8 /* implies USE_ATSUI */
9077 font->mac_style &&
9078 #endif
9079 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
9080 || strcmp (family, "times") == 0))
9081 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
9082 #endif
9084 return font;
9088 void
9089 mac_unload_font (dpyinfo, font)
9090 struct mac_display_info *dpyinfo;
9091 XFontStruct *font;
9093 xfree (font->full_name);
9094 #if USE_ATSUI
9095 if (font->mac_style)
9097 int i;
9099 for (i = font->min_byte1; i <= font->max_byte1; i++)
9100 if (font->bounds.rows[i])
9101 xfree (font->bounds.rows[i]);
9102 xfree (font->bounds.rows);
9103 ATSUDisposeStyle (font->mac_style);
9105 else
9106 #endif
9107 if (font->bounds.per_char)
9108 xfree (font->bounds.per_char);
9109 #if USE_CG_TEXT_DRAWING
9110 if (font->cg_font)
9111 CGFontRelease (font->cg_font);
9112 if (font->cg_glyphs)
9113 xfree (font->cg_glyphs);
9114 #endif
9115 xfree (font);
9119 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9120 pointer to the structure font_info while allocating it dynamically.
9121 If SIZE is 0, load any size of font.
9122 If loading is failed, return NULL. */
9124 struct font_info *
9125 x_load_font (f, fontname, size)
9126 struct frame *f;
9127 register char *fontname;
9128 int size;
9130 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9131 Lisp_Object font_names;
9133 /* Get a list of all the fonts that match this name. Once we
9134 have a list of matching fonts, we compare them against the fonts
9135 we already have by comparing names. */
9136 font_names = x_list_fonts (f, build_string (fontname), size, 1);
9138 if (!NILP (font_names))
9140 Lisp_Object tail;
9141 int i;
9143 for (i = 0; i < dpyinfo->n_fonts; i++)
9144 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
9145 if (dpyinfo->font_table[i].name
9146 && (!strcmp (dpyinfo->font_table[i].name,
9147 SDATA (XCAR (tail)))
9148 || !strcmp (dpyinfo->font_table[i].full_name,
9149 SDATA (XCAR (tail)))))
9150 return (dpyinfo->font_table + i);
9152 else
9153 return NULL;
9155 /* Load the font and add it to the table. */
9157 struct MacFontStruct *font;
9158 struct font_info *fontp;
9159 int i;
9161 fontname = (char *) SDATA (XCAR (font_names));
9163 BLOCK_INPUT;
9164 font = mac_load_query_font (f, fontname);
9165 UNBLOCK_INPUT;
9166 if (!font)
9167 return NULL;
9169 /* Find a free slot in the font table. */
9170 for (i = 0; i < dpyinfo->n_fonts; ++i)
9171 if (dpyinfo->font_table[i].name == NULL)
9172 break;
9174 /* If no free slot found, maybe enlarge the font table. */
9175 if (i == dpyinfo->n_fonts
9176 && dpyinfo->n_fonts == dpyinfo->font_table_size)
9178 int sz;
9179 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
9180 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
9181 dpyinfo->font_table
9182 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
9185 fontp = dpyinfo->font_table + i;
9186 if (i == dpyinfo->n_fonts)
9187 ++dpyinfo->n_fonts;
9189 /* Now fill in the slots of *FONTP. */
9190 BLOCK_INPUT;
9191 bzero (fontp, sizeof (*fontp));
9192 fontp->font = font;
9193 fontp->font_idx = i;
9194 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
9195 bcopy (fontname, fontp->name, strlen (fontname) + 1);
9197 if (font->min_bounds.width == font->max_bounds.width)
9199 /* Fixed width font. */
9200 fontp->average_width = fontp->space_width = font->min_bounds.width;
9202 else
9204 XChar2b char2b;
9205 XCharStruct *pcm;
9207 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
9208 pcm = mac_per_char_metric (font, &char2b, 0);
9209 if (pcm)
9210 fontp->space_width = pcm->width;
9211 else
9212 fontp->space_width = FONT_WIDTH (font);
9214 if (pcm)
9216 int width = pcm->width;
9217 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
9218 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
9219 width += pcm->width;
9220 fontp->average_width = width / 95;
9222 else
9223 fontp->average_width = FONT_WIDTH (font);
9226 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
9227 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
9229 fontp->size = font->max_bounds.width;
9230 fontp->height = FONT_HEIGHT (font);
9232 /* For some font, ascent and descent in max_bounds field is
9233 larger than the above value. */
9234 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
9235 if (max_height > fontp->height)
9236 fontp->height = max_height;
9239 /* The slot `encoding' specifies how to map a character
9240 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9241 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9242 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9243 2:0xA020..0xFF7F). For the moment, we don't know which charset
9244 uses this font. So, we set information in fontp->encoding[1]
9245 which is never used by any charset. If mapping can't be
9246 decided, set FONT_ENCODING_NOT_DECIDED. */
9247 if (font->mac_scriptcode == smJapanese)
9248 fontp->encoding[1] = 4;
9249 else
9251 fontp->encoding[1]
9252 = (font->max_byte1 == 0
9253 /* 1-byte font */
9254 ? (font->min_char_or_byte2 < 0x80
9255 ? (font->max_char_or_byte2 < 0x80
9256 ? 0 /* 0x20..0x7F */
9257 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
9258 : 1) /* 0xA0..0xFF */
9259 /* 2-byte font */
9260 : (font->min_byte1 < 0x80
9261 ? (font->max_byte1 < 0x80
9262 ? (font->min_char_or_byte2 < 0x80
9263 ? (font->max_char_or_byte2 < 0x80
9264 ? 0 /* 0x2020..0x7F7F */
9265 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
9266 : 3) /* 0x20A0..0x7FFF */
9267 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
9268 : (font->min_char_or_byte2 < 0x80
9269 ? (font->max_char_or_byte2 < 0x80
9270 ? 2 /* 0xA020..0xFF7F */
9271 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
9272 : 1))); /* 0xA0A0..0xFFFF */
9275 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9276 fontp->baseline_offset
9277 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
9278 ? (long) value : 0);
9279 fontp->relative_compose
9280 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
9281 ? (long) value : 0);
9282 fontp->default_ascent
9283 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
9284 ? (long) value : 0);
9285 #else
9286 fontp->baseline_offset = 0;
9287 fontp->relative_compose = 0;
9288 fontp->default_ascent = 0;
9289 #endif
9291 /* Set global flag fonts_changed_p to non-zero if the font loaded
9292 has a character with a smaller width than any other character
9293 before, or if the font loaded has a smaller height than any
9294 other font loaded before. If this happens, it will make a
9295 glyph matrix reallocation necessary. */
9296 fonts_changed_p |= x_compute_min_glyph_bounds (f);
9297 UNBLOCK_INPUT;
9298 return fontp;
9303 /* Return a pointer to struct font_info of a font named FONTNAME for
9304 frame F. If no such font is loaded, return NULL. */
9306 struct font_info *
9307 x_query_font (f, fontname)
9308 struct frame *f;
9309 register char *fontname;
9311 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9312 int i;
9314 for (i = 0; i < dpyinfo->n_fonts; i++)
9315 if (dpyinfo->font_table[i].name
9316 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
9317 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
9318 return (dpyinfo->font_table + i);
9319 return NULL;
9323 /* Find a CCL program for a font specified by FONTP, and set the member
9324 `encoder' of the structure. */
9326 void
9327 x_find_ccl_program (fontp)
9328 struct font_info *fontp;
9330 Lisp_Object list, elt;
9332 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
9334 elt = XCAR (list);
9335 if (CONSP (elt)
9336 && STRINGP (XCAR (elt))
9337 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
9338 >= 0))
9339 break;
9341 if (! NILP (list))
9343 struct ccl_program *ccl
9344 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
9346 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
9347 xfree (ccl);
9348 else
9349 fontp->font_encoder = ccl;
9353 #if USE_MAC_FONT_PANEL
9354 /* Whether Font Panel has been shown before. The first call to font
9355 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9356 slow. This variable is used for deferring such a call as much as
9357 possible. */
9358 static int font_panel_shown_p = 0;
9360 extern Lisp_Object Qfont;
9361 static Lisp_Object Qpanel_closed, Qselection;
9363 static OSStatus mac_store_event_ref_as_apple_event P_ ((AEEventClass, AEEventID,
9364 Lisp_Object,
9365 Lisp_Object,
9366 EventRef, UInt32,
9367 const EventParamName *,
9368 const EventParamType *));
9371 mac_font_panel_visible_p ()
9373 return font_panel_shown_p && FPIsFontPanelVisible ();
9376 static pascal OSStatus
9377 mac_handle_font_event (next_handler, event, data)
9378 EventHandlerCallRef next_handler;
9379 EventRef event;
9380 void *data;
9382 OSStatus result, err;
9383 Lisp_Object id_key;
9384 int num_params;
9385 const EventParamName *names;
9386 const EventParamType *types;
9387 static const EventParamName names_sel[] = {kEventParamATSUFontID,
9388 kEventParamATSUFontSize,
9389 kEventParamFMFontFamily,
9390 kEventParamFMFontStyle,
9391 kEventParamFMFontSize,
9392 kEventParamFontColor};
9393 static const EventParamType types_sel[] = {typeATSUFontID,
9394 typeATSUSize,
9395 typeFMFontFamily,
9396 typeFMFontStyle,
9397 typeFMFontSize,
9398 typeFontColor};
9400 result = CallNextEventHandler (next_handler, event);
9401 if (result != eventNotHandledErr)
9402 return result;
9404 switch (GetEventKind (event))
9406 case kEventFontPanelClosed:
9407 id_key = Qpanel_closed;
9408 num_params = 0;
9409 names = NULL;
9410 types = NULL;
9411 break;
9413 case kEventFontSelection:
9414 id_key = Qselection;
9415 num_params = sizeof (names_sel) / sizeof (names_sel[0]);
9416 names = names_sel;
9417 types = types_sel;
9418 break;
9421 err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
9422 event, num_params,
9423 names, types);
9424 if (err == noErr)
9425 result = noErr;
9427 return result;
9430 OSStatus
9431 mac_show_hide_font_panel ()
9433 if (!font_panel_shown_p)
9435 OSStatus err;
9437 static const EventTypeSpec specs[] =
9438 {{kEventClassFont, kEventFontPanelClosed},
9439 {kEventClassFont, kEventFontSelection}};
9441 err = InstallApplicationEventHandler (mac_handle_font_event,
9442 GetEventTypeCount (specs),
9443 specs, NULL, NULL);
9444 if (err != noErr)
9445 return err;
9447 font_panel_shown_p = 1;
9450 return FPShowHideFontPanel ();
9453 OSStatus
9454 mac_set_font_info_for_selection (f, face_id, c)
9455 struct frame *f;
9456 int face_id, c;
9458 OSStatus err;
9459 EventTargetRef target = NULL;
9460 XFontStruct *font = NULL;
9462 if (!mac_font_panel_visible_p ())
9463 return noErr;
9465 if (f)
9467 target = GetWindowEventTarget (FRAME_MAC_WINDOW (f));
9469 if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0))
9471 struct face *face;
9473 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
9474 face = FACE_FROM_ID (f, face_id);
9475 font = face->font;
9479 if (font == NULL)
9480 err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target);
9481 else
9483 if (font->mac_fontnum != -1)
9485 FontSelectionQDStyle qd_style;
9487 qd_style.version = kFontSelectionQDStyleVersionZero;
9488 qd_style.instance.fontFamily = font->mac_fontnum;
9489 qd_style.instance.fontStyle = font->mac_fontface;
9490 qd_style.size = font->mac_fontsize;
9491 qd_style.hasColor = false;
9493 err = SetFontInfoForSelection (kFontSelectionQDType,
9494 1, &qd_style, target);
9496 else
9497 err = SetFontInfoForSelection (kFontSelectionATSUIType,
9498 1, &font->mac_style, target);
9501 return err;
9503 #endif
9506 /* The Mac Event loop code */
9508 #if !TARGET_API_MAC_CARBON
9509 #include <Events.h>
9510 #include <Quickdraw.h>
9511 #include <Balloons.h>
9512 #include <Devices.h>
9513 #include <Fonts.h>
9514 #include <Gestalt.h>
9515 #include <Menus.h>
9516 #include <Processes.h>
9517 #include <Sound.h>
9518 #include <ToolUtils.h>
9519 #include <TextUtils.h>
9520 #include <Dialogs.h>
9521 #include <Script.h>
9522 #include <Types.h>
9523 #include <Resources.h>
9525 #if __MWERKS__
9526 #include <unix.h>
9527 #endif
9528 #endif /* ! TARGET_API_MAC_CARBON */
9530 #define M_APPLE 234
9531 #define I_ABOUT 1
9533 #define DEFAULT_NUM_COLS 80
9535 #define MIN_DOC_SIZE 64
9536 #define MAX_DOC_SIZE 32767
9538 #define EXTRA_STACK_ALLOC (256 * 1024)
9540 #define ARGV_STRING_LIST_ID 129
9541 #define ABOUT_ALERT_ID 128
9542 #define RAM_TOO_LARGE_ALERT_ID 129
9544 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9545 Lisp_Object Qreverse;
9548 /* Modifier associated with the control key, or nil to ignore. */
9549 Lisp_Object Vmac_control_modifier;
9551 /* Modifier associated with the option key, or nil to ignore. */
9552 Lisp_Object Vmac_option_modifier;
9554 /* Modifier associated with the command key, or nil to ignore. */
9555 Lisp_Object Vmac_command_modifier;
9557 /* Modifier associated with the function key, or nil to ignore. */
9558 Lisp_Object Vmac_function_modifier;
9560 /* True if the option and command modifiers should be used to emulate
9561 a three button mouse */
9562 Lisp_Object Vmac_emulate_three_button_mouse;
9564 #if TARGET_API_MAC_CARBON
9565 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9566 mouse-2, instead of mouse-3. */
9567 int mac_wheel_button_is_mouse_2;
9569 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9570 for processing before Emacs sees it. */
9571 int mac_pass_command_to_system;
9573 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9574 for processing before Emacs sees it. */
9575 int mac_pass_control_to_system;
9576 #endif
9578 /* Points to the variable `inev' in the function XTread_socket. It is
9579 used for passing an input event to the function back from
9580 Carbon/Apple event handlers. */
9581 static struct input_event *read_socket_inev = NULL;
9583 /* Whether or not the screen configuration has changed. */
9584 static int mac_screen_config_changed = 0;
9586 Point saved_menu_event_location;
9588 /* Apple Events */
9589 #if TARGET_API_MAC_CARBON
9590 static Lisp_Object Qhi_command;
9591 #ifdef MAC_OSX
9592 extern Lisp_Object Qwindow;
9593 static Lisp_Object Qtoolbar_switch_mode;
9594 #endif
9595 #if USE_MAC_TSM
9596 static TSMDocumentID tsm_document_id;
9597 static Lisp_Object Qtext_input;
9598 static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
9599 static Lisp_Object Vmac_ts_active_input_overlay;
9600 extern Lisp_Object Qbefore_string;
9601 static Lisp_Object Vmac_ts_script_language_on_focus;
9602 static Lisp_Object saved_ts_script_language_on_focus;
9603 static ScriptLanguageRecord saved_ts_language;
9604 static Component saved_ts_component;
9605 #endif
9606 #endif /* TARGET_API_MAC_CARBON */
9607 extern int mac_ready_for_apple_events;
9608 extern Lisp_Object Qundefined;
9609 extern void init_apple_event_handler P_ ((void));
9610 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
9611 Lisp_Object *, Lisp_Object *,
9612 Lisp_Object *));
9613 extern OSErr init_coercion_handler P_ ((void));
9615 /* Drag and Drop */
9616 extern OSErr install_drag_handler P_ ((WindowRef));
9617 extern void remove_drag_handler P_ ((WindowRef));
9619 #if TARGET_API_MAC_CARBON
9620 /* Showing help echo string during menu tracking */
9621 extern OSStatus install_menu_target_item_handler P_ ((void));
9623 #ifdef MAC_OSX
9624 extern OSStatus install_service_handler ();
9625 static Lisp_Object Qservice, Qpaste, Qperform;
9626 #endif
9627 #endif
9629 extern void init_emacs_passwd_dir ();
9630 extern int emacs_main (int, char **, char **);
9632 extern void initialize_applescript();
9633 extern void terminate_applescript();
9635 /* Table for translating Mac keycode to X keysym values. Contributed
9636 by Sudhir Shenoy.
9637 Mapping for special keys is now identical to that in Apple X11
9638 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9639 on the right of the Cmd key on laptops, and fn + `enter' (->
9640 <linefeed>). */
9641 static const unsigned char keycode_to_xkeysym_table[] = {
9642 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9643 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9644 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9646 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9647 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9648 /*0x38*/ 0, 0, 0, 0,
9649 /*0x3C*/ 0, 0, 0, 0,
9651 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9652 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9653 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9654 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9656 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9657 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9658 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9659 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9661 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9662 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9663 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9664 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9666 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9667 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9668 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9669 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9672 #ifdef MAC_OSX
9673 /* Table for translating Mac keycode with the laptop `fn' key to that
9674 without it. Destination symbols in comments are keys on US
9675 keyboard, and they may not be the same on other types of keyboards.
9676 If the destination is identical to the source (f1 ... f12), it
9677 doesn't map `fn' key to a modifier. */
9678 static const unsigned char fn_keycode_to_keycode_table[] = {
9679 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9680 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9681 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9683 /*0x30*/ 0, 0, 0, 0,
9684 /*0x34*/ 0, 0, 0, 0,
9685 /*0x38*/ 0, 0, 0, 0,
9686 /*0x3C*/ 0, 0, 0, 0,
9688 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9689 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9690 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9691 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9693 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9694 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9695 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9696 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9698 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9699 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9700 /*0x68*/ 0, 0, 0, 0,
9701 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9703 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9704 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9705 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9706 /*0x7C*/ 0, 0, 0, 0
9708 #endif /* MAC_OSX */
9710 static int
9711 #if TARGET_API_MAC_CARBON
9712 mac_to_emacs_modifiers (UInt32 mods)
9713 #else
9714 mac_to_emacs_modifiers (EventModifiers mods)
9715 #endif
9717 unsigned int result = 0;
9718 if (mods & shiftKey)
9719 result |= shift_modifier;
9721 /* Deactivated to simplify configuration:
9722 if Vmac_option_modifier is non-NIL, we fully process the Option
9723 key. Otherwise, we only process it if an additional Ctrl or Command
9724 is pressed. That way the system may convert the character to a
9725 composed one.
9726 if ((mods & optionKey) &&
9727 (( !NILP(Vmac_option_modifier) ||
9728 ((mods & cmdKey) || (mods & controlKey))))) */
9730 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
9731 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
9732 if (INTEGERP(val))
9733 result |= XUINT(val);
9735 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
9736 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
9737 if (INTEGERP(val))
9738 result |= XUINT(val);
9740 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
9741 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
9742 if (INTEGERP(val))
9743 result |= XUINT(val);
9746 #ifdef MAC_OSX
9747 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
9748 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
9749 if (INTEGERP(val))
9750 result |= XUINT(val);
9752 #endif
9754 return result;
9757 static UInt32
9758 mac_mapped_modifiers (modifiers)
9759 UInt32 modifiers;
9761 UInt32 mapped_modifiers_all =
9762 (NILP (Vmac_control_modifier) ? 0 : controlKey)
9763 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
9764 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
9766 #ifdef MAC_OSX
9767 mapped_modifiers_all |=
9768 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
9769 #endif
9771 return mapped_modifiers_all & modifiers;
9774 static int
9775 mac_get_emulated_btn ( UInt32 modifiers )
9777 int result = 0;
9778 if (!NILP (Vmac_emulate_three_button_mouse)) {
9779 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
9780 if (modifiers & cmdKey)
9781 result = cmdIs3 ? 2 : 1;
9782 else if (modifiers & optionKey)
9783 result = cmdIs3 ? 1 : 2;
9785 return result;
9788 #if TARGET_API_MAC_CARBON
9789 /***** Code to handle C-g testing *****/
9790 extern int quit_char;
9791 extern int make_ctrl_char P_ ((int));
9794 mac_quit_char_key_p (modifiers, key_code)
9795 UInt32 modifiers, key_code;
9797 UInt32 char_code;
9798 unsigned long some_state = 0;
9799 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9800 int c, emacs_modifiers;
9802 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9803 key_code |= (modifiers & ~(mac_mapped_modifiers (modifiers)));
9804 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
9805 if (char_code & ~0xff)
9806 return 0;
9808 emacs_modifiers = mac_to_emacs_modifiers (modifiers);
9809 if (emacs_modifiers & ctrl_modifier)
9810 c = make_ctrl_char (char_code);
9812 c |= (emacs_modifiers
9813 & (meta_modifier | alt_modifier
9814 | hyper_modifier | super_modifier));
9816 return c == quit_char;
9818 #endif
9820 #if TARGET_API_MAC_CARBON
9821 /* Obtains the event modifiers from the event ref and then calls
9822 mac_to_emacs_modifiers. */
9823 static int
9824 mac_event_to_emacs_modifiers (EventRef eventRef)
9826 UInt32 mods = 0, class;
9828 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
9829 sizeof (UInt32), NULL, &mods);
9830 class = GetEventClass (eventRef);
9831 if (!NILP (Vmac_emulate_three_button_mouse) &&
9832 (class == kEventClassMouse || class == kEventClassCommand))
9834 mods &= ~(optionKey | cmdKey);
9836 return mac_to_emacs_modifiers (mods);
9839 /* Given an event ref, return the code to use for the mouse button
9840 code in the emacs input_event. */
9841 static int
9842 mac_get_mouse_btn (EventRef ref)
9844 EventMouseButton result = kEventMouseButtonPrimary;
9845 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
9846 sizeof (EventMouseButton), NULL, &result);
9847 switch (result)
9849 case kEventMouseButtonPrimary:
9850 if (NILP (Vmac_emulate_three_button_mouse))
9851 return 0;
9852 else {
9853 UInt32 mods = 0;
9854 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
9855 sizeof (UInt32), NULL, &mods);
9856 return mac_get_emulated_btn(mods);
9858 case kEventMouseButtonSecondary:
9859 return mac_wheel_button_is_mouse_2 ? 2 : 1;
9860 case kEventMouseButtonTertiary:
9861 case 4: /* 4 is the number for the mouse wheel button */
9862 return mac_wheel_button_is_mouse_2 ? 1 : 2;
9863 default:
9864 return 0;
9868 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9869 events. However the click of the mouse wheel is not converted to a
9870 mouseDown or mouseUp event. Likewise for dead key events. This
9871 calls ConvertEventRefToEventRecord, but then checks to see if it is
9872 a mouse up/down, or a dead key Carbon event that has not been
9873 converted, and if so, converts it by hand (to be picked up in the
9874 XTread_socket loop). */
9875 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
9877 OSStatus err;
9878 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
9879 EventKind action;
9881 if (result)
9882 return result;
9884 switch (GetEventClass (eventRef))
9886 case kEventClassMouse:
9887 switch (GetEventKind (eventRef))
9889 case kEventMouseDown:
9890 eventRec->what = mouseDown;
9891 result = 1;
9892 break;
9894 case kEventMouseUp:
9895 eventRec->what = mouseUp;
9896 result = 1;
9897 break;
9899 default:
9900 break;
9902 break;
9904 case kEventClassKeyboard:
9905 switch (GetEventKind (eventRef))
9907 case kEventRawKeyDown:
9908 action = keyDown;
9909 goto keystroke_common;
9910 case kEventRawKeyRepeat:
9911 action = autoKey;
9912 goto keystroke_common;
9913 case kEventRawKeyUp:
9914 action = keyUp;
9915 keystroke_common:
9917 unsigned char char_codes;
9918 UInt32 key_code;
9920 err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes,
9921 typeChar, NULL, sizeof (char),
9922 NULL, &char_codes);
9923 if (err == noErr)
9924 err = GetEventParameter (eventRef, kEventParamKeyCode,
9925 typeUInt32, NULL, sizeof (UInt32),
9926 NULL, &key_code);
9927 if (err == noErr)
9929 eventRec->what = action;
9930 eventRec->message = char_codes | ((key_code & 0xff) << 8);
9931 result = 1;
9934 break;
9936 default:
9937 break;
9939 break;
9941 default:
9942 break;
9945 if (result)
9947 /* Need where and when. */
9948 UInt32 mods = 0;
9950 GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
9951 NULL, sizeof (Point), NULL, &eventRec->where);
9952 /* Use two step process because new event modifiers are 32-bit
9953 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9954 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
9955 NULL, sizeof (UInt32), NULL, &mods);
9956 eventRec->modifiers = mods;
9958 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
9961 return result;
9964 #endif
9966 #ifdef MAC_OS8
9967 static void
9968 do_get_menus (void)
9970 Handle menubar_handle;
9971 MenuRef menu;
9973 menubar_handle = GetNewMBar (128);
9974 if(menubar_handle == NULL)
9975 abort ();
9976 SetMenuBar (menubar_handle);
9977 DrawMenuBar ();
9979 #if !TARGET_API_MAC_CARBON
9980 menu = GetMenuRef (M_APPLE);
9981 if (menu != NULL)
9982 AppendResMenu (menu, 'DRVR');
9983 else
9984 abort ();
9985 #endif
9989 static void
9990 do_init_managers (void)
9992 #if !TARGET_API_MAC_CARBON
9993 InitGraf (&qd.thePort);
9994 InitFonts ();
9995 FlushEvents (everyEvent, 0);
9996 InitWindows ();
9997 InitMenus ();
9998 TEInit ();
9999 InitDialogs (NULL);
10000 #endif /* !TARGET_API_MAC_CARBON */
10001 InitCursor ();
10003 #if !TARGET_API_MAC_CARBON
10004 /* set up some extra stack space for use by emacs */
10005 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
10007 /* MaxApplZone must be called for AppleScript to execute more
10008 complicated scripts */
10009 MaxApplZone ();
10010 MoreMasters ();
10011 #endif /* !TARGET_API_MAC_CARBON */
10014 static void
10015 do_check_ram_size (void)
10017 SInt32 physical_ram_size, logical_ram_size;
10019 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
10020 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
10021 || physical_ram_size > (1 << VALBITS)
10022 || logical_ram_size > (1 << VALBITS))
10024 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
10025 exit (1);
10028 #endif /* MAC_OS8 */
10030 static void
10031 do_window_update (WindowRef win)
10033 struct frame *f = mac_window_to_frame (win);
10035 BeginUpdate (win);
10037 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10038 below. */
10039 if (win != tip_window)
10041 if (f->async_visible == 0)
10043 /* Update events may occur when a frame gets iconified. */
10044 #if 0
10045 f->async_visible = 1;
10046 f->async_iconified = 0;
10047 SET_FRAME_GARBAGED (f);
10048 #endif
10050 else
10052 Rect r;
10053 #if TARGET_API_MAC_CARBON
10054 RgnHandle region = NewRgn ();
10056 GetPortVisibleRegion (GetWindowPort (win), region);
10057 GetRegionBounds (region, &r);
10058 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
10059 #if USE_CG_DRAWING
10060 mac_prepare_for_quickdraw (f);
10061 #endif
10062 UpdateControls (win, region);
10063 DisposeRgn (region);
10064 #else
10065 r = (*win->visRgn)->rgnBBox;
10066 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
10067 UpdateControls (win, win->visRgn);
10068 #endif
10072 EndUpdate (win);
10075 static int
10076 is_emacs_window (WindowRef win)
10078 Lisp_Object tail, frame;
10080 if (!win)
10081 return 0;
10083 FOR_EACH_FRAME (tail, frame)
10084 if (FRAME_MAC_P (XFRAME (frame)))
10085 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
10086 return 1;
10088 return 0;
10091 #if USE_MAC_TSM
10092 static OSStatus
10093 mac_tsm_resume ()
10095 OSStatus err;
10096 ScriptLanguageRecord slrec, *slptr = NULL;
10098 err = ActivateTSMDocument (tsm_document_id);
10100 if (err == noErr)
10102 if (EQ (Vmac_ts_script_language_on_focus, Qt)
10103 && EQ (saved_ts_script_language_on_focus, Qt))
10104 slptr = &saved_ts_language;
10105 else if (CONSP (Vmac_ts_script_language_on_focus)
10106 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
10107 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
10108 && CONSP (saved_ts_script_language_on_focus)
10109 && EQ (XCAR (saved_ts_script_language_on_focus),
10110 XCAR (Vmac_ts_script_language_on_focus))
10111 && EQ (XCDR (saved_ts_script_language_on_focus),
10112 XCDR (Vmac_ts_script_language_on_focus)))
10114 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
10115 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
10116 slptr = &slrec;
10120 if (slptr)
10122 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10123 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
10124 kKeyboardInputMethodClass);
10125 #else
10126 err = SetDefaultInputMethod (saved_ts_component, slptr);
10127 #endif
10128 if (err == noErr)
10129 err = SetTextServiceLanguage (slptr);
10131 /* Seems to be needed on Mac OS X 10.2. */
10132 if (err == noErr)
10133 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
10136 return err;
10139 static OSStatus
10140 mac_tsm_suspend ()
10142 OSStatus err;
10143 ScriptLanguageRecord slrec, *slptr = NULL;
10145 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
10147 if (EQ (Vmac_ts_script_language_on_focus, Qt))
10149 err = GetTextServiceLanguage (&saved_ts_language);
10150 if (err == noErr)
10151 slptr = &saved_ts_language;
10153 else if (CONSP (Vmac_ts_script_language_on_focus)
10154 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
10155 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
10157 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
10158 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
10159 slptr = &slrec;
10162 if (slptr)
10164 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10165 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
10166 kKeyboardInputMethodClass);
10167 #else
10168 GetDefaultInputMethod (&saved_ts_component, slptr);
10169 #endif
10172 err = DeactivateTSMDocument (tsm_document_id);
10174 return err;
10176 #endif
10178 #if !TARGET_API_MAC_CARBON
10179 void
10180 do_apple_menu (SInt16 menu_item)
10182 Str255 item_name;
10183 SInt16 da_driver_refnum;
10185 if (menu_item == I_ABOUT)
10186 NoteAlert (ABOUT_ALERT_ID, NULL);
10187 else
10189 GetMenuItemText (GetMenuRef (M_APPLE), menu_item, item_name);
10190 da_driver_refnum = OpenDeskAcc (item_name);
10193 #endif /* !TARGET_API_MAC_CARBON */
10195 /* Handle drags in size box. Based on code contributed by Ben
10196 Mesander and IM - Window Manager A. */
10198 static void
10199 do_grow_window (w, e)
10200 WindowRef w;
10201 const EventRecord *e;
10203 Rect limit_rect;
10204 int rows, columns, width, height;
10205 struct frame *f = mac_window_to_frame (w);
10206 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
10207 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
10208 #if TARGET_API_MAC_CARBON
10209 Rect new_rect;
10210 #else
10211 long grow_size;
10212 #endif
10214 if (size_hints->flags & PMinSize)
10216 min_width = size_hints->min_width;
10217 min_height = size_hints->min_height;
10219 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
10221 #if TARGET_API_MAC_CARBON
10222 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
10223 return;
10224 height = new_rect.bottom - new_rect.top;
10225 width = new_rect.right - new_rect.left;
10226 #else
10227 grow_size = GrowWindow (w, e->where, &limit_rect);
10228 /* see if it really changed size */
10229 if (grow_size == 0)
10230 return;
10231 height = HiWord (grow_size);
10232 width = LoWord (grow_size);
10233 #endif
10235 if (width != FRAME_PIXEL_WIDTH (f)
10236 || height != FRAME_PIXEL_HEIGHT (f))
10238 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
10239 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
10241 x_set_window_size (f, 0, columns, rows);
10246 #if TARGET_API_MAC_CARBON
10247 static Point
10248 mac_get_ideal_size (f)
10249 struct frame *f;
10251 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10252 WindowRef w = FRAME_MAC_WINDOW (f);
10253 Point ideal_size;
10254 Rect standard_rect;
10255 int height, width, columns, rows;
10257 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
10258 ideal_size.v = dpyinfo->height;
10259 IsWindowInStandardState (w, &ideal_size, &standard_rect);
10260 /* Adjust the standard size according to character boundaries. */
10261 width = standard_rect.right - standard_rect.left;
10262 height = standard_rect.bottom - standard_rect.top;
10263 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
10264 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
10265 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
10266 ideal_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
10268 return ideal_size;
10270 #endif
10272 /* Handle clicks in zoom box. Calculation of "standard state" based
10273 on code in IM - Window Manager A and code contributed by Ben
10274 Mesander. The standard state of an Emacs window is 80-characters
10275 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10277 static void
10278 do_zoom_window (WindowRef w, int zoom_in_or_out)
10280 Rect zoom_rect, port_rect;
10281 int width, height;
10282 struct frame *f = mac_window_to_frame (w);
10283 #if TARGET_API_MAC_CARBON
10284 Point ideal_size = mac_get_ideal_size (f);
10286 GetWindowBounds (w, kWindowContentRgn, &port_rect);
10287 if (IsWindowInStandardState (w, &ideal_size, &zoom_rect)
10288 && port_rect.left == zoom_rect.left
10289 && port_rect.top == zoom_rect.top)
10290 zoom_in_or_out = inZoomIn;
10291 else
10292 zoom_in_or_out = inZoomOut;
10294 #ifdef MAC_OS8
10295 mac_clear_window (f);
10296 #endif
10297 ZoomWindowIdeal (w, zoom_in_or_out, &ideal_size);
10298 #else /* not TARGET_API_MAC_CARBON */
10299 GrafPtr save_port;
10300 Point top_left;
10301 int w_title_height, rows;
10302 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10304 GetPort (&save_port);
10306 SetPortWindowPort (w);
10308 /* Clear window to avoid flicker. */
10309 EraseRect (&(w->portRect));
10310 if (zoom_in_or_out == inZoomOut)
10312 SetPt (&top_left, w->portRect.left, w->portRect.top);
10313 LocalToGlobal (&top_left);
10315 /* calculate height of window's title bar */
10316 w_title_height = top_left.v - 1
10317 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
10319 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10320 zoom_rect = qd.screenBits.bounds;
10321 zoom_rect.top += w_title_height;
10322 InsetRect (&zoom_rect, 8, 4); /* not too tight */
10324 zoom_rect.right = zoom_rect.left
10325 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
10327 /* Adjust the standard size according to character boundaries. */
10328 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
10329 zoom_rect.bottom =
10330 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
10332 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
10333 = zoom_rect;
10336 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
10338 SetPort (save_port);
10339 #endif /* not TARGET_API_MAC_CARBON */
10341 #if !TARGET_API_MAC_CARBON
10342 /* retrieve window size and update application values */
10343 port_rect = w->portRect;
10344 height = port_rect.bottom - port_rect.top;
10345 width = port_rect.right - port_rect.left;
10347 mac_handle_size_change (f, width, height);
10348 mac_handle_origin_change (f);
10349 #endif
10352 static void
10353 mac_set_unicode_keystroke_event (code, buf)
10354 UniChar code;
10355 struct input_event *buf;
10357 int charset_id, c1, c2;
10359 if (code < 0x80)
10361 buf->kind = ASCII_KEYSTROKE_EVENT;
10362 buf->code = code;
10364 else if (code < 0x100)
10366 if (code < 0xA0)
10367 charset_id = CHARSET_8_BIT_CONTROL;
10368 else
10369 charset_id = charset_latin_iso8859_1;
10370 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10371 buf->code = MAKE_CHAR (charset_id, code, 0);
10373 else
10375 if (code < 0x2500)
10376 charset_id = charset_mule_unicode_0100_24ff,
10377 code -= 0x100;
10378 else if (code < 0x33FF)
10379 charset_id = charset_mule_unicode_2500_33ff,
10380 code -= 0x2500;
10381 else if (code >= 0xE000)
10382 charset_id = charset_mule_unicode_e000_ffff,
10383 code -= 0xE000;
10384 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
10385 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10386 buf->code = MAKE_CHAR (charset_id, c1, c2);
10390 static void
10391 do_keystroke (action, char_code, key_code, modifiers, timestamp, buf)
10392 EventKind action;
10393 unsigned char char_code;
10394 UInt32 key_code, modifiers;
10395 unsigned long timestamp;
10396 struct input_event *buf;
10398 static SInt16 last_key_script = -1;
10399 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
10400 UInt32 mapped_modifiers = mac_mapped_modifiers (modifiers);
10402 #ifdef MAC_OSX
10403 if (mapped_modifiers & kEventKeyModifierFnMask
10404 && key_code <= 0x7f
10405 && fn_keycode_to_keycode_table[key_code])
10406 key_code = fn_keycode_to_keycode_table[key_code];
10407 #endif
10409 if (key_code <= 0x7f && keycode_to_xkeysym_table[key_code])
10411 buf->kind = NON_ASCII_KEYSTROKE_EVENT;
10412 buf->code = 0xff00 | keycode_to_xkeysym_table[key_code];
10413 #ifdef MAC_OSX
10414 if (modifiers & kEventKeyModifierFnMask
10415 && key_code <= 0x7f
10416 && fn_keycode_to_keycode_table[key_code] == key_code)
10417 modifiers &= ~kEventKeyModifierFnMask;
10418 #endif
10420 else if (mapped_modifiers)
10422 /* translate the keycode back to determine the original key */
10423 #ifdef MAC_OSX
10424 UCKeyboardLayout *uchr_ptr = NULL;
10425 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10426 OSStatus err;
10427 KeyboardLayoutRef layout;
10429 err = KLGetCurrentKeyboardLayout (&layout);
10430 if (err == noErr)
10431 err = KLGetKeyboardLayoutProperty (layout, kKLuchrData,
10432 (const void **) &uchr_ptr);
10433 #else
10434 static SInt16 last_key_layout_id = 0;
10435 static Handle uchr_handle = (Handle)-1;
10436 SInt16 current_key_layout_id =
10437 GetScriptVariable (current_key_script, smScriptKeys);
10439 if (uchr_handle == (Handle)-1
10440 || last_key_layout_id != current_key_layout_id)
10442 uchr_handle = GetResource ('uchr', current_key_layout_id);
10443 last_key_layout_id = current_key_layout_id;
10445 if (uchr_handle)
10446 uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
10447 #endif
10449 if (uchr_ptr)
10451 OSStatus status;
10452 UInt16 key_action = action - keyDown;
10453 UInt32 modifier_key_state = (modifiers & ~mapped_modifiers) >> 8;
10454 UInt32 keyboard_type = LMGetKbdType ();
10455 SInt32 dead_key_state = 0;
10456 UniChar code;
10457 UniCharCount actual_length;
10459 status = UCKeyTranslate (uchr_ptr, key_code, key_action,
10460 modifier_key_state, keyboard_type,
10461 kUCKeyTranslateNoDeadKeysMask,
10462 &dead_key_state,
10463 1, &actual_length, &code);
10464 if (status == noErr && actual_length == 1)
10465 mac_set_unicode_keystroke_event (code, buf);
10467 #endif /* MAC_OSX */
10469 if (buf->kind == NO_EVENT)
10471 /* This code comes from Keyboard Resource, Appendix C of IM
10472 - Text. This is necessary since shift is ignored in KCHR
10473 table translation when option or command is pressed. It
10474 also does not translate correctly control-shift chars
10475 like C-% so mask off shift here also. */
10476 /* Mask off modifier keys that are mapped to some Emacs
10477 modifiers. */
10478 int new_modifiers = modifiers & ~mapped_modifiers;
10479 /* set high byte of keycode to modifier high byte*/
10480 int new_key_code = key_code | new_modifiers;
10481 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
10482 unsigned long some_state = 0;
10483 UInt32 new_char_code;
10485 new_char_code = KeyTranslate (kchr_ptr, new_key_code, &some_state);
10486 if (new_char_code == 0)
10487 /* Seems like a dead key. Append up-stroke. */
10488 new_char_code = KeyTranslate (kchr_ptr, new_key_code | 0x80,
10489 &some_state);
10490 if (new_char_code)
10492 buf->kind = ASCII_KEYSTROKE_EVENT;
10493 buf->code = new_char_code & 0xff;
10498 if (buf->kind == NO_EVENT)
10500 buf->kind = ASCII_KEYSTROKE_EVENT;
10501 buf->code = char_code;
10504 buf->modifiers = mac_to_emacs_modifiers (modifiers);
10505 buf->modifiers |= (extra_keyboard_modifiers
10506 & (meta_modifier | alt_modifier
10507 | hyper_modifier | super_modifier));
10509 #if TARGET_API_MAC_CARBON
10510 if (buf->kind == ASCII_KEYSTROKE_EVENT
10511 && buf->code >= 0x80 && buf->modifiers)
10513 OSStatus err;
10514 TextEncoding encoding = kTextEncodingMacRoman;
10515 TextToUnicodeInfo ttu_info;
10517 UpgradeScriptInfoToTextEncoding (current_key_script,
10518 kTextLanguageDontCare,
10519 kTextRegionDontCare,
10520 NULL, &encoding);
10521 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
10522 if (err == noErr)
10524 UniChar code;
10525 Str255 pstr;
10526 ByteCount unicode_len;
10528 pstr[0] = 1;
10529 pstr[1] = buf->code;
10530 err = ConvertFromPStringToUnicode (ttu_info, pstr,
10531 sizeof (UniChar),
10532 &unicode_len, &code);
10533 if (err == noErr && unicode_len == sizeof (UniChar))
10534 mac_set_unicode_keystroke_event (code, buf);
10535 DisposeTextToUnicodeInfo (&ttu_info);
10538 #endif
10540 if (buf->kind == ASCII_KEYSTROKE_EVENT
10541 && buf->code >= 0x80
10542 && last_key_script != current_key_script)
10544 struct input_event event;
10546 EVENT_INIT (event);
10547 event.kind = LANGUAGE_CHANGE_EVENT;
10548 event.arg = Qnil;
10549 event.code = current_key_script;
10550 event.timestamp = timestamp;
10551 kbd_buffer_store_event (&event);
10552 last_key_script = current_key_script;
10556 void
10557 mac_store_apple_event (class, id, desc)
10558 Lisp_Object class, id;
10559 const AEDesc *desc;
10561 struct input_event buf;
10563 EVENT_INIT (buf);
10565 buf.kind = MAC_APPLE_EVENT;
10566 buf.x = class;
10567 buf.y = id;
10568 XSETFRAME (buf.frame_or_window,
10569 mac_focus_frame (&one_mac_display_info));
10570 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10571 is safe to use them during read_socket_hook. */
10572 buf.arg = mac_aedesc_to_lisp (desc);
10573 kbd_buffer_store_event (&buf);
10576 #if TARGET_API_MAC_CARBON
10577 static OSStatus
10578 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
10579 event, num_params, names, types)
10580 AEEventClass class;
10581 AEEventID id;
10582 Lisp_Object class_key, id_key;
10583 EventRef event;
10584 UInt32 num_params;
10585 const EventParamName *names;
10586 const EventParamType *types;
10588 OSStatus err = eventNotHandledErr;
10589 Lisp_Object binding;
10591 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
10592 if (!NILP (binding) && !EQ (binding, Qundefined))
10594 if (INTEGERP (binding))
10595 err = XINT (binding);
10596 else
10598 AppleEvent apple_event;
10599 err = create_apple_event_from_event_ref (event, num_params,
10600 names, types,
10601 &apple_event);
10602 if (err == noErr)
10604 mac_store_apple_event (class_key, id_key, &apple_event);
10605 AEDisposeDesc (&apple_event);
10606 mac_wakeup_from_rne ();
10611 return err;
10614 void
10615 mac_store_drag_event (window, mouse_pos, modifiers, desc)
10616 WindowRef window;
10617 Point mouse_pos;
10618 SInt16 modifiers;
10619 const AEDesc *desc;
10621 struct input_event buf;
10623 EVENT_INIT (buf);
10625 buf.kind = DRAG_N_DROP_EVENT;
10626 buf.modifiers = mac_to_emacs_modifiers (modifiers);
10627 buf.timestamp = TickCount () * (1000 / 60);
10628 XSETINT (buf.x, mouse_pos.h);
10629 XSETINT (buf.y, mouse_pos.v);
10630 XSETFRAME (buf.frame_or_window, mac_window_to_frame (window));
10631 buf.arg = mac_aedesc_to_lisp (desc);
10632 kbd_buffer_store_event (&buf);
10635 #ifdef MAC_OSX
10636 OSStatus
10637 mac_store_service_event (event)
10638 EventRef event;
10640 OSStatus err;
10641 Lisp_Object id_key;
10642 int num_params;
10643 const EventParamName *names;
10644 const EventParamType *types;
10645 static const EventParamName names_pfm[] =
10646 {kEventParamServiceMessageName, kEventParamServiceUserData};
10647 static const EventParamType types_pfm[] =
10648 {typeCFStringRef, typeCFStringRef};
10650 switch (GetEventKind (event))
10652 case kEventServicePaste:
10653 id_key = Qpaste;
10654 num_params = 0;
10655 names = NULL;
10656 types = NULL;
10657 break;
10659 case kEventServicePerform:
10660 id_key = Qperform;
10661 num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
10662 names = names_pfm;
10663 types = types_pfm;
10664 break;
10666 default:
10667 abort ();
10670 err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
10671 event, num_params,
10672 names, types);
10674 return err;
10676 #endif /* MAC_OSX */
10678 static pascal OSStatus
10679 mac_handle_window_event (next_handler, event, data)
10680 EventHandlerCallRef next_handler;
10681 EventRef event;
10682 void *data;
10684 WindowRef wp;
10685 OSStatus err, result = eventNotHandledErr;
10686 struct frame *f;
10687 UInt32 attributes;
10688 XSizeHints *size_hints;
10690 err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
10691 NULL, sizeof (WindowRef), NULL, &wp);
10692 if (err != noErr)
10693 return eventNotHandledErr;
10695 f = mac_window_to_frame (wp);
10696 switch (GetEventKind (event))
10698 /* -- window refresh events -- */
10700 case kEventWindowUpdate:
10701 result = CallNextEventHandler (next_handler, event);
10702 if (result != eventNotHandledErr)
10703 break;
10705 do_window_update (wp);
10706 result = noErr;
10707 break;
10709 /* -- window state change events -- */
10711 case kEventWindowShowing:
10712 size_hints = FRAME_SIZE_HINTS (f);
10713 if (!(size_hints->flags & (USPosition | PPosition)))
10715 struct frame *sf = SELECTED_FRAME ();
10717 if (!(FRAME_MAC_P (sf) && sf->async_visible))
10718 RepositionWindow (wp, NULL, kWindowCenterOnMainScreen);
10719 else
10721 RepositionWindow (wp, FRAME_MAC_WINDOW (sf),
10722 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10723 kWindowCascadeStartAtParentWindowScreen
10724 #else
10725 kWindowCascadeOnParentWindowScreen
10726 #endif
10728 #if USE_MAC_TOOLBAR
10729 /* This is a workaround. RepositionWindow fails to put
10730 a window at the cascading position when its parent
10731 window has a Carbon HIToolbar. */
10732 if ((f->left_pos == sf->left_pos
10733 && f->top_pos == sf->top_pos)
10734 || (f->left_pos == sf->left_pos + 10 * 2
10735 && f->top_pos == sf->top_pos + 32 * 2))
10736 MoveWindowStructure (wp, sf->left_pos + 10, sf->top_pos + 32);
10737 #endif
10739 result = noErr;
10741 break;
10743 case kEventWindowHiding:
10744 /* Before unmapping the window, update the WM_SIZE_HINTS
10745 property to claim that the current position of the window is
10746 user-specified, rather than program-specified, so that when
10747 the window is mapped again, it will be placed at the same
10748 location, without forcing the user to position it by hand
10749 again (they have already done that once for this window.) */
10750 x_wm_set_size_hint (f, (long) 0, 1);
10751 result = noErr;
10752 break;
10754 case kEventWindowShown:
10755 case kEventWindowHidden:
10756 case kEventWindowCollapsed:
10757 case kEventWindowExpanded:
10758 mac_handle_visibility_change (f);
10759 result = noErr;
10760 break;
10762 case kEventWindowBoundsChanging:
10763 result = CallNextEventHandler (next_handler, event);
10764 if (result != eventNotHandledErr)
10765 break;
10767 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
10768 NULL, sizeof (UInt32), NULL, &attributes);
10769 if (err != noErr)
10770 break;
10772 size_hints = FRAME_SIZE_HINTS (f);
10773 if ((attributes & kWindowBoundsChangeUserResize)
10774 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
10775 == (PResizeInc | PBaseSize | PMinSize)))
10777 Rect bounds;
10778 int width, height;
10780 err = GetEventParameter (event, kEventParamCurrentBounds,
10781 typeQDRectangle, NULL, sizeof (Rect),
10782 NULL, &bounds);
10783 if (err != noErr)
10784 break;
10786 width = bounds.right - bounds.left;
10787 height = bounds.bottom - bounds.top;
10789 if (width < size_hints->min_width)
10790 width = size_hints->min_width;
10791 else
10792 width = size_hints->base_width
10793 + (int) ((width - size_hints->base_width)
10794 / (float) size_hints->width_inc + .5)
10795 * size_hints->width_inc;
10797 if (height < size_hints->min_height)
10798 height = size_hints->min_height;
10799 else
10800 height = size_hints->base_height
10801 + (int) ((height - size_hints->base_height)
10802 / (float) size_hints->height_inc + .5)
10803 * size_hints->height_inc;
10805 bounds.right = bounds.left + width;
10806 bounds.bottom = bounds.top + height;
10807 SetEventParameter (event, kEventParamCurrentBounds,
10808 typeQDRectangle, sizeof (Rect), &bounds);
10809 result = noErr;
10811 break;
10813 case kEventWindowBoundsChanged:
10814 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
10815 NULL, sizeof (UInt32), NULL, &attributes);
10816 if (err != noErr)
10817 break;
10819 if (attributes & kWindowBoundsChangeSizeChanged)
10821 Rect bounds;
10823 err = GetEventParameter (event, kEventParamCurrentBounds,
10824 typeQDRectangle, NULL, sizeof (Rect),
10825 NULL, &bounds);
10826 if (err == noErr)
10828 int width, height;
10830 width = bounds.right - bounds.left;
10831 height = bounds.bottom - bounds.top;
10832 mac_handle_size_change (f, width, height);
10833 mac_wakeup_from_rne ();
10837 if (attributes & kWindowBoundsChangeOriginChanged)
10838 mac_handle_origin_change (f);
10840 result = noErr;
10841 break;
10843 /* -- window action events -- */
10845 case kEventWindowClose:
10847 struct input_event buf;
10849 EVENT_INIT (buf);
10850 buf.kind = DELETE_WINDOW_EVENT;
10851 XSETFRAME (buf.frame_or_window, f);
10852 buf.arg = Qnil;
10853 kbd_buffer_store_event (&buf);
10855 result = noErr;
10856 break;
10858 case kEventWindowGetIdealSize:
10859 result = CallNextEventHandler (next_handler, event);
10860 if (result != eventNotHandledErr)
10861 break;
10864 Point ideal_size = mac_get_ideal_size (f);
10866 err = SetEventParameter (event, kEventParamDimensions,
10867 typeQDPoint, sizeof (Point), &ideal_size);
10868 if (err == noErr)
10869 result = noErr;
10871 break;
10873 #ifdef MAC_OSX
10874 case kEventWindowToolbarSwitchMode:
10876 static const EventParamName names[] = {kEventParamDirectObject,
10877 kEventParamWindowMouseLocation,
10878 kEventParamKeyModifiers,
10879 kEventParamMouseButton,
10880 kEventParamClickCount,
10881 kEventParamMouseChord};
10882 static const EventParamType types[] = {typeWindowRef,
10883 typeQDPoint,
10884 typeUInt32,
10885 typeMouseButton,
10886 typeUInt32,
10887 typeUInt32};
10888 int num_params = sizeof (names) / sizeof (names[0]);
10890 err = mac_store_event_ref_as_apple_event (0, 0,
10891 Qwindow,
10892 Qtoolbar_switch_mode,
10893 event, num_params,
10894 names, types);
10896 if (err == noErr)
10897 result = noErr;
10898 break;
10899 #endif
10901 #if USE_MAC_TSM
10902 /* -- window focus events -- */
10904 case kEventWindowFocusAcquired:
10905 err = mac_tsm_resume ();
10906 if (err == noErr)
10907 result = noErr;
10908 break;
10910 case kEventWindowFocusRelinquish:
10911 err = mac_tsm_suspend ();
10912 if (err == noErr)
10913 result = noErr;
10914 break;
10915 #endif
10917 default:
10918 abort ();
10921 return result;
10924 static pascal OSStatus
10925 mac_handle_application_event (next_handler, event, data)
10926 EventHandlerCallRef next_handler;
10927 EventRef event;
10928 void *data;
10930 OSStatus err, result = eventNotHandledErr;
10932 switch (GetEventKind (event))
10934 #if USE_MAC_TSM
10935 case kEventAppActivated:
10936 err = mac_tsm_resume ();
10937 break;
10939 case kEventAppDeactivated:
10940 err = mac_tsm_suspend ();
10941 break;
10942 #endif
10944 default:
10945 abort ();
10948 if (err == noErr)
10949 result = noErr;
10951 return result;
10954 static pascal OSStatus
10955 mac_handle_keyboard_event (next_handler, event, data)
10956 EventHandlerCallRef next_handler;
10957 EventRef event;
10958 void *data;
10960 OSStatus err, result = eventNotHandledErr;
10961 UInt32 event_kind, key_code, modifiers;
10962 unsigned char char_code;
10964 event_kind = GetEventKind (event);
10965 switch (event_kind)
10967 case kEventRawKeyDown:
10968 case kEventRawKeyRepeat:
10969 case kEventRawKeyUp:
10970 /* When using Carbon Events, we need to pass raw keyboard events
10971 to the TSM ourselves. If TSM handles it, it will pass back
10972 noErr, otherwise it will pass back "eventNotHandledErr" and
10973 we can process it normally. */
10974 result = CallNextEventHandler (next_handler, event);
10975 if (result != eventNotHandledErr)
10976 break;
10978 if (read_socket_inev == NULL)
10979 break;
10981 #if USE_MAC_TSM
10982 if (read_socket_inev->kind != NO_EVENT)
10984 result = noErr;
10985 break;
10987 #endif
10989 if (event_kind == kEventRawKeyUp)
10990 break;
10992 err = GetEventParameter (event, kEventParamKeyMacCharCodes,
10993 typeChar, NULL,
10994 sizeof (char), NULL, &char_code);
10995 if (err != noErr)
10996 break;
10998 err = GetEventParameter (event, kEventParamKeyCode,
10999 typeUInt32, NULL,
11000 sizeof (UInt32), NULL, &key_code);
11001 if (err != noErr)
11002 break;
11004 err = GetEventParameter (event, kEventParamKeyModifiers,
11005 typeUInt32, NULL,
11006 sizeof (UInt32), NULL, &modifiers);
11007 if (err != noErr)
11008 break;
11010 do_keystroke ((event_kind == kEventRawKeyDown ? keyDown : autoKey),
11011 char_code, key_code, modifiers,
11012 ((unsigned long)
11013 (GetEventTime (event) / kEventDurationMillisecond)),
11014 read_socket_inev);
11015 result = noErr;
11016 break;
11018 default:
11019 abort ();
11022 return result;
11025 static pascal OSStatus
11026 mac_handle_command_event (next_handler, event, data)
11027 EventHandlerCallRef next_handler;
11028 EventRef event;
11029 void *data;
11031 OSStatus err, result = eventNotHandledErr;
11032 HICommand command;
11033 static const EventParamName names[] =
11034 {kEventParamDirectObject, kEventParamKeyModifiers};
11035 static const EventParamType types[] =
11036 {typeHICommand, typeUInt32};
11037 int num_params = sizeof (names) / sizeof (names[0]);
11039 err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
11040 NULL, sizeof (HICommand), NULL, &command);
11041 if (err != noErr)
11042 return eventNotHandledErr;
11044 switch (GetEventKind (event))
11046 case kEventCommandProcess:
11047 result = CallNextEventHandler (next_handler, event);
11048 if (result != eventNotHandledErr)
11049 break;
11051 err = GetEventParameter (event, kEventParamDirectObject,
11052 typeHICommand, NULL,
11053 sizeof (HICommand), NULL, &command);
11055 if (err != noErr || command.commandID == 0)
11056 break;
11058 /* A HI command event is mapped to an Apple event whose event
11059 class symbol is `hi-command' and event ID is its command
11060 ID. */
11061 err = mac_store_event_ref_as_apple_event (0, command.commandID,
11062 Qhi_command, Qnil,
11063 event, num_params,
11064 names, types);
11065 if (err == noErr)
11066 result = noErr;
11067 break;
11069 default:
11070 abort ();
11073 return result;
11076 static pascal OSStatus
11077 mac_handle_mouse_event (next_handler, event, data)
11078 EventHandlerCallRef next_handler;
11079 EventRef event;
11080 void *data;
11082 OSStatus err, result = eventNotHandledErr;
11084 switch (GetEventKind (event))
11086 case kEventMouseWheelMoved:
11088 WindowRef wp;
11089 struct frame *f;
11090 EventMouseWheelAxis axis;
11091 SInt32 delta;
11092 Point point;
11094 result = CallNextEventHandler (next_handler, event);
11095 if (result != eventNotHandledErr || read_socket_inev == NULL)
11096 break;
11098 f = mac_focus_frame (&one_mac_display_info);
11100 err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
11101 NULL, sizeof (WindowRef), NULL, &wp);
11102 if (err != noErr
11103 || wp != FRAME_MAC_WINDOW (f))
11104 break;
11106 err = GetEventParameter (event, kEventParamMouseWheelAxis,
11107 typeMouseWheelAxis, NULL,
11108 sizeof (EventMouseWheelAxis), NULL, &axis);
11109 if (err != noErr || axis != kEventMouseWheelAxisY)
11110 break;
11112 err = GetEventParameter (event, kEventParamMouseLocation,
11113 typeQDPoint, NULL, sizeof (Point),
11114 NULL, &point);
11115 if (err != noErr)
11116 break;
11118 point.h -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
11119 point.v -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
11120 if (point.h < 0 || point.v < 0
11121 || EQ (window_from_coordinates (f, point.h, point.v, 0, 0, 0, 1),
11122 f->tool_bar_window))
11123 break;
11125 err = GetEventParameter (event, kEventParamMouseWheelDelta,
11126 typeSInt32, NULL, sizeof (SInt32),
11127 NULL, &delta);
11128 if (err != noErr)
11129 break;
11131 read_socket_inev->kind = WHEEL_EVENT;
11132 read_socket_inev->code = 0;
11133 read_socket_inev->modifiers =
11134 (mac_event_to_emacs_modifiers (event)
11135 | ((delta < 0) ? down_modifier : up_modifier));
11136 XSETINT (read_socket_inev->x, point.h);
11137 XSETINT (read_socket_inev->y, point.v);
11138 XSETFRAME (read_socket_inev->frame_or_window, f);
11140 result = noErr;
11142 break;
11144 default:
11145 abort ();
11148 return result;
11151 #if USE_MAC_TSM
11152 static pascal OSStatus
11153 mac_handle_text_input_event (next_handler, event, data)
11154 EventHandlerCallRef next_handler;
11155 EventRef event;
11156 void *data;
11158 OSStatus err, result;
11159 Lisp_Object id_key = Qnil;
11160 int num_params;
11161 const EventParamName *names;
11162 const EventParamType *types;
11163 static UInt32 seqno_uaia = 0;
11164 static const EventParamName names_uaia[] =
11165 {kEventParamTextInputSendComponentInstance,
11166 kEventParamTextInputSendRefCon,
11167 kEventParamTextInputSendSLRec,
11168 kEventParamTextInputSendFixLen,
11169 kEventParamTextInputSendText,
11170 kEventParamTextInputSendUpdateRng,
11171 kEventParamTextInputSendHiliteRng,
11172 kEventParamTextInputSendClauseRng,
11173 kEventParamTextInputSendPinRng,
11174 kEventParamTextInputSendTextServiceEncoding,
11175 kEventParamTextInputSendTextServiceMacEncoding,
11176 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
11177 static const EventParamType types_uaia[] =
11178 {typeComponentInstance,
11179 typeLongInteger,
11180 typeIntlWritingCode,
11181 typeLongInteger,
11182 #ifdef MAC_OSX
11183 typeUnicodeText,
11184 #else
11185 typeChar,
11186 #endif
11187 typeTextRangeArray,
11188 typeTextRangeArray,
11189 typeOffsetArray,
11190 typeTextRange,
11191 typeUInt32,
11192 typeUInt32,
11193 typeUInt32};
11194 static const EventParamName names_ufke[] =
11195 {kEventParamTextInputSendComponentInstance,
11196 kEventParamTextInputSendRefCon,
11197 kEventParamTextInputSendSLRec,
11198 kEventParamTextInputSendText};
11199 static const EventParamType types_ufke[] =
11200 {typeComponentInstance,
11201 typeLongInteger,
11202 typeIntlWritingCode,
11203 typeUnicodeText};
11205 result = CallNextEventHandler (next_handler, event);
11206 if (result != eventNotHandledErr)
11207 return result;
11209 switch (GetEventKind (event))
11211 case kEventTextInputUpdateActiveInputArea:
11212 id_key = Qupdate_active_input_area;
11213 num_params = sizeof (names_uaia) / sizeof (names_uaia[0]);
11214 names = names_uaia;
11215 types = types_uaia;
11216 SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
11217 typeUInt32, sizeof (UInt32), &seqno_uaia);
11218 seqno_uaia++;
11219 result = noErr;
11220 break;
11222 case kEventTextInputUnicodeForKeyEvent:
11224 EventRef kbd_event;
11225 UInt32 actual_size, modifiers;
11227 err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent,
11228 typeEventRef, NULL, sizeof (EventRef), NULL,
11229 &kbd_event);
11230 if (err == noErr)
11231 err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
11232 typeUInt32, NULL,
11233 sizeof (UInt32), NULL, &modifiers);
11234 if (err == noErr && mac_mapped_modifiers (modifiers))
11235 /* There're mapped modifier keys. Process it in
11236 do_keystroke. */
11237 break;
11238 if (err == noErr)
11239 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
11240 typeUnicodeText, NULL, 0, &actual_size,
11241 NULL);
11242 if (err == noErr && actual_size == sizeof (UniChar))
11244 UniChar code;
11246 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
11247 typeUnicodeText, NULL,
11248 sizeof (UniChar), NULL, &code);
11249 if (err == noErr && code < 0x80)
11251 /* ASCII character. Process it in do_keystroke. */
11252 if (read_socket_inev && code >= 0x20 && code <= 0x7e)
11254 UInt32 key_code;
11256 err = GetEventParameter (kbd_event, kEventParamKeyCode,
11257 typeUInt32, NULL, sizeof (UInt32),
11258 NULL, &key_code);
11259 if (!(err == noErr && key_code <= 0x7f
11260 && keycode_to_xkeysym_table [key_code]))
11262 struct frame *f =
11263 mac_focus_frame (&one_mac_display_info);
11265 read_socket_inev->kind = ASCII_KEYSTROKE_EVENT;
11266 read_socket_inev->code = code;
11267 read_socket_inev->modifiers =
11268 mac_to_emacs_modifiers (modifiers);
11269 read_socket_inev->modifiers |=
11270 (extra_keyboard_modifiers
11271 & (meta_modifier | alt_modifier
11272 | hyper_modifier | super_modifier));
11273 XSETFRAME (read_socket_inev->frame_or_window, f);
11276 break;
11279 if (err == noErr)
11281 /* Non-ASCII keystrokes without mapped modifiers are
11282 processed at the Lisp level. */
11283 id_key = Qunicode_for_key_event;
11284 num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
11285 names = names_ufke;
11286 types = types_ufke;
11287 result = noErr;
11290 break;
11292 case kEventTextInputOffsetToPos:
11294 struct frame *f;
11295 struct window *w;
11296 Point p;
11298 if (!OVERLAYP (Vmac_ts_active_input_overlay))
11299 break;
11301 /* Strictly speaking, this is not always correct because
11302 previous events may change some states about display. */
11303 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
11305 /* Active input area is displayed around the current point. */
11306 f = SELECTED_FRAME ();
11307 w = XWINDOW (f->selected_window);
11309 else if (WINDOWP (echo_area_window))
11311 /* Active input area is displayed in the echo area. */
11312 w = XWINDOW (echo_area_window);
11313 f = WINDOW_XFRAME (w);
11315 else
11316 break;
11318 p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
11319 + WINDOW_LEFT_FRINGE_WIDTH (w)
11320 + f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f));
11321 p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
11322 + FONT_BASE (FRAME_FONT (f))
11323 + f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f));
11324 err = SetEventParameter (event, kEventParamTextInputReplyPoint,
11325 typeQDPoint, sizeof (typeQDPoint), &p);
11326 if (err == noErr)
11327 result = noErr;
11329 break;
11331 default:
11332 abort ();
11335 if (!NILP (id_key))
11336 err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
11337 event, num_params,
11338 names, types);
11339 return result;
11341 #endif
11342 #endif /* TARGET_API_MAC_CARBON */
11345 OSStatus
11346 install_window_handler (window)
11347 WindowRef window;
11349 OSStatus err = noErr;
11351 #if TARGET_API_MAC_CARBON
11352 if (err == noErr)
11354 static const EventTypeSpec specs[] =
11356 /* -- window refresh events -- */
11357 {kEventClassWindow, kEventWindowUpdate},
11358 /* -- window state change events -- */
11359 {kEventClassWindow, kEventWindowShowing},
11360 {kEventClassWindow, kEventWindowHiding},
11361 {kEventClassWindow, kEventWindowShown},
11362 {kEventClassWindow, kEventWindowHidden},
11363 {kEventClassWindow, kEventWindowCollapsed},
11364 {kEventClassWindow, kEventWindowExpanded},
11365 {kEventClassWindow, kEventWindowBoundsChanging},
11366 {kEventClassWindow, kEventWindowBoundsChanged},
11367 /* -- window action events -- */
11368 {kEventClassWindow, kEventWindowClose},
11369 {kEventClassWindow, kEventWindowGetIdealSize},
11370 #ifdef MAC_OSX
11371 {kEventClassWindow, kEventWindowToolbarSwitchMode},
11372 #endif
11373 #if USE_MAC_TSM
11374 /* -- window focus events -- */
11375 {kEventClassWindow, kEventWindowFocusAcquired},
11376 {kEventClassWindow, kEventWindowFocusRelinquish},
11377 #endif
11379 static EventHandlerUPP handle_window_eventUPP = NULL;
11381 if (handle_window_eventUPP == NULL)
11382 handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
11384 err = InstallWindowEventHandler (window, handle_window_eventUPP,
11385 GetEventTypeCount (specs),
11386 specs, NULL, NULL);
11388 #endif
11390 if (err == noErr)
11391 err = install_drag_handler (window);
11393 return err;
11396 void
11397 remove_window_handler (window)
11398 WindowRef window;
11400 remove_drag_handler (window);
11403 #if TARGET_API_MAC_CARBON
11404 static OSStatus
11405 install_application_handler ()
11407 OSStatus err = noErr;
11409 if (err == noErr)
11411 static const EventTypeSpec specs[] = {
11412 #if USE_MAC_TSM
11413 {kEventClassApplication, kEventAppActivated},
11414 {kEventClassApplication, kEventAppDeactivated},
11415 #endif
11418 err = InstallApplicationEventHandler (NewEventHandlerUPP
11419 (mac_handle_application_event),
11420 GetEventTypeCount (specs),
11421 specs, NULL, NULL);
11424 if (err == noErr)
11426 static const EventTypeSpec specs[] =
11427 {{kEventClassKeyboard, kEventRawKeyDown},
11428 {kEventClassKeyboard, kEventRawKeyRepeat},
11429 {kEventClassKeyboard, kEventRawKeyUp}};
11431 err = InstallApplicationEventHandler (NewEventHandlerUPP
11432 (mac_handle_keyboard_event),
11433 GetEventTypeCount (specs),
11434 specs, NULL, NULL);
11437 if (err == noErr)
11439 static const EventTypeSpec specs[] =
11440 {{kEventClassCommand, kEventCommandProcess}};
11442 err = InstallApplicationEventHandler (NewEventHandlerUPP
11443 (mac_handle_command_event),
11444 GetEventTypeCount (specs),
11445 specs, NULL, NULL);
11448 if (err == noErr)
11450 static const EventTypeSpec specs[] =
11451 {{kEventClassMouse, kEventMouseWheelMoved}};
11453 err = InstallApplicationEventHandler (NewEventHandlerUPP
11454 (mac_handle_mouse_event),
11455 GetEventTypeCount (specs),
11456 specs, NULL, NULL);
11459 #if USE_MAC_TSM
11460 if (err == noErr)
11462 static const EventTypeSpec spec[] =
11463 {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
11464 {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
11465 {kEventClassTextInput, kEventTextInputOffsetToPos}};
11467 err = InstallApplicationEventHandler (NewEventHandlerUPP
11468 (mac_handle_text_input_event),
11469 GetEventTypeCount (spec),
11470 spec, NULL, NULL);
11472 #endif
11474 if (err == noErr)
11475 err = install_menu_target_item_handler ();
11477 #ifdef MAC_OSX
11478 if (err == noErr)
11479 err = install_service_handler ();
11480 #endif
11482 return err;
11484 #endif
11486 static pascal void
11487 mac_handle_dm_notification (event)
11488 AppleEvent *event;
11490 mac_screen_config_changed = 1;
11493 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11494 static void
11495 mac_handle_cg_display_reconfig (display, flags, user_info)
11496 CGDirectDisplayID display;
11497 CGDisplayChangeSummaryFlags flags;
11498 void *user_info;
11500 mac_screen_config_changed = 1;
11502 #endif
11504 static OSErr
11505 init_dm_notification_handler ()
11507 OSErr err = noErr;
11509 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11510 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11511 if (CGDisplayRegisterReconfigurationCallback != NULL)
11512 #endif
11514 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig,
11515 NULL);
11517 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11518 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11519 #endif
11520 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11521 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11523 static DMNotificationUPP handle_dm_notificationUPP = NULL;
11524 ProcessSerialNumber psn;
11526 if (handle_dm_notificationUPP == NULL)
11527 handle_dm_notificationUPP =
11528 NewDMNotificationUPP (mac_handle_dm_notification);
11530 err = GetCurrentProcess (&psn);
11531 if (err == noErr)
11532 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
11534 #endif
11536 return err;
11539 static void
11540 mac_get_screen_info (dpyinfo)
11541 struct mac_display_info *dpyinfo;
11543 #ifdef MAC_OSX
11544 /* HasDepth returns true if it is possible to have a 32 bit display,
11545 but this may not be what is actually used. Mac OSX can do better. */
11546 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
11547 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
11549 CGDisplayErr err;
11550 CGDisplayCount ndisps;
11551 CGDirectDisplayID *displays;
11553 err = CGGetActiveDisplayList (0, NULL, &ndisps);
11554 if (err == noErr)
11556 displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
11557 err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
11559 if (err == noErr)
11561 CGRect bounds = CGRectZero;
11563 while (ndisps-- > 0)
11564 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
11565 dpyinfo->height = CGRectGetHeight (bounds);
11566 dpyinfo->width = CGRectGetWidth (bounds);
11568 else
11570 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
11571 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
11574 #else /* !MAC_OSX */
11576 GDHandle gdh = GetMainDevice ();
11577 Rect rect = (**gdh).gdRect;
11579 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
11580 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
11581 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
11582 break;
11584 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
11585 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
11586 UnionRect (&rect, &(**gdh).gdRect, &rect);
11588 dpyinfo->height = rect.bottom - rect.top;
11589 dpyinfo->width = rect.right - rect.left;
11591 #endif /* !MAC_OSX */
11595 #if __profile__
11596 void
11597 profiler_exit_proc ()
11599 ProfilerDump ("\pEmacs.prof");
11600 ProfilerTerm ();
11602 #endif
11604 /* These few functions implement Emacs as a normal Mac application
11605 (almost): set up the heap and the Toolbox, handle necessary system
11606 events plus a few simple menu events. They also set up Emacs's
11607 access to functions defined in the rest of this file. Emacs uses
11608 function hooks to perform all its terminal I/O. A complete list of
11609 these functions appear in termhooks.h. For what they do, read the
11610 comments there and see also w32term.c and xterm.c. What's
11611 noticeably missing here is the event loop, which is normally
11612 present in most Mac application. After performing the necessary
11613 Mac initializations, main passes off control to emacs_main
11614 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11615 (defined further below) to read input. This is where
11616 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11618 #ifdef MAC_OS8
11619 #undef main
11621 main (void)
11623 #if __profile__ /* is the profiler on? */
11624 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
11625 exit(1);
11626 #endif
11628 #if __MWERKS__
11629 /* set creator and type for files created by MSL */
11630 _fcreator = MAC_EMACS_CREATOR_CODE;
11631 _ftype = 'TEXT';
11632 #endif
11634 do_init_managers ();
11636 do_get_menus ();
11638 #ifndef USE_LSB_TAG
11639 do_check_ram_size ();
11640 #endif
11642 init_emacs_passwd_dir ();
11644 init_environ ();
11646 init_coercion_handler ();
11648 initialize_applescript ();
11650 init_apple_event_handler ();
11652 init_dm_notification_handler ();
11655 char **argv;
11656 int argc = 0;
11658 /* set up argv array from STR# resource */
11659 get_string_list (&argv, ARGV_STRING_LIST_ID);
11660 while (argv[argc])
11661 argc++;
11663 /* free up AppleScript resources on exit */
11664 atexit (terminate_applescript);
11666 #if __profile__ /* is the profiler on? */
11667 atexit (profiler_exit_proc);
11668 #endif
11670 /* 3rd param "envp" never used in emacs_main */
11671 (void) emacs_main (argc, argv, 0);
11674 /* Never reached - real exit in Fkill_emacs */
11675 return 0;
11677 #endif
11679 #if !TARGET_API_MAC_CARBON
11680 static RgnHandle mouse_region = NULL;
11682 Boolean
11683 mac_wait_next_event (er, sleep_time, dequeue)
11684 EventRecord *er;
11685 UInt32 sleep_time;
11686 Boolean dequeue;
11688 static EventRecord er_buf = {nullEvent};
11689 UInt32 target_tick, current_tick;
11690 EventMask event_mask;
11692 if (mouse_region == NULL)
11693 mouse_region = NewRgn ();
11695 event_mask = everyEvent;
11696 if (!mac_ready_for_apple_events)
11697 event_mask -= highLevelEventMask;
11699 current_tick = TickCount ();
11700 target_tick = current_tick + sleep_time;
11702 if (er_buf.what == nullEvent)
11703 while (!WaitNextEvent (event_mask, &er_buf,
11704 target_tick - current_tick, mouse_region))
11706 current_tick = TickCount ();
11707 if (target_tick <= current_tick)
11708 return false;
11711 *er = er_buf;
11712 if (dequeue)
11713 er_buf.what = nullEvent;
11714 return true;
11716 #endif /* not TARGET_API_MAC_CARBON */
11718 #if TARGET_API_MAC_CARBON
11719 OSStatus
11720 mac_post_mouse_moved_event ()
11722 EventRef event = NULL;
11723 OSStatus err;
11725 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
11726 kEventAttributeNone, &event);
11727 if (err == noErr)
11729 Point mouse_pos;
11731 GetGlobalMouse (&mouse_pos);
11732 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
11733 sizeof (Point), &mouse_pos);
11735 if (err == noErr)
11737 UInt32 modifiers = GetCurrentKeyModifiers ();
11739 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
11740 sizeof (UInt32), &modifiers);
11742 if (err == noErr)
11743 err = PostEventToQueue (GetCurrentEventQueue (), event,
11744 kEventPriorityStandard);
11745 if (event)
11746 ReleaseEvent (event);
11748 return err;
11750 #endif
11752 /* Emacs calls this whenever it wants to read an input event from the
11753 user. */
11755 XTread_socket (sd, expected, hold_quit)
11756 int sd, expected;
11757 struct input_event *hold_quit;
11759 struct input_event inev;
11760 int count = 0;
11761 #if TARGET_API_MAC_CARBON
11762 EventRef eventRef;
11763 EventTargetRef toolbox_dispatcher;
11764 #endif
11765 EventRecord er;
11766 struct mac_display_info *dpyinfo = &one_mac_display_info;
11768 if (interrupt_input_blocked)
11770 interrupt_input_pending = 1;
11771 return -1;
11774 interrupt_input_pending = 0;
11775 BLOCK_INPUT;
11777 /* So people can tell when we have read the available input. */
11778 input_signal_count++;
11780 ++handling_signal;
11782 #if TARGET_API_MAC_CARBON
11783 toolbox_dispatcher = GetEventDispatcherTarget ();
11785 while (
11786 #if USE_CG_DRAWING
11787 mac_prepare_for_quickdraw (NULL),
11788 #endif
11789 !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
11790 kEventRemoveFromQueue, &eventRef))
11791 #else /* !TARGET_API_MAC_CARBON */
11792 while (mac_wait_next_event (&er, 0, true))
11793 #endif /* !TARGET_API_MAC_CARBON */
11795 int do_help = 0;
11796 struct frame *f;
11797 unsigned long timestamp;
11799 EVENT_INIT (inev);
11800 inev.kind = NO_EVENT;
11801 inev.arg = Qnil;
11803 #if TARGET_API_MAC_CARBON
11804 timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
11806 if (!mac_convert_event_ref (eventRef, &er))
11807 goto OTHER;
11808 #else /* !TARGET_API_MAC_CARBON */
11809 timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
11810 #endif /* !TARGET_API_MAC_CARBON */
11812 switch (er.what)
11814 case mouseDown:
11815 case mouseUp:
11817 WindowRef window_ptr;
11818 ControlPartCode part_code;
11819 int tool_bar_p = 0;
11821 #if TARGET_API_MAC_CARBON
11822 OSStatus err;
11824 /* This is needed to send mouse events like aqua window
11825 buttons to the correct handler. */
11826 read_socket_inev = &inev;
11827 err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
11828 read_socket_inev = NULL;
11829 if (err != eventNotHandledErr)
11830 break;
11831 #endif
11832 last_mouse_glyph_frame = 0;
11834 if (dpyinfo->grabbed && last_mouse_frame
11835 && FRAME_LIVE_P (last_mouse_frame))
11837 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
11838 part_code = inContent;
11840 else
11842 part_code = FindWindow (er.where, &window_ptr);
11843 if (tip_window && window_ptr == tip_window)
11845 HideWindow (tip_window);
11846 part_code = FindWindow (er.where, &window_ptr);
11850 if (er.what != mouseDown &&
11851 (part_code != inContent || dpyinfo->grabbed == 0))
11852 break;
11854 switch (part_code)
11856 case inMenuBar:
11857 f = mac_focus_frame (dpyinfo);
11858 saved_menu_event_location = er.where;
11859 inev.kind = MENU_BAR_ACTIVATE_EVENT;
11860 XSETFRAME (inev.frame_or_window, f);
11861 break;
11863 case inContent:
11864 if (
11865 #if TARGET_API_MAC_CARBON
11866 FrontNonFloatingWindow ()
11867 #else
11868 FrontWindow ()
11869 #endif
11870 != window_ptr
11871 || (mac_window_to_frame (window_ptr)
11872 != dpyinfo->x_focus_frame))
11873 SelectWindow (window_ptr);
11874 else
11876 ControlPartCode control_part_code;
11877 ControlRef ch;
11878 Point mouse_loc;
11879 #ifdef MAC_OSX
11880 ControlKind control_kind;
11881 #endif
11883 f = mac_window_to_frame (window_ptr);
11884 /* convert to local coordinates of new window */
11885 mouse_loc.h = (er.where.h
11886 - (f->left_pos
11887 + FRAME_OUTER_TO_INNER_DIFF_X (f)));
11888 mouse_loc.v = (er.where.v
11889 - (f->top_pos
11890 + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
11891 #if TARGET_API_MAC_CARBON
11892 ch = FindControlUnderMouse (mouse_loc, window_ptr,
11893 &control_part_code);
11894 #ifdef MAC_OSX
11895 if (ch)
11896 GetControlKind (ch, &control_kind);
11897 #endif
11898 #else
11899 control_part_code = FindControl (mouse_loc, window_ptr,
11900 &ch);
11901 #endif
11903 #if TARGET_API_MAC_CARBON
11904 inev.code = mac_get_mouse_btn (eventRef);
11905 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
11906 #else
11907 inev.code = mac_get_emulated_btn (er.modifiers);
11908 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
11909 #endif
11910 XSETINT (inev.x, mouse_loc.h);
11911 XSETINT (inev.y, mouse_loc.v);
11913 if ((dpyinfo->grabbed && tracked_scroll_bar)
11914 || (ch != 0
11915 #ifndef USE_TOOLKIT_SCROLL_BARS
11916 /* control_part_code becomes kControlNoPart if
11917 a progress indicator is clicked. */
11918 && control_part_code != kControlNoPart
11919 #else /* USE_TOOLKIT_SCROLL_BARS */
11920 #ifdef MAC_OSX
11921 && control_kind.kind == kControlKindScrollBar
11922 #endif /* MAC_OSX */
11923 #endif /* USE_TOOLKIT_SCROLL_BARS */
11926 struct scroll_bar *bar;
11928 if (dpyinfo->grabbed && tracked_scroll_bar)
11930 bar = tracked_scroll_bar;
11931 #ifndef USE_TOOLKIT_SCROLL_BARS
11932 control_part_code = kControlIndicatorPart;
11933 #endif
11935 else
11936 bar = (struct scroll_bar *) GetControlReference (ch);
11937 #ifdef USE_TOOLKIT_SCROLL_BARS
11938 /* Make the "Ctrl-Mouse-2 splits window" work
11939 for toolkit scroll bars. */
11940 if (inev.modifiers & ctrl_modifier)
11941 x_scroll_bar_handle_click (bar, control_part_code,
11942 &er, &inev);
11943 else if (er.what == mouseDown)
11944 x_scroll_bar_handle_press (bar, control_part_code,
11945 mouse_loc, &inev);
11946 else
11947 x_scroll_bar_handle_release (bar, &inev);
11948 #else /* not USE_TOOLKIT_SCROLL_BARS */
11949 x_scroll_bar_handle_click (bar, control_part_code,
11950 &er, &inev);
11951 if (er.what == mouseDown
11952 && control_part_code == kControlIndicatorPart)
11953 tracked_scroll_bar = bar;
11954 else
11955 tracked_scroll_bar = NULL;
11956 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11958 else
11960 Lisp_Object window;
11961 int x = mouse_loc.h;
11962 int y = mouse_loc.v;
11964 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
11965 if (EQ (window, f->tool_bar_window))
11967 if (er.what == mouseDown)
11968 handle_tool_bar_click (f, x, y, 1, 0);
11969 else
11970 handle_tool_bar_click (f, x, y, 0,
11971 inev.modifiers);
11972 tool_bar_p = 1;
11974 else
11976 XSETFRAME (inev.frame_or_window, f);
11977 inev.kind = MOUSE_CLICK_EVENT;
11981 if (er.what == mouseDown)
11983 dpyinfo->grabbed |= (1 << inev.code);
11984 last_mouse_frame = f;
11986 if (!tool_bar_p)
11987 last_tool_bar_item = -1;
11989 else
11991 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
11992 /* If a button is released though it was not
11993 previously pressed, that would be because
11994 of multi-button emulation. */
11995 dpyinfo->grabbed = 0;
11996 else
11997 dpyinfo->grabbed &= ~(1 << inev.code);
12000 /* Ignore any mouse motion that happened before
12001 this event; any subsequent mouse-movement Emacs
12002 events should reflect only motion after the
12003 ButtonPress. */
12004 if (f != 0)
12005 f->mouse_moved = 0;
12007 #ifdef USE_TOOLKIT_SCROLL_BARS
12008 if (inev.kind == MOUSE_CLICK_EVENT
12009 || (inev.kind == SCROLL_BAR_CLICK_EVENT
12010 && (inev.modifiers & ctrl_modifier)))
12011 #endif
12012 switch (er.what)
12014 case mouseDown:
12015 inev.modifiers |= down_modifier;
12016 break;
12017 case mouseUp:
12018 inev.modifiers |= up_modifier;
12019 break;
12022 break;
12024 case inDrag:
12025 #if TARGET_API_MAC_CARBON
12026 case inProxyIcon:
12027 if (IsWindowPathSelectClick (window_ptr, &er))
12029 WindowPathSelect (window_ptr, NULL, NULL);
12030 break;
12032 if (part_code == inProxyIcon
12033 && (TrackWindowProxyDrag (window_ptr, er.where)
12034 != errUserWantsToDragWindow))
12035 break;
12036 DragWindow (window_ptr, er.where, NULL);
12037 #else /* not TARGET_API_MAC_CARBON */
12038 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12039 /* Update the frame parameters. */
12041 struct frame *f = mac_window_to_frame (window_ptr);
12043 if (f && !f->async_iconified)
12044 mac_handle_origin_change (f);
12046 #endif /* not TARGET_API_MAC_CARBON */
12047 break;
12049 case inGoAway:
12050 if (TrackGoAway (window_ptr, er.where))
12052 inev.kind = DELETE_WINDOW_EVENT;
12053 XSETFRAME (inev.frame_or_window,
12054 mac_window_to_frame (window_ptr));
12056 break;
12058 /* window resize handling added --ben */
12059 case inGrow:
12060 do_grow_window (window_ptr, &er);
12061 break;
12063 /* window zoom handling added --ben */
12064 case inZoomIn:
12065 case inZoomOut:
12066 if (TrackBox (window_ptr, er.where, part_code))
12067 do_zoom_window (window_ptr, part_code);
12068 break;
12070 #if USE_MAC_TOOLBAR
12071 case inStructure:
12073 OSStatus err;
12074 HIViewRef ch;
12076 err = HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr),
12077 eventRef, &ch);
12078 /* This doesn't work on Mac OS X 10.2. */
12079 if (err == noErr)
12080 HIViewClick (ch, eventRef);
12082 break;
12083 #endif /* USE_MAC_TOOLBAR */
12085 default:
12086 break;
12089 break;
12091 #if !TARGET_API_MAC_CARBON
12092 case updateEvt:
12093 do_window_update ((WindowRef) er.message);
12094 break;
12095 #endif
12097 case osEvt:
12098 switch ((er.message >> 24) & 0x000000FF)
12100 case mouseMovedMessage:
12101 #if !TARGET_API_MAC_CARBON
12102 SetRectRgn (mouse_region, er.where.h, er.where.v,
12103 er.where.h + 1, er.where.v + 1);
12104 #endif
12105 previous_help_echo_string = help_echo_string;
12106 help_echo_string = Qnil;
12108 if (dpyinfo->grabbed && last_mouse_frame
12109 && FRAME_LIVE_P (last_mouse_frame))
12110 f = last_mouse_frame;
12111 else
12112 f = dpyinfo->x_focus_frame;
12114 if (dpyinfo->mouse_face_hidden)
12116 dpyinfo->mouse_face_hidden = 0;
12117 clear_mouse_face (dpyinfo);
12120 if (f)
12122 WindowRef wp = FRAME_MAC_WINDOW (f);
12123 Point mouse_pos;
12125 mouse_pos.h = (er.where.h
12126 - (f->left_pos
12127 + FRAME_OUTER_TO_INNER_DIFF_X (f)));
12128 mouse_pos.v = (er.where.v
12129 - (f->top_pos
12130 + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
12131 if (dpyinfo->grabbed && tracked_scroll_bar)
12132 #ifdef USE_TOOLKIT_SCROLL_BARS
12133 x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
12134 mouse_pos, &inev);
12135 #else /* not USE_TOOLKIT_SCROLL_BARS */
12136 x_scroll_bar_note_movement (tracked_scroll_bar,
12137 mouse_pos.v
12138 - XINT (tracked_scroll_bar->top),
12139 er.when * (1000 / 60));
12140 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12141 else
12143 /* Generate SELECT_WINDOW_EVENTs when needed. */
12144 if (!NILP (Vmouse_autoselect_window))
12146 Lisp_Object window;
12148 window = window_from_coordinates (f,
12149 mouse_pos.h,
12150 mouse_pos.v,
12151 0, 0, 0, 0);
12153 /* Window will be selected only when it is
12154 not selected now and last mouse movement
12155 event was not in it. Minibuffer window
12156 will be selected only when it is active. */
12157 if (WINDOWP (window)
12158 && !EQ (window, last_window)
12159 && !EQ (window, selected_window)
12160 /* For click-to-focus window managers
12161 create event iff we don't leave the
12162 selected frame. */
12163 && (focus_follows_mouse
12164 || (EQ (XWINDOW (window)->frame,
12165 XWINDOW (selected_window)->frame))))
12167 inev.kind = SELECT_WINDOW_EVENT;
12168 inev.frame_or_window = window;
12171 last_window=window;
12173 if (!note_mouse_movement (f, &mouse_pos))
12174 help_echo_string = previous_help_echo_string;
12175 #if USE_MAC_TOOLBAR
12176 else
12177 mac_tool_bar_note_mouse_movement (f, eventRef);
12178 #endif
12182 /* If the contents of the global variable
12183 help_echo_string has changed, generate a
12184 HELP_EVENT. */
12185 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
12186 do_help = 1;
12187 break;
12189 default:
12190 goto OTHER;
12192 break;
12194 case activateEvt:
12196 WindowRef window_ptr = (WindowRef) er.message;
12197 OSErr err;
12198 ControlRef root_control;
12200 if (window_ptr == tip_window)
12202 HideWindow (tip_window);
12203 break;
12206 if (!is_emacs_window (window_ptr))
12207 goto OTHER;
12209 f = mac_window_to_frame (window_ptr);
12211 if ((er.modifiers & activeFlag) != 0)
12213 /* A window has been activated */
12214 Point mouse_loc;
12216 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
12217 if (err == noErr)
12218 ActivateControl (root_control);
12220 x_detect_focus_change (dpyinfo, &er, &inev);
12222 mouse_loc.h = (er.where.h
12223 - (f->left_pos
12224 + FRAME_OUTER_TO_INNER_DIFF_X (f)));
12225 mouse_loc.v = (er.where.v
12226 - (f->top_pos
12227 + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
12228 /* Window-activated event counts as mouse movement,
12229 so update things that depend on mouse position. */
12230 note_mouse_movement (f, &mouse_loc);
12232 else
12234 /* A window has been deactivated */
12235 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
12236 if (err == noErr)
12237 DeactivateControl (root_control);
12239 #ifdef USE_TOOLKIT_SCROLL_BARS
12240 if (dpyinfo->grabbed && tracked_scroll_bar)
12242 struct input_event event;
12244 EVENT_INIT (event);
12245 event.kind = NO_EVENT;
12246 x_scroll_bar_handle_release (tracked_scroll_bar, &event);
12247 if (event.kind != NO_EVENT)
12249 event.timestamp = timestamp;
12250 kbd_buffer_store_event_hold (&event, hold_quit);
12251 count++;
12254 #endif
12255 dpyinfo->grabbed = 0;
12257 x_detect_focus_change (dpyinfo, &er, &inev);
12259 if (f == dpyinfo->mouse_face_mouse_frame)
12261 /* If we move outside the frame, then we're
12262 certainly no longer on any text in the
12263 frame. */
12264 clear_mouse_face (dpyinfo);
12265 dpyinfo->mouse_face_mouse_frame = 0;
12268 /* Generate a nil HELP_EVENT to cancel a help-echo.
12269 Do it only if there's something to cancel.
12270 Otherwise, the startup message is cleared when the
12271 mouse leaves the frame. */
12272 if (any_help_event_p)
12273 do_help = -1;
12276 break;
12278 case keyDown:
12279 case keyUp:
12280 case autoKey:
12281 ObscureCursor ();
12283 f = mac_focus_frame (dpyinfo);
12284 XSETFRAME (inev.frame_or_window, f);
12286 /* If mouse-highlight is an integer, input clears out mouse
12287 highlighting. */
12288 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
12289 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
12291 clear_mouse_face (dpyinfo);
12292 dpyinfo->mouse_face_hidden = 1;
12296 UInt32 modifiers = er.modifiers, mapped_modifiers;
12298 #ifdef MAC_OSX
12299 GetEventParameter (eventRef, kEventParamKeyModifiers,
12300 typeUInt32, NULL,
12301 sizeof (UInt32), NULL, &modifiers);
12302 #endif
12303 mapped_modifiers = mac_mapped_modifiers (modifiers);
12305 #if TARGET_API_MAC_CARBON
12306 if (!(mapped_modifiers
12307 & ~(mac_pass_command_to_system ? cmdKey : 0)
12308 & ~(mac_pass_control_to_system ? controlKey : 0)))
12309 goto OTHER;
12310 else
12311 #endif
12312 if (er.what != keyUp)
12313 do_keystroke (er.what, er.message & charCodeMask,
12314 (er.message & keyCodeMask) >> 8,
12315 modifiers, timestamp, &inev);
12317 break;
12319 case kHighLevelEvent:
12320 AEProcessAppleEvent (&er);
12321 break;
12323 default:
12324 OTHER:
12325 #if TARGET_API_MAC_CARBON
12327 OSStatus err;
12329 read_socket_inev = &inev;
12330 err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
12331 read_socket_inev = NULL;
12333 #endif
12334 break;
12336 #if TARGET_API_MAC_CARBON
12337 ReleaseEvent (eventRef);
12338 #endif
12340 if (inev.kind != NO_EVENT)
12342 inev.timestamp = timestamp;
12343 kbd_buffer_store_event_hold (&inev, hold_quit);
12344 count++;
12347 if (do_help
12348 && !(hold_quit && hold_quit->kind != NO_EVENT))
12350 Lisp_Object frame;
12352 if (f)
12353 XSETFRAME (frame, f);
12354 else
12355 frame = Qnil;
12357 if (do_help > 0)
12359 any_help_event_p = 1;
12360 gen_help_event (help_echo_string, frame, help_echo_window,
12361 help_echo_object, help_echo_pos);
12363 else
12365 help_echo_string = Qnil;
12366 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
12368 count++;
12372 /* If the focus was just given to an autoraising frame,
12373 raise it now. */
12374 /* ??? This ought to be able to handle more than one such frame. */
12375 if (pending_autoraise_frame)
12377 x_raise_frame (pending_autoraise_frame);
12378 pending_autoraise_frame = 0;
12381 if (mac_screen_config_changed)
12383 mac_get_screen_info (dpyinfo);
12384 mac_screen_config_changed = 0;
12387 #if !TARGET_API_MAC_CARBON
12388 /* Check which frames are still visible. We do this here because
12389 there doesn't seem to be any direct notification from the Window
12390 Manager that the visibility of a window has changed (at least,
12391 not in all cases). */
12393 Lisp_Object tail, frame;
12395 FOR_EACH_FRAME (tail, frame)
12397 struct frame *f = XFRAME (frame);
12399 /* The tooltip has been drawn already. Avoid the
12400 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12401 if (EQ (frame, tip_frame))
12402 continue;
12404 if (FRAME_MAC_P (f))
12405 mac_handle_visibility_change (f);
12408 #endif
12410 --handling_signal;
12411 UNBLOCK_INPUT;
12412 return count;
12416 /* Need to override CodeWarrior's input function so no conversion is
12417 done on newlines Otherwise compiled functions in .elc files will be
12418 read incorrectly. Defined in ...:MSL C:MSL
12419 Common:Source:buffer_io.c. */
12420 #ifdef __MWERKS__
12421 void
12422 __convert_to_newlines (unsigned char * p, size_t * n)
12424 #pragma unused(p,n)
12427 void
12428 __convert_from_newlines (unsigned char * p, size_t * n)
12430 #pragma unused(p,n)
12432 #endif
12434 #ifdef MAC_OS8
12435 void
12436 make_mac_terminal_frame (struct frame *f)
12438 Lisp_Object frame;
12439 Rect r;
12441 XSETFRAME (frame, f);
12443 f->output_method = output_mac;
12444 f->output_data.mac = (struct mac_output *)
12445 xmalloc (sizeof (struct mac_output));
12446 bzero (f->output_data.mac, sizeof (struct mac_output));
12448 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
12450 FRAME_COLS (f) = 96;
12451 FRAME_LINES (f) = 4;
12453 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
12454 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
12456 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
12458 f->output_data.mac->cursor_pixel = 0;
12459 f->output_data.mac->border_pixel = 0x00ff00;
12460 f->output_data.mac->mouse_pixel = 0xff00ff;
12461 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
12463 f->output_data.mac->text_cursor = kThemeIBeamCursor;
12464 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
12465 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
12466 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
12467 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
12468 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
12470 FRAME_FONTSET (f) = -1;
12471 f->output_data.mac->explicit_parent = 0;
12472 f->left_pos = 8;
12473 f->top_pos = 32;
12474 f->border_width = 0;
12476 f->internal_border_width = 0;
12478 f->auto_raise = 1;
12479 f->auto_lower = 1;
12481 f->new_text_cols = 0;
12482 f->new_text_lines = 0;
12484 SetRect (&r, f->left_pos, f->top_pos,
12485 f->left_pos + FRAME_PIXEL_WIDTH (f),
12486 f->top_pos + FRAME_PIXEL_HEIGHT (f));
12488 BLOCK_INPUT;
12490 if (!(FRAME_MAC_WINDOW (f) =
12491 NewCWindow (NULL, &r, "\p", true, dBoxProc,
12492 (WindowRef) -1, 1, (long) f->output_data.mac)))
12493 abort ();
12494 /* so that update events can find this mac_output struct */
12495 f->output_data.mac->mFP = f; /* point back to emacs frame */
12497 UNBLOCK_INPUT;
12499 x_make_gc (f);
12501 /* Need to be initialized for unshow_buffer in window.c. */
12502 selected_window = f->selected_window;
12504 Fmodify_frame_parameters (frame,
12505 Fcons (Fcons (Qfont,
12506 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
12507 Fmodify_frame_parameters (frame,
12508 Fcons (Fcons (Qforeground_color,
12509 build_string ("black")), Qnil));
12510 Fmodify_frame_parameters (frame,
12511 Fcons (Fcons (Qbackground_color,
12512 build_string ("white")), Qnil));
12514 #endif
12517 /***********************************************************************
12518 Initialization
12519 ***********************************************************************/
12521 static int mac_initialized = 0;
12523 static XrmDatabase
12524 mac_make_rdb (xrm_option)
12525 const char *xrm_option;
12527 XrmDatabase database;
12529 database = xrm_get_preference_database (NULL);
12530 if (xrm_option)
12531 xrm_merge_string_database (database, xrm_option);
12533 return database;
12536 struct mac_display_info *
12537 mac_term_init (display_name, xrm_option, resource_name)
12538 Lisp_Object display_name;
12539 char *xrm_option;
12540 char *resource_name;
12542 struct mac_display_info *dpyinfo;
12543 struct terminal *terminal;
12545 BLOCK_INPUT;
12547 if (!mac_initialized)
12549 mac_initialize ();
12550 mac_initialized = 1;
12553 if (x_display_list)
12554 error ("Sorry, this version can only handle one display");
12556 dpyinfo = &one_mac_display_info;
12557 bzero (dpyinfo, sizeof (*dpyinfo));
12559 terminal = mac_create_terminal (dpyinfo);
12561 /* Set the name of the terminal. */
12562 terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
12563 strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
12564 terminal->name[SBYTES (display_name)] = 0;
12566 #ifdef MAC_OSX
12567 dpyinfo->mac_id_name
12568 = (char *) xmalloc (SCHARS (Vinvocation_name)
12569 + SCHARS (Vsystem_name)
12570 + 2);
12571 sprintf (dpyinfo->mac_id_name, "%s@%s",
12572 SDATA (Vinvocation_name), SDATA (Vsystem_name));
12573 #else
12574 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
12575 strcpy (dpyinfo->mac_id_name, "Mac Display");
12576 #endif
12578 dpyinfo->reference_count = 0;
12579 dpyinfo->resx = 72.0;
12580 dpyinfo->resy = 72.0;
12582 mac_get_screen_info (dpyinfo);
12584 dpyinfo->grabbed = 0;
12585 dpyinfo->root_window = NULL;
12586 dpyinfo->image_cache = make_image_cache ();
12588 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
12589 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
12590 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
12591 dpyinfo->mouse_face_window = Qnil;
12592 dpyinfo->mouse_face_overlay = Qnil;
12593 dpyinfo->mouse_face_hidden = 0;
12595 dpyinfo->xrdb = mac_make_rdb (xrm_option);
12597 /* Put this display on the chain. */
12598 dpyinfo->next = x_display_list;
12599 x_display_list = dpyinfo;
12601 /* Put it on x_display_name_list. */
12602 x_display_name_list = Fcons (Fcons (display_name,
12603 Fcons (Qnil, dpyinfo->xrdb)),
12604 x_display_name_list);
12605 dpyinfo->name_list_element = XCAR (x_display_name_list);
12607 /* FIXME: Untested.
12608 Add the default keyboard. */
12609 add_keyboard_wait_descriptor (0);
12611 #if USE_CG_DRAWING
12612 mac_init_fringe (terminal->rif);
12613 #endif
12615 UNBLOCK_INPUT;
12617 return dpyinfo;
12620 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12622 void
12623 x_delete_display (dpyinfo)
12624 struct mac_display_info *dpyinfo;
12626 int i;
12628 /* Discard this display from x_display_name_list and x_display_list.
12629 We can't use Fdelq because that can quit. */
12630 if (! NILP (x_display_name_list)
12631 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
12632 x_display_name_list = XCDR (x_display_name_list);
12633 else
12635 Lisp_Object tail;
12637 tail = x_display_name_list;
12638 while (CONSP (tail) && CONSP (XCDR (tail)))
12640 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
12642 XSETCDR (tail, XCDR (XCDR (tail)));
12643 break;
12645 tail = XCDR (tail);
12649 if (x_display_list == dpyinfo)
12650 x_display_list = dpyinfo->next;
12651 else
12653 struct x_display_info *tail;
12655 for (tail = x_display_list; tail; tail = tail->next)
12656 if (tail->next == dpyinfo)
12657 tail->next = tail->next->next;
12660 /* Free the font names in the font table. */
12661 for (i = 0; i < dpyinfo->n_fonts; i++)
12662 if (dpyinfo->font_table[i].name)
12664 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
12665 xfree (dpyinfo->font_table[i].full_name);
12666 xfree (dpyinfo->font_table[i].name);
12669 if (dpyinfo->font_table)
12671 if (dpyinfo->font_table->font_encoder)
12672 xfree (dpyinfo->font_table->font_encoder);
12673 xfree (dpyinfo->font_table);
12675 if (dpyinfo->mac_id_name)
12676 xfree (dpyinfo->mac_id_name);
12678 if (x_display_list == 0)
12680 mac_clear_font_name_table ();
12681 bzero (dpyinfo, sizeof (*dpyinfo));
12686 static void
12687 init_menu_bar ()
12689 #ifdef MAC_OSX
12690 OSStatus err;
12691 MenuRef menu;
12692 MenuItemIndex menu_index;
12694 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
12695 &menu, &menu_index);
12696 if (err == noErr)
12697 SetMenuItemCommandKey (menu, menu_index, false, 0);
12698 EnableMenuCommand (NULL, kHICommandPreferences);
12699 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
12700 &menu, &menu_index);
12701 if (err == noErr)
12703 SetMenuItemCommandKey (menu, menu_index, false, 0);
12704 InsertMenuItemTextWithCFString (menu, NULL,
12705 0, kMenuItemAttrSeparator, 0);
12706 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
12707 0, 0, kHICommandAbout);
12709 #else /* !MAC_OSX */
12710 #if TARGET_API_MAC_CARBON
12711 SetMenuItemCommandID (GetMenuRef (M_APPLE), I_ABOUT, kHICommandAbout);
12712 #endif
12713 #endif
12716 #if USE_MAC_TSM
12717 static void
12718 init_tsm ()
12720 #ifdef MAC_OSX
12721 static InterfaceTypeList types = {kUnicodeDocument};
12722 #else
12723 static InterfaceTypeList types = {kTextService};
12724 #endif
12726 NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
12727 &tsm_document_id, 0);
12729 #endif
12731 /* Set up use of X before we make the first connection. */
12733 extern frame_parm_handler mac_frame_parm_handlers[];
12735 static struct redisplay_interface x_redisplay_interface =
12737 mac_frame_parm_handlers,
12738 x_produce_glyphs,
12739 x_write_glyphs,
12740 x_insert_glyphs,
12741 x_clear_end_of_line,
12742 x_scroll_run,
12743 x_after_update_window_line,
12744 x_update_window_begin,
12745 x_update_window_end,
12746 x_cursor_to,
12747 x_flush,
12748 #if USE_CG_DRAWING
12749 mac_flush_display_optional,
12750 #else
12751 0, /* flush_display_optional */
12752 #endif
12753 x_clear_window_mouse_face,
12754 x_get_glyph_overhangs,
12755 x_fix_overlapping_area,
12756 x_draw_fringe_bitmap,
12757 #if USE_CG_DRAWING
12758 mac_define_fringe_bitmap,
12759 mac_destroy_fringe_bitmap,
12760 #else
12761 0, /* define_fringe_bitmap */
12762 0, /* destroy_fringe_bitmap */
12763 #endif
12764 mac_per_char_metric,
12765 mac_encode_char,
12766 mac_compute_glyph_string_overhangs,
12767 x_draw_glyph_string,
12768 mac_define_frame_cursor,
12769 mac_clear_frame_area,
12770 mac_draw_window_cursor,
12771 mac_draw_vertical_window_border,
12772 mac_shift_glyphs_for_insert
12775 static struct terminal *
12776 mac_create_terminal (struct mac_display_info *dpyinfo)
12778 struct terminal *terminal;
12780 terminal = create_terminal ();
12782 terminal->type = output_mac;
12783 terminal->display_info.mac = dpyinfo;
12784 dpyinfo->terminal = terminal;
12786 terminal->clear_frame_hook = x_clear_frame;
12787 terminal->ins_del_lines_hook = x_ins_del_lines;
12788 terminal->delete_glyphs_hook = x_delete_glyphs;
12789 terminal->ring_bell_hook = XTring_bell;
12790 terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
12791 terminal->set_terminal_modes_hook = XTset_terminal_modes;
12792 terminal->update_begin_hook = x_update_begin;
12793 terminal->update_end_hook = x_update_end;
12794 terminal->set_terminal_window_hook = XTset_terminal_window;
12795 terminal->read_socket_hook = XTread_socket;
12796 terminal->frame_up_to_date_hook = XTframe_up_to_date;
12797 terminal->mouse_position_hook = XTmouse_position;
12798 terminal->frame_rehighlight_hook = XTframe_rehighlight;
12799 terminal->frame_raise_lower_hook = XTframe_raise_lower;
12800 /* terminal->fullscreen_hook = XTfullscreen_hook; */
12801 terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
12802 terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
12803 terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
12804 terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
12805 terminal->delete_frame_hook = x_destroy_window;
12806 /* terminal->delete_terminal_hook = x_delete_terminal; */
12808 terminal->rif = &x_redisplay_interface;
12809 #if 0
12810 TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
12811 TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
12812 TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
12813 TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
12814 TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
12815 scrolls off the
12816 bottom */
12817 #else
12818 terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
12819 terminal->char_ins_del_ok = 1;
12820 terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
12821 terminal->fast_clear_end_of_line = 1; /* X does this well. */
12822 terminal->memory_below_frame = 0; /* We don't remember what scrolls
12823 off the bottom. */
12825 #endif
12827 /* FIXME: This keyboard setup is 100% untested, just copied from
12828 w32_create_terminal in order to set window-system now that it's
12829 a keyboard object. */
12830 /* We don't yet support separate terminals on Mac, so don't try to share
12831 keyboards between virtual terminals that are on the same physical
12832 terminal like X does. */
12833 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
12834 init_kboard (terminal->kboard);
12835 terminal->kboard->Vwindow_system = intern ("mac");
12836 terminal->kboard->next_kboard = all_kboards;
12837 all_kboards = terminal->kboard;
12838 /* Don't let the initial kboard remain current longer than necessary.
12839 That would cause problems if a file loaded on startup tries to
12840 prompt in the mini-buffer. */
12841 if (current_kboard == initial_kboard)
12842 current_kboard = terminal->kboard;
12843 terminal->kboard->reference_count++;
12845 return terminal;
12848 static void
12849 mac_initialize ()
12852 baud_rate = 19200;
12854 last_tool_bar_item = -1;
12855 any_help_event_p = 0;
12857 /* Try to use interrupt input; if we can't, then start polling. */
12858 Fset_input_interrupt_mode (Qt);
12860 BLOCK_INPUT;
12862 #if TARGET_API_MAC_CARBON
12864 install_application_handler ();
12866 init_menu_bar ();
12868 #if USE_MAC_TSM
12869 init_tsm ();
12870 #endif
12872 #ifdef MAC_OSX
12873 init_coercion_handler ();
12875 init_apple_event_handler ();
12877 init_dm_notification_handler ();
12879 if (!inhibit_window_system)
12881 static const ProcessSerialNumber psn = {0, kCurrentProcess};
12883 SetFrontProcess (&psn);
12885 #endif
12886 #endif
12888 #if USE_CG_DRAWING
12889 init_cg_color ();
12890 #endif
12892 UNBLOCK_INPUT;
12897 void
12898 syms_of_macterm ()
12900 #if 0
12901 staticpro (&x_error_message_string);
12902 x_error_message_string = Qnil;
12903 #endif
12905 Qcontrol = intern ("control"); staticpro (&Qcontrol);
12906 Qmeta = intern ("meta"); staticpro (&Qmeta);
12907 Qalt = intern ("alt"); staticpro (&Qalt);
12908 Qhyper = intern ("hyper"); staticpro (&Qhyper);
12909 Qsuper = intern ("super"); staticpro (&Qsuper);
12910 Qmodifier_value = intern ("modifier-value");
12911 staticpro (&Qmodifier_value);
12913 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
12914 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
12915 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
12916 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
12917 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
12919 #if TARGET_API_MAC_CARBON
12920 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
12921 #ifdef MAC_OSX
12922 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
12923 staticpro (&Qtoolbar_switch_mode);
12924 #if USE_MAC_FONT_PANEL
12925 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
12926 Qselection = intern ("selection"); staticpro (&Qselection);
12927 #endif
12929 Qservice = intern ("service"); staticpro (&Qservice);
12930 Qpaste = intern ("paste"); staticpro (&Qpaste);
12931 Qperform = intern ("perform"); staticpro (&Qperform);
12932 #endif
12933 #if USE_MAC_TSM
12934 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
12935 Qupdate_active_input_area = intern ("update-active-input-area");
12936 staticpro (&Qupdate_active_input_area);
12937 Qunicode_for_key_event = intern ("unicode-for-key-event");
12938 staticpro (&Qunicode_for_key_event);
12939 #endif
12940 #endif
12942 #ifdef MAC_OSX
12943 Fprovide (intern ("mac-carbon"), Qnil);
12944 #endif
12946 staticpro (&Qreverse);
12947 Qreverse = intern ("reverse");
12949 staticpro (&x_display_name_list);
12950 x_display_name_list = Qnil;
12952 staticpro (&last_mouse_scroll_bar);
12953 last_mouse_scroll_bar = Qnil;
12955 staticpro (&fm_font_family_alist);
12956 fm_font_family_alist = Qnil;
12958 #if USE_ATSUI
12959 staticpro (&atsu_font_id_hash);
12960 atsu_font_id_hash = Qnil;
12962 staticpro (&fm_style_face_attributes_alist);
12963 fm_style_face_attributes_alist = Qnil;
12964 #endif
12966 #if USE_MAC_TSM
12967 staticpro (&saved_ts_script_language_on_focus);
12968 saved_ts_script_language_on_focus = Qnil;
12969 #endif
12971 /* We don't yet support this, but defining this here avoids whining
12972 from cus-start.el and other places, like "M-x set-variable". */
12973 DEFVAR_BOOL ("x-use-underline-position-properties",
12974 &x_use_underline_position_properties,
12975 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12976 A value of nil means ignore them. If you encounter fonts with bogus
12977 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12978 to 4.1, set this to nil.
12980 NOTE: Not supported on Mac yet. */);
12981 x_use_underline_position_properties = 0;
12983 DEFVAR_BOOL ("x-underline-at-descent-line",
12984 &x_underline_at_descent_line,
12985 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
12986 A value of nil means to draw the underline according to the value of the
12987 variable `x-use-underline-position-properties', which is usually at the
12988 baseline level. The default value is nil. */);
12989 x_underline_at_descent_line = 0;
12991 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
12992 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
12993 #ifdef USE_TOOLKIT_SCROLL_BARS
12994 Vx_toolkit_scroll_bars = Qt;
12995 #else
12996 Vx_toolkit_scroll_bars = Qnil;
12997 #endif
12999 staticpro (&last_mouse_motion_frame);
13000 last_mouse_motion_frame = Qnil;
13002 /* Variables to configure modifier key assignment. */
13004 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
13005 doc: /* *Modifier key assumed when the Mac control key is pressed.
13006 The value can be `control', `meta', `alt', `hyper', or `super' for the
13007 respective modifier. The default is `control'. */);
13008 Vmac_control_modifier = Qcontrol;
13010 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
13011 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
13012 The value can be `control', `meta', `alt', `hyper', or `super' for the
13013 respective modifier. If the value is nil then the key will act as the
13014 normal Mac control modifier, and the option key can be used to compose
13015 characters depending on the chosen Mac keyboard setting. */);
13016 Vmac_option_modifier = Qnil;
13018 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
13019 doc: /* *Modifier key assumed when the Mac command key is pressed.
13020 The value can be `control', `meta', `alt', `hyper', or `super' for the
13021 respective modifier. The default is `meta'. */);
13022 Vmac_command_modifier = Qmeta;
13024 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
13025 doc: /* *Modifier key assumed when the Mac function key is pressed.
13026 The value can be `control', `meta', `alt', `hyper', or `super' for the
13027 respective modifier. Note that remapping the function key may lead to
13028 unexpected results for some keys on non-US/GB keyboards. */);
13029 Vmac_function_modifier = Qnil;
13031 DEFVAR_LISP ("mac-emulate-three-button-mouse",
13032 &Vmac_emulate_three_button_mouse,
13033 doc: /* *Specify a way of three button mouse emulation.
13034 The value can be nil, t, or the symbol `reverse'.
13035 A value of nil means that no emulation should be done and the modifiers
13036 should be placed on the mouse-1 event.
13037 t means that when the option-key is held down while pressing the mouse
13038 button, the click will register as mouse-2 and while the command-key
13039 is held down, the click will register as mouse-3.
13040 The symbol `reverse' means that the option-key will register for
13041 mouse-3 and the command-key will register for mouse-2. */);
13042 Vmac_emulate_three_button_mouse = Qnil;
13044 #if TARGET_API_MAC_CARBON
13045 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
13046 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
13047 Otherwise, the right click will be treated as mouse-2 and the wheel
13048 button will be mouse-3. */);
13049 mac_wheel_button_is_mouse_2 = 1;
13051 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
13052 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
13053 mac_pass_command_to_system = 1;
13055 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
13056 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
13057 mac_pass_control_to_system = 1;
13059 #endif
13061 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
13062 doc: /* *If non-nil, allow anti-aliasing.
13063 The text will be rendered using Core Graphics text rendering which
13064 may anti-alias the text. */);
13065 #if USE_CG_DRAWING
13066 mac_use_core_graphics = 1;
13067 #else
13068 mac_use_core_graphics = 0;
13069 #endif
13071 /* Register an entry for `mac-roman' so that it can be used when
13072 creating the terminal frame on Mac OS 9 before loading
13073 term/mac-win.elc. */
13074 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
13075 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
13076 Each entry should be of the form:
13078 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13080 where CHARSET-NAME is a string used in font names to identify the
13081 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13082 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13083 Vmac_charset_info_alist =
13084 Fcons (list3 (build_string ("mac-roman"),
13085 make_number (smRoman), Qnil), Qnil);
13087 #if USE_MAC_TSM
13088 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
13089 doc: /* Overlay used to display Mac TSM active input area. */);
13090 Vmac_ts_active_input_overlay = Qnil;
13092 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
13093 doc: /* *How to change Mac TSM script/language when a frame gets focus.
13094 If the value is t, the input script and language are restored to those
13095 used in the last focus frame. If the value is a pair of integers, the
13096 input script and language codes, which are defined in the Script
13097 Manager, are set to its car and cdr parts, respectively. Otherwise,
13098 Emacs doesn't set them and thus follows the system default behavior. */);
13099 Vmac_ts_script_language_on_focus = Qnil;
13100 #endif
13103 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13104 (do not change this comment) */