(Special Diary Entries): Fix Thanksgiving example.
[emacs.git] / src / macterm.c
blob9bc96e492d30ef4d9882958fff0fcabae4e72ca3
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 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 #ifdef USE_TOOLKIT_SCROLL_BARS
5002 bar->track_top = Qnil;
5003 bar->track_height = Qnil;
5004 bar->min_handle = Qnil;
5005 #endif
5007 /* Add bar to its frame's list of scroll bars. */
5008 bar->next = FRAME_SCROLL_BARS (f);
5009 bar->prev = Qnil;
5010 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5011 if (!NILP (bar->next))
5012 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5014 UNBLOCK_INPUT;
5015 return bar;
5019 /* Draw BAR's handle in the proper position.
5021 If the handle is already drawn from START to END, don't bother
5022 redrawing it, unless REBUILD is non-zero; in that case, always
5023 redraw it. (REBUILD is handy for drawing the handle after expose
5024 events.)
5026 Normally, we want to constrain the start and end of the handle to
5027 fit inside its rectangle, but if the user is dragging the scroll
5028 bar handle, we want to let them drag it down all the way, so that
5029 the bar's top is as far down as it goes; otherwise, there's no way
5030 to move to the very end of the buffer. */
5032 #ifndef USE_TOOLKIT_SCROLL_BARS
5034 static void
5035 x_scroll_bar_set_handle (bar, start, end, rebuild)
5036 struct scroll_bar *bar;
5037 int start, end;
5038 int rebuild;
5040 int dragging = ! NILP (bar->dragging);
5041 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5042 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5043 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5044 int length = end - start;
5046 /* If the display is already accurate, do nothing. */
5047 if (! rebuild
5048 && start == XINT (bar->start)
5049 && end == XINT (bar->end))
5050 return;
5052 BLOCK_INPUT;
5054 /* Make sure the values are reasonable, and try to preserve the
5055 distance between start and end. */
5056 if (start < 0)
5057 start = 0;
5058 else if (start > top_range)
5059 start = top_range;
5060 end = start + length;
5062 if (end < start)
5063 end = start;
5064 else if (end > top_range && ! dragging)
5065 end = top_range;
5067 /* Store the adjusted setting in the scroll bar. */
5068 XSETINT (bar->start, start);
5069 XSETINT (bar->end, end);
5071 /* Clip the end position, just for display. */
5072 if (end > top_range)
5073 end = top_range;
5075 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
5076 top positions, to make sure the handle is always at least that
5077 many pixels tall. */
5078 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
5080 SetControlMinimum (ch, 0);
5081 /* Don't inadvertently activate deactivated scroll bars */
5082 if (GetControlMaximum (ch) != -1)
5083 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
5084 - (end - start));
5085 SetControlValue (ch, start);
5086 #if TARGET_API_MAC_CARBON
5087 SetControlViewSize (ch, end - start);
5088 #endif
5090 UNBLOCK_INPUT;
5093 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5095 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5096 nil. */
5098 static void
5099 x_scroll_bar_remove (bar)
5100 struct scroll_bar *bar;
5102 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5104 BLOCK_INPUT;
5106 #if USE_CG_DRAWING
5107 mac_prepare_for_quickdraw (f);
5108 #endif
5109 /* Destroy the Mac scroll bar control */
5110 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
5112 /* Disassociate this scroll bar from its window. */
5113 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5115 UNBLOCK_INPUT;
5119 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5120 that we are displaying PORTION characters out of a total of WHOLE
5121 characters, starting at POSITION. If WINDOW has no scroll bar,
5122 create one. */
5124 static void
5125 XTset_vertical_scroll_bar (w, portion, whole, position)
5126 struct window *w;
5127 int portion, whole, position;
5129 struct frame *f = XFRAME (w->frame);
5130 struct scroll_bar *bar;
5131 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
5132 int window_y, window_height;
5134 /* Get window dimensions. */
5135 window_box (w, -1, 0, &window_y, 0, &window_height);
5136 top = window_y;
5137 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
5138 height = window_height;
5140 /* Compute the left edge of the scroll bar area. */
5141 left = WINDOW_SCROLL_BAR_AREA_X (w);
5143 /* Compute the width of the scroll bar which might be less than
5144 the width of the area reserved for the scroll bar. */
5145 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
5146 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
5147 else
5148 sb_width = width;
5150 /* Compute the left edge of the scroll bar. */
5151 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
5152 sb_left = left;
5153 else
5154 sb_left = left + width - sb_width;
5156 /* Adjustments according to Inside Macintosh to make it look nice */
5157 disp_top = top;
5158 disp_height = height;
5159 #ifdef MAC_OS8
5160 if (disp_top == 0)
5162 disp_top = -1;
5163 disp_height++;
5165 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
5167 disp_top++;
5168 disp_height--;
5171 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
5172 sb_left++;
5173 #endif
5175 /* Does the scroll bar exist yet? */
5176 if (NILP (w->vertical_scroll_bar))
5178 BLOCK_INPUT;
5179 mac_clear_area (f, left, top, width, height);
5180 UNBLOCK_INPUT;
5181 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
5182 disp_height);
5183 XSETVECTOR (w->vertical_scroll_bar, bar);
5185 else
5187 /* It may just need to be moved and resized. */
5188 ControlHandle ch;
5190 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5191 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5193 BLOCK_INPUT;
5195 /* If already correctly positioned, do nothing. */
5196 if (!(XINT (bar->left) == sb_left
5197 && XINT (bar->top) == top
5198 && XINT (bar->width) == sb_width
5199 && XINT (bar->height) == height))
5201 /* Since toolkit scroll bars are smaller than the space reserved
5202 for them on the frame, we have to clear "under" them. */
5203 mac_clear_area (f, left, top, width, height);
5205 #if USE_CG_DRAWING
5206 mac_prepare_for_quickdraw (f);
5207 #endif
5208 HideControl (ch);
5209 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
5210 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5211 disp_height);
5212 #ifndef USE_TOOLKIT_SCROLL_BARS
5213 if (sb_width < disp_height)
5214 ShowControl (ch);
5215 #endif
5217 /* Remember new settings. */
5218 XSETINT (bar->left, sb_left);
5219 XSETINT (bar->top, top);
5220 XSETINT (bar->width, sb_width);
5221 XSETINT (bar->height, height);
5222 #ifdef USE_TOOLKIT_SCROLL_BARS
5223 bar->track_top = Qnil;
5224 bar->track_height = Qnil;
5225 bar->min_handle = Qnil;
5226 #endif
5229 UNBLOCK_INPUT;
5232 #ifdef USE_TOOLKIT_SCROLL_BARS
5233 if (NILP (bar->track_top))
5235 if (sb_width >= disp_height
5236 #ifdef MAC_OSX
5237 || sb_width < MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
5238 #endif
5241 XSETINT (bar->track_top, 0);
5242 XSETINT (bar->track_height, 0);
5243 XSETINT (bar->min_handle, 0);
5245 else
5247 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5248 Rect r0, r1;
5250 BLOCK_INPUT;
5252 SetControl32BitMinimum (ch, 0);
5253 SetControl32BitMaximum (ch, 1 << 30);
5254 SetControlViewSize (ch, 1);
5256 /* Move the scroll bar thumb to the top. */
5257 SetControl32BitValue (ch, 0);
5258 get_control_part_bounds (ch, kControlIndicatorPart, &r0);
5260 /* Move the scroll bar thumb to the bottom. */
5261 SetControl32BitValue (ch, 1 << 30);
5262 get_control_part_bounds (ch, kControlIndicatorPart, &r1);
5264 UnionRect (&r0, &r1, &r0);
5265 XSETINT (bar->track_top, r0.top);
5266 XSETINT (bar->track_height, r0.bottom - r0.top);
5267 XSETINT (bar->min_handle, r1.bottom - r1.top);
5269 /* Don't show the scroll bar if its height is not enough to
5270 display the scroll bar thumb. */
5271 if (r0.bottom - r0.top > 0)
5272 ShowControl (ch);
5274 UNBLOCK_INPUT;
5278 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5279 #else /* not USE_TOOLKIT_SCROLL_BARS */
5280 /* Set the scroll bar's current state, unless we're currently being
5281 dragged. */
5282 if (NILP (bar->dragging))
5284 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5286 if (whole == 0)
5287 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5288 else
5290 int start = ((double) position * top_range) / whole;
5291 int end = ((double) (position + portion) * top_range) / whole;
5292 x_scroll_bar_set_handle (bar, start, end, 0);
5295 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5299 /* The following three hooks are used when we're doing a thorough
5300 redisplay of the frame. We don't explicitly know which scroll bars
5301 are going to be deleted, because keeping track of when windows go
5302 away is a real pain - "Can you say set-window-configuration, boys
5303 and girls?" Instead, we just assert at the beginning of redisplay
5304 that *all* scroll bars are to be removed, and then save a scroll bar
5305 from the fiery pit when we actually redisplay its window. */
5307 /* Arrange for all scroll bars on FRAME to be removed at the next call
5308 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5309 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5311 static void
5312 XTcondemn_scroll_bars (frame)
5313 FRAME_PTR frame;
5315 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5316 while (! NILP (FRAME_SCROLL_BARS (frame)))
5318 Lisp_Object bar;
5319 bar = FRAME_SCROLL_BARS (frame);
5320 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5321 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5322 XSCROLL_BAR (bar)->prev = Qnil;
5323 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5324 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5325 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5330 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5331 Note that WINDOW isn't necessarily condemned at all. */
5333 static void
5334 XTredeem_scroll_bar (window)
5335 struct window *window;
5337 struct scroll_bar *bar;
5338 struct frame *f;
5340 /* We can't redeem this window's scroll bar if it doesn't have one. */
5341 if (NILP (window->vertical_scroll_bar))
5342 abort ();
5344 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5346 /* Unlink it from the condemned list. */
5347 f = XFRAME (WINDOW_FRAME (window));
5348 if (NILP (bar->prev))
5350 /* If the prev pointer is nil, it must be the first in one of
5351 the lists. */
5352 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5353 /* It's not condemned. Everything's fine. */
5354 return;
5355 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5356 window->vertical_scroll_bar))
5357 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5358 else
5359 /* If its prev pointer is nil, it must be at the front of
5360 one or the other! */
5361 abort ();
5363 else
5364 XSCROLL_BAR (bar->prev)->next = bar->next;
5366 if (! NILP (bar->next))
5367 XSCROLL_BAR (bar->next)->prev = bar->prev;
5369 bar->next = FRAME_SCROLL_BARS (f);
5370 bar->prev = Qnil;
5371 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5372 if (! NILP (bar->next))
5373 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5376 /* Remove all scroll bars on FRAME that haven't been saved since the
5377 last call to `*condemn_scroll_bars_hook'. */
5379 static void
5380 XTjudge_scroll_bars (f)
5381 FRAME_PTR f;
5383 Lisp_Object bar, next;
5385 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5387 /* Clear out the condemned list now so we won't try to process any
5388 more events on the hapless scroll bars. */
5389 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5391 for (; ! NILP (bar); bar = next)
5393 struct scroll_bar *b = XSCROLL_BAR (bar);
5395 x_scroll_bar_remove (b);
5397 next = b->next;
5398 b->next = b->prev = Qnil;
5401 /* Now there should be no references to the condemned scroll bars,
5402 and they should get garbage-collected. */
5406 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5407 is set to something other than NO_EVENT, it is enqueued.
5409 This may be called from a signal handler, so we have to ignore GC
5410 mark bits. */
5412 static void
5413 x_scroll_bar_handle_click (bar, part_code, er, bufp)
5414 struct scroll_bar *bar;
5415 ControlPartCode part_code;
5416 const EventRecord *er;
5417 struct input_event *bufp;
5419 int win_y, top_range;
5421 if (! GC_WINDOWP (bar->window))
5422 abort ();
5424 bufp->kind = SCROLL_BAR_CLICK_EVENT;
5425 bufp->frame_or_window = bar->window;
5426 bufp->arg = Qnil;
5428 bar->dragging = Qnil;
5430 switch (part_code)
5432 case kControlUpButtonPart:
5433 bufp->part = scroll_bar_up_arrow;
5434 break;
5435 case kControlDownButtonPart:
5436 bufp->part = scroll_bar_down_arrow;
5437 break;
5438 case kControlPageUpPart:
5439 bufp->part = scroll_bar_above_handle;
5440 break;
5441 case kControlPageDownPart:
5442 bufp->part = scroll_bar_below_handle;
5443 break;
5444 #if TARGET_API_MAC_CARBON
5445 default:
5446 #else
5447 case kControlIndicatorPart:
5448 #endif
5449 if (er->what == mouseDown)
5450 bar->dragging = make_number (0);
5451 XSETVECTOR (last_mouse_scroll_bar, bar);
5452 bufp->part = scroll_bar_handle;
5453 break;
5456 win_y = XINT (bufp->y) - XINT (bar->top);
5457 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
5459 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5461 win_y -= 24;
5463 if (! NILP (bar->dragging))
5464 win_y -= XINT (bar->dragging);
5466 if (win_y < 0)
5467 win_y = 0;
5468 if (win_y > top_range)
5469 win_y = top_range;
5471 XSETINT (bufp->x, win_y);
5472 XSETINT (bufp->y, top_range);
5475 #ifndef USE_TOOLKIT_SCROLL_BARS
5477 /* Handle some mouse motion while someone is dragging the scroll bar.
5479 This may be called from a signal handler, so we have to ignore GC
5480 mark bits. */
5482 static void
5483 x_scroll_bar_note_movement (bar, y_pos, t)
5484 struct scroll_bar *bar;
5485 int y_pos;
5486 Time t;
5488 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5490 last_mouse_movement_time = t;
5492 f->mouse_moved = 1;
5493 XSETVECTOR (last_mouse_scroll_bar, bar);
5495 /* If we're dragging the bar, display it. */
5496 if (! GC_NILP (bar->dragging))
5498 /* Where should the handle be now? */
5499 int new_start = y_pos - 24;
5501 if (new_start != XINT (bar->start))
5503 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
5505 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5510 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5512 /* Return information to the user about the current position of the mouse
5513 on the scroll bar. */
5515 static void
5516 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
5517 FRAME_PTR *fp;
5518 Lisp_Object *bar_window;
5519 enum scroll_bar_part *part;
5520 Lisp_Object *x, *y;
5521 unsigned long *time;
5523 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5524 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5525 #if TARGET_API_MAC_CARBON
5526 WindowPtr wp = GetControlOwner (ch);
5527 #else
5528 WindowPtr wp = (*ch)->contrlOwner;
5529 #endif
5530 Point mouse_pos;
5531 struct frame *f = mac_window_to_frame (wp);
5532 int win_y, top_range;
5534 SetPortWindowPort (wp);
5536 GetMouse (&mouse_pos);
5538 win_y = mouse_pos.v - XINT (bar->top);
5539 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5541 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5543 win_y -= 24;
5545 if (! NILP (bar->dragging))
5546 win_y -= XINT (bar->dragging);
5548 if (win_y < 0)
5549 win_y = 0;
5550 if (win_y > top_range)
5551 win_y = top_range;
5553 *fp = f;
5554 *bar_window = bar->window;
5556 if (! NILP (bar->dragging))
5557 *part = scroll_bar_handle;
5558 else if (win_y < XINT (bar->start))
5559 *part = scroll_bar_above_handle;
5560 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5561 *part = scroll_bar_handle;
5562 else
5563 *part = scroll_bar_below_handle;
5565 XSETINT (*x, win_y);
5566 XSETINT (*y, top_range);
5568 f->mouse_moved = 0;
5569 last_mouse_scroll_bar = Qnil;
5571 *time = last_mouse_movement_time;
5575 /* The screen has been cleared so we may have changed foreground or
5576 background colors, and the scroll bars may need to be redrawn.
5577 Clear out the scroll bars, and ask for expose events, so we can
5578 redraw them. */
5580 void
5581 x_scroll_bar_clear (f)
5582 FRAME_PTR f;
5584 XTcondemn_scroll_bars (f);
5585 XTjudge_scroll_bars (f);
5589 /***********************************************************************
5590 Text Cursor
5591 ***********************************************************************/
5593 /* Set clipping for output in glyph row ROW. W is the window in which
5594 we operate. GC is the graphics context to set clipping in.
5596 ROW may be a text row or, e.g., a mode line. Text rows must be
5597 clipped to the interior of the window dedicated to text display,
5598 mode lines must be clipped to the whole window. */
5600 static void
5601 x_clip_to_row (w, row, area, gc)
5602 struct window *w;
5603 struct glyph_row *row;
5604 int area;
5605 GC gc;
5607 struct frame *f = XFRAME (WINDOW_FRAME (w));
5608 Rect clip_rect;
5609 int window_x, window_y, window_width;
5611 window_box (w, area, &window_x, &window_y, &window_width, 0);
5613 clip_rect.left = window_x;
5614 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5615 clip_rect.top = max (clip_rect.top, window_y);
5616 clip_rect.right = clip_rect.left + window_width;
5617 clip_rect.bottom = clip_rect.top + row->visible_height;
5619 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
5623 /* Draw a hollow box cursor on window W in glyph row ROW. */
5625 static void
5626 x_draw_hollow_cursor (w, row)
5627 struct window *w;
5628 struct glyph_row *row;
5630 struct frame *f = XFRAME (WINDOW_FRAME (w));
5631 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5632 Display *dpy = FRAME_MAC_DISPLAY (f);
5633 int x, y, wd, h;
5634 XGCValues xgcv;
5635 struct glyph *cursor_glyph;
5636 GC gc;
5638 /* Get the glyph the cursor is on. If we can't tell because
5639 the current matrix is invalid or such, give up. */
5640 cursor_glyph = get_phys_cursor_glyph (w);
5641 if (cursor_glyph == NULL)
5642 return;
5644 /* Compute frame-relative coordinates for phys cursor. */
5645 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
5646 wd = w->phys_cursor_width;
5648 /* The foreground of cursor_gc is typically the same as the normal
5649 background color, which can cause the cursor box to be invisible. */
5650 xgcv.foreground = f->output_data.mac->cursor_pixel;
5651 if (dpyinfo->scratch_cursor_gc)
5652 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5653 else
5654 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5655 GCForeground, &xgcv);
5656 gc = dpyinfo->scratch_cursor_gc;
5658 /* Set clipping, draw the rectangle, and reset clipping again. */
5659 x_clip_to_row (w, row, TEXT_AREA, gc);
5660 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
5661 mac_reset_clip_rectangles (dpy, gc);
5665 /* Draw a bar cursor on window W in glyph row ROW.
5667 Implementation note: One would like to draw a bar cursor with an
5668 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5669 Unfortunately, I didn't find a font yet that has this property set.
5670 --gerd. */
5672 static void
5673 x_draw_bar_cursor (w, row, width, kind)
5674 struct window *w;
5675 struct glyph_row *row;
5676 int width;
5677 enum text_cursor_kinds kind;
5679 struct frame *f = XFRAME (w->frame);
5680 struct glyph *cursor_glyph;
5682 /* If cursor is out of bounds, don't draw garbage. This can happen
5683 in mini-buffer windows when switching between echo area glyphs
5684 and mini-buffer. */
5685 cursor_glyph = get_phys_cursor_glyph (w);
5686 if (cursor_glyph == NULL)
5687 return;
5689 /* If on an image, draw like a normal cursor. That's usually better
5690 visible than drawing a bar, esp. if the image is large so that
5691 the bar might not be in the window. */
5692 if (cursor_glyph->type == IMAGE_GLYPH)
5694 struct glyph_row *row;
5695 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5696 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5698 else
5700 Display *dpy = FRAME_MAC_DISPLAY (f);
5701 Window window = FRAME_MAC_WINDOW (f);
5702 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5703 unsigned long mask = GCForeground | GCBackground;
5704 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5705 XGCValues xgcv;
5707 /* If the glyph's background equals the color we normally draw
5708 the bar cursor in, the bar cursor in its normal color is
5709 invisible. Use the glyph's foreground color instead in this
5710 case, on the assumption that the glyph's colors are chosen so
5711 that the glyph is legible. */
5712 if (face->background == f->output_data.mac->cursor_pixel)
5713 xgcv.background = xgcv.foreground = face->foreground;
5714 else
5715 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5717 if (gc)
5718 XChangeGC (dpy, gc, mask, &xgcv);
5719 else
5721 gc = XCreateGC (dpy, window, mask, &xgcv);
5722 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5725 if (width < 0)
5726 width = FRAME_CURSOR_WIDTH (f);
5727 width = min (cursor_glyph->pixel_width, width);
5729 w->phys_cursor_width = width;
5730 x_clip_to_row (w, row, TEXT_AREA, gc);
5732 if (kind == BAR_CURSOR)
5733 mac_fill_rectangle (f, gc,
5734 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5735 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5736 width, row->height);
5737 else
5738 mac_fill_rectangle (f, gc,
5739 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5740 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5741 row->height - width),
5742 cursor_glyph->pixel_width,
5743 width);
5745 mac_reset_clip_rectangles (dpy, gc);
5750 /* RIF: Define cursor CURSOR on frame F. */
5752 static void
5753 mac_define_frame_cursor (f, cursor)
5754 struct frame *f;
5755 Cursor cursor;
5757 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5759 if (dpyinfo->x_focus_frame == f)
5760 SetThemeCursor (cursor);
5764 /* RIF: Clear area on frame F. */
5766 static void
5767 mac_clear_frame_area (f, x, y, width, height)
5768 struct frame *f;
5769 int x, y, width, height;
5771 mac_clear_area (f, x, y, width, height);
5775 /* RIF: Draw cursor on window W. */
5777 static void
5778 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5779 struct window *w;
5780 struct glyph_row *glyph_row;
5781 int x, y;
5782 int cursor_type, cursor_width;
5783 int on_p, active_p;
5785 if (on_p)
5787 w->phys_cursor_type = cursor_type;
5788 w->phys_cursor_on_p = 1;
5790 if (glyph_row->exact_window_width_line_p
5791 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5793 glyph_row->cursor_in_fringe_p = 1;
5794 draw_fringe_bitmap (w, glyph_row, 0);
5796 else
5797 switch (cursor_type)
5799 case HOLLOW_BOX_CURSOR:
5800 x_draw_hollow_cursor (w, glyph_row);
5801 break;
5803 case FILLED_BOX_CURSOR:
5804 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5805 break;
5807 case BAR_CURSOR:
5808 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5809 break;
5811 case HBAR_CURSOR:
5812 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5813 break;
5815 case NO_CURSOR:
5816 w->phys_cursor_width = 0;
5817 break;
5819 default:
5820 abort ();
5826 /* Icons. */
5828 #if 0 /* MAC_TODO: no icon support yet. */
5830 x_bitmap_icon (f, icon)
5831 struct frame *f;
5832 Lisp_Object icon;
5834 HANDLE hicon;
5836 if (FRAME_W32_WINDOW (f) == 0)
5837 return 1;
5839 if (NILP (icon))
5840 hicon = LoadIcon (hinst, EMACS_CLASS);
5841 else if (STRINGP (icon))
5842 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5843 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5844 else if (SYMBOLP (icon))
5846 LPCTSTR name;
5848 if (EQ (icon, intern ("application")))
5849 name = (LPCTSTR) IDI_APPLICATION;
5850 else if (EQ (icon, intern ("hand")))
5851 name = (LPCTSTR) IDI_HAND;
5852 else if (EQ (icon, intern ("question")))
5853 name = (LPCTSTR) IDI_QUESTION;
5854 else if (EQ (icon, intern ("exclamation")))
5855 name = (LPCTSTR) IDI_EXCLAMATION;
5856 else if (EQ (icon, intern ("asterisk")))
5857 name = (LPCTSTR) IDI_ASTERISK;
5858 else if (EQ (icon, intern ("winlogo")))
5859 name = (LPCTSTR) IDI_WINLOGO;
5860 else
5861 return 1;
5863 hicon = LoadIcon (NULL, name);
5865 else
5866 return 1;
5868 if (hicon == NULL)
5869 return 1;
5871 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5872 (LPARAM) hicon);
5874 return 0;
5876 #endif /* MAC_TODO */
5878 /************************************************************************
5879 Handling X errors
5880 ************************************************************************/
5882 /* Display Error Handling functions not used on W32. Listing them here
5883 helps diff stay in step when comparing w32term.c with xterm.c.
5885 x_error_catcher (display, error)
5886 x_catch_errors (dpy)
5887 x_catch_errors_unwind (old_val)
5888 x_check_errors (dpy, format)
5889 x_had_errors_p (dpy)
5890 x_clear_errors (dpy)
5891 x_uncatch_errors (dpy, count)
5892 x_trace_wire ()
5893 x_connection_signal (signalnum)
5894 x_connection_closed (dpy, error_message)
5895 x_error_quitter (display, error)
5896 x_error_handler (display, error)
5897 x_io_error_quitter (display)
5902 /* Changing the font of the frame. */
5904 /* Give frame F the font named FONTNAME as its default font, and
5905 return the full name of that font. FONTNAME may be a wildcard
5906 pattern; in that case, we choose some font that fits the pattern.
5907 The return value shows which font we chose. */
5909 Lisp_Object
5910 x_new_font (f, fontname)
5911 struct frame *f;
5912 register char *fontname;
5914 struct font_info *fontp
5915 = FS_LOAD_FONT (f, 0, fontname, -1);
5917 if (!fontp)
5918 return Qnil;
5920 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5921 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5922 FRAME_FONTSET (f) = -1;
5924 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5925 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5926 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5928 compute_fringe_widths (f, 1);
5930 /* Compute the scroll bar width in character columns. */
5931 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5933 int wid = FRAME_COLUMN_WIDTH (f);
5934 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5935 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5937 else
5939 int wid = FRAME_COLUMN_WIDTH (f);
5940 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5943 /* Now make the frame display the given font. */
5944 if (FRAME_MAC_WINDOW (f) != 0)
5946 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5947 FRAME_FONT (f));
5948 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5949 FRAME_FONT (f));
5950 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5951 FRAME_FONT (f));
5953 /* Don't change the size of a tip frame; there's no point in
5954 doing it because it's done in Fx_show_tip, and it leads to
5955 problems because the tip frame has no widget. */
5956 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5957 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5960 return build_string (fontp->full_name);
5963 /* Give frame F the fontset named FONTSETNAME as its default font, and
5964 return the full name of that fontset. FONTSETNAME may be a wildcard
5965 pattern; in that case, we choose some fontset that fits the pattern.
5966 The return value shows which fontset we chose. */
5968 Lisp_Object
5969 x_new_fontset (f, fontsetname)
5970 struct frame *f;
5971 char *fontsetname;
5973 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5974 Lisp_Object result;
5976 if (fontset < 0)
5977 return Qnil;
5979 if (FRAME_FONTSET (f) == fontset)
5980 /* This fontset is already set in frame F. There's nothing more
5981 to do. */
5982 return fontset_name (fontset);
5984 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5986 if (!STRINGP (result))
5987 /* Can't load ASCII font. */
5988 return Qnil;
5990 /* Since x_new_font doesn't update any fontset information, do it now. */
5991 FRAME_FONTSET (f) = fontset;
5993 return build_string (fontsetname);
5997 /***********************************************************************
5998 TODO: W32 Input Methods
5999 ***********************************************************************/
6000 /* Listing missing functions from xterm.c helps diff stay in step.
6002 xim_destroy_callback (xim, client_data, call_data)
6003 xim_open_dpy (dpyinfo, resource_name)
6004 struct xim_inst_t
6005 xim_instantiate_callback (display, client_data, call_data)
6006 xim_initialize (dpyinfo, resource_name)
6007 xim_close_dpy (dpyinfo)
6012 void
6013 mac_get_window_bounds (f, inner, outer)
6014 struct frame *f;
6015 Rect *inner, *outer;
6017 #if TARGET_API_MAC_CARBON
6018 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
6019 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
6020 #else /* not TARGET_API_MAC_CARBON */
6021 RgnHandle region = NewRgn ();
6023 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
6024 *inner = (*region)->rgnBBox;
6025 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
6026 *outer = (*region)->rgnBBox;
6027 DisposeRgn (region);
6028 #endif /* not TARGET_API_MAC_CARBON */
6031 static void
6032 mac_handle_origin_change (f)
6033 struct frame *f;
6035 x_real_positions (f, &f->left_pos, &f->top_pos);
6038 static void
6039 mac_handle_size_change (f, pixelwidth, pixelheight)
6040 struct frame *f;
6041 int pixelwidth, pixelheight;
6043 int cols, rows;
6045 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
6046 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
6048 if (cols != FRAME_COLS (f)
6049 || rows != FRAME_LINES (f)
6050 || pixelwidth != FRAME_PIXEL_WIDTH (f)
6051 || pixelheight != FRAME_PIXEL_HEIGHT (f))
6053 /* We pass 1 for DELAY since we can't run Lisp code inside of
6054 a BLOCK_INPUT. */
6055 change_frame_size (f, rows, cols, 0, 1, 0);
6056 FRAME_PIXEL_WIDTH (f) = pixelwidth;
6057 FRAME_PIXEL_HEIGHT (f) = pixelheight;
6058 SET_FRAME_GARBAGED (f);
6060 /* If cursor was outside the new size, mark it as off. */
6061 mark_window_cursors_off (XWINDOW (f->root_window));
6063 /* Clear out any recollection of where the mouse highlighting
6064 was, since it might be in a place that's outside the new
6065 frame size. Actually checking whether it is outside is a
6066 pain in the neck, so don't try--just let the highlighting be
6067 done afresh with new size. */
6068 cancel_mouse_face (f);
6070 #if TARGET_API_MAC_CARBON
6071 if (f->output_data.mac->hourglass_control)
6073 #if USE_CG_DRAWING
6074 mac_prepare_for_quickdraw (f);
6075 #endif
6076 MoveControl (f->output_data.mac->hourglass_control,
6077 pixelwidth - HOURGLASS_WIDTH, 0);
6079 #endif
6084 /* Calculate the absolute position in frame F
6085 from its current recorded position values and gravity. */
6087 void
6088 x_calc_absolute_position (f)
6089 struct frame *f;
6091 int width_diff = 0, height_diff = 0;
6092 int flags = f->size_hint_flags;
6093 Rect inner, outer;
6095 /* We have nothing to do if the current position
6096 is already for the top-left corner. */
6097 if (! ((flags & XNegative) || (flags & YNegative)))
6098 return;
6100 /* Find the offsets of the outside upper-left corner of
6101 the inner window, with respect to the outer window. */
6102 BLOCK_INPUT;
6103 mac_get_window_bounds (f, &inner, &outer);
6104 UNBLOCK_INPUT;
6106 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
6107 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
6109 /* Treat negative positions as relative to the leftmost bottommost
6110 position that fits on the screen. */
6111 if (flags & XNegative)
6112 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
6113 - width_diff
6114 - FRAME_PIXEL_WIDTH (f)
6115 + f->left_pos);
6117 if (flags & YNegative)
6118 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
6119 - height_diff
6120 - FRAME_PIXEL_HEIGHT (f)
6121 + f->top_pos);
6123 /* The left_pos and top_pos
6124 are now relative to the top and left screen edges,
6125 so the flags should correspond. */
6126 f->size_hint_flags &= ~ (XNegative | YNegative);
6129 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6130 to really change the position, and 0 when calling from
6131 x_make_frame_visible (in that case, XOFF and YOFF are the current
6132 position values). It is -1 when calling from x_set_frame_parameters,
6133 which means, do adjust for borders but don't change the gravity. */
6135 void
6136 x_set_offset (f, xoff, yoff, change_gravity)
6137 struct frame *f;
6138 register int xoff, yoff;
6139 int change_gravity;
6141 if (change_gravity > 0)
6143 f->top_pos = yoff;
6144 f->left_pos = xoff;
6145 f->size_hint_flags &= ~ (XNegative | YNegative);
6146 if (xoff < 0)
6147 f->size_hint_flags |= XNegative;
6148 if (yoff < 0)
6149 f->size_hint_flags |= YNegative;
6150 f->win_gravity = NorthWestGravity;
6152 x_calc_absolute_position (f);
6154 BLOCK_INPUT;
6155 x_wm_set_size_hint (f, (long) 0, 0);
6157 #if TARGET_API_MAC_CARBON
6158 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
6159 /* If the title bar is completely outside the screen, adjust the
6160 position. */
6161 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
6162 kWindowConstrainMoveRegardlessOfFit
6163 | kWindowConstrainAllowPartial, NULL, NULL);
6164 #if USE_CARBON_EVENTS
6165 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
6166 #endif
6167 mac_handle_origin_change (f);
6168 #else
6170 Rect inner, outer, screen_rect, dummy;
6171 RgnHandle region = NewRgn ();
6173 mac_get_window_bounds (f, &inner, &outer);
6174 f->x_pixels_diff = inner.left - outer.left;
6175 f->y_pixels_diff = inner.top - outer.top;
6176 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6177 f->top_pos + f->y_pixels_diff, false);
6179 /* If the title bar is completely outside the screen, adjust the
6180 position. The variable `outer' holds the title bar rectangle.
6181 The variable `inner' holds slightly smaller one than `outer',
6182 so that the calculation of overlapping may not become too
6183 strict. */
6184 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
6185 outer = (*region)->rgnBBox;
6186 DisposeRgn (region);
6187 inner = outer;
6188 InsetRect (&inner, 8, 8);
6189 screen_rect = qd.screenBits.bounds;
6190 screen_rect.top += GetMBarHeight ();
6192 if (!SectRect (&inner, &screen_rect, &dummy))
6194 if (inner.right <= screen_rect.left)
6195 f->left_pos = screen_rect.left;
6196 else if (inner.left >= screen_rect.right)
6197 f->left_pos = screen_rect.right - (outer.right - outer.left);
6199 if (inner.bottom <= screen_rect.top)
6200 f->top_pos = screen_rect.top;
6201 else if (inner.top >= screen_rect.bottom)
6202 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
6204 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
6205 f->top_pos + f->y_pixels_diff, false);
6208 #endif
6210 UNBLOCK_INPUT;
6213 /* Call this to change the size of frame F's x-window.
6214 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
6215 for this size change and subsequent size changes.
6216 Otherwise we leave the window gravity unchanged. */
6218 void
6219 x_set_window_size (f, change_gravity, cols, rows)
6220 struct frame *f;
6221 int change_gravity;
6222 int cols, rows;
6224 int pixelwidth, pixelheight;
6226 BLOCK_INPUT;
6228 check_frame_size (f, &rows, &cols);
6229 f->scroll_bar_actual_width
6230 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
6232 compute_fringe_widths (f, 0);
6234 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
6235 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
6237 f->win_gravity = NorthWestGravity;
6238 x_wm_set_size_hint (f, (long) 0, 0);
6240 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
6242 #if USE_CARBON_EVENTS
6243 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
6244 #endif
6245 mac_handle_size_change (f, pixelwidth, pixelheight);
6247 if (f->output_data.mac->internal_border_width
6248 != FRAME_INTERNAL_BORDER_WIDTH (f))
6250 mac_clear_window (f);
6251 f->output_data.mac->internal_border_width
6252 = FRAME_INTERNAL_BORDER_WIDTH (f);
6255 SET_FRAME_GARBAGED (f);
6257 UNBLOCK_INPUT;
6260 /* Mouse warping. */
6262 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
6264 void
6265 x_set_mouse_position (f, x, y)
6266 struct frame *f;
6267 int x, y;
6269 int pix_x, pix_y;
6271 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
6272 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
6274 if (pix_x < 0) pix_x = 0;
6275 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
6277 if (pix_y < 0) pix_y = 0;
6278 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
6280 x_set_mouse_pixel_position (f, pix_x, pix_y);
6283 void
6284 x_set_mouse_pixel_position (f, pix_x, pix_y)
6285 struct frame *f;
6286 int pix_x, pix_y;
6288 #ifdef MAC_OSX
6289 Point p;
6290 CGPoint point;
6292 BLOCK_INPUT;
6293 SetPortWindowPort (FRAME_MAC_WINDOW (f));
6294 p.h = pix_x;
6295 p.v = pix_y;
6296 LocalToGlobal (&p);
6297 point.x = p.h;
6298 point.y = p.v;
6299 CGWarpMouseCursorPosition (point);
6300 UNBLOCK_INPUT;
6301 #else
6302 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
6303 BLOCK_INPUT;
6305 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
6306 0, 0, 0, 0, pix_x, pix_y);
6307 UNBLOCK_INPUT;
6308 #endif
6309 #endif
6312 /* focus shifting, raising and lowering. */
6314 void
6315 x_focus_on_frame (f)
6316 struct frame *f;
6318 #if 0 /* This proves to be unpleasant. */
6319 x_raise_frame (f);
6320 #endif
6321 #if 0
6322 /* I don't think that the ICCCM allows programs to do things like this
6323 without the interaction of the window manager. Whatever you end up
6324 doing with this code, do it to x_unfocus_frame too. */
6325 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6326 RevertToPointerRoot, CurrentTime);
6327 #endif /* ! 0 */
6330 void
6331 x_unfocus_frame (f)
6332 struct frame *f;
6336 /* Raise frame F. */
6338 void
6339 x_raise_frame (f)
6340 struct frame *f;
6342 if (f->async_visible)
6344 BLOCK_INPUT;
6345 BringToFront (FRAME_MAC_WINDOW (f));
6346 UNBLOCK_INPUT;
6350 /* Lower frame F. */
6352 void
6353 x_lower_frame (f)
6354 struct frame *f;
6356 if (f->async_visible)
6358 BLOCK_INPUT;
6359 SendBehind (FRAME_MAC_WINDOW (f), NULL);
6360 UNBLOCK_INPUT;
6364 static void
6365 XTframe_raise_lower (f, raise_flag)
6366 FRAME_PTR f;
6367 int raise_flag;
6369 if (raise_flag)
6370 x_raise_frame (f);
6371 else
6372 x_lower_frame (f);
6375 /* Change of visibility. */
6377 static void
6378 mac_handle_visibility_change (f)
6379 struct frame *f;
6381 WindowPtr wp = FRAME_MAC_WINDOW (f);
6382 int visible = 0, iconified = 0;
6383 struct input_event buf;
6385 if (IsWindowVisible (wp))
6387 if (IsWindowCollapsed (wp))
6388 iconified = 1;
6389 else
6390 visible = 1;
6393 if (!f->async_visible && visible)
6395 if (f->iconified)
6397 /* wait_reading_process_output will notice this and update
6398 the frame's display structures. If we were made
6399 invisible, we should not set garbaged, because that stops
6400 redrawing on Update events. */
6401 SET_FRAME_GARBAGED (f);
6403 EVENT_INIT (buf);
6404 buf.kind = DEICONIFY_EVENT;
6405 XSETFRAME (buf.frame_or_window, f);
6406 buf.arg = Qnil;
6407 kbd_buffer_store_event (&buf);
6409 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
6410 /* Force a redisplay sooner or later to update the
6411 frame titles in case this is the second frame. */
6412 record_asynch_buffer_change ();
6414 else if (f->async_visible && !visible)
6415 if (iconified)
6417 EVENT_INIT (buf);
6418 buf.kind = ICONIFY_EVENT;
6419 XSETFRAME (buf.frame_or_window, f);
6420 buf.arg = Qnil;
6421 kbd_buffer_store_event (&buf);
6424 f->async_visible = visible;
6425 f->async_iconified = iconified;
6428 /* This tries to wait until the frame is really visible.
6429 However, if the window manager asks the user where to position
6430 the frame, this will return before the user finishes doing that.
6431 The frame will not actually be visible at that time,
6432 but it will become visible later when the window manager
6433 finishes with it. */
6435 void
6436 x_make_frame_visible (f)
6437 struct frame *f;
6439 BLOCK_INPUT;
6441 if (! FRAME_VISIBLE_P (f))
6443 /* We test FRAME_GARBAGED_P here to make sure we don't
6444 call x_set_offset a second time
6445 if we get to x_make_frame_visible a second time
6446 before the window gets really visible. */
6447 if (! FRAME_ICONIFIED_P (f)
6448 && ! f->output_data.mac->asked_for_visible)
6450 #if TARGET_API_MAC_CARBON
6451 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
6453 struct frame *sf = SELECTED_FRAME ();
6454 if (!FRAME_MAC_P (sf))
6455 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
6456 kWindowCenterOnMainScreen);
6457 else
6458 RepositionWindow (FRAME_MAC_WINDOW (f),
6459 FRAME_MAC_WINDOW (sf),
6460 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6461 kWindowCascadeStartAtParentWindowScreen
6462 #else
6463 kWindowCascadeOnParentWindowScreen
6464 #endif
6466 #if USE_CARBON_EVENTS
6467 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
6468 #endif
6469 mac_handle_origin_change (f);
6471 else
6472 #endif
6473 x_set_offset (f, f->left_pos, f->top_pos, 0);
6476 f->output_data.mac->asked_for_visible = 1;
6478 CollapseWindow (FRAME_MAC_WINDOW (f), false);
6479 ShowWindow (FRAME_MAC_WINDOW (f));
6482 XFlush (FRAME_MAC_DISPLAY (f));
6484 /* Synchronize to ensure Emacs knows the frame is visible
6485 before we do anything else. We do this loop with input not blocked
6486 so that incoming events are handled. */
6488 Lisp_Object frame;
6489 int count;
6491 /* This must come after we set COUNT. */
6492 UNBLOCK_INPUT;
6494 XSETFRAME (frame, f);
6496 /* Wait until the frame is visible. Process X events until a
6497 MapNotify event has been seen, or until we think we won't get a
6498 MapNotify at all.. */
6499 for (count = input_signal_count + 10;
6500 input_signal_count < count && !FRAME_VISIBLE_P (f);)
6502 /* Force processing of queued events. */
6503 x_sync (f);
6505 /* Machines that do polling rather than SIGIO have been
6506 observed to go into a busy-wait here. So we'll fake an
6507 alarm signal to let the handler know that there's something
6508 to be read. We used to raise a real alarm, but it seems
6509 that the handler isn't always enabled here. This is
6510 probably a bug. */
6511 if (input_polling_used ())
6513 /* It could be confusing if a real alarm arrives while
6514 processing the fake one. Turn it off and let the
6515 handler reset it. */
6516 extern void poll_for_input_1 P_ ((void));
6517 int old_poll_suppress_count = poll_suppress_count;
6518 poll_suppress_count = 1;
6519 poll_for_input_1 ();
6520 poll_suppress_count = old_poll_suppress_count;
6523 /* See if a MapNotify event has been processed. */
6524 FRAME_SAMPLE_VISIBILITY (f);
6529 /* Change from mapped state to withdrawn state. */
6531 /* Make the frame visible (mapped and not iconified). */
6533 void
6534 x_make_frame_invisible (f)
6535 struct frame *f;
6537 /* A deactivate event does not occur when the last visible frame is
6538 made invisible. So if we clear the highlight here, it will not
6539 be rehighlighted when it is made visible. */
6540 #if 0
6541 /* Don't keep the highlight on an invisible frame. */
6542 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6543 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6544 #endif
6546 BLOCK_INPUT;
6548 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6549 that the current position of the window is user-specified, rather than
6550 program-specified, so that when the window is mapped again, it will be
6551 placed at the same location, without forcing the user to position it
6552 by hand again (they have already done that once for this window.) */
6553 x_wm_set_size_hint (f, (long) 0, 1);
6555 HideWindow (FRAME_MAC_WINDOW (f));
6557 UNBLOCK_INPUT;
6559 #if !USE_CARBON_EVENTS
6560 mac_handle_visibility_change (f);
6561 #endif
6564 /* Change window state from mapped to iconified. */
6566 void
6567 x_iconify_frame (f)
6568 struct frame *f;
6570 OSStatus err;
6572 /* A deactivate event does not occur when the last visible frame is
6573 iconified. So if we clear the highlight here, it will not be
6574 rehighlighted when it is deiconified. */
6575 #if 0
6576 /* Don't keep the highlight on an invisible frame. */
6577 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6578 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6579 #endif
6581 if (f->async_iconified)
6582 return;
6584 BLOCK_INPUT;
6586 FRAME_SAMPLE_VISIBILITY (f);
6588 if (! FRAME_VISIBLE_P (f))
6589 ShowWindow (FRAME_MAC_WINDOW (f));
6591 err = CollapseWindow (FRAME_MAC_WINDOW (f), true);
6593 UNBLOCK_INPUT;
6595 if (err != noErr)
6596 error ("Can't notify window manager of iconification");
6598 #if !USE_CARBON_EVENTS
6599 mac_handle_visibility_change (f);
6600 #endif
6604 /* Free X resources of frame F. */
6606 void
6607 x_free_frame_resources (f)
6608 struct frame *f;
6610 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6611 WindowPtr wp = FRAME_MAC_WINDOW (f);
6613 BLOCK_INPUT;
6615 if (wp != tip_window)
6616 remove_window_handler (wp);
6618 #if USE_CG_DRAWING
6619 mac_prepare_for_quickdraw (f);
6620 #endif
6621 DisposeWindow (wp);
6622 if (wp == tip_window)
6623 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6624 closed' event. So we reset tip_window here. */
6625 tip_window = NULL;
6627 free_frame_menubar (f);
6629 if (FRAME_FACE_CACHE (f))
6630 free_frame_faces (f);
6632 x_free_gcs (f);
6634 if (FRAME_SIZE_HINTS (f))
6635 xfree (FRAME_SIZE_HINTS (f));
6637 xfree (f->output_data.mac);
6638 f->output_data.mac = NULL;
6640 if (f == dpyinfo->x_focus_frame)
6642 dpyinfo->x_focus_frame = 0;
6643 #if USE_MAC_FONT_PANEL
6644 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
6645 #endif
6647 if (f == dpyinfo->x_focus_event_frame)
6648 dpyinfo->x_focus_event_frame = 0;
6649 if (f == dpyinfo->x_highlight_frame)
6650 dpyinfo->x_highlight_frame = 0;
6652 if (f == dpyinfo->mouse_face_mouse_frame)
6654 dpyinfo->mouse_face_beg_row
6655 = dpyinfo->mouse_face_beg_col = -1;
6656 dpyinfo->mouse_face_end_row
6657 = dpyinfo->mouse_face_end_col = -1;
6658 dpyinfo->mouse_face_window = Qnil;
6659 dpyinfo->mouse_face_deferred_gc = 0;
6660 dpyinfo->mouse_face_mouse_frame = 0;
6663 UNBLOCK_INPUT;
6667 /* Destroy the X window of frame F. */
6669 void
6670 x_destroy_window (f)
6671 struct frame *f;
6673 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6675 x_free_frame_resources (f);
6677 dpyinfo->reference_count--;
6681 /* Setting window manager hints. */
6683 /* Set the normal size hints for the window manager, for frame F.
6684 FLAGS is the flags word to use--or 0 meaning preserve the flags
6685 that the window now has.
6686 If USER_POSITION is nonzero, we set the USPosition
6687 flag (this is useful when FLAGS is 0). */
6688 void
6689 x_wm_set_size_hint (f, flags, user_position)
6690 struct frame *f;
6691 long flags;
6692 int user_position;
6694 int base_width, base_height, width_inc, height_inc;
6695 int min_rows = 0, min_cols = 0;
6696 XSizeHints *size_hints;
6698 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6699 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6700 width_inc = FRAME_COLUMN_WIDTH (f);
6701 height_inc = FRAME_LINE_HEIGHT (f);
6703 check_frame_size (f, &min_rows, &min_cols);
6705 size_hints = FRAME_SIZE_HINTS (f);
6706 if (size_hints == NULL)
6708 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6709 bzero (size_hints, sizeof (XSizeHints));
6712 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6713 size_hints->width_inc = width_inc;
6714 size_hints->height_inc = height_inc;
6715 size_hints->min_width = base_width + min_cols * width_inc;
6716 size_hints->min_height = base_height + min_rows * height_inc;
6717 size_hints->base_width = base_width;
6718 size_hints->base_height = base_height;
6720 if (flags)
6721 size_hints->flags = flags;
6722 else if (user_position)
6724 size_hints->flags &= ~ PPosition;
6725 size_hints->flags |= USPosition;
6729 #if 0 /* MAC_TODO: hide application instead of iconify? */
6730 /* Used for IconicState or NormalState */
6732 void
6733 x_wm_set_window_state (f, state)
6734 struct frame *f;
6735 int state;
6737 #ifdef USE_X_TOOLKIT
6738 Arg al[1];
6740 XtSetArg (al[0], XtNinitialState, state);
6741 XtSetValues (f->output_data.x->widget, al, 1);
6742 #else /* not USE_X_TOOLKIT */
6743 Window window = FRAME_X_WINDOW (f);
6745 f->output_data.x->wm_hints.flags |= StateHint;
6746 f->output_data.x->wm_hints.initial_state = state;
6748 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6749 #endif /* not USE_X_TOOLKIT */
6752 void
6753 x_wm_set_icon_pixmap (f, pixmap_id)
6754 struct frame *f;
6755 int pixmap_id;
6757 Pixmap icon_pixmap;
6759 #ifndef USE_X_TOOLKIT
6760 Window window = FRAME_X_WINDOW (f);
6761 #endif
6763 if (pixmap_id > 0)
6765 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6766 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6768 else
6770 /* It seems there is no way to turn off use of an icon pixmap.
6771 The following line does it, only if no icon has yet been created,
6772 for some window managers. But with mwm it crashes.
6773 Some people say it should clear the IconPixmapHint bit in this case,
6774 but that doesn't work, and the X consortium said it isn't the
6775 right thing at all. Since there is no way to win,
6776 best to explicitly give up. */
6777 #if 0
6778 f->output_data.x->wm_hints.icon_pixmap = None;
6779 #else
6780 return;
6781 #endif
6784 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6787 Arg al[1];
6788 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6789 XtSetValues (f->output_data.x->widget, al, 1);
6792 #else /* not USE_X_TOOLKIT */
6794 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6795 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6797 #endif /* not USE_X_TOOLKIT */
6800 #endif /* MAC_TODO */
6802 void
6803 x_wm_set_icon_position (f, icon_x, icon_y)
6804 struct frame *f;
6805 int icon_x, icon_y;
6807 #if 0 /* MAC_TODO: no icons on Mac */
6808 #ifdef USE_X_TOOLKIT
6809 Window window = XtWindow (f->output_data.x->widget);
6810 #else
6811 Window window = FRAME_X_WINDOW (f);
6812 #endif
6814 f->output_data.x->wm_hints.flags |= IconPositionHint;
6815 f->output_data.x->wm_hints.icon_x = icon_x;
6816 f->output_data.x->wm_hints.icon_y = icon_y;
6818 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6819 #endif /* MAC_TODO */
6823 /***********************************************************************
6824 XLFD Pattern Match
6825 ***********************************************************************/
6827 /* An XLFD pattern is divided into blocks delimited by '*'. This
6828 structure holds information for each block. */
6829 struct xlfdpat_block
6831 /* Length of the pattern string in this block. Non-zero except for
6832 the first and the last blocks. */
6833 int len;
6835 /* Pattern string except the last character in this block. The last
6836 character is replaced with NUL in order to use it as a
6837 sentinel. */
6838 unsigned char *pattern;
6840 /* Last character of the pattern string. Must not be '?'. */
6841 unsigned char last_char;
6843 /* One of the tables for the Boyer-Moore string search. It
6844 specifies the number of positions to proceed for each character
6845 with which the match fails. */
6846 int skip[256];
6848 /* The skip value for the last character in the above `skip' is
6849 assigned to `infinity' in order to simplify a loop condition.
6850 The original value is saved here. */
6851 int last_char_skip;
6854 struct xlfdpat
6856 /* Normalized pattern string. "Normalized" means that capital
6857 letters are lowered, blocks are not empty except the first and
6858 the last ones, and trailing '?'s in a block that is not the last
6859 one are moved to the next one. The last character in each block
6860 is replaced with NUL. */
6861 unsigned char *buf;
6863 /* Number of characters except '*'s and trailing '?'s in the
6864 normalized pattern string. */
6865 int nchars;
6867 /* Number of trailing '?'s in the normalized pattern string. */
6868 int trailing_anychars;
6870 /* Number of blocks and information for each block. The latter is
6871 NULL if the pattern is exact (no '*' or '?' in it). */
6872 int nblocks;
6873 struct xlfdpat_block *blocks;
6876 static void
6877 xlfdpat_destroy (pat)
6878 struct xlfdpat *pat;
6880 if (pat)
6882 if (pat->buf)
6884 if (pat->blocks)
6885 xfree (pat->blocks);
6886 xfree (pat->buf);
6888 xfree (pat);
6892 static struct xlfdpat *
6893 xlfdpat_create (pattern)
6894 const char *pattern;
6896 struct xlfdpat *pat;
6897 int nblocks, i, skip;
6898 unsigned char last_char, *p, *q, *anychar_head;
6899 const unsigned char *ptr;
6900 struct xlfdpat_block *blk;
6902 pat = xmalloc (sizeof (struct xlfdpat));
6903 pat->buf = xmalloc (strlen (pattern) + 1);
6905 /* Normalize the pattern string and store it to `pat->buf'. */
6906 nblocks = 0;
6907 anychar_head = NULL;
6908 q = pat->buf;
6909 last_char = '\0';
6910 for (ptr = pattern; *ptr; ptr++)
6912 unsigned char c = *ptr;
6914 if (c == '*')
6915 if (last_char == '*')
6916 /* ...a** -> ...a* */
6917 continue;
6918 else
6920 if (last_char == '?')
6922 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6923 /* ...*??* -> ...*?? */
6924 continue;
6925 else
6926 /* ...a??* -> ...a*?? */
6928 *anychar_head++ = '*';
6929 c = '?';
6932 nblocks++;
6934 else if (c == '?')
6936 if (last_char != '?')
6937 anychar_head = q;
6939 else
6940 /* On Mac OS X 10.3, tolower also converts non-ASCII
6941 characters for some locales. */
6942 if (isascii (c))
6943 c = tolower (c);
6945 *q++ = last_char = c;
6947 *q = '\0';
6948 nblocks++;
6949 pat->nblocks = nblocks;
6950 if (last_char != '?')
6951 pat->trailing_anychars = 0;
6952 else
6954 pat->trailing_anychars = q - anychar_head;
6955 q = anychar_head;
6957 pat->nchars = q - pat->buf - (nblocks - 1);
6959 if (anychar_head == NULL && nblocks == 1)
6961 /* The pattern is exact. */
6962 pat->blocks = NULL;
6963 return pat;
6966 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6968 /* Divide the normalized pattern into blocks. */
6969 p = pat->buf;
6970 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6972 blk->pattern = p;
6973 while (*p != '*')
6974 p++;
6975 blk->len = p - blk->pattern;
6976 p++;
6978 blk->pattern = p;
6979 blk->len = q - blk->pattern;
6981 /* Setup a table for the Boyer-Moore string search. */
6982 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6983 if (blk->len != 0)
6985 blk->last_char = blk->pattern[blk->len - 1];
6986 blk->pattern[blk->len - 1] = '\0';
6988 for (skip = 1; skip < blk->len; skip++)
6989 if (blk->pattern[blk->len - skip - 1] == '?')
6990 break;
6992 for (i = 0; i < 256; i++)
6993 blk->skip[i] = skip;
6995 p = blk->pattern + (blk->len - skip);
6996 while (--skip > 0)
6997 blk->skip[*p++] = skip;
6999 blk->last_char_skip = blk->skip[blk->last_char];
7002 return pat;
7005 static INLINE int
7006 xlfdpat_exact_p (pat)
7007 struct xlfdpat *pat;
7009 return pat->blocks == NULL;
7012 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
7013 that the pattern in *BLK matches with its prefix. Return NULL
7014 there is no such strings. STRING must be lowered in advance. */
7016 static const char *
7017 xlfdpat_block_match_1 (blk, string, start_max)
7018 struct xlfdpat_block *blk;
7019 const unsigned char *string;
7020 int start_max;
7022 int start, infinity;
7023 unsigned char *p;
7024 const unsigned char *s;
7026 xassert (blk->len > 0);
7027 xassert (start_max + blk->len <= strlen (string));
7028 xassert (blk->last_char != '?');
7030 /* See the comments in the function `boyer_moore' (search.c) for the
7031 use of `infinity'. */
7032 infinity = start_max + blk->len + 1;
7033 blk->skip[blk->last_char] = infinity;
7035 start = 0;
7038 /* Check the last character of the pattern. */
7039 s = string + blk->len - 1;
7042 start += blk->skip[*(s + start)];
7044 while (start <= start_max);
7046 if (start < infinity)
7047 /* Couldn't find the last character. */
7048 return NULL;
7050 /* No less than `infinity' means we could find the last
7051 character at `s[start - infinity]'. */
7052 start -= infinity;
7054 /* Check the remaining characters. We prefer making no-'?'
7055 cases faster because the use of '?' is really rare. */
7056 p = blk->pattern;
7057 s = string + start;
7060 while (*p++ == *s++)
7063 while (*(p - 1) == '?');
7065 if (*(p - 1) == '\0')
7066 /* Matched. */
7067 return string + start;
7069 /* Didn't match. */
7070 start += blk->last_char_skip;
7072 while (start <= start_max);
7074 return NULL;
7077 #define xlfdpat_block_match(b, s, m) \
7078 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
7079 : xlfdpat_block_match_1 (b, s, m))
7081 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
7082 matches with STRING. STRING must be lowered in advance. */
7084 static int
7085 xlfdpat_match (pat, string)
7086 struct xlfdpat *pat;
7087 const unsigned char *string;
7089 int str_len, nblocks, i, start_max;
7090 struct xlfdpat_block *blk;
7091 const unsigned char *s;
7093 xassert (pat->nblocks > 0);
7095 if (xlfdpat_exact_p (pat))
7096 return strcmp (pat->buf, string) == 0;
7098 /* The number of the characters in the string must not be smaller
7099 than that in the pattern. */
7100 str_len = strlen (string);
7101 if (str_len < pat->nchars + pat->trailing_anychars)
7102 return 0;
7104 /* Chop off the trailing '?'s. */
7105 str_len -= pat->trailing_anychars;
7107 /* The last block. When it is non-empty, it must match at the end
7108 of the string. */
7109 nblocks = pat->nblocks;
7110 blk = pat->blocks + (nblocks - 1);
7111 if (nblocks == 1)
7112 /* The last block is also the first one. */
7113 return (str_len == blk->len
7114 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
7115 else if (blk->len != 0)
7116 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
7117 return 0;
7119 /* The first block. When it is non-empty, it must match at the
7120 beginning of the string. */
7121 blk = pat->blocks;
7122 if (blk->len != 0)
7124 s = xlfdpat_block_match (blk, string, 0);
7125 if (s == NULL)
7126 return 0;
7127 string = s + blk->len;
7130 /* The rest of the blocks. */
7131 start_max = str_len - pat->nchars;
7132 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
7134 s = xlfdpat_block_match (blk, string, start_max);
7135 if (s == NULL)
7136 return 0;
7137 start_max -= s - string;
7138 string = s + blk->len;
7141 return 1;
7145 /***********************************************************************
7146 Fonts
7147 ***********************************************************************/
7149 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
7151 struct font_info *
7152 x_get_font_info (f, font_idx)
7153 FRAME_PTR f;
7154 int font_idx;
7156 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
7159 /* the global font name table */
7160 static char **font_name_table = NULL;
7161 static int font_name_table_size = 0;
7162 static int font_name_count = 0;
7164 /* Alist linking font family names to Font Manager font family
7165 references (which can also be used as QuickDraw font IDs). We use
7166 an alist because hash tables are not ready when the terminal frame
7167 for Mac OS Classic is created. */
7168 static Lisp_Object fm_font_family_alist;
7169 #if USE_ATSUI
7170 /* Hash table linking font family names to ATSU font IDs. */
7171 static Lisp_Object atsu_font_id_hash;
7172 /* Alist linking Font Manager style to face attributes. */
7173 static Lisp_Object fm_style_face_attributes_alist;
7174 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
7175 #endif
7177 /* Alist linking character set strings to Mac text encoding and Emacs
7178 coding system. */
7179 static Lisp_Object Vmac_charset_info_alist;
7181 static Lisp_Object
7182 create_text_encoding_info_alist ()
7184 Lisp_Object result = Qnil, rest;
7186 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
7188 Lisp_Object charset_info = XCAR (rest);
7189 Lisp_Object charset, coding_system, text_encoding;
7190 Lisp_Object existing_info;
7192 if (!(CONSP (charset_info)
7193 && (charset = XCAR (charset_info),
7194 STRINGP (charset))
7195 && CONSP (XCDR (charset_info))
7196 && (text_encoding = XCAR (XCDR (charset_info)),
7197 INTEGERP (text_encoding))
7198 && CONSP (XCDR (XCDR (charset_info)))
7199 && (coding_system = XCAR (XCDR (XCDR (charset_info))),
7200 SYMBOLP (coding_system))))
7201 continue;
7203 existing_info = assq_no_quit (text_encoding, result);
7204 if (NILP (existing_info))
7205 result = Fcons (list3 (text_encoding, coding_system, charset),
7206 result);
7207 else
7208 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
7209 XSETCDR (XCDR (existing_info),
7210 Fcons (charset, XCDR (XCDR (existing_info))));
7213 return result;
7217 static void
7218 decode_mac_font_name (name, size, coding_system)
7219 char *name;
7220 int size;
7221 Lisp_Object coding_system;
7223 struct coding_system coding;
7224 char *buf, *p;
7226 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
7228 for (p = name; *p; p++)
7229 if (!isascii (*p) || iscntrl (*p))
7230 break;
7232 if (*p)
7234 setup_coding_system (coding_system, &coding);
7235 coding.src_multibyte = 0;
7236 coding.dst_multibyte = 1;
7237 coding.mode |= CODING_MODE_LAST_BLOCK;
7238 coding.composing = COMPOSITION_DISABLED;
7239 buf = (char *) alloca (size);
7241 decode_coding (&coding, name, buf, strlen (name), size - 1);
7242 bcopy (buf, name, coding.produced);
7243 name[coding.produced] = '\0';
7247 /* If there's just one occurrence of '-' in the family name, it is
7248 replaced with '_'. (More than one occurrence of '-' means a
7249 "FOUNDRY-FAMILY-CHARSET"-style name.) */
7250 p = strchr (name, '-');
7251 if (p && strchr (p + 1, '-') == NULL)
7252 *p = '_';
7254 for (p = name; *p; p++)
7255 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7256 for some locales. */
7257 if (isascii (*p))
7258 *p = tolower (*p);
7262 static char *
7263 mac_to_x_fontname (name, size, style, charset)
7264 const char *name;
7265 int size;
7266 Style style;
7267 char *charset;
7269 Str31 foundry, cs;
7270 Str255 family;
7271 char xf[256], *result;
7272 unsigned char *p;
7274 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
7275 charset = cs;
7276 else
7278 strcpy(foundry, "Apple");
7279 strcpy(family, name);
7282 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7283 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
7284 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
7286 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
7287 sprintf (result, "-%s-%s-%s", foundry, family, xf);
7288 for (p = result; *p; p++)
7289 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7290 for some locales. */
7291 if (isascii (*p))
7292 *p = tolower (*p);
7293 return result;
7297 /* Parse fully-specified and instantiated X11 font spec XF, and store
7298 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7299 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7300 caller must allocate at least 256 and 32 bytes respectively. For
7301 ordinary Mac fonts, the value stored to FAMILY should just be their
7302 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7303 intlfonts collection contain their charset designation in their
7304 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7305 types of font names are handled accordingly. */
7307 const int kDefaultFontSize = 12;
7309 static int
7310 parse_x_font_name (xf, family, size, style, charset)
7311 const char *xf;
7312 char *family;
7313 int *size;
7314 Style *style;
7315 char *charset;
7317 Str31 foundry, weight;
7318 int point_size, avgwidth;
7319 char slant[2], *p;
7321 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7322 foundry, family, weight, slant, size,
7323 &point_size, &avgwidth, charset) != 8
7324 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7325 foundry, family, weight, slant, size,
7326 &point_size, &avgwidth, charset) != 8)
7327 return 0;
7329 if (*size == 0)
7331 if (point_size > 0)
7332 *size = point_size / 10;
7333 else if (avgwidth > 0)
7334 *size = avgwidth / 10;
7336 if (*size == 0)
7337 *size = kDefaultFontSize;
7339 *style = normal;
7340 if (strcmp (weight, "bold") == 0)
7341 *style |= bold;
7342 if (*slant == 'i')
7343 *style |= italic;
7345 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
7347 int foundry_len = strlen (foundry), family_len = strlen (family);
7349 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
7351 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7352 but take overlap into account. */
7353 memmove (family + foundry_len + 1, family, family_len);
7354 memcpy (family, foundry, foundry_len);
7355 family[foundry_len] = '-';
7356 family[foundry_len + 1 + family_len] = '-';
7357 strcpy (family + foundry_len + 1 + family_len + 1, charset);
7359 else
7360 return 0;
7363 for (p = family; *p; p++)
7364 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7365 for some locales. */
7366 if (isascii (*p))
7367 *p = tolower (*p);
7369 return 1;
7373 static void
7374 add_font_name_table_entry (char *font_name)
7376 if (font_name_table_size == 0)
7378 font_name_table_size = 256;
7379 font_name_table = (char **)
7380 xmalloc (font_name_table_size * sizeof (char *));
7382 else if (font_name_count + 1 >= font_name_table_size)
7384 font_name_table_size *= 2;
7385 font_name_table = (char **)
7386 xrealloc (font_name_table,
7387 font_name_table_size * sizeof (char *));
7390 font_name_table[font_name_count++] = font_name;
7393 static void
7394 add_mac_font_name (name, size, style, charset)
7395 const char *name;
7396 int size;
7397 Style style;
7398 const char *charset;
7400 if (size > 0)
7401 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
7402 else
7404 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
7405 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
7406 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
7407 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
7408 charset));
7412 #if USE_ATSUI
7413 static FMFontStyle
7414 fm_get_style_from_font (font)
7415 FMFont font;
7417 OSStatus err;
7418 FMFontStyle style = normal;
7419 ByteCount len;
7420 UInt16 mac_style;
7421 FMFontFamily font_family;
7422 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
7424 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
7425 some font (e.g., Optima) even if it is `bold'. */
7426 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
7427 sizeof (mac_style), &mac_style, &len);
7428 if (err == noErr
7429 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
7430 style = EndianU16_BtoN (mac_style);
7431 else
7432 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
7434 return style;
7437 static ATSUFontID
7438 atsu_find_font_from_family_name (family)
7439 const char *family;
7441 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
7442 unsigned hash_code;
7443 int i;
7444 Lisp_Object rest, best;
7445 FMFontStyle min_style, style;
7447 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
7448 &hash_code);
7449 if (i < 0)
7450 return kATSUInvalidFontID;
7452 rest = HASH_VALUE (h, i);
7453 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
7454 return cons_to_long (rest);
7456 rest = Fnreverse (rest);
7457 best = XCAR (rest);
7458 rest = XCDR (rest);
7459 if (!NILP (rest)
7460 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
7463 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
7464 if (style < min_style)
7466 best = XCAR (rest);
7467 if (style == normal)
7468 break;
7469 else
7470 min_style = style;
7472 rest = XCDR (rest);
7474 while (!NILP (rest));
7476 HASH_VALUE (h, i) = best;
7477 return cons_to_long (best);
7480 static Lisp_Object
7481 fm_style_to_face_attributes (fm_style)
7482 FMFontStyle fm_style;
7484 Lisp_Object tem;
7486 fm_style &= (bold | italic);
7487 tem = assq_no_quit (make_number (fm_style),
7488 fm_style_face_attributes_alist);
7489 if (!NILP (tem))
7490 return XCDR (tem);
7492 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
7493 QCslant, fm_style & italic ? Qitalic : Qnormal);
7494 fm_style_face_attributes_alist =
7495 Fcons (Fcons (make_number (fm_style), tem),
7496 fm_style_face_attributes_alist);
7498 return tem;
7501 static Lisp_Object
7502 atsu_find_font_family_name (font_id)
7503 ATSUFontID font_id;
7505 OSStatus err;
7506 ByteCount len;
7507 Lisp_Object family = Qnil;
7509 err = ATSUFindFontName (font_id, kFontFamilyName,
7510 kFontMacintoshPlatform, kFontNoScript,
7511 kFontNoLanguage, 0, NULL, &len, NULL);
7512 if (err == noErr)
7514 family = make_uninit_string (len);
7515 err = ATSUFindFontName (font_id, kFontFamilyName,
7516 kFontMacintoshPlatform, kFontNoScript,
7517 kFontNoLanguage, len, SDATA (family),
7518 NULL, NULL);
7520 if (err == noErr)
7521 decode_mac_font_name (SDATA (family), len + 1, Qnil);
7523 return family;
7526 Lisp_Object
7527 mac_atsu_font_face_attributes (font_id)
7528 ATSUFontID font_id;
7530 Lisp_Object family, style_attrs;
7532 family = atsu_find_font_family_name (font_id);
7533 if (NILP (family))
7534 return Qnil;
7535 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
7536 return Fcons (QCfamily, Fcons (family, style_attrs));
7538 #endif
7540 /* Sets up the table font_name_table to contain the list of all fonts
7541 in the system the first time the table is used so that the Resource
7542 Manager need not be accessed every time this information is
7543 needed. */
7545 static void
7546 init_font_name_table ()
7548 #if TARGET_API_MAC_CARBON
7549 FMFontFamilyIterator ffi;
7550 FMFontFamilyInstanceIterator ffii;
7551 FMFontFamily ff;
7552 Lisp_Object text_encoding_info_alist;
7553 struct gcpro gcpro1;
7555 text_encoding_info_alist = create_text_encoding_info_alist ();
7557 #if USE_ATSUI
7558 #if USE_CG_TEXT_DRAWING
7559 init_cg_text_anti_aliasing_threshold ();
7560 #endif
7561 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
7562 text_encoding_info_alist)))
7564 OSStatus err;
7565 struct Lisp_Hash_Table *h;
7566 unsigned hash_code;
7567 ItemCount nfonts, i;
7568 ATSUFontID *font_ids = NULL;
7569 Lisp_Object prev_family = Qnil;
7570 int j;
7572 atsu_font_id_hash =
7573 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
7574 make_float (DEFAULT_REHASH_SIZE),
7575 make_float (DEFAULT_REHASH_THRESHOLD),
7576 Qnil, Qnil, Qnil);
7577 h = XHASH_TABLE (atsu_font_id_hash);
7579 err = ATSUFontCount (&nfonts);
7580 if (err == noErr)
7582 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
7583 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
7585 if (err == noErr)
7586 for (i = 0; i < nfonts; i++)
7588 Lisp_Object family;
7590 family = atsu_find_font_family_name (font_ids[i]);
7591 if (NILP (family) || SREF (family, 0) == '.')
7592 continue;
7593 if (!NILP (Fequal (prev_family, family)))
7594 family = prev_family;
7595 else
7596 j = hash_lookup (h, family, &hash_code);
7597 if (j < 0)
7599 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
7600 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
7601 Qnil), hash_code);
7603 else if (EQ (prev_family, family))
7604 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
7605 HASH_VALUE (h, j));
7606 prev_family = family;
7608 if (font_ids)
7609 xfree (font_ids);
7611 #endif
7613 /* Create a dummy instance iterator here to avoid creating and
7614 destroying it in the loop. */
7615 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
7616 return;
7617 /* Create an iterator to enumerate the font families. */
7618 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
7619 != noErr)
7621 FMDisposeFontFamilyInstanceIterator (&ffii);
7622 return;
7625 GCPRO1 (text_encoding_info_alist);
7627 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
7629 Str255 name;
7630 FMFont font;
7631 FMFontStyle style;
7632 FMFontSize size;
7633 TextEncoding encoding;
7634 TextEncodingBase sc;
7635 Lisp_Object text_encoding_info, family;
7637 if (FMGetFontFamilyName (ff, name) != noErr)
7638 continue;
7639 p2cstr (name);
7640 if (*name == '.')
7641 continue;
7643 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
7644 continue;
7645 sc = GetTextEncodingBase (encoding);
7646 text_encoding_info = assq_no_quit (make_number (sc),
7647 text_encoding_info_alist);
7648 if (NILP (text_encoding_info))
7649 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
7650 text_encoding_info_alist);
7651 decode_mac_font_name (name, sizeof (name),
7652 XCAR (XCDR (text_encoding_info)));
7653 family = build_string (name);
7654 if (!NILP (Fassoc (family, fm_font_family_alist)))
7655 continue;
7656 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
7657 fm_font_family_alist);
7659 /* Point the instance iterator at the current font family. */
7660 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
7661 continue;
7663 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
7664 == noErr)
7666 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7668 if (size > 0 || style == normal)
7669 for (; !NILP (rest); rest = XCDR (rest))
7670 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
7674 UNGCPRO;
7676 /* Dispose of the iterators. */
7677 FMDisposeFontFamilyIterator (&ffi);
7678 FMDisposeFontFamilyInstanceIterator (&ffii);
7679 #else /* !TARGET_API_MAC_CARBON */
7680 GrafPtr port;
7681 SInt16 fontnum, old_fontnum;
7682 int num_mac_fonts = CountResources('FOND');
7683 int i, j;
7684 Handle font_handle, font_handle_2;
7685 short id, scriptcode;
7686 ResType type;
7687 Str255 name;
7688 struct FontAssoc *fat;
7689 struct AsscEntry *assc_entry;
7690 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
7691 struct gcpro gcpro1;
7693 GetPort (&port); /* save the current font number used */
7694 old_fontnum = port->txFont;
7696 text_encoding_info_alist = create_text_encoding_info_alist ();
7698 GCPRO1 (text_encoding_info_alist);
7700 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
7702 font_handle = GetIndResource ('FOND', i);
7703 if (!font_handle)
7704 continue;
7706 GetResInfo (font_handle, &id, &type, name);
7707 GetFNum (name, &fontnum);
7708 p2cstr (name);
7709 if (fontnum == 0 || *name == '.')
7710 continue;
7712 TextFont (fontnum);
7713 scriptcode = FontToScript (fontnum);
7714 text_encoding_info = assq_no_quit (make_number (scriptcode),
7715 text_encoding_info_alist);
7716 if (NILP (text_encoding_info))
7717 text_encoding_info = assq_no_quit (make_number (smRoman),
7718 text_encoding_info_alist);
7719 decode_mac_font_name (name, sizeof (name),
7720 XCAR (XCDR (text_encoding_info)));
7721 family = build_string (name);
7722 if (!NILP (Fassoc (family, fm_font_family_alist)))
7723 continue;
7724 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
7725 fm_font_family_alist);
7728 HLock (font_handle);
7730 if (GetResourceSizeOnDisk (font_handle)
7731 >= sizeof (struct FamRec))
7733 fat = (struct FontAssoc *) (*font_handle
7734 + sizeof (struct FamRec));
7735 assc_entry
7736 = (struct AsscEntry *) (*font_handle
7737 + sizeof (struct FamRec)
7738 + sizeof (struct FontAssoc));
7740 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
7742 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7744 for (; !NILP (rest); rest = XCDR (rest))
7745 add_mac_font_name (name, assc_entry->fontSize,
7746 assc_entry->fontStyle,
7747 SDATA (XCAR (rest)));
7751 HUnlock (font_handle);
7752 font_handle_2 = GetNextFOND (font_handle);
7753 ReleaseResource (font_handle);
7754 font_handle = font_handle_2;
7756 while (ResError () == noErr && font_handle);
7759 UNGCPRO;
7761 TextFont (old_fontnum);
7762 #endif /* !TARGET_API_MAC_CARBON */
7766 void
7767 mac_clear_font_name_table ()
7769 int i;
7771 for (i = 0; i < font_name_count; i++)
7772 xfree (font_name_table[i]);
7773 xfree (font_name_table);
7774 font_name_table = NULL;
7775 font_name_table_size = font_name_count = 0;
7776 fm_font_family_alist = Qnil;
7780 enum xlfd_scalable_field_index
7782 XLFD_SCL_PIXEL_SIZE,
7783 XLFD_SCL_POINT_SIZE,
7784 XLFD_SCL_AVGWIDTH,
7785 XLFD_SCL_LAST
7788 static const int xlfd_scalable_fields[] =
7790 6, /* PIXEL_SIZE */
7791 7, /* POINT_SIZE */
7792 11, /* AVGWIDTH */
7796 static Lisp_Object
7797 mac_do_list_fonts (pattern, maxnames)
7798 const char *pattern;
7799 int maxnames;
7801 int i, n_fonts = 0;
7802 Lisp_Object font_list = Qnil;
7803 struct xlfdpat *pat;
7804 char *scaled;
7805 const char *ptr;
7806 int scl_val[XLFD_SCL_LAST], *val;
7807 const int *field;
7808 int exact;
7810 if (font_name_table == NULL) /* Initialize when first used. */
7811 init_font_name_table ();
7813 for (i = 0; i < XLFD_SCL_LAST; i++)
7814 scl_val[i] = -1;
7816 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7817 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7818 fonts are scaled according to the specified size. */
7819 ptr = pattern;
7820 i = 0;
7821 field = xlfd_scalable_fields;
7822 val = scl_val;
7823 if (*ptr == '-')
7826 ptr++;
7827 if (i == *field)
7829 if ('0' <= *ptr && *ptr <= '9')
7831 *val = *ptr++ - '0';
7832 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
7833 *val = *val * 10 + *ptr++ - '0';
7834 if (*ptr != '-')
7835 *val = -1;
7837 field++;
7838 val++;
7840 ptr = strchr (ptr, '-');
7841 i++;
7843 while (ptr && i < 14);
7845 if (i == 14 && ptr == NULL)
7847 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
7848 scl_val[XLFD_SCL_PIXEL_SIZE] =
7849 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
7850 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
7851 : -1));
7852 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
7853 scl_val[XLFD_SCL_POINT_SIZE] =
7854 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7855 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
7856 : -1));
7857 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
7858 scl_val[XLFD_SCL_AVGWIDTH] =
7859 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7860 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
7861 : -1));
7863 else
7864 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
7866 pat = xlfdpat_create (pattern);
7867 if (pat == NULL)
7868 return Qnil;
7870 exact = xlfdpat_exact_p (pat);
7872 for (i = 0; i < font_name_count; i++)
7874 if (xlfdpat_match (pat, font_name_table[i]))
7876 font_list = Fcons (build_string (font_name_table[i]), font_list);
7877 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7878 break;
7880 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
7881 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
7883 int former_len = ptr - font_name_table[i];
7885 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
7886 memcpy (scaled, font_name_table[i], former_len);
7887 sprintf (scaled + former_len,
7888 "-%d-%d-72-72-m-%d-%s",
7889 scl_val[XLFD_SCL_PIXEL_SIZE],
7890 scl_val[XLFD_SCL_POINT_SIZE],
7891 scl_val[XLFD_SCL_AVGWIDTH],
7892 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
7894 if (xlfdpat_match (pat, scaled))
7896 font_list = Fcons (build_string (scaled), font_list);
7897 xfree (scaled);
7898 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7899 break;
7901 else
7902 xfree (scaled);
7906 xlfdpat_destroy (pat);
7908 return font_list;
7911 /* Return a list of names of available fonts matching PATTERN on frame F.
7913 Frame F null means we have not yet created any frame on Mac, and
7914 consult the first display in x_display_list. MAXNAMES sets a limit
7915 on how many fonts to match. */
7917 Lisp_Object
7918 x_list_fonts (f, pattern, size, maxnames)
7919 struct frame *f;
7920 Lisp_Object pattern;
7921 int size, maxnames;
7923 Lisp_Object list = Qnil, patterns, tem, key;
7924 struct mac_display_info *dpyinfo
7925 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
7927 xassert (size <= 0);
7929 patterns = Fassoc (pattern, Valternate_fontname_alist);
7930 if (NILP (patterns))
7931 patterns = Fcons (pattern, Qnil);
7933 for (; CONSP (patterns); patterns = XCDR (patterns))
7935 pattern = XCAR (patterns);
7937 if (!STRINGP (pattern))
7938 continue;
7940 tem = XCAR (XCDR (dpyinfo->name_list_element));
7941 key = Fcons (pattern, make_number (maxnames));
7943 list = Fassoc (key, tem);
7944 if (!NILP (list))
7946 list = Fcdr_safe (list);
7947 /* We have a cashed list. Don't have to get the list again. */
7948 goto label_cached;
7951 BLOCK_INPUT;
7952 list = mac_do_list_fonts (SDATA (pattern), maxnames);
7953 UNBLOCK_INPUT;
7955 /* MAC_TODO: add code for matching outline fonts here */
7957 /* Now store the result in the cache. */
7958 XSETCAR (XCDR (dpyinfo->name_list_element),
7959 Fcons (Fcons (key, list),
7960 XCAR (XCDR (dpyinfo->name_list_element))));
7962 label_cached:
7963 if (NILP (list)) continue; /* Try the remaining alternatives. */
7966 return list;
7970 #if GLYPH_DEBUG
7972 /* Check that FONT is valid on frame F. It is if it can be found in F's
7973 font table. */
7975 static void
7976 x_check_font (f, font)
7977 struct frame *f;
7978 XFontStruct *font;
7980 int i;
7981 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7983 xassert (font != NULL);
7985 for (i = 0; i < dpyinfo->n_fonts; i++)
7986 if (dpyinfo->font_table[i].name
7987 && font == dpyinfo->font_table[i].font)
7988 break;
7990 xassert (i < dpyinfo->n_fonts);
7993 #endif /* GLYPH_DEBUG != 0 */
7995 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7996 Note: There are (broken) X fonts out there with invalid XFontStruct
7997 min_bounds contents. For example, handa@etl.go.jp reports that
7998 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7999 have font->min_bounds.width == 0. */
8001 static INLINE void
8002 x_font_min_bounds (font, w, h)
8003 MacFontStruct *font;
8004 int *w, *h;
8006 *h = FONT_HEIGHT (font);
8007 *w = font->min_bounds.width;
8011 /* Compute the smallest character width and smallest font height over
8012 all fonts available on frame F. Set the members smallest_char_width
8013 and smallest_font_height in F's x_display_info structure to
8014 the values computed. Value is non-zero if smallest_font_height or
8015 smallest_char_width become smaller than they were before. */
8017 static int
8018 x_compute_min_glyph_bounds (f)
8019 struct frame *f;
8021 int i;
8022 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8023 MacFontStruct *font;
8024 int old_width = dpyinfo->smallest_char_width;
8025 int old_height = dpyinfo->smallest_font_height;
8027 dpyinfo->smallest_font_height = 100000;
8028 dpyinfo->smallest_char_width = 100000;
8030 for (i = 0; i < dpyinfo->n_fonts; ++i)
8031 if (dpyinfo->font_table[i].name)
8033 struct font_info *fontp = dpyinfo->font_table + i;
8034 int w, h;
8036 font = (MacFontStruct *) fontp->font;
8037 xassert (font != (MacFontStruct *) ~0);
8038 x_font_min_bounds (font, &w, &h);
8040 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8041 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8044 xassert (dpyinfo->smallest_char_width > 0
8045 && dpyinfo->smallest_font_height > 0);
8047 return (dpyinfo->n_fonts == 1
8048 || dpyinfo->smallest_char_width < old_width
8049 || dpyinfo->smallest_font_height < old_height);
8053 /* Determine whether given string is a fully-specified XLFD: all 14
8054 fields are present, none is '*'. */
8056 static int
8057 is_fully_specified_xlfd (p)
8058 const char *p;
8060 int i;
8061 char *q;
8063 if (*p != '-')
8064 return 0;
8066 for (i = 0; i < 13; i++)
8068 q = strchr (p + 1, '-');
8069 if (q == NULL)
8070 return 0;
8071 if (q - p == 2 && *(p + 1) == '*')
8072 return 0;
8073 p = q;
8076 if (strchr (p + 1, '-') != NULL)
8077 return 0;
8079 if (*(p + 1) == '*' && *(p + 2) == '\0')
8080 return 0;
8082 return 1;
8086 /* mac_load_query_font creates and returns an internal representation
8087 for a font in a MacFontStruct struct. There is really no concept
8088 corresponding to "loading" a font on the Mac. But we check its
8089 existence and find the font number and all other information for it
8090 and store them in the returned MacFontStruct. */
8092 static MacFontStruct *
8093 mac_load_query_font (f, fontname)
8094 struct frame *f;
8095 char *fontname;
8097 int size;
8098 char *name;
8099 Str255 family;
8100 Str31 charset;
8101 SInt16 fontnum;
8102 #if USE_ATSUI
8103 static ATSUFontID font_id;
8104 ATSUStyle mac_style = NULL;
8105 #endif
8106 Style fontface;
8107 #if TARGET_API_MAC_CARBON
8108 TextEncoding encoding;
8109 int scriptcode;
8110 #else
8111 short scriptcode;
8112 #endif
8113 MacFontStruct *font;
8114 XCharStruct *space_bounds = NULL, *pcm;
8116 if (is_fully_specified_xlfd (fontname))
8117 name = fontname;
8118 else
8120 Lisp_Object matched_fonts;
8122 matched_fonts = mac_do_list_fonts (fontname, 1);
8123 if (NILP (matched_fonts))
8124 return NULL;
8125 name = SDATA (XCAR (matched_fonts));
8128 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
8129 return NULL;
8131 #if USE_ATSUI
8132 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
8134 OSStatus err;
8135 static const ATSUAttributeTag tags[] =
8136 {kATSUFontTag, kATSUSizeTag,
8137 kATSUQDBoldfaceTag, kATSUQDItalicTag};
8138 static const ByteCount sizes[] =
8139 {sizeof (ATSUFontID), sizeof (Fixed),
8140 sizeof (Boolean), sizeof (Boolean)};
8141 static Fixed size_fixed;
8142 static Boolean bold_p, italic_p;
8143 static const ATSUAttributeValuePtr values[] =
8144 {&font_id, &size_fixed,
8145 &bold_p, &italic_p};
8146 static const ATSUFontFeatureType types[] =
8147 {kAllTypographicFeaturesType, kDiacriticsType};
8148 static const ATSUFontFeatureSelector selectors[] =
8149 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
8150 FMFontStyle style;
8152 font_id = atsu_find_font_from_family_name (family);
8153 if (font_id == kATSUInvalidFontID)
8154 return NULL;
8155 size_fixed = Long2Fix (size);
8156 bold_p = (fontface & bold) != 0;
8157 italic_p = (fontface & italic) != 0;
8158 err = ATSUCreateStyle (&mac_style);
8159 if (err != noErr)
8160 return NULL;
8161 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
8162 types, selectors);
8163 if (err != noErr)
8164 return NULL;
8165 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
8166 tags, sizes, values);
8167 if (err != noErr)
8168 return NULL;
8169 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
8170 if (err != noErr)
8171 fontnum = -1;
8172 scriptcode = kTextEncodingMacUnicode;
8174 else
8175 #endif
8177 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
8179 if (NILP (tmp))
8180 return NULL;
8181 fontnum = XINT (XCDR (tmp));
8182 #if TARGET_API_MAC_CARBON
8183 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
8184 return NULL;
8185 scriptcode = GetTextEncodingBase (encoding);
8186 #else
8187 scriptcode = FontToScript (fontnum);
8188 #endif
8191 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
8193 font->mac_fontnum = fontnum;
8194 font->mac_fontsize = size;
8195 font->mac_fontface = fontface;
8196 font->mac_scriptcode = scriptcode;
8197 #if USE_ATSUI
8198 font->mac_style = mac_style;
8199 #if USE_CG_TEXT_DRAWING
8200 font->cg_font = NULL;
8201 font->cg_glyphs = NULL;
8202 #endif
8203 #endif
8205 /* Apple Japanese (SJIS) font is listed as both
8206 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
8207 (Roman script) in init_font_name_table (). The latter should be
8208 treated as a one-byte font. */
8209 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
8210 font->mac_scriptcode = smRoman;
8212 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
8214 #if USE_ATSUI
8215 if (font->mac_style)
8217 OSStatus err;
8218 UniChar c;
8220 font->min_byte1 = 0;
8221 font->max_byte1 = 0xff;
8222 font->min_char_or_byte2 = 0;
8223 font->max_char_or_byte2 = 0xff;
8225 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
8226 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
8227 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
8228 pcm_init (font->bounds.rows[0], 0x100);
8230 #if USE_CG_TEXT_DRAWING
8231 if (fontnum != -1)
8233 FMFontStyle style;
8234 ATSFontRef ats_font;
8236 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
8237 &font_id, &style);
8238 /* Use CG text drawing if italic/bold is not synthesized. */
8239 if (err == noErr && style == fontface)
8241 ats_font = FMGetATSFontRefFromFont (font_id);
8242 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
8246 if (font->cg_font)
8248 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
8249 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
8251 #endif
8252 space_bounds = font->bounds.rows[0] + 0x20;
8253 err = mac_query_char_extents (font->mac_style, 0x20,
8254 &font->ascent, &font->descent,
8255 space_bounds,
8256 #if USE_CG_TEXT_DRAWING
8257 (font->cg_glyphs ? font->cg_glyphs + 0x20
8258 : NULL)
8259 #else
8260 NULL
8261 #endif
8263 if (err != noErr
8264 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
8266 mac_unload_font (&one_mac_display_info, font);
8267 return NULL;
8270 pcm = font->bounds.rows[0];
8271 for (c = 0x21; c <= 0xff; c++)
8273 if (c == 0xad)
8274 /* Soft hyphen is not supported in ATSUI. */
8275 continue;
8276 else if (c == 0x7f)
8278 #if USE_CG_TEXT_DRAWING
8279 if (font->cg_glyphs)
8281 c = 0x9f;
8282 pcm = NULL;
8283 continue;
8285 #endif
8286 break;
8289 mac_query_char_extents (font->mac_style, c, NULL, NULL,
8290 pcm ? pcm + c : NULL,
8291 #if USE_CG_TEXT_DRAWING
8292 (font->cg_glyphs ? font->cg_glyphs + c
8293 : NULL)
8294 #else
8295 NULL
8296 #endif
8299 #if USE_CG_TEXT_DRAWING
8300 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
8302 /* Don't use CG text drawing if font substitution occurs in
8303 ASCII or Latin-1 characters. */
8304 CGFontRelease (font->cg_font);
8305 font->cg_font = NULL;
8306 xfree (font->cg_glyphs);
8307 font->cg_glyphs = NULL;
8308 if (pcm == NULL)
8309 break;
8311 #endif
8314 else
8315 #endif
8317 OSStatus err;
8318 FontInfo the_fontinfo;
8319 int is_two_byte_font;
8321 #if USE_CG_DRAWING
8322 mac_prepare_for_quickdraw (f);
8323 #endif
8324 SetPortWindowPort (FRAME_MAC_WINDOW (f));
8326 TextFont (fontnum);
8327 TextSize (size);
8328 TextFace (fontface);
8330 GetFontInfo (&the_fontinfo);
8332 font->ascent = the_fontinfo.ascent;
8333 font->descent = the_fontinfo.descent;
8335 is_two_byte_font = (font->mac_scriptcode == smJapanese
8336 || font->mac_scriptcode == smTradChinese
8337 || font->mac_scriptcode == smSimpChinese
8338 || font->mac_scriptcode == smKorean);
8340 if (is_two_byte_font)
8342 int char_width;
8344 font->min_byte1 = 0xa1;
8345 font->max_byte1 = 0xfe;
8346 font->min_char_or_byte2 = 0xa1;
8347 font->max_char_or_byte2 = 0xfe;
8349 /* Use the width of an "ideographic space" of that font
8350 because the_fontinfo.widMax returns the wrong width for
8351 some fonts. */
8352 switch (font->mac_scriptcode)
8354 case smJapanese:
8355 font->min_byte1 = 0x81;
8356 font->max_byte1 = 0xfc;
8357 font->min_char_or_byte2 = 0x40;
8358 font->max_char_or_byte2 = 0xfc;
8359 char_width = StringWidth("\p\x81\x40");
8360 break;
8361 case smTradChinese:
8362 font->min_char_or_byte2 = 0x40;
8363 char_width = StringWidth("\p\xa1\x40");
8364 break;
8365 case smSimpChinese:
8366 char_width = StringWidth("\p\xa1\xa1");
8367 break;
8368 case smKorean:
8369 char_width = StringWidth("\p\xa1\xa1");
8370 break;
8373 font->bounds.per_char = NULL;
8375 if (fontface & italic)
8376 font->max_bounds.rbearing = char_width + 1;
8377 else
8378 font->max_bounds.rbearing = char_width;
8379 font->max_bounds.lbearing = 0;
8380 font->max_bounds.width = char_width;
8381 font->max_bounds.ascent = the_fontinfo.ascent;
8382 font->max_bounds.descent = the_fontinfo.descent;
8384 font->min_bounds = font->max_bounds;
8386 else
8388 int c;
8390 font->min_byte1 = font->max_byte1 = 0;
8391 font->min_char_or_byte2 = 0x20;
8392 font->max_char_or_byte2 = 0xff;
8394 font->bounds.per_char =
8395 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
8396 bzero (font->bounds.per_char,
8397 sizeof (XCharStruct) * (0xff - 0x20 + 1));
8399 space_bounds = font->bounds.per_char;
8400 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
8401 &font->descent, space_bounds, NULL);
8402 if (err != noErr || space_bounds->width <= 0)
8404 mac_unload_font (&one_mac_display_info, font);
8405 return NULL;
8408 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
8409 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
8413 if (space_bounds)
8415 int c;
8417 font->min_bounds = font->max_bounds = *space_bounds;
8418 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
8419 if (pcm->width > 0)
8421 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
8422 pcm->lbearing);
8423 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
8424 pcm->rbearing);
8425 font->min_bounds.width = min (font->min_bounds.width,
8426 pcm->width);
8427 font->min_bounds.ascent = min (font->min_bounds.ascent,
8428 pcm->ascent);
8429 font->min_bounds.descent = min (font->min_bounds.descent,
8430 pcm->descent);
8432 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
8433 pcm->lbearing);
8434 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
8435 pcm->rbearing);
8436 font->max_bounds.width = max (font->max_bounds.width,
8437 pcm->width);
8438 font->max_bounds.ascent = max (font->max_bounds.ascent,
8439 pcm->ascent);
8440 font->max_bounds.descent = max (font->max_bounds.descent,
8441 pcm->descent);
8443 if (
8444 #if USE_ATSUI
8445 font->mac_style == NULL &&
8446 #endif
8447 font->max_bounds.width == font->min_bounds.width
8448 && font->min_bounds.lbearing >= 0
8449 && font->max_bounds.rbearing <= font->max_bounds.width)
8451 /* Fixed width and no overhangs. */
8452 xfree (font->bounds.per_char);
8453 font->bounds.per_char = NULL;
8457 #if !defined (MAC_OS8) || USE_ATSUI
8458 /* AppKit and WebKit do some adjustment to the heights of Courier,
8459 Helvetica, and Times. This only works on the environments where
8460 srcCopy text transfer mode is never used. */
8461 if (
8462 #ifdef MAC_OS8 /* implies USE_ATSUI */
8463 font->mac_style &&
8464 #endif
8465 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
8466 || strcmp (family, "times") == 0))
8467 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
8468 #endif
8470 return font;
8474 void
8475 mac_unload_font (dpyinfo, font)
8476 struct mac_display_info *dpyinfo;
8477 XFontStruct *font;
8479 xfree (font->full_name);
8480 #if USE_ATSUI
8481 if (font->mac_style)
8483 int i;
8485 for (i = font->min_byte1; i <= font->max_byte1; i++)
8486 if (font->bounds.rows[i])
8487 xfree (font->bounds.rows[i]);
8488 xfree (font->bounds.rows);
8489 ATSUDisposeStyle (font->mac_style);
8491 else
8492 #endif
8493 if (font->bounds.per_char)
8494 xfree (font->bounds.per_char);
8495 #if USE_CG_TEXT_DRAWING
8496 if (font->cg_font)
8497 CGFontRelease (font->cg_font);
8498 if (font->cg_glyphs)
8499 xfree (font->cg_glyphs);
8500 #endif
8501 xfree (font);
8505 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8506 pointer to the structure font_info while allocating it dynamically.
8507 If SIZE is 0, load any size of font.
8508 If loading is failed, return NULL. */
8510 struct font_info *
8511 x_load_font (f, fontname, size)
8512 struct frame *f;
8513 register char *fontname;
8514 int size;
8516 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8517 Lisp_Object font_names;
8519 /* Get a list of all the fonts that match this name. Once we
8520 have a list of matching fonts, we compare them against the fonts
8521 we already have by comparing names. */
8522 font_names = x_list_fonts (f, build_string (fontname), size, 1);
8524 if (!NILP (font_names))
8526 Lisp_Object tail;
8527 int i;
8529 for (i = 0; i < dpyinfo->n_fonts; i++)
8530 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
8531 if (dpyinfo->font_table[i].name
8532 && (!strcmp (dpyinfo->font_table[i].name,
8533 SDATA (XCAR (tail)))
8534 || !strcmp (dpyinfo->font_table[i].full_name,
8535 SDATA (XCAR (tail)))))
8536 return (dpyinfo->font_table + i);
8538 else
8539 return NULL;
8541 /* Load the font and add it to the table. */
8543 struct MacFontStruct *font;
8544 struct font_info *fontp;
8545 int i;
8547 fontname = (char *) SDATA (XCAR (font_names));
8549 BLOCK_INPUT;
8550 font = mac_load_query_font (f, fontname);
8551 UNBLOCK_INPUT;
8552 if (!font)
8553 return NULL;
8555 /* Find a free slot in the font table. */
8556 for (i = 0; i < dpyinfo->n_fonts; ++i)
8557 if (dpyinfo->font_table[i].name == NULL)
8558 break;
8560 /* If no free slot found, maybe enlarge the font table. */
8561 if (i == dpyinfo->n_fonts
8562 && dpyinfo->n_fonts == dpyinfo->font_table_size)
8564 int sz;
8565 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
8566 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
8567 dpyinfo->font_table
8568 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
8571 fontp = dpyinfo->font_table + i;
8572 if (i == dpyinfo->n_fonts)
8573 ++dpyinfo->n_fonts;
8575 /* Now fill in the slots of *FONTP. */
8576 BLOCK_INPUT;
8577 bzero (fontp, sizeof (*fontp));
8578 fontp->font = font;
8579 fontp->font_idx = i;
8580 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
8581 bcopy (fontname, fontp->name, strlen (fontname) + 1);
8583 if (font->min_bounds.width == font->max_bounds.width)
8585 /* Fixed width font. */
8586 fontp->average_width = fontp->space_width = font->min_bounds.width;
8588 else
8590 XChar2b char2b;
8591 XCharStruct *pcm;
8593 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
8594 pcm = mac_per_char_metric (font, &char2b, 0);
8595 if (pcm)
8596 fontp->space_width = pcm->width;
8597 else
8598 fontp->space_width = FONT_WIDTH (font);
8600 if (pcm)
8602 int width = pcm->width;
8603 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
8604 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
8605 width += pcm->width;
8606 fontp->average_width = width / 95;
8608 else
8609 fontp->average_width = FONT_WIDTH (font);
8612 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
8613 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
8615 fontp->size = font->max_bounds.width;
8616 fontp->height = FONT_HEIGHT (font);
8618 /* For some font, ascent and descent in max_bounds field is
8619 larger than the above value. */
8620 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
8621 if (max_height > fontp->height)
8622 fontp->height = max_height;
8625 /* The slot `encoding' specifies how to map a character
8626 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8627 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8628 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8629 2:0xA020..0xFF7F). For the moment, we don't know which charset
8630 uses this font. So, we set information in fontp->encoding[1]
8631 which is never used by any charset. If mapping can't be
8632 decided, set FONT_ENCODING_NOT_DECIDED. */
8633 if (font->mac_scriptcode == smJapanese)
8634 fontp->encoding[1] = 4;
8635 else
8637 fontp->encoding[1]
8638 = (font->max_byte1 == 0
8639 /* 1-byte font */
8640 ? (font->min_char_or_byte2 < 0x80
8641 ? (font->max_char_or_byte2 < 0x80
8642 ? 0 /* 0x20..0x7F */
8643 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
8644 : 1) /* 0xA0..0xFF */
8645 /* 2-byte font */
8646 : (font->min_byte1 < 0x80
8647 ? (font->max_byte1 < 0x80
8648 ? (font->min_char_or_byte2 < 0x80
8649 ? (font->max_char_or_byte2 < 0x80
8650 ? 0 /* 0x2020..0x7F7F */
8651 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
8652 : 3) /* 0x20A0..0x7FFF */
8653 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
8654 : (font->min_char_or_byte2 < 0x80
8655 ? (font->max_char_or_byte2 < 0x80
8656 ? 2 /* 0xA020..0xFF7F */
8657 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
8658 : 1))); /* 0xA0A0..0xFFFF */
8661 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8662 fontp->baseline_offset
8663 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
8664 ? (long) value : 0);
8665 fontp->relative_compose
8666 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
8667 ? (long) value : 0);
8668 fontp->default_ascent
8669 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
8670 ? (long) value : 0);
8671 #else
8672 fontp->baseline_offset = 0;
8673 fontp->relative_compose = 0;
8674 fontp->default_ascent = 0;
8675 #endif
8677 /* Set global flag fonts_changed_p to non-zero if the font loaded
8678 has a character with a smaller width than any other character
8679 before, or if the font loaded has a smaller height than any
8680 other font loaded before. If this happens, it will make a
8681 glyph matrix reallocation necessary. */
8682 fonts_changed_p |= x_compute_min_glyph_bounds (f);
8683 UNBLOCK_INPUT;
8684 return fontp;
8689 /* Return a pointer to struct font_info of a font named FONTNAME for
8690 frame F. If no such font is loaded, return NULL. */
8692 struct font_info *
8693 x_query_font (f, fontname)
8694 struct frame *f;
8695 register char *fontname;
8697 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8698 int i;
8700 for (i = 0; i < dpyinfo->n_fonts; i++)
8701 if (dpyinfo->font_table[i].name
8702 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
8703 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
8704 return (dpyinfo->font_table + i);
8705 return NULL;
8709 /* Find a CCL program for a font specified by FONTP, and set the member
8710 `encoder' of the structure. */
8712 void
8713 x_find_ccl_program (fontp)
8714 struct font_info *fontp;
8716 Lisp_Object list, elt;
8718 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
8720 elt = XCAR (list);
8721 if (CONSP (elt)
8722 && STRINGP (XCAR (elt))
8723 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
8724 >= 0))
8725 break;
8727 if (! NILP (list))
8729 struct ccl_program *ccl
8730 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
8732 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
8733 xfree (ccl);
8734 else
8735 fontp->font_encoder = ccl;
8739 #if USE_MAC_FONT_PANEL
8740 /* Whether Font Panel has been shown before. The first call to font
8741 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8742 slow. This variable is used for deferring such a call as much as
8743 possible. */
8744 static int font_panel_shown_p = 0;
8747 mac_font_panel_visible_p ()
8749 return font_panel_shown_p && FPIsFontPanelVisible ();
8752 OSStatus
8753 mac_show_hide_font_panel ()
8755 font_panel_shown_p = 1;
8757 return FPShowHideFontPanel ();
8760 OSStatus
8761 mac_set_font_info_for_selection (f, face_id, c)
8762 struct frame *f;
8763 int face_id, c;
8765 OSStatus err;
8766 EventTargetRef target = NULL;
8767 XFontStruct *font = NULL;
8769 if (!mac_font_panel_visible_p ())
8770 return noErr;
8772 if (f)
8774 target = GetWindowEventTarget (FRAME_MAC_WINDOW (f));
8776 if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0))
8778 struct face *face;
8780 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
8781 face = FACE_FROM_ID (f, face_id);
8782 font = face->font;
8786 if (font == NULL)
8787 err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target);
8788 else
8790 if (font->mac_fontnum != -1)
8792 FontSelectionQDStyle qd_style;
8794 qd_style.version = kFontSelectionQDStyleVersionZero;
8795 qd_style.instance.fontFamily = font->mac_fontnum;
8796 qd_style.instance.fontStyle = font->mac_fontface;
8797 qd_style.size = font->mac_fontsize;
8798 qd_style.hasColor = false;
8800 err = SetFontInfoForSelection (kFontSelectionQDType,
8801 1, &qd_style, target);
8803 else
8804 err = SetFontInfoForSelection (kFontSelectionATSUIType,
8805 1, &font->mac_style, target);
8808 return err;
8810 #endif
8813 /* The Mac Event loop code */
8815 #if !TARGET_API_MAC_CARBON
8816 #include <Events.h>
8817 #include <Quickdraw.h>
8818 #include <Balloons.h>
8819 #include <Devices.h>
8820 #include <Fonts.h>
8821 #include <Gestalt.h>
8822 #include <Menus.h>
8823 #include <Processes.h>
8824 #include <Sound.h>
8825 #include <ToolUtils.h>
8826 #include <TextUtils.h>
8827 #include <Dialogs.h>
8828 #include <Script.h>
8829 #include <Types.h>
8830 #include <Resources.h>
8832 #if __MWERKS__
8833 #include <unix.h>
8834 #endif
8835 #endif /* ! TARGET_API_MAC_CARBON */
8837 #define M_APPLE 234
8838 #define I_ABOUT 1
8840 #define DEFAULT_NUM_COLS 80
8842 #define MIN_DOC_SIZE 64
8843 #define MAX_DOC_SIZE 32767
8845 #define EXTRA_STACK_ALLOC (256 * 1024)
8847 #define ARGV_STRING_LIST_ID 129
8848 #define ABOUT_ALERT_ID 128
8849 #define RAM_TOO_LARGE_ALERT_ID 129
8851 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8852 Lisp_Object Qreverse;
8855 /* Modifier associated with the control key, or nil to ignore. */
8856 Lisp_Object Vmac_control_modifier;
8858 /* Modifier associated with the option key, or nil to ignore. */
8859 Lisp_Object Vmac_option_modifier;
8861 /* Modifier associated with the command key, or nil to ignore. */
8862 Lisp_Object Vmac_command_modifier;
8864 /* Modifier associated with the function key, or nil to ignore. */
8865 Lisp_Object Vmac_function_modifier;
8867 /* True if the option and command modifiers should be used to emulate
8868 a three button mouse */
8869 Lisp_Object Vmac_emulate_three_button_mouse;
8871 #if USE_CARBON_EVENTS
8872 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8873 mouse-2, instead of mouse-3. */
8874 int mac_wheel_button_is_mouse_2;
8876 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8877 for processing before Emacs sees it. */
8878 int mac_pass_command_to_system;
8880 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8881 for processing before Emacs sees it. */
8882 int mac_pass_control_to_system;
8883 #endif
8885 /* Points to the variable `inev' in the function XTread_socket. It is
8886 used for passing an input event to the function back from
8887 Carbon/Apple event handlers. */
8888 static struct input_event *read_socket_inev = NULL;
8890 /* Whether or not the screen configuration has changed. */
8891 static int mac_screen_config_changed = 0;
8893 Point saved_menu_event_location;
8895 /* Apple Events */
8896 #if USE_CARBON_EVENTS
8897 static Lisp_Object Qhi_command;
8898 #ifdef MAC_OSX
8899 extern Lisp_Object Qwindow;
8900 static Lisp_Object Qtoolbar_switch_mode;
8901 #endif
8902 #if USE_MAC_FONT_PANEL
8903 extern Lisp_Object Qfont;
8904 static Lisp_Object Qpanel_closed, Qselection;
8905 #endif
8906 #if USE_MAC_TSM
8907 static TSMDocumentID tsm_document_id;
8908 static Lisp_Object Qtext_input;
8909 static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
8910 static Lisp_Object Vmac_ts_active_input_overlay;
8911 extern Lisp_Object Qbefore_string;
8912 static Lisp_Object Vmac_ts_script_language_on_focus;
8913 static Lisp_Object saved_ts_script_language_on_focus;
8914 static ScriptLanguageRecord saved_ts_language;
8915 static Component saved_ts_component;
8916 #endif
8917 #endif
8918 extern int mac_ready_for_apple_events;
8919 extern Lisp_Object Qundefined;
8920 extern void init_apple_event_handler P_ ((void));
8921 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
8922 Lisp_Object *, Lisp_Object *,
8923 Lisp_Object *));
8924 extern OSErr init_coercion_handler P_ ((void));
8926 /* Drag and Drop */
8927 extern OSErr install_drag_handler P_ ((WindowRef));
8928 extern void remove_drag_handler P_ ((WindowRef));
8930 /* Showing help echo string during menu tracking */
8931 extern OSStatus install_menu_target_item_handler P_ ((WindowPtr));
8933 #if USE_CARBON_EVENTS
8934 #ifdef MAC_OSX
8935 extern void init_service_handler ();
8936 static Lisp_Object Qservice, Qpaste, Qperform;
8937 #endif
8939 /* Window Event Handler */
8940 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
8941 EventRef, void *);
8942 #endif
8943 OSStatus install_window_handler (WindowPtr);
8945 extern void init_emacs_passwd_dir ();
8946 extern int emacs_main (int, char **, char **);
8948 extern void initialize_applescript();
8949 extern void terminate_applescript();
8951 /* Table for translating Mac keycode to X keysym values. Contributed
8952 by Sudhir Shenoy.
8953 Mapping for special keys is now identical to that in Apple X11
8954 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8955 on the right of the Cmd key on laptops, and fn + `enter' (->
8956 <linefeed>). */
8957 static const unsigned char keycode_to_xkeysym_table[] = {
8958 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8959 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8960 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8962 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8963 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8964 /*0x38*/ 0, 0, 0, 0,
8965 /*0x3C*/ 0, 0, 0, 0,
8967 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8968 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8969 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8970 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8972 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8973 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8974 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8975 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8977 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8978 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8979 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8980 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8982 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8983 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8984 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8985 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8988 #ifdef MAC_OSX
8989 /* Table for translating Mac keycode with the laptop `fn' key to that
8990 without it. Destination symbols in comments are keys on US
8991 keyboard, and they may not be the same on other types of keyboards.
8992 If the destination is identical to the source (f1 ... f12), it
8993 doesn't map `fn' key to a modifier. */
8994 static const unsigned char fn_keycode_to_keycode_table[] = {
8995 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8996 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8997 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8999 /*0x30*/ 0, 0, 0, 0,
9000 /*0x34*/ 0, 0, 0, 0,
9001 /*0x38*/ 0, 0, 0, 0,
9002 /*0x3C*/ 0, 0, 0, 0,
9004 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
9005 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9006 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9007 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
9009 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9010 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9011 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9012 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9014 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9015 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9016 /*0x68*/ 0, 0, 0, 0,
9017 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9019 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9020 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9021 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9022 /*0x7C*/ 0, 0, 0, 0
9024 #endif /* MAC_OSX */
9026 static int
9027 #if USE_CARBON_EVENTS
9028 mac_to_emacs_modifiers (UInt32 mods)
9029 #else
9030 mac_to_emacs_modifiers (EventModifiers mods)
9031 #endif
9033 unsigned int result = 0;
9034 if (mods & shiftKey)
9035 result |= shift_modifier;
9037 /* Deactivated to simplify configuration:
9038 if Vmac_option_modifier is non-NIL, we fully process the Option
9039 key. Otherwise, we only process it if an additional Ctrl or Command
9040 is pressed. That way the system may convert the character to a
9041 composed one.
9042 if ((mods & optionKey) &&
9043 (( !NILP(Vmac_option_modifier) ||
9044 ((mods & cmdKey) || (mods & controlKey))))) */
9046 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
9047 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
9048 if (INTEGERP(val))
9049 result |= XUINT(val);
9051 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
9052 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
9053 if (INTEGERP(val))
9054 result |= XUINT(val);
9056 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
9057 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
9058 if (INTEGERP(val))
9059 result |= XUINT(val);
9062 #ifdef MAC_OSX
9063 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
9064 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
9065 if (INTEGERP(val))
9066 result |= XUINT(val);
9068 #endif
9070 return result;
9073 static UInt32
9074 mac_mapped_modifiers (modifiers)
9075 UInt32 modifiers;
9077 UInt32 mapped_modifiers_all =
9078 (NILP (Vmac_control_modifier) ? 0 : controlKey)
9079 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
9080 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
9082 #ifdef MAC_OSX
9083 mapped_modifiers_all |=
9084 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
9085 #endif
9087 return mapped_modifiers_all & modifiers;
9090 static int
9091 mac_get_emulated_btn ( UInt32 modifiers )
9093 int result = 0;
9094 if (!NILP (Vmac_emulate_three_button_mouse)) {
9095 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
9096 if (modifiers & cmdKey)
9097 result = cmdIs3 ? 2 : 1;
9098 else if (modifiers & optionKey)
9099 result = cmdIs3 ? 1 : 2;
9101 return result;
9104 #if TARGET_API_MAC_CARBON
9105 /***** Code to handle C-g testing *****/
9106 extern int quit_char;
9107 extern int make_ctrl_char P_ ((int));
9110 mac_quit_char_key_p (modifiers, key_code)
9111 UInt32 modifiers, key_code;
9113 UInt32 char_code;
9114 unsigned long some_state = 0;
9115 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9116 int c, emacs_modifiers;
9118 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
9119 key_code |= (modifiers & ~(mac_mapped_modifiers (modifiers)));
9120 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
9121 if (char_code & ~0xff)
9122 return 0;
9124 emacs_modifiers = mac_to_emacs_modifiers (modifiers);
9125 if (emacs_modifiers & ctrl_modifier)
9126 c = make_ctrl_char (char_code);
9128 c |= (emacs_modifiers
9129 & (meta_modifier | alt_modifier
9130 | hyper_modifier | super_modifier));
9132 return c == quit_char;
9134 #endif
9136 #if USE_CARBON_EVENTS
9137 /* Obtains the event modifiers from the event ref and then calls
9138 mac_to_emacs_modifiers. */
9139 static int
9140 mac_event_to_emacs_modifiers (EventRef eventRef)
9142 UInt32 mods = 0;
9143 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
9144 sizeof (UInt32), NULL, &mods);
9145 if (!NILP (Vmac_emulate_three_button_mouse) &&
9146 GetEventClass(eventRef) == kEventClassMouse)
9148 mods &= ~(optionKey | cmdKey);
9150 return mac_to_emacs_modifiers (mods);
9153 /* Given an event ref, return the code to use for the mouse button
9154 code in the emacs input_event. */
9155 static int
9156 mac_get_mouse_btn (EventRef ref)
9158 EventMouseButton result = kEventMouseButtonPrimary;
9159 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
9160 sizeof (EventMouseButton), NULL, &result);
9161 switch (result)
9163 case kEventMouseButtonPrimary:
9164 if (NILP (Vmac_emulate_three_button_mouse))
9165 return 0;
9166 else {
9167 UInt32 mods = 0;
9168 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
9169 sizeof (UInt32), NULL, &mods);
9170 return mac_get_emulated_btn(mods);
9172 case kEventMouseButtonSecondary:
9173 return mac_wheel_button_is_mouse_2 ? 2 : 1;
9174 case kEventMouseButtonTertiary:
9175 case 4: /* 4 is the number for the mouse wheel button */
9176 return mac_wheel_button_is_mouse_2 ? 1 : 2;
9177 default:
9178 return 0;
9182 /* Normally, ConvertEventRefToEventRecord will correctly handle all
9183 events. However the click of the mouse wheel is not converted to a
9184 mouseDown or mouseUp event. Likewise for dead key events. This
9185 calls ConvertEventRefToEventRecord, but then checks to see if it is
9186 a mouse up/down, or a dead key Carbon event that has not been
9187 converted, and if so, converts it by hand (to be picked up in the
9188 XTread_socket loop). */
9189 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
9191 OSStatus err;
9192 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
9193 EventKind action;
9195 if (result)
9196 return result;
9198 switch (GetEventClass (eventRef))
9200 case kEventClassMouse:
9201 switch (GetEventKind (eventRef))
9203 case kEventMouseDown:
9204 eventRec->what = mouseDown;
9205 result = 1;
9206 break;
9208 case kEventMouseUp:
9209 eventRec->what = mouseUp;
9210 result = 1;
9211 break;
9213 default:
9214 break;
9216 break;
9218 case kEventClassKeyboard:
9219 switch (GetEventKind (eventRef))
9221 case kEventRawKeyDown:
9222 action = keyDown;
9223 goto keystroke_common;
9224 case kEventRawKeyRepeat:
9225 action = autoKey;
9226 goto keystroke_common;
9227 case kEventRawKeyUp:
9228 action = keyUp;
9229 keystroke_common:
9231 unsigned char char_codes;
9232 UInt32 key_code;
9234 err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes,
9235 typeChar, NULL, sizeof (char),
9236 NULL, &char_codes);
9237 if (err == noErr)
9238 err = GetEventParameter (eventRef, kEventParamKeyCode,
9239 typeUInt32, NULL, sizeof (UInt32),
9240 NULL, &key_code);
9241 if (err == noErr)
9243 eventRec->what = action;
9244 eventRec->message = char_codes | ((key_code & 0xff) << 8);
9245 result = 1;
9248 break;
9250 default:
9251 break;
9253 break;
9255 default:
9256 break;
9259 if (result)
9261 /* Need where and when. */
9262 UInt32 mods = 0;
9264 GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
9265 NULL, sizeof (Point), NULL, &eventRec->where);
9266 /* Use two step process because new event modifiers are 32-bit
9267 and old are 16-bit. Currently, only loss is NumLock & Fn. */
9268 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
9269 NULL, sizeof (UInt32), NULL, &mods);
9270 eventRec->modifiers = mods;
9272 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
9275 return result;
9278 #endif
9280 #ifdef MAC_OS8
9281 static void
9282 do_get_menus (void)
9284 Handle menubar_handle;
9285 MenuHandle menu_handle;
9287 menubar_handle = GetNewMBar (128);
9288 if(menubar_handle == NULL)
9289 abort ();
9290 SetMenuBar (menubar_handle);
9291 DrawMenuBar ();
9293 #if !TARGET_API_MAC_CARBON
9294 menu_handle = GetMenuHandle (M_APPLE);
9295 if(menu_handle != NULL)
9296 AppendResMenu (menu_handle,'DRVR');
9297 else
9298 abort ();
9299 #endif
9303 static void
9304 do_init_managers (void)
9306 #if !TARGET_API_MAC_CARBON
9307 InitGraf (&qd.thePort);
9308 InitFonts ();
9309 FlushEvents (everyEvent, 0);
9310 InitWindows ();
9311 InitMenus ();
9312 TEInit ();
9313 InitDialogs (NULL);
9314 #endif /* !TARGET_API_MAC_CARBON */
9315 InitCursor ();
9317 #if !TARGET_API_MAC_CARBON
9318 /* set up some extra stack space for use by emacs */
9319 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
9321 /* MaxApplZone must be called for AppleScript to execute more
9322 complicated scripts */
9323 MaxApplZone ();
9324 MoreMasters ();
9325 #endif /* !TARGET_API_MAC_CARBON */
9328 static void
9329 do_check_ram_size (void)
9331 SInt32 physical_ram_size, logical_ram_size;
9333 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
9334 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
9335 || physical_ram_size > (1 << VALBITS)
9336 || logical_ram_size > (1 << VALBITS))
9338 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
9339 exit (1);
9342 #endif /* MAC_OS8 */
9344 static void
9345 do_window_update (WindowPtr win)
9347 struct frame *f = mac_window_to_frame (win);
9349 BeginUpdate (win);
9351 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
9352 below. */
9353 if (win != tip_window)
9355 if (f->async_visible == 0)
9357 /* Update events may occur when a frame gets iconified. */
9358 #if 0
9359 f->async_visible = 1;
9360 f->async_iconified = 0;
9361 SET_FRAME_GARBAGED (f);
9362 #endif
9364 else
9366 Rect r;
9367 #if TARGET_API_MAC_CARBON
9368 RgnHandle region = NewRgn ();
9370 GetPortVisibleRegion (GetWindowPort (win), region);
9371 GetRegionBounds (region, &r);
9372 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
9373 #if USE_CG_DRAWING
9374 mac_prepare_for_quickdraw (f);
9375 #endif
9376 UpdateControls (win, region);
9377 DisposeRgn (region);
9378 #else
9379 r = (*win->visRgn)->rgnBBox;
9380 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
9381 UpdateControls (win, win->visRgn);
9382 #endif
9386 EndUpdate (win);
9389 static int
9390 is_emacs_window (WindowPtr win)
9392 Lisp_Object tail, frame;
9394 if (!win)
9395 return 0;
9397 FOR_EACH_FRAME (tail, frame)
9398 if (FRAME_MAC_P (XFRAME (frame)))
9399 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
9400 return 1;
9402 return 0;
9405 #if USE_MAC_TSM
9406 static OSStatus
9407 mac_tsm_resume ()
9409 OSStatus err;
9410 ScriptLanguageRecord slrec, *slptr = NULL;
9412 err = ActivateTSMDocument (tsm_document_id);
9414 if (err == noErr)
9416 if (EQ (Vmac_ts_script_language_on_focus, Qt)
9417 && EQ (saved_ts_script_language_on_focus, Qt))
9418 slptr = &saved_ts_language;
9419 else if (CONSP (Vmac_ts_script_language_on_focus)
9420 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
9421 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
9422 && CONSP (saved_ts_script_language_on_focus)
9423 && EQ (XCAR (saved_ts_script_language_on_focus),
9424 XCAR (Vmac_ts_script_language_on_focus))
9425 && EQ (XCDR (saved_ts_script_language_on_focus),
9426 XCDR (Vmac_ts_script_language_on_focus)))
9428 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
9429 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
9430 slptr = &slrec;
9434 if (slptr)
9436 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9437 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
9438 kKeyboardInputMethodClass);
9439 #else
9440 err = SetDefaultInputMethod (saved_ts_component, slptr);
9441 #endif
9442 if (err == noErr)
9443 err = SetTextServiceLanguage (slptr);
9445 /* Seems to be needed on Mac OS X 10.2. */
9446 if (err == noErr)
9447 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
9450 return err;
9453 static OSStatus
9454 mac_tsm_suspend ()
9456 OSStatus err;
9457 ScriptLanguageRecord slrec, *slptr = NULL;
9459 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
9461 if (EQ (Vmac_ts_script_language_on_focus, Qt))
9463 err = GetTextServiceLanguage (&saved_ts_language);
9464 if (err == noErr)
9465 slptr = &saved_ts_language;
9467 else if (CONSP (Vmac_ts_script_language_on_focus)
9468 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
9469 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
9471 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
9472 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
9473 slptr = &slrec;
9476 if (slptr)
9478 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
9479 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
9480 kKeyboardInputMethodClass);
9481 #else
9482 GetDefaultInputMethod (&saved_ts_component, slptr);
9483 #endif
9486 err = DeactivateTSMDocument (tsm_document_id);
9488 return err;
9490 #endif
9492 #if !TARGET_API_MAC_CARBON
9493 void
9494 do_apple_menu (SInt16 menu_item)
9496 Str255 item_name;
9497 SInt16 da_driver_refnum;
9499 if (menu_item == I_ABOUT)
9500 NoteAlert (ABOUT_ALERT_ID, NULL);
9501 else
9503 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
9504 da_driver_refnum = OpenDeskAcc (item_name);
9507 #endif /* !TARGET_API_MAC_CARBON */
9509 /* Handle drags in size box. Based on code contributed by Ben
9510 Mesander and IM - Window Manager A. */
9512 static void
9513 do_grow_window (w, e)
9514 WindowPtr w;
9515 const EventRecord *e;
9517 Rect limit_rect;
9518 int rows, columns, width, height;
9519 struct frame *f = mac_window_to_frame (w);
9520 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
9521 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
9522 #if TARGET_API_MAC_CARBON
9523 Rect new_rect;
9524 #else
9525 long grow_size;
9526 #endif
9528 if (size_hints->flags & PMinSize)
9530 min_width = size_hints->min_width;
9531 min_height = size_hints->min_height;
9533 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
9535 #if TARGET_API_MAC_CARBON
9536 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
9537 return;
9538 height = new_rect.bottom - new_rect.top;
9539 width = new_rect.right - new_rect.left;
9540 #else
9541 grow_size = GrowWindow (w, e->where, &limit_rect);
9542 /* see if it really changed size */
9543 if (grow_size == 0)
9544 return;
9545 height = HiWord (grow_size);
9546 width = LoWord (grow_size);
9547 #endif
9549 if (width != FRAME_PIXEL_WIDTH (f)
9550 || height != FRAME_PIXEL_HEIGHT (f))
9552 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
9553 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
9555 x_set_window_size (f, 0, columns, rows);
9560 #if TARGET_API_MAC_CARBON
9561 static Point
9562 mac_get_ideal_size (f)
9563 struct frame *f;
9565 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9566 WindowPtr w = FRAME_MAC_WINDOW (f);
9567 Point ideal_size;
9568 Rect standard_rect;
9569 int height, width, columns, rows;
9571 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
9572 ideal_size.v = dpyinfo->height;
9573 IsWindowInStandardState (w, &ideal_size, &standard_rect);
9574 /* Adjust the standard size according to character boundaries. */
9575 width = standard_rect.right - standard_rect.left;
9576 height = standard_rect.bottom - standard_rect.top;
9577 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
9578 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
9579 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
9580 ideal_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
9582 return ideal_size;
9584 #endif
9586 /* Handle clicks in zoom box. Calculation of "standard state" based
9587 on code in IM - Window Manager A and code contributed by Ben
9588 Mesander. The standard state of an Emacs window is 80-characters
9589 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
9591 static void
9592 do_zoom_window (WindowPtr w, int zoom_in_or_out)
9594 Rect zoom_rect, port_rect;
9595 int width, height;
9596 struct frame *f = mac_window_to_frame (w);
9597 #if TARGET_API_MAC_CARBON
9598 Point ideal_size = mac_get_ideal_size (f);
9600 GetWindowBounds (w, kWindowContentRgn, &port_rect);
9601 if (IsWindowInStandardState (w, &ideal_size, &zoom_rect)
9602 && port_rect.left == zoom_rect.left
9603 && port_rect.top == zoom_rect.top)
9604 zoom_in_or_out = inZoomIn;
9605 else
9606 zoom_in_or_out = inZoomOut;
9608 #ifdef MAC_OS8
9609 mac_clear_window (f);
9610 #endif
9611 ZoomWindowIdeal (w, zoom_in_or_out, &ideal_size);
9612 #else /* not TARGET_API_MAC_CARBON */
9613 GrafPtr save_port;
9614 Point top_left;
9615 int w_title_height, rows;
9616 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
9618 GetPort (&save_port);
9620 SetPortWindowPort (w);
9622 /* Clear window to avoid flicker. */
9623 EraseRect (&(w->portRect));
9624 if (zoom_in_or_out == inZoomOut)
9626 SetPt (&top_left, w->portRect.left, w->portRect.top);
9627 LocalToGlobal (&top_left);
9629 /* calculate height of window's title bar */
9630 w_title_height = top_left.v - 1
9631 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
9633 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9634 zoom_rect = qd.screenBits.bounds;
9635 zoom_rect.top += w_title_height;
9636 InsetRect (&zoom_rect, 8, 4); /* not too tight */
9638 zoom_rect.right = zoom_rect.left
9639 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
9641 /* Adjust the standard size according to character boundaries. */
9642 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
9643 zoom_rect.bottom =
9644 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
9646 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
9647 = zoom_rect;
9650 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
9652 SetPort (save_port);
9653 #endif /* not TARGET_API_MAC_CARBON */
9655 #if !USE_CARBON_EVENTS
9656 /* retrieve window size and update application values */
9657 #if TARGET_API_MAC_CARBON
9658 GetWindowPortBounds (w, &port_rect);
9659 #else
9660 port_rect = w->portRect;
9661 #endif
9662 height = port_rect.bottom - port_rect.top;
9663 width = port_rect.right - port_rect.left;
9665 mac_handle_size_change (f, width, height);
9666 mac_handle_origin_change (f);
9667 #endif
9670 void
9671 mac_store_apple_event (class, id, desc)
9672 Lisp_Object class, id;
9673 const AEDesc *desc;
9675 struct input_event buf;
9677 EVENT_INIT (buf);
9679 buf.kind = MAC_APPLE_EVENT;
9680 buf.x = class;
9681 buf.y = id;
9682 XSETFRAME (buf.frame_or_window,
9683 mac_focus_frame (&one_mac_display_info));
9684 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9685 is safe to use them during read_socket_hook. */
9686 buf.arg = mac_aedesc_to_lisp (desc);
9687 kbd_buffer_store_event (&buf);
9690 #if TARGET_API_MAC_CARBON
9691 static OSStatus
9692 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
9693 event, num_params, names, types)
9694 AEEventClass class;
9695 AEEventID id;
9696 Lisp_Object class_key, id_key;
9697 EventRef event;
9698 UInt32 num_params;
9699 const EventParamName *names;
9700 const EventParamType *types;
9702 OSStatus err = eventNotHandledErr;
9703 Lisp_Object binding;
9705 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
9706 if (!NILP (binding) && !EQ (binding, Qundefined))
9708 if (INTEGERP (binding))
9709 err = XINT (binding);
9710 else
9712 AppleEvent apple_event;
9713 err = create_apple_event_from_event_ref (event, num_params,
9714 names, types,
9715 &apple_event);
9716 if (err == noErr)
9718 mac_store_apple_event (class_key, id_key, &apple_event);
9719 AEDisposeDesc (&apple_event);
9720 mac_wakeup_from_rne ();
9725 return err;
9728 void
9729 mac_store_drag_event (window, mouse_pos, modifiers, desc)
9730 WindowRef window;
9731 Point mouse_pos;
9732 SInt16 modifiers;
9733 const AEDesc *desc;
9735 struct input_event buf;
9737 EVENT_INIT (buf);
9739 buf.kind = DRAG_N_DROP_EVENT;
9740 buf.modifiers = mac_to_emacs_modifiers (modifiers);
9741 buf.timestamp = TickCount () * (1000 / 60);
9742 XSETINT (buf.x, mouse_pos.h);
9743 XSETINT (buf.y, mouse_pos.v);
9744 XSETFRAME (buf.frame_or_window, mac_window_to_frame (window));
9745 buf.arg = mac_aedesc_to_lisp (desc);
9746 kbd_buffer_store_event (&buf);
9748 #endif
9750 #if USE_CARBON_EVENTS
9751 static pascal OSStatus
9752 mac_handle_command_event (next_handler, event, data)
9753 EventHandlerCallRef next_handler;
9754 EventRef event;
9755 void *data;
9757 OSStatus result, err;
9758 HICommand command;
9759 static const EventParamName names[] =
9760 {kEventParamDirectObject, kEventParamKeyModifiers};
9761 static const EventParamType types[] =
9762 {typeHICommand, typeUInt32};
9763 int num_params = sizeof (names) / sizeof (names[0]);
9765 result = CallNextEventHandler (next_handler, event);
9766 if (result != eventNotHandledErr)
9767 return result;
9769 err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
9770 NULL, sizeof (HICommand), NULL, &command);
9772 if (err != noErr || command.commandID == 0)
9773 return eventNotHandledErr;
9775 /* A HI command event is mapped to an Apple event whose event class
9776 symbol is `hi-command' and event ID is its command ID. */
9777 err = mac_store_event_ref_as_apple_event (0, command.commandID,
9778 Qhi_command, Qnil,
9779 event, num_params, names, types);
9780 return err == noErr ? noErr : eventNotHandledErr;
9783 static OSStatus
9784 init_command_handler ()
9786 static const EventTypeSpec specs[] =
9787 {{kEventClassCommand, kEventCommandProcess}};
9788 static EventHandlerUPP handle_command_eventUPP = NULL;
9790 if (handle_command_eventUPP == NULL)
9791 handle_command_eventUPP = NewEventHandlerUPP (mac_handle_command_event);
9792 return InstallApplicationEventHandler (handle_command_eventUPP,
9793 GetEventTypeCount (specs), specs,
9794 NULL, NULL);
9797 static pascal OSStatus
9798 mac_handle_window_event (next_handler, event, data)
9799 EventHandlerCallRef next_handler;
9800 EventRef event;
9801 void *data;
9803 WindowPtr wp;
9804 OSStatus result, err;
9805 struct frame *f;
9806 UInt32 attributes;
9807 XSizeHints *size_hints;
9809 err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
9810 NULL, sizeof (WindowPtr), NULL, &wp);
9811 if (err != noErr)
9812 return eventNotHandledErr;
9814 f = mac_window_to_frame (wp);
9815 switch (GetEventKind (event))
9817 case kEventWindowUpdate:
9818 result = CallNextEventHandler (next_handler, event);
9819 if (result != eventNotHandledErr)
9820 return result;
9822 do_window_update (wp);
9823 return noErr;
9825 case kEventWindowGetIdealSize:
9826 result = CallNextEventHandler (next_handler, event);
9827 if (result != eventNotHandledErr)
9828 return result;
9831 Point ideal_size = mac_get_ideal_size (f);
9833 err = SetEventParameter (event, kEventParamDimensions,
9834 typeQDPoint, sizeof (Point), &ideal_size);
9835 if (err == noErr)
9836 return noErr;
9838 break;
9840 case kEventWindowBoundsChanging:
9841 result = CallNextEventHandler (next_handler, event);
9842 if (result != eventNotHandledErr)
9843 return result;
9845 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
9846 NULL, sizeof (UInt32), NULL, &attributes);
9847 if (err != noErr)
9848 break;
9850 size_hints = FRAME_SIZE_HINTS (f);
9851 if ((attributes & kWindowBoundsChangeUserResize)
9852 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
9853 == (PResizeInc | PBaseSize | PMinSize)))
9855 Rect bounds;
9856 int width, height;
9858 err = GetEventParameter (event, kEventParamCurrentBounds,
9859 typeQDRectangle, NULL, sizeof (Rect),
9860 NULL, &bounds);
9861 if (err != noErr)
9862 break;
9864 width = bounds.right - bounds.left;
9865 height = bounds.bottom - bounds.top;
9867 if (width < size_hints->min_width)
9868 width = size_hints->min_width;
9869 else
9870 width = size_hints->base_width
9871 + (int) ((width - size_hints->base_width)
9872 / (float) size_hints->width_inc + .5)
9873 * size_hints->width_inc;
9875 if (height < size_hints->min_height)
9876 height = size_hints->min_height;
9877 else
9878 height = size_hints->base_height
9879 + (int) ((height - size_hints->base_height)
9880 / (float) size_hints->height_inc + .5)
9881 * size_hints->height_inc;
9883 bounds.right = bounds.left + width;
9884 bounds.bottom = bounds.top + height;
9885 SetEventParameter (event, kEventParamCurrentBounds,
9886 typeQDRectangle, sizeof (Rect), &bounds);
9887 return noErr;
9889 break;
9891 case kEventWindowBoundsChanged:
9892 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
9893 NULL, sizeof (UInt32), NULL, &attributes);
9894 if (err != noErr)
9895 break;
9897 if (attributes & kWindowBoundsChangeSizeChanged)
9899 Rect bounds;
9901 err = GetEventParameter (event, kEventParamCurrentBounds,
9902 typeQDRectangle, NULL, sizeof (Rect),
9903 NULL, &bounds);
9904 if (err == noErr)
9906 int width, height;
9908 width = bounds.right - bounds.left;
9909 height = bounds.bottom - bounds.top;
9910 mac_handle_size_change (f, width, height);
9911 mac_wakeup_from_rne ();
9915 if (attributes & kWindowBoundsChangeOriginChanged)
9916 mac_handle_origin_change (f);
9918 return noErr;
9920 case kEventWindowShown:
9921 case kEventWindowHidden:
9922 case kEventWindowExpanded:
9923 case kEventWindowCollapsed:
9924 result = CallNextEventHandler (next_handler, event);
9926 mac_handle_visibility_change (f);
9927 return noErr;
9929 break;
9931 case kEventWindowClose:
9932 result = CallNextEventHandler (next_handler, event);
9934 struct input_event buf;
9936 EVENT_INIT (buf);
9937 buf.kind = DELETE_WINDOW_EVENT;
9938 XSETFRAME (buf.frame_or_window, f);
9939 buf.arg = Qnil;
9940 kbd_buffer_store_event (&buf);
9942 return noErr;
9944 #ifdef MAC_OSX
9945 case kEventWindowToolbarSwitchMode:
9946 result = CallNextEventHandler (next_handler, event);
9948 static const EventParamName names[] = {kEventParamDirectObject,
9949 kEventParamWindowMouseLocation,
9950 kEventParamKeyModifiers,
9951 kEventParamMouseButton,
9952 kEventParamClickCount,
9953 kEventParamMouseChord};
9954 static const EventParamType types[] = {typeWindowRef,
9955 typeQDPoint,
9956 typeUInt32,
9957 typeMouseButton,
9958 typeUInt32,
9959 typeUInt32};
9960 int num_params = sizeof (names) / sizeof (names[0]);
9962 err = mac_store_event_ref_as_apple_event (0, 0,
9963 Qwindow,
9964 Qtoolbar_switch_mode,
9965 event, num_params,
9966 names, types);
9968 return err == noErr ? noErr : result;
9969 #endif
9971 #if USE_MAC_TSM
9972 case kEventWindowFocusAcquired:
9973 result = CallNextEventHandler (next_handler, event);
9974 err = mac_tsm_resume ();
9975 return err == noErr ? noErr : result;
9977 case kEventWindowFocusRelinquish:
9978 result = CallNextEventHandler (next_handler, event);
9979 err = mac_tsm_suspend ();
9980 return err == noErr ? noErr : result;
9981 #endif
9984 return eventNotHandledErr;
9987 static pascal OSStatus
9988 mac_handle_mouse_event (next_handler, event, data)
9989 EventHandlerCallRef next_handler;
9990 EventRef event;
9991 void *data;
9993 OSStatus result, err;
9995 switch (GetEventKind (event))
9997 case kEventMouseWheelMoved:
9999 WindowPtr wp;
10000 struct frame *f;
10001 EventMouseWheelAxis axis;
10002 SInt32 delta;
10003 Point point;
10005 result = CallNextEventHandler (next_handler, event);
10006 if (result != eventNotHandledErr || read_socket_inev == NULL)
10007 return result;
10009 err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
10010 NULL, sizeof (WindowRef), NULL, &wp);
10011 if (err != noErr)
10012 break;
10014 f = mac_window_to_frame (wp);
10015 if (f != mac_focus_frame (&one_mac_display_info))
10016 break;
10018 err = GetEventParameter (event, kEventParamMouseWheelAxis,
10019 typeMouseWheelAxis, NULL,
10020 sizeof (EventMouseWheelAxis), NULL, &axis);
10021 if (err != noErr || axis != kEventMouseWheelAxisY)
10022 break;
10024 err = GetEventParameter (event, kEventParamMouseLocation,
10025 typeQDPoint, NULL, sizeof (Point),
10026 NULL, &point);
10027 if (err != noErr)
10028 break;
10030 SetPortWindowPort (wp);
10031 GlobalToLocal (&point);
10032 if (point.h < 0 || point.v < 0
10033 || EQ (window_from_coordinates (f, point.h, point.v, 0, 0, 0, 1),
10034 f->tool_bar_window))
10035 break;
10037 err = GetEventParameter (event, kEventParamMouseWheelDelta,
10038 typeSInt32, NULL, sizeof (SInt32),
10039 NULL, &delta);
10040 if (err != noErr)
10041 break;
10043 read_socket_inev->kind = WHEEL_EVENT;
10044 read_socket_inev->code = 0;
10045 read_socket_inev->modifiers =
10046 (mac_event_to_emacs_modifiers (event)
10047 | ((delta < 0) ? down_modifier : up_modifier));
10048 XSETINT (read_socket_inev->x, point.h);
10049 XSETINT (read_socket_inev->y, point.v);
10050 XSETFRAME (read_socket_inev->frame_or_window, f);
10052 return noErr;
10054 break;
10056 default:
10057 break;
10060 return eventNotHandledErr;
10063 #if USE_MAC_FONT_PANEL
10064 static pascal OSStatus
10065 mac_handle_font_event (next_handler, event, data)
10066 EventHandlerCallRef next_handler;
10067 EventRef event;
10068 void *data;
10070 OSStatus result, err;
10071 Lisp_Object id_key;
10072 int num_params;
10073 const EventParamName *names;
10074 const EventParamType *types;
10075 static const EventParamName names_sel[] = {kEventParamATSUFontID,
10076 kEventParamATSUFontSize,
10077 kEventParamFMFontFamily,
10078 kEventParamFMFontSize,
10079 kEventParamFontColor};
10080 static const EventParamType types_sel[] = {typeATSUFontID,
10081 typeATSUSize,
10082 typeFMFontFamily,
10083 typeFMFontSize,
10084 typeFontColor};
10086 result = CallNextEventHandler (next_handler, event);
10087 if (result != eventNotHandledErr)
10088 return result;
10090 switch (GetEventKind (event))
10092 case kEventFontPanelClosed:
10093 id_key = Qpanel_closed;
10094 num_params = 0;
10095 names = NULL;
10096 types = NULL;
10097 break;
10099 case kEventFontSelection:
10100 id_key = Qselection;
10101 num_params = sizeof (names_sel) / sizeof (names_sel[0]);
10102 names = names_sel;
10103 types = types_sel;
10104 break;
10107 err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
10108 event, num_params,
10109 names, types);
10111 return err == noErr ? noErr : eventNotHandledErr;
10113 #endif
10115 #if USE_MAC_TSM
10116 static pascal OSStatus
10117 mac_handle_text_input_event (next_handler, event, data)
10118 EventHandlerCallRef next_handler;
10119 EventRef event;
10120 void *data;
10122 OSStatus result, err = noErr;
10123 Lisp_Object id_key = Qnil;
10124 int num_params;
10125 const EventParamName *names;
10126 const EventParamType *types;
10127 static UInt32 seqno_uaia = 0;
10128 static const EventParamName names_uaia[] =
10129 {kEventParamTextInputSendComponentInstance,
10130 kEventParamTextInputSendRefCon,
10131 kEventParamTextInputSendSLRec,
10132 kEventParamTextInputSendFixLen,
10133 kEventParamTextInputSendText,
10134 kEventParamTextInputSendUpdateRng,
10135 kEventParamTextInputSendHiliteRng,
10136 kEventParamTextInputSendClauseRng,
10137 kEventParamTextInputSendPinRng,
10138 kEventParamTextInputSendTextServiceEncoding,
10139 kEventParamTextInputSendTextServiceMacEncoding,
10140 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
10141 static const EventParamType types_uaia[] =
10142 {typeComponentInstance,
10143 typeLongInteger,
10144 typeIntlWritingCode,
10145 typeLongInteger,
10146 #ifdef MAC_OSX
10147 typeUnicodeText,
10148 #else
10149 typeChar,
10150 #endif
10151 typeTextRangeArray,
10152 typeTextRangeArray,
10153 typeOffsetArray,
10154 typeTextRange,
10155 typeUInt32,
10156 typeUInt32,
10157 typeUInt32};
10158 static const EventParamName names_ufke[] =
10159 {kEventParamTextInputSendComponentInstance,
10160 kEventParamTextInputSendRefCon,
10161 kEventParamTextInputSendSLRec,
10162 kEventParamTextInputSendText};
10163 static const EventParamType types_ufke[] =
10164 {typeComponentInstance,
10165 typeLongInteger,
10166 typeIntlWritingCode,
10167 typeUnicodeText};
10169 result = CallNextEventHandler (next_handler, event);
10171 switch (GetEventKind (event))
10173 case kEventTextInputUpdateActiveInputArea:
10174 id_key = Qupdate_active_input_area;
10175 num_params = sizeof (names_uaia) / sizeof (names_uaia[0]);
10176 names = names_uaia;
10177 types = types_uaia;
10178 SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
10179 typeUInt32, sizeof (UInt32), &seqno_uaia);
10180 seqno_uaia++;
10181 break;
10183 case kEventTextInputUnicodeForKeyEvent:
10185 EventRef kbd_event;
10186 UInt32 actual_size, modifiers;
10188 err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent,
10189 typeEventRef, NULL, sizeof (EventRef), NULL,
10190 &kbd_event);
10191 if (err == noErr)
10192 err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
10193 typeUInt32, NULL,
10194 sizeof (UInt32), NULL, &modifiers);
10195 if (err == noErr && mac_mapped_modifiers (modifiers))
10196 /* There're mapped modifier keys. Process it in
10197 XTread_socket. */
10198 return eventNotHandledErr;
10199 if (err == noErr)
10200 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
10201 typeUnicodeText, NULL, 0, &actual_size,
10202 NULL);
10203 if (err == noErr && actual_size == sizeof (UniChar))
10205 UniChar code;
10207 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
10208 typeUnicodeText, NULL,
10209 sizeof (UniChar), NULL, &code);
10210 if (err == noErr && code < 0x80)
10212 /* ASCII character. Process it in XTread_socket. */
10213 if (read_socket_inev && code >= 0x20 && code <= 0x7e)
10215 UInt32 key_code;
10217 err = GetEventParameter (kbd_event, kEventParamKeyCode,
10218 typeUInt32, NULL, sizeof (UInt32),
10219 NULL, &key_code);
10220 if (!(err == noErr && key_code <= 0x7f
10221 && keycode_to_xkeysym_table [key_code]))
10223 struct frame *f =
10224 mac_focus_frame (&one_mac_display_info);
10226 read_socket_inev->kind = ASCII_KEYSTROKE_EVENT;
10227 read_socket_inev->code = code;
10228 read_socket_inev->modifiers =
10229 mac_to_emacs_modifiers (modifiers);
10230 read_socket_inev->modifiers |=
10231 (extra_keyboard_modifiers
10232 & (meta_modifier | alt_modifier
10233 | hyper_modifier | super_modifier));
10234 XSETFRAME (read_socket_inev->frame_or_window, f);
10237 return eventNotHandledErr;
10241 /* Non-ASCII keystrokes without mapped modifiers are processed
10242 at the Lisp level. */
10243 id_key = Qunicode_for_key_event;
10244 num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
10245 names = names_ufke;
10246 types = types_ufke;
10247 break;
10249 case kEventTextInputOffsetToPos:
10251 struct frame *f;
10252 struct window *w;
10253 Point p;
10255 if (!OVERLAYP (Vmac_ts_active_input_overlay))
10256 return eventNotHandledErr;
10258 /* Strictly speaking, this is not always correct because
10259 previous events may change some states about display. */
10260 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
10262 if (!WINDOWP (echo_area_window))
10263 return eventNotHandledErr;
10265 /* Active input area is displayed in the echo area. */
10266 w = XWINDOW (echo_area_window);
10267 f = WINDOW_XFRAME (w);
10269 else
10271 /* Active input area is displayed around the current point. */
10272 f = SELECTED_FRAME ();
10273 w = XWINDOW (f->selected_window);
10276 p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
10277 + WINDOW_LEFT_FRINGE_WIDTH (w));
10278 p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
10279 + FONT_BASE (FRAME_FONT (f)));
10280 SetPortWindowPort (FRAME_MAC_WINDOW (f));
10281 LocalToGlobal (&p);
10282 err = SetEventParameter (event, kEventParamTextInputReplyPoint,
10283 typeQDPoint, sizeof (typeQDPoint), &p);
10285 break;
10287 default:
10288 abort ();
10291 if (!NILP (id_key))
10292 err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
10293 event, num_params,
10294 names, types);
10296 return err == noErr ? noErr : result;
10298 #endif
10300 #ifdef MAC_OSX
10301 OSStatus
10302 mac_store_service_event (event)
10303 EventRef event;
10305 OSStatus err;
10306 Lisp_Object id_key;
10307 int num_params;
10308 const EventParamName *names;
10309 const EventParamType *types;
10310 static const EventParamName names_pfm[] =
10311 {kEventParamServiceMessageName, kEventParamServiceUserData};
10312 static const EventParamType types_pfm[] =
10313 {typeCFStringRef, typeCFStringRef};
10315 switch (GetEventKind (event))
10317 case kEventServicePaste:
10318 id_key = Qpaste;
10319 num_params = 0;
10320 names = NULL;
10321 types = NULL;
10322 break;
10324 case kEventServicePerform:
10325 id_key = Qperform;
10326 num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
10327 names = names_pfm;
10328 types = types_pfm;
10329 break;
10331 default:
10332 abort ();
10335 err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
10336 event, num_params,
10337 names, types);
10339 return err;
10341 #endif /* MAC_OSX */
10342 #endif /* USE_CARBON_EVENTS */
10345 OSStatus
10346 install_window_handler (window)
10347 WindowPtr window;
10349 OSStatus err = noErr;
10350 #if USE_CARBON_EVENTS
10351 static const EventTypeSpec specs_window[] =
10352 {{kEventClassWindow, kEventWindowUpdate},
10353 {kEventClassWindow, kEventWindowGetIdealSize},
10354 {kEventClassWindow, kEventWindowBoundsChanging},
10355 {kEventClassWindow, kEventWindowBoundsChanged},
10356 {kEventClassWindow, kEventWindowShown},
10357 {kEventClassWindow, kEventWindowHidden},
10358 {kEventClassWindow, kEventWindowExpanded},
10359 {kEventClassWindow, kEventWindowCollapsed},
10360 {kEventClassWindow, kEventWindowClose},
10361 #ifdef MAC_OSX
10362 {kEventClassWindow, kEventWindowToolbarSwitchMode},
10363 #endif
10364 #if USE_MAC_TSM
10365 {kEventClassWindow, kEventWindowFocusAcquired},
10366 {kEventClassWindow, kEventWindowFocusRelinquish},
10367 #endif
10369 static const EventTypeSpec specs_mouse[] =
10370 {{kEventClassMouse, kEventMouseWheelMoved}};
10371 static EventHandlerUPP handle_window_eventUPP = NULL;
10372 static EventHandlerUPP handle_mouse_eventUPP = NULL;
10373 #if USE_MAC_FONT_PANEL
10374 static const EventTypeSpec specs_font[] =
10375 {{kEventClassFont, kEventFontPanelClosed},
10376 {kEventClassFont, kEventFontSelection}};
10377 static EventHandlerUPP handle_font_eventUPP = NULL;
10378 #endif
10379 #if USE_MAC_TSM
10380 static const EventTypeSpec specs_text_input[] =
10381 {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
10382 {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
10383 {kEventClassTextInput, kEventTextInputOffsetToPos}};
10384 static EventHandlerUPP handle_text_input_eventUPP = NULL;
10385 #endif
10387 if (handle_window_eventUPP == NULL)
10388 handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
10389 if (handle_mouse_eventUPP == NULL)
10390 handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
10391 #if USE_MAC_FONT_PANEL
10392 if (handle_font_eventUPP == NULL)
10393 handle_font_eventUPP = NewEventHandlerUPP (mac_handle_font_event);
10394 #endif
10395 #if USE_MAC_TSM
10396 if (handle_text_input_eventUPP == NULL)
10397 handle_text_input_eventUPP =
10398 NewEventHandlerUPP (mac_handle_text_input_event);
10399 #endif
10400 err = InstallWindowEventHandler (window, handle_window_eventUPP,
10401 GetEventTypeCount (specs_window),
10402 specs_window, NULL, NULL);
10403 if (err == noErr)
10404 err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
10405 GetEventTypeCount (specs_mouse),
10406 specs_mouse, NULL, NULL);
10407 #if USE_MAC_FONT_PANEL
10408 if (err == noErr)
10409 err = InstallWindowEventHandler (window, handle_font_eventUPP,
10410 GetEventTypeCount (specs_font),
10411 specs_font, NULL, NULL);
10412 #endif
10413 #if USE_MAC_TSM
10414 if (err == noErr)
10415 err = InstallWindowEventHandler (window, handle_text_input_eventUPP,
10416 GetEventTypeCount (specs_text_input),
10417 specs_text_input, window, NULL);
10418 #endif
10419 #endif
10420 if (err == noErr)
10421 err = install_drag_handler (window);
10422 if (err == noErr)
10423 err = install_menu_target_item_handler (window);
10425 return err;
10428 void
10429 remove_window_handler (window)
10430 WindowPtr window;
10432 remove_drag_handler (window);
10436 static pascal void
10437 mac_handle_dm_notification (event)
10438 AppleEvent *event;
10440 mac_screen_config_changed = 1;
10443 static OSErr
10444 init_dm_notification_handler ()
10446 OSErr err;
10447 static DMNotificationUPP handle_dm_notificationUPP = NULL;
10448 ProcessSerialNumber psn;
10450 if (handle_dm_notificationUPP == NULL)
10451 handle_dm_notificationUPP =
10452 NewDMNotificationUPP (mac_handle_dm_notification);
10454 err = GetCurrentProcess (&psn);
10455 if (err == noErr)
10456 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
10458 return err;
10461 static void
10462 mac_get_screen_info (dpyinfo)
10463 struct mac_display_info *dpyinfo;
10465 #ifdef MAC_OSX
10466 /* HasDepth returns true if it is possible to have a 32 bit display,
10467 but this may not be what is actually used. Mac OSX can do better. */
10468 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
10469 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
10471 CGDisplayErr err;
10472 CGDisplayCount ndisps;
10473 CGDirectDisplayID *displays;
10475 err = CGGetActiveDisplayList (0, NULL, &ndisps);
10476 if (err == noErr)
10478 displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
10479 err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
10481 if (err == noErr)
10483 CGRect bounds = CGRectZero;
10485 while (ndisps-- > 0)
10486 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
10487 dpyinfo->height = CGRectGetHeight (bounds);
10488 dpyinfo->width = CGRectGetWidth (bounds);
10490 else
10492 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
10493 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
10496 #else /* !MAC_OSX */
10498 GDHandle gdh = GetMainDevice ();
10499 Rect rect = (**gdh).gdRect;
10501 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
10502 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
10503 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
10504 break;
10506 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
10507 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
10508 UnionRect (&rect, &(**gdh).gdRect, &rect);
10510 dpyinfo->height = rect.bottom - rect.top;
10511 dpyinfo->width = rect.right - rect.left;
10513 #endif /* !MAC_OSX */
10517 #if __profile__
10518 void
10519 profiler_exit_proc ()
10521 ProfilerDump ("\pEmacs.prof");
10522 ProfilerTerm ();
10524 #endif
10526 /* These few functions implement Emacs as a normal Mac application
10527 (almost): set up the heap and the Toolbox, handle necessary system
10528 events plus a few simple menu events. They also set up Emacs's
10529 access to functions defined in the rest of this file. Emacs uses
10530 function hooks to perform all its terminal I/O. A complete list of
10531 these functions appear in termhooks.h. For what they do, read the
10532 comments there and see also w32term.c and xterm.c. What's
10533 noticeably missing here is the event loop, which is normally
10534 present in most Mac application. After performing the necessary
10535 Mac initializations, main passes off control to emacs_main
10536 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
10537 (defined further below) to read input. This is where
10538 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
10540 #ifdef MAC_OS8
10541 #undef main
10543 main (void)
10545 #if __profile__ /* is the profiler on? */
10546 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
10547 exit(1);
10548 #endif
10550 #if __MWERKS__
10551 /* set creator and type for files created by MSL */
10552 _fcreator = MAC_EMACS_CREATOR_CODE;
10553 _ftype = 'TEXT';
10554 #endif
10556 do_init_managers ();
10558 do_get_menus ();
10560 #ifndef USE_LSB_TAG
10561 do_check_ram_size ();
10562 #endif
10564 init_emacs_passwd_dir ();
10566 init_environ ();
10568 init_coercion_handler ();
10570 initialize_applescript ();
10572 init_apple_event_handler ();
10574 init_dm_notification_handler ();
10577 char **argv;
10578 int argc = 0;
10580 /* set up argv array from STR# resource */
10581 get_string_list (&argv, ARGV_STRING_LIST_ID);
10582 while (argv[argc])
10583 argc++;
10585 /* free up AppleScript resources on exit */
10586 atexit (terminate_applescript);
10588 #if __profile__ /* is the profiler on? */
10589 atexit (profiler_exit_proc);
10590 #endif
10592 /* 3rd param "envp" never used in emacs_main */
10593 (void) emacs_main (argc, argv, 0);
10596 /* Never reached - real exit in Fkill_emacs */
10597 return 0;
10599 #endif
10601 #if !USE_CARBON_EVENTS
10602 static RgnHandle mouse_region = NULL;
10604 Boolean
10605 mac_wait_next_event (er, sleep_time, dequeue)
10606 EventRecord *er;
10607 UInt32 sleep_time;
10608 Boolean dequeue;
10610 static EventRecord er_buf = {nullEvent};
10611 UInt32 target_tick, current_tick;
10612 EventMask event_mask;
10614 if (mouse_region == NULL)
10615 mouse_region = NewRgn ();
10617 event_mask = everyEvent;
10618 if (!mac_ready_for_apple_events)
10619 event_mask -= highLevelEventMask;
10621 current_tick = TickCount ();
10622 target_tick = current_tick + sleep_time;
10624 if (er_buf.what == nullEvent)
10625 while (!WaitNextEvent (event_mask, &er_buf,
10626 target_tick - current_tick, mouse_region))
10628 current_tick = TickCount ();
10629 if (target_tick <= current_tick)
10630 return false;
10633 *er = er_buf;
10634 if (dequeue)
10635 er_buf.what = nullEvent;
10636 return true;
10638 #endif /* not USE_CARBON_EVENTS */
10640 #if TARGET_API_MAC_CARBON
10641 OSStatus
10642 mac_post_mouse_moved_event ()
10644 EventRef event = NULL;
10645 OSStatus err;
10647 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
10648 kEventAttributeNone, &event);
10649 if (err == noErr)
10651 Point mouse_pos;
10653 GetGlobalMouse (&mouse_pos);
10654 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
10655 sizeof (Point), &mouse_pos);
10657 if (err == noErr)
10659 UInt32 modifiers = GetCurrentKeyModifiers ();
10661 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
10662 sizeof (UInt32), &modifiers);
10664 if (err == noErr)
10665 err = PostEventToQueue (GetCurrentEventQueue (), event,
10666 kEventPriorityStandard);
10667 if (event)
10668 ReleaseEvent (event);
10670 return err;
10673 static void
10674 mac_set_unicode_keystroke_event (code, buf)
10675 UniChar code;
10676 struct input_event *buf;
10678 int charset_id, c1, c2;
10680 if (code < 0x80)
10682 buf->kind = ASCII_KEYSTROKE_EVENT;
10683 buf->code = code;
10685 else if (code < 0x100)
10687 if (code < 0xA0)
10688 charset_id = CHARSET_8_BIT_CONTROL;
10689 else
10690 charset_id = charset_latin_iso8859_1;
10691 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10692 buf->code = MAKE_CHAR (charset_id, code, 0);
10694 else
10696 if (code < 0x2500)
10697 charset_id = charset_mule_unicode_0100_24ff,
10698 code -= 0x100;
10699 else if (code < 0x33FF)
10700 charset_id = charset_mule_unicode_2500_33ff,
10701 code -= 0x2500;
10702 else if (code >= 0xE000)
10703 charset_id = charset_mule_unicode_e000_ffff,
10704 code -= 0xE000;
10705 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
10706 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10707 buf->code = MAKE_CHAR (charset_id, c1, c2);
10710 #endif
10712 /* Emacs calls this whenever it wants to read an input event from the
10713 user. */
10715 XTread_socket (sd, expected, hold_quit)
10716 int sd, expected;
10717 struct input_event *hold_quit;
10719 struct input_event inev;
10720 int count = 0;
10721 #if USE_CARBON_EVENTS
10722 EventRef eventRef;
10723 EventTargetRef toolbox_dispatcher;
10724 #endif
10725 EventRecord er;
10726 struct mac_display_info *dpyinfo = &one_mac_display_info;
10728 if (interrupt_input_blocked)
10730 interrupt_input_pending = 1;
10731 return -1;
10734 interrupt_input_pending = 0;
10735 BLOCK_INPUT;
10737 /* So people can tell when we have read the available input. */
10738 input_signal_count++;
10740 ++handling_signal;
10742 #if USE_CARBON_EVENTS
10743 toolbox_dispatcher = GetEventDispatcherTarget ();
10745 while (
10746 #if USE_CG_DRAWING
10747 mac_prepare_for_quickdraw (NULL),
10748 #endif
10749 !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
10750 kEventRemoveFromQueue, &eventRef))
10751 #else /* !USE_CARBON_EVENTS */
10752 while (mac_wait_next_event (&er, 0, true))
10753 #endif /* !USE_CARBON_EVENTS */
10755 int do_help = 0;
10756 struct frame *f;
10757 unsigned long timestamp;
10759 EVENT_INIT (inev);
10760 inev.kind = NO_EVENT;
10761 inev.arg = Qnil;
10763 #if USE_CARBON_EVENTS
10764 timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
10765 #else
10766 timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
10767 #endif
10769 #if USE_CARBON_EVENTS
10770 /* Handle new events */
10771 if (!mac_convert_event_ref (eventRef, &er))
10773 /* There used to be a handler for the kEventMouseWheelMoved
10774 event here. But as of Mac OS X 10.4, this kind of event
10775 is not directly posted to the main event queue by
10776 two-finger scrolling on the trackpad. Instead, some
10777 private event is posted and it is converted to a wheel
10778 event by the default handler for the application target.
10779 The converted one can be received by a Carbon event
10780 handler installed on a window target. */
10781 read_socket_inev = &inev;
10782 SendEventToEventTarget (eventRef, toolbox_dispatcher);
10783 read_socket_inev = NULL;
10785 else
10786 #endif /* USE_CARBON_EVENTS */
10787 switch (er.what)
10789 case mouseDown:
10790 case mouseUp:
10792 WindowPtr window_ptr;
10793 ControlPartCode part_code;
10794 int tool_bar_p = 0;
10796 #if USE_CARBON_EVENTS
10797 /* This is needed to send mouse events like aqua window
10798 buttons to the correct handler. */
10799 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10800 != eventNotHandledErr)
10801 break;
10802 #endif
10803 last_mouse_glyph_frame = 0;
10805 if (dpyinfo->grabbed && last_mouse_frame
10806 && FRAME_LIVE_P (last_mouse_frame))
10808 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
10809 part_code = inContent;
10811 else
10813 part_code = FindWindow (er.where, &window_ptr);
10814 if (tip_window && window_ptr == tip_window)
10816 HideWindow (tip_window);
10817 part_code = FindWindow (er.where, &window_ptr);
10821 if (er.what != mouseDown &&
10822 (part_code != inContent || dpyinfo->grabbed == 0))
10823 break;
10825 switch (part_code)
10827 case inMenuBar:
10828 f = mac_focus_frame (dpyinfo);
10829 saved_menu_event_location = er.where;
10830 inev.kind = MENU_BAR_ACTIVATE_EVENT;
10831 XSETFRAME (inev.frame_or_window, f);
10832 break;
10834 case inContent:
10835 if (
10836 #if TARGET_API_MAC_CARBON
10837 FrontNonFloatingWindow ()
10838 #else
10839 FrontWindow ()
10840 #endif
10841 != window_ptr
10842 || (mac_window_to_frame (window_ptr)
10843 != dpyinfo->x_focus_frame))
10844 SelectWindow (window_ptr);
10845 else
10847 ControlPartCode control_part_code;
10848 ControlHandle ch;
10849 Point mouse_loc = er.where;
10850 #ifdef MAC_OSX
10851 ControlKind control_kind;
10852 #endif
10854 f = mac_window_to_frame (window_ptr);
10855 /* convert to local coordinates of new window */
10856 SetPortWindowPort (window_ptr);
10858 GlobalToLocal (&mouse_loc);
10859 #if TARGET_API_MAC_CARBON
10860 ch = FindControlUnderMouse (mouse_loc, window_ptr,
10861 &control_part_code);
10862 #ifdef MAC_OSX
10863 if (ch)
10864 GetControlKind (ch, &control_kind);
10865 #endif
10866 #else
10867 control_part_code = FindControl (mouse_loc, window_ptr,
10868 &ch);
10869 #endif
10871 #if USE_CARBON_EVENTS
10872 inev.code = mac_get_mouse_btn (eventRef);
10873 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
10874 #else
10875 inev.code = mac_get_emulated_btn (er.modifiers);
10876 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
10877 #endif
10878 XSETINT (inev.x, mouse_loc.h);
10879 XSETINT (inev.y, mouse_loc.v);
10881 if ((dpyinfo->grabbed && tracked_scroll_bar)
10882 || (ch != 0
10883 #ifndef USE_TOOLKIT_SCROLL_BARS
10884 /* control_part_code becomes kControlNoPart if
10885 a progress indicator is clicked. */
10886 && control_part_code != kControlNoPart
10887 #else /* USE_TOOLKIT_SCROLL_BARS */
10888 #ifdef MAC_OSX
10889 && control_kind.kind == kControlKindScrollBar
10890 #endif /* MAC_OSX */
10891 #endif /* USE_TOOLKIT_SCROLL_BARS */
10894 struct scroll_bar *bar;
10896 if (dpyinfo->grabbed && tracked_scroll_bar)
10898 bar = tracked_scroll_bar;
10899 #ifndef USE_TOOLKIT_SCROLL_BARS
10900 control_part_code = kControlIndicatorPart;
10901 #endif
10903 else
10904 bar = (struct scroll_bar *) GetControlReference (ch);
10905 #ifdef USE_TOOLKIT_SCROLL_BARS
10906 /* Make the "Ctrl-Mouse-2 splits window" work
10907 for toolkit scroll bars. */
10908 if (inev.modifiers & ctrl_modifier)
10909 x_scroll_bar_handle_click (bar, control_part_code,
10910 &er, &inev);
10911 else if (er.what == mouseDown)
10912 x_scroll_bar_handle_press (bar, control_part_code,
10913 mouse_loc, &inev);
10914 else
10915 x_scroll_bar_handle_release (bar, &inev);
10916 #else /* not USE_TOOLKIT_SCROLL_BARS */
10917 x_scroll_bar_handle_click (bar, control_part_code,
10918 &er, &inev);
10919 if (er.what == mouseDown
10920 && control_part_code == kControlIndicatorPart)
10921 tracked_scroll_bar = bar;
10922 else
10923 tracked_scroll_bar = NULL;
10924 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10926 else
10928 Lisp_Object window;
10929 int x = mouse_loc.h;
10930 int y = mouse_loc.v;
10932 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
10933 if (EQ (window, f->tool_bar_window))
10935 if (er.what == mouseDown)
10936 handle_tool_bar_click (f, x, y, 1, 0);
10937 else
10938 handle_tool_bar_click (f, x, y, 0,
10939 inev.modifiers);
10940 tool_bar_p = 1;
10942 else
10944 XSETFRAME (inev.frame_or_window, f);
10945 inev.kind = MOUSE_CLICK_EVENT;
10949 if (er.what == mouseDown)
10951 dpyinfo->grabbed |= (1 << inev.code);
10952 last_mouse_frame = f;
10954 if (!tool_bar_p)
10955 last_tool_bar_item = -1;
10957 else
10959 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
10960 /* If a button is released though it was not
10961 previously pressed, that would be because
10962 of multi-button emulation. */
10963 dpyinfo->grabbed = 0;
10964 else
10965 dpyinfo->grabbed &= ~(1 << inev.code);
10968 /* Ignore any mouse motion that happened before
10969 this event; any subsequent mouse-movement Emacs
10970 events should reflect only motion after the
10971 ButtonPress. */
10972 if (f != 0)
10973 f->mouse_moved = 0;
10975 #ifdef USE_TOOLKIT_SCROLL_BARS
10976 if (inev.kind == MOUSE_CLICK_EVENT
10977 || (inev.kind == SCROLL_BAR_CLICK_EVENT
10978 && (inev.modifiers & ctrl_modifier)))
10979 #endif
10980 switch (er.what)
10982 case mouseDown:
10983 inev.modifiers |= down_modifier;
10984 break;
10985 case mouseUp:
10986 inev.modifiers |= up_modifier;
10987 break;
10990 break;
10992 case inDrag:
10993 #if TARGET_API_MAC_CARBON
10994 case inProxyIcon:
10995 if (IsWindowPathSelectClick (window_ptr, &er))
10997 WindowPathSelect (window_ptr, NULL, NULL);
10998 break;
11000 if (part_code == inProxyIcon
11001 && (TrackWindowProxyDrag (window_ptr, er.where)
11002 != errUserWantsToDragWindow))
11003 break;
11004 DragWindow (window_ptr, er.where, NULL);
11005 #else /* not TARGET_API_MAC_CARBON */
11006 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
11007 #endif /* not TARGET_API_MAC_CARBON */
11008 /* Update the frame parameters. */
11009 #if !USE_CARBON_EVENTS
11011 struct frame *f = mac_window_to_frame (window_ptr);
11013 if (f && !f->async_iconified)
11014 mac_handle_origin_change (f);
11016 #endif
11017 break;
11019 case inGoAway:
11020 if (TrackGoAway (window_ptr, er.where))
11022 inev.kind = DELETE_WINDOW_EVENT;
11023 XSETFRAME (inev.frame_or_window,
11024 mac_window_to_frame (window_ptr));
11026 break;
11028 /* window resize handling added --ben */
11029 case inGrow:
11030 do_grow_window (window_ptr, &er);
11031 break;
11033 /* window zoom handling added --ben */
11034 case inZoomIn:
11035 case inZoomOut:
11036 if (TrackBox (window_ptr, er.where, part_code))
11037 do_zoom_window (window_ptr, part_code);
11038 break;
11040 default:
11041 break;
11044 break;
11046 case updateEvt:
11047 #if USE_CARBON_EVENTS
11048 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
11049 != eventNotHandledErr)
11050 break;
11051 #else
11052 do_window_update ((WindowPtr) er.message);
11053 #endif
11054 break;
11056 case osEvt:
11057 #if USE_CARBON_EVENTS
11058 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
11059 != eventNotHandledErr)
11060 break;
11061 #endif
11062 switch ((er.message >> 24) & 0x000000FF)
11064 case suspendResumeMessage:
11065 #if USE_MAC_TSM
11066 if (er.message & resumeFlag)
11067 mac_tsm_resume ();
11068 else
11069 mac_tsm_suspend ();
11070 #endif
11071 break;
11073 case mouseMovedMessage:
11074 #if !USE_CARBON_EVENTS
11075 SetRectRgn (mouse_region, er.where.h, er.where.v,
11076 er.where.h + 1, er.where.v + 1);
11077 #endif
11078 previous_help_echo_string = help_echo_string;
11079 help_echo_string = Qnil;
11081 if (dpyinfo->grabbed && last_mouse_frame
11082 && FRAME_LIVE_P (last_mouse_frame))
11083 f = last_mouse_frame;
11084 else
11085 f = dpyinfo->x_focus_frame;
11087 if (dpyinfo->mouse_face_hidden)
11089 dpyinfo->mouse_face_hidden = 0;
11090 clear_mouse_face (dpyinfo);
11093 if (f)
11095 WindowPtr wp = FRAME_MAC_WINDOW (f);
11096 Point mouse_pos = er.where;
11098 SetPortWindowPort (wp);
11100 GlobalToLocal (&mouse_pos);
11102 if (dpyinfo->grabbed && tracked_scroll_bar)
11103 #ifdef USE_TOOLKIT_SCROLL_BARS
11104 x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
11105 mouse_pos, &inev);
11106 #else /* not USE_TOOLKIT_SCROLL_BARS */
11107 x_scroll_bar_note_movement (tracked_scroll_bar,
11108 mouse_pos.v
11109 - XINT (tracked_scroll_bar->top),
11110 er.when * (1000 / 60));
11111 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11112 else
11114 /* Generate SELECT_WINDOW_EVENTs when needed. */
11115 if (!NILP (Vmouse_autoselect_window))
11117 Lisp_Object window;
11119 window = window_from_coordinates (f,
11120 mouse_pos.h,
11121 mouse_pos.v,
11122 0, 0, 0, 0);
11124 /* Window will be selected only when it is
11125 not selected now and last mouse movement
11126 event was not in it. Minibuffer window
11127 will be selected only when it is active. */
11128 if (WINDOWP (window)
11129 && !EQ (window, last_window)
11130 && !EQ (window, selected_window)
11131 /* For click-to-focus window managers
11132 create event iff we don't leave the
11133 selected frame. */
11134 && (focus_follows_mouse
11135 || (EQ (XWINDOW (window)->frame,
11136 XWINDOW (selected_window)->frame))))
11138 inev.kind = SELECT_WINDOW_EVENT;
11139 inev.frame_or_window = window;
11142 last_window=window;
11144 if (!note_mouse_movement (f, &mouse_pos))
11145 help_echo_string = previous_help_echo_string;
11149 /* If the contents of the global variable
11150 help_echo_string has changed, generate a
11151 HELP_EVENT. */
11152 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
11153 do_help = 1;
11154 break;
11156 break;
11158 case activateEvt:
11160 WindowPtr window_ptr = (WindowPtr) er.message;
11162 #if USE_CARBON_EVENTS
11163 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
11164 != eventNotHandledErr)
11165 break;
11166 #endif
11167 if (window_ptr == tip_window)
11169 HideWindow (tip_window);
11170 break;
11173 if (!is_emacs_window (window_ptr))
11174 break;
11176 if ((er.modifiers & activeFlag) != 0)
11178 /* A window has been activated */
11179 Point mouse_loc = er.where;
11181 x_detect_focus_change (dpyinfo, &er, &inev);
11183 SetPortWindowPort (window_ptr);
11184 GlobalToLocal (&mouse_loc);
11185 /* Window-activated event counts as mouse movement,
11186 so update things that depend on mouse position. */
11187 note_mouse_movement (mac_window_to_frame (window_ptr),
11188 &mouse_loc);
11190 else
11192 /* A window has been deactivated */
11193 #ifdef USE_TOOLKIT_SCROLL_BARS
11194 if (dpyinfo->grabbed && tracked_scroll_bar)
11196 struct input_event event;
11198 EVENT_INIT (event);
11199 event.kind = NO_EVENT;
11200 x_scroll_bar_handle_release (tracked_scroll_bar, &event);
11201 if (event.kind != NO_EVENT)
11203 event.timestamp = timestamp;
11204 kbd_buffer_store_event_hold (&event, hold_quit);
11205 count++;
11208 #endif
11209 dpyinfo->grabbed = 0;
11211 x_detect_focus_change (dpyinfo, &er, &inev);
11213 f = mac_window_to_frame (window_ptr);
11214 if (f == dpyinfo->mouse_face_mouse_frame)
11216 /* If we move outside the frame, then we're
11217 certainly no longer on any text in the
11218 frame. */
11219 clear_mouse_face (dpyinfo);
11220 dpyinfo->mouse_face_mouse_frame = 0;
11223 /* Generate a nil HELP_EVENT to cancel a help-echo.
11224 Do it only if there's something to cancel.
11225 Otherwise, the startup message is cleared when the
11226 mouse leaves the frame. */
11227 if (any_help_event_p)
11228 do_help = -1;
11231 break;
11233 case keyDown:
11234 case keyUp:
11235 case autoKey:
11237 int keycode = (er.message & keyCodeMask) >> 8;
11238 static SInt16 last_key_script = -1;
11239 SInt16 current_key_script;
11240 UInt32 modifiers = er.modifiers, mapped_modifiers;
11242 #if USE_CARBON_EVENTS && defined (MAC_OSX)
11243 GetEventParameter (eventRef, kEventParamKeyModifiers,
11244 typeUInt32, NULL,
11245 sizeof (UInt32), NULL, &modifiers);
11246 #endif
11247 mapped_modifiers = mac_mapped_modifiers (modifiers);
11249 #if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM)
11250 /* When using Carbon Events, we need to pass raw keyboard
11251 events to the TSM ourselves. If TSM handles it, it
11252 will pass back noErr, otherwise it will pass back
11253 "eventNotHandledErr" and we can process it
11254 normally. */
11255 if (!(mapped_modifiers
11256 & ~(mac_pass_command_to_system ? cmdKey : 0)
11257 & ~(mac_pass_control_to_system ? controlKey : 0)))
11259 OSStatus err;
11261 read_socket_inev = &inev;
11262 err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
11263 read_socket_inev = NULL;
11264 if (err != eventNotHandledErr)
11265 break;
11267 #endif
11268 if (er.what == keyUp)
11269 break;
11271 ObscureCursor ();
11273 f = mac_focus_frame (dpyinfo);
11275 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
11276 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
11278 clear_mouse_face (dpyinfo);
11279 dpyinfo->mouse_face_hidden = 1;
11282 current_key_script = GetScriptManagerVariable (smKeyScript);
11283 if (last_key_script != current_key_script)
11285 struct input_event event;
11287 EVENT_INIT (event);
11288 event.kind = LANGUAGE_CHANGE_EVENT;
11289 event.arg = Qnil;
11290 event.code = current_key_script;
11291 event.timestamp = timestamp;
11292 kbd_buffer_store_event (&event);
11293 count++;
11294 last_key_script = current_key_script;
11297 #if USE_MAC_TSM
11298 if (inev.kind != NO_EVENT)
11299 break;
11300 #endif
11302 #ifdef MAC_OSX
11303 if (mapped_modifiers & kEventKeyModifierFnMask
11304 && keycode <= 0x7f
11305 && fn_keycode_to_keycode_table[keycode])
11306 keycode = fn_keycode_to_keycode_table[keycode];
11307 #endif
11308 if (keycode <= 0x7f && keycode_to_xkeysym_table [keycode])
11310 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
11311 inev.code = 0xff00 | keycode_to_xkeysym_table [keycode];
11312 #ifdef MAC_OSX
11313 if (modifiers & kEventKeyModifierFnMask
11314 && keycode <= 0x7f
11315 && fn_keycode_to_keycode_table[keycode] == keycode)
11316 modifiers &= ~kEventKeyModifierFnMask;
11317 #endif
11319 else if (mapped_modifiers)
11321 /* translate the keycode back to determine the
11322 original key */
11323 #ifdef MAC_OSX
11324 UCKeyboardLayout *uchr_ptr = NULL;
11325 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
11326 OSStatus err;
11327 KeyboardLayoutRef layout;
11329 err = KLGetCurrentKeyboardLayout (&layout);
11330 if (err == noErr)
11331 KLGetKeyboardLayoutProperty (layout, kKLuchrData,
11332 (const void **) &uchr_ptr);
11333 #else
11334 static SInt16 last_key_layout_id = 0;
11335 static Handle uchr_handle = (Handle)-1;
11336 SInt16 current_key_layout_id =
11337 GetScriptVariable (current_key_script, smScriptKeys);
11339 if (uchr_handle == (Handle)-1
11340 || last_key_layout_id != current_key_layout_id)
11342 uchr_handle = GetResource ('uchr', current_key_layout_id);
11343 last_key_layout_id = current_key_layout_id;
11345 if (uchr_handle)
11346 uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
11347 #endif
11349 if (uchr_ptr)
11351 OSStatus status;
11352 UInt16 key_action = er.what - keyDown;
11353 UInt32 modifier_key_state =
11354 (modifiers & ~mapped_modifiers) >> 8;
11355 UInt32 keyboard_type = LMGetKbdType ();
11356 SInt32 dead_key_state = 0;
11357 UniChar code;
11358 UniCharCount actual_length;
11360 status = UCKeyTranslate (uchr_ptr,
11361 keycode, key_action,
11362 modifier_key_state,
11363 keyboard_type,
11364 kUCKeyTranslateNoDeadKeysMask,
11365 &dead_key_state,
11366 1, &actual_length, &code);
11367 if (status == noErr && actual_length == 1)
11368 mac_set_unicode_keystroke_event (code, &inev);
11370 #endif /* MAC_OSX */
11372 if (inev.kind == NO_EVENT)
11374 /* This code comes from Keyboard Resource,
11375 Appendix C of IM - Text. This is necessary
11376 since shift is ignored in KCHR table
11377 translation when option or command is pressed.
11378 It also does not translate correctly
11379 control-shift chars like C-% so mask off shift
11380 here also. */
11381 /* Mask off modifier keys that are mapped to some
11382 Emacs modifiers. */
11383 int new_modifiers = er.modifiers & ~mapped_modifiers;
11384 /* set high byte of keycode to modifier high byte*/
11385 int new_keycode = keycode | new_modifiers;
11386 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
11387 unsigned long some_state = 0;
11388 UInt32 new_char_code;
11390 new_char_code = KeyTranslate (kchr_ptr, new_keycode,
11391 &some_state);
11392 if (new_char_code == 0)
11393 /* Seems like a dead key. Append up-stroke. */
11394 new_char_code = KeyTranslate (kchr_ptr,
11395 new_keycode | 0x80,
11396 &some_state);
11397 if (new_char_code)
11399 inev.kind = ASCII_KEYSTROKE_EVENT;
11400 inev.code = new_char_code & 0xff;
11405 if (inev.kind == NO_EVENT)
11407 inev.kind = ASCII_KEYSTROKE_EVENT;
11408 inev.code = er.message & charCodeMask;
11411 inev.modifiers = mac_to_emacs_modifiers (modifiers);
11412 inev.modifiers |= (extra_keyboard_modifiers
11413 & (meta_modifier | alt_modifier
11414 | hyper_modifier | super_modifier));
11415 XSETFRAME (inev.frame_or_window, f);
11417 #if TARGET_API_MAC_CARBON
11418 if (inev.kind == ASCII_KEYSTROKE_EVENT
11419 && inev.code >= 0x80 && inev.modifiers)
11421 OSStatus err;
11422 TextEncoding encoding = kTextEncodingMacRoman;
11423 TextToUnicodeInfo ttu_info;
11425 UpgradeScriptInfoToTextEncoding (current_key_script,
11426 kTextLanguageDontCare,
11427 kTextRegionDontCare,
11428 NULL, &encoding);
11429 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
11430 if (err == noErr)
11432 UniChar code;
11433 Str255 pstr;
11434 ByteCount unicode_len;
11436 pstr[0] = 1;
11437 pstr[1] = inev.code;
11438 err = ConvertFromPStringToUnicode (ttu_info, pstr,
11439 sizeof (UniChar),
11440 &unicode_len, &code);
11441 if (err == noErr && unicode_len == sizeof (UniChar))
11442 mac_set_unicode_keystroke_event (code, &inev);
11443 DisposeTextToUnicodeInfo (&ttu_info);
11446 #endif
11448 break;
11450 case kHighLevelEvent:
11451 AEProcessAppleEvent (&er);
11452 break;
11454 default:
11455 break;
11457 #if USE_CARBON_EVENTS
11458 ReleaseEvent (eventRef);
11459 #endif
11461 if (inev.kind != NO_EVENT)
11463 inev.timestamp = timestamp;
11464 kbd_buffer_store_event_hold (&inev, hold_quit);
11465 count++;
11468 if (do_help
11469 && !(hold_quit && hold_quit->kind != NO_EVENT))
11471 Lisp_Object frame;
11473 if (f)
11474 XSETFRAME (frame, f);
11475 else
11476 frame = Qnil;
11478 if (do_help > 0)
11480 any_help_event_p = 1;
11481 gen_help_event (help_echo_string, frame, help_echo_window,
11482 help_echo_object, help_echo_pos);
11484 else
11486 help_echo_string = Qnil;
11487 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
11489 count++;
11494 /* If the focus was just given to an autoraising frame,
11495 raise it now. */
11496 /* ??? This ought to be able to handle more than one such frame. */
11497 if (pending_autoraise_frame)
11499 x_raise_frame (pending_autoraise_frame);
11500 pending_autoraise_frame = 0;
11503 if (mac_screen_config_changed)
11505 mac_get_screen_info (dpyinfo);
11506 mac_screen_config_changed = 0;
11509 #if !USE_CARBON_EVENTS
11510 /* Check which frames are still visible. We do this here because
11511 there doesn't seem to be any direct notification from the Window
11512 Manager that the visibility of a window has changed (at least,
11513 not in all cases). */
11515 Lisp_Object tail, frame;
11517 FOR_EACH_FRAME (tail, frame)
11519 struct frame *f = XFRAME (frame);
11521 /* The tooltip has been drawn already. Avoid the
11522 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
11523 if (EQ (frame, tip_frame))
11524 continue;
11526 if (FRAME_MAC_P (f))
11527 mac_handle_visibility_change (f);
11530 #endif
11532 --handling_signal;
11533 UNBLOCK_INPUT;
11534 return count;
11538 /* Need to override CodeWarrior's input function so no conversion is
11539 done on newlines Otherwise compiled functions in .elc files will be
11540 read incorrectly. Defined in ...:MSL C:MSL
11541 Common:Source:buffer_io.c. */
11542 #ifdef __MWERKS__
11543 void
11544 __convert_to_newlines (unsigned char * p, size_t * n)
11546 #pragma unused(p,n)
11549 void
11550 __convert_from_newlines (unsigned char * p, size_t * n)
11552 #pragma unused(p,n)
11554 #endif
11556 #ifdef MAC_OS8
11557 void
11558 make_mac_terminal_frame (struct frame *f)
11560 Lisp_Object frame;
11561 Rect r;
11563 XSETFRAME (frame, f);
11565 f->output_method = output_mac;
11566 f->output_data.mac = (struct mac_output *)
11567 xmalloc (sizeof (struct mac_output));
11568 bzero (f->output_data.mac, sizeof (struct mac_output));
11570 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
11572 FRAME_COLS (f) = 96;
11573 FRAME_LINES (f) = 4;
11575 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
11576 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
11578 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
11580 f->output_data.mac->cursor_pixel = 0;
11581 f->output_data.mac->border_pixel = 0x00ff00;
11582 f->output_data.mac->mouse_pixel = 0xff00ff;
11583 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
11585 f->output_data.mac->text_cursor = kThemeIBeamCursor;
11586 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
11587 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
11588 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
11589 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
11590 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
11592 FRAME_FONTSET (f) = -1;
11593 f->output_data.mac->explicit_parent = 0;
11594 f->left_pos = 8;
11595 f->top_pos = 32;
11596 f->border_width = 0;
11598 f->internal_border_width = 0;
11600 f->auto_raise = 1;
11601 f->auto_lower = 1;
11603 f->new_text_cols = 0;
11604 f->new_text_lines = 0;
11606 SetRect (&r, f->left_pos, f->top_pos,
11607 f->left_pos + FRAME_PIXEL_WIDTH (f),
11608 f->top_pos + FRAME_PIXEL_HEIGHT (f));
11610 BLOCK_INPUT;
11612 if (!(FRAME_MAC_WINDOW (f) =
11613 NewCWindow (NULL, &r, "\p", true, dBoxProc,
11614 (WindowPtr) -1, 1, (long) f->output_data.mac)))
11615 abort ();
11616 /* so that update events can find this mac_output struct */
11617 f->output_data.mac->mFP = f; /* point back to emacs frame */
11619 UNBLOCK_INPUT;
11621 x_make_gc (f);
11623 /* Need to be initialized for unshow_buffer in window.c. */
11624 selected_window = f->selected_window;
11626 Fmodify_frame_parameters (frame,
11627 Fcons (Fcons (Qfont,
11628 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
11629 Fmodify_frame_parameters (frame,
11630 Fcons (Fcons (Qforeground_color,
11631 build_string ("black")), Qnil));
11632 Fmodify_frame_parameters (frame,
11633 Fcons (Fcons (Qbackground_color,
11634 build_string ("white")), Qnil));
11636 #endif
11639 /***********************************************************************
11640 Initialization
11641 ***********************************************************************/
11643 static int mac_initialized = 0;
11645 static XrmDatabase
11646 mac_make_rdb (xrm_option)
11647 const char *xrm_option;
11649 XrmDatabase database;
11651 database = xrm_get_preference_database (NULL);
11652 if (xrm_option)
11653 xrm_merge_string_database (database, xrm_option);
11655 return database;
11658 struct mac_display_info *
11659 mac_term_init (display_name, xrm_option, resource_name)
11660 Lisp_Object display_name;
11661 char *xrm_option;
11662 char *resource_name;
11664 struct mac_display_info *dpyinfo;
11666 BLOCK_INPUT;
11668 if (!mac_initialized)
11670 mac_initialize ();
11671 mac_initialized = 1;
11674 if (x_display_list)
11675 error ("Sorry, this version can only handle one display");
11677 dpyinfo = &one_mac_display_info;
11678 bzero (dpyinfo, sizeof (*dpyinfo));
11680 #ifdef MAC_OSX
11681 dpyinfo->mac_id_name
11682 = (char *) xmalloc (SCHARS (Vinvocation_name)
11683 + SCHARS (Vsystem_name)
11684 + 2);
11685 sprintf (dpyinfo->mac_id_name, "%s@%s",
11686 SDATA (Vinvocation_name), SDATA (Vsystem_name));
11687 #else
11688 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
11689 strcpy (dpyinfo->mac_id_name, "Mac Display");
11690 #endif
11692 dpyinfo->reference_count = 0;
11693 dpyinfo->resx = 72.0;
11694 dpyinfo->resy = 72.0;
11696 mac_get_screen_info (dpyinfo);
11698 dpyinfo->grabbed = 0;
11699 dpyinfo->root_window = NULL;
11700 dpyinfo->image_cache = make_image_cache ();
11702 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
11703 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
11704 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
11705 dpyinfo->mouse_face_window = Qnil;
11706 dpyinfo->mouse_face_overlay = Qnil;
11707 dpyinfo->mouse_face_hidden = 0;
11709 dpyinfo->xrdb = mac_make_rdb (xrm_option);
11711 /* Put this display on the chain. */
11712 dpyinfo->next = x_display_list;
11713 x_display_list = dpyinfo;
11715 /* Put it on x_display_name_list. */
11716 x_display_name_list = Fcons (Fcons (display_name,
11717 Fcons (Qnil, dpyinfo->xrdb)),
11718 x_display_name_list);
11719 dpyinfo->name_list_element = XCAR (x_display_name_list);
11721 UNBLOCK_INPUT;
11723 return dpyinfo;
11726 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11728 void
11729 x_delete_display (dpyinfo)
11730 struct mac_display_info *dpyinfo;
11732 int i;
11734 /* Discard this display from x_display_name_list and x_display_list.
11735 We can't use Fdelq because that can quit. */
11736 if (! NILP (x_display_name_list)
11737 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
11738 x_display_name_list = XCDR (x_display_name_list);
11739 else
11741 Lisp_Object tail;
11743 tail = x_display_name_list;
11744 while (CONSP (tail) && CONSP (XCDR (tail)))
11746 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
11748 XSETCDR (tail, XCDR (XCDR (tail)));
11749 break;
11751 tail = XCDR (tail);
11755 if (x_display_list == dpyinfo)
11756 x_display_list = dpyinfo->next;
11757 else
11759 struct x_display_info *tail;
11761 for (tail = x_display_list; tail; tail = tail->next)
11762 if (tail->next == dpyinfo)
11763 tail->next = tail->next->next;
11766 /* Free the font names in the font table. */
11767 for (i = 0; i < dpyinfo->n_fonts; i++)
11768 if (dpyinfo->font_table[i].name)
11770 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
11771 xfree (dpyinfo->font_table[i].full_name);
11772 xfree (dpyinfo->font_table[i].name);
11775 if (dpyinfo->font_table)
11777 if (dpyinfo->font_table->font_encoder)
11778 xfree (dpyinfo->font_table->font_encoder);
11779 xfree (dpyinfo->font_table);
11781 if (dpyinfo->mac_id_name)
11782 xfree (dpyinfo->mac_id_name);
11784 if (x_display_list == 0)
11786 mac_clear_font_name_table ();
11787 bzero (dpyinfo, sizeof (*dpyinfo));
11792 static void
11793 init_menu_bar ()
11795 #ifdef MAC_OSX
11796 OSStatus err;
11797 MenuRef menu;
11798 MenuItemIndex menu_index;
11800 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
11801 &menu, &menu_index);
11802 if (err == noErr)
11803 SetMenuItemCommandKey (menu, menu_index, false, 0);
11804 #if USE_CARBON_EVENTS
11805 EnableMenuCommand (NULL, kHICommandPreferences);
11806 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
11807 &menu, &menu_index);
11808 if (err == noErr)
11810 SetMenuItemCommandKey (menu, menu_index, false, 0);
11811 InsertMenuItemTextWithCFString (menu, NULL,
11812 0, kMenuItemAttrSeparator, 0);
11813 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
11814 0, 0, kHICommandAbout);
11816 #endif /* USE_CARBON_EVENTS */
11817 #else /* !MAC_OSX */
11818 #if USE_CARBON_EVENTS
11819 SetMenuItemCommandID (GetMenuHandle (M_APPLE), I_ABOUT, kHICommandAbout);
11820 #endif
11821 #endif
11824 #if USE_MAC_TSM
11825 static void
11826 init_tsm ()
11828 #ifdef MAC_OSX
11829 static InterfaceTypeList types = {kUnicodeDocument};
11830 #else
11831 static InterfaceTypeList types = {kTextService};
11832 #endif
11834 NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
11835 &tsm_document_id, 0);
11837 #endif
11839 /* Set up use of X before we make the first connection. */
11841 extern frame_parm_handler mac_frame_parm_handlers[];
11843 static struct redisplay_interface x_redisplay_interface =
11845 mac_frame_parm_handlers,
11846 x_produce_glyphs,
11847 x_write_glyphs,
11848 x_insert_glyphs,
11849 x_clear_end_of_line,
11850 x_scroll_run,
11851 x_after_update_window_line,
11852 x_update_window_begin,
11853 x_update_window_end,
11854 x_cursor_to,
11855 x_flush,
11856 #if USE_CG_DRAWING
11857 mac_flush_display_optional,
11858 #else
11859 0, /* flush_display_optional */
11860 #endif
11861 x_clear_window_mouse_face,
11862 x_get_glyph_overhangs,
11863 x_fix_overlapping_area,
11864 x_draw_fringe_bitmap,
11865 #if USE_CG_DRAWING
11866 mac_define_fringe_bitmap,
11867 mac_destroy_fringe_bitmap,
11868 #else
11869 0, /* define_fringe_bitmap */
11870 0, /* destroy_fringe_bitmap */
11871 #endif
11872 mac_per_char_metric,
11873 mac_encode_char,
11874 mac_compute_glyph_string_overhangs,
11875 x_draw_glyph_string,
11876 mac_define_frame_cursor,
11877 mac_clear_frame_area,
11878 mac_draw_window_cursor,
11879 mac_draw_vertical_window_border,
11880 mac_shift_glyphs_for_insert
11883 void
11884 mac_initialize ()
11886 rif = &x_redisplay_interface;
11888 clear_frame_hook = x_clear_frame;
11889 ins_del_lines_hook = x_ins_del_lines;
11890 delete_glyphs_hook = x_delete_glyphs;
11891 ring_bell_hook = XTring_bell;
11892 reset_terminal_modes_hook = XTreset_terminal_modes;
11893 set_terminal_modes_hook = XTset_terminal_modes;
11894 update_begin_hook = x_update_begin;
11895 update_end_hook = x_update_end;
11896 set_terminal_window_hook = XTset_terminal_window;
11897 read_socket_hook = XTread_socket;
11898 frame_up_to_date_hook = XTframe_up_to_date;
11899 mouse_position_hook = XTmouse_position;
11900 frame_rehighlight_hook = XTframe_rehighlight;
11901 frame_raise_lower_hook = XTframe_raise_lower;
11903 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
11904 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
11905 redeem_scroll_bar_hook = XTredeem_scroll_bar;
11906 judge_scroll_bars_hook = XTjudge_scroll_bars;
11908 scroll_region_ok = 1; /* we'll scroll partial frames */
11909 char_ins_del_ok = 1;
11910 line_ins_del_ok = 1; /* we'll just blt 'em */
11911 fast_clear_end_of_line = 1; /* X does this well */
11912 memory_below_frame = 0; /* we don't remember what scrolls
11913 off the bottom */
11914 baud_rate = 19200;
11916 last_tool_bar_item = -1;
11917 any_help_event_p = 0;
11919 /* Try to use interrupt input; if we can't, then start polling. */
11920 Fset_input_mode (Qt, Qnil, Qt, Qnil);
11922 BLOCK_INPUT;
11924 #if TARGET_API_MAC_CARBON
11926 #if USE_CARBON_EVENTS
11927 #ifdef MAC_OSX
11928 init_service_handler ();
11929 #endif /* MAC_OSX */
11931 init_command_handler ();
11933 init_menu_bar ();
11935 #if USE_MAC_TSM
11936 init_tsm ();
11937 #endif
11938 #endif /* USE_CARBON_EVENTS */
11940 #ifdef MAC_OSX
11941 init_coercion_handler ();
11943 init_apple_event_handler ();
11945 init_dm_notification_handler ();
11947 if (!inhibit_window_system)
11949 static const ProcessSerialNumber psn = {0, kCurrentProcess};
11951 SetFrontProcess (&psn);
11953 #endif
11954 #endif
11956 #if USE_CG_DRAWING
11957 init_cg_color ();
11959 mac_init_fringe ();
11960 #endif
11962 UNBLOCK_INPUT;
11966 void
11967 syms_of_macterm ()
11969 #if 0
11970 staticpro (&x_error_message_string);
11971 x_error_message_string = Qnil;
11972 #endif
11974 Qcontrol = intern ("control"); staticpro (&Qcontrol);
11975 Qmeta = intern ("meta"); staticpro (&Qmeta);
11976 Qalt = intern ("alt"); staticpro (&Qalt);
11977 Qhyper = intern ("hyper"); staticpro (&Qhyper);
11978 Qsuper = intern ("super"); staticpro (&Qsuper);
11979 Qmodifier_value = intern ("modifier-value");
11980 staticpro (&Qmodifier_value);
11982 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
11983 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
11984 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
11985 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
11986 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
11988 #if USE_CARBON_EVENTS
11989 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
11990 #ifdef MAC_OSX
11991 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
11992 staticpro (&Qtoolbar_switch_mode);
11993 #if USE_MAC_FONT_PANEL
11994 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
11995 Qselection = intern ("selection"); staticpro (&Qselection);
11996 #endif
11998 Qservice = intern ("service"); staticpro (&Qservice);
11999 Qpaste = intern ("paste"); staticpro (&Qpaste);
12000 Qperform = intern ("perform"); staticpro (&Qperform);
12001 #endif
12002 #if USE_MAC_TSM
12003 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
12004 Qupdate_active_input_area = intern ("update-active-input-area");
12005 staticpro (&Qupdate_active_input_area);
12006 Qunicode_for_key_event = intern ("unicode-for-key-event");
12007 staticpro (&Qunicode_for_key_event);
12008 #endif
12009 #endif
12011 #ifdef MAC_OSX
12012 Fprovide (intern ("mac-carbon"), Qnil);
12013 #endif
12015 staticpro (&Qreverse);
12016 Qreverse = intern ("reverse");
12018 staticpro (&x_display_name_list);
12019 x_display_name_list = Qnil;
12021 staticpro (&last_mouse_scroll_bar);
12022 last_mouse_scroll_bar = Qnil;
12024 staticpro (&fm_font_family_alist);
12025 fm_font_family_alist = Qnil;
12027 #if USE_ATSUI
12028 staticpro (&atsu_font_id_hash);
12029 atsu_font_id_hash = Qnil;
12031 staticpro (&fm_style_face_attributes_alist);
12032 fm_style_face_attributes_alist = Qnil;
12033 #endif
12035 #if USE_MAC_TSM
12036 staticpro (&saved_ts_script_language_on_focus);
12037 saved_ts_script_language_on_focus = Qnil;
12038 #endif
12040 /* We don't yet support this, but defining this here avoids whining
12041 from cus-start.el and other places, like "M-x set-variable". */
12042 DEFVAR_BOOL ("x-use-underline-position-properties",
12043 &x_use_underline_position_properties,
12044 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
12045 A value of nil means ignore them. If you encounter fonts with bogus
12046 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
12047 to 4.1, set this to nil.
12049 NOTE: Not supported on Mac yet. */);
12050 x_use_underline_position_properties = 0;
12052 DEFVAR_BOOL ("x-underline-at-descent-line",
12053 &x_underline_at_descent_line,
12054 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
12055 A value of nil means to draw the underline according to the value of the
12056 variable `x-use-underline-position-properties', which is usually at the
12057 baseline level. The default value is nil. */);
12058 x_underline_at_descent_line = 0;
12060 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
12061 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
12062 #ifdef USE_TOOLKIT_SCROLL_BARS
12063 Vx_toolkit_scroll_bars = Qt;
12064 #else
12065 Vx_toolkit_scroll_bars = Qnil;
12066 #endif
12068 staticpro (&last_mouse_motion_frame);
12069 last_mouse_motion_frame = Qnil;
12071 /* Variables to configure modifier key assignment. */
12073 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
12074 doc: /* *Modifier key assumed when the Mac control key is pressed.
12075 The value can be `control', `meta', `alt', `hyper', or `super' for the
12076 respective modifier. The default is `control'. */);
12077 Vmac_control_modifier = Qcontrol;
12079 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
12080 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
12081 The value can be `control', `meta', `alt', `hyper', or `super' for the
12082 respective modifier. If the value is nil then the key will act as the
12083 normal Mac control modifier, and the option key can be used to compose
12084 characters depending on the chosen Mac keyboard setting. */);
12085 Vmac_option_modifier = Qnil;
12087 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
12088 doc: /* *Modifier key assumed when the Mac command key is pressed.
12089 The value can be `control', `meta', `alt', `hyper', or `super' for the
12090 respective modifier. The default is `meta'. */);
12091 Vmac_command_modifier = Qmeta;
12093 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
12094 doc: /* *Modifier key assumed when the Mac function key is pressed.
12095 The value can be `control', `meta', `alt', `hyper', or `super' for the
12096 respective modifier. Note that remapping the function key may lead to
12097 unexpected results for some keys on non-US/GB keyboards. */);
12098 Vmac_function_modifier = Qnil;
12100 DEFVAR_LISP ("mac-emulate-three-button-mouse",
12101 &Vmac_emulate_three_button_mouse,
12102 doc: /* *Specify a way of three button mouse emulation.
12103 The value can be nil, t, or the symbol `reverse'.
12104 A value of nil means that no emulation should be done and the modifiers
12105 should be placed on the mouse-1 event.
12106 t means that when the option-key is held down while pressing the mouse
12107 button, the click will register as mouse-2 and while the command-key
12108 is held down, the click will register as mouse-3.
12109 The symbol `reverse' means that the option-key will register for
12110 mouse-3 and the command-key will register for mouse-2. */);
12111 Vmac_emulate_three_button_mouse = Qnil;
12113 #if USE_CARBON_EVENTS
12114 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
12115 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
12116 Otherwise, the right click will be treated as mouse-2 and the wheel
12117 button will be mouse-3. */);
12118 mac_wheel_button_is_mouse_2 = 1;
12120 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
12121 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
12122 mac_pass_command_to_system = 1;
12124 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
12125 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
12126 mac_pass_control_to_system = 1;
12128 #endif
12130 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
12131 doc: /* *If non-nil, allow anti-aliasing.
12132 The text will be rendered using Core Graphics text rendering which
12133 may anti-alias the text. */);
12134 #if USE_CG_DRAWING
12135 mac_use_core_graphics = 1;
12136 #else
12137 mac_use_core_graphics = 0;
12138 #endif
12140 /* Register an entry for `mac-roman' so that it can be used when
12141 creating the terminal frame on Mac OS 9 before loading
12142 term/mac-win.elc. */
12143 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
12144 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
12145 Each entry should be of the form:
12147 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
12149 where CHARSET-NAME is a string used in font names to identify the
12150 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
12151 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
12152 Vmac_charset_info_alist =
12153 Fcons (list3 (build_string ("mac-roman"),
12154 make_number (smRoman), Qnil), Qnil);
12156 #if USE_MAC_TSM
12157 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
12158 doc: /* Overlay used to display Mac TSM active input area. */);
12159 Vmac_ts_active_input_overlay = Qnil;
12161 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
12162 doc: /* *How to change Mac TSM script/language when a frame gets focus.
12163 If the value is t, the input script and language are restored to those
12164 used in the last focus frame. If the value is a pair of integers, the
12165 input script and language codes, which are defined in the Script
12166 Manager, are set to its car and cdr parts, respectively. Otherwise,
12167 Emacs doesn't set them and thus follows the system default behavior. */);
12168 Vmac_ts_script_language_on_focus = Qnil;
12169 #endif
12172 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
12173 (do not change this comment) */