(get_overlay_strings_1): Add missing argument type.
[emacs.git] / src / macterm.c
blobb3e163029c6438889b3c27a659943d6024cebce2
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 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
41 used instead. */
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
46 #include <Sound.h>
47 #include <Events.h>
48 #include <Script.h>
49 #include <Resources.h>
50 #include <Fonts.h>
51 #include <TextUtils.h>
52 #include <LowMem.h>
53 #include <Controls.h>
54 #include <Windows.h>
55 #include <Displays.h>
56 #if defined (__MRC__) || (__MSL__ >= 0x6000)
57 #include <ControlDefinitions.h>
58 #endif
60 #if __profile__
61 #include <profiler.h>
62 #endif
63 #endif /* not TARGET_API_MAC_CARBON */
65 #include "systty.h"
66 #include "systime.h"
68 #include <ctype.h>
69 #include <errno.h>
70 #include <setjmp.h>
71 #include <sys/stat.h>
73 #include "charset.h"
74 #include "coding.h"
75 #include "frame.h"
76 #include "dispextern.h"
77 #include "fontset.h"
78 #include "termhooks.h"
79 #include "termopts.h"
80 #include "termchar.h"
81 #include "disptab.h"
82 #include "buffer.h"
83 #include "window.h"
84 #include "keyboard.h"
85 #include "intervals.h"
86 #include "atimer.h"
87 #include "keymap.h"
91 /* Non-nil means Emacs uses toolkit scroll bars. */
93 Lisp_Object Vx_toolkit_scroll_bars;
95 /* If non-zero, the text will be rendered using Core Graphics text
96 rendering which may anti-alias the text. */
97 int mac_use_core_graphics;
100 /* Non-zero means that a HELP_EVENT has been generated since Emacs
101 start. */
103 static int any_help_event_p;
105 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
106 static Lisp_Object last_window;
108 /* Non-zero means make use of UNDERLINE_POSITION font properties.
109 (Not yet supported.) */
110 int x_use_underline_position_properties;
112 /* Non-zero means to draw the underline at the same place as the descent line. */
114 int x_underline_at_descent_line;
116 /* This is a chain of structures for all the X displays currently in
117 use. */
119 struct x_display_info *x_display_list;
121 /* This is a list of cons cells, each of the form (NAME
122 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
123 x_display_list and in the same order. NAME is the name of the
124 frame. FONT-LIST-CACHE records previous values returned by
125 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
126 equivalent, which is implemented with a Lisp object, for the
127 display. */
129 Lisp_Object x_display_name_list;
131 /* This is display since Mac does not support multiple ones. */
132 struct mac_display_info one_mac_display_info;
134 /* Frame being updated by update_frame. This is declared in term.c.
135 This is set by update_begin and looked at by all the XT functions.
136 It is zero while not inside an update. In that case, the XT
137 functions assume that `selected_frame' is the frame to apply to. */
139 extern struct frame *updating_frame;
141 /* This is a frame waiting to be auto-raised, within XTread_socket. */
143 struct frame *pending_autoraise_frame;
145 /* Mouse movement.
147 Formerly, we used PointerMotionHintMask (in standard_event_mask)
148 so that we would have to call XQueryPointer after each MotionNotify
149 event to ask for another such event. However, this made mouse tracking
150 slow, and there was a bug that made it eventually stop.
152 Simply asking for MotionNotify all the time seems to work better.
154 In order to avoid asking for motion events and then throwing most
155 of them away or busy-polling the server for mouse positions, we ask
156 the server for pointer motion hints. This means that we get only
157 one event per group of mouse movements. "Groups" are delimited by
158 other kinds of events (focus changes and button clicks, for
159 example), or by XQueryPointer calls; when one of these happens, we
160 get another MotionNotify event the next time the mouse moves. This
161 is at least as efficient as getting motion events when mouse
162 tracking is on, and I suspect only negligibly worse when tracking
163 is off. */
165 /* Where the mouse was last time we reported a mouse event. */
167 static Rect last_mouse_glyph;
168 static FRAME_PTR last_mouse_glyph_frame;
170 /* The scroll bar in which the last X motion event occurred.
172 If the last X motion event occurred in a scroll bar, we set this so
173 XTmouse_position can know whether to report a scroll bar motion or
174 an ordinary motion.
176 If the last X motion event didn't occur in a scroll bar, we set
177 this to Qnil, to tell XTmouse_position to return an ordinary motion
178 event. */
180 static Lisp_Object last_mouse_scroll_bar;
182 /* This is a hack. We would really prefer that XTmouse_position would
183 return the time associated with the position it returns, but there
184 doesn't seem to be any way to wrest the time-stamp from the server
185 along with the position query. So, we just keep track of the time
186 of the last movement we received, and return that in hopes that
187 it's somewhat accurate. */
189 static Time last_mouse_movement_time;
191 struct scroll_bar *tracked_scroll_bar = NULL;
193 /* Incremented by XTread_socket whenever it really tries to read
194 events. */
196 #ifdef __STDC__
197 static int volatile input_signal_count;
198 #else
199 static int input_signal_count;
200 #endif
202 extern Lisp_Object Vsystem_name;
204 extern Lisp_Object Qeql;
206 /* A mask of extra modifier bits to put into every keyboard char. */
208 extern EMACS_INT extra_keyboard_modifiers;
210 /* The keysyms to use for the various modifiers. */
212 static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
214 extern int inhibit_window_system;
216 #if __MRC__ && !TARGET_API_MAC_CARBON
217 QDGlobals qd; /* QuickDraw global information structure. */
218 #endif
220 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
222 struct mac_display_info *mac_display_info_for_display (Display *);
223 static void x_update_window_end P_ ((struct window *, int, int));
224 int x_catch_errors P_ ((Display *));
225 void x_uncatch_errors P_ ((Display *, int));
226 void x_lower_frame P_ ((struct frame *));
227 void x_scroll_bar_clear P_ ((struct frame *));
228 int x_had_errors_p P_ ((Display *));
229 void x_wm_set_size_hint P_ ((struct frame *, long, int));
230 void x_raise_frame P_ ((struct frame *));
231 void x_set_window_size P_ ((struct frame *, int, int, int));
232 void x_wm_set_window_state P_ ((struct frame *, int));
233 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
234 void mac_initialize P_ ((void));
235 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
236 static int x_compute_min_glyph_bounds P_ ((struct frame *));
237 static void x_update_end P_ ((struct frame *));
238 static void XTframe_up_to_date P_ ((struct frame *));
239 static void XTset_terminal_modes P_ ((void));
240 static void XTreset_terminal_modes P_ ((void));
241 static void x_clear_frame P_ ((void));
242 static void frame_highlight P_ ((struct frame *));
243 static void frame_unhighlight P_ ((struct frame *));
244 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
245 static void mac_focus_changed P_ ((int, struct mac_display_info *,
246 struct frame *, struct input_event *));
247 static void x_detect_focus_change P_ ((struct mac_display_info *,
248 const EventRecord *,
249 struct input_event *));
250 static void XTframe_rehighlight P_ ((struct frame *));
251 static void x_frame_rehighlight P_ ((struct x_display_info *));
252 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
253 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
254 enum text_cursor_kinds));
256 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
257 static void x_flush P_ ((struct frame *f));
258 static void x_update_begin P_ ((struct frame *));
259 static void x_update_window_begin P_ ((struct window *));
260 static void x_after_update_window_line P_ ((struct glyph_row *));
261 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
262 enum scroll_bar_part *,
263 Lisp_Object *, Lisp_Object *,
264 unsigned long *));
266 static int is_emacs_window P_ ((WindowPtr));
267 static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
268 static void XSetFont P_ ((Display *, GC, XFontStruct *));
270 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
271 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
272 #define GC_FONT(gc) ((gc)->xgcv.font)
273 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
275 #define CG_SET_FILL_COLOR(context, color) \
276 CGContextSetRGBFillColor (context, \
277 RED_FROM_ULONG (color) / 255.0f, \
278 GREEN_FROM_ULONG (color) / 255.0f, \
279 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
280 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
281 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
282 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
283 do { \
284 if (CGColorGetTypeID != NULL) \
285 CGContextSetFillColorWithColor (context, cg_color); \
286 else \
287 CG_SET_FILL_COLOR (context, color); \
288 } while (0)
289 #else
290 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
291 CGContextSetFillColorWithColor (context, cg_color)
292 #endif
293 #else
294 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
295 CG_SET_FILL_COLOR (context, color)
296 #endif
297 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
298 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
299 (gc)->cg_fore_color)
300 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
301 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
302 (gc)->cg_back_color)
305 #define CG_SET_STROKE_COLOR(context, color) \
306 CGContextSetRGBStrokeColor (context, \
307 RED_FROM_ULONG (color) / 255.0f, \
308 GREEN_FROM_ULONG (color) / 255.0f, \
309 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
310 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
311 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
312 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
313 do { \
314 if (CGColorGetTypeID != NULL) \
315 CGContextSetStrokeColorWithColor (context, cg_color); \
316 else \
317 CG_SET_STROKE_COLOR (context, color); \
318 } while (0)
319 #else
320 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
321 CGContextSetStrokeColorWithColor (context, cg_color)
322 #endif
323 #else
324 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
325 CG_SET_STROKE_COLOR (context, color)
326 #endif
327 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
328 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
329 (gc)->cg_fore_color)
331 #if USE_CG_DRAWING
332 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
334 /* Fringe bitmaps. */
336 static int max_fringe_bmp = 0;
337 static CGImageRef *fringe_bmp = 0;
339 static CGColorSpaceRef mac_cg_color_space_rgb;
340 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
341 static CGColorRef mac_cg_color_black;
342 #endif
344 static void
345 init_cg_color ()
347 mac_cg_color_space_rgb = CGColorSpaceCreateDeviceRGB ();
348 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
349 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
350 /* Don't check the availability of CGColorCreate; this symbol is
351 defined even in Mac OS X 10.1. */
352 if (CGColorGetTypeID != NULL)
353 #endif
355 float rgba[] = {0.0f, 0.0f, 0.0f, 1.0f};
357 mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba);
359 #endif
362 static CGContextRef
363 mac_begin_cg_clip (f, gc)
364 struct frame *f;
365 GC gc;
367 CGContextRef context = FRAME_CG_CONTEXT (f);
369 if (!context)
371 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
372 FRAME_CG_CONTEXT (f) = context;
375 CGContextSaveGState (context);
376 CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
377 CGContextScaleCTM (context, 1, -1);
378 if (gc && gc->n_clip_rects)
379 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
381 return context;
384 static void
385 mac_end_cg_clip (f)
386 struct frame *f;
388 CGContextRestoreGState (FRAME_CG_CONTEXT (f));
391 void
392 mac_prepare_for_quickdraw (f)
393 struct frame *f;
395 if (f == NULL)
397 Lisp_Object rest, frame;
398 FOR_EACH_FRAME (rest, frame)
399 if (FRAME_MAC_P (XFRAME (frame)))
400 mac_prepare_for_quickdraw (XFRAME (frame));
402 else
404 CGContextRef context = FRAME_CG_CONTEXT (f);
406 if (context)
408 CGContextSynchronize (context);
409 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
410 &FRAME_CG_CONTEXT (f));
414 #endif
416 static RgnHandle saved_port_clip_region = NULL;
418 static void
419 mac_begin_clip (gc)
420 GC gc;
422 static RgnHandle new_region = NULL;
424 if (saved_port_clip_region == NULL)
425 saved_port_clip_region = NewRgn ();
426 if (new_region == NULL)
427 new_region = NewRgn ();
429 if (gc->n_clip_rects)
431 GetClip (saved_port_clip_region);
432 SectRgn (saved_port_clip_region, gc->clip_region, new_region);
433 SetClip (new_region);
437 static void
438 mac_end_clip (gc)
439 GC gc;
441 if (gc->n_clip_rects)
442 SetClip (saved_port_clip_region);
446 /* X display function emulation */
448 void
449 XFreePixmap (display, pixmap)
450 Display *display; /* not used */
451 Pixmap pixmap;
453 DisposeGWorld (pixmap);
457 /* Mac version of XDrawLine. */
459 static void
460 mac_draw_line (f, gc, x1, y1, x2, y2)
461 struct frame *f;
462 GC gc;
463 int x1, y1, x2, y2;
465 #if USE_CG_DRAWING
466 CGContextRef context;
467 float gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
469 if (y1 != y2)
470 gx1 += 0.5f, gx2 += 0.5f;
471 if (x1 != x2)
472 gy1 += 0.5f, gy2 += 0.5f;
474 context = mac_begin_cg_clip (f, gc);
475 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
476 CGContextBeginPath (context);
477 CGContextMoveToPoint (context, gx1, gy1);
478 CGContextAddLineToPoint (context, gx2, gy2);
479 CGContextClosePath (context);
480 CGContextStrokePath (context);
481 mac_end_cg_clip (f);
482 #else
483 if (x1 == x2)
485 if (y1 > y2)
486 y1--;
487 else if (y2 > y1)
488 y2--;
490 else if (y1 == y2)
492 if (x1 > x2)
493 x1--;
494 else
495 x2--;
498 SetPortWindowPort (FRAME_MAC_WINDOW (f));
500 RGBForeColor (GC_FORE_COLOR (gc));
502 mac_begin_clip (gc);
503 MoveTo (x1, y1);
504 LineTo (x2, y2);
505 mac_end_clip (gc);
506 #endif
509 /* Mac version of XDrawLine (to Pixmap). */
511 void
512 XDrawLine (display, p, gc, x1, y1, x2, y2)
513 Display *display;
514 Pixmap p;
515 GC gc;
516 int x1, y1, x2, y2;
518 CGrafPtr old_port;
519 GDHandle old_gdh;
521 if (x1 == x2)
523 if (y1 > y2)
524 y1--;
525 else if (y2 > y1)
526 y2--;
528 else if (y1 == y2)
530 if (x1 > x2)
531 x1--;
532 else
533 x2--;
536 GetGWorld (&old_port, &old_gdh);
537 SetGWorld (p, NULL);
539 RGBForeColor (GC_FORE_COLOR (gc));
541 LockPixels (GetGWorldPixMap (p));
542 MoveTo (x1, y1);
543 LineTo (x2, y2);
544 UnlockPixels (GetGWorldPixMap (p));
546 SetGWorld (old_port, old_gdh);
550 static void
551 mac_erase_rectangle (f, gc, x, y, width, height)
552 struct frame *f;
553 GC gc;
554 int x, y;
555 unsigned int width, height;
557 #if USE_CG_DRAWING
558 CGContextRef context;
560 context = mac_begin_cg_clip (f, gc);
561 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
562 CGContextFillRect (context, CGRectMake (x, y, width, height));
563 mac_end_cg_clip (f);
564 #else
565 Rect r;
567 SetPortWindowPort (FRAME_MAC_WINDOW (f));
569 RGBBackColor (GC_BACK_COLOR (gc));
570 SetRect (&r, x, y, x + width, y + height);
572 mac_begin_clip (gc);
573 EraseRect (&r);
574 mac_end_clip (gc);
576 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
577 #endif
581 /* Mac version of XClearArea. */
583 void
584 mac_clear_area (f, x, y, width, height)
585 struct frame *f;
586 int x, y;
587 unsigned int width, height;
589 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
592 /* Mac version of XClearWindow. */
594 static void
595 mac_clear_window (f)
596 struct frame *f;
598 #if USE_CG_DRAWING
599 CGContextRef context;
600 GC gc = FRAME_NORMAL_GC (f);
602 context = mac_begin_cg_clip (f, NULL);
603 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
604 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
605 FRAME_PIXEL_HEIGHT (f)));
606 mac_end_cg_clip (f);
607 #else
608 SetPortWindowPort (FRAME_MAC_WINDOW (f));
610 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
612 #if TARGET_API_MAC_CARBON
614 Rect r;
616 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
617 EraseRect (&r);
619 #else /* not TARGET_API_MAC_CARBON */
620 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
621 #endif /* not TARGET_API_MAC_CARBON */
622 #endif
626 /* Mac replacement for XCopyArea. */
628 #if USE_CG_DRAWING
629 static void
630 mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
631 dest_x, dest_y, overlay_p)
632 CGImageRef image;
633 struct frame *f;
634 GC gc;
635 int src_x, src_y;
636 unsigned int width, height;
637 int dest_x, dest_y, overlay_p;
639 CGContextRef context;
640 float port_height = FRAME_PIXEL_HEIGHT (f);
641 CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
643 context = mac_begin_cg_clip (f, gc);
644 if (!overlay_p)
646 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
647 CGContextFillRect (context, dest_rect);
649 CGContextClipToRect (context, dest_rect);
650 CGContextScaleCTM (context, 1, -1);
651 CGContextTranslateCTM (context, 0, -port_height);
652 if (CGImageIsMask (image))
653 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
654 CGContextDrawImage (context,
655 CGRectMake (dest_x - src_x,
656 port_height - (dest_y - src_y
657 + CGImageGetHeight (image)),
658 CGImageGetWidth (image),
659 CGImageGetHeight (image)),
660 image);
661 mac_end_cg_clip (f);
664 #else /* !USE_CG_DRAWING */
666 static void
667 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
668 struct frame *f;
669 GC gc;
670 int x, y, width, height;
671 unsigned short *bits;
672 int overlay_p;
674 BitMap bitmap;
675 Rect r;
677 bitmap.rowBytes = sizeof(unsigned short);
678 bitmap.baseAddr = (char *)bits;
679 SetRect (&(bitmap.bounds), 0, 0, width, height);
681 SetPortWindowPort (FRAME_MAC_WINDOW (f));
683 RGBForeColor (GC_FORE_COLOR (gc));
684 RGBBackColor (GC_BACK_COLOR (gc));
685 SetRect (&r, x, y, x + width, y + height);
687 mac_begin_clip (gc);
688 #if TARGET_API_MAC_CARBON
690 CGrafPtr port;
692 GetPort (&port);
693 LockPortBits (port);
694 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
695 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
696 UnlockPortBits (port);
698 #else /* not TARGET_API_MAC_CARBON */
699 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
700 overlay_p ? srcOr : srcCopy, 0);
701 #endif /* not TARGET_API_MAC_CARBON */
702 mac_end_clip (gc);
704 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
706 #endif /* !USE_CG_DRAWING */
709 /* Mac replacement for XCreateBitmapFromBitmapData. */
711 static void
712 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
713 BitMap *bitmap;
714 char *bits;
715 int w, h;
717 static const unsigned char swap_nibble[16]
718 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
719 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
720 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
721 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
722 int i, j, w1;
723 char *p;
725 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
726 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
727 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
728 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
729 for (i = 0; i < h; i++)
731 p = bitmap->baseAddr + i * bitmap->rowBytes;
732 for (j = 0; j < w1; j++)
734 /* Bitswap XBM bytes to match how Mac does things. */
735 unsigned char c = *bits++;
736 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
737 | (swap_nibble[(c>>4) & 0xf]));
741 SetRect (&(bitmap->bounds), 0, 0, w, h);
745 static void
746 mac_free_bitmap (bitmap)
747 BitMap *bitmap;
749 xfree (bitmap->baseAddr);
753 Pixmap
754 XCreatePixmap (display, w, width, height, depth)
755 Display *display; /* not used */
756 WindowPtr w;
757 unsigned int width, height;
758 unsigned int depth;
760 Pixmap pixmap;
761 Rect r;
762 QDErr err;
764 SetPortWindowPort (w);
766 SetRect (&r, 0, 0, width, height);
767 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
768 if (depth == 1)
769 #endif
770 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
771 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
772 else
773 /* CreateCGImageFromPixMaps requires ARGB format. */
774 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
775 #endif
776 if (err != noErr)
777 return NULL;
778 return pixmap;
782 Pixmap
783 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
784 Display *display; /* not used */
785 WindowPtr w;
786 char *data;
787 unsigned int width, height;
788 unsigned long fg, bg;
789 unsigned int depth;
791 Pixmap pixmap;
792 BitMap bitmap;
793 CGrafPtr old_port;
794 GDHandle old_gdh;
795 static GC gc = NULL; /* not reentrant */
797 if (gc == NULL)
798 gc = XCreateGC (display, w, 0, NULL);
800 pixmap = XCreatePixmap (display, w, width, height, depth);
801 if (pixmap == NULL)
802 return NULL;
804 GetGWorld (&old_port, &old_gdh);
805 SetGWorld (pixmap, NULL);
806 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
807 XSetForeground (display, gc, fg);
808 XSetBackground (display, gc, bg);
809 RGBForeColor (GC_FORE_COLOR (gc));
810 RGBBackColor (GC_BACK_COLOR (gc));
811 LockPixels (GetGWorldPixMap (pixmap));
812 #if TARGET_API_MAC_CARBON
813 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
814 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
815 #else /* not TARGET_API_MAC_CARBON */
816 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
817 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
818 #endif /* not TARGET_API_MAC_CARBON */
819 UnlockPixels (GetGWorldPixMap (pixmap));
820 SetGWorld (old_port, old_gdh);
821 mac_free_bitmap (&bitmap);
823 return pixmap;
827 /* Mac replacement for XFillRectangle. */
829 static void
830 mac_fill_rectangle (f, gc, x, y, width, height)
831 struct frame *f;
832 GC gc;
833 int x, y;
834 unsigned int width, height;
836 #if USE_CG_DRAWING
837 CGContextRef context;
839 context = mac_begin_cg_clip (f, gc);
840 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
841 CGContextFillRect (context, CGRectMake (x, y, width, height));
842 mac_end_cg_clip (f);
843 #else
844 Rect r;
846 SetPortWindowPort (FRAME_MAC_WINDOW (f));
848 RGBForeColor (GC_FORE_COLOR (gc));
849 SetRect (&r, x, y, x + width, y + height);
851 mac_begin_clip (gc);
852 PaintRect (&r); /* using foreground color of gc */
853 mac_end_clip (gc);
854 #endif
858 /* Mac replacement for XDrawRectangle: dest is a window. */
860 static void
861 mac_draw_rectangle (f, gc, x, y, width, height)
862 struct frame *f;
863 GC gc;
864 int x, y;
865 unsigned int width, height;
867 #if USE_CG_DRAWING
868 CGContextRef context;
870 context = mac_begin_cg_clip (f, gc);
871 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
872 CGContextStrokeRect (context,
873 CGRectMake (x + 0.5f, y + 0.5f, width, height));
874 mac_end_cg_clip (f);
875 #else
876 Rect r;
878 SetPortWindowPort (FRAME_MAC_WINDOW (f));
880 RGBForeColor (GC_FORE_COLOR (gc));
881 SetRect (&r, x, y, x + width + 1, y + height + 1);
883 mac_begin_clip (gc);
884 FrameRect (&r); /* using foreground color of gc */
885 mac_end_clip (gc);
886 #endif
890 #if USE_ATSUI
891 static OSStatus
892 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
893 ConstUniCharArrayPtr text;
894 UniCharCount text_length;
895 ATSUStyle style;
896 ATSUTextLayout *text_layout;
898 OSStatus err;
899 static ATSUTextLayout saved_text_layout = NULL; /* not reentrant */
901 if (saved_text_layout == NULL)
903 static const UniCharCount lengths[] = {kATSUToTextEnd};
904 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
905 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
906 static ATSLineLayoutOptions line_layout =
907 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
908 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
909 | kATSLineUseQDRendering
910 #else
911 kATSLineIsDisplayOnly | kATSLineFractDisable
912 #endif
914 static const ATSUAttributeValuePtr values[] = {&line_layout};
916 err = ATSUCreateTextLayoutWithTextPtr (text,
917 kATSUFromTextBeginning,
918 kATSUToTextEnd,
919 text_length,
920 1, lengths, &style,
921 &saved_text_layout);
922 if (err == noErr)
923 err = ATSUSetLayoutControls (saved_text_layout,
924 sizeof (tags) / sizeof (tags[0]),
925 tags, sizes, values);
926 /* XXX: Should we do this? */
927 if (err == noErr)
928 err = ATSUSetTransientFontMatching (saved_text_layout, true);
930 else
932 err = ATSUSetRunStyle (saved_text_layout, style,
933 kATSUFromTextBeginning, kATSUToTextEnd);
934 if (err == noErr)
935 err = ATSUSetTextPointerLocation (saved_text_layout, text,
936 kATSUFromTextBeginning,
937 kATSUToTextEnd,
938 text_length);
941 if (err == noErr)
942 *text_layout = saved_text_layout;
943 return err;
945 #endif
948 static void
949 mac_invert_rectangle (f, x, y, width, height)
950 struct frame *f;
951 int x, y;
952 unsigned int width, height;
954 Rect r;
956 #if USE_CG_DRAWING
957 mac_prepare_for_quickdraw (f);
958 #endif
959 SetPortWindowPort (FRAME_MAC_WINDOW (f));
961 SetRect (&r, x, y, x + width, y + height);
963 InvertRect (&r);
967 static void
968 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
969 overstrike_p, bytes_per_char)
970 struct frame *f;
971 GC gc;
972 int x, y;
973 char *buf;
974 int nchars, bg_width, overstrike_p, bytes_per_char;
976 SetPortWindowPort (FRAME_MAC_WINDOW (f));
978 #if USE_ATSUI
979 if (GC_FONT (gc)->mac_style)
981 OSStatus err;
982 ATSUTextLayout text_layout;
984 xassert (bytes_per_char == 2);
986 #ifndef WORDS_BIG_ENDIAN
988 int i;
989 UniChar *text = (UniChar *)buf;
991 for (i = 0; i < nchars; i++)
992 text[i] = EndianU16_BtoN (text[i]);
994 #endif
995 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
996 nchars,
997 GC_FONT (gc)->mac_style,
998 &text_layout);
999 if (err != noErr)
1000 return;
1001 #ifdef MAC_OSX
1002 if (!mac_use_core_graphics)
1004 #endif
1005 #if USE_CG_DRAWING
1006 mac_prepare_for_quickdraw (f);
1007 #endif
1008 mac_begin_clip (gc);
1009 RGBForeColor (GC_FORE_COLOR (gc));
1010 if (bg_width)
1012 Rect r;
1014 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1015 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1016 RGBBackColor (GC_BACK_COLOR (gc));
1017 EraseRect (&r);
1018 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1020 MoveTo (x, y);
1021 ATSUDrawText (text_layout,
1022 kATSUFromTextBeginning, kATSUToTextEnd,
1023 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1024 if (overstrike_p)
1026 MoveTo (x + 1, y);
1027 ATSUDrawText (text_layout,
1028 kATSUFromTextBeginning, kATSUToTextEnd,
1029 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1031 mac_end_clip (gc);
1032 #ifdef MAC_OSX
1034 else
1036 CGrafPtr port;
1037 static CGContextRef context;
1038 float port_height = FRAME_PIXEL_HEIGHT (f);
1039 static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
1040 static const ByteCount sizes[] = {sizeof (CGContextRef)};
1041 static const ATSUAttributeValuePtr values[] = {&context};
1043 #if USE_CG_DRAWING
1044 context = mac_begin_cg_clip (f, gc);
1045 #else
1046 GetPort (&port);
1047 QDBeginCGContext (port, &context);
1048 if (gc->n_clip_rects || bg_width)
1050 CGContextTranslateCTM (context, 0, port_height);
1051 CGContextScaleCTM (context, 1, -1);
1052 if (gc->n_clip_rects)
1053 CGContextClipToRects (context, gc->clip_rects,
1054 gc->n_clip_rects);
1055 #endif
1056 if (bg_width)
1058 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1059 CGContextFillRect
1060 (context,
1061 CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
1062 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1064 CGContextScaleCTM (context, 1, -1);
1065 CGContextTranslateCTM (context, 0, -port_height);
1066 #if !USE_CG_DRAWING
1068 #endif
1069 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1070 err = ATSUSetLayoutControls (text_layout,
1071 sizeof (tags) / sizeof (tags[0]),
1072 tags, sizes, values);
1073 if (err == noErr)
1075 ATSUDrawText (text_layout,
1076 kATSUFromTextBeginning, kATSUToTextEnd,
1077 Long2Fix (x), Long2Fix (port_height - y));
1078 if (overstrike_p)
1079 ATSUDrawText (text_layout,
1080 kATSUFromTextBeginning, kATSUToTextEnd,
1081 Long2Fix (x + 1), Long2Fix (port_height - y));
1083 #if USE_CG_DRAWING
1084 mac_end_cg_clip (f);
1085 context = NULL;
1086 #else
1087 CGContextSynchronize (context);
1088 QDEndCGContext (port, &context);
1089 #endif
1090 #if 0
1091 /* This doesn't work on Mac OS X 10.1. */
1092 ATSUClearLayoutControls (text_layout,
1093 sizeof (tags) / sizeof (tags[0]), tags);
1094 #else
1095 ATSUSetLayoutControls (text_layout,
1096 sizeof (tags) / sizeof (tags[0]),
1097 tags, sizes, values);
1098 #endif
1100 #endif /* MAC_OSX */
1102 else
1103 #endif /* USE_ATSUI */
1105 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1106 UInt32 savedFlags;
1108 if (mac_use_core_graphics)
1109 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
1110 #endif
1111 #if USE_CG_DRAWING
1112 mac_prepare_for_quickdraw (f);
1113 #endif
1114 mac_begin_clip (gc);
1115 RGBForeColor (GC_FORE_COLOR (gc));
1116 #ifdef MAC_OS8
1117 if (bg_width)
1119 RGBBackColor (GC_BACK_COLOR (gc));
1120 TextMode (srcCopy);
1122 else
1123 TextMode (srcOr);
1124 #else
1125 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1126 because:
1127 - Screen is double-buffered. (In srcCopy mode, a text is
1128 drawn into an offscreen graphics world first. So
1129 performance gain cannot be expected.)
1130 - It lowers rendering quality.
1131 - Some fonts leave garbage on cursor movement. */
1132 if (bg_width)
1134 Rect r;
1136 RGBBackColor (GC_BACK_COLOR (gc));
1137 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1138 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1139 EraseRect (&r);
1141 TextMode (srcOr);
1142 #endif
1143 TextFont (GC_FONT (gc)->mac_fontnum);
1144 TextSize (GC_FONT (gc)->mac_fontsize);
1145 TextFace (GC_FONT (gc)->mac_fontface);
1146 MoveTo (x, y);
1147 DrawText (buf, 0, nchars * bytes_per_char);
1148 if (overstrike_p)
1150 TextMode (srcOr);
1151 MoveTo (x + 1, y);
1152 DrawText (buf, 0, nchars * bytes_per_char);
1154 if (bg_width)
1155 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1156 mac_end_clip (gc);
1158 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1159 if (mac_use_core_graphics)
1160 SwapQDTextFlags(savedFlags);
1161 #endif
1166 /* Mac replacement for XDrawImageString. */
1168 static void
1169 mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1170 struct frame *f;
1171 GC gc;
1172 int x, y;
1173 char *buf;
1174 int nchars, bg_width, overstrike_p;
1176 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1177 overstrike_p, 1);
1181 /* Mac replacement for XDrawImageString16. */
1183 static void
1184 mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1185 struct frame *f;
1186 GC gc;
1187 int x, y;
1188 XChar2b *buf;
1189 int nchars, bg_width, overstrike_p;
1191 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
1192 overstrike_p, 2);
1196 /* Mac replacement for XQueryTextExtents, but takes a character. If
1197 STYLE is NULL, measurement is done by QuickDraw Text routines for
1198 the font of the current graphics port. If CG_GLYPH is not NULL,
1199 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1201 static OSStatus
1202 mac_query_char_extents (style, c,
1203 font_ascent_return, font_descent_return,
1204 overall_return, cg_glyph)
1205 #if USE_ATSUI
1206 ATSUStyle style;
1207 #else
1208 void *style;
1209 #endif
1210 int c;
1211 int *font_ascent_return, *font_descent_return;
1212 XCharStruct *overall_return;
1213 #if USE_CG_TEXT_DRAWING
1214 CGGlyph *cg_glyph;
1215 #else
1216 void *cg_glyph;
1217 #endif
1219 OSStatus err = noErr;
1220 int width;
1221 Rect char_bounds;
1223 #if USE_ATSUI
1224 if (style)
1226 ATSUTextLayout text_layout;
1227 UniChar ch = c;
1229 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
1230 if (err == noErr
1231 && (font_ascent_return || font_descent_return || overall_return))
1233 ATSTrapezoid glyph_bounds;
1235 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1236 kATSUFromTextBeginning, kATSUToTextEnd,
1237 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1238 kATSUseFractionalOrigins,
1239 #else
1240 kATSUseDeviceOrigins,
1241 #endif
1242 1, &glyph_bounds, NULL);
1243 if (err == noErr)
1245 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1246 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1248 width = Fix2Long (glyph_bounds.upperRight.x
1249 - glyph_bounds.upperLeft.x);
1250 if (font_ascent_return)
1251 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1252 if (font_descent_return)
1253 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1256 if (err == noErr && overall_return)
1258 err = ATSUMeasureTextImage (text_layout,
1259 kATSUFromTextBeginning, kATSUToTextEnd,
1260 0, 0, &char_bounds);
1261 if (err == noErr)
1262 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1263 #if USE_CG_TEXT_DRAWING
1264 if (err == noErr && cg_glyph)
1266 OSStatus err1;
1267 ATSUGlyphInfoArray glyph_info_array;
1268 ByteCount count = sizeof (ATSUGlyphInfoArray);
1270 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1271 kATSUToTextEnd, NULL, NULL, NULL);
1272 if (err1 == noErr)
1273 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1274 kATSUToTextEnd, &count,
1275 &glyph_info_array);
1276 if (err1 == noErr
1277 /* Make sure that we don't have to make layout
1278 adjustments. */
1279 && glyph_info_array.glyphs[0].deltaY == 0.0f
1280 && glyph_info_array.glyphs[0].idealX == 0.0f
1281 && glyph_info_array.glyphs[0].screenX == 0)
1283 xassert (glyph_info_array.glyphs[0].glyphID);
1284 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1286 else
1287 *cg_glyph = 0;
1289 #endif
1292 else
1293 #endif
1295 if (font_ascent_return || font_descent_return)
1297 FontInfo font_info;
1299 GetFontInfo (&font_info);
1300 if (font_ascent_return)
1301 *font_ascent_return = font_info.ascent;
1302 if (font_descent_return)
1303 *font_descent_return = font_info.descent;
1305 if (overall_return)
1307 char ch = c;
1309 width = CharWidth (ch);
1310 QDTextBounds (1, &ch, &char_bounds);
1311 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1315 return err;
1319 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1321 static int
1322 mac_text_extents_16 (font_struct, string, nchars, overall_return)
1323 XFontStruct *font_struct;
1324 XChar2b *string;
1325 int nchars;
1326 XCharStruct *overall_return;
1328 int i;
1329 short width = 0, lbearing = 0, rbearing = 0;
1330 XCharStruct *pcm;
1332 for (i = 0; i < nchars; i++)
1334 pcm = mac_per_char_metric (font_struct, string, 0);
1335 if (pcm == NULL)
1336 width += FONT_WIDTH (font_struct);
1337 else
1339 lbearing = min (lbearing, width + pcm->lbearing);
1340 rbearing = max (rbearing, width + pcm->rbearing);
1341 width += pcm->width;
1343 string++;
1346 overall_return->lbearing = lbearing;
1347 overall_return->rbearing = rbearing;
1348 overall_return->width = width;
1350 /* What's the meaning of the return value of XTextExtents16? */
1354 #if USE_CG_TEXT_DRAWING
1355 static int cg_text_anti_aliasing_threshold = 8;
1357 static void
1358 init_cg_text_anti_aliasing_threshold ()
1360 int threshold;
1361 Boolean valid_p;
1363 threshold =
1364 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1365 kCFPreferencesCurrentApplication,
1366 &valid_p);
1367 if (valid_p)
1368 cg_text_anti_aliasing_threshold = threshold;
1371 static int
1372 mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1373 struct frame *f;
1374 GC gc;
1375 int x, y;
1376 XChar2b *buf;
1377 int nchars, bg_width, overstrike_p;
1379 CGrafPtr port;
1380 float port_height, gx, gy;
1381 int i;
1382 CGContextRef context;
1383 CGGlyph *glyphs;
1384 CGSize *advances;
1386 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1387 return 0;
1389 port = GetWindowPort (FRAME_MAC_WINDOW (f));
1390 port_height = FRAME_PIXEL_HEIGHT (f);
1391 gx = x;
1392 gy = port_height - y;
1393 glyphs = (CGGlyph *)buf;
1394 advances = alloca (sizeof (CGSize) * nchars);
1395 if (advances == NULL)
1396 return 0;
1397 for (i = 0; i < nchars; i++)
1399 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1401 advances[i].width = pcm->width;
1402 advances[i].height = 0;
1403 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1404 buf++;
1407 #if USE_CG_DRAWING
1408 context = mac_begin_cg_clip (f, gc);
1409 #else
1410 QDBeginCGContext (port, &context);
1411 if (gc->n_clip_rects || bg_width)
1413 CGContextTranslateCTM (context, 0, port_height);
1414 CGContextScaleCTM (context, 1, -1);
1415 if (gc->n_clip_rects)
1416 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1417 #endif
1418 if (bg_width)
1420 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1421 CGContextFillRect
1422 (context,
1423 CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
1424 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1426 CGContextScaleCTM (context, 1, -1);
1427 CGContextTranslateCTM (context, 0, -port_height);
1428 #if !USE_CG_DRAWING
1430 #endif
1431 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1432 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1433 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1434 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1435 CGContextSetShouldAntialias (context, false);
1436 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1437 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1438 if (CGContextShowGlyphsWithAdvances != NULL)
1439 #endif
1441 CGContextSetTextPosition (context, gx, gy);
1442 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1443 if (overstrike_p)
1445 CGContextSetTextPosition (context, gx + 1.0f, gy);
1446 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1449 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1450 else
1451 #endif
1452 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1453 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1455 for (i = 0; i < nchars; i++)
1457 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1458 if (overstrike_p)
1459 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
1460 gx += advances[i].width;
1463 #endif
1464 #if USE_CG_DRAWING
1465 mac_end_cg_clip (f);
1466 #else
1467 CGContextSynchronize (context);
1468 QDEndCGContext (port, &context);
1469 #endif
1471 return 1;
1473 #endif
1476 #if !USE_CG_DRAWING
1477 /* Mac replacement for XCopyArea: dest must be window. */
1479 static void
1480 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1481 Pixmap src;
1482 struct frame *f;
1483 GC gc;
1484 int src_x, src_y;
1485 unsigned int width, height;
1486 int dest_x, dest_y;
1488 Rect src_r, dest_r;
1490 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1492 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1493 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1495 ForeColor (blackColor);
1496 BackColor (whiteColor);
1498 mac_begin_clip (gc);
1499 LockPixels (GetGWorldPixMap (src));
1500 #if TARGET_API_MAC_CARBON
1502 CGrafPtr port;
1504 GetPort (&port);
1505 LockPortBits (port);
1506 CopyBits (GetPortBitMapForCopyBits (src),
1507 GetPortBitMapForCopyBits (port),
1508 &src_r, &dest_r, srcCopy, 0);
1509 UnlockPortBits (port);
1511 #else /* not TARGET_API_MAC_CARBON */
1512 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1513 &src_r, &dest_r, srcCopy, 0);
1514 #endif /* not TARGET_API_MAC_CARBON */
1515 UnlockPixels (GetGWorldPixMap (src));
1516 mac_end_clip (gc);
1518 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1522 static void
1523 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1524 width, height, dest_x, dest_y)
1525 Pixmap src, mask;
1526 struct frame *f;
1527 GC gc;
1528 int src_x, src_y;
1529 unsigned int width, height;
1530 int dest_x, dest_y;
1532 Rect src_r, dest_r;
1534 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1536 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1537 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1539 ForeColor (blackColor);
1540 BackColor (whiteColor);
1542 mac_begin_clip (gc);
1543 LockPixels (GetGWorldPixMap (src));
1544 LockPixels (GetGWorldPixMap (mask));
1545 #if TARGET_API_MAC_CARBON
1547 CGrafPtr port;
1549 GetPort (&port);
1550 LockPortBits (port);
1551 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1552 GetPortBitMapForCopyBits (port),
1553 &src_r, &src_r, &dest_r);
1554 UnlockPortBits (port);
1556 #else /* not TARGET_API_MAC_CARBON */
1557 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1558 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1559 #endif /* not TARGET_API_MAC_CARBON */
1560 UnlockPixels (GetGWorldPixMap (mask));
1561 UnlockPixels (GetGWorldPixMap (src));
1562 mac_end_clip (gc);
1564 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1566 #endif /* !USE_CG_DRAWING */
1569 /* Mac replacement for XCopyArea: used only for scrolling. */
1571 static void
1572 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1573 struct frame *f;
1574 GC gc;
1575 int src_x, src_y;
1576 unsigned int width, height;
1577 int dest_x, dest_y;
1579 #if TARGET_API_MAC_CARBON
1580 Rect src_r;
1581 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
1583 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1584 #if USE_CG_DRAWING
1585 mac_prepare_for_quickdraw (f);
1586 #endif
1587 ScrollWindowRect (FRAME_MAC_WINDOW (f),
1588 &src_r, dest_x - src_x, dest_y - src_y,
1589 kScrollWindowNoOptions, dummy);
1590 DisposeRgn (dummy);
1591 #else /* not TARGET_API_MAC_CARBON */
1592 Rect src_r, dest_r;
1593 WindowPtr w = FRAME_MAC_WINDOW (f);
1595 SetPort (w);
1597 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1598 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1600 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1601 color mapping in CopyBits. Otherwise, it will be slow. */
1602 ForeColor (blackColor);
1603 BackColor (whiteColor);
1604 mac_begin_clip (gc);
1605 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1606 mac_end_clip (gc);
1608 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1609 #endif /* not TARGET_API_MAC_CARBON */
1613 /* Mac replacement for XChangeGC. */
1615 static void
1616 XChangeGC (display, gc, mask, xgcv)
1617 Display *display;
1618 GC gc;
1619 unsigned long mask;
1620 XGCValues *xgcv;
1622 if (mask & GCForeground)
1623 XSetForeground (display, gc, xgcv->foreground);
1624 if (mask & GCBackground)
1625 XSetBackground (display, gc, xgcv->background);
1626 if (mask & GCFont)
1627 XSetFont (display, gc, xgcv->font);
1631 /* Mac replacement for XCreateGC. */
1634 XCreateGC (display, d, mask, xgcv)
1635 Display *display;
1636 void *d;
1637 unsigned long mask;
1638 XGCValues *xgcv;
1640 GC gc = xmalloc (sizeof (*gc));
1642 bzero (gc, sizeof (*gc));
1643 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1644 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1645 if (CGColorGetTypeID != NULL)
1646 #endif
1648 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
1649 CGColorRetain (gc->cg_fore_color);
1650 CGColorRetain (gc->cg_back_color);
1652 #endif
1653 XChangeGC (display, gc, mask, xgcv);
1655 return gc;
1659 /* Used in xfaces.c. */
1661 void
1662 XFreeGC (display, gc)
1663 Display *display;
1664 GC gc;
1666 if (gc->clip_region)
1667 DisposeRgn (gc->clip_region);
1668 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1669 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1670 if (CGColorGetTypeID != NULL)
1671 #endif
1673 CGColorRelease (gc->cg_fore_color);
1674 CGColorRelease (gc->cg_back_color);
1676 #endif
1677 xfree (gc);
1681 /* Mac replacement for XGetGCValues. */
1683 static void
1684 XGetGCValues (display, gc, mask, xgcv)
1685 Display *display;
1686 GC gc;
1687 unsigned long mask;
1688 XGCValues *xgcv;
1690 if (mask & GCForeground)
1691 xgcv->foreground = gc->xgcv.foreground;
1692 if (mask & GCBackground)
1693 xgcv->background = gc->xgcv.background;
1694 if (mask & GCFont)
1695 xgcv->font = gc->xgcv.font;
1699 /* Mac replacement for XSetForeground. */
1701 void
1702 XSetForeground (display, gc, color)
1703 Display *display;
1704 GC gc;
1705 unsigned long color;
1707 if (gc->xgcv.foreground != color)
1709 gc->xgcv.foreground = color;
1710 gc->fore_color.red = RED16_FROM_ULONG (color);
1711 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1712 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1713 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1714 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1715 if (CGColorGetTypeID != NULL)
1716 #endif
1718 CGColorRelease (gc->cg_fore_color);
1719 if (color == 0)
1721 gc->cg_fore_color = mac_cg_color_black;
1722 CGColorRetain (gc->cg_fore_color);
1724 else
1726 float rgba[4];
1728 rgba[0] = gc->fore_color.red / 65535.0f;
1729 rgba[1] = gc->fore_color.green / 65535.0f;
1730 rgba[2] = gc->fore_color.blue / 65535.0f;
1731 rgba[3] = 1.0f;
1732 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1735 #endif
1740 /* Mac replacement for XSetBackground. */
1742 void
1743 XSetBackground (display, gc, color)
1744 Display *display;
1745 GC gc;
1746 unsigned long color;
1748 if (gc->xgcv.background != color)
1750 gc->xgcv.background = color;
1751 gc->back_color.red = RED16_FROM_ULONG (color);
1752 gc->back_color.green = GREEN16_FROM_ULONG (color);
1753 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1754 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1755 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1756 if (CGColorGetTypeID != NULL)
1757 #endif
1759 CGColorRelease (gc->cg_back_color);
1760 if (color == 0)
1762 gc->cg_back_color = mac_cg_color_black;
1763 CGColorRetain (gc->cg_back_color);
1765 else
1767 float rgba[4];
1769 rgba[0] = gc->back_color.red / 65535.0f;
1770 rgba[1] = gc->back_color.green / 65535.0f;
1771 rgba[2] = gc->back_color.blue / 65535.0f;
1772 rgba[3] = 1.0f;
1773 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1776 #endif
1781 /* Mac replacement for XSetFont. */
1783 static void
1784 XSetFont (display, gc, font)
1785 Display *display;
1786 GC gc;
1787 XFontStruct *font;
1789 gc->xgcv.font = font;
1793 /* Mac replacement for XSetClipRectangles. */
1795 static void
1796 mac_set_clip_rectangles (display, gc, rectangles, n)
1797 Display *display;
1798 GC gc;
1799 Rect *rectangles;
1800 int n;
1802 int i;
1804 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1806 gc->n_clip_rects = n;
1807 if (n > 0)
1809 if (gc->clip_region == NULL)
1810 gc->clip_region = NewRgn ();
1811 RectRgn (gc->clip_region, rectangles);
1812 if (n > 1)
1814 RgnHandle region = NewRgn ();
1816 for (i = 1; i < n; i++)
1818 RectRgn (region, rectangles + i);
1819 UnionRgn (gc->clip_region, region, gc->clip_region);
1821 DisposeRgn (region);
1824 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1825 for (i = 0; i < n; i++)
1827 Rect *rect = rectangles + i;
1829 gc->clip_rects[i] = CGRectMake (rect->left, rect->top,
1830 rect->right - rect->left,
1831 rect->bottom - rect->top);
1833 #endif
1837 /* Mac replacement for XSetClipMask. */
1839 static INLINE void
1840 mac_reset_clip_rectangles (display, gc)
1841 Display *display;
1842 GC gc;
1844 gc->n_clip_rects = 0;
1848 /* Mac replacement for XSetWindowBackground. */
1850 void
1851 XSetWindowBackground (display, w, color)
1852 Display *display;
1853 WindowPtr w;
1854 unsigned long color;
1856 #if !TARGET_API_MAC_CARBON
1857 AuxWinHandle aw_handle;
1858 CTabHandle ctab_handle;
1859 ColorSpecPtr ct_table;
1860 short ct_size;
1861 #endif
1862 RGBColor bg_color;
1864 bg_color.red = RED16_FROM_ULONG (color);
1865 bg_color.green = GREEN16_FROM_ULONG (color);
1866 bg_color.blue = BLUE16_FROM_ULONG (color);
1868 #if TARGET_API_MAC_CARBON
1869 SetWindowContentColor (w, &bg_color);
1870 #else
1871 if (GetAuxWin (w, &aw_handle))
1873 ctab_handle = (*aw_handle)->awCTable;
1874 HandToHand ((Handle *) &ctab_handle);
1875 ct_table = (*ctab_handle)->ctTable;
1876 ct_size = (*ctab_handle)->ctSize;
1877 while (ct_size > -1)
1879 if (ct_table->value == 0)
1881 ct_table->rgb = bg_color;
1882 CTabChanged (ctab_handle);
1883 SetWinColor (w, (WCTabHandle) ctab_handle);
1885 ct_size--;
1888 #endif
1891 /* Flush display of frame F, or of all frames if F is null. */
1893 static void
1894 x_flush (f)
1895 struct frame *f;
1897 #if TARGET_API_MAC_CARBON
1898 BLOCK_INPUT;
1899 #if USE_CG_DRAWING
1900 mac_prepare_for_quickdraw (f);
1901 #endif
1902 if (f)
1903 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1904 else
1905 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1906 UNBLOCK_INPUT;
1907 #endif
1911 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1912 Calls to XFlush should be unnecessary because the X output buffer
1913 is flushed automatically as needed by calls to XPending,
1914 XNextEvent, or XWindowEvent according to the XFlush man page.
1915 XTread_socket calls XPending. Removing XFlush improves
1916 performance. */
1918 #define XFlush(DISPLAY) (void) 0
1920 #if USE_CG_DRAWING
1921 static void
1922 mac_flush_display_optional (f)
1923 struct frame *f;
1925 BLOCK_INPUT;
1926 mac_prepare_for_quickdraw (f);
1927 UNBLOCK_INPUT;
1929 #endif
1931 /***********************************************************************
1932 Starting and ending an update
1933 ***********************************************************************/
1935 /* Start an update of frame F. This function is installed as a hook
1936 for update_begin, i.e. it is called when update_begin is called.
1937 This function is called prior to calls to x_update_window_begin for
1938 each window being updated. */
1940 static void
1941 x_update_begin (f)
1942 struct frame *f;
1944 #if TARGET_API_MAC_CARBON
1945 /* During update of a frame, availability of input events is
1946 periodically checked with ReceiveNextEvent if
1947 redisplay-dont-pause is nil. That normally flushes window buffer
1948 changes for every check, and thus screen update looks waving even
1949 if no input is available. So we disable screen updates during
1950 update of a frame. */
1951 BLOCK_INPUT;
1952 DisableScreenUpdates ();
1953 UNBLOCK_INPUT;
1954 #endif
1958 /* Start update of window W. Set the global variable updated_window
1959 to the window being updated and set output_cursor to the cursor
1960 position of W. */
1962 static void
1963 x_update_window_begin (w)
1964 struct window *w;
1966 struct frame *f = XFRAME (WINDOW_FRAME (w));
1967 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1969 updated_window = w;
1970 set_output_cursor (&w->cursor);
1972 BLOCK_INPUT;
1974 if (f == display_info->mouse_face_mouse_frame)
1976 /* Don't do highlighting for mouse motion during the update. */
1977 display_info->mouse_face_defer = 1;
1979 /* If F needs to be redrawn, simply forget about any prior mouse
1980 highlighting. */
1981 if (FRAME_GARBAGED_P (f))
1982 display_info->mouse_face_window = Qnil;
1984 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1985 their mouse_face_p flag set, which means that they are always
1986 unequal to rows in a desired matrix which never have that
1987 flag set. So, rows containing mouse-face glyphs are never
1988 scrolled, and we don't have to switch the mouse highlight off
1989 here to prevent it from being scrolled. */
1991 /* Can we tell that this update does not affect the window
1992 where the mouse highlight is? If so, no need to turn off.
1993 Likewise, don't do anything if the frame is garbaged;
1994 in that case, the frame's current matrix that we would use
1995 is all wrong, and we will redisplay that line anyway. */
1996 if (!NILP (display_info->mouse_face_window)
1997 && w == XWINDOW (display_info->mouse_face_window))
1999 int i;
2001 for (i = 0; i < w->desired_matrix->nrows; ++i)
2002 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
2003 break;
2005 if (i < w->desired_matrix->nrows)
2006 clear_mouse_face (display_info);
2008 #endif /* 0 */
2011 UNBLOCK_INPUT;
2015 /* Draw a vertical window border from (x,y0) to (x,y1) */
2017 static void
2018 mac_draw_vertical_window_border (w, x, y0, y1)
2019 struct window *w;
2020 int x, y0, y1;
2022 struct frame *f = XFRAME (WINDOW_FRAME (w));
2023 struct face *face;
2025 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
2026 if (face)
2027 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
2028 face->foreground);
2030 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
2033 /* End update of window W (which is equal to updated_window).
2035 Draw vertical borders between horizontally adjacent windows, and
2036 display W's cursor if CURSOR_ON_P is non-zero.
2038 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
2039 glyphs in mouse-face were overwritten. In that case we have to
2040 make sure that the mouse-highlight is properly redrawn.
2042 W may be a menu bar pseudo-window in case we don't have X toolkit
2043 support. Such windows don't have a cursor, so don't display it
2044 here. */
2046 static void
2047 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
2048 struct window *w;
2049 int cursor_on_p, mouse_face_overwritten_p;
2051 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
2053 if (!w->pseudo_window_p)
2055 BLOCK_INPUT;
2057 if (cursor_on_p)
2058 display_and_set_cursor (w, 1, output_cursor.hpos,
2059 output_cursor.vpos,
2060 output_cursor.x, output_cursor.y);
2062 if (draw_window_fringes (w, 1))
2063 x_draw_vertical_border (w);
2065 UNBLOCK_INPUT;
2068 /* If a row with mouse-face was overwritten, arrange for
2069 XTframe_up_to_date to redisplay the mouse highlight. */
2070 if (mouse_face_overwritten_p)
2072 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
2073 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
2074 dpyinfo->mouse_face_window = Qnil;
2077 updated_window = NULL;
2081 /* End update of frame F. This function is installed as a hook in
2082 update_end. */
2084 static void
2085 x_update_end (f)
2086 struct frame *f;
2088 /* Mouse highlight may be displayed again. */
2089 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
2091 BLOCK_INPUT;
2092 #if TARGET_API_MAC_CARBON
2093 EnableScreenUpdates ();
2094 #endif
2095 XFlush (FRAME_MAC_DISPLAY (f));
2096 UNBLOCK_INPUT;
2100 /* This function is called from various places in xdisp.c whenever a
2101 complete update has been performed. The global variable
2102 updated_window is not available here. */
2104 static void
2105 XTframe_up_to_date (f)
2106 struct frame *f;
2108 if (FRAME_MAC_P (f))
2110 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2112 if (dpyinfo->mouse_face_deferred_gc
2113 || f == dpyinfo->mouse_face_mouse_frame)
2115 BLOCK_INPUT;
2116 if (dpyinfo->mouse_face_mouse_frame)
2117 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
2118 dpyinfo->mouse_face_mouse_x,
2119 dpyinfo->mouse_face_mouse_y);
2120 dpyinfo->mouse_face_deferred_gc = 0;
2121 UNBLOCK_INPUT;
2127 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2128 arrow bitmaps, or clear the fringes if no bitmaps are required
2129 before DESIRED_ROW is made current. The window being updated is
2130 found in updated_window. This function is called from
2131 update_window_line only if it is known that there are differences
2132 between bitmaps to be drawn between current row and DESIRED_ROW. */
2134 static void
2135 x_after_update_window_line (desired_row)
2136 struct glyph_row *desired_row;
2138 struct window *w = updated_window;
2139 struct frame *f;
2140 int width, height;
2142 xassert (w);
2144 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2145 desired_row->redraw_fringe_bitmaps_p = 1;
2147 /* When a window has disappeared, make sure that no rest of
2148 full-width rows stays visible in the internal border. Could
2149 check here if updated_window is the leftmost/rightmost window,
2150 but I guess it's not worth doing since vertically split windows
2151 are almost never used, internal border is rarely set, and the
2152 overhead is very small. */
2153 if (windows_or_buffers_changed
2154 && desired_row->full_width_p
2155 && (f = XFRAME (w->frame),
2156 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2157 width != 0)
2158 && (height = desired_row->visible_height,
2159 height > 0))
2161 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2163 /* Internal border is drawn below the tool bar. */
2164 if (WINDOWP (f->tool_bar_window)
2165 && w == XWINDOW (f->tool_bar_window))
2166 y -= width;
2168 BLOCK_INPUT;
2169 mac_clear_area (f, 0, y, width, height);
2170 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
2171 UNBLOCK_INPUT;
2176 /* Draw the bitmap WHICH in one of the left or right fringes of
2177 window W. ROW is the glyph row for which to display the bitmap; it
2178 determines the vertical position at which the bitmap has to be
2179 drawn. */
2181 static void
2182 x_draw_fringe_bitmap (w, row, p)
2183 struct window *w;
2184 struct glyph_row *row;
2185 struct draw_fringe_bitmap_params *p;
2187 struct frame *f = XFRAME (WINDOW_FRAME (w));
2188 Display *display = FRAME_MAC_DISPLAY (f);
2189 struct face *face = p->face;
2190 int rowY;
2192 /* Must clip because of partially visible lines. */
2193 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2194 if (p->y < rowY)
2196 /* Adjust position of "bottom aligned" bitmap on partially
2197 visible last row. */
2198 int oldY = row->y;
2199 int oldVH = row->visible_height;
2200 row->visible_height = p->h;
2201 row->y -= rowY - p->y;
2202 x_clip_to_row (w, row, -1, face->gc);
2203 row->y = oldY;
2204 row->visible_height = oldVH;
2206 else
2207 x_clip_to_row (w, row, -1, face->gc);
2209 if (p->bx >= 0 && !p->overlay_p)
2211 #if 0 /* MAC_TODO: stipple */
2212 /* In case the same realized face is used for fringes and
2213 for something displayed in the text (e.g. face `region' on
2214 mono-displays, the fill style may have been changed to
2215 FillSolid in x_draw_glyph_string_background. */
2216 if (face->stipple)
2217 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2218 else
2219 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2220 #endif
2222 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
2224 #if 0 /* MAC_TODO: stipple */
2225 if (!face->stipple)
2226 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2227 #endif
2230 if (p->which
2231 #if USE_CG_DRAWING
2232 && p->which < max_fringe_bmp
2233 #endif
2236 XGCValues gcv;
2238 XGetGCValues (display, face->gc, GCForeground, &gcv);
2239 XSetForeground (display, face->gc,
2240 (p->cursor_p
2241 ? (p->overlay_p ? face->background
2242 : f->output_data.mac->cursor_pixel)
2243 : face->foreground));
2244 #if USE_CG_DRAWING
2245 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
2246 p->wd, p->h, p->x, p->y, p->overlay_p);
2247 #else
2248 mac_draw_bitmap (f, face->gc, p->x, p->y,
2249 p->wd, p->h, p->bits + p->dh, p->overlay_p);
2250 #endif
2251 XSetForeground (display, face->gc, gcv.foreground);
2254 mac_reset_clip_rectangles (display, face->gc);
2257 #if USE_CG_DRAWING
2258 static void
2259 mac_define_fringe_bitmap (which, bits, h, wd)
2260 int which;
2261 unsigned short *bits;
2262 int h, wd;
2264 int i;
2265 CGDataProviderRef provider;
2267 if (which >= max_fringe_bmp)
2269 i = max_fringe_bmp;
2270 max_fringe_bmp = which + 20;
2271 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
2272 while (i < max_fringe_bmp)
2273 fringe_bmp[i++] = 0;
2276 for (i = 0; i < h; i++)
2277 bits[i] = ~bits[i];
2279 BLOCK_INPUT;
2281 provider = CGDataProviderCreateWithData (NULL, bits,
2282 sizeof (unsigned short) * h, NULL);
2283 if (provider)
2285 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
2286 sizeof (unsigned short),
2287 provider, NULL, 0);
2288 CGDataProviderRelease (provider);
2291 UNBLOCK_INPUT;
2294 static void
2295 mac_destroy_fringe_bitmap (which)
2296 int which;
2298 if (which >= max_fringe_bmp)
2299 return;
2301 if (fringe_bmp[which])
2303 BLOCK_INPUT;
2304 CGImageRelease (fringe_bmp[which]);
2305 UNBLOCK_INPUT;
2307 fringe_bmp[which] = 0;
2309 #endif
2312 /* This is called when starting Emacs and when restarting after
2313 suspend. When starting Emacs, no window is mapped. And nothing
2314 must be done to Emacs's own window if it is suspended (though that
2315 rarely happens). */
2317 static void
2318 XTset_terminal_modes ()
2322 /* This is called when exiting or suspending Emacs. Exiting will make
2323 the windows go away, and suspending requires no action. */
2325 static void
2326 XTreset_terminal_modes ()
2332 /***********************************************************************
2333 Display Iterator
2334 ***********************************************************************/
2336 /* Function prototypes of this page. */
2338 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
2339 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
2342 static void
2343 pcm_init (pcm, count)
2344 XCharStruct *pcm;
2345 int count;
2347 bzero (pcm, sizeof (XCharStruct) * count);
2348 while (--count >= 0)
2350 pcm->descent = PCM_INVALID;
2351 pcm++;
2355 static enum pcm_status
2356 pcm_get_status (pcm)
2357 const XCharStruct *pcm;
2359 int height = pcm->ascent + pcm->descent;
2361 /* Negative height means some special status. */
2362 return height >= 0 ? PCM_VALID : height;
2365 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2366 is not contained in the font. */
2368 static INLINE XCharStruct *
2369 x_per_char_metric (font, char2b)
2370 XFontStruct *font;
2371 XChar2b *char2b;
2373 /* The result metric information. */
2374 XCharStruct *pcm = NULL;
2376 xassert (font && char2b);
2378 #if USE_ATSUI
2379 if (font->mac_style)
2381 XCharStruct **row = font->bounds.rows + char2b->byte1;
2383 if (*row == NULL)
2385 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2386 pcm_init (*row, 0x100);
2388 pcm = *row + char2b->byte2;
2389 if (pcm_get_status (pcm) != PCM_VALID)
2391 BLOCK_INPUT;
2392 mac_query_char_extents (font->mac_style,
2393 (char2b->byte1 << 8) + char2b->byte2,
2394 NULL, NULL, pcm, NULL);
2395 UNBLOCK_INPUT;
2398 else
2400 #endif
2401 if (font->bounds.per_char != NULL)
2403 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2405 /* min_char_or_byte2 specifies the linear character index
2406 corresponding to the first element of the per_char array,
2407 max_char_or_byte2 is the index of the last character. A
2408 character with non-zero CHAR2B->byte1 is not in the font.
2409 A character with byte2 less than min_char_or_byte2 or
2410 greater max_char_or_byte2 is not in the font. */
2411 if (char2b->byte1 == 0
2412 && char2b->byte2 >= font->min_char_or_byte2
2413 && char2b->byte2 <= font->max_char_or_byte2)
2414 pcm = font->bounds.per_char
2415 + (char2b->byte2 - font->min_char_or_byte2);
2417 else
2419 /* If either min_byte1 or max_byte1 are nonzero, both
2420 min_char_or_byte2 and max_char_or_byte2 are less than
2421 256, and the 2-byte character index values corresponding
2422 to the per_char array element N (counting from 0) are:
2424 byte1 = N/D + min_byte1
2425 byte2 = N\D + min_char_or_byte2
2427 where:
2429 D = max_char_or_byte2 - min_char_or_byte2 + 1
2430 / = integer division
2431 \ = integer modulus */
2432 if (char2b->byte1 >= font->min_byte1
2433 && char2b->byte1 <= font->max_byte1
2434 && char2b->byte2 >= font->min_char_or_byte2
2435 && char2b->byte2 <= font->max_char_or_byte2)
2437 pcm = (font->bounds.per_char
2438 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2439 * (char2b->byte1 - font->min_byte1))
2440 + (char2b->byte2 - font->min_char_or_byte2));
2444 else
2446 /* If the per_char pointer is null, all glyphs between the first
2447 and last character indexes inclusive have the same
2448 information, as given by both min_bounds and max_bounds. */
2449 if (char2b->byte2 >= font->min_char_or_byte2
2450 && char2b->byte2 <= font->max_char_or_byte2)
2451 pcm = &font->max_bounds;
2453 #if USE_ATSUI
2455 #endif
2457 return ((pcm == NULL
2458 || (pcm->width == 0
2459 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2460 && (pcm->rbearing - pcm->lbearing) == 0
2461 #endif
2463 ? NULL : pcm);
2466 /* RIF:
2469 static XCharStruct *
2470 mac_per_char_metric (font, char2b, font_type)
2471 XFontStruct *font;
2472 XChar2b *char2b;
2473 int font_type;
2475 return x_per_char_metric (font, char2b);
2478 /* RIF:
2479 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2480 the two-byte form of C. Encoding is returned in *CHAR2B. */
2482 static int
2483 mac_encode_char (c, char2b, font_info, two_byte_p)
2484 int c;
2485 XChar2b *char2b;
2486 struct font_info *font_info;
2487 int *two_byte_p;
2489 int charset = CHAR_CHARSET (c);
2490 XFontStruct *font = font_info->font;
2492 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2493 This may be either a program in a special encoder language or a
2494 fixed encoding. */
2495 if (font_info->font_encoder)
2497 /* It's a program. */
2498 struct ccl_program *ccl = font_info->font_encoder;
2500 check_ccl_update (ccl);
2501 if (CHARSET_DIMENSION (charset) == 1)
2503 ccl->reg[0] = charset;
2504 ccl->reg[1] = char2b->byte2;
2505 ccl->reg[2] = -1;
2507 else
2509 ccl->reg[0] = charset;
2510 ccl->reg[1] = char2b->byte1;
2511 ccl->reg[2] = char2b->byte2;
2514 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2516 /* We assume that MSBs are appropriately set/reset by CCL
2517 program. */
2518 if (font->max_byte1 == 0) /* 1-byte font */
2519 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2520 else
2521 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2523 else if (font_info->encoding[charset])
2525 /* Fixed encoding scheme. See fontset.h for the meaning of the
2526 encoding numbers. */
2527 int enc = font_info->encoding[charset];
2529 if ((enc == 1 || enc == 2)
2530 && CHARSET_DIMENSION (charset) == 2)
2531 char2b->byte1 |= 0x80;
2533 if (enc == 1 || enc == 3)
2534 char2b->byte2 |= 0x80;
2536 if (enc == 4)
2538 int sjis1, sjis2;
2540 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2541 char2b->byte1 = sjis1;
2542 char2b->byte2 = sjis2;
2546 if (two_byte_p)
2547 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2549 return FONT_TYPE_UNKNOWN;
2554 /***********************************************************************
2555 Glyph display
2556 ***********************************************************************/
2560 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2561 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2562 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2563 int));
2564 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2565 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2566 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2567 static void x_draw_glyph_string P_ ((struct glyph_string *));
2568 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2569 static void x_set_cursor_gc P_ ((struct glyph_string *));
2570 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2571 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2572 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2573 unsigned long *, double, int));*/
2574 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2575 double, int, unsigned long));
2576 static void x_setup_relief_colors P_ ((struct glyph_string *));
2577 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2578 static void x_draw_image_relief P_ ((struct glyph_string *));
2579 static void x_draw_image_foreground P_ ((struct glyph_string *));
2580 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2581 int, int, int));
2582 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2583 int, int, int, int, int, int,
2584 Rect *));
2585 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2586 int, int, int, Rect *));
2588 #if GLYPH_DEBUG
2589 static void x_check_font P_ ((struct frame *, XFontStruct *));
2590 #endif
2593 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2594 face. */
2596 static void
2597 x_set_cursor_gc (s)
2598 struct glyph_string *s;
2600 if (s->font == FRAME_FONT (s->f)
2601 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2602 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2603 && !s->cmp)
2604 s->gc = s->f->output_data.mac->cursor_gc;
2605 else
2607 /* Cursor on non-default face: must merge. */
2608 XGCValues xgcv;
2609 unsigned long mask;
2611 xgcv.background = s->f->output_data.mac->cursor_pixel;
2612 xgcv.foreground = s->face->background;
2614 /* If the glyph would be invisible, try a different foreground. */
2615 if (xgcv.foreground == xgcv.background)
2616 xgcv.foreground = s->face->foreground;
2617 if (xgcv.foreground == xgcv.background)
2618 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2619 if (xgcv.foreground == xgcv.background)
2620 xgcv.foreground = s->face->foreground;
2622 /* Make sure the cursor is distinct from text in this face. */
2623 if (xgcv.background == s->face->background
2624 && xgcv.foreground == s->face->foreground)
2626 xgcv.background = s->face->foreground;
2627 xgcv.foreground = s->face->background;
2630 IF_DEBUG (x_check_font (s->f, s->font));
2631 xgcv.font = s->font;
2632 mask = GCForeground | GCBackground | GCFont;
2634 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2635 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2636 mask, &xgcv);
2637 else
2638 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2639 = XCreateGC (s->display, s->window, mask, &xgcv);
2641 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2646 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2648 static void
2649 x_set_mouse_face_gc (s)
2650 struct glyph_string *s;
2652 int face_id;
2653 struct face *face;
2655 /* What face has to be used last for the mouse face? */
2656 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2657 face = FACE_FROM_ID (s->f, face_id);
2658 if (face == NULL)
2659 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2661 if (s->first_glyph->type == CHAR_GLYPH)
2662 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2663 else
2664 face_id = FACE_FOR_CHAR (s->f, face, 0);
2665 s->face = FACE_FROM_ID (s->f, face_id);
2666 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2668 /* If font in this face is same as S->font, use it. */
2669 if (s->font == s->face->font)
2670 s->gc = s->face->gc;
2671 else
2673 /* Otherwise construct scratch_cursor_gc with values from FACE
2674 but font FONT. */
2675 XGCValues xgcv;
2676 unsigned long mask;
2678 xgcv.background = s->face->background;
2679 xgcv.foreground = s->face->foreground;
2680 IF_DEBUG (x_check_font (s->f, s->font));
2681 xgcv.font = s->font;
2682 mask = GCForeground | GCBackground | GCFont;
2684 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2685 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2686 mask, &xgcv);
2687 else
2688 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2689 = XCreateGC (s->display, s->window, mask, &xgcv);
2691 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2694 xassert (s->gc != 0);
2698 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2699 Faces to use in the mode line have already been computed when the
2700 matrix was built, so there isn't much to do, here. */
2702 static INLINE void
2703 x_set_mode_line_face_gc (s)
2704 struct glyph_string *s;
2706 s->gc = s->face->gc;
2710 /* Set S->gc of glyph string S for drawing that glyph string. Set
2711 S->stippled_p to a non-zero value if the face of S has a stipple
2712 pattern. */
2714 static INLINE void
2715 x_set_glyph_string_gc (s)
2716 struct glyph_string *s;
2718 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2720 if (s->hl == DRAW_NORMAL_TEXT)
2722 s->gc = s->face->gc;
2723 s->stippled_p = s->face->stipple != 0;
2725 else if (s->hl == DRAW_INVERSE_VIDEO)
2727 x_set_mode_line_face_gc (s);
2728 s->stippled_p = s->face->stipple != 0;
2730 else if (s->hl == DRAW_CURSOR)
2732 x_set_cursor_gc (s);
2733 s->stippled_p = 0;
2735 else if (s->hl == DRAW_MOUSE_FACE)
2737 x_set_mouse_face_gc (s);
2738 s->stippled_p = s->face->stipple != 0;
2740 else if (s->hl == DRAW_IMAGE_RAISED
2741 || s->hl == DRAW_IMAGE_SUNKEN)
2743 s->gc = s->face->gc;
2744 s->stippled_p = s->face->stipple != 0;
2746 else
2748 s->gc = s->face->gc;
2749 s->stippled_p = s->face->stipple != 0;
2752 /* GC must have been set. */
2753 xassert (s->gc != 0);
2757 /* Set clipping for output of glyph string S. S may be part of a mode
2758 line or menu if we don't have X toolkit support. */
2760 static INLINE void
2761 x_set_glyph_string_clipping (s)
2762 struct glyph_string *s;
2764 Rect rects[MAX_CLIP_RECTS];
2765 int n;
2767 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
2768 mac_set_clip_rectangles (s->display, s->gc, rects, n);
2772 /* RIF:
2773 Compute left and right overhang of glyph string S. If S is a glyph
2774 string for a composition, assume overhangs don't exist. */
2776 static void
2777 mac_compute_glyph_string_overhangs (s)
2778 struct glyph_string *s;
2780 if (!(s->cmp == NULL
2781 && s->first_glyph->type == CHAR_GLYPH))
2782 return;
2784 if (!s->two_byte_p
2785 #if USE_ATSUI
2786 || s->font->mac_style
2787 #endif
2790 XCharStruct cs;
2792 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2793 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2794 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2796 else
2798 Rect r;
2799 MacFontStruct *font = s->font;
2801 #if USE_CG_DRAWING
2802 mac_prepare_for_quickdraw (s->f);
2803 #endif
2804 SetPortWindowPort (FRAME_MAC_WINDOW (s->f));
2806 TextFont (font->mac_fontnum);
2807 TextSize (font->mac_fontsize);
2808 TextFace (font->mac_fontface);
2810 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2812 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2813 s->left_overhang = r.left < 0 ? -r.left : 0;
2818 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2820 static INLINE void
2821 x_clear_glyph_string_rect (s, x, y, w, h)
2822 struct glyph_string *s;
2823 int x, y, w, h;
2825 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
2829 /* Draw the background of glyph_string S. If S->background_filled_p
2830 is non-zero don't draw it. FORCE_P non-zero means draw the
2831 background even if it wouldn't be drawn normally. This is used
2832 when a string preceding S draws into the background of S, or S
2833 contains the first component of a composition. */
2835 static void
2836 x_draw_glyph_string_background (s, force_p)
2837 struct glyph_string *s;
2838 int force_p;
2840 /* Nothing to do if background has already been drawn or if it
2841 shouldn't be drawn in the first place. */
2842 if (!s->background_filled_p)
2844 int box_line_width = max (s->face->box_line_width, 0);
2846 #if 0 /* MAC_TODO: stipple */
2847 if (s->stippled_p)
2849 /* Fill background with a stipple pattern. */
2850 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2851 XFillRectangle (s->display, s->window, s->gc, s->x,
2852 s->y + box_line_width,
2853 s->background_width,
2854 s->height - 2 * box_line_width);
2855 XSetFillStyle (s->display, s->gc, FillSolid);
2856 s->background_filled_p = 1;
2858 else
2859 #endif
2860 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2861 || s->font_not_found_p
2862 || s->extends_to_end_of_line_p
2863 || force_p)
2865 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2866 s->background_width,
2867 s->height - 2 * box_line_width);
2868 s->background_filled_p = 1;
2874 /* Draw the foreground of glyph string S. */
2876 static void
2877 x_draw_glyph_string_foreground (s)
2878 struct glyph_string *s;
2880 int i, x, bg_width;
2882 /* If first glyph of S has a left box line, start drawing the text
2883 of S to the right of that box line. */
2884 if (s->face->box != FACE_NO_BOX
2885 && s->first_glyph->left_box_line_p)
2886 x = s->x + abs (s->face->box_line_width);
2887 else
2888 x = s->x;
2890 /* Draw characters of S as rectangles if S's font could not be
2891 loaded. */
2892 if (s->font_not_found_p)
2894 for (i = 0; i < s->nchars; ++i)
2896 struct glyph *g = s->first_glyph + i;
2897 mac_draw_rectangle (s->f, s->gc, x, s->y,
2898 g->pixel_width - 1, s->height - 1);
2899 x += g->pixel_width;
2902 else
2904 char *char1b = (char *) s->char2b;
2905 int boff = s->font_info->baseline_offset;
2907 if (s->font_info->vertical_centering)
2908 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2910 /* If we can use 8-bit functions, condense S->char2b. */
2911 if (!s->two_byte_p
2912 #if USE_ATSUI
2913 && GC_FONT (s->gc)->mac_style == NULL
2914 #endif
2916 for (i = 0; i < s->nchars; ++i)
2917 char1b[i] = s->char2b[i].byte2;
2919 /* Draw text with XDrawString if background has already been
2920 filled. Otherwise, use XDrawImageString. (Note that
2921 XDrawImageString is usually faster than XDrawString.) Always
2922 use XDrawImageString when drawing the cursor so that there is
2923 no chance that characters under a box cursor are invisible. */
2924 if (s->for_overlaps
2925 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2926 bg_width = 0; /* Corresponds to XDrawString. */
2927 else
2928 bg_width = s->background_width; /* Corresponds to XDrawImageString. */
2930 if (s->two_byte_p
2931 #if USE_ATSUI
2932 || GC_FONT (s->gc)->mac_style
2933 #endif
2935 #if USE_CG_TEXT_DRAWING
2936 if (!s->two_byte_p
2937 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
2938 s->char2b, s->nchars, bg_width,
2939 s->face->overstrike))
2941 else
2942 #endif
2943 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
2944 s->char2b, s->nchars, bg_width,
2945 s->face->overstrike);
2946 else
2947 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
2948 char1b, s->nchars, bg_width,
2949 s->face->overstrike);
2953 /* Draw the foreground of composite glyph string S. */
2955 static void
2956 x_draw_composite_glyph_string_foreground (s)
2957 struct glyph_string *s;
2959 int i, x;
2961 /* If first glyph of S has a left box line, start drawing the text
2962 of S to the right of that box line. */
2963 if (s->face->box != FACE_NO_BOX
2964 && s->first_glyph->left_box_line_p)
2965 x = s->x + abs (s->face->box_line_width);
2966 else
2967 x = s->x;
2969 /* S is a glyph string for a composition. S->gidx is the index of
2970 the first character drawn for glyphs of this composition.
2971 S->gidx == 0 means we are drawing the very first character of
2972 this composition. */
2974 /* Draw a rectangle for the composition if the font for the very
2975 first character of the composition could not be loaded. */
2976 if (s->font_not_found_p)
2978 if (s->gidx == 0)
2979 mac_draw_rectangle (s->f, s->gc, x, s->y,
2980 s->width - 1, s->height - 1);
2982 else
2984 for (i = 0; i < s->nchars; i++, ++s->gidx)
2985 if (mac_per_char_metric (GC_FONT (s->gc), s->char2b + i, 0) == NULL)
2986 /* This is a nonexistent or zero-width glyph such as a
2987 combining diacritic. Draw a rectangle. */
2988 mac_draw_rectangle (s->f, s->gc,
2989 x + s->cmp->offsets[s->gidx * 2], s->y,
2990 FONT_WIDTH (GC_FONT (s->gc)) - 1, s->height - 1);
2991 else
2992 mac_draw_image_string_16 (s->f, s->gc,
2993 x + s->cmp->offsets[s->gidx * 2],
2994 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2995 s->char2b + i, 1, 0, s->face->overstrike);
3000 #ifdef USE_X_TOOLKIT
3002 static struct frame *x_frame_of_widget P_ ((Widget));
3005 /* Return the frame on which widget WIDGET is used.. Abort if frame
3006 cannot be determined. */
3008 static struct frame *
3009 x_frame_of_widget (widget)
3010 Widget widget;
3012 struct x_display_info *dpyinfo;
3013 Lisp_Object tail;
3014 struct frame *f;
3016 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3018 /* Find the top-level shell of the widget. Note that this function
3019 can be called when the widget is not yet realized, so XtWindow
3020 (widget) == 0. That's the reason we can't simply use
3021 x_any_window_to_frame. */
3022 while (!XtIsTopLevelShell (widget))
3023 widget = XtParent (widget);
3025 /* Look for a frame with that top-level widget. Allocate the color
3026 on that frame to get the right gamma correction value. */
3027 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3028 if (GC_FRAMEP (XCAR (tail))
3029 && (f = XFRAME (XCAR (tail)),
3030 (f->output_data.nothing != 1
3031 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3032 && f->output_data.x->widget == widget)
3033 return f;
3035 abort ();
3039 /* Allocate the color COLOR->pixel on the screen and display of
3040 widget WIDGET in colormap CMAP. If an exact match cannot be
3041 allocated, try the nearest color available. Value is non-zero
3042 if successful. This is called from lwlib. */
3045 x_alloc_nearest_color_for_widget (widget, cmap, color)
3046 Widget widget;
3047 Colormap cmap;
3048 XColor *color;
3050 struct frame *f = x_frame_of_widget (widget);
3051 return x_alloc_nearest_color (f, cmap, color);
3055 #endif /* USE_X_TOOLKIT */
3057 #if 0 /* MAC_TODO */
3059 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3060 CMAP. If an exact match can't be allocated, try the nearest color
3061 available. Value is non-zero if successful. Set *COLOR to the
3062 color allocated. */
3065 x_alloc_nearest_color (f, cmap, color)
3066 struct frame *f;
3067 Colormap cmap;
3068 XColor *color;
3070 Display *display = FRAME_X_DISPLAY (f);
3071 Screen *screen = FRAME_X_SCREEN (f);
3072 int rc;
3074 gamma_correct (f, color);
3075 rc = XAllocColor (display, cmap, color);
3076 if (rc == 0)
3078 /* If we got to this point, the colormap is full, so we're going
3079 to try to get the next closest color. The algorithm used is
3080 a least-squares matching, which is what X uses for closest
3081 color matching with StaticColor visuals. */
3082 int nearest, i;
3083 unsigned long nearest_delta = ~0;
3084 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3085 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3087 for (i = 0; i < ncells; ++i)
3088 cells[i].pixel = i;
3089 XQueryColors (display, cmap, cells, ncells);
3091 for (nearest = i = 0; i < ncells; ++i)
3093 long dred = (color->red >> 8) - (cells[i].red >> 8);
3094 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3095 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3096 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3098 if (delta < nearest_delta)
3100 nearest = i;
3101 nearest_delta = delta;
3105 color->red = cells[nearest].red;
3106 color->green = cells[nearest].green;
3107 color->blue = cells[nearest].blue;
3108 rc = XAllocColor (display, cmap, color);
3111 #ifdef DEBUG_X_COLORS
3112 if (rc)
3113 register_color (color->pixel);
3114 #endif /* DEBUG_X_COLORS */
3116 return rc;
3120 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3121 It's necessary to do this instead of just using PIXEL directly to
3122 get color reference counts right. */
3124 unsigned long
3125 x_copy_color (f, pixel)
3126 struct frame *f;
3127 unsigned long pixel;
3129 XColor color;
3131 color.pixel = pixel;
3132 BLOCK_INPUT;
3133 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3134 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3135 UNBLOCK_INPUT;
3136 #ifdef DEBUG_X_COLORS
3137 register_color (pixel);
3138 #endif
3139 return color.pixel;
3143 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3144 It's necessary to do this instead of just using PIXEL directly to
3145 get color reference counts right. */
3147 unsigned long
3148 x_copy_dpy_color (dpy, cmap, pixel)
3149 Display *dpy;
3150 Colormap cmap;
3151 unsigned long pixel;
3153 XColor color;
3155 color.pixel = pixel;
3156 BLOCK_INPUT;
3157 XQueryColor (dpy, cmap, &color);
3158 XAllocColor (dpy, cmap, &color);
3159 UNBLOCK_INPUT;
3160 #ifdef DEBUG_X_COLORS
3161 register_color (pixel);
3162 #endif
3163 return color.pixel;
3166 #endif /* MAC_TODO */
3169 /* Brightness beyond which a color won't have its highlight brightness
3170 boosted.
3172 Nominally, highlight colors for `3d' faces are calculated by
3173 brightening an object's color by a constant scale factor, but this
3174 doesn't yield good results for dark colors, so for colors who's
3175 brightness is less than this value (on a scale of 0-255) have to
3176 use an additional additive factor.
3178 The value here is set so that the default menu-bar/mode-line color
3179 (grey75) will not have its highlights changed at all. */
3180 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3183 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3184 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3185 If this produces the same color as COLOR, try a color where all RGB
3186 values have DELTA added. Return the allocated color in *COLOR.
3187 DISPLAY is the X display, CMAP is the colormap to operate on.
3188 Value is non-zero if successful. */
3190 static int
3191 mac_alloc_lighter_color (f, color, factor, delta)
3192 struct frame *f;
3193 unsigned long *color;
3194 double factor;
3195 int delta;
3197 unsigned long new;
3198 long bright;
3200 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3201 delta /= 256;
3203 /* Change RGB values by specified FACTOR. Avoid overflow! */
3204 xassert (factor >= 0);
3205 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3206 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3207 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3209 /* Calculate brightness of COLOR. */
3210 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
3211 + BLUE_FROM_ULONG (*color)) / 6;
3213 /* We only boost colors that are darker than
3214 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3215 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3216 /* Make an additive adjustment to NEW, because it's dark enough so
3217 that scaling by FACTOR alone isn't enough. */
3219 /* How far below the limit this color is (0 - 1, 1 being darker). */
3220 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3221 /* The additive adjustment. */
3222 int min_delta = delta * dimness * factor / 2;
3224 if (factor < 1)
3225 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
3226 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
3227 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
3228 else
3229 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
3230 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
3231 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
3234 if (new == *color)
3235 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3236 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3237 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3239 /* MAC_TODO: Map to palette and retry with delta if same? */
3240 /* MAC_TODO: Free colors (if using palette)? */
3242 if (new == *color)
3243 return 0;
3245 *color = new;
3247 return 1;
3251 /* Set up the foreground color for drawing relief lines of glyph
3252 string S. RELIEF is a pointer to a struct relief containing the GC
3253 with which lines will be drawn. Use a color that is FACTOR or
3254 DELTA lighter or darker than the relief's background which is found
3255 in S->f->output_data.x->relief_background. If such a color cannot
3256 be allocated, use DEFAULT_PIXEL, instead. */
3258 static void
3259 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3260 struct frame *f;
3261 struct relief *relief;
3262 double factor;
3263 int delta;
3264 unsigned long default_pixel;
3266 XGCValues xgcv;
3267 struct mac_output *di = f->output_data.mac;
3268 unsigned long mask = GCForeground;
3269 unsigned long pixel;
3270 unsigned long background = di->relief_background;
3271 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3273 /* MAC_TODO: Free colors (if using palette)? */
3275 /* Allocate new color. */
3276 xgcv.foreground = default_pixel;
3277 pixel = background;
3278 if (dpyinfo->n_planes != 1
3279 && mac_alloc_lighter_color (f, &pixel, factor, delta))
3281 relief->allocated_p = 1;
3282 xgcv.foreground = relief->pixel = pixel;
3285 if (relief->gc == 0)
3287 #if 0 /* MAC_TODO: stipple */
3288 xgcv.stipple = dpyinfo->gray;
3289 mask |= GCStipple;
3290 #endif
3291 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3293 else
3294 XChangeGC (NULL, relief->gc, mask, &xgcv);
3298 /* Set up colors for the relief lines around glyph string S. */
3300 static void
3301 x_setup_relief_colors (s)
3302 struct glyph_string *s;
3304 struct mac_output *di = s->f->output_data.mac;
3305 unsigned long color;
3307 if (s->face->use_box_color_for_shadows_p)
3308 color = s->face->box_color;
3309 else if (s->first_glyph->type == IMAGE_GLYPH
3310 && s->img->pixmap
3311 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3312 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3313 else
3315 XGCValues xgcv;
3317 /* Get the background color of the face. */
3318 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3319 color = xgcv.background;
3322 if (di->white_relief.gc == 0
3323 || color != di->relief_background)
3325 di->relief_background = color;
3326 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3327 WHITE_PIX_DEFAULT (s->f));
3328 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3329 BLACK_PIX_DEFAULT (s->f));
3334 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3335 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3336 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3337 relief. LEFT_P non-zero means draw a relief on the left side of
3338 the rectangle. RIGHT_P non-zero means draw a relief on the right
3339 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3340 when drawing. */
3342 static void
3343 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3344 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
3345 struct frame *f;
3346 int left_x, top_y, right_x, bottom_y, width;
3347 int top_p, bot_p, left_p, right_p, raised_p;
3348 Rect *clip_rect;
3350 Display *dpy = FRAME_MAC_DISPLAY (f);
3351 int i;
3352 GC gc;
3354 if (raised_p)
3355 gc = f->output_data.mac->white_relief.gc;
3356 else
3357 gc = f->output_data.mac->black_relief.gc;
3358 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3360 /* Top. */
3361 if (top_p)
3362 for (i = 0; i < width; ++i)
3363 mac_draw_line (f, gc,
3364 left_x + i * left_p, top_y + i,
3365 right_x + 1 - i * right_p, top_y + i);
3367 /* Left. */
3368 if (left_p)
3369 for (i = 0; i < width; ++i)
3370 mac_draw_line (f, gc,
3371 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3373 mac_reset_clip_rectangles (dpy, gc);
3374 if (raised_p)
3375 gc = f->output_data.mac->black_relief.gc;
3376 else
3377 gc = f->output_data.mac->white_relief.gc;
3378 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3380 /* Bottom. */
3381 if (bot_p)
3382 for (i = 0; i < width; ++i)
3383 mac_draw_line (f, gc,
3384 left_x + i * left_p, bottom_y - i,
3385 right_x + 1 - i * right_p, bottom_y - i);
3387 /* Right. */
3388 if (right_p)
3389 for (i = 0; i < width; ++i)
3390 mac_draw_line (f, gc,
3391 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3393 mac_reset_clip_rectangles (dpy, gc);
3397 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3398 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3399 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3400 left side of the rectangle. RIGHT_P non-zero means draw a line
3401 on the right side of the rectangle. CLIP_RECT is the clipping
3402 rectangle to use when drawing. */
3404 static void
3405 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3406 left_p, right_p, clip_rect)
3407 struct glyph_string *s;
3408 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3409 Rect *clip_rect;
3411 XGCValues xgcv;
3413 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3414 XSetForeground (s->display, s->gc, s->face->box_color);
3415 mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1);
3417 /* Top. */
3418 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3419 right_x - left_x + 1, width);
3421 /* Left. */
3422 if (left_p)
3423 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3424 width, bottom_y - top_y + 1);
3426 /* Bottom. */
3427 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
3428 right_x - left_x + 1, width);
3430 /* Right. */
3431 if (right_p)
3432 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
3433 top_y, width, bottom_y - top_y + 1);
3435 XSetForeground (s->display, s->gc, xgcv.foreground);
3436 mac_reset_clip_rectangles (s->display, s->gc);
3440 /* Draw a box around glyph string S. */
3442 static void
3443 x_draw_glyph_string_box (s)
3444 struct glyph_string *s;
3446 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3447 int left_p, right_p;
3448 struct glyph *last_glyph;
3449 Rect clip_rect;
3451 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3452 ? WINDOW_RIGHT_EDGE_X (s->w)
3453 : window_box_right (s->w, s->area));
3455 /* The glyph that may have a right box line. */
3456 last_glyph = (s->cmp || s->img
3457 ? s->first_glyph
3458 : s->first_glyph + s->nchars - 1);
3460 width = abs (s->face->box_line_width);
3461 raised_p = s->face->box == FACE_RAISED_BOX;
3462 left_x = s->x;
3463 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3464 ? last_x - 1
3465 : min (last_x, s->x + s->background_width) - 1);
3466 top_y = s->y;
3467 bottom_y = top_y + s->height - 1;
3469 left_p = (s->first_glyph->left_box_line_p
3470 || (s->hl == DRAW_MOUSE_FACE
3471 && (s->prev == NULL
3472 || s->prev->hl != s->hl)));
3473 right_p = (last_glyph->right_box_line_p
3474 || (s->hl == DRAW_MOUSE_FACE
3475 && (s->next == NULL
3476 || s->next->hl != s->hl)));
3478 get_glyph_string_clip_rect (s, &clip_rect);
3480 if (s->face->box == FACE_SIMPLE_BOX)
3481 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3482 left_p, right_p, &clip_rect);
3483 else
3485 x_setup_relief_colors (s);
3486 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3487 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
3492 /* Draw foreground of image glyph string S. */
3494 static void
3495 x_draw_image_foreground (s)
3496 struct glyph_string *s;
3498 int x = s->x;
3499 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3501 /* If first glyph of S has a left box line, start drawing it to the
3502 right of that line. */
3503 if (s->face->box != FACE_NO_BOX
3504 && s->first_glyph->left_box_line_p
3505 && s->slice.x == 0)
3506 x += abs (s->face->box_line_width);
3508 /* If there is a margin around the image, adjust x- and y-position
3509 by that margin. */
3510 if (s->slice.x == 0)
3511 x += s->img->hmargin;
3512 if (s->slice.y == 0)
3513 y += s->img->vmargin;
3515 if (s->img->pixmap)
3517 x_set_glyph_string_clipping (s);
3519 #if USE_CG_DRAWING
3520 mac_draw_cg_image (s->img->data.ptr_val,
3521 s->f, s->gc, s->slice.x, s->slice.y,
3522 s->slice.width, s->slice.height, x, y, 1);
3523 #endif
3524 if (s->img->mask)
3525 #if !USE_CG_DRAWING
3526 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3527 s->f, s->gc, s->slice.x, s->slice.y,
3528 s->slice.width, s->slice.height, x, y);
3529 #else
3531 #endif
3532 else
3534 #if !USE_CG_DRAWING
3535 mac_copy_area (s->img->pixmap,
3536 s->f, s->gc, s->slice.x, s->slice.y,
3537 s->slice.width, s->slice.height, x, y);
3538 #endif
3540 /* When the image has a mask, we can expect that at
3541 least part of a mouse highlight or a block cursor will
3542 be visible. If the image doesn't have a mask, make
3543 a block cursor visible by drawing a rectangle around
3544 the image. I believe it's looking better if we do
3545 nothing here for mouse-face. */
3546 if (s->hl == DRAW_CURSOR)
3548 int r = s->img->relief;
3549 if (r < 0) r = -r;
3550 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
3551 s->slice.width + r*2 - 1,
3552 s->slice.height + r*2 - 1);
3556 else
3557 /* Draw a rectangle if image could not be loaded. */
3558 mac_draw_rectangle (s->f, s->gc, x, y,
3559 s->slice.width - 1, s->slice.height - 1);
3563 /* Draw a relief around the image glyph string S. */
3565 static void
3566 x_draw_image_relief (s)
3567 struct glyph_string *s;
3569 int x0, y0, x1, y1, thick, raised_p;
3570 Rect r;
3571 int x = s->x;
3572 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3574 /* If first glyph of S has a left box line, start drawing it to the
3575 right of that line. */
3576 if (s->face->box != FACE_NO_BOX
3577 && s->first_glyph->left_box_line_p
3578 && s->slice.x == 0)
3579 x += abs (s->face->box_line_width);
3581 /* If there is a margin around the image, adjust x- and y-position
3582 by that margin. */
3583 if (s->slice.x == 0)
3584 x += s->img->hmargin;
3585 if (s->slice.y == 0)
3586 y += s->img->vmargin;
3588 if (s->hl == DRAW_IMAGE_SUNKEN
3589 || s->hl == DRAW_IMAGE_RAISED)
3591 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3592 raised_p = s->hl == DRAW_IMAGE_RAISED;
3594 else
3596 thick = abs (s->img->relief);
3597 raised_p = s->img->relief > 0;
3600 x0 = x - thick;
3601 y0 = y - thick;
3602 x1 = x + s->slice.width + thick - 1;
3603 y1 = y + s->slice.height + thick - 1;
3605 x_setup_relief_colors (s);
3606 get_glyph_string_clip_rect (s, &r);
3607 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3608 s->slice.y == 0,
3609 s->slice.y + s->slice.height == s->img->height,
3610 s->slice.x == 0,
3611 s->slice.x + s->slice.width == s->img->width,
3612 &r);
3616 /* Draw part of the background of glyph string S. X, Y, W, and H
3617 give the rectangle to draw. */
3619 static void
3620 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3621 struct glyph_string *s;
3622 int x, y, w, h;
3624 #if 0 /* MAC_TODO: stipple */
3625 if (s->stippled_p)
3627 /* Fill background with a stipple pattern. */
3628 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3629 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3630 XSetFillStyle (s->display, s->gc, FillSolid);
3632 else
3633 #endif /* MAC_TODO */
3634 x_clear_glyph_string_rect (s, x, y, w, h);
3638 /* Draw image glyph string S.
3640 s->y
3641 s->x +-------------------------
3642 | s->face->box
3644 | +-------------------------
3645 | | s->img->margin
3647 | | +-------------------
3648 | | | the image
3652 static void
3653 x_draw_image_glyph_string (s)
3654 struct glyph_string *s;
3656 int x, y;
3657 int box_line_hwidth = abs (s->face->box_line_width);
3658 int box_line_vwidth = max (s->face->box_line_width, 0);
3659 int height;
3661 height = s->height - 2 * box_line_vwidth;
3664 /* Fill background with face under the image. Do it only if row is
3665 taller than image or if image has a clip mask to reduce
3666 flickering. */
3667 s->stippled_p = s->face->stipple != 0;
3668 if (height > s->slice.height
3669 || s->img->hmargin
3670 || s->img->vmargin
3671 || s->img->mask
3672 || s->img->pixmap == 0
3673 || s->width != s->background_width)
3675 x = s->x;
3676 if (s->first_glyph->left_box_line_p
3677 && s->slice.x == 0)
3678 x += box_line_hwidth;
3680 y = s->y;
3681 if (s->slice.y == 0)
3682 y += box_line_vwidth;
3684 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3686 s->background_filled_p = 1;
3689 /* Draw the foreground. */
3690 x_draw_image_foreground (s);
3692 /* If we must draw a relief around the image, do it. */
3693 if (s->img->relief
3694 || s->hl == DRAW_IMAGE_RAISED
3695 || s->hl == DRAW_IMAGE_SUNKEN)
3696 x_draw_image_relief (s);
3700 /* Draw stretch glyph string S. */
3702 static void
3703 x_draw_stretch_glyph_string (s)
3704 struct glyph_string *s;
3706 xassert (s->first_glyph->type == STRETCH_GLYPH);
3708 if (s->hl == DRAW_CURSOR
3709 && !x_stretch_cursor_p)
3711 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3712 as wide as the stretch glyph. */
3713 int width, background_width = s->background_width;
3714 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3716 if (x < left_x)
3718 background_width -= left_x - x;
3719 x = left_x;
3721 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3723 /* Draw cursor. */
3724 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3726 /* Clear rest using the GC of the original non-cursor face. */
3727 if (width < background_width)
3729 int y = s->y;
3730 int w = background_width - width, h = s->height;
3731 Rect r;
3732 GC gc;
3734 x += width;
3735 if (s->row->mouse_face_p
3736 && cursor_in_mouse_face_p (s->w))
3738 x_set_mouse_face_gc (s);
3739 gc = s->gc;
3741 else
3742 gc = s->face->gc;
3744 get_glyph_string_clip_rect (s, &r);
3745 mac_set_clip_rectangles (s->display, gc, &r, 1);
3747 #if 0 /* MAC_TODO: stipple */
3748 if (s->face->stipple)
3750 /* Fill background with a stipple pattern. */
3751 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3752 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3753 XSetFillStyle (s->display, gc, FillSolid);
3755 else
3756 #endif /* MAC_TODO */
3757 mac_erase_rectangle (s->f, gc, x, y, w, h);
3760 else if (!s->background_filled_p)
3762 int background_width = s->background_width;
3763 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3765 /* Don't draw into left margin, fringe or scrollbar area
3766 except for header line and mode line. */
3767 if (x < left_x && !s->row->mode_line_p)
3769 background_width -= left_x - x;
3770 x = left_x;
3772 if (background_width > 0)
3773 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3776 s->background_filled_p = 1;
3780 /* Draw glyph string S. */
3782 static void
3783 x_draw_glyph_string (s)
3784 struct glyph_string *s;
3786 int relief_drawn_p = 0;
3788 /* If S draws into the background of its successor that does not
3789 draw a cursor, draw the background of the successor first so that
3790 S can draw into it. This makes S->next use XDrawString instead
3791 of XDrawImageString. */
3792 if (s->next && s->right_overhang && !s->for_overlaps
3793 && s->next->hl != DRAW_CURSOR)
3795 xassert (s->next->img == NULL);
3796 x_set_glyph_string_gc (s->next);
3797 x_set_glyph_string_clipping (s->next);
3798 x_draw_glyph_string_background (s->next, 1);
3801 /* Set up S->gc, set clipping and draw S. */
3802 x_set_glyph_string_gc (s);
3804 /* Draw relief (if any) in advance for char/composition so that the
3805 glyph string can be drawn over it. */
3806 if (!s->for_overlaps
3807 && s->face->box != FACE_NO_BOX
3808 && (s->first_glyph->type == CHAR_GLYPH
3809 || s->first_glyph->type == COMPOSITE_GLYPH))
3812 x_set_glyph_string_clipping (s);
3813 x_draw_glyph_string_background (s, 1);
3814 x_draw_glyph_string_box (s);
3815 x_set_glyph_string_clipping (s);
3816 relief_drawn_p = 1;
3818 else
3819 x_set_glyph_string_clipping (s);
3821 switch (s->first_glyph->type)
3823 case IMAGE_GLYPH:
3824 x_draw_image_glyph_string (s);
3825 break;
3827 case STRETCH_GLYPH:
3828 x_draw_stretch_glyph_string (s);
3829 break;
3831 case CHAR_GLYPH:
3832 if (s->for_overlaps)
3833 s->background_filled_p = 1;
3834 else
3835 x_draw_glyph_string_background (s, 0);
3836 x_draw_glyph_string_foreground (s);
3837 break;
3839 case COMPOSITE_GLYPH:
3840 if (s->for_overlaps || s->gidx > 0)
3841 s->background_filled_p = 1;
3842 else
3843 x_draw_glyph_string_background (s, 1);
3844 x_draw_composite_glyph_string_foreground (s);
3845 break;
3847 default:
3848 abort ();
3851 if (!s->for_overlaps)
3853 /* Draw underline. */
3854 if (s->face->underline_p)
3856 unsigned long tem, h;
3857 int y;
3859 #if 0
3860 /* Get the underline thickness. Default is 1 pixel. */
3861 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3862 #endif
3863 h = 1;
3865 y = s->y + s->height - h;
3866 if (!x_underline_at_descent_line)
3868 /* Get the underline position. This is the recommended
3869 vertical offset in pixels from the baseline to the top of
3870 the underline. This is a signed value according to the
3871 specs, and its default is
3873 ROUND ((maximum descent) / 2), with
3874 ROUND(x) = floor (x + 0.5) */
3876 #if 0
3877 if (x_use_underline_position_properties
3878 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
3879 y = s->ybase + (long) tem;
3880 else
3881 #endif
3882 if (s->face->font)
3883 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
3886 if (s->face->underline_defaulted_p)
3887 mac_fill_rectangle (s->f, s->gc, s->x, y,
3888 s->background_width, h);
3889 else
3891 XGCValues xgcv;
3892 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3893 XSetForeground (s->display, s->gc, s->face->underline_color);
3894 mac_fill_rectangle (s->f, s->gc, s->x, y,
3895 s->background_width, h);
3896 XSetForeground (s->display, s->gc, xgcv.foreground);
3900 /* Draw overline. */
3901 if (s->face->overline_p)
3903 unsigned long dy = 0, h = 1;
3905 if (s->face->overline_color_defaulted_p)
3906 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3907 s->background_width, h);
3908 else
3910 XGCValues xgcv;
3911 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3912 XSetForeground (s->display, s->gc, s->face->overline_color);
3913 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3914 s->background_width, h);
3915 XSetForeground (s->display, s->gc, xgcv.foreground);
3919 /* Draw strike-through. */
3920 if (s->face->strike_through_p)
3922 unsigned long h = 1;
3923 unsigned long dy = (s->height - h) / 2;
3925 if (s->face->strike_through_color_defaulted_p)
3926 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3927 s->width, h);
3928 else
3930 XGCValues xgcv;
3931 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3932 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3933 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3934 s->width, h);
3935 XSetForeground (s->display, s->gc, xgcv.foreground);
3939 /* Draw relief if not yet drawn. */
3940 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3941 x_draw_glyph_string_box (s);
3944 /* Reset clipping. */
3945 mac_reset_clip_rectangles (s->display, s->gc);
3948 /* Shift display to make room for inserted glyphs. */
3950 void
3951 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3952 struct frame *f;
3953 int x, y, width, height, shift_by;
3955 mac_scroll_area (f, f->output_data.mac->normal_gc,
3956 x, y, width, height,
3957 x + shift_by, y);
3960 /* Delete N glyphs at the nominal cursor position. Not implemented
3961 for X frames. */
3963 static void
3964 x_delete_glyphs (n)
3965 register int n;
3967 abort ();
3971 /* Clear entire frame. If updating_frame is non-null, clear that
3972 frame. Otherwise clear the selected frame. */
3974 static void
3975 x_clear_frame ()
3977 struct frame *f;
3979 if (updating_frame)
3980 f = updating_frame;
3981 else
3982 f = SELECTED_FRAME ();
3984 /* Clearing the frame will erase any cursor, so mark them all as no
3985 longer visible. */
3986 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3987 output_cursor.hpos = output_cursor.vpos = 0;
3988 output_cursor.x = -1;
3990 /* We don't set the output cursor here because there will always
3991 follow an explicit cursor_to. */
3992 BLOCK_INPUT;
3993 mac_clear_window (f);
3995 /* We have to clear the scroll bars, too. If we have changed
3996 colors or something like that, then they should be notified. */
3997 x_scroll_bar_clear (f);
3999 XFlush (FRAME_MAC_DISPLAY (f));
4000 UNBLOCK_INPUT;
4005 /* Invert the middle quarter of the frame for .15 sec. */
4007 /* We use the select system call to do the waiting, so we have to make
4008 sure it's available. If it isn't, we just won't do visual bells. */
4010 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4013 /* Subtract the `struct timeval' values X and Y, storing the result in
4014 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4016 static int
4017 timeval_subtract (result, x, y)
4018 struct timeval *result, x, y;
4020 /* Perform the carry for the later subtraction by updating y. This
4021 is safer because on some systems the tv_sec member is unsigned. */
4022 if (x.tv_usec < y.tv_usec)
4024 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4025 y.tv_usec -= 1000000 * nsec;
4026 y.tv_sec += nsec;
4029 if (x.tv_usec - y.tv_usec > 1000000)
4031 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4032 y.tv_usec += 1000000 * nsec;
4033 y.tv_sec -= nsec;
4036 /* Compute the time remaining to wait. tv_usec is certainly
4037 positive. */
4038 result->tv_sec = x.tv_sec - y.tv_sec;
4039 result->tv_usec = x.tv_usec - y.tv_usec;
4041 /* Return indication of whether the result should be considered
4042 negative. */
4043 return x.tv_sec < y.tv_sec;
4046 void
4047 XTflash (f)
4048 struct frame *f;
4050 /* Get the height not including a menu bar widget. */
4051 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
4052 /* Height of each line to flash. */
4053 int flash_height = FRAME_LINE_HEIGHT (f);
4054 /* These will be the left and right margins of the rectangles. */
4055 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4056 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4058 int width;
4060 /* Don't flash the area between a scroll bar and the frame
4061 edge it is next to. */
4062 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4064 case vertical_scroll_bar_left:
4065 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4066 break;
4068 case vertical_scroll_bar_right:
4069 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4070 break;
4072 default:
4073 break;
4076 width = flash_right - flash_left;
4078 BLOCK_INPUT;
4080 /* If window is tall, flash top and bottom line. */
4081 if (height > 3 * FRAME_LINE_HEIGHT (f))
4083 mac_invert_rectangle (f, flash_left,
4084 (FRAME_INTERNAL_BORDER_WIDTH (f)
4085 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4086 width, flash_height);
4087 mac_invert_rectangle (f, flash_left,
4088 (height - flash_height
4089 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4090 width, flash_height);
4092 else
4093 /* If it is short, flash it all. */
4094 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4095 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4097 x_flush (f);
4100 struct timeval wakeup;
4102 EMACS_GET_TIME (wakeup);
4104 /* Compute time to wait until, propagating carry from usecs. */
4105 wakeup.tv_usec += 150000;
4106 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4107 wakeup.tv_usec %= 1000000;
4109 /* Keep waiting until past the time wakeup or any input gets
4110 available. */
4111 while (! detect_input_pending ())
4113 struct timeval current;
4114 struct timeval timeout;
4116 EMACS_GET_TIME (current);
4118 /* Break if result would be negative. */
4119 if (timeval_subtract (&current, wakeup, current))
4120 break;
4122 /* How long `select' should wait. */
4123 timeout.tv_sec = 0;
4124 timeout.tv_usec = 10000;
4126 /* Try to wait that long--but we might wake up sooner. */
4127 select (0, NULL, NULL, NULL, &timeout);
4131 /* If window is tall, flash top and bottom line. */
4132 if (height > 3 * FRAME_LINE_HEIGHT (f))
4134 mac_invert_rectangle (f, flash_left,
4135 (FRAME_INTERNAL_BORDER_WIDTH (f)
4136 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4137 width, flash_height);
4138 mac_invert_rectangle (f, flash_left,
4139 (height - flash_height
4140 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4141 width, flash_height);
4143 else
4144 /* If it is short, flash it all. */
4145 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4146 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4148 x_flush (f);
4150 UNBLOCK_INPUT;
4153 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4156 /* Make audible bell. */
4158 void
4159 XTring_bell ()
4161 struct frame *f = SELECTED_FRAME ();
4163 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4164 if (visible_bell)
4165 XTflash (f);
4166 else
4167 #endif
4169 BLOCK_INPUT;
4170 SysBeep (1);
4171 XFlush (FRAME_MAC_DISPLAY (f));
4172 UNBLOCK_INPUT;
4177 /* Specify how many text lines, from the top of the window,
4178 should be affected by insert-lines and delete-lines operations.
4179 This, and those operations, are used only within an update
4180 that is bounded by calls to x_update_begin and x_update_end. */
4182 static void
4183 XTset_terminal_window (n)
4184 register int n;
4186 /* This function intentionally left blank. */
4191 /***********************************************************************
4192 Line Dance
4193 ***********************************************************************/
4195 /* Perform an insert-lines or delete-lines operation, inserting N
4196 lines or deleting -N lines at vertical position VPOS. */
4198 static void
4199 x_ins_del_lines (vpos, n)
4200 int vpos, n;
4202 abort ();
4206 /* Scroll part of the display as described by RUN. */
4208 static void
4209 x_scroll_run (w, run)
4210 struct window *w;
4211 struct run *run;
4213 struct frame *f = XFRAME (w->frame);
4214 int x, y, width, height, from_y, to_y, bottom_y;
4216 /* Get frame-relative bounding box of the text display area of W,
4217 without mode lines. Include in this box the left and right
4218 fringe of W. */
4219 window_box (w, -1, &x, &y, &width, &height);
4221 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4222 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4223 bottom_y = y + height;
4225 if (to_y < from_y)
4227 /* Scrolling up. Make sure we don't copy part of the mode
4228 line at the bottom. */
4229 if (from_y + run->height > bottom_y)
4230 height = bottom_y - from_y;
4231 else
4232 height = run->height;
4234 else
4236 /* Scolling down. Make sure we don't copy over the mode line.
4237 at the bottom. */
4238 if (to_y + run->height > bottom_y)
4239 height = bottom_y - to_y;
4240 else
4241 height = run->height;
4244 BLOCK_INPUT;
4246 /* Cursor off. Will be switched on again in x_update_window_end. */
4247 updated_window = w;
4248 x_clear_cursor (w);
4250 mac_scroll_area (f, f->output_data.mac->normal_gc,
4251 x, from_y,
4252 width, height,
4253 x, to_y);
4255 UNBLOCK_INPUT;
4260 /***********************************************************************
4261 Exposure Events
4262 ***********************************************************************/
4265 static void
4266 frame_highlight (f)
4267 struct frame *f;
4269 OSErr err;
4270 ControlRef root_control;
4272 BLOCK_INPUT;
4273 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
4274 if (err == noErr)
4275 ActivateControl (root_control);
4276 UNBLOCK_INPUT;
4277 x_update_cursor (f, 1);
4280 static void
4281 frame_unhighlight (f)
4282 struct frame *f;
4284 OSErr err;
4285 ControlRef root_control;
4287 BLOCK_INPUT;
4288 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
4289 if (err == noErr)
4290 DeactivateControl (root_control);
4291 UNBLOCK_INPUT;
4292 x_update_cursor (f, 1);
4295 /* The focus has changed. Update the frames as necessary to reflect
4296 the new situation. Note that we can't change the selected frame
4297 here, because the Lisp code we are interrupting might become confused.
4298 Each event gets marked with the frame in which it occurred, so the
4299 Lisp code can tell when the switch took place by examining the events. */
4301 static void
4302 x_new_focus_frame (dpyinfo, frame)
4303 struct x_display_info *dpyinfo;
4304 struct frame *frame;
4306 struct frame *old_focus = dpyinfo->x_focus_frame;
4308 if (frame != dpyinfo->x_focus_frame)
4310 /* Set this before calling other routines, so that they see
4311 the correct value of x_focus_frame. */
4312 dpyinfo->x_focus_frame = frame;
4314 if (old_focus && old_focus->auto_lower)
4315 x_lower_frame (old_focus);
4317 #if 0
4318 selected_frame = frame;
4319 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
4320 selected_frame);
4321 Fselect_window (selected_frame->selected_window, Qnil);
4322 choose_minibuf_frame ();
4323 #endif /* ! 0 */
4325 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4326 pending_autoraise_frame = dpyinfo->x_focus_frame;
4327 else
4328 pending_autoraise_frame = 0;
4330 #if USE_MAC_FONT_PANEL
4331 if (frame)
4332 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
4333 #endif
4336 x_frame_rehighlight (dpyinfo);
4339 /* Handle FocusIn and FocusOut state changes for FRAME.
4340 If FRAME has focus and there exists more than one frame, puts
4341 a FOCUS_IN_EVENT into *BUFP. */
4343 static void
4344 mac_focus_changed (type, dpyinfo, frame, bufp)
4345 int type;
4346 struct mac_display_info *dpyinfo;
4347 struct frame *frame;
4348 struct input_event *bufp;
4350 if (type == activeFlag)
4352 if (dpyinfo->x_focus_event_frame != frame)
4354 x_new_focus_frame (dpyinfo, frame);
4355 dpyinfo->x_focus_event_frame = frame;
4357 /* Don't stop displaying the initial startup message
4358 for a switch-frame event we don't need. */
4359 if (GC_NILP (Vterminal_frame)
4360 && GC_CONSP (Vframe_list)
4361 && !GC_NILP (XCDR (Vframe_list)))
4363 bufp->kind = FOCUS_IN_EVENT;
4364 XSETFRAME (bufp->frame_or_window, frame);
4368 else
4370 if (dpyinfo->x_focus_event_frame == frame)
4372 dpyinfo->x_focus_event_frame = 0;
4373 x_new_focus_frame (dpyinfo, 0);
4378 /* The focus may have changed. Figure out if it is a real focus change,
4379 by checking both FocusIn/Out and Enter/LeaveNotify events.
4381 Returns FOCUS_IN_EVENT event in *BUFP. */
4383 static void
4384 x_detect_focus_change (dpyinfo, event, bufp)
4385 struct mac_display_info *dpyinfo;
4386 const EventRecord *event;
4387 struct input_event *bufp;
4389 struct frame *frame;
4391 frame = mac_window_to_frame ((WindowPtr) event->message);
4392 if (! frame)
4393 return;
4395 /* On Mac, this is only called from focus events, so no switch needed. */
4396 mac_focus_changed ((event->modifiers & activeFlag),
4397 dpyinfo, frame, bufp);
4401 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4403 void
4404 x_mouse_leave (dpyinfo)
4405 struct x_display_info *dpyinfo;
4407 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4410 /* The focus has changed, or we have redirected a frame's focus to
4411 another frame (this happens when a frame uses a surrogate
4412 mini-buffer frame). Shift the highlight as appropriate.
4414 The FRAME argument doesn't necessarily have anything to do with which
4415 frame is being highlighted or un-highlighted; we only use it to find
4416 the appropriate X display info. */
4418 static void
4419 XTframe_rehighlight (frame)
4420 struct frame *frame;
4422 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
4425 static void
4426 x_frame_rehighlight (dpyinfo)
4427 struct x_display_info *dpyinfo;
4429 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4431 if (dpyinfo->x_focus_frame)
4433 dpyinfo->x_highlight_frame
4434 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4435 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4436 : dpyinfo->x_focus_frame);
4437 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4439 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
4440 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4443 else
4444 dpyinfo->x_highlight_frame = 0;
4446 if (dpyinfo->x_highlight_frame != old_highlight)
4448 if (old_highlight)
4449 frame_unhighlight (old_highlight);
4450 if (dpyinfo->x_highlight_frame)
4451 frame_highlight (dpyinfo->x_highlight_frame);
4457 /* Convert a keysym to its name. */
4459 char *
4460 x_get_keysym_name (keysym)
4461 int keysym;
4463 char *value;
4465 BLOCK_INPUT;
4466 #if 0
4467 value = XKeysymToString (keysym);
4468 #else
4469 value = 0;
4470 #endif
4471 UNBLOCK_INPUT;
4473 return value;
4478 /* Function to report a mouse movement to the mainstream Emacs code.
4479 The input handler calls this.
4481 We have received a mouse movement event, which is given in *event.
4482 If the mouse is over a different glyph than it was last time, tell
4483 the mainstream emacs code by setting mouse_moved. If not, ask for
4484 another motion event, so we can check again the next time it moves. */
4486 static Point last_mouse_motion_position;
4487 static Lisp_Object last_mouse_motion_frame;
4489 static int
4490 note_mouse_movement (frame, pos)
4491 FRAME_PTR frame;
4492 Point *pos;
4494 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4495 #if TARGET_API_MAC_CARBON
4496 Rect r;
4497 #endif
4499 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4500 last_mouse_motion_position = *pos;
4501 XSETFRAME (last_mouse_motion_frame, frame);
4503 if (frame == dpyinfo->mouse_face_mouse_frame
4504 #if TARGET_API_MAC_CARBON
4505 && !PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r))
4506 #else
4507 && !PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect)
4508 #endif
4511 /* This case corresponds to LeaveNotify in X11. If we move
4512 outside the frame, then we're certainly no longer on any text
4513 in the frame. */
4514 clear_mouse_face (dpyinfo);
4515 dpyinfo->mouse_face_mouse_frame = 0;
4516 if (!dpyinfo->grabbed)
4517 rif->define_frame_cursor (frame,
4518 frame->output_data.mac->nontext_cursor);
4521 /* Has the mouse moved off the glyph it was on at the last sighting? */
4522 if (frame != last_mouse_glyph_frame
4523 || !PtInRect (*pos, &last_mouse_glyph))
4525 frame->mouse_moved = 1;
4526 last_mouse_scroll_bar = Qnil;
4527 note_mouse_highlight (frame, pos->h, pos->v);
4528 /* Remember which glyph we're now on. */
4529 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
4530 last_mouse_glyph_frame = frame;
4531 return 1;
4534 return 0;
4538 /************************************************************************
4539 Mouse Face
4540 ************************************************************************/
4542 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4544 static void
4545 redo_mouse_highlight ()
4547 if (!NILP (last_mouse_motion_frame)
4548 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4549 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4550 last_mouse_motion_position.h,
4551 last_mouse_motion_position.v);
4555 static struct frame *
4556 mac_focus_frame (dpyinfo)
4557 struct mac_display_info *dpyinfo;
4559 if (dpyinfo->x_focus_frame)
4560 return dpyinfo->x_focus_frame;
4561 else
4562 /* Mac version may get events, such as a menu bar click, even when
4563 all the frames are invisible. In this case, we regard the
4564 event came to the selected frame. */
4565 return SELECTED_FRAME ();
4569 /* Return the current position of the mouse.
4570 *FP should be a frame which indicates which display to ask about.
4572 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4573 and *PART to the frame, window, and scroll bar part that the mouse
4574 is over. Set *X and *Y to the portion and whole of the mouse's
4575 position on the scroll bar.
4577 If the mouse movement started elsewhere, set *FP to the frame the
4578 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4579 the mouse is over.
4581 Set *TIME to the server time-stamp for the time at which the mouse
4582 was at this position.
4584 Don't store anything if we don't have a valid set of values to report.
4586 This clears the mouse_moved flag, so we can wait for the next mouse
4587 movement. */
4589 static void
4590 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4591 FRAME_PTR *fp;
4592 int insist;
4593 Lisp_Object *bar_window;
4594 enum scroll_bar_part *part;
4595 Lisp_Object *x, *y;
4596 unsigned long *time;
4598 FRAME_PTR f1;
4600 BLOCK_INPUT;
4602 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4603 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4604 else
4606 Lisp_Object frame, tail;
4608 /* Clear the mouse-moved flag for every frame on this display. */
4609 FOR_EACH_FRAME (tail, frame)
4610 XFRAME (frame)->mouse_moved = 0;
4612 last_mouse_scroll_bar = Qnil;
4614 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4615 && FRAME_LIVE_P (last_mouse_frame))
4616 f1 = last_mouse_frame;
4617 else
4618 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4620 if (f1)
4622 /* Ok, we found a frame. Store all the values.
4623 last_mouse_glyph is a rectangle used to reduce the
4624 generation of mouse events. To not miss any motion
4625 events, we must divide the frame into rectangles of the
4626 size of the smallest character that could be displayed
4627 on it, i.e. into the same rectangles that matrices on
4628 the frame are divided into. */
4629 Point mouse_pos;
4631 SetPortWindowPort (FRAME_MAC_WINDOW (f1));
4632 GetMouse (&mouse_pos);
4633 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4634 &last_mouse_glyph);
4635 last_mouse_glyph_frame = f1;
4637 *bar_window = Qnil;
4638 *part = 0;
4639 *fp = f1;
4640 XSETINT (*x, mouse_pos.h);
4641 XSETINT (*y, mouse_pos.v);
4642 *time = last_mouse_movement_time;
4646 UNBLOCK_INPUT;
4650 /************************************************************************
4651 Toolkit scroll bars
4652 ************************************************************************/
4654 #ifdef USE_TOOLKIT_SCROLL_BARS
4656 static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
4657 static OSStatus install_scroll_bar_timer P_ ((void));
4658 static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
4659 static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
4660 static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
4661 struct input_event *));
4662 static OSStatus get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
4663 Rect *));
4664 static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
4665 ControlPartCode, Point,
4666 struct input_event *));
4667 static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
4668 struct input_event *));
4669 static void x_scroll_bar_handle_drag P_ ((WindowPtr, struct scroll_bar *,
4670 Point, struct input_event *));
4671 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
4672 int, int, int));
4674 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4676 static int last_scroll_bar_part;
4678 static EventLoopTimerRef scroll_bar_timer;
4680 static int scroll_bar_timer_event_posted_p;
4682 #define SCROLL_BAR_FIRST_DELAY 0.5
4683 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4685 static pascal void
4686 scroll_bar_timer_callback (timer, data)
4687 EventLoopTimerRef timer;
4688 void *data;
4690 OSStatus err;
4692 err = mac_post_mouse_moved_event ();
4693 if (err == noErr)
4694 scroll_bar_timer_event_posted_p = 1;
4697 static OSStatus
4698 install_scroll_bar_timer ()
4700 static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
4702 if (scroll_bar_timer_callbackUPP == NULL)
4703 scroll_bar_timer_callbackUPP =
4704 NewEventLoopTimerUPP (scroll_bar_timer_callback);
4706 if (scroll_bar_timer == NULL)
4707 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4708 kEventDurationForever as delays. */
4709 return
4710 InstallEventLoopTimer (GetCurrentEventLoop (),
4711 kEventDurationForever, kEventDurationForever,
4712 scroll_bar_timer_callbackUPP, NULL,
4713 &scroll_bar_timer);
4716 static OSStatus
4717 set_scroll_bar_timer (delay)
4718 EventTimerInterval delay;
4720 if (scroll_bar_timer == NULL)
4721 install_scroll_bar_timer ();
4723 scroll_bar_timer_event_posted_p = 0;
4725 return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
4728 static int
4729 control_part_code_to_scroll_bar_part (part_code)
4730 ControlPartCode part_code;
4732 switch (part_code)
4734 case kControlUpButtonPart: return scroll_bar_up_arrow;
4735 case kControlDownButtonPart: return scroll_bar_down_arrow;
4736 case kControlPageUpPart: return scroll_bar_above_handle;
4737 case kControlPageDownPart: return scroll_bar_below_handle;
4738 case kControlIndicatorPart: return scroll_bar_handle;
4741 return -1;
4744 static void
4745 construct_scroll_bar_click (bar, part, bufp)
4746 struct scroll_bar *bar;
4747 int part;
4748 struct input_event *bufp;
4750 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4751 bufp->frame_or_window = bar->window;
4752 bufp->arg = Qnil;
4753 bufp->part = part;
4754 bufp->code = 0;
4755 XSETINT (bufp->x, 0);
4756 XSETINT (bufp->y, 0);
4757 bufp->modifiers = 0;
4760 static OSStatus
4761 get_control_part_bounds (ch, part_code, rect)
4762 ControlHandle ch;
4763 ControlPartCode part_code;
4764 Rect *rect;
4766 RgnHandle region = NewRgn ();
4767 OSStatus err;
4769 err = GetControlRegion (ch, part_code, region);
4770 if (err == noErr)
4771 GetRegionBounds (region, rect);
4772 DisposeRgn (region);
4774 return err;
4777 static void
4778 x_scroll_bar_handle_press (bar, part_code, mouse_pos, bufp)
4779 struct scroll_bar *bar;
4780 ControlPartCode part_code;
4781 Point mouse_pos;
4782 struct input_event *bufp;
4784 int part = control_part_code_to_scroll_bar_part (part_code);
4786 if (part < 0)
4787 return;
4789 if (part != scroll_bar_handle)
4791 construct_scroll_bar_click (bar, part, bufp);
4792 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4793 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
4794 bar->dragging = Qnil;
4796 else
4798 Rect r;
4800 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar),
4801 kControlIndicatorPart, &r);
4802 XSETINT (bar->dragging, - (mouse_pos.v - r.top) - 1);
4805 last_scroll_bar_part = part;
4806 tracked_scroll_bar = bar;
4809 static void
4810 x_scroll_bar_handle_release (bar, bufp)
4811 struct scroll_bar *bar;
4812 struct input_event *bufp;
4814 if (last_scroll_bar_part != scroll_bar_handle
4815 || (INTEGERP (bar->dragging) && XINT (bar->dragging) >= 0))
4816 construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
4818 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4819 set_scroll_bar_timer (kEventDurationForever);
4821 last_scroll_bar_part = -1;
4822 bar->dragging = Qnil;
4823 tracked_scroll_bar = NULL;
4826 static void
4827 x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
4828 WindowPtr win;
4829 struct scroll_bar *bar;
4830 Point mouse_pos;
4831 struct input_event *bufp;
4833 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4835 if (last_scroll_bar_part == scroll_bar_handle)
4837 int top, top_range;
4838 Rect r;
4840 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar),
4841 kControlIndicatorPart, &r);
4843 if (INTEGERP (bar->dragging) && XINT (bar->dragging) < 0)
4844 XSETINT (bar->dragging, - (XINT (bar->dragging) + 1));
4846 top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
4847 top_range = XINT (bar->track_height) - XINT (bar->min_handle);
4849 if (top < 0)
4850 top = 0;
4851 if (top > top_range)
4852 top = top_range;
4854 construct_scroll_bar_click (bar, scroll_bar_handle, bufp);
4855 XSETINT (bufp->x, top);
4856 XSETINT (bufp->y, top_range);
4858 else
4860 ControlPartCode part_code;
4861 int unhilite_p = 0, part;
4863 if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
4864 unhilite_p = 1;
4865 else
4867 part = control_part_code_to_scroll_bar_part (part_code);
4869 switch (last_scroll_bar_part)
4871 case scroll_bar_above_handle:
4872 case scroll_bar_below_handle:
4873 if (part != scroll_bar_above_handle
4874 && part != scroll_bar_below_handle)
4875 unhilite_p = 1;
4876 break;
4878 case scroll_bar_up_arrow:
4879 case scroll_bar_down_arrow:
4880 if (part != scroll_bar_up_arrow
4881 && part != scroll_bar_down_arrow)
4882 unhilite_p = 1;
4883 break;
4887 if (unhilite_p)
4888 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4889 else if (part != last_scroll_bar_part
4890 || scroll_bar_timer_event_posted_p)
4892 construct_scroll_bar_click (bar, part, bufp);
4893 last_scroll_bar_part = part;
4894 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4895 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
4900 /* Set the thumb size and position of scroll bar BAR. We are currently
4901 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4903 static void
4904 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4905 struct scroll_bar *bar;
4906 int portion, position, whole;
4908 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4909 int value, viewsize, maximum;
4911 if (XINT (bar->track_height) == 0)
4912 return;
4914 if (whole <= portion)
4915 value = 0, viewsize = 1, maximum = 0;
4916 else
4918 float scale;
4920 maximum = XINT (bar->track_height) - XINT (bar->min_handle);
4921 scale = (float) maximum / (whole - portion);
4922 value = position * scale + 0.5f;
4923 viewsize = (int) (portion * scale + 0.5f) + XINT (bar->min_handle);
4926 BLOCK_INPUT;
4928 if (GetControlViewSize (ch) != viewsize
4929 || GetControl32BitValue (ch) != value
4930 || GetControl32BitMaximum (ch) != maximum)
4932 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4933 SetControlVisibility (ch, false, false);
4935 SetControl32BitMaximum (ch, maximum);
4936 SetControl32BitValue (ch, value);
4937 SetControlViewSize (ch, viewsize);
4939 SetControlVisibility (ch, true, true);
4942 UNBLOCK_INPUT;
4945 #endif /* USE_TOOLKIT_SCROLL_BARS */
4949 /************************************************************************
4950 Scroll bars, general
4951 ************************************************************************/
4953 /* Create a scroll bar and return the scroll bar vector for it. W is
4954 the Emacs window on which to create the scroll bar. TOP, LEFT,
4955 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4956 scroll bar. */
4958 static struct scroll_bar *
4959 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4960 struct window *w;
4961 int top, left, width, height, disp_top, disp_height;
4963 struct frame *f = XFRAME (w->frame);
4964 struct scroll_bar *bar
4965 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4966 Rect r;
4967 ControlHandle ch;
4969 BLOCK_INPUT;
4971 r.left = left;
4972 r.top = disp_top;
4973 r.right = left + width;
4974 r.bottom = disp_top + disp_height;
4976 #if USE_CG_DRAWING
4977 mac_prepare_for_quickdraw (f);
4978 #endif
4979 #if TARGET_API_MAC_CARBON
4980 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
4981 #ifdef USE_TOOLKIT_SCROLL_BARS
4982 false,
4983 #else
4984 width < disp_height,
4985 #endif
4986 0, 0, 0, kControlScrollBarProc, (long) bar);
4987 #else
4988 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
4989 0, 0, 0, scrollBarProc, (long) bar);
4990 #endif
4991 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4993 XSETWINDOW (bar->window, w);
4994 XSETINT (bar->top, top);
4995 XSETINT (bar->left, left);
4996 XSETINT (bar->width, width);
4997 XSETINT (bar->height, height);
4998 XSETINT (bar->start, 0);
4999 XSETINT (bar->end, 0);
5000 bar->dragging = Qnil;
5001 bar->redraw_needed_p = Qnil;
5002 #ifdef USE_TOOLKIT_SCROLL_BARS
5003 bar->track_top = Qnil;
5004 bar->track_height = Qnil;
5005 bar->min_handle = Qnil;
5006 #endif
5008 /* Add bar to its frame's list of scroll bars. */
5009 bar->next = FRAME_SCROLL_BARS (f);
5010 bar->prev = Qnil;
5011 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5012 if (!NILP (bar->next))
5013 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5015 UNBLOCK_INPUT;
5016 return bar;
5020 /* Draw BAR's handle in the proper position.
5022 If the handle is already drawn from START to END, don't bother
5023 redrawing it, unless REBUILD is non-zero; in that case, always
5024 redraw it. (REBUILD is handy for drawing the handle after expose
5025 events.)
5027 Normally, we want to constrain the start and end of the handle to
5028 fit inside its rectangle, but if the user is dragging the scroll
5029 bar handle, we want to let them drag it down all the way, so that
5030 the bar's top is as far down as it goes; otherwise, there's no way
5031 to move to the very end of the buffer. */
5033 #ifndef USE_TOOLKIT_SCROLL_BARS
5035 static void
5036 x_scroll_bar_set_handle (bar, start, end, rebuild)
5037 struct scroll_bar *bar;
5038 int start, end;
5039 int rebuild;
5041 int dragging = ! NILP (bar->dragging);
5042 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5043 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5044 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5045 int length = end - start;
5047 /* If the display is already accurate, do nothing. */
5048 if (! rebuild
5049 && start == XINT (bar->start)
5050 && end == XINT (bar->end))
5051 return;
5053 BLOCK_INPUT;
5055 /* Make sure the values are reasonable, and try to preserve the
5056 distance between start and end. */
5057 if (start < 0)
5058 start = 0;
5059 else if (start > top_range)
5060 start = top_range;
5061 end = start + length;
5063 if (end < start)
5064 end = start;
5065 else if (end > top_range && ! dragging)
5066 end = top_range;
5068 /* Store the adjusted setting in the scroll bar. */
5069 XSETINT (bar->start, start);
5070 XSETINT (bar->end, end);
5072 /* Clip the end position, just for display. */
5073 if (end > top_range)
5074 end = top_range;
5076 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5077 top positions, to make sure the handle is always at least that
5078 many pixels tall. */
5079 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
5081 SetControlMinimum (ch, 0);
5082 /* Don't inadvertently activate deactivated scroll bars */
5083 if (GetControlMaximum (ch) != -1)
5084 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
5085 - (end - start));
5086 SetControlValue (ch, start);
5087 #if TARGET_API_MAC_CARBON
5088 SetControlViewSize (ch, end - start);
5089 #endif
5091 UNBLOCK_INPUT;
5094 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5096 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5097 nil. */
5099 static void
5100 x_scroll_bar_remove (bar)
5101 struct scroll_bar *bar;
5103 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5105 BLOCK_INPUT;
5107 #if USE_CG_DRAWING
5108 mac_prepare_for_quickdraw (f);
5109 #endif
5110 /* Destroy the Mac scroll bar control */
5111 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
5113 /* Disassociate this scroll bar from its window. */
5114 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5116 UNBLOCK_INPUT;
5120 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5121 that we are displaying PORTION characters out of a total of WHOLE
5122 characters, starting at POSITION. If WINDOW has no scroll bar,
5123 create one. */
5125 static void
5126 XTset_vertical_scroll_bar (w, portion, whole, position)
5127 struct window *w;
5128 int portion, whole, position;
5130 struct frame *f = XFRAME (w->frame);
5131 struct scroll_bar *bar;
5132 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
5133 int window_y, window_height;
5135 /* Get window dimensions. */
5136 window_box (w, -1, 0, &window_y, 0, &window_height);
5137 top = window_y;
5138 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5139 height = window_height;
5141 /* Compute the left edge of the scroll bar area. */
5142 left = WINDOW_SCROLL_BAR_AREA_X (w);
5144 /* Compute the width of the scroll bar which might be less than
5145 the width of the area reserved for the scroll bar. */
5146 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
5147 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
5148 else
5149 sb_width = width;
5151 /* Compute the left edge of the scroll bar. */
5152 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5153 sb_left = left;
5154 else
5155 sb_left = left + width - sb_width;
5157 /* Adjustments according to Inside Macintosh to make it look nice */
5158 disp_top = top;
5159 disp_height = height;
5160 #ifdef MAC_OS8
5161 if (disp_top == 0)
5163 disp_top = -1;
5164 disp_height++;
5166 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
5168 disp_top++;
5169 disp_height--;
5172 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
5173 sb_left++;
5174 #endif
5176 /* Does the scroll bar exist yet? */
5177 if (NILP (w->vertical_scroll_bar))
5179 BLOCK_INPUT;
5180 mac_clear_area (f, left, top, width, height);
5181 UNBLOCK_INPUT;
5182 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
5183 disp_height);
5184 XSETVECTOR (w->vertical_scroll_bar, bar);
5186 else
5188 /* It may just need to be moved and resized. */
5189 ControlHandle ch;
5191 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5192 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5194 BLOCK_INPUT;
5196 /* If already correctly positioned, do nothing. */
5197 if (XINT (bar->left) == sb_left
5198 && XINT (bar->top) == top
5199 && XINT (bar->width) == sb_width
5200 && XINT (bar->height) == height)
5202 if (!NILP (bar->redraw_needed_p))
5204 #if USE_CG_DRAWING
5205 mac_prepare_for_quickdraw (f);
5206 #endif
5207 Draw1Control (SCROLL_BAR_CONTROL_HANDLE (bar));
5210 else
5212 /* Since toolkit scroll bars are smaller than the space reserved
5213 for them on the frame, we have to clear "under" them. */
5214 mac_clear_area (f, left, top, width, height);
5216 #if USE_CG_DRAWING
5217 mac_prepare_for_quickdraw (f);
5218 #endif
5219 HideControl (ch);
5220 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
5221 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5222 disp_height);
5223 #ifndef USE_TOOLKIT_SCROLL_BARS
5224 if (sb_width < disp_height)
5225 ShowControl (ch);
5226 #endif
5228 /* Remember new settings. */
5229 XSETINT (bar->left, sb_left);
5230 XSETINT (bar->top, top);
5231 XSETINT (bar->width, sb_width);
5232 XSETINT (bar->height, height);
5233 #ifdef USE_TOOLKIT_SCROLL_BARS
5234 bar->track_top = Qnil;
5235 bar->track_height = Qnil;
5236 bar->min_handle = Qnil;
5237 #endif
5240 UNBLOCK_INPUT;
5243 bar->redraw_needed_p = Qnil;
5245 #ifdef USE_TOOLKIT_SCROLL_BARS
5246 if (NILP (bar->track_top))
5248 if (sb_width >= disp_height
5249 #ifdef MAC_OSX
5250 || sb_width < MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5251 #endif
5254 XSETINT (bar->track_top, 0);
5255 XSETINT (bar->track_height, 0);
5256 XSETINT (bar->min_handle, 0);
5258 else
5260 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5261 Rect r0, r1;
5263 BLOCK_INPUT;
5265 SetControl32BitMinimum (ch, 0);
5266 SetControl32BitMaximum (ch, 1 << 30);
5267 SetControlViewSize (ch, 1);
5269 /* Move the scroll bar thumb to the top. */
5270 SetControl32BitValue (ch, 0);
5271 get_control_part_bounds (ch, kControlIndicatorPart, &r0);
5273 /* Move the scroll bar thumb to the bottom. */
5274 SetControl32BitValue (ch, 1 << 30);
5275 get_control_part_bounds (ch, kControlIndicatorPart, &r1);
5277 UnionRect (&r0, &r1, &r0);
5278 XSETINT (bar->track_top, r0.top);
5279 XSETINT (bar->track_height, r0.bottom - r0.top);
5280 XSETINT (bar->min_handle, r1.bottom - r1.top);
5282 /* Don't show the scroll bar if its height is not enough to
5283 display the scroll bar thumb. */
5284 if (r0.bottom - r0.top > 0)
5285 ShowControl (ch);
5287 UNBLOCK_INPUT;
5291 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5292 #else /* not USE_TOOLKIT_SCROLL_BARS */
5293 /* Set the scroll bar's current state, unless we're currently being
5294 dragged. */
5295 if (NILP (bar->dragging))
5297 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5299 if (whole == 0)
5300 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5301 else
5303 int start = ((double) position * top_range) / whole;
5304 int end = ((double) (position + portion) * top_range) / whole;
5305 x_scroll_bar_set_handle (bar, start, end, 0);
5308 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5312 /* The following three hooks are used when we're doing a thorough
5313 redisplay of the frame. We don't explicitly know which scroll bars
5314 are going to be deleted, because keeping track of when windows go
5315 away is a real pain - "Can you say set-window-configuration, boys
5316 and girls?" Instead, we just assert at the beginning of redisplay
5317 that *all* scroll bars are to be removed, and then save a scroll bar
5318 from the fiery pit when we actually redisplay its window. */
5320 /* Arrange for all scroll bars on FRAME to be removed at the next call
5321 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5322 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5324 static void
5325 XTcondemn_scroll_bars (frame)
5326 FRAME_PTR frame;
5328 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5329 while (! NILP (FRAME_SCROLL_BARS (frame)))
5331 Lisp_Object bar;
5332 bar = FRAME_SCROLL_BARS (frame);
5333 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5334 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5335 XSCROLL_BAR (bar)->prev = Qnil;
5336 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5337 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5338 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5343 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5344 Note that WINDOW isn't necessarily condemned at all. */
5346 static void
5347 XTredeem_scroll_bar (window)
5348 struct window *window;
5350 struct scroll_bar *bar;
5351 struct frame *f;
5353 /* We can't redeem this window's scroll bar if it doesn't have one. */
5354 if (NILP (window->vertical_scroll_bar))
5355 abort ();
5357 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5359 /* Unlink it from the condemned list. */
5360 f = XFRAME (WINDOW_FRAME (window));
5361 if (NILP (bar->prev))
5363 /* If the prev pointer is nil, it must be the first in one of
5364 the lists. */
5365 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5366 /* It's not condemned. Everything's fine. */
5367 return;
5368 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5369 window->vertical_scroll_bar))
5370 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5371 else
5372 /* If its prev pointer is nil, it must be at the front of
5373 one or the other! */
5374 abort ();
5376 else
5377 XSCROLL_BAR (bar->prev)->next = bar->next;
5379 if (! NILP (bar->next))
5380 XSCROLL_BAR (bar->next)->prev = bar->prev;
5382 bar->next = FRAME_SCROLL_BARS (f);
5383 bar->prev = Qnil;
5384 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5385 if (! NILP (bar->next))
5386 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5389 /* Remove all scroll bars on FRAME that haven't been saved since the
5390 last call to `*condemn_scroll_bars_hook'. */
5392 static void
5393 XTjudge_scroll_bars (f)
5394 FRAME_PTR f;
5396 Lisp_Object bar, next;
5398 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5400 /* Clear out the condemned list now so we won't try to process any
5401 more events on the hapless scroll bars. */
5402 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5404 for (; ! NILP (bar); bar = next)
5406 struct scroll_bar *b = XSCROLL_BAR (bar);
5408 x_scroll_bar_remove (b);
5410 next = b->next;
5411 b->next = b->prev = Qnil;
5414 /* Now there should be no references to the condemned scroll bars,
5415 and they should get garbage-collected. */
5419 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5420 is set to something other than NO_EVENT, it is enqueued.
5422 This may be called from a signal handler, so we have to ignore GC
5423 mark bits. */
5425 static void
5426 x_scroll_bar_handle_click (bar, part_code, er, bufp)
5427 struct scroll_bar *bar;
5428 ControlPartCode part_code;
5429 const EventRecord *er;
5430 struct input_event *bufp;
5432 int win_y, top_range;
5434 if (! GC_WINDOWP (bar->window))
5435 abort ();
5437 bufp->kind = SCROLL_BAR_CLICK_EVENT;
5438 bufp->frame_or_window = bar->window;
5439 bufp->arg = Qnil;
5441 bar->dragging = Qnil;
5443 switch (part_code)
5445 case kControlUpButtonPart:
5446 bufp->part = scroll_bar_up_arrow;
5447 break;
5448 case kControlDownButtonPart:
5449 bufp->part = scroll_bar_down_arrow;
5450 break;
5451 case kControlPageUpPart:
5452 bufp->part = scroll_bar_above_handle;
5453 break;
5454 case kControlPageDownPart:
5455 bufp->part = scroll_bar_below_handle;
5456 break;
5457 #if TARGET_API_MAC_CARBON
5458 default:
5459 #else
5460 case kControlIndicatorPart:
5461 #endif
5462 if (er->what == mouseDown)
5463 bar->dragging = make_number (0);
5464 XSETVECTOR (last_mouse_scroll_bar, bar);
5465 bufp->part = scroll_bar_handle;
5466 break;
5469 win_y = XINT (bufp->y) - XINT (bar->top);
5470 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
5472 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5474 win_y -= 24;
5476 if (! NILP (bar->dragging))
5477 win_y -= XINT (bar->dragging);
5479 if (win_y < 0)
5480 win_y = 0;
5481 if (win_y > top_range)
5482 win_y = top_range;
5484 XSETINT (bufp->x, win_y);
5485 XSETINT (bufp->y, top_range);
5488 #ifndef USE_TOOLKIT_SCROLL_BARS
5490 /* Handle some mouse motion while someone is dragging the scroll bar.
5492 This may be called from a signal handler, so we have to ignore GC
5493 mark bits. */
5495 static void
5496 x_scroll_bar_note_movement (bar, y_pos, t)
5497 struct scroll_bar *bar;
5498 int y_pos;
5499 Time t;
5501 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5503 last_mouse_movement_time = t;
5505 f->mouse_moved = 1;
5506 XSETVECTOR (last_mouse_scroll_bar, bar);
5508 /* If we're dragging the bar, display it. */
5509 if (! GC_NILP (bar->dragging))
5511 /* Where should the handle be now? */
5512 int new_start = y_pos - 24;
5514 if (new_start != XINT (bar->start))
5516 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
5518 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5523 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5525 /* Return information to the user about the current position of the mouse
5526 on the scroll bar. */
5528 static void
5529 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
5530 FRAME_PTR *fp;
5531 Lisp_Object *bar_window;
5532 enum scroll_bar_part *part;
5533 Lisp_Object *x, *y;
5534 unsigned long *time;
5536 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5537 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5538 #if TARGET_API_MAC_CARBON
5539 WindowPtr wp = GetControlOwner (ch);
5540 #else
5541 WindowPtr wp = (*ch)->contrlOwner;
5542 #endif
5543 Point mouse_pos;
5544 struct frame *f = mac_window_to_frame (wp);
5545 int win_y, top_range;
5547 SetPortWindowPort (wp);
5549 GetMouse (&mouse_pos);
5551 win_y = mouse_pos.v - XINT (bar->top);
5552 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5554 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5556 win_y -= 24;
5558 if (! NILP (bar->dragging))
5559 win_y -= XINT (bar->dragging);
5561 if (win_y < 0)
5562 win_y = 0;
5563 if (win_y > top_range)
5564 win_y = top_range;
5566 *fp = f;
5567 *bar_window = bar->window;
5569 if (! NILP (bar->dragging))
5570 *part = scroll_bar_handle;
5571 else if (win_y < XINT (bar->start))
5572 *part = scroll_bar_above_handle;
5573 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5574 *part = scroll_bar_handle;
5575 else
5576 *part = scroll_bar_below_handle;
5578 XSETINT (*x, win_y);
5579 XSETINT (*y, top_range);
5581 f->mouse_moved = 0;
5582 last_mouse_scroll_bar = Qnil;
5584 *time = last_mouse_movement_time;
5588 /* The screen has been cleared so we may have changed foreground or
5589 background colors, and the scroll bars may need to be redrawn.
5590 Clear out the scroll bars, and ask for expose events, so we can
5591 redraw them. */
5593 void
5594 x_scroll_bar_clear (f)
5595 FRAME_PTR f;
5597 Lisp_Object bar;
5599 /* We can have scroll bars even if this is 0,
5600 if we just turned off scroll bar mode.
5601 But in that case we should not clear them. */
5602 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5603 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
5604 bar = XSCROLL_BAR (bar)->next)
5605 XSCROLL_BAR (bar)->redraw_needed_p = Qt;
5609 /***********************************************************************
5610 Text Cursor
5611 ***********************************************************************/
5613 /* Set clipping for output in glyph row ROW. W is the window in which
5614 we operate. GC is the graphics context to set clipping in.
5616 ROW may be a text row or, e.g., a mode line. Text rows must be
5617 clipped to the interior of the window dedicated to text display,
5618 mode lines must be clipped to the whole window. */
5620 static void
5621 x_clip_to_row (w, row, area, gc)
5622 struct window *w;
5623 struct glyph_row *row;
5624 int area;
5625 GC gc;
5627 struct frame *f = XFRAME (WINDOW_FRAME (w));
5628 Rect clip_rect;
5629 int window_x, window_y, window_width;
5631 window_box (w, area, &window_x, &window_y, &window_width, 0);
5633 clip_rect.left = window_x;
5634 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5635 clip_rect.top = max (clip_rect.top, window_y);
5636 clip_rect.right = clip_rect.left + window_width;
5637 clip_rect.bottom = clip_rect.top + row->visible_height;
5639 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
5643 /* Draw a hollow box cursor on window W in glyph row ROW. */
5645 static void
5646 x_draw_hollow_cursor (w, row)
5647 struct window *w;
5648 struct glyph_row *row;
5650 struct frame *f = XFRAME (WINDOW_FRAME (w));
5651 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5652 Display *dpy = FRAME_MAC_DISPLAY (f);
5653 int x, y, wd, h;
5654 XGCValues xgcv;
5655 struct glyph *cursor_glyph;
5656 GC gc;
5658 /* Get the glyph the cursor is on. If we can't tell because
5659 the current matrix is invalid or such, give up. */
5660 cursor_glyph = get_phys_cursor_glyph (w);
5661 if (cursor_glyph == NULL)
5662 return;
5664 /* Compute frame-relative coordinates for phys cursor. */
5665 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
5666 wd = w->phys_cursor_width;
5668 /* The foreground of cursor_gc is typically the same as the normal
5669 background color, which can cause the cursor box to be invisible. */
5670 xgcv.foreground = f->output_data.mac->cursor_pixel;
5671 if (dpyinfo->scratch_cursor_gc)
5672 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5673 else
5674 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5675 GCForeground, &xgcv);
5676 gc = dpyinfo->scratch_cursor_gc;
5678 /* Set clipping, draw the rectangle, and reset clipping again. */
5679 x_clip_to_row (w, row, TEXT_AREA, gc);
5680 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
5681 mac_reset_clip_rectangles (dpy, gc);
5685 /* Draw a bar cursor on window W in glyph row ROW.
5687 Implementation note: One would like to draw a bar cursor with an
5688 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5689 Unfortunately, I didn't find a font yet that has this property set.
5690 --gerd. */
5692 static void
5693 x_draw_bar_cursor (w, row, width, kind)
5694 struct window *w;
5695 struct glyph_row *row;
5696 int width;
5697 enum text_cursor_kinds kind;
5699 struct frame *f = XFRAME (w->frame);
5700 struct glyph *cursor_glyph;
5702 /* If cursor is out of bounds, don't draw garbage. This can happen
5703 in mini-buffer windows when switching between echo area glyphs
5704 and mini-buffer. */
5705 cursor_glyph = get_phys_cursor_glyph (w);
5706 if (cursor_glyph == NULL)
5707 return;
5709 /* If on an image, draw like a normal cursor. That's usually better
5710 visible than drawing a bar, esp. if the image is large so that
5711 the bar might not be in the window. */
5712 if (cursor_glyph->type == IMAGE_GLYPH)
5714 struct glyph_row *row;
5715 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5716 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5718 else
5720 Display *dpy = FRAME_MAC_DISPLAY (f);
5721 Window window = FRAME_MAC_WINDOW (f);
5722 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5723 unsigned long mask = GCForeground | GCBackground;
5724 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5725 XGCValues xgcv;
5727 /* If the glyph's background equals the color we normally draw
5728 the bar cursor in, the bar cursor in its normal color is
5729 invisible. Use the glyph's foreground color instead in this
5730 case, on the assumption that the glyph's colors are chosen so
5731 that the glyph is legible. */
5732 if (face->background == f->output_data.mac->cursor_pixel)
5733 xgcv.background = xgcv.foreground = face->foreground;
5734 else
5735 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5737 if (gc)
5738 XChangeGC (dpy, gc, mask, &xgcv);
5739 else
5741 gc = XCreateGC (dpy, window, mask, &xgcv);
5742 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5745 if (width < 0)
5746 width = FRAME_CURSOR_WIDTH (f);
5747 width = min (cursor_glyph->pixel_width, width);
5749 w->phys_cursor_width = width;
5750 x_clip_to_row (w, row, TEXT_AREA, gc);
5752 if (kind == BAR_CURSOR)
5753 mac_fill_rectangle (f, gc,
5754 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5755 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5756 width, row->height);
5757 else
5758 mac_fill_rectangle (f, gc,
5759 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5760 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5761 row->height - width),
5762 cursor_glyph->pixel_width,
5763 width);
5765 mac_reset_clip_rectangles (dpy, gc);
5770 /* RIF: Define cursor CURSOR on frame F. */
5772 static void
5773 mac_define_frame_cursor (f, cursor)
5774 struct frame *f;
5775 Cursor cursor;
5777 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5779 if (dpyinfo->x_focus_frame == f)
5780 SetThemeCursor (cursor);
5784 /* RIF: Clear area on frame F. */
5786 static void
5787 mac_clear_frame_area (f, x, y, width, height)
5788 struct frame *f;
5789 int x, y, width, height;
5791 mac_clear_area (f, x, y, width, height);
5795 /* RIF: Draw cursor on window W. */
5797 static void
5798 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5799 struct window *w;
5800 struct glyph_row *glyph_row;
5801 int x, y;
5802 int cursor_type, cursor_width;
5803 int on_p, active_p;
5805 if (on_p)
5807 w->phys_cursor_type = cursor_type;
5808 w->phys_cursor_on_p = 1;
5810 if (glyph_row->exact_window_width_line_p
5811 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5813 glyph_row->cursor_in_fringe_p = 1;
5814 draw_fringe_bitmap (w, glyph_row, 0);
5816 else
5817 switch (cursor_type)
5819 case HOLLOW_BOX_CURSOR:
5820 x_draw_hollow_cursor (w, glyph_row);
5821 break;
5823 case FILLED_BOX_CURSOR:
5824 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5825 break;
5827 case BAR_CURSOR:
5828 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5829 break;
5831 case HBAR_CURSOR:
5832 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5833 break;
5835 case NO_CURSOR:
5836 w->phys_cursor_width = 0;
5837 break;
5839 default:
5840 abort ();
5846 /* Icons. */
5848 #if 0 /* MAC_TODO: no icon support yet. */
5850 x_bitmap_icon (f, icon)
5851 struct frame *f;
5852 Lisp_Object icon;
5854 HANDLE hicon;
5856 if (FRAME_W32_WINDOW (f) == 0)
5857 return 1;
5859 if (NILP (icon))
5860 hicon = LoadIcon (hinst, EMACS_CLASS);
5861 else if (STRINGP (icon))
5862 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5863 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5864 else if (SYMBOLP (icon))
5866 LPCTSTR name;
5868 if (EQ (icon, intern ("application")))
5869 name = (LPCTSTR) IDI_APPLICATION;
5870 else if (EQ (icon, intern ("hand")))
5871 name = (LPCTSTR) IDI_HAND;
5872 else if (EQ (icon, intern ("question")))
5873 name = (LPCTSTR) IDI_QUESTION;
5874 else if (EQ (icon, intern ("exclamation")))
5875 name = (LPCTSTR) IDI_EXCLAMATION;
5876 else if (EQ (icon, intern ("asterisk")))
5877 name = (LPCTSTR) IDI_ASTERISK;
5878 else if (EQ (icon, intern ("winlogo")))
5879 name = (LPCTSTR) IDI_WINLOGO;
5880 else
5881 return 1;
5883 hicon = LoadIcon (NULL, name);
5885 else
5886 return 1;
5888 if (hicon == NULL)
5889 return 1;
5891 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5892 (LPARAM) hicon);
5894 return 0;
5896 #endif /* MAC_TODO */
5898 /************************************************************************
5899 Handling X errors
5900 ************************************************************************/
5902 /* Display Error Handling functions not used on W32. Listing them here
5903 helps diff stay in step when comparing w32term.c with xterm.c.
5905 x_error_catcher (display, error)
5906 x_catch_errors (dpy)
5907 x_catch_errors_unwind (old_val)
5908 x_check_errors (dpy, format)
5909 x_had_errors_p (dpy)
5910 x_clear_errors (dpy)
5911 x_uncatch_errors (dpy, count)
5912 x_trace_wire ()
5913 x_connection_signal (signalnum)
5914 x_connection_closed (dpy, error_message)
5915 x_error_quitter (display, error)
5916 x_error_handler (display, error)
5917 x_io_error_quitter (display)
5922 /* Changing the font of the frame. */
5924 /* Give frame F the font named FONTNAME as its default font, and
5925 return the full name of that font. FONTNAME may be a wildcard
5926 pattern; in that case, we choose some font that fits the pattern.
5927 The return value shows which font we chose. */
5929 Lisp_Object
5930 x_new_font (f, fontname)
5931 struct frame *f;
5932 register char *fontname;
5934 struct font_info *fontp
5935 = FS_LOAD_FONT (f, 0, fontname, -1);
5937 if (!fontp)
5938 return Qnil;
5940 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5941 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5942 FRAME_FONTSET (f) = -1;
5944 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5945 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5946 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5948 compute_fringe_widths (f, 1);
5950 /* Compute the scroll bar width in character columns. */
5951 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5953 int wid = FRAME_COLUMN_WIDTH (f);
5954 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5955 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5957 else
5959 int wid = FRAME_COLUMN_WIDTH (f);
5960 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5963 /* Now make the frame display the given font. */
5964 if (FRAME_MAC_WINDOW (f) != 0)
5966 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5967 FRAME_FONT (f));
5968 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5969 FRAME_FONT (f));
5970 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5971 FRAME_FONT (f));
5973 /* Don't change the size of a tip frame; there's no point in
5974 doing it because it's done in Fx_show_tip, and it leads to
5975 problems because the tip frame has no widget. */
5976 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5977 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5980 return build_string (fontp->full_name);
5983 /* Give frame F the fontset named FONTSETNAME as its default font, and
5984 return the full name of that fontset. FONTSETNAME may be a wildcard
5985 pattern; in that case, we choose some fontset that fits the pattern.
5986 The return value shows which fontset we chose. */
5988 Lisp_Object
5989 x_new_fontset (f, fontsetname)
5990 struct frame *f;
5991 char *fontsetname;
5993 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5994 Lisp_Object result;
5996 if (fontset < 0)
5997 return Qnil;
5999 if (FRAME_FONTSET (f) == fontset)
6000 /* This fontset is already set in frame F. There's nothing more
6001 to do. */
6002 return fontset_name (fontset);
6004 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
6006 if (!STRINGP (result))
6007 /* Can't load ASCII font. */
6008 return Qnil;
6010 /* Since x_new_font doesn't update any fontset information, do it now. */
6011 FRAME_FONTSET (f) = fontset;
6013 return build_string (fontsetname);
6017 /***********************************************************************
6018 TODO: W32 Input Methods
6019 ***********************************************************************/
6020 /* Listing missing functions from xterm.c helps diff stay in step.
6022 xim_destroy_callback (xim, client_data, call_data)
6023 xim_open_dpy (dpyinfo, resource_name)
6024 struct xim_inst_t
6025 xim_instantiate_callback (display, client_data, call_data)
6026 xim_initialize (dpyinfo, resource_name)
6027 xim_close_dpy (dpyinfo)
6032 void
6033 mac_get_window_bounds (f, inner, outer)
6034 struct frame *f;
6035 Rect *inner, *outer;
6037 #if TARGET_API_MAC_CARBON
6038 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
6039 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
6040 #else /* not TARGET_API_MAC_CARBON */
6041 RgnHandle region = NewRgn ();
6043 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
6044 *inner = (*region)->rgnBBox;
6045 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
6046 *outer = (*region)->rgnBBox;
6047 DisposeRgn (region);
6048 #endif /* not TARGET_API_MAC_CARBON */
6051 static void
6052 mac_handle_origin_change (f)
6053 struct frame *f;
6055 x_real_positions (f, &f->left_pos, &f->top_pos);
6058 static void
6059 mac_handle_size_change (f, pixelwidth, pixelheight)
6060 struct frame *f;
6061 int pixelwidth, pixelheight;
6063 int cols, rows;
6065 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
6066 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
6068 if (cols != FRAME_COLS (f)
6069 || rows != FRAME_LINES (f)
6070 || pixelwidth != FRAME_PIXEL_WIDTH (f)
6071 || pixelheight != FRAME_PIXEL_HEIGHT (f))
6073 /* We pass 1 for DELAY since we can't run Lisp code inside of
6074 a BLOCK_INPUT. */
6075 change_frame_size (f, rows, cols, 0, 1, 0);
6076 FRAME_PIXEL_WIDTH (f) = pixelwidth;
6077 FRAME_PIXEL_HEIGHT (f) = pixelheight;
6078 SET_FRAME_GARBAGED (f);
6080 /* If cursor was outside the new size, mark it as off. */
6081 mark_window_cursors_off (XWINDOW (f->root_window));
6083 /* Clear out any recollection of where the mouse highlighting
6084 was, since it might be in a place that's outside the new
6085 frame size. Actually checking whether it is outside is a
6086 pain in the neck, so don't try--just let the highlighting be
6087 done afresh with new size. */
6088 cancel_mouse_face (f);
6090 #if TARGET_API_MAC_CARBON
6091 if (f->output_data.mac->hourglass_control)
6093 #if USE_CG_DRAWING
6094 mac_prepare_for_quickdraw (f);
6095 #endif
6096 MoveControl (f->output_data.mac->hourglass_control,
6097 pixelwidth - HOURGLASS_WIDTH, 0);
6099 #endif
6104 /* Calculate the absolute position in frame F
6105 from its current recorded position values and gravity. */
6107 void
6108 x_calc_absolute_position (f)
6109 struct frame *f;
6111 int width_diff = 0, height_diff = 0;
6112 int flags = f->size_hint_flags;
6113 Rect inner, outer;
6115 /* We have nothing to do if the current position
6116 is already for the top-left corner. */
6117 if (! ((flags & XNegative) || (flags & YNegative)))
6118 return;
6120 /* Find the offsets of the outside upper-left corner of
6121 the inner window, with respect to the outer window. */
6122 BLOCK_INPUT;
6123 mac_get_window_bounds (f, &inner, &outer);
6124 UNBLOCK_INPUT;
6126 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
6127 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
6129 /* Treat negative positions as relative to the leftmost bottommost
6130 position that fits on the screen. */
6131 if (flags & XNegative)
6132 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
6133 - width_diff
6134 - FRAME_PIXEL_WIDTH (f)
6135 + f->left_pos);
6137 if (flags & YNegative)
6138 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
6139 - height_diff
6140 - FRAME_PIXEL_HEIGHT (f)
6141 + f->top_pos);
6143 /* The left_pos and top_pos
6144 are now relative to the top and left screen edges,
6145 so the flags should correspond. */
6146 f->size_hint_flags &= ~ (XNegative | YNegative);
6149 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6150 to really change the position, and 0 when calling from
6151 x_make_frame_visible (in that case, XOFF and YOFF are the current
6152 position values). It is -1 when calling from x_set_frame_parameters,
6153 which means, do adjust for borders but don't change the gravity. */
6155 void
6156 x_set_offset (f, xoff, yoff, change_gravity)
6157 struct frame *f;
6158 register int xoff, yoff;
6159 int change_gravity;
6161 if (change_gravity > 0)
6163 f->top_pos = yoff;
6164 f->left_pos = xoff;
6165 f->size_hint_flags &= ~ (XNegative | YNegative);
6166 if (xoff < 0)
6167 f->size_hint_flags |= XNegative;
6168 if (yoff < 0)
6169 f->size_hint_flags |= YNegative;
6170 f->win_gravity = NorthWestGravity;
6172 x_calc_absolute_position (f);
6174 BLOCK_INPUT;
6175 x_wm_set_size_hint (f, (long) 0, 0);
6177 #if TARGET_API_MAC_CARBON
6178 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
6179 /* If the title bar is completely outside the screen, adjust the
6180 position. */
6181 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
6182 kWindowConstrainMoveRegardlessOfFit
6183 | kWindowConstrainAllowPartial, NULL, NULL);
6184 #if USE_CARBON_EVENTS
6185 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
6186 #endif
6187 mac_handle_origin_change (f);
6188 #else
6190 Rect inner, outer, screen_rect, dummy;
6191 RgnHandle region = NewRgn ();
6193 mac_get_window_bounds (f, &inner, &outer);
6194 f->x_pixels_diff = inner.left - outer.left;
6195 f->y_pixels_diff = inner.top - outer.top;
6196 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6197 f->top_pos + f->y_pixels_diff, false);
6199 /* If the title bar is completely outside the screen, adjust the
6200 position. The variable `outer' holds the title bar rectangle.
6201 The variable `inner' holds slightly smaller one than `outer',
6202 so that the calculation of overlapping may not become too
6203 strict. */
6204 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
6205 outer = (*region)->rgnBBox;
6206 DisposeRgn (region);
6207 inner = outer;
6208 InsetRect (&inner, 8, 8);
6209 screen_rect = qd.screenBits.bounds;
6210 screen_rect.top += GetMBarHeight ();
6212 if (!SectRect (&inner, &screen_rect, &dummy))
6214 if (inner.right <= screen_rect.left)
6215 f->left_pos = screen_rect.left;
6216 else if (inner.left >= screen_rect.right)
6217 f->left_pos = screen_rect.right - (outer.right - outer.left);
6219 if (inner.bottom <= screen_rect.top)
6220 f->top_pos = screen_rect.top;
6221 else if (inner.top >= screen_rect.bottom)
6222 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
6224 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6225 f->top_pos + f->y_pixels_diff, false);
6228 #endif
6230 UNBLOCK_INPUT;
6233 /* Call this to change the size of frame F's x-window.
6234 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6235 for this size change and subsequent size changes.
6236 Otherwise we leave the window gravity unchanged. */
6238 void
6239 x_set_window_size (f, change_gravity, cols, rows)
6240 struct frame *f;
6241 int change_gravity;
6242 int cols, rows;
6244 int pixelwidth, pixelheight;
6246 BLOCK_INPUT;
6248 check_frame_size (f, &rows, &cols);
6249 f->scroll_bar_actual_width
6250 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
6252 compute_fringe_widths (f, 0);
6254 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
6255 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
6257 f->win_gravity = NorthWestGravity;
6258 x_wm_set_size_hint (f, (long) 0, 0);
6260 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
6262 #if USE_CARBON_EVENTS
6263 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
6264 #endif
6265 mac_handle_size_change (f, pixelwidth, pixelheight);
6267 if (f->output_data.mac->internal_border_width
6268 != FRAME_INTERNAL_BORDER_WIDTH (f))
6270 mac_clear_window (f);
6271 f->output_data.mac->internal_border_width
6272 = FRAME_INTERNAL_BORDER_WIDTH (f);
6275 SET_FRAME_GARBAGED (f);
6277 UNBLOCK_INPUT;
6280 /* Mouse warping. */
6282 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
6284 void
6285 x_set_mouse_position (f, x, y)
6286 struct frame *f;
6287 int x, y;
6289 int pix_x, pix_y;
6291 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
6292 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
6294 if (pix_x < 0) pix_x = 0;
6295 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
6297 if (pix_y < 0) pix_y = 0;
6298 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
6300 x_set_mouse_pixel_position (f, pix_x, pix_y);
6303 void
6304 x_set_mouse_pixel_position (f, pix_x, pix_y)
6305 struct frame *f;
6306 int pix_x, pix_y;
6308 #ifdef MAC_OSX
6309 Point p;
6310 CGPoint point;
6312 BLOCK_INPUT;
6313 SetPortWindowPort (FRAME_MAC_WINDOW (f));
6314 p.h = pix_x;
6315 p.v = pix_y;
6316 LocalToGlobal (&p);
6317 point.x = p.h;
6318 point.y = p.v;
6319 CGWarpMouseCursorPosition (point);
6320 UNBLOCK_INPUT;
6321 #else
6322 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6323 BLOCK_INPUT;
6325 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
6326 0, 0, 0, 0, pix_x, pix_y);
6327 UNBLOCK_INPUT;
6328 #endif
6329 #endif
6332 /* focus shifting, raising and lowering. */
6334 void
6335 x_focus_on_frame (f)
6336 struct frame *f;
6338 #if 0 /* This proves to be unpleasant. */
6339 x_raise_frame (f);
6340 #endif
6341 #if 0
6342 /* I don't think that the ICCCM allows programs to do things like this
6343 without the interaction of the window manager. Whatever you end up
6344 doing with this code, do it to x_unfocus_frame too. */
6345 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6346 RevertToPointerRoot, CurrentTime);
6347 #endif /* ! 0 */
6350 void
6351 x_unfocus_frame (f)
6352 struct frame *f;
6356 /* Raise frame F. */
6358 void
6359 x_raise_frame (f)
6360 struct frame *f;
6362 if (f->async_visible)
6364 BLOCK_INPUT;
6365 BringToFront (FRAME_MAC_WINDOW (f));
6366 UNBLOCK_INPUT;
6370 /* Lower frame F. */
6372 void
6373 x_lower_frame (f)
6374 struct frame *f;
6376 if (f->async_visible)
6378 BLOCK_INPUT;
6379 SendBehind (FRAME_MAC_WINDOW (f), NULL);
6380 UNBLOCK_INPUT;
6384 static void
6385 XTframe_raise_lower (f, raise_flag)
6386 FRAME_PTR f;
6387 int raise_flag;
6389 if (raise_flag)
6390 x_raise_frame (f);
6391 else
6392 x_lower_frame (f);
6395 /* Change of visibility. */
6397 static void
6398 mac_handle_visibility_change (f)
6399 struct frame *f;
6401 WindowPtr wp = FRAME_MAC_WINDOW (f);
6402 int visible = 0, iconified = 0;
6403 struct input_event buf;
6405 if (IsWindowVisible (wp))
6407 if (IsWindowCollapsed (wp))
6408 iconified = 1;
6409 else
6410 visible = 1;
6413 if (!f->async_visible && visible)
6415 if (f->iconified)
6417 /* wait_reading_process_output will notice this and update
6418 the frame's display structures. If we were made
6419 invisible, we should not set garbaged, because that stops
6420 redrawing on Update events. */
6421 SET_FRAME_GARBAGED (f);
6423 EVENT_INIT (buf);
6424 buf.kind = DEICONIFY_EVENT;
6425 XSETFRAME (buf.frame_or_window, f);
6426 buf.arg = Qnil;
6427 kbd_buffer_store_event (&buf);
6429 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
6430 /* Force a redisplay sooner or later to update the
6431 frame titles in case this is the second frame. */
6432 record_asynch_buffer_change ();
6434 else if (f->async_visible && !visible)
6435 if (iconified)
6437 EVENT_INIT (buf);
6438 buf.kind = ICONIFY_EVENT;
6439 XSETFRAME (buf.frame_or_window, f);
6440 buf.arg = Qnil;
6441 kbd_buffer_store_event (&buf);
6444 f->async_visible = visible;
6445 f->async_iconified = iconified;
6448 /* This tries to wait until the frame is really visible.
6449 However, if the window manager asks the user where to position
6450 the frame, this will return before the user finishes doing that.
6451 The frame will not actually be visible at that time,
6452 but it will become visible later when the window manager
6453 finishes with it. */
6455 void
6456 x_make_frame_visible (f)
6457 struct frame *f;
6459 BLOCK_INPUT;
6461 if (! FRAME_VISIBLE_P (f))
6463 /* We test FRAME_GARBAGED_P here to make sure we don't
6464 call x_set_offset a second time
6465 if we get to x_make_frame_visible a second time
6466 before the window gets really visible. */
6467 if (! FRAME_ICONIFIED_P (f)
6468 && ! f->output_data.mac->asked_for_visible)
6470 #if TARGET_API_MAC_CARBON
6471 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
6473 struct frame *sf = SELECTED_FRAME ();
6474 if (!FRAME_MAC_P (sf))
6475 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
6476 kWindowCenterOnMainScreen);
6477 else
6478 RepositionWindow (FRAME_MAC_WINDOW (f),
6479 FRAME_MAC_WINDOW (sf),
6480 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6481 kWindowCascadeStartAtParentWindowScreen
6482 #else
6483 kWindowCascadeOnParentWindowScreen
6484 #endif
6486 #if USE_CARBON_EVENTS
6487 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
6488 #endif
6489 mac_handle_origin_change (f);
6491 else
6492 #endif
6493 x_set_offset (f, f->left_pos, f->top_pos, 0);
6496 f->output_data.mac->asked_for_visible = 1;
6498 CollapseWindow (FRAME_MAC_WINDOW (f), false);
6499 ShowWindow (FRAME_MAC_WINDOW (f));
6502 XFlush (FRAME_MAC_DISPLAY (f));
6504 /* Synchronize to ensure Emacs knows the frame is visible
6505 before we do anything else. We do this loop with input not blocked
6506 so that incoming events are handled. */
6508 Lisp_Object frame;
6509 int count;
6511 /* This must come after we set COUNT. */
6512 UNBLOCK_INPUT;
6514 XSETFRAME (frame, f);
6516 /* Wait until the frame is visible. Process X events until a
6517 MapNotify event has been seen, or until we think we won't get a
6518 MapNotify at all.. */
6519 for (count = input_signal_count + 10;
6520 input_signal_count < count && !FRAME_VISIBLE_P (f);)
6522 /* Force processing of queued events. */
6523 x_sync (f);
6525 /* Machines that do polling rather than SIGIO have been
6526 observed to go into a busy-wait here. So we'll fake an
6527 alarm signal to let the handler know that there's something
6528 to be read. We used to raise a real alarm, but it seems
6529 that the handler isn't always enabled here. This is
6530 probably a bug. */
6531 if (input_polling_used ())
6533 /* It could be confusing if a real alarm arrives while
6534 processing the fake one. Turn it off and let the
6535 handler reset it. */
6536 extern void poll_for_input_1 P_ ((void));
6537 int old_poll_suppress_count = poll_suppress_count;
6538 poll_suppress_count = 1;
6539 poll_for_input_1 ();
6540 poll_suppress_count = old_poll_suppress_count;
6543 /* See if a MapNotify event has been processed. */
6544 FRAME_SAMPLE_VISIBILITY (f);
6549 /* Change from mapped state to withdrawn state. */
6551 /* Make the frame visible (mapped and not iconified). */
6553 void
6554 x_make_frame_invisible (f)
6555 struct frame *f;
6557 /* A deactivate event does not occur when the last visible frame is
6558 made invisible. So if we clear the highlight here, it will not
6559 be rehighlighted when it is made visible. */
6560 #if 0
6561 /* Don't keep the highlight on an invisible frame. */
6562 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6563 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6564 #endif
6566 BLOCK_INPUT;
6568 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6569 that the current position of the window is user-specified, rather than
6570 program-specified, so that when the window is mapped again, it will be
6571 placed at the same location, without forcing the user to position it
6572 by hand again (they have already done that once for this window.) */
6573 x_wm_set_size_hint (f, (long) 0, 1);
6575 HideWindow (FRAME_MAC_WINDOW (f));
6577 UNBLOCK_INPUT;
6579 #if !USE_CARBON_EVENTS
6580 mac_handle_visibility_change (f);
6581 #endif
6584 /* Change window state from mapped to iconified. */
6586 void
6587 x_iconify_frame (f)
6588 struct frame *f;
6590 OSStatus err;
6592 /* A deactivate event does not occur when the last visible frame is
6593 iconified. So if we clear the highlight here, it will not be
6594 rehighlighted when it is deiconified. */
6595 #if 0
6596 /* Don't keep the highlight on an invisible frame. */
6597 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6598 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6599 #endif
6601 if (f->async_iconified)
6602 return;
6604 BLOCK_INPUT;
6606 FRAME_SAMPLE_VISIBILITY (f);
6608 if (! FRAME_VISIBLE_P (f))
6609 ShowWindow (FRAME_MAC_WINDOW (f));
6611 err = CollapseWindow (FRAME_MAC_WINDOW (f), true);
6613 UNBLOCK_INPUT;
6615 if (err != noErr)
6616 error ("Can't notify window manager of iconification");
6618 #if !USE_CARBON_EVENTS
6619 mac_handle_visibility_change (f);
6620 #endif
6624 /* Free X resources of frame F. */
6626 void
6627 x_free_frame_resources (f)
6628 struct frame *f;
6630 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6631 WindowPtr wp = FRAME_MAC_WINDOW (f);
6633 BLOCK_INPUT;
6635 if (wp != tip_window)
6636 remove_window_handler (wp);
6638 #if USE_CG_DRAWING
6639 mac_prepare_for_quickdraw (f);
6640 #endif
6641 DisposeWindow (wp);
6642 if (wp == tip_window)
6643 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6644 closed' event. So we reset tip_window here. */
6645 tip_window = NULL;
6647 free_frame_menubar (f);
6649 if (FRAME_FACE_CACHE (f))
6650 free_frame_faces (f);
6652 x_free_gcs (f);
6654 if (FRAME_SIZE_HINTS (f))
6655 xfree (FRAME_SIZE_HINTS (f));
6657 xfree (f->output_data.mac);
6658 f->output_data.mac = NULL;
6660 if (f == dpyinfo->x_focus_frame)
6662 dpyinfo->x_focus_frame = 0;
6663 #if USE_MAC_FONT_PANEL
6664 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
6665 #endif
6667 if (f == dpyinfo->x_focus_event_frame)
6668 dpyinfo->x_focus_event_frame = 0;
6669 if (f == dpyinfo->x_highlight_frame)
6670 dpyinfo->x_highlight_frame = 0;
6672 if (f == dpyinfo->mouse_face_mouse_frame)
6674 dpyinfo->mouse_face_beg_row
6675 = dpyinfo->mouse_face_beg_col = -1;
6676 dpyinfo->mouse_face_end_row
6677 = dpyinfo->mouse_face_end_col = -1;
6678 dpyinfo->mouse_face_window = Qnil;
6679 dpyinfo->mouse_face_deferred_gc = 0;
6680 dpyinfo->mouse_face_mouse_frame = 0;
6683 UNBLOCK_INPUT;
6687 /* Destroy the X window of frame F. */
6689 void
6690 x_destroy_window (f)
6691 struct frame *f;
6693 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6695 x_free_frame_resources (f);
6697 dpyinfo->reference_count--;
6701 /* Setting window manager hints. */
6703 /* Set the normal size hints for the window manager, for frame F.
6704 FLAGS is the flags word to use--or 0 meaning preserve the flags
6705 that the window now has.
6706 If USER_POSITION is nonzero, we set the USPosition
6707 flag (this is useful when FLAGS is 0). */
6708 void
6709 x_wm_set_size_hint (f, flags, user_position)
6710 struct frame *f;
6711 long flags;
6712 int user_position;
6714 int base_width, base_height, width_inc, height_inc;
6715 int min_rows = 0, min_cols = 0;
6716 XSizeHints *size_hints;
6718 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6719 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6720 width_inc = FRAME_COLUMN_WIDTH (f);
6721 height_inc = FRAME_LINE_HEIGHT (f);
6723 check_frame_size (f, &min_rows, &min_cols);
6725 size_hints = FRAME_SIZE_HINTS (f);
6726 if (size_hints == NULL)
6728 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6729 bzero (size_hints, sizeof (XSizeHints));
6732 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6733 size_hints->width_inc = width_inc;
6734 size_hints->height_inc = height_inc;
6735 size_hints->min_width = base_width + min_cols * width_inc;
6736 size_hints->min_height = base_height + min_rows * height_inc;
6737 size_hints->base_width = base_width;
6738 size_hints->base_height = base_height;
6740 if (flags)
6741 size_hints->flags = flags;
6742 else if (user_position)
6744 size_hints->flags &= ~ PPosition;
6745 size_hints->flags |= USPosition;
6749 #if 0 /* MAC_TODO: hide application instead of iconify? */
6750 /* Used for IconicState or NormalState */
6752 void
6753 x_wm_set_window_state (f, state)
6754 struct frame *f;
6755 int state;
6757 #ifdef USE_X_TOOLKIT
6758 Arg al[1];
6760 XtSetArg (al[0], XtNinitialState, state);
6761 XtSetValues (f->output_data.x->widget, al, 1);
6762 #else /* not USE_X_TOOLKIT */
6763 Window window = FRAME_X_WINDOW (f);
6765 f->output_data.x->wm_hints.flags |= StateHint;
6766 f->output_data.x->wm_hints.initial_state = state;
6768 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6769 #endif /* not USE_X_TOOLKIT */
6772 void
6773 x_wm_set_icon_pixmap (f, pixmap_id)
6774 struct frame *f;
6775 int pixmap_id;
6777 Pixmap icon_pixmap;
6779 #ifndef USE_X_TOOLKIT
6780 Window window = FRAME_X_WINDOW (f);
6781 #endif
6783 if (pixmap_id > 0)
6785 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6786 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6788 else
6790 /* It seems there is no way to turn off use of an icon pixmap.
6791 The following line does it, only if no icon has yet been created,
6792 for some window managers. But with mwm it crashes.
6793 Some people say it should clear the IconPixmapHint bit in this case,
6794 but that doesn't work, and the X consortium said it isn't the
6795 right thing at all. Since there is no way to win,
6796 best to explicitly give up. */
6797 #if 0
6798 f->output_data.x->wm_hints.icon_pixmap = None;
6799 #else
6800 return;
6801 #endif
6804 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6807 Arg al[1];
6808 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6809 XtSetValues (f->output_data.x->widget, al, 1);
6812 #else /* not USE_X_TOOLKIT */
6814 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6815 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6817 #endif /* not USE_X_TOOLKIT */
6820 #endif /* MAC_TODO */
6822 void
6823 x_wm_set_icon_position (f, icon_x, icon_y)
6824 struct frame *f;
6825 int icon_x, icon_y;
6827 #if 0 /* MAC_TODO: no icons on Mac */
6828 #ifdef USE_X_TOOLKIT
6829 Window window = XtWindow (f->output_data.x->widget);
6830 #else
6831 Window window = FRAME_X_WINDOW (f);
6832 #endif
6834 f->output_data.x->wm_hints.flags |= IconPositionHint;
6835 f->output_data.x->wm_hints.icon_x = icon_x;
6836 f->output_data.x->wm_hints.icon_y = icon_y;
6838 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6839 #endif /* MAC_TODO */
6843 /***********************************************************************
6844 XLFD Pattern Match
6845 ***********************************************************************/
6847 /* An XLFD pattern is divided into blocks delimited by '*'. This
6848 structure holds information for each block. */
6849 struct xlfdpat_block
6851 /* Length of the pattern string in this block. Non-zero except for
6852 the first and the last blocks. */
6853 int len;
6855 /* Pattern string except the last character in this block. The last
6856 character is replaced with NUL in order to use it as a
6857 sentinel. */
6858 unsigned char *pattern;
6860 /* Last character of the pattern string. Must not be '?'. */
6861 unsigned char last_char;
6863 /* One of the tables for the Boyer-Moore string search. It
6864 specifies the number of positions to proceed for each character
6865 with which the match fails. */
6866 int skip[256];
6868 /* The skip value for the last character in the above `skip' is
6869 assigned to `infinity' in order to simplify a loop condition.
6870 The original value is saved here. */
6871 int last_char_skip;
6874 struct xlfdpat
6876 /* Normalized pattern string. "Normalized" means that capital
6877 letters are lowered, blocks are not empty except the first and
6878 the last ones, and trailing '?'s in a block that is not the last
6879 one are moved to the next one. The last character in each block
6880 is replaced with NUL. */
6881 unsigned char *buf;
6883 /* Number of characters except '*'s and trailing '?'s in the
6884 normalized pattern string. */
6885 int nchars;
6887 /* Number of trailing '?'s in the normalized pattern string. */
6888 int trailing_anychars;
6890 /* Number of blocks and information for each block. The latter is
6891 NULL if the pattern is exact (no '*' or '?' in it). */
6892 int nblocks;
6893 struct xlfdpat_block *blocks;
6896 static void
6897 xlfdpat_destroy (pat)
6898 struct xlfdpat *pat;
6900 if (pat)
6902 if (pat->buf)
6904 if (pat->blocks)
6905 xfree (pat->blocks);
6906 xfree (pat->buf);
6908 xfree (pat);
6912 static struct xlfdpat *
6913 xlfdpat_create (pattern)
6914 const char *pattern;
6916 struct xlfdpat *pat;
6917 int nblocks, i, skip;
6918 unsigned char last_char, *p, *q, *anychar_head;
6919 const unsigned char *ptr;
6920 struct xlfdpat_block *blk;
6922 pat = xmalloc (sizeof (struct xlfdpat));
6923 pat->buf = xmalloc (strlen (pattern) + 1);
6925 /* Normalize the pattern string and store it to `pat->buf'. */
6926 nblocks = 0;
6927 anychar_head = NULL;
6928 q = pat->buf;
6929 last_char = '\0';
6930 for (ptr = pattern; *ptr; ptr++)
6932 unsigned char c = *ptr;
6934 if (c == '*')
6935 if (last_char == '*')
6936 /* ...a** -> ...a* */
6937 continue;
6938 else
6940 if (last_char == '?')
6942 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6943 /* ...*??* -> ...*?? */
6944 continue;
6945 else
6946 /* ...a??* -> ...a*?? */
6948 *anychar_head++ = '*';
6949 c = '?';
6952 nblocks++;
6954 else if (c == '?')
6956 if (last_char != '?')
6957 anychar_head = q;
6959 else
6960 /* On Mac OS X 10.3, tolower also converts non-ASCII
6961 characters for some locales. */
6962 if (isascii (c))
6963 c = tolower (c);
6965 *q++ = last_char = c;
6967 *q = '\0';
6968 nblocks++;
6969 pat->nblocks = nblocks;
6970 if (last_char != '?')
6971 pat->trailing_anychars = 0;
6972 else
6974 pat->trailing_anychars = q - anychar_head;
6975 q = anychar_head;
6977 pat->nchars = q - pat->buf - (nblocks - 1);
6979 if (anychar_head == NULL && nblocks == 1)
6981 /* The pattern is exact. */
6982 pat->blocks = NULL;
6983 return pat;
6986 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6988 /* Divide the normalized pattern into blocks. */
6989 p = pat->buf;
6990 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6992 blk->pattern = p;
6993 while (*p != '*')
6994 p++;
6995 blk->len = p - blk->pattern;
6996 p++;
6998 blk->pattern = p;
6999 blk->len = q - blk->pattern;
7001 /* Setup a table for the Boyer-Moore string search. */
7002 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
7003 if (blk->len != 0)
7005 blk->last_char = blk->pattern[blk->len - 1];
7006 blk->pattern[blk->len - 1] = '\0';
7008 for (skip = 1; skip < blk->len; skip++)
7009 if (blk->pattern[blk->len - skip - 1] == '?')
7010 break;
7012 for (i = 0; i < 256; i++)
7013 blk->skip[i] = skip;
7015 p = blk->pattern + (blk->len - skip);
7016 while (--skip > 0)
7017 blk->skip[*p++] = skip;
7019 blk->last_char_skip = blk->skip[blk->last_char];
7022 return pat;
7025 static INLINE int
7026 xlfdpat_exact_p (pat)
7027 struct xlfdpat *pat;
7029 return pat->blocks == NULL;
7032 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7033 that the pattern in *BLK matches with its prefix. Return NULL
7034 there is no such strings. STRING must be lowered in advance. */
7036 static const char *
7037 xlfdpat_block_match_1 (blk, string, start_max)
7038 struct xlfdpat_block *blk;
7039 const unsigned char *string;
7040 int start_max;
7042 int start, infinity;
7043 unsigned char *p;
7044 const unsigned char *s;
7046 xassert (blk->len > 0);
7047 xassert (start_max + blk->len <= strlen (string));
7048 xassert (blk->last_char != '?');
7050 /* See the comments in the function `boyer_moore' (search.c) for the
7051 use of `infinity'. */
7052 infinity = start_max + blk->len + 1;
7053 blk->skip[blk->last_char] = infinity;
7055 start = 0;
7058 /* Check the last character of the pattern. */
7059 s = string + blk->len - 1;
7062 start += blk->skip[*(s + start)];
7064 while (start <= start_max);
7066 if (start < infinity)
7067 /* Couldn't find the last character. */
7068 return NULL;
7070 /* No less than `infinity' means we could find the last
7071 character at `s[start - infinity]'. */
7072 start -= infinity;
7074 /* Check the remaining characters. We prefer making no-'?'
7075 cases faster because the use of '?' is really rare. */
7076 p = blk->pattern;
7077 s = string + start;
7080 while (*p++ == *s++)
7083 while (*(p - 1) == '?');
7085 if (*(p - 1) == '\0')
7086 /* Matched. */
7087 return string + start;
7089 /* Didn't match. */
7090 start += blk->last_char_skip;
7092 while (start <= start_max);
7094 return NULL;
7097 #define xlfdpat_block_match(b, s, m) \
7098 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7099 : xlfdpat_block_match_1 (b, s, m))
7101 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7102 matches with STRING. STRING must be lowered in advance. */
7104 static int
7105 xlfdpat_match (pat, string)
7106 struct xlfdpat *pat;
7107 const unsigned char *string;
7109 int str_len, nblocks, i, start_max;
7110 struct xlfdpat_block *blk;
7111 const unsigned char *s;
7113 xassert (pat->nblocks > 0);
7115 if (xlfdpat_exact_p (pat))
7116 return strcmp (pat->buf, string) == 0;
7118 /* The number of the characters in the string must not be smaller
7119 than that in the pattern. */
7120 str_len = strlen (string);
7121 if (str_len < pat->nchars + pat->trailing_anychars)
7122 return 0;
7124 /* Chop off the trailing '?'s. */
7125 str_len -= pat->trailing_anychars;
7127 /* The last block. When it is non-empty, it must match at the end
7128 of the string. */
7129 nblocks = pat->nblocks;
7130 blk = pat->blocks + (nblocks - 1);
7131 if (nblocks == 1)
7132 /* The last block is also the first one. */
7133 return (str_len == blk->len
7134 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
7135 else if (blk->len != 0)
7136 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
7137 return 0;
7139 /* The first block. When it is non-empty, it must match at the
7140 beginning of the string. */
7141 blk = pat->blocks;
7142 if (blk->len != 0)
7144 s = xlfdpat_block_match (blk, string, 0);
7145 if (s == NULL)
7146 return 0;
7147 string = s + blk->len;
7150 /* The rest of the blocks. */
7151 start_max = str_len - pat->nchars;
7152 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
7154 s = xlfdpat_block_match (blk, string, start_max);
7155 if (s == NULL)
7156 return 0;
7157 start_max -= s - string;
7158 string = s + blk->len;
7161 return 1;
7165 /***********************************************************************
7166 Fonts
7167 ***********************************************************************/
7169 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7171 struct font_info *
7172 x_get_font_info (f, font_idx)
7173 FRAME_PTR f;
7174 int font_idx;
7176 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
7179 /* the global font name table */
7180 static char **font_name_table = NULL;
7181 static int font_name_table_size = 0;
7182 static int font_name_count = 0;
7184 /* Alist linking font family names to Font Manager font family
7185 references (which can also be used as QuickDraw font IDs). We use
7186 an alist because hash tables are not ready when the terminal frame
7187 for Mac OS Classic is created. */
7188 static Lisp_Object fm_font_family_alist;
7189 #if USE_ATSUI
7190 /* Hash table linking font family names to ATSU font IDs. */
7191 static Lisp_Object atsu_font_id_hash;
7192 /* Alist linking Font Manager style to face attributes. */
7193 static Lisp_Object fm_style_face_attributes_alist;
7194 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
7195 #endif
7197 /* Alist linking character set strings to Mac text encoding and Emacs
7198 coding system. */
7199 static Lisp_Object Vmac_charset_info_alist;
7201 static Lisp_Object
7202 create_text_encoding_info_alist ()
7204 Lisp_Object result = Qnil, rest;
7206 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
7208 Lisp_Object charset_info = XCAR (rest);
7209 Lisp_Object charset, coding_system, text_encoding;
7210 Lisp_Object existing_info;
7212 if (!(CONSP (charset_info)
7213 && (charset = XCAR (charset_info),
7214 STRINGP (charset))
7215 && CONSP (XCDR (charset_info))
7216 && (text_encoding = XCAR (XCDR (charset_info)),
7217 INTEGERP (text_encoding))
7218 && CONSP (XCDR (XCDR (charset_info)))
7219 && (coding_system = XCAR (XCDR (XCDR (charset_info))),
7220 SYMBOLP (coding_system))))
7221 continue;
7223 existing_info = assq_no_quit (text_encoding, result);
7224 if (NILP (existing_info))
7225 result = Fcons (list3 (text_encoding, coding_system, charset),
7226 result);
7227 else
7228 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
7229 XSETCDR (XCDR (existing_info),
7230 Fcons (charset, XCDR (XCDR (existing_info))));
7233 return result;
7237 static void
7238 decode_mac_font_name (name, size, coding_system)
7239 char *name;
7240 int size;
7241 Lisp_Object coding_system;
7243 struct coding_system coding;
7244 char *buf, *p;
7246 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
7248 for (p = name; *p; p++)
7249 if (!isascii (*p) || iscntrl (*p))
7250 break;
7252 if (*p)
7254 setup_coding_system (coding_system, &coding);
7255 coding.src_multibyte = 0;
7256 coding.dst_multibyte = 1;
7257 coding.mode |= CODING_MODE_LAST_BLOCK;
7258 coding.composing = COMPOSITION_DISABLED;
7259 buf = (char *) alloca (size);
7261 decode_coding (&coding, name, buf, strlen (name), size - 1);
7262 bcopy (buf, name, coding.produced);
7263 name[coding.produced] = '\0';
7267 /* If there's just one occurrence of '-' in the family name, it is
7268 replaced with '_'. (More than one occurrence of '-' means a
7269 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7270 p = strchr (name, '-');
7271 if (p && strchr (p + 1, '-') == NULL)
7272 *p = '_';
7274 for (p = name; *p; p++)
7275 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7276 for some locales. */
7277 if (isascii (*p))
7278 *p = tolower (*p);
7282 static char *
7283 mac_to_x_fontname (name, size, style, charset)
7284 const char *name;
7285 int size;
7286 Style style;
7287 char *charset;
7289 Str31 foundry, cs;
7290 Str255 family;
7291 char xf[256], *result;
7292 unsigned char *p;
7294 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
7295 charset = cs;
7296 else
7298 strcpy(foundry, "Apple");
7299 strcpy(family, name);
7302 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7303 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
7304 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
7306 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
7307 sprintf (result, "-%s-%s-%s", foundry, family, xf);
7308 for (p = result; *p; p++)
7309 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7310 for some locales. */
7311 if (isascii (*p))
7312 *p = tolower (*p);
7313 return result;
7317 /* Parse fully-specified and instantiated X11 font spec XF, and store
7318 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7319 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7320 caller must allocate at least 256 and 32 bytes respectively. For
7321 ordinary Mac fonts, the value stored to FAMILY should just be their
7322 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7323 intlfonts collection contain their charset designation in their
7324 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7325 types of font names are handled accordingly. */
7327 const int kDefaultFontSize = 12;
7329 static int
7330 parse_x_font_name (xf, family, size, style, charset)
7331 const char *xf;
7332 char *family;
7333 int *size;
7334 Style *style;
7335 char *charset;
7337 Str31 foundry, weight;
7338 int point_size, avgwidth;
7339 char slant[2], *p;
7341 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7342 foundry, family, weight, slant, size,
7343 &point_size, &avgwidth, charset) != 8
7344 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7345 foundry, family, weight, slant, size,
7346 &point_size, &avgwidth, charset) != 8)
7347 return 0;
7349 if (*size == 0)
7351 if (point_size > 0)
7352 *size = point_size / 10;
7353 else if (avgwidth > 0)
7354 *size = avgwidth / 10;
7356 if (*size == 0)
7357 *size = kDefaultFontSize;
7359 *style = normal;
7360 if (strcmp (weight, "bold") == 0)
7361 *style |= bold;
7362 if (*slant == 'i')
7363 *style |= italic;
7365 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
7367 int foundry_len = strlen (foundry), family_len = strlen (family);
7369 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
7371 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7372 but take overlap into account. */
7373 memmove (family + foundry_len + 1, family, family_len);
7374 memcpy (family, foundry, foundry_len);
7375 family[foundry_len] = '-';
7376 family[foundry_len + 1 + family_len] = '-';
7377 strcpy (family + foundry_len + 1 + family_len + 1, charset);
7379 else
7380 return 0;
7383 for (p = family; *p; p++)
7384 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7385 for some locales. */
7386 if (isascii (*p))
7387 *p = tolower (*p);
7389 return 1;
7393 static void
7394 add_font_name_table_entry (char *font_name)
7396 if (font_name_table_size == 0)
7398 font_name_table_size = 256;
7399 font_name_table = (char **)
7400 xmalloc (font_name_table_size * sizeof (char *));
7402 else if (font_name_count + 1 >= font_name_table_size)
7404 font_name_table_size *= 2;
7405 font_name_table = (char **)
7406 xrealloc (font_name_table,
7407 font_name_table_size * sizeof (char *));
7410 font_name_table[font_name_count++] = font_name;
7413 static void
7414 add_mac_font_name (name, size, style, charset)
7415 const char *name;
7416 int size;
7417 Style style;
7418 const char *charset;
7420 if (size > 0)
7421 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
7422 else
7424 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
7425 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
7426 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
7427 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
7428 charset));
7432 #if USE_ATSUI
7433 static FMFontStyle
7434 fm_get_style_from_font (font)
7435 FMFont font;
7437 OSStatus err;
7438 FMFontStyle style = normal;
7439 ByteCount len;
7440 UInt16 mac_style;
7441 FMFontFamily font_family;
7442 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
7444 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
7445 some font (e.g., Optima) even if it is `bold'. */
7446 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
7447 sizeof (mac_style), &mac_style, &len);
7448 if (err == noErr
7449 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
7450 style = EndianU16_BtoN (mac_style);
7451 else
7452 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
7454 return style;
7457 static ATSUFontID
7458 atsu_find_font_from_family_name (family)
7459 const char *family;
7461 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
7462 unsigned hash_code;
7463 int i;
7464 Lisp_Object rest, best;
7465 FMFontStyle min_style, style;
7467 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
7468 &hash_code);
7469 if (i < 0)
7470 return kATSUInvalidFontID;
7472 rest = HASH_VALUE (h, i);
7473 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
7474 return cons_to_long (rest);
7476 rest = Fnreverse (rest);
7477 best = XCAR (rest);
7478 rest = XCDR (rest);
7479 if (!NILP (rest)
7480 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
7483 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
7484 if (style < min_style)
7486 best = XCAR (rest);
7487 if (style == normal)
7488 break;
7489 else
7490 min_style = style;
7492 rest = XCDR (rest);
7494 while (!NILP (rest));
7496 HASH_VALUE (h, i) = best;
7497 return cons_to_long (best);
7500 static Lisp_Object
7501 fm_style_to_face_attributes (fm_style)
7502 FMFontStyle fm_style;
7504 Lisp_Object tem;
7506 fm_style &= (bold | italic);
7507 tem = assq_no_quit (make_number (fm_style),
7508 fm_style_face_attributes_alist);
7509 if (!NILP (tem))
7510 return XCDR (tem);
7512 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
7513 QCslant, fm_style & italic ? Qitalic : Qnormal);
7514 fm_style_face_attributes_alist =
7515 Fcons (Fcons (make_number (fm_style), tem),
7516 fm_style_face_attributes_alist);
7518 return tem;
7521 static Lisp_Object
7522 atsu_find_font_family_name (font_id)
7523 ATSUFontID font_id;
7525 OSStatus err;
7526 ByteCount len;
7527 Lisp_Object family = Qnil;
7529 err = ATSUFindFontName (font_id, kFontFamilyName,
7530 kFontMacintoshPlatform, kFontNoScript,
7531 kFontNoLanguage, 0, NULL, &len, NULL);
7532 if (err == noErr)
7534 family = make_uninit_string (len);
7535 err = ATSUFindFontName (font_id, kFontFamilyName,
7536 kFontMacintoshPlatform, kFontNoScript,
7537 kFontNoLanguage, len, SDATA (family),
7538 NULL, NULL);
7540 if (err == noErr)
7541 decode_mac_font_name (SDATA (family), len + 1, Qnil);
7543 return family;
7546 Lisp_Object
7547 mac_atsu_font_face_attributes (font_id)
7548 ATSUFontID font_id;
7550 Lisp_Object family, style_attrs;
7552 family = atsu_find_font_family_name (font_id);
7553 if (NILP (family))
7554 return Qnil;
7555 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
7556 return Fcons (QCfamily, Fcons (family, style_attrs));
7558 #endif
7560 /* Sets up the table font_name_table to contain the list of all fonts
7561 in the system the first time the table is used so that the Resource
7562 Manager need not be accessed every time this information is
7563 needed. */
7565 static void
7566 init_font_name_table ()
7568 #if TARGET_API_MAC_CARBON
7569 FMFontFamilyIterator ffi;
7570 FMFontFamilyInstanceIterator ffii;
7571 FMFontFamily ff;
7572 Lisp_Object text_encoding_info_alist;
7573 struct gcpro gcpro1;
7575 text_encoding_info_alist = create_text_encoding_info_alist ();
7577 #if USE_ATSUI
7578 #if USE_CG_TEXT_DRAWING
7579 init_cg_text_anti_aliasing_threshold ();
7580 #endif
7581 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
7582 text_encoding_info_alist)))
7584 OSStatus err;
7585 struct Lisp_Hash_Table *h;
7586 unsigned hash_code;
7587 ItemCount nfonts, i;
7588 ATSUFontID *font_ids = NULL;
7589 Lisp_Object prev_family = Qnil;
7590 int j;
7592 atsu_font_id_hash =
7593 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
7594 make_float (DEFAULT_REHASH_SIZE),
7595 make_float (DEFAULT_REHASH_THRESHOLD),
7596 Qnil, Qnil, Qnil);
7597 h = XHASH_TABLE (atsu_font_id_hash);
7599 err = ATSUFontCount (&nfonts);
7600 if (err == noErr)
7602 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
7603 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
7605 if (err == noErr)
7606 for (i = 0; i < nfonts; i++)
7608 Lisp_Object family;
7610 family = atsu_find_font_family_name (font_ids[i]);
7611 if (NILP (family) || SREF (family, 0) == '.')
7612 continue;
7613 if (!NILP (Fequal (prev_family, family)))
7614 family = prev_family;
7615 else
7616 j = hash_lookup (h, family, &hash_code);
7617 if (j < 0)
7619 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
7620 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
7621 Qnil), hash_code);
7623 else if (EQ (prev_family, family))
7624 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
7625 HASH_VALUE (h, j));
7626 prev_family = family;
7628 if (font_ids)
7629 xfree (font_ids);
7631 #endif
7633 /* Create a dummy instance iterator here to avoid creating and
7634 destroying it in the loop. */
7635 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
7636 return;
7637 /* Create an iterator to enumerate the font families. */
7638 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
7639 != noErr)
7641 FMDisposeFontFamilyInstanceIterator (&ffii);
7642 return;
7645 GCPRO1 (text_encoding_info_alist);
7647 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
7649 Str255 name;
7650 FMFont font;
7651 FMFontStyle style;
7652 FMFontSize size;
7653 TextEncoding encoding;
7654 TextEncodingBase sc;
7655 Lisp_Object text_encoding_info, family;
7657 if (FMGetFontFamilyName (ff, name) != noErr)
7658 continue;
7659 p2cstr (name);
7660 if (*name == '.')
7661 continue;
7663 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
7664 continue;
7665 sc = GetTextEncodingBase (encoding);
7666 text_encoding_info = assq_no_quit (make_number (sc),
7667 text_encoding_info_alist);
7668 if (NILP (text_encoding_info))
7669 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
7670 text_encoding_info_alist);
7671 decode_mac_font_name (name, sizeof (name),
7672 XCAR (XCDR (text_encoding_info)));
7673 family = build_string (name);
7674 if (!NILP (Fassoc (family, fm_font_family_alist)))
7675 continue;
7676 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
7677 fm_font_family_alist);
7679 /* Point the instance iterator at the current font family. */
7680 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
7681 continue;
7683 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
7684 == noErr)
7686 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7688 if (size > 0 || style == normal)
7689 for (; !NILP (rest); rest = XCDR (rest))
7690 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
7694 UNGCPRO;
7696 /* Dispose of the iterators. */
7697 FMDisposeFontFamilyIterator (&ffi);
7698 FMDisposeFontFamilyInstanceIterator (&ffii);
7699 #else /* !TARGET_API_MAC_CARBON */
7700 GrafPtr port;
7701 SInt16 fontnum, old_fontnum;
7702 int num_mac_fonts = CountResources('FOND');
7703 int i, j;
7704 Handle font_handle, font_handle_2;
7705 short id, scriptcode;
7706 ResType type;
7707 Str255 name;
7708 struct FontAssoc *fat;
7709 struct AsscEntry *assc_entry;
7710 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
7711 struct gcpro gcpro1;
7713 GetPort (&port); /* save the current font number used */
7714 old_fontnum = port->txFont;
7716 text_encoding_info_alist = create_text_encoding_info_alist ();
7718 GCPRO1 (text_encoding_info_alist);
7720 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
7722 font_handle = GetIndResource ('FOND', i);
7723 if (!font_handle)
7724 continue;
7726 GetResInfo (font_handle, &id, &type, name);
7727 GetFNum (name, &fontnum);
7728 p2cstr (name);
7729 if (fontnum == 0 || *name == '.')
7730 continue;
7732 TextFont (fontnum);
7733 scriptcode = FontToScript (fontnum);
7734 text_encoding_info = assq_no_quit (make_number (scriptcode),
7735 text_encoding_info_alist);
7736 if (NILP (text_encoding_info))
7737 text_encoding_info = assq_no_quit (make_number (smRoman),
7738 text_encoding_info_alist);
7739 decode_mac_font_name (name, sizeof (name),
7740 XCAR (XCDR (text_encoding_info)));
7741 family = build_string (name);
7742 if (!NILP (Fassoc (family, fm_font_family_alist)))
7743 continue;
7744 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
7745 fm_font_family_alist);
7748 HLock (font_handle);
7750 if (GetResourceSizeOnDisk (font_handle)
7751 >= sizeof (struct FamRec))
7753 fat = (struct FontAssoc *) (*font_handle
7754 + sizeof (struct FamRec));
7755 assc_entry
7756 = (struct AsscEntry *) (*font_handle
7757 + sizeof (struct FamRec)
7758 + sizeof (struct FontAssoc));
7760 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
7762 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7764 for (; !NILP (rest); rest = XCDR (rest))
7765 add_mac_font_name (name, assc_entry->fontSize,
7766 assc_entry->fontStyle,
7767 SDATA (XCAR (rest)));
7771 HUnlock (font_handle);
7772 font_handle_2 = GetNextFOND (font_handle);
7773 ReleaseResource (font_handle);
7774 font_handle = font_handle_2;
7776 while (ResError () == noErr && font_handle);
7779 UNGCPRO;
7781 TextFont (old_fontnum);
7782 #endif /* !TARGET_API_MAC_CARBON */
7786 void
7787 mac_clear_font_name_table ()
7789 int i;
7791 for (i = 0; i < font_name_count; i++)
7792 xfree (font_name_table[i]);
7793 xfree (font_name_table);
7794 font_name_table = NULL;
7795 font_name_table_size = font_name_count = 0;
7796 fm_font_family_alist = Qnil;
7800 enum xlfd_scalable_field_index
7802 XLFD_SCL_PIXEL_SIZE,
7803 XLFD_SCL_POINT_SIZE,
7804 XLFD_SCL_AVGWIDTH,
7805 XLFD_SCL_LAST
7808 static const int xlfd_scalable_fields[] =
7810 6, /* PIXEL_SIZE */
7811 7, /* POINT_SIZE */
7812 11, /* AVGWIDTH */
7816 static Lisp_Object
7817 mac_do_list_fonts (pattern, maxnames)
7818 const char *pattern;
7819 int maxnames;
7821 int i, n_fonts = 0;
7822 Lisp_Object font_list = Qnil;
7823 struct xlfdpat *pat;
7824 char *scaled;
7825 const char *ptr;
7826 int scl_val[XLFD_SCL_LAST], *val;
7827 const int *field;
7828 int exact;
7830 if (font_name_table == NULL) /* Initialize when first used. */
7831 init_font_name_table ();
7833 for (i = 0; i < XLFD_SCL_LAST; i++)
7834 scl_val[i] = -1;
7836 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7837 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7838 fonts are scaled according to the specified size. */
7839 ptr = pattern;
7840 i = 0;
7841 field = xlfd_scalable_fields;
7842 val = scl_val;
7843 if (*ptr == '-')
7846 ptr++;
7847 if (i == *field)
7849 if ('0' <= *ptr && *ptr <= '9')
7851 *val = *ptr++ - '0';
7852 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
7853 *val = *val * 10 + *ptr++ - '0';
7854 if (*ptr != '-')
7855 *val = -1;
7857 field++;
7858 val++;
7860 ptr = strchr (ptr, '-');
7861 i++;
7863 while (ptr && i < 14);
7865 if (i == 14 && ptr == NULL)
7867 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
7868 scl_val[XLFD_SCL_PIXEL_SIZE] =
7869 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
7870 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
7871 : -1));
7872 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
7873 scl_val[XLFD_SCL_POINT_SIZE] =
7874 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7875 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
7876 : -1));
7877 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
7878 scl_val[XLFD_SCL_AVGWIDTH] =
7879 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7880 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
7881 : -1));
7883 else
7884 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
7886 pat = xlfdpat_create (pattern);
7887 if (pat == NULL)
7888 return Qnil;
7890 exact = xlfdpat_exact_p (pat);
7892 for (i = 0; i < font_name_count; i++)
7894 if (xlfdpat_match (pat, font_name_table[i]))
7896 font_list = Fcons (build_string (font_name_table[i]), font_list);
7897 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7898 break;
7900 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
7901 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
7903 int former_len = ptr - font_name_table[i];
7905 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
7906 memcpy (scaled, font_name_table[i], former_len);
7907 sprintf (scaled + former_len,
7908 "-%d-%d-72-72-m-%d-%s",
7909 scl_val[XLFD_SCL_PIXEL_SIZE],
7910 scl_val[XLFD_SCL_POINT_SIZE],
7911 scl_val[XLFD_SCL_AVGWIDTH],
7912 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
7914 if (xlfdpat_match (pat, scaled))
7916 font_list = Fcons (build_string (scaled), font_list);
7917 xfree (scaled);
7918 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7919 break;
7921 else
7922 xfree (scaled);
7926 xlfdpat_destroy (pat);
7928 return font_list;
7931 /* Return a list of names of available fonts matching PATTERN on frame F.
7933 Frame F null means we have not yet created any frame on Mac, and
7934 consult the first display in x_display_list. MAXNAMES sets a limit
7935 on how many fonts to match. */
7937 Lisp_Object
7938 x_list_fonts (f, pattern, size, maxnames)
7939 struct frame *f;
7940 Lisp_Object pattern;
7941 int size, maxnames;
7943 Lisp_Object list = Qnil, patterns, tem, key;
7944 struct mac_display_info *dpyinfo
7945 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
7947 xassert (size <= 0);
7949 patterns = Fassoc (pattern, Valternate_fontname_alist);
7950 if (NILP (patterns))
7951 patterns = Fcons (pattern, Qnil);
7953 for (; CONSP (patterns); patterns = XCDR (patterns))
7955 pattern = XCAR (patterns);
7957 if (!STRINGP (pattern))
7958 continue;
7960 tem = XCAR (XCDR (dpyinfo->name_list_element));
7961 key = Fcons (pattern, make_number (maxnames));
7963 list = Fassoc (key, tem);
7964 if (!NILP (list))
7966 list = Fcdr_safe (list);
7967 /* We have a cashed list. Don't have to get the list again. */
7968 goto label_cached;
7971 BLOCK_INPUT;
7972 list = mac_do_list_fonts (SDATA (pattern), maxnames);
7973 UNBLOCK_INPUT;
7975 /* MAC_TODO: add code for matching outline fonts here */
7977 /* Now store the result in the cache. */
7978 XSETCAR (XCDR (dpyinfo->name_list_element),
7979 Fcons (Fcons (key, list),
7980 XCAR (XCDR (dpyinfo->name_list_element))));
7982 label_cached:
7983 if (NILP (list)) continue; /* Try the remaining alternatives. */
7986 return list;
7990 #if GLYPH_DEBUG
7992 /* Check that FONT is valid on frame F. It is if it can be found in F's
7993 font table. */
7995 static void
7996 x_check_font (f, font)
7997 struct frame *f;
7998 XFontStruct *font;
8000 int i;
8001 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8003 xassert (font != NULL);
8005 for (i = 0; i < dpyinfo->n_fonts; i++)
8006 if (dpyinfo->font_table[i].name
8007 && font == dpyinfo->font_table[i].font)
8008 break;
8010 xassert (i < dpyinfo->n_fonts);
8013 #endif /* GLYPH_DEBUG != 0 */
8015 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8016 Note: There are (broken) X fonts out there with invalid XFontStruct
8017 min_bounds contents. For example, handa@etl.go.jp reports that
8018 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8019 have font->min_bounds.width == 0. */
8021 static INLINE void
8022 x_font_min_bounds (font, w, h)
8023 MacFontStruct *font;
8024 int *w, *h;
8026 *h = FONT_HEIGHT (font);
8027 *w = font->min_bounds.width;
8031 /* Compute the smallest character width and smallest font height over
8032 all fonts available on frame F. Set the members smallest_char_width
8033 and smallest_font_height in F's x_display_info structure to
8034 the values computed. Value is non-zero if smallest_font_height or
8035 smallest_char_width become smaller than they were before. */
8037 static int
8038 x_compute_min_glyph_bounds (f)
8039 struct frame *f;
8041 int i;
8042 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8043 MacFontStruct *font;
8044 int old_width = dpyinfo->smallest_char_width;
8045 int old_height = dpyinfo->smallest_font_height;
8047 dpyinfo->smallest_font_height = 100000;
8048 dpyinfo->smallest_char_width = 100000;
8050 for (i = 0; i < dpyinfo->n_fonts; ++i)
8051 if (dpyinfo->font_table[i].name)
8053 struct font_info *fontp = dpyinfo->font_table + i;
8054 int w, h;
8056 font = (MacFontStruct *) fontp->font;
8057 xassert (font != (MacFontStruct *) ~0);
8058 x_font_min_bounds (font, &w, &h);
8060 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8061 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8064 xassert (dpyinfo->smallest_char_width > 0
8065 && dpyinfo->smallest_font_height > 0);
8067 return (dpyinfo->n_fonts == 1
8068 || dpyinfo->smallest_char_width < old_width
8069 || dpyinfo->smallest_font_height < old_height);
8073 /* Determine whether given string is a fully-specified XLFD: all 14
8074 fields are present, none is '*'. */
8076 static int
8077 is_fully_specified_xlfd (p)
8078 const char *p;
8080 int i;
8081 char *q;
8083 if (*p != '-')
8084 return 0;
8086 for (i = 0; i < 13; i++)
8088 q = strchr (p + 1, '-');
8089 if (q == NULL)
8090 return 0;
8091 if (q - p == 2 && *(p + 1) == '*')
8092 return 0;
8093 p = q;
8096 if (strchr (p + 1, '-') != NULL)
8097 return 0;
8099 if (*(p + 1) == '*' && *(p + 2) == '\0')
8100 return 0;
8102 return 1;
8106 /* mac_load_query_font creates and returns an internal representation
8107 for a font in a MacFontStruct struct. There is really no concept
8108 corresponding to "loading" a font on the Mac. But we check its
8109 existence and find the font number and all other information for it
8110 and store them in the returned MacFontStruct. */
8112 static MacFontStruct *
8113 mac_load_query_font (f, fontname)
8114 struct frame *f;
8115 char *fontname;
8117 int size;
8118 char *name;
8119 Str255 family;
8120 Str31 charset;
8121 SInt16 fontnum;
8122 #if USE_ATSUI
8123 static ATSUFontID font_id;
8124 ATSUStyle mac_style = NULL;
8125 #endif
8126 Style fontface;
8127 #if TARGET_API_MAC_CARBON
8128 TextEncoding encoding;
8129 int scriptcode;
8130 #else
8131 short scriptcode;
8132 #endif
8133 MacFontStruct *font;
8134 XCharStruct *space_bounds = NULL, *pcm;
8136 if (is_fully_specified_xlfd (fontname))
8137 name = fontname;
8138 else
8140 Lisp_Object matched_fonts;
8142 matched_fonts = mac_do_list_fonts (fontname, 1);
8143 if (NILP (matched_fonts))
8144 return NULL;
8145 name = SDATA (XCAR (matched_fonts));
8148 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
8149 return NULL;
8151 #if USE_ATSUI
8152 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
8154 OSStatus err;
8155 static const ATSUAttributeTag tags[] =
8156 {kATSUFontTag, kATSUSizeTag,
8157 kATSUQDBoldfaceTag, kATSUQDItalicTag};
8158 static const ByteCount sizes[] =
8159 {sizeof (ATSUFontID), sizeof (Fixed),
8160 sizeof (Boolean), sizeof (Boolean)};
8161 static Fixed size_fixed;
8162 static Boolean bold_p, italic_p;
8163 static const ATSUAttributeValuePtr values[] =
8164 {&font_id, &size_fixed,
8165 &bold_p, &italic_p};
8166 static const ATSUFontFeatureType types[] =
8167 {kAllTypographicFeaturesType, kDiacriticsType};
8168 static const ATSUFontFeatureSelector selectors[] =
8169 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
8170 FMFontStyle style;
8172 font_id = atsu_find_font_from_family_name (family);
8173 if (font_id == kATSUInvalidFontID)
8174 return NULL;
8175 size_fixed = Long2Fix (size);
8176 bold_p = (fontface & bold) != 0;
8177 italic_p = (fontface & italic) != 0;
8178 err = ATSUCreateStyle (&mac_style);
8179 if (err != noErr)
8180 return NULL;
8181 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
8182 types, selectors);
8183 if (err != noErr)
8184 return NULL;
8185 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
8186 tags, sizes, values);
8187 if (err != noErr)
8188 return NULL;
8189 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
8190 if (err != noErr)
8191 fontnum = -1;
8192 scriptcode = kTextEncodingMacUnicode;
8194 else
8195 #endif
8197 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
8199 if (NILP (tmp))
8200 return NULL;
8201 fontnum = XINT (XCDR (tmp));
8202 #if TARGET_API_MAC_CARBON
8203 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
8204 return NULL;
8205 scriptcode = GetTextEncodingBase (encoding);
8206 #else
8207 scriptcode = FontToScript (fontnum);
8208 #endif
8211 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
8213 font->mac_fontnum = fontnum;
8214 font->mac_fontsize = size;
8215 font->mac_fontface = fontface;
8216 font->mac_scriptcode = scriptcode;
8217 #if USE_ATSUI
8218 font->mac_style = mac_style;
8219 #if USE_CG_TEXT_DRAWING
8220 font->cg_font = NULL;
8221 font->cg_glyphs = NULL;
8222 #endif
8223 #endif
8225 /* Apple Japanese (SJIS) font is listed as both
8226 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8227 (Roman script) in init_font_name_table (). The latter should be
8228 treated as a one-byte font. */
8229 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
8230 font->mac_scriptcode = smRoman;
8232 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
8234 #if USE_ATSUI
8235 if (font->mac_style)
8237 OSStatus err;
8238 UniChar c;
8240 font->min_byte1 = 0;
8241 font->max_byte1 = 0xff;
8242 font->min_char_or_byte2 = 0;
8243 font->max_char_or_byte2 = 0xff;
8245 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
8246 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
8247 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
8248 pcm_init (font->bounds.rows[0], 0x100);
8250 #if USE_CG_TEXT_DRAWING
8251 if (fontnum != -1)
8253 FMFontStyle style;
8254 ATSFontRef ats_font;
8256 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
8257 &font_id, &style);
8258 /* Use CG text drawing if italic/bold is not synthesized. */
8259 if (err == noErr && style == fontface)
8261 ats_font = FMGetATSFontRefFromFont (font_id);
8262 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
8266 if (font->cg_font)
8268 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
8269 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
8271 #endif
8272 space_bounds = font->bounds.rows[0] + 0x20;
8273 err = mac_query_char_extents (font->mac_style, 0x20,
8274 &font->ascent, &font->descent,
8275 space_bounds,
8276 #if USE_CG_TEXT_DRAWING
8277 (font->cg_glyphs ? font->cg_glyphs + 0x20
8278 : NULL)
8279 #else
8280 NULL
8281 #endif
8283 if (err != noErr
8284 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
8286 mac_unload_font (&one_mac_display_info, font);
8287 return NULL;
8290 pcm = font->bounds.rows[0];
8291 for (c = 0x21; c <= 0xff; c++)
8293 if (c == 0xad)
8294 /* Soft hyphen is not supported in ATSUI. */
8295 continue;
8296 else if (c == 0x7f)
8298 #if USE_CG_TEXT_DRAWING
8299 if (font->cg_glyphs)
8301 c = 0x9f;
8302 pcm = NULL;
8303 continue;
8305 #endif
8306 break;
8309 mac_query_char_extents (font->mac_style, c, NULL, NULL,
8310 pcm ? pcm + c : NULL,
8311 #if USE_CG_TEXT_DRAWING
8312 (font->cg_glyphs ? font->cg_glyphs + c
8313 : NULL)
8314 #else
8315 NULL
8316 #endif
8319 #if USE_CG_TEXT_DRAWING
8320 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
8322 /* Don't use CG text drawing if font substitution occurs in
8323 ASCII or Latin-1 characters. */
8324 CGFontRelease (font->cg_font);
8325 font->cg_font = NULL;
8326 xfree (font->cg_glyphs);
8327 font->cg_glyphs = NULL;
8328 if (pcm == NULL)
8329 break;
8331 #endif
8334 else
8335 #endif
8337 OSStatus err;
8338 FontInfo the_fontinfo;
8339 int is_two_byte_font;
8341 #if USE_CG_DRAWING
8342 mac_prepare_for_quickdraw (f);
8343 #endif
8344 SetPortWindowPort (FRAME_MAC_WINDOW (f));
8346 TextFont (fontnum);
8347 TextSize (size);
8348 TextFace (fontface);
8350 GetFontInfo (&the_fontinfo);
8352 font->ascent = the_fontinfo.ascent;
8353 font->descent = the_fontinfo.descent;
8355 is_two_byte_font = (font->mac_scriptcode == smJapanese
8356 || font->mac_scriptcode == smTradChinese
8357 || font->mac_scriptcode == smSimpChinese
8358 || font->mac_scriptcode == smKorean);
8360 if (is_two_byte_font)
8362 int char_width;
8364 font->min_byte1 = 0xa1;
8365 font->max_byte1 = 0xfe;
8366 font->min_char_or_byte2 = 0xa1;
8367 font->max_char_or_byte2 = 0xfe;
8369 /* Use the width of an "ideographic space" of that font
8370 because the_fontinfo.widMax returns the wrong width for
8371 some fonts. */
8372 switch (font->mac_scriptcode)
8374 case smJapanese:
8375 font->min_byte1 = 0x81;
8376 font->max_byte1 = 0xfc;
8377 font->min_char_or_byte2 = 0x40;
8378 font->max_char_or_byte2 = 0xfc;
8379 char_width = StringWidth("\p\x81\x40");
8380 break;
8381 case smTradChinese:
8382 font->min_char_or_byte2 = 0x40;
8383 char_width = StringWidth("\p\xa1\x40");
8384 break;
8385 case smSimpChinese:
8386 char_width = StringWidth("\p\xa1\xa1");
8387 break;
8388 case smKorean:
8389 char_width = StringWidth("\p\xa1\xa1");
8390 break;
8393 font->bounds.per_char = NULL;
8395 if (fontface & italic)
8396 font->max_bounds.rbearing = char_width + 1;
8397 else
8398 font->max_bounds.rbearing = char_width;
8399 font->max_bounds.lbearing = 0;
8400 font->max_bounds.width = char_width;
8401 font->max_bounds.ascent = the_fontinfo.ascent;
8402 font->max_bounds.descent = the_fontinfo.descent;
8404 font->min_bounds = font->max_bounds;
8406 else
8408 int c;
8410 font->min_byte1 = font->max_byte1 = 0;
8411 font->min_char_or_byte2 = 0x20;
8412 font->max_char_or_byte2 = 0xff;
8414 font->bounds.per_char =
8415 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
8416 bzero (font->bounds.per_char,
8417 sizeof (XCharStruct) * (0xff - 0x20 + 1));
8419 space_bounds = font->bounds.per_char;
8420 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
8421 &font->descent, space_bounds, NULL);
8422 if (err != noErr || space_bounds->width <= 0)
8424 mac_unload_font (&one_mac_display_info, font);
8425 return NULL;
8428 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
8429 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
8433 if (space_bounds)
8435 int c;
8437 font->min_bounds = font->max_bounds = *space_bounds;
8438 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
8439 if (pcm->width > 0)
8441 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
8442 pcm->lbearing);
8443 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
8444 pcm->rbearing);
8445 font->min_bounds.width = min (font->min_bounds.width,
8446 pcm->width);
8447 font->min_bounds.ascent = min (font->min_bounds.ascent,
8448 pcm->ascent);
8449 font->min_bounds.descent = min (font->min_bounds.descent,
8450 pcm->descent);
8452 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
8453 pcm->lbearing);
8454 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
8455 pcm->rbearing);
8456 font->max_bounds.width = max (font->max_bounds.width,
8457 pcm->width);
8458 font->max_bounds.ascent = max (font->max_bounds.ascent,
8459 pcm->ascent);
8460 font->max_bounds.descent = max (font->max_bounds.descent,
8461 pcm->descent);
8463 if (
8464 #if USE_ATSUI
8465 font->mac_style == NULL &&
8466 #endif
8467 font->max_bounds.width == font->min_bounds.width
8468 && font->min_bounds.lbearing >= 0
8469 && font->max_bounds.rbearing <= font->max_bounds.width)
8471 /* Fixed width and no overhangs. */
8472 xfree (font->bounds.per_char);
8473 font->bounds.per_char = NULL;
8477 #if !defined (MAC_OS8) || USE_ATSUI
8478 /* AppKit and WebKit do some adjustment to the heights of Courier,
8479 Helvetica, and Times. This only works on the environments where
8480 srcCopy text transfer mode is never used. */
8481 if (
8482 #ifdef MAC_OS8 /* implies USE_ATSUI */
8483 font->mac_style &&
8484 #endif
8485 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
8486 || strcmp (family, "times") == 0))
8487 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
8488 #endif
8490 return font;
8494 void
8495 mac_unload_font (dpyinfo, font)
8496 struct mac_display_info *dpyinfo;
8497 XFontStruct *font;
8499 xfree (font->full_name);
8500 #if USE_ATSUI
8501 if (font->mac_style)
8503 int i;
8505 for (i = font->min_byte1; i <= font->max_byte1; i++)
8506 if (font->bounds.rows[i])
8507 xfree (font->bounds.rows[i]);
8508 xfree (font->bounds.rows);
8509 ATSUDisposeStyle (font->mac_style);
8511 else
8512 #endif
8513 if (font->bounds.per_char)
8514 xfree (font->bounds.per_char);
8515 #if USE_CG_TEXT_DRAWING
8516 if (font->cg_font)
8517 CGFontRelease (font->cg_font);
8518 if (font->cg_glyphs)
8519 xfree (font->cg_glyphs);
8520 #endif
8521 xfree (font);
8525 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8526 pointer to the structure font_info while allocating it dynamically.
8527 If SIZE is 0, load any size of font.
8528 If loading is failed, return NULL. */
8530 struct font_info *
8531 x_load_font (f, fontname, size)
8532 struct frame *f;
8533 register char *fontname;
8534 int size;
8536 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8537 Lisp_Object font_names;
8539 /* Get a list of all the fonts that match this name. Once we
8540 have a list of matching fonts, we compare them against the fonts
8541 we already have by comparing names. */
8542 font_names = x_list_fonts (f, build_string (fontname), size, 1);
8544 if (!NILP (font_names))
8546 Lisp_Object tail;
8547 int i;
8549 for (i = 0; i < dpyinfo->n_fonts; i++)
8550 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
8551 if (dpyinfo->font_table[i].name
8552 && (!strcmp (dpyinfo->font_table[i].name,
8553 SDATA (XCAR (tail)))
8554 || !strcmp (dpyinfo->font_table[i].full_name,
8555 SDATA (XCAR (tail)))))
8556 return (dpyinfo->font_table + i);
8558 else
8559 return NULL;
8561 /* Load the font and add it to the table. */
8563 struct MacFontStruct *font;
8564 struct font_info *fontp;
8565 int i;
8567 fontname = (char *) SDATA (XCAR (font_names));
8569 BLOCK_INPUT;
8570 font = mac_load_query_font (f, fontname);
8571 UNBLOCK_INPUT;
8572 if (!font)
8573 return NULL;
8575 /* Find a free slot in the font table. */
8576 for (i = 0; i < dpyinfo->n_fonts; ++i)
8577 if (dpyinfo->font_table[i].name == NULL)
8578 break;
8580 /* If no free slot found, maybe enlarge the font table. */
8581 if (i == dpyinfo->n_fonts
8582 && dpyinfo->n_fonts == dpyinfo->font_table_size)
8584 int sz;
8585 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
8586 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
8587 dpyinfo->font_table
8588 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
8591 fontp = dpyinfo->font_table + i;
8592 if (i == dpyinfo->n_fonts)
8593 ++dpyinfo->n_fonts;
8595 /* Now fill in the slots of *FONTP. */
8596 BLOCK_INPUT;
8597 bzero (fontp, sizeof (*fontp));
8598 fontp->font = font;
8599 fontp->font_idx = i;
8600 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
8601 bcopy (fontname, fontp->name, strlen (fontname) + 1);
8603 if (font->min_bounds.width == font->max_bounds.width)
8605 /* Fixed width font. */
8606 fontp->average_width = fontp->space_width = font->min_bounds.width;
8608 else
8610 XChar2b char2b;
8611 XCharStruct *pcm;
8613 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
8614 pcm = mac_per_char_metric (font, &char2b, 0);
8615 if (pcm)
8616 fontp->space_width = pcm->width;
8617 else
8618 fontp->space_width = FONT_WIDTH (font);
8620 if (pcm)
8622 int width = pcm->width;
8623 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
8624 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
8625 width += pcm->width;
8626 fontp->average_width = width / 95;
8628 else
8629 fontp->average_width = FONT_WIDTH (font);
8632 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
8633 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
8635 fontp->size = font->max_bounds.width;
8636 fontp->height = FONT_HEIGHT (font);
8638 /* For some font, ascent and descent in max_bounds field is
8639 larger than the above value. */
8640 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
8641 if (max_height > fontp->height)
8642 fontp->height = max_height;
8645 /* The slot `encoding' specifies how to map a character
8646 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8647 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8648 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8649 2:0xA020..0xFF7F). For the moment, we don't know which charset
8650 uses this font. So, we set information in fontp->encoding[1]
8651 which is never used by any charset. If mapping can't be
8652 decided, set FONT_ENCODING_NOT_DECIDED. */
8653 if (font->mac_scriptcode == smJapanese)
8654 fontp->encoding[1] = 4;
8655 else
8657 fontp->encoding[1]
8658 = (font->max_byte1 == 0
8659 /* 1-byte font */
8660 ? (font->min_char_or_byte2 < 0x80
8661 ? (font->max_char_or_byte2 < 0x80
8662 ? 0 /* 0x20..0x7F */
8663 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
8664 : 1) /* 0xA0..0xFF */
8665 /* 2-byte font */
8666 : (font->min_byte1 < 0x80
8667 ? (font->max_byte1 < 0x80
8668 ? (font->min_char_or_byte2 < 0x80
8669 ? (font->max_char_or_byte2 < 0x80
8670 ? 0 /* 0x2020..0x7F7F */
8671 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
8672 : 3) /* 0x20A0..0x7FFF */
8673 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
8674 : (font->min_char_or_byte2 < 0x80
8675 ? (font->max_char_or_byte2 < 0x80
8676 ? 2 /* 0xA020..0xFF7F */
8677 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
8678 : 1))); /* 0xA0A0..0xFFFF */
8681 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8682 fontp->baseline_offset
8683 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
8684 ? (long) value : 0);
8685 fontp->relative_compose
8686 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
8687 ? (long) value : 0);
8688 fontp->default_ascent
8689 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
8690 ? (long) value : 0);
8691 #else
8692 fontp->baseline_offset = 0;
8693 fontp->relative_compose = 0;
8694 fontp->default_ascent = 0;
8695 #endif
8697 /* Set global flag fonts_changed_p to non-zero if the font loaded
8698 has a character with a smaller width than any other character
8699 before, or if the font loaded has a smaller height than any
8700 other font loaded before. If this happens, it will make a
8701 glyph matrix reallocation necessary. */
8702 fonts_changed_p |= x_compute_min_glyph_bounds (f);
8703 UNBLOCK_INPUT;
8704 return fontp;
8709 /* Return a pointer to struct font_info of a font named FONTNAME for
8710 frame F. If no such font is loaded, return NULL. */
8712 struct font_info *
8713 x_query_font (f, fontname)
8714 struct frame *f;
8715 register char *fontname;
8717 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8718 int i;
8720 for (i = 0; i < dpyinfo->n_fonts; i++)
8721 if (dpyinfo->font_table[i].name
8722 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
8723 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
8724 return (dpyinfo->font_table + i);
8725 return NULL;
8729 /* Find a CCL program for a font specified by FONTP, and set the member
8730 `encoder' of the structure. */
8732 void
8733 x_find_ccl_program (fontp)
8734 struct font_info *fontp;
8736 Lisp_Object list, elt;
8738 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
8740 elt = XCAR (list);
8741 if (CONSP (elt)
8742 && STRINGP (XCAR (elt))
8743 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
8744 >= 0))
8745 break;
8747 if (! NILP (list))
8749 struct ccl_program *ccl
8750 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
8752 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
8753 xfree (ccl);
8754 else
8755 fontp->font_encoder = ccl;
8759 #if USE_MAC_FONT_PANEL
8760 /* Whether Font Panel has been shown before. The first call to font
8761 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8762 slow. This variable is used for deferring such a call as much as
8763 possible. */
8764 static int font_panel_shown_p = 0;
8767 mac_font_panel_visible_p ()
8769 return font_panel_shown_p && FPIsFontPanelVisible ();
8772 OSStatus
8773 mac_show_hide_font_panel ()
8775 font_panel_shown_p = 1;
8777 return FPShowHideFontPanel ();
8780 OSStatus
8781 mac_set_font_info_for_selection (f, face_id, c)
8782 struct frame *f;
8783 int face_id, c;
8785 OSStatus err;
8786 EventTargetRef target = NULL;
8787 XFontStruct *font = NULL;
8789 if (!mac_font_panel_visible_p ())
8790 return noErr;
8792 if (f)
8794 target = GetWindowEventTarget (FRAME_MAC_WINDOW (f));
8796 if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0))
8798 struct face *face;
8800 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
8801 face = FACE_FROM_ID (f, face_id);
8802 font = face->font;
8806 if (font == NULL)
8807 err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target);
8808 else
8810 if (font->mac_fontnum != -1)
8812 FontSelectionQDStyle qd_style;
8814 qd_style.version = kFontSelectionQDStyleVersionZero;
8815 qd_style.instance.fontFamily = font->mac_fontnum;
8816 qd_style.instance.fontStyle = font->mac_fontface;
8817 qd_style.size = font->mac_fontsize;
8818 qd_style.hasColor = false;
8820 err = SetFontInfoForSelection (kFontSelectionQDType,
8821 1, &qd_style, target);
8823 else
8824 err = SetFontInfoForSelection (kFontSelectionATSUIType,
8825 1, &font->mac_style, target);
8828 return err;
8830 #endif
8833 /* The Mac Event loop code */
8835 #if !TARGET_API_MAC_CARBON
8836 #include <Events.h>
8837 #include <Quickdraw.h>
8838 #include <Balloons.h>
8839 #include <Devices.h>
8840 #include <Fonts.h>
8841 #include <Gestalt.h>
8842 #include <Menus.h>
8843 #include <Processes.h>
8844 #include <Sound.h>
8845 #include <ToolUtils.h>
8846 #include <TextUtils.h>
8847 #include <Dialogs.h>
8848 #include <Script.h>
8849 #include <Types.h>
8850 #include <Resources.h>
8852 #if __MWERKS__
8853 #include <unix.h>
8854 #endif
8855 #endif /* ! TARGET_API_MAC_CARBON */
8857 #define M_APPLE 234
8858 #define I_ABOUT 1
8860 #define DEFAULT_NUM_COLS 80
8862 #define MIN_DOC_SIZE 64
8863 #define MAX_DOC_SIZE 32767
8865 #define EXTRA_STACK_ALLOC (256 * 1024)
8867 #define ARGV_STRING_LIST_ID 129
8868 #define ABOUT_ALERT_ID 128
8869 #define RAM_TOO_LARGE_ALERT_ID 129
8871 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8872 Lisp_Object Qreverse;
8875 /* Modifier associated with the control key, or nil to ignore. */
8876 Lisp_Object Vmac_control_modifier;
8878 /* Modifier associated with the option key, or nil to ignore. */
8879 Lisp_Object Vmac_option_modifier;
8881 /* Modifier associated with the command key, or nil to ignore. */
8882 Lisp_Object Vmac_command_modifier;
8884 /* Modifier associated with the function key, or nil to ignore. */
8885 Lisp_Object Vmac_function_modifier;
8887 /* True if the option and command modifiers should be used to emulate
8888 a three button mouse */
8889 Lisp_Object Vmac_emulate_three_button_mouse;
8891 #if USE_CARBON_EVENTS
8892 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8893 mouse-2, instead of mouse-3. */
8894 int mac_wheel_button_is_mouse_2;
8896 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8897 for processing before Emacs sees it. */
8898 int mac_pass_command_to_system;
8900 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8901 for processing before Emacs sees it. */
8902 int mac_pass_control_to_system;
8903 #endif
8905 /* Points to the variable `inev' in the function XTread_socket. It is
8906 used for passing an input event to the function back from
8907 Carbon/Apple event handlers. */
8908 static struct input_event *read_socket_inev = NULL;
8910 /* Whether or not the screen configuration has changed. */
8911 static int mac_screen_config_changed = 0;
8913 Point saved_menu_event_location;
8915 /* Apple Events */
8916 #if USE_CARBON_EVENTS
8917 static Lisp_Object Qhi_command;
8918 #ifdef MAC_OSX
8919 extern Lisp_Object Qwindow;
8920 static Lisp_Object Qtoolbar_switch_mode;
8921 #endif
8922 #if USE_MAC_FONT_PANEL
8923 extern Lisp_Object Qfont;
8924 static Lisp_Object Qpanel_closed, Qselection;
8925 #endif
8926 #if USE_MAC_TSM
8927 static TSMDocumentID tsm_document_id;
8928 static Lisp_Object Qtext_input;
8929 static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
8930 static Lisp_Object Vmac_ts_active_input_overlay;
8931 extern Lisp_Object Qbefore_string;
8932 static Lisp_Object Vmac_ts_script_language_on_focus;
8933 static Lisp_Object saved_ts_script_language_on_focus;
8934 static ScriptLanguageRecord saved_ts_language;
8935 static Component saved_ts_component;
8936 #endif
8937 #endif
8938 extern int mac_ready_for_apple_events;
8939 extern Lisp_Object Qundefined;
8940 extern void init_apple_event_handler P_ ((void));
8941 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
8942 Lisp_Object *, Lisp_Object *,
8943 Lisp_Object *));
8944 extern OSErr init_coercion_handler P_ ((void));
8946 /* Drag and Drop */
8947 extern OSErr install_drag_handler P_ ((WindowRef));
8948 extern void remove_drag_handler P_ ((WindowRef));
8950 /* Showing help echo string during menu tracking */
8951 extern OSStatus install_menu_target_item_handler P_ ((WindowPtr));
8953 #if USE_CARBON_EVENTS
8954 #ifdef MAC_OSX
8955 extern void init_service_handler ();
8956 static Lisp_Object Qservice, Qpaste, Qperform;
8957 #endif
8959 /* Window Event Handler */
8960 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
8961 EventRef, void *);
8962 #endif
8963 OSStatus install_window_handler (WindowPtr);
8965 extern void init_emacs_passwd_dir ();
8966 extern int emacs_main (int, char **, char **);
8968 extern void initialize_applescript();
8969 extern void terminate_applescript();
8971 /* Table for translating Mac keycode to X keysym values. Contributed
8972 by Sudhir Shenoy.
8973 Mapping for special keys is now identical to that in Apple X11
8974 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8975 on the right of the Cmd key on laptops, and fn + `enter' (->
8976 <linefeed>). */
8977 static const unsigned char keycode_to_xkeysym_table[] = {
8978 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8979 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8980 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8982 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8983 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8984 /*0x38*/ 0, 0, 0, 0,
8985 /*0x3C*/ 0, 0, 0, 0,
8987 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8988 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8989 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8990 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8992 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8993 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8994 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8995 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8997 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8998 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8999 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9000 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9002 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9003 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9004 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9005 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9008 #ifdef MAC_OSX
9009 /* Table for translating Mac keycode with the laptop `fn' key to that
9010 without it. Destination symbols in comments are keys on US
9011 keyboard, and they may not be the same on other types of keyboards.
9012 If the destination is identical to the source, it doesn't map `fn'
9013 key to a modifier. */
9014 static const unsigned char fn_keycode_to_keycode_table[] = {
9015 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9016 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9017 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9019 /*0x30*/ 0, 0, 0, 0,
9020 /*0x34*/ 0, 0, 0, 0,
9021 /*0x38*/ 0, 0, 0, 0,
9022 /*0x3C*/ 0, 0, 0, 0,
9024 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9025 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9026 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9027 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9029 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9030 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9031 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9032 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9034 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9035 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9036 /*0x68*/ 0, 0x69 /*f13 = f13*/, 0x6a /*f16 = f16*/, 0x6b /*f14 = f14*/,
9037 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9039 /*0x70*/ 0, 0x71 /*f15 = f15*/, 0x72 /*help = help*/, 0x7b /*home -> left*/,
9040 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9041 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0x7b /*left = left*/,
9042 /*0x7C*/ 0x7c /*right = right*/, 0x7d /*down = down*/, 0x7e /*up = up*/, 0
9044 #endif /* MAC_OSX */
9046 static int
9047 #if USE_CARBON_EVENTS
9048 mac_to_emacs_modifiers (UInt32 mods, UInt32 unmapped_mods)
9049 #else
9050 mac_to_emacs_modifiers (EventModifiers mods, EventModifiers unmapped_mods)
9051 #endif
9053 unsigned int result = 0;
9054 if ((mods | unmapped_mods) & shiftKey)
9055 result |= shift_modifier;
9057 /* Deactivated to simplify configuration:
9058 if Vmac_option_modifier is non-NIL, we fully process the Option
9059 key. Otherwise, we only process it if an additional Ctrl or Command
9060 is pressed. That way the system may convert the character to a
9061 composed one.
9062 if ((mods & optionKey) &&
9063 (( !NILP(Vmac_option_modifier) ||
9064 ((mods & cmdKey) || (mods & controlKey))))) */
9066 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
9067 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
9068 if (INTEGERP(val))
9069 result |= XUINT(val);
9071 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
9072 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
9073 if (INTEGERP(val))
9074 result |= XUINT(val);
9076 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
9077 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
9078 if (INTEGERP(val))
9079 result |= XUINT(val);
9082 #ifdef MAC_OSX
9083 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
9084 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
9085 if (INTEGERP(val))
9086 result |= XUINT(val);
9088 #endif
9090 return result;
9093 static UInt32
9094 mac_mapped_modifiers (modifiers, key_code)
9095 UInt32 modifiers, key_code;
9097 UInt32 mapped_modifiers_all =
9098 (NILP (Vmac_control_modifier) ? 0 : controlKey)
9099 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
9100 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
9102 #ifdef MAC_OSX
9103 mapped_modifiers_all |=
9104 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
9106 /* The meaning of kEventKeyModifierFnMask has changed in Mac OS X
9107 10.5, and it now behaves much like Cocoa's NSFunctionKeyMask. It
9108 no longer means laptop's `fn' key is down for the following keys:
9109 F1, F2, and so on, Help, Forward Delete, Home, End, Page Up, Page
9110 Down, the arrow keys, and Clear. We ignore the corresponding bit
9111 if that key can be entered without the `fn' key on laptops. */
9112 if (modifiers & kEventKeyModifierFnMask
9113 && key_code <= 0x7f
9114 && fn_keycode_to_keycode_table[key_code] == key_code)
9115 modifiers &= ~kEventKeyModifierFnMask;
9116 #endif
9118 return mapped_modifiers_all & modifiers;
9121 static int
9122 mac_get_emulated_btn ( UInt32 modifiers )
9124 int result = 0;
9125 if (!NILP (Vmac_emulate_three_button_mouse)) {
9126 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
9127 if (modifiers & cmdKey)
9128 result = cmdIs3 ? 2 : 1;
9129 else if (modifiers & optionKey)
9130 result = cmdIs3 ? 1 : 2;
9132 return result;
9135 #if TARGET_API_MAC_CARBON
9136 /***** Code to handle C-g testing *****/
9137 extern int quit_char;
9138 extern int make_ctrl_char P_ ((int));
9141 mac_quit_char_key_p (modifiers, key_code)
9142 UInt32 modifiers, key_code;
9144 UInt32 char_code, mapped_modifiers;
9145 unsigned long some_state = 0;
9146 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9147 int c, emacs_modifiers;
9149 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9150 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
9151 key_code |= (modifiers & ~mapped_modifiers);
9152 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
9153 if (char_code & ~0xff)
9154 return 0;
9156 emacs_modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
9157 if (emacs_modifiers & ctrl_modifier)
9158 c = make_ctrl_char (char_code);
9160 c |= (emacs_modifiers
9161 & (meta_modifier | alt_modifier
9162 | hyper_modifier | super_modifier));
9164 return c == quit_char;
9166 #endif
9168 #if USE_CARBON_EVENTS
9169 /* Obtains the event modifiers from the event ref and then calls
9170 mac_to_emacs_modifiers. */
9171 static int
9172 mac_event_to_emacs_modifiers (EventRef eventRef)
9174 UInt32 mods = 0;
9175 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
9176 sizeof (UInt32), NULL, &mods);
9177 if (!NILP (Vmac_emulate_three_button_mouse) &&
9178 GetEventClass(eventRef) == kEventClassMouse)
9180 mods &= ~(optionKey | cmdKey);
9182 return mac_to_emacs_modifiers (mods, 0);
9185 /* Given an event ref, return the code to use for the mouse button
9186 code in the emacs input_event. */
9187 static int
9188 mac_get_mouse_btn (EventRef ref)
9190 EventMouseButton result = kEventMouseButtonPrimary;
9191 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
9192 sizeof (EventMouseButton), NULL, &result);
9193 switch (result)
9195 case kEventMouseButtonPrimary:
9196 if (NILP (Vmac_emulate_three_button_mouse))
9197 return 0;
9198 else {
9199 UInt32 mods = 0;
9200 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
9201 sizeof (UInt32), NULL, &mods);
9202 return mac_get_emulated_btn(mods);
9204 case kEventMouseButtonSecondary:
9205 return mac_wheel_button_is_mouse_2 ? 2 : 1;
9206 case kEventMouseButtonTertiary:
9207 case 4: /* 4 is the number for the mouse wheel button */
9208 return mac_wheel_button_is_mouse_2 ? 1 : 2;
9209 default:
9210 return 0;
9214 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9215 events. However the click of the mouse wheel is not converted to a
9216 mouseDown or mouseUp event. Likewise for dead key events. This
9217 calls ConvertEventRefToEventRecord, but then checks to see if it is
9218 a mouse up/down, or a dead key Carbon event that has not been
9219 converted, and if so, converts it by hand (to be picked up in the
9220 XTread_socket loop). */
9221 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
9223 OSStatus err;
9224 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
9225 EventKind action;
9227 if (result)
9228 return result;
9230 switch (GetEventClass (eventRef))
9232 case kEventClassMouse:
9233 switch (GetEventKind (eventRef))
9235 case kEventMouseDown:
9236 eventRec->what = mouseDown;
9237 result = 1;
9238 break;
9240 case kEventMouseUp:
9241 eventRec->what = mouseUp;
9242 result = 1;
9243 break;
9245 default:
9246 break;
9248 break;
9250 case kEventClassKeyboard:
9251 switch (GetEventKind (eventRef))
9253 case kEventRawKeyDown:
9254 action = keyDown;
9255 goto keystroke_common;
9256 case kEventRawKeyRepeat:
9257 action = autoKey;
9258 goto keystroke_common;
9259 case kEventRawKeyUp:
9260 action = keyUp;
9261 keystroke_common:
9263 unsigned char char_codes;
9264 UInt32 key_code;
9266 err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes,
9267 typeChar, NULL, sizeof (char),
9268 NULL, &char_codes);
9269 if (err == noErr)
9270 err = GetEventParameter (eventRef, kEventParamKeyCode,
9271 typeUInt32, NULL, sizeof (UInt32),
9272 NULL, &key_code);
9273 if (err == noErr)
9275 eventRec->what = action;
9276 eventRec->message = char_codes | ((key_code & 0xff) << 8);
9277 result = 1;
9280 break;
9282 default:
9283 break;
9285 break;
9287 default:
9288 break;
9291 if (result)
9293 /* Need where and when. */
9294 UInt32 mods = 0;
9296 GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
9297 NULL, sizeof (Point), NULL, &eventRec->where);
9298 /* Use two step process because new event modifiers are 32-bit
9299 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9300 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
9301 NULL, sizeof (UInt32), NULL, &mods);
9302 eventRec->modifiers = mods;
9304 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
9307 return result;
9310 #endif
9312 #ifdef MAC_OS8
9313 static void
9314 do_get_menus (void)
9316 Handle menubar_handle;
9317 MenuHandle menu_handle;
9319 menubar_handle = GetNewMBar (128);
9320 if(menubar_handle == NULL)
9321 abort ();
9322 SetMenuBar (menubar_handle);
9323 DrawMenuBar ();
9325 #if !TARGET_API_MAC_CARBON
9326 menu_handle = GetMenuHandle (M_APPLE);
9327 if(menu_handle != NULL)
9328 AppendResMenu (menu_handle,'DRVR');
9329 else
9330 abort ();
9331 #endif
9335 static void
9336 do_init_managers (void)
9338 #if !TARGET_API_MAC_CARBON
9339 InitGraf (&qd.thePort);
9340 InitFonts ();
9341 FlushEvents (everyEvent, 0);
9342 InitWindows ();
9343 InitMenus ();
9344 TEInit ();
9345 InitDialogs (NULL);
9346 #endif /* !TARGET_API_MAC_CARBON */
9347 InitCursor ();
9349 #if !TARGET_API_MAC_CARBON
9350 /* set up some extra stack space for use by emacs */
9351 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
9353 /* MaxApplZone must be called for AppleScript to execute more
9354 complicated scripts */
9355 MaxApplZone ();
9356 MoreMasters ();
9357 #endif /* !TARGET_API_MAC_CARBON */
9360 static void
9361 do_check_ram_size (void)
9363 SInt32 physical_ram_size, logical_ram_size;
9365 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
9366 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
9367 || physical_ram_size > (1 << VALBITS)
9368 || logical_ram_size > (1 << VALBITS))
9370 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
9371 exit (1);
9374 #endif /* MAC_OS8 */
9376 static void
9377 do_window_update (WindowPtr win)
9379 struct frame *f = mac_window_to_frame (win);
9381 BeginUpdate (win);
9383 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
9384 below. */
9385 if (win != tip_window)
9387 if (f->async_visible == 0)
9389 /* Update events may occur when a frame gets iconified. */
9390 #if 0
9391 f->async_visible = 1;
9392 f->async_iconified = 0;
9393 SET_FRAME_GARBAGED (f);
9394 #endif
9396 else
9398 Rect r;
9399 #if TARGET_API_MAC_CARBON
9400 RgnHandle region = NewRgn ();
9402 GetPortVisibleRegion (GetWindowPort (win), region);
9403 GetRegionBounds (region, &r);
9404 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
9405 #if USE_CG_DRAWING
9406 mac_prepare_for_quickdraw (f);
9407 #endif
9408 UpdateControls (win, region);
9409 DisposeRgn (region);
9410 #else
9411 r = (*win->visRgn)->rgnBBox;
9412 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
9413 UpdateControls (win, win->visRgn);
9414 #endif
9418 EndUpdate (win);
9421 static int
9422 is_emacs_window (WindowPtr win)
9424 Lisp_Object tail, frame;
9426 if (!win)
9427 return 0;
9429 FOR_EACH_FRAME (tail, frame)
9430 if (FRAME_MAC_P (XFRAME (frame)))
9431 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
9432 return 1;
9434 return 0;
9437 #if USE_MAC_TSM
9438 static OSStatus
9439 mac_tsm_resume ()
9441 OSStatus err;
9442 ScriptLanguageRecord slrec, *slptr = NULL;
9444 err = ActivateTSMDocument (tsm_document_id);
9446 if (err == noErr)
9448 if (EQ (Vmac_ts_script_language_on_focus, Qt)
9449 && EQ (saved_ts_script_language_on_focus, Qt))
9450 slptr = &saved_ts_language;
9451 else if (CONSP (Vmac_ts_script_language_on_focus)
9452 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
9453 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
9454 && CONSP (saved_ts_script_language_on_focus)
9455 && EQ (XCAR (saved_ts_script_language_on_focus),
9456 XCAR (Vmac_ts_script_language_on_focus))
9457 && EQ (XCDR (saved_ts_script_language_on_focus),
9458 XCDR (Vmac_ts_script_language_on_focus)))
9460 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
9461 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
9462 slptr = &slrec;
9466 if (slptr)
9468 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9469 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
9470 kKeyboardInputMethodClass);
9471 #else
9472 err = SetDefaultInputMethod (saved_ts_component, slptr);
9473 #endif
9474 if (err == noErr)
9475 err = SetTextServiceLanguage (slptr);
9477 /* Seems to be needed on Mac OS X 10.2. */
9478 if (err == noErr)
9479 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
9482 return err;
9485 static OSStatus
9486 mac_tsm_suspend ()
9488 OSStatus err;
9489 ScriptLanguageRecord slrec, *slptr = NULL;
9491 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
9493 if (EQ (Vmac_ts_script_language_on_focus, Qt))
9495 err = GetTextServiceLanguage (&saved_ts_language);
9496 if (err == noErr)
9497 slptr = &saved_ts_language;
9499 else if (CONSP (Vmac_ts_script_language_on_focus)
9500 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
9501 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
9503 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
9504 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
9505 slptr = &slrec;
9508 if (slptr)
9510 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9511 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
9512 kKeyboardInputMethodClass);
9513 #else
9514 GetDefaultInputMethod (&saved_ts_component, slptr);
9515 #endif
9518 err = DeactivateTSMDocument (tsm_document_id);
9520 return err;
9522 #endif
9524 #if !TARGET_API_MAC_CARBON
9525 void
9526 do_apple_menu (SInt16 menu_item)
9528 Str255 item_name;
9529 SInt16 da_driver_refnum;
9531 if (menu_item == I_ABOUT)
9532 NoteAlert (ABOUT_ALERT_ID, NULL);
9533 else
9535 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
9536 da_driver_refnum = OpenDeskAcc (item_name);
9539 #endif /* !TARGET_API_MAC_CARBON */
9541 /* Handle drags in size box. Based on code contributed by Ben
9542 Mesander and IM - Window Manager A. */
9544 static void
9545 do_grow_window (w, e)
9546 WindowPtr w;
9547 const EventRecord *e;
9549 Rect limit_rect;
9550 int rows, columns, width, height;
9551 struct frame *f = mac_window_to_frame (w);
9552 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
9553 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
9554 #if TARGET_API_MAC_CARBON
9555 Rect new_rect;
9556 #else
9557 long grow_size;
9558 #endif
9560 if (size_hints->flags & PMinSize)
9562 min_width = size_hints->min_width;
9563 min_height = size_hints->min_height;
9565 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
9567 #if TARGET_API_MAC_CARBON
9568 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
9569 return;
9570 height = new_rect.bottom - new_rect.top;
9571 width = new_rect.right - new_rect.left;
9572 #else
9573 grow_size = GrowWindow (w, e->where, &limit_rect);
9574 /* see if it really changed size */
9575 if (grow_size == 0)
9576 return;
9577 height = HiWord (grow_size);
9578 width = LoWord (grow_size);
9579 #endif
9581 if (width != FRAME_PIXEL_WIDTH (f)
9582 || height != FRAME_PIXEL_HEIGHT (f))
9584 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
9585 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
9587 x_set_window_size (f, 0, columns, rows);
9592 #if TARGET_API_MAC_CARBON
9593 static Point
9594 mac_get_ideal_size (f)
9595 struct frame *f;
9597 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9598 WindowPtr w = FRAME_MAC_WINDOW (f);
9599 Point ideal_size;
9600 Rect standard_rect;
9601 int height, width, columns, rows;
9603 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
9604 ideal_size.v = dpyinfo->height;
9605 IsWindowInStandardState (w, &ideal_size, &standard_rect);
9606 /* Adjust the standard size according to character boundaries. */
9607 width = standard_rect.right - standard_rect.left;
9608 height = standard_rect.bottom - standard_rect.top;
9609 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
9610 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
9611 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
9612 ideal_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
9614 return ideal_size;
9616 #endif
9618 /* Handle clicks in zoom box. Calculation of "standard state" based
9619 on code in IM - Window Manager A and code contributed by Ben
9620 Mesander. The standard state of an Emacs window is 80-characters
9621 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9623 static void
9624 do_zoom_window (WindowPtr w, int zoom_in_or_out)
9626 Rect zoom_rect, port_rect;
9627 int width, height;
9628 struct frame *f = mac_window_to_frame (w);
9629 #if TARGET_API_MAC_CARBON
9630 Point ideal_size = mac_get_ideal_size (f);
9632 GetWindowBounds (w, kWindowContentRgn, &port_rect);
9633 if (IsWindowInStandardState (w, &ideal_size, &zoom_rect)
9634 && port_rect.left == zoom_rect.left
9635 && port_rect.top == zoom_rect.top)
9636 zoom_in_or_out = inZoomIn;
9637 else
9638 zoom_in_or_out = inZoomOut;
9640 #ifdef MAC_OS8
9641 mac_clear_window (f);
9642 #endif
9643 ZoomWindowIdeal (w, zoom_in_or_out, &ideal_size);
9644 #else /* not TARGET_API_MAC_CARBON */
9645 GrafPtr save_port;
9646 Point top_left;
9647 int w_title_height, rows;
9648 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9650 GetPort (&save_port);
9652 SetPortWindowPort (w);
9654 /* Clear window to avoid flicker. */
9655 EraseRect (&(w->portRect));
9656 if (zoom_in_or_out == inZoomOut)
9658 SetPt (&top_left, w->portRect.left, w->portRect.top);
9659 LocalToGlobal (&top_left);
9661 /* calculate height of window's title bar */
9662 w_title_height = top_left.v - 1
9663 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
9665 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9666 zoom_rect = qd.screenBits.bounds;
9667 zoom_rect.top += w_title_height;
9668 InsetRect (&zoom_rect, 8, 4); /* not too tight */
9670 zoom_rect.right = zoom_rect.left
9671 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
9673 /* Adjust the standard size according to character boundaries. */
9674 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
9675 zoom_rect.bottom =
9676 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
9678 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
9679 = zoom_rect;
9682 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
9684 SetPort (save_port);
9685 #endif /* not TARGET_API_MAC_CARBON */
9687 #if !USE_CARBON_EVENTS
9688 /* retrieve window size and update application values */
9689 #if TARGET_API_MAC_CARBON
9690 GetWindowPortBounds (w, &port_rect);
9691 #else
9692 port_rect = w->portRect;
9693 #endif
9694 height = port_rect.bottom - port_rect.top;
9695 width = port_rect.right - port_rect.left;
9697 mac_handle_size_change (f, width, height);
9698 mac_handle_origin_change (f);
9699 #endif
9702 void
9703 mac_store_apple_event (class, id, desc)
9704 Lisp_Object class, id;
9705 const AEDesc *desc;
9707 struct input_event buf;
9709 EVENT_INIT (buf);
9711 buf.kind = MAC_APPLE_EVENT;
9712 buf.x = class;
9713 buf.y = id;
9714 XSETFRAME (buf.frame_or_window,
9715 mac_focus_frame (&one_mac_display_info));
9716 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9717 is safe to use them during read_socket_hook. */
9718 buf.arg = mac_aedesc_to_lisp (desc);
9719 kbd_buffer_store_event (&buf);
9722 #if TARGET_API_MAC_CARBON
9723 static OSStatus
9724 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
9725 event, num_params, names, types)
9726 AEEventClass class;
9727 AEEventID id;
9728 Lisp_Object class_key, id_key;
9729 EventRef event;
9730 UInt32 num_params;
9731 const EventParamName *names;
9732 const EventParamType *types;
9734 OSStatus err = eventNotHandledErr;
9735 Lisp_Object binding;
9737 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
9738 if (!NILP (binding) && !EQ (binding, Qundefined))
9740 if (INTEGERP (binding))
9741 err = XINT (binding);
9742 else
9744 AppleEvent apple_event;
9745 err = create_apple_event_from_event_ref (event, num_params,
9746 names, types,
9747 &apple_event);
9748 if (err == noErr)
9750 mac_store_apple_event (class_key, id_key, &apple_event);
9751 AEDisposeDesc (&apple_event);
9752 mac_wakeup_from_rne ();
9757 return err;
9760 void
9761 mac_store_drag_event (window, mouse_pos, modifiers, desc)
9762 WindowRef window;
9763 Point mouse_pos;
9764 SInt16 modifiers;
9765 const AEDesc *desc;
9767 struct input_event buf;
9769 EVENT_INIT (buf);
9771 buf.kind = DRAG_N_DROP_EVENT;
9772 buf.modifiers = mac_to_emacs_modifiers (modifiers, 0);
9773 buf.timestamp = TickCount () * (1000 / 60);
9774 XSETINT (buf.x, mouse_pos.h);
9775 XSETINT (buf.y, mouse_pos.v);
9776 XSETFRAME (buf.frame_or_window, mac_window_to_frame (window));
9777 buf.arg = mac_aedesc_to_lisp (desc);
9778 kbd_buffer_store_event (&buf);
9780 #endif
9782 #if USE_CARBON_EVENTS
9783 static pascal OSStatus
9784 mac_handle_command_event (next_handler, event, data)
9785 EventHandlerCallRef next_handler;
9786 EventRef event;
9787 void *data;
9789 OSStatus result, err;
9790 HICommand command;
9791 static const EventParamName names[] =
9792 {kEventParamDirectObject, kEventParamKeyModifiers};
9793 static const EventParamType types[] =
9794 {typeHICommand, typeUInt32};
9795 int num_params = sizeof (names) / sizeof (names[0]);
9797 result = CallNextEventHandler (next_handler, event);
9798 if (result != eventNotHandledErr)
9799 return result;
9801 err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
9802 NULL, sizeof (HICommand), NULL, &command);
9804 if (err != noErr || command.commandID == 0)
9805 return eventNotHandledErr;
9807 /* A HI command event is mapped to an Apple event whose event class
9808 symbol is `hi-command' and event ID is its command ID. */
9809 err = mac_store_event_ref_as_apple_event (0, command.commandID,
9810 Qhi_command, Qnil,
9811 event, num_params, names, types);
9812 return err == noErr ? noErr : eventNotHandledErr;
9815 static OSStatus
9816 init_command_handler ()
9818 static const EventTypeSpec specs[] =
9819 {{kEventClassCommand, kEventCommandProcess}};
9820 static EventHandlerUPP handle_command_eventUPP = NULL;
9822 if (handle_command_eventUPP == NULL)
9823 handle_command_eventUPP = NewEventHandlerUPP (mac_handle_command_event);
9824 return InstallApplicationEventHandler (handle_command_eventUPP,
9825 GetEventTypeCount (specs), specs,
9826 NULL, NULL);
9829 static pascal OSStatus
9830 mac_handle_window_event (next_handler, event, data)
9831 EventHandlerCallRef next_handler;
9832 EventRef event;
9833 void *data;
9835 WindowPtr wp;
9836 OSStatus result, err;
9837 struct frame *f;
9838 UInt32 attributes;
9839 XSizeHints *size_hints;
9841 err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
9842 NULL, sizeof (WindowPtr), NULL, &wp);
9843 if (err != noErr)
9844 return eventNotHandledErr;
9846 f = mac_window_to_frame (wp);
9847 switch (GetEventKind (event))
9849 case kEventWindowUpdate:
9850 result = CallNextEventHandler (next_handler, event);
9851 if (result != eventNotHandledErr)
9852 return result;
9854 do_window_update (wp);
9855 return noErr;
9857 case kEventWindowGetIdealSize:
9858 result = CallNextEventHandler (next_handler, event);
9859 if (result != eventNotHandledErr)
9860 return result;
9863 Point ideal_size = mac_get_ideal_size (f);
9865 err = SetEventParameter (event, kEventParamDimensions,
9866 typeQDPoint, sizeof (Point), &ideal_size);
9867 if (err == noErr)
9868 return noErr;
9870 break;
9872 case kEventWindowBoundsChanging:
9873 result = CallNextEventHandler (next_handler, event);
9874 if (result != eventNotHandledErr)
9875 return result;
9877 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
9878 NULL, sizeof (UInt32), NULL, &attributes);
9879 if (err != noErr)
9880 break;
9882 size_hints = FRAME_SIZE_HINTS (f);
9883 if ((attributes & kWindowBoundsChangeUserResize)
9884 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
9885 == (PResizeInc | PBaseSize | PMinSize)))
9887 Rect bounds;
9888 int width, height;
9890 err = GetEventParameter (event, kEventParamCurrentBounds,
9891 typeQDRectangle, NULL, sizeof (Rect),
9892 NULL, &bounds);
9893 if (err != noErr)
9894 break;
9896 width = bounds.right - bounds.left;
9897 height = bounds.bottom - bounds.top;
9899 if (width < size_hints->min_width)
9900 width = size_hints->min_width;
9901 else
9902 width = size_hints->base_width
9903 + (int) ((width - size_hints->base_width)
9904 / (float) size_hints->width_inc + .5)
9905 * size_hints->width_inc;
9907 if (height < size_hints->min_height)
9908 height = size_hints->min_height;
9909 else
9910 height = size_hints->base_height
9911 + (int) ((height - size_hints->base_height)
9912 / (float) size_hints->height_inc + .5)
9913 * size_hints->height_inc;
9915 bounds.right = bounds.left + width;
9916 bounds.bottom = bounds.top + height;
9917 SetEventParameter (event, kEventParamCurrentBounds,
9918 typeQDRectangle, sizeof (Rect), &bounds);
9919 return noErr;
9921 break;
9923 case kEventWindowBoundsChanged:
9924 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
9925 NULL, sizeof (UInt32), NULL, &attributes);
9926 if (err != noErr)
9927 break;
9929 if (attributes & kWindowBoundsChangeSizeChanged)
9931 Rect bounds;
9933 err = GetEventParameter (event, kEventParamCurrentBounds,
9934 typeQDRectangle, NULL, sizeof (Rect),
9935 NULL, &bounds);
9936 if (err == noErr)
9938 int width, height;
9940 width = bounds.right - bounds.left;
9941 height = bounds.bottom - bounds.top;
9942 mac_handle_size_change (f, width, height);
9943 mac_wakeup_from_rne ();
9947 if (attributes & kWindowBoundsChangeOriginChanged)
9948 mac_handle_origin_change (f);
9950 return noErr;
9952 case kEventWindowShown:
9953 case kEventWindowHidden:
9954 case kEventWindowExpanded:
9955 case kEventWindowCollapsed:
9956 result = CallNextEventHandler (next_handler, event);
9958 mac_handle_visibility_change (f);
9959 return noErr;
9961 break;
9963 case kEventWindowClose:
9964 result = CallNextEventHandler (next_handler, event);
9966 struct input_event buf;
9968 EVENT_INIT (buf);
9969 buf.kind = DELETE_WINDOW_EVENT;
9970 XSETFRAME (buf.frame_or_window, f);
9971 buf.arg = Qnil;
9972 kbd_buffer_store_event (&buf);
9974 return noErr;
9976 #ifdef MAC_OSX
9977 case kEventWindowToolbarSwitchMode:
9978 result = CallNextEventHandler (next_handler, event);
9980 static const EventParamName names[] = {kEventParamDirectObject,
9981 kEventParamWindowMouseLocation,
9982 kEventParamKeyModifiers,
9983 kEventParamMouseButton,
9984 kEventParamClickCount,
9985 kEventParamMouseChord};
9986 static const EventParamType types[] = {typeWindowRef,
9987 typeQDPoint,
9988 typeUInt32,
9989 typeMouseButton,
9990 typeUInt32,
9991 typeUInt32};
9992 int num_params = sizeof (names) / sizeof (names[0]);
9994 err = mac_store_event_ref_as_apple_event (0, 0,
9995 Qwindow,
9996 Qtoolbar_switch_mode,
9997 event, num_params,
9998 names, types);
10000 return err == noErr ? noErr : result;
10001 #endif
10003 #if USE_MAC_TSM
10004 case kEventWindowFocusAcquired:
10005 result = CallNextEventHandler (next_handler, event);
10006 err = mac_tsm_resume ();
10007 return err == noErr ? noErr : result;
10009 case kEventWindowFocusRelinquish:
10010 result = CallNextEventHandler (next_handler, event);
10011 err = mac_tsm_suspend ();
10012 return err == noErr ? noErr : result;
10013 #endif
10016 return eventNotHandledErr;
10019 static pascal OSStatus
10020 mac_handle_mouse_event (next_handler, event, data)
10021 EventHandlerCallRef next_handler;
10022 EventRef event;
10023 void *data;
10025 OSStatus result, err;
10027 switch (GetEventKind (event))
10029 case kEventMouseWheelMoved:
10031 WindowPtr wp;
10032 struct frame *f;
10033 EventMouseWheelAxis axis;
10034 SInt32 delta;
10035 Point point;
10037 result = CallNextEventHandler (next_handler, event);
10038 if (result != eventNotHandledErr || read_socket_inev == NULL)
10039 return result;
10041 err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
10042 NULL, sizeof (WindowRef), NULL, &wp);
10043 if (err != noErr)
10044 break;
10046 f = mac_window_to_frame (wp);
10047 if (f != mac_focus_frame (&one_mac_display_info))
10048 break;
10050 err = GetEventParameter (event, kEventParamMouseWheelAxis,
10051 typeMouseWheelAxis, NULL,
10052 sizeof (EventMouseWheelAxis), NULL, &axis);
10053 if (err != noErr || axis != kEventMouseWheelAxisY)
10054 break;
10056 err = GetEventParameter (event, kEventParamMouseLocation,
10057 typeQDPoint, NULL, sizeof (Point),
10058 NULL, &point);
10059 if (err != noErr)
10060 break;
10062 SetPortWindowPort (wp);
10063 GlobalToLocal (&point);
10064 if (point.h < 0 || point.v < 0
10065 || EQ (window_from_coordinates (f, point.h, point.v, 0, 0, 0, 1),
10066 f->tool_bar_window))
10067 break;
10069 err = GetEventParameter (event, kEventParamMouseWheelDelta,
10070 typeSInt32, NULL, sizeof (SInt32),
10071 NULL, &delta);
10072 if (err != noErr)
10073 break;
10075 read_socket_inev->kind = WHEEL_EVENT;
10076 read_socket_inev->code = 0;
10077 read_socket_inev->modifiers =
10078 (mac_event_to_emacs_modifiers (event)
10079 | ((delta < 0) ? down_modifier : up_modifier));
10080 XSETINT (read_socket_inev->x, point.h);
10081 XSETINT (read_socket_inev->y, point.v);
10082 XSETFRAME (read_socket_inev->frame_or_window, f);
10084 return noErr;
10086 break;
10088 default:
10089 break;
10092 return eventNotHandledErr;
10095 #if USE_MAC_FONT_PANEL
10096 static pascal OSStatus
10097 mac_handle_font_event (next_handler, event, data)
10098 EventHandlerCallRef next_handler;
10099 EventRef event;
10100 void *data;
10102 OSStatus result, err;
10103 Lisp_Object id_key;
10104 int num_params;
10105 const EventParamName *names;
10106 const EventParamType *types;
10107 static const EventParamName names_sel[] = {kEventParamATSUFontID,
10108 kEventParamATSUFontSize,
10109 kEventParamFMFontFamily,
10110 kEventParamFMFontSize,
10111 kEventParamFontColor};
10112 static const EventParamType types_sel[] = {typeATSUFontID,
10113 typeATSUSize,
10114 typeFMFontFamily,
10115 typeFMFontSize,
10116 typeFontColor};
10118 result = CallNextEventHandler (next_handler, event);
10119 if (result != eventNotHandledErr)
10120 return result;
10122 switch (GetEventKind (event))
10124 case kEventFontPanelClosed:
10125 id_key = Qpanel_closed;
10126 num_params = 0;
10127 names = NULL;
10128 types = NULL;
10129 break;
10131 case kEventFontSelection:
10132 id_key = Qselection;
10133 num_params = sizeof (names_sel) / sizeof (names_sel[0]);
10134 names = names_sel;
10135 types = types_sel;
10136 break;
10139 err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
10140 event, num_params,
10141 names, types);
10143 return err == noErr ? noErr : eventNotHandledErr;
10145 #endif
10147 #if USE_MAC_TSM
10148 static pascal OSStatus
10149 mac_handle_text_input_event (next_handler, event, data)
10150 EventHandlerCallRef next_handler;
10151 EventRef event;
10152 void *data;
10154 OSStatus result, err = noErr;
10155 Lisp_Object id_key = Qnil;
10156 int num_params;
10157 const EventParamName *names;
10158 const EventParamType *types;
10159 static UInt32 seqno_uaia = 0;
10160 static const EventParamName names_uaia[] =
10161 {kEventParamTextInputSendComponentInstance,
10162 kEventParamTextInputSendRefCon,
10163 kEventParamTextInputSendSLRec,
10164 kEventParamTextInputSendFixLen,
10165 kEventParamTextInputSendText,
10166 kEventParamTextInputSendUpdateRng,
10167 kEventParamTextInputSendHiliteRng,
10168 kEventParamTextInputSendClauseRng,
10169 kEventParamTextInputSendPinRng,
10170 kEventParamTextInputSendTextServiceEncoding,
10171 kEventParamTextInputSendTextServiceMacEncoding,
10172 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
10173 static const EventParamType types_uaia[] =
10174 {typeComponentInstance,
10175 typeLongInteger,
10176 typeIntlWritingCode,
10177 typeLongInteger,
10178 #ifdef MAC_OSX
10179 typeUnicodeText,
10180 #else
10181 typeChar,
10182 #endif
10183 typeTextRangeArray,
10184 typeTextRangeArray,
10185 typeOffsetArray,
10186 typeTextRange,
10187 typeUInt32,
10188 typeUInt32,
10189 typeUInt32};
10190 static const EventParamName names_ufke[] =
10191 {kEventParamTextInputSendComponentInstance,
10192 kEventParamTextInputSendRefCon,
10193 kEventParamTextInputSendSLRec,
10194 kEventParamTextInputSendText};
10195 static const EventParamType types_ufke[] =
10196 {typeComponentInstance,
10197 typeLongInteger,
10198 typeIntlWritingCode,
10199 typeUnicodeText};
10201 result = CallNextEventHandler (next_handler, event);
10203 switch (GetEventKind (event))
10205 case kEventTextInputUpdateActiveInputArea:
10206 id_key = Qupdate_active_input_area;
10207 num_params = sizeof (names_uaia) / sizeof (names_uaia[0]);
10208 names = names_uaia;
10209 types = types_uaia;
10210 SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
10211 typeUInt32, sizeof (UInt32), &seqno_uaia);
10212 seqno_uaia++;
10213 break;
10215 case kEventTextInputUnicodeForKeyEvent:
10217 EventRef kbd_event;
10218 UInt32 actual_size, modifiers, key_code;
10220 err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent,
10221 typeEventRef, NULL, sizeof (EventRef), NULL,
10222 &kbd_event);
10223 if (err == noErr)
10224 err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
10225 typeUInt32, NULL,
10226 sizeof (UInt32), NULL, &modifiers);
10227 if (err == noErr)
10228 err = GetEventParameter (kbd_event, kEventParamKeyCode,
10229 typeUInt32, NULL, sizeof (UInt32),
10230 NULL, &key_code);
10231 if (err == noErr && mac_mapped_modifiers (modifiers, key_code))
10232 /* There're mapped modifier keys. Process it in
10233 XTread_socket. */
10234 return eventNotHandledErr;
10235 if (err == noErr)
10236 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
10237 typeUnicodeText, NULL, 0, &actual_size,
10238 NULL);
10239 if (err == noErr && actual_size == sizeof (UniChar))
10241 UniChar code;
10243 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
10244 typeUnicodeText, NULL,
10245 sizeof (UniChar), NULL, &code);
10246 if (err == noErr && code < 0x80)
10248 /* ASCII character. Process it in XTread_socket. */
10249 if (read_socket_inev && code >= 0x20 && code <= 0x7e
10250 && !(key_code <= 0x7f
10251 && keycode_to_xkeysym_table [key_code]))
10253 struct frame *f = mac_focus_frame (&one_mac_display_info);
10255 read_socket_inev->kind = ASCII_KEYSTROKE_EVENT;
10256 read_socket_inev->code = code;
10257 read_socket_inev->modifiers =
10258 mac_to_emacs_modifiers (modifiers, 0);
10259 read_socket_inev->modifiers |=
10260 (extra_keyboard_modifiers
10261 & (meta_modifier | alt_modifier
10262 | hyper_modifier | super_modifier));
10263 XSETFRAME (read_socket_inev->frame_or_window, f);
10265 return eventNotHandledErr;
10269 /* Non-ASCII keystrokes without mapped modifiers are processed
10270 at the Lisp level. */
10271 id_key = Qunicode_for_key_event;
10272 num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
10273 names = names_ufke;
10274 types = types_ufke;
10275 break;
10277 case kEventTextInputOffsetToPos:
10279 struct frame *f;
10280 struct window *w;
10281 Point p;
10283 if (!OVERLAYP (Vmac_ts_active_input_overlay))
10284 return eventNotHandledErr;
10286 /* Strictly speaking, this is not always correct because
10287 previous events may change some states about display. */
10288 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
10290 if (!WINDOWP (echo_area_window))
10291 return eventNotHandledErr;
10293 /* Active input area is displayed in the echo area. */
10294 w = XWINDOW (echo_area_window);
10295 f = WINDOW_XFRAME (w);
10297 else
10299 /* Active input area is displayed around the current point. */
10300 f = SELECTED_FRAME ();
10301 w = XWINDOW (f->selected_window);
10304 p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
10305 + WINDOW_LEFT_FRINGE_WIDTH (w));
10306 p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
10307 + FONT_BASE (FRAME_FONT (f)));
10308 SetPortWindowPort (FRAME_MAC_WINDOW (f));
10309 LocalToGlobal (&p);
10310 err = SetEventParameter (event, kEventParamTextInputReplyPoint,
10311 typeQDPoint, sizeof (typeQDPoint), &p);
10313 break;
10315 default:
10316 abort ();
10319 if (!NILP (id_key))
10320 err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
10321 event, num_params,
10322 names, types);
10324 return err == noErr ? noErr : result;
10326 #endif
10328 #ifdef MAC_OSX
10329 OSStatus
10330 mac_store_service_event (event)
10331 EventRef event;
10333 OSStatus err;
10334 Lisp_Object id_key;
10335 int num_params;
10336 const EventParamName *names;
10337 const EventParamType *types;
10338 static const EventParamName names_pfm[] =
10339 {kEventParamServiceMessageName, kEventParamServiceUserData};
10340 static const EventParamType types_pfm[] =
10341 {typeCFStringRef, typeCFStringRef};
10343 switch (GetEventKind (event))
10345 case kEventServicePaste:
10346 id_key = Qpaste;
10347 num_params = 0;
10348 names = NULL;
10349 types = NULL;
10350 break;
10352 case kEventServicePerform:
10353 id_key = Qperform;
10354 num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
10355 names = names_pfm;
10356 types = types_pfm;
10357 break;
10359 default:
10360 abort ();
10363 err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
10364 event, num_params,
10365 names, types);
10367 return err;
10369 #endif /* MAC_OSX */
10370 #endif /* USE_CARBON_EVENTS */
10373 OSStatus
10374 install_window_handler (window)
10375 WindowPtr window;
10377 OSStatus err = noErr;
10378 #if USE_CARBON_EVENTS
10379 static const EventTypeSpec specs_window[] =
10380 {{kEventClassWindow, kEventWindowUpdate},
10381 {kEventClassWindow, kEventWindowGetIdealSize},
10382 {kEventClassWindow, kEventWindowBoundsChanging},
10383 {kEventClassWindow, kEventWindowBoundsChanged},
10384 {kEventClassWindow, kEventWindowShown},
10385 {kEventClassWindow, kEventWindowHidden},
10386 {kEventClassWindow, kEventWindowExpanded},
10387 {kEventClassWindow, kEventWindowCollapsed},
10388 {kEventClassWindow, kEventWindowClose},
10389 #ifdef MAC_OSX
10390 {kEventClassWindow, kEventWindowToolbarSwitchMode},
10391 #endif
10392 #if USE_MAC_TSM
10393 {kEventClassWindow, kEventWindowFocusAcquired},
10394 {kEventClassWindow, kEventWindowFocusRelinquish},
10395 #endif
10397 static const EventTypeSpec specs_mouse[] =
10398 {{kEventClassMouse, kEventMouseWheelMoved}};
10399 static EventHandlerUPP handle_window_eventUPP = NULL;
10400 static EventHandlerUPP handle_mouse_eventUPP = NULL;
10401 #if USE_MAC_FONT_PANEL
10402 static const EventTypeSpec specs_font[] =
10403 {{kEventClassFont, kEventFontPanelClosed},
10404 {kEventClassFont, kEventFontSelection}};
10405 static EventHandlerUPP handle_font_eventUPP = NULL;
10406 #endif
10407 #if USE_MAC_TSM
10408 static const EventTypeSpec specs_text_input[] =
10409 {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
10410 {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
10411 {kEventClassTextInput, kEventTextInputOffsetToPos}};
10412 static EventHandlerUPP handle_text_input_eventUPP = NULL;
10413 #endif
10415 if (handle_window_eventUPP == NULL)
10416 handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
10417 if (handle_mouse_eventUPP == NULL)
10418 handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
10419 #if USE_MAC_FONT_PANEL
10420 if (handle_font_eventUPP == NULL)
10421 handle_font_eventUPP = NewEventHandlerUPP (mac_handle_font_event);
10422 #endif
10423 #if USE_MAC_TSM
10424 if (handle_text_input_eventUPP == NULL)
10425 handle_text_input_eventUPP =
10426 NewEventHandlerUPP (mac_handle_text_input_event);
10427 #endif
10428 err = InstallWindowEventHandler (window, handle_window_eventUPP,
10429 GetEventTypeCount (specs_window),
10430 specs_window, NULL, NULL);
10431 if (err == noErr)
10432 err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
10433 GetEventTypeCount (specs_mouse),
10434 specs_mouse, NULL, NULL);
10435 #if USE_MAC_FONT_PANEL
10436 if (err == noErr)
10437 err = InstallWindowEventHandler (window, handle_font_eventUPP,
10438 GetEventTypeCount (specs_font),
10439 specs_font, NULL, NULL);
10440 #endif
10441 #if USE_MAC_TSM
10442 if (err == noErr)
10443 err = InstallWindowEventHandler (window, handle_text_input_eventUPP,
10444 GetEventTypeCount (specs_text_input),
10445 specs_text_input, window, NULL);
10446 #endif
10447 #endif
10448 if (err == noErr)
10449 err = install_drag_handler (window);
10450 if (err == noErr)
10451 err = install_menu_target_item_handler (window);
10453 return err;
10456 void
10457 remove_window_handler (window)
10458 WindowPtr window;
10460 remove_drag_handler (window);
10464 static pascal void
10465 mac_handle_dm_notification (event)
10466 AppleEvent *event;
10468 mac_screen_config_changed = 1;
10471 static OSErr
10472 init_dm_notification_handler ()
10474 OSErr err;
10475 static DMNotificationUPP handle_dm_notificationUPP = NULL;
10476 ProcessSerialNumber psn;
10478 if (handle_dm_notificationUPP == NULL)
10479 handle_dm_notificationUPP =
10480 NewDMNotificationUPP (mac_handle_dm_notification);
10482 err = GetCurrentProcess (&psn);
10483 if (err == noErr)
10484 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
10486 return err;
10489 static void
10490 mac_get_screen_info (dpyinfo)
10491 struct mac_display_info *dpyinfo;
10493 #ifdef MAC_OSX
10494 /* HasDepth returns true if it is possible to have a 32 bit display,
10495 but this may not be what is actually used. Mac OSX can do better. */
10496 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
10497 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
10499 CGDisplayErr err;
10500 CGDisplayCount ndisps;
10501 CGDirectDisplayID *displays;
10503 err = CGGetActiveDisplayList (0, NULL, &ndisps);
10504 if (err == noErr)
10506 displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
10507 err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
10509 if (err == noErr)
10511 CGRect bounds = CGRectZero;
10513 while (ndisps-- > 0)
10514 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
10515 dpyinfo->height = CGRectGetHeight (bounds);
10516 dpyinfo->width = CGRectGetWidth (bounds);
10518 else
10520 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
10521 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
10524 #else /* !MAC_OSX */
10526 GDHandle gdh = GetMainDevice ();
10527 Rect rect = (**gdh).gdRect;
10529 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
10530 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
10531 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
10532 break;
10534 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
10535 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
10536 UnionRect (&rect, &(**gdh).gdRect, &rect);
10538 dpyinfo->height = rect.bottom - rect.top;
10539 dpyinfo->width = rect.right - rect.left;
10541 #endif /* !MAC_OSX */
10545 #if __profile__
10546 void
10547 profiler_exit_proc ()
10549 ProfilerDump ("\pEmacs.prof");
10550 ProfilerTerm ();
10552 #endif
10554 /* These few functions implement Emacs as a normal Mac application
10555 (almost): set up the heap and the Toolbox, handle necessary system
10556 events plus a few simple menu events. They also set up Emacs's
10557 access to functions defined in the rest of this file. Emacs uses
10558 function hooks to perform all its terminal I/O. A complete list of
10559 these functions appear in termhooks.h. For what they do, read the
10560 comments there and see also w32term.c and xterm.c. What's
10561 noticeably missing here is the event loop, which is normally
10562 present in most Mac application. After performing the necessary
10563 Mac initializations, main passes off control to emacs_main
10564 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10565 (defined further below) to read input. This is where
10566 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10568 #ifdef MAC_OS8
10569 #undef main
10571 main (void)
10573 #if __profile__ /* is the profiler on? */
10574 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
10575 exit(1);
10576 #endif
10578 #if __MWERKS__
10579 /* set creator and type for files created by MSL */
10580 _fcreator = MAC_EMACS_CREATOR_CODE;
10581 _ftype = 'TEXT';
10582 #endif
10584 do_init_managers ();
10586 do_get_menus ();
10588 #ifndef USE_LSB_TAG
10589 do_check_ram_size ();
10590 #endif
10592 init_emacs_passwd_dir ();
10594 init_environ ();
10596 init_coercion_handler ();
10598 initialize_applescript ();
10600 init_apple_event_handler ();
10602 init_dm_notification_handler ();
10605 char **argv;
10606 int argc = 0;
10608 /* set up argv array from STR# resource */
10609 get_string_list (&argv, ARGV_STRING_LIST_ID);
10610 while (argv[argc])
10611 argc++;
10613 /* free up AppleScript resources on exit */
10614 atexit (terminate_applescript);
10616 #if __profile__ /* is the profiler on? */
10617 atexit (profiler_exit_proc);
10618 #endif
10620 /* 3rd param "envp" never used in emacs_main */
10621 (void) emacs_main (argc, argv, 0);
10624 /* Never reached - real exit in Fkill_emacs */
10625 return 0;
10627 #endif
10629 #if !USE_CARBON_EVENTS
10630 static RgnHandle mouse_region = NULL;
10632 Boolean
10633 mac_wait_next_event (er, sleep_time, dequeue)
10634 EventRecord *er;
10635 UInt32 sleep_time;
10636 Boolean dequeue;
10638 static EventRecord er_buf = {nullEvent};
10639 UInt32 target_tick, current_tick;
10640 EventMask event_mask;
10642 if (mouse_region == NULL)
10643 mouse_region = NewRgn ();
10645 event_mask = everyEvent;
10646 if (!mac_ready_for_apple_events)
10647 event_mask -= highLevelEventMask;
10649 current_tick = TickCount ();
10650 target_tick = current_tick + sleep_time;
10652 if (er_buf.what == nullEvent)
10653 while (!WaitNextEvent (event_mask, &er_buf,
10654 target_tick - current_tick, mouse_region))
10656 current_tick = TickCount ();
10657 if (target_tick <= current_tick)
10658 return false;
10661 *er = er_buf;
10662 if (dequeue)
10663 er_buf.what = nullEvent;
10664 return true;
10666 #endif /* not USE_CARBON_EVENTS */
10668 #if TARGET_API_MAC_CARBON
10669 OSStatus
10670 mac_post_mouse_moved_event ()
10672 EventRef event = NULL;
10673 OSStatus err;
10675 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
10676 kEventAttributeNone, &event);
10677 if (err == noErr)
10679 Point mouse_pos;
10681 GetGlobalMouse (&mouse_pos);
10682 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
10683 sizeof (Point), &mouse_pos);
10685 if (err == noErr)
10687 UInt32 modifiers = GetCurrentKeyModifiers ();
10689 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
10690 sizeof (UInt32), &modifiers);
10692 if (err == noErr)
10693 err = PostEventToQueue (GetCurrentEventQueue (), event,
10694 kEventPriorityStandard);
10695 if (event)
10696 ReleaseEvent (event);
10698 return err;
10701 static void
10702 mac_set_unicode_keystroke_event (code, buf)
10703 UniChar code;
10704 struct input_event *buf;
10706 int charset_id, c1, c2;
10708 if (code < 0x80)
10710 buf->kind = ASCII_KEYSTROKE_EVENT;
10711 buf->code = code;
10713 else if (code < 0x100)
10715 if (code < 0xA0)
10716 charset_id = CHARSET_8_BIT_CONTROL;
10717 else
10718 charset_id = charset_latin_iso8859_1;
10719 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10720 buf->code = MAKE_CHAR (charset_id, code, 0);
10722 else
10724 if (code < 0x2500)
10725 charset_id = charset_mule_unicode_0100_24ff,
10726 code -= 0x100;
10727 else if (code < 0x33FF)
10728 charset_id = charset_mule_unicode_2500_33ff,
10729 code -= 0x2500;
10730 else if (code >= 0xE000)
10731 charset_id = charset_mule_unicode_e000_ffff,
10732 code -= 0xE000;
10733 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
10734 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10735 buf->code = MAKE_CHAR (charset_id, c1, c2);
10738 #endif
10740 /* Emacs calls this whenever it wants to read an input event from the
10741 user. */
10743 XTread_socket (sd, expected, hold_quit)
10744 int sd, expected;
10745 struct input_event *hold_quit;
10747 struct input_event inev;
10748 int count = 0;
10749 #if USE_CARBON_EVENTS
10750 EventRef eventRef;
10751 EventTargetRef toolbox_dispatcher;
10752 #endif
10753 EventRecord er;
10754 struct mac_display_info *dpyinfo = &one_mac_display_info;
10756 if (interrupt_input_blocked)
10758 interrupt_input_pending = 1;
10759 return -1;
10762 interrupt_input_pending = 0;
10763 BLOCK_INPUT;
10765 /* So people can tell when we have read the available input. */
10766 input_signal_count++;
10768 ++handling_signal;
10770 #if USE_CARBON_EVENTS
10771 toolbox_dispatcher = GetEventDispatcherTarget ();
10773 while (
10774 #if USE_CG_DRAWING
10775 mac_prepare_for_quickdraw (NULL),
10776 #endif
10777 !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
10778 kEventRemoveFromQueue, &eventRef))
10779 #else /* !USE_CARBON_EVENTS */
10780 while (mac_wait_next_event (&er, 0, true))
10781 #endif /* !USE_CARBON_EVENTS */
10783 int do_help = 0;
10784 struct frame *f;
10785 unsigned long timestamp;
10787 EVENT_INIT (inev);
10788 inev.kind = NO_EVENT;
10789 inev.arg = Qnil;
10791 #if USE_CARBON_EVENTS
10792 timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
10793 #else
10794 timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
10795 #endif
10797 #if USE_CARBON_EVENTS
10798 /* Handle new events */
10799 if (!mac_convert_event_ref (eventRef, &er))
10801 /* There used to be a handler for the kEventMouseWheelMoved
10802 event here. But as of Mac OS X 10.4, this kind of event
10803 is not directly posted to the main event queue by
10804 two-finger scrolling on the trackpad. Instead, some
10805 private event is posted and it is converted to a wheel
10806 event by the default handler for the application target.
10807 The converted one can be received by a Carbon event
10808 handler installed on a window target. */
10809 read_socket_inev = &inev;
10810 SendEventToEventTarget (eventRef, toolbox_dispatcher);
10811 read_socket_inev = NULL;
10813 else
10814 #endif /* USE_CARBON_EVENTS */
10815 switch (er.what)
10817 case mouseDown:
10818 case mouseUp:
10820 WindowPtr window_ptr;
10821 ControlPartCode part_code;
10822 int tool_bar_p = 0;
10824 #if USE_CARBON_EVENTS
10825 /* This is needed to send mouse events like aqua window
10826 buttons to the correct handler. */
10827 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10828 != eventNotHandledErr)
10829 break;
10830 #endif
10831 last_mouse_glyph_frame = 0;
10833 if (dpyinfo->grabbed && last_mouse_frame
10834 && FRAME_LIVE_P (last_mouse_frame))
10836 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
10837 part_code = inContent;
10839 else
10841 part_code = FindWindow (er.where, &window_ptr);
10842 if (tip_window && window_ptr == tip_window)
10844 HideWindow (tip_window);
10845 part_code = FindWindow (er.where, &window_ptr);
10849 if (er.what != mouseDown &&
10850 (part_code != inContent || dpyinfo->grabbed == 0))
10851 break;
10853 switch (part_code)
10855 case inMenuBar:
10856 f = mac_focus_frame (dpyinfo);
10857 saved_menu_event_location = er.where;
10858 inev.kind = MENU_BAR_ACTIVATE_EVENT;
10859 XSETFRAME (inev.frame_or_window, f);
10860 break;
10862 case inContent:
10863 if (
10864 #if TARGET_API_MAC_CARBON
10865 FrontNonFloatingWindow ()
10866 #else
10867 FrontWindow ()
10868 #endif
10869 != window_ptr
10870 || (mac_window_to_frame (window_ptr)
10871 != dpyinfo->x_focus_frame))
10872 SelectWindow (window_ptr);
10873 else
10875 ControlPartCode control_part_code;
10876 ControlHandle ch;
10877 Point mouse_loc = er.where;
10878 #ifdef MAC_OSX
10879 ControlKind control_kind;
10880 #endif
10882 f = mac_window_to_frame (window_ptr);
10883 /* convert to local coordinates of new window */
10884 SetPortWindowPort (window_ptr);
10886 GlobalToLocal (&mouse_loc);
10887 #if TARGET_API_MAC_CARBON
10888 ch = FindControlUnderMouse (mouse_loc, window_ptr,
10889 &control_part_code);
10890 #ifdef MAC_OSX
10891 if (ch)
10892 GetControlKind (ch, &control_kind);
10893 #endif
10894 #else
10895 control_part_code = FindControl (mouse_loc, window_ptr,
10896 &ch);
10897 #endif
10899 #if USE_CARBON_EVENTS
10900 inev.code = mac_get_mouse_btn (eventRef);
10901 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
10902 #else
10903 inev.code = mac_get_emulated_btn (er.modifiers);
10904 inev.modifiers = mac_to_emacs_modifiers (er.modifiers, 0);
10905 #endif
10906 XSETINT (inev.x, mouse_loc.h);
10907 XSETINT (inev.y, mouse_loc.v);
10909 if ((dpyinfo->grabbed && tracked_scroll_bar)
10910 || (ch != 0
10911 #ifndef USE_TOOLKIT_SCROLL_BARS
10912 /* control_part_code becomes kControlNoPart if
10913 a progress indicator is clicked. */
10914 && control_part_code != kControlNoPart
10915 #else /* USE_TOOLKIT_SCROLL_BARS */
10916 #ifdef MAC_OSX
10917 && control_kind.kind == kControlKindScrollBar
10918 #endif /* MAC_OSX */
10919 #endif /* USE_TOOLKIT_SCROLL_BARS */
10922 struct scroll_bar *bar;
10924 if (dpyinfo->grabbed && tracked_scroll_bar)
10926 bar = tracked_scroll_bar;
10927 #ifndef USE_TOOLKIT_SCROLL_BARS
10928 control_part_code = kControlIndicatorPart;
10929 #endif
10931 else
10932 bar = (struct scroll_bar *) GetControlReference (ch);
10933 #ifdef USE_TOOLKIT_SCROLL_BARS
10934 /* Make the "Ctrl-Mouse-2 splits window" work
10935 for toolkit scroll bars. */
10936 if (inev.modifiers & ctrl_modifier)
10937 x_scroll_bar_handle_click (bar, control_part_code,
10938 &er, &inev);
10939 else if (er.what == mouseDown)
10940 x_scroll_bar_handle_press (bar, control_part_code,
10941 mouse_loc, &inev);
10942 else
10943 x_scroll_bar_handle_release (bar, &inev);
10944 #else /* not USE_TOOLKIT_SCROLL_BARS */
10945 x_scroll_bar_handle_click (bar, control_part_code,
10946 &er, &inev);
10947 if (er.what == mouseDown
10948 && control_part_code == kControlIndicatorPart)
10949 tracked_scroll_bar = bar;
10950 else
10951 tracked_scroll_bar = NULL;
10952 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10954 else
10956 Lisp_Object window;
10957 int x = mouse_loc.h;
10958 int y = mouse_loc.v;
10960 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
10961 if (EQ (window, f->tool_bar_window))
10963 if (er.what == mouseDown)
10964 handle_tool_bar_click (f, x, y, 1, 0);
10965 else
10966 handle_tool_bar_click (f, x, y, 0,
10967 inev.modifiers);
10968 tool_bar_p = 1;
10970 else
10972 XSETFRAME (inev.frame_or_window, f);
10973 inev.kind = MOUSE_CLICK_EVENT;
10977 if (er.what == mouseDown)
10979 dpyinfo->grabbed |= (1 << inev.code);
10980 last_mouse_frame = f;
10982 if (!tool_bar_p)
10983 last_tool_bar_item = -1;
10985 else
10987 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
10988 /* If a button is released though it was not
10989 previously pressed, that would be because
10990 of multi-button emulation. */
10991 dpyinfo->grabbed = 0;
10992 else
10993 dpyinfo->grabbed &= ~(1 << inev.code);
10996 /* Ignore any mouse motion that happened before
10997 this event; any subsequent mouse-movement Emacs
10998 events should reflect only motion after the
10999 ButtonPress. */
11000 if (f != 0)
11001 f->mouse_moved = 0;
11003 #ifdef USE_TOOLKIT_SCROLL_BARS
11004 if (inev.kind == MOUSE_CLICK_EVENT
11005 || (inev.kind == SCROLL_BAR_CLICK_EVENT
11006 && (inev.modifiers & ctrl_modifier)))
11007 #endif
11008 switch (er.what)
11010 case mouseDown:
11011 inev.modifiers |= down_modifier;
11012 break;
11013 case mouseUp:
11014 inev.modifiers |= up_modifier;
11015 break;
11018 break;
11020 case inDrag:
11021 #if TARGET_API_MAC_CARBON
11022 case inProxyIcon:
11023 if (IsWindowPathSelectClick (window_ptr, &er))
11025 WindowPathSelect (window_ptr, NULL, NULL);
11026 break;
11028 if (part_code == inProxyIcon
11029 && (TrackWindowProxyDrag (window_ptr, er.where)
11030 != errUserWantsToDragWindow))
11031 break;
11032 DragWindow (window_ptr, er.where, NULL);
11033 #else /* not TARGET_API_MAC_CARBON */
11034 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
11035 #endif /* not TARGET_API_MAC_CARBON */
11036 /* Update the frame parameters. */
11037 #if !USE_CARBON_EVENTS
11039 struct frame *f = mac_window_to_frame (window_ptr);
11041 if (f && !f->async_iconified)
11042 mac_handle_origin_change (f);
11044 #endif
11045 break;
11047 case inGoAway:
11048 if (TrackGoAway (window_ptr, er.where))
11050 inev.kind = DELETE_WINDOW_EVENT;
11051 XSETFRAME (inev.frame_or_window,
11052 mac_window_to_frame (window_ptr));
11054 break;
11056 /* window resize handling added --ben */
11057 case inGrow:
11058 do_grow_window (window_ptr, &er);
11059 break;
11061 /* window zoom handling added --ben */
11062 case inZoomIn:
11063 case inZoomOut:
11064 if (TrackBox (window_ptr, er.where, part_code))
11065 do_zoom_window (window_ptr, part_code);
11066 break;
11068 default:
11069 break;
11072 break;
11074 case updateEvt:
11075 #if USE_CARBON_EVENTS
11076 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
11077 != eventNotHandledErr)
11078 break;
11079 #else
11080 do_window_update ((WindowPtr) er.message);
11081 #endif
11082 break;
11084 case osEvt:
11085 #if USE_CARBON_EVENTS
11086 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
11087 != eventNotHandledErr)
11088 break;
11089 #endif
11090 switch ((er.message >> 24) & 0x000000FF)
11092 case suspendResumeMessage:
11093 #if USE_MAC_TSM
11094 if (er.message & resumeFlag)
11095 mac_tsm_resume ();
11096 else
11097 mac_tsm_suspend ();
11098 #endif
11099 break;
11101 case mouseMovedMessage:
11102 #if !USE_CARBON_EVENTS
11103 SetRectRgn (mouse_region, er.where.h, er.where.v,
11104 er.where.h + 1, er.where.v + 1);
11105 #endif
11106 previous_help_echo_string = help_echo_string;
11107 help_echo_string = Qnil;
11109 if (dpyinfo->grabbed && last_mouse_frame
11110 && FRAME_LIVE_P (last_mouse_frame))
11111 f = last_mouse_frame;
11112 else
11113 f = dpyinfo->x_focus_frame;
11115 if (dpyinfo->mouse_face_hidden)
11117 dpyinfo->mouse_face_hidden = 0;
11118 clear_mouse_face (dpyinfo);
11121 if (f)
11123 WindowPtr wp = FRAME_MAC_WINDOW (f);
11124 Point mouse_pos = er.where;
11126 SetPortWindowPort (wp);
11128 GlobalToLocal (&mouse_pos);
11130 if (dpyinfo->grabbed && tracked_scroll_bar)
11131 #ifdef USE_TOOLKIT_SCROLL_BARS
11132 x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
11133 mouse_pos, &inev);
11134 #else /* not USE_TOOLKIT_SCROLL_BARS */
11135 x_scroll_bar_note_movement (tracked_scroll_bar,
11136 mouse_pos.v
11137 - XINT (tracked_scroll_bar->top),
11138 er.when * (1000 / 60));
11139 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11140 else
11142 /* Generate SELECT_WINDOW_EVENTs when needed. */
11143 if (!NILP (Vmouse_autoselect_window))
11145 Lisp_Object window;
11147 window = window_from_coordinates (f,
11148 mouse_pos.h,
11149 mouse_pos.v,
11150 0, 0, 0, 0);
11152 /* Window will be selected only when it is
11153 not selected now and last mouse movement
11154 event was not in it. Minibuffer window
11155 will be selected only when it is active. */
11156 if (WINDOWP (window)
11157 && !EQ (window, last_window)
11158 && !EQ (window, selected_window)
11159 /* For click-to-focus window managers
11160 create event iff we don't leave the
11161 selected frame. */
11162 && (focus_follows_mouse
11163 || (EQ (XWINDOW (window)->frame,
11164 XWINDOW (selected_window)->frame))))
11166 inev.kind = SELECT_WINDOW_EVENT;
11167 inev.frame_or_window = window;
11170 last_window=window;
11172 if (!note_mouse_movement (f, &mouse_pos))
11173 help_echo_string = previous_help_echo_string;
11177 /* If the contents of the global variable
11178 help_echo_string has changed, generate a
11179 HELP_EVENT. */
11180 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
11181 do_help = 1;
11182 break;
11184 break;
11186 case activateEvt:
11188 WindowPtr window_ptr = (WindowPtr) er.message;
11190 #if USE_CARBON_EVENTS
11191 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
11192 != eventNotHandledErr)
11193 break;
11194 #endif
11195 if (window_ptr == tip_window)
11197 HideWindow (tip_window);
11198 break;
11201 if (!is_emacs_window (window_ptr))
11202 break;
11204 if ((er.modifiers & activeFlag) != 0)
11206 /* A window has been activated */
11207 Point mouse_loc = er.where;
11209 x_detect_focus_change (dpyinfo, &er, &inev);
11211 SetPortWindowPort (window_ptr);
11212 GlobalToLocal (&mouse_loc);
11213 /* Window-activated event counts as mouse movement,
11214 so update things that depend on mouse position. */
11215 note_mouse_movement (mac_window_to_frame (window_ptr),
11216 &mouse_loc);
11218 else
11220 /* A window has been deactivated */
11221 #ifdef USE_TOOLKIT_SCROLL_BARS
11222 if (dpyinfo->grabbed && tracked_scroll_bar)
11224 struct input_event event;
11226 EVENT_INIT (event);
11227 event.kind = NO_EVENT;
11228 x_scroll_bar_handle_release (tracked_scroll_bar, &event);
11229 if (event.kind != NO_EVENT)
11231 event.timestamp = timestamp;
11232 kbd_buffer_store_event_hold (&event, hold_quit);
11233 count++;
11236 #endif
11237 dpyinfo->grabbed = 0;
11239 x_detect_focus_change (dpyinfo, &er, &inev);
11241 f = mac_window_to_frame (window_ptr);
11242 if (f == dpyinfo->mouse_face_mouse_frame)
11244 /* If we move outside the frame, then we're
11245 certainly no longer on any text in the
11246 frame. */
11247 clear_mouse_face (dpyinfo);
11248 dpyinfo->mouse_face_mouse_frame = 0;
11251 /* Generate a nil HELP_EVENT to cancel a help-echo.
11252 Do it only if there's something to cancel.
11253 Otherwise, the startup message is cleared when the
11254 mouse leaves the frame. */
11255 if (any_help_event_p)
11256 do_help = -1;
11259 break;
11261 case keyDown:
11262 case keyUp:
11263 case autoKey:
11265 int keycode = (er.message & keyCodeMask) >> 8;
11266 static SInt16 last_key_script = -1;
11267 SInt16 current_key_script;
11268 UInt32 modifiers = er.modifiers, mapped_modifiers;
11270 #if USE_CARBON_EVENTS && defined (MAC_OSX)
11271 GetEventParameter (eventRef, kEventParamKeyModifiers,
11272 typeUInt32, NULL,
11273 sizeof (UInt32), NULL, &modifiers);
11274 #endif
11275 mapped_modifiers = mac_mapped_modifiers (modifiers, keycode);
11277 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
11278 /* When using Carbon Events, we need to pass raw keyboard
11279 events to the TSM ourselves. If TSM handles it, it
11280 will pass back noErr, otherwise it will pass back
11281 "eventNotHandledErr" and we can process it
11282 normally. */
11283 if (!(mapped_modifiers
11284 & ~(mac_pass_command_to_system ? cmdKey : 0)
11285 & ~(mac_pass_control_to_system ? controlKey : 0)))
11287 OSStatus err;
11289 read_socket_inev = &inev;
11290 err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
11291 read_socket_inev = NULL;
11292 if (err != eventNotHandledErr)
11293 break;
11295 #endif
11296 if (er.what == keyUp)
11297 break;
11299 ObscureCursor ();
11301 f = mac_focus_frame (dpyinfo);
11303 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
11304 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
11306 clear_mouse_face (dpyinfo);
11307 dpyinfo->mouse_face_hidden = 1;
11310 current_key_script = GetScriptManagerVariable (smKeyScript);
11311 if (last_key_script != current_key_script)
11313 struct input_event event;
11315 EVENT_INIT (event);
11316 event.kind = LANGUAGE_CHANGE_EVENT;
11317 event.arg = Qnil;
11318 event.code = current_key_script;
11319 event.timestamp = timestamp;
11320 kbd_buffer_store_event (&event);
11321 count++;
11322 last_key_script = current_key_script;
11325 #if USE_MAC_TSM
11326 if (inev.kind != NO_EVENT)
11327 break;
11328 #endif
11330 #ifdef MAC_OSX
11331 if (mapped_modifiers & kEventKeyModifierFnMask
11332 && keycode <= 0x7f
11333 && fn_keycode_to_keycode_table[keycode])
11334 keycode = fn_keycode_to_keycode_table[keycode];
11335 #endif
11336 if (keycode <= 0x7f && keycode_to_xkeysym_table [keycode])
11338 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
11339 inev.code = 0xff00 | keycode_to_xkeysym_table [keycode];
11341 else if (mapped_modifiers)
11343 /* translate the keycode back to determine the
11344 original key */
11345 #ifdef MAC_OSX
11346 UCKeyboardLayout *uchr_ptr = NULL;
11347 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
11348 OSStatus err;
11349 KeyboardLayoutRef layout;
11351 err = KLGetCurrentKeyboardLayout (&layout);
11352 if (err == noErr)
11353 KLGetKeyboardLayoutProperty (layout, kKLuchrData,
11354 (const void **) &uchr_ptr);
11355 #else
11356 static SInt16 last_key_layout_id = 0;
11357 static Handle uchr_handle = (Handle)-1;
11358 SInt16 current_key_layout_id =
11359 GetScriptVariable (current_key_script, smScriptKeys);
11361 if (uchr_handle == (Handle)-1
11362 || last_key_layout_id != current_key_layout_id)
11364 uchr_handle = GetResource ('uchr', current_key_layout_id);
11365 last_key_layout_id = current_key_layout_id;
11367 if (uchr_handle)
11368 uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
11369 #endif
11371 if (uchr_ptr)
11373 OSStatus status;
11374 UInt16 key_action = er.what - keyDown;
11375 UInt32 modifier_key_state =
11376 (modifiers & ~mapped_modifiers) >> 8;
11377 UInt32 keyboard_type = LMGetKbdType ();
11378 SInt32 dead_key_state = 0;
11379 UniChar code;
11380 UniCharCount actual_length;
11382 status = UCKeyTranslate (uchr_ptr,
11383 keycode, key_action,
11384 modifier_key_state,
11385 keyboard_type,
11386 kUCKeyTranslateNoDeadKeysMask,
11387 &dead_key_state,
11388 1, &actual_length, &code);
11389 if (status == noErr && actual_length == 1)
11390 mac_set_unicode_keystroke_event (code, &inev);
11392 #endif /* MAC_OSX */
11394 if (inev.kind == NO_EVENT)
11396 /* This code comes from Keyboard Resource,
11397 Appendix C of IM - Text. This is necessary
11398 since shift is ignored in KCHR table
11399 translation when option or command is pressed.
11400 It also does not translate correctly
11401 control-shift chars like C-% so mask off shift
11402 here also. */
11403 /* Mask off modifier keys that are mapped to some
11404 Emacs modifiers. */
11405 int new_modifiers = er.modifiers & ~mapped_modifiers;
11406 /* set high byte of keycode to modifier high byte*/
11407 int new_keycode = keycode | new_modifiers;
11408 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
11409 unsigned long some_state = 0;
11410 UInt32 new_char_code;
11412 new_char_code = KeyTranslate (kchr_ptr, new_keycode,
11413 &some_state);
11414 if (new_char_code == 0)
11415 /* Seems like a dead key. Append up-stroke. */
11416 new_char_code = KeyTranslate (kchr_ptr,
11417 new_keycode | 0x80,
11418 &some_state);
11419 if (new_char_code)
11421 inev.kind = ASCII_KEYSTROKE_EVENT;
11422 inev.code = new_char_code & 0xff;
11427 if (inev.kind == NO_EVENT)
11429 inev.kind = ASCII_KEYSTROKE_EVENT;
11430 inev.code = er.message & charCodeMask;
11433 inev.modifiers = mac_to_emacs_modifiers (mapped_modifiers,
11434 modifiers);
11435 inev.modifiers |= (extra_keyboard_modifiers
11436 & (meta_modifier | alt_modifier
11437 | hyper_modifier | super_modifier));
11438 XSETFRAME (inev.frame_or_window, f);
11440 #if TARGET_API_MAC_CARBON
11441 if (inev.kind == ASCII_KEYSTROKE_EVENT
11442 && inev.code >= 0x80 && inev.modifiers)
11444 OSStatus err;
11445 TextEncoding encoding = kTextEncodingMacRoman;
11446 TextToUnicodeInfo ttu_info;
11448 UpgradeScriptInfoToTextEncoding (current_key_script,
11449 kTextLanguageDontCare,
11450 kTextRegionDontCare,
11451 NULL, &encoding);
11452 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
11453 if (err == noErr)
11455 UniChar code;
11456 Str255 pstr;
11457 ByteCount unicode_len;
11459 pstr[0] = 1;
11460 pstr[1] = inev.code;
11461 err = ConvertFromPStringToUnicode (ttu_info, pstr,
11462 sizeof (UniChar),
11463 &unicode_len, &code);
11464 if (err == noErr && unicode_len == sizeof (UniChar))
11465 mac_set_unicode_keystroke_event (code, &inev);
11466 DisposeTextToUnicodeInfo (&ttu_info);
11469 #endif
11471 break;
11473 case kHighLevelEvent:
11474 AEProcessAppleEvent (&er);
11475 break;
11477 default:
11478 break;
11480 #if USE_CARBON_EVENTS
11481 ReleaseEvent (eventRef);
11482 #endif
11484 if (inev.kind != NO_EVENT)
11486 inev.timestamp = timestamp;
11487 kbd_buffer_store_event_hold (&inev, hold_quit);
11488 count++;
11491 if (do_help
11492 && !(hold_quit && hold_quit->kind != NO_EVENT))
11494 Lisp_Object frame;
11496 if (f)
11497 XSETFRAME (frame, f);
11498 else
11499 frame = Qnil;
11501 if (do_help > 0)
11503 any_help_event_p = 1;
11504 gen_help_event (help_echo_string, frame, help_echo_window,
11505 help_echo_object, help_echo_pos);
11507 else
11509 help_echo_string = Qnil;
11510 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
11512 count++;
11517 /* If the focus was just given to an autoraising frame,
11518 raise it now. */
11519 /* ??? This ought to be able to handle more than one such frame. */
11520 if (pending_autoraise_frame)
11522 x_raise_frame (pending_autoraise_frame);
11523 pending_autoraise_frame = 0;
11526 if (mac_screen_config_changed)
11528 mac_get_screen_info (dpyinfo);
11529 mac_screen_config_changed = 0;
11532 #if !USE_CARBON_EVENTS
11533 /* Check which frames are still visible. We do this here because
11534 there doesn't seem to be any direct notification from the Window
11535 Manager that the visibility of a window has changed (at least,
11536 not in all cases). */
11538 Lisp_Object tail, frame;
11540 FOR_EACH_FRAME (tail, frame)
11542 struct frame *f = XFRAME (frame);
11544 /* The tooltip has been drawn already. Avoid the
11545 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11546 if (EQ (frame, tip_frame))
11547 continue;
11549 if (FRAME_MAC_P (f))
11550 mac_handle_visibility_change (f);
11553 #endif
11555 --handling_signal;
11556 UNBLOCK_INPUT;
11557 return count;
11561 /* Need to override CodeWarrior's input function so no conversion is
11562 done on newlines Otherwise compiled functions in .elc files will be
11563 read incorrectly. Defined in ...:MSL C:MSL
11564 Common:Source:buffer_io.c. */
11565 #ifdef __MWERKS__
11566 void
11567 __convert_to_newlines (unsigned char * p, size_t * n)
11569 #pragma unused(p,n)
11572 void
11573 __convert_from_newlines (unsigned char * p, size_t * n)
11575 #pragma unused(p,n)
11577 #endif
11579 #ifdef MAC_OS8
11580 void
11581 make_mac_terminal_frame (struct frame *f)
11583 Lisp_Object frame;
11584 Rect r;
11586 XSETFRAME (frame, f);
11588 f->output_method = output_mac;
11589 f->output_data.mac = (struct mac_output *)
11590 xmalloc (sizeof (struct mac_output));
11591 bzero (f->output_data.mac, sizeof (struct mac_output));
11593 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
11595 FRAME_COLS (f) = 96;
11596 FRAME_LINES (f) = 4;
11598 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
11599 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
11601 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
11603 f->output_data.mac->cursor_pixel = 0;
11604 f->output_data.mac->border_pixel = 0x00ff00;
11605 f->output_data.mac->mouse_pixel = 0xff00ff;
11606 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
11608 f->output_data.mac->text_cursor = kThemeIBeamCursor;
11609 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
11610 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
11611 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
11612 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
11613 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
11615 FRAME_FONTSET (f) = -1;
11616 f->output_data.mac->explicit_parent = 0;
11617 f->left_pos = 8;
11618 f->top_pos = 32;
11619 f->border_width = 0;
11621 f->internal_border_width = 0;
11623 f->auto_raise = 1;
11624 f->auto_lower = 1;
11626 f->new_text_cols = 0;
11627 f->new_text_lines = 0;
11629 SetRect (&r, f->left_pos, f->top_pos,
11630 f->left_pos + FRAME_PIXEL_WIDTH (f),
11631 f->top_pos + FRAME_PIXEL_HEIGHT (f));
11633 BLOCK_INPUT;
11635 if (!(FRAME_MAC_WINDOW (f) =
11636 NewCWindow (NULL, &r, "\p", true, dBoxProc,
11637 (WindowPtr) -1, 1, (long) f->output_data.mac)))
11638 abort ();
11639 /* so that update events can find this mac_output struct */
11640 f->output_data.mac->mFP = f; /* point back to emacs frame */
11642 UNBLOCK_INPUT;
11644 x_make_gc (f);
11646 /* Need to be initialized for unshow_buffer in window.c. */
11647 selected_window = f->selected_window;
11649 Fmodify_frame_parameters (frame,
11650 Fcons (Fcons (Qfont,
11651 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
11652 Fmodify_frame_parameters (frame,
11653 Fcons (Fcons (Qforeground_color,
11654 build_string ("black")), Qnil));
11655 Fmodify_frame_parameters (frame,
11656 Fcons (Fcons (Qbackground_color,
11657 build_string ("white")), Qnil));
11659 #endif
11662 /***********************************************************************
11663 Initialization
11664 ***********************************************************************/
11666 static int mac_initialized = 0;
11668 static XrmDatabase
11669 mac_make_rdb (xrm_option)
11670 const char *xrm_option;
11672 XrmDatabase database;
11674 database = xrm_get_preference_database (NULL);
11675 if (xrm_option)
11676 xrm_merge_string_database (database, xrm_option);
11678 return database;
11681 struct mac_display_info *
11682 mac_term_init (display_name, xrm_option, resource_name)
11683 Lisp_Object display_name;
11684 char *xrm_option;
11685 char *resource_name;
11687 struct mac_display_info *dpyinfo;
11689 BLOCK_INPUT;
11691 if (!mac_initialized)
11693 mac_initialize ();
11694 mac_initialized = 1;
11697 if (x_display_list)
11698 error ("Sorry, this version can only handle one display");
11700 dpyinfo = &one_mac_display_info;
11701 bzero (dpyinfo, sizeof (*dpyinfo));
11703 #ifdef MAC_OSX
11704 dpyinfo->mac_id_name
11705 = (char *) xmalloc (SCHARS (Vinvocation_name)
11706 + SCHARS (Vsystem_name)
11707 + 2);
11708 sprintf (dpyinfo->mac_id_name, "%s@%s",
11709 SDATA (Vinvocation_name), SDATA (Vsystem_name));
11710 #else
11711 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
11712 strcpy (dpyinfo->mac_id_name, "Mac Display");
11713 #endif
11715 dpyinfo->reference_count = 0;
11716 dpyinfo->resx = 72.0;
11717 dpyinfo->resy = 72.0;
11719 mac_get_screen_info (dpyinfo);
11721 dpyinfo->grabbed = 0;
11722 dpyinfo->root_window = NULL;
11723 dpyinfo->image_cache = make_image_cache ();
11725 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
11726 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
11727 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
11728 dpyinfo->mouse_face_window = Qnil;
11729 dpyinfo->mouse_face_overlay = Qnil;
11730 dpyinfo->mouse_face_hidden = 0;
11732 dpyinfo->xrdb = mac_make_rdb (xrm_option);
11734 /* Put this display on the chain. */
11735 dpyinfo->next = x_display_list;
11736 x_display_list = dpyinfo;
11738 /* Put it on x_display_name_list. */
11739 x_display_name_list = Fcons (Fcons (display_name,
11740 Fcons (Qnil, dpyinfo->xrdb)),
11741 x_display_name_list);
11742 dpyinfo->name_list_element = XCAR (x_display_name_list);
11744 UNBLOCK_INPUT;
11746 return dpyinfo;
11749 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11751 void
11752 x_delete_display (dpyinfo)
11753 struct mac_display_info *dpyinfo;
11755 int i;
11757 /* Discard this display from x_display_name_list and x_display_list.
11758 We can't use Fdelq because that can quit. */
11759 if (! NILP (x_display_name_list)
11760 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
11761 x_display_name_list = XCDR (x_display_name_list);
11762 else
11764 Lisp_Object tail;
11766 tail = x_display_name_list;
11767 while (CONSP (tail) && CONSP (XCDR (tail)))
11769 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
11771 XSETCDR (tail, XCDR (XCDR (tail)));
11772 break;
11774 tail = XCDR (tail);
11778 if (x_display_list == dpyinfo)
11779 x_display_list = dpyinfo->next;
11780 else
11782 struct x_display_info *tail;
11784 for (tail = x_display_list; tail; tail = tail->next)
11785 if (tail->next == dpyinfo)
11786 tail->next = tail->next->next;
11789 /* Free the font names in the font table. */
11790 for (i = 0; i < dpyinfo->n_fonts; i++)
11791 if (dpyinfo->font_table[i].name)
11793 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
11794 xfree (dpyinfo->font_table[i].full_name);
11795 xfree (dpyinfo->font_table[i].name);
11798 if (dpyinfo->font_table)
11800 if (dpyinfo->font_table->font_encoder)
11801 xfree (dpyinfo->font_table->font_encoder);
11802 xfree (dpyinfo->font_table);
11804 if (dpyinfo->mac_id_name)
11805 xfree (dpyinfo->mac_id_name);
11807 if (x_display_list == 0)
11809 mac_clear_font_name_table ();
11810 bzero (dpyinfo, sizeof (*dpyinfo));
11815 static void
11816 init_menu_bar ()
11818 #ifdef MAC_OSX
11819 OSStatus err;
11820 MenuRef menu;
11821 MenuItemIndex menu_index;
11823 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
11824 &menu, &menu_index);
11825 if (err == noErr)
11826 SetMenuItemCommandKey (menu, menu_index, false, 0);
11827 #if USE_CARBON_EVENTS
11828 EnableMenuCommand (NULL, kHICommandPreferences);
11829 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
11830 &menu, &menu_index);
11831 if (err == noErr)
11833 SetMenuItemCommandKey (menu, menu_index, false, 0);
11834 InsertMenuItemTextWithCFString (menu, NULL,
11835 0, kMenuItemAttrSeparator, 0);
11836 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
11837 0, 0, kHICommandAbout);
11839 #endif /* USE_CARBON_EVENTS */
11840 #else /* !MAC_OSX */
11841 #if USE_CARBON_EVENTS
11842 SetMenuItemCommandID (GetMenuHandle (M_APPLE), I_ABOUT, kHICommandAbout);
11843 #endif
11844 #endif
11847 #if USE_MAC_TSM
11848 static void
11849 init_tsm ()
11851 #ifdef MAC_OSX
11852 static InterfaceTypeList types = {kUnicodeDocument};
11853 #else
11854 static InterfaceTypeList types = {kTextService};
11855 #endif
11857 NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
11858 &tsm_document_id, 0);
11860 #endif
11862 /* Set up use of X before we make the first connection. */
11864 extern frame_parm_handler mac_frame_parm_handlers[];
11866 static struct redisplay_interface x_redisplay_interface =
11868 mac_frame_parm_handlers,
11869 x_produce_glyphs,
11870 x_write_glyphs,
11871 x_insert_glyphs,
11872 x_clear_end_of_line,
11873 x_scroll_run,
11874 x_after_update_window_line,
11875 x_update_window_begin,
11876 x_update_window_end,
11877 x_cursor_to,
11878 x_flush,
11879 #if USE_CG_DRAWING
11880 mac_flush_display_optional,
11881 #else
11882 0, /* flush_display_optional */
11883 #endif
11884 x_clear_window_mouse_face,
11885 x_get_glyph_overhangs,
11886 x_fix_overlapping_area,
11887 x_draw_fringe_bitmap,
11888 #if USE_CG_DRAWING
11889 mac_define_fringe_bitmap,
11890 mac_destroy_fringe_bitmap,
11891 #else
11892 0, /* define_fringe_bitmap */
11893 0, /* destroy_fringe_bitmap */
11894 #endif
11895 mac_per_char_metric,
11896 mac_encode_char,
11897 mac_compute_glyph_string_overhangs,
11898 x_draw_glyph_string,
11899 mac_define_frame_cursor,
11900 mac_clear_frame_area,
11901 mac_draw_window_cursor,
11902 mac_draw_vertical_window_border,
11903 mac_shift_glyphs_for_insert
11906 void
11907 mac_initialize ()
11909 rif = &x_redisplay_interface;
11911 clear_frame_hook = x_clear_frame;
11912 ins_del_lines_hook = x_ins_del_lines;
11913 delete_glyphs_hook = x_delete_glyphs;
11914 ring_bell_hook = XTring_bell;
11915 reset_terminal_modes_hook = XTreset_terminal_modes;
11916 set_terminal_modes_hook = XTset_terminal_modes;
11917 update_begin_hook = x_update_begin;
11918 update_end_hook = x_update_end;
11919 set_terminal_window_hook = XTset_terminal_window;
11920 read_socket_hook = XTread_socket;
11921 frame_up_to_date_hook = XTframe_up_to_date;
11922 mouse_position_hook = XTmouse_position;
11923 frame_rehighlight_hook = XTframe_rehighlight;
11924 frame_raise_lower_hook = XTframe_raise_lower;
11926 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
11927 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
11928 redeem_scroll_bar_hook = XTredeem_scroll_bar;
11929 judge_scroll_bars_hook = XTjudge_scroll_bars;
11931 scroll_region_ok = 1; /* we'll scroll partial frames */
11932 char_ins_del_ok = 1;
11933 line_ins_del_ok = 1; /* we'll just blt 'em */
11934 fast_clear_end_of_line = 1; /* X does this well */
11935 memory_below_frame = 0; /* we don't remember what scrolls
11936 off the bottom */
11937 baud_rate = 19200;
11939 last_tool_bar_item = -1;
11940 any_help_event_p = 0;
11942 /* Try to use interrupt input; if we can't, then start polling. */
11943 Fset_input_mode (Qt, Qnil, Qt, Qnil);
11945 BLOCK_INPUT;
11947 #if TARGET_API_MAC_CARBON
11949 #if USE_CARBON_EVENTS
11950 #ifdef MAC_OSX
11951 init_service_handler ();
11952 #endif /* MAC_OSX */
11954 init_command_handler ();
11956 init_menu_bar ();
11958 #if USE_MAC_TSM
11959 init_tsm ();
11960 #endif
11961 #endif /* USE_CARBON_EVENTS */
11963 #ifdef MAC_OSX
11964 init_coercion_handler ();
11966 init_apple_event_handler ();
11968 init_dm_notification_handler ();
11970 if (!inhibit_window_system)
11972 static const ProcessSerialNumber psn = {0, kCurrentProcess};
11974 SetFrontProcess (&psn);
11976 #endif
11977 #endif
11979 #if USE_CG_DRAWING
11980 init_cg_color ();
11982 mac_init_fringe ();
11983 #endif
11985 UNBLOCK_INPUT;
11989 void
11990 syms_of_macterm ()
11992 #if 0
11993 staticpro (&x_error_message_string);
11994 x_error_message_string = Qnil;
11995 #endif
11997 Qcontrol = intern ("control"); staticpro (&Qcontrol);
11998 Qmeta = intern ("meta"); staticpro (&Qmeta);
11999 Qalt = intern ("alt"); staticpro (&Qalt);
12000 Qhyper = intern ("hyper"); staticpro (&Qhyper);
12001 Qsuper = intern ("super"); staticpro (&Qsuper);
12002 Qmodifier_value = intern ("modifier-value");
12003 staticpro (&Qmodifier_value);
12005 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
12006 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
12007 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
12008 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
12009 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
12011 #if USE_CARBON_EVENTS
12012 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
12013 #ifdef MAC_OSX
12014 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
12015 staticpro (&Qtoolbar_switch_mode);
12016 #if USE_MAC_FONT_PANEL
12017 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
12018 Qselection = intern ("selection"); staticpro (&Qselection);
12019 #endif
12021 Qservice = intern ("service"); staticpro (&Qservice);
12022 Qpaste = intern ("paste"); staticpro (&Qpaste);
12023 Qperform = intern ("perform"); staticpro (&Qperform);
12024 #endif
12025 #if USE_MAC_TSM
12026 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
12027 Qupdate_active_input_area = intern ("update-active-input-area");
12028 staticpro (&Qupdate_active_input_area);
12029 Qunicode_for_key_event = intern ("unicode-for-key-event");
12030 staticpro (&Qunicode_for_key_event);
12031 #endif
12032 #endif
12034 #ifdef MAC_OSX
12035 Fprovide (intern ("mac-carbon"), Qnil);
12036 #endif
12038 staticpro (&Qreverse);
12039 Qreverse = intern ("reverse");
12041 staticpro (&x_display_name_list);
12042 x_display_name_list = Qnil;
12044 staticpro (&last_mouse_scroll_bar);
12045 last_mouse_scroll_bar = Qnil;
12047 staticpro (&fm_font_family_alist);
12048 fm_font_family_alist = Qnil;
12050 #if USE_ATSUI
12051 staticpro (&atsu_font_id_hash);
12052 atsu_font_id_hash = Qnil;
12054 staticpro (&fm_style_face_attributes_alist);
12055 fm_style_face_attributes_alist = Qnil;
12056 #endif
12058 #if USE_MAC_TSM
12059 staticpro (&saved_ts_script_language_on_focus);
12060 saved_ts_script_language_on_focus = Qnil;
12061 #endif
12063 /* We don't yet support this, but defining this here avoids whining
12064 from cus-start.el and other places, like "M-x set-variable". */
12065 DEFVAR_BOOL ("x-use-underline-position-properties",
12066 &x_use_underline_position_properties,
12067 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12068 A value of nil means ignore them. If you encounter fonts with bogus
12069 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12070 to 4.1, set this to nil.
12072 NOTE: Not supported on Mac yet. */);
12073 x_use_underline_position_properties = 0;
12075 DEFVAR_BOOL ("x-underline-at-descent-line",
12076 &x_underline_at_descent_line,
12077 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
12078 A value of nil means to draw the underline according to the value of the
12079 variable `x-use-underline-position-properties', which is usually at the
12080 baseline level. The default value is nil. */);
12081 x_underline_at_descent_line = 0;
12083 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
12084 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
12085 #ifdef USE_TOOLKIT_SCROLL_BARS
12086 Vx_toolkit_scroll_bars = Qt;
12087 #else
12088 Vx_toolkit_scroll_bars = Qnil;
12089 #endif
12091 staticpro (&last_mouse_motion_frame);
12092 last_mouse_motion_frame = Qnil;
12094 /* Variables to configure modifier key assignment. */
12096 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
12097 doc: /* *Modifier key assumed when the Mac control key is pressed.
12098 The value can be `control', `meta', `alt', `hyper', or `super' for the
12099 respective modifier. The default is `control'. */);
12100 Vmac_control_modifier = Qcontrol;
12102 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
12103 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
12104 The value can be `control', `meta', `alt', `hyper', or `super' for the
12105 respective modifier. If the value is nil then the key will act as the
12106 normal Mac control modifier, and the option key can be used to compose
12107 characters depending on the chosen Mac keyboard setting. */);
12108 Vmac_option_modifier = Qnil;
12110 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
12111 doc: /* *Modifier key assumed when the Mac command key is pressed.
12112 The value can be `control', `meta', `alt', `hyper', or `super' for the
12113 respective modifier. The default is `meta'. */);
12114 Vmac_command_modifier = Qmeta;
12116 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
12117 doc: /* *Modifier key assumed when the Mac function key is pressed.
12118 The value can be `control', `meta', `alt', `hyper', or `super' for the
12119 respective modifier. Note that remapping the function key may lead to
12120 unexpected results for some keys on non-US/GB keyboards. */);
12121 Vmac_function_modifier = Qnil;
12123 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12124 &Vmac_emulate_three_button_mouse,
12125 doc: /* *Specify a way of three button mouse emulation.
12126 The value can be nil, t, or the symbol `reverse'.
12127 A value of nil means that no emulation should be done and the modifiers
12128 should be placed on the mouse-1 event.
12129 t means that when the option-key is held down while pressing the mouse
12130 button, the click will register as mouse-2 and while the command-key
12131 is held down, the click will register as mouse-3.
12132 The symbol `reverse' means that the option-key will register for
12133 mouse-3 and the command-key will register for mouse-2. */);
12134 Vmac_emulate_three_button_mouse = Qnil;
12136 #if USE_CARBON_EVENTS
12137 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
12138 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12139 Otherwise, the right click will be treated as mouse-2 and the wheel
12140 button will be mouse-3. */);
12141 mac_wheel_button_is_mouse_2 = 1;
12143 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
12144 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12145 mac_pass_command_to_system = 1;
12147 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
12148 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12149 mac_pass_control_to_system = 1;
12151 #endif
12153 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
12154 doc: /* *If non-nil, allow anti-aliasing.
12155 The text will be rendered using Core Graphics text rendering which
12156 may anti-alias the text. */);
12157 #if USE_CG_DRAWING
12158 mac_use_core_graphics = 1;
12159 #else
12160 mac_use_core_graphics = 0;
12161 #endif
12163 /* Register an entry for `mac-roman' so that it can be used when
12164 creating the terminal frame on Mac OS 9 before loading
12165 term/mac-win.elc. */
12166 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
12167 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
12168 Each entry should be of the form:
12170 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12172 where CHARSET-NAME is a string used in font names to identify the
12173 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12174 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
12175 Vmac_charset_info_alist =
12176 Fcons (list3 (build_string ("mac-roman"),
12177 make_number (smRoman), Qnil), Qnil);
12179 #if USE_MAC_TSM
12180 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
12181 doc: /* Overlay used to display Mac TSM active input area. */);
12182 Vmac_ts_active_input_overlay = Qnil;
12184 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
12185 doc: /* *How to change Mac TSM script/language when a frame gets focus.
12186 If the value is t, the input script and language are restored to those
12187 used in the last focus frame. If the value is a pair of integers, the
12188 input script and language codes, which are defined in the Script
12189 Manager, are set to its car and cdr parts, respectively. Otherwise,
12190 Emacs doesn't set them and thus follows the system default behavior. */);
12191 Vmac_ts_script_language_on_focus = Qnil;
12192 #endif
12195 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
12196 (do not change this comment) */