Replace MenuHandle and GetMenuHandle with MenuRef and
[emacs.git] / src / macterm.c
blob9e5753ec3cca3c2b0f2d88970bdf816951716a62
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 void mac_initialize P_ ((void));
230 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
231 static int x_compute_min_glyph_bounds P_ ((struct frame *));
232 static void x_update_end P_ ((struct frame *));
233 static void XTframe_up_to_date P_ ((struct frame *));
234 static void XTset_terminal_modes P_ ((void));
235 static void XTreset_terminal_modes P_ ((void));
236 static void x_clear_frame P_ ((void));
237 static void frame_highlight P_ ((struct frame *));
238 static void frame_unhighlight P_ ((struct frame *));
239 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
240 static void mac_focus_changed P_ ((int, struct mac_display_info *,
241 struct frame *, struct input_event *));
242 static void x_detect_focus_change P_ ((struct mac_display_info *,
243 const EventRecord *,
244 struct input_event *));
245 static void XTframe_rehighlight P_ ((struct frame *));
246 static void x_frame_rehighlight P_ ((struct x_display_info *));
247 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
248 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
249 enum text_cursor_kinds));
251 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
252 static void x_flush P_ ((struct frame *f));
253 static void x_update_begin P_ ((struct frame *));
254 static void x_update_window_begin P_ ((struct window *));
255 static void x_after_update_window_line P_ ((struct glyph_row *));
256 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
257 enum scroll_bar_part *,
258 Lisp_Object *, Lisp_Object *,
259 unsigned long *));
261 static int is_emacs_window P_ ((WindowRef));
262 static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
263 static void XSetFont P_ ((Display *, GC, XFontStruct *));
265 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
266 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
267 #define GC_FONT(gc) ((gc)->xgcv.font)
268 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
270 #define CG_SET_FILL_COLOR(context, color) \
271 CGContextSetRGBFillColor (context, \
272 RED_FROM_ULONG (color) / 255.0f, \
273 GREEN_FROM_ULONG (color) / 255.0f, \
274 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
275 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
276 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
277 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
278 do { \
279 if (CGColorGetTypeID != NULL) \
280 CGContextSetFillColorWithColor (context, cg_color); \
281 else \
282 CG_SET_FILL_COLOR (context, color); \
283 } while (0)
284 #else
285 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
286 CGContextSetFillColorWithColor (context, cg_color)
287 #endif
288 #else
289 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
290 CG_SET_FILL_COLOR (context, color)
291 #endif
292 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
293 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
294 (gc)->cg_fore_color)
295 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
296 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
297 (gc)->cg_back_color)
300 #define CG_SET_STROKE_COLOR(context, color) \
301 CGContextSetRGBStrokeColor (context, \
302 RED_FROM_ULONG (color) / 255.0f, \
303 GREEN_FROM_ULONG (color) / 255.0f, \
304 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
305 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
306 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
307 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
308 do { \
309 if (CGColorGetTypeID != NULL) \
310 CGContextSetStrokeColorWithColor (context, cg_color); \
311 else \
312 CG_SET_STROKE_COLOR (context, color); \
313 } while (0)
314 #else
315 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
316 CGContextSetStrokeColorWithColor (context, cg_color)
317 #endif
318 #else
319 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
320 CG_SET_STROKE_COLOR (context, color)
321 #endif
322 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
323 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
324 (gc)->cg_fore_color)
326 #if USE_CG_DRAWING
327 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
329 /* Fringe bitmaps. */
331 static int max_fringe_bmp = 0;
332 static CGImageRef *fringe_bmp = 0;
334 static CGColorSpaceRef mac_cg_color_space_rgb;
335 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
336 static CGColorRef mac_cg_color_black;
337 #endif
339 static void
340 init_cg_color ()
342 mac_cg_color_space_rgb = CGColorSpaceCreateDeviceRGB ();
343 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
344 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
345 /* Don't check the availability of CGColorCreate; this symbol is
346 defined even in Mac OS X 10.1. */
347 if (CGColorGetTypeID != NULL)
348 #endif
350 float rgba[] = {0.0f, 0.0f, 0.0f, 1.0f};
352 mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba);
354 #endif
357 static CGContextRef
358 mac_begin_cg_clip (f, gc)
359 struct frame *f;
360 GC gc;
362 CGContextRef context = FRAME_CG_CONTEXT (f);
364 if (!context)
366 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
367 FRAME_CG_CONTEXT (f) = context;
370 CGContextSaveGState (context);
371 CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
372 CGContextScaleCTM (context, 1, -1);
373 if (gc && gc->n_clip_rects)
374 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
376 return context;
379 static void
380 mac_end_cg_clip (f)
381 struct frame *f;
383 CGContextRestoreGState (FRAME_CG_CONTEXT (f));
386 void
387 mac_prepare_for_quickdraw (f)
388 struct frame *f;
390 if (f == NULL)
392 Lisp_Object rest, frame;
393 FOR_EACH_FRAME (rest, frame)
394 if (FRAME_MAC_P (XFRAME (frame)))
395 mac_prepare_for_quickdraw (XFRAME (frame));
397 else
399 CGContextRef context = FRAME_CG_CONTEXT (f);
401 if (context)
403 CGContextSynchronize (context);
404 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
405 &FRAME_CG_CONTEXT (f));
409 #endif
411 static RgnHandle saved_port_clip_region = NULL;
413 static void
414 mac_begin_clip (f, gc)
415 struct frame *f;
416 GC gc;
418 static RgnHandle new_region = NULL;
420 if (saved_port_clip_region == NULL)
421 saved_port_clip_region = NewRgn ();
422 if (new_region == NULL)
423 new_region = NewRgn ();
425 #if USE_CG_DRAWING
426 mac_prepare_for_quickdraw (f);
427 #endif
428 SetPortWindowPort (FRAME_MAC_WINDOW (f));
430 if (gc->n_clip_rects)
432 GetClip (saved_port_clip_region);
433 SectRgn (saved_port_clip_region, gc->clip_region, new_region);
434 SetClip (new_region);
438 static void
439 mac_end_clip (gc)
440 GC gc;
442 if (gc->n_clip_rects)
443 SetClip (saved_port_clip_region);
447 /* X display function emulation */
449 /* Mac version of XDrawLine. */
451 static void
452 mac_draw_line (f, gc, x1, y1, x2, y2)
453 struct frame *f;
454 GC gc;
455 int x1, y1, x2, y2;
457 #if USE_CG_DRAWING
458 CGContextRef context;
459 float gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
461 if (y1 != y2)
462 gx1 += 0.5f, gx2 += 0.5f;
463 if (x1 != x2)
464 gy1 += 0.5f, gy2 += 0.5f;
466 context = mac_begin_cg_clip (f, gc);
467 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
468 CGContextBeginPath (context);
469 CGContextMoveToPoint (context, gx1, gy1);
470 CGContextAddLineToPoint (context, gx2, gy2);
471 CGContextClosePath (context);
472 CGContextStrokePath (context);
473 mac_end_cg_clip (f);
474 #else
475 if (x1 == x2)
477 if (y1 > y2)
478 y1--;
479 else if (y2 > y1)
480 y2--;
482 else if (y1 == y2)
484 if (x1 > x2)
485 x1--;
486 else
487 x2--;
490 mac_begin_clip (f, gc);
491 RGBForeColor (GC_FORE_COLOR (gc));
492 MoveTo (x1, y1);
493 LineTo (x2, y2);
494 mac_end_clip (gc);
495 #endif
498 /* Mac version of XDrawLine (to Pixmap). */
500 void
501 XDrawLine (display, p, gc, x1, y1, x2, y2)
502 Display *display;
503 Pixmap p;
504 GC gc;
505 int x1, y1, x2, y2;
507 CGrafPtr old_port;
508 GDHandle old_gdh;
510 if (x1 == x2)
512 if (y1 > y2)
513 y1--;
514 else if (y2 > y1)
515 y2--;
517 else if (y1 == y2)
519 if (x1 > x2)
520 x1--;
521 else
522 x2--;
525 GetGWorld (&old_port, &old_gdh);
526 SetGWorld (p, NULL);
528 RGBForeColor (GC_FORE_COLOR (gc));
530 LockPixels (GetGWorldPixMap (p));
531 MoveTo (x1, y1);
532 LineTo (x2, y2);
533 UnlockPixels (GetGWorldPixMap (p));
535 SetGWorld (old_port, old_gdh);
539 static void
540 mac_erase_rectangle (f, gc, x, y, width, height)
541 struct frame *f;
542 GC gc;
543 int x, y;
544 unsigned int width, height;
546 #if USE_CG_DRAWING
548 CGContextRef context;
550 context = mac_begin_cg_clip (f, gc);
551 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
552 CGContextFillRect (context, CGRectMake (x, y, width, height));
553 mac_end_cg_clip (f);
555 #else
557 Rect r;
559 mac_begin_clip (f, gc);
560 RGBBackColor (GC_BACK_COLOR (gc));
561 SetRect (&r, x, y, x + width, y + height);
562 EraseRect (&r);
563 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
564 mac_end_clip (gc);
566 #endif
570 /* Mac version of XClearArea. */
572 void
573 mac_clear_area (f, x, y, width, height)
574 struct frame *f;
575 int x, y;
576 unsigned int width, height;
578 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
581 /* Mac version of XClearWindow. */
583 static void
584 mac_clear_window (f)
585 struct frame *f;
587 #if USE_CG_DRAWING
589 CGContextRef context;
590 GC gc = FRAME_NORMAL_GC (f);
592 context = mac_begin_cg_clip (f, NULL);
593 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
594 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
595 FRAME_PIXEL_HEIGHT (f)));
596 mac_end_cg_clip (f);
598 #else /* !USE_CG_DRAWING */
599 SetPortWindowPort (FRAME_MAC_WINDOW (f));
601 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
603 #if TARGET_API_MAC_CARBON
605 Rect r;
607 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
608 EraseRect (&r);
610 #else /* not TARGET_API_MAC_CARBON */
611 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
612 #endif /* not TARGET_API_MAC_CARBON */
613 #endif
617 /* Mac replacement for XCopyArea. */
619 #if USE_CG_DRAWING
620 static void
621 mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
622 dest_x, dest_y, overlay_p)
623 CGImageRef image;
624 struct frame *f;
625 GC gc;
626 int src_x, src_y;
627 unsigned int width, height;
628 int dest_x, dest_y, overlay_p;
630 CGContextRef context;
631 float port_height = FRAME_PIXEL_HEIGHT (f);
632 CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
634 context = mac_begin_cg_clip (f, gc);
635 if (!overlay_p)
637 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
638 CGContextFillRect (context, dest_rect);
640 CGContextClipToRect (context, dest_rect);
641 CGContextScaleCTM (context, 1, -1);
642 CGContextTranslateCTM (context, 0, -port_height);
643 if (CGImageIsMask (image))
644 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
645 CGContextDrawImage (context,
646 CGRectMake (dest_x - src_x,
647 port_height - (dest_y - src_y
648 + CGImageGetHeight (image)),
649 CGImageGetWidth (image),
650 CGImageGetHeight (image)),
651 image);
652 mac_end_cg_clip (f);
655 #else /* !USE_CG_DRAWING */
657 static void
658 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
659 struct frame *f;
660 GC gc;
661 int x, y, width, height;
662 unsigned short *bits;
663 int overlay_p;
665 BitMap bitmap;
666 Rect r;
668 bitmap.rowBytes = sizeof(unsigned short);
669 bitmap.baseAddr = (char *)bits;
670 SetRect (&(bitmap.bounds), 0, 0, width, height);
672 mac_begin_clip (f, gc);
673 RGBForeColor (GC_FORE_COLOR (gc));
674 RGBBackColor (GC_BACK_COLOR (gc));
675 SetRect (&r, x, y, x + width, y + height);
676 #if TARGET_API_MAC_CARBON
678 CGrafPtr port;
680 GetPort (&port);
681 LockPortBits (port);
682 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
683 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
684 UnlockPortBits (port);
686 #else /* not TARGET_API_MAC_CARBON */
687 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
688 overlay_p ? srcOr : srcCopy, 0);
689 #endif /* not TARGET_API_MAC_CARBON */
690 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
691 mac_end_clip (gc);
693 #endif /* !USE_CG_DRAWING */
696 /* Mac replacement for XCreateBitmapFromBitmapData. */
698 static void
699 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
700 BitMap *bitmap;
701 char *bits;
702 int w, h;
704 static const unsigned char swap_nibble[16]
705 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
706 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
707 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
708 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
709 int i, j, w1;
710 char *p;
712 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
713 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
714 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
715 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
716 for (i = 0; i < h; i++)
718 p = bitmap->baseAddr + i * bitmap->rowBytes;
719 for (j = 0; j < w1; j++)
721 /* Bitswap XBM bytes to match how Mac does things. */
722 unsigned char c = *bits++;
723 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
724 | (swap_nibble[(c>>4) & 0xf]));
728 SetRect (&(bitmap->bounds), 0, 0, w, h);
732 static void
733 mac_free_bitmap (bitmap)
734 BitMap *bitmap;
736 xfree (bitmap->baseAddr);
740 Pixmap
741 XCreatePixmap (display, w, width, height, depth)
742 Display *display;
743 WindowRef w;
744 unsigned int width, height;
745 unsigned int depth;
747 Pixmap pixmap;
748 Rect r;
749 QDErr err;
751 SetPortWindowPort (w);
753 SetRect (&r, 0, 0, width, height);
754 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
755 if (depth == 1)
756 #endif
757 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
758 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
759 else
760 /* CreateCGImageFromPixMaps requires ARGB format. */
761 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
762 #endif
763 if (err != noErr)
764 return NULL;
765 return pixmap;
769 Pixmap
770 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
771 Display *display;
772 WindowRef w;
773 char *data;
774 unsigned int width, height;
775 unsigned long fg, bg;
776 unsigned int depth;
778 Pixmap pixmap;
779 BitMap bitmap;
780 CGrafPtr old_port;
781 GDHandle old_gdh;
782 static GC gc = NULL;
784 if (gc == NULL)
785 gc = XCreateGC (display, w, 0, NULL);
787 pixmap = XCreatePixmap (display, w, width, height, depth);
788 if (pixmap == NULL)
789 return NULL;
791 GetGWorld (&old_port, &old_gdh);
792 SetGWorld (pixmap, NULL);
793 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
794 XSetForeground (display, gc, fg);
795 XSetBackground (display, gc, bg);
796 RGBForeColor (GC_FORE_COLOR (gc));
797 RGBBackColor (GC_BACK_COLOR (gc));
798 LockPixels (GetGWorldPixMap (pixmap));
799 #if TARGET_API_MAC_CARBON
800 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
801 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
802 #else /* not TARGET_API_MAC_CARBON */
803 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
804 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
805 #endif /* not TARGET_API_MAC_CARBON */
806 UnlockPixels (GetGWorldPixMap (pixmap));
807 SetGWorld (old_port, old_gdh);
808 mac_free_bitmap (&bitmap);
810 return pixmap;
814 void
815 XFreePixmap (display, pixmap)
816 Display *display;
817 Pixmap pixmap;
819 DisposeGWorld (pixmap);
823 /* Mac replacement for XFillRectangle. */
825 static void
826 mac_fill_rectangle (f, gc, x, y, width, height)
827 struct frame *f;
828 GC gc;
829 int x, y;
830 unsigned int width, height;
832 #if USE_CG_DRAWING
833 CGContextRef context;
835 context = mac_begin_cg_clip (f, gc);
836 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
837 CGContextFillRect (context, CGRectMake (x, y, width, height));
838 mac_end_cg_clip (f);
839 #else
840 Rect r;
842 mac_begin_clip (f, gc);
843 RGBForeColor (GC_FORE_COLOR (gc));
844 SetRect (&r, x, y, x + width, y + height);
845 PaintRect (&r); /* using foreground color of gc */
846 mac_end_clip (gc);
847 #endif
851 /* Mac replacement for XDrawRectangle: dest is a window. */
853 static void
854 mac_draw_rectangle (f, gc, x, y, width, height)
855 struct frame *f;
856 GC gc;
857 int x, y;
858 unsigned int width, height;
860 #if USE_CG_DRAWING
861 CGContextRef context;
863 context = mac_begin_cg_clip (f, gc);
864 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
865 CGContextStrokeRect (context,
866 CGRectMake (x + 0.5f, y + 0.5f, width, height));
867 mac_end_cg_clip (f);
868 #else
869 Rect r;
871 mac_begin_clip (f, gc);
872 RGBForeColor (GC_FORE_COLOR (gc));
873 SetRect (&r, x, y, x + width + 1, y + height + 1);
874 FrameRect (&r); /* using foreground color of gc */
875 mac_end_clip (gc);
876 #endif
880 static void
881 mac_invert_rectangle (f, x, y, width, height)
882 struct frame *f;
883 int x, y;
884 unsigned int width, height;
886 Rect r;
888 #if USE_CG_DRAWING
889 mac_prepare_for_quickdraw (f);
890 #endif
891 SetPortWindowPort (FRAME_MAC_WINDOW (f));
893 SetRect (&r, x, y, x + width, y + height);
895 InvertRect (&r);
899 #if USE_ATSUI
900 static OSStatus
901 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
902 ConstUniCharArrayPtr text;
903 UniCharCount text_length;
904 ATSUStyle style;
905 ATSUTextLayout *text_layout;
907 OSStatus err;
908 static ATSUTextLayout saved_text_layout = NULL;
910 if (saved_text_layout == NULL)
912 static const UniCharCount lengths[] = {kATSUToTextEnd};
913 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
914 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
915 static ATSLineLayoutOptions line_layout =
916 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
917 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
918 | kATSLineUseQDRendering
919 #else
920 kATSLineIsDisplayOnly | kATSLineFractDisable
921 #endif
923 static const ATSUAttributeValuePtr values[] = {&line_layout};
925 err = ATSUCreateTextLayoutWithTextPtr (text,
926 kATSUFromTextBeginning,
927 kATSUToTextEnd,
928 text_length,
929 1, lengths, &style,
930 &saved_text_layout);
931 if (err == noErr)
932 err = ATSUSetLayoutControls (saved_text_layout,
933 sizeof (tags) / sizeof (tags[0]),
934 tags, sizes, values);
935 if (err == noErr)
936 err = ATSUSetTransientFontMatching (saved_text_layout, true);
938 else
940 err = ATSUSetRunStyle (saved_text_layout, style,
941 kATSUFromTextBeginning, kATSUToTextEnd);
942 if (err == noErr)
943 err = ATSUSetTextPointerLocation (saved_text_layout, text,
944 kATSUFromTextBeginning,
945 kATSUToTextEnd,
946 text_length);
949 if (err == noErr)
950 *text_layout = saved_text_layout;
951 return err;
955 static void
956 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
957 overstrike_p, bytes_per_char)
958 struct frame *f;
959 GC gc;
960 int x, y;
961 char *buf;
962 int nchars, bg_width, overstrike_p, bytes_per_char;
964 OSStatus err;
965 ATSUTextLayout text_layout;
967 xassert (bytes_per_char == 2);
969 #ifndef WORDS_BIG_ENDIAN
971 int i;
972 UniChar *text = (UniChar *)buf;
974 for (i = 0; i < nchars; i++)
975 text[i] = EndianU16_BtoN (text[i]);
977 #endif
978 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
979 nchars,
980 GC_FONT (gc)->mac_style,
981 &text_layout);
982 if (err != noErr)
983 return;
984 #ifdef MAC_OSX
985 if (!mac_use_core_graphics)
987 #endif
988 mac_begin_clip (f, gc);
989 RGBForeColor (GC_FORE_COLOR (gc));
990 if (bg_width)
992 Rect r;
994 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
995 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
996 RGBBackColor (GC_BACK_COLOR (gc));
997 EraseRect (&r);
998 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1000 MoveTo (x, y);
1001 ATSUDrawText (text_layout,
1002 kATSUFromTextBeginning, kATSUToTextEnd,
1003 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1004 if (overstrike_p)
1006 MoveTo (x + 1, y);
1007 ATSUDrawText (text_layout,
1008 kATSUFromTextBeginning, kATSUToTextEnd,
1009 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1011 mac_end_clip (gc);
1012 #ifdef MAC_OSX
1014 else
1016 static CGContextRef context;
1017 float port_height = FRAME_PIXEL_HEIGHT (f);
1018 static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
1019 static const ByteCount sizes[] = {sizeof (CGContextRef)};
1020 static const ATSUAttributeValuePtr values[] = {&context};
1022 #if USE_CG_DRAWING
1023 context = mac_begin_cg_clip (f, gc);
1024 #else
1025 CGrafPtr port;
1027 GetPort (&port);
1028 QDBeginCGContext (port, &context);
1029 if (gc->n_clip_rects || bg_width)
1031 CGContextTranslateCTM (context, 0, port_height);
1032 CGContextScaleCTM (context, 1, -1);
1033 if (gc->n_clip_rects)
1034 CGContextClipToRects (context, gc->clip_rects,
1035 gc->n_clip_rects);
1036 #endif
1037 if (bg_width)
1039 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1040 CGContextFillRect (context,
1041 CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
1042 bg_width,
1043 FONT_HEIGHT (GC_FONT (gc))));
1045 CGContextScaleCTM (context, 1, -1);
1046 CGContextTranslateCTM (context, 0, -port_height);
1047 #if !USE_CG_DRAWING
1049 #endif
1050 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1051 err = ATSUSetLayoutControls (text_layout,
1052 sizeof (tags) / sizeof (tags[0]),
1053 tags, sizes, values);
1054 if (err == noErr)
1056 ATSUDrawText (text_layout,
1057 kATSUFromTextBeginning, kATSUToTextEnd,
1058 Long2Fix (x), Long2Fix (port_height - y));
1059 if (overstrike_p)
1060 ATSUDrawText (text_layout,
1061 kATSUFromTextBeginning, kATSUToTextEnd,
1062 Long2Fix (x + 1), Long2Fix (port_height - y));
1064 #if USE_CG_DRAWING
1065 mac_end_cg_clip (f);
1066 context = NULL;
1067 #else
1068 CGContextSynchronize (context);
1069 QDEndCGContext (port, &context);
1070 #endif
1071 #if 0
1072 /* This doesn't work on Mac OS X 10.1. */
1073 ATSUClearLayoutControls (text_layout,
1074 sizeof (tags) / sizeof (tags[0]), tags);
1075 #else
1076 ATSUSetLayoutControls (text_layout,
1077 sizeof (tags) / sizeof (tags[0]),
1078 tags, sizes, values);
1079 #endif
1081 #endif /* MAC_OSX */
1083 #endif /* USE_ATSUI */
1086 static void
1087 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1088 overstrike_p, bytes_per_char)
1089 struct frame *f;
1090 GC gc;
1091 int x, y;
1092 char *buf;
1093 int nchars, bg_width, overstrike_p, bytes_per_char;
1095 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1096 UInt32 savedFlags;
1097 #endif
1099 mac_begin_clip (f, gc);
1100 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1101 if (mac_use_core_graphics)
1102 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
1103 #endif
1104 RGBForeColor (GC_FORE_COLOR (gc));
1105 #ifdef MAC_OS8
1106 if (bg_width)
1108 RGBBackColor (GC_BACK_COLOR (gc));
1109 TextMode (srcCopy);
1111 else
1112 TextMode (srcOr);
1113 #else
1114 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1115 because:
1116 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1117 into an offscreen graphics world first. So performance gain
1118 cannot be expected.)
1119 - It lowers rendering quality.
1120 - Some fonts leave garbage on cursor movement. */
1121 if (bg_width)
1123 Rect r;
1125 RGBBackColor (GC_BACK_COLOR (gc));
1126 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1127 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1128 EraseRect (&r);
1130 TextMode (srcOr);
1131 #endif
1132 TextFont (GC_FONT (gc)->mac_fontnum);
1133 TextSize (GC_FONT (gc)->mac_fontsize);
1134 TextFace (GC_FONT (gc)->mac_fontface);
1135 MoveTo (x, y);
1136 DrawText (buf, 0, nchars * bytes_per_char);
1137 if (overstrike_p)
1139 TextMode (srcOr);
1140 MoveTo (x + 1, y);
1141 DrawText (buf, 0, nchars * bytes_per_char);
1143 if (bg_width)
1144 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1145 mac_end_clip (gc);
1147 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1148 if (mac_use_core_graphics)
1149 SwapQDTextFlags(savedFlags);
1150 #endif
1154 static INLINE void
1155 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1156 overstrike_p, bytes_per_char)
1157 struct frame *f;
1158 GC gc;
1159 int x, y;
1160 char *buf;
1161 int nchars, bg_width, overstrike_p, bytes_per_char;
1163 #if USE_ATSUI
1164 if (GC_FONT (gc)->mac_style)
1165 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
1166 overstrike_p, bytes_per_char);
1167 else
1168 #endif /* USE_ATSUI */
1169 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1170 overstrike_p, bytes_per_char);
1174 /* Mac replacement for XDrawImageString. */
1176 static void
1177 mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1178 struct frame *f;
1179 GC gc;
1180 int x, y;
1181 char *buf;
1182 int nchars, bg_width, overstrike_p;
1184 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1185 overstrike_p, 1);
1189 /* Mac replacement for XDrawImageString16. */
1191 static void
1192 mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1193 struct frame *f;
1194 GC gc;
1195 int x, y;
1196 XChar2b *buf;
1197 int nchars, bg_width, overstrike_p;
1199 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
1200 overstrike_p, 2);
1204 /* Mac replacement for XQueryTextExtents, but takes a character. If
1205 STYLE is NULL, measurement is done by QuickDraw Text routines for
1206 the font of the current graphics port. If CG_GLYPH is not NULL,
1207 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1209 static OSStatus
1210 mac_query_char_extents (style, c,
1211 font_ascent_return, font_descent_return,
1212 overall_return, cg_glyph)
1213 #if USE_ATSUI
1214 ATSUStyle style;
1215 #else
1216 void *style;
1217 #endif
1218 int c;
1219 int *font_ascent_return, *font_descent_return;
1220 XCharStruct *overall_return;
1221 #if USE_CG_TEXT_DRAWING
1222 CGGlyph *cg_glyph;
1223 #else
1224 void *cg_glyph;
1225 #endif
1227 OSStatus err = noErr;
1228 int width;
1229 Rect char_bounds;
1231 #if USE_ATSUI
1232 if (style)
1234 ATSUTextLayout text_layout;
1235 UniChar ch = c;
1237 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
1238 if (err == noErr
1239 && (font_ascent_return || font_descent_return || overall_return))
1241 ATSTrapezoid glyph_bounds;
1243 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1244 kATSUFromTextBeginning, kATSUToTextEnd,
1245 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1246 kATSUseFractionalOrigins,
1247 #else
1248 kATSUseDeviceOrigins,
1249 #endif
1250 1, &glyph_bounds, NULL);
1251 if (err == noErr)
1253 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1254 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1256 width = Fix2Long (glyph_bounds.upperRight.x
1257 - glyph_bounds.upperLeft.x);
1258 if (font_ascent_return)
1259 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1260 if (font_descent_return)
1261 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1264 if (err == noErr && overall_return)
1266 err = ATSUMeasureTextImage (text_layout,
1267 kATSUFromTextBeginning, kATSUToTextEnd,
1268 0, 0, &char_bounds);
1269 if (err == noErr)
1270 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1271 #if USE_CG_TEXT_DRAWING
1272 if (err == noErr && cg_glyph)
1274 OSStatus err1;
1275 ATSUGlyphInfoArray glyph_info_array;
1276 ByteCount count = sizeof (ATSUGlyphInfoArray);
1278 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1279 kATSUToTextEnd, NULL, NULL, NULL);
1280 if (err1 == noErr)
1281 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1282 kATSUToTextEnd, &count,
1283 &glyph_info_array);
1284 if (err1 == noErr
1285 /* Make sure that we don't have to make layout
1286 adjustments. */
1287 && glyph_info_array.glyphs[0].deltaY == 0.0f
1288 && glyph_info_array.glyphs[0].idealX == 0.0f
1289 && glyph_info_array.glyphs[0].screenX == 0)
1291 xassert (glyph_info_array.glyphs[0].glyphID);
1292 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1294 else
1295 *cg_glyph = 0;
1297 #endif
1300 else
1301 #endif
1303 if (font_ascent_return || font_descent_return)
1305 FontInfo font_info;
1307 GetFontInfo (&font_info);
1308 if (font_ascent_return)
1309 *font_ascent_return = font_info.ascent;
1310 if (font_descent_return)
1311 *font_descent_return = font_info.descent;
1313 if (overall_return)
1315 char ch = c;
1317 width = CharWidth (ch);
1318 QDTextBounds (1, &ch, &char_bounds);
1319 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1323 return err;
1327 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1329 static int
1330 mac_text_extents_16 (font_struct, string, nchars, overall_return)
1331 XFontStruct *font_struct;
1332 XChar2b *string;
1333 int nchars;
1334 XCharStruct *overall_return;
1336 int i;
1337 short width = 0, lbearing = 0, rbearing = 0;
1338 XCharStruct *pcm;
1340 for (i = 0; i < nchars; i++)
1342 pcm = mac_per_char_metric (font_struct, string, 0);
1343 if (pcm == NULL)
1344 width += FONT_WIDTH (font_struct);
1345 else
1347 lbearing = min (lbearing, width + pcm->lbearing);
1348 rbearing = max (rbearing, width + pcm->rbearing);
1349 width += pcm->width;
1351 string++;
1354 overall_return->lbearing = lbearing;
1355 overall_return->rbearing = rbearing;
1356 overall_return->width = width;
1358 /* What's the meaning of the return value of XTextExtents16? */
1362 #if USE_CG_TEXT_DRAWING
1363 static int cg_text_anti_aliasing_threshold = 8;
1365 static void
1366 init_cg_text_anti_aliasing_threshold ()
1368 int threshold;
1369 Boolean valid_p;
1371 threshold =
1372 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1373 kCFPreferencesCurrentApplication,
1374 &valid_p);
1375 if (valid_p)
1376 cg_text_anti_aliasing_threshold = threshold;
1379 static int
1380 mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1381 struct frame *f;
1382 GC gc;
1383 int x, y;
1384 XChar2b *buf;
1385 int nchars, bg_width, overstrike_p;
1387 float port_height, gx, gy;
1388 int i;
1389 CGContextRef context;
1390 CGGlyph *glyphs;
1391 CGSize *advances;
1393 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1394 return 0;
1396 port_height = FRAME_PIXEL_HEIGHT (f);
1397 gx = x;
1398 gy = port_height - y;
1399 glyphs = (CGGlyph *)buf;
1400 advances = alloca (sizeof (CGSize) * nchars);
1401 if (advances == NULL)
1402 return 0;
1403 for (i = 0; i < nchars; i++)
1405 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1407 advances[i].width = pcm->width;
1408 advances[i].height = 0;
1409 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1410 buf++;
1413 #if USE_CG_DRAWING
1414 context = mac_begin_cg_clip (f, gc);
1415 #else
1416 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1417 if (gc->n_clip_rects || bg_width)
1419 CGContextTranslateCTM (context, 0, port_height);
1420 CGContextScaleCTM (context, 1, -1);
1421 if (gc->n_clip_rects)
1422 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1423 #endif
1424 if (bg_width)
1426 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1427 CGContextFillRect
1428 (context,
1429 CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
1430 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1432 CGContextScaleCTM (context, 1, -1);
1433 CGContextTranslateCTM (context, 0, -port_height);
1434 #if !USE_CG_DRAWING
1436 #endif
1437 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1438 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1439 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1440 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1441 CGContextSetShouldAntialias (context, false);
1442 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1443 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1444 if (CGContextShowGlyphsWithAdvances != NULL)
1445 #endif
1447 CGContextSetTextPosition (context, gx, gy);
1448 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1449 if (overstrike_p)
1451 CGContextSetTextPosition (context, gx + 1.0f, gy);
1452 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1455 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1456 else /* CGContextShowGlyphsWithAdvances == NULL */
1457 #endif
1458 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1459 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1461 for (i = 0; i < nchars; i++)
1463 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1464 if (overstrike_p)
1465 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
1466 gx += advances[i].width;
1469 #endif
1470 #if USE_CG_DRAWING
1471 mac_end_cg_clip (f);
1472 #else
1473 CGContextSynchronize (context);
1474 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1475 #endif
1477 return 1;
1479 #endif
1482 #if !USE_CG_DRAWING
1483 /* Mac replacement for XCopyArea: dest must be window. */
1485 static void
1486 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1487 Pixmap src;
1488 struct frame *f;
1489 GC gc;
1490 int src_x, src_y;
1491 unsigned int width, height;
1492 int dest_x, dest_y;
1494 Rect src_r, dest_r;
1496 mac_begin_clip (f, gc);
1498 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1499 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1501 ForeColor (blackColor);
1502 BackColor (whiteColor);
1504 LockPixels (GetGWorldPixMap (src));
1505 #if TARGET_API_MAC_CARBON
1507 CGrafPtr port;
1509 GetPort (&port);
1510 LockPortBits (port);
1511 CopyBits (GetPortBitMapForCopyBits (src),
1512 GetPortBitMapForCopyBits (port),
1513 &src_r, &dest_r, srcCopy, 0);
1514 UnlockPortBits (port);
1516 #else /* not TARGET_API_MAC_CARBON */
1517 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1518 &src_r, &dest_r, srcCopy, 0);
1519 #endif /* not TARGET_API_MAC_CARBON */
1520 UnlockPixels (GetGWorldPixMap (src));
1522 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1524 mac_end_clip (gc);
1528 static void
1529 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1530 width, height, dest_x, dest_y)
1531 Pixmap src, mask;
1532 struct frame *f;
1533 GC gc;
1534 int src_x, src_y;
1535 unsigned int width, height;
1536 int dest_x, dest_y;
1538 Rect src_r, dest_r;
1540 mac_begin_clip (f, gc);
1542 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1543 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1545 ForeColor (blackColor);
1546 BackColor (whiteColor);
1548 LockPixels (GetGWorldPixMap (src));
1549 LockPixels (GetGWorldPixMap (mask));
1550 #if TARGET_API_MAC_CARBON
1552 CGrafPtr port;
1554 GetPort (&port);
1555 LockPortBits (port);
1556 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1557 GetPortBitMapForCopyBits (port),
1558 &src_r, &src_r, &dest_r);
1559 UnlockPortBits (port);
1561 #else /* not TARGET_API_MAC_CARBON */
1562 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1563 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1564 #endif /* not TARGET_API_MAC_CARBON */
1565 UnlockPixels (GetGWorldPixMap (mask));
1566 UnlockPixels (GetGWorldPixMap (src));
1568 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1570 mac_end_clip (gc);
1572 #endif /* !USE_CG_DRAWING */
1575 /* Mac replacement for XCopyArea: used only for scrolling. */
1577 static void
1578 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1579 struct frame *f;
1580 GC gc;
1581 int src_x, src_y;
1582 unsigned int width, height;
1583 int dest_x, dest_y;
1585 #if TARGET_API_MAC_CARBON
1586 Rect src_r;
1587 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
1589 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1590 #if USE_CG_DRAWING
1591 mac_prepare_for_quickdraw (f);
1592 #endif
1593 ScrollWindowRect (FRAME_MAC_WINDOW (f),
1594 &src_r, dest_x - src_x, dest_y - src_y,
1595 kScrollWindowNoOptions, dummy);
1596 DisposeRgn (dummy);
1597 #else /* not TARGET_API_MAC_CARBON */
1598 Rect src_r, dest_r;
1599 WindowRef w = FRAME_MAC_WINDOW (f);
1601 mac_begin_clip (f, gc);
1603 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1604 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1606 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1607 color mapping in CopyBits. Otherwise, it will be slow. */
1608 ForeColor (blackColor);
1609 BackColor (whiteColor);
1610 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1612 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1614 mac_end_clip (gc);
1615 #endif /* not TARGET_API_MAC_CARBON */
1619 /* Mac replacement for XChangeGC. */
1621 static void
1622 XChangeGC (display, gc, mask, xgcv)
1623 Display *display;
1624 GC gc;
1625 unsigned long mask;
1626 XGCValues *xgcv;
1628 if (mask & GCForeground)
1629 XSetForeground (display, gc, xgcv->foreground);
1630 if (mask & GCBackground)
1631 XSetBackground (display, gc, xgcv->background);
1632 if (mask & GCFont)
1633 XSetFont (display, gc, xgcv->font);
1637 /* Mac replacement for XCreateGC. */
1640 XCreateGC (display, d, mask, xgcv)
1641 Display *display;
1642 void *d;
1643 unsigned long mask;
1644 XGCValues *xgcv;
1646 GC gc = xmalloc (sizeof (*gc));
1648 bzero (gc, sizeof (*gc));
1649 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1650 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1651 if (CGColorGetTypeID != NULL)
1652 #endif
1654 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
1655 CGColorRetain (gc->cg_fore_color);
1656 CGColorRetain (gc->cg_back_color);
1658 #endif
1659 XChangeGC (display, gc, mask, xgcv);
1661 return gc;
1665 /* Used in xfaces.c. */
1667 void
1668 XFreeGC (display, gc)
1669 Display *display;
1670 GC gc;
1672 if (gc->clip_region)
1673 DisposeRgn (gc->clip_region);
1674 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1675 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1676 if (CGColorGetTypeID != NULL)
1677 #endif
1679 CGColorRelease (gc->cg_fore_color);
1680 CGColorRelease (gc->cg_back_color);
1682 #endif
1683 xfree (gc);
1687 /* Mac replacement for XGetGCValues. */
1689 static void
1690 XGetGCValues (display, gc, mask, xgcv)
1691 Display *display;
1692 GC gc;
1693 unsigned long mask;
1694 XGCValues *xgcv;
1696 if (mask & GCForeground)
1697 xgcv->foreground = gc->xgcv.foreground;
1698 if (mask & GCBackground)
1699 xgcv->background = gc->xgcv.background;
1700 if (mask & GCFont)
1701 xgcv->font = gc->xgcv.font;
1705 /* Mac replacement for XSetForeground. */
1707 void
1708 XSetForeground (display, gc, color)
1709 Display *display;
1710 GC gc;
1711 unsigned long color;
1713 if (gc->xgcv.foreground != color)
1715 gc->xgcv.foreground = color;
1716 gc->fore_color.red = RED16_FROM_ULONG (color);
1717 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1718 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1719 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1720 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1721 if (CGColorGetTypeID != NULL)
1722 #endif
1724 CGColorRelease (gc->cg_fore_color);
1725 if (color == 0)
1727 gc->cg_fore_color = mac_cg_color_black;
1728 CGColorRetain (gc->cg_fore_color);
1730 else
1732 float rgba[4];
1734 rgba[0] = gc->fore_color.red / 65535.0f;
1735 rgba[1] = gc->fore_color.green / 65535.0f;
1736 rgba[2] = gc->fore_color.blue / 65535.0f;
1737 rgba[3] = 1.0f;
1738 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1741 #endif
1746 /* Mac replacement for XSetBackground. */
1748 void
1749 XSetBackground (display, gc, color)
1750 Display *display;
1751 GC gc;
1752 unsigned long color;
1754 if (gc->xgcv.background != color)
1756 gc->xgcv.background = color;
1757 gc->back_color.red = RED16_FROM_ULONG (color);
1758 gc->back_color.green = GREEN16_FROM_ULONG (color);
1759 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1760 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1761 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1762 if (CGColorGetTypeID != NULL)
1763 #endif
1765 CGColorRelease (gc->cg_back_color);
1766 if (color == 0)
1768 gc->cg_back_color = mac_cg_color_black;
1769 CGColorRetain (gc->cg_back_color);
1771 else
1773 float rgba[4];
1775 rgba[0] = gc->back_color.red / 65535.0f;
1776 rgba[1] = gc->back_color.green / 65535.0f;
1777 rgba[2] = gc->back_color.blue / 65535.0f;
1778 rgba[3] = 1.0f;
1779 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1782 #endif
1787 /* Mac replacement for XSetFont. */
1789 static void
1790 XSetFont (display, gc, font)
1791 Display *display;
1792 GC gc;
1793 XFontStruct *font;
1795 gc->xgcv.font = font;
1799 /* Mac replacement for XSetClipRectangles. */
1801 static void
1802 mac_set_clip_rectangles (display, gc, rectangles, n)
1803 Display *display;
1804 GC gc;
1805 Rect *rectangles;
1806 int n;
1808 int i;
1810 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1812 gc->n_clip_rects = n;
1813 if (n > 0)
1815 if (gc->clip_region == NULL)
1816 gc->clip_region = NewRgn ();
1817 RectRgn (gc->clip_region, rectangles);
1818 if (n > 1)
1820 RgnHandle region = NewRgn ();
1822 for (i = 1; i < n; i++)
1824 RectRgn (region, rectangles + i);
1825 UnionRgn (gc->clip_region, region, gc->clip_region);
1827 DisposeRgn (region);
1830 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1831 for (i = 0; i < n; i++)
1833 Rect *rect = rectangles + i;
1835 gc->clip_rects[i] = CGRectMake (rect->left, rect->top,
1836 rect->right - rect->left,
1837 rect->bottom - rect->top);
1839 #endif
1843 /* Mac replacement for XSetClipMask. */
1845 static INLINE void
1846 mac_reset_clip_rectangles (display, gc)
1847 Display *display;
1848 GC gc;
1850 gc->n_clip_rects = 0;
1854 /* Mac replacement for XSetWindowBackground. */
1856 void
1857 XSetWindowBackground (display, w, color)
1858 Display *display;
1859 WindowRef w;
1860 unsigned long color;
1862 #if !TARGET_API_MAC_CARBON
1863 AuxWinHandle aw_handle;
1864 CTabHandle ctab_handle;
1865 ColorSpecPtr ct_table;
1866 short ct_size;
1867 #endif
1868 RGBColor bg_color;
1870 bg_color.red = RED16_FROM_ULONG (color);
1871 bg_color.green = GREEN16_FROM_ULONG (color);
1872 bg_color.blue = BLUE16_FROM_ULONG (color);
1874 #if TARGET_API_MAC_CARBON
1875 SetWindowContentColor (w, &bg_color);
1876 #else
1877 if (GetAuxWin (w, &aw_handle))
1879 ctab_handle = (*aw_handle)->awCTable;
1880 HandToHand ((Handle *) &ctab_handle);
1881 ct_table = (*ctab_handle)->ctTable;
1882 ct_size = (*ctab_handle)->ctSize;
1883 while (ct_size > -1)
1885 if (ct_table->value == 0)
1887 ct_table->rgb = bg_color;
1888 CTabChanged (ctab_handle);
1889 SetWinColor (w, (WCTabHandle) ctab_handle);
1891 ct_size--;
1894 #endif
1897 /* Flush display of frame F, or of all frames if F is null. */
1899 static void
1900 x_flush (f)
1901 struct frame *f;
1903 #if TARGET_API_MAC_CARBON
1904 BLOCK_INPUT;
1905 #if USE_CG_DRAWING
1906 mac_prepare_for_quickdraw (f);
1907 #endif
1908 if (f)
1909 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1910 else
1911 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1912 UNBLOCK_INPUT;
1913 #endif
1917 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1918 Calls to XFlush should be unnecessary because the X output buffer
1919 is flushed automatically as needed by calls to XPending,
1920 XNextEvent, or XWindowEvent according to the XFlush man page.
1921 XTread_socket calls XPending. Removing XFlush improves
1922 performance. */
1924 #define XFlush(DISPLAY) (void) 0
1926 #if USE_CG_DRAWING
1927 static void
1928 mac_flush_display_optional (f)
1929 struct frame *f;
1931 BLOCK_INPUT;
1932 mac_prepare_for_quickdraw (f);
1933 UNBLOCK_INPUT;
1935 #endif
1937 /***********************************************************************
1938 Starting and ending an update
1939 ***********************************************************************/
1941 /* Start an update of frame F. This function is installed as a hook
1942 for update_begin, i.e. it is called when update_begin is called.
1943 This function is called prior to calls to x_update_window_begin for
1944 each window being updated. */
1946 static void
1947 x_update_begin (f)
1948 struct frame *f;
1950 #if TARGET_API_MAC_CARBON
1951 /* During update of a frame, availability of input events is
1952 periodically checked with ReceiveNextEvent if
1953 redisplay-dont-pause is nil. That normally flushes window buffer
1954 changes for every check, and thus screen update looks waving even
1955 if no input is available. So we disable screen updates during
1956 update of a frame. */
1957 BLOCK_INPUT;
1958 DisableScreenUpdates ();
1959 UNBLOCK_INPUT;
1960 #endif
1964 /* Start update of window W. Set the global variable updated_window
1965 to the window being updated and set output_cursor to the cursor
1966 position of W. */
1968 static void
1969 x_update_window_begin (w)
1970 struct window *w;
1972 struct frame *f = XFRAME (WINDOW_FRAME (w));
1973 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1975 updated_window = w;
1976 set_output_cursor (&w->cursor);
1978 BLOCK_INPUT;
1980 if (f == display_info->mouse_face_mouse_frame)
1982 /* Don't do highlighting for mouse motion during the update. */
1983 display_info->mouse_face_defer = 1;
1985 /* If F needs to be redrawn, simply forget about any prior mouse
1986 highlighting. */
1987 if (FRAME_GARBAGED_P (f))
1988 display_info->mouse_face_window = Qnil;
1990 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1991 their mouse_face_p flag set, which means that they are always
1992 unequal to rows in a desired matrix which never have that
1993 flag set. So, rows containing mouse-face glyphs are never
1994 scrolled, and we don't have to switch the mouse highlight off
1995 here to prevent it from being scrolled. */
1997 /* Can we tell that this update does not affect the window
1998 where the mouse highlight is? If so, no need to turn off.
1999 Likewise, don't do anything if the frame is garbaged;
2000 in that case, the frame's current matrix that we would use
2001 is all wrong, and we will redisplay that line anyway. */
2002 if (!NILP (display_info->mouse_face_window)
2003 && w == XWINDOW (display_info->mouse_face_window))
2005 int i;
2007 for (i = 0; i < w->desired_matrix->nrows; ++i)
2008 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
2009 break;
2011 if (i < w->desired_matrix->nrows)
2012 clear_mouse_face (display_info);
2014 #endif /* 0 */
2017 UNBLOCK_INPUT;
2021 /* Draw a vertical window border from (x,y0) to (x,y1) */
2023 static void
2024 mac_draw_vertical_window_border (w, x, y0, y1)
2025 struct window *w;
2026 int x, y0, y1;
2028 struct frame *f = XFRAME (WINDOW_FRAME (w));
2029 struct face *face;
2031 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
2032 if (face)
2033 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
2034 face->foreground);
2036 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
2039 /* End update of window W (which is equal to updated_window).
2041 Draw vertical borders between horizontally adjacent windows, and
2042 display W's cursor if CURSOR_ON_P is non-zero.
2044 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2045 glyphs in mouse-face were overwritten. In that case we have to
2046 make sure that the mouse-highlight is properly redrawn.
2048 W may be a menu bar pseudo-window in case we don't have X toolkit
2049 support. Such windows don't have a cursor, so don't display it
2050 here. */
2052 static void
2053 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
2054 struct window *w;
2055 int cursor_on_p, mouse_face_overwritten_p;
2057 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
2059 if (!w->pseudo_window_p)
2061 BLOCK_INPUT;
2063 if (cursor_on_p)
2064 display_and_set_cursor (w, 1, output_cursor.hpos,
2065 output_cursor.vpos,
2066 output_cursor.x, output_cursor.y);
2068 if (draw_window_fringes (w, 1))
2069 x_draw_vertical_border (w);
2071 UNBLOCK_INPUT;
2074 /* If a row with mouse-face was overwritten, arrange for
2075 XTframe_up_to_date to redisplay the mouse highlight. */
2076 if (mouse_face_overwritten_p)
2078 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
2079 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
2080 dpyinfo->mouse_face_window = Qnil;
2083 updated_window = NULL;
2087 /* End update of frame F. This function is installed as a hook in
2088 update_end. */
2090 static void
2091 x_update_end (f)
2092 struct frame *f;
2094 /* Mouse highlight may be displayed again. */
2095 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
2097 BLOCK_INPUT;
2098 #if TARGET_API_MAC_CARBON
2099 EnableScreenUpdates ();
2100 #endif
2101 XFlush (FRAME_MAC_DISPLAY (f));
2102 UNBLOCK_INPUT;
2106 /* This function is called from various places in xdisp.c whenever a
2107 complete update has been performed. The global variable
2108 updated_window is not available here. */
2110 static void
2111 XTframe_up_to_date (f)
2112 struct frame *f;
2114 if (FRAME_MAC_P (f))
2116 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2118 if (dpyinfo->mouse_face_deferred_gc
2119 || f == dpyinfo->mouse_face_mouse_frame)
2121 BLOCK_INPUT;
2122 if (dpyinfo->mouse_face_mouse_frame)
2123 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
2124 dpyinfo->mouse_face_mouse_x,
2125 dpyinfo->mouse_face_mouse_y);
2126 dpyinfo->mouse_face_deferred_gc = 0;
2127 UNBLOCK_INPUT;
2133 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2134 arrow bitmaps, or clear the fringes if no bitmaps are required
2135 before DESIRED_ROW is made current. The window being updated is
2136 found in updated_window. This function is called from
2137 update_window_line only if it is known that there are differences
2138 between bitmaps to be drawn between current row and DESIRED_ROW. */
2140 static void
2141 x_after_update_window_line (desired_row)
2142 struct glyph_row *desired_row;
2144 struct window *w = updated_window;
2145 struct frame *f;
2146 int width, height;
2148 xassert (w);
2150 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2151 desired_row->redraw_fringe_bitmaps_p = 1;
2153 /* When a window has disappeared, make sure that no rest of
2154 full-width rows stays visible in the internal border. Could
2155 check here if updated_window is the leftmost/rightmost window,
2156 but I guess it's not worth doing since vertically split windows
2157 are almost never used, internal border is rarely set, and the
2158 overhead is very small. */
2159 if (windows_or_buffers_changed
2160 && desired_row->full_width_p
2161 && (f = XFRAME (w->frame),
2162 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2163 width != 0)
2164 && (height = desired_row->visible_height,
2165 height > 0))
2167 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2169 /* Internal border is drawn below the tool bar. */
2170 if (WINDOWP (f->tool_bar_window)
2171 && w == XWINDOW (f->tool_bar_window))
2172 y -= width;
2174 BLOCK_INPUT;
2175 mac_clear_area (f, 0, y, width, height);
2176 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
2177 UNBLOCK_INPUT;
2182 /* Draw the bitmap WHICH in one of the left or right fringes of
2183 window W. ROW is the glyph row for which to display the bitmap; it
2184 determines the vertical position at which the bitmap has to be
2185 drawn. */
2187 static void
2188 x_draw_fringe_bitmap (w, row, p)
2189 struct window *w;
2190 struct glyph_row *row;
2191 struct draw_fringe_bitmap_params *p;
2193 struct frame *f = XFRAME (WINDOW_FRAME (w));
2194 Display *display = FRAME_MAC_DISPLAY (f);
2195 struct face *face = p->face;
2196 int rowY;
2197 int overlay_p = p->overlay_p;
2199 #ifdef MAC_OSX
2200 if (!overlay_p)
2202 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2204 #if 0 /* MAC_TODO: stipple */
2205 /* In case the same realized face is used for fringes and
2206 for something displayed in the text (e.g. face `region' on
2207 mono-displays, the fill style may have been changed to
2208 FillSolid in x_draw_glyph_string_background. */
2209 if (face->stipple)
2210 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2211 else
2212 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2213 #endif
2215 /* If the fringe is adjacent to the left (right) scroll bar of a
2216 leftmost (rightmost, respectively) window, then extend its
2217 background to the gap between the fringe and the bar. */
2218 if ((WINDOW_LEFTMOST_P (w)
2219 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2220 || (WINDOW_RIGHTMOST_P (w)
2221 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2223 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2225 if (sb_width > 0)
2227 int left = WINDOW_SCROLL_BAR_AREA_X (w);
2228 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2229 * FRAME_COLUMN_WIDTH (f));
2231 if (bx < 0
2232 && (left + width == p->x
2233 || p->x + p->wd == left))
2235 /* Bitmap fills the fringe and we need background
2236 extension. */
2237 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
2239 bx = p->x;
2240 nx = p->wd;
2241 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
2242 row->y));
2243 ny = row->visible_height;
2246 if (bx >= 0)
2248 if (left + width == bx)
2250 bx = left + sb_width;
2251 nx += width - sb_width;
2253 else if (bx + nx == left)
2254 nx += width - sb_width;
2259 if (bx >= 0)
2261 mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
2262 /* The fringe background has already been filled. */
2263 overlay_p = 1;
2266 #if 0 /* MAC_TODO: stipple */
2267 if (!face->stipple)
2268 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2269 #endif
2271 #endif /* MAC_OSX */
2273 /* Must clip because of partially visible lines. */
2274 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2275 if (p->y < rowY)
2277 /* Adjust position of "bottom aligned" bitmap on partially
2278 visible last row. */
2279 int oldY = row->y;
2280 int oldVH = row->visible_height;
2281 row->visible_height = p->h;
2282 row->y -= rowY - p->y;
2283 x_clip_to_row (w, row, -1, face->gc);
2284 row->y = oldY;
2285 row->visible_height = oldVH;
2287 else
2288 x_clip_to_row (w, row, -1, face->gc);
2290 #ifndef MAC_OSX
2291 if (p->bx >= 0 && !p->overlay_p)
2293 #if 0 /* MAC_TODO: stipple */
2294 /* In case the same realized face is used for fringes and
2295 for something displayed in the text (e.g. face `region' on
2296 mono-displays, the fill style may have been changed to
2297 FillSolid in x_draw_glyph_string_background. */
2298 if (face->stipple)
2299 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2300 else
2301 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2302 #endif
2304 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
2306 #if 0 /* MAC_TODO: stipple */
2307 if (!face->stipple)
2308 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2309 #endif
2311 #endif /* !MAC_OSX */
2313 if (p->which
2314 #if USE_CG_DRAWING
2315 && p->which < max_fringe_bmp
2316 #endif
2319 XGCValues gcv;
2321 XGetGCValues (display, face->gc, GCForeground, &gcv);
2322 XSetForeground (display, face->gc,
2323 (p->cursor_p
2324 ? (p->overlay_p ? face->background
2325 : f->output_data.mac->cursor_pixel)
2326 : face->foreground));
2327 #if USE_CG_DRAWING
2328 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
2329 p->wd, p->h, p->x, p->y, overlay_p);
2330 #else
2331 mac_draw_bitmap (f, face->gc, p->x, p->y,
2332 p->wd, p->h, p->bits + p->dh, overlay_p);
2333 #endif
2334 XSetForeground (display, face->gc, gcv.foreground);
2337 mac_reset_clip_rectangles (display, face->gc);
2340 #if USE_CG_DRAWING
2341 static void
2342 mac_define_fringe_bitmap (which, bits, h, wd)
2343 int which;
2344 unsigned short *bits;
2345 int h, wd;
2347 int i;
2348 CGDataProviderRef provider;
2350 if (which >= max_fringe_bmp)
2352 i = max_fringe_bmp;
2353 max_fringe_bmp = which + 20;
2354 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
2355 while (i < max_fringe_bmp)
2356 fringe_bmp[i++] = 0;
2359 for (i = 0; i < h; i++)
2360 bits[i] = ~bits[i];
2362 BLOCK_INPUT;
2364 provider = CGDataProviderCreateWithData (NULL, bits,
2365 sizeof (unsigned short) * h, NULL);
2366 if (provider)
2368 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
2369 sizeof (unsigned short),
2370 provider, NULL, 0);
2371 CGDataProviderRelease (provider);
2374 UNBLOCK_INPUT;
2377 static void
2378 mac_destroy_fringe_bitmap (which)
2379 int which;
2381 if (which >= max_fringe_bmp)
2382 return;
2384 if (fringe_bmp[which])
2386 BLOCK_INPUT;
2387 CGImageRelease (fringe_bmp[which]);
2388 UNBLOCK_INPUT;
2390 fringe_bmp[which] = 0;
2392 #endif
2395 /* This is called when starting Emacs and when restarting after
2396 suspend. When starting Emacs, no window is mapped. And nothing
2397 must be done to Emacs's own window if it is suspended (though that
2398 rarely happens). */
2400 static void
2401 XTset_terminal_modes ()
2405 /* This is called when exiting or suspending Emacs. Exiting will make
2406 the windows go away, and suspending requires no action. */
2408 static void
2409 XTreset_terminal_modes ()
2415 /***********************************************************************
2416 Display Iterator
2417 ***********************************************************************/
2419 /* Function prototypes of this page. */
2421 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
2422 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
2425 static void
2426 pcm_init (pcm, count)
2427 XCharStruct *pcm;
2428 int count;
2430 bzero (pcm, sizeof (XCharStruct) * count);
2431 while (--count >= 0)
2433 pcm->descent = PCM_INVALID;
2434 pcm++;
2438 static enum pcm_status
2439 pcm_get_status (pcm)
2440 const XCharStruct *pcm;
2442 int height = pcm->ascent + pcm->descent;
2444 /* Negative height means some special status. */
2445 return height >= 0 ? PCM_VALID : height;
2448 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2449 is not contained in the font. */
2451 static INLINE XCharStruct *
2452 x_per_char_metric (font, char2b)
2453 XFontStruct *font;
2454 XChar2b *char2b;
2456 /* The result metric information. */
2457 XCharStruct *pcm = NULL;
2459 xassert (font && char2b);
2461 #if USE_ATSUI
2462 if (font->mac_style)
2464 XCharStruct **row = font->bounds.rows + char2b->byte1;
2466 if (*row == NULL)
2468 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2469 pcm_init (*row, 0x100);
2471 pcm = *row + char2b->byte2;
2472 if (pcm_get_status (pcm) != PCM_VALID)
2474 BLOCK_INPUT;
2475 mac_query_char_extents (font->mac_style,
2476 (char2b->byte1 << 8) + char2b->byte2,
2477 NULL, NULL, pcm, NULL);
2478 UNBLOCK_INPUT;
2481 else
2483 #endif
2484 if (font->bounds.per_char != NULL)
2486 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2488 /* min_char_or_byte2 specifies the linear character index
2489 corresponding to the first element of the per_char array,
2490 max_char_or_byte2 is the index of the last character. A
2491 character with non-zero CHAR2B->byte1 is not in the font.
2492 A character with byte2 less than min_char_or_byte2 or
2493 greater max_char_or_byte2 is not in the font. */
2494 if (char2b->byte1 == 0
2495 && char2b->byte2 >= font->min_char_or_byte2
2496 && char2b->byte2 <= font->max_char_or_byte2)
2497 pcm = font->bounds.per_char
2498 + (char2b->byte2 - font->min_char_or_byte2);
2500 else
2502 /* If either min_byte1 or max_byte1 are nonzero, both
2503 min_char_or_byte2 and max_char_or_byte2 are less than
2504 256, and the 2-byte character index values corresponding
2505 to the per_char array element N (counting from 0) are:
2507 byte1 = N/D + min_byte1
2508 byte2 = N\D + min_char_or_byte2
2510 where:
2512 D = max_char_or_byte2 - min_char_or_byte2 + 1
2513 / = integer division
2514 \ = integer modulus */
2515 if (char2b->byte1 >= font->min_byte1
2516 && char2b->byte1 <= font->max_byte1
2517 && char2b->byte2 >= font->min_char_or_byte2
2518 && char2b->byte2 <= font->max_char_or_byte2)
2520 pcm = (font->bounds.per_char
2521 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2522 * (char2b->byte1 - font->min_byte1))
2523 + (char2b->byte2 - font->min_char_or_byte2));
2527 else
2529 /* If the per_char pointer is null, all glyphs between the first
2530 and last character indexes inclusive have the same
2531 information, as given by both min_bounds and max_bounds. */
2532 if (char2b->byte2 >= font->min_char_or_byte2
2533 && char2b->byte2 <= font->max_char_or_byte2)
2534 pcm = &font->max_bounds;
2536 #if USE_ATSUI
2538 #endif
2540 return ((pcm == NULL
2541 || (pcm->width == 0
2542 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2543 && (pcm->rbearing - pcm->lbearing) == 0
2544 #endif
2546 ? NULL : pcm);
2549 /* RIF:
2552 static XCharStruct *
2553 mac_per_char_metric (font, char2b, font_type)
2554 XFontStruct *font;
2555 XChar2b *char2b;
2556 int font_type;
2558 return x_per_char_metric (font, char2b);
2561 /* RIF:
2562 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2563 the two-byte form of C. Encoding is returned in *CHAR2B. */
2565 static int
2566 mac_encode_char (c, char2b, font_info, two_byte_p)
2567 int c;
2568 XChar2b *char2b;
2569 struct font_info *font_info;
2570 int *two_byte_p;
2572 int charset = CHAR_CHARSET (c);
2573 XFontStruct *font = font_info->font;
2575 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2576 This may be either a program in a special encoder language or a
2577 fixed encoding. */
2578 if (font_info->font_encoder)
2580 /* It's a program. */
2581 struct ccl_program *ccl = font_info->font_encoder;
2583 check_ccl_update (ccl);
2584 if (CHARSET_DIMENSION (charset) == 1)
2586 ccl->reg[0] = charset;
2587 ccl->reg[1] = char2b->byte2;
2588 ccl->reg[2] = -1;
2590 else
2592 ccl->reg[0] = charset;
2593 ccl->reg[1] = char2b->byte1;
2594 ccl->reg[2] = char2b->byte2;
2597 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2599 /* We assume that MSBs are appropriately set/reset by CCL
2600 program. */
2601 if (font->max_byte1 == 0) /* 1-byte font */
2602 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2603 else
2604 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2606 else if (font_info->encoding[charset])
2608 /* Fixed encoding scheme. See fontset.h for the meaning of the
2609 encoding numbers. */
2610 int enc = font_info->encoding[charset];
2612 if ((enc == 1 || enc == 2)
2613 && CHARSET_DIMENSION (charset) == 2)
2614 char2b->byte1 |= 0x80;
2616 if (enc == 1 || enc == 3)
2617 char2b->byte2 |= 0x80;
2619 if (enc == 4)
2621 int sjis1, sjis2;
2623 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2624 char2b->byte1 = sjis1;
2625 char2b->byte2 = sjis2;
2629 if (two_byte_p)
2630 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2632 return FONT_TYPE_UNKNOWN;
2637 /***********************************************************************
2638 Glyph display
2639 ***********************************************************************/
2643 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2644 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2645 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2646 int));
2647 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2648 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2649 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2650 static void x_draw_glyph_string P_ ((struct glyph_string *));
2651 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2652 static void x_set_cursor_gc P_ ((struct glyph_string *));
2653 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2654 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2655 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2656 unsigned long *, double, int));*/
2657 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2658 double, int, unsigned long));
2659 static void x_setup_relief_colors P_ ((struct glyph_string *));
2660 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2661 static void x_draw_image_relief P_ ((struct glyph_string *));
2662 static void x_draw_image_foreground P_ ((struct glyph_string *));
2663 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2664 int, int, int));
2665 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2666 int, int, int, int, int, int,
2667 Rect *));
2668 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2669 int, int, int, Rect *));
2671 #if GLYPH_DEBUG
2672 static void x_check_font P_ ((struct frame *, XFontStruct *));
2673 #endif
2676 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2677 face. */
2679 static void
2680 x_set_cursor_gc (s)
2681 struct glyph_string *s;
2683 if (s->font == FRAME_FONT (s->f)
2684 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2685 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2686 && !s->cmp)
2687 s->gc = s->f->output_data.mac->cursor_gc;
2688 else
2690 /* Cursor on non-default face: must merge. */
2691 XGCValues xgcv;
2692 unsigned long mask;
2694 xgcv.background = s->f->output_data.mac->cursor_pixel;
2695 xgcv.foreground = s->face->background;
2697 /* If the glyph would be invisible, try a different foreground. */
2698 if (xgcv.foreground == xgcv.background)
2699 xgcv.foreground = s->face->foreground;
2700 if (xgcv.foreground == xgcv.background)
2701 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2702 if (xgcv.foreground == xgcv.background)
2703 xgcv.foreground = s->face->foreground;
2705 /* Make sure the cursor is distinct from text in this face. */
2706 if (xgcv.background == s->face->background
2707 && xgcv.foreground == s->face->foreground)
2709 xgcv.background = s->face->foreground;
2710 xgcv.foreground = s->face->background;
2713 IF_DEBUG (x_check_font (s->f, s->font));
2714 xgcv.font = s->font;
2715 mask = GCForeground | GCBackground | GCFont;
2717 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2718 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2719 mask, &xgcv);
2720 else
2721 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2722 = XCreateGC (s->display, s->window, mask, &xgcv);
2724 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2729 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2731 static void
2732 x_set_mouse_face_gc (s)
2733 struct glyph_string *s;
2735 int face_id;
2736 struct face *face;
2738 /* What face has to be used last for the mouse face? */
2739 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2740 face = FACE_FROM_ID (s->f, face_id);
2741 if (face == NULL)
2742 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2744 if (s->first_glyph->type == CHAR_GLYPH)
2745 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2746 else
2747 face_id = FACE_FOR_CHAR (s->f, face, 0);
2748 s->face = FACE_FROM_ID (s->f, face_id);
2749 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2751 /* If font in this face is same as S->font, use it. */
2752 if (s->font == s->face->font)
2753 s->gc = s->face->gc;
2754 else
2756 /* Otherwise construct scratch_cursor_gc with values from FACE
2757 but font FONT. */
2758 XGCValues xgcv;
2759 unsigned long mask;
2761 xgcv.background = s->face->background;
2762 xgcv.foreground = s->face->foreground;
2763 IF_DEBUG (x_check_font (s->f, s->font));
2764 xgcv.font = s->font;
2765 mask = GCForeground | GCBackground | GCFont;
2767 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2768 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2769 mask, &xgcv);
2770 else
2771 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2772 = XCreateGC (s->display, s->window, mask, &xgcv);
2774 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2777 xassert (s->gc != 0);
2781 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2782 Faces to use in the mode line have already been computed when the
2783 matrix was built, so there isn't much to do, here. */
2785 static INLINE void
2786 x_set_mode_line_face_gc (s)
2787 struct glyph_string *s;
2789 s->gc = s->face->gc;
2793 /* Set S->gc of glyph string S for drawing that glyph string. Set
2794 S->stippled_p to a non-zero value if the face of S has a stipple
2795 pattern. */
2797 static INLINE void
2798 x_set_glyph_string_gc (s)
2799 struct glyph_string *s;
2801 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2803 if (s->hl == DRAW_NORMAL_TEXT)
2805 s->gc = s->face->gc;
2806 s->stippled_p = s->face->stipple != 0;
2808 else if (s->hl == DRAW_INVERSE_VIDEO)
2810 x_set_mode_line_face_gc (s);
2811 s->stippled_p = s->face->stipple != 0;
2813 else if (s->hl == DRAW_CURSOR)
2815 x_set_cursor_gc (s);
2816 s->stippled_p = 0;
2818 else if (s->hl == DRAW_MOUSE_FACE)
2820 x_set_mouse_face_gc (s);
2821 s->stippled_p = s->face->stipple != 0;
2823 else if (s->hl == DRAW_IMAGE_RAISED
2824 || s->hl == DRAW_IMAGE_SUNKEN)
2826 s->gc = s->face->gc;
2827 s->stippled_p = s->face->stipple != 0;
2829 else
2831 s->gc = s->face->gc;
2832 s->stippled_p = s->face->stipple != 0;
2835 /* GC must have been set. */
2836 xassert (s->gc != 0);
2840 /* Set clipping for output of glyph string S. S may be part of a mode
2841 line or menu if we don't have X toolkit support. */
2843 static INLINE void
2844 x_set_glyph_string_clipping (s)
2845 struct glyph_string *s;
2847 Rect rects[MAX_CLIP_RECTS];
2848 int n;
2850 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
2851 mac_set_clip_rectangles (s->display, s->gc, rects, n);
2855 /* RIF:
2856 Compute left and right overhang of glyph string S. If S is a glyph
2857 string for a composition, assume overhangs don't exist. */
2859 static void
2860 mac_compute_glyph_string_overhangs (s)
2861 struct glyph_string *s;
2863 if (!(s->cmp == NULL
2864 && s->first_glyph->type == CHAR_GLYPH))
2865 return;
2867 if (!s->two_byte_p
2868 #if USE_ATSUI
2869 || s->font->mac_style
2870 #endif
2873 XCharStruct cs;
2875 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2876 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2877 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2879 else
2881 Rect r;
2882 MacFontStruct *font = s->font;
2884 #if USE_CG_DRAWING
2885 mac_prepare_for_quickdraw (s->f);
2886 #endif
2887 SetPortWindowPort (FRAME_MAC_WINDOW (s->f));
2889 TextFont (font->mac_fontnum);
2890 TextSize (font->mac_fontsize);
2891 TextFace (font->mac_fontface);
2893 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2895 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2896 s->left_overhang = r.left < 0 ? -r.left : 0;
2901 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2903 static INLINE void
2904 x_clear_glyph_string_rect (s, x, y, w, h)
2905 struct glyph_string *s;
2906 int x, y, w, h;
2908 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
2912 /* Draw the background of glyph_string S. If S->background_filled_p
2913 is non-zero don't draw it. FORCE_P non-zero means draw the
2914 background even if it wouldn't be drawn normally. This is used
2915 when a string preceding S draws into the background of S, or S
2916 contains the first component of a composition. */
2918 static void
2919 x_draw_glyph_string_background (s, force_p)
2920 struct glyph_string *s;
2921 int force_p;
2923 /* Nothing to do if background has already been drawn or if it
2924 shouldn't be drawn in the first place. */
2925 if (!s->background_filled_p)
2927 int box_line_width = max (s->face->box_line_width, 0);
2929 #if 0 /* MAC_TODO: stipple */
2930 if (s->stippled_p)
2932 /* Fill background with a stipple pattern. */
2933 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2934 XFillRectangle (s->display, s->window, s->gc, s->x,
2935 s->y + box_line_width,
2936 s->background_width,
2937 s->height - 2 * box_line_width);
2938 XSetFillStyle (s->display, s->gc, FillSolid);
2939 s->background_filled_p = 1;
2941 else
2942 #endif
2943 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2944 || s->font_not_found_p
2945 || s->extends_to_end_of_line_p
2946 || force_p)
2948 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2949 s->background_width,
2950 s->height - 2 * box_line_width);
2951 s->background_filled_p = 1;
2957 /* Draw the foreground of glyph string S. */
2959 static void
2960 x_draw_glyph_string_foreground (s)
2961 struct glyph_string *s;
2963 int i, x, bg_width;
2965 /* If first glyph of S has a left box line, start drawing the text
2966 of S to the right of that box line. */
2967 if (s->face->box != FACE_NO_BOX
2968 && s->first_glyph->left_box_line_p)
2969 x = s->x + abs (s->face->box_line_width);
2970 else
2971 x = s->x;
2973 /* Draw characters of S as rectangles if S's font could not be
2974 loaded. */
2975 if (s->font_not_found_p)
2977 for (i = 0; i < s->nchars; ++i)
2979 struct glyph *g = s->first_glyph + i;
2980 mac_draw_rectangle (s->f, s->gc, x, s->y,
2981 g->pixel_width - 1, s->height - 1);
2982 x += g->pixel_width;
2985 else
2987 char *char1b = (char *) s->char2b;
2988 int boff = s->font_info->baseline_offset;
2990 if (s->font_info->vertical_centering)
2991 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2993 /* If we can use 8-bit functions, condense S->char2b. */
2994 if (!s->two_byte_p
2995 #if USE_ATSUI
2996 && GC_FONT (s->gc)->mac_style == NULL
2997 #endif
2999 for (i = 0; i < s->nchars; ++i)
3000 char1b[i] = s->char2b[i].byte2;
3002 /* Draw text with XDrawString if background has already been
3003 filled. Otherwise, use XDrawImageString. (Note that
3004 XDrawImageString is usually faster than XDrawString.) Always
3005 use XDrawImageString when drawing the cursor so that there is
3006 no chance that characters under a box cursor are invisible. */
3007 if (s->for_overlaps
3008 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3009 bg_width = 0; /* Corresponds to XDrawString. */
3010 else
3011 bg_width = s->background_width; /* Corresponds to XDrawImageString. */
3013 if (s->two_byte_p
3014 #if USE_ATSUI
3015 || GC_FONT (s->gc)->mac_style
3016 #endif
3018 #if USE_CG_TEXT_DRAWING
3019 if (!s->two_byte_p
3020 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
3021 s->char2b, s->nchars, bg_width,
3022 s->face->overstrike))
3024 else
3025 #endif
3026 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
3027 s->char2b, s->nchars, bg_width,
3028 s->face->overstrike);
3029 else
3030 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
3031 char1b, s->nchars, bg_width,
3032 s->face->overstrike);
3036 /* Draw the foreground of composite glyph string S. */
3038 static void
3039 x_draw_composite_glyph_string_foreground (s)
3040 struct glyph_string *s;
3042 int i, x;
3044 /* If first glyph of S has a left box line, start drawing the text
3045 of S to the right of that box line. */
3046 if (s->face->box != FACE_NO_BOX
3047 && s->first_glyph->left_box_line_p)
3048 x = s->x + abs (s->face->box_line_width);
3049 else
3050 x = s->x;
3052 /* S is a glyph string for a composition. S->gidx is the index of
3053 the first character drawn for glyphs of this composition.
3054 S->gidx == 0 means we are drawing the very first character of
3055 this composition. */
3057 /* Draw a rectangle for the composition if the font for the very
3058 first character of the composition could not be loaded. */
3059 if (s->font_not_found_p)
3061 if (s->gidx == 0)
3062 mac_draw_rectangle (s->f, s->gc, x, s->y,
3063 s->width - 1, s->height - 1);
3065 else
3067 for (i = 0; i < s->nchars; i++, ++s->gidx)
3068 if (mac_per_char_metric (GC_FONT (s->gc), s->char2b + i, 0) == NULL)
3069 /* This is a nonexistent or zero-width glyph such as a
3070 combining diacritic. Draw a rectangle. */
3071 mac_draw_rectangle (s->f, s->gc,
3072 x + s->cmp->offsets[s->gidx * 2], s->y,
3073 FONT_WIDTH (GC_FONT (s->gc)) - 1, s->height - 1);
3074 else
3075 mac_draw_image_string_16 (s->f, s->gc,
3076 x + s->cmp->offsets[s->gidx * 2],
3077 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3078 s->char2b + i, 1, 0, s->face->overstrike);
3083 #ifdef USE_X_TOOLKIT
3085 static struct frame *x_frame_of_widget P_ ((Widget));
3088 /* Return the frame on which widget WIDGET is used.. Abort if frame
3089 cannot be determined. */
3091 static struct frame *
3092 x_frame_of_widget (widget)
3093 Widget widget;
3095 struct x_display_info *dpyinfo;
3096 Lisp_Object tail;
3097 struct frame *f;
3099 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3101 /* Find the top-level shell of the widget. Note that this function
3102 can be called when the widget is not yet realized, so XtWindow
3103 (widget) == 0. That's the reason we can't simply use
3104 x_any_window_to_frame. */
3105 while (!XtIsTopLevelShell (widget))
3106 widget = XtParent (widget);
3108 /* Look for a frame with that top-level widget. Allocate the color
3109 on that frame to get the right gamma correction value. */
3110 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3111 if (GC_FRAMEP (XCAR (tail))
3112 && (f = XFRAME (XCAR (tail)),
3113 (f->output_data.nothing != 1
3114 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3115 && f->output_data.x->widget == widget)
3116 return f;
3118 abort ();
3122 /* Allocate the color COLOR->pixel on the screen and display of
3123 widget WIDGET in colormap CMAP. If an exact match cannot be
3124 allocated, try the nearest color available. Value is non-zero
3125 if successful. This is called from lwlib. */
3128 x_alloc_nearest_color_for_widget (widget, cmap, color)
3129 Widget widget;
3130 Colormap cmap;
3131 XColor *color;
3133 struct frame *f = x_frame_of_widget (widget);
3134 return x_alloc_nearest_color (f, cmap, color);
3138 #endif /* USE_X_TOOLKIT */
3140 #if 0 /* MAC_TODO */
3142 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3143 CMAP. If an exact match can't be allocated, try the nearest color
3144 available. Value is non-zero if successful. Set *COLOR to the
3145 color allocated. */
3148 x_alloc_nearest_color (f, cmap, color)
3149 struct frame *f;
3150 Colormap cmap;
3151 XColor *color;
3153 Display *display = FRAME_X_DISPLAY (f);
3154 Screen *screen = FRAME_X_SCREEN (f);
3155 int rc;
3157 gamma_correct (f, color);
3158 rc = XAllocColor (display, cmap, color);
3159 if (rc == 0)
3161 /* If we got to this point, the colormap is full, so we're going
3162 to try to get the next closest color. The algorithm used is
3163 a least-squares matching, which is what X uses for closest
3164 color matching with StaticColor visuals. */
3165 int nearest, i;
3166 unsigned long nearest_delta = ~0;
3167 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3168 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3170 for (i = 0; i < ncells; ++i)
3171 cells[i].pixel = i;
3172 XQueryColors (display, cmap, cells, ncells);
3174 for (nearest = i = 0; i < ncells; ++i)
3176 long dred = (color->red >> 8) - (cells[i].red >> 8);
3177 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3178 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3179 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3181 if (delta < nearest_delta)
3183 nearest = i;
3184 nearest_delta = delta;
3188 color->red = cells[nearest].red;
3189 color->green = cells[nearest].green;
3190 color->blue = cells[nearest].blue;
3191 rc = XAllocColor (display, cmap, color);
3194 #ifdef DEBUG_X_COLORS
3195 if (rc)
3196 register_color (color->pixel);
3197 #endif /* DEBUG_X_COLORS */
3199 return rc;
3203 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3204 It's necessary to do this instead of just using PIXEL directly to
3205 get color reference counts right. */
3207 unsigned long
3208 x_copy_color (f, pixel)
3209 struct frame *f;
3210 unsigned long pixel;
3212 XColor color;
3214 color.pixel = pixel;
3215 BLOCK_INPUT;
3216 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3217 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3218 UNBLOCK_INPUT;
3219 #ifdef DEBUG_X_COLORS
3220 register_color (pixel);
3221 #endif
3222 return color.pixel;
3226 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3227 It's necessary to do this instead of just using PIXEL directly to
3228 get color reference counts right. */
3230 unsigned long
3231 x_copy_dpy_color (dpy, cmap, pixel)
3232 Display *dpy;
3233 Colormap cmap;
3234 unsigned long pixel;
3236 XColor color;
3238 color.pixel = pixel;
3239 BLOCK_INPUT;
3240 XQueryColor (dpy, cmap, &color);
3241 XAllocColor (dpy, cmap, &color);
3242 UNBLOCK_INPUT;
3243 #ifdef DEBUG_X_COLORS
3244 register_color (pixel);
3245 #endif
3246 return color.pixel;
3249 #endif /* MAC_TODO */
3252 /* Brightness beyond which a color won't have its highlight brightness
3253 boosted.
3255 Nominally, highlight colors for `3d' faces are calculated by
3256 brightening an object's color by a constant scale factor, but this
3257 doesn't yield good results for dark colors, so for colors who's
3258 brightness is less than this value (on a scale of 0-255) have to
3259 use an additional additive factor.
3261 The value here is set so that the default menu-bar/mode-line color
3262 (grey75) will not have its highlights changed at all. */
3263 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3266 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3267 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3268 If this produces the same color as COLOR, try a color where all RGB
3269 values have DELTA added. Return the allocated color in *COLOR.
3270 DISPLAY is the X display, CMAP is the colormap to operate on.
3271 Value is non-zero if successful. */
3273 static int
3274 mac_alloc_lighter_color (f, color, factor, delta)
3275 struct frame *f;
3276 unsigned long *color;
3277 double factor;
3278 int delta;
3280 unsigned long new;
3281 long bright;
3283 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3284 delta /= 256;
3286 /* Change RGB values by specified FACTOR. Avoid overflow! */
3287 xassert (factor >= 0);
3288 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3289 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3290 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3292 /* Calculate brightness of COLOR. */
3293 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
3294 + BLUE_FROM_ULONG (*color)) / 6;
3296 /* We only boost colors that are darker than
3297 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3298 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3299 /* Make an additive adjustment to NEW, because it's dark enough so
3300 that scaling by FACTOR alone isn't enough. */
3302 /* How far below the limit this color is (0 - 1, 1 being darker). */
3303 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3304 /* The additive adjustment. */
3305 int min_delta = delta * dimness * factor / 2;
3307 if (factor < 1)
3308 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
3309 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
3310 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
3311 else
3312 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
3313 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
3314 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
3317 if (new == *color)
3318 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3319 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3320 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3322 /* MAC_TODO: Map to palette and retry with delta if same? */
3323 /* MAC_TODO: Free colors (if using palette)? */
3325 if (new == *color)
3326 return 0;
3328 *color = new;
3330 return 1;
3334 /* Set up the foreground color for drawing relief lines of glyph
3335 string S. RELIEF is a pointer to a struct relief containing the GC
3336 with which lines will be drawn. Use a color that is FACTOR or
3337 DELTA lighter or darker than the relief's background which is found
3338 in S->f->output_data.x->relief_background. If such a color cannot
3339 be allocated, use DEFAULT_PIXEL, instead. */
3341 static void
3342 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3343 struct frame *f;
3344 struct relief *relief;
3345 double factor;
3346 int delta;
3347 unsigned long default_pixel;
3349 XGCValues xgcv;
3350 struct mac_output *di = f->output_data.mac;
3351 unsigned long mask = GCForeground;
3352 unsigned long pixel;
3353 unsigned long background = di->relief_background;
3354 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3356 /* MAC_TODO: Free colors (if using palette)? */
3358 /* Allocate new color. */
3359 xgcv.foreground = default_pixel;
3360 pixel = background;
3361 if (dpyinfo->n_planes != 1
3362 && mac_alloc_lighter_color (f, &pixel, factor, delta))
3364 relief->allocated_p = 1;
3365 xgcv.foreground = relief->pixel = pixel;
3368 if (relief->gc == 0)
3370 #if 0 /* MAC_TODO: stipple */
3371 xgcv.stipple = dpyinfo->gray;
3372 mask |= GCStipple;
3373 #endif
3374 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3376 else
3377 XChangeGC (NULL, relief->gc, mask, &xgcv);
3381 /* Set up colors for the relief lines around glyph string S. */
3383 static void
3384 x_setup_relief_colors (s)
3385 struct glyph_string *s;
3387 struct mac_output *di = s->f->output_data.mac;
3388 unsigned long color;
3390 if (s->face->use_box_color_for_shadows_p)
3391 color = s->face->box_color;
3392 else if (s->first_glyph->type == IMAGE_GLYPH
3393 && s->img->pixmap
3394 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3395 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3396 else
3398 XGCValues xgcv;
3400 /* Get the background color of the face. */
3401 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3402 color = xgcv.background;
3405 if (di->white_relief.gc == 0
3406 || color != di->relief_background)
3408 di->relief_background = color;
3409 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3410 WHITE_PIX_DEFAULT (s->f));
3411 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3412 BLACK_PIX_DEFAULT (s->f));
3417 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3418 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3419 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3420 relief. LEFT_P non-zero means draw a relief on the left side of
3421 the rectangle. RIGHT_P non-zero means draw a relief on the right
3422 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3423 when drawing. */
3425 static void
3426 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3427 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
3428 struct frame *f;
3429 int left_x, top_y, right_x, bottom_y, width;
3430 int top_p, bot_p, left_p, right_p, raised_p;
3431 Rect *clip_rect;
3433 Display *dpy = FRAME_MAC_DISPLAY (f);
3434 int i;
3435 GC gc;
3437 if (raised_p)
3438 gc = f->output_data.mac->white_relief.gc;
3439 else
3440 gc = f->output_data.mac->black_relief.gc;
3441 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3443 /* Top. */
3444 if (top_p)
3445 for (i = 0; i < width; ++i)
3446 mac_draw_line (f, gc,
3447 left_x + i * left_p, top_y + i,
3448 right_x + 1 - i * right_p, top_y + i);
3450 /* Left. */
3451 if (left_p)
3452 for (i = 0; i < width; ++i)
3453 mac_draw_line (f, gc,
3454 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3456 mac_reset_clip_rectangles (dpy, gc);
3457 if (raised_p)
3458 gc = f->output_data.mac->black_relief.gc;
3459 else
3460 gc = f->output_data.mac->white_relief.gc;
3461 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3463 /* Bottom. */
3464 if (bot_p)
3465 for (i = 0; i < width; ++i)
3466 mac_draw_line (f, gc,
3467 left_x + i * left_p, bottom_y - i,
3468 right_x + 1 - i * right_p, bottom_y - i);
3470 /* Right. */
3471 if (right_p)
3472 for (i = 0; i < width; ++i)
3473 mac_draw_line (f, gc,
3474 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3476 mac_reset_clip_rectangles (dpy, gc);
3480 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3481 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3482 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3483 left side of the rectangle. RIGHT_P non-zero means draw a line
3484 on the right side of the rectangle. CLIP_RECT is the clipping
3485 rectangle to use when drawing. */
3487 static void
3488 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3489 left_p, right_p, clip_rect)
3490 struct glyph_string *s;
3491 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3492 Rect *clip_rect;
3494 XGCValues xgcv;
3496 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3497 XSetForeground (s->display, s->gc, s->face->box_color);
3498 mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1);
3500 /* Top. */
3501 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3502 right_x - left_x + 1, width);
3504 /* Left. */
3505 if (left_p)
3506 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3507 width, bottom_y - top_y + 1);
3509 /* Bottom. */
3510 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
3511 right_x - left_x + 1, width);
3513 /* Right. */
3514 if (right_p)
3515 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
3516 top_y, width, bottom_y - top_y + 1);
3518 XSetForeground (s->display, s->gc, xgcv.foreground);
3519 mac_reset_clip_rectangles (s->display, s->gc);
3523 /* Draw a box around glyph string S. */
3525 static void
3526 x_draw_glyph_string_box (s)
3527 struct glyph_string *s;
3529 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3530 int left_p, right_p;
3531 struct glyph *last_glyph;
3532 Rect clip_rect;
3534 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3535 ? WINDOW_RIGHT_EDGE_X (s->w)
3536 : window_box_right (s->w, s->area));
3538 /* The glyph that may have a right box line. */
3539 last_glyph = (s->cmp || s->img
3540 ? s->first_glyph
3541 : s->first_glyph + s->nchars - 1);
3543 width = abs (s->face->box_line_width);
3544 raised_p = s->face->box == FACE_RAISED_BOX;
3545 left_x = s->x;
3546 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3547 ? last_x - 1
3548 : min (last_x, s->x + s->background_width) - 1);
3549 top_y = s->y;
3550 bottom_y = top_y + s->height - 1;
3552 left_p = (s->first_glyph->left_box_line_p
3553 || (s->hl == DRAW_MOUSE_FACE
3554 && (s->prev == NULL
3555 || s->prev->hl != s->hl)));
3556 right_p = (last_glyph->right_box_line_p
3557 || (s->hl == DRAW_MOUSE_FACE
3558 && (s->next == NULL
3559 || s->next->hl != s->hl)));
3561 get_glyph_string_clip_rect (s, &clip_rect);
3563 if (s->face->box == FACE_SIMPLE_BOX)
3564 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3565 left_p, right_p, &clip_rect);
3566 else
3568 x_setup_relief_colors (s);
3569 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3570 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
3575 /* Draw foreground of image glyph string S. */
3577 static void
3578 x_draw_image_foreground (s)
3579 struct glyph_string *s;
3581 int x = s->x;
3582 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3584 /* If first glyph of S has a left box line, start drawing it to the
3585 right of that line. */
3586 if (s->face->box != FACE_NO_BOX
3587 && s->first_glyph->left_box_line_p
3588 && s->slice.x == 0)
3589 x += abs (s->face->box_line_width);
3591 /* If there is a margin around the image, adjust x- and y-position
3592 by that margin. */
3593 if (s->slice.x == 0)
3594 x += s->img->hmargin;
3595 if (s->slice.y == 0)
3596 y += s->img->vmargin;
3598 if (s->img->pixmap)
3600 x_set_glyph_string_clipping (s);
3602 #if USE_CG_DRAWING
3603 mac_draw_cg_image (s->img->data.ptr_val,
3604 s->f, s->gc, s->slice.x, s->slice.y,
3605 s->slice.width, s->slice.height, x, y, 1);
3606 #endif
3607 if (s->img->mask)
3608 #if !USE_CG_DRAWING
3609 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3610 s->f, s->gc, s->slice.x, s->slice.y,
3611 s->slice.width, s->slice.height, x, y);
3612 #else
3614 #endif
3615 else
3617 #if !USE_CG_DRAWING
3618 mac_copy_area (s->img->pixmap,
3619 s->f, s->gc, s->slice.x, s->slice.y,
3620 s->slice.width, s->slice.height, x, y);
3621 #endif
3623 /* When the image has a mask, we can expect that at
3624 least part of a mouse highlight or a block cursor will
3625 be visible. If the image doesn't have a mask, make
3626 a block cursor visible by drawing a rectangle around
3627 the image. I believe it's looking better if we do
3628 nothing here for mouse-face. */
3629 if (s->hl == DRAW_CURSOR)
3631 int r = s->img->relief;
3632 if (r < 0) r = -r;
3633 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
3634 s->slice.width + r*2 - 1,
3635 s->slice.height + r*2 - 1);
3639 else
3640 /* Draw a rectangle if image could not be loaded. */
3641 mac_draw_rectangle (s->f, s->gc, x, y,
3642 s->slice.width - 1, s->slice.height - 1);
3646 /* Draw a relief around the image glyph string S. */
3648 static void
3649 x_draw_image_relief (s)
3650 struct glyph_string *s;
3652 int x0, y0, x1, y1, thick, raised_p;
3653 Rect r;
3654 int x = s->x;
3655 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3657 /* If first glyph of S has a left box line, start drawing it to the
3658 right of that line. */
3659 if (s->face->box != FACE_NO_BOX
3660 && s->first_glyph->left_box_line_p
3661 && s->slice.x == 0)
3662 x += abs (s->face->box_line_width);
3664 /* If there is a margin around the image, adjust x- and y-position
3665 by that margin. */
3666 if (s->slice.x == 0)
3667 x += s->img->hmargin;
3668 if (s->slice.y == 0)
3669 y += s->img->vmargin;
3671 if (s->hl == DRAW_IMAGE_SUNKEN
3672 || s->hl == DRAW_IMAGE_RAISED)
3674 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3675 raised_p = s->hl == DRAW_IMAGE_RAISED;
3677 else
3679 thick = abs (s->img->relief);
3680 raised_p = s->img->relief > 0;
3683 x0 = x - thick;
3684 y0 = y - thick;
3685 x1 = x + s->slice.width + thick - 1;
3686 y1 = y + s->slice.height + thick - 1;
3688 x_setup_relief_colors (s);
3689 get_glyph_string_clip_rect (s, &r);
3690 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3691 s->slice.y == 0,
3692 s->slice.y + s->slice.height == s->img->height,
3693 s->slice.x == 0,
3694 s->slice.x + s->slice.width == s->img->width,
3695 &r);
3699 /* Draw part of the background of glyph string S. X, Y, W, and H
3700 give the rectangle to draw. */
3702 static void
3703 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3704 struct glyph_string *s;
3705 int x, y, w, h;
3707 #if 0 /* MAC_TODO: stipple */
3708 if (s->stippled_p)
3710 /* Fill background with a stipple pattern. */
3711 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3712 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3713 XSetFillStyle (s->display, s->gc, FillSolid);
3715 else
3716 #endif /* MAC_TODO */
3717 x_clear_glyph_string_rect (s, x, y, w, h);
3721 /* Draw image glyph string S.
3723 s->y
3724 s->x +-------------------------
3725 | s->face->box
3727 | +-------------------------
3728 | | s->img->margin
3730 | | +-------------------
3731 | | | the image
3735 static void
3736 x_draw_image_glyph_string (s)
3737 struct glyph_string *s;
3739 int x, y;
3740 int box_line_hwidth = abs (s->face->box_line_width);
3741 int box_line_vwidth = max (s->face->box_line_width, 0);
3742 int height;
3744 height = s->height - 2 * box_line_vwidth;
3747 /* Fill background with face under the image. Do it only if row is
3748 taller than image or if image has a clip mask to reduce
3749 flickering. */
3750 s->stippled_p = s->face->stipple != 0;
3751 if (height > s->slice.height
3752 || s->img->hmargin
3753 || s->img->vmargin
3754 || s->img->mask
3755 || s->img->pixmap == 0
3756 || s->width != s->background_width)
3758 x = s->x;
3759 if (s->first_glyph->left_box_line_p
3760 && s->slice.x == 0)
3761 x += box_line_hwidth;
3763 y = s->y;
3764 if (s->slice.y == 0)
3765 y += box_line_vwidth;
3767 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3769 s->background_filled_p = 1;
3772 /* Draw the foreground. */
3773 x_draw_image_foreground (s);
3775 /* If we must draw a relief around the image, do it. */
3776 if (s->img->relief
3777 || s->hl == DRAW_IMAGE_RAISED
3778 || s->hl == DRAW_IMAGE_SUNKEN)
3779 x_draw_image_relief (s);
3783 /* Draw stretch glyph string S. */
3785 static void
3786 x_draw_stretch_glyph_string (s)
3787 struct glyph_string *s;
3789 xassert (s->first_glyph->type == STRETCH_GLYPH);
3791 if (s->hl == DRAW_CURSOR
3792 && !x_stretch_cursor_p)
3794 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3795 as wide as the stretch glyph. */
3796 int width, background_width = s->background_width;
3797 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3799 if (x < left_x)
3801 background_width -= left_x - x;
3802 x = left_x;
3804 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3806 /* Draw cursor. */
3807 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3809 /* Clear rest using the GC of the original non-cursor face. */
3810 if (width < background_width)
3812 int y = s->y;
3813 int w = background_width - width, h = s->height;
3814 Rect r;
3815 GC gc;
3817 x += width;
3818 if (s->row->mouse_face_p
3819 && cursor_in_mouse_face_p (s->w))
3821 x_set_mouse_face_gc (s);
3822 gc = s->gc;
3824 else
3825 gc = s->face->gc;
3827 get_glyph_string_clip_rect (s, &r);
3828 mac_set_clip_rectangles (s->display, gc, &r, 1);
3830 #if 0 /* MAC_TODO: stipple */
3831 if (s->face->stipple)
3833 /* Fill background with a stipple pattern. */
3834 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3835 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3836 XSetFillStyle (s->display, gc, FillSolid);
3838 else
3839 #endif /* MAC_TODO */
3840 mac_erase_rectangle (s->f, gc, x, y, w, h);
3843 else if (!s->background_filled_p)
3845 int background_width = s->background_width;
3846 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3848 /* Don't draw into left margin, fringe or scrollbar area
3849 except for header line and mode line. */
3850 if (x < left_x && !s->row->mode_line_p)
3852 background_width -= left_x - x;
3853 x = left_x;
3855 if (background_width > 0)
3856 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3859 s->background_filled_p = 1;
3863 /* Draw glyph string S. */
3865 static void
3866 x_draw_glyph_string (s)
3867 struct glyph_string *s;
3869 int relief_drawn_p = 0;
3871 /* If S draws into the background of its successor that does not
3872 draw a cursor, draw the background of the successor first so that
3873 S can draw into it. This makes S->next use XDrawString instead
3874 of XDrawImageString. */
3875 if (s->next && s->right_overhang && !s->for_overlaps
3876 && s->next->hl != DRAW_CURSOR)
3878 xassert (s->next->img == NULL);
3879 x_set_glyph_string_gc (s->next);
3880 x_set_glyph_string_clipping (s->next);
3881 x_draw_glyph_string_background (s->next, 1);
3884 /* Set up S->gc, set clipping and draw S. */
3885 x_set_glyph_string_gc (s);
3887 /* Draw relief (if any) in advance for char/composition so that the
3888 glyph string can be drawn over it. */
3889 if (!s->for_overlaps
3890 && s->face->box != FACE_NO_BOX
3891 && (s->first_glyph->type == CHAR_GLYPH
3892 || s->first_glyph->type == COMPOSITE_GLYPH))
3895 x_set_glyph_string_clipping (s);
3896 x_draw_glyph_string_background (s, 1);
3897 x_draw_glyph_string_box (s);
3898 x_set_glyph_string_clipping (s);
3899 relief_drawn_p = 1;
3901 else
3902 x_set_glyph_string_clipping (s);
3904 switch (s->first_glyph->type)
3906 case IMAGE_GLYPH:
3907 x_draw_image_glyph_string (s);
3908 break;
3910 case STRETCH_GLYPH:
3911 x_draw_stretch_glyph_string (s);
3912 break;
3914 case CHAR_GLYPH:
3915 if (s->for_overlaps)
3916 s->background_filled_p = 1;
3917 else
3918 x_draw_glyph_string_background (s, 0);
3919 x_draw_glyph_string_foreground (s);
3920 break;
3922 case COMPOSITE_GLYPH:
3923 if (s->for_overlaps || s->gidx > 0)
3924 s->background_filled_p = 1;
3925 else
3926 x_draw_glyph_string_background (s, 1);
3927 x_draw_composite_glyph_string_foreground (s);
3928 break;
3930 default:
3931 abort ();
3934 if (!s->for_overlaps)
3936 /* Draw underline. */
3937 if (s->face->underline_p)
3939 unsigned long tem, h;
3940 int y;
3942 #if 0
3943 /* Get the underline thickness. Default is 1 pixel. */
3944 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3945 #endif
3946 h = 1;
3948 y = s->y + s->height - h;
3949 if (!x_underline_at_descent_line)
3951 /* Get the underline position. This is the recommended
3952 vertical offset in pixels from the baseline to the top of
3953 the underline. This is a signed value according to the
3954 specs, and its default is
3956 ROUND ((maximum descent) / 2), with
3957 ROUND(x) = floor (x + 0.5) */
3959 #if 0
3960 if (x_use_underline_position_properties
3961 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
3962 y = s->ybase + (long) tem;
3963 else
3964 #endif
3965 if (s->face->font)
3966 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
3969 if (s->face->underline_defaulted_p)
3970 mac_fill_rectangle (s->f, s->gc, s->x, y,
3971 s->background_width, h);
3972 else
3974 XGCValues xgcv;
3975 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3976 XSetForeground (s->display, s->gc, s->face->underline_color);
3977 mac_fill_rectangle (s->f, s->gc, s->x, y,
3978 s->background_width, h);
3979 XSetForeground (s->display, s->gc, xgcv.foreground);
3983 /* Draw overline. */
3984 if (s->face->overline_p)
3986 unsigned long dy = 0, h = 1;
3988 if (s->face->overline_color_defaulted_p)
3989 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3990 s->background_width, h);
3991 else
3993 XGCValues xgcv;
3994 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3995 XSetForeground (s->display, s->gc, s->face->overline_color);
3996 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3997 s->background_width, h);
3998 XSetForeground (s->display, s->gc, xgcv.foreground);
4002 /* Draw strike-through. */
4003 if (s->face->strike_through_p)
4005 unsigned long h = 1;
4006 unsigned long dy = (s->height - h) / 2;
4008 if (s->face->strike_through_color_defaulted_p)
4009 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
4010 s->width, h);
4011 else
4013 XGCValues xgcv;
4014 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4015 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4016 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
4017 s->width, h);
4018 XSetForeground (s->display, s->gc, xgcv.foreground);
4022 /* Draw relief if not yet drawn. */
4023 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4024 x_draw_glyph_string_box (s);
4027 /* Reset clipping. */
4028 mac_reset_clip_rectangles (s->display, s->gc);
4031 /* Shift display to make room for inserted glyphs. */
4033 void
4034 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
4035 struct frame *f;
4036 int x, y, width, height, shift_by;
4038 mac_scroll_area (f, f->output_data.mac->normal_gc,
4039 x, y, width, height,
4040 x + shift_by, y);
4043 /* Delete N glyphs at the nominal cursor position. Not implemented
4044 for X frames. */
4046 static void
4047 x_delete_glyphs (n)
4048 register int n;
4050 abort ();
4054 /* Clear entire frame. If updating_frame is non-null, clear that
4055 frame. Otherwise clear the selected frame. */
4057 static void
4058 x_clear_frame ()
4060 struct frame *f;
4062 if (updating_frame)
4063 f = updating_frame;
4064 else
4065 f = SELECTED_FRAME ();
4067 /* Clearing the frame will erase any cursor, so mark them all as no
4068 longer visible. */
4069 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4070 output_cursor.hpos = output_cursor.vpos = 0;
4071 output_cursor.x = -1;
4073 /* We don't set the output cursor here because there will always
4074 follow an explicit cursor_to. */
4075 BLOCK_INPUT;
4076 mac_clear_window (f);
4078 /* We have to clear the scroll bars, too. If we have changed
4079 colors or something like that, then they should be notified. */
4080 x_scroll_bar_clear (f);
4082 XFlush (FRAME_MAC_DISPLAY (f));
4083 UNBLOCK_INPUT;
4088 /* Invert the middle quarter of the frame for .15 sec. */
4090 /* We use the select system call to do the waiting, so we have to make
4091 sure it's available. If it isn't, we just won't do visual bells. */
4093 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4096 /* Subtract the `struct timeval' values X and Y, storing the result in
4097 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4099 static int
4100 timeval_subtract (result, x, y)
4101 struct timeval *result, x, y;
4103 /* Perform the carry for the later subtraction by updating y. This
4104 is safer because on some systems the tv_sec member is unsigned. */
4105 if (x.tv_usec < y.tv_usec)
4107 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4108 y.tv_usec -= 1000000 * nsec;
4109 y.tv_sec += nsec;
4112 if (x.tv_usec - y.tv_usec > 1000000)
4114 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4115 y.tv_usec += 1000000 * nsec;
4116 y.tv_sec -= nsec;
4119 /* Compute the time remaining to wait. tv_usec is certainly
4120 positive. */
4121 result->tv_sec = x.tv_sec - y.tv_sec;
4122 result->tv_usec = x.tv_usec - y.tv_usec;
4124 /* Return indication of whether the result should be considered
4125 negative. */
4126 return x.tv_sec < y.tv_sec;
4129 void
4130 XTflash (f)
4131 struct frame *f;
4133 /* Get the height not including a menu bar widget. */
4134 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
4135 /* Height of each line to flash. */
4136 int flash_height = FRAME_LINE_HEIGHT (f);
4137 /* These will be the left and right margins of the rectangles. */
4138 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4139 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4141 int width;
4143 /* Don't flash the area between a scroll bar and the frame
4144 edge it is next to. */
4145 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4147 case vertical_scroll_bar_left:
4148 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4149 break;
4151 case vertical_scroll_bar_right:
4152 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4153 break;
4155 default:
4156 break;
4159 width = flash_right - flash_left;
4161 BLOCK_INPUT;
4163 /* If window is tall, flash top and bottom line. */
4164 if (height > 3 * FRAME_LINE_HEIGHT (f))
4166 mac_invert_rectangle (f, flash_left,
4167 (FRAME_INTERNAL_BORDER_WIDTH (f)
4168 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4169 width, flash_height);
4170 mac_invert_rectangle (f, flash_left,
4171 (height - flash_height
4172 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4173 width, flash_height);
4175 else
4176 /* If it is short, flash it all. */
4177 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4178 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4180 x_flush (f);
4183 struct timeval wakeup;
4185 EMACS_GET_TIME (wakeup);
4187 /* Compute time to wait until, propagating carry from usecs. */
4188 wakeup.tv_usec += 150000;
4189 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4190 wakeup.tv_usec %= 1000000;
4192 /* Keep waiting until past the time wakeup or any input gets
4193 available. */
4194 while (! detect_input_pending ())
4196 struct timeval current;
4197 struct timeval timeout;
4199 EMACS_GET_TIME (current);
4201 /* Break if result would be negative. */
4202 if (timeval_subtract (&current, wakeup, current))
4203 break;
4205 /* How long `select' should wait. */
4206 timeout.tv_sec = 0;
4207 timeout.tv_usec = 10000;
4209 /* Try to wait that long--but we might wake up sooner. */
4210 select (0, NULL, NULL, NULL, &timeout);
4214 /* If window is tall, flash top and bottom line. */
4215 if (height > 3 * FRAME_LINE_HEIGHT (f))
4217 mac_invert_rectangle (f, flash_left,
4218 (FRAME_INTERNAL_BORDER_WIDTH (f)
4219 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4220 width, flash_height);
4221 mac_invert_rectangle (f, flash_left,
4222 (height - flash_height
4223 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4224 width, flash_height);
4226 else
4227 /* If it is short, flash it all. */
4228 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4229 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4231 x_flush (f);
4233 UNBLOCK_INPUT;
4236 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4239 /* Make audible bell. */
4241 void
4242 XTring_bell ()
4244 struct frame *f = SELECTED_FRAME ();
4246 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4247 if (visible_bell)
4248 XTflash (f);
4249 else
4250 #endif
4252 BLOCK_INPUT;
4253 SysBeep (1);
4254 XFlush (FRAME_MAC_DISPLAY (f));
4255 UNBLOCK_INPUT;
4260 /* Specify how many text lines, from the top of the window,
4261 should be affected by insert-lines and delete-lines operations.
4262 This, and those operations, are used only within an update
4263 that is bounded by calls to x_update_begin and x_update_end. */
4265 static void
4266 XTset_terminal_window (n)
4267 register int n;
4269 /* This function intentionally left blank. */
4274 /***********************************************************************
4275 Line Dance
4276 ***********************************************************************/
4278 /* Perform an insert-lines or delete-lines operation, inserting N
4279 lines or deleting -N lines at vertical position VPOS. */
4281 static void
4282 x_ins_del_lines (vpos, n)
4283 int vpos, n;
4285 abort ();
4289 /* Scroll part of the display as described by RUN. */
4291 static void
4292 x_scroll_run (w, run)
4293 struct window *w;
4294 struct run *run;
4296 struct frame *f = XFRAME (w->frame);
4297 int x, y, width, height, from_y, to_y, bottom_y;
4299 /* Get frame-relative bounding box of the text display area of W,
4300 without mode lines. Include in this box the left and right
4301 fringe of W. */
4302 window_box (w, -1, &x, &y, &width, &height);
4304 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4305 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4306 bottom_y = y + height;
4308 if (to_y < from_y)
4310 /* Scrolling up. Make sure we don't copy part of the mode
4311 line at the bottom. */
4312 if (from_y + run->height > bottom_y)
4313 height = bottom_y - from_y;
4314 else
4315 height = run->height;
4317 else
4319 /* Scolling down. Make sure we don't copy over the mode line.
4320 at the bottom. */
4321 if (to_y + run->height > bottom_y)
4322 height = bottom_y - to_y;
4323 else
4324 height = run->height;
4327 BLOCK_INPUT;
4329 /* Cursor off. Will be switched on again in x_update_window_end. */
4330 updated_window = w;
4331 x_clear_cursor (w);
4333 mac_scroll_area (f, f->output_data.mac->normal_gc,
4334 x, from_y,
4335 width, height,
4336 x, to_y);
4338 UNBLOCK_INPUT;
4343 /***********************************************************************
4344 Exposure Events
4345 ***********************************************************************/
4348 static void
4349 frame_highlight (f)
4350 struct frame *f;
4352 x_update_cursor (f, 1);
4355 static void
4356 frame_unhighlight (f)
4357 struct frame *f;
4359 x_update_cursor (f, 1);
4362 /* The focus has changed. Update the frames as necessary to reflect
4363 the new situation. Note that we can't change the selected frame
4364 here, because the Lisp code we are interrupting might become confused.
4365 Each event gets marked with the frame in which it occurred, so the
4366 Lisp code can tell when the switch took place by examining the events. */
4368 static void
4369 x_new_focus_frame (dpyinfo, frame)
4370 struct x_display_info *dpyinfo;
4371 struct frame *frame;
4373 struct frame *old_focus = dpyinfo->x_focus_frame;
4375 if (frame != dpyinfo->x_focus_frame)
4377 /* Set this before calling other routines, so that they see
4378 the correct value of x_focus_frame. */
4379 dpyinfo->x_focus_frame = frame;
4381 if (old_focus && old_focus->auto_lower)
4382 x_lower_frame (old_focus);
4384 #if 0
4385 selected_frame = frame;
4386 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
4387 selected_frame);
4388 Fselect_window (selected_frame->selected_window, Qnil);
4389 choose_minibuf_frame ();
4390 #endif /* ! 0 */
4392 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4393 pending_autoraise_frame = dpyinfo->x_focus_frame;
4394 else
4395 pending_autoraise_frame = 0;
4397 #if USE_MAC_FONT_PANEL
4398 if (frame)
4399 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
4400 #endif
4403 x_frame_rehighlight (dpyinfo);
4406 /* Handle FocusIn and FocusOut state changes for FRAME.
4407 If FRAME has focus and there exists more than one frame, puts
4408 a FOCUS_IN_EVENT into *BUFP. */
4410 static void
4411 mac_focus_changed (type, dpyinfo, frame, bufp)
4412 int type;
4413 struct mac_display_info *dpyinfo;
4414 struct frame *frame;
4415 struct input_event *bufp;
4417 if (type == activeFlag)
4419 if (dpyinfo->x_focus_event_frame != frame)
4421 x_new_focus_frame (dpyinfo, frame);
4422 dpyinfo->x_focus_event_frame = frame;
4424 /* Don't stop displaying the initial startup message
4425 for a switch-frame event we don't need. */
4426 if (GC_NILP (Vterminal_frame)
4427 && GC_CONSP (Vframe_list)
4428 && !GC_NILP (XCDR (Vframe_list)))
4430 bufp->kind = FOCUS_IN_EVENT;
4431 XSETFRAME (bufp->frame_or_window, frame);
4435 else
4437 if (dpyinfo->x_focus_event_frame == frame)
4439 dpyinfo->x_focus_event_frame = 0;
4440 x_new_focus_frame (dpyinfo, 0);
4445 /* The focus may have changed. Figure out if it is a real focus change,
4446 by checking both FocusIn/Out and Enter/LeaveNotify events.
4448 Returns FOCUS_IN_EVENT event in *BUFP. */
4450 static void
4451 x_detect_focus_change (dpyinfo, event, bufp)
4452 struct mac_display_info *dpyinfo;
4453 const EventRecord *event;
4454 struct input_event *bufp;
4456 struct frame *frame;
4458 frame = mac_window_to_frame ((WindowRef) event->message);
4459 if (! frame)
4460 return;
4462 /* On Mac, this is only called from focus events, so no switch needed. */
4463 mac_focus_changed ((event->modifiers & activeFlag),
4464 dpyinfo, frame, bufp);
4468 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4470 void
4471 x_mouse_leave (dpyinfo)
4472 struct x_display_info *dpyinfo;
4474 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4477 /* The focus has changed, or we have redirected a frame's focus to
4478 another frame (this happens when a frame uses a surrogate
4479 mini-buffer frame). Shift the highlight as appropriate.
4481 The FRAME argument doesn't necessarily have anything to do with which
4482 frame is being highlighted or un-highlighted; we only use it to find
4483 the appropriate X display info. */
4485 static void
4486 XTframe_rehighlight (frame)
4487 struct frame *frame;
4489 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
4492 static void
4493 x_frame_rehighlight (dpyinfo)
4494 struct x_display_info *dpyinfo;
4496 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4498 if (dpyinfo->x_focus_frame)
4500 dpyinfo->x_highlight_frame
4501 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4502 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4503 : dpyinfo->x_focus_frame);
4504 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4506 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
4507 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4510 else
4511 dpyinfo->x_highlight_frame = 0;
4513 if (dpyinfo->x_highlight_frame != old_highlight)
4515 if (old_highlight)
4516 frame_unhighlight (old_highlight);
4517 if (dpyinfo->x_highlight_frame)
4518 frame_highlight (dpyinfo->x_highlight_frame);
4524 /* Convert a keysym to its name. */
4526 char *
4527 x_get_keysym_name (keysym)
4528 int keysym;
4530 char *value;
4532 BLOCK_INPUT;
4533 #if 0
4534 value = XKeysymToString (keysym);
4535 #else
4536 value = 0;
4537 #endif
4538 UNBLOCK_INPUT;
4540 return value;
4545 /* Function to report a mouse movement to the mainstream Emacs code.
4546 The input handler calls this.
4548 We have received a mouse movement event, which is given in *event.
4549 If the mouse is over a different glyph than it was last time, tell
4550 the mainstream emacs code by setting mouse_moved. If not, ask for
4551 another motion event, so we can check again the next time it moves. */
4553 static Point last_mouse_motion_position;
4554 static Lisp_Object last_mouse_motion_frame;
4556 static int
4557 note_mouse_movement (frame, pos)
4558 FRAME_PTR frame;
4559 Point *pos;
4561 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4562 #if TARGET_API_MAC_CARBON
4563 Rect r;
4564 #endif
4566 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4567 last_mouse_motion_position = *pos;
4568 XSETFRAME (last_mouse_motion_frame, frame);
4570 if (frame == dpyinfo->mouse_face_mouse_frame
4571 #if TARGET_API_MAC_CARBON
4572 && !PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r))
4573 #else
4574 && !PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect)
4575 #endif
4578 /* This case corresponds to LeaveNotify in X11. If we move
4579 outside the frame, then we're certainly no longer on any text
4580 in the frame. */
4581 clear_mouse_face (dpyinfo);
4582 dpyinfo->mouse_face_mouse_frame = 0;
4583 if (!dpyinfo->grabbed)
4584 rif->define_frame_cursor (frame,
4585 frame->output_data.mac->nontext_cursor);
4588 /* Has the mouse moved off the glyph it was on at the last sighting? */
4589 if (frame != last_mouse_glyph_frame
4590 || !PtInRect (*pos, &last_mouse_glyph))
4592 frame->mouse_moved = 1;
4593 last_mouse_scroll_bar = Qnil;
4594 note_mouse_highlight (frame, pos->h, pos->v);
4595 /* Remember which glyph we're now on. */
4596 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
4597 last_mouse_glyph_frame = frame;
4598 return 1;
4601 return 0;
4605 /************************************************************************
4606 Mouse Face
4607 ************************************************************************/
4609 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4611 static void
4612 redo_mouse_highlight ()
4614 if (!NILP (last_mouse_motion_frame)
4615 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4616 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4617 last_mouse_motion_position.h,
4618 last_mouse_motion_position.v);
4622 static struct frame *
4623 mac_focus_frame (dpyinfo)
4624 struct mac_display_info *dpyinfo;
4626 if (dpyinfo->x_focus_frame)
4627 return dpyinfo->x_focus_frame;
4628 else
4629 /* Mac version may get events, such as a menu bar click, even when
4630 all the frames are invisible. In this case, we regard the
4631 event came to the selected frame. */
4632 return SELECTED_FRAME ();
4636 /* Return the current position of the mouse.
4637 *FP should be a frame which indicates which display to ask about.
4639 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4640 and *PART to the frame, window, and scroll bar part that the mouse
4641 is over. Set *X and *Y to the portion and whole of the mouse's
4642 position on the scroll bar.
4644 If the mouse movement started elsewhere, set *FP to the frame the
4645 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4646 the mouse is over.
4648 Set *TIME to the server time-stamp for the time at which the mouse
4649 was at this position.
4651 Don't store anything if we don't have a valid set of values to report.
4653 This clears the mouse_moved flag, so we can wait for the next mouse
4654 movement. */
4656 static void
4657 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4658 FRAME_PTR *fp;
4659 int insist;
4660 Lisp_Object *bar_window;
4661 enum scroll_bar_part *part;
4662 Lisp_Object *x, *y;
4663 unsigned long *time;
4665 FRAME_PTR f1;
4667 BLOCK_INPUT;
4669 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4670 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4671 else
4673 Lisp_Object frame, tail;
4675 /* Clear the mouse-moved flag for every frame on this display. */
4676 FOR_EACH_FRAME (tail, frame)
4677 XFRAME (frame)->mouse_moved = 0;
4679 last_mouse_scroll_bar = Qnil;
4681 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4682 && FRAME_LIVE_P (last_mouse_frame))
4683 f1 = last_mouse_frame;
4684 else
4685 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4687 if (f1)
4689 /* Ok, we found a frame. Store all the values.
4690 last_mouse_glyph is a rectangle used to reduce the
4691 generation of mouse events. To not miss any motion
4692 events, we must divide the frame into rectangles of the
4693 size of the smallest character that could be displayed
4694 on it, i.e. into the same rectangles that matrices on
4695 the frame are divided into. */
4696 Point mouse_pos;
4698 #if TARGET_API_MAC_CARBON
4699 GetGlobalMouse (&mouse_pos);
4700 mouse_pos.h -= f1->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f1);
4701 mouse_pos.v -= f1->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f1);
4702 #else
4703 SetPortWindowPort (FRAME_MAC_WINDOW (f1));
4704 GetMouse (&mouse_pos);
4705 #endif
4706 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4707 &last_mouse_glyph);
4708 last_mouse_glyph_frame = f1;
4710 *bar_window = Qnil;
4711 *part = 0;
4712 *fp = f1;
4713 XSETINT (*x, mouse_pos.h);
4714 XSETINT (*y, mouse_pos.v);
4715 *time = last_mouse_movement_time;
4719 UNBLOCK_INPUT;
4723 /************************************************************************
4724 Toolkit scroll bars
4725 ************************************************************************/
4727 #ifdef USE_TOOLKIT_SCROLL_BARS
4729 static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
4730 static OSStatus install_scroll_bar_timer P_ ((void));
4731 static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
4732 static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
4733 static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
4734 struct input_event *));
4735 static OSStatus get_control_part_bounds P_ ((ControlRef, ControlPartCode,
4736 Rect *));
4737 static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
4738 ControlPartCode, Point,
4739 struct input_event *));
4740 static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
4741 struct input_event *));
4742 static void x_scroll_bar_handle_drag P_ ((WindowRef, struct scroll_bar *,
4743 Point, struct input_event *));
4744 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
4745 int, int, int));
4747 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4749 static int last_scroll_bar_part;
4751 static EventLoopTimerRef scroll_bar_timer;
4753 static int scroll_bar_timer_event_posted_p;
4755 #define SCROLL_BAR_FIRST_DELAY 0.5
4756 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4758 static pascal void
4759 scroll_bar_timer_callback (timer, data)
4760 EventLoopTimerRef timer;
4761 void *data;
4763 OSStatus err;
4765 err = mac_post_mouse_moved_event ();
4766 if (err == noErr)
4767 scroll_bar_timer_event_posted_p = 1;
4770 static OSStatus
4771 install_scroll_bar_timer ()
4773 static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
4775 if (scroll_bar_timer_callbackUPP == NULL)
4776 scroll_bar_timer_callbackUPP =
4777 NewEventLoopTimerUPP (scroll_bar_timer_callback);
4779 if (scroll_bar_timer == NULL)
4780 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4781 kEventDurationForever as delays. */
4782 return
4783 InstallEventLoopTimer (GetCurrentEventLoop (),
4784 kEventDurationForever, kEventDurationForever,
4785 scroll_bar_timer_callbackUPP, NULL,
4786 &scroll_bar_timer);
4789 static OSStatus
4790 set_scroll_bar_timer (delay)
4791 EventTimerInterval delay;
4793 if (scroll_bar_timer == NULL)
4794 install_scroll_bar_timer ();
4796 scroll_bar_timer_event_posted_p = 0;
4798 return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
4801 static int
4802 control_part_code_to_scroll_bar_part (part_code)
4803 ControlPartCode part_code;
4805 switch (part_code)
4807 case kControlUpButtonPart: return scroll_bar_up_arrow;
4808 case kControlDownButtonPart: return scroll_bar_down_arrow;
4809 case kControlPageUpPart: return scroll_bar_above_handle;
4810 case kControlPageDownPart: return scroll_bar_below_handle;
4811 case kControlIndicatorPart: return scroll_bar_handle;
4814 return -1;
4817 static void
4818 construct_scroll_bar_click (bar, part, bufp)
4819 struct scroll_bar *bar;
4820 int part;
4821 struct input_event *bufp;
4823 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4824 bufp->frame_or_window = bar->window;
4825 bufp->arg = Qnil;
4826 bufp->part = part;
4827 bufp->code = 0;
4828 XSETINT (bufp->x, 0);
4829 XSETINT (bufp->y, 0);
4830 bufp->modifiers = 0;
4833 static OSStatus
4834 get_control_part_bounds (ch, part_code, rect)
4835 ControlRef ch;
4836 ControlPartCode part_code;
4837 Rect *rect;
4839 RgnHandle region = NewRgn ();
4840 OSStatus err;
4842 err = GetControlRegion (ch, part_code, region);
4843 if (err == noErr)
4844 GetRegionBounds (region, rect);
4845 DisposeRgn (region);
4847 return err;
4850 static void
4851 x_scroll_bar_handle_press (bar, part_code, mouse_pos, bufp)
4852 struct scroll_bar *bar;
4853 ControlPartCode part_code;
4854 Point mouse_pos;
4855 struct input_event *bufp;
4857 int part = control_part_code_to_scroll_bar_part (part_code);
4859 if (part < 0)
4860 return;
4862 if (part != scroll_bar_handle)
4864 construct_scroll_bar_click (bar, part, bufp);
4865 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), part_code);
4866 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
4867 bar->dragging = Qnil;
4869 else
4871 Rect r;
4873 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar),
4874 kControlIndicatorPart, &r);
4875 XSETINT (bar->dragging, - (mouse_pos.v - r.top) - 1);
4878 last_scroll_bar_part = part;
4879 tracked_scroll_bar = bar;
4882 static void
4883 x_scroll_bar_handle_release (bar, bufp)
4884 struct scroll_bar *bar;
4885 struct input_event *bufp;
4887 if (last_scroll_bar_part != scroll_bar_handle
4888 || (INTEGERP (bar->dragging) && XINT (bar->dragging) >= 0))
4889 construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
4891 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), 0);
4892 set_scroll_bar_timer (kEventDurationForever);
4894 last_scroll_bar_part = -1;
4895 bar->dragging = Qnil;
4896 tracked_scroll_bar = NULL;
4899 static void
4900 x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
4901 WindowRef win;
4902 struct scroll_bar *bar;
4903 Point mouse_pos;
4904 struct input_event *bufp;
4906 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
4908 if (last_scroll_bar_part == scroll_bar_handle)
4910 int top, top_range;
4911 Rect r;
4913 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar),
4914 kControlIndicatorPart, &r);
4916 if (INTEGERP (bar->dragging) && XINT (bar->dragging) < 0)
4917 XSETINT (bar->dragging, - (XINT (bar->dragging) + 1));
4919 top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
4920 top_range = XINT (bar->track_height) - XINT (bar->min_handle);
4922 if (top < 0)
4923 top = 0;
4924 if (top > top_range)
4925 top = top_range;
4927 construct_scroll_bar_click (bar, scroll_bar_handle, bufp);
4928 XSETINT (bufp->x, top);
4929 XSETINT (bufp->y, top_range);
4931 else
4933 ControlPartCode part_code;
4934 int unhilite_p = 0, part;
4936 if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
4937 unhilite_p = 1;
4938 else
4940 part = control_part_code_to_scroll_bar_part (part_code);
4942 switch (last_scroll_bar_part)
4944 case scroll_bar_above_handle:
4945 case scroll_bar_below_handle:
4946 if (part != scroll_bar_above_handle
4947 && part != scroll_bar_below_handle)
4948 unhilite_p = 1;
4949 break;
4951 case scroll_bar_up_arrow:
4952 case scroll_bar_down_arrow:
4953 if (part != scroll_bar_up_arrow
4954 && part != scroll_bar_down_arrow)
4955 unhilite_p = 1;
4956 break;
4960 if (unhilite_p)
4961 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), 0);
4962 else if (part != last_scroll_bar_part
4963 || scroll_bar_timer_event_posted_p)
4965 construct_scroll_bar_click (bar, part, bufp);
4966 last_scroll_bar_part = part;
4967 HiliteControl (SCROLL_BAR_CONTROL_REF (bar), part_code);
4968 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
4973 /* Set the thumb size and position of scroll bar BAR. We are currently
4974 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4976 static void
4977 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4978 struct scroll_bar *bar;
4979 int portion, position, whole;
4981 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
4982 int value, viewsize, maximum;
4984 if (XINT (bar->track_height) == 0)
4985 return;
4987 if (whole <= portion)
4988 value = 0, viewsize = 1, maximum = 0;
4989 else
4991 float scale;
4993 maximum = XINT (bar->track_height) - XINT (bar->min_handle);
4994 scale = (float) maximum / (whole - portion);
4995 value = position * scale + 0.5f;
4996 viewsize = (int) (portion * scale + 0.5f) + XINT (bar->min_handle);
4999 BLOCK_INPUT;
5001 if (GetControlViewSize (ch) != viewsize
5002 || GetControl32BitValue (ch) != value
5003 || GetControl32BitMaximum (ch) != maximum)
5005 /* Temporarily hide the scroll bar to avoid multiple redraws. */
5006 SetControlVisibility (ch, false, false);
5008 SetControl32BitMaximum (ch, maximum);
5009 SetControl32BitValue (ch, value);
5010 SetControlViewSize (ch, viewsize);
5012 SetControlVisibility (ch, true, true);
5015 UNBLOCK_INPUT;
5018 #endif /* USE_TOOLKIT_SCROLL_BARS */
5022 /************************************************************************
5023 Scroll bars, general
5024 ************************************************************************/
5026 /* Create a scroll bar and return the scroll bar vector for it. W is
5027 the Emacs window on which to create the scroll bar. TOP, LEFT,
5028 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
5029 scroll bar. */
5031 static struct scroll_bar *
5032 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
5033 struct window *w;
5034 int top, left, width, height, disp_top, disp_height;
5036 struct frame *f = XFRAME (w->frame);
5037 struct scroll_bar *bar
5038 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
5039 Rect r;
5040 ControlRef ch;
5042 BLOCK_INPUT;
5044 r.left = left;
5045 r.top = disp_top;
5046 r.right = left + width;
5047 r.bottom = disp_top + disp_height;
5049 #if USE_CG_DRAWING
5050 mac_prepare_for_quickdraw (f);
5051 #endif
5052 #if TARGET_API_MAC_CARBON
5053 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
5054 #ifdef USE_TOOLKIT_SCROLL_BARS
5055 false,
5056 #else
5057 width < disp_height,
5058 #endif
5059 0, 0, 0, kControlScrollBarProc, (long) bar);
5060 #else
5061 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
5062 0, 0, 0, scrollBarProc, (long) bar);
5063 #endif
5064 SET_SCROLL_BAR_CONTROL_REF (bar, ch);
5066 XSETWINDOW (bar->window, w);
5067 XSETINT (bar->top, top);
5068 XSETINT (bar->left, left);
5069 XSETINT (bar->width, width);
5070 XSETINT (bar->height, height);
5071 XSETINT (bar->start, 0);
5072 XSETINT (bar->end, 0);
5073 bar->dragging = Qnil;
5074 #ifdef MAC_OSX
5075 bar->fringe_extended_p = Qnil;
5076 #endif
5077 bar->redraw_needed_p = Qnil;
5078 #ifdef USE_TOOLKIT_SCROLL_BARS
5079 bar->track_top = Qnil;
5080 bar->track_height = Qnil;
5081 bar->min_handle = Qnil;
5082 #endif
5084 /* Add bar to its frame's list of scroll bars. */
5085 bar->next = FRAME_SCROLL_BARS (f);
5086 bar->prev = Qnil;
5087 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5088 if (!NILP (bar->next))
5089 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5091 UNBLOCK_INPUT;
5092 return bar;
5096 /* Draw BAR's handle in the proper position.
5098 If the handle is already drawn from START to END, don't bother
5099 redrawing it, unless REBUILD is non-zero; in that case, always
5100 redraw it. (REBUILD is handy for drawing the handle after expose
5101 events.)
5103 Normally, we want to constrain the start and end of the handle to
5104 fit inside its rectangle, but if the user is dragging the scroll
5105 bar handle, we want to let them drag it down all the way, so that
5106 the bar's top is as far down as it goes; otherwise, there's no way
5107 to move to the very end of the buffer. */
5109 #ifndef USE_TOOLKIT_SCROLL_BARS
5111 static void
5112 x_scroll_bar_set_handle (bar, start, end, rebuild)
5113 struct scroll_bar *bar;
5114 int start, end;
5115 int rebuild;
5117 int dragging = ! NILP (bar->dragging);
5118 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
5119 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5120 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5121 int length = end - start;
5123 /* If the display is already accurate, do nothing. */
5124 if (! rebuild
5125 && start == XINT (bar->start)
5126 && end == XINT (bar->end))
5127 return;
5129 BLOCK_INPUT;
5131 /* Make sure the values are reasonable, and try to preserve the
5132 distance between start and end. */
5133 if (start < 0)
5134 start = 0;
5135 else if (start > top_range)
5136 start = top_range;
5137 end = start + length;
5139 if (end < start)
5140 end = start;
5141 else if (end > top_range && ! dragging)
5142 end = top_range;
5144 /* Store the adjusted setting in the scroll bar. */
5145 XSETINT (bar->start, start);
5146 XSETINT (bar->end, end);
5148 /* Clip the end position, just for display. */
5149 if (end > top_range)
5150 end = top_range;
5152 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5153 top positions, to make sure the handle is always at least that
5154 many pixels tall. */
5155 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
5157 SetControlMinimum (ch, 0);
5158 /* Don't inadvertently activate deactivated scroll bars */
5159 if (GetControlMaximum (ch) != -1)
5160 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
5161 - (end - start));
5162 SetControlValue (ch, start);
5163 #if TARGET_API_MAC_CARBON
5164 SetControlViewSize (ch, end - start);
5165 #endif
5167 UNBLOCK_INPUT;
5170 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5172 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5173 nil. */
5175 static void
5176 x_scroll_bar_remove (bar)
5177 struct scroll_bar *bar;
5179 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5181 BLOCK_INPUT;
5183 #if USE_CG_DRAWING
5184 mac_prepare_for_quickdraw (f);
5185 #endif
5186 /* Destroy the Mac scroll bar control */
5187 DisposeControl (SCROLL_BAR_CONTROL_REF (bar));
5189 /* Disassociate this scroll bar from its window. */
5190 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5192 UNBLOCK_INPUT;
5196 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5197 that we are displaying PORTION characters out of a total of WHOLE
5198 characters, starting at POSITION. If WINDOW has no scroll bar,
5199 create one. */
5201 static void
5202 XTset_vertical_scroll_bar (w, portion, whole, position)
5203 struct window *w;
5204 int portion, whole, position;
5206 struct frame *f = XFRAME (w->frame);
5207 struct scroll_bar *bar;
5208 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
5209 int window_y, window_height;
5210 #ifdef MAC_OSX
5211 int fringe_extended_p;
5212 #endif
5214 /* Get window dimensions. */
5215 window_box (w, -1, 0, &window_y, 0, &window_height);
5216 top = window_y;
5217 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5218 height = window_height;
5220 /* Compute the left edge of the scroll bar area. */
5221 left = WINDOW_SCROLL_BAR_AREA_X (w);
5223 /* Compute the width of the scroll bar which might be less than
5224 the width of the area reserved for the scroll bar. */
5225 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
5226 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
5227 else
5228 sb_width = width;
5230 /* Compute the left edge of the scroll bar. */
5231 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5232 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
5233 else
5234 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
5236 /* Adjustments according to Inside Macintosh to make it look nice */
5237 disp_top = top;
5238 disp_height = height;
5239 #ifdef MAC_OS8
5240 if (disp_top == 0)
5242 disp_top = -1;
5243 disp_height++;
5245 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
5247 disp_top++;
5248 disp_height--;
5251 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
5252 sb_left++;
5253 #endif
5255 #ifdef MAC_OSX
5256 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
5257 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
5258 && WINDOW_LEFT_FRINGE_WIDTH (w)
5259 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5260 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
5261 else
5262 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
5263 && WINDOW_RIGHT_FRINGE_WIDTH (w)
5264 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
5265 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
5266 #endif
5268 /* Does the scroll bar exist yet? */
5269 if (NILP (w->vertical_scroll_bar))
5271 BLOCK_INPUT;
5272 #ifdef MAC_OSX
5273 if (fringe_extended_p)
5274 mac_clear_area (f, sb_left, top, sb_width, height);
5275 else
5276 #endif
5277 mac_clear_area (f, left, top, width, height);
5278 UNBLOCK_INPUT;
5279 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
5280 disp_height);
5281 XSETVECTOR (w->vertical_scroll_bar, bar);
5283 else
5285 /* It may just need to be moved and resized. */
5286 ControlRef ch;
5288 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5289 ch = SCROLL_BAR_CONTROL_REF (bar);
5291 BLOCK_INPUT;
5293 /* If already correctly positioned, do nothing. */
5294 if (XINT (bar->left) == sb_left
5295 && XINT (bar->top) == top
5296 && XINT (bar->width) == sb_width
5297 && XINT (bar->height) == height
5298 #ifdef MAC_OSX
5299 && !NILP (bar->fringe_extended_p) == fringe_extended_p
5300 #endif
5303 if (!NILP (bar->redraw_needed_p))
5305 #if USE_CG_DRAWING
5306 mac_prepare_for_quickdraw (f);
5307 #endif
5308 Draw1Control (SCROLL_BAR_CONTROL_REF (bar));
5311 else
5313 /* Since toolkit scroll bars are smaller than the space reserved
5314 for them on the frame, we have to clear "under" them. */
5315 #ifdef MAC_OSX
5316 if (fringe_extended_p)
5317 mac_clear_area (f, sb_left, top, sb_width, height);
5318 else
5319 #endif
5320 mac_clear_area (f, left, top, width, height);
5322 #if USE_CG_DRAWING
5323 mac_prepare_for_quickdraw (f);
5324 #endif
5325 HideControl (ch);
5326 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
5327 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5328 disp_height);
5329 #ifndef USE_TOOLKIT_SCROLL_BARS
5330 if (sb_width < disp_height)
5331 ShowControl (ch);
5332 #endif
5334 /* Remember new settings. */
5335 XSETINT (bar->left, sb_left);
5336 XSETINT (bar->top, top);
5337 XSETINT (bar->width, sb_width);
5338 XSETINT (bar->height, height);
5339 #ifdef USE_TOOLKIT_SCROLL_BARS
5340 bar->track_top = Qnil;
5341 bar->track_height = Qnil;
5342 bar->min_handle = Qnil;
5343 #endif
5346 UNBLOCK_INPUT;
5349 #ifdef MAC_OSX
5350 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
5351 #endif
5352 bar->redraw_needed_p = Qnil;
5354 #ifdef USE_TOOLKIT_SCROLL_BARS
5355 if (NILP (bar->track_top))
5357 if (sb_width >= disp_height
5358 #ifdef MAC_OSX
5359 || sb_width < MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5360 #endif
5363 XSETINT (bar->track_top, 0);
5364 XSETINT (bar->track_height, 0);
5365 XSETINT (bar->min_handle, 0);
5367 else
5369 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
5370 Rect r0, r1;
5372 BLOCK_INPUT;
5374 SetControl32BitMinimum (ch, 0);
5375 SetControl32BitMaximum (ch, 1 << 30);
5376 SetControlViewSize (ch, 1);
5378 /* Move the scroll bar thumb to the top. */
5379 SetControl32BitValue (ch, 0);
5380 get_control_part_bounds (ch, kControlIndicatorPart, &r0);
5382 /* Move the scroll bar thumb to the bottom. */
5383 SetControl32BitValue (ch, 1 << 30);
5384 get_control_part_bounds (ch, kControlIndicatorPart, &r1);
5386 UnionRect (&r0, &r1, &r0);
5387 XSETINT (bar->track_top, r0.top);
5388 XSETINT (bar->track_height, r0.bottom - r0.top);
5389 XSETINT (bar->min_handle, r1.bottom - r1.top);
5391 /* Don't show the scroll bar if its height is not enough to
5392 display the scroll bar thumb. */
5393 if (r0.bottom - r0.top > 0)
5394 ShowControl (ch);
5396 UNBLOCK_INPUT;
5400 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5401 #else /* not USE_TOOLKIT_SCROLL_BARS */
5402 /* Set the scroll bar's current state, unless we're currently being
5403 dragged. */
5404 if (NILP (bar->dragging))
5406 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5408 if (whole == 0)
5409 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5410 else
5412 int start = ((double) position * top_range) / whole;
5413 int end = ((double) (position + portion) * top_range) / whole;
5414 x_scroll_bar_set_handle (bar, start, end, 0);
5417 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5421 /* The following three hooks are used when we're doing a thorough
5422 redisplay of the frame. We don't explicitly know which scroll bars
5423 are going to be deleted, because keeping track of when windows go
5424 away is a real pain - "Can you say set-window-configuration, boys
5425 and girls?" Instead, we just assert at the beginning of redisplay
5426 that *all* scroll bars are to be removed, and then save a scroll bar
5427 from the fiery pit when we actually redisplay its window. */
5429 /* Arrange for all scroll bars on FRAME to be removed at the next call
5430 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5431 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5433 static void
5434 XTcondemn_scroll_bars (frame)
5435 FRAME_PTR frame;
5437 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5438 while (! NILP (FRAME_SCROLL_BARS (frame)))
5440 Lisp_Object bar;
5441 bar = FRAME_SCROLL_BARS (frame);
5442 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5443 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5444 XSCROLL_BAR (bar)->prev = Qnil;
5445 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5446 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5447 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5452 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5453 Note that WINDOW isn't necessarily condemned at all. */
5455 static void
5456 XTredeem_scroll_bar (window)
5457 struct window *window;
5459 struct scroll_bar *bar;
5460 struct frame *f;
5462 /* We can't redeem this window's scroll bar if it doesn't have one. */
5463 if (NILP (window->vertical_scroll_bar))
5464 abort ();
5466 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5468 /* Unlink it from the condemned list. */
5469 f = XFRAME (WINDOW_FRAME (window));
5470 if (NILP (bar->prev))
5472 /* If the prev pointer is nil, it must be the first in one of
5473 the lists. */
5474 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5475 /* It's not condemned. Everything's fine. */
5476 return;
5477 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5478 window->vertical_scroll_bar))
5479 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5480 else
5481 /* If its prev pointer is nil, it must be at the front of
5482 one or the other! */
5483 abort ();
5485 else
5486 XSCROLL_BAR (bar->prev)->next = bar->next;
5488 if (! NILP (bar->next))
5489 XSCROLL_BAR (bar->next)->prev = bar->prev;
5491 bar->next = FRAME_SCROLL_BARS (f);
5492 bar->prev = Qnil;
5493 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5494 if (! NILP (bar->next))
5495 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5498 /* Remove all scroll bars on FRAME that haven't been saved since the
5499 last call to `*condemn_scroll_bars_hook'. */
5501 static void
5502 XTjudge_scroll_bars (f)
5503 FRAME_PTR f;
5505 Lisp_Object bar, next;
5507 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5509 /* Clear out the condemned list now so we won't try to process any
5510 more events on the hapless scroll bars. */
5511 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5513 for (; ! NILP (bar); bar = next)
5515 struct scroll_bar *b = XSCROLL_BAR (bar);
5517 x_scroll_bar_remove (b);
5519 next = b->next;
5520 b->next = b->prev = Qnil;
5523 /* Now there should be no references to the condemned scroll bars,
5524 and they should get garbage-collected. */
5528 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5529 is set to something other than NO_EVENT, it is enqueued.
5531 This may be called from a signal handler, so we have to ignore GC
5532 mark bits. */
5534 static void
5535 x_scroll_bar_handle_click (bar, part_code, er, bufp)
5536 struct scroll_bar *bar;
5537 ControlPartCode part_code;
5538 const EventRecord *er;
5539 struct input_event *bufp;
5541 int win_y, top_range;
5543 if (! GC_WINDOWP (bar->window))
5544 abort ();
5546 bufp->kind = SCROLL_BAR_CLICK_EVENT;
5547 bufp->frame_or_window = bar->window;
5548 bufp->arg = Qnil;
5550 bar->dragging = Qnil;
5552 switch (part_code)
5554 case kControlUpButtonPart:
5555 bufp->part = scroll_bar_up_arrow;
5556 break;
5557 case kControlDownButtonPart:
5558 bufp->part = scroll_bar_down_arrow;
5559 break;
5560 case kControlPageUpPart:
5561 bufp->part = scroll_bar_above_handle;
5562 break;
5563 case kControlPageDownPart:
5564 bufp->part = scroll_bar_below_handle;
5565 break;
5566 #if TARGET_API_MAC_CARBON
5567 default:
5568 #else
5569 case kControlIndicatorPart:
5570 #endif
5571 if (er->what == mouseDown)
5572 bar->dragging = make_number (0);
5573 XSETVECTOR (last_mouse_scroll_bar, bar);
5574 bufp->part = scroll_bar_handle;
5575 break;
5578 win_y = XINT (bufp->y) - XINT (bar->top);
5579 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
5581 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5583 win_y -= 24;
5585 if (! NILP (bar->dragging))
5586 win_y -= XINT (bar->dragging);
5588 if (win_y < 0)
5589 win_y = 0;
5590 if (win_y > top_range)
5591 win_y = top_range;
5593 XSETINT (bufp->x, win_y);
5594 XSETINT (bufp->y, top_range);
5597 #ifndef USE_TOOLKIT_SCROLL_BARS
5599 /* Handle some mouse motion while someone is dragging the scroll bar.
5601 This may be called from a signal handler, so we have to ignore GC
5602 mark bits. */
5604 static void
5605 x_scroll_bar_note_movement (bar, y_pos, t)
5606 struct scroll_bar *bar;
5607 int y_pos;
5608 Time t;
5610 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5612 last_mouse_movement_time = t;
5614 f->mouse_moved = 1;
5615 XSETVECTOR (last_mouse_scroll_bar, bar);
5617 /* If we're dragging the bar, display it. */
5618 if (! GC_NILP (bar->dragging))
5620 /* Where should the handle be now? */
5621 int new_start = y_pos - 24;
5623 if (new_start != XINT (bar->start))
5625 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
5627 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5632 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5634 /* Return information to the user about the current position of the mouse
5635 on the scroll bar. */
5637 static void
5638 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
5639 FRAME_PTR *fp;
5640 Lisp_Object *bar_window;
5641 enum scroll_bar_part *part;
5642 Lisp_Object *x, *y;
5643 unsigned long *time;
5645 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5646 ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
5647 #if TARGET_API_MAC_CARBON
5648 WindowRef wp = GetControlOwner (ch);
5649 #else
5650 WindowRef wp = (*ch)->contrlOwner;
5651 #endif
5652 Point mouse_pos;
5653 struct frame *f = mac_window_to_frame (wp);
5654 int win_y, top_range;
5656 #if TARGET_API_MAC_CARBON
5657 GetGlobalMouse (&mouse_pos);
5658 mouse_pos.h -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
5659 mouse_pos.v -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
5660 #else
5661 SetPortWindowPort (wp);
5662 GetMouse (&mouse_pos);
5663 #endif
5665 win_y = mouse_pos.v - XINT (bar->top);
5666 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5668 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5670 win_y -= 24;
5672 if (! NILP (bar->dragging))
5673 win_y -= XINT (bar->dragging);
5675 if (win_y < 0)
5676 win_y = 0;
5677 if (win_y > top_range)
5678 win_y = top_range;
5680 *fp = f;
5681 *bar_window = bar->window;
5683 if (! NILP (bar->dragging))
5684 *part = scroll_bar_handle;
5685 else if (win_y < XINT (bar->start))
5686 *part = scroll_bar_above_handle;
5687 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5688 *part = scroll_bar_handle;
5689 else
5690 *part = scroll_bar_below_handle;
5692 XSETINT (*x, win_y);
5693 XSETINT (*y, top_range);
5695 f->mouse_moved = 0;
5696 last_mouse_scroll_bar = Qnil;
5698 *time = last_mouse_movement_time;
5702 /* The screen has been cleared so we may have changed foreground or
5703 background colors, and the scroll bars may need to be redrawn.
5704 Clear out the scroll bars, and ask for expose events, so we can
5705 redraw them. */
5707 void
5708 x_scroll_bar_clear (f)
5709 FRAME_PTR f;
5711 Lisp_Object bar;
5713 /* We can have scroll bars even if this is 0,
5714 if we just turned off scroll bar mode.
5715 But in that case we should not clear them. */
5716 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5717 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
5718 bar = XSCROLL_BAR (bar)->next)
5719 XSCROLL_BAR (bar)->redraw_needed_p = Qt;
5723 /***********************************************************************
5724 Tool-bars
5725 ***********************************************************************/
5726 #if USE_MAC_TOOLBAR
5728 /* In identifiers such as function/variable names, Emacs tool bar is
5729 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
5731 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
5732 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
5734 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
5735 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
5736 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5737 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
5738 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5739 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
5740 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
5742 static int mac_event_to_emacs_modifiers P_ ((EventRef));
5743 static void mac_handle_origin_change P_ ((struct frame *));
5744 static OSStatus mac_handle_toolbar_command_event P_ ((EventHandlerCallRef,
5745 EventRef, void *));
5747 static void
5748 mac_move_window_with_gravity (f, win_gravity, left, top)
5749 struct frame *f;
5750 int win_gravity;
5751 short left, top;
5753 Rect inner, outer;
5755 mac_get_window_bounds (f, &inner, &outer);
5757 switch (win_gravity)
5759 case NorthWestGravity:
5760 case WestGravity:
5761 case SouthWestGravity:
5762 left += inner.left - outer.left;
5763 break;
5765 case NorthGravity:
5766 case CenterGravity:
5767 case SouthGravity:
5768 left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
5769 break;
5771 case NorthEastGravity:
5772 case EastGravity:
5773 case SouthEastGravity:
5774 left += inner.right - outer.right;
5775 break;
5778 switch (win_gravity)
5780 case NorthWestGravity:
5781 case NorthGravity:
5782 case NorthEastGravity:
5783 top += inner.top - outer.top;
5784 break;
5786 case WestGravity:
5787 case CenterGravity:
5788 case EastGravity:
5789 top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
5790 break;
5792 case SouthWestGravity:
5793 case SouthGravity:
5794 case SouthEastGravity:
5795 top += inner.bottom - outer.bottom;
5796 break;
5799 MoveWindow (FRAME_MAC_WINDOW (f), left, top, false);
5802 static void
5803 mac_get_window_origin_with_gravity (f, win_gravity, left, top)
5804 struct frame *f;
5805 int win_gravity;
5806 short *left, *top;
5808 Rect inner, outer;
5810 mac_get_window_bounds (f, &inner, &outer);
5812 switch (win_gravity)
5814 case NorthWestGravity:
5815 case WestGravity:
5816 case SouthWestGravity:
5817 *left = outer.left;
5818 break;
5820 case NorthGravity:
5821 case CenterGravity:
5822 case SouthGravity:
5823 *left = outer.left + ((outer.right - outer.left)
5824 - (inner.right - inner.left)) / 2;
5825 break;
5827 case NorthEastGravity:
5828 case EastGravity:
5829 case SouthEastGravity:
5830 *left = outer.right - (inner.right - inner.left);
5831 break;
5834 switch (win_gravity)
5836 case NorthWestGravity:
5837 case NorthGravity:
5838 case NorthEastGravity:
5839 *top = outer.top;
5840 break;
5842 case WestGravity:
5843 case CenterGravity:
5844 case EastGravity:
5845 *top = outer.top + ((outer.bottom - outer.top)
5846 - (inner.bottom - inner.top)) / 2;
5847 break;
5849 case SouthWestGravity:
5850 case SouthGravity:
5851 case SouthEastGravity:
5852 *top = outer.bottom - (inner.bottom - inner.top);
5853 break;
5857 static OSStatus
5858 mac_handle_toolbar_event (next_handler, event, data)
5859 EventHandlerCallRef next_handler;
5860 EventRef event;
5861 void *data;
5863 OSStatus err, result = eventNotHandledErr;
5865 switch (GetEventKind (event))
5867 case kEventToolbarGetDefaultIdentifiers:
5868 result = noErr;
5869 break;
5871 case kEventToolbarGetAllowedIdentifiers:
5873 CFMutableArrayRef array;
5875 GetEventParameter (event, kEventParamMutableArray,
5876 typeCFMutableArrayRef, NULL,
5877 sizeof (CFMutableArrayRef), NULL, &array);
5878 CFArrayAppendValue (array, TOOLBAR_ICON_ITEM_IDENTIFIER);
5879 result = noErr;
5881 break;
5883 case kEventToolbarCreateItemWithIdentifier:
5885 CFStringRef identifier;
5886 HIToolbarItemRef item = NULL;
5888 GetEventParameter (event, kEventParamToolbarItemIdentifier,
5889 typeCFStringRef, NULL,
5890 sizeof (CFStringRef), NULL, &identifier);
5892 if (CFStringCompare (identifier, TOOLBAR_ICON_ITEM_IDENTIFIER, 0)
5893 == kCFCompareEqualTo)
5894 HIToolbarItemCreate (identifier,
5895 kHIToolbarItemAllowDuplicates
5896 | kHIToolbarItemCantBeRemoved, &item);
5898 if (item)
5900 SetEventParameter (event, kEventParamToolbarItem,
5901 typeHIToolbarItemRef,
5902 sizeof (HIToolbarItemRef), &item);
5903 result = noErr;
5906 break;
5908 default:
5909 abort ();
5912 return result;
5915 static CGImageRef
5916 mac_image_spec_to_cg_image (f, image)
5917 struct frame *f;
5918 Lisp_Object image;
5920 if (!valid_image_p (image))
5921 return NULL;
5922 else
5924 int img_id = lookup_image (f, image);
5925 struct image *img = IMAGE_FROM_ID (f, img_id);
5927 prepare_image_for_display (f, img);
5929 return img->data.ptr_val;
5933 /* Create a tool bar for frame F. */
5935 static OSStatus
5936 mac_create_frame_tool_bar (f)
5937 FRAME_PTR f;
5939 OSStatus err;
5940 HIToolbarRef toolbar;
5942 err = HIToolbarCreate (TOOLBAR_IDENTIFIER, kHIToolbarNoAttributes,
5943 &toolbar);
5944 if (err == noErr)
5946 static const EventTypeSpec specs[] =
5947 {{kEventClassToolbar, kEventToolbarGetDefaultIdentifiers},
5948 {kEventClassToolbar, kEventToolbarGetAllowedIdentifiers},
5949 {kEventClassToolbar, kEventToolbarCreateItemWithIdentifier}};
5951 err = InstallEventHandler (HIObjectGetEventTarget (toolbar),
5952 mac_handle_toolbar_event,
5953 GetEventTypeCount (specs), specs,
5954 f, NULL);
5957 if (err == noErr)
5958 err = HIToolbarSetDisplayMode (toolbar, kHIToolbarDisplayModeIconOnly);
5959 if (err == noErr)
5961 static const EventTypeSpec specs[] =
5962 {{kEventClassCommand, kEventCommandProcess}};
5964 err = InstallWindowEventHandler (FRAME_MAC_WINDOW (f),
5965 mac_handle_toolbar_command_event,
5966 GetEventTypeCount (specs),
5967 specs, f, NULL);
5969 if (err == noErr)
5970 err = SetWindowToolbar (FRAME_MAC_WINDOW (f), toolbar);
5972 if (toolbar)
5973 CFRelease (toolbar);
5975 return err;
5978 /* Update the tool bar for frame F. Add new buttons and remove old. */
5980 void
5981 update_frame_tool_bar (f)
5982 FRAME_PTR f;
5984 HIToolbarRef toolbar = NULL;
5985 short left, top;
5986 CFArrayRef old_items = NULL;
5987 CFIndex old_count;
5988 int i, pos, win_gravity = f->output_data.mac->toolbar_win_gravity;
5989 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5991 BLOCK_INPUT;
5993 GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
5994 if (toolbar == NULL)
5996 mac_create_frame_tool_bar (f);
5997 GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
5998 if (toolbar == NULL)
5999 goto out;
6000 if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
6001 mac_get_window_origin_with_gravity (f, win_gravity, &left, &top);
6004 HIToolbarCopyItems (toolbar, &old_items);
6005 if (old_items == NULL)
6006 goto out;
6008 old_count = CFArrayGetCount (old_items);
6009 pos = 0;
6010 for (i = 0; i < f->n_tool_bar_items; ++i)
6012 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
6014 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
6015 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
6016 int idx;
6017 Lisp_Object image;
6018 CGImageRef cg_image;
6019 CFStringRef label;
6020 HIToolbarItemRef item;
6022 /* If image is a vector, choose the image according to the
6023 button state. */
6024 image = PROP (TOOL_BAR_ITEM_IMAGES);
6025 if (VECTORP (image))
6027 if (enabled_p)
6028 idx = (selected_p
6029 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6030 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
6031 else
6032 idx = (selected_p
6033 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6034 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
6036 xassert (ASIZE (image) >= idx);
6037 image = AREF (image, idx);
6039 else
6040 idx = -1;
6042 cg_image = mac_image_spec_to_cg_image (f, image);
6043 /* Ignore invalid image specifications. */
6044 if (cg_image == NULL)
6045 continue;
6047 label = cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION));
6048 if (label == NULL)
6049 label = CFSTR ("");
6051 if (pos < old_count)
6053 CGImageRef old_cg_image = NULL;
6054 CFStringRef old_label = NULL;
6055 Boolean old_enabled_p;
6057 item = (HIToolbarItemRef) CFArrayGetValueAtIndex (old_items, pos);
6059 HIToolbarItemCopyImage (item, &old_cg_image);
6060 if (cg_image != old_cg_image)
6061 HIToolbarItemSetImage (item, cg_image);
6062 CGImageRelease (old_cg_image);
6064 HIToolbarItemCopyLabel (item, &old_label);
6065 if (CFStringCompare (label, old_label, 0) != kCFCompareEqualTo)
6066 HIToolbarItemSetLabel (item, label);
6067 CFRelease (old_label);
6069 old_enabled_p = HIToolbarItemIsEnabled (item);
6070 if ((enabled_p || idx >= 0) != old_enabled_p)
6071 HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
6073 else
6075 item = NULL;
6076 HIToolbarCreateItemWithIdentifier (toolbar,
6077 TOOLBAR_ICON_ITEM_IDENTIFIER,
6078 NULL, &item);
6079 if (item)
6081 HIToolbarItemSetImage (item, cg_image);
6082 HIToolbarItemSetLabel (item, label);
6083 HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
6084 HIToolbarAppendItem (toolbar, item);
6085 CFRelease (item);
6089 CFRelease (label);
6090 if (item)
6092 HIToolbarItemSetCommandID (item, TOOLBAR_ITEM_MAKE_COMMAND_ID (i));
6093 pos++;
6097 CFRelease (old_items);
6099 while (pos < old_count)
6100 HIToolbarRemoveItemAtIndex (toolbar, --old_count);
6102 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), true,
6103 !win_gravity && f == mac_focus_frame (dpyinfo));
6104 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
6105 toolbar visibility change. */
6106 mac_handle_origin_change (f);
6107 if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
6109 mac_move_window_with_gravity (f, win_gravity, left, top);
6110 /* If the title bar is completely outside the screen, adjust the
6111 position. */
6112 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
6113 kWindowConstrainMoveRegardlessOfFit
6114 | kWindowConstrainAllowPartial, NULL, NULL);
6115 f->output_data.mac->toolbar_win_gravity = 0;
6118 out:
6119 UNBLOCK_INPUT;
6122 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
6123 doesn't deallocate the resources. */
6125 void
6126 free_frame_tool_bar (f)
6127 FRAME_PTR f;
6129 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f)))
6131 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6133 BLOCK_INPUT;
6134 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), false,
6135 (NILP (find_symbol_value
6136 (intern ("frame-notice-user-settings")))
6137 && f == mac_focus_frame (dpyinfo)));
6138 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
6139 on toolbar visibility change. */
6140 mac_handle_origin_change (f);
6141 UNBLOCK_INPUT;
6145 static void
6146 mac_tool_bar_note_mouse_movement (f, event)
6147 struct frame *f;
6148 EventRef event;
6150 OSStatus err;
6151 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6152 int mouse_down_p;
6153 WindowRef window;
6154 WindowPartCode part_code;
6155 HIViewRef item_view;
6156 UInt32 command_id;
6158 mouse_down_p = (dpyinfo->grabbed
6159 && f == last_mouse_frame
6160 && FRAME_LIVE_P (f));
6161 if (mouse_down_p)
6162 return;
6164 err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef, NULL,
6165 sizeof (WindowRef), NULL, &window);
6166 if (err != noErr || window != FRAME_MAC_WINDOW (f))
6167 return;
6169 err = GetEventParameter (event, kEventParamWindowPartCode,
6170 typeWindowPartCode, NULL,
6171 sizeof (WindowPartCode), NULL, &part_code);
6172 if (err != noErr || part_code != inStructure)
6173 return;
6175 err = HIViewGetViewForMouseEvent (HIViewGetRoot (window), event, &item_view);
6176 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
6177 toolbar item view seems to have the same command ID with that of
6178 the toolbar item. */
6179 if (err == noErr)
6180 err = GetControlCommandID (item_view, &command_id);
6181 if (err == noErr && TOOLBAR_ITEM_COMMAND_ID_P (command_id))
6183 int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id);
6185 if (i < f->n_tool_bar_items)
6187 HIRect bounds;
6188 HIViewRef content_view;
6190 err = HIViewGetBounds (item_view, &bounds);
6191 if (err == noErr)
6192 err = HIViewFindByID (HIViewGetRoot (window),
6193 kHIViewWindowContentID, &content_view);
6194 if (err == noErr)
6195 err = HIViewConvertRect (&bounds, item_view, content_view);
6196 if (err == noErr)
6197 SetRect (&last_mouse_glyph,
6198 CGRectGetMinX (bounds), CGRectGetMinY (bounds),
6199 CGRectGetMaxX (bounds), CGRectGetMaxY (bounds));
6201 help_echo_object = help_echo_window = Qnil;
6202 help_echo_pos = -1;
6203 help_echo_string = PROP (TOOL_BAR_ITEM_HELP);
6204 if (NILP (help_echo_string))
6205 help_echo_string = PROP (TOOL_BAR_ITEM_CAPTION);
6210 static OSStatus
6211 mac_handle_toolbar_command_event (next_handler, event, data)
6212 EventHandlerCallRef next_handler;
6213 EventRef event;
6214 void *data;
6216 OSStatus err, result = eventNotHandledErr;
6217 struct frame *f = (struct frame *) data;
6218 HICommand command;
6220 err = GetEventParameter (event, kEventParamDirectObject,
6221 typeHICommand, NULL,
6222 sizeof (HICommand), NULL, &command);
6223 if (err != noErr)
6224 return result;
6226 switch (GetEventKind (event))
6228 case kEventCommandProcess:
6229 if (!TOOLBAR_ITEM_COMMAND_ID_P (command.commandID))
6230 result = CallNextEventHandler (next_handler, event);
6231 else
6233 int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command.commandID);
6235 if (i < f->n_tool_bar_items
6236 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)))
6238 Lisp_Object frame;
6239 struct input_event buf;
6241 EVENT_INIT (buf);
6243 XSETFRAME (frame, f);
6244 buf.kind = TOOL_BAR_EVENT;
6245 buf.frame_or_window = frame;
6246 buf.arg = frame;
6247 kbd_buffer_store_event (&buf);
6249 buf.kind = TOOL_BAR_EVENT;
6250 buf.frame_or_window = frame;
6251 buf.arg = PROP (TOOL_BAR_ITEM_KEY);
6252 buf.modifiers = mac_event_to_emacs_modifiers (event);
6253 kbd_buffer_store_event (&buf);
6255 result = noErr;
6258 break;
6260 default:
6261 abort ();
6263 #undef PROP
6265 return result;
6267 #endif /* USE_MAC_TOOLBAR */
6270 /***********************************************************************
6271 Text Cursor
6272 ***********************************************************************/
6274 /* Set clipping for output in glyph row ROW. W is the window in which
6275 we operate. GC is the graphics context to set clipping in.
6277 ROW may be a text row or, e.g., a mode line. Text rows must be
6278 clipped to the interior of the window dedicated to text display,
6279 mode lines must be clipped to the whole window. */
6281 static void
6282 x_clip_to_row (w, row, area, gc)
6283 struct window *w;
6284 struct glyph_row *row;
6285 int area;
6286 GC gc;
6288 struct frame *f = XFRAME (WINDOW_FRAME (w));
6289 Rect clip_rect;
6290 int window_x, window_y, window_width;
6292 window_box (w, area, &window_x, &window_y, &window_width, 0);
6294 clip_rect.left = window_x;
6295 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
6296 clip_rect.top = max (clip_rect.top, window_y);
6297 clip_rect.right = clip_rect.left + window_width;
6298 clip_rect.bottom = clip_rect.top + row->visible_height;
6300 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
6304 /* Draw a hollow box cursor on window W in glyph row ROW. */
6306 static void
6307 x_draw_hollow_cursor (w, row)
6308 struct window *w;
6309 struct glyph_row *row;
6311 struct frame *f = XFRAME (WINDOW_FRAME (w));
6312 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6313 Display *dpy = FRAME_MAC_DISPLAY (f);
6314 int x, y, wd, h;
6315 XGCValues xgcv;
6316 struct glyph *cursor_glyph;
6317 GC gc;
6319 /* Get the glyph the cursor is on. If we can't tell because
6320 the current matrix is invalid or such, give up. */
6321 cursor_glyph = get_phys_cursor_glyph (w);
6322 if (cursor_glyph == NULL)
6323 return;
6325 /* Compute frame-relative coordinates for phys cursor. */
6326 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
6327 wd = w->phys_cursor_width;
6329 /* The foreground of cursor_gc is typically the same as the normal
6330 background color, which can cause the cursor box to be invisible. */
6331 xgcv.foreground = f->output_data.mac->cursor_pixel;
6332 if (dpyinfo->scratch_cursor_gc)
6333 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
6334 else
6335 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
6336 GCForeground, &xgcv);
6337 gc = dpyinfo->scratch_cursor_gc;
6339 /* Set clipping, draw the rectangle, and reset clipping again. */
6340 x_clip_to_row (w, row, TEXT_AREA, gc);
6341 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
6342 mac_reset_clip_rectangles (dpy, gc);
6346 /* Draw a bar cursor on window W in glyph row ROW.
6348 Implementation note: One would like to draw a bar cursor with an
6349 angle equal to the one given by the font property XA_ITALIC_ANGLE.
6350 Unfortunately, I didn't find a font yet that has this property set.
6351 --gerd. */
6353 static void
6354 x_draw_bar_cursor (w, row, width, kind)
6355 struct window *w;
6356 struct glyph_row *row;
6357 int width;
6358 enum text_cursor_kinds kind;
6360 struct frame *f = XFRAME (w->frame);
6361 struct glyph *cursor_glyph;
6363 /* If cursor is out of bounds, don't draw garbage. This can happen
6364 in mini-buffer windows when switching between echo area glyphs
6365 and mini-buffer. */
6366 cursor_glyph = get_phys_cursor_glyph (w);
6367 if (cursor_glyph == NULL)
6368 return;
6370 /* If on an image, draw like a normal cursor. That's usually better
6371 visible than drawing a bar, esp. if the image is large so that
6372 the bar might not be in the window. */
6373 if (cursor_glyph->type == IMAGE_GLYPH)
6375 struct glyph_row *row;
6376 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
6377 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
6379 else
6381 Display *dpy = FRAME_MAC_DISPLAY (f);
6382 Window window = FRAME_MAC_WINDOW (f);
6383 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
6384 unsigned long mask = GCForeground | GCBackground;
6385 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
6386 XGCValues xgcv;
6388 /* If the glyph's background equals the color we normally draw
6389 the bar cursor in, the bar cursor in its normal color is
6390 invisible. Use the glyph's foreground color instead in this
6391 case, on the assumption that the glyph's colors are chosen so
6392 that the glyph is legible. */
6393 if (face->background == f->output_data.mac->cursor_pixel)
6394 xgcv.background = xgcv.foreground = face->foreground;
6395 else
6396 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
6398 if (gc)
6399 XChangeGC (dpy, gc, mask, &xgcv);
6400 else
6402 gc = XCreateGC (dpy, window, mask, &xgcv);
6403 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
6406 if (width < 0)
6407 width = FRAME_CURSOR_WIDTH (f);
6408 width = min (cursor_glyph->pixel_width, width);
6410 w->phys_cursor_width = width;
6411 x_clip_to_row (w, row, TEXT_AREA, gc);
6413 if (kind == BAR_CURSOR)
6414 mac_fill_rectangle (f, gc,
6415 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
6416 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
6417 width, row->height);
6418 else
6419 mac_fill_rectangle (f, gc,
6420 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
6421 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
6422 row->height - width),
6423 cursor_glyph->pixel_width,
6424 width);
6426 mac_reset_clip_rectangles (dpy, gc);
6431 /* RIF: Define cursor CURSOR on frame F. */
6433 static void
6434 mac_define_frame_cursor (f, cursor)
6435 struct frame *f;
6436 Cursor cursor;
6438 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6440 if (dpyinfo->x_focus_frame == f)
6441 SetThemeCursor (cursor);
6445 /* RIF: Clear area on frame F. */
6447 static void
6448 mac_clear_frame_area (f, x, y, width, height)
6449 struct frame *f;
6450 int x, y, width, height;
6452 mac_clear_area (f, x, y, width, height);
6456 /* RIF: Draw cursor on window W. */
6458 static void
6459 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
6460 struct window *w;
6461 struct glyph_row *glyph_row;
6462 int x, y;
6463 int cursor_type, cursor_width;
6464 int on_p, active_p;
6466 if (on_p)
6468 w->phys_cursor_type = cursor_type;
6469 w->phys_cursor_on_p = 1;
6471 if (glyph_row->exact_window_width_line_p
6472 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
6474 glyph_row->cursor_in_fringe_p = 1;
6475 draw_fringe_bitmap (w, glyph_row, 0);
6477 else
6478 switch (cursor_type)
6480 case HOLLOW_BOX_CURSOR:
6481 x_draw_hollow_cursor (w, glyph_row);
6482 break;
6484 case FILLED_BOX_CURSOR:
6485 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
6486 break;
6488 case BAR_CURSOR:
6489 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
6490 break;
6492 case HBAR_CURSOR:
6493 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
6494 break;
6496 case NO_CURSOR:
6497 w->phys_cursor_width = 0;
6498 break;
6500 default:
6501 abort ();
6507 /* Icons. */
6509 #if 0 /* MAC_TODO: no icon support yet. */
6511 x_bitmap_icon (f, icon)
6512 struct frame *f;
6513 Lisp_Object icon;
6515 HANDLE hicon;
6517 if (FRAME_W32_WINDOW (f) == 0)
6518 return 1;
6520 if (NILP (icon))
6521 hicon = LoadIcon (hinst, EMACS_CLASS);
6522 else if (STRINGP (icon))
6523 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
6524 LR_DEFAULTSIZE | LR_LOADFROMFILE);
6525 else if (SYMBOLP (icon))
6527 LPCTSTR name;
6529 if (EQ (icon, intern ("application")))
6530 name = (LPCTSTR) IDI_APPLICATION;
6531 else if (EQ (icon, intern ("hand")))
6532 name = (LPCTSTR) IDI_HAND;
6533 else if (EQ (icon, intern ("question")))
6534 name = (LPCTSTR) IDI_QUESTION;
6535 else if (EQ (icon, intern ("exclamation")))
6536 name = (LPCTSTR) IDI_EXCLAMATION;
6537 else if (EQ (icon, intern ("asterisk")))
6538 name = (LPCTSTR) IDI_ASTERISK;
6539 else if (EQ (icon, intern ("winlogo")))
6540 name = (LPCTSTR) IDI_WINLOGO;
6541 else
6542 return 1;
6544 hicon = LoadIcon (NULL, name);
6546 else
6547 return 1;
6549 if (hicon == NULL)
6550 return 1;
6552 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
6553 (LPARAM) hicon);
6555 return 0;
6557 #endif /* MAC_TODO */
6559 /************************************************************************
6560 Handling X errors
6561 ************************************************************************/
6563 /* Display Error Handling functions not used on W32. Listing them here
6564 helps diff stay in step when comparing w32term.c with xterm.c.
6566 x_error_catcher (display, error)
6567 x_catch_errors (dpy)
6568 x_catch_errors_unwind (old_val)
6569 x_check_errors (dpy, format)
6570 x_had_errors_p (dpy)
6571 x_clear_errors (dpy)
6572 x_uncatch_errors (dpy, count)
6573 x_trace_wire ()
6574 x_connection_signal (signalnum)
6575 x_connection_closed (dpy, error_message)
6576 x_error_quitter (display, error)
6577 x_error_handler (display, error)
6578 x_io_error_quitter (display)
6583 /* Changing the font of the frame. */
6585 /* Give frame F the font named FONTNAME as its default font, and
6586 return the full name of that font. FONTNAME may be a wildcard
6587 pattern; in that case, we choose some font that fits the pattern.
6588 The return value shows which font we chose. */
6590 Lisp_Object
6591 x_new_font (f, fontname)
6592 struct frame *f;
6593 register char *fontname;
6595 struct font_info *fontp
6596 = FS_LOAD_FONT (f, 0, fontname, -1);
6598 if (!fontp)
6599 return Qnil;
6601 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
6602 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
6603 FRAME_FONTSET (f) = -1;
6605 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
6606 FRAME_SPACE_WIDTH (f) = fontp->space_width;
6607 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
6609 compute_fringe_widths (f, 1);
6611 /* Compute the scroll bar width in character columns. */
6612 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
6614 int wid = FRAME_COLUMN_WIDTH (f);
6615 FRAME_CONFIG_SCROLL_BAR_COLS (f)
6616 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
6618 else
6620 int wid = FRAME_COLUMN_WIDTH (f);
6621 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
6624 /* Now make the frame display the given font. */
6625 if (FRAME_MAC_WINDOW (f) != 0)
6627 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
6628 FRAME_FONT (f));
6629 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
6630 FRAME_FONT (f));
6631 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
6632 FRAME_FONT (f));
6634 /* Don't change the size of a tip frame; there's no point in
6635 doing it because it's done in Fx_show_tip, and it leads to
6636 problems because the tip frame has no widget. */
6637 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
6638 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
6641 return build_string (fontp->full_name);
6644 /* Give frame F the fontset named FONTSETNAME as its default font, and
6645 return the full name of that fontset. FONTSETNAME may be a wildcard
6646 pattern; in that case, we choose some fontset that fits the pattern.
6647 The return value shows which fontset we chose. */
6649 Lisp_Object
6650 x_new_fontset (f, fontsetname)
6651 struct frame *f;
6652 char *fontsetname;
6654 int fontset = fs_query_fontset (build_string (fontsetname), 0);
6655 Lisp_Object result;
6657 if (fontset < 0)
6658 return Qnil;
6660 if (FRAME_FONTSET (f) == fontset)
6661 /* This fontset is already set in frame F. There's nothing more
6662 to do. */
6663 return fontset_name (fontset);
6665 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
6667 if (!STRINGP (result))
6668 /* Can't load ASCII font. */
6669 return Qnil;
6671 /* Since x_new_font doesn't update any fontset information, do it now. */
6672 FRAME_FONTSET (f) = fontset;
6674 return build_string (fontsetname);
6678 /***********************************************************************
6679 TODO: W32 Input Methods
6680 ***********************************************************************/
6681 /* Listing missing functions from xterm.c helps diff stay in step.
6683 xim_destroy_callback (xim, client_data, call_data)
6684 xim_open_dpy (dpyinfo, resource_name)
6685 struct xim_inst_t
6686 xim_instantiate_callback (display, client_data, call_data)
6687 xim_initialize (dpyinfo, resource_name)
6688 xim_close_dpy (dpyinfo)
6693 void
6694 mac_get_window_bounds (f, inner, outer)
6695 struct frame *f;
6696 Rect *inner, *outer;
6698 #if TARGET_API_MAC_CARBON
6699 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
6700 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
6701 #else /* not TARGET_API_MAC_CARBON */
6702 RgnHandle region = NewRgn ();
6704 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
6705 *inner = (*region)->rgnBBox;
6706 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
6707 *outer = (*region)->rgnBBox;
6708 DisposeRgn (region);
6709 #endif /* not TARGET_API_MAC_CARBON */
6712 static void
6713 mac_handle_origin_change (f)
6714 struct frame *f;
6716 x_real_positions (f, &f->left_pos, &f->top_pos);
6719 static void
6720 mac_handle_size_change (f, pixelwidth, pixelheight)
6721 struct frame *f;
6722 int pixelwidth, pixelheight;
6724 int cols, rows;
6726 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
6727 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
6729 if (cols != FRAME_COLS (f)
6730 || rows != FRAME_LINES (f)
6731 || pixelwidth != FRAME_PIXEL_WIDTH (f)
6732 || pixelheight != FRAME_PIXEL_HEIGHT (f))
6734 /* We pass 1 for DELAY since we can't run Lisp code inside of
6735 a BLOCK_INPUT. */
6736 change_frame_size (f, rows, cols, 0, 1, 0);
6737 FRAME_PIXEL_WIDTH (f) = pixelwidth;
6738 FRAME_PIXEL_HEIGHT (f) = pixelheight;
6739 SET_FRAME_GARBAGED (f);
6741 /* If cursor was outside the new size, mark it as off. */
6742 mark_window_cursors_off (XWINDOW (f->root_window));
6744 /* Clear out any recollection of where the mouse highlighting
6745 was, since it might be in a place that's outside the new
6746 frame size. Actually checking whether it is outside is a
6747 pain in the neck, so don't try--just let the highlighting be
6748 done afresh with new size. */
6749 cancel_mouse_face (f);
6751 #if TARGET_API_MAC_CARBON
6752 if (f->output_data.mac->hourglass_control)
6754 #if USE_CG_DRAWING
6755 mac_prepare_for_quickdraw (f);
6756 #endif
6757 MoveControl (f->output_data.mac->hourglass_control,
6758 pixelwidth - HOURGLASS_WIDTH, 0);
6760 #endif
6765 /* Calculate the absolute position in frame F
6766 from its current recorded position values and gravity. */
6768 void
6769 x_calc_absolute_position (f)
6770 struct frame *f;
6772 int width_diff = 0, height_diff = 0;
6773 int flags = f->size_hint_flags;
6774 Rect inner, outer;
6776 /* We have nothing to do if the current position
6777 is already for the top-left corner. */
6778 if (! ((flags & XNegative) || (flags & YNegative)))
6779 return;
6781 /* Find the offsets of the outside upper-left corner of
6782 the inner window, with respect to the outer window. */
6783 BLOCK_INPUT;
6784 mac_get_window_bounds (f, &inner, &outer);
6785 UNBLOCK_INPUT;
6787 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
6788 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
6790 /* Treat negative positions as relative to the leftmost bottommost
6791 position that fits on the screen. */
6792 if (flags & XNegative)
6793 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
6794 - width_diff
6795 - FRAME_PIXEL_WIDTH (f)
6796 + f->left_pos);
6798 if (flags & YNegative)
6799 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
6800 - height_diff
6801 - FRAME_PIXEL_HEIGHT (f)
6802 + f->top_pos);
6804 /* The left_pos and top_pos
6805 are now relative to the top and left screen edges,
6806 so the flags should correspond. */
6807 f->size_hint_flags &= ~ (XNegative | YNegative);
6810 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6811 to really change the position, and 0 when calling from
6812 x_make_frame_visible (in that case, XOFF and YOFF are the current
6813 position values). It is -1 when calling from x_set_frame_parameters,
6814 which means, do adjust for borders but don't change the gravity. */
6816 void
6817 x_set_offset (f, xoff, yoff, change_gravity)
6818 struct frame *f;
6819 register int xoff, yoff;
6820 int change_gravity;
6822 if (change_gravity > 0)
6824 f->top_pos = yoff;
6825 f->left_pos = xoff;
6826 f->size_hint_flags &= ~ (XNegative | YNegative);
6827 if (xoff < 0)
6828 f->size_hint_flags |= XNegative;
6829 if (yoff < 0)
6830 f->size_hint_flags |= YNegative;
6831 f->win_gravity = NorthWestGravity;
6833 x_calc_absolute_position (f);
6835 BLOCK_INPUT;
6836 x_wm_set_size_hint (f, (long) 0, 0);
6838 #if TARGET_API_MAC_CARBON
6839 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
6840 /* If the title bar is completely outside the screen, adjust the
6841 position. */
6842 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
6843 kWindowConstrainMoveRegardlessOfFit
6844 | kWindowConstrainAllowPartial, NULL, NULL);
6845 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
6846 mac_handle_origin_change (f);
6847 #else
6849 Rect inner, outer, screen_rect, dummy;
6850 RgnHandle region = NewRgn ();
6852 mac_get_window_bounds (f, &inner, &outer);
6853 f->x_pixels_diff = inner.left - outer.left;
6854 f->y_pixels_diff = inner.top - outer.top;
6855 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6856 f->top_pos + f->y_pixels_diff, false);
6858 /* If the title bar is completely outside the screen, adjust the
6859 position. The variable `outer' holds the title bar rectangle.
6860 The variable `inner' holds slightly smaller one than `outer',
6861 so that the calculation of overlapping may not become too
6862 strict. */
6863 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
6864 outer = (*region)->rgnBBox;
6865 DisposeRgn (region);
6866 inner = outer;
6867 InsetRect (&inner, 8, 8);
6868 screen_rect = qd.screenBits.bounds;
6869 screen_rect.top += GetMBarHeight ();
6871 if (!SectRect (&inner, &screen_rect, &dummy))
6873 if (inner.right <= screen_rect.left)
6874 f->left_pos = screen_rect.left;
6875 else if (inner.left >= screen_rect.right)
6876 f->left_pos = screen_rect.right - (outer.right - outer.left);
6878 if (inner.bottom <= screen_rect.top)
6879 f->top_pos = screen_rect.top;
6880 else if (inner.top >= screen_rect.bottom)
6881 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
6883 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6884 f->top_pos + f->y_pixels_diff, false);
6887 #endif
6889 UNBLOCK_INPUT;
6892 /* Call this to change the size of frame F's x-window.
6893 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6894 for this size change and subsequent size changes.
6895 Otherwise we leave the window gravity unchanged. */
6897 void
6898 x_set_window_size (f, change_gravity, cols, rows)
6899 struct frame *f;
6900 int change_gravity;
6901 int cols, rows;
6903 int pixelwidth, pixelheight;
6905 BLOCK_INPUT;
6907 check_frame_size (f, &rows, &cols);
6908 f->scroll_bar_actual_width
6909 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
6911 compute_fringe_widths (f, 0);
6913 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
6914 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
6916 f->win_gravity = NorthWestGravity;
6917 x_wm_set_size_hint (f, (long) 0, 0);
6919 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
6921 #if TARGET_API_MAC_CARBON
6922 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
6923 #endif
6924 mac_handle_size_change (f, pixelwidth, pixelheight);
6926 if (f->output_data.mac->internal_border_width
6927 != FRAME_INTERNAL_BORDER_WIDTH (f))
6929 mac_clear_window (f);
6930 f->output_data.mac->internal_border_width
6931 = FRAME_INTERNAL_BORDER_WIDTH (f);
6934 SET_FRAME_GARBAGED (f);
6936 UNBLOCK_INPUT;
6939 /* Mouse warping. */
6941 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
6943 void
6944 x_set_mouse_position (f, x, y)
6945 struct frame *f;
6946 int x, y;
6948 int pix_x, pix_y;
6950 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
6951 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
6953 if (pix_x < 0) pix_x = 0;
6954 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
6956 if (pix_y < 0) pix_y = 0;
6957 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
6959 x_set_mouse_pixel_position (f, pix_x, pix_y);
6962 void
6963 x_set_mouse_pixel_position (f, pix_x, pix_y)
6964 struct frame *f;
6965 int pix_x, pix_y;
6967 #ifdef MAC_OSX
6968 pix_x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
6969 pix_y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
6971 BLOCK_INPUT;
6972 CGWarpMouseCursorPosition (CGPointMake (pix_x, pix_y));
6973 UNBLOCK_INPUT;
6974 #else
6975 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6976 BLOCK_INPUT;
6978 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
6979 0, 0, 0, 0, pix_x, pix_y);
6980 UNBLOCK_INPUT;
6981 #endif
6982 #endif
6985 /* focus shifting, raising and lowering. */
6987 void
6988 x_focus_on_frame (f)
6989 struct frame *f;
6991 #if 0 /* This proves to be unpleasant. */
6992 x_raise_frame (f);
6993 #endif
6994 #if 0
6995 /* I don't think that the ICCCM allows programs to do things like this
6996 without the interaction of the window manager. Whatever you end up
6997 doing with this code, do it to x_unfocus_frame too. */
6998 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6999 RevertToPointerRoot, CurrentTime);
7000 #endif /* ! 0 */
7003 void
7004 x_unfocus_frame (f)
7005 struct frame *f;
7009 /* Raise frame F. */
7011 void
7012 x_raise_frame (f)
7013 struct frame *f;
7015 if (f->async_visible)
7017 BLOCK_INPUT;
7018 BringToFront (FRAME_MAC_WINDOW (f));
7019 UNBLOCK_INPUT;
7023 /* Lower frame F. */
7025 void
7026 x_lower_frame (f)
7027 struct frame *f;
7029 if (f->async_visible)
7031 BLOCK_INPUT;
7032 SendBehind (FRAME_MAC_WINDOW (f), NULL);
7033 UNBLOCK_INPUT;
7037 static void
7038 XTframe_raise_lower (f, raise_flag)
7039 FRAME_PTR f;
7040 int raise_flag;
7042 if (raise_flag)
7043 x_raise_frame (f);
7044 else
7045 x_lower_frame (f);
7048 /* Change of visibility. */
7050 static void
7051 mac_handle_visibility_change (f)
7052 struct frame *f;
7054 WindowRef wp = FRAME_MAC_WINDOW (f);
7055 int visible = 0, iconified = 0;
7056 struct input_event buf;
7058 if (IsWindowVisible (wp))
7060 if (IsWindowCollapsed (wp))
7061 iconified = 1;
7062 else
7063 visible = 1;
7066 if (!f->async_visible && visible)
7068 if (f->iconified)
7070 /* wait_reading_process_output will notice this and update
7071 the frame's display structures. If we were made
7072 invisible, we should not set garbaged, because that stops
7073 redrawing on Update events. */
7074 SET_FRAME_GARBAGED (f);
7076 EVENT_INIT (buf);
7077 buf.kind = DEICONIFY_EVENT;
7078 XSETFRAME (buf.frame_or_window, f);
7079 buf.arg = Qnil;
7080 kbd_buffer_store_event (&buf);
7082 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
7083 /* Force a redisplay sooner or later to update the
7084 frame titles in case this is the second frame. */
7085 record_asynch_buffer_change ();
7087 else if (f->async_visible && !visible)
7088 if (iconified)
7090 EVENT_INIT (buf);
7091 buf.kind = ICONIFY_EVENT;
7092 XSETFRAME (buf.frame_or_window, f);
7093 buf.arg = Qnil;
7094 kbd_buffer_store_event (&buf);
7097 f->async_visible = visible;
7098 f->async_iconified = iconified;
7101 /* This tries to wait until the frame is really visible.
7102 However, if the window manager asks the user where to position
7103 the frame, this will return before the user finishes doing that.
7104 The frame will not actually be visible at that time,
7105 but it will become visible later when the window manager
7106 finishes with it. */
7108 void
7109 x_make_frame_visible (f)
7110 struct frame *f;
7112 BLOCK_INPUT;
7114 if (! FRAME_VISIBLE_P (f))
7116 /* We test FRAME_GARBAGED_P here to make sure we don't
7117 call x_set_offset a second time
7118 if we get to x_make_frame_visible a second time
7119 before the window gets really visible. */
7120 if (! FRAME_ICONIFIED_P (f)
7121 && ! f->output_data.mac->asked_for_visible)
7122 x_set_offset (f, f->left_pos, f->top_pos, 0);
7124 f->output_data.mac->asked_for_visible = 1;
7126 CollapseWindow (FRAME_MAC_WINDOW (f), false);
7127 ShowWindow (FRAME_MAC_WINDOW (f));
7130 XFlush (FRAME_MAC_DISPLAY (f));
7132 /* Synchronize to ensure Emacs knows the frame is visible
7133 before we do anything else. We do this loop with input not blocked
7134 so that incoming events are handled. */
7136 Lisp_Object frame;
7137 int count;
7139 /* This must come after we set COUNT. */
7140 UNBLOCK_INPUT;
7142 XSETFRAME (frame, f);
7144 /* Wait until the frame is visible. Process X events until a
7145 MapNotify event has been seen, or until we think we won't get a
7146 MapNotify at all.. */
7147 for (count = input_signal_count + 10;
7148 input_signal_count < count && !FRAME_VISIBLE_P (f);)
7150 /* Force processing of queued events. */
7151 x_sync (f);
7153 /* Machines that do polling rather than SIGIO have been
7154 observed to go into a busy-wait here. So we'll fake an
7155 alarm signal to let the handler know that there's something
7156 to be read. We used to raise a real alarm, but it seems
7157 that the handler isn't always enabled here. This is
7158 probably a bug. */
7159 if (input_polling_used ())
7161 /* It could be confusing if a real alarm arrives while
7162 processing the fake one. Turn it off and let the
7163 handler reset it. */
7164 extern void poll_for_input_1 P_ ((void));
7165 int old_poll_suppress_count = poll_suppress_count;
7166 poll_suppress_count = 1;
7167 poll_for_input_1 ();
7168 poll_suppress_count = old_poll_suppress_count;
7171 /* See if a MapNotify event has been processed. */
7172 FRAME_SAMPLE_VISIBILITY (f);
7177 /* Change from mapped state to withdrawn state. */
7179 /* Make the frame visible (mapped and not iconified). */
7181 void
7182 x_make_frame_invisible (f)
7183 struct frame *f;
7185 /* A deactivate event does not occur when the last visible frame is
7186 made invisible. So if we clear the highlight here, it will not
7187 be rehighlighted when it is made visible. */
7188 #if 0
7189 /* Don't keep the highlight on an invisible frame. */
7190 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
7191 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
7192 #endif
7194 BLOCK_INPUT;
7196 #if !TARGET_API_MAC_CARBON
7197 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
7198 that the current position of the window is user-specified, rather than
7199 program-specified, so that when the window is mapped again, it will be
7200 placed at the same location, without forcing the user to position it
7201 by hand again (they have already done that once for this window.) */
7202 x_wm_set_size_hint (f, (long) 0, 1);
7203 #endif
7205 HideWindow (FRAME_MAC_WINDOW (f));
7207 UNBLOCK_INPUT;
7209 #if !TARGET_API_MAC_CARBON
7210 mac_handle_visibility_change (f);
7211 #endif
7214 /* Change window state from mapped to iconified. */
7216 void
7217 x_iconify_frame (f)
7218 struct frame *f;
7220 OSStatus err;
7222 /* A deactivate event does not occur when the last visible frame is
7223 iconified. So if we clear the highlight here, it will not be
7224 rehighlighted when it is deiconified. */
7225 #if 0
7226 /* Don't keep the highlight on an invisible frame. */
7227 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
7228 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
7229 #endif
7231 if (f->async_iconified)
7232 return;
7234 BLOCK_INPUT;
7236 FRAME_SAMPLE_VISIBILITY (f);
7238 if (! FRAME_VISIBLE_P (f))
7239 ShowWindow (FRAME_MAC_WINDOW (f));
7241 err = CollapseWindow (FRAME_MAC_WINDOW (f), true);
7243 UNBLOCK_INPUT;
7245 if (err != noErr)
7246 error ("Can't notify window manager of iconification");
7248 #if !TARGET_API_MAC_CARBON
7249 mac_handle_visibility_change (f);
7250 #endif
7254 /* Free X resources of frame F. */
7256 void
7257 x_free_frame_resources (f)
7258 struct frame *f;
7260 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7261 WindowRef wp = FRAME_MAC_WINDOW (f);
7263 BLOCK_INPUT;
7265 if (wp != tip_window)
7266 remove_window_handler (wp);
7268 #if USE_CG_DRAWING
7269 mac_prepare_for_quickdraw (f);
7270 #endif
7271 DisposeWindow (wp);
7272 if (wp == tip_window)
7273 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
7274 closed' event. So we reset tip_window here. */
7275 tip_window = NULL;
7277 free_frame_menubar (f);
7279 if (FRAME_FACE_CACHE (f))
7280 free_frame_faces (f);
7282 x_free_gcs (f);
7284 if (FRAME_SIZE_HINTS (f))
7285 xfree (FRAME_SIZE_HINTS (f));
7287 xfree (f->output_data.mac);
7288 f->output_data.mac = NULL;
7290 if (f == dpyinfo->x_focus_frame)
7292 dpyinfo->x_focus_frame = 0;
7293 #if USE_MAC_FONT_PANEL
7294 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
7295 #endif
7297 if (f == dpyinfo->x_focus_event_frame)
7298 dpyinfo->x_focus_event_frame = 0;
7299 if (f == dpyinfo->x_highlight_frame)
7300 dpyinfo->x_highlight_frame = 0;
7302 if (f == dpyinfo->mouse_face_mouse_frame)
7304 dpyinfo->mouse_face_beg_row
7305 = dpyinfo->mouse_face_beg_col = -1;
7306 dpyinfo->mouse_face_end_row
7307 = dpyinfo->mouse_face_end_col = -1;
7308 dpyinfo->mouse_face_window = Qnil;
7309 dpyinfo->mouse_face_deferred_gc = 0;
7310 dpyinfo->mouse_face_mouse_frame = 0;
7313 UNBLOCK_INPUT;
7317 /* Destroy the X window of frame F. */
7319 void
7320 x_destroy_window (f)
7321 struct frame *f;
7323 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7325 x_free_frame_resources (f);
7327 dpyinfo->reference_count--;
7331 /* Setting window manager hints. */
7333 /* Set the normal size hints for the window manager, for frame F.
7334 FLAGS is the flags word to use--or 0 meaning preserve the flags
7335 that the window now has.
7336 If USER_POSITION is nonzero, we set the USPosition
7337 flag (this is useful when FLAGS is 0). */
7338 void
7339 x_wm_set_size_hint (f, flags, user_position)
7340 struct frame *f;
7341 long flags;
7342 int user_position;
7344 int base_width, base_height, width_inc, height_inc;
7345 int min_rows = 0, min_cols = 0;
7346 XSizeHints *size_hints;
7348 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
7349 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
7350 width_inc = FRAME_COLUMN_WIDTH (f);
7351 height_inc = FRAME_LINE_HEIGHT (f);
7353 check_frame_size (f, &min_rows, &min_cols);
7355 size_hints = FRAME_SIZE_HINTS (f);
7356 if (size_hints == NULL)
7358 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
7359 bzero (size_hints, sizeof (XSizeHints));
7362 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
7363 size_hints->width_inc = width_inc;
7364 size_hints->height_inc = height_inc;
7365 size_hints->min_width = base_width + min_cols * width_inc;
7366 size_hints->min_height = base_height + min_rows * height_inc;
7367 size_hints->base_width = base_width;
7368 size_hints->base_height = base_height;
7370 if (flags)
7371 size_hints->flags = flags;
7372 else if (user_position)
7374 size_hints->flags &= ~ PPosition;
7375 size_hints->flags |= USPosition;
7379 #if 0 /* MAC_TODO: hide application instead of iconify? */
7380 /* Used for IconicState or NormalState */
7382 void
7383 x_wm_set_window_state (f, state)
7384 struct frame *f;
7385 int state;
7387 #ifdef USE_X_TOOLKIT
7388 Arg al[1];
7390 XtSetArg (al[0], XtNinitialState, state);
7391 XtSetValues (f->output_data.x->widget, al, 1);
7392 #else /* not USE_X_TOOLKIT */
7393 Window window = FRAME_X_WINDOW (f);
7395 f->output_data.x->wm_hints.flags |= StateHint;
7396 f->output_data.x->wm_hints.initial_state = state;
7398 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
7399 #endif /* not USE_X_TOOLKIT */
7402 void
7403 x_wm_set_icon_pixmap (f, pixmap_id)
7404 struct frame *f;
7405 int pixmap_id;
7407 Pixmap icon_pixmap;
7409 #ifndef USE_X_TOOLKIT
7410 Window window = FRAME_X_WINDOW (f);
7411 #endif
7413 if (pixmap_id > 0)
7415 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7416 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
7418 else
7420 /* It seems there is no way to turn off use of an icon pixmap.
7421 The following line does it, only if no icon has yet been created,
7422 for some window managers. But with mwm it crashes.
7423 Some people say it should clear the IconPixmapHint bit in this case,
7424 but that doesn't work, and the X consortium said it isn't the
7425 right thing at all. Since there is no way to win,
7426 best to explicitly give up. */
7427 #if 0
7428 f->output_data.x->wm_hints.icon_pixmap = None;
7429 #else
7430 return;
7431 #endif
7434 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
7437 Arg al[1];
7438 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
7439 XtSetValues (f->output_data.x->widget, al, 1);
7442 #else /* not USE_X_TOOLKIT */
7444 f->output_data.x->wm_hints.flags |= IconPixmapHint;
7445 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
7447 #endif /* not USE_X_TOOLKIT */
7450 #endif /* MAC_TODO */
7452 void
7453 x_wm_set_icon_position (f, icon_x, icon_y)
7454 struct frame *f;
7455 int icon_x, icon_y;
7457 #if 0 /* MAC_TODO: no icons on Mac */
7458 #ifdef USE_X_TOOLKIT
7459 Window window = XtWindow (f->output_data.x->widget);
7460 #else
7461 Window window = FRAME_X_WINDOW (f);
7462 #endif
7464 f->output_data.x->wm_hints.flags |= IconPositionHint;
7465 f->output_data.x->wm_hints.icon_x = icon_x;
7466 f->output_data.x->wm_hints.icon_y = icon_y;
7468 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
7469 #endif /* MAC_TODO */
7473 /***********************************************************************
7474 XLFD Pattern Match
7475 ***********************************************************************/
7477 /* An XLFD pattern is divided into blocks delimited by '*'. This
7478 structure holds information for each block. */
7479 struct xlfdpat_block
7481 /* Length of the pattern string in this block. Non-zero except for
7482 the first and the last blocks. */
7483 int len;
7485 /* Pattern string except the last character in this block. The last
7486 character is replaced with NUL in order to use it as a
7487 sentinel. */
7488 unsigned char *pattern;
7490 /* Last character of the pattern string. Must not be '?'. */
7491 unsigned char last_char;
7493 /* One of the tables for the Boyer-Moore string search. It
7494 specifies the number of positions to proceed for each character
7495 with which the match fails. */
7496 int skip[256];
7498 /* The skip value for the last character in the above `skip' is
7499 assigned to `infinity' in order to simplify a loop condition.
7500 The original value is saved here. */
7501 int last_char_skip;
7504 struct xlfdpat
7506 /* Normalized pattern string. "Normalized" means that capital
7507 letters are lowered, blocks are not empty except the first and
7508 the last ones, and trailing '?'s in a block that is not the last
7509 one are moved to the next one. The last character in each block
7510 is replaced with NUL. */
7511 unsigned char *buf;
7513 /* Number of characters except '*'s and trailing '?'s in the
7514 normalized pattern string. */
7515 int nchars;
7517 /* Number of trailing '?'s in the normalized pattern string. */
7518 int trailing_anychars;
7520 /* Number of blocks and information for each block. The latter is
7521 NULL if the pattern is exact (no '*' or '?' in it). */
7522 int nblocks;
7523 struct xlfdpat_block *blocks;
7526 static void
7527 xlfdpat_destroy (pat)
7528 struct xlfdpat *pat;
7530 if (pat)
7532 if (pat->buf)
7534 if (pat->blocks)
7535 xfree (pat->blocks);
7536 xfree (pat->buf);
7538 xfree (pat);
7542 static struct xlfdpat *
7543 xlfdpat_create (pattern)
7544 const char *pattern;
7546 struct xlfdpat *pat;
7547 int nblocks, i, skip;
7548 unsigned char last_char, *p, *q, *anychar_head;
7549 const unsigned char *ptr;
7550 struct xlfdpat_block *blk;
7552 pat = xmalloc (sizeof (struct xlfdpat));
7553 pat->buf = xmalloc (strlen (pattern) + 1);
7555 /* Normalize the pattern string and store it to `pat->buf'. */
7556 nblocks = 0;
7557 anychar_head = NULL;
7558 q = pat->buf;
7559 last_char = '\0';
7560 for (ptr = pattern; *ptr; ptr++)
7562 unsigned char c = *ptr;
7564 if (c == '*')
7565 if (last_char == '*')
7566 /* ...a** -> ...a* */
7567 continue;
7568 else
7570 if (last_char == '?')
7572 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
7573 /* ...*??* -> ...*?? */
7574 continue;
7575 else
7576 /* ...a??* -> ...a*?? */
7578 *anychar_head++ = '*';
7579 c = '?';
7582 nblocks++;
7584 else if (c == '?')
7586 if (last_char != '?')
7587 anychar_head = q;
7589 else
7590 /* On Mac OS X 10.3, tolower also converts non-ASCII
7591 characters for some locales. */
7592 if (isascii (c))
7593 c = tolower (c);
7595 *q++ = last_char = c;
7597 *q = '\0';
7598 nblocks++;
7599 pat->nblocks = nblocks;
7600 if (last_char != '?')
7601 pat->trailing_anychars = 0;
7602 else
7604 pat->trailing_anychars = q - anychar_head;
7605 q = anychar_head;
7607 pat->nchars = q - pat->buf - (nblocks - 1);
7609 if (anychar_head == NULL && nblocks == 1)
7611 /* The pattern is exact. */
7612 pat->blocks = NULL;
7613 return pat;
7616 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
7618 /* Divide the normalized pattern into blocks. */
7619 p = pat->buf;
7620 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
7622 blk->pattern = p;
7623 while (*p != '*')
7624 p++;
7625 blk->len = p - blk->pattern;
7626 p++;
7628 blk->pattern = p;
7629 blk->len = q - blk->pattern;
7631 /* Setup a table for the Boyer-Moore string search. */
7632 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
7633 if (blk->len != 0)
7635 blk->last_char = blk->pattern[blk->len - 1];
7636 blk->pattern[blk->len - 1] = '\0';
7638 for (skip = 1; skip < blk->len; skip++)
7639 if (blk->pattern[blk->len - skip - 1] == '?')
7640 break;
7642 for (i = 0; i < 256; i++)
7643 blk->skip[i] = skip;
7645 p = blk->pattern + (blk->len - skip);
7646 while (--skip > 0)
7647 blk->skip[*p++] = skip;
7649 blk->last_char_skip = blk->skip[blk->last_char];
7652 return pat;
7655 static INLINE int
7656 xlfdpat_exact_p (pat)
7657 struct xlfdpat *pat;
7659 return pat->blocks == NULL;
7662 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7663 that the pattern in *BLK matches with its prefix. Return NULL
7664 there is no such strings. STRING must be lowered in advance. */
7666 static const char *
7667 xlfdpat_block_match_1 (blk, string, start_max)
7668 struct xlfdpat_block *blk;
7669 const unsigned char *string;
7670 int start_max;
7672 int start, infinity;
7673 unsigned char *p;
7674 const unsigned char *s;
7676 xassert (blk->len > 0);
7677 xassert (start_max + blk->len <= strlen (string));
7678 xassert (blk->last_char != '?');
7680 /* See the comments in the function `boyer_moore' (search.c) for the
7681 use of `infinity'. */
7682 infinity = start_max + blk->len + 1;
7683 blk->skip[blk->last_char] = infinity;
7685 start = 0;
7688 /* Check the last character of the pattern. */
7689 s = string + blk->len - 1;
7692 start += blk->skip[*(s + start)];
7694 while (start <= start_max);
7696 if (start < infinity)
7697 /* Couldn't find the last character. */
7698 return NULL;
7700 /* No less than `infinity' means we could find the last
7701 character at `s[start - infinity]'. */
7702 start -= infinity;
7704 /* Check the remaining characters. We prefer making no-'?'
7705 cases faster because the use of '?' is really rare. */
7706 p = blk->pattern;
7707 s = string + start;
7710 while (*p++ == *s++)
7713 while (*(p - 1) == '?');
7715 if (*(p - 1) == '\0')
7716 /* Matched. */
7717 return string + start;
7719 /* Didn't match. */
7720 start += blk->last_char_skip;
7722 while (start <= start_max);
7724 return NULL;
7727 #define xlfdpat_block_match(b, s, m) \
7728 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7729 : xlfdpat_block_match_1 (b, s, m))
7731 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7732 matches with STRING. STRING must be lowered in advance. */
7734 static int
7735 xlfdpat_match (pat, string)
7736 struct xlfdpat *pat;
7737 const unsigned char *string;
7739 int str_len, nblocks, i, start_max;
7740 struct xlfdpat_block *blk;
7741 const unsigned char *s;
7743 xassert (pat->nblocks > 0);
7745 if (xlfdpat_exact_p (pat))
7746 return strcmp (pat->buf, string) == 0;
7748 /* The number of the characters in the string must not be smaller
7749 than that in the pattern. */
7750 str_len = strlen (string);
7751 if (str_len < pat->nchars + pat->trailing_anychars)
7752 return 0;
7754 /* Chop off the trailing '?'s. */
7755 str_len -= pat->trailing_anychars;
7757 /* The last block. When it is non-empty, it must match at the end
7758 of the string. */
7759 nblocks = pat->nblocks;
7760 blk = pat->blocks + (nblocks - 1);
7761 if (nblocks == 1)
7762 /* The last block is also the first one. */
7763 return (str_len == blk->len
7764 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
7765 else if (blk->len != 0)
7766 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
7767 return 0;
7769 /* The first block. When it is non-empty, it must match at the
7770 beginning of the string. */
7771 blk = pat->blocks;
7772 if (blk->len != 0)
7774 s = xlfdpat_block_match (blk, string, 0);
7775 if (s == NULL)
7776 return 0;
7777 string = s + blk->len;
7780 /* The rest of the blocks. */
7781 start_max = str_len - pat->nchars;
7782 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
7784 s = xlfdpat_block_match (blk, string, start_max);
7785 if (s == NULL)
7786 return 0;
7787 start_max -= s - string;
7788 string = s + blk->len;
7791 return 1;
7795 /***********************************************************************
7796 Fonts
7797 ***********************************************************************/
7799 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7801 struct font_info *
7802 x_get_font_info (f, font_idx)
7803 FRAME_PTR f;
7804 int font_idx;
7806 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
7809 /* the global font name table */
7810 static char **font_name_table = NULL;
7811 static int font_name_table_size = 0;
7812 static int font_name_count = 0;
7814 /* Alist linking font family names to Font Manager font family
7815 references (which can also be used as QuickDraw font IDs). We use
7816 an alist because hash tables are not ready when the terminal frame
7817 for Mac OS Classic is created. */
7818 static Lisp_Object fm_font_family_alist;
7819 #if USE_ATSUI
7820 /* Hash table linking font family names to ATSU font IDs. */
7821 static Lisp_Object atsu_font_id_hash;
7822 /* Alist linking Font Manager style to face attributes. */
7823 static Lisp_Object fm_style_face_attributes_alist;
7824 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
7825 #endif
7827 /* Alist linking character set strings to Mac text encoding and Emacs
7828 coding system. */
7829 static Lisp_Object Vmac_charset_info_alist;
7831 static Lisp_Object
7832 create_text_encoding_info_alist ()
7834 Lisp_Object result = Qnil, rest;
7836 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
7838 Lisp_Object charset_info = XCAR (rest);
7839 Lisp_Object charset, coding_system, text_encoding;
7840 Lisp_Object existing_info;
7842 if (!(CONSP (charset_info)
7843 && (charset = XCAR (charset_info),
7844 STRINGP (charset))
7845 && CONSP (XCDR (charset_info))
7846 && (text_encoding = XCAR (XCDR (charset_info)),
7847 INTEGERP (text_encoding))
7848 && CONSP (XCDR (XCDR (charset_info)))
7849 && (coding_system = XCAR (XCDR (XCDR (charset_info))),
7850 SYMBOLP (coding_system))))
7851 continue;
7853 existing_info = assq_no_quit (text_encoding, result);
7854 if (NILP (existing_info))
7855 result = Fcons (list3 (text_encoding, coding_system, charset),
7856 result);
7857 else
7858 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
7859 XSETCDR (XCDR (existing_info),
7860 Fcons (charset, XCDR (XCDR (existing_info))));
7863 return result;
7867 static void
7868 decode_mac_font_name (name, size, coding_system)
7869 char *name;
7870 int size;
7871 Lisp_Object coding_system;
7873 struct coding_system coding;
7874 char *buf, *p;
7876 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
7878 for (p = name; *p; p++)
7879 if (!isascii (*p) || iscntrl (*p))
7880 break;
7882 if (*p)
7884 setup_coding_system (coding_system, &coding);
7885 coding.src_multibyte = 0;
7886 coding.dst_multibyte = 1;
7887 coding.mode |= CODING_MODE_LAST_BLOCK;
7888 coding.composing = COMPOSITION_DISABLED;
7889 buf = (char *) alloca (size);
7891 decode_coding (&coding, name, buf, strlen (name), size - 1);
7892 bcopy (buf, name, coding.produced);
7893 name[coding.produced] = '\0';
7897 /* If there's just one occurrence of '-' in the family name, it is
7898 replaced with '_'. (More than one occurrence of '-' means a
7899 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7900 p = strchr (name, '-');
7901 if (p && strchr (p + 1, '-') == NULL)
7902 *p = '_';
7904 for (p = name; *p; p++)
7905 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7906 for some locales. */
7907 if (isascii (*p))
7908 *p = tolower (*p);
7912 static char *
7913 mac_to_x_fontname (name, size, style, charset)
7914 const char *name;
7915 int size;
7916 Style style;
7917 char *charset;
7919 Str31 foundry, cs;
7920 Str255 family;
7921 char xf[256], *result;
7922 unsigned char *p;
7924 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
7925 charset = cs;
7926 else
7928 strcpy(foundry, "Apple");
7929 strcpy(family, name);
7932 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7933 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
7934 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
7936 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
7937 sprintf (result, "-%s-%s-%s", foundry, family, xf);
7938 for (p = result; *p; p++)
7939 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7940 for some locales. */
7941 if (isascii (*p))
7942 *p = tolower (*p);
7943 return result;
7947 /* Parse fully-specified and instantiated X11 font spec XF, and store
7948 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7949 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7950 caller must allocate at least 256 and 32 bytes respectively. For
7951 ordinary Mac fonts, the value stored to FAMILY should just be their
7952 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7953 intlfonts collection contain their charset designation in their
7954 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7955 types of font names are handled accordingly. */
7957 const int kDefaultFontSize = 12;
7959 static int
7960 parse_x_font_name (xf, family, size, style, charset)
7961 const char *xf;
7962 char *family;
7963 int *size;
7964 Style *style;
7965 char *charset;
7967 Str31 foundry, weight;
7968 int point_size, avgwidth;
7969 char slant[2], *p;
7971 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7972 foundry, family, weight, slant, size,
7973 &point_size, &avgwidth, charset) != 8
7974 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7975 foundry, family, weight, slant, size,
7976 &point_size, &avgwidth, charset) != 8)
7977 return 0;
7979 if (*size == 0)
7981 if (point_size > 0)
7982 *size = point_size / 10;
7983 else if (avgwidth > 0)
7984 *size = avgwidth / 10;
7986 if (*size == 0)
7987 *size = kDefaultFontSize;
7989 *style = normal;
7990 if (strcmp (weight, "bold") == 0)
7991 *style |= bold;
7992 if (*slant == 'i')
7993 *style |= italic;
7995 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
7997 int foundry_len = strlen (foundry), family_len = strlen (family);
7999 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
8001 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
8002 but take overlap into account. */
8003 memmove (family + foundry_len + 1, family, family_len);
8004 memcpy (family, foundry, foundry_len);
8005 family[foundry_len] = '-';
8006 family[foundry_len + 1 + family_len] = '-';
8007 strcpy (family + foundry_len + 1 + family_len + 1, charset);
8009 else
8010 return 0;
8013 for (p = family; *p; p++)
8014 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
8015 for some locales. */
8016 if (isascii (*p))
8017 *p = tolower (*p);
8019 return 1;
8023 static void
8024 add_font_name_table_entry (char *font_name)
8026 if (font_name_table_size == 0)
8028 font_name_table_size = 256;
8029 font_name_table = (char **)
8030 xmalloc (font_name_table_size * sizeof (char *));
8032 else if (font_name_count + 1 >= font_name_table_size)
8034 font_name_table_size *= 2;
8035 font_name_table = (char **)
8036 xrealloc (font_name_table,
8037 font_name_table_size * sizeof (char *));
8040 font_name_table[font_name_count++] = font_name;
8043 static void
8044 add_mac_font_name (name, size, style, charset)
8045 const char *name;
8046 int size;
8047 Style style;
8048 const char *charset;
8050 if (size > 0)
8051 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
8052 else
8054 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
8055 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
8056 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
8057 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
8058 charset));
8062 #if USE_ATSUI
8063 static FMFontStyle
8064 fm_get_style_from_font (font)
8065 FMFont font;
8067 OSStatus err;
8068 FMFontStyle style = normal;
8069 ByteCount len;
8070 UInt16 mac_style;
8071 FMFontFamily font_family;
8072 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
8074 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
8075 some font (e.g., Optima) even if it is `bold'. */
8076 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
8077 sizeof (mac_style), &mac_style, &len);
8078 if (err == noErr
8079 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
8080 style = EndianU16_BtoN (mac_style);
8081 else
8082 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
8084 return style;
8087 static ATSUFontID
8088 atsu_find_font_from_family_name (family)
8089 const char *family;
8091 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
8092 unsigned hash_code;
8093 int i;
8094 Lisp_Object rest, best;
8095 FMFontStyle min_style, style;
8097 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
8098 &hash_code);
8099 if (i < 0)
8100 return kATSUInvalidFontID;
8102 rest = HASH_VALUE (h, i);
8103 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
8104 return cons_to_long (rest);
8106 rest = Fnreverse (rest);
8107 best = XCAR (rest);
8108 rest = XCDR (rest);
8109 if (!NILP (rest)
8110 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
8113 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
8114 if (style < min_style)
8116 best = XCAR (rest);
8117 if (style == normal)
8118 break;
8119 else
8120 min_style = style;
8122 rest = XCDR (rest);
8124 while (!NILP (rest));
8126 HASH_VALUE (h, i) = best;
8127 return cons_to_long (best);
8130 static Lisp_Object
8131 fm_style_to_face_attributes (fm_style)
8132 FMFontStyle fm_style;
8134 Lisp_Object tem;
8136 fm_style &= (bold | italic);
8137 tem = assq_no_quit (make_number (fm_style),
8138 fm_style_face_attributes_alist);
8139 if (!NILP (tem))
8140 return XCDR (tem);
8142 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
8143 QCslant, fm_style & italic ? Qitalic : Qnormal);
8144 fm_style_face_attributes_alist =
8145 Fcons (Fcons (make_number (fm_style), tem),
8146 fm_style_face_attributes_alist);
8148 return tem;
8151 static Lisp_Object
8152 atsu_find_font_family_name (font_id)
8153 ATSUFontID font_id;
8155 OSStatus err;
8156 ByteCount len;
8157 Lisp_Object family = Qnil;
8159 err = ATSUFindFontName (font_id, kFontFamilyName,
8160 kFontMacintoshPlatform, kFontNoScript,
8161 kFontNoLanguage, 0, NULL, &len, NULL);
8162 if (err == noErr)
8164 family = make_uninit_string (len);
8165 err = ATSUFindFontName (font_id, kFontFamilyName,
8166 kFontMacintoshPlatform, kFontNoScript,
8167 kFontNoLanguage, len, SDATA (family),
8168 NULL, NULL);
8170 if (err == noErr)
8171 decode_mac_font_name (SDATA (family), len + 1, Qnil);
8173 return family;
8176 Lisp_Object
8177 mac_atsu_font_face_attributes (font_id)
8178 ATSUFontID font_id;
8180 Lisp_Object family, style_attrs;
8182 family = atsu_find_font_family_name (font_id);
8183 if (NILP (family))
8184 return Qnil;
8185 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
8186 return Fcons (QCfamily, Fcons (family, style_attrs));
8188 #endif
8190 /* Sets up the table font_name_table to contain the list of all fonts
8191 in the system the first time the table is used so that the Resource
8192 Manager need not be accessed every time this information is
8193 needed. */
8195 static void
8196 init_font_name_table ()
8198 #if TARGET_API_MAC_CARBON
8199 FMFontFamilyIterator ffi;
8200 FMFontFamilyInstanceIterator ffii;
8201 FMFontFamily ff;
8202 Lisp_Object text_encoding_info_alist;
8203 struct gcpro gcpro1;
8205 text_encoding_info_alist = create_text_encoding_info_alist ();
8207 #if USE_ATSUI
8208 #if USE_CG_TEXT_DRAWING
8209 init_cg_text_anti_aliasing_threshold ();
8210 #endif
8211 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
8212 text_encoding_info_alist)))
8214 OSStatus err;
8215 struct Lisp_Hash_Table *h;
8216 unsigned hash_code;
8217 ItemCount nfonts, i;
8218 ATSUFontID *font_ids = NULL;
8219 Lisp_Object prev_family = Qnil;
8220 int j;
8222 atsu_font_id_hash =
8223 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
8224 make_float (DEFAULT_REHASH_SIZE),
8225 make_float (DEFAULT_REHASH_THRESHOLD),
8226 Qnil, Qnil, Qnil);
8227 h = XHASH_TABLE (atsu_font_id_hash);
8229 err = ATSUFontCount (&nfonts);
8230 if (err == noErr)
8232 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
8233 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
8235 if (err == noErr)
8236 for (i = 0; i < nfonts; i++)
8238 Lisp_Object family;
8240 family = atsu_find_font_family_name (font_ids[i]);
8241 if (NILP (family) || SREF (family, 0) == '.')
8242 continue;
8243 if (!NILP (Fequal (prev_family, family)))
8244 family = prev_family;
8245 else
8246 j = hash_lookup (h, family, &hash_code);
8247 if (j < 0)
8249 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
8250 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
8251 Qnil), hash_code);
8253 else if (EQ (prev_family, family))
8254 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
8255 HASH_VALUE (h, j));
8256 prev_family = family;
8258 if (font_ids)
8259 xfree (font_ids);
8261 #endif
8263 /* Create a dummy instance iterator here to avoid creating and
8264 destroying it in the loop. */
8265 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
8266 return;
8267 /* Create an iterator to enumerate the font families. */
8268 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
8269 != noErr)
8271 FMDisposeFontFamilyInstanceIterator (&ffii);
8272 return;
8275 GCPRO1 (text_encoding_info_alist);
8277 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
8279 Str255 name;
8280 FMFont font;
8281 FMFontStyle style;
8282 FMFontSize size;
8283 TextEncoding encoding;
8284 TextEncodingBase sc;
8285 Lisp_Object text_encoding_info, family;
8287 if (FMGetFontFamilyName (ff, name) != noErr)
8288 continue;
8289 p2cstr (name);
8290 if (*name == '.')
8291 continue;
8293 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
8294 continue;
8295 sc = GetTextEncodingBase (encoding);
8296 text_encoding_info = assq_no_quit (make_number (sc),
8297 text_encoding_info_alist);
8298 if (NILP (text_encoding_info))
8299 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
8300 text_encoding_info_alist);
8301 decode_mac_font_name (name, sizeof (name),
8302 XCAR (XCDR (text_encoding_info)));
8303 family = build_string (name);
8304 if (!NILP (Fassoc (family, fm_font_family_alist)))
8305 continue;
8306 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
8307 fm_font_family_alist);
8309 /* Point the instance iterator at the current font family. */
8310 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
8311 continue;
8313 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
8314 == noErr)
8316 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
8318 if (size > 0 || style == normal)
8319 for (; !NILP (rest); rest = XCDR (rest))
8320 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
8324 UNGCPRO;
8326 /* Dispose of the iterators. */
8327 FMDisposeFontFamilyIterator (&ffi);
8328 FMDisposeFontFamilyInstanceIterator (&ffii);
8329 #else /* !TARGET_API_MAC_CARBON */
8330 GrafPtr port;
8331 SInt16 fontnum, old_fontnum;
8332 int num_mac_fonts = CountResources('FOND');
8333 int i, j;
8334 Handle font_handle, font_handle_2;
8335 short id, scriptcode;
8336 ResType type;
8337 Str255 name;
8338 struct FontAssoc *fat;
8339 struct AsscEntry *assc_entry;
8340 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
8341 struct gcpro gcpro1;
8343 GetPort (&port); /* save the current font number used */
8344 old_fontnum = port->txFont;
8346 text_encoding_info_alist = create_text_encoding_info_alist ();
8348 GCPRO1 (text_encoding_info_alist);
8350 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
8352 font_handle = GetIndResource ('FOND', i);
8353 if (!font_handle)
8354 continue;
8356 GetResInfo (font_handle, &id, &type, name);
8357 GetFNum (name, &fontnum);
8358 p2cstr (name);
8359 if (fontnum == 0 || *name == '.')
8360 continue;
8362 TextFont (fontnum);
8363 scriptcode = FontToScript (fontnum);
8364 text_encoding_info = assq_no_quit (make_number (scriptcode),
8365 text_encoding_info_alist);
8366 if (NILP (text_encoding_info))
8367 text_encoding_info = assq_no_quit (make_number (smRoman),
8368 text_encoding_info_alist);
8369 decode_mac_font_name (name, sizeof (name),
8370 XCAR (XCDR (text_encoding_info)));
8371 family = build_string (name);
8372 if (!NILP (Fassoc (family, fm_font_family_alist)))
8373 continue;
8374 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
8375 fm_font_family_alist);
8378 HLock (font_handle);
8380 if (GetResourceSizeOnDisk (font_handle)
8381 >= sizeof (struct FamRec))
8383 fat = (struct FontAssoc *) (*font_handle
8384 + sizeof (struct FamRec));
8385 assc_entry
8386 = (struct AsscEntry *) (*font_handle
8387 + sizeof (struct FamRec)
8388 + sizeof (struct FontAssoc));
8390 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
8392 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
8394 for (; !NILP (rest); rest = XCDR (rest))
8395 add_mac_font_name (name, assc_entry->fontSize,
8396 assc_entry->fontStyle,
8397 SDATA (XCAR (rest)));
8401 HUnlock (font_handle);
8402 font_handle_2 = GetNextFOND (font_handle);
8403 ReleaseResource (font_handle);
8404 font_handle = font_handle_2;
8406 while (ResError () == noErr && font_handle);
8409 UNGCPRO;
8411 TextFont (old_fontnum);
8412 #endif /* !TARGET_API_MAC_CARBON */
8416 void
8417 mac_clear_font_name_table ()
8419 int i;
8421 for (i = 0; i < font_name_count; i++)
8422 xfree (font_name_table[i]);
8423 xfree (font_name_table);
8424 font_name_table = NULL;
8425 font_name_table_size = font_name_count = 0;
8426 fm_font_family_alist = Qnil;
8430 enum xlfd_scalable_field_index
8432 XLFD_SCL_PIXEL_SIZE,
8433 XLFD_SCL_POINT_SIZE,
8434 XLFD_SCL_AVGWIDTH,
8435 XLFD_SCL_LAST
8438 static const int xlfd_scalable_fields[] =
8440 6, /* PIXEL_SIZE */
8441 7, /* POINT_SIZE */
8442 11, /* AVGWIDTH */
8446 static Lisp_Object
8447 mac_do_list_fonts (pattern, maxnames)
8448 const char *pattern;
8449 int maxnames;
8451 int i, n_fonts = 0;
8452 Lisp_Object font_list = Qnil;
8453 struct xlfdpat *pat;
8454 char *scaled;
8455 const char *ptr;
8456 int scl_val[XLFD_SCL_LAST], *val;
8457 const int *field;
8458 int exact;
8460 if (font_name_table == NULL) /* Initialize when first used. */
8461 init_font_name_table ();
8463 for (i = 0; i < XLFD_SCL_LAST; i++)
8464 scl_val[i] = -1;
8466 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
8467 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
8468 fonts are scaled according to the specified size. */
8469 ptr = pattern;
8470 i = 0;
8471 field = xlfd_scalable_fields;
8472 val = scl_val;
8473 if (*ptr == '-')
8476 ptr++;
8477 if (i == *field)
8479 if ('0' <= *ptr && *ptr <= '9')
8481 *val = *ptr++ - '0';
8482 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
8483 *val = *val * 10 + *ptr++ - '0';
8484 if (*ptr != '-')
8485 *val = -1;
8487 field++;
8488 val++;
8490 ptr = strchr (ptr, '-');
8491 i++;
8493 while (ptr && i < 14);
8495 if (i == 14 && ptr == NULL)
8497 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
8498 scl_val[XLFD_SCL_PIXEL_SIZE] =
8499 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
8500 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
8501 : -1));
8502 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
8503 scl_val[XLFD_SCL_POINT_SIZE] =
8504 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
8505 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
8506 : -1));
8507 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
8508 scl_val[XLFD_SCL_AVGWIDTH] =
8509 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
8510 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
8511 : -1));
8513 else
8514 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
8516 pat = xlfdpat_create (pattern);
8517 if (pat == NULL)
8518 return Qnil;
8520 exact = xlfdpat_exact_p (pat);
8522 for (i = 0; i < font_name_count; i++)
8524 if (xlfdpat_match (pat, font_name_table[i]))
8526 font_list = Fcons (build_string (font_name_table[i]), font_list);
8527 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
8528 break;
8530 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
8531 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
8533 int former_len = ptr - font_name_table[i];
8535 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
8536 memcpy (scaled, font_name_table[i], former_len);
8537 sprintf (scaled + former_len,
8538 "-%d-%d-72-72-m-%d-%s",
8539 scl_val[XLFD_SCL_PIXEL_SIZE],
8540 scl_val[XLFD_SCL_POINT_SIZE],
8541 scl_val[XLFD_SCL_AVGWIDTH],
8542 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
8544 if (xlfdpat_match (pat, scaled))
8546 font_list = Fcons (build_string (scaled), font_list);
8547 xfree (scaled);
8548 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
8549 break;
8551 else
8552 xfree (scaled);
8556 xlfdpat_destroy (pat);
8558 return font_list;
8561 /* Return a list of names of available fonts matching PATTERN on frame F.
8563 Frame F null means we have not yet created any frame on Mac, and
8564 consult the first display in x_display_list. MAXNAMES sets a limit
8565 on how many fonts to match. */
8567 Lisp_Object
8568 x_list_fonts (f, pattern, size, maxnames)
8569 struct frame *f;
8570 Lisp_Object pattern;
8571 int size, maxnames;
8573 Lisp_Object list = Qnil, patterns, tem, key;
8574 struct mac_display_info *dpyinfo
8575 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
8577 xassert (size <= 0);
8579 patterns = Fassoc (pattern, Valternate_fontname_alist);
8580 if (NILP (patterns))
8581 patterns = Fcons (pattern, Qnil);
8583 for (; CONSP (patterns); patterns = XCDR (patterns))
8585 pattern = XCAR (patterns);
8587 if (!STRINGP (pattern))
8588 continue;
8590 tem = XCAR (XCDR (dpyinfo->name_list_element));
8591 key = Fcons (pattern, make_number (maxnames));
8593 list = Fassoc (key, tem);
8594 if (!NILP (list))
8596 list = Fcdr_safe (list);
8597 /* We have a cashed list. Don't have to get the list again. */
8598 goto label_cached;
8601 BLOCK_INPUT;
8602 list = mac_do_list_fonts (SDATA (pattern), maxnames);
8603 UNBLOCK_INPUT;
8605 /* MAC_TODO: add code for matching outline fonts here */
8607 /* Now store the result in the cache. */
8608 XSETCAR (XCDR (dpyinfo->name_list_element),
8609 Fcons (Fcons (key, list),
8610 XCAR (XCDR (dpyinfo->name_list_element))));
8612 label_cached:
8613 if (NILP (list)) continue; /* Try the remaining alternatives. */
8616 return list;
8620 #if GLYPH_DEBUG
8622 /* Check that FONT is valid on frame F. It is if it can be found in F's
8623 font table. */
8625 static void
8626 x_check_font (f, font)
8627 struct frame *f;
8628 XFontStruct *font;
8630 int i;
8631 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8633 xassert (font != NULL);
8635 for (i = 0; i < dpyinfo->n_fonts; i++)
8636 if (dpyinfo->font_table[i].name
8637 && font == dpyinfo->font_table[i].font)
8638 break;
8640 xassert (i < dpyinfo->n_fonts);
8643 #endif /* GLYPH_DEBUG != 0 */
8645 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8646 Note: There are (broken) X fonts out there with invalid XFontStruct
8647 min_bounds contents. For example, handa@etl.go.jp reports that
8648 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8649 have font->min_bounds.width == 0. */
8651 static INLINE void
8652 x_font_min_bounds (font, w, h)
8653 MacFontStruct *font;
8654 int *w, *h;
8656 *h = FONT_HEIGHT (font);
8657 *w = font->min_bounds.width;
8661 /* Compute the smallest character width and smallest font height over
8662 all fonts available on frame F. Set the members smallest_char_width
8663 and smallest_font_height in F's x_display_info structure to
8664 the values computed. Value is non-zero if smallest_font_height or
8665 smallest_char_width become smaller than they were before. */
8667 static int
8668 x_compute_min_glyph_bounds (f)
8669 struct frame *f;
8671 int i;
8672 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8673 MacFontStruct *font;
8674 int old_width = dpyinfo->smallest_char_width;
8675 int old_height = dpyinfo->smallest_font_height;
8677 dpyinfo->smallest_font_height = 100000;
8678 dpyinfo->smallest_char_width = 100000;
8680 for (i = 0; i < dpyinfo->n_fonts; ++i)
8681 if (dpyinfo->font_table[i].name)
8683 struct font_info *fontp = dpyinfo->font_table + i;
8684 int w, h;
8686 font = (MacFontStruct *) fontp->font;
8687 xassert (font != (MacFontStruct *) ~0);
8688 x_font_min_bounds (font, &w, &h);
8690 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8691 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8694 xassert (dpyinfo->smallest_char_width > 0
8695 && dpyinfo->smallest_font_height > 0);
8697 return (dpyinfo->n_fonts == 1
8698 || dpyinfo->smallest_char_width < old_width
8699 || dpyinfo->smallest_font_height < old_height);
8703 /* Determine whether given string is a fully-specified XLFD: all 14
8704 fields are present, none is '*'. */
8706 static int
8707 is_fully_specified_xlfd (p)
8708 const char *p;
8710 int i;
8711 char *q;
8713 if (*p != '-')
8714 return 0;
8716 for (i = 0; i < 13; i++)
8718 q = strchr (p + 1, '-');
8719 if (q == NULL)
8720 return 0;
8721 if (q - p == 2 && *(p + 1) == '*')
8722 return 0;
8723 p = q;
8726 if (strchr (p + 1, '-') != NULL)
8727 return 0;
8729 if (*(p + 1) == '*' && *(p + 2) == '\0')
8730 return 0;
8732 return 1;
8736 /* mac_load_query_font creates and returns an internal representation
8737 for a font in a MacFontStruct struct. There is really no concept
8738 corresponding to "loading" a font on the Mac. But we check its
8739 existence and find the font number and all other information for it
8740 and store them in the returned MacFontStruct. */
8742 static MacFontStruct *
8743 mac_load_query_font (f, fontname)
8744 struct frame *f;
8745 char *fontname;
8747 int size;
8748 char *name;
8749 Str255 family;
8750 Str31 charset;
8751 SInt16 fontnum;
8752 #if USE_ATSUI
8753 static ATSUFontID font_id;
8754 ATSUStyle mac_style = NULL;
8755 #endif
8756 Style fontface;
8757 #if TARGET_API_MAC_CARBON
8758 TextEncoding encoding;
8759 int scriptcode;
8760 #else
8761 short scriptcode;
8762 #endif
8763 MacFontStruct *font;
8764 XCharStruct *space_bounds = NULL, *pcm;
8766 if (is_fully_specified_xlfd (fontname))
8767 name = fontname;
8768 else
8770 Lisp_Object matched_fonts;
8772 matched_fonts = mac_do_list_fonts (fontname, 1);
8773 if (NILP (matched_fonts))
8774 return NULL;
8775 name = SDATA (XCAR (matched_fonts));
8778 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
8779 return NULL;
8781 #if USE_ATSUI
8782 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
8784 OSStatus err;
8785 static const ATSUAttributeTag tags[] =
8786 {kATSUFontTag, kATSUSizeTag,
8787 kATSUQDBoldfaceTag, kATSUQDItalicTag};
8788 static const ByteCount sizes[] =
8789 {sizeof (ATSUFontID), sizeof (Fixed),
8790 sizeof (Boolean), sizeof (Boolean)};
8791 static Fixed size_fixed;
8792 static Boolean bold_p, italic_p;
8793 static const ATSUAttributeValuePtr values[] =
8794 {&font_id, &size_fixed,
8795 &bold_p, &italic_p};
8796 static const ATSUFontFeatureType types[] =
8797 {kAllTypographicFeaturesType, kDiacriticsType};
8798 static const ATSUFontFeatureSelector selectors[] =
8799 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
8800 FMFontStyle style;
8802 font_id = atsu_find_font_from_family_name (family);
8803 if (font_id == kATSUInvalidFontID)
8804 return NULL;
8805 size_fixed = Long2Fix (size);
8806 bold_p = (fontface & bold) != 0;
8807 italic_p = (fontface & italic) != 0;
8808 err = ATSUCreateStyle (&mac_style);
8809 if (err != noErr)
8810 return NULL;
8811 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
8812 types, selectors);
8813 if (err != noErr)
8814 return NULL;
8815 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
8816 tags, sizes, values);
8817 if (err != noErr)
8818 return NULL;
8819 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
8820 if (err != noErr)
8821 fontnum = -1;
8822 scriptcode = kTextEncodingMacUnicode;
8824 else
8825 #endif
8827 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
8829 if (NILP (tmp))
8830 return NULL;
8831 fontnum = XINT (XCDR (tmp));
8832 #if TARGET_API_MAC_CARBON
8833 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
8834 return NULL;
8835 scriptcode = GetTextEncodingBase (encoding);
8836 #else
8837 scriptcode = FontToScript (fontnum);
8838 #endif
8841 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
8843 font->mac_fontnum = fontnum;
8844 font->mac_fontsize = size;
8845 font->mac_fontface = fontface;
8846 font->mac_scriptcode = scriptcode;
8847 #if USE_ATSUI
8848 font->mac_style = mac_style;
8849 #if USE_CG_TEXT_DRAWING
8850 font->cg_font = NULL;
8851 font->cg_glyphs = NULL;
8852 #endif
8853 #endif
8855 /* Apple Japanese (SJIS) font is listed as both
8856 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8857 (Roman script) in init_font_name_table (). The latter should be
8858 treated as a one-byte font. */
8859 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
8860 font->mac_scriptcode = smRoman;
8862 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
8864 #if USE_ATSUI
8865 if (font->mac_style)
8867 OSStatus err;
8868 UniChar c;
8870 font->min_byte1 = 0;
8871 font->max_byte1 = 0xff;
8872 font->min_char_or_byte2 = 0;
8873 font->max_char_or_byte2 = 0xff;
8875 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
8876 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
8877 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
8878 pcm_init (font->bounds.rows[0], 0x100);
8880 #if USE_CG_TEXT_DRAWING
8881 if (fontnum != -1)
8883 FMFontStyle style;
8884 ATSFontRef ats_font;
8886 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
8887 &font_id, &style);
8888 /* Use CG text drawing if italic/bold is not synthesized. */
8889 if (err == noErr && style == fontface)
8891 ats_font = FMGetATSFontRefFromFont (font_id);
8892 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
8896 if (font->cg_font)
8898 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
8899 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
8901 #endif
8902 space_bounds = font->bounds.rows[0] + 0x20;
8903 err = mac_query_char_extents (font->mac_style, 0x20,
8904 &font->ascent, &font->descent,
8905 space_bounds,
8906 #if USE_CG_TEXT_DRAWING
8907 (font->cg_glyphs ? font->cg_glyphs + 0x20
8908 : NULL)
8909 #else
8910 NULL
8911 #endif
8913 if (err != noErr
8914 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
8916 mac_unload_font (&one_mac_display_info, font);
8917 return NULL;
8920 pcm = font->bounds.rows[0];
8921 for (c = 0x21; c <= 0xff; c++)
8923 if (c == 0xad)
8924 /* Soft hyphen is not supported in ATSUI. */
8925 continue;
8926 else if (c == 0x7f)
8928 #if USE_CG_TEXT_DRAWING
8929 if (font->cg_glyphs)
8931 c = 0x9f;
8932 pcm = NULL;
8933 continue;
8935 #endif
8936 break;
8939 mac_query_char_extents (font->mac_style, c, NULL, NULL,
8940 pcm ? pcm + c : NULL,
8941 #if USE_CG_TEXT_DRAWING
8942 (font->cg_glyphs ? font->cg_glyphs + c
8943 : NULL)
8944 #else
8945 NULL
8946 #endif
8949 #if USE_CG_TEXT_DRAWING
8950 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
8952 /* Don't use CG text drawing if font substitution occurs in
8953 ASCII or Latin-1 characters. */
8954 CGFontRelease (font->cg_font);
8955 font->cg_font = NULL;
8956 xfree (font->cg_glyphs);
8957 font->cg_glyphs = NULL;
8958 if (pcm == NULL)
8959 break;
8961 #endif
8964 else
8965 #endif
8967 OSStatus err;
8968 FontInfo the_fontinfo;
8969 int is_two_byte_font;
8971 #if USE_CG_DRAWING
8972 mac_prepare_for_quickdraw (f);
8973 #endif
8974 SetPortWindowPort (FRAME_MAC_WINDOW (f));
8976 TextFont (fontnum);
8977 TextSize (size);
8978 TextFace (fontface);
8980 GetFontInfo (&the_fontinfo);
8982 font->ascent = the_fontinfo.ascent;
8983 font->descent = the_fontinfo.descent;
8985 is_two_byte_font = (font->mac_scriptcode == smJapanese
8986 || font->mac_scriptcode == smTradChinese
8987 || font->mac_scriptcode == smSimpChinese
8988 || font->mac_scriptcode == smKorean);
8990 if (is_two_byte_font)
8992 int char_width;
8994 font->min_byte1 = 0xa1;
8995 font->max_byte1 = 0xfe;
8996 font->min_char_or_byte2 = 0xa1;
8997 font->max_char_or_byte2 = 0xfe;
8999 /* Use the width of an "ideographic space" of that font
9000 because the_fontinfo.widMax returns the wrong width for
9001 some fonts. */
9002 switch (font->mac_scriptcode)
9004 case smJapanese:
9005 font->min_byte1 = 0x81;
9006 font->max_byte1 = 0xfc;
9007 font->min_char_or_byte2 = 0x40;
9008 font->max_char_or_byte2 = 0xfc;
9009 char_width = StringWidth("\p\x81\x40");
9010 break;
9011 case smTradChinese:
9012 font->min_char_or_byte2 = 0x40;
9013 char_width = StringWidth("\p\xa1\x40");
9014 break;
9015 case smSimpChinese:
9016 char_width = StringWidth("\p\xa1\xa1");
9017 break;
9018 case smKorean:
9019 char_width = StringWidth("\p\xa1\xa1");
9020 break;
9023 font->bounds.per_char = NULL;
9025 if (fontface & italic)
9026 font->max_bounds.rbearing = char_width + 1;
9027 else
9028 font->max_bounds.rbearing = char_width;
9029 font->max_bounds.lbearing = 0;
9030 font->max_bounds.width = char_width;
9031 font->max_bounds.ascent = the_fontinfo.ascent;
9032 font->max_bounds.descent = the_fontinfo.descent;
9034 font->min_bounds = font->max_bounds;
9036 else
9038 int c;
9040 font->min_byte1 = font->max_byte1 = 0;
9041 font->min_char_or_byte2 = 0x20;
9042 font->max_char_or_byte2 = 0xff;
9044 font->bounds.per_char =
9045 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
9046 bzero (font->bounds.per_char,
9047 sizeof (XCharStruct) * (0xff - 0x20 + 1));
9049 space_bounds = font->bounds.per_char;
9050 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
9051 &font->descent, space_bounds, NULL);
9052 if (err != noErr || space_bounds->width <= 0)
9054 mac_unload_font (&one_mac_display_info, font);
9055 return NULL;
9058 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
9059 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
9063 if (space_bounds)
9065 int c;
9067 font->min_bounds = font->max_bounds = *space_bounds;
9068 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
9069 if (pcm->width > 0)
9071 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
9072 pcm->lbearing);
9073 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
9074 pcm->rbearing);
9075 font->min_bounds.width = min (font->min_bounds.width,
9076 pcm->width);
9077 font->min_bounds.ascent = min (font->min_bounds.ascent,
9078 pcm->ascent);
9079 font->min_bounds.descent = min (font->min_bounds.descent,
9080 pcm->descent);
9082 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
9083 pcm->lbearing);
9084 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
9085 pcm->rbearing);
9086 font->max_bounds.width = max (font->max_bounds.width,
9087 pcm->width);
9088 font->max_bounds.ascent = max (font->max_bounds.ascent,
9089 pcm->ascent);
9090 font->max_bounds.descent = max (font->max_bounds.descent,
9091 pcm->descent);
9093 if (
9094 #if USE_ATSUI
9095 font->mac_style == NULL &&
9096 #endif
9097 font->max_bounds.width == font->min_bounds.width
9098 && font->min_bounds.lbearing >= 0
9099 && font->max_bounds.rbearing <= font->max_bounds.width)
9101 /* Fixed width and no overhangs. */
9102 xfree (font->bounds.per_char);
9103 font->bounds.per_char = NULL;
9107 #if !defined (MAC_OS8) || USE_ATSUI
9108 /* AppKit and WebKit do some adjustment to the heights of Courier,
9109 Helvetica, and Times. This only works on the environments where
9110 srcCopy text transfer mode is never used. */
9111 if (
9112 #ifdef MAC_OS8 /* implies USE_ATSUI */
9113 font->mac_style &&
9114 #endif
9115 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
9116 || strcmp (family, "times") == 0))
9117 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
9118 #endif
9120 return font;
9124 void
9125 mac_unload_font (dpyinfo, font)
9126 struct mac_display_info *dpyinfo;
9127 XFontStruct *font;
9129 xfree (font->full_name);
9130 #if USE_ATSUI
9131 if (font->mac_style)
9133 int i;
9135 for (i = font->min_byte1; i <= font->max_byte1; i++)
9136 if (font->bounds.rows[i])
9137 xfree (font->bounds.rows[i]);
9138 xfree (font->bounds.rows);
9139 ATSUDisposeStyle (font->mac_style);
9141 else
9142 #endif
9143 if (font->bounds.per_char)
9144 xfree (font->bounds.per_char);
9145 #if USE_CG_TEXT_DRAWING
9146 if (font->cg_font)
9147 CGFontRelease (font->cg_font);
9148 if (font->cg_glyphs)
9149 xfree (font->cg_glyphs);
9150 #endif
9151 xfree (font);
9155 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9156 pointer to the structure font_info while allocating it dynamically.
9157 If SIZE is 0, load any size of font.
9158 If loading is failed, return NULL. */
9160 struct font_info *
9161 x_load_font (f, fontname, size)
9162 struct frame *f;
9163 register char *fontname;
9164 int size;
9166 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9167 Lisp_Object font_names;
9169 /* Get a list of all the fonts that match this name. Once we
9170 have a list of matching fonts, we compare them against the fonts
9171 we already have by comparing names. */
9172 font_names = x_list_fonts (f, build_string (fontname), size, 1);
9174 if (!NILP (font_names))
9176 Lisp_Object tail;
9177 int i;
9179 for (i = 0; i < dpyinfo->n_fonts; i++)
9180 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
9181 if (dpyinfo->font_table[i].name
9182 && (!strcmp (dpyinfo->font_table[i].name,
9183 SDATA (XCAR (tail)))
9184 || !strcmp (dpyinfo->font_table[i].full_name,
9185 SDATA (XCAR (tail)))))
9186 return (dpyinfo->font_table + i);
9188 else
9189 return NULL;
9191 /* Load the font and add it to the table. */
9193 struct MacFontStruct *font;
9194 struct font_info *fontp;
9195 int i;
9197 fontname = (char *) SDATA (XCAR (font_names));
9199 BLOCK_INPUT;
9200 font = mac_load_query_font (f, fontname);
9201 UNBLOCK_INPUT;
9202 if (!font)
9203 return NULL;
9205 /* Find a free slot in the font table. */
9206 for (i = 0; i < dpyinfo->n_fonts; ++i)
9207 if (dpyinfo->font_table[i].name == NULL)
9208 break;
9210 /* If no free slot found, maybe enlarge the font table. */
9211 if (i == dpyinfo->n_fonts
9212 && dpyinfo->n_fonts == dpyinfo->font_table_size)
9214 int sz;
9215 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
9216 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
9217 dpyinfo->font_table
9218 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
9221 fontp = dpyinfo->font_table + i;
9222 if (i == dpyinfo->n_fonts)
9223 ++dpyinfo->n_fonts;
9225 /* Now fill in the slots of *FONTP. */
9226 BLOCK_INPUT;
9227 bzero (fontp, sizeof (*fontp));
9228 fontp->font = font;
9229 fontp->font_idx = i;
9230 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
9231 bcopy (fontname, fontp->name, strlen (fontname) + 1);
9233 if (font->min_bounds.width == font->max_bounds.width)
9235 /* Fixed width font. */
9236 fontp->average_width = fontp->space_width = font->min_bounds.width;
9238 else
9240 XChar2b char2b;
9241 XCharStruct *pcm;
9243 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
9244 pcm = mac_per_char_metric (font, &char2b, 0);
9245 if (pcm)
9246 fontp->space_width = pcm->width;
9247 else
9248 fontp->space_width = FONT_WIDTH (font);
9250 if (pcm)
9252 int width = pcm->width;
9253 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
9254 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
9255 width += pcm->width;
9256 fontp->average_width = width / 95;
9258 else
9259 fontp->average_width = FONT_WIDTH (font);
9262 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
9263 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
9265 fontp->size = font->max_bounds.width;
9266 fontp->height = FONT_HEIGHT (font);
9268 /* For some font, ascent and descent in max_bounds field is
9269 larger than the above value. */
9270 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
9271 if (max_height > fontp->height)
9272 fontp->height = max_height;
9275 /* The slot `encoding' specifies how to map a character
9276 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9277 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9278 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9279 2:0xA020..0xFF7F). For the moment, we don't know which charset
9280 uses this font. So, we set information in fontp->encoding[1]
9281 which is never used by any charset. If mapping can't be
9282 decided, set FONT_ENCODING_NOT_DECIDED. */
9283 if (font->mac_scriptcode == smJapanese)
9284 fontp->encoding[1] = 4;
9285 else
9287 fontp->encoding[1]
9288 = (font->max_byte1 == 0
9289 /* 1-byte font */
9290 ? (font->min_char_or_byte2 < 0x80
9291 ? (font->max_char_or_byte2 < 0x80
9292 ? 0 /* 0x20..0x7F */
9293 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
9294 : 1) /* 0xA0..0xFF */
9295 /* 2-byte font */
9296 : (font->min_byte1 < 0x80
9297 ? (font->max_byte1 < 0x80
9298 ? (font->min_char_or_byte2 < 0x80
9299 ? (font->max_char_or_byte2 < 0x80
9300 ? 0 /* 0x2020..0x7F7F */
9301 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
9302 : 3) /* 0x20A0..0x7FFF */
9303 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
9304 : (font->min_char_or_byte2 < 0x80
9305 ? (font->max_char_or_byte2 < 0x80
9306 ? 2 /* 0xA020..0xFF7F */
9307 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
9308 : 1))); /* 0xA0A0..0xFFFF */
9311 #if 0 /* MAC_TODO: fill these out with more reasonably values */
9312 fontp->baseline_offset
9313 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
9314 ? (long) value : 0);
9315 fontp->relative_compose
9316 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
9317 ? (long) value : 0);
9318 fontp->default_ascent
9319 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
9320 ? (long) value : 0);
9321 #else
9322 fontp->baseline_offset = 0;
9323 fontp->relative_compose = 0;
9324 fontp->default_ascent = 0;
9325 #endif
9327 /* Set global flag fonts_changed_p to non-zero if the font loaded
9328 has a character with a smaller width than any other character
9329 before, or if the font loaded has a smaller height than any
9330 other font loaded before. If this happens, it will make a
9331 glyph matrix reallocation necessary. */
9332 fonts_changed_p |= x_compute_min_glyph_bounds (f);
9333 UNBLOCK_INPUT;
9334 return fontp;
9339 /* Return a pointer to struct font_info of a font named FONTNAME for
9340 frame F. If no such font is loaded, return NULL. */
9342 struct font_info *
9343 x_query_font (f, fontname)
9344 struct frame *f;
9345 register char *fontname;
9347 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9348 int i;
9350 for (i = 0; i < dpyinfo->n_fonts; i++)
9351 if (dpyinfo->font_table[i].name
9352 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
9353 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
9354 return (dpyinfo->font_table + i);
9355 return NULL;
9359 /* Find a CCL program for a font specified by FONTP, and set the member
9360 `encoder' of the structure. */
9362 void
9363 x_find_ccl_program (fontp)
9364 struct font_info *fontp;
9366 Lisp_Object list, elt;
9368 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
9370 elt = XCAR (list);
9371 if (CONSP (elt)
9372 && STRINGP (XCAR (elt))
9373 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
9374 >= 0))
9375 break;
9377 if (! NILP (list))
9379 struct ccl_program *ccl
9380 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
9382 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
9383 xfree (ccl);
9384 else
9385 fontp->font_encoder = ccl;
9389 #if USE_MAC_FONT_PANEL
9390 /* Whether Font Panel has been shown before. The first call to font
9391 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
9392 slow. This variable is used for deferring such a call as much as
9393 possible. */
9394 static int font_panel_shown_p = 0;
9396 extern Lisp_Object Qfont;
9397 static Lisp_Object Qpanel_closed, Qselection;
9399 static OSStatus mac_store_event_ref_as_apple_event P_ ((AEEventClass, AEEventID,
9400 Lisp_Object,
9401 Lisp_Object,
9402 EventRef, UInt32,
9403 const EventParamName *,
9404 const EventParamType *));
9407 mac_font_panel_visible_p ()
9409 return font_panel_shown_p && FPIsFontPanelVisible ();
9412 static pascal OSStatus
9413 mac_handle_font_event (next_handler, event, data)
9414 EventHandlerCallRef next_handler;
9415 EventRef event;
9416 void *data;
9418 OSStatus result, err;
9419 Lisp_Object id_key;
9420 int num_params;
9421 const EventParamName *names;
9422 const EventParamType *types;
9423 static const EventParamName names_sel[] = {kEventParamATSUFontID,
9424 kEventParamATSUFontSize,
9425 kEventParamFMFontFamily,
9426 kEventParamFMFontStyle,
9427 kEventParamFMFontSize,
9428 kEventParamFontColor};
9429 static const EventParamType types_sel[] = {typeATSUFontID,
9430 typeATSUSize,
9431 typeFMFontFamily,
9432 typeFMFontStyle,
9433 typeFMFontSize,
9434 typeFontColor};
9436 result = CallNextEventHandler (next_handler, event);
9437 if (result != eventNotHandledErr)
9438 return result;
9440 switch (GetEventKind (event))
9442 case kEventFontPanelClosed:
9443 id_key = Qpanel_closed;
9444 num_params = 0;
9445 names = NULL;
9446 types = NULL;
9447 break;
9449 case kEventFontSelection:
9450 id_key = Qselection;
9451 num_params = sizeof (names_sel) / sizeof (names_sel[0]);
9452 names = names_sel;
9453 types = types_sel;
9454 break;
9457 err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
9458 event, num_params,
9459 names, types);
9460 if (err == noErr)
9461 result = noErr;
9463 return result;
9466 OSStatus
9467 mac_show_hide_font_panel ()
9469 if (!font_panel_shown_p)
9471 OSStatus err;
9473 static const EventTypeSpec specs[] =
9474 {{kEventClassFont, kEventFontPanelClosed},
9475 {kEventClassFont, kEventFontSelection}};
9477 err = InstallApplicationEventHandler (mac_handle_font_event,
9478 GetEventTypeCount (specs),
9479 specs, NULL, NULL);
9480 if (err != noErr)
9481 return err;
9483 font_panel_shown_p = 1;
9486 return FPShowHideFontPanel ();
9489 OSStatus
9490 mac_set_font_info_for_selection (f, face_id, c)
9491 struct frame *f;
9492 int face_id, c;
9494 OSStatus err;
9495 EventTargetRef target = NULL;
9496 XFontStruct *font = NULL;
9498 if (!mac_font_panel_visible_p ())
9499 return noErr;
9501 if (f)
9503 target = GetWindowEventTarget (FRAME_MAC_WINDOW (f));
9505 if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0))
9507 struct face *face;
9509 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
9510 face = FACE_FROM_ID (f, face_id);
9511 font = face->font;
9515 if (font == NULL)
9516 err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target);
9517 else
9519 if (font->mac_fontnum != -1)
9521 FontSelectionQDStyle qd_style;
9523 qd_style.version = kFontSelectionQDStyleVersionZero;
9524 qd_style.instance.fontFamily = font->mac_fontnum;
9525 qd_style.instance.fontStyle = font->mac_fontface;
9526 qd_style.size = font->mac_fontsize;
9527 qd_style.hasColor = false;
9529 err = SetFontInfoForSelection (kFontSelectionQDType,
9530 1, &qd_style, target);
9532 else
9533 err = SetFontInfoForSelection (kFontSelectionATSUIType,
9534 1, &font->mac_style, target);
9537 return err;
9539 #endif
9542 /* The Mac Event loop code */
9544 #if !TARGET_API_MAC_CARBON
9545 #include <Events.h>
9546 #include <Quickdraw.h>
9547 #include <Balloons.h>
9548 #include <Devices.h>
9549 #include <Fonts.h>
9550 #include <Gestalt.h>
9551 #include <Menus.h>
9552 #include <Processes.h>
9553 #include <Sound.h>
9554 #include <ToolUtils.h>
9555 #include <TextUtils.h>
9556 #include <Dialogs.h>
9557 #include <Script.h>
9558 #include <Types.h>
9559 #include <Resources.h>
9561 #if __MWERKS__
9562 #include <unix.h>
9563 #endif
9564 #endif /* ! TARGET_API_MAC_CARBON */
9566 #define M_APPLE 234
9567 #define I_ABOUT 1
9569 #define DEFAULT_NUM_COLS 80
9571 #define MIN_DOC_SIZE 64
9572 #define MAX_DOC_SIZE 32767
9574 #define EXTRA_STACK_ALLOC (256 * 1024)
9576 #define ARGV_STRING_LIST_ID 129
9577 #define ABOUT_ALERT_ID 128
9578 #define RAM_TOO_LARGE_ALERT_ID 129
9580 /* Contains the string "reverse", which is a constant for mouse button emu.*/
9581 Lisp_Object Qreverse;
9584 /* Modifier associated with the control key, or nil to ignore. */
9585 Lisp_Object Vmac_control_modifier;
9587 /* Modifier associated with the option key, or nil to ignore. */
9588 Lisp_Object Vmac_option_modifier;
9590 /* Modifier associated with the command key, or nil to ignore. */
9591 Lisp_Object Vmac_command_modifier;
9593 /* Modifier associated with the function key, or nil to ignore. */
9594 Lisp_Object Vmac_function_modifier;
9596 /* True if the option and command modifiers should be used to emulate
9597 a three button mouse */
9598 Lisp_Object Vmac_emulate_three_button_mouse;
9600 #if TARGET_API_MAC_CARBON
9601 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
9602 mouse-2, instead of mouse-3. */
9603 int mac_wheel_button_is_mouse_2;
9605 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
9606 for processing before Emacs sees it. */
9607 int mac_pass_command_to_system;
9609 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
9610 for processing before Emacs sees it. */
9611 int mac_pass_control_to_system;
9612 #endif
9614 /* Points to the variable `inev' in the function XTread_socket. It is
9615 used for passing an input event to the function back from
9616 Carbon/Apple event handlers. */
9617 static struct input_event *read_socket_inev = NULL;
9619 /* Whether or not the screen configuration has changed. */
9620 static int mac_screen_config_changed = 0;
9622 Point saved_menu_event_location;
9624 /* Apple Events */
9625 #if TARGET_API_MAC_CARBON
9626 static Lisp_Object Qhi_command;
9627 #ifdef MAC_OSX
9628 extern Lisp_Object Qwindow;
9629 static Lisp_Object Qtoolbar_switch_mode;
9630 #endif
9631 #if USE_MAC_TSM
9632 static TSMDocumentID tsm_document_id;
9633 static Lisp_Object Qtext_input;
9634 static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
9635 static Lisp_Object Vmac_ts_active_input_overlay;
9636 extern Lisp_Object Qbefore_string;
9637 static Lisp_Object Vmac_ts_script_language_on_focus;
9638 static Lisp_Object saved_ts_script_language_on_focus;
9639 static ScriptLanguageRecord saved_ts_language;
9640 static Component saved_ts_component;
9641 #endif
9642 #endif /* TARGET_API_MAC_CARBON */
9643 extern int mac_ready_for_apple_events;
9644 extern Lisp_Object Qundefined;
9645 extern void init_apple_event_handler P_ ((void));
9646 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
9647 Lisp_Object *, Lisp_Object *,
9648 Lisp_Object *));
9649 extern OSErr init_coercion_handler P_ ((void));
9651 /* Drag and Drop */
9652 extern OSErr install_drag_handler P_ ((WindowRef));
9653 extern void remove_drag_handler P_ ((WindowRef));
9655 #if TARGET_API_MAC_CARBON
9656 /* Showing help echo string during menu tracking */
9657 extern OSStatus install_menu_target_item_handler P_ ((void));
9659 #ifdef MAC_OSX
9660 extern OSStatus install_service_handler ();
9661 static Lisp_Object Qservice, Qpaste, Qperform;
9662 #endif
9663 #endif
9665 extern void init_emacs_passwd_dir ();
9666 extern int emacs_main (int, char **, char **);
9668 extern void initialize_applescript();
9669 extern void terminate_applescript();
9671 /* Table for translating Mac keycode to X keysym values. Contributed
9672 by Sudhir Shenoy.
9673 Mapping for special keys is now identical to that in Apple X11
9674 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9675 on the right of the Cmd key on laptops, and fn + `enter' (->
9676 <linefeed>). */
9677 static const unsigned char keycode_to_xkeysym_table[] = {
9678 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9679 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9680 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9682 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9683 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9684 /*0x38*/ 0, 0, 0, 0,
9685 /*0x3C*/ 0, 0, 0, 0,
9687 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
9688 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
9689 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
9690 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
9692 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9693 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9694 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9695 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9697 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9698 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9699 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9700 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9702 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9703 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9704 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9705 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9708 #ifdef MAC_OSX
9709 /* Table for translating Mac keycode with the laptop `fn' key to that
9710 without it. Destination symbols in comments are keys on US
9711 keyboard, and they may not be the same on other types of keyboards.
9712 If the destination is identical to the source, it doesn't map `fn'
9713 key to a modifier. */
9714 static const unsigned char fn_keycode_to_keycode_table[] = {
9715 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9716 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9717 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9719 /*0x30*/ 0, 0, 0, 0,
9720 /*0x34*/ 0, 0, 0, 0,
9721 /*0x38*/ 0, 0, 0, 0,
9722 /*0x3C*/ 0, 0, 0, 0,
9724 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9725 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9726 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9727 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9729 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9730 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9731 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9732 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9734 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9735 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9736 /*0x68*/ 0, 0x69 /*f13 = f13*/, 0x6a /*f16 = f16*/, 0x6b /*f14 = f14*/,
9737 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9739 /*0x70*/ 0, 0x71 /*f15 = f15*/, 0x72 /*help = help*/, 0x7b /*home -> left*/,
9740 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9741 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0x7b /*left = left*/,
9742 /*0x7C*/ 0x7c /*right = right*/, 0x7d /*down = down*/, 0x7e /*up = up*/, 0
9744 #endif /* MAC_OSX */
9746 static int
9747 #if TARGET_API_MAC_CARBON
9748 mac_to_emacs_modifiers (UInt32 mods, UInt32 unmapped_mods)
9749 #else
9750 mac_to_emacs_modifiers (EventModifiers mods, EventModifiers unmapped_mods)
9751 #endif
9753 unsigned int result = 0;
9754 if ((mods | unmapped_mods) & shiftKey)
9755 result |= shift_modifier;
9757 /* Deactivated to simplify configuration:
9758 if Vmac_option_modifier is non-NIL, we fully process the Option
9759 key. Otherwise, we only process it if an additional Ctrl or Command
9760 is pressed. That way the system may convert the character to a
9761 composed one.
9762 if ((mods & optionKey) &&
9763 (( !NILP(Vmac_option_modifier) ||
9764 ((mods & cmdKey) || (mods & controlKey))))) */
9766 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
9767 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
9768 if (INTEGERP(val))
9769 result |= XUINT(val);
9771 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
9772 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
9773 if (INTEGERP(val))
9774 result |= XUINT(val);
9776 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
9777 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
9778 if (INTEGERP(val))
9779 result |= XUINT(val);
9782 #ifdef MAC_OSX
9783 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
9784 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
9785 if (INTEGERP(val))
9786 result |= XUINT(val);
9788 #endif
9790 return result;
9793 static UInt32
9794 mac_mapped_modifiers (modifiers, key_code)
9795 UInt32 modifiers, key_code;
9797 UInt32 mapped_modifiers_all =
9798 (NILP (Vmac_control_modifier) ? 0 : controlKey)
9799 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
9800 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
9802 #ifdef MAC_OSX
9803 mapped_modifiers_all |=
9804 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
9806 /* The meaning of kEventKeyModifierFnMask has changed in Mac OS X
9807 10.5, and it now behaves much like Cocoa's NSFunctionKeyMask. It
9808 no longer means laptop's `fn' key is down for the following keys:
9809 F1, F2, and so on, Help, Forward Delete, Home, End, Page Up, Page
9810 Down, the arrow keys, and Clear. We ignore the corresponding bit
9811 if that key can be entered without the `fn' key on laptops. */
9812 if (modifiers & kEventKeyModifierFnMask
9813 && key_code <= 0x7f
9814 && fn_keycode_to_keycode_table[key_code] == key_code)
9815 modifiers &= ~kEventKeyModifierFnMask;
9816 #endif
9818 return mapped_modifiers_all & modifiers;
9821 static int
9822 mac_get_emulated_btn ( UInt32 modifiers )
9824 int result = 0;
9825 if (!NILP (Vmac_emulate_three_button_mouse)) {
9826 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
9827 if (modifiers & cmdKey)
9828 result = cmdIs3 ? 2 : 1;
9829 else if (modifiers & optionKey)
9830 result = cmdIs3 ? 1 : 2;
9832 return result;
9835 #if TARGET_API_MAC_CARBON
9836 /***** Code to handle C-g testing *****/
9837 extern int quit_char;
9838 extern int make_ctrl_char P_ ((int));
9841 mac_quit_char_key_p (modifiers, key_code)
9842 UInt32 modifiers, key_code;
9844 UInt32 char_code, mapped_modifiers;
9845 unsigned long some_state = 0;
9846 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9847 int c, emacs_modifiers;
9849 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9850 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
9851 key_code |= (modifiers & ~mapped_modifiers);
9852 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
9853 if (char_code & ~0xff)
9854 return 0;
9856 emacs_modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
9857 if (emacs_modifiers & ctrl_modifier)
9858 c = make_ctrl_char (char_code);
9860 c |= (emacs_modifiers
9861 & (meta_modifier | alt_modifier
9862 | hyper_modifier | super_modifier));
9864 return c == quit_char;
9866 #endif
9868 #if TARGET_API_MAC_CARBON
9869 /* Obtains the event modifiers from the event ref and then calls
9870 mac_to_emacs_modifiers. */
9871 static int
9872 mac_event_to_emacs_modifiers (EventRef eventRef)
9874 UInt32 mods = 0, class;
9876 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
9877 sizeof (UInt32), NULL, &mods);
9878 class = GetEventClass (eventRef);
9879 if (!NILP (Vmac_emulate_three_button_mouse) &&
9880 (class == kEventClassMouse || class == kEventClassCommand))
9882 mods &= ~(optionKey | cmdKey);
9884 return mac_to_emacs_modifiers (mods, 0);
9887 /* Given an event ref, return the code to use for the mouse button
9888 code in the emacs input_event. */
9889 static int
9890 mac_get_mouse_btn (EventRef ref)
9892 EventMouseButton result = kEventMouseButtonPrimary;
9893 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
9894 sizeof (EventMouseButton), NULL, &result);
9895 switch (result)
9897 case kEventMouseButtonPrimary:
9898 if (NILP (Vmac_emulate_three_button_mouse))
9899 return 0;
9900 else {
9901 UInt32 mods = 0;
9902 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
9903 sizeof (UInt32), NULL, &mods);
9904 return mac_get_emulated_btn(mods);
9906 case kEventMouseButtonSecondary:
9907 return mac_wheel_button_is_mouse_2 ? 2 : 1;
9908 case kEventMouseButtonTertiary:
9909 case 4: /* 4 is the number for the mouse wheel button */
9910 return mac_wheel_button_is_mouse_2 ? 1 : 2;
9911 default:
9912 return 0;
9916 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9917 events. However the click of the mouse wheel is not converted to a
9918 mouseDown or mouseUp event. Likewise for dead key events. This
9919 calls ConvertEventRefToEventRecord, but then checks to see if it is
9920 a mouse up/down, or a dead key Carbon event that has not been
9921 converted, and if so, converts it by hand (to be picked up in the
9922 XTread_socket loop). */
9923 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
9925 OSStatus err;
9926 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
9927 EventKind action;
9929 if (result)
9930 return result;
9932 switch (GetEventClass (eventRef))
9934 case kEventClassMouse:
9935 switch (GetEventKind (eventRef))
9937 case kEventMouseDown:
9938 eventRec->what = mouseDown;
9939 result = 1;
9940 break;
9942 case kEventMouseUp:
9943 eventRec->what = mouseUp;
9944 result = 1;
9945 break;
9947 default:
9948 break;
9950 break;
9952 case kEventClassKeyboard:
9953 switch (GetEventKind (eventRef))
9955 case kEventRawKeyDown:
9956 action = keyDown;
9957 goto keystroke_common;
9958 case kEventRawKeyRepeat:
9959 action = autoKey;
9960 goto keystroke_common;
9961 case kEventRawKeyUp:
9962 action = keyUp;
9963 keystroke_common:
9965 unsigned char char_codes;
9966 UInt32 key_code;
9968 err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes,
9969 typeChar, NULL, sizeof (char),
9970 NULL, &char_codes);
9971 if (err == noErr)
9972 err = GetEventParameter (eventRef, kEventParamKeyCode,
9973 typeUInt32, NULL, sizeof (UInt32),
9974 NULL, &key_code);
9975 if (err == noErr)
9977 eventRec->what = action;
9978 eventRec->message = char_codes | ((key_code & 0xff) << 8);
9979 result = 1;
9982 break;
9984 default:
9985 break;
9987 break;
9989 default:
9990 break;
9993 if (result)
9995 /* Need where and when. */
9996 UInt32 mods = 0;
9998 GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
9999 NULL, sizeof (Point), NULL, &eventRec->where);
10000 /* Use two step process because new event modifiers are 32-bit
10001 and old are 16-bit. Currently, only loss is NumLock & Fn. */
10002 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
10003 NULL, sizeof (UInt32), NULL, &mods);
10004 eventRec->modifiers = mods;
10006 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
10009 return result;
10012 #endif
10014 #ifdef MAC_OS8
10015 static void
10016 do_get_menus (void)
10018 Handle menubar_handle;
10019 MenuRef menu;
10021 menubar_handle = GetNewMBar (128);
10022 if(menubar_handle == NULL)
10023 abort ();
10024 SetMenuBar (menubar_handle);
10025 DrawMenuBar ();
10027 #if !TARGET_API_MAC_CARBON
10028 menu = GetMenuRef (M_APPLE);
10029 if (menu != NULL)
10030 AppendResMenu (menu, 'DRVR');
10031 else
10032 abort ();
10033 #endif
10037 static void
10038 do_init_managers (void)
10040 #if !TARGET_API_MAC_CARBON
10041 InitGraf (&qd.thePort);
10042 InitFonts ();
10043 FlushEvents (everyEvent, 0);
10044 InitWindows ();
10045 InitMenus ();
10046 TEInit ();
10047 InitDialogs (NULL);
10048 #endif /* !TARGET_API_MAC_CARBON */
10049 InitCursor ();
10051 #if !TARGET_API_MAC_CARBON
10052 /* set up some extra stack space for use by emacs */
10053 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
10055 /* MaxApplZone must be called for AppleScript to execute more
10056 complicated scripts */
10057 MaxApplZone ();
10058 MoreMasters ();
10059 #endif /* !TARGET_API_MAC_CARBON */
10062 static void
10063 do_check_ram_size (void)
10065 SInt32 physical_ram_size, logical_ram_size;
10067 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
10068 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
10069 || physical_ram_size > (1 << VALBITS)
10070 || logical_ram_size > (1 << VALBITS))
10072 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
10073 exit (1);
10076 #endif /* MAC_OS8 */
10078 static void
10079 do_window_update (WindowRef win)
10081 struct frame *f = mac_window_to_frame (win);
10083 BeginUpdate (win);
10085 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
10086 below. */
10087 if (win != tip_window)
10089 if (f->async_visible == 0)
10091 /* Update events may occur when a frame gets iconified. */
10092 #if 0
10093 f->async_visible = 1;
10094 f->async_iconified = 0;
10095 SET_FRAME_GARBAGED (f);
10096 #endif
10098 else
10100 Rect r;
10101 #if TARGET_API_MAC_CARBON
10102 RgnHandle region = NewRgn ();
10104 GetPortVisibleRegion (GetWindowPort (win), region);
10105 GetRegionBounds (region, &r);
10106 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
10107 #if USE_CG_DRAWING
10108 mac_prepare_for_quickdraw (f);
10109 #endif
10110 UpdateControls (win, region);
10111 DisposeRgn (region);
10112 #else
10113 r = (*win->visRgn)->rgnBBox;
10114 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
10115 UpdateControls (win, win->visRgn);
10116 #endif
10120 EndUpdate (win);
10123 static int
10124 is_emacs_window (WindowRef win)
10126 Lisp_Object tail, frame;
10128 if (!win)
10129 return 0;
10131 FOR_EACH_FRAME (tail, frame)
10132 if (FRAME_MAC_P (XFRAME (frame)))
10133 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
10134 return 1;
10136 return 0;
10139 #if USE_MAC_TSM
10140 static OSStatus
10141 mac_tsm_resume ()
10143 OSStatus err;
10144 ScriptLanguageRecord slrec, *slptr = NULL;
10146 err = ActivateTSMDocument (tsm_document_id);
10148 if (err == noErr)
10150 if (EQ (Vmac_ts_script_language_on_focus, Qt)
10151 && EQ (saved_ts_script_language_on_focus, Qt))
10152 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))
10156 && CONSP (saved_ts_script_language_on_focus)
10157 && EQ (XCAR (saved_ts_script_language_on_focus),
10158 XCAR (Vmac_ts_script_language_on_focus))
10159 && EQ (XCDR (saved_ts_script_language_on_focus),
10160 XCDR (Vmac_ts_script_language_on_focus)))
10162 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
10163 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
10164 slptr = &slrec;
10168 if (slptr)
10170 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10171 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
10172 kKeyboardInputMethodClass);
10173 #else
10174 err = SetDefaultInputMethod (saved_ts_component, slptr);
10175 #endif
10176 if (err == noErr)
10177 err = SetTextServiceLanguage (slptr);
10179 /* Seems to be needed on Mac OS X 10.2. */
10180 if (err == noErr)
10181 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
10184 return err;
10187 static OSStatus
10188 mac_tsm_suspend ()
10190 OSStatus err;
10191 ScriptLanguageRecord slrec, *slptr = NULL;
10193 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
10195 if (EQ (Vmac_ts_script_language_on_focus, Qt))
10197 err = GetTextServiceLanguage (&saved_ts_language);
10198 if (err == noErr)
10199 slptr = &saved_ts_language;
10201 else if (CONSP (Vmac_ts_script_language_on_focus)
10202 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
10203 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
10205 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
10206 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
10207 slptr = &slrec;
10210 if (slptr)
10212 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10213 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
10214 kKeyboardInputMethodClass);
10215 #else
10216 GetDefaultInputMethod (&saved_ts_component, slptr);
10217 #endif
10220 err = DeactivateTSMDocument (tsm_document_id);
10222 return err;
10224 #endif
10226 #if !TARGET_API_MAC_CARBON
10227 void
10228 do_apple_menu (SInt16 menu_item)
10230 Str255 item_name;
10231 SInt16 da_driver_refnum;
10233 if (menu_item == I_ABOUT)
10234 NoteAlert (ABOUT_ALERT_ID, NULL);
10235 else
10237 GetMenuItemText (GetMenuRef (M_APPLE), menu_item, item_name);
10238 da_driver_refnum = OpenDeskAcc (item_name);
10241 #endif /* !TARGET_API_MAC_CARBON */
10243 /* Handle drags in size box. Based on code contributed by Ben
10244 Mesander and IM - Window Manager A. */
10246 static void
10247 do_grow_window (w, e)
10248 WindowRef w;
10249 const EventRecord *e;
10251 Rect limit_rect;
10252 int rows, columns, width, height;
10253 struct frame *f = mac_window_to_frame (w);
10254 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
10255 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
10256 #if TARGET_API_MAC_CARBON
10257 Rect new_rect;
10258 #else
10259 long grow_size;
10260 #endif
10262 if (size_hints->flags & PMinSize)
10264 min_width = size_hints->min_width;
10265 min_height = size_hints->min_height;
10267 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
10269 #if TARGET_API_MAC_CARBON
10270 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
10271 return;
10272 height = new_rect.bottom - new_rect.top;
10273 width = new_rect.right - new_rect.left;
10274 #else
10275 grow_size = GrowWindow (w, e->where, &limit_rect);
10276 /* see if it really changed size */
10277 if (grow_size == 0)
10278 return;
10279 height = HiWord (grow_size);
10280 width = LoWord (grow_size);
10281 #endif
10283 if (width != FRAME_PIXEL_WIDTH (f)
10284 || height != FRAME_PIXEL_HEIGHT (f))
10286 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
10287 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
10289 x_set_window_size (f, 0, columns, rows);
10294 #if TARGET_API_MAC_CARBON
10295 static Point
10296 mac_get_ideal_size (f)
10297 struct frame *f;
10299 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10300 WindowRef w = FRAME_MAC_WINDOW (f);
10301 Point ideal_size;
10302 Rect standard_rect;
10303 int height, width, columns, rows;
10305 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
10306 ideal_size.v = dpyinfo->height;
10307 IsWindowInStandardState (w, &ideal_size, &standard_rect);
10308 /* Adjust the standard size according to character boundaries. */
10309 width = standard_rect.right - standard_rect.left;
10310 height = standard_rect.bottom - standard_rect.top;
10311 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
10312 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
10313 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
10314 ideal_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
10316 return ideal_size;
10318 #endif
10320 /* Handle clicks in zoom box. Calculation of "standard state" based
10321 on code in IM - Window Manager A and code contributed by Ben
10322 Mesander. The standard state of an Emacs window is 80-characters
10323 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
10325 static void
10326 do_zoom_window (WindowRef w, int zoom_in_or_out)
10328 Rect zoom_rect, port_rect;
10329 int width, height;
10330 struct frame *f = mac_window_to_frame (w);
10331 #if TARGET_API_MAC_CARBON
10332 Point ideal_size = mac_get_ideal_size (f);
10334 GetWindowBounds (w, kWindowContentRgn, &port_rect);
10335 if (IsWindowInStandardState (w, &ideal_size, &zoom_rect)
10336 && port_rect.left == zoom_rect.left
10337 && port_rect.top == zoom_rect.top)
10338 zoom_in_or_out = inZoomIn;
10339 else
10340 zoom_in_or_out = inZoomOut;
10342 #ifdef MAC_OS8
10343 mac_clear_window (f);
10344 #endif
10345 ZoomWindowIdeal (w, zoom_in_or_out, &ideal_size);
10346 #else /* not TARGET_API_MAC_CARBON */
10347 GrafPtr save_port;
10348 Point top_left;
10349 int w_title_height, rows;
10350 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
10352 GetPort (&save_port);
10354 SetPortWindowPort (w);
10356 /* Clear window to avoid flicker. */
10357 EraseRect (&(w->portRect));
10358 if (zoom_in_or_out == inZoomOut)
10360 SetPt (&top_left, w->portRect.left, w->portRect.top);
10361 LocalToGlobal (&top_left);
10363 /* calculate height of window's title bar */
10364 w_title_height = top_left.v - 1
10365 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
10367 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
10368 zoom_rect = qd.screenBits.bounds;
10369 zoom_rect.top += w_title_height;
10370 InsetRect (&zoom_rect, 8, 4); /* not too tight */
10372 zoom_rect.right = zoom_rect.left
10373 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
10375 /* Adjust the standard size according to character boundaries. */
10376 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
10377 zoom_rect.bottom =
10378 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
10380 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
10381 = zoom_rect;
10384 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
10386 SetPort (save_port);
10387 #endif /* not TARGET_API_MAC_CARBON */
10389 #if !TARGET_API_MAC_CARBON
10390 /* retrieve window size and update application values */
10391 port_rect = w->portRect;
10392 height = port_rect.bottom - port_rect.top;
10393 width = port_rect.right - port_rect.left;
10395 mac_handle_size_change (f, width, height);
10396 mac_handle_origin_change (f);
10397 #endif
10400 static void
10401 mac_set_unicode_keystroke_event (code, buf)
10402 UniChar code;
10403 struct input_event *buf;
10405 int charset_id, c1, c2;
10407 if (code < 0x80)
10409 buf->kind = ASCII_KEYSTROKE_EVENT;
10410 buf->code = code;
10412 else if (code < 0x100)
10414 if (code < 0xA0)
10415 charset_id = CHARSET_8_BIT_CONTROL;
10416 else
10417 charset_id = charset_latin_iso8859_1;
10418 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10419 buf->code = MAKE_CHAR (charset_id, code, 0);
10421 else
10423 if (code < 0x2500)
10424 charset_id = charset_mule_unicode_0100_24ff,
10425 code -= 0x100;
10426 else if (code < 0x33FF)
10427 charset_id = charset_mule_unicode_2500_33ff,
10428 code -= 0x2500;
10429 else if (code >= 0xE000)
10430 charset_id = charset_mule_unicode_e000_ffff,
10431 code -= 0xE000;
10432 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
10433 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10434 buf->code = MAKE_CHAR (charset_id, c1, c2);
10438 static void
10439 do_keystroke (action, char_code, key_code, modifiers, timestamp, buf)
10440 EventKind action;
10441 unsigned char char_code;
10442 UInt32 key_code, modifiers;
10443 unsigned long timestamp;
10444 struct input_event *buf;
10446 static SInt16 last_key_script = -1;
10447 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
10448 UInt32 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
10450 #ifdef MAC_OSX
10451 if (mapped_modifiers & kEventKeyModifierFnMask
10452 && key_code <= 0x7f
10453 && fn_keycode_to_keycode_table[key_code])
10454 key_code = fn_keycode_to_keycode_table[key_code];
10455 #endif
10457 if (key_code <= 0x7f && keycode_to_xkeysym_table[key_code])
10459 buf->kind = NON_ASCII_KEYSTROKE_EVENT;
10460 buf->code = 0xff00 | keycode_to_xkeysym_table[key_code];
10462 else if (mapped_modifiers)
10464 /* translate the keycode back to determine the original key */
10465 #ifdef MAC_OSX
10466 UCKeyboardLayout *uchr_ptr = NULL;
10467 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10468 OSStatus err;
10469 KeyboardLayoutRef layout;
10471 err = KLGetCurrentKeyboardLayout (&layout);
10472 if (err == noErr)
10473 err = KLGetKeyboardLayoutProperty (layout, kKLuchrData,
10474 (const void **) &uchr_ptr);
10475 #else
10476 static SInt16 last_key_layout_id = 0;
10477 static Handle uchr_handle = (Handle)-1;
10478 SInt16 current_key_layout_id =
10479 GetScriptVariable (current_key_script, smScriptKeys);
10481 if (uchr_handle == (Handle)-1
10482 || last_key_layout_id != current_key_layout_id)
10484 uchr_handle = GetResource ('uchr', current_key_layout_id);
10485 last_key_layout_id = current_key_layout_id;
10487 if (uchr_handle)
10488 uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
10489 #endif
10491 if (uchr_ptr)
10493 OSStatus status;
10494 UInt16 key_action = action - keyDown;
10495 UInt32 modifier_key_state = (modifiers & ~mapped_modifiers) >> 8;
10496 UInt32 keyboard_type = LMGetKbdType ();
10497 SInt32 dead_key_state = 0;
10498 UniChar code;
10499 UniCharCount actual_length;
10501 status = UCKeyTranslate (uchr_ptr, key_code, key_action,
10502 modifier_key_state, keyboard_type,
10503 kUCKeyTranslateNoDeadKeysMask,
10504 &dead_key_state,
10505 1, &actual_length, &code);
10506 if (status == noErr && actual_length == 1)
10507 mac_set_unicode_keystroke_event (code, buf);
10509 #endif /* MAC_OSX */
10511 if (buf->kind == NO_EVENT)
10513 /* This code comes from Keyboard Resource, Appendix C of IM
10514 - Text. This is necessary since shift is ignored in KCHR
10515 table translation when option or command is pressed. It
10516 also does not translate correctly control-shift chars
10517 like C-% so mask off shift here also. */
10518 /* Mask off modifier keys that are mapped to some Emacs
10519 modifiers. */
10520 int new_modifiers = modifiers & ~mapped_modifiers;
10521 /* set high byte of keycode to modifier high byte*/
10522 int new_key_code = key_code | new_modifiers;
10523 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
10524 unsigned long some_state = 0;
10525 UInt32 new_char_code;
10527 new_char_code = KeyTranslate (kchr_ptr, new_key_code, &some_state);
10528 if (new_char_code == 0)
10529 /* Seems like a dead key. Append up-stroke. */
10530 new_char_code = KeyTranslate (kchr_ptr, new_key_code | 0x80,
10531 &some_state);
10532 if (new_char_code)
10534 buf->kind = ASCII_KEYSTROKE_EVENT;
10535 buf->code = new_char_code & 0xff;
10540 if (buf->kind == NO_EVENT)
10542 buf->kind = ASCII_KEYSTROKE_EVENT;
10543 buf->code = char_code;
10546 buf->modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
10547 buf->modifiers |= (extra_keyboard_modifiers
10548 & (meta_modifier | alt_modifier
10549 | hyper_modifier | super_modifier));
10551 #if TARGET_API_MAC_CARBON
10552 if (buf->kind == ASCII_KEYSTROKE_EVENT
10553 && buf->code >= 0x80 && buf->modifiers)
10555 OSStatus err;
10556 TextEncoding encoding = kTextEncodingMacRoman;
10557 TextToUnicodeInfo ttu_info;
10559 UpgradeScriptInfoToTextEncoding (current_key_script,
10560 kTextLanguageDontCare,
10561 kTextRegionDontCare,
10562 NULL, &encoding);
10563 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
10564 if (err == noErr)
10566 UniChar code;
10567 Str255 pstr;
10568 ByteCount unicode_len;
10570 pstr[0] = 1;
10571 pstr[1] = buf->code;
10572 err = ConvertFromPStringToUnicode (ttu_info, pstr,
10573 sizeof (UniChar),
10574 &unicode_len, &code);
10575 if (err == noErr && unicode_len == sizeof (UniChar))
10576 mac_set_unicode_keystroke_event (code, buf);
10577 DisposeTextToUnicodeInfo (&ttu_info);
10580 #endif
10582 if (buf->kind == ASCII_KEYSTROKE_EVENT
10583 && buf->code >= 0x80
10584 && last_key_script != current_key_script)
10586 struct input_event event;
10588 EVENT_INIT (event);
10589 event.kind = LANGUAGE_CHANGE_EVENT;
10590 event.arg = Qnil;
10591 event.code = current_key_script;
10592 event.timestamp = timestamp;
10593 kbd_buffer_store_event (&event);
10594 last_key_script = current_key_script;
10598 void
10599 mac_store_apple_event (class, id, desc)
10600 Lisp_Object class, id;
10601 const AEDesc *desc;
10603 struct input_event buf;
10605 EVENT_INIT (buf);
10607 buf.kind = MAC_APPLE_EVENT;
10608 buf.x = class;
10609 buf.y = id;
10610 XSETFRAME (buf.frame_or_window,
10611 mac_focus_frame (&one_mac_display_info));
10612 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
10613 is safe to use them during read_socket_hook. */
10614 buf.arg = mac_aedesc_to_lisp (desc);
10615 kbd_buffer_store_event (&buf);
10618 #if TARGET_API_MAC_CARBON
10619 static OSStatus
10620 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
10621 event, num_params, names, types)
10622 AEEventClass class;
10623 AEEventID id;
10624 Lisp_Object class_key, id_key;
10625 EventRef event;
10626 UInt32 num_params;
10627 const EventParamName *names;
10628 const EventParamType *types;
10630 OSStatus err = eventNotHandledErr;
10631 Lisp_Object binding;
10633 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
10634 if (!NILP (binding) && !EQ (binding, Qundefined))
10636 if (INTEGERP (binding))
10637 err = XINT (binding);
10638 else
10640 AppleEvent apple_event;
10641 err = create_apple_event_from_event_ref (event, num_params,
10642 names, types,
10643 &apple_event);
10644 if (err == noErr)
10646 mac_store_apple_event (class_key, id_key, &apple_event);
10647 AEDisposeDesc (&apple_event);
10648 mac_wakeup_from_rne ();
10653 return err;
10656 void
10657 mac_store_drag_event (window, mouse_pos, modifiers, desc)
10658 WindowRef window;
10659 Point mouse_pos;
10660 SInt16 modifiers;
10661 const AEDesc *desc;
10663 struct input_event buf;
10665 EVENT_INIT (buf);
10667 buf.kind = DRAG_N_DROP_EVENT;
10668 buf.modifiers = mac_to_emacs_modifiers (modifiers, 0);
10669 buf.timestamp = TickCount () * (1000 / 60);
10670 XSETINT (buf.x, mouse_pos.h);
10671 XSETINT (buf.y, mouse_pos.v);
10672 XSETFRAME (buf.frame_or_window, mac_window_to_frame (window));
10673 buf.arg = mac_aedesc_to_lisp (desc);
10674 kbd_buffer_store_event (&buf);
10677 #ifdef MAC_OSX
10678 OSStatus
10679 mac_store_service_event (event)
10680 EventRef event;
10682 OSStatus err;
10683 Lisp_Object id_key;
10684 int num_params;
10685 const EventParamName *names;
10686 const EventParamType *types;
10687 static const EventParamName names_pfm[] =
10688 {kEventParamServiceMessageName, kEventParamServiceUserData};
10689 static const EventParamType types_pfm[] =
10690 {typeCFStringRef, typeCFStringRef};
10692 switch (GetEventKind (event))
10694 case kEventServicePaste:
10695 id_key = Qpaste;
10696 num_params = 0;
10697 names = NULL;
10698 types = NULL;
10699 break;
10701 case kEventServicePerform:
10702 id_key = Qperform;
10703 num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
10704 names = names_pfm;
10705 types = types_pfm;
10706 break;
10708 default:
10709 abort ();
10712 err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
10713 event, num_params,
10714 names, types);
10716 return err;
10718 #endif /* MAC_OSX */
10720 static pascal OSStatus
10721 mac_handle_window_event (next_handler, event, data)
10722 EventHandlerCallRef next_handler;
10723 EventRef event;
10724 void *data;
10726 WindowRef wp;
10727 OSStatus err, result = eventNotHandledErr;
10728 struct frame *f;
10729 UInt32 attributes;
10730 XSizeHints *size_hints;
10732 err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
10733 NULL, sizeof (WindowRef), NULL, &wp);
10734 if (err != noErr)
10735 return eventNotHandledErr;
10737 f = mac_window_to_frame (wp);
10738 switch (GetEventKind (event))
10740 /* -- window refresh events -- */
10742 case kEventWindowUpdate:
10743 result = CallNextEventHandler (next_handler, event);
10744 if (result != eventNotHandledErr)
10745 break;
10747 do_window_update (wp);
10748 result = noErr;
10749 break;
10751 /* -- window state change events -- */
10753 case kEventWindowShowing:
10754 size_hints = FRAME_SIZE_HINTS (f);
10755 if (!(size_hints->flags & (USPosition | PPosition)))
10757 struct frame *sf = SELECTED_FRAME ();
10759 if (!(FRAME_MAC_P (sf) && sf->async_visible))
10760 RepositionWindow (wp, NULL, kWindowCenterOnMainScreen);
10761 else
10763 RepositionWindow (wp, FRAME_MAC_WINDOW (sf),
10764 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
10765 kWindowCascadeStartAtParentWindowScreen
10766 #else
10767 kWindowCascadeOnParentWindowScreen
10768 #endif
10770 #if USE_MAC_TOOLBAR
10771 /* This is a workaround. RepositionWindow fails to put
10772 a window at the cascading position when its parent
10773 window has a Carbon HIToolbar. */
10774 if ((f->left_pos == sf->left_pos
10775 && f->top_pos == sf->top_pos)
10776 || (f->left_pos == sf->left_pos + 10 * 2
10777 && f->top_pos == sf->top_pos + 32 * 2))
10778 MoveWindowStructure (wp, sf->left_pos + 10, sf->top_pos + 32);
10779 #endif
10781 result = noErr;
10783 break;
10785 case kEventWindowHiding:
10786 /* Before unmapping the window, update the WM_SIZE_HINTS
10787 property to claim that the current position of the window is
10788 user-specified, rather than program-specified, so that when
10789 the window is mapped again, it will be placed at the same
10790 location, without forcing the user to position it by hand
10791 again (they have already done that once for this window.) */
10792 x_wm_set_size_hint (f, (long) 0, 1);
10793 result = noErr;
10794 break;
10796 case kEventWindowShown:
10797 case kEventWindowHidden:
10798 case kEventWindowCollapsed:
10799 case kEventWindowExpanded:
10800 mac_handle_visibility_change (f);
10801 result = noErr;
10802 break;
10804 case kEventWindowBoundsChanging:
10805 result = CallNextEventHandler (next_handler, event);
10806 if (result != eventNotHandledErr)
10807 break;
10809 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
10810 NULL, sizeof (UInt32), NULL, &attributes);
10811 if (err != noErr)
10812 break;
10814 size_hints = FRAME_SIZE_HINTS (f);
10815 if ((attributes & kWindowBoundsChangeUserResize)
10816 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
10817 == (PResizeInc | PBaseSize | PMinSize)))
10819 Rect bounds;
10820 int width, height;
10822 err = GetEventParameter (event, kEventParamCurrentBounds,
10823 typeQDRectangle, NULL, sizeof (Rect),
10824 NULL, &bounds);
10825 if (err != noErr)
10826 break;
10828 width = bounds.right - bounds.left;
10829 height = bounds.bottom - bounds.top;
10831 if (width < size_hints->min_width)
10832 width = size_hints->min_width;
10833 else
10834 width = size_hints->base_width
10835 + (int) ((width - size_hints->base_width)
10836 / (float) size_hints->width_inc + .5)
10837 * size_hints->width_inc;
10839 if (height < size_hints->min_height)
10840 height = size_hints->min_height;
10841 else
10842 height = size_hints->base_height
10843 + (int) ((height - size_hints->base_height)
10844 / (float) size_hints->height_inc + .5)
10845 * size_hints->height_inc;
10847 bounds.right = bounds.left + width;
10848 bounds.bottom = bounds.top + height;
10849 SetEventParameter (event, kEventParamCurrentBounds,
10850 typeQDRectangle, sizeof (Rect), &bounds);
10851 result = noErr;
10853 break;
10855 case kEventWindowBoundsChanged:
10856 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
10857 NULL, sizeof (UInt32), NULL, &attributes);
10858 if (err != noErr)
10859 break;
10861 if (attributes & kWindowBoundsChangeSizeChanged)
10863 Rect bounds;
10865 err = GetEventParameter (event, kEventParamCurrentBounds,
10866 typeQDRectangle, NULL, sizeof (Rect),
10867 NULL, &bounds);
10868 if (err == noErr)
10870 int width, height;
10872 width = bounds.right - bounds.left;
10873 height = bounds.bottom - bounds.top;
10874 mac_handle_size_change (f, width, height);
10875 mac_wakeup_from_rne ();
10879 if (attributes & kWindowBoundsChangeOriginChanged)
10880 mac_handle_origin_change (f);
10882 result = noErr;
10883 break;
10885 /* -- window action events -- */
10887 case kEventWindowClose:
10889 struct input_event buf;
10891 EVENT_INIT (buf);
10892 buf.kind = DELETE_WINDOW_EVENT;
10893 XSETFRAME (buf.frame_or_window, f);
10894 buf.arg = Qnil;
10895 kbd_buffer_store_event (&buf);
10897 result = noErr;
10898 break;
10900 case kEventWindowGetIdealSize:
10901 result = CallNextEventHandler (next_handler, event);
10902 if (result != eventNotHandledErr)
10903 break;
10906 Point ideal_size = mac_get_ideal_size (f);
10908 err = SetEventParameter (event, kEventParamDimensions,
10909 typeQDPoint, sizeof (Point), &ideal_size);
10910 if (err == noErr)
10911 result = noErr;
10913 break;
10915 #ifdef MAC_OSX
10916 case kEventWindowToolbarSwitchMode:
10918 static const EventParamName names[] = {kEventParamDirectObject,
10919 kEventParamWindowMouseLocation,
10920 kEventParamKeyModifiers,
10921 kEventParamMouseButton,
10922 kEventParamClickCount,
10923 kEventParamMouseChord};
10924 static const EventParamType types[] = {typeWindowRef,
10925 typeQDPoint,
10926 typeUInt32,
10927 typeMouseButton,
10928 typeUInt32,
10929 typeUInt32};
10930 int num_params = sizeof (names) / sizeof (names[0]);
10932 err = mac_store_event_ref_as_apple_event (0, 0,
10933 Qwindow,
10934 Qtoolbar_switch_mode,
10935 event, num_params,
10936 names, types);
10938 if (err == noErr)
10939 result = noErr;
10940 break;
10941 #endif
10943 #if USE_MAC_TSM
10944 /* -- window focus events -- */
10946 case kEventWindowFocusAcquired:
10947 err = mac_tsm_resume ();
10948 if (err == noErr)
10949 result = noErr;
10950 break;
10952 case kEventWindowFocusRelinquish:
10953 err = mac_tsm_suspend ();
10954 if (err == noErr)
10955 result = noErr;
10956 break;
10957 #endif
10959 default:
10960 abort ();
10963 return result;
10966 static pascal OSStatus
10967 mac_handle_keyboard_event (next_handler, event, data)
10968 EventHandlerCallRef next_handler;
10969 EventRef event;
10970 void *data;
10972 OSStatus err, result = eventNotHandledErr;
10973 UInt32 event_kind, key_code, modifiers;
10974 unsigned char char_code;
10976 event_kind = GetEventKind (event);
10977 switch (event_kind)
10979 case kEventRawKeyDown:
10980 case kEventRawKeyRepeat:
10981 case kEventRawKeyUp:
10982 /* When using Carbon Events, we need to pass raw keyboard events
10983 to the TSM ourselves. If TSM handles it, it will pass back
10984 noErr, otherwise it will pass back "eventNotHandledErr" and
10985 we can process it normally. */
10986 result = CallNextEventHandler (next_handler, event);
10987 if (result != eventNotHandledErr)
10988 break;
10990 if (read_socket_inev == NULL)
10991 break;
10993 #if USE_MAC_TSM
10994 if (read_socket_inev->kind != NO_EVENT)
10996 result = noErr;
10997 break;
10999 #endif
11001 if (event_kind == kEventRawKeyUp)
11002 break;
11004 err = GetEventParameter (event, kEventParamKeyMacCharCodes,
11005 typeChar, NULL,
11006 sizeof (char), NULL, &char_code);
11007 if (err != noErr)
11008 break;
11010 err = GetEventParameter (event, kEventParamKeyCode,
11011 typeUInt32, NULL,
11012 sizeof (UInt32), NULL, &key_code);
11013 if (err != noErr)
11014 break;
11016 err = GetEventParameter (event, kEventParamKeyModifiers,
11017 typeUInt32, NULL,
11018 sizeof (UInt32), NULL, &modifiers);
11019 if (err != noErr)
11020 break;
11022 do_keystroke ((event_kind == kEventRawKeyDown ? keyDown : autoKey),
11023 char_code, key_code, modifiers,
11024 ((unsigned long)
11025 (GetEventTime (event) / kEventDurationMillisecond)),
11026 read_socket_inev);
11027 result = noErr;
11028 break;
11030 default:
11031 abort ();
11034 return result;
11037 static pascal OSStatus
11038 mac_handle_command_event (next_handler, event, data)
11039 EventHandlerCallRef next_handler;
11040 EventRef event;
11041 void *data;
11043 OSStatus err, result = eventNotHandledErr;
11044 HICommand command;
11045 static const EventParamName names[] =
11046 {kEventParamDirectObject, kEventParamKeyModifiers};
11047 static const EventParamType types[] =
11048 {typeHICommand, typeUInt32};
11049 int num_params = sizeof (names) / sizeof (names[0]);
11051 err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
11052 NULL, sizeof (HICommand), NULL, &command);
11053 if (err != noErr)
11054 return eventNotHandledErr;
11056 switch (GetEventKind (event))
11058 case kEventCommandProcess:
11059 result = CallNextEventHandler (next_handler, event);
11060 if (result != eventNotHandledErr)
11061 break;
11063 err = GetEventParameter (event, kEventParamDirectObject,
11064 typeHICommand, NULL,
11065 sizeof (HICommand), NULL, &command);
11067 if (err != noErr || command.commandID == 0)
11068 break;
11070 /* A HI command event is mapped to an Apple event whose event
11071 class symbol is `hi-command' and event ID is its command
11072 ID. */
11073 err = mac_store_event_ref_as_apple_event (0, command.commandID,
11074 Qhi_command, Qnil,
11075 event, num_params,
11076 names, types);
11077 if (err == noErr)
11078 result = noErr;
11079 break;
11081 default:
11082 abort ();
11085 return result;
11088 static pascal OSStatus
11089 mac_handle_mouse_event (next_handler, event, data)
11090 EventHandlerCallRef next_handler;
11091 EventRef event;
11092 void *data;
11094 OSStatus err, result = eventNotHandledErr;
11096 switch (GetEventKind (event))
11098 case kEventMouseWheelMoved:
11100 WindowRef wp;
11101 struct frame *f;
11102 EventMouseWheelAxis axis;
11103 SInt32 delta;
11104 Point point;
11106 result = CallNextEventHandler (next_handler, event);
11107 if (result != eventNotHandledErr || read_socket_inev == NULL)
11108 break;
11110 f = mac_focus_frame (&one_mac_display_info);
11112 err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
11113 NULL, sizeof (WindowRef), NULL, &wp);
11114 if (err != noErr
11115 || wp != FRAME_MAC_WINDOW (f))
11116 break;
11118 err = GetEventParameter (event, kEventParamMouseWheelAxis,
11119 typeMouseWheelAxis, NULL,
11120 sizeof (EventMouseWheelAxis), NULL, &axis);
11121 if (err != noErr || axis != kEventMouseWheelAxisY)
11122 break;
11124 err = GetEventParameter (event, kEventParamMouseLocation,
11125 typeQDPoint, NULL, sizeof (Point),
11126 NULL, &point);
11127 if (err != noErr)
11128 break;
11130 point.h -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
11131 point.v -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
11132 if (point.h < 0 || point.v < 0
11133 || EQ (window_from_coordinates (f, point.h, point.v, 0, 0, 0, 1),
11134 f->tool_bar_window))
11135 break;
11137 err = GetEventParameter (event, kEventParamMouseWheelDelta,
11138 typeSInt32, NULL, sizeof (SInt32),
11139 NULL, &delta);
11140 if (err != noErr)
11141 break;
11143 read_socket_inev->kind = WHEEL_EVENT;
11144 read_socket_inev->code = 0;
11145 read_socket_inev->modifiers =
11146 (mac_event_to_emacs_modifiers (event)
11147 | ((delta < 0) ? down_modifier : up_modifier));
11148 XSETINT (read_socket_inev->x, point.h);
11149 XSETINT (read_socket_inev->y, point.v);
11150 XSETFRAME (read_socket_inev->frame_or_window, f);
11152 result = noErr;
11154 break;
11156 default:
11157 abort ();
11160 return result;
11163 #if USE_MAC_TSM
11164 static pascal OSStatus
11165 mac_handle_text_input_event (next_handler, event, data)
11166 EventHandlerCallRef next_handler;
11167 EventRef event;
11168 void *data;
11170 OSStatus err, result;
11171 Lisp_Object id_key = Qnil;
11172 int num_params;
11173 const EventParamName *names;
11174 const EventParamType *types;
11175 static UInt32 seqno_uaia = 0;
11176 static const EventParamName names_uaia[] =
11177 {kEventParamTextInputSendComponentInstance,
11178 kEventParamTextInputSendRefCon,
11179 kEventParamTextInputSendSLRec,
11180 kEventParamTextInputSendFixLen,
11181 kEventParamTextInputSendText,
11182 kEventParamTextInputSendUpdateRng,
11183 kEventParamTextInputSendHiliteRng,
11184 kEventParamTextInputSendClauseRng,
11185 kEventParamTextInputSendPinRng,
11186 kEventParamTextInputSendTextServiceEncoding,
11187 kEventParamTextInputSendTextServiceMacEncoding,
11188 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
11189 static const EventParamType types_uaia[] =
11190 {typeComponentInstance,
11191 typeLongInteger,
11192 typeIntlWritingCode,
11193 typeLongInteger,
11194 #ifdef MAC_OSX
11195 typeUnicodeText,
11196 #else
11197 typeChar,
11198 #endif
11199 typeTextRangeArray,
11200 typeTextRangeArray,
11201 typeOffsetArray,
11202 typeTextRange,
11203 typeUInt32,
11204 typeUInt32,
11205 typeUInt32};
11206 static const EventParamName names_ufke[] =
11207 {kEventParamTextInputSendComponentInstance,
11208 kEventParamTextInputSendRefCon,
11209 kEventParamTextInputSendSLRec,
11210 kEventParamTextInputSendText};
11211 static const EventParamType types_ufke[] =
11212 {typeComponentInstance,
11213 typeLongInteger,
11214 typeIntlWritingCode,
11215 typeUnicodeText};
11217 result = CallNextEventHandler (next_handler, event);
11218 if (result != eventNotHandledErr)
11219 return result;
11221 switch (GetEventKind (event))
11223 case kEventTextInputUpdateActiveInputArea:
11224 id_key = Qupdate_active_input_area;
11225 num_params = sizeof (names_uaia) / sizeof (names_uaia[0]);
11226 names = names_uaia;
11227 types = types_uaia;
11228 SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
11229 typeUInt32, sizeof (UInt32), &seqno_uaia);
11230 seqno_uaia++;
11231 result = noErr;
11232 break;
11234 case kEventTextInputUnicodeForKeyEvent:
11236 EventRef kbd_event;
11237 UInt32 actual_size, modifiers, key_code;
11239 err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent,
11240 typeEventRef, NULL, sizeof (EventRef), NULL,
11241 &kbd_event);
11242 if (err == noErr)
11243 err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
11244 typeUInt32, NULL,
11245 sizeof (UInt32), NULL, &modifiers);
11246 if (err == noErr)
11247 err = GetEventParameter (kbd_event, kEventParamKeyCode,
11248 typeUInt32, NULL, sizeof (UInt32),
11249 NULL, &key_code);
11250 if (err == noErr && mac_mapped_modifiers (modifiers, key_code))
11251 /* There're mapped modifier keys. Process it in
11252 do_keystroke. */
11253 break;
11254 if (err == noErr)
11255 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
11256 typeUnicodeText, NULL, 0, &actual_size,
11257 NULL);
11258 if (err == noErr && actual_size == sizeof (UniChar))
11260 UniChar code;
11262 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
11263 typeUnicodeText, NULL,
11264 sizeof (UniChar), NULL, &code);
11265 if (err == noErr && code < 0x80)
11267 /* ASCII character. Process it in do_keystroke. */
11268 if (read_socket_inev && code >= 0x20 && code <= 0x7e
11269 && !(key_code <= 0x7f
11270 && keycode_to_xkeysym_table [key_code]))
11272 struct frame *f = mac_focus_frame (&one_mac_display_info);
11274 read_socket_inev->kind = ASCII_KEYSTROKE_EVENT;
11275 read_socket_inev->code = code;
11276 read_socket_inev->modifiers =
11277 mac_to_emacs_modifiers (modifiers, 0);
11278 read_socket_inev->modifiers |=
11279 (extra_keyboard_modifiers
11280 & (meta_modifier | alt_modifier
11281 | hyper_modifier | super_modifier));
11282 XSETFRAME (read_socket_inev->frame_or_window, f);
11284 break;
11287 if (err == noErr)
11289 /* Non-ASCII keystrokes without mapped modifiers are
11290 processed at the Lisp level. */
11291 id_key = Qunicode_for_key_event;
11292 num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
11293 names = names_ufke;
11294 types = types_ufke;
11295 result = noErr;
11298 break;
11300 case kEventTextInputOffsetToPos:
11302 struct frame *f;
11303 struct window *w;
11304 Point p;
11306 if (!OVERLAYP (Vmac_ts_active_input_overlay))
11307 break;
11309 /* Strictly speaking, this is not always correct because
11310 previous events may change some states about display. */
11311 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
11313 /* Active input area is displayed around the current point. */
11314 f = SELECTED_FRAME ();
11315 w = XWINDOW (f->selected_window);
11317 else if (WINDOWP (echo_area_window))
11319 /* Active input area is displayed in the echo area. */
11320 w = XWINDOW (echo_area_window);
11321 f = WINDOW_XFRAME (w);
11323 else
11324 break;
11326 p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
11327 + WINDOW_LEFT_FRINGE_WIDTH (w)
11328 + f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f));
11329 p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
11330 + FONT_BASE (FRAME_FONT (f))
11331 + f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f));
11332 err = SetEventParameter (event, kEventParamTextInputReplyPoint,
11333 typeQDPoint, sizeof (typeQDPoint), &p);
11334 if (err == noErr)
11335 result = noErr;
11337 break;
11339 default:
11340 abort ();
11343 if (!NILP (id_key))
11344 err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
11345 event, num_params,
11346 names, types);
11347 return result;
11349 #endif
11350 #endif /* TARGET_API_MAC_CARBON */
11353 OSStatus
11354 install_window_handler (window)
11355 WindowRef window;
11357 OSStatus err = noErr;
11359 #if TARGET_API_MAC_CARBON
11360 if (err == noErr)
11362 static const EventTypeSpec specs[] =
11364 /* -- window refresh events -- */
11365 {kEventClassWindow, kEventWindowUpdate},
11366 /* -- window state change events -- */
11367 {kEventClassWindow, kEventWindowShowing},
11368 {kEventClassWindow, kEventWindowHiding},
11369 {kEventClassWindow, kEventWindowShown},
11370 {kEventClassWindow, kEventWindowHidden},
11371 {kEventClassWindow, kEventWindowCollapsed},
11372 {kEventClassWindow, kEventWindowExpanded},
11373 {kEventClassWindow, kEventWindowBoundsChanging},
11374 {kEventClassWindow, kEventWindowBoundsChanged},
11375 /* -- window action events -- */
11376 {kEventClassWindow, kEventWindowClose},
11377 {kEventClassWindow, kEventWindowGetIdealSize},
11378 #ifdef MAC_OSX
11379 {kEventClassWindow, kEventWindowToolbarSwitchMode},
11380 #endif
11381 #if USE_MAC_TSM
11382 /* -- window focus events -- */
11383 {kEventClassWindow, kEventWindowFocusAcquired},
11384 {kEventClassWindow, kEventWindowFocusRelinquish},
11385 #endif
11387 static EventHandlerUPP handle_window_eventUPP = NULL;
11389 if (handle_window_eventUPP == NULL)
11390 handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
11392 err = InstallWindowEventHandler (window, handle_window_eventUPP,
11393 GetEventTypeCount (specs),
11394 specs, NULL, NULL);
11396 #endif
11398 if (err == noErr)
11399 err = install_drag_handler (window);
11401 return err;
11404 void
11405 remove_window_handler (window)
11406 WindowRef window;
11408 remove_drag_handler (window);
11411 #if TARGET_API_MAC_CARBON
11412 static OSStatus
11413 install_application_handler ()
11415 OSStatus err = noErr;
11417 if (err == noErr)
11419 static const EventTypeSpec specs[] =
11420 {{kEventClassKeyboard, kEventRawKeyDown},
11421 {kEventClassKeyboard, kEventRawKeyRepeat},
11422 {kEventClassKeyboard, kEventRawKeyUp}};
11424 err = InstallApplicationEventHandler (NewEventHandlerUPP
11425 (mac_handle_keyboard_event),
11426 GetEventTypeCount (specs),
11427 specs, NULL, NULL);
11430 if (err == noErr)
11432 static const EventTypeSpec specs[] =
11433 {{kEventClassCommand, kEventCommandProcess}};
11435 err = InstallApplicationEventHandler (NewEventHandlerUPP
11436 (mac_handle_command_event),
11437 GetEventTypeCount (specs),
11438 specs, NULL, NULL);
11441 if (err == noErr)
11443 static const EventTypeSpec specs[] =
11444 {{kEventClassMouse, kEventMouseWheelMoved}};
11446 err = InstallApplicationEventHandler (NewEventHandlerUPP
11447 (mac_handle_mouse_event),
11448 GetEventTypeCount (specs),
11449 specs, NULL, NULL);
11452 #if USE_MAC_TSM
11453 if (err == noErr)
11455 static const EventTypeSpec spec[] =
11456 {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
11457 {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
11458 {kEventClassTextInput, kEventTextInputOffsetToPos}};
11460 err = InstallApplicationEventHandler (NewEventHandlerUPP
11461 (mac_handle_text_input_event),
11462 GetEventTypeCount (spec),
11463 spec, NULL, NULL);
11465 #endif
11467 if (err == noErr)
11468 err = install_menu_target_item_handler ();
11470 #ifdef MAC_OSX
11471 if (err == noErr)
11472 err = install_service_handler ();
11473 #endif
11475 return err;
11477 #endif
11479 static pascal void
11480 mac_handle_dm_notification (event)
11481 AppleEvent *event;
11483 mac_screen_config_changed = 1;
11486 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11487 static void
11488 mac_handle_cg_display_reconfig (display, flags, user_info)
11489 CGDirectDisplayID display;
11490 CGDisplayChangeSummaryFlags flags;
11491 void *user_info;
11493 mac_screen_config_changed = 1;
11495 #endif
11497 static OSErr
11498 init_dm_notification_handler ()
11500 OSErr err = noErr;
11502 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
11503 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11504 if (CGDisplayRegisterReconfigurationCallback != NULL)
11505 #endif
11507 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig,
11508 NULL);
11510 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11511 else /* CGDisplayRegisterReconfigurationCallback == NULL */
11512 #endif
11513 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
11514 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
11516 static DMNotificationUPP handle_dm_notificationUPP = NULL;
11517 ProcessSerialNumber psn;
11519 if (handle_dm_notificationUPP == NULL)
11520 handle_dm_notificationUPP =
11521 NewDMNotificationUPP (mac_handle_dm_notification);
11523 err = GetCurrentProcess (&psn);
11524 if (err == noErr)
11525 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
11527 #endif
11529 return err;
11532 static void
11533 mac_get_screen_info (dpyinfo)
11534 struct mac_display_info *dpyinfo;
11536 #ifdef MAC_OSX
11537 /* HasDepth returns true if it is possible to have a 32 bit display,
11538 but this may not be what is actually used. Mac OSX can do better. */
11539 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
11540 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
11542 CGDisplayErr err;
11543 CGDisplayCount ndisps;
11544 CGDirectDisplayID *displays;
11546 err = CGGetActiveDisplayList (0, NULL, &ndisps);
11547 if (err == noErr)
11549 displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
11550 err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
11552 if (err == noErr)
11554 CGRect bounds = CGRectZero;
11556 while (ndisps-- > 0)
11557 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
11558 dpyinfo->height = CGRectGetHeight (bounds);
11559 dpyinfo->width = CGRectGetWidth (bounds);
11561 else
11563 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
11564 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
11567 #else /* !MAC_OSX */
11569 GDHandle gdh = GetMainDevice ();
11570 Rect rect = (**gdh).gdRect;
11572 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
11573 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
11574 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
11575 break;
11577 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
11578 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
11579 UnionRect (&rect, &(**gdh).gdRect, &rect);
11581 dpyinfo->height = rect.bottom - rect.top;
11582 dpyinfo->width = rect.right - rect.left;
11584 #endif /* !MAC_OSX */
11588 #if __profile__
11589 void
11590 profiler_exit_proc ()
11592 ProfilerDump ("\pEmacs.prof");
11593 ProfilerTerm ();
11595 #endif
11597 /* These few functions implement Emacs as a normal Mac application
11598 (almost): set up the heap and the Toolbox, handle necessary system
11599 events plus a few simple menu events. They also set up Emacs's
11600 access to functions defined in the rest of this file. Emacs uses
11601 function hooks to perform all its terminal I/O. A complete list of
11602 these functions appear in termhooks.h. For what they do, read the
11603 comments there and see also w32term.c and xterm.c. What's
11604 noticeably missing here is the event loop, which is normally
11605 present in most Mac application. After performing the necessary
11606 Mac initializations, main passes off control to emacs_main
11607 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
11608 (defined further below) to read input. This is where
11609 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
11611 #ifdef MAC_OS8
11612 #undef main
11614 main (void)
11616 #if __profile__ /* is the profiler on? */
11617 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
11618 exit(1);
11619 #endif
11621 #if __MWERKS__
11622 /* set creator and type for files created by MSL */
11623 _fcreator = MAC_EMACS_CREATOR_CODE;
11624 _ftype = 'TEXT';
11625 #endif
11627 do_init_managers ();
11629 do_get_menus ();
11631 #ifndef USE_LSB_TAG
11632 do_check_ram_size ();
11633 #endif
11635 init_emacs_passwd_dir ();
11637 init_environ ();
11639 init_coercion_handler ();
11641 initialize_applescript ();
11643 init_apple_event_handler ();
11645 init_dm_notification_handler ();
11648 char **argv;
11649 int argc = 0;
11651 /* set up argv array from STR# resource */
11652 get_string_list (&argv, ARGV_STRING_LIST_ID);
11653 while (argv[argc])
11654 argc++;
11656 /* free up AppleScript resources on exit */
11657 atexit (terminate_applescript);
11659 #if __profile__ /* is the profiler on? */
11660 atexit (profiler_exit_proc);
11661 #endif
11663 /* 3rd param "envp" never used in emacs_main */
11664 (void) emacs_main (argc, argv, 0);
11667 /* Never reached - real exit in Fkill_emacs */
11668 return 0;
11670 #endif
11672 #if !TARGET_API_MAC_CARBON
11673 static RgnHandle mouse_region = NULL;
11675 Boolean
11676 mac_wait_next_event (er, sleep_time, dequeue)
11677 EventRecord *er;
11678 UInt32 sleep_time;
11679 Boolean dequeue;
11681 static EventRecord er_buf = {nullEvent};
11682 UInt32 target_tick, current_tick;
11683 EventMask event_mask;
11685 if (mouse_region == NULL)
11686 mouse_region = NewRgn ();
11688 event_mask = everyEvent;
11689 if (!mac_ready_for_apple_events)
11690 event_mask -= highLevelEventMask;
11692 current_tick = TickCount ();
11693 target_tick = current_tick + sleep_time;
11695 if (er_buf.what == nullEvent)
11696 while (!WaitNextEvent (event_mask, &er_buf,
11697 target_tick - current_tick, mouse_region))
11699 current_tick = TickCount ();
11700 if (target_tick <= current_tick)
11701 return false;
11704 *er = er_buf;
11705 if (dequeue)
11706 er_buf.what = nullEvent;
11707 return true;
11709 #endif /* not TARGET_API_MAC_CARBON */
11711 #if TARGET_API_MAC_CARBON
11712 OSStatus
11713 mac_post_mouse_moved_event ()
11715 EventRef event = NULL;
11716 OSStatus err;
11718 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
11719 kEventAttributeNone, &event);
11720 if (err == noErr)
11722 Point mouse_pos;
11724 GetGlobalMouse (&mouse_pos);
11725 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
11726 sizeof (Point), &mouse_pos);
11728 if (err == noErr)
11730 UInt32 modifiers = GetCurrentKeyModifiers ();
11732 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
11733 sizeof (UInt32), &modifiers);
11735 if (err == noErr)
11736 err = PostEventToQueue (GetCurrentEventQueue (), event,
11737 kEventPriorityStandard);
11738 if (event)
11739 ReleaseEvent (event);
11741 return err;
11743 #endif
11745 /* Emacs calls this whenever it wants to read an input event from the
11746 user. */
11748 XTread_socket (sd, expected, hold_quit)
11749 int sd, expected;
11750 struct input_event *hold_quit;
11752 struct input_event inev;
11753 int count = 0;
11754 #if TARGET_API_MAC_CARBON
11755 EventRef eventRef;
11756 EventTargetRef toolbox_dispatcher;
11757 #endif
11758 EventRecord er;
11759 struct mac_display_info *dpyinfo = &one_mac_display_info;
11761 if (interrupt_input_blocked)
11763 interrupt_input_pending = 1;
11764 return -1;
11767 interrupt_input_pending = 0;
11768 BLOCK_INPUT;
11770 /* So people can tell when we have read the available input. */
11771 input_signal_count++;
11773 ++handling_signal;
11775 #if TARGET_API_MAC_CARBON
11776 toolbox_dispatcher = GetEventDispatcherTarget ();
11778 while (
11779 #if USE_CG_DRAWING
11780 mac_prepare_for_quickdraw (NULL),
11781 #endif
11782 !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
11783 kEventRemoveFromQueue, &eventRef))
11784 #else /* !TARGET_API_MAC_CARBON */
11785 while (mac_wait_next_event (&er, 0, true))
11786 #endif /* !TARGET_API_MAC_CARBON */
11788 int do_help = 0;
11789 struct frame *f;
11790 unsigned long timestamp;
11792 EVENT_INIT (inev);
11793 inev.kind = NO_EVENT;
11794 inev.arg = Qnil;
11796 #if TARGET_API_MAC_CARBON
11797 timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
11799 if (!mac_convert_event_ref (eventRef, &er))
11800 goto OTHER;
11801 #else /* !TARGET_API_MAC_CARBON */
11802 timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
11803 #endif /* !TARGET_API_MAC_CARBON */
11805 switch (er.what)
11807 case mouseDown:
11808 case mouseUp:
11810 WindowRef window_ptr;
11811 ControlPartCode part_code;
11812 int tool_bar_p = 0;
11814 #if TARGET_API_MAC_CARBON
11815 OSStatus err;
11817 /* This is needed to send mouse events like aqua window
11818 buttons to the correct handler. */
11819 read_socket_inev = &inev;
11820 err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
11821 read_socket_inev = NULL;
11822 if (err != eventNotHandledErr)
11823 break;
11824 #endif
11825 last_mouse_glyph_frame = 0;
11827 if (dpyinfo->grabbed && last_mouse_frame
11828 && FRAME_LIVE_P (last_mouse_frame))
11830 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
11831 part_code = inContent;
11833 else
11835 part_code = FindWindow (er.where, &window_ptr);
11836 if (tip_window && window_ptr == tip_window)
11838 HideWindow (tip_window);
11839 part_code = FindWindow (er.where, &window_ptr);
11843 if (er.what != mouseDown &&
11844 (part_code != inContent || dpyinfo->grabbed == 0))
11845 break;
11847 switch (part_code)
11849 case inMenuBar:
11850 f = mac_focus_frame (dpyinfo);
11851 saved_menu_event_location = er.where;
11852 inev.kind = MENU_BAR_ACTIVATE_EVENT;
11853 XSETFRAME (inev.frame_or_window, f);
11854 break;
11856 case inContent:
11857 if (
11858 #if TARGET_API_MAC_CARBON
11859 FrontNonFloatingWindow ()
11860 #else
11861 FrontWindow ()
11862 #endif
11863 != window_ptr
11864 || (mac_window_to_frame (window_ptr)
11865 != dpyinfo->x_focus_frame))
11866 SelectWindow (window_ptr);
11867 else
11869 ControlPartCode control_part_code;
11870 ControlRef ch;
11871 Point mouse_loc;
11872 #ifdef MAC_OSX
11873 ControlKind control_kind;
11874 #endif
11876 f = mac_window_to_frame (window_ptr);
11877 /* convert to local coordinates of new window */
11878 mouse_loc.h = (er.where.h
11879 - (f->left_pos
11880 + FRAME_OUTER_TO_INNER_DIFF_X (f)));
11881 mouse_loc.v = (er.where.v
11882 - (f->top_pos
11883 + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
11884 #if TARGET_API_MAC_CARBON
11885 ch = FindControlUnderMouse (mouse_loc, window_ptr,
11886 &control_part_code);
11887 #ifdef MAC_OSX
11888 if (ch)
11889 GetControlKind (ch, &control_kind);
11890 #endif
11891 #else
11892 control_part_code = FindControl (mouse_loc, window_ptr,
11893 &ch);
11894 #endif
11896 #if TARGET_API_MAC_CARBON
11897 inev.code = mac_get_mouse_btn (eventRef);
11898 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
11899 #else
11900 inev.code = mac_get_emulated_btn (er.modifiers);
11901 inev.modifiers = mac_to_emacs_modifiers (er.modifiers, 0);
11902 #endif
11903 XSETINT (inev.x, mouse_loc.h);
11904 XSETINT (inev.y, mouse_loc.v);
11906 if ((dpyinfo->grabbed && tracked_scroll_bar)
11907 || (ch != 0
11908 #ifndef USE_TOOLKIT_SCROLL_BARS
11909 /* control_part_code becomes kControlNoPart if
11910 a progress indicator is clicked. */
11911 && control_part_code != kControlNoPart
11912 #else /* USE_TOOLKIT_SCROLL_BARS */
11913 #ifdef MAC_OSX
11914 && control_kind.kind == kControlKindScrollBar
11915 #endif /* MAC_OSX */
11916 #endif /* USE_TOOLKIT_SCROLL_BARS */
11919 struct scroll_bar *bar;
11921 if (dpyinfo->grabbed && tracked_scroll_bar)
11923 bar = tracked_scroll_bar;
11924 #ifndef USE_TOOLKIT_SCROLL_BARS
11925 control_part_code = kControlIndicatorPart;
11926 #endif
11928 else
11929 bar = (struct scroll_bar *) GetControlReference (ch);
11930 #ifdef USE_TOOLKIT_SCROLL_BARS
11931 /* Make the "Ctrl-Mouse-2 splits window" work
11932 for toolkit scroll bars. */
11933 if (inev.modifiers & ctrl_modifier)
11934 x_scroll_bar_handle_click (bar, control_part_code,
11935 &er, &inev);
11936 else if (er.what == mouseDown)
11937 x_scroll_bar_handle_press (bar, control_part_code,
11938 mouse_loc, &inev);
11939 else
11940 x_scroll_bar_handle_release (bar, &inev);
11941 #else /* not USE_TOOLKIT_SCROLL_BARS */
11942 x_scroll_bar_handle_click (bar, control_part_code,
11943 &er, &inev);
11944 if (er.what == mouseDown
11945 && control_part_code == kControlIndicatorPart)
11946 tracked_scroll_bar = bar;
11947 else
11948 tracked_scroll_bar = NULL;
11949 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11951 else
11953 Lisp_Object window;
11954 int x = mouse_loc.h;
11955 int y = mouse_loc.v;
11957 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
11958 if (EQ (window, f->tool_bar_window))
11960 if (er.what == mouseDown)
11961 handle_tool_bar_click (f, x, y, 1, 0);
11962 else
11963 handle_tool_bar_click (f, x, y, 0,
11964 inev.modifiers);
11965 tool_bar_p = 1;
11967 else
11969 XSETFRAME (inev.frame_or_window, f);
11970 inev.kind = MOUSE_CLICK_EVENT;
11974 if (er.what == mouseDown)
11976 dpyinfo->grabbed |= (1 << inev.code);
11977 last_mouse_frame = f;
11979 if (!tool_bar_p)
11980 last_tool_bar_item = -1;
11982 else
11984 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
11985 /* If a button is released though it was not
11986 previously pressed, that would be because
11987 of multi-button emulation. */
11988 dpyinfo->grabbed = 0;
11989 else
11990 dpyinfo->grabbed &= ~(1 << inev.code);
11993 /* Ignore any mouse motion that happened before
11994 this event; any subsequent mouse-movement Emacs
11995 events should reflect only motion after the
11996 ButtonPress. */
11997 if (f != 0)
11998 f->mouse_moved = 0;
12000 #ifdef USE_TOOLKIT_SCROLL_BARS
12001 if (inev.kind == MOUSE_CLICK_EVENT
12002 || (inev.kind == SCROLL_BAR_CLICK_EVENT
12003 && (inev.modifiers & ctrl_modifier)))
12004 #endif
12005 switch (er.what)
12007 case mouseDown:
12008 inev.modifiers |= down_modifier;
12009 break;
12010 case mouseUp:
12011 inev.modifiers |= up_modifier;
12012 break;
12015 break;
12017 case inDrag:
12018 #if TARGET_API_MAC_CARBON
12019 case inProxyIcon:
12020 if (IsWindowPathSelectClick (window_ptr, &er))
12022 WindowPathSelect (window_ptr, NULL, NULL);
12023 break;
12025 if (part_code == inProxyIcon
12026 && (TrackWindowProxyDrag (window_ptr, er.where)
12027 != errUserWantsToDragWindow))
12028 break;
12029 DragWindow (window_ptr, er.where, NULL);
12030 #else /* not TARGET_API_MAC_CARBON */
12031 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
12032 /* Update the frame parameters. */
12034 struct frame *f = mac_window_to_frame (window_ptr);
12036 if (f && !f->async_iconified)
12037 mac_handle_origin_change (f);
12039 #endif /* not TARGET_API_MAC_CARBON */
12040 break;
12042 case inGoAway:
12043 if (TrackGoAway (window_ptr, er.where))
12045 inev.kind = DELETE_WINDOW_EVENT;
12046 XSETFRAME (inev.frame_or_window,
12047 mac_window_to_frame (window_ptr));
12049 break;
12051 /* window resize handling added --ben */
12052 case inGrow:
12053 do_grow_window (window_ptr, &er);
12054 break;
12056 /* window zoom handling added --ben */
12057 case inZoomIn:
12058 case inZoomOut:
12059 if (TrackBox (window_ptr, er.where, part_code))
12060 do_zoom_window (window_ptr, part_code);
12061 break;
12063 #if USE_MAC_TOOLBAR
12064 case inStructure:
12066 OSStatus err;
12067 HIViewRef ch;
12069 err = HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr),
12070 eventRef, &ch);
12071 /* This doesn't work on Mac OS X 10.2. */
12072 if (err == noErr)
12073 HIViewClick (ch, eventRef);
12075 break;
12076 #endif /* USE_MAC_TOOLBAR */
12078 default:
12079 break;
12082 break;
12084 #if !TARGET_API_MAC_CARBON
12085 case updateEvt:
12086 do_window_update ((WindowRef) er.message);
12087 break;
12088 #endif
12090 case osEvt:
12091 #if TARGET_API_MAC_CARBON
12092 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
12093 != eventNotHandledErr)
12094 break;
12095 #endif
12096 switch ((er.message >> 24) & 0x000000FF)
12098 #if USE_MAC_TSM
12099 case suspendResumeMessage:
12100 if (er.message & resumeFlag)
12101 mac_tsm_resume ();
12102 else
12103 mac_tsm_suspend ();
12104 break;
12105 #endif
12107 case mouseMovedMessage:
12108 #if !TARGET_API_MAC_CARBON
12109 SetRectRgn (mouse_region, er.where.h, er.where.v,
12110 er.where.h + 1, er.where.v + 1);
12111 #endif
12112 previous_help_echo_string = help_echo_string;
12113 help_echo_string = Qnil;
12115 if (dpyinfo->grabbed && last_mouse_frame
12116 && FRAME_LIVE_P (last_mouse_frame))
12117 f = last_mouse_frame;
12118 else
12119 f = dpyinfo->x_focus_frame;
12121 if (dpyinfo->mouse_face_hidden)
12123 dpyinfo->mouse_face_hidden = 0;
12124 clear_mouse_face (dpyinfo);
12127 if (f)
12129 WindowRef wp = FRAME_MAC_WINDOW (f);
12130 Point mouse_pos;
12132 mouse_pos.h = (er.where.h
12133 - (f->left_pos
12134 + FRAME_OUTER_TO_INNER_DIFF_X (f)));
12135 mouse_pos.v = (er.where.v
12136 - (f->top_pos
12137 + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
12138 if (dpyinfo->grabbed && tracked_scroll_bar)
12139 #ifdef USE_TOOLKIT_SCROLL_BARS
12140 x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
12141 mouse_pos, &inev);
12142 #else /* not USE_TOOLKIT_SCROLL_BARS */
12143 x_scroll_bar_note_movement (tracked_scroll_bar,
12144 mouse_pos.v
12145 - XINT (tracked_scroll_bar->top),
12146 er.when * (1000 / 60));
12147 #endif /* not USE_TOOLKIT_SCROLL_BARS */
12148 else
12150 /* Generate SELECT_WINDOW_EVENTs when needed. */
12151 if (!NILP (Vmouse_autoselect_window))
12153 Lisp_Object window;
12155 window = window_from_coordinates (f,
12156 mouse_pos.h,
12157 mouse_pos.v,
12158 0, 0, 0, 0);
12160 /* Window will be selected only when it is
12161 not selected now and last mouse movement
12162 event was not in it. Minibuffer window
12163 will be selected only when it is active. */
12164 if (WINDOWP (window)
12165 && !EQ (window, last_window)
12166 && !EQ (window, selected_window)
12167 /* For click-to-focus window managers
12168 create event iff we don't leave the
12169 selected frame. */
12170 && (focus_follows_mouse
12171 || (EQ (XWINDOW (window)->frame,
12172 XWINDOW (selected_window)->frame))))
12174 inev.kind = SELECT_WINDOW_EVENT;
12175 inev.frame_or_window = window;
12178 last_window=window;
12180 if (!note_mouse_movement (f, &mouse_pos))
12181 help_echo_string = previous_help_echo_string;
12182 #if USE_MAC_TOOLBAR
12183 else
12184 mac_tool_bar_note_mouse_movement (f, eventRef);
12185 #endif
12189 /* If the contents of the global variable
12190 help_echo_string has changed, generate a
12191 HELP_EVENT. */
12192 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
12193 do_help = 1;
12194 break;
12196 break;
12198 case activateEvt:
12200 WindowRef window_ptr = (WindowRef) er.message;
12201 OSErr err;
12202 ControlRef root_control;
12204 if (window_ptr == tip_window)
12206 HideWindow (tip_window);
12207 break;
12210 if (!is_emacs_window (window_ptr))
12211 goto OTHER;
12213 f = mac_window_to_frame (window_ptr);
12215 if ((er.modifiers & activeFlag) != 0)
12217 /* A window has been activated */
12218 Point mouse_loc;
12220 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
12221 if (err == noErr)
12222 ActivateControl (root_control);
12224 x_detect_focus_change (dpyinfo, &er, &inev);
12226 mouse_loc.h = (er.where.h
12227 - (f->left_pos
12228 + FRAME_OUTER_TO_INNER_DIFF_X (f)));
12229 mouse_loc.v = (er.where.v
12230 - (f->top_pos
12231 + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
12232 /* Window-activated event counts as mouse movement,
12233 so update things that depend on mouse position. */
12234 note_mouse_movement (f, &mouse_loc);
12236 else
12238 /* A window has been deactivated */
12239 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
12240 if (err == noErr)
12241 DeactivateControl (root_control);
12243 #ifdef USE_TOOLKIT_SCROLL_BARS
12244 if (dpyinfo->grabbed && tracked_scroll_bar)
12246 struct input_event event;
12248 EVENT_INIT (event);
12249 event.kind = NO_EVENT;
12250 x_scroll_bar_handle_release (tracked_scroll_bar, &event);
12251 if (event.kind != NO_EVENT)
12253 event.timestamp = timestamp;
12254 kbd_buffer_store_event_hold (&event, hold_quit);
12255 count++;
12258 #endif
12259 dpyinfo->grabbed = 0;
12261 x_detect_focus_change (dpyinfo, &er, &inev);
12263 if (f == dpyinfo->mouse_face_mouse_frame)
12265 /* If we move outside the frame, then we're
12266 certainly no longer on any text in the
12267 frame. */
12268 clear_mouse_face (dpyinfo);
12269 dpyinfo->mouse_face_mouse_frame = 0;
12272 /* Generate a nil HELP_EVENT to cancel a help-echo.
12273 Do it only if there's something to cancel.
12274 Otherwise, the startup message is cleared when the
12275 mouse leaves the frame. */
12276 if (any_help_event_p)
12277 do_help = -1;
12280 break;
12282 case keyDown:
12283 case keyUp:
12284 case autoKey:
12285 ObscureCursor ();
12287 f = mac_focus_frame (dpyinfo);
12288 XSETFRAME (inev.frame_or_window, f);
12290 /* If mouse-highlight is an integer, input clears out mouse
12291 highlighting. */
12292 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
12293 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
12295 clear_mouse_face (dpyinfo);
12296 dpyinfo->mouse_face_hidden = 1;
12300 UInt32 modifiers = er.modifiers, mapped_modifiers;
12301 UInt32 key_code = (er.message & keyCodeMask) >> 8;
12303 #ifdef MAC_OSX
12304 GetEventParameter (eventRef, kEventParamKeyModifiers,
12305 typeUInt32, NULL,
12306 sizeof (UInt32), NULL, &modifiers);
12307 #endif
12308 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
12310 #if TARGET_API_MAC_CARBON
12311 if (!(mapped_modifiers
12312 & ~(mac_pass_command_to_system ? cmdKey : 0)
12313 & ~(mac_pass_control_to_system ? controlKey : 0)))
12314 goto OTHER;
12315 else
12316 #endif
12317 if (er.what != keyUp)
12318 do_keystroke (er.what, er.message & charCodeMask,
12319 key_code, modifiers, timestamp, &inev);
12321 break;
12323 case kHighLevelEvent:
12324 AEProcessAppleEvent (&er);
12325 break;
12327 default:
12328 OTHER:
12329 #if TARGET_API_MAC_CARBON
12331 OSStatus err;
12333 read_socket_inev = &inev;
12334 err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
12335 read_socket_inev = NULL;
12337 #endif
12338 break;
12340 #if TARGET_API_MAC_CARBON
12341 ReleaseEvent (eventRef);
12342 #endif
12344 if (inev.kind != NO_EVENT)
12346 inev.timestamp = timestamp;
12347 kbd_buffer_store_event_hold (&inev, hold_quit);
12348 count++;
12351 if (do_help
12352 && !(hold_quit && hold_quit->kind != NO_EVENT))
12354 Lisp_Object frame;
12356 if (f)
12357 XSETFRAME (frame, f);
12358 else
12359 frame = Qnil;
12361 if (do_help > 0)
12363 any_help_event_p = 1;
12364 gen_help_event (help_echo_string, frame, help_echo_window,
12365 help_echo_object, help_echo_pos);
12367 else
12369 help_echo_string = Qnil;
12370 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
12372 count++;
12376 /* If the focus was just given to an autoraising frame,
12377 raise it now. */
12378 /* ??? This ought to be able to handle more than one such frame. */
12379 if (pending_autoraise_frame)
12381 x_raise_frame (pending_autoraise_frame);
12382 pending_autoraise_frame = 0;
12385 if (mac_screen_config_changed)
12387 mac_get_screen_info (dpyinfo);
12388 mac_screen_config_changed = 0;
12391 #if !TARGET_API_MAC_CARBON
12392 /* Check which frames are still visible. We do this here because
12393 there doesn't seem to be any direct notification from the Window
12394 Manager that the visibility of a window has changed (at least,
12395 not in all cases). */
12397 Lisp_Object tail, frame;
12399 FOR_EACH_FRAME (tail, frame)
12401 struct frame *f = XFRAME (frame);
12403 /* The tooltip has been drawn already. Avoid the
12404 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
12405 if (EQ (frame, tip_frame))
12406 continue;
12408 if (FRAME_MAC_P (f))
12409 mac_handle_visibility_change (f);
12412 #endif
12414 --handling_signal;
12415 UNBLOCK_INPUT;
12416 return count;
12420 /* Need to override CodeWarrior's input function so no conversion is
12421 done on newlines Otherwise compiled functions in .elc files will be
12422 read incorrectly. Defined in ...:MSL C:MSL
12423 Common:Source:buffer_io.c. */
12424 #ifdef __MWERKS__
12425 void
12426 __convert_to_newlines (unsigned char * p, size_t * n)
12428 #pragma unused(p,n)
12431 void
12432 __convert_from_newlines (unsigned char * p, size_t * n)
12434 #pragma unused(p,n)
12436 #endif
12438 #ifdef MAC_OS8
12439 void
12440 make_mac_terminal_frame (struct frame *f)
12442 Lisp_Object frame;
12443 Rect r;
12445 XSETFRAME (frame, f);
12447 f->output_method = output_mac;
12448 f->output_data.mac = (struct mac_output *)
12449 xmalloc (sizeof (struct mac_output));
12450 bzero (f->output_data.mac, sizeof (struct mac_output));
12452 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
12454 FRAME_COLS (f) = 96;
12455 FRAME_LINES (f) = 4;
12457 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
12458 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
12460 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
12462 f->output_data.mac->cursor_pixel = 0;
12463 f->output_data.mac->border_pixel = 0x00ff00;
12464 f->output_data.mac->mouse_pixel = 0xff00ff;
12465 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
12467 f->output_data.mac->text_cursor = kThemeIBeamCursor;
12468 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
12469 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
12470 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
12471 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
12472 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
12474 FRAME_FONTSET (f) = -1;
12475 f->output_data.mac->explicit_parent = 0;
12476 f->left_pos = 8;
12477 f->top_pos = 32;
12478 f->border_width = 0;
12480 f->internal_border_width = 0;
12482 f->auto_raise = 1;
12483 f->auto_lower = 1;
12485 f->new_text_cols = 0;
12486 f->new_text_lines = 0;
12488 SetRect (&r, f->left_pos, f->top_pos,
12489 f->left_pos + FRAME_PIXEL_WIDTH (f),
12490 f->top_pos + FRAME_PIXEL_HEIGHT (f));
12492 BLOCK_INPUT;
12494 if (!(FRAME_MAC_WINDOW (f) =
12495 NewCWindow (NULL, &r, "\p", true, dBoxProc,
12496 (WindowRef) -1, 1, (long) f->output_data.mac)))
12497 abort ();
12498 /* so that update events can find this mac_output struct */
12499 f->output_data.mac->mFP = f; /* point back to emacs frame */
12501 UNBLOCK_INPUT;
12503 x_make_gc (f);
12505 /* Need to be initialized for unshow_buffer in window.c. */
12506 selected_window = f->selected_window;
12508 Fmodify_frame_parameters (frame,
12509 Fcons (Fcons (Qfont,
12510 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
12511 Fmodify_frame_parameters (frame,
12512 Fcons (Fcons (Qforeground_color,
12513 build_string ("black")), Qnil));
12514 Fmodify_frame_parameters (frame,
12515 Fcons (Fcons (Qbackground_color,
12516 build_string ("white")), Qnil));
12518 #endif
12521 /***********************************************************************
12522 Initialization
12523 ***********************************************************************/
12525 static int mac_initialized = 0;
12527 static XrmDatabase
12528 mac_make_rdb (xrm_option)
12529 const char *xrm_option;
12531 XrmDatabase database;
12533 database = xrm_get_preference_database (NULL);
12534 if (xrm_option)
12535 xrm_merge_string_database (database, xrm_option);
12537 return database;
12540 struct mac_display_info *
12541 mac_term_init (display_name, xrm_option, resource_name)
12542 Lisp_Object display_name;
12543 char *xrm_option;
12544 char *resource_name;
12546 struct mac_display_info *dpyinfo;
12548 BLOCK_INPUT;
12550 if (!mac_initialized)
12552 mac_initialize ();
12553 mac_initialized = 1;
12556 if (x_display_list)
12557 error ("Sorry, this version can only handle one display");
12559 dpyinfo = &one_mac_display_info;
12560 bzero (dpyinfo, sizeof (*dpyinfo));
12562 #ifdef MAC_OSX
12563 dpyinfo->mac_id_name
12564 = (char *) xmalloc (SCHARS (Vinvocation_name)
12565 + SCHARS (Vsystem_name)
12566 + 2);
12567 sprintf (dpyinfo->mac_id_name, "%s@%s",
12568 SDATA (Vinvocation_name), SDATA (Vsystem_name));
12569 #else
12570 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
12571 strcpy (dpyinfo->mac_id_name, "Mac Display");
12572 #endif
12574 dpyinfo->reference_count = 0;
12575 dpyinfo->resx = 72.0;
12576 dpyinfo->resy = 72.0;
12578 mac_get_screen_info (dpyinfo);
12580 dpyinfo->grabbed = 0;
12581 dpyinfo->root_window = NULL;
12582 dpyinfo->image_cache = make_image_cache ();
12584 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
12585 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
12586 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
12587 dpyinfo->mouse_face_window = Qnil;
12588 dpyinfo->mouse_face_overlay = Qnil;
12589 dpyinfo->mouse_face_hidden = 0;
12591 dpyinfo->xrdb = mac_make_rdb (xrm_option);
12593 /* Put this display on the chain. */
12594 dpyinfo->next = x_display_list;
12595 x_display_list = dpyinfo;
12597 /* Put it on x_display_name_list. */
12598 x_display_name_list = Fcons (Fcons (display_name,
12599 Fcons (Qnil, dpyinfo->xrdb)),
12600 x_display_name_list);
12601 dpyinfo->name_list_element = XCAR (x_display_name_list);
12603 UNBLOCK_INPUT;
12605 return dpyinfo;
12608 /* Get rid of display DPYINFO, assuming all frames are already gone. */
12610 void
12611 x_delete_display (dpyinfo)
12612 struct mac_display_info *dpyinfo;
12614 int i;
12616 /* Discard this display from x_display_name_list and x_display_list.
12617 We can't use Fdelq because that can quit. */
12618 if (! NILP (x_display_name_list)
12619 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
12620 x_display_name_list = XCDR (x_display_name_list);
12621 else
12623 Lisp_Object tail;
12625 tail = x_display_name_list;
12626 while (CONSP (tail) && CONSP (XCDR (tail)))
12628 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
12630 XSETCDR (tail, XCDR (XCDR (tail)));
12631 break;
12633 tail = XCDR (tail);
12637 if (x_display_list == dpyinfo)
12638 x_display_list = dpyinfo->next;
12639 else
12641 struct x_display_info *tail;
12643 for (tail = x_display_list; tail; tail = tail->next)
12644 if (tail->next == dpyinfo)
12645 tail->next = tail->next->next;
12648 /* Free the font names in the font table. */
12649 for (i = 0; i < dpyinfo->n_fonts; i++)
12650 if (dpyinfo->font_table[i].name)
12652 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
12653 xfree (dpyinfo->font_table[i].full_name);
12654 xfree (dpyinfo->font_table[i].name);
12657 if (dpyinfo->font_table)
12659 if (dpyinfo->font_table->font_encoder)
12660 xfree (dpyinfo->font_table->font_encoder);
12661 xfree (dpyinfo->font_table);
12663 if (dpyinfo->mac_id_name)
12664 xfree (dpyinfo->mac_id_name);
12666 if (x_display_list == 0)
12668 mac_clear_font_name_table ();
12669 bzero (dpyinfo, sizeof (*dpyinfo));
12674 static void
12675 init_menu_bar ()
12677 #ifdef MAC_OSX
12678 OSStatus err;
12679 MenuRef menu;
12680 MenuItemIndex menu_index;
12682 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
12683 &menu, &menu_index);
12684 if (err == noErr)
12685 SetMenuItemCommandKey (menu, menu_index, false, 0);
12686 EnableMenuCommand (NULL, kHICommandPreferences);
12687 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
12688 &menu, &menu_index);
12689 if (err == noErr)
12691 SetMenuItemCommandKey (menu, menu_index, false, 0);
12692 InsertMenuItemTextWithCFString (menu, NULL,
12693 0, kMenuItemAttrSeparator, 0);
12694 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
12695 0, 0, kHICommandAbout);
12697 #else /* !MAC_OSX */
12698 #if TARGET_API_MAC_CARBON
12699 SetMenuItemCommandID (GetMenuRef (M_APPLE), I_ABOUT, kHICommandAbout);
12700 #endif
12701 #endif
12704 #if USE_MAC_TSM
12705 static void
12706 init_tsm ()
12708 #ifdef MAC_OSX
12709 static InterfaceTypeList types = {kUnicodeDocument};
12710 #else
12711 static InterfaceTypeList types = {kTextService};
12712 #endif
12714 NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
12715 &tsm_document_id, 0);
12717 #endif
12719 /* Set up use of X before we make the first connection. */
12721 extern frame_parm_handler mac_frame_parm_handlers[];
12723 static struct redisplay_interface x_redisplay_interface =
12725 mac_frame_parm_handlers,
12726 x_produce_glyphs,
12727 x_write_glyphs,
12728 x_insert_glyphs,
12729 x_clear_end_of_line,
12730 x_scroll_run,
12731 x_after_update_window_line,
12732 x_update_window_begin,
12733 x_update_window_end,
12734 x_cursor_to,
12735 x_flush,
12736 #if USE_CG_DRAWING
12737 mac_flush_display_optional,
12738 #else
12739 0, /* flush_display_optional */
12740 #endif
12741 x_clear_window_mouse_face,
12742 x_get_glyph_overhangs,
12743 x_fix_overlapping_area,
12744 x_draw_fringe_bitmap,
12745 #if USE_CG_DRAWING
12746 mac_define_fringe_bitmap,
12747 mac_destroy_fringe_bitmap,
12748 #else
12749 0, /* define_fringe_bitmap */
12750 0, /* destroy_fringe_bitmap */
12751 #endif
12752 mac_per_char_metric,
12753 mac_encode_char,
12754 mac_compute_glyph_string_overhangs,
12755 x_draw_glyph_string,
12756 mac_define_frame_cursor,
12757 mac_clear_frame_area,
12758 mac_draw_window_cursor,
12759 mac_draw_vertical_window_border,
12760 mac_shift_glyphs_for_insert
12763 void
12764 mac_initialize ()
12766 rif = &x_redisplay_interface;
12768 clear_frame_hook = x_clear_frame;
12769 ins_del_lines_hook = x_ins_del_lines;
12770 delete_glyphs_hook = x_delete_glyphs;
12771 ring_bell_hook = XTring_bell;
12772 reset_terminal_modes_hook = XTreset_terminal_modes;
12773 set_terminal_modes_hook = XTset_terminal_modes;
12774 update_begin_hook = x_update_begin;
12775 update_end_hook = x_update_end;
12776 set_terminal_window_hook = XTset_terminal_window;
12777 read_socket_hook = XTread_socket;
12778 frame_up_to_date_hook = XTframe_up_to_date;
12779 mouse_position_hook = XTmouse_position;
12780 frame_rehighlight_hook = XTframe_rehighlight;
12781 frame_raise_lower_hook = XTframe_raise_lower;
12783 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
12784 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
12785 redeem_scroll_bar_hook = XTredeem_scroll_bar;
12786 judge_scroll_bars_hook = XTjudge_scroll_bars;
12788 scroll_region_ok = 1; /* we'll scroll partial frames */
12789 char_ins_del_ok = 1;
12790 line_ins_del_ok = 1; /* we'll just blt 'em */
12791 fast_clear_end_of_line = 1; /* X does this well */
12792 memory_below_frame = 0; /* we don't remember what scrolls
12793 off the bottom */
12794 baud_rate = 19200;
12796 last_tool_bar_item = -1;
12797 any_help_event_p = 0;
12799 /* Try to use interrupt input; if we can't, then start polling. */
12800 Fset_input_mode (Qt, Qnil, Qt, Qnil);
12802 BLOCK_INPUT;
12804 #if TARGET_API_MAC_CARBON
12806 install_application_handler ();
12808 init_menu_bar ();
12810 #if USE_MAC_TSM
12811 init_tsm ();
12812 #endif
12814 #ifdef MAC_OSX
12815 init_coercion_handler ();
12817 init_apple_event_handler ();
12819 init_dm_notification_handler ();
12821 if (!inhibit_window_system)
12823 static const ProcessSerialNumber psn = {0, kCurrentProcess};
12825 SetFrontProcess (&psn);
12827 #endif
12828 #endif
12830 #if USE_CG_DRAWING
12831 init_cg_color ();
12833 mac_init_fringe ();
12834 #endif
12836 UNBLOCK_INPUT;
12840 void
12841 syms_of_macterm ()
12843 #if 0
12844 staticpro (&x_error_message_string);
12845 x_error_message_string = Qnil;
12846 #endif
12848 Qcontrol = intern ("control"); staticpro (&Qcontrol);
12849 Qmeta = intern ("meta"); staticpro (&Qmeta);
12850 Qalt = intern ("alt"); staticpro (&Qalt);
12851 Qhyper = intern ("hyper"); staticpro (&Qhyper);
12852 Qsuper = intern ("super"); staticpro (&Qsuper);
12853 Qmodifier_value = intern ("modifier-value");
12854 staticpro (&Qmodifier_value);
12856 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
12857 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
12858 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
12859 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
12860 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
12862 #if TARGET_API_MAC_CARBON
12863 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
12864 #ifdef MAC_OSX
12865 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
12866 staticpro (&Qtoolbar_switch_mode);
12867 #if USE_MAC_FONT_PANEL
12868 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
12869 Qselection = intern ("selection"); staticpro (&Qselection);
12870 #endif
12872 Qservice = intern ("service"); staticpro (&Qservice);
12873 Qpaste = intern ("paste"); staticpro (&Qpaste);
12874 Qperform = intern ("perform"); staticpro (&Qperform);
12875 #endif
12876 #if USE_MAC_TSM
12877 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
12878 Qupdate_active_input_area = intern ("update-active-input-area");
12879 staticpro (&Qupdate_active_input_area);
12880 Qunicode_for_key_event = intern ("unicode-for-key-event");
12881 staticpro (&Qunicode_for_key_event);
12882 #endif
12883 #endif
12885 #ifdef MAC_OSX
12886 Fprovide (intern ("mac-carbon"), Qnil);
12887 #endif
12889 staticpro (&Qreverse);
12890 Qreverse = intern ("reverse");
12892 staticpro (&x_display_name_list);
12893 x_display_name_list = Qnil;
12895 staticpro (&last_mouse_scroll_bar);
12896 last_mouse_scroll_bar = Qnil;
12898 staticpro (&fm_font_family_alist);
12899 fm_font_family_alist = Qnil;
12901 #if USE_ATSUI
12902 staticpro (&atsu_font_id_hash);
12903 atsu_font_id_hash = Qnil;
12905 staticpro (&fm_style_face_attributes_alist);
12906 fm_style_face_attributes_alist = Qnil;
12907 #endif
12909 #if USE_MAC_TSM
12910 staticpro (&saved_ts_script_language_on_focus);
12911 saved_ts_script_language_on_focus = Qnil;
12912 #endif
12914 /* We don't yet support this, but defining this here avoids whining
12915 from cus-start.el and other places, like "M-x set-variable". */
12916 DEFVAR_BOOL ("x-use-underline-position-properties",
12917 &x_use_underline_position_properties,
12918 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12919 A value of nil means ignore them. If you encounter fonts with bogus
12920 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12921 to 4.1, set this to nil.
12923 NOTE: Not supported on Mac yet. */);
12924 x_use_underline_position_properties = 0;
12926 DEFVAR_BOOL ("x-underline-at-descent-line",
12927 &x_underline_at_descent_line,
12928 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
12929 A value of nil means to draw the underline according to the value of the
12930 variable `x-use-underline-position-properties', which is usually at the
12931 baseline level. The default value is nil. */);
12932 x_underline_at_descent_line = 0;
12934 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
12935 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
12936 #ifdef USE_TOOLKIT_SCROLL_BARS
12937 Vx_toolkit_scroll_bars = Qt;
12938 #else
12939 Vx_toolkit_scroll_bars = Qnil;
12940 #endif
12942 staticpro (&last_mouse_motion_frame);
12943 last_mouse_motion_frame = Qnil;
12945 /* Variables to configure modifier key assignment. */
12947 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
12948 doc: /* *Modifier key assumed when the Mac control key is pressed.
12949 The value can be `control', `meta', `alt', `hyper', or `super' for the
12950 respective modifier. The default is `control'. */);
12951 Vmac_control_modifier = Qcontrol;
12953 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
12954 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
12955 The value can be `control', `meta', `alt', `hyper', or `super' for the
12956 respective modifier. If the value is nil then the key will act as the
12957 normal Mac control modifier, and the option key can be used to compose
12958 characters depending on the chosen Mac keyboard setting. */);
12959 Vmac_option_modifier = Qnil;
12961 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
12962 doc: /* *Modifier key assumed when the Mac command key is pressed.
12963 The value can be `control', `meta', `alt', `hyper', or `super' for the
12964 respective modifier. The default is `meta'. */);
12965 Vmac_command_modifier = Qmeta;
12967 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
12968 doc: /* *Modifier key assumed when the Mac function key is pressed.
12969 The value can be `control', `meta', `alt', `hyper', or `super' for the
12970 respective modifier. Note that remapping the function key may lead to
12971 unexpected results for some keys on non-US/GB keyboards. */);
12972 Vmac_function_modifier = Qnil;
12974 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12975 &Vmac_emulate_three_button_mouse,
12976 doc: /* *Specify a way of three button mouse emulation.
12977 The value can be nil, t, or the symbol `reverse'.
12978 A value of nil means that no emulation should be done and the modifiers
12979 should be placed on the mouse-1 event.
12980 t means that when the option-key is held down while pressing the mouse
12981 button, the click will register as mouse-2 and while the command-key
12982 is held down, the click will register as mouse-3.
12983 The symbol `reverse' means that the option-key will register for
12984 mouse-3 and the command-key will register for mouse-2. */);
12985 Vmac_emulate_three_button_mouse = Qnil;
12987 #if TARGET_API_MAC_CARBON
12988 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
12989 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12990 Otherwise, the right click will be treated as mouse-2 and the wheel
12991 button will be mouse-3. */);
12992 mac_wheel_button_is_mouse_2 = 1;
12994 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
12995 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12996 mac_pass_command_to_system = 1;
12998 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
12999 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
13000 mac_pass_control_to_system = 1;
13002 #endif
13004 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
13005 doc: /* *If non-nil, allow anti-aliasing.
13006 The text will be rendered using Core Graphics text rendering which
13007 may anti-alias the text. */);
13008 #if USE_CG_DRAWING
13009 mac_use_core_graphics = 1;
13010 #else
13011 mac_use_core_graphics = 0;
13012 #endif
13014 /* Register an entry for `mac-roman' so that it can be used when
13015 creating the terminal frame on Mac OS 9 before loading
13016 term/mac-win.elc. */
13017 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
13018 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
13019 Each entry should be of the form:
13021 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
13023 where CHARSET-NAME is a string used in font names to identify the
13024 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
13025 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
13026 Vmac_charset_info_alist =
13027 Fcons (list3 (build_string ("mac-roman"),
13028 make_number (smRoman), Qnil), Qnil);
13030 #if USE_MAC_TSM
13031 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
13032 doc: /* Overlay used to display Mac TSM active input area. */);
13033 Vmac_ts_active_input_overlay = Qnil;
13035 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
13036 doc: /* *How to change Mac TSM script/language when a frame gets focus.
13037 If the value is t, the input script and language are restored to those
13038 used in the last focus frame. If the value is a pair of integers, the
13039 input script and language codes, which are defined in the Script
13040 Manager, are set to its car and cdr parts, respectively. Otherwise,
13041 Emacs doesn't set them and thus follows the system default behavior. */);
13042 Vmac_ts_script_language_on_focus = Qnil;
13043 #endif
13046 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
13047 (do not change this comment) */