*** empty log message ***
[emacs.git] / src / macterm.c
bloba043e5a4860a0db349e44745e330af6197188f00
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
24 #include <config.h>
25 #include <signal.h>
27 #include <stdio.h>
29 #include "lisp.h"
30 #include "blockinput.h"
32 #include "macterm.h"
34 #ifndef MAC_OSX
35 #include <alloca.h>
36 #endif
38 #if !TARGET_API_MAC_CARBON
39 #include <Quickdraw.h>
40 #include <ToolUtils.h>
41 #include <Sound.h>
42 #include <Events.h>
43 #include <Script.h>
44 #include <Resources.h>
45 #include <Fonts.h>
46 #include <TextUtils.h>
47 #include <LowMem.h>
48 #include <Controls.h>
49 #include <Windows.h>
50 #include <Displays.h>
51 #if defined (__MRC__) || (__MSL__ >= 0x6000)
52 #include <ControlDefinitions.h>
53 #endif
55 #if __profile__
56 #include <profiler.h>
57 #endif
58 #endif /* not TARGET_API_MAC_CARBON */
60 #include "systty.h"
61 #include "systime.h"
63 #include <ctype.h>
64 #include <errno.h>
65 #include <setjmp.h>
66 #include <sys/stat.h>
68 #include "charset.h"
69 #include "coding.h"
70 #include "frame.h"
71 #include "dispextern.h"
72 #include "fontset.h"
73 #include "termhooks.h"
74 #include "termopts.h"
75 #include "termchar.h"
76 #include "disptab.h"
77 #include "buffer.h"
78 #include "window.h"
79 #include "keyboard.h"
80 #include "intervals.h"
81 #include "atimer.h"
82 #include "keymap.h"
86 /* Non-nil means Emacs uses toolkit scroll bars. */
88 Lisp_Object Vx_toolkit_scroll_bars;
90 /* If non-zero, the text will be rendered using Core Graphics text
91 rendering which may anti-alias the text. */
92 int mac_use_core_graphics;
94 /* Non-zero means make use of UNDERLINE_POSITION font properties.
95 (Not yet supported.) */
96 int x_use_underline_position_properties;
98 /* Non-zero means to draw the underline at the same place as the descent line. */
100 int x_underline_at_descent_line;
102 /* This is a chain of structures for all the X displays currently in
103 use. */
105 struct x_display_info *x_display_list;
107 /* This is a list of cons cells, each of the form (NAME
108 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
109 x_display_list and in the same order. NAME is the name of the
110 frame. FONT-LIST-CACHE records previous values returned by
111 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
112 equivalent, which is implemented with a Lisp object, for the
113 display. */
115 Lisp_Object x_display_name_list;
117 /* This is display since Mac does not support multiple ones. */
118 struct mac_display_info one_mac_display_info;
120 /* Frame being updated by update_frame. This is declared in term.c.
121 This is set by update_begin and looked at by all the XT functions.
122 It is zero while not inside an update. In that case, the XT
123 functions assume that `selected_frame' is the frame to apply to. */
125 extern struct frame *updating_frame;
127 /* This is a frame waiting to be auto-raised, within XTread_socket. */
129 struct frame *pending_autoraise_frame;
131 /* Mouse movement.
133 Formerly, we used PointerMotionHintMask (in standard_event_mask)
134 so that we would have to call XQueryPointer after each MotionNotify
135 event to ask for another such event. However, this made mouse tracking
136 slow, and there was a bug that made it eventually stop.
138 Simply asking for MotionNotify all the time seems to work better.
140 In order to avoid asking for motion events and then throwing most
141 of them away or busy-polling the server for mouse positions, we ask
142 the server for pointer motion hints. This means that we get only
143 one event per group of mouse movements. "Groups" are delimited by
144 other kinds of events (focus changes and button clicks, for
145 example), or by XQueryPointer calls; when one of these happens, we
146 get another MotionNotify event the next time the mouse moves. This
147 is at least as efficient as getting motion events when mouse
148 tracking is on, and I suspect only negligibly worse when tracking
149 is off. */
151 /* Where the mouse was last time we reported a mouse event. */
153 Rect last_mouse_glyph;
154 FRAME_PTR last_mouse_glyph_frame;
156 /* The scroll bar in which the last X motion event occurred.
158 If the last X motion event occurred in a scroll bar, we set this so
159 XTmouse_position can know whether to report a scroll bar motion or
160 an ordinary motion.
162 If the last X motion event didn't occur in a scroll bar, we set
163 this to Qnil, to tell XTmouse_position to return an ordinary motion
164 event. */
166 Lisp_Object last_mouse_scroll_bar;
168 /* This is a hack. We would really prefer that XTmouse_position would
169 return the time associated with the position it returns, but there
170 doesn't seem to be any way to wrest the time-stamp from the server
171 along with the position query. So, we just keep track of the time
172 of the last movement we received, and return that in hopes that
173 it's somewhat accurate. */
175 Time last_mouse_movement_time;
177 struct scroll_bar *tracked_scroll_bar = NULL;
179 /* Incremented by XTread_socket whenever it really tries to read
180 events. */
182 #ifdef __STDC__
183 int volatile input_signal_count;
184 #else
185 int input_signal_count;
186 #endif
188 extern Lisp_Object Vsystem_name;
190 extern Lisp_Object Qeql;
192 /* A mask of extra modifier bits to put into every keyboard char. */
194 extern EMACS_INT extra_keyboard_modifiers;
196 /* The keysyms to use for the various modifiers. */
198 static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
200 extern int inhibit_window_system;
202 #if __MRC__ && !TARGET_API_MAC_CARBON
203 QDGlobals qd; /* QuickDraw global information structure. */
204 #endif
206 struct mac_display_info *mac_display_info_for_display (Display *);
207 static void x_update_window_end P_ ((struct window *, int, int));
208 int x_catch_errors P_ ((Display *));
209 void x_uncatch_errors P_ ((Display *, int));
210 void x_lower_frame P_ ((struct frame *));
211 void x_scroll_bar_clear P_ ((struct frame *));
212 int x_had_errors_p P_ ((Display *));
213 void x_wm_set_size_hint P_ ((struct frame *, long, int));
214 void x_raise_frame P_ ((struct frame *));
215 void x_set_window_size P_ ((struct frame *, int, int, int));
216 void x_wm_set_window_state P_ ((struct frame *, int));
217 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
218 void mac_initialize P_ ((void));
219 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
220 static int x_compute_min_glyph_bounds P_ ((struct frame *));
221 static void x_update_end P_ ((struct frame *));
222 static void XTframe_up_to_date P_ ((struct frame *));
223 static void XTset_terminal_modes P_ ((void));
224 static void XTreset_terminal_modes P_ ((void));
225 static void x_clear_frame P_ ((void));
226 static void frame_highlight P_ ((struct frame *));
227 static void frame_unhighlight P_ ((struct frame *));
228 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
229 static void XTframe_rehighlight P_ ((struct frame *));
230 static void x_frame_rehighlight P_ ((struct x_display_info *));
231 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
232 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
233 enum text_cursor_kinds));
235 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
236 static void x_update_begin P_ ((struct frame *));
237 static void x_update_window_begin P_ ((struct window *));
238 static void x_after_update_window_line P_ ((struct glyph_row *));
240 static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
241 static void XSetFont P_ ((Display *, GC, XFontStruct *));
243 extern void mac_toolbox_initialize P_ ((void));
244 extern void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
245 enum scroll_bar_part *,
246 Lisp_Object *, Lisp_Object *,
247 unsigned long *));
248 #if USE_CG_DRAWING
249 extern void mac_flush_display_optional P_ ((struct frame *));
250 #endif
252 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
253 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
254 #define GC_FONT(gc) ((gc)->xgcv.font)
255 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
257 #define CG_SET_FILL_COLOR(context, color) \
258 CGContextSetRGBFillColor (context, \
259 RED_FROM_ULONG (color) / 255.0f, \
260 GREEN_FROM_ULONG (color) / 255.0f, \
261 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
262 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
263 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
264 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
265 do { \
266 if (CGColorGetTypeID != NULL) \
267 CGContextSetFillColorWithColor (context, cg_color); \
268 else \
269 CG_SET_FILL_COLOR (context, color); \
270 } while (0)
271 #else
272 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
273 CGContextSetFillColorWithColor (context, cg_color)
274 #endif
275 #else
276 #define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
277 CG_SET_FILL_COLOR (context, color)
278 #endif
279 #define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \
280 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
281 (gc)->cg_fore_color)
282 #define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \
283 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \
284 (gc)->cg_back_color)
287 #define CG_SET_STROKE_COLOR(context, color) \
288 CGContextSetRGBStrokeColor (context, \
289 RED_FROM_ULONG (color) / 255.0f, \
290 GREEN_FROM_ULONG (color) / 255.0f, \
291 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
292 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
293 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
294 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
295 do { \
296 if (CGColorGetTypeID != NULL) \
297 CGContextSetStrokeColorWithColor (context, cg_color); \
298 else \
299 CG_SET_STROKE_COLOR (context, color); \
300 } while (0)
301 #else
302 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
303 CGContextSetStrokeColorWithColor (context, cg_color)
304 #endif
305 #else
306 #define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
307 CG_SET_STROKE_COLOR (context, color)
308 #endif
309 #define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
310 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
311 (gc)->cg_fore_color)
313 #if USE_CG_DRAWING
314 /* Fringe bitmaps. */
316 static int max_fringe_bmp = 0;
317 static CGImageRef *fringe_bmp = 0;
319 static CGColorSpaceRef mac_cg_color_space_rgb;
320 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
321 static CGColorRef mac_cg_color_black;
322 #endif
324 static void
325 init_cg_color ()
327 mac_cg_color_space_rgb = CGColorSpaceCreateDeviceRGB ();
328 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
329 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
330 /* Don't check the availability of CGColorCreate; this symbol is
331 defined even in Mac OS X 10.1. */
332 if (CGColorGetTypeID != NULL)
333 #endif
335 float rgba[] = {0.0f, 0.0f, 0.0f, 1.0f};
337 mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba);
339 #endif
341 #endif /* USE_CG_DRAWING */
343 /* X display function emulation */
345 /* Mac version of XDrawLine. */
347 static void
348 mac_draw_line (f, gc, x1, y1, x2, y2)
349 struct frame *f;
350 GC gc;
351 int x1, y1, x2, y2;
353 #if USE_CG_DRAWING
354 CGContextRef context;
355 float gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
357 if (y1 != y2)
358 gx1 += 0.5f, gx2 += 0.5f;
359 if (x1 != x2)
360 gy1 += 0.5f, gy2 += 0.5f;
362 context = mac_begin_cg_clip (f, gc);
363 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
364 CGContextBeginPath (context);
365 CGContextMoveToPoint (context, gx1, gy1);
366 CGContextAddLineToPoint (context, gx2, gy2);
367 CGContextClosePath (context);
368 CGContextStrokePath (context);
369 mac_end_cg_clip (f);
370 #else
371 if (x1 == x2)
373 if (y1 > y2)
374 y1--;
375 else if (y2 > y1)
376 y2--;
378 else if (y1 == y2)
380 if (x1 > x2)
381 x1--;
382 else
383 x2--;
386 mac_begin_clip (f, gc);
387 RGBForeColor (GC_FORE_COLOR (gc));
388 MoveTo (x1, y1);
389 LineTo (x2, y2);
390 mac_end_clip (f, gc);
391 #endif
394 /* Mac version of XDrawLine (to Pixmap). */
396 void
397 XDrawLine (display, p, gc, x1, y1, x2, y2)
398 Display *display;
399 Pixmap p;
400 GC gc;
401 int x1, y1, x2, y2;
403 CGrafPtr old_port;
404 GDHandle old_gdh;
406 if (x1 == x2)
408 if (y1 > y2)
409 y1--;
410 else if (y2 > y1)
411 y2--;
413 else if (y1 == y2)
415 if (x1 > x2)
416 x1--;
417 else
418 x2--;
421 GetGWorld (&old_port, &old_gdh);
422 SetGWorld (p, NULL);
424 RGBForeColor (GC_FORE_COLOR (gc));
426 LockPixels (GetGWorldPixMap (p));
427 MoveTo (x1, y1);
428 LineTo (x2, y2);
429 UnlockPixels (GetGWorldPixMap (p));
431 SetGWorld (old_port, old_gdh);
435 static void
436 mac_erase_rectangle (f, gc, x, y, width, height)
437 struct frame *f;
438 GC gc;
439 int x, y;
440 unsigned int width, height;
442 #if USE_CG_DRAWING
444 CGContextRef context;
446 context = mac_begin_cg_clip (f, gc);
447 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
448 CGContextFillRect (context, CGRectMake (x, y, width, height));
449 mac_end_cg_clip (f);
451 #else
453 Rect r;
455 mac_begin_clip (f, gc);
456 RGBBackColor (GC_BACK_COLOR (gc));
457 SetRect (&r, x, y, x + width, y + height);
458 EraseRect (&r);
459 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
460 mac_end_clip (f, gc);
462 #endif
466 /* Mac version of XClearArea. */
468 void
469 mac_clear_area (f, x, y, width, height)
470 struct frame *f;
471 int x, y;
472 unsigned int width, height;
474 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
477 /* Mac version of XClearWindow. */
479 static void
480 mac_clear_window (f)
481 struct frame *f;
483 #if USE_CG_DRAWING
485 CGContextRef context;
486 GC gc = FRAME_NORMAL_GC (f);
488 context = mac_begin_cg_clip (f, NULL);
489 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
490 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
491 FRAME_PIXEL_HEIGHT (f)));
492 mac_end_cg_clip (f);
494 #else /* !USE_CG_DRAWING */
495 mac_begin_clip (f, NULL);
496 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
497 #if TARGET_API_MAC_CARBON
499 Rect r;
501 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
502 EraseRect (&r);
504 #else /* not TARGET_API_MAC_CARBON */
505 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
506 #endif /* not TARGET_API_MAC_CARBON */
507 mac_end_clip (f, NULL);
508 #endif
512 /* Mac replacement for XCopyArea. */
514 #if USE_CG_DRAWING
515 static void
516 mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
517 dest_x, dest_y, overlay_p)
518 CGImageRef image;
519 struct frame *f;
520 GC gc;
521 int src_x, src_y;
522 unsigned int width, height;
523 int dest_x, dest_y, overlay_p;
525 CGContextRef context;
526 float port_height = FRAME_PIXEL_HEIGHT (f);
527 CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
529 context = mac_begin_cg_clip (f, gc);
530 if (!overlay_p)
532 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
533 CGContextFillRect (context, dest_rect);
535 CGContextClipToRect (context, dest_rect);
536 CGContextScaleCTM (context, 1, -1);
537 CGContextTranslateCTM (context, 0, -port_height);
538 if (CGImageIsMask (image))
539 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
540 CGContextDrawImage (context,
541 CGRectMake (dest_x - src_x,
542 port_height - (dest_y - src_y
543 + CGImageGetHeight (image)),
544 CGImageGetWidth (image),
545 CGImageGetHeight (image)),
546 image);
547 mac_end_cg_clip (f);
550 #else /* !USE_CG_DRAWING */
552 static void
553 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
554 struct frame *f;
555 GC gc;
556 int x, y, width, height;
557 unsigned short *bits;
558 int overlay_p;
560 BitMap bitmap;
561 Rect r;
563 bitmap.rowBytes = sizeof(unsigned short);
564 bitmap.baseAddr = (char *)bits;
565 SetRect (&(bitmap.bounds), 0, 0, width, height);
567 mac_begin_clip (f, gc);
568 RGBForeColor (GC_FORE_COLOR (gc));
569 RGBBackColor (GC_BACK_COLOR (gc));
570 SetRect (&r, x, y, x + width, y + height);
571 #if TARGET_API_MAC_CARBON
573 CGrafPtr port;
575 GetPort (&port);
576 LockPortBits (port);
577 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
578 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
579 UnlockPortBits (port);
581 #else /* not TARGET_API_MAC_CARBON */
582 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
583 overlay_p ? srcOr : srcCopy, 0);
584 #endif /* not TARGET_API_MAC_CARBON */
585 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
586 mac_end_clip (f, gc);
588 #endif /* !USE_CG_DRAWING */
591 /* Mac replacement for XCreateBitmapFromBitmapData. */
593 static void
594 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
595 BitMap *bitmap;
596 char *bits;
597 int w, h;
599 static const unsigned char swap_nibble[16]
600 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
601 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
602 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
603 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
604 int i, j, w1;
605 char *p;
607 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
608 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
609 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
610 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
611 for (i = 0; i < h; i++)
613 p = bitmap->baseAddr + i * bitmap->rowBytes;
614 for (j = 0; j < w1; j++)
616 /* Bitswap XBM bytes to match how Mac does things. */
617 unsigned char c = *bits++;
618 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
619 | (swap_nibble[(c>>4) & 0xf]));
623 SetRect (&(bitmap->bounds), 0, 0, w, h);
627 static void
628 mac_free_bitmap (bitmap)
629 BitMap *bitmap;
631 xfree (bitmap->baseAddr);
635 Pixmap
636 XCreatePixmap (display, w, width, height, depth)
637 Display *display;
638 WindowRef w;
639 unsigned int width, height;
640 unsigned int depth;
642 Pixmap pixmap;
643 Rect r;
644 QDErr err;
646 SetPortWindowPort (w);
648 SetRect (&r, 0, 0, width, height);
649 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
650 if (depth == 1)
651 #endif
652 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
653 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
654 else
655 /* CreateCGImageFromPixMaps requires ARGB format. */
656 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
657 #endif
658 if (err != noErr)
659 return NULL;
660 return pixmap;
664 Pixmap
665 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
666 Display *display;
667 WindowRef w;
668 char *data;
669 unsigned int width, height;
670 unsigned long fg, bg;
671 unsigned int depth;
673 Pixmap pixmap;
674 BitMap bitmap;
675 CGrafPtr old_port;
676 GDHandle old_gdh;
677 static GC gc = NULL;
679 if (gc == NULL)
680 gc = XCreateGC (display, w, 0, NULL);
682 pixmap = XCreatePixmap (display, w, width, height, depth);
683 if (pixmap == NULL)
684 return NULL;
686 GetGWorld (&old_port, &old_gdh);
687 SetGWorld (pixmap, NULL);
688 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
689 XSetForeground (display, gc, fg);
690 XSetBackground (display, gc, bg);
691 RGBForeColor (GC_FORE_COLOR (gc));
692 RGBBackColor (GC_BACK_COLOR (gc));
693 LockPixels (GetGWorldPixMap (pixmap));
694 #if TARGET_API_MAC_CARBON
695 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
696 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
697 #else /* not TARGET_API_MAC_CARBON */
698 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
699 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
700 #endif /* not TARGET_API_MAC_CARBON */
701 UnlockPixels (GetGWorldPixMap (pixmap));
702 SetGWorld (old_port, old_gdh);
703 mac_free_bitmap (&bitmap);
705 return pixmap;
709 void
710 XFreePixmap (display, pixmap)
711 Display *display;
712 Pixmap pixmap;
714 DisposeGWorld (pixmap);
718 /* Mac replacement for XFillRectangle. */
720 static void
721 mac_fill_rectangle (f, gc, x, y, width, height)
722 struct frame *f;
723 GC gc;
724 int x, y;
725 unsigned int width, height;
727 #if USE_CG_DRAWING
728 CGContextRef context;
730 context = mac_begin_cg_clip (f, gc);
731 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
732 CGContextFillRect (context, CGRectMake (x, y, width, height));
733 mac_end_cg_clip (f);
734 #else
735 Rect r;
737 mac_begin_clip (f, gc);
738 RGBForeColor (GC_FORE_COLOR (gc));
739 SetRect (&r, x, y, x + width, y + height);
740 PaintRect (&r); /* using foreground color of gc */
741 mac_end_clip (f, gc);
742 #endif
746 /* Mac replacement for XDrawRectangle: dest is a window. */
748 static void
749 mac_draw_rectangle (f, gc, x, y, width, height)
750 struct frame *f;
751 GC gc;
752 int x, y;
753 unsigned int width, height;
755 #if USE_CG_DRAWING
756 CGContextRef context;
758 context = mac_begin_cg_clip (f, gc);
759 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
760 CGContextStrokeRect (context,
761 CGRectMake (x + 0.5f, y + 0.5f, width, height));
762 mac_end_cg_clip (f);
763 #else
764 Rect r;
766 mac_begin_clip (f, gc);
767 RGBForeColor (GC_FORE_COLOR (gc));
768 SetRect (&r, x, y, x + width + 1, y + height + 1);
769 FrameRect (&r); /* using foreground color of gc */
770 mac_end_clip (f, gc);
771 #endif
775 static void
776 mac_invert_rectangle (f, x, y, width, height)
777 struct frame *f;
778 int x, y;
779 unsigned int width, height;
781 Rect r;
783 mac_begin_clip (f, NULL);
784 SetRect (&r, x, y, x + width, y + height);
785 InvertRect (&r);
786 mac_end_clip (f, NULL);
790 #if USE_ATSUI
791 static OSStatus
792 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
793 ConstUniCharArrayPtr text;
794 UniCharCount text_length;
795 ATSUStyle style;
796 ATSUTextLayout *text_layout;
798 OSStatus err;
799 static ATSUTextLayout saved_text_layout = NULL;
801 if (saved_text_layout == NULL)
803 static const UniCharCount lengths[] = {kATSUToTextEnd};
804 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
805 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
806 static ATSLineLayoutOptions line_layout =
807 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
808 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
809 | kATSLineUseQDRendering
810 #else
811 kATSLineIsDisplayOnly | kATSLineFractDisable
812 #endif
814 static const ATSUAttributeValuePtr values[] = {&line_layout};
816 err = ATSUCreateTextLayoutWithTextPtr (text,
817 kATSUFromTextBeginning,
818 kATSUToTextEnd,
819 text_length,
820 1, lengths, &style,
821 &saved_text_layout);
822 if (err == noErr)
823 err = ATSUSetLayoutControls (saved_text_layout,
824 sizeof (tags) / sizeof (tags[0]),
825 tags, sizes, values);
826 if (err == noErr)
827 err = ATSUSetTransientFontMatching (saved_text_layout, true);
829 else
831 err = ATSUSetRunStyle (saved_text_layout, style,
832 kATSUFromTextBeginning, kATSUToTextEnd);
833 if (err == noErr)
834 err = ATSUSetTextPointerLocation (saved_text_layout, text,
835 kATSUFromTextBeginning,
836 kATSUToTextEnd,
837 text_length);
840 if (err == noErr)
841 *text_layout = saved_text_layout;
842 return err;
846 static void
847 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
848 overstrike_p, bytes_per_char)
849 struct frame *f;
850 GC gc;
851 int x, y;
852 char *buf;
853 int nchars, bg_width, overstrike_p, bytes_per_char;
855 OSStatus err;
856 ATSUTextLayout text_layout;
858 xassert (bytes_per_char == 2);
860 #ifndef WORDS_BIG_ENDIAN
862 int i;
863 UniChar *text = (UniChar *)buf;
865 for (i = 0; i < nchars; i++)
866 text[i] = EndianU16_BtoN (text[i]);
868 #endif
869 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
870 nchars,
871 GC_FONT (gc)->mac_style,
872 &text_layout);
873 if (err != noErr)
874 return;
875 #ifdef MAC_OSX
876 if (!mac_use_core_graphics)
878 #endif
879 mac_begin_clip (f, gc);
880 RGBForeColor (GC_FORE_COLOR (gc));
881 if (bg_width)
883 Rect r;
885 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
886 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
887 RGBBackColor (GC_BACK_COLOR (gc));
888 EraseRect (&r);
889 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
891 MoveTo (x, y);
892 ATSUDrawText (text_layout,
893 kATSUFromTextBeginning, kATSUToTextEnd,
894 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
895 if (overstrike_p)
897 MoveTo (x + 1, y);
898 ATSUDrawText (text_layout,
899 kATSUFromTextBeginning, kATSUToTextEnd,
900 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
902 mac_end_clip (f, gc);
903 #ifdef MAC_OSX
905 else
907 static CGContextRef context;
908 float port_height = FRAME_PIXEL_HEIGHT (f);
909 static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
910 static const ByteCount sizes[] = {sizeof (CGContextRef)};
911 static const ATSUAttributeValuePtr values[] = {&context};
913 #if USE_CG_DRAWING
914 context = mac_begin_cg_clip (f, gc);
915 #else
916 CGrafPtr port;
918 GetPort (&port);
919 QDBeginCGContext (port, &context);
920 if (gc->n_clip_rects || bg_width)
922 CGContextTranslateCTM (context, 0, port_height);
923 CGContextScaleCTM (context, 1, -1);
924 if (gc->n_clip_rects)
925 CGContextClipToRects (context, gc->clip_rects,
926 gc->n_clip_rects);
927 #endif
928 if (bg_width)
930 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
931 CGContextFillRect (context,
932 CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
933 bg_width,
934 FONT_HEIGHT (GC_FONT (gc))));
936 CGContextScaleCTM (context, 1, -1);
937 CGContextTranslateCTM (context, 0, -port_height);
938 #if !USE_CG_DRAWING
940 #endif
941 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
942 err = ATSUSetLayoutControls (text_layout,
943 sizeof (tags) / sizeof (tags[0]),
944 tags, sizes, values);
945 if (err == noErr)
947 ATSUDrawText (text_layout,
948 kATSUFromTextBeginning, kATSUToTextEnd,
949 Long2Fix (x), Long2Fix (port_height - y));
950 if (overstrike_p)
951 ATSUDrawText (text_layout,
952 kATSUFromTextBeginning, kATSUToTextEnd,
953 Long2Fix (x + 1), Long2Fix (port_height - y));
955 #if USE_CG_DRAWING
956 mac_end_cg_clip (f);
957 context = NULL;
958 #else
959 CGContextSynchronize (context);
960 QDEndCGContext (port, &context);
961 #endif
962 #if 0
963 /* This doesn't work on Mac OS X 10.1. */
964 ATSUClearLayoutControls (text_layout,
965 sizeof (tags) / sizeof (tags[0]), tags);
966 #else
967 ATSUSetLayoutControls (text_layout,
968 sizeof (tags) / sizeof (tags[0]),
969 tags, sizes, values);
970 #endif
972 #endif /* MAC_OSX */
974 #endif /* USE_ATSUI */
977 static void
978 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
979 overstrike_p, bytes_per_char)
980 struct frame *f;
981 GC gc;
982 int x, y;
983 char *buf;
984 int nchars, bg_width, overstrike_p, bytes_per_char;
986 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
987 UInt32 savedFlags;
988 #endif
990 mac_begin_clip (f, gc);
991 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
992 if (mac_use_core_graphics)
993 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
994 #endif
995 RGBForeColor (GC_FORE_COLOR (gc));
996 #ifdef MAC_OS8
997 if (bg_width)
999 RGBBackColor (GC_BACK_COLOR (gc));
1000 TextMode (srcCopy);
1002 else
1003 TextMode (srcOr);
1004 #else
1005 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1006 because:
1007 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1008 into an offscreen graphics world first. So performance gain
1009 cannot be expected.)
1010 - It lowers rendering quality.
1011 - Some fonts leave garbage on cursor movement. */
1012 if (bg_width)
1014 Rect r;
1016 RGBBackColor (GC_BACK_COLOR (gc));
1017 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1018 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1019 EraseRect (&r);
1021 TextMode (srcOr);
1022 #endif
1023 TextFont (GC_FONT (gc)->mac_fontnum);
1024 TextSize (GC_FONT (gc)->mac_fontsize);
1025 TextFace (GC_FONT (gc)->mac_fontface);
1026 MoveTo (x, y);
1027 DrawText (buf, 0, nchars * bytes_per_char);
1028 if (overstrike_p)
1030 TextMode (srcOr);
1031 MoveTo (x + 1, y);
1032 DrawText (buf, 0, nchars * bytes_per_char);
1034 if (bg_width)
1035 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1036 mac_end_clip (f, gc);
1038 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1039 if (mac_use_core_graphics)
1040 SwapQDTextFlags(savedFlags);
1041 #endif
1045 static INLINE void
1046 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1047 overstrike_p, bytes_per_char)
1048 struct frame *f;
1049 GC gc;
1050 int x, y;
1051 char *buf;
1052 int nchars, bg_width, overstrike_p, bytes_per_char;
1054 #if USE_ATSUI
1055 if (GC_FONT (gc)->mac_style)
1056 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
1057 overstrike_p, bytes_per_char);
1058 else
1059 #endif /* USE_ATSUI */
1060 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1061 overstrike_p, bytes_per_char);
1065 /* Mac replacement for XDrawImageString. */
1067 static void
1068 mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1069 struct frame *f;
1070 GC gc;
1071 int x, y;
1072 char *buf;
1073 int nchars, bg_width, overstrike_p;
1075 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1076 overstrike_p, 1);
1080 /* Mac replacement for XDrawImageString16. */
1082 static void
1083 mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1084 struct frame *f;
1085 GC gc;
1086 int x, y;
1087 XChar2b *buf;
1088 int nchars, bg_width, overstrike_p;
1090 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
1091 overstrike_p, 2);
1095 /* Mac replacement for XQueryTextExtents, but takes a character. If
1096 STYLE is NULL, measurement is done by QuickDraw Text routines for
1097 the font of the current graphics port. If CG_GLYPH is not NULL,
1098 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1100 static OSStatus
1101 mac_query_char_extents (style, c,
1102 font_ascent_return, font_descent_return,
1103 overall_return, cg_glyph)
1104 #if USE_ATSUI
1105 ATSUStyle style;
1106 #else
1107 void *style;
1108 #endif
1109 int c;
1110 int *font_ascent_return, *font_descent_return;
1111 XCharStruct *overall_return;
1112 #if USE_CG_TEXT_DRAWING
1113 CGGlyph *cg_glyph;
1114 #else
1115 void *cg_glyph;
1116 #endif
1118 OSStatus err = noErr;
1119 int width;
1120 Rect char_bounds;
1122 #if USE_ATSUI
1123 if (style)
1125 ATSUTextLayout text_layout;
1126 UniChar ch = c;
1128 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
1129 if (err == noErr
1130 && (font_ascent_return || font_descent_return || overall_return))
1132 ATSTrapezoid glyph_bounds;
1134 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1135 kATSUFromTextBeginning, kATSUToTextEnd,
1136 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1137 kATSUseFractionalOrigins,
1138 #else
1139 kATSUseDeviceOrigins,
1140 #endif
1141 1, &glyph_bounds, NULL);
1142 if (err == noErr)
1144 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1145 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1147 width = Fix2Long (glyph_bounds.upperRight.x
1148 - glyph_bounds.upperLeft.x);
1149 if (font_ascent_return)
1150 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1151 if (font_descent_return)
1152 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1155 if (err == noErr && overall_return)
1157 err = ATSUMeasureTextImage (text_layout,
1158 kATSUFromTextBeginning, kATSUToTextEnd,
1159 0, 0, &char_bounds);
1160 if (err == noErr)
1161 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1162 #if USE_CG_TEXT_DRAWING
1163 if (err == noErr && cg_glyph)
1165 OSStatus err1;
1166 ATSUGlyphInfoArray glyph_info_array;
1167 ByteCount count = sizeof (ATSUGlyphInfoArray);
1169 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1170 kATSUToTextEnd, NULL, NULL, NULL);
1171 if (err1 == noErr)
1172 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1173 kATSUToTextEnd, &count,
1174 &glyph_info_array);
1175 if (err1 == noErr
1176 /* Make sure that we don't have to make layout
1177 adjustments. */
1178 && glyph_info_array.glyphs[0].deltaY == 0.0f
1179 && glyph_info_array.glyphs[0].idealX == 0.0f
1180 && glyph_info_array.glyphs[0].screenX == 0)
1182 xassert (glyph_info_array.glyphs[0].glyphID);
1183 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1185 else
1186 *cg_glyph = 0;
1188 #endif
1191 else
1192 #endif
1194 if (font_ascent_return || font_descent_return)
1196 FontInfo font_info;
1198 GetFontInfo (&font_info);
1199 if (font_ascent_return)
1200 *font_ascent_return = font_info.ascent;
1201 if (font_descent_return)
1202 *font_descent_return = font_info.descent;
1204 if (overall_return)
1206 char ch = c;
1208 width = CharWidth (ch);
1209 QDTextBounds (1, &ch, &char_bounds);
1210 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1214 return err;
1218 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1220 static int
1221 mac_text_extents_16 (font_struct, string, nchars, overall_return)
1222 XFontStruct *font_struct;
1223 XChar2b *string;
1224 int nchars;
1225 XCharStruct *overall_return;
1227 int i;
1228 short width = 0, lbearing = 0, rbearing = 0;
1229 XCharStruct *pcm;
1231 for (i = 0; i < nchars; i++)
1233 pcm = mac_per_char_metric (font_struct, string, 0);
1234 if (pcm == NULL)
1235 width += FONT_WIDTH (font_struct);
1236 else
1238 lbearing = min (lbearing, width + pcm->lbearing);
1239 rbearing = max (rbearing, width + pcm->rbearing);
1240 width += pcm->width;
1242 string++;
1245 overall_return->lbearing = lbearing;
1246 overall_return->rbearing = rbearing;
1247 overall_return->width = width;
1249 /* What's the meaning of the return value of XTextExtents16? */
1253 #if USE_CG_TEXT_DRAWING
1254 static int cg_text_anti_aliasing_threshold = 8;
1256 static void
1257 init_cg_text_anti_aliasing_threshold ()
1259 int threshold;
1260 Boolean valid_p;
1262 threshold =
1263 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1264 kCFPreferencesCurrentApplication,
1265 &valid_p);
1266 if (valid_p)
1267 cg_text_anti_aliasing_threshold = threshold;
1270 static int
1271 mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1272 struct frame *f;
1273 GC gc;
1274 int x, y;
1275 XChar2b *buf;
1276 int nchars, bg_width, overstrike_p;
1278 float port_height, gx, gy;
1279 int i;
1280 CGContextRef context;
1281 CGGlyph *glyphs;
1282 CGSize *advances;
1284 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1285 return 0;
1287 port_height = FRAME_PIXEL_HEIGHT (f);
1288 gx = x;
1289 gy = port_height - y;
1290 glyphs = (CGGlyph *)buf;
1291 advances = alloca (sizeof (CGSize) * nchars);
1292 if (advances == NULL)
1293 return 0;
1294 for (i = 0; i < nchars; i++)
1296 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1298 advances[i].width = pcm->width;
1299 advances[i].height = 0;
1300 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1301 buf++;
1304 #if USE_CG_DRAWING
1305 context = mac_begin_cg_clip (f, gc);
1306 #else
1307 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1308 if (gc->n_clip_rects || bg_width)
1310 CGContextTranslateCTM (context, 0, port_height);
1311 CGContextScaleCTM (context, 1, -1);
1312 if (gc->n_clip_rects)
1313 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1314 #endif
1315 if (bg_width)
1317 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1318 CGContextFillRect
1319 (context,
1320 CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
1321 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1323 CGContextScaleCTM (context, 1, -1);
1324 CGContextTranslateCTM (context, 0, -port_height);
1325 #if !USE_CG_DRAWING
1327 #endif
1328 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1329 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1330 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1331 CGContextSetTextMatrix (context, CGAffineTransformIdentity);
1332 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1333 CGContextSetShouldAntialias (context, false);
1334 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1335 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1336 if (CGContextShowGlyphsWithAdvances != NULL)
1337 #endif
1339 CGContextSetTextPosition (context, gx, gy);
1340 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1341 if (overstrike_p)
1343 CGContextSetTextPosition (context, gx + 1.0f, gy);
1344 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1347 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1348 else /* CGContextShowGlyphsWithAdvances == NULL */
1349 #endif
1350 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1351 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1353 for (i = 0; i < nchars; i++)
1355 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1356 if (overstrike_p)
1357 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
1358 gx += advances[i].width;
1361 #endif
1362 #if USE_CG_DRAWING
1363 mac_end_cg_clip (f);
1364 #else
1365 CGContextSynchronize (context);
1366 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1367 #endif
1369 return 1;
1371 #endif
1374 #if !USE_CG_DRAWING
1375 /* Mac replacement for XCopyArea: dest must be window. */
1377 static void
1378 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1379 Pixmap src;
1380 struct frame *f;
1381 GC gc;
1382 int src_x, src_y;
1383 unsigned int width, height;
1384 int dest_x, dest_y;
1386 Rect src_r, dest_r;
1388 mac_begin_clip (f, gc);
1390 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1391 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1393 ForeColor (blackColor);
1394 BackColor (whiteColor);
1396 LockPixels (GetGWorldPixMap (src));
1397 #if TARGET_API_MAC_CARBON
1399 CGrafPtr port;
1401 GetPort (&port);
1402 LockPortBits (port);
1403 CopyBits (GetPortBitMapForCopyBits (src),
1404 GetPortBitMapForCopyBits (port),
1405 &src_r, &dest_r, srcCopy, 0);
1406 UnlockPortBits (port);
1408 #else /* not TARGET_API_MAC_CARBON */
1409 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1410 &src_r, &dest_r, srcCopy, 0);
1411 #endif /* not TARGET_API_MAC_CARBON */
1412 UnlockPixels (GetGWorldPixMap (src));
1414 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1416 mac_end_clip (f, gc);
1420 static void
1421 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1422 width, height, dest_x, dest_y)
1423 Pixmap src, mask;
1424 struct frame *f;
1425 GC gc;
1426 int src_x, src_y;
1427 unsigned int width, height;
1428 int dest_x, dest_y;
1430 Rect src_r, dest_r;
1432 mac_begin_clip (f, gc);
1434 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1435 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1437 ForeColor (blackColor);
1438 BackColor (whiteColor);
1440 LockPixels (GetGWorldPixMap (src));
1441 LockPixels (GetGWorldPixMap (mask));
1442 #if TARGET_API_MAC_CARBON
1444 CGrafPtr port;
1446 GetPort (&port);
1447 LockPortBits (port);
1448 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1449 GetPortBitMapForCopyBits (port),
1450 &src_r, &src_r, &dest_r);
1451 UnlockPortBits (port);
1453 #else /* not TARGET_API_MAC_CARBON */
1454 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1455 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1456 #endif /* not TARGET_API_MAC_CARBON */
1457 UnlockPixels (GetGWorldPixMap (mask));
1458 UnlockPixels (GetGWorldPixMap (src));
1460 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1462 mac_end_clip (f, gc);
1464 #endif /* !USE_CG_DRAWING */
1467 /* Mac replacement for XCopyArea: used only for scrolling. */
1469 #if TARGET_API_MAC_CARBON
1470 /* Defined in mactoolbox.c. */
1471 extern void mac_scroll_area P_ ((struct frame *, GC, int, int,
1472 unsigned int, unsigned int, int, int));
1473 #else /* not TARGET_API_MAC_CARBON */
1474 static void
1475 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1476 struct frame *f;
1477 GC gc;
1478 int src_x, src_y;
1479 unsigned int width, height;
1480 int dest_x, dest_y;
1482 Rect src_r, dest_r;
1483 WindowRef w = FRAME_MAC_WINDOW (f);
1485 mac_begin_clip (f, gc);
1487 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1488 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1490 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1491 color mapping in CopyBits. Otherwise, it will be slow. */
1492 ForeColor (blackColor);
1493 BackColor (whiteColor);
1494 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1496 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1498 mac_end_clip (f, gc);
1500 #endif /* not TARGET_API_MAC_CARBON */
1503 /* Mac replacement for XChangeGC. */
1505 static void
1506 XChangeGC (display, gc, mask, xgcv)
1507 Display *display;
1508 GC gc;
1509 unsigned long mask;
1510 XGCValues *xgcv;
1512 if (mask & GCForeground)
1513 XSetForeground (display, gc, xgcv->foreground);
1514 if (mask & GCBackground)
1515 XSetBackground (display, gc, xgcv->background);
1516 if (mask & GCFont)
1517 XSetFont (display, gc, xgcv->font);
1521 /* Mac replacement for XCreateGC. */
1524 XCreateGC (display, d, mask, xgcv)
1525 Display *display;
1526 void *d;
1527 unsigned long mask;
1528 XGCValues *xgcv;
1530 GC gc = xmalloc (sizeof (*gc));
1532 bzero (gc, sizeof (*gc));
1533 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1534 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1535 if (CGColorGetTypeID != NULL)
1536 #endif
1538 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
1539 CGColorRetain (gc->cg_fore_color);
1540 CGColorRetain (gc->cg_back_color);
1542 #endif
1543 XChangeGC (display, gc, mask, xgcv);
1545 return gc;
1549 /* Used in xfaces.c. */
1551 void
1552 XFreeGC (display, gc)
1553 Display *display;
1554 GC gc;
1556 if (gc->clip_region)
1557 DisposeRgn (gc->clip_region);
1558 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1559 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1560 if (CGColorGetTypeID != NULL)
1561 #endif
1563 CGColorRelease (gc->cg_fore_color);
1564 CGColorRelease (gc->cg_back_color);
1566 #endif
1567 xfree (gc);
1571 /* Mac replacement for XGetGCValues. */
1573 static void
1574 XGetGCValues (display, gc, mask, xgcv)
1575 Display *display;
1576 GC gc;
1577 unsigned long mask;
1578 XGCValues *xgcv;
1580 if (mask & GCForeground)
1581 xgcv->foreground = gc->xgcv.foreground;
1582 if (mask & GCBackground)
1583 xgcv->background = gc->xgcv.background;
1584 if (mask & GCFont)
1585 xgcv->font = gc->xgcv.font;
1589 /* Mac replacement for XSetForeground. */
1591 void
1592 XSetForeground (display, gc, color)
1593 Display *display;
1594 GC gc;
1595 unsigned long color;
1597 if (gc->xgcv.foreground != color)
1599 gc->xgcv.foreground = color;
1600 gc->fore_color.red = RED16_FROM_ULONG (color);
1601 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1602 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1603 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1604 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1605 if (CGColorGetTypeID != NULL)
1606 #endif
1608 CGColorRelease (gc->cg_fore_color);
1609 if (color == 0)
1611 gc->cg_fore_color = mac_cg_color_black;
1612 CGColorRetain (gc->cg_fore_color);
1614 else
1616 float rgba[4];
1618 rgba[0] = gc->fore_color.red / 65535.0f;
1619 rgba[1] = gc->fore_color.green / 65535.0f;
1620 rgba[2] = gc->fore_color.blue / 65535.0f;
1621 rgba[3] = 1.0f;
1622 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1625 #endif
1630 /* Mac replacement for XSetBackground. */
1632 void
1633 XSetBackground (display, gc, color)
1634 Display *display;
1635 GC gc;
1636 unsigned long color;
1638 if (gc->xgcv.background != color)
1640 gc->xgcv.background = color;
1641 gc->back_color.red = RED16_FROM_ULONG (color);
1642 gc->back_color.green = GREEN16_FROM_ULONG (color);
1643 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1644 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1645 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1646 if (CGColorGetTypeID != NULL)
1647 #endif
1649 CGColorRelease (gc->cg_back_color);
1650 if (color == 0)
1652 gc->cg_back_color = mac_cg_color_black;
1653 CGColorRetain (gc->cg_back_color);
1655 else
1657 float rgba[4];
1659 rgba[0] = gc->back_color.red / 65535.0f;
1660 rgba[1] = gc->back_color.green / 65535.0f;
1661 rgba[2] = gc->back_color.blue / 65535.0f;
1662 rgba[3] = 1.0f;
1663 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1666 #endif
1671 /* Mac replacement for XSetFont. */
1673 static void
1674 XSetFont (display, gc, font)
1675 Display *display;
1676 GC gc;
1677 XFontStruct *font;
1679 gc->xgcv.font = font;
1683 /* Mac replacement for XSetClipRectangles. */
1685 static void
1686 mac_set_clip_rectangles (display, gc, rectangles, n)
1687 Display *display;
1688 GC gc;
1689 Rect *rectangles;
1690 int n;
1692 int i;
1694 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1696 gc->n_clip_rects = n;
1697 if (n > 0)
1699 if (gc->clip_region == NULL)
1700 gc->clip_region = NewRgn ();
1701 RectRgn (gc->clip_region, rectangles);
1702 if (n > 1)
1704 RgnHandle region = NewRgn ();
1706 for (i = 1; i < n; i++)
1708 RectRgn (region, rectangles + i);
1709 UnionRgn (gc->clip_region, region, gc->clip_region);
1711 DisposeRgn (region);
1714 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1715 for (i = 0; i < n; i++)
1717 Rect *rect = rectangles + i;
1719 gc->clip_rects[i] = CGRectMake (rect->left, rect->top,
1720 rect->right - rect->left,
1721 rect->bottom - rect->top);
1723 #endif
1727 /* Mac replacement for XSetClipMask. */
1729 static INLINE void
1730 mac_reset_clip_rectangles (display, gc)
1731 Display *display;
1732 GC gc;
1734 gc->n_clip_rects = 0;
1737 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1738 Calls to XFlush should be unnecessary because the X output buffer
1739 is flushed automatically as needed by calls to XPending,
1740 XNextEvent, or XWindowEvent according to the XFlush man page.
1741 XTread_socket calls XPending. Removing XFlush improves
1742 performance. */
1744 #define XFlush(DISPLAY) (void) 0
1747 /***********************************************************************
1748 Starting and ending an update
1749 ***********************************************************************/
1751 /* Start an update of frame F. This function is installed as a hook
1752 for update_begin, i.e. it is called when update_begin is called.
1753 This function is called prior to calls to x_update_window_begin for
1754 each window being updated. */
1756 static void
1757 x_update_begin (f)
1758 struct frame *f;
1760 BLOCK_INPUT;
1761 mac_update_begin (f);
1762 UNBLOCK_INPUT;
1766 /* Start update of window W. Set the global variable updated_window
1767 to the window being updated and set output_cursor to the cursor
1768 position of W. */
1770 static void
1771 x_update_window_begin (w)
1772 struct window *w;
1774 struct frame *f = XFRAME (WINDOW_FRAME (w));
1775 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1777 updated_window = w;
1778 set_output_cursor (&w->cursor);
1780 BLOCK_INPUT;
1782 if (f == display_info->mouse_face_mouse_frame)
1784 /* Don't do highlighting for mouse motion during the update. */
1785 display_info->mouse_face_defer = 1;
1787 /* If F needs to be redrawn, simply forget about any prior mouse
1788 highlighting. */
1789 if (FRAME_GARBAGED_P (f))
1790 display_info->mouse_face_window = Qnil;
1792 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1793 their mouse_face_p flag set, which means that they are always
1794 unequal to rows in a desired matrix which never have that
1795 flag set. So, rows containing mouse-face glyphs are never
1796 scrolled, and we don't have to switch the mouse highlight off
1797 here to prevent it from being scrolled. */
1799 /* Can we tell that this update does not affect the window
1800 where the mouse highlight is? If so, no need to turn off.
1801 Likewise, don't do anything if the frame is garbaged;
1802 in that case, the frame's current matrix that we would use
1803 is all wrong, and we will redisplay that line anyway. */
1804 if (!NILP (display_info->mouse_face_window)
1805 && w == XWINDOW (display_info->mouse_face_window))
1807 int i;
1809 for (i = 0; i < w->desired_matrix->nrows; ++i)
1810 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1811 break;
1813 if (i < w->desired_matrix->nrows)
1814 clear_mouse_face (display_info);
1816 #endif /* 0 */
1819 UNBLOCK_INPUT;
1823 /* Draw a vertical window border from (x,y0) to (x,y1) */
1825 static void
1826 mac_draw_vertical_window_border (w, x, y0, y1)
1827 struct window *w;
1828 int x, y0, y1;
1830 struct frame *f = XFRAME (WINDOW_FRAME (w));
1831 struct face *face;
1833 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
1834 if (face)
1835 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
1836 face->foreground);
1838 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
1841 /* End update of window W (which is equal to updated_window).
1843 Draw vertical borders between horizontally adjacent windows, and
1844 display W's cursor if CURSOR_ON_P is non-zero.
1846 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1847 glyphs in mouse-face were overwritten. In that case we have to
1848 make sure that the mouse-highlight is properly redrawn.
1850 W may be a menu bar pseudo-window in case we don't have X toolkit
1851 support. Such windows don't have a cursor, so don't display it
1852 here. */
1854 static void
1855 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1856 struct window *w;
1857 int cursor_on_p, mouse_face_overwritten_p;
1859 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1861 if (!w->pseudo_window_p)
1863 BLOCK_INPUT;
1865 if (cursor_on_p)
1866 display_and_set_cursor (w, 1, output_cursor.hpos,
1867 output_cursor.vpos,
1868 output_cursor.x, output_cursor.y);
1870 if (draw_window_fringes (w, 1))
1871 x_draw_vertical_border (w);
1873 UNBLOCK_INPUT;
1876 /* If a row with mouse-face was overwritten, arrange for
1877 XTframe_up_to_date to redisplay the mouse highlight. */
1878 if (mouse_face_overwritten_p)
1880 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1881 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1882 dpyinfo->mouse_face_window = Qnil;
1885 updated_window = NULL;
1889 /* End update of frame F. This function is installed as a hook in
1890 update_end. */
1892 static void
1893 x_update_end (f)
1894 struct frame *f;
1896 /* Mouse highlight may be displayed again. */
1897 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1899 BLOCK_INPUT;
1900 mac_update_end (f);
1901 XFlush (FRAME_MAC_DISPLAY (f));
1902 UNBLOCK_INPUT;
1906 /* This function is called from various places in xdisp.c whenever a
1907 complete update has been performed. The global variable
1908 updated_window is not available here. */
1910 static void
1911 XTframe_up_to_date (f)
1912 struct frame *f;
1914 if (FRAME_MAC_P (f))
1916 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1918 if (dpyinfo->mouse_face_deferred_gc
1919 || f == dpyinfo->mouse_face_mouse_frame)
1921 BLOCK_INPUT;
1922 if (dpyinfo->mouse_face_mouse_frame)
1923 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1924 dpyinfo->mouse_face_mouse_x,
1925 dpyinfo->mouse_face_mouse_y);
1926 dpyinfo->mouse_face_deferred_gc = 0;
1927 UNBLOCK_INPUT;
1930 mac_frame_up_to_date (f);
1935 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1936 arrow bitmaps, or clear the fringes if no bitmaps are required
1937 before DESIRED_ROW is made current. The window being updated is
1938 found in updated_window. This function is called from
1939 update_window_line only if it is known that there are differences
1940 between bitmaps to be drawn between current row and DESIRED_ROW. */
1942 static void
1943 x_after_update_window_line (desired_row)
1944 struct glyph_row *desired_row;
1946 struct window *w = updated_window;
1947 struct frame *f;
1948 int width, height;
1950 xassert (w);
1952 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1953 desired_row->redraw_fringe_bitmaps_p = 1;
1955 /* When a window has disappeared, make sure that no rest of
1956 full-width rows stays visible in the internal border. Could
1957 check here if updated_window is the leftmost/rightmost window,
1958 but I guess it's not worth doing since vertically split windows
1959 are almost never used, internal border is rarely set, and the
1960 overhead is very small. */
1961 if (windows_or_buffers_changed
1962 && desired_row->full_width_p
1963 && (f = XFRAME (w->frame),
1964 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1965 width != 0)
1966 && (height = desired_row->visible_height,
1967 height > 0))
1969 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1971 /* Internal border is drawn below the tool bar. */
1972 if (WINDOWP (f->tool_bar_window)
1973 && w == XWINDOW (f->tool_bar_window))
1974 y -= width;
1976 BLOCK_INPUT;
1977 mac_clear_area (f, 0, y, width, height);
1978 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
1979 UNBLOCK_INPUT;
1984 /* Draw the bitmap WHICH in one of the left or right fringes of
1985 window W. ROW is the glyph row for which to display the bitmap; it
1986 determines the vertical position at which the bitmap has to be
1987 drawn. */
1989 static void
1990 x_draw_fringe_bitmap (w, row, p)
1991 struct window *w;
1992 struct glyph_row *row;
1993 struct draw_fringe_bitmap_params *p;
1995 struct frame *f = XFRAME (WINDOW_FRAME (w));
1996 Display *display = FRAME_MAC_DISPLAY (f);
1997 struct face *face = p->face;
1998 int rowY;
1999 int overlay_p = p->overlay_p;
2001 #ifdef MAC_OSX
2002 if (!overlay_p)
2004 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2006 #if 0 /* MAC_TODO: stipple */
2007 /* In case the same realized face is used for fringes and
2008 for something displayed in the text (e.g. face `region' on
2009 mono-displays, the fill style may have been changed to
2010 FillSolid in x_draw_glyph_string_background. */
2011 if (face->stipple)
2012 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2013 else
2014 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2015 #endif
2017 /* If the fringe is adjacent to the left (right) scroll bar of a
2018 leftmost (rightmost, respectively) window, then extend its
2019 background to the gap between the fringe and the bar. */
2020 if ((WINDOW_LEFTMOST_P (w)
2021 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2022 || (WINDOW_RIGHTMOST_P (w)
2023 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2025 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2027 if (sb_width > 0)
2029 int left = WINDOW_SCROLL_BAR_AREA_X (w);
2030 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2031 * FRAME_COLUMN_WIDTH (f));
2033 if (bx < 0
2034 && (left + width == p->x
2035 || p->x + p->wd == left))
2037 /* Bitmap fills the fringe and we need background
2038 extension. */
2039 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
2041 bx = p->x;
2042 nx = p->wd;
2043 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
2044 row->y));
2045 ny = row->visible_height;
2048 if (bx >= 0)
2050 if (left + width == bx)
2052 bx = left + sb_width;
2053 nx += width - sb_width;
2055 else if (bx + nx == left)
2056 nx += width - sb_width;
2061 if (bx >= 0)
2063 mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
2064 /* The fringe background has already been filled. */
2065 overlay_p = 1;
2068 #if 0 /* MAC_TODO: stipple */
2069 if (!face->stipple)
2070 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2071 #endif
2073 #endif /* MAC_OSX */
2075 /* Must clip because of partially visible lines. */
2076 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2077 if (p->y < rowY)
2079 /* Adjust position of "bottom aligned" bitmap on partially
2080 visible last row. */
2081 int oldY = row->y;
2082 int oldVH = row->visible_height;
2083 row->visible_height = p->h;
2084 row->y -= rowY - p->y;
2085 x_clip_to_row (w, row, -1, face->gc);
2086 row->y = oldY;
2087 row->visible_height = oldVH;
2089 else
2090 x_clip_to_row (w, row, -1, face->gc);
2092 #ifndef MAC_OSX
2093 if (p->bx >= 0 && !p->overlay_p)
2095 #if 0 /* MAC_TODO: stipple */
2096 /* In case the same realized face is used for fringes and
2097 for something displayed in the text (e.g. face `region' on
2098 mono-displays, the fill style may have been changed to
2099 FillSolid in x_draw_glyph_string_background. */
2100 if (face->stipple)
2101 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2102 else
2103 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2104 #endif
2106 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
2108 #if 0 /* MAC_TODO: stipple */
2109 if (!face->stipple)
2110 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2111 #endif
2113 #endif /* !MAC_OSX */
2115 if (p->which
2116 #if USE_CG_DRAWING
2117 && p->which < max_fringe_bmp
2118 #endif
2121 XGCValues gcv;
2123 XGetGCValues (display, face->gc, GCForeground, &gcv);
2124 XSetForeground (display, face->gc,
2125 (p->cursor_p
2126 ? (p->overlay_p ? face->background
2127 : f->output_data.mac->cursor_pixel)
2128 : face->foreground));
2129 #if USE_CG_DRAWING
2130 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
2131 p->wd, p->h, p->x, p->y, overlay_p);
2132 #else
2133 mac_draw_bitmap (f, face->gc, p->x, p->y,
2134 p->wd, p->h, p->bits + p->dh, overlay_p);
2135 #endif
2136 XSetForeground (display, face->gc, gcv.foreground);
2139 mac_reset_clip_rectangles (display, face->gc);
2142 #if USE_CG_DRAWING
2143 static void
2144 mac_define_fringe_bitmap (which, bits, h, wd)
2145 int which;
2146 unsigned short *bits;
2147 int h, wd;
2149 int i;
2150 CGDataProviderRef provider;
2152 if (which >= max_fringe_bmp)
2154 i = max_fringe_bmp;
2155 max_fringe_bmp = which + 20;
2156 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
2157 while (i < max_fringe_bmp)
2158 fringe_bmp[i++] = 0;
2161 for (i = 0; i < h; i++)
2162 bits[i] = ~bits[i];
2164 BLOCK_INPUT;
2166 provider = CGDataProviderCreateWithData (NULL, bits,
2167 sizeof (unsigned short) * h, NULL);
2168 if (provider)
2170 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
2171 sizeof (unsigned short),
2172 provider, NULL, 0);
2173 CGDataProviderRelease (provider);
2176 UNBLOCK_INPUT;
2179 static void
2180 mac_destroy_fringe_bitmap (which)
2181 int which;
2183 if (which >= max_fringe_bmp)
2184 return;
2186 if (fringe_bmp[which])
2188 BLOCK_INPUT;
2189 CGImageRelease (fringe_bmp[which]);
2190 UNBLOCK_INPUT;
2192 fringe_bmp[which] = 0;
2194 #endif
2197 /* This is called when starting Emacs and when restarting after
2198 suspend. When starting Emacs, no window is mapped. And nothing
2199 must be done to Emacs's own window if it is suspended (though that
2200 rarely happens). */
2202 static void
2203 XTset_terminal_modes ()
2207 /* This is called when exiting or suspending Emacs. Exiting will make
2208 the windows go away, and suspending requires no action. */
2210 static void
2211 XTreset_terminal_modes ()
2217 /***********************************************************************
2218 Display Iterator
2219 ***********************************************************************/
2221 /* Function prototypes of this page. */
2223 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
2224 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
2227 static void
2228 pcm_init (pcm, count)
2229 XCharStruct *pcm;
2230 int count;
2232 bzero (pcm, sizeof (XCharStruct) * count);
2233 while (--count >= 0)
2235 pcm->descent = PCM_INVALID;
2236 pcm++;
2240 static enum pcm_status
2241 pcm_get_status (pcm)
2242 const XCharStruct *pcm;
2244 int height = pcm->ascent + pcm->descent;
2246 /* Negative height means some special status. */
2247 return height >= 0 ? PCM_VALID : height;
2250 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2251 is not contained in the font. */
2253 static INLINE XCharStruct *
2254 x_per_char_metric (font, char2b)
2255 XFontStruct *font;
2256 XChar2b *char2b;
2258 /* The result metric information. */
2259 XCharStruct *pcm = NULL;
2261 xassert (font && char2b);
2263 #if USE_ATSUI
2264 if (font->mac_style)
2266 XCharStruct **row = font->bounds.rows + char2b->byte1;
2268 if (*row == NULL)
2270 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2271 pcm_init (*row, 0x100);
2273 pcm = *row + char2b->byte2;
2274 if (pcm_get_status (pcm) != PCM_VALID)
2276 BLOCK_INPUT;
2277 mac_query_char_extents (font->mac_style,
2278 (char2b->byte1 << 8) + char2b->byte2,
2279 NULL, NULL, pcm, NULL);
2280 UNBLOCK_INPUT;
2283 else
2285 #endif
2286 if (font->bounds.per_char != NULL)
2288 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2290 /* min_char_or_byte2 specifies the linear character index
2291 corresponding to the first element of the per_char array,
2292 max_char_or_byte2 is the index of the last character. A
2293 character with non-zero CHAR2B->byte1 is not in the font.
2294 A character with byte2 less than min_char_or_byte2 or
2295 greater max_char_or_byte2 is not in the font. */
2296 if (char2b->byte1 == 0
2297 && char2b->byte2 >= font->min_char_or_byte2
2298 && char2b->byte2 <= font->max_char_or_byte2)
2299 pcm = font->bounds.per_char
2300 + (char2b->byte2 - font->min_char_or_byte2);
2302 else
2304 /* If either min_byte1 or max_byte1 are nonzero, both
2305 min_char_or_byte2 and max_char_or_byte2 are less than
2306 256, and the 2-byte character index values corresponding
2307 to the per_char array element N (counting from 0) are:
2309 byte1 = N/D + min_byte1
2310 byte2 = N\D + min_char_or_byte2
2312 where:
2314 D = max_char_or_byte2 - min_char_or_byte2 + 1
2315 / = integer division
2316 \ = integer modulus */
2317 if (char2b->byte1 >= font->min_byte1
2318 && char2b->byte1 <= font->max_byte1
2319 && char2b->byte2 >= font->min_char_or_byte2
2320 && char2b->byte2 <= font->max_char_or_byte2)
2322 pcm = (font->bounds.per_char
2323 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2324 * (char2b->byte1 - font->min_byte1))
2325 + (char2b->byte2 - font->min_char_or_byte2));
2329 else
2331 /* If the per_char pointer is null, all glyphs between the first
2332 and last character indexes inclusive have the same
2333 information, as given by both min_bounds and max_bounds. */
2334 if (char2b->byte2 >= font->min_char_or_byte2
2335 && char2b->byte2 <= font->max_char_or_byte2)
2336 pcm = &font->max_bounds;
2338 #if USE_ATSUI
2340 #endif
2342 return ((pcm == NULL
2343 || (pcm->width == 0
2344 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2345 && (pcm->rbearing - pcm->lbearing) == 0
2346 #endif
2348 ? NULL : pcm);
2351 /* RIF:
2354 static XCharStruct *
2355 mac_per_char_metric (font, char2b, font_type)
2356 XFontStruct *font;
2357 XChar2b *char2b;
2358 int font_type;
2360 return x_per_char_metric (font, char2b);
2363 /* RIF:
2364 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2365 the two-byte form of C. Encoding is returned in *CHAR2B. */
2367 static int
2368 mac_encode_char (c, char2b, font_info, two_byte_p)
2369 int c;
2370 XChar2b *char2b;
2371 struct font_info *font_info;
2372 int *two_byte_p;
2374 int charset = CHAR_CHARSET (c);
2375 XFontStruct *font = font_info->font;
2377 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2378 This may be either a program in a special encoder language or a
2379 fixed encoding. */
2380 if (font_info->font_encoder)
2382 /* It's a program. */
2383 struct ccl_program *ccl = font_info->font_encoder;
2385 check_ccl_update (ccl);
2386 if (CHARSET_DIMENSION (charset) == 1)
2388 ccl->reg[0] = charset;
2389 ccl->reg[1] = char2b->byte2;
2390 ccl->reg[2] = -1;
2392 else
2394 ccl->reg[0] = charset;
2395 ccl->reg[1] = char2b->byte1;
2396 ccl->reg[2] = char2b->byte2;
2399 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2401 /* We assume that MSBs are appropriately set/reset by CCL
2402 program. */
2403 if (font->max_byte1 == 0) /* 1-byte font */
2404 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2405 else
2406 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2408 else if (font_info->encoding[charset])
2410 /* Fixed encoding scheme. See fontset.h for the meaning of the
2411 encoding numbers. */
2412 int enc = font_info->encoding[charset];
2414 if ((enc == 1 || enc == 2)
2415 && CHARSET_DIMENSION (charset) == 2)
2416 char2b->byte1 |= 0x80;
2418 if (enc == 1 || enc == 3)
2419 char2b->byte2 |= 0x80;
2421 if (enc == 4)
2423 int sjis1, sjis2;
2425 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2426 char2b->byte1 = sjis1;
2427 char2b->byte2 = sjis2;
2431 if (two_byte_p)
2432 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2434 return FONT_TYPE_UNKNOWN;
2439 /***********************************************************************
2440 Glyph display
2441 ***********************************************************************/
2445 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2446 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2447 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2448 int));
2449 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2450 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2451 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2452 static void x_draw_glyph_string P_ ((struct glyph_string *));
2453 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2454 static void x_set_cursor_gc P_ ((struct glyph_string *));
2455 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2456 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2457 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2458 unsigned long *, double, int));*/
2459 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2460 double, int, unsigned long));
2461 static void x_setup_relief_colors P_ ((struct glyph_string *));
2462 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2463 static void x_draw_image_relief P_ ((struct glyph_string *));
2464 static void x_draw_image_foreground P_ ((struct glyph_string *));
2465 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2466 int, int, int));
2467 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2468 int, int, int, int, int, int,
2469 Rect *));
2470 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2471 int, int, int, Rect *));
2473 #if GLYPH_DEBUG
2474 static void x_check_font P_ ((struct frame *, XFontStruct *));
2475 #endif
2478 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2479 face. */
2481 static void
2482 x_set_cursor_gc (s)
2483 struct glyph_string *s;
2485 if (s->font == FRAME_FONT (s->f)
2486 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2487 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2488 && !s->cmp)
2489 s->gc = s->f->output_data.mac->cursor_gc;
2490 else
2492 /* Cursor on non-default face: must merge. */
2493 XGCValues xgcv;
2494 unsigned long mask;
2496 xgcv.background = s->f->output_data.mac->cursor_pixel;
2497 xgcv.foreground = s->face->background;
2499 /* If the glyph would be invisible, try a different foreground. */
2500 if (xgcv.foreground == xgcv.background)
2501 xgcv.foreground = s->face->foreground;
2502 if (xgcv.foreground == xgcv.background)
2503 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2504 if (xgcv.foreground == xgcv.background)
2505 xgcv.foreground = s->face->foreground;
2507 /* Make sure the cursor is distinct from text in this face. */
2508 if (xgcv.background == s->face->background
2509 && xgcv.foreground == s->face->foreground)
2511 xgcv.background = s->face->foreground;
2512 xgcv.foreground = s->face->background;
2515 IF_DEBUG (x_check_font (s->f, s->font));
2516 xgcv.font = s->font;
2517 mask = GCForeground | GCBackground | GCFont;
2519 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2520 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2521 mask, &xgcv);
2522 else
2523 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2524 = XCreateGC (s->display, s->window, mask, &xgcv);
2526 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2531 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2533 static void
2534 x_set_mouse_face_gc (s)
2535 struct glyph_string *s;
2537 int face_id;
2538 struct face *face;
2540 /* What face has to be used last for the mouse face? */
2541 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2542 face = FACE_FROM_ID (s->f, face_id);
2543 if (face == NULL)
2544 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2546 if (s->first_glyph->type == CHAR_GLYPH)
2547 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2548 else
2549 face_id = FACE_FOR_CHAR (s->f, face, 0);
2550 s->face = FACE_FROM_ID (s->f, face_id);
2551 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2553 /* If font in this face is same as S->font, use it. */
2554 if (s->font == s->face->font)
2555 s->gc = s->face->gc;
2556 else
2558 /* Otherwise construct scratch_cursor_gc with values from FACE
2559 but font FONT. */
2560 XGCValues xgcv;
2561 unsigned long mask;
2563 xgcv.background = s->face->background;
2564 xgcv.foreground = s->face->foreground;
2565 IF_DEBUG (x_check_font (s->f, s->font));
2566 xgcv.font = s->font;
2567 mask = GCForeground | GCBackground | GCFont;
2569 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2570 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2571 mask, &xgcv);
2572 else
2573 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2574 = XCreateGC (s->display, s->window, mask, &xgcv);
2576 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2579 xassert (s->gc != 0);
2583 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2584 Faces to use in the mode line have already been computed when the
2585 matrix was built, so there isn't much to do, here. */
2587 static INLINE void
2588 x_set_mode_line_face_gc (s)
2589 struct glyph_string *s;
2591 s->gc = s->face->gc;
2595 /* Set S->gc of glyph string S for drawing that glyph string. Set
2596 S->stippled_p to a non-zero value if the face of S has a stipple
2597 pattern. */
2599 static INLINE void
2600 x_set_glyph_string_gc (s)
2601 struct glyph_string *s;
2603 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2605 if (s->hl == DRAW_NORMAL_TEXT)
2607 s->gc = s->face->gc;
2608 s->stippled_p = s->face->stipple != 0;
2610 else if (s->hl == DRAW_INVERSE_VIDEO)
2612 x_set_mode_line_face_gc (s);
2613 s->stippled_p = s->face->stipple != 0;
2615 else if (s->hl == DRAW_CURSOR)
2617 x_set_cursor_gc (s);
2618 s->stippled_p = 0;
2620 else if (s->hl == DRAW_MOUSE_FACE)
2622 x_set_mouse_face_gc (s);
2623 s->stippled_p = s->face->stipple != 0;
2625 else if (s->hl == DRAW_IMAGE_RAISED
2626 || s->hl == DRAW_IMAGE_SUNKEN)
2628 s->gc = s->face->gc;
2629 s->stippled_p = s->face->stipple != 0;
2631 else
2633 s->gc = s->face->gc;
2634 s->stippled_p = s->face->stipple != 0;
2637 /* GC must have been set. */
2638 xassert (s->gc != 0);
2642 /* Set clipping for output of glyph string S. S may be part of a mode
2643 line or menu if we don't have X toolkit support. */
2645 static INLINE void
2646 x_set_glyph_string_clipping (s)
2647 struct glyph_string *s;
2649 Rect rects[MAX_CLIP_RECTS];
2650 int n;
2652 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
2653 mac_set_clip_rectangles (s->display, s->gc, rects, n);
2657 /* RIF:
2658 Compute left and right overhang of glyph string S. If S is a glyph
2659 string for a composition, assume overhangs don't exist. */
2661 static void
2662 mac_compute_glyph_string_overhangs (s)
2663 struct glyph_string *s;
2665 if (!(s->cmp == NULL
2666 && s->first_glyph->type == CHAR_GLYPH))
2667 return;
2669 if (!s->two_byte_p
2670 #if USE_ATSUI
2671 || s->font->mac_style
2672 #endif
2675 XCharStruct cs;
2677 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2678 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2679 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2681 else
2683 Rect r;
2684 MacFontStruct *font = s->font;
2686 mac_begin_clip (s->f, NULL);
2688 TextFont (font->mac_fontnum);
2689 TextSize (font->mac_fontsize);
2690 TextFace (font->mac_fontface);
2692 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2694 mac_end_clip (s->f, NULL);
2696 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2697 s->left_overhang = r.left < 0 ? -r.left : 0;
2702 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2704 static INLINE void
2705 x_clear_glyph_string_rect (s, x, y, w, h)
2706 struct glyph_string *s;
2707 int x, y, w, h;
2709 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
2713 /* Draw the background of glyph_string S. If S->background_filled_p
2714 is non-zero don't draw it. FORCE_P non-zero means draw the
2715 background even if it wouldn't be drawn normally. This is used
2716 when a string preceding S draws into the background of S, or S
2717 contains the first component of a composition. */
2719 static void
2720 x_draw_glyph_string_background (s, force_p)
2721 struct glyph_string *s;
2722 int force_p;
2724 /* Nothing to do if background has already been drawn or if it
2725 shouldn't be drawn in the first place. */
2726 if (!s->background_filled_p)
2728 int box_line_width = max (s->face->box_line_width, 0);
2730 #if 0 /* MAC_TODO: stipple */
2731 if (s->stippled_p)
2733 /* Fill background with a stipple pattern. */
2734 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2735 XFillRectangle (s->display, s->window, s->gc, s->x,
2736 s->y + box_line_width,
2737 s->background_width,
2738 s->height - 2 * box_line_width);
2739 XSetFillStyle (s->display, s->gc, FillSolid);
2740 s->background_filled_p = 1;
2742 else
2743 #endif
2744 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2745 || s->font_not_found_p
2746 || s->extends_to_end_of_line_p
2747 || force_p)
2749 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2750 s->background_width,
2751 s->height - 2 * box_line_width);
2752 s->background_filled_p = 1;
2758 /* Draw the foreground of glyph string S. */
2760 static void
2761 x_draw_glyph_string_foreground (s)
2762 struct glyph_string *s;
2764 int i, x, bg_width;
2766 /* If first glyph of S has a left box line, start drawing the text
2767 of S to the right of that box line. */
2768 if (s->face->box != FACE_NO_BOX
2769 && s->first_glyph->left_box_line_p)
2770 x = s->x + abs (s->face->box_line_width);
2771 else
2772 x = s->x;
2774 /* Draw characters of S as rectangles if S's font could not be
2775 loaded. */
2776 if (s->font_not_found_p)
2778 for (i = 0; i < s->nchars; ++i)
2780 struct glyph *g = s->first_glyph + i;
2781 mac_draw_rectangle (s->f, s->gc, x, s->y,
2782 g->pixel_width - 1, s->height - 1);
2783 x += g->pixel_width;
2786 else
2788 char *char1b = (char *) s->char2b;
2789 int boff = s->font_info->baseline_offset;
2791 if (s->font_info->vertical_centering)
2792 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2794 /* If we can use 8-bit functions, condense S->char2b. */
2795 if (!s->two_byte_p
2796 #if USE_ATSUI
2797 && GC_FONT (s->gc)->mac_style == NULL
2798 #endif
2800 for (i = 0; i < s->nchars; ++i)
2801 char1b[i] = s->char2b[i].byte2;
2803 /* Draw text with XDrawString if background has already been
2804 filled. Otherwise, use XDrawImageString. (Note that
2805 XDrawImageString is usually faster than XDrawString.) Always
2806 use XDrawImageString when drawing the cursor so that there is
2807 no chance that characters under a box cursor are invisible. */
2808 if (s->for_overlaps
2809 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2810 bg_width = 0; /* Corresponds to XDrawString. */
2811 else
2812 bg_width = s->background_width; /* Corresponds to XDrawImageString. */
2814 if (s->two_byte_p
2815 #if USE_ATSUI
2816 || GC_FONT (s->gc)->mac_style
2817 #endif
2819 #if USE_CG_TEXT_DRAWING
2820 if (!s->two_byte_p
2821 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
2822 s->char2b, s->nchars, bg_width,
2823 s->face->overstrike))
2825 else
2826 #endif
2827 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
2828 s->char2b, s->nchars, bg_width,
2829 s->face->overstrike);
2830 else
2831 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
2832 char1b, s->nchars, bg_width,
2833 s->face->overstrike);
2837 /* Draw the foreground of composite glyph string S. */
2839 static void
2840 x_draw_composite_glyph_string_foreground (s)
2841 struct glyph_string *s;
2843 int i, x;
2845 /* If first glyph of S has a left box line, start drawing the text
2846 of S to the right of that box line. */
2847 if (s->face->box != FACE_NO_BOX
2848 && s->first_glyph->left_box_line_p)
2849 x = s->x + abs (s->face->box_line_width);
2850 else
2851 x = s->x;
2853 /* S is a glyph string for a composition. S->gidx is the index of
2854 the first character drawn for glyphs of this composition.
2855 S->gidx == 0 means we are drawing the very first character of
2856 this composition. */
2858 /* Draw a rectangle for the composition if the font for the very
2859 first character of the composition could not be loaded. */
2860 if (s->font_not_found_p)
2862 if (s->gidx == 0)
2863 mac_draw_rectangle (s->f, s->gc, x, s->y,
2864 s->width - 1, s->height - 1);
2866 else
2868 for (i = 0; i < s->nchars; i++, ++s->gidx)
2869 if (mac_per_char_metric (GC_FONT (s->gc), s->char2b + i, 0) == NULL)
2870 /* This is a nonexistent or zero-width glyph such as a
2871 combining diacritic. Draw a rectangle. */
2872 mac_draw_rectangle (s->f, s->gc,
2873 x + s->cmp->offsets[s->gidx * 2], s->y,
2874 FONT_WIDTH (GC_FONT (s->gc)) - 1, s->height - 1);
2875 else
2876 mac_draw_image_string_16 (s->f, s->gc,
2877 x + s->cmp->offsets[s->gidx * 2],
2878 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2879 s->char2b + i, 1, 0, s->face->overstrike);
2884 #ifdef USE_X_TOOLKIT
2886 static struct frame *x_frame_of_widget P_ ((Widget));
2889 /* Return the frame on which widget WIDGET is used.. Abort if frame
2890 cannot be determined. */
2892 static struct frame *
2893 x_frame_of_widget (widget)
2894 Widget widget;
2896 struct x_display_info *dpyinfo;
2897 Lisp_Object tail;
2898 struct frame *f;
2900 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2902 /* Find the top-level shell of the widget. Note that this function
2903 can be called when the widget is not yet realized, so XtWindow
2904 (widget) == 0. That's the reason we can't simply use
2905 x_any_window_to_frame. */
2906 while (!XtIsTopLevelShell (widget))
2907 widget = XtParent (widget);
2909 /* Look for a frame with that top-level widget. Allocate the color
2910 on that frame to get the right gamma correction value. */
2911 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2912 if (GC_FRAMEP (XCAR (tail))
2913 && (f = XFRAME (XCAR (tail)),
2914 (f->output_data.nothing != 1
2915 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2916 && f->output_data.x->widget == widget)
2917 return f;
2919 abort ();
2923 /* Allocate the color COLOR->pixel on the screen and display of
2924 widget WIDGET in colormap CMAP. If an exact match cannot be
2925 allocated, try the nearest color available. Value is non-zero
2926 if successful. This is called from lwlib. */
2929 x_alloc_nearest_color_for_widget (widget, cmap, color)
2930 Widget widget;
2931 Colormap cmap;
2932 XColor *color;
2934 struct frame *f = x_frame_of_widget (widget);
2935 return x_alloc_nearest_color (f, cmap, color);
2939 #endif /* USE_X_TOOLKIT */
2941 #if 0 /* MAC_TODO */
2943 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2944 CMAP. If an exact match can't be allocated, try the nearest color
2945 available. Value is non-zero if successful. Set *COLOR to the
2946 color allocated. */
2949 x_alloc_nearest_color (f, cmap, color)
2950 struct frame *f;
2951 Colormap cmap;
2952 XColor *color;
2954 Display *display = FRAME_X_DISPLAY (f);
2955 Screen *screen = FRAME_X_SCREEN (f);
2956 int rc;
2958 gamma_correct (f, color);
2959 rc = XAllocColor (display, cmap, color);
2960 if (rc == 0)
2962 /* If we got to this point, the colormap is full, so we're going
2963 to try to get the next closest color. The algorithm used is
2964 a least-squares matching, which is what X uses for closest
2965 color matching with StaticColor visuals. */
2966 int nearest, i;
2967 unsigned long nearest_delta = ~0;
2968 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2969 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2971 for (i = 0; i < ncells; ++i)
2972 cells[i].pixel = i;
2973 XQueryColors (display, cmap, cells, ncells);
2975 for (nearest = i = 0; i < ncells; ++i)
2977 long dred = (color->red >> 8) - (cells[i].red >> 8);
2978 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2979 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2980 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2982 if (delta < nearest_delta)
2984 nearest = i;
2985 nearest_delta = delta;
2989 color->red = cells[nearest].red;
2990 color->green = cells[nearest].green;
2991 color->blue = cells[nearest].blue;
2992 rc = XAllocColor (display, cmap, color);
2995 #ifdef DEBUG_X_COLORS
2996 if (rc)
2997 register_color (color->pixel);
2998 #endif /* DEBUG_X_COLORS */
3000 return rc;
3004 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3005 It's necessary to do this instead of just using PIXEL directly to
3006 get color reference counts right. */
3008 unsigned long
3009 x_copy_color (f, pixel)
3010 struct frame *f;
3011 unsigned long pixel;
3013 XColor color;
3015 color.pixel = pixel;
3016 BLOCK_INPUT;
3017 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3018 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3019 UNBLOCK_INPUT;
3020 #ifdef DEBUG_X_COLORS
3021 register_color (pixel);
3022 #endif
3023 return color.pixel;
3027 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3028 It's necessary to do this instead of just using PIXEL directly to
3029 get color reference counts right. */
3031 unsigned long
3032 x_copy_dpy_color (dpy, cmap, pixel)
3033 Display *dpy;
3034 Colormap cmap;
3035 unsigned long pixel;
3037 XColor color;
3039 color.pixel = pixel;
3040 BLOCK_INPUT;
3041 XQueryColor (dpy, cmap, &color);
3042 XAllocColor (dpy, cmap, &color);
3043 UNBLOCK_INPUT;
3044 #ifdef DEBUG_X_COLORS
3045 register_color (pixel);
3046 #endif
3047 return color.pixel;
3050 #endif /* MAC_TODO */
3053 /* Brightness beyond which a color won't have its highlight brightness
3054 boosted.
3056 Nominally, highlight colors for `3d' faces are calculated by
3057 brightening an object's color by a constant scale factor, but this
3058 doesn't yield good results for dark colors, so for colors who's
3059 brightness is less than this value (on a scale of 0-255) have to
3060 use an additional additive factor.
3062 The value here is set so that the default menu-bar/mode-line color
3063 (grey75) will not have its highlights changed at all. */
3064 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3067 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3068 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3069 If this produces the same color as COLOR, try a color where all RGB
3070 values have DELTA added. Return the allocated color in *COLOR.
3071 DISPLAY is the X display, CMAP is the colormap to operate on.
3072 Value is non-zero if successful. */
3074 static int
3075 mac_alloc_lighter_color (f, color, factor, delta)
3076 struct frame *f;
3077 unsigned long *color;
3078 double factor;
3079 int delta;
3081 unsigned long new;
3082 long bright;
3084 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3085 delta /= 256;
3087 /* Change RGB values by specified FACTOR. Avoid overflow! */
3088 xassert (factor >= 0);
3089 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3090 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3091 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3093 /* Calculate brightness of COLOR. */
3094 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
3095 + BLUE_FROM_ULONG (*color)) / 6;
3097 /* We only boost colors that are darker than
3098 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3099 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3100 /* Make an additive adjustment to NEW, because it's dark enough so
3101 that scaling by FACTOR alone isn't enough. */
3103 /* How far below the limit this color is (0 - 1, 1 being darker). */
3104 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3105 /* The additive adjustment. */
3106 int min_delta = delta * dimness * factor / 2;
3108 if (factor < 1)
3109 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
3110 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
3111 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
3112 else
3113 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
3114 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
3115 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
3118 if (new == *color)
3119 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3120 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3121 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3123 /* MAC_TODO: Map to palette and retry with delta if same? */
3124 /* MAC_TODO: Free colors (if using palette)? */
3126 if (new == *color)
3127 return 0;
3129 *color = new;
3131 return 1;
3135 /* Set up the foreground color for drawing relief lines of glyph
3136 string S. RELIEF is a pointer to a struct relief containing the GC
3137 with which lines will be drawn. Use a color that is FACTOR or
3138 DELTA lighter or darker than the relief's background which is found
3139 in S->f->output_data.x->relief_background. If such a color cannot
3140 be allocated, use DEFAULT_PIXEL, instead. */
3142 static void
3143 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3144 struct frame *f;
3145 struct relief *relief;
3146 double factor;
3147 int delta;
3148 unsigned long default_pixel;
3150 XGCValues xgcv;
3151 struct mac_output *di = f->output_data.mac;
3152 unsigned long mask = GCForeground;
3153 unsigned long pixel;
3154 unsigned long background = di->relief_background;
3155 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3157 /* MAC_TODO: Free colors (if using palette)? */
3159 /* Allocate new color. */
3160 xgcv.foreground = default_pixel;
3161 pixel = background;
3162 if (dpyinfo->n_planes != 1
3163 && mac_alloc_lighter_color (f, &pixel, factor, delta))
3165 relief->allocated_p = 1;
3166 xgcv.foreground = relief->pixel = pixel;
3169 if (relief->gc == 0)
3171 #if 0 /* MAC_TODO: stipple */
3172 xgcv.stipple = dpyinfo->gray;
3173 mask |= GCStipple;
3174 #endif
3175 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3177 else
3178 XChangeGC (NULL, relief->gc, mask, &xgcv);
3182 /* Set up colors for the relief lines around glyph string S. */
3184 static void
3185 x_setup_relief_colors (s)
3186 struct glyph_string *s;
3188 struct mac_output *di = s->f->output_data.mac;
3189 unsigned long color;
3191 if (s->face->use_box_color_for_shadows_p)
3192 color = s->face->box_color;
3193 else if (s->first_glyph->type == IMAGE_GLYPH
3194 && s->img->pixmap
3195 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3196 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3197 else
3199 XGCValues xgcv;
3201 /* Get the background color of the face. */
3202 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3203 color = xgcv.background;
3206 if (di->white_relief.gc == 0
3207 || color != di->relief_background)
3209 di->relief_background = color;
3210 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3211 WHITE_PIX_DEFAULT (s->f));
3212 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3213 BLACK_PIX_DEFAULT (s->f));
3218 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3219 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3220 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3221 relief. LEFT_P non-zero means draw a relief on the left side of
3222 the rectangle. RIGHT_P non-zero means draw a relief on the right
3223 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3224 when drawing. */
3226 static void
3227 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3228 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
3229 struct frame *f;
3230 int left_x, top_y, right_x, bottom_y, width;
3231 int top_p, bot_p, left_p, right_p, raised_p;
3232 Rect *clip_rect;
3234 Display *dpy = FRAME_MAC_DISPLAY (f);
3235 int i;
3236 GC gc;
3238 if (raised_p)
3239 gc = f->output_data.mac->white_relief.gc;
3240 else
3241 gc = f->output_data.mac->black_relief.gc;
3242 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3244 /* Top. */
3245 if (top_p)
3246 for (i = 0; i < width; ++i)
3247 mac_draw_line (f, gc,
3248 left_x + i * left_p, top_y + i,
3249 right_x + 1 - i * right_p, top_y + i);
3251 /* Left. */
3252 if (left_p)
3253 for (i = 0; i < width; ++i)
3254 mac_draw_line (f, gc,
3255 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3257 mac_reset_clip_rectangles (dpy, gc);
3258 if (raised_p)
3259 gc = f->output_data.mac->black_relief.gc;
3260 else
3261 gc = f->output_data.mac->white_relief.gc;
3262 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3264 /* Bottom. */
3265 if (bot_p)
3266 for (i = 0; i < width; ++i)
3267 mac_draw_line (f, gc,
3268 left_x + i * left_p, bottom_y - i,
3269 right_x + 1 - i * right_p, bottom_y - i);
3271 /* Right. */
3272 if (right_p)
3273 for (i = 0; i < width; ++i)
3274 mac_draw_line (f, gc,
3275 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3277 mac_reset_clip_rectangles (dpy, gc);
3281 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3282 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3283 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3284 left side of the rectangle. RIGHT_P non-zero means draw a line
3285 on the right side of the rectangle. CLIP_RECT is the clipping
3286 rectangle to use when drawing. */
3288 static void
3289 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3290 left_p, right_p, clip_rect)
3291 struct glyph_string *s;
3292 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3293 Rect *clip_rect;
3295 XGCValues xgcv;
3297 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3298 XSetForeground (s->display, s->gc, s->face->box_color);
3299 mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1);
3301 /* Top. */
3302 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3303 right_x - left_x + 1, width);
3305 /* Left. */
3306 if (left_p)
3307 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3308 width, bottom_y - top_y + 1);
3310 /* Bottom. */
3311 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
3312 right_x - left_x + 1, width);
3314 /* Right. */
3315 if (right_p)
3316 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
3317 top_y, width, bottom_y - top_y + 1);
3319 XSetForeground (s->display, s->gc, xgcv.foreground);
3320 mac_reset_clip_rectangles (s->display, s->gc);
3324 /* Draw a box around glyph string S. */
3326 static void
3327 x_draw_glyph_string_box (s)
3328 struct glyph_string *s;
3330 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3331 int left_p, right_p;
3332 struct glyph *last_glyph;
3333 Rect clip_rect;
3335 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3336 ? WINDOW_RIGHT_EDGE_X (s->w)
3337 : window_box_right (s->w, s->area));
3339 /* The glyph that may have a right box line. */
3340 last_glyph = (s->cmp || s->img
3341 ? s->first_glyph
3342 : s->first_glyph + s->nchars - 1);
3344 width = abs (s->face->box_line_width);
3345 raised_p = s->face->box == FACE_RAISED_BOX;
3346 left_x = s->x;
3347 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3348 ? last_x - 1
3349 : min (last_x, s->x + s->background_width) - 1);
3350 top_y = s->y;
3351 bottom_y = top_y + s->height - 1;
3353 left_p = (s->first_glyph->left_box_line_p
3354 || (s->hl == DRAW_MOUSE_FACE
3355 && (s->prev == NULL
3356 || s->prev->hl != s->hl)));
3357 right_p = (last_glyph->right_box_line_p
3358 || (s->hl == DRAW_MOUSE_FACE
3359 && (s->next == NULL
3360 || s->next->hl != s->hl)));
3362 get_glyph_string_clip_rect (s, &clip_rect);
3364 if (s->face->box == FACE_SIMPLE_BOX)
3365 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3366 left_p, right_p, &clip_rect);
3367 else
3369 x_setup_relief_colors (s);
3370 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3371 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
3376 /* Draw foreground of image glyph string S. */
3378 static void
3379 x_draw_image_foreground (s)
3380 struct glyph_string *s;
3382 int x = s->x;
3383 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3385 /* If first glyph of S has a left box line, start drawing it to the
3386 right of that line. */
3387 if (s->face->box != FACE_NO_BOX
3388 && s->first_glyph->left_box_line_p
3389 && s->slice.x == 0)
3390 x += abs (s->face->box_line_width);
3392 /* If there is a margin around the image, adjust x- and y-position
3393 by that margin. */
3394 if (s->slice.x == 0)
3395 x += s->img->hmargin;
3396 if (s->slice.y == 0)
3397 y += s->img->vmargin;
3399 if (s->img->pixmap)
3401 x_set_glyph_string_clipping (s);
3403 #if USE_CG_DRAWING
3404 mac_draw_cg_image (s->img->data.ptr_val,
3405 s->f, s->gc, s->slice.x, s->slice.y,
3406 s->slice.width, s->slice.height, x, y, 1);
3407 #endif
3408 if (s->img->mask)
3409 #if !USE_CG_DRAWING
3410 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3411 s->f, s->gc, s->slice.x, s->slice.y,
3412 s->slice.width, s->slice.height, x, y);
3413 #else
3415 #endif
3416 else
3418 #if !USE_CG_DRAWING
3419 mac_copy_area (s->img->pixmap,
3420 s->f, s->gc, s->slice.x, s->slice.y,
3421 s->slice.width, s->slice.height, x, y);
3422 #endif
3424 /* When the image has a mask, we can expect that at
3425 least part of a mouse highlight or a block cursor will
3426 be visible. If the image doesn't have a mask, make
3427 a block cursor visible by drawing a rectangle around
3428 the image. I believe it's looking better if we do
3429 nothing here for mouse-face. */
3430 if (s->hl == DRAW_CURSOR)
3432 int r = s->img->relief;
3433 if (r < 0) r = -r;
3434 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
3435 s->slice.width + r*2 - 1,
3436 s->slice.height + r*2 - 1);
3440 else
3441 /* Draw a rectangle if image could not be loaded. */
3442 mac_draw_rectangle (s->f, s->gc, x, y,
3443 s->slice.width - 1, s->slice.height - 1);
3447 /* Draw a relief around the image glyph string S. */
3449 static void
3450 x_draw_image_relief (s)
3451 struct glyph_string *s;
3453 int x0, y0, x1, y1, thick, raised_p;
3454 Rect r;
3455 int x = s->x;
3456 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3458 /* If first glyph of S has a left box line, start drawing it to the
3459 right of that line. */
3460 if (s->face->box != FACE_NO_BOX
3461 && s->first_glyph->left_box_line_p
3462 && s->slice.x == 0)
3463 x += abs (s->face->box_line_width);
3465 /* If there is a margin around the image, adjust x- and y-position
3466 by that margin. */
3467 if (s->slice.x == 0)
3468 x += s->img->hmargin;
3469 if (s->slice.y == 0)
3470 y += s->img->vmargin;
3472 if (s->hl == DRAW_IMAGE_SUNKEN
3473 || s->hl == DRAW_IMAGE_RAISED)
3475 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3476 raised_p = s->hl == DRAW_IMAGE_RAISED;
3478 else
3480 thick = abs (s->img->relief);
3481 raised_p = s->img->relief > 0;
3484 x0 = x - thick;
3485 y0 = y - thick;
3486 x1 = x + s->slice.width + thick - 1;
3487 y1 = y + s->slice.height + thick - 1;
3489 x_setup_relief_colors (s);
3490 get_glyph_string_clip_rect (s, &r);
3491 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3492 s->slice.y == 0,
3493 s->slice.y + s->slice.height == s->img->height,
3494 s->slice.x == 0,
3495 s->slice.x + s->slice.width == s->img->width,
3496 &r);
3500 /* Draw part of the background of glyph string S. X, Y, W, and H
3501 give the rectangle to draw. */
3503 static void
3504 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3505 struct glyph_string *s;
3506 int x, y, w, h;
3508 #if 0 /* MAC_TODO: stipple */
3509 if (s->stippled_p)
3511 /* Fill background with a stipple pattern. */
3512 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3513 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3514 XSetFillStyle (s->display, s->gc, FillSolid);
3516 else
3517 #endif /* MAC_TODO */
3518 x_clear_glyph_string_rect (s, x, y, w, h);
3522 /* Draw image glyph string S.
3524 s->y
3525 s->x +-------------------------
3526 | s->face->box
3528 | +-------------------------
3529 | | s->img->margin
3531 | | +-------------------
3532 | | | the image
3536 static void
3537 x_draw_image_glyph_string (s)
3538 struct glyph_string *s;
3540 int x, y;
3541 int box_line_hwidth = abs (s->face->box_line_width);
3542 int box_line_vwidth = max (s->face->box_line_width, 0);
3543 int height;
3545 height = s->height - 2 * box_line_vwidth;
3548 /* Fill background with face under the image. Do it only if row is
3549 taller than image or if image has a clip mask to reduce
3550 flickering. */
3551 s->stippled_p = s->face->stipple != 0;
3552 if (height > s->slice.height
3553 || s->img->hmargin
3554 || s->img->vmargin
3555 || s->img->mask
3556 || s->img->pixmap == 0
3557 || s->width != s->background_width)
3559 x = s->x;
3560 if (s->first_glyph->left_box_line_p
3561 && s->slice.x == 0)
3562 x += box_line_hwidth;
3564 y = s->y;
3565 if (s->slice.y == 0)
3566 y += box_line_vwidth;
3568 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3570 s->background_filled_p = 1;
3573 /* Draw the foreground. */
3574 x_draw_image_foreground (s);
3576 /* If we must draw a relief around the image, do it. */
3577 if (s->img->relief
3578 || s->hl == DRAW_IMAGE_RAISED
3579 || s->hl == DRAW_IMAGE_SUNKEN)
3580 x_draw_image_relief (s);
3584 /* Draw stretch glyph string S. */
3586 static void
3587 x_draw_stretch_glyph_string (s)
3588 struct glyph_string *s;
3590 xassert (s->first_glyph->type == STRETCH_GLYPH);
3592 if (s->hl == DRAW_CURSOR
3593 && !x_stretch_cursor_p)
3595 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3596 as wide as the stretch glyph. */
3597 int width, background_width = s->background_width;
3598 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3600 if (x < left_x)
3602 background_width -= left_x - x;
3603 x = left_x;
3605 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3607 /* Draw cursor. */
3608 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3610 /* Clear rest using the GC of the original non-cursor face. */
3611 if (width < background_width)
3613 int y = s->y;
3614 int w = background_width - width, h = s->height;
3615 Rect r;
3616 GC gc;
3618 x += width;
3619 if (s->row->mouse_face_p
3620 && cursor_in_mouse_face_p (s->w))
3622 x_set_mouse_face_gc (s);
3623 gc = s->gc;
3625 else
3626 gc = s->face->gc;
3628 get_glyph_string_clip_rect (s, &r);
3629 mac_set_clip_rectangles (s->display, gc, &r, 1);
3631 #if 0 /* MAC_TODO: stipple */
3632 if (s->face->stipple)
3634 /* Fill background with a stipple pattern. */
3635 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3636 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3637 XSetFillStyle (s->display, gc, FillSolid);
3639 else
3640 #endif /* MAC_TODO */
3641 mac_erase_rectangle (s->f, gc, x, y, w, h);
3644 else if (!s->background_filled_p)
3646 int background_width = s->background_width;
3647 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3649 /* Don't draw into left margin, fringe or scrollbar area
3650 except for header line and mode line. */
3651 if (x < left_x && !s->row->mode_line_p)
3653 background_width -= left_x - x;
3654 x = left_x;
3656 if (background_width > 0)
3657 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3660 s->background_filled_p = 1;
3664 /* Draw glyph string S. */
3666 static void
3667 x_draw_glyph_string (s)
3668 struct glyph_string *s;
3670 int relief_drawn_p = 0;
3672 /* If S draws into the background of its successor that does not
3673 draw a cursor, draw the background of the successor first so that
3674 S can draw into it. This makes S->next use XDrawString instead
3675 of XDrawImageString. */
3676 if (s->next && s->right_overhang && !s->for_overlaps
3677 && s->next->hl != DRAW_CURSOR)
3679 xassert (s->next->img == NULL);
3680 x_set_glyph_string_gc (s->next);
3681 x_set_glyph_string_clipping (s->next);
3682 x_draw_glyph_string_background (s->next, 1);
3685 /* Set up S->gc, set clipping and draw S. */
3686 x_set_glyph_string_gc (s);
3688 /* Draw relief (if any) in advance for char/composition so that the
3689 glyph string can be drawn over it. */
3690 if (!s->for_overlaps
3691 && s->face->box != FACE_NO_BOX
3692 && (s->first_glyph->type == CHAR_GLYPH
3693 || s->first_glyph->type == COMPOSITE_GLYPH))
3696 x_set_glyph_string_clipping (s);
3697 x_draw_glyph_string_background (s, 1);
3698 x_draw_glyph_string_box (s);
3699 x_set_glyph_string_clipping (s);
3700 relief_drawn_p = 1;
3702 else
3703 x_set_glyph_string_clipping (s);
3705 switch (s->first_glyph->type)
3707 case IMAGE_GLYPH:
3708 x_draw_image_glyph_string (s);
3709 break;
3711 case STRETCH_GLYPH:
3712 x_draw_stretch_glyph_string (s);
3713 break;
3715 case CHAR_GLYPH:
3716 if (s->for_overlaps)
3717 s->background_filled_p = 1;
3718 else
3719 x_draw_glyph_string_background (s, 0);
3720 x_draw_glyph_string_foreground (s);
3721 break;
3723 case COMPOSITE_GLYPH:
3724 if (s->for_overlaps || s->gidx > 0)
3725 s->background_filled_p = 1;
3726 else
3727 x_draw_glyph_string_background (s, 1);
3728 x_draw_composite_glyph_string_foreground (s);
3729 break;
3731 default:
3732 abort ();
3735 if (!s->for_overlaps)
3737 /* Draw underline. */
3738 if (s->face->underline_p)
3740 unsigned long tem, h;
3741 int y;
3743 #if 0
3744 /* Get the underline thickness. Default is 1 pixel. */
3745 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3746 #endif
3747 h = 1;
3749 y = s->y + s->height - h;
3750 if (!x_underline_at_descent_line)
3752 /* Get the underline position. This is the recommended
3753 vertical offset in pixels from the baseline to the top of
3754 the underline. This is a signed value according to the
3755 specs, and its default is
3757 ROUND ((maximum descent) / 2), with
3758 ROUND(x) = floor (x + 0.5) */
3760 #if 0
3761 if (x_use_underline_position_properties
3762 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
3763 y = s->ybase + (long) tem;
3764 else
3765 #endif
3766 if (s->face->font)
3767 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
3770 if (s->face->underline_defaulted_p)
3771 mac_fill_rectangle (s->f, s->gc, s->x, y,
3772 s->background_width, h);
3773 else
3775 XGCValues xgcv;
3776 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3777 XSetForeground (s->display, s->gc, s->face->underline_color);
3778 mac_fill_rectangle (s->f, s->gc, s->x, y,
3779 s->background_width, h);
3780 XSetForeground (s->display, s->gc, xgcv.foreground);
3784 /* Draw overline. */
3785 if (s->face->overline_p)
3787 unsigned long dy = 0, h = 1;
3789 if (s->face->overline_color_defaulted_p)
3790 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3791 s->background_width, h);
3792 else
3794 XGCValues xgcv;
3795 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3796 XSetForeground (s->display, s->gc, s->face->overline_color);
3797 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3798 s->background_width, h);
3799 XSetForeground (s->display, s->gc, xgcv.foreground);
3803 /* Draw strike-through. */
3804 if (s->face->strike_through_p)
3806 unsigned long h = 1;
3807 unsigned long dy = (s->height - h) / 2;
3809 if (s->face->strike_through_color_defaulted_p)
3810 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3811 s->width, h);
3812 else
3814 XGCValues xgcv;
3815 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3816 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3817 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3818 s->width, h);
3819 XSetForeground (s->display, s->gc, xgcv.foreground);
3823 /* Draw relief if not yet drawn. */
3824 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3825 x_draw_glyph_string_box (s);
3828 /* Reset clipping. */
3829 mac_reset_clip_rectangles (s->display, s->gc);
3832 /* Shift display to make room for inserted glyphs. */
3834 void
3835 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3836 struct frame *f;
3837 int x, y, width, height, shift_by;
3839 mac_scroll_area (f, f->output_data.mac->normal_gc,
3840 x, y, width, height,
3841 x + shift_by, y);
3844 /* Delete N glyphs at the nominal cursor position. Not implemented
3845 for X frames. */
3847 static void
3848 x_delete_glyphs (n)
3849 register int n;
3851 abort ();
3855 /* Clear entire frame. If updating_frame is non-null, clear that
3856 frame. Otherwise clear the selected frame. */
3858 static void
3859 x_clear_frame ()
3861 struct frame *f;
3863 if (updating_frame)
3864 f = updating_frame;
3865 else
3866 f = SELECTED_FRAME ();
3868 /* Clearing the frame will erase any cursor, so mark them all as no
3869 longer visible. */
3870 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3871 output_cursor.hpos = output_cursor.vpos = 0;
3872 output_cursor.x = -1;
3874 /* We don't set the output cursor here because there will always
3875 follow an explicit cursor_to. */
3876 BLOCK_INPUT;
3877 mac_clear_window (f);
3879 /* We have to clear the scroll bars, too. If we have changed
3880 colors or something like that, then they should be notified. */
3881 x_scroll_bar_clear (f);
3883 XFlush (FRAME_MAC_DISPLAY (f));
3884 UNBLOCK_INPUT;
3889 /* Invert the middle quarter of the frame for .15 sec. */
3891 /* We use the select system call to do the waiting, so we have to make
3892 sure it's available. If it isn't, we just won't do visual bells. */
3894 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3897 /* Subtract the `struct timeval' values X and Y, storing the result in
3898 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3900 static int
3901 timeval_subtract (result, x, y)
3902 struct timeval *result, x, y;
3904 /* Perform the carry for the later subtraction by updating y. This
3905 is safer because on some systems the tv_sec member is unsigned. */
3906 if (x.tv_usec < y.tv_usec)
3908 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3909 y.tv_usec -= 1000000 * nsec;
3910 y.tv_sec += nsec;
3913 if (x.tv_usec - y.tv_usec > 1000000)
3915 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3916 y.tv_usec += 1000000 * nsec;
3917 y.tv_sec -= nsec;
3920 /* Compute the time remaining to wait. tv_usec is certainly
3921 positive. */
3922 result->tv_sec = x.tv_sec - y.tv_sec;
3923 result->tv_usec = x.tv_usec - y.tv_usec;
3925 /* Return indication of whether the result should be considered
3926 negative. */
3927 return x.tv_sec < y.tv_sec;
3930 void
3931 XTflash (f)
3932 struct frame *f;
3934 /* Get the height not including a menu bar widget. */
3935 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
3936 /* Height of each line to flash. */
3937 int flash_height = FRAME_LINE_HEIGHT (f);
3938 /* These will be the left and right margins of the rectangles. */
3939 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
3940 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
3942 int width;
3944 /* Don't flash the area between a scroll bar and the frame
3945 edge it is next to. */
3946 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
3948 case vertical_scroll_bar_left:
3949 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3950 break;
3952 case vertical_scroll_bar_right:
3953 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3954 break;
3956 default:
3957 break;
3960 width = flash_right - flash_left;
3962 BLOCK_INPUT;
3964 /* If window is tall, flash top and bottom line. */
3965 if (height > 3 * FRAME_LINE_HEIGHT (f))
3967 mac_invert_rectangle (f, flash_left,
3968 (FRAME_INTERNAL_BORDER_WIDTH (f)
3969 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
3970 width, flash_height);
3971 mac_invert_rectangle (f, flash_left,
3972 (height - flash_height
3973 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3974 width, flash_height);
3976 else
3977 /* If it is short, flash it all. */
3978 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3979 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3981 x_flush (f);
3984 struct timeval wakeup;
3986 EMACS_GET_TIME (wakeup);
3988 /* Compute time to wait until, propagating carry from usecs. */
3989 wakeup.tv_usec += 150000;
3990 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3991 wakeup.tv_usec %= 1000000;
3993 /* Keep waiting until past the time wakeup or any input gets
3994 available. */
3995 while (! detect_input_pending ())
3997 struct timeval current;
3998 struct timeval timeout;
4000 EMACS_GET_TIME (current);
4002 /* Break if result would be negative. */
4003 if (timeval_subtract (&current, wakeup, current))
4004 break;
4006 /* How long `select' should wait. */
4007 timeout.tv_sec = 0;
4008 timeout.tv_usec = 10000;
4010 /* Try to wait that long--but we might wake up sooner. */
4011 select (0, NULL, NULL, NULL, &timeout);
4015 /* If window is tall, flash top and bottom line. */
4016 if (height > 3 * FRAME_LINE_HEIGHT (f))
4018 mac_invert_rectangle (f, flash_left,
4019 (FRAME_INTERNAL_BORDER_WIDTH (f)
4020 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4021 width, flash_height);
4022 mac_invert_rectangle (f, flash_left,
4023 (height - flash_height
4024 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4025 width, flash_height);
4027 else
4028 /* If it is short, flash it all. */
4029 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4030 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4032 x_flush (f);
4034 UNBLOCK_INPUT;
4037 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4040 /* Make audible bell. */
4042 void
4043 XTring_bell ()
4045 struct frame *f = SELECTED_FRAME ();
4047 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4048 if (visible_bell)
4049 XTflash (f);
4050 else
4051 #endif
4053 BLOCK_INPUT;
4054 mac_alert_sound_play ();
4055 XFlush (FRAME_MAC_DISPLAY (f));
4056 UNBLOCK_INPUT;
4061 /* Specify how many text lines, from the top of the window,
4062 should be affected by insert-lines and delete-lines operations.
4063 This, and those operations, are used only within an update
4064 that is bounded by calls to x_update_begin and x_update_end. */
4066 static void
4067 XTset_terminal_window (n)
4068 register int n;
4070 /* This function intentionally left blank. */
4075 /***********************************************************************
4076 Line Dance
4077 ***********************************************************************/
4079 /* Perform an insert-lines or delete-lines operation, inserting N
4080 lines or deleting -N lines at vertical position VPOS. */
4082 static void
4083 x_ins_del_lines (vpos, n)
4084 int vpos, n;
4086 abort ();
4090 /* Scroll part of the display as described by RUN. */
4092 static void
4093 x_scroll_run (w, run)
4094 struct window *w;
4095 struct run *run;
4097 struct frame *f = XFRAME (w->frame);
4098 int x, y, width, height, from_y, to_y, bottom_y;
4100 /* Get frame-relative bounding box of the text display area of W,
4101 without mode lines. Include in this box the left and right
4102 fringe of W. */
4103 window_box (w, -1, &x, &y, &width, &height);
4105 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4106 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4107 bottom_y = y + height;
4109 if (to_y < from_y)
4111 /* Scrolling up. Make sure we don't copy part of the mode
4112 line at the bottom. */
4113 if (from_y + run->height > bottom_y)
4114 height = bottom_y - from_y;
4115 else
4116 height = run->height;
4118 else
4120 /* Scolling down. Make sure we don't copy over the mode line.
4121 at the bottom. */
4122 if (to_y + run->height > bottom_y)
4123 height = bottom_y - to_y;
4124 else
4125 height = run->height;
4128 BLOCK_INPUT;
4130 /* Cursor off. Will be switched on again in x_update_window_end. */
4131 updated_window = w;
4132 x_clear_cursor (w);
4134 mac_scroll_area (f, f->output_data.mac->normal_gc,
4135 x, from_y,
4136 width, height,
4137 x, to_y);
4139 UNBLOCK_INPUT;
4144 /***********************************************************************
4145 Exposure Events
4146 ***********************************************************************/
4149 static void
4150 frame_highlight (f)
4151 struct frame *f;
4153 x_update_cursor (f, 1);
4156 static void
4157 frame_unhighlight (f)
4158 struct frame *f;
4160 x_update_cursor (f, 1);
4163 /* The focus has changed. Update the frames as necessary to reflect
4164 the new situation. Note that we can't change the selected frame
4165 here, because the Lisp code we are interrupting might become confused.
4166 Each event gets marked with the frame in which it occurred, so the
4167 Lisp code can tell when the switch took place by examining the events. */
4169 static void
4170 x_new_focus_frame (dpyinfo, frame)
4171 struct x_display_info *dpyinfo;
4172 struct frame *frame;
4174 struct frame *old_focus = dpyinfo->x_focus_frame;
4176 if (frame != dpyinfo->x_focus_frame)
4178 /* Set this before calling other routines, so that they see
4179 the correct value of x_focus_frame. */
4180 dpyinfo->x_focus_frame = frame;
4182 if (old_focus && old_focus->auto_lower)
4183 x_lower_frame (old_focus);
4185 #if 0
4186 selected_frame = frame;
4187 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
4188 selected_frame);
4189 Fselect_window (selected_frame->selected_window, Qnil);
4190 choose_minibuf_frame ();
4191 #endif /* ! 0 */
4193 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4194 pending_autoraise_frame = dpyinfo->x_focus_frame;
4195 else
4196 pending_autoraise_frame = 0;
4198 #if USE_MAC_FONT_PANEL
4199 if (frame)
4200 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
4201 #endif
4204 x_frame_rehighlight (dpyinfo);
4207 /* Handle FocusIn and FocusOut state changes for FRAME.
4208 If FRAME has focus and there exists more than one frame, puts
4209 a FOCUS_IN_EVENT into *BUFP. */
4211 void
4212 mac_focus_changed (type, dpyinfo, frame, bufp)
4213 int type;
4214 struct mac_display_info *dpyinfo;
4215 struct frame *frame;
4216 struct input_event *bufp;
4218 if (type == activeFlag)
4220 if (dpyinfo->x_focus_event_frame != frame)
4222 x_new_focus_frame (dpyinfo, frame);
4223 dpyinfo->x_focus_event_frame = frame;
4225 /* Don't stop displaying the initial startup message
4226 for a switch-frame event we don't need. */
4227 if (GC_NILP (Vterminal_frame)
4228 && GC_CONSP (Vframe_list)
4229 && !GC_NILP (XCDR (Vframe_list)))
4231 bufp->kind = FOCUS_IN_EVENT;
4232 XSETFRAME (bufp->frame_or_window, frame);
4236 else
4238 if (dpyinfo->x_focus_event_frame == frame)
4240 dpyinfo->x_focus_event_frame = 0;
4241 x_new_focus_frame (dpyinfo, 0);
4246 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4248 void
4249 x_mouse_leave (dpyinfo)
4250 struct x_display_info *dpyinfo;
4252 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4255 /* The focus has changed, or we have redirected a frame's focus to
4256 another frame (this happens when a frame uses a surrogate
4257 mini-buffer frame). Shift the highlight as appropriate.
4259 The FRAME argument doesn't necessarily have anything to do with which
4260 frame is being highlighted or un-highlighted; we only use it to find
4261 the appropriate X display info. */
4263 static void
4264 XTframe_rehighlight (frame)
4265 struct frame *frame;
4267 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
4270 static void
4271 x_frame_rehighlight (dpyinfo)
4272 struct x_display_info *dpyinfo;
4274 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4276 if (dpyinfo->x_focus_frame)
4278 dpyinfo->x_highlight_frame
4279 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4280 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4281 : dpyinfo->x_focus_frame);
4282 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4284 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
4285 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4288 else
4289 dpyinfo->x_highlight_frame = 0;
4291 if (dpyinfo->x_highlight_frame != old_highlight)
4293 if (old_highlight)
4294 frame_unhighlight (old_highlight);
4295 if (dpyinfo->x_highlight_frame)
4296 frame_highlight (dpyinfo->x_highlight_frame);
4302 /* Convert a keysym to its name. */
4304 char *
4305 x_get_keysym_name (keysym)
4306 int keysym;
4308 char *value;
4310 BLOCK_INPUT;
4311 #if 0
4312 value = XKeysymToString (keysym);
4313 #else
4314 value = 0;
4315 #endif
4316 UNBLOCK_INPUT;
4318 return value;
4323 /* Function to report a mouse movement to the mainstream Emacs code.
4324 The input handler calls this.
4326 We have received a mouse movement event, which is given in *event.
4327 If the mouse is over a different glyph than it was last time, tell
4328 the mainstream emacs code by setting mouse_moved. If not, ask for
4329 another motion event, so we can check again the next time it moves. */
4331 static Point last_mouse_motion_position;
4332 static Lisp_Object last_mouse_motion_frame;
4335 note_mouse_movement (frame, pos)
4336 FRAME_PTR frame;
4337 Point *pos;
4339 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4340 Rect r;
4342 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4343 last_mouse_motion_position = *pos;
4344 XSETFRAME (last_mouse_motion_frame, frame);
4346 if (frame == dpyinfo->mouse_face_mouse_frame
4347 && !PtInRect (*pos, mac_get_frame_bounds (frame, &r)))
4349 /* This case corresponds to LeaveNotify in X11. If we move
4350 outside the frame, then we're certainly no longer on any text
4351 in the frame. */
4352 clear_mouse_face (dpyinfo);
4353 dpyinfo->mouse_face_mouse_frame = 0;
4354 if (!dpyinfo->grabbed)
4355 rif->define_frame_cursor (frame,
4356 frame->output_data.mac->nontext_cursor);
4359 /* Has the mouse moved off the glyph it was on at the last sighting? */
4360 if (frame != last_mouse_glyph_frame
4361 || !PtInRect (*pos, &last_mouse_glyph))
4363 frame->mouse_moved = 1;
4364 last_mouse_scroll_bar = Qnil;
4365 note_mouse_highlight (frame, pos->h, pos->v);
4366 /* Remember which glyph we're now on. */
4367 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
4368 last_mouse_glyph_frame = frame;
4369 return 1;
4372 return 0;
4376 /************************************************************************
4377 Mouse Face
4378 ************************************************************************/
4380 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4382 static void
4383 redo_mouse_highlight ()
4385 if (!NILP (last_mouse_motion_frame)
4386 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4387 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4388 last_mouse_motion_position.h,
4389 last_mouse_motion_position.v);
4393 struct frame *
4394 mac_focus_frame (dpyinfo)
4395 struct mac_display_info *dpyinfo;
4397 if (dpyinfo->x_focus_frame)
4398 return dpyinfo->x_focus_frame;
4399 else
4400 /* Mac version may get events, such as a menu bar click, even when
4401 all the frames are invisible. In this case, we regard the
4402 event came to the selected frame. */
4403 return SELECTED_FRAME ();
4407 /* Return the current position of the mouse.
4408 *FP should be a frame which indicates which display to ask about.
4410 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4411 and *PART to the frame, window, and scroll bar part that the mouse
4412 is over. Set *X and *Y to the portion and whole of the mouse's
4413 position on the scroll bar.
4415 If the mouse movement started elsewhere, set *FP to the frame the
4416 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4417 the mouse is over.
4419 Set *TIME to the server time-stamp for the time at which the mouse
4420 was at this position.
4422 Don't store anything if we don't have a valid set of values to report.
4424 This clears the mouse_moved flag, so we can wait for the next mouse
4425 movement. */
4427 static void
4428 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4429 FRAME_PTR *fp;
4430 int insist;
4431 Lisp_Object *bar_window;
4432 enum scroll_bar_part *part;
4433 Lisp_Object *x, *y;
4434 unsigned long *time;
4436 FRAME_PTR f1;
4438 BLOCK_INPUT;
4440 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4441 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4442 else
4444 Lisp_Object frame, tail;
4446 /* Clear the mouse-moved flag for every frame on this display. */
4447 FOR_EACH_FRAME (tail, frame)
4448 XFRAME (frame)->mouse_moved = 0;
4450 last_mouse_scroll_bar = Qnil;
4452 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4453 && FRAME_LIVE_P (last_mouse_frame))
4454 f1 = last_mouse_frame;
4455 else
4456 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4458 if (f1)
4460 /* Ok, we found a frame. Store all the values.
4461 last_mouse_glyph is a rectangle used to reduce the
4462 generation of mouse events. To not miss any motion
4463 events, we must divide the frame into rectangles of the
4464 size of the smallest character that could be displayed
4465 on it, i.e. into the same rectangles that matrices on
4466 the frame are divided into. */
4467 Point mouse_pos;
4469 mac_get_frame_mouse (f1, &mouse_pos);
4470 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4471 &last_mouse_glyph);
4472 last_mouse_glyph_frame = f1;
4474 *bar_window = Qnil;
4475 *part = 0;
4476 *fp = f1;
4477 XSETINT (*x, mouse_pos.h);
4478 XSETINT (*y, mouse_pos.v);
4479 *time = last_mouse_movement_time;
4483 UNBLOCK_INPUT;
4487 /************************************************************************
4488 Scroll bars, general
4489 ************************************************************************/
4491 /* Create a scroll bar and return the scroll bar vector for it. W is
4492 the Emacs window on which to create the scroll bar. TOP, LEFT,
4493 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4494 scroll bar. */
4496 static struct scroll_bar *
4497 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4498 struct window *w;
4499 int top, left, width, height, disp_top, disp_height;
4501 struct frame *f = XFRAME (w->frame);
4502 struct scroll_bar *bar
4503 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4504 Rect r;
4506 BLOCK_INPUT;
4508 XSETWINDOW (bar->window, w);
4509 XSETINT (bar->top, top);
4510 XSETINT (bar->left, left);
4511 XSETINT (bar->width, width);
4512 XSETINT (bar->height, height);
4513 #ifdef MAC_OSX
4514 bar->fringe_extended_p = Qnil;
4515 #endif
4516 bar->redraw_needed_p = Qnil;
4518 SetRect (&r, left, disp_top, left + width, disp_top + disp_height);
4519 mac_create_scroll_bar (bar, &r,
4520 #ifdef USE_TOOLKIT_SCROLL_BARS
4521 false
4522 #else
4523 width < disp_height
4524 #endif
4527 /* Add bar to its frame's list of scroll bars. */
4528 bar->next = FRAME_SCROLL_BARS (f);
4529 bar->prev = Qnil;
4530 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4531 if (!NILP (bar->next))
4532 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4534 UNBLOCK_INPUT;
4535 return bar;
4539 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4540 nil. */
4542 static void
4543 x_scroll_bar_remove (bar)
4544 struct scroll_bar *bar;
4546 BLOCK_INPUT;
4548 /* Destroy the Mac scroll bar control */
4549 mac_dispose_scroll_bar (bar);
4551 /* Disassociate this scroll bar from its window. */
4552 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4554 UNBLOCK_INPUT;
4558 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4559 that we are displaying PORTION characters out of a total of WHOLE
4560 characters, starting at POSITION. If WINDOW has no scroll bar,
4561 create one. */
4563 static void
4564 XTset_vertical_scroll_bar (w, portion, whole, position)
4565 struct window *w;
4566 int portion, whole, position;
4568 struct frame *f = XFRAME (w->frame);
4569 struct scroll_bar *bar;
4570 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4571 int window_y, window_height;
4572 #ifdef MAC_OSX
4573 int fringe_extended_p;
4574 #endif
4576 /* Get window dimensions. */
4577 window_box (w, -1, 0, &window_y, 0, &window_height);
4578 top = window_y;
4579 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4580 height = window_height;
4582 /* Compute the left edge of the scroll bar area. */
4583 left = WINDOW_SCROLL_BAR_AREA_X (w);
4585 /* Compute the width of the scroll bar which might be less than
4586 the width of the area reserved for the scroll bar. */
4587 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4588 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4589 else
4590 sb_width = width;
4592 /* Compute the left edge of the scroll bar. */
4593 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4594 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
4595 else
4596 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
4598 /* Adjustments according to Inside Macintosh to make it look nice */
4599 disp_top = top;
4600 disp_height = height;
4601 #ifdef MAC_OS8
4602 if (disp_top == 0)
4604 disp_top = -1;
4605 disp_height++;
4607 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4609 disp_top++;
4610 disp_height--;
4613 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4614 sb_left++;
4615 #endif
4617 #ifdef MAC_OSX
4618 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
4619 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
4620 && WINDOW_LEFT_FRINGE_WIDTH (w)
4621 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
4622 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
4623 else
4624 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
4625 && WINDOW_RIGHT_FRINGE_WIDTH (w)
4626 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
4627 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
4628 #endif
4630 /* Does the scroll bar exist yet? */
4631 if (NILP (w->vertical_scroll_bar))
4633 BLOCK_INPUT;
4634 #ifdef MAC_OSX
4635 if (fringe_extended_p)
4636 mac_clear_area (f, sb_left, top, sb_width, height);
4637 else
4638 #endif
4639 mac_clear_area (f, left, top, width, height);
4640 UNBLOCK_INPUT;
4641 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4642 disp_height);
4643 XSETVECTOR (w->vertical_scroll_bar, bar);
4645 else
4647 /* It may just need to be moved and resized. */
4648 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4650 BLOCK_INPUT;
4652 /* If already correctly positioned, do nothing. */
4653 if (XINT (bar->left) == sb_left
4654 && XINT (bar->top) == top
4655 && XINT (bar->width) == sb_width
4656 && XINT (bar->height) == height
4657 #ifdef MAC_OSX
4658 && !NILP (bar->fringe_extended_p) == fringe_extended_p
4659 #endif
4662 if (!NILP (bar->redraw_needed_p))
4663 mac_redraw_scroll_bar (bar);
4665 else
4667 Rect r;
4669 /* Since toolkit scroll bars are smaller than the space reserved
4670 for them on the frame, we have to clear "under" them. */
4671 #ifdef MAC_OSX
4672 if (fringe_extended_p)
4673 mac_clear_area (f, sb_left, top, sb_width, height);
4674 else
4675 #endif
4676 mac_clear_area (f, left, top, width, height);
4678 SetRect (&r, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top,
4679 sb_left + sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4680 disp_top + disp_height);
4681 mac_set_scroll_bar_bounds (bar, &r);
4683 /* Remember new settings. */
4684 XSETINT (bar->left, sb_left);
4685 XSETINT (bar->top, top);
4686 XSETINT (bar->width, sb_width);
4687 XSETINT (bar->height, height);
4690 UNBLOCK_INPUT;
4693 #ifdef MAC_OSX
4694 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
4695 #endif
4696 bar->redraw_needed_p = Qnil;
4698 #ifdef USE_TOOLKIT_SCROLL_BARS
4699 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4700 #else /* not USE_TOOLKIT_SCROLL_BARS */
4701 /* Set the scroll bar's current state, unless we're currently being
4702 dragged. */
4703 if (NILP (bar->dragging))
4705 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4707 if (whole == 0)
4708 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4709 else
4711 int start = ((double) position * top_range) / whole;
4712 int end = ((double) (position + portion) * top_range) / whole;
4713 x_scroll_bar_set_handle (bar, start, end, 0);
4716 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4720 /* The following three hooks are used when we're doing a thorough
4721 redisplay of the frame. We don't explicitly know which scroll bars
4722 are going to be deleted, because keeping track of when windows go
4723 away is a real pain - "Can you say set-window-configuration, boys
4724 and girls?" Instead, we just assert at the beginning of redisplay
4725 that *all* scroll bars are to be removed, and then save a scroll bar
4726 from the fiery pit when we actually redisplay its window. */
4728 /* Arrange for all scroll bars on FRAME to be removed at the next call
4729 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4730 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4732 static void
4733 XTcondemn_scroll_bars (frame)
4734 FRAME_PTR frame;
4736 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4737 while (! NILP (FRAME_SCROLL_BARS (frame)))
4739 Lisp_Object bar;
4740 bar = FRAME_SCROLL_BARS (frame);
4741 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4742 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4743 XSCROLL_BAR (bar)->prev = Qnil;
4744 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4745 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4746 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4751 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4752 Note that WINDOW isn't necessarily condemned at all. */
4754 static void
4755 XTredeem_scroll_bar (window)
4756 struct window *window;
4758 struct scroll_bar *bar;
4759 struct frame *f;
4761 /* We can't redeem this window's scroll bar if it doesn't have one. */
4762 if (NILP (window->vertical_scroll_bar))
4763 abort ();
4765 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4767 /* Unlink it from the condemned list. */
4768 f = XFRAME (WINDOW_FRAME (window));
4769 if (NILP (bar->prev))
4771 /* If the prev pointer is nil, it must be the first in one of
4772 the lists. */
4773 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4774 /* It's not condemned. Everything's fine. */
4775 return;
4776 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4777 window->vertical_scroll_bar))
4778 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4779 else
4780 /* If its prev pointer is nil, it must be at the front of
4781 one or the other! */
4782 abort ();
4784 else
4785 XSCROLL_BAR (bar->prev)->next = bar->next;
4787 if (! NILP (bar->next))
4788 XSCROLL_BAR (bar->next)->prev = bar->prev;
4790 bar->next = FRAME_SCROLL_BARS (f);
4791 bar->prev = Qnil;
4792 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4793 if (! NILP (bar->next))
4794 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4797 /* Remove all scroll bars on FRAME that haven't been saved since the
4798 last call to `*condemn_scroll_bars_hook'. */
4800 static void
4801 XTjudge_scroll_bars (f)
4802 FRAME_PTR f;
4804 Lisp_Object bar, next;
4806 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4808 /* Clear out the condemned list now so we won't try to process any
4809 more events on the hapless scroll bars. */
4810 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4812 for (; ! NILP (bar); bar = next)
4814 struct scroll_bar *b = XSCROLL_BAR (bar);
4816 x_scroll_bar_remove (b);
4818 next = b->next;
4819 b->next = b->prev = Qnil;
4822 /* Now there should be no references to the condemned scroll bars,
4823 and they should get garbage-collected. */
4826 /* The screen has been cleared so we may have changed foreground or
4827 background colors, and the scroll bars may need to be redrawn.
4828 Clear out the scroll bars, and ask for expose events, so we can
4829 redraw them. */
4831 void
4832 x_scroll_bar_clear (f)
4833 FRAME_PTR f;
4835 Lisp_Object bar;
4837 /* We can have scroll bars even if this is 0,
4838 if we just turned off scroll bar mode.
4839 But in that case we should not clear them. */
4840 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4841 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4842 bar = XSCROLL_BAR (bar)->next)
4843 XSCROLL_BAR (bar)->redraw_needed_p = Qt;
4847 /***********************************************************************
4848 Tool-bars
4849 ***********************************************************************/
4850 #if USE_MAC_TOOLBAR
4851 void
4852 mac_move_window_with_gravity (f, win_gravity, left, top)
4853 struct frame *f;
4854 int win_gravity;
4855 short left, top;
4857 Rect inner, outer;
4859 mac_get_window_bounds (f, &inner, &outer);
4861 switch (win_gravity)
4863 case NorthWestGravity:
4864 case WestGravity:
4865 case SouthWestGravity:
4866 left += inner.left - outer.left;
4867 break;
4869 case NorthGravity:
4870 case CenterGravity:
4871 case SouthGravity:
4872 left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
4873 break;
4875 case NorthEastGravity:
4876 case EastGravity:
4877 case SouthEastGravity:
4878 left += inner.right - outer.right;
4879 break;
4882 switch (win_gravity)
4884 case NorthWestGravity:
4885 case NorthGravity:
4886 case NorthEastGravity:
4887 top += inner.top - outer.top;
4888 break;
4890 case WestGravity:
4891 case CenterGravity:
4892 case EastGravity:
4893 top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
4894 break;
4896 case SouthWestGravity:
4897 case SouthGravity:
4898 case SouthEastGravity:
4899 top += inner.bottom - outer.bottom;
4900 break;
4903 mac_move_window (FRAME_MAC_WINDOW (f), left, top, false);
4906 void
4907 mac_get_window_origin_with_gravity (f, win_gravity, left, top)
4908 struct frame *f;
4909 int win_gravity;
4910 short *left, *top;
4912 Rect inner, outer;
4914 mac_get_window_bounds (f, &inner, &outer);
4916 switch (win_gravity)
4918 case NorthWestGravity:
4919 case WestGravity:
4920 case SouthWestGravity:
4921 *left = outer.left;
4922 break;
4924 case NorthGravity:
4925 case CenterGravity:
4926 case SouthGravity:
4927 *left = outer.left + ((outer.right - outer.left)
4928 - (inner.right - inner.left)) / 2;
4929 break;
4931 case NorthEastGravity:
4932 case EastGravity:
4933 case SouthEastGravity:
4934 *left = outer.right - (inner.right - inner.left);
4935 break;
4938 switch (win_gravity)
4940 case NorthWestGravity:
4941 case NorthGravity:
4942 case NorthEastGravity:
4943 *top = outer.top;
4944 break;
4946 case WestGravity:
4947 case CenterGravity:
4948 case EastGravity:
4949 *top = outer.top + ((outer.bottom - outer.top)
4950 - (inner.bottom - inner.top)) / 2;
4951 break;
4953 case SouthWestGravity:
4954 case SouthGravity:
4955 case SouthEastGravity:
4956 *top = outer.bottom - (inner.bottom - inner.top);
4957 break;
4961 CGImageRef
4962 mac_image_spec_to_cg_image (f, image)
4963 struct frame *f;
4964 Lisp_Object image;
4966 if (!valid_image_p (image))
4967 return NULL;
4968 else
4970 int img_id = lookup_image (f, image);
4971 struct image *img = IMAGE_FROM_ID (f, img_id);
4973 prepare_image_for_display (f, img);
4975 return img->data.ptr_val;
4978 #endif /* USE_MAC_TOOLBAR */
4981 /***********************************************************************
4982 Text Cursor
4983 ***********************************************************************/
4985 /* Set clipping for output in glyph row ROW. W is the window in which
4986 we operate. GC is the graphics context to set clipping in.
4988 ROW may be a text row or, e.g., a mode line. Text rows must be
4989 clipped to the interior of the window dedicated to text display,
4990 mode lines must be clipped to the whole window. */
4992 static void
4993 x_clip_to_row (w, row, area, gc)
4994 struct window *w;
4995 struct glyph_row *row;
4996 int area;
4997 GC gc;
4999 struct frame *f = XFRAME (WINDOW_FRAME (w));
5000 Rect clip_rect;
5001 int window_x, window_y, window_width;
5003 window_box (w, area, &window_x, &window_y, &window_width, 0);
5005 clip_rect.left = window_x;
5006 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5007 clip_rect.top = max (clip_rect.top, window_y);
5008 clip_rect.right = clip_rect.left + window_width;
5009 clip_rect.bottom = clip_rect.top + row->visible_height;
5011 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
5015 /* Draw a hollow box cursor on window W in glyph row ROW. */
5017 static void
5018 x_draw_hollow_cursor (w, row)
5019 struct window *w;
5020 struct glyph_row *row;
5022 struct frame *f = XFRAME (WINDOW_FRAME (w));
5023 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5024 Display *dpy = FRAME_MAC_DISPLAY (f);
5025 int x, y, wd, h;
5026 XGCValues xgcv;
5027 struct glyph *cursor_glyph;
5028 GC gc;
5030 /* Get the glyph the cursor is on. If we can't tell because
5031 the current matrix is invalid or such, give up. */
5032 cursor_glyph = get_phys_cursor_glyph (w);
5033 if (cursor_glyph == NULL)
5034 return;
5036 /* Compute frame-relative coordinates for phys cursor. */
5037 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
5038 wd = w->phys_cursor_width;
5040 /* The foreground of cursor_gc is typically the same as the normal
5041 background color, which can cause the cursor box to be invisible. */
5042 xgcv.foreground = f->output_data.mac->cursor_pixel;
5043 if (dpyinfo->scratch_cursor_gc)
5044 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5045 else
5046 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5047 GCForeground, &xgcv);
5048 gc = dpyinfo->scratch_cursor_gc;
5050 /* Set clipping, draw the rectangle, and reset clipping again. */
5051 x_clip_to_row (w, row, TEXT_AREA, gc);
5052 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
5053 mac_reset_clip_rectangles (dpy, gc);
5057 /* Draw a bar cursor on window W in glyph row ROW.
5059 Implementation note: One would like to draw a bar cursor with an
5060 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5061 Unfortunately, I didn't find a font yet that has this property set.
5062 --gerd. */
5064 static void
5065 x_draw_bar_cursor (w, row, width, kind)
5066 struct window *w;
5067 struct glyph_row *row;
5068 int width;
5069 enum text_cursor_kinds kind;
5071 struct frame *f = XFRAME (w->frame);
5072 struct glyph *cursor_glyph;
5074 /* If cursor is out of bounds, don't draw garbage. This can happen
5075 in mini-buffer windows when switching between echo area glyphs
5076 and mini-buffer. */
5077 cursor_glyph = get_phys_cursor_glyph (w);
5078 if (cursor_glyph == NULL)
5079 return;
5081 /* If on an image, draw like a normal cursor. That's usually better
5082 visible than drawing a bar, esp. if the image is large so that
5083 the bar might not be in the window. */
5084 if (cursor_glyph->type == IMAGE_GLYPH)
5086 struct glyph_row *row;
5087 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5088 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5090 else
5092 Display *dpy = FRAME_MAC_DISPLAY (f);
5093 Window window = FRAME_MAC_WINDOW (f);
5094 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5095 unsigned long mask = GCForeground | GCBackground;
5096 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5097 XGCValues xgcv;
5099 /* If the glyph's background equals the color we normally draw
5100 the bar cursor in, the bar cursor in its normal color is
5101 invisible. Use the glyph's foreground color instead in this
5102 case, on the assumption that the glyph's colors are chosen so
5103 that the glyph is legible. */
5104 if (face->background == f->output_data.mac->cursor_pixel)
5105 xgcv.background = xgcv.foreground = face->foreground;
5106 else
5107 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5109 if (gc)
5110 XChangeGC (dpy, gc, mask, &xgcv);
5111 else
5113 gc = XCreateGC (dpy, window, mask, &xgcv);
5114 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5117 if (width < 0)
5118 width = FRAME_CURSOR_WIDTH (f);
5119 width = min (cursor_glyph->pixel_width, width);
5121 w->phys_cursor_width = width;
5122 x_clip_to_row (w, row, TEXT_AREA, gc);
5124 if (kind == BAR_CURSOR)
5125 mac_fill_rectangle (f, gc,
5126 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5127 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5128 width, row->height);
5129 else
5130 mac_fill_rectangle (f, gc,
5131 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5132 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5133 row->height - width),
5134 cursor_glyph->pixel_width,
5135 width);
5137 mac_reset_clip_rectangles (dpy, gc);
5142 /* RIF: Define cursor CURSOR on frame F. */
5144 static void
5145 mac_define_frame_cursor (f, cursor)
5146 struct frame *f;
5147 Cursor cursor;
5149 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5151 if (dpyinfo->x_focus_frame == f)
5152 SetThemeCursor (cursor);
5156 /* RIF: Clear area on frame F. */
5158 static void
5159 mac_clear_frame_area (f, x, y, width, height)
5160 struct frame *f;
5161 int x, y, width, height;
5163 mac_clear_area (f, x, y, width, height);
5167 /* RIF: Draw cursor on window W. */
5169 static void
5170 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5171 struct window *w;
5172 struct glyph_row *glyph_row;
5173 int x, y;
5174 int cursor_type, cursor_width;
5175 int on_p, active_p;
5177 if (on_p)
5179 w->phys_cursor_type = cursor_type;
5180 w->phys_cursor_on_p = 1;
5182 if (glyph_row->exact_window_width_line_p
5183 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5185 glyph_row->cursor_in_fringe_p = 1;
5186 draw_fringe_bitmap (w, glyph_row, 0);
5188 else
5189 switch (cursor_type)
5191 case HOLLOW_BOX_CURSOR:
5192 x_draw_hollow_cursor (w, glyph_row);
5193 break;
5195 case FILLED_BOX_CURSOR:
5196 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5197 break;
5199 case BAR_CURSOR:
5200 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5201 break;
5203 case HBAR_CURSOR:
5204 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5205 break;
5207 case NO_CURSOR:
5208 w->phys_cursor_width = 0;
5209 break;
5211 default:
5212 abort ();
5218 /* Icons. */
5220 #if 0 /* MAC_TODO: no icon support yet. */
5222 x_bitmap_icon (f, icon)
5223 struct frame *f;
5224 Lisp_Object icon;
5226 HANDLE hicon;
5228 if (FRAME_W32_WINDOW (f) == 0)
5229 return 1;
5231 if (NILP (icon))
5232 hicon = LoadIcon (hinst, EMACS_CLASS);
5233 else if (STRINGP (icon))
5234 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5235 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5236 else if (SYMBOLP (icon))
5238 LPCTSTR name;
5240 if (EQ (icon, intern ("application")))
5241 name = (LPCTSTR) IDI_APPLICATION;
5242 else if (EQ (icon, intern ("hand")))
5243 name = (LPCTSTR) IDI_HAND;
5244 else if (EQ (icon, intern ("question")))
5245 name = (LPCTSTR) IDI_QUESTION;
5246 else if (EQ (icon, intern ("exclamation")))
5247 name = (LPCTSTR) IDI_EXCLAMATION;
5248 else if (EQ (icon, intern ("asterisk")))
5249 name = (LPCTSTR) IDI_ASTERISK;
5250 else if (EQ (icon, intern ("winlogo")))
5251 name = (LPCTSTR) IDI_WINLOGO;
5252 else
5253 return 1;
5255 hicon = LoadIcon (NULL, name);
5257 else
5258 return 1;
5260 if (hicon == NULL)
5261 return 1;
5263 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5264 (LPARAM) hicon);
5266 return 0;
5268 #endif /* MAC_TODO */
5270 /************************************************************************
5271 Handling X errors
5272 ************************************************************************/
5274 /* Display Error Handling functions not used on W32. Listing them here
5275 helps diff stay in step when comparing w32term.c with xterm.c.
5277 x_error_catcher (display, error)
5278 x_catch_errors (dpy)
5279 x_catch_errors_unwind (old_val)
5280 x_check_errors (dpy, format)
5281 x_had_errors_p (dpy)
5282 x_clear_errors (dpy)
5283 x_uncatch_errors (dpy, count)
5284 x_trace_wire ()
5285 x_connection_signal (signalnum)
5286 x_connection_closed (dpy, error_message)
5287 x_error_quitter (display, error)
5288 x_error_handler (display, error)
5289 x_io_error_quitter (display)
5294 /* Changing the font of the frame. */
5296 /* Give frame F the font named FONTNAME as its default font, and
5297 return the full name of that font. FONTNAME may be a wildcard
5298 pattern; in that case, we choose some font that fits the pattern.
5299 The return value shows which font we chose. */
5301 Lisp_Object
5302 x_new_font (f, fontname)
5303 struct frame *f;
5304 register char *fontname;
5306 struct font_info *fontp
5307 = FS_LOAD_FONT (f, 0, fontname, -1);
5309 if (!fontp)
5310 return Qnil;
5312 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5313 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5314 FRAME_FONTSET (f) = -1;
5316 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5317 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5318 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5320 compute_fringe_widths (f, 1);
5322 /* Compute the scroll bar width in character columns. */
5323 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5325 int wid = FRAME_COLUMN_WIDTH (f);
5326 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5327 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5329 else
5331 int wid = FRAME_COLUMN_WIDTH (f);
5332 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5335 /* Now make the frame display the given font. */
5336 if (FRAME_MAC_WINDOW (f) != 0)
5338 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5339 FRAME_FONT (f));
5340 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5341 FRAME_FONT (f));
5342 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5343 FRAME_FONT (f));
5345 /* Don't change the size of a tip frame; there's no point in
5346 doing it because it's done in Fx_show_tip, and it leads to
5347 problems because the tip frame has no widget. */
5348 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5349 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5352 return build_string (fontp->full_name);
5355 /* Give frame F the fontset named FONTSETNAME as its default font, and
5356 return the full name of that fontset. FONTSETNAME may be a wildcard
5357 pattern; in that case, we choose some fontset that fits the pattern.
5358 The return value shows which fontset we chose. */
5360 Lisp_Object
5361 x_new_fontset (f, fontsetname)
5362 struct frame *f;
5363 char *fontsetname;
5365 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5366 Lisp_Object result;
5368 if (fontset < 0)
5369 return Qnil;
5371 if (FRAME_FONTSET (f) == fontset)
5372 /* This fontset is already set in frame F. There's nothing more
5373 to do. */
5374 return fontset_name (fontset);
5376 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5378 if (!STRINGP (result))
5379 /* Can't load ASCII font. */
5380 return Qnil;
5382 /* Since x_new_font doesn't update any fontset information, do it now. */
5383 FRAME_FONTSET (f) = fontset;
5385 return build_string (fontsetname);
5389 /***********************************************************************
5390 TODO: W32 Input Methods
5391 ***********************************************************************/
5392 /* Listing missing functions from xterm.c helps diff stay in step.
5394 xim_destroy_callback (xim, client_data, call_data)
5395 xim_open_dpy (dpyinfo, resource_name)
5396 struct xim_inst_t
5397 xim_instantiate_callback (display, client_data, call_data)
5398 xim_initialize (dpyinfo, resource_name)
5399 xim_close_dpy (dpyinfo)
5404 void
5405 mac_handle_origin_change (f)
5406 struct frame *f;
5408 x_real_positions (f, &f->left_pos, &f->top_pos);
5411 void
5412 mac_handle_size_change (f, pixelwidth, pixelheight)
5413 struct frame *f;
5414 int pixelwidth, pixelheight;
5416 int cols, rows;
5418 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
5419 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
5421 if (cols != FRAME_COLS (f)
5422 || rows != FRAME_LINES (f)
5423 || pixelwidth != FRAME_PIXEL_WIDTH (f)
5424 || pixelheight != FRAME_PIXEL_HEIGHT (f))
5426 /* We pass 1 for DELAY since we can't run Lisp code inside of
5427 a BLOCK_INPUT. */
5428 change_frame_size (f, rows, cols, 0, 1, 0);
5429 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5430 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5431 SET_FRAME_GARBAGED (f);
5433 /* If cursor was outside the new size, mark it as off. */
5434 mark_window_cursors_off (XWINDOW (f->root_window));
5436 /* Clear out any recollection of where the mouse highlighting
5437 was, since it might be in a place that's outside the new
5438 frame size. Actually checking whether it is outside is a
5439 pain in the neck, so don't try--just let the highlighting be
5440 done afresh with new size. */
5441 cancel_mouse_face (f);
5443 #if TARGET_API_MAC_CARBON
5444 mac_reposition_hourglass (f);
5445 #endif
5450 /* Calculate the absolute position in frame F
5451 from its current recorded position values and gravity. */
5453 void
5454 x_calc_absolute_position (f)
5455 struct frame *f;
5457 int width_diff = 0, height_diff = 0;
5458 int flags = f->size_hint_flags;
5459 Rect inner, outer;
5461 /* We have nothing to do if the current position
5462 is already for the top-left corner. */
5463 if (! ((flags & XNegative) || (flags & YNegative)))
5464 return;
5466 /* Find the offsets of the outside upper-left corner of
5467 the inner window, with respect to the outer window. */
5468 BLOCK_INPUT;
5469 mac_get_window_bounds (f, &inner, &outer);
5470 UNBLOCK_INPUT;
5472 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5473 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5475 /* Treat negative positions as relative to the leftmost bottommost
5476 position that fits on the screen. */
5477 if (flags & XNegative)
5478 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5479 - width_diff
5480 - FRAME_PIXEL_WIDTH (f)
5481 + f->left_pos);
5483 if (flags & YNegative)
5484 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5485 - height_diff
5486 - FRAME_PIXEL_HEIGHT (f)
5487 + f->top_pos);
5489 /* The left_pos and top_pos
5490 are now relative to the top and left screen edges,
5491 so the flags should correspond. */
5492 f->size_hint_flags &= ~ (XNegative | YNegative);
5495 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5496 to really change the position, and 0 when calling from
5497 x_make_frame_visible (in that case, XOFF and YOFF are the current
5498 position values). It is -1 when calling from x_set_frame_parameters,
5499 which means, do adjust for borders but don't change the gravity. */
5501 void
5502 x_set_offset (f, xoff, yoff, change_gravity)
5503 struct frame *f;
5504 register int xoff, yoff;
5505 int change_gravity;
5507 if (change_gravity > 0)
5509 f->top_pos = yoff;
5510 f->left_pos = xoff;
5511 f->size_hint_flags &= ~ (XNegative | YNegative);
5512 if (xoff < 0)
5513 f->size_hint_flags |= XNegative;
5514 if (yoff < 0)
5515 f->size_hint_flags |= YNegative;
5516 f->win_gravity = NorthWestGravity;
5518 x_calc_absolute_position (f);
5520 BLOCK_INPUT;
5521 x_wm_set_size_hint (f, (long) 0, 0);
5523 #if TARGET_API_MAC_CARBON
5524 mac_move_window_structure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5525 /* If the title bar is completely outside the screen, adjust the
5526 position. */
5527 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5528 kWindowConstrainMoveRegardlessOfFit
5529 | kWindowConstrainAllowPartial, NULL, NULL);
5530 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
5531 mac_handle_origin_change (f);
5532 #else
5534 Rect inner, outer, screen_rect, dummy;
5535 RgnHandle region = NewRgn ();
5537 mac_get_window_bounds (f, &inner, &outer);
5538 f->x_pixels_diff = inner.left - outer.left;
5539 f->y_pixels_diff = inner.top - outer.top;
5540 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5541 f->top_pos + f->y_pixels_diff, false);
5543 /* If the title bar is completely outside the screen, adjust the
5544 position. The variable `outer' holds the title bar rectangle.
5545 The variable `inner' holds slightly smaller one than `outer',
5546 so that the calculation of overlapping may not become too
5547 strict. */
5548 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5549 outer = (*region)->rgnBBox;
5550 DisposeRgn (region);
5551 inner = outer;
5552 InsetRect (&inner, 8, 8);
5553 screen_rect = qd.screenBits.bounds;
5554 screen_rect.top += GetMBarHeight ();
5556 if (!SectRect (&inner, &screen_rect, &dummy))
5558 if (inner.right <= screen_rect.left)
5559 f->left_pos = screen_rect.left;
5560 else if (inner.left >= screen_rect.right)
5561 f->left_pos = screen_rect.right - (outer.right - outer.left);
5563 if (inner.bottom <= screen_rect.top)
5564 f->top_pos = screen_rect.top;
5565 else if (inner.top >= screen_rect.bottom)
5566 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5568 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5569 f->top_pos + f->y_pixels_diff, false);
5572 #endif
5574 UNBLOCK_INPUT;
5577 /* Call this to change the size of frame F's x-window.
5578 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5579 for this size change and subsequent size changes.
5580 Otherwise we leave the window gravity unchanged. */
5582 void
5583 x_set_window_size (f, change_gravity, cols, rows)
5584 struct frame *f;
5585 int change_gravity;
5586 int cols, rows;
5588 int pixelwidth, pixelheight;
5590 BLOCK_INPUT;
5592 check_frame_size (f, &rows, &cols);
5593 f->scroll_bar_actual_width
5594 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5596 compute_fringe_widths (f, 0);
5598 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5599 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5601 f->win_gravity = NorthWestGravity;
5602 x_wm_set_size_hint (f, (long) 0, 0);
5604 mac_size_window (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5606 #if TARGET_API_MAC_CARBON
5607 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
5608 #endif
5609 mac_handle_size_change (f, pixelwidth, pixelheight);
5611 if (f->output_data.mac->internal_border_width
5612 != FRAME_INTERNAL_BORDER_WIDTH (f))
5614 mac_clear_window (f);
5615 f->output_data.mac->internal_border_width
5616 = FRAME_INTERNAL_BORDER_WIDTH (f);
5619 SET_FRAME_GARBAGED (f);
5621 UNBLOCK_INPUT;
5624 /* Mouse warping. */
5626 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5628 void
5629 x_set_mouse_position (f, x, y)
5630 struct frame *f;
5631 int x, y;
5633 int pix_x, pix_y;
5635 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5636 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5638 if (pix_x < 0) pix_x = 0;
5639 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5641 if (pix_y < 0) pix_y = 0;
5642 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5644 x_set_mouse_pixel_position (f, pix_x, pix_y);
5647 void
5648 x_set_mouse_pixel_position (f, pix_x, pix_y)
5649 struct frame *f;
5650 int pix_x, pix_y;
5652 #ifdef MAC_OSX
5653 BLOCK_INPUT;
5654 mac_convert_frame_point_to_global (f, &pix_x, &pix_y);
5655 CGWarpMouseCursorPosition (CGPointMake (pix_x, pix_y));
5656 UNBLOCK_INPUT;
5657 #else
5658 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
5659 BLOCK_INPUT;
5661 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5662 0, 0, 0, 0, pix_x, pix_y);
5663 UNBLOCK_INPUT;
5664 #endif
5665 #endif
5668 /* focus shifting, raising and lowering. */
5670 void
5671 x_focus_on_frame (f)
5672 struct frame *f;
5674 #if 0 /* This proves to be unpleasant. */
5675 x_raise_frame (f);
5676 #endif
5677 #if 0
5678 /* I don't think that the ICCCM allows programs to do things like this
5679 without the interaction of the window manager. Whatever you end up
5680 doing with this code, do it to x_unfocus_frame too. */
5681 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5682 RevertToPointerRoot, CurrentTime);
5683 #endif /* ! 0 */
5686 void
5687 x_unfocus_frame (f)
5688 struct frame *f;
5692 /* Raise frame F. */
5694 void
5695 x_raise_frame (f)
5696 struct frame *f;
5698 if (f->async_visible)
5700 BLOCK_INPUT;
5701 mac_bring_window_to_front (FRAME_MAC_WINDOW (f));
5702 UNBLOCK_INPUT;
5706 /* Lower frame F. */
5708 void
5709 x_lower_frame (f)
5710 struct frame *f;
5712 if (f->async_visible)
5714 BLOCK_INPUT;
5715 mac_send_window_behind (FRAME_MAC_WINDOW (f), NULL);
5716 UNBLOCK_INPUT;
5720 static void
5721 XTframe_raise_lower (f, raise_flag)
5722 FRAME_PTR f;
5723 int raise_flag;
5725 if (raise_flag)
5726 x_raise_frame (f);
5727 else
5728 x_lower_frame (f);
5731 /* Change of visibility. */
5733 void
5734 mac_handle_visibility_change (f)
5735 struct frame *f;
5737 Window wp = FRAME_MAC_WINDOW (f);
5738 int visible = 0, iconified = 0;
5739 struct input_event buf;
5741 if (mac_is_window_visible (wp))
5743 if (mac_is_window_collapsed (wp))
5744 iconified = 1;
5745 else
5746 visible = 1;
5749 if (!f->async_visible && visible)
5751 if (f->iconified)
5753 /* wait_reading_process_output will notice this and update
5754 the frame's display structures. If we were made
5755 invisible, we should not set garbaged, because that stops
5756 redrawing on Update events. */
5757 SET_FRAME_GARBAGED (f);
5759 EVENT_INIT (buf);
5760 buf.kind = DEICONIFY_EVENT;
5761 XSETFRAME (buf.frame_or_window, f);
5762 buf.arg = Qnil;
5763 kbd_buffer_store_event (&buf);
5765 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
5766 /* Force a redisplay sooner or later to update the
5767 frame titles in case this is the second frame. */
5768 record_asynch_buffer_change ();
5770 else if (f->async_visible && !visible)
5771 if (iconified)
5773 EVENT_INIT (buf);
5774 buf.kind = ICONIFY_EVENT;
5775 XSETFRAME (buf.frame_or_window, f);
5776 buf.arg = Qnil;
5777 kbd_buffer_store_event (&buf);
5780 f->async_visible = visible;
5781 f->async_iconified = iconified;
5784 /* This tries to wait until the frame is really visible.
5785 However, if the window manager asks the user where to position
5786 the frame, this will return before the user finishes doing that.
5787 The frame will not actually be visible at that time,
5788 but it will become visible later when the window manager
5789 finishes with it. */
5791 void
5792 x_make_frame_visible (f)
5793 struct frame *f;
5795 BLOCK_INPUT;
5797 if (! FRAME_VISIBLE_P (f))
5799 /* We test FRAME_GARBAGED_P here to make sure we don't
5800 call x_set_offset a second time
5801 if we get to x_make_frame_visible a second time
5802 before the window gets really visible. */
5803 if (! FRAME_ICONIFIED_P (f)
5804 && ! f->output_data.mac->asked_for_visible)
5805 x_set_offset (f, f->left_pos, f->top_pos, 0);
5807 f->output_data.mac->asked_for_visible = 1;
5809 mac_collapse_window (FRAME_MAC_WINDOW (f), false);
5810 mac_show_window (FRAME_MAC_WINDOW (f));
5813 XFlush (FRAME_MAC_DISPLAY (f));
5815 /* Synchronize to ensure Emacs knows the frame is visible
5816 before we do anything else. We do this loop with input not blocked
5817 so that incoming events are handled. */
5819 Lisp_Object frame;
5820 int count;
5822 /* This must come after we set COUNT. */
5823 UNBLOCK_INPUT;
5825 XSETFRAME (frame, f);
5827 /* Wait until the frame is visible. Process X events until a
5828 MapNotify event has been seen, or until we think we won't get a
5829 MapNotify at all.. */
5830 for (count = input_signal_count + 10;
5831 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5833 /* Force processing of queued events. */
5834 x_sync (f);
5836 /* Machines that do polling rather than SIGIO have been
5837 observed to go into a busy-wait here. So we'll fake an
5838 alarm signal to let the handler know that there's something
5839 to be read. We used to raise a real alarm, but it seems
5840 that the handler isn't always enabled here. This is
5841 probably a bug. */
5842 if (input_polling_used ())
5844 /* It could be confusing if a real alarm arrives while
5845 processing the fake one. Turn it off and let the
5846 handler reset it. */
5847 extern void poll_for_input_1 P_ ((void));
5848 int old_poll_suppress_count = poll_suppress_count;
5849 poll_suppress_count = 1;
5850 poll_for_input_1 ();
5851 poll_suppress_count = old_poll_suppress_count;
5854 /* See if a MapNotify event has been processed. */
5855 FRAME_SAMPLE_VISIBILITY (f);
5860 /* Change from mapped state to withdrawn state. */
5862 /* Make the frame visible (mapped and not iconified). */
5864 void
5865 x_make_frame_invisible (f)
5866 struct frame *f;
5868 /* A deactivate event does not occur when the last visible frame is
5869 made invisible. So if we clear the highlight here, it will not
5870 be rehighlighted when it is made visible. */
5871 #if 0
5872 /* Don't keep the highlight on an invisible frame. */
5873 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5874 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5875 #endif
5877 BLOCK_INPUT;
5879 #if !TARGET_API_MAC_CARBON
5880 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5881 that the current position of the window is user-specified, rather than
5882 program-specified, so that when the window is mapped again, it will be
5883 placed at the same location, without forcing the user to position it
5884 by hand again (they have already done that once for this window.) */
5885 x_wm_set_size_hint (f, (long) 0, 1);
5886 #endif
5888 mac_hide_window (FRAME_MAC_WINDOW (f));
5890 UNBLOCK_INPUT;
5892 #if !TARGET_API_MAC_CARBON
5893 mac_handle_visibility_change (f);
5894 #endif
5897 /* Change window state from mapped to iconified. */
5899 void
5900 x_iconify_frame (f)
5901 struct frame *f;
5903 OSStatus err;
5905 /* A deactivate event does not occur when the last visible frame is
5906 iconified. So if we clear the highlight here, it will not be
5907 rehighlighted when it is deiconified. */
5908 #if 0
5909 /* Don't keep the highlight on an invisible frame. */
5910 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5911 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5912 #endif
5914 if (f->async_iconified)
5915 return;
5917 BLOCK_INPUT;
5919 FRAME_SAMPLE_VISIBILITY (f);
5921 if (! FRAME_VISIBLE_P (f))
5922 mac_show_window (FRAME_MAC_WINDOW (f));
5924 err = mac_collapse_window (FRAME_MAC_WINDOW (f), true);
5926 UNBLOCK_INPUT;
5928 if (err != noErr)
5929 error ("Can't notify window manager of iconification");
5931 #if !TARGET_API_MAC_CARBON
5932 mac_handle_visibility_change (f);
5933 #endif
5937 /* Free X resources of frame F. */
5939 void
5940 x_free_frame_resources (f)
5941 struct frame *f;
5943 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5944 Window wp = FRAME_MAC_WINDOW (f);
5946 BLOCK_INPUT;
5948 /* AppKit version of mac_dispose_frame_window, which is implemented
5949 as -[NSWindow close], will change the focus to the next window
5950 during its call. So, unlike other platforms, we clean up the
5951 focus-related variables before calling mac_dispose_frame_window. */
5952 if (f == dpyinfo->x_focus_frame)
5954 dpyinfo->x_focus_frame = 0;
5955 #if USE_MAC_FONT_PANEL
5956 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
5957 #endif
5959 if (f == dpyinfo->x_focus_event_frame)
5960 dpyinfo->x_focus_event_frame = 0;
5961 if (f == dpyinfo->x_highlight_frame)
5962 dpyinfo->x_highlight_frame = 0;
5964 if (f == dpyinfo->mouse_face_mouse_frame)
5966 dpyinfo->mouse_face_beg_row
5967 = dpyinfo->mouse_face_beg_col = -1;
5968 dpyinfo->mouse_face_end_row
5969 = dpyinfo->mouse_face_end_col = -1;
5970 dpyinfo->mouse_face_window = Qnil;
5971 dpyinfo->mouse_face_deferred_gc = 0;
5972 dpyinfo->mouse_face_mouse_frame = 0;
5975 mac_dispose_frame_window (f);
5976 if (wp == tip_window)
5977 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5978 closed' event. So we reset tip_window here. */
5979 tip_window = NULL;
5981 free_frame_menubar (f);
5983 if (FRAME_FACE_CACHE (f))
5984 free_frame_faces (f);
5986 x_free_gcs (f);
5988 if (FRAME_SIZE_HINTS (f))
5989 xfree (FRAME_SIZE_HINTS (f));
5991 xfree (f->output_data.mac);
5992 f->output_data.mac = NULL;
5994 UNBLOCK_INPUT;
5998 /* Destroy the X window of frame F. */
6000 void
6001 x_destroy_window (f)
6002 struct frame *f;
6004 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6006 x_free_frame_resources (f);
6008 dpyinfo->reference_count--;
6012 /* Setting window manager hints. */
6014 /* Set the normal size hints for the window manager, for frame F.
6015 FLAGS is the flags word to use--or 0 meaning preserve the flags
6016 that the window now has.
6017 If USER_POSITION is nonzero, we set the USPosition
6018 flag (this is useful when FLAGS is 0). */
6019 void
6020 x_wm_set_size_hint (f, flags, user_position)
6021 struct frame *f;
6022 long flags;
6023 int user_position;
6025 int base_width, base_height, width_inc, height_inc;
6026 int min_rows = 0, min_cols = 0;
6027 XSizeHints *size_hints;
6029 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6030 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6031 width_inc = FRAME_COLUMN_WIDTH (f);
6032 height_inc = FRAME_LINE_HEIGHT (f);
6034 check_frame_size (f, &min_rows, &min_cols);
6036 size_hints = FRAME_SIZE_HINTS (f);
6037 if (size_hints == NULL)
6039 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6040 bzero (size_hints, sizeof (XSizeHints));
6043 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6044 size_hints->width_inc = width_inc;
6045 size_hints->height_inc = height_inc;
6046 size_hints->min_width = base_width + min_cols * width_inc;
6047 size_hints->min_height = base_height + min_rows * height_inc;
6048 size_hints->base_width = base_width;
6049 size_hints->base_height = base_height;
6051 if (flags)
6052 size_hints->flags = flags;
6053 else if (user_position)
6055 size_hints->flags &= ~ PPosition;
6056 size_hints->flags |= USPosition;
6060 #if 0 /* MAC_TODO: hide application instead of iconify? */
6061 /* Used for IconicState or NormalState */
6063 void
6064 x_wm_set_window_state (f, state)
6065 struct frame *f;
6066 int state;
6068 #ifdef USE_X_TOOLKIT
6069 Arg al[1];
6071 XtSetArg (al[0], XtNinitialState, state);
6072 XtSetValues (f->output_data.x->widget, al, 1);
6073 #else /* not USE_X_TOOLKIT */
6074 Window window = FRAME_X_WINDOW (f);
6076 f->output_data.x->wm_hints.flags |= StateHint;
6077 f->output_data.x->wm_hints.initial_state = state;
6079 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6080 #endif /* not USE_X_TOOLKIT */
6083 void
6084 x_wm_set_icon_pixmap (f, pixmap_id)
6085 struct frame *f;
6086 int pixmap_id;
6088 Pixmap icon_pixmap;
6090 #ifndef USE_X_TOOLKIT
6091 Window window = FRAME_X_WINDOW (f);
6092 #endif
6094 if (pixmap_id > 0)
6096 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6097 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6099 else
6101 /* It seems there is no way to turn off use of an icon pixmap.
6102 The following line does it, only if no icon has yet been created,
6103 for some window managers. But with mwm it crashes.
6104 Some people say it should clear the IconPixmapHint bit in this case,
6105 but that doesn't work, and the X consortium said it isn't the
6106 right thing at all. Since there is no way to win,
6107 best to explicitly give up. */
6108 #if 0
6109 f->output_data.x->wm_hints.icon_pixmap = None;
6110 #else
6111 return;
6112 #endif
6115 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6118 Arg al[1];
6119 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6120 XtSetValues (f->output_data.x->widget, al, 1);
6123 #else /* not USE_X_TOOLKIT */
6125 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6126 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6128 #endif /* not USE_X_TOOLKIT */
6131 #endif /* MAC_TODO */
6133 void
6134 x_wm_set_icon_position (f, icon_x, icon_y)
6135 struct frame *f;
6136 int icon_x, icon_y;
6138 #if 0 /* MAC_TODO: no icons on Mac */
6139 #ifdef USE_X_TOOLKIT
6140 Window window = XtWindow (f->output_data.x->widget);
6141 #else
6142 Window window = FRAME_X_WINDOW (f);
6143 #endif
6145 f->output_data.x->wm_hints.flags |= IconPositionHint;
6146 f->output_data.x->wm_hints.icon_x = icon_x;
6147 f->output_data.x->wm_hints.icon_y = icon_y;
6149 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6150 #endif /* MAC_TODO */
6154 /***********************************************************************
6155 XLFD Pattern Match
6156 ***********************************************************************/
6158 /* An XLFD pattern is divided into blocks delimited by '*'. This
6159 structure holds information for each block. */
6160 struct xlfdpat_block
6162 /* Length of the pattern string in this block. Non-zero except for
6163 the first and the last blocks. */
6164 int len;
6166 /* Pattern string except the last character in this block. The last
6167 character is replaced with NUL in order to use it as a
6168 sentinel. */
6169 unsigned char *pattern;
6171 /* Last character of the pattern string. Must not be '?'. */
6172 unsigned char last_char;
6174 /* One of the tables for the Boyer-Moore string search. It
6175 specifies the number of positions to proceed for each character
6176 with which the match fails. */
6177 int skip[256];
6179 /* The skip value for the last character in the above `skip' is
6180 assigned to `infinity' in order to simplify a loop condition.
6181 The original value is saved here. */
6182 int last_char_skip;
6185 struct xlfdpat
6187 /* Normalized pattern string. "Normalized" means that capital
6188 letters are lowered, blocks are not empty except the first and
6189 the last ones, and trailing '?'s in a block that is not the last
6190 one are moved to the next one. The last character in each block
6191 is replaced with NUL. */
6192 unsigned char *buf;
6194 /* Number of characters except '*'s and trailing '?'s in the
6195 normalized pattern string. */
6196 int nchars;
6198 /* Number of trailing '?'s in the normalized pattern string. */
6199 int trailing_anychars;
6201 /* Number of blocks and information for each block. The latter is
6202 NULL if the pattern is exact (no '*' or '?' in it). */
6203 int nblocks;
6204 struct xlfdpat_block *blocks;
6207 static void
6208 xlfdpat_destroy (pat)
6209 struct xlfdpat *pat;
6211 if (pat)
6213 if (pat->buf)
6215 if (pat->blocks)
6216 xfree (pat->blocks);
6217 xfree (pat->buf);
6219 xfree (pat);
6223 static struct xlfdpat *
6224 xlfdpat_create (pattern)
6225 const char *pattern;
6227 struct xlfdpat *pat;
6228 int nblocks, i, skip;
6229 unsigned char last_char, *p, *q, *anychar_head;
6230 const unsigned char *ptr;
6231 struct xlfdpat_block *blk;
6233 pat = xmalloc (sizeof (struct xlfdpat));
6234 pat->buf = xmalloc (strlen (pattern) + 1);
6236 /* Normalize the pattern string and store it to `pat->buf'. */
6237 nblocks = 0;
6238 anychar_head = NULL;
6239 q = pat->buf;
6240 last_char = '\0';
6241 for (ptr = pattern; *ptr; ptr++)
6243 unsigned char c = *ptr;
6245 if (c == '*')
6246 if (last_char == '*')
6247 /* ...a** -> ...a* */
6248 continue;
6249 else
6251 if (last_char == '?')
6253 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6254 /* ...*??* -> ...*?? */
6255 continue;
6256 else
6257 /* ...a??* -> ...a*?? */
6259 *anychar_head++ = '*';
6260 c = '?';
6263 nblocks++;
6265 else if (c == '?')
6267 if (last_char != '?')
6268 anychar_head = q;
6270 else
6271 /* On Mac OS X 10.3, tolower also converts non-ASCII
6272 characters for some locales. */
6273 if (isascii (c))
6274 c = tolower (c);
6276 *q++ = last_char = c;
6278 *q = '\0';
6279 nblocks++;
6280 pat->nblocks = nblocks;
6281 if (last_char != '?')
6282 pat->trailing_anychars = 0;
6283 else
6285 pat->trailing_anychars = q - anychar_head;
6286 q = anychar_head;
6288 pat->nchars = q - pat->buf - (nblocks - 1);
6290 if (anychar_head == NULL && nblocks == 1)
6292 /* The pattern is exact. */
6293 pat->blocks = NULL;
6294 return pat;
6297 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6299 /* Divide the normalized pattern into blocks. */
6300 p = pat->buf;
6301 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6303 blk->pattern = p;
6304 while (*p != '*')
6305 p++;
6306 blk->len = p - blk->pattern;
6307 p++;
6309 blk->pattern = p;
6310 blk->len = q - blk->pattern;
6312 /* Setup a table for the Boyer-Moore string search. */
6313 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6314 if (blk->len != 0)
6316 blk->last_char = blk->pattern[blk->len - 1];
6317 blk->pattern[blk->len - 1] = '\0';
6319 for (skip = 1; skip < blk->len; skip++)
6320 if (blk->pattern[blk->len - skip - 1] == '?')
6321 break;
6323 for (i = 0; i < 256; i++)
6324 blk->skip[i] = skip;
6326 p = blk->pattern + (blk->len - skip);
6327 while (--skip > 0)
6328 blk->skip[*p++] = skip;
6330 blk->last_char_skip = blk->skip[blk->last_char];
6333 return pat;
6336 static INLINE int
6337 xlfdpat_exact_p (pat)
6338 struct xlfdpat *pat;
6340 return pat->blocks == NULL;
6343 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6344 that the pattern in *BLK matches with its prefix. Return NULL
6345 there is no such strings. STRING must be lowered in advance. */
6347 static const char *
6348 xlfdpat_block_match_1 (blk, string, start_max)
6349 struct xlfdpat_block *blk;
6350 const unsigned char *string;
6351 int start_max;
6353 int start, infinity;
6354 unsigned char *p;
6355 const unsigned char *s;
6357 xassert (blk->len > 0);
6358 xassert (start_max + blk->len <= strlen (string));
6359 xassert (blk->last_char != '?');
6361 /* See the comments in the function `boyer_moore' (search.c) for the
6362 use of `infinity'. */
6363 infinity = start_max + blk->len + 1;
6364 blk->skip[blk->last_char] = infinity;
6366 start = 0;
6369 /* Check the last character of the pattern. */
6370 s = string + blk->len - 1;
6373 start += blk->skip[*(s + start)];
6375 while (start <= start_max);
6377 if (start < infinity)
6378 /* Couldn't find the last character. */
6379 return NULL;
6381 /* No less than `infinity' means we could find the last
6382 character at `s[start - infinity]'. */
6383 start -= infinity;
6385 /* Check the remaining characters. We prefer making no-'?'
6386 cases faster because the use of '?' is really rare. */
6387 p = blk->pattern;
6388 s = string + start;
6391 while (*p++ == *s++)
6394 while (*(p - 1) == '?');
6396 if (*(p - 1) == '\0')
6397 /* Matched. */
6398 return string + start;
6400 /* Didn't match. */
6401 start += blk->last_char_skip;
6403 while (start <= start_max);
6405 return NULL;
6408 #define xlfdpat_block_match(b, s, m) \
6409 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6410 : xlfdpat_block_match_1 (b, s, m))
6412 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
6413 matches with STRING. STRING must be lowered in advance. */
6415 static int
6416 xlfdpat_match (pat, string)
6417 struct xlfdpat *pat;
6418 const unsigned char *string;
6420 int str_len, nblocks, i, start_max;
6421 struct xlfdpat_block *blk;
6422 const unsigned char *s;
6424 xassert (pat->nblocks > 0);
6426 if (xlfdpat_exact_p (pat))
6427 return strcmp (pat->buf, string) == 0;
6429 /* The number of the characters in the string must not be smaller
6430 than that in the pattern. */
6431 str_len = strlen (string);
6432 if (str_len < pat->nchars + pat->trailing_anychars)
6433 return 0;
6435 /* Chop off the trailing '?'s. */
6436 str_len -= pat->trailing_anychars;
6438 /* The last block. When it is non-empty, it must match at the end
6439 of the string. */
6440 nblocks = pat->nblocks;
6441 blk = pat->blocks + (nblocks - 1);
6442 if (nblocks == 1)
6443 /* The last block is also the first one. */
6444 return (str_len == blk->len
6445 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
6446 else if (blk->len != 0)
6447 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
6448 return 0;
6450 /* The first block. When it is non-empty, it must match at the
6451 beginning of the string. */
6452 blk = pat->blocks;
6453 if (blk->len != 0)
6455 s = xlfdpat_block_match (blk, string, 0);
6456 if (s == NULL)
6457 return 0;
6458 string = s + blk->len;
6461 /* The rest of the blocks. */
6462 start_max = str_len - pat->nchars;
6463 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
6465 s = xlfdpat_block_match (blk, string, start_max);
6466 if (s == NULL)
6467 return 0;
6468 start_max -= s - string;
6469 string = s + blk->len;
6472 return 1;
6476 /***********************************************************************
6477 Fonts
6478 ***********************************************************************/
6480 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6482 struct font_info *
6483 x_get_font_info (f, font_idx)
6484 FRAME_PTR f;
6485 int font_idx;
6487 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
6490 /* the global font name table */
6491 static char **font_name_table = NULL;
6492 static int font_name_table_size = 0;
6493 static int font_name_count = 0;
6495 /* Alist linking font family names to Font Manager font family
6496 references (which can also be used as QuickDraw font IDs). We use
6497 an alist because hash tables are not ready when the terminal frame
6498 for Mac OS Classic is created. */
6499 static Lisp_Object fm_font_family_alist;
6500 #if USE_ATSUI
6501 /* Hash table linking font family names to ATSU font IDs. */
6502 static Lisp_Object atsu_font_id_hash;
6503 /* Alist linking Font Manager style to face attributes. */
6504 static Lisp_Object fm_style_face_attributes_alist;
6505 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
6506 #endif
6507 #if USE_MAC_FONT_PANEL
6508 Lisp_Object Qpanel_closed, Qselection;
6509 #endif
6511 /* Alist linking character set strings to Mac text encoding and Emacs
6512 coding system. */
6513 static Lisp_Object Vmac_charset_info_alist;
6515 static Lisp_Object
6516 create_text_encoding_info_alist ()
6518 Lisp_Object result = Qnil, rest;
6520 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6522 Lisp_Object charset_info = XCAR (rest);
6523 Lisp_Object charset, coding_system, text_encoding;
6524 Lisp_Object existing_info;
6526 if (!(CONSP (charset_info)
6527 && (charset = XCAR (charset_info),
6528 STRINGP (charset))
6529 && CONSP (XCDR (charset_info))
6530 && (text_encoding = XCAR (XCDR (charset_info)),
6531 INTEGERP (text_encoding))
6532 && CONSP (XCDR (XCDR (charset_info)))
6533 && (coding_system = XCAR (XCDR (XCDR (charset_info))),
6534 SYMBOLP (coding_system))))
6535 continue;
6537 existing_info = assq_no_quit (text_encoding, result);
6538 if (NILP (existing_info))
6539 result = Fcons (list3 (text_encoding, coding_system, charset),
6540 result);
6541 else
6542 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
6543 XSETCDR (XCDR (existing_info),
6544 Fcons (charset, XCDR (XCDR (existing_info))));
6547 return result;
6551 static void
6552 decode_mac_font_name (name, size, coding_system)
6553 char *name;
6554 int size;
6555 Lisp_Object coding_system;
6557 struct coding_system coding;
6558 char *buf, *p;
6560 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
6562 for (p = name; *p; p++)
6563 if (!isascii (*p) || iscntrl (*p))
6564 break;
6566 if (*p)
6568 setup_coding_system (coding_system, &coding);
6569 coding.src_multibyte = 0;
6570 coding.dst_multibyte = 1;
6571 coding.mode |= CODING_MODE_LAST_BLOCK;
6572 coding.composing = COMPOSITION_DISABLED;
6573 buf = (char *) alloca (size);
6575 decode_coding (&coding, name, buf, strlen (name), size - 1);
6576 bcopy (buf, name, coding.produced);
6577 name[coding.produced] = '\0';
6581 /* If there's just one occurrence of '-' in the family name, it is
6582 replaced with '_'. (More than one occurrence of '-' means a
6583 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6584 p = strchr (name, '-');
6585 if (p && strchr (p + 1, '-') == NULL)
6586 *p = '_';
6588 for (p = name; *p; p++)
6589 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6590 for some locales. */
6591 if (isascii (*p))
6592 *p = tolower (*p);
6596 static char *
6597 mac_to_x_fontname (name, size, style, charset)
6598 const char *name;
6599 int size;
6600 Style style;
6601 char *charset;
6603 Str31 foundry, cs;
6604 Str255 family;
6605 char xf[256], *result;
6606 unsigned char *p;
6608 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
6609 charset = cs;
6610 else
6612 strcpy(foundry, "Apple");
6613 strcpy(family, name);
6616 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6617 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
6618 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
6620 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
6621 sprintf (result, "-%s-%s-%s", foundry, family, xf);
6622 for (p = result; *p; p++)
6623 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6624 for some locales. */
6625 if (isascii (*p))
6626 *p = tolower (*p);
6627 return result;
6631 /* Parse fully-specified and instantiated X11 font spec XF, and store
6632 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6633 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6634 caller must allocate at least 256 and 32 bytes respectively. For
6635 ordinary Mac fonts, the value stored to FAMILY should just be their
6636 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6637 intlfonts collection contain their charset designation in their
6638 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6639 types of font names are handled accordingly. */
6641 const int kDefaultFontSize = 12;
6643 static int
6644 parse_x_font_name (xf, family, size, style, charset)
6645 const char *xf;
6646 char *family;
6647 int *size;
6648 Style *style;
6649 char *charset;
6651 Str31 foundry, weight;
6652 int point_size, avgwidth;
6653 char slant[2], *p;
6655 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6656 foundry, family, weight, slant, size,
6657 &point_size, &avgwidth, charset) != 8
6658 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6659 foundry, family, weight, slant, size,
6660 &point_size, &avgwidth, charset) != 8)
6661 return 0;
6663 if (*size == 0)
6665 if (point_size > 0)
6666 *size = point_size / 10;
6667 else if (avgwidth > 0)
6668 *size = avgwidth / 10;
6670 if (*size == 0)
6671 *size = kDefaultFontSize;
6673 *style = normal;
6674 if (strcmp (weight, "bold") == 0)
6675 *style |= bold;
6676 if (*slant == 'i')
6677 *style |= italic;
6679 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
6681 int foundry_len = strlen (foundry), family_len = strlen (family);
6683 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
6685 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6686 but take overlap into account. */
6687 memmove (family + foundry_len + 1, family, family_len);
6688 memcpy (family, foundry, foundry_len);
6689 family[foundry_len] = '-';
6690 family[foundry_len + 1 + family_len] = '-';
6691 strcpy (family + foundry_len + 1 + family_len + 1, charset);
6693 else
6694 return 0;
6697 for (p = family; *p; p++)
6698 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6699 for some locales. */
6700 if (isascii (*p))
6701 *p = tolower (*p);
6703 return 1;
6707 static void
6708 add_font_name_table_entry (char *font_name)
6710 if (font_name_table_size == 0)
6712 font_name_table_size = 256;
6713 font_name_table = (char **)
6714 xmalloc (font_name_table_size * sizeof (char *));
6716 else if (font_name_count + 1 >= font_name_table_size)
6718 font_name_table_size *= 2;
6719 font_name_table = (char **)
6720 xrealloc (font_name_table,
6721 font_name_table_size * sizeof (char *));
6724 font_name_table[font_name_count++] = font_name;
6727 static void
6728 add_mac_font_name (name, size, style, charset)
6729 const char *name;
6730 int size;
6731 Style style;
6732 const char *charset;
6734 if (size > 0)
6735 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
6736 else
6738 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
6739 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
6740 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
6741 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
6742 charset));
6746 #if USE_ATSUI
6747 static FMFontStyle
6748 fm_get_style_from_font (font)
6749 FMFont font;
6751 OSStatus err;
6752 FMFontStyle style = normal;
6753 ByteCount len;
6754 UInt16 mac_style;
6755 FMFontFamily font_family;
6756 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
6758 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
6759 some font (e.g., Optima) even if it is `bold'. */
6760 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
6761 sizeof (mac_style), &mac_style, &len);
6762 if (err == noErr
6763 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
6764 style = EndianU16_BtoN (mac_style);
6765 else
6766 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
6768 return style;
6771 static ATSUFontID
6772 atsu_find_font_from_family_name (family)
6773 const char *family;
6775 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
6776 unsigned hash_code;
6777 int i;
6778 Lisp_Object rest, best;
6779 FMFontStyle min_style, style;
6781 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
6782 &hash_code);
6783 if (i < 0)
6784 return kATSUInvalidFontID;
6786 rest = HASH_VALUE (h, i);
6787 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
6788 return cons_to_long (rest);
6790 rest = Fnreverse (rest);
6791 best = XCAR (rest);
6792 rest = XCDR (rest);
6793 if (!NILP (rest)
6794 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
6797 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
6798 if (style < min_style)
6800 best = XCAR (rest);
6801 if (style == normal)
6802 break;
6803 else
6804 min_style = style;
6806 rest = XCDR (rest);
6808 while (!NILP (rest));
6810 HASH_VALUE (h, i) = best;
6811 return cons_to_long (best);
6814 static Lisp_Object
6815 fm_style_to_face_attributes (fm_style)
6816 FMFontStyle fm_style;
6818 Lisp_Object tem;
6820 fm_style &= (bold | italic);
6821 tem = assq_no_quit (make_number (fm_style),
6822 fm_style_face_attributes_alist);
6823 if (!NILP (tem))
6824 return XCDR (tem);
6826 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
6827 QCslant, fm_style & italic ? Qitalic : Qnormal);
6828 fm_style_face_attributes_alist =
6829 Fcons (Fcons (make_number (fm_style), tem),
6830 fm_style_face_attributes_alist);
6832 return tem;
6835 static Lisp_Object
6836 atsu_find_font_family_name (font_id)
6837 ATSUFontID font_id;
6839 OSStatus err;
6840 ByteCount len;
6841 Lisp_Object family = Qnil;
6843 err = ATSUFindFontName (font_id, kFontFamilyName,
6844 kFontMacintoshPlatform, kFontNoScript,
6845 kFontNoLanguage, 0, NULL, &len, NULL);
6846 if (err == noErr)
6848 family = make_uninit_string (len);
6849 err = ATSUFindFontName (font_id, kFontFamilyName,
6850 kFontMacintoshPlatform, kFontNoScript,
6851 kFontNoLanguage, len, SDATA (family),
6852 NULL, NULL);
6854 if (err == noErr)
6855 decode_mac_font_name (SDATA (family), len + 1, Qnil);
6857 return family;
6860 Lisp_Object
6861 mac_atsu_font_face_attributes (font_id)
6862 ATSUFontID font_id;
6864 Lisp_Object family, style_attrs;
6866 family = atsu_find_font_family_name (font_id);
6867 if (NILP (family))
6868 return Qnil;
6869 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
6870 return Fcons (QCfamily, Fcons (family, style_attrs));
6872 #endif
6874 /* Sets up the table font_name_table to contain the list of all fonts
6875 in the system the first time the table is used so that the Resource
6876 Manager need not be accessed every time this information is
6877 needed. */
6879 static void
6880 init_font_name_table ()
6882 #if TARGET_API_MAC_CARBON
6883 FMFontFamilyIterator ffi;
6884 FMFontFamilyInstanceIterator ffii;
6885 FMFontFamily ff;
6886 Lisp_Object text_encoding_info_alist;
6887 struct gcpro gcpro1;
6889 text_encoding_info_alist = create_text_encoding_info_alist ();
6891 #if USE_ATSUI
6892 #if USE_CG_TEXT_DRAWING
6893 init_cg_text_anti_aliasing_threshold ();
6894 #endif
6895 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
6896 text_encoding_info_alist)))
6898 OSStatus err;
6899 struct Lisp_Hash_Table *h;
6900 unsigned hash_code;
6901 ItemCount nfonts, i;
6902 ATSUFontID *font_ids = NULL;
6903 Lisp_Object prev_family = Qnil;
6904 int j;
6906 atsu_font_id_hash =
6907 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
6908 make_float (DEFAULT_REHASH_SIZE),
6909 make_float (DEFAULT_REHASH_THRESHOLD),
6910 Qnil, Qnil, Qnil);
6911 h = XHASH_TABLE (atsu_font_id_hash);
6913 err = ATSUFontCount (&nfonts);
6914 if (err == noErr)
6916 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
6917 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
6919 if (err == noErr)
6920 for (i = 0; i < nfonts; i++)
6922 Lisp_Object family;
6924 family = atsu_find_font_family_name (font_ids[i]);
6925 if (NILP (family) || SREF (family, 0) == '.')
6926 continue;
6927 if (!NILP (Fequal (prev_family, family)))
6928 family = prev_family;
6929 else
6930 j = hash_lookup (h, family, &hash_code);
6931 if (j < 0)
6933 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
6934 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
6935 Qnil), hash_code);
6937 else if (EQ (prev_family, family))
6938 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
6939 HASH_VALUE (h, j));
6940 prev_family = family;
6942 if (font_ids)
6943 xfree (font_ids);
6945 #endif
6947 /* Create a dummy instance iterator here to avoid creating and
6948 destroying it in the loop. */
6949 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6950 return;
6951 /* Create an iterator to enumerate the font families. */
6952 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6953 != noErr)
6955 FMDisposeFontFamilyInstanceIterator (&ffii);
6956 return;
6959 GCPRO1 (text_encoding_info_alist);
6961 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6963 Str255 name;
6964 FMFont font;
6965 FMFontStyle style;
6966 FMFontSize size;
6967 TextEncoding encoding;
6968 TextEncodingBase sc;
6969 Lisp_Object text_encoding_info, family;
6971 if (FMGetFontFamilyName (ff, name) != noErr)
6972 continue;
6973 p2cstr (name);
6974 if (*name == '.')
6975 continue;
6977 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6978 continue;
6979 sc = GetTextEncodingBase (encoding);
6980 text_encoding_info = assq_no_quit (make_number (sc),
6981 text_encoding_info_alist);
6982 if (NILP (text_encoding_info))
6983 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
6984 text_encoding_info_alist);
6985 decode_mac_font_name (name, sizeof (name),
6986 XCAR (XCDR (text_encoding_info)));
6987 family = build_string (name);
6988 if (!NILP (Fassoc (family, fm_font_family_alist)))
6989 continue;
6990 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
6991 fm_font_family_alist);
6993 /* Point the instance iterator at the current font family. */
6994 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6995 continue;
6997 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6998 == noErr)
7000 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7002 if (size > 0 || style == normal)
7003 for (; !NILP (rest); rest = XCDR (rest))
7004 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
7008 UNGCPRO;
7010 /* Dispose of the iterators. */
7011 FMDisposeFontFamilyIterator (&ffi);
7012 FMDisposeFontFamilyInstanceIterator (&ffii);
7013 #else /* !TARGET_API_MAC_CARBON */
7014 GrafPtr port;
7015 SInt16 fontnum, old_fontnum;
7016 int num_mac_fonts = CountResources('FOND');
7017 int i, j;
7018 Handle font_handle, font_handle_2;
7019 short id, scriptcode;
7020 ResType type;
7021 Str255 name;
7022 struct FontAssoc *fat;
7023 struct AsscEntry *assc_entry;
7024 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
7025 struct gcpro gcpro1;
7027 GetPort (&port); /* save the current font number used */
7028 old_fontnum = port->txFont;
7030 text_encoding_info_alist = create_text_encoding_info_alist ();
7032 GCPRO1 (text_encoding_info_alist);
7034 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
7036 font_handle = GetIndResource ('FOND', i);
7037 if (!font_handle)
7038 continue;
7040 GetResInfo (font_handle, &id, &type, name);
7041 GetFNum (name, &fontnum);
7042 p2cstr (name);
7043 if (fontnum == 0 || *name == '.')
7044 continue;
7046 TextFont (fontnum);
7047 scriptcode = FontToScript (fontnum);
7048 text_encoding_info = assq_no_quit (make_number (scriptcode),
7049 text_encoding_info_alist);
7050 if (NILP (text_encoding_info))
7051 text_encoding_info = assq_no_quit (make_number (smRoman),
7052 text_encoding_info_alist);
7053 decode_mac_font_name (name, sizeof (name),
7054 XCAR (XCDR (text_encoding_info)));
7055 family = build_string (name);
7056 if (!NILP (Fassoc (family, fm_font_family_alist)))
7057 continue;
7058 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
7059 fm_font_family_alist);
7062 HLock (font_handle);
7064 if (GetResourceSizeOnDisk (font_handle)
7065 >= sizeof (struct FamRec))
7067 fat = (struct FontAssoc *) (*font_handle
7068 + sizeof (struct FamRec));
7069 assc_entry
7070 = (struct AsscEntry *) (*font_handle
7071 + sizeof (struct FamRec)
7072 + sizeof (struct FontAssoc));
7074 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
7076 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7078 for (; !NILP (rest); rest = XCDR (rest))
7079 add_mac_font_name (name, assc_entry->fontSize,
7080 assc_entry->fontStyle,
7081 SDATA (XCAR (rest)));
7085 HUnlock (font_handle);
7086 font_handle_2 = GetNextFOND (font_handle);
7087 ReleaseResource (font_handle);
7088 font_handle = font_handle_2;
7090 while (ResError () == noErr && font_handle);
7093 UNGCPRO;
7095 TextFont (old_fontnum);
7096 #endif /* !TARGET_API_MAC_CARBON */
7100 void
7101 mac_clear_font_name_table ()
7103 int i;
7105 for (i = 0; i < font_name_count; i++)
7106 xfree (font_name_table[i]);
7107 xfree (font_name_table);
7108 font_name_table = NULL;
7109 font_name_table_size = font_name_count = 0;
7110 fm_font_family_alist = Qnil;
7114 enum xlfd_scalable_field_index
7116 XLFD_SCL_PIXEL_SIZE,
7117 XLFD_SCL_POINT_SIZE,
7118 XLFD_SCL_AVGWIDTH,
7119 XLFD_SCL_LAST
7122 static const int xlfd_scalable_fields[] =
7124 6, /* PIXEL_SIZE */
7125 7, /* POINT_SIZE */
7126 11, /* AVGWIDTH */
7130 static Lisp_Object
7131 mac_do_list_fonts (pattern, maxnames)
7132 const char *pattern;
7133 int maxnames;
7135 int i, n_fonts = 0;
7136 Lisp_Object font_list = Qnil;
7137 struct xlfdpat *pat;
7138 char *scaled;
7139 const char *ptr;
7140 int scl_val[XLFD_SCL_LAST], *val;
7141 const int *field;
7142 int exact;
7144 if (font_name_table == NULL) /* Initialize when first used. */
7145 init_font_name_table ();
7147 for (i = 0; i < XLFD_SCL_LAST; i++)
7148 scl_val[i] = -1;
7150 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7151 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7152 fonts are scaled according to the specified size. */
7153 ptr = pattern;
7154 i = 0;
7155 field = xlfd_scalable_fields;
7156 val = scl_val;
7157 if (*ptr == '-')
7160 ptr++;
7161 if (i == *field)
7163 if ('0' <= *ptr && *ptr <= '9')
7165 *val = *ptr++ - '0';
7166 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
7167 *val = *val * 10 + *ptr++ - '0';
7168 if (*ptr != '-')
7169 *val = -1;
7171 field++;
7172 val++;
7174 ptr = strchr (ptr, '-');
7175 i++;
7177 while (ptr && i < 14);
7179 if (i == 14 && ptr == NULL)
7181 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
7182 scl_val[XLFD_SCL_PIXEL_SIZE] =
7183 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
7184 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
7185 : -1));
7186 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
7187 scl_val[XLFD_SCL_POINT_SIZE] =
7188 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7189 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
7190 : -1));
7191 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
7192 scl_val[XLFD_SCL_AVGWIDTH] =
7193 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7194 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
7195 : -1));
7197 else
7198 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
7200 pat = xlfdpat_create (pattern);
7201 if (pat == NULL)
7202 return Qnil;
7204 exact = xlfdpat_exact_p (pat);
7206 for (i = 0; i < font_name_count; i++)
7208 if (xlfdpat_match (pat, font_name_table[i]))
7210 font_list = Fcons (build_string (font_name_table[i]), font_list);
7211 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7212 break;
7214 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
7215 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
7217 int former_len = ptr - font_name_table[i];
7219 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
7220 memcpy (scaled, font_name_table[i], former_len);
7221 sprintf (scaled + former_len,
7222 "-%d-%d-72-72-m-%d-%s",
7223 scl_val[XLFD_SCL_PIXEL_SIZE],
7224 scl_val[XLFD_SCL_POINT_SIZE],
7225 scl_val[XLFD_SCL_AVGWIDTH],
7226 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
7228 if (xlfdpat_match (pat, scaled))
7230 font_list = Fcons (build_string (scaled), font_list);
7231 xfree (scaled);
7232 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7233 break;
7235 else
7236 xfree (scaled);
7240 xlfdpat_destroy (pat);
7242 return font_list;
7245 /* Return a list of names of available fonts matching PATTERN on frame F.
7247 Frame F null means we have not yet created any frame on Mac, and
7248 consult the first display in x_display_list. MAXNAMES sets a limit
7249 on how many fonts to match. */
7251 Lisp_Object
7252 x_list_fonts (f, pattern, size, maxnames)
7253 struct frame *f;
7254 Lisp_Object pattern;
7255 int size, maxnames;
7257 Lisp_Object list = Qnil, patterns, tem, key;
7258 struct mac_display_info *dpyinfo
7259 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
7261 xassert (size <= 0);
7263 patterns = Fassoc (pattern, Valternate_fontname_alist);
7264 if (NILP (patterns))
7265 patterns = Fcons (pattern, Qnil);
7267 for (; CONSP (patterns); patterns = XCDR (patterns))
7269 pattern = XCAR (patterns);
7271 if (!STRINGP (pattern))
7272 continue;
7274 tem = XCAR (XCDR (dpyinfo->name_list_element));
7275 key = Fcons (pattern, make_number (maxnames));
7277 list = Fassoc (key, tem);
7278 if (!NILP (list))
7280 list = Fcdr_safe (list);
7281 /* We have a cashed list. Don't have to get the list again. */
7282 goto label_cached;
7285 BLOCK_INPUT;
7286 list = mac_do_list_fonts (SDATA (pattern), maxnames);
7287 UNBLOCK_INPUT;
7289 /* MAC_TODO: add code for matching outline fonts here */
7291 /* Now store the result in the cache. */
7292 XSETCAR (XCDR (dpyinfo->name_list_element),
7293 Fcons (Fcons (key, list),
7294 XCAR (XCDR (dpyinfo->name_list_element))));
7296 label_cached:
7297 if (NILP (list)) continue; /* Try the remaining alternatives. */
7300 return list;
7304 #if GLYPH_DEBUG
7306 /* Check that FONT is valid on frame F. It is if it can be found in F's
7307 font table. */
7309 static void
7310 x_check_font (f, font)
7311 struct frame *f;
7312 XFontStruct *font;
7314 int i;
7315 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7317 xassert (font != NULL);
7319 for (i = 0; i < dpyinfo->n_fonts; i++)
7320 if (dpyinfo->font_table[i].name
7321 && font == dpyinfo->font_table[i].font)
7322 break;
7324 xassert (i < dpyinfo->n_fonts);
7327 #endif /* GLYPH_DEBUG != 0 */
7329 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7330 Note: There are (broken) X fonts out there with invalid XFontStruct
7331 min_bounds contents. For example, handa@etl.go.jp reports that
7332 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7333 have font->min_bounds.width == 0. */
7335 static INLINE void
7336 x_font_min_bounds (font, w, h)
7337 MacFontStruct *font;
7338 int *w, *h;
7340 *h = FONT_HEIGHT (font);
7341 *w = font->min_bounds.width;
7345 /* Compute the smallest character width and smallest font height over
7346 all fonts available on frame F. Set the members smallest_char_width
7347 and smallest_font_height in F's x_display_info structure to
7348 the values computed. Value is non-zero if smallest_font_height or
7349 smallest_char_width become smaller than they were before. */
7351 static int
7352 x_compute_min_glyph_bounds (f)
7353 struct frame *f;
7355 int i;
7356 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7357 MacFontStruct *font;
7358 int old_width = dpyinfo->smallest_char_width;
7359 int old_height = dpyinfo->smallest_font_height;
7361 dpyinfo->smallest_font_height = 100000;
7362 dpyinfo->smallest_char_width = 100000;
7364 for (i = 0; i < dpyinfo->n_fonts; ++i)
7365 if (dpyinfo->font_table[i].name)
7367 struct font_info *fontp = dpyinfo->font_table + i;
7368 int w, h;
7370 font = (MacFontStruct *) fontp->font;
7371 xassert (font != (MacFontStruct *) ~0);
7372 x_font_min_bounds (font, &w, &h);
7374 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
7375 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
7378 xassert (dpyinfo->smallest_char_width > 0
7379 && dpyinfo->smallest_font_height > 0);
7381 return (dpyinfo->n_fonts == 1
7382 || dpyinfo->smallest_char_width < old_width
7383 || dpyinfo->smallest_font_height < old_height);
7387 /* Determine whether given string is a fully-specified XLFD: all 14
7388 fields are present, none is '*'. */
7390 static int
7391 is_fully_specified_xlfd (p)
7392 const char *p;
7394 int i;
7395 char *q;
7397 if (*p != '-')
7398 return 0;
7400 for (i = 0; i < 13; i++)
7402 q = strchr (p + 1, '-');
7403 if (q == NULL)
7404 return 0;
7405 if (q - p == 2 && *(p + 1) == '*')
7406 return 0;
7407 p = q;
7410 if (strchr (p + 1, '-') != NULL)
7411 return 0;
7413 if (*(p + 1) == '*' && *(p + 2) == '\0')
7414 return 0;
7416 return 1;
7420 /* mac_load_query_font creates and returns an internal representation
7421 for a font in a MacFontStruct struct. There is really no concept
7422 corresponding to "loading" a font on the Mac. But we check its
7423 existence and find the font number and all other information for it
7424 and store them in the returned MacFontStruct. */
7426 static MacFontStruct *
7427 mac_load_query_font (f, fontname)
7428 struct frame *f;
7429 char *fontname;
7431 int size;
7432 char *name;
7433 Str255 family;
7434 Str31 charset;
7435 SInt16 fontnum;
7436 #if USE_ATSUI
7437 static ATSUFontID font_id;
7438 ATSUStyle mac_style = NULL;
7439 #endif
7440 Style fontface;
7441 #if TARGET_API_MAC_CARBON
7442 TextEncoding encoding;
7443 int scriptcode;
7444 #else
7445 short scriptcode;
7446 #endif
7447 MacFontStruct *font;
7448 XCharStruct *space_bounds = NULL, *pcm;
7450 if (is_fully_specified_xlfd (fontname))
7451 name = fontname;
7452 else
7454 Lisp_Object matched_fonts;
7456 matched_fonts = mac_do_list_fonts (fontname, 1);
7457 if (NILP (matched_fonts))
7458 return NULL;
7459 name = SDATA (XCAR (matched_fonts));
7462 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
7463 return NULL;
7465 #if USE_ATSUI
7466 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
7468 OSStatus err;
7469 static const ATSUAttributeTag tags[] =
7470 {kATSUFontTag, kATSUSizeTag,
7471 kATSUQDBoldfaceTag, kATSUQDItalicTag};
7472 static const ByteCount sizes[] =
7473 {sizeof (ATSUFontID), sizeof (Fixed),
7474 sizeof (Boolean), sizeof (Boolean)};
7475 static Fixed size_fixed;
7476 static Boolean bold_p, italic_p;
7477 static const ATSUAttributeValuePtr values[] =
7478 {&font_id, &size_fixed,
7479 &bold_p, &italic_p};
7480 static const ATSUFontFeatureType types[] =
7481 {kAllTypographicFeaturesType, kDiacriticsType};
7482 static const ATSUFontFeatureSelector selectors[] =
7483 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
7484 FMFontStyle style;
7486 font_id = atsu_find_font_from_family_name (family);
7487 if (font_id == kATSUInvalidFontID)
7488 return NULL;
7489 size_fixed = Long2Fix (size);
7490 bold_p = (fontface & bold) != 0;
7491 italic_p = (fontface & italic) != 0;
7492 err = ATSUCreateStyle (&mac_style);
7493 if (err != noErr)
7494 return NULL;
7495 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
7496 types, selectors);
7497 if (err != noErr)
7498 return NULL;
7499 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
7500 tags, sizes, values);
7501 if (err != noErr)
7502 return NULL;
7503 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
7504 if (err != noErr)
7505 fontnum = -1;
7506 scriptcode = kTextEncodingMacUnicode;
7508 else
7509 #endif
7511 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
7513 if (NILP (tmp))
7514 return NULL;
7515 fontnum = XINT (XCDR (tmp));
7516 #if TARGET_API_MAC_CARBON
7517 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
7518 return NULL;
7519 scriptcode = GetTextEncodingBase (encoding);
7520 #else
7521 scriptcode = FontToScript (fontnum);
7522 #endif
7525 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
7527 font->mac_fontnum = fontnum;
7528 font->mac_fontsize = size;
7529 font->mac_fontface = fontface;
7530 font->mac_scriptcode = scriptcode;
7531 #if USE_ATSUI
7532 font->mac_style = mac_style;
7533 #if USE_CG_TEXT_DRAWING
7534 font->cg_font = NULL;
7535 font->cg_glyphs = NULL;
7536 #endif
7537 #endif
7539 /* Apple Japanese (SJIS) font is listed as both
7540 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7541 (Roman script) in init_font_name_table (). The latter should be
7542 treated as a one-byte font. */
7543 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
7544 font->mac_scriptcode = smRoman;
7546 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
7548 #if USE_ATSUI
7549 if (font->mac_style)
7551 OSStatus err;
7552 UniChar c;
7554 font->min_byte1 = 0;
7555 font->max_byte1 = 0xff;
7556 font->min_char_or_byte2 = 0;
7557 font->max_char_or_byte2 = 0xff;
7559 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
7560 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
7561 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
7562 pcm_init (font->bounds.rows[0], 0x100);
7564 #if USE_CG_TEXT_DRAWING
7565 if (fontnum != -1)
7567 FMFontStyle style;
7568 ATSFontRef ats_font;
7570 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
7571 &font_id, &style);
7572 /* Use CG text drawing if italic/bold is not synthesized. */
7573 if (err == noErr && style == fontface)
7575 ats_font = FMGetATSFontRefFromFont (font_id);
7576 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
7580 if (font->cg_font)
7582 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
7583 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
7585 #endif
7586 space_bounds = font->bounds.rows[0] + 0x20;
7587 err = mac_query_char_extents (font->mac_style, 0x20,
7588 &font->ascent, &font->descent,
7589 space_bounds,
7590 #if USE_CG_TEXT_DRAWING
7591 (font->cg_glyphs ? font->cg_glyphs + 0x20
7592 : NULL)
7593 #else
7594 NULL
7595 #endif
7597 if (err != noErr
7598 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
7600 mac_unload_font (&one_mac_display_info, font);
7601 return NULL;
7604 pcm = font->bounds.rows[0];
7605 for (c = 0x21; c <= 0xff; c++)
7607 if (c == 0xad)
7608 /* Soft hyphen is not supported in ATSUI. */
7609 continue;
7610 else if (c == 0x7f)
7612 #if USE_CG_TEXT_DRAWING
7613 if (font->cg_glyphs)
7615 c = 0x9f;
7616 pcm = NULL;
7617 continue;
7619 #endif
7620 break;
7623 mac_query_char_extents (font->mac_style, c, NULL, NULL,
7624 pcm ? pcm + c : NULL,
7625 #if USE_CG_TEXT_DRAWING
7626 (font->cg_glyphs ? font->cg_glyphs + c
7627 : NULL)
7628 #else
7629 NULL
7630 #endif
7633 #if USE_CG_TEXT_DRAWING
7634 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
7636 /* Don't use CG text drawing if font substitution occurs in
7637 ASCII or Latin-1 characters. */
7638 CGFontRelease (font->cg_font);
7639 font->cg_font = NULL;
7640 xfree (font->cg_glyphs);
7641 font->cg_glyphs = NULL;
7642 if (pcm == NULL)
7643 break;
7645 #endif
7648 else
7649 #endif
7651 OSStatus err;
7652 FontInfo the_fontinfo;
7653 int is_two_byte_font;
7655 mac_begin_clip (f, NULL);
7657 TextFont (fontnum);
7658 TextSize (size);
7659 TextFace (fontface);
7661 GetFontInfo (&the_fontinfo);
7663 font->ascent = the_fontinfo.ascent;
7664 font->descent = the_fontinfo.descent;
7666 is_two_byte_font = (font->mac_scriptcode == smJapanese
7667 || font->mac_scriptcode == smTradChinese
7668 || font->mac_scriptcode == smSimpChinese
7669 || font->mac_scriptcode == smKorean);
7671 if (is_two_byte_font)
7673 int char_width;
7675 font->min_byte1 = 0xa1;
7676 font->max_byte1 = 0xfe;
7677 font->min_char_or_byte2 = 0xa1;
7678 font->max_char_or_byte2 = 0xfe;
7680 /* Use the width of an "ideographic space" of that font
7681 because the_fontinfo.widMax returns the wrong width for
7682 some fonts. */
7683 switch (font->mac_scriptcode)
7685 case smJapanese:
7686 font->min_byte1 = 0x81;
7687 font->max_byte1 = 0xfc;
7688 font->min_char_or_byte2 = 0x40;
7689 font->max_char_or_byte2 = 0xfc;
7690 char_width = StringWidth("\p\x81\x40");
7691 break;
7692 case smTradChinese:
7693 font->min_char_or_byte2 = 0x40;
7694 char_width = StringWidth("\p\xa1\x40");
7695 break;
7696 case smSimpChinese:
7697 char_width = StringWidth("\p\xa1\xa1");
7698 break;
7699 case smKorean:
7700 char_width = StringWidth("\p\xa1\xa1");
7701 break;
7704 font->bounds.per_char = NULL;
7706 if (fontface & italic)
7707 font->max_bounds.rbearing = char_width + 1;
7708 else
7709 font->max_bounds.rbearing = char_width;
7710 font->max_bounds.lbearing = 0;
7711 font->max_bounds.width = char_width;
7712 font->max_bounds.ascent = the_fontinfo.ascent;
7713 font->max_bounds.descent = the_fontinfo.descent;
7715 font->min_bounds = font->max_bounds;
7717 else
7719 int c;
7721 font->min_byte1 = font->max_byte1 = 0;
7722 font->min_char_or_byte2 = 0x20;
7723 font->max_char_or_byte2 = 0xff;
7725 font->bounds.per_char =
7726 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
7727 bzero (font->bounds.per_char,
7728 sizeof (XCharStruct) * (0xff - 0x20 + 1));
7730 space_bounds = font->bounds.per_char;
7731 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
7732 &font->descent, space_bounds, NULL);
7733 if (err != noErr || space_bounds->width <= 0)
7735 mac_unload_font (&one_mac_display_info, font);
7736 return NULL;
7739 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
7740 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
7743 mac_end_clip (f, NULL);
7746 if (space_bounds)
7748 int c;
7750 font->min_bounds = font->max_bounds = *space_bounds;
7751 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
7752 if (pcm->width > 0)
7754 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
7755 pcm->lbearing);
7756 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
7757 pcm->rbearing);
7758 font->min_bounds.width = min (font->min_bounds.width,
7759 pcm->width);
7760 font->min_bounds.ascent = min (font->min_bounds.ascent,
7761 pcm->ascent);
7762 font->min_bounds.descent = min (font->min_bounds.descent,
7763 pcm->descent);
7765 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
7766 pcm->lbearing);
7767 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
7768 pcm->rbearing);
7769 font->max_bounds.width = max (font->max_bounds.width,
7770 pcm->width);
7771 font->max_bounds.ascent = max (font->max_bounds.ascent,
7772 pcm->ascent);
7773 font->max_bounds.descent = max (font->max_bounds.descent,
7774 pcm->descent);
7776 if (
7777 #if USE_ATSUI
7778 font->mac_style == NULL &&
7779 #endif
7780 font->max_bounds.width == font->min_bounds.width
7781 && font->min_bounds.lbearing >= 0
7782 && font->max_bounds.rbearing <= font->max_bounds.width)
7784 /* Fixed width and no overhangs. */
7785 xfree (font->bounds.per_char);
7786 font->bounds.per_char = NULL;
7790 #if !defined (MAC_OS8) || USE_ATSUI
7791 /* AppKit and WebKit do some adjustment to the heights of Courier,
7792 Helvetica, and Times. This only works on the environments where
7793 srcCopy text transfer mode is never used. */
7794 if (
7795 #ifdef MAC_OS8 /* implies USE_ATSUI */
7796 font->mac_style &&
7797 #endif
7798 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
7799 || strcmp (family, "times") == 0))
7800 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
7801 #endif
7803 return font;
7807 void
7808 mac_unload_font (dpyinfo, font)
7809 struct mac_display_info *dpyinfo;
7810 XFontStruct *font;
7812 xfree (font->full_name);
7813 #if USE_ATSUI
7814 if (font->mac_style)
7816 int i;
7818 for (i = font->min_byte1; i <= font->max_byte1; i++)
7819 if (font->bounds.rows[i])
7820 xfree (font->bounds.rows[i]);
7821 xfree (font->bounds.rows);
7822 ATSUDisposeStyle (font->mac_style);
7824 else
7825 #endif
7826 if (font->bounds.per_char)
7827 xfree (font->bounds.per_char);
7828 #if USE_CG_TEXT_DRAWING
7829 if (font->cg_font)
7830 CGFontRelease (font->cg_font);
7831 if (font->cg_glyphs)
7832 xfree (font->cg_glyphs);
7833 #endif
7834 xfree (font);
7838 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7839 pointer to the structure font_info while allocating it dynamically.
7840 If SIZE is 0, load any size of font.
7841 If loading is failed, return NULL. */
7843 struct font_info *
7844 x_load_font (f, fontname, size)
7845 struct frame *f;
7846 register char *fontname;
7847 int size;
7849 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7850 Lisp_Object font_names;
7852 /* Get a list of all the fonts that match this name. Once we
7853 have a list of matching fonts, we compare them against the fonts
7854 we already have by comparing names. */
7855 font_names = x_list_fonts (f, build_string (fontname), size, 1);
7857 if (!NILP (font_names))
7859 Lisp_Object tail;
7860 int i;
7862 for (i = 0; i < dpyinfo->n_fonts; i++)
7863 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
7864 if (dpyinfo->font_table[i].name
7865 && (!strcmp (dpyinfo->font_table[i].name,
7866 SDATA (XCAR (tail)))
7867 || !strcmp (dpyinfo->font_table[i].full_name,
7868 SDATA (XCAR (tail)))))
7869 return (dpyinfo->font_table + i);
7871 else
7872 return NULL;
7874 /* Load the font and add it to the table. */
7876 struct MacFontStruct *font;
7877 struct font_info *fontp;
7878 int i;
7880 fontname = (char *) SDATA (XCAR (font_names));
7882 BLOCK_INPUT;
7883 font = mac_load_query_font (f, fontname);
7884 UNBLOCK_INPUT;
7885 if (!font)
7886 return NULL;
7888 /* Find a free slot in the font table. */
7889 for (i = 0; i < dpyinfo->n_fonts; ++i)
7890 if (dpyinfo->font_table[i].name == NULL)
7891 break;
7893 /* If no free slot found, maybe enlarge the font table. */
7894 if (i == dpyinfo->n_fonts
7895 && dpyinfo->n_fonts == dpyinfo->font_table_size)
7897 int sz;
7898 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
7899 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
7900 dpyinfo->font_table
7901 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
7904 fontp = dpyinfo->font_table + i;
7905 if (i == dpyinfo->n_fonts)
7906 ++dpyinfo->n_fonts;
7908 /* Now fill in the slots of *FONTP. */
7909 BLOCK_INPUT;
7910 bzero (fontp, sizeof (*fontp));
7911 fontp->font = font;
7912 fontp->font_idx = i;
7913 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
7914 bcopy (fontname, fontp->name, strlen (fontname) + 1);
7916 if (font->min_bounds.width == font->max_bounds.width)
7918 /* Fixed width font. */
7919 fontp->average_width = fontp->space_width = font->min_bounds.width;
7921 else
7923 XChar2b char2b;
7924 XCharStruct *pcm;
7926 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
7927 pcm = mac_per_char_metric (font, &char2b, 0);
7928 if (pcm)
7929 fontp->space_width = pcm->width;
7930 else
7931 fontp->space_width = FONT_WIDTH (font);
7933 if (pcm)
7935 int width = pcm->width;
7936 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
7937 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
7938 width += pcm->width;
7939 fontp->average_width = width / 95;
7941 else
7942 fontp->average_width = FONT_WIDTH (font);
7945 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
7946 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
7948 fontp->size = font->max_bounds.width;
7949 fontp->height = FONT_HEIGHT (font);
7951 /* For some font, ascent and descent in max_bounds field is
7952 larger than the above value. */
7953 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
7954 if (max_height > fontp->height)
7955 fontp->height = max_height;
7958 /* The slot `encoding' specifies how to map a character
7959 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7960 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7961 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7962 2:0xA020..0xFF7F). For the moment, we don't know which charset
7963 uses this font. So, we set information in fontp->encoding[1]
7964 which is never used by any charset. If mapping can't be
7965 decided, set FONT_ENCODING_NOT_DECIDED. */
7966 if (font->mac_scriptcode == smJapanese)
7967 fontp->encoding[1] = 4;
7968 else
7970 fontp->encoding[1]
7971 = (font->max_byte1 == 0
7972 /* 1-byte font */
7973 ? (font->min_char_or_byte2 < 0x80
7974 ? (font->max_char_or_byte2 < 0x80
7975 ? 0 /* 0x20..0x7F */
7976 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
7977 : 1) /* 0xA0..0xFF */
7978 /* 2-byte font */
7979 : (font->min_byte1 < 0x80
7980 ? (font->max_byte1 < 0x80
7981 ? (font->min_char_or_byte2 < 0x80
7982 ? (font->max_char_or_byte2 < 0x80
7983 ? 0 /* 0x2020..0x7F7F */
7984 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
7985 : 3) /* 0x20A0..0x7FFF */
7986 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
7987 : (font->min_char_or_byte2 < 0x80
7988 ? (font->max_char_or_byte2 < 0x80
7989 ? 2 /* 0xA020..0xFF7F */
7990 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
7991 : 1))); /* 0xA0A0..0xFFFF */
7994 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7995 fontp->baseline_offset
7996 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
7997 ? (long) value : 0);
7998 fontp->relative_compose
7999 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
8000 ? (long) value : 0);
8001 fontp->default_ascent
8002 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
8003 ? (long) value : 0);
8004 #else
8005 fontp->baseline_offset = 0;
8006 fontp->relative_compose = 0;
8007 fontp->default_ascent = 0;
8008 #endif
8010 /* Set global flag fonts_changed_p to non-zero if the font loaded
8011 has a character with a smaller width than any other character
8012 before, or if the font loaded has a smaller height than any
8013 other font loaded before. If this happens, it will make a
8014 glyph matrix reallocation necessary. */
8015 fonts_changed_p |= x_compute_min_glyph_bounds (f);
8016 UNBLOCK_INPUT;
8017 return fontp;
8022 /* Return a pointer to struct font_info of a font named FONTNAME for
8023 frame F. If no such font is loaded, return NULL. */
8025 struct font_info *
8026 x_query_font (f, fontname)
8027 struct frame *f;
8028 register char *fontname;
8030 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8031 int i;
8033 for (i = 0; i < dpyinfo->n_fonts; i++)
8034 if (dpyinfo->font_table[i].name
8035 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
8036 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
8037 return (dpyinfo->font_table + i);
8038 return NULL;
8042 /* Find a CCL program for a font specified by FONTP, and set the member
8043 `encoder' of the structure. */
8045 void
8046 x_find_ccl_program (fontp)
8047 struct font_info *fontp;
8049 Lisp_Object list, elt;
8051 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
8053 elt = XCAR (list);
8054 if (CONSP (elt)
8055 && STRINGP (XCAR (elt))
8056 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
8057 >= 0))
8058 break;
8060 if (! NILP (list))
8062 struct ccl_program *ccl
8063 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
8065 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
8066 xfree (ccl);
8067 else
8068 fontp->font_encoder = ccl;
8073 /* The Mac Event loop code */
8075 #if !TARGET_API_MAC_CARBON
8076 #include <Events.h>
8077 #include <Quickdraw.h>
8078 #include <Balloons.h>
8079 #include <Devices.h>
8080 #include <Fonts.h>
8081 #include <Gestalt.h>
8082 #include <Menus.h>
8083 #include <Processes.h>
8084 #include <Sound.h>
8085 #include <ToolUtils.h>
8086 #include <TextUtils.h>
8087 #include <Dialogs.h>
8088 #include <Script.h>
8089 #include <Types.h>
8090 #include <Resources.h>
8092 #if __MWERKS__
8093 #include <unix.h>
8094 #endif
8095 #endif /* ! TARGET_API_MAC_CARBON */
8097 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8098 Lisp_Object Qreverse;
8101 /* Modifier associated with the control key, or nil to ignore. */
8102 Lisp_Object Vmac_control_modifier;
8104 /* Modifier associated with the option key, or nil to ignore. */
8105 Lisp_Object Vmac_option_modifier;
8107 /* Modifier associated with the command key, or nil to ignore. */
8108 Lisp_Object Vmac_command_modifier;
8110 /* Modifier associated with the function key, or nil to ignore. */
8111 Lisp_Object Vmac_function_modifier;
8113 /* True if the option and command modifiers should be used to emulate
8114 a three button mouse */
8115 Lisp_Object Vmac_emulate_three_button_mouse;
8117 #if TARGET_API_MAC_CARBON
8118 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8119 mouse-2, instead of mouse-3. */
8120 int mac_wheel_button_is_mouse_2;
8122 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8123 for processing before Emacs sees it. */
8124 int mac_pass_command_to_system;
8126 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8127 for processing before Emacs sees it. */
8128 int mac_pass_control_to_system;
8129 #endif
8131 /* Whether or not the screen configuration has changed. */
8132 int mac_screen_config_changed = 0;
8134 /* Apple Events */
8135 #if TARGET_API_MAC_CARBON
8136 Lisp_Object Qhi_command;
8137 #ifdef MAC_OSX
8138 Lisp_Object Qtoolbar_switch_mode;
8139 #endif
8140 #if USE_MAC_TSM
8141 Lisp_Object Qtext_input;
8142 Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
8143 Lisp_Object Vmac_ts_active_input_overlay;
8144 Lisp_Object Vmac_ts_script_language_on_focus;
8145 Lisp_Object saved_ts_script_language_on_focus;
8146 static ScriptLanguageRecord saved_ts_language;
8147 static Component saved_ts_component;
8148 #endif
8149 #ifdef MAC_OSX
8150 Lisp_Object Qservice, Qpaste, Qperform;
8151 #endif
8152 #endif /* TARGET_API_MAC_CARBON */
8153 extern Lisp_Object Qundefined;
8154 extern int XTread_socket P_ ((int, int, struct input_event *));
8155 extern void init_apple_event_handler P_ ((void));
8156 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
8157 Lisp_Object *, Lisp_Object *,
8158 Lisp_Object *));
8159 extern OSErr init_coercion_handler P_ ((void));
8161 /* Table for translating Mac keycode to X keysym values. Contributed
8162 by Sudhir Shenoy.
8163 Mapping for special keys is now identical to that in Apple X11
8164 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8165 on the right of the Cmd key on laptops, and fn + `enter' (->
8166 <linefeed>). */
8167 const unsigned char keycode_to_xkeysym_table[] = {
8168 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8169 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8170 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8172 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8173 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8174 /*0x38*/ 0, 0, 0, 0,
8175 /*0x3C*/ 0, 0, 0, 0,
8177 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8178 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8179 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8180 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8182 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8183 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8184 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8185 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8187 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8188 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8189 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8190 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8192 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8193 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8194 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8195 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8198 #ifdef MAC_OSX
8199 /* Table for translating Mac keycode with the laptop `fn' key to that
8200 without it. Destination symbols in comments are keys on US
8201 keyboard, and they may not be the same on other types of keyboards.
8202 If the destination is identical to the source, it doesn't map `fn'
8203 key to a modifier. */
8204 static const unsigned char fn_keycode_to_keycode_table[] = {
8205 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8206 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8207 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8209 /*0x30*/ 0, 0, 0, 0,
8210 /*0x34*/ 0, 0, 0, 0,
8211 /*0x38*/ 0, 0, 0, 0,
8212 /*0x3C*/ 0, 0, 0, 0,
8214 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8215 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8216 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8217 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
8219 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8220 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8221 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8222 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8224 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8225 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8226 /*0x68*/ 0, 0x69 /*f13 = f13*/, 0x6a /*f16 = f16*/, 0x6b /*f14 = f14*/,
8227 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8229 /*0x70*/ 0, 0x71 /*f15 = f15*/, 0x72 /*help = help*/, 0x7b /*home -> left*/,
8230 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
8231 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0x7b /*left = left*/,
8232 /*0x7C*/ 0x7c /*right = right*/, 0x7d /*down = down*/, 0x7e /*up = up*/, 0
8234 #endif /* MAC_OSX */
8237 #if TARGET_API_MAC_CARBON
8238 mac_to_emacs_modifiers (UInt32 mods, UInt32 unmapped_mods)
8239 #else
8240 mac_to_emacs_modifiers (EventModifiers mods, EventModifiers unmapped_mods)
8241 #endif
8243 unsigned int result = 0;
8244 if ((mods | unmapped_mods) & shiftKey)
8245 result |= shift_modifier;
8247 /* Deactivated to simplify configuration:
8248 if Vmac_option_modifier is non-NIL, we fully process the Option
8249 key. Otherwise, we only process it if an additional Ctrl or Command
8250 is pressed. That way the system may convert the character to a
8251 composed one.
8252 if ((mods & optionKey) &&
8253 (( !NILP(Vmac_option_modifier) ||
8254 ((mods & cmdKey) || (mods & controlKey))))) */
8256 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
8257 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
8258 if (INTEGERP(val))
8259 result |= XUINT(val);
8261 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
8262 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
8263 if (INTEGERP(val))
8264 result |= XUINT(val);
8266 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
8267 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
8268 if (INTEGERP(val))
8269 result |= XUINT(val);
8272 #ifdef MAC_OSX
8273 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
8274 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
8275 if (INTEGERP(val))
8276 result |= XUINT(val);
8278 #endif
8280 return result;
8283 UInt32
8284 mac_mapped_modifiers (modifiers, key_code)
8285 UInt32 modifiers, key_code;
8287 UInt32 mapped_modifiers_all =
8288 (NILP (Vmac_control_modifier) ? 0 : controlKey)
8289 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
8290 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
8292 #ifdef MAC_OSX
8293 mapped_modifiers_all |=
8294 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
8296 /* The meaning of kEventKeyModifierFnMask has changed in Mac OS X
8297 10.5, and it now behaves much like Cocoa's NSFunctionKeyMask. It
8298 no longer means laptop's `fn' key is down for the following keys:
8299 F1, F2, and so on, Help, Forward Delete, Home, End, Page Up, Page
8300 Down, the arrow keys, and Clear. We ignore the corresponding bit
8301 if that key can be entered without the `fn' key on laptops. */
8302 if (modifiers & kEventKeyModifierFnMask
8303 && key_code <= 0x7f
8304 && fn_keycode_to_keycode_table[key_code] == key_code)
8305 modifiers &= ~kEventKeyModifierFnMask;
8306 #endif
8308 return mapped_modifiers_all & modifiers;
8312 mac_get_emulated_btn ( UInt32 modifiers )
8314 int result = 0;
8315 if (!NILP (Vmac_emulate_three_button_mouse)) {
8316 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
8317 if (modifiers & cmdKey)
8318 result = cmdIs3 ? 2 : 1;
8319 else if (modifiers & optionKey)
8320 result = cmdIs3 ? 1 : 2;
8322 return result;
8325 #if USE_MAC_TSM
8326 OSStatus
8327 mac_restore_keyboard_input_source ()
8329 OSStatus err = noErr;
8330 ScriptLanguageRecord slrec, *slptr = NULL;
8332 if (EQ (Vmac_ts_script_language_on_focus, Qt)
8333 && EQ (saved_ts_script_language_on_focus, Qt))
8334 slptr = &saved_ts_language;
8335 else if (CONSP (Vmac_ts_script_language_on_focus)
8336 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
8337 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
8338 && CONSP (saved_ts_script_language_on_focus)
8339 && EQ (XCAR (saved_ts_script_language_on_focus),
8340 XCAR (Vmac_ts_script_language_on_focus))
8341 && EQ (XCDR (saved_ts_script_language_on_focus),
8342 XCDR (Vmac_ts_script_language_on_focus)))
8344 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
8345 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
8346 slptr = &slrec;
8349 if (slptr)
8351 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8352 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
8353 kKeyboardInputMethodClass);
8354 #else
8355 err = SetDefaultInputMethod (saved_ts_component, slptr);
8356 #endif
8357 if (err == noErr)
8358 err = SetTextServiceLanguage (slptr);
8360 /* Seems to be needed on Mac OS X 10.2. */
8361 if (err == noErr)
8362 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
8365 return err;
8368 void
8369 mac_save_keyboard_input_source ()
8371 OSStatus err;
8372 ScriptLanguageRecord slrec, *slptr = NULL;
8374 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
8376 if (EQ (Vmac_ts_script_language_on_focus, Qt))
8378 err = GetTextServiceLanguage (&saved_ts_language);
8379 if (err == noErr)
8380 slptr = &saved_ts_language;
8382 else if (CONSP (Vmac_ts_script_language_on_focus)
8383 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
8384 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
8386 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
8387 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
8388 slptr = &slrec;
8391 if (slptr)
8393 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8394 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
8395 kKeyboardInputMethodClass);
8396 #else
8397 GetDefaultInputMethod (&saved_ts_component, slptr);
8398 #endif
8401 #endif
8403 #if TARGET_API_MAC_CARBON
8404 /***** Code to handle C-g testing *****/
8405 extern int quit_char;
8406 extern int make_ctrl_char P_ ((int));
8409 mac_quit_char_key_p (modifiers, key_code)
8410 UInt32 modifiers, key_code;
8412 UInt32 char_code, mapped_modifiers;
8413 unsigned long some_state = 0;
8414 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8415 int c, emacs_modifiers;
8417 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
8418 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
8419 key_code |= (modifiers & ~mapped_modifiers);
8420 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
8421 if (char_code & ~0xff)
8422 return 0;
8424 emacs_modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
8425 if (emacs_modifiers & ctrl_modifier)
8426 c = make_ctrl_char (char_code);
8428 c |= (emacs_modifiers
8429 & (meta_modifier | alt_modifier
8430 | hyper_modifier | super_modifier));
8432 return c == quit_char;
8434 #endif
8436 static void
8437 mac_set_unicode_keystroke_event (code, buf)
8438 UniChar code;
8439 struct input_event *buf;
8441 int charset_id, c1, c2;
8443 if (code < 0x80)
8445 buf->kind = ASCII_KEYSTROKE_EVENT;
8446 buf->code = code;
8448 else if (code < 0x100)
8450 if (code < 0xA0)
8451 charset_id = CHARSET_8_BIT_CONTROL;
8452 else
8453 charset_id = charset_latin_iso8859_1;
8454 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8455 buf->code = MAKE_CHAR (charset_id, code, 0);
8457 else
8459 if (code < 0x2500)
8460 charset_id = charset_mule_unicode_0100_24ff,
8461 code -= 0x100;
8462 else if (code < 0x33FF)
8463 charset_id = charset_mule_unicode_2500_33ff,
8464 code -= 0x2500;
8465 else if (code >= 0xE000)
8466 charset_id = charset_mule_unicode_e000_ffff,
8467 code -= 0xE000;
8468 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
8469 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8470 buf->code = MAKE_CHAR (charset_id, c1, c2);
8474 void
8475 do_keystroke (action, char_code, key_code, modifiers, timestamp, buf)
8476 EventKind action;
8477 unsigned char char_code;
8478 UInt32 key_code, modifiers;
8479 unsigned long timestamp;
8480 struct input_event *buf;
8482 static SInt16 last_key_script = -1;
8483 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
8484 UInt32 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
8486 #ifdef MAC_OSX
8487 if (mapped_modifiers & kEventKeyModifierFnMask
8488 && key_code <= 0x7f
8489 && fn_keycode_to_keycode_table[key_code])
8490 key_code = fn_keycode_to_keycode_table[key_code];
8491 #endif
8493 if (key_code <= 0x7f && keycode_to_xkeysym_table[key_code])
8495 buf->kind = NON_ASCII_KEYSTROKE_EVENT;
8496 buf->code = 0xff00 | keycode_to_xkeysym_table[key_code];
8498 else if (mapped_modifiers)
8500 /* translate the keycode back to determine the original key */
8501 #ifdef MAC_OSX
8502 UCKeyboardLayout *uchr_ptr = NULL;
8503 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8504 OSStatus err;
8505 KeyboardLayoutRef layout;
8507 err = KLGetCurrentKeyboardLayout (&layout);
8508 if (err == noErr)
8509 err = KLGetKeyboardLayoutProperty (layout, kKLuchrData,
8510 (const void **) &uchr_ptr);
8511 #else
8512 static SInt16 last_key_layout_id = 0;
8513 static Handle uchr_handle = (Handle)-1;
8514 SInt16 current_key_layout_id =
8515 GetScriptVariable (current_key_script, smScriptKeys);
8517 if (uchr_handle == (Handle)-1
8518 || last_key_layout_id != current_key_layout_id)
8520 uchr_handle = GetResource ('uchr', current_key_layout_id);
8521 last_key_layout_id = current_key_layout_id;
8523 if (uchr_handle)
8524 uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
8525 #endif
8527 if (uchr_ptr)
8529 OSStatus status;
8530 UInt16 key_action = action - keyDown;
8531 UInt32 modifier_key_state = (modifiers & ~mapped_modifiers) >> 8;
8532 UInt32 keyboard_type = LMGetKbdType ();
8533 SInt32 dead_key_state = 0;
8534 UniChar code;
8535 UniCharCount actual_length;
8537 status = UCKeyTranslate (uchr_ptr, key_code, key_action,
8538 modifier_key_state, keyboard_type,
8539 kUCKeyTranslateNoDeadKeysMask,
8540 &dead_key_state,
8541 1, &actual_length, &code);
8542 if (status == noErr && actual_length == 1)
8543 mac_set_unicode_keystroke_event (code, buf);
8545 #endif /* MAC_OSX */
8547 if (buf->kind == NO_EVENT)
8549 /* This code comes from Keyboard Resource, Appendix C of IM
8550 - Text. This is necessary since shift is ignored in KCHR
8551 table translation when option or command is pressed. It
8552 also does not translate correctly control-shift chars
8553 like C-% so mask off shift here also. */
8554 /* Mask off modifier keys that are mapped to some Emacs
8555 modifiers. */
8556 int new_modifiers = modifiers & ~mapped_modifiers;
8557 /* set high byte of keycode to modifier high byte*/
8558 int new_key_code = key_code | new_modifiers;
8559 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8560 unsigned long some_state = 0;
8561 UInt32 new_char_code;
8563 new_char_code = KeyTranslate (kchr_ptr, new_key_code, &some_state);
8564 if (new_char_code == 0)
8565 /* Seems like a dead key. Append up-stroke. */
8566 new_char_code = KeyTranslate (kchr_ptr, new_key_code | 0x80,
8567 &some_state);
8568 if (new_char_code)
8570 buf->kind = ASCII_KEYSTROKE_EVENT;
8571 buf->code = new_char_code & 0xff;
8576 if (buf->kind == NO_EVENT)
8578 buf->kind = ASCII_KEYSTROKE_EVENT;
8579 buf->code = char_code;
8582 buf->modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
8583 buf->modifiers |= (extra_keyboard_modifiers
8584 & (meta_modifier | alt_modifier
8585 | hyper_modifier | super_modifier));
8587 #if TARGET_API_MAC_CARBON
8588 if (buf->kind == ASCII_KEYSTROKE_EVENT
8589 && buf->code >= 0x80 && buf->modifiers)
8591 OSStatus err;
8592 TextEncoding encoding = kTextEncodingMacRoman;
8593 TextToUnicodeInfo ttu_info;
8595 UpgradeScriptInfoToTextEncoding (current_key_script,
8596 kTextLanguageDontCare,
8597 kTextRegionDontCare,
8598 NULL, &encoding);
8599 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
8600 if (err == noErr)
8602 UniChar code;
8603 Str255 pstr;
8604 ByteCount unicode_len;
8606 pstr[0] = 1;
8607 pstr[1] = buf->code;
8608 err = ConvertFromPStringToUnicode (ttu_info, pstr,
8609 sizeof (UniChar),
8610 &unicode_len, &code);
8611 if (err == noErr && unicode_len == sizeof (UniChar))
8612 mac_set_unicode_keystroke_event (code, buf);
8613 DisposeTextToUnicodeInfo (&ttu_info);
8616 #endif
8618 if (buf->kind == ASCII_KEYSTROKE_EVENT
8619 && buf->code >= 0x80
8620 && last_key_script != current_key_script)
8622 struct input_event event;
8624 EVENT_INIT (event);
8625 event.kind = LANGUAGE_CHANGE_EVENT;
8626 event.arg = Qnil;
8627 event.code = current_key_script;
8628 event.timestamp = timestamp;
8629 kbd_buffer_store_event (&event);
8630 last_key_script = current_key_script;
8634 void
8635 mac_store_apple_event (class, id, desc)
8636 Lisp_Object class, id;
8637 const AEDesc *desc;
8639 struct input_event buf;
8641 EVENT_INIT (buf);
8643 buf.kind = MAC_APPLE_EVENT;
8644 buf.x = class;
8645 buf.y = id;
8646 XSETFRAME (buf.frame_or_window,
8647 mac_focus_frame (&one_mac_display_info));
8648 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
8649 is safe to use them during read_socket_hook. */
8650 buf.arg = mac_aedesc_to_lisp (desc);
8651 kbd_buffer_store_event (&buf);
8654 #if TARGET_API_MAC_CARBON
8655 OSStatus
8656 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
8657 event, num_params, names, types)
8658 AEEventClass class;
8659 AEEventID id;
8660 Lisp_Object class_key, id_key;
8661 EventRef event;
8662 UInt32 num_params;
8663 const EventParamName *names;
8664 const EventParamType *types;
8666 OSStatus err = eventNotHandledErr;
8667 Lisp_Object binding;
8669 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
8670 if (!NILP (binding) && !EQ (binding, Qundefined))
8672 if (INTEGERP (binding))
8673 err = XINT (binding);
8674 else
8676 AppleEvent apple_event;
8677 err = create_apple_event_from_event_ref (event, num_params,
8678 names, types,
8679 &apple_event);
8680 if (err == noErr)
8682 mac_store_apple_event (class_key, id_key, &apple_event);
8683 AEDisposeDesc (&apple_event);
8684 mac_wakeup_from_rne ();
8689 return err;
8691 #endif /* TARGET_API_MAC_CARBON */
8693 static pascal void
8694 mac_handle_dm_notification (event)
8695 AppleEvent *event;
8697 mac_screen_config_changed = 1;
8700 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8701 static void
8702 mac_handle_cg_display_reconfig (display, flags, user_info)
8703 CGDirectDisplayID display;
8704 CGDisplayChangeSummaryFlags flags;
8705 void *user_info;
8707 mac_screen_config_changed = 1;
8709 #endif
8711 static OSErr
8712 init_dm_notification_handler ()
8714 OSErr err = noErr;
8716 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8717 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8718 if (CGDisplayRegisterReconfigurationCallback != NULL)
8719 #endif
8721 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig,
8722 NULL);
8724 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8725 else /* CGDisplayRegisterReconfigurationCallback == NULL */
8726 #endif
8727 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
8728 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8730 static DMNotificationUPP handle_dm_notificationUPP = NULL;
8731 ProcessSerialNumber psn;
8733 if (handle_dm_notificationUPP == NULL)
8734 handle_dm_notificationUPP =
8735 NewDMNotificationUPP (mac_handle_dm_notification);
8737 err = GetCurrentProcess (&psn);
8738 if (err == noErr)
8739 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
8741 #endif
8743 return err;
8746 void
8747 mac_get_screen_info (dpyinfo)
8748 struct mac_display_info *dpyinfo;
8750 #ifdef MAC_OSX
8751 /* HasDepth returns true if it is possible to have a 32 bit display,
8752 but this may not be what is actually used. Mac OSX can do better. */
8753 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
8754 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
8756 CGDisplayErr err;
8757 CGDisplayCount ndisps;
8758 CGDirectDisplayID *displays;
8760 err = CGGetActiveDisplayList (0, NULL, &ndisps);
8761 if (err == noErr)
8763 displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
8764 err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
8766 if (err == noErr)
8768 CGRect bounds = CGRectZero;
8770 while (ndisps-- > 0)
8771 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
8772 dpyinfo->height = CGRectGetHeight (bounds);
8773 dpyinfo->width = CGRectGetWidth (bounds);
8775 else
8777 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
8778 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
8781 #else /* !MAC_OSX */
8783 GDHandle gdh = GetMainDevice ();
8784 Rect rect = (**gdh).gdRect;
8786 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
8787 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
8788 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
8789 break;
8791 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
8792 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
8793 UnionRect (&rect, &(**gdh).gdRect, &rect);
8795 dpyinfo->height = rect.bottom - rect.top;
8796 dpyinfo->width = rect.right - rect.left;
8798 #endif /* !MAC_OSX */
8802 /***********************************************************************
8803 Initialization (Mac OS Classic)
8804 ***********************************************************************/
8806 #ifdef MAC_OS8
8807 extern void init_emacs_passwd_dir ();
8808 extern int emacs_main (int, char **, char **);
8810 extern void initialize_applescript();
8811 extern void terminate_applescript();
8813 static void
8814 do_get_menus (void)
8816 Handle menubar_handle;
8817 MenuRef menu;
8819 menubar_handle = GetNewMBar (128);
8820 if(menubar_handle == NULL)
8821 abort ();
8822 SetMenuBar (menubar_handle);
8823 DrawMenuBar ();
8825 #if !TARGET_API_MAC_CARBON
8826 menu = GetMenuRef (M_APPLE);
8827 if (menu != NULL)
8828 AppendResMenu (menu, 'DRVR');
8829 else
8830 abort ();
8831 #endif
8834 static void
8835 do_init_managers (void)
8837 #if !TARGET_API_MAC_CARBON
8838 InitGraf (&qd.thePort);
8839 InitFonts ();
8840 FlushEvents (everyEvent, 0);
8841 InitWindows ();
8842 InitMenus ();
8843 TEInit ();
8844 InitDialogs (NULL);
8845 #endif /* !TARGET_API_MAC_CARBON */
8846 InitCursor ();
8848 #if !TARGET_API_MAC_CARBON
8849 /* set up some extra stack space for use by emacs */
8850 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
8852 /* MaxApplZone must be called for AppleScript to execute more
8853 complicated scripts */
8854 MaxApplZone ();
8855 MoreMasters ();
8856 #endif /* !TARGET_API_MAC_CARBON */
8859 static void
8860 do_check_ram_size (void)
8862 SInt32 physical_ram_size, logical_ram_size;
8864 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
8865 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
8866 || physical_ram_size > (1 << VALBITS)
8867 || logical_ram_size > (1 << VALBITS))
8869 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
8870 exit (1);
8874 #if __profile__
8875 void
8876 profiler_exit_proc ()
8878 ProfilerDump ("\pEmacs.prof");
8879 ProfilerTerm ();
8881 #endif
8883 /* These few functions implement Emacs as a normal Mac application
8884 (almost): set up the heap and the Toolbox, handle necessary system
8885 events plus a few simple menu events. They also set up Emacs's
8886 access to functions defined in the rest of this file. Emacs uses
8887 function hooks to perform all its terminal I/O. A complete list of
8888 these functions appear in termhooks.h. For what they do, read the
8889 comments there and see also w32term.c and xterm.c. What's
8890 noticeably missing here is the event loop, which is normally
8891 present in most Mac application. After performing the necessary
8892 Mac initializations, main passes off control to emacs_main
8893 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
8894 (defined further below) to read input. This is where
8895 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
8897 #undef main
8899 main (void)
8901 #if __profile__ /* is the profiler on? */
8902 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
8903 exit(1);
8904 #endif
8906 #if __MWERKS__
8907 /* set creator and type for files created by MSL */
8908 _fcreator = MAC_EMACS_CREATOR_CODE;
8909 _ftype = 'TEXT';
8910 #endif
8912 do_init_managers ();
8914 do_get_menus ();
8916 #ifndef USE_LSB_TAG
8917 do_check_ram_size ();
8918 #endif
8920 init_emacs_passwd_dir ();
8922 init_environ ();
8924 init_coercion_handler ();
8926 initialize_applescript ();
8928 init_apple_event_handler ();
8930 init_dm_notification_handler ();
8933 char **argv;
8934 int argc = 0;
8936 /* set up argv array from STR# resource */
8937 get_string_list (&argv, ARGV_STRING_LIST_ID);
8938 while (argv[argc])
8939 argc++;
8941 /* free up AppleScript resources on exit */
8942 atexit (terminate_applescript);
8944 #if __profile__ /* is the profiler on? */
8945 atexit (profiler_exit_proc);
8946 #endif
8948 /* 3rd param "envp" never used in emacs_main */
8949 (void) emacs_main (argc, argv, 0);
8952 /* Never reached - real exit in Fkill_emacs */
8953 return 0;
8956 /* Need to override CodeWarrior's input function so no conversion is
8957 done on newlines Otherwise compiled functions in .elc files will be
8958 read incorrectly. Defined in ...:MSL C:MSL
8959 Common:Source:buffer_io.c. */
8960 #ifdef __MWERKS__
8961 void
8962 __convert_to_newlines (unsigned char * p, size_t * n)
8964 #pragma unused(p,n)
8967 void
8968 __convert_from_newlines (unsigned char * p, size_t * n)
8970 #pragma unused(p,n)
8972 #endif
8974 void
8975 make_mac_terminal_frame (struct frame *f)
8977 Lisp_Object frame;
8978 Rect r;
8980 XSETFRAME (frame, f);
8982 f->output_method = output_mac;
8983 f->output_data.mac = (struct mac_output *)
8984 xmalloc (sizeof (struct mac_output));
8985 bzero (f->output_data.mac, sizeof (struct mac_output));
8987 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
8989 FRAME_COLS (f) = 96;
8990 FRAME_LINES (f) = 4;
8992 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
8993 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
8995 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
8997 f->output_data.mac->cursor_pixel = 0;
8998 f->output_data.mac->border_pixel = 0x00ff00;
8999 f->output_data.mac->mouse_pixel = 0xff00ff;
9000 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9002 f->output_data.mac->text_cursor = kThemeIBeamCursor;
9003 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
9004 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
9005 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
9006 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
9007 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
9009 FRAME_FONTSET (f) = -1;
9010 f->output_data.mac->explicit_parent = 0;
9011 f->left_pos = 8;
9012 f->top_pos = 32;
9013 f->border_width = 0;
9015 f->internal_border_width = 0;
9017 f->auto_raise = 1;
9018 f->auto_lower = 1;
9020 f->new_text_cols = 0;
9021 f->new_text_lines = 0;
9023 SetRect (&r, f->left_pos, f->top_pos,
9024 f->left_pos + FRAME_PIXEL_WIDTH (f),
9025 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9027 BLOCK_INPUT;
9029 if (!(FRAME_MAC_WINDOW (f) =
9030 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9031 (WindowRef) -1, 1, (long) f->output_data.mac)))
9032 abort ();
9033 /* so that update events can find this mac_output struct */
9034 f->output_data.mac->mFP = f; /* point back to emacs frame */
9036 UNBLOCK_INPUT;
9038 x_make_gc (f);
9040 /* Need to be initialized for unshow_buffer in window.c. */
9041 selected_window = f->selected_window;
9043 Fmodify_frame_parameters (frame,
9044 Fcons (Fcons (Qfont,
9045 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9046 Fmodify_frame_parameters (frame,
9047 Fcons (Fcons (Qforeground_color,
9048 build_string ("black")), Qnil));
9049 Fmodify_frame_parameters (frame,
9050 Fcons (Fcons (Qbackground_color,
9051 build_string ("white")), Qnil));
9053 #endif /* MAC_OS8 */
9056 /***********************************************************************
9057 Initialization
9058 ***********************************************************************/
9060 static int mac_initialized = 0;
9062 static XrmDatabase
9063 mac_make_rdb (xrm_option)
9064 const char *xrm_option;
9066 XrmDatabase database;
9068 database = xrm_get_preference_database (NULL);
9069 if (xrm_option)
9070 xrm_merge_string_database (database, xrm_option);
9072 return database;
9075 struct mac_display_info *
9076 mac_term_init (display_name, xrm_option, resource_name)
9077 Lisp_Object display_name;
9078 char *xrm_option;
9079 char *resource_name;
9081 struct mac_display_info *dpyinfo;
9083 BLOCK_INPUT;
9085 if (!mac_initialized)
9087 mac_initialize ();
9088 mac_initialized = 1;
9091 if (x_display_list)
9092 error ("Sorry, this version can only handle one display");
9094 dpyinfo = &one_mac_display_info;
9095 bzero (dpyinfo, sizeof (*dpyinfo));
9097 #ifdef MAC_OSX
9098 dpyinfo->mac_id_name
9099 = (char *) xmalloc (SCHARS (Vinvocation_name)
9100 + SCHARS (Vsystem_name)
9101 + 2);
9102 sprintf (dpyinfo->mac_id_name, "%s@%s",
9103 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9104 #else
9105 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9106 strcpy (dpyinfo->mac_id_name, "Mac Display");
9107 #endif
9109 dpyinfo->reference_count = 0;
9110 dpyinfo->resx = 72.0;
9111 dpyinfo->resy = 72.0;
9113 mac_get_screen_info (dpyinfo);
9115 dpyinfo->grabbed = 0;
9116 dpyinfo->root_window = NULL;
9117 dpyinfo->image_cache = make_image_cache ();
9119 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9120 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9121 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9122 dpyinfo->mouse_face_window = Qnil;
9123 dpyinfo->mouse_face_overlay = Qnil;
9124 dpyinfo->mouse_face_hidden = 0;
9126 dpyinfo->xrdb = mac_make_rdb (xrm_option);
9128 /* Put this display on the chain. */
9129 dpyinfo->next = x_display_list;
9130 x_display_list = dpyinfo;
9132 /* Put it on x_display_name_list. */
9133 x_display_name_list = Fcons (Fcons (display_name,
9134 Fcons (Qnil, dpyinfo->xrdb)),
9135 x_display_name_list);
9136 dpyinfo->name_list_element = XCAR (x_display_name_list);
9138 UNBLOCK_INPUT;
9140 return dpyinfo;
9143 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9145 void
9146 x_delete_display (dpyinfo)
9147 struct mac_display_info *dpyinfo;
9149 int i;
9151 /* Discard this display from x_display_name_list and x_display_list.
9152 We can't use Fdelq because that can quit. */
9153 if (! NILP (x_display_name_list)
9154 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9155 x_display_name_list = XCDR (x_display_name_list);
9156 else
9158 Lisp_Object tail;
9160 tail = x_display_name_list;
9161 while (CONSP (tail) && CONSP (XCDR (tail)))
9163 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9165 XSETCDR (tail, XCDR (XCDR (tail)));
9166 break;
9168 tail = XCDR (tail);
9172 if (x_display_list == dpyinfo)
9173 x_display_list = dpyinfo->next;
9174 else
9176 struct x_display_info *tail;
9178 for (tail = x_display_list; tail; tail = tail->next)
9179 if (tail->next == dpyinfo)
9180 tail->next = tail->next->next;
9183 /* Free the font names in the font table. */
9184 for (i = 0; i < dpyinfo->n_fonts; i++)
9185 if (dpyinfo->font_table[i].name)
9187 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9188 xfree (dpyinfo->font_table[i].full_name);
9189 xfree (dpyinfo->font_table[i].name);
9192 if (dpyinfo->font_table)
9194 if (dpyinfo->font_table->font_encoder)
9195 xfree (dpyinfo->font_table->font_encoder);
9196 xfree (dpyinfo->font_table);
9198 if (dpyinfo->mac_id_name)
9199 xfree (dpyinfo->mac_id_name);
9201 if (x_display_list == 0)
9203 mac_clear_font_name_table ();
9204 bzero (dpyinfo, sizeof (*dpyinfo));
9209 /* Set up use of X before we make the first connection. */
9211 extern frame_parm_handler mac_frame_parm_handlers[];
9213 static struct redisplay_interface x_redisplay_interface =
9215 mac_frame_parm_handlers,
9216 x_produce_glyphs,
9217 x_write_glyphs,
9218 x_insert_glyphs,
9219 x_clear_end_of_line,
9220 x_scroll_run,
9221 x_after_update_window_line,
9222 x_update_window_begin,
9223 x_update_window_end,
9224 x_cursor_to,
9225 x_flush,
9226 #if USE_CG_DRAWING
9227 mac_flush_display_optional,
9228 #else
9229 0, /* flush_display_optional */
9230 #endif
9231 x_clear_window_mouse_face,
9232 x_get_glyph_overhangs,
9233 x_fix_overlapping_area,
9234 x_draw_fringe_bitmap,
9235 #if USE_CG_DRAWING
9236 mac_define_fringe_bitmap,
9237 mac_destroy_fringe_bitmap,
9238 #else
9239 0, /* define_fringe_bitmap */
9240 0, /* destroy_fringe_bitmap */
9241 #endif
9242 mac_per_char_metric,
9243 mac_encode_char,
9244 mac_compute_glyph_string_overhangs,
9245 x_draw_glyph_string,
9246 mac_define_frame_cursor,
9247 mac_clear_frame_area,
9248 mac_draw_window_cursor,
9249 mac_draw_vertical_window_border,
9250 mac_shift_glyphs_for_insert
9253 void
9254 mac_initialize ()
9256 rif = &x_redisplay_interface;
9258 clear_frame_hook = x_clear_frame;
9259 ins_del_lines_hook = x_ins_del_lines;
9260 delete_glyphs_hook = x_delete_glyphs;
9261 ring_bell_hook = XTring_bell;
9262 reset_terminal_modes_hook = XTreset_terminal_modes;
9263 set_terminal_modes_hook = XTset_terminal_modes;
9264 update_begin_hook = x_update_begin;
9265 update_end_hook = x_update_end;
9266 set_terminal_window_hook = XTset_terminal_window;
9267 read_socket_hook = XTread_socket;
9268 frame_up_to_date_hook = XTframe_up_to_date;
9269 mouse_position_hook = XTmouse_position;
9270 frame_rehighlight_hook = XTframe_rehighlight;
9271 frame_raise_lower_hook = XTframe_raise_lower;
9273 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9274 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9275 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9276 judge_scroll_bars_hook = XTjudge_scroll_bars;
9278 scroll_region_ok = 1; /* we'll scroll partial frames */
9279 char_ins_del_ok = 1;
9280 line_ins_del_ok = 1; /* we'll just blt 'em */
9281 fast_clear_end_of_line = 1; /* X does this well */
9282 memory_below_frame = 0; /* we don't remember what scrolls
9283 off the bottom */
9284 baud_rate = 19200;
9286 last_tool_bar_item = -1;
9288 /* Try to use interrupt input; if we can't, then start polling. */
9289 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9291 BLOCK_INPUT;
9293 #if TARGET_API_MAC_CARBON
9294 #ifdef MAC_OSX
9295 init_coercion_handler ();
9297 init_dm_notification_handler ();
9298 #endif
9300 install_application_handler ();
9302 mac_toolbox_initialize ();
9304 #ifdef MAC_OSX
9305 if (!inhibit_window_system)
9307 static const ProcessSerialNumber psn = {0, kCurrentProcess};
9309 SetFrontProcess (&psn);
9311 #endif
9312 #endif
9314 #if USE_CG_DRAWING
9315 init_cg_color ();
9317 mac_init_fringe ();
9318 #endif
9320 UNBLOCK_INPUT;
9324 void
9325 syms_of_macterm ()
9327 #if 0
9328 staticpro (&x_error_message_string);
9329 x_error_message_string = Qnil;
9330 #endif
9332 Qcontrol = intern ("control"); staticpro (&Qcontrol);
9333 Qmeta = intern ("meta"); staticpro (&Qmeta);
9334 Qalt = intern ("alt"); staticpro (&Qalt);
9335 Qhyper = intern ("hyper"); staticpro (&Qhyper);
9336 Qsuper = intern ("super"); staticpro (&Qsuper);
9337 Qmodifier_value = intern ("modifier-value");
9338 staticpro (&Qmodifier_value);
9340 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
9341 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
9342 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9343 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9344 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9346 #if TARGET_API_MAC_CARBON
9347 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
9348 #ifdef MAC_OSX
9349 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
9350 staticpro (&Qtoolbar_switch_mode);
9351 #if USE_MAC_FONT_PANEL
9352 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
9353 Qselection = intern ("selection"); staticpro (&Qselection);
9354 #endif
9356 Qservice = intern ("service"); staticpro (&Qservice);
9357 Qpaste = intern ("paste"); staticpro (&Qpaste);
9358 Qperform = intern ("perform"); staticpro (&Qperform);
9359 #endif
9360 #if USE_MAC_TSM
9361 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
9362 Qupdate_active_input_area = intern ("update-active-input-area");
9363 staticpro (&Qupdate_active_input_area);
9364 Qunicode_for_key_event = intern ("unicode-for-key-event");
9365 staticpro (&Qunicode_for_key_event);
9366 #endif
9367 #endif
9369 #ifdef MAC_OSX
9370 Fprovide (intern ("mac-carbon"), Qnil);
9371 #endif
9373 staticpro (&Qreverse);
9374 Qreverse = intern ("reverse");
9376 staticpro (&x_display_name_list);
9377 x_display_name_list = Qnil;
9379 staticpro (&last_mouse_scroll_bar);
9380 last_mouse_scroll_bar = Qnil;
9382 staticpro (&fm_font_family_alist);
9383 fm_font_family_alist = Qnil;
9385 #if USE_ATSUI
9386 staticpro (&atsu_font_id_hash);
9387 atsu_font_id_hash = Qnil;
9389 staticpro (&fm_style_face_attributes_alist);
9390 fm_style_face_attributes_alist = Qnil;
9391 #endif
9393 #if USE_MAC_TSM
9394 staticpro (&saved_ts_script_language_on_focus);
9395 saved_ts_script_language_on_focus = Qnil;
9396 #endif
9398 /* We don't yet support this, but defining this here avoids whining
9399 from cus-start.el and other places, like "M-x set-variable". */
9400 DEFVAR_BOOL ("x-use-underline-position-properties",
9401 &x_use_underline_position_properties,
9402 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9403 A value of nil means ignore them. If you encounter fonts with bogus
9404 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9405 to 4.1, set this to nil.
9407 NOTE: Not supported on Mac yet. */);
9408 x_use_underline_position_properties = 0;
9410 DEFVAR_BOOL ("x-underline-at-descent-line",
9411 &x_underline_at_descent_line,
9412 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
9413 A value of nil means to draw the underline according to the value of the
9414 variable `x-use-underline-position-properties', which is usually at the
9415 baseline level. The default value is nil. */);
9416 x_underline_at_descent_line = 0;
9418 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9419 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9420 #ifdef USE_TOOLKIT_SCROLL_BARS
9421 Vx_toolkit_scroll_bars = Qt;
9422 #else
9423 Vx_toolkit_scroll_bars = Qnil;
9424 #endif
9426 staticpro (&last_mouse_motion_frame);
9427 last_mouse_motion_frame = Qnil;
9429 /* Variables to configure modifier key assignment. */
9431 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
9432 doc: /* *Modifier key assumed when the Mac control key is pressed.
9433 The value can be `control', `meta', `alt', `hyper', or `super' for the
9434 respective modifier. The default is `control'. */);
9435 Vmac_control_modifier = Qcontrol;
9437 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9438 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
9439 The value can be `control', `meta', `alt', `hyper', or `super' for the
9440 respective modifier. If the value is nil then the key will act as the
9441 normal Mac control modifier, and the option key can be used to compose
9442 characters depending on the chosen Mac keyboard setting. */);
9443 Vmac_option_modifier = Qnil;
9445 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
9446 doc: /* *Modifier key assumed when the Mac command key is pressed.
9447 The value can be `control', `meta', `alt', `hyper', or `super' for the
9448 respective modifier. The default is `meta'. */);
9449 Vmac_command_modifier = Qmeta;
9451 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
9452 doc: /* *Modifier key assumed when the Mac function key is pressed.
9453 The value can be `control', `meta', `alt', `hyper', or `super' for the
9454 respective modifier. Note that remapping the function key may lead to
9455 unexpected results for some keys on non-US/GB keyboards. */);
9456 Vmac_function_modifier = Qnil;
9458 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9459 &Vmac_emulate_three_button_mouse,
9460 doc: /* *Specify a way of three button mouse emulation.
9461 The value can be nil, t, or the symbol `reverse'.
9462 A value of nil means that no emulation should be done and the modifiers
9463 should be placed on the mouse-1 event.
9464 t means that when the option-key is held down while pressing the mouse
9465 button, the click will register as mouse-2 and while the command-key
9466 is held down, the click will register as mouse-3.
9467 The symbol `reverse' means that the option-key will register for
9468 mouse-3 and the command-key will register for mouse-2. */);
9469 Vmac_emulate_three_button_mouse = Qnil;
9471 #if TARGET_API_MAC_CARBON
9472 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
9473 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
9474 Otherwise, the right click will be treated as mouse-2 and the wheel
9475 button will be mouse-3. */);
9476 mac_wheel_button_is_mouse_2 = 1;
9478 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
9479 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
9480 mac_pass_command_to_system = 1;
9482 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
9483 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
9484 mac_pass_control_to_system = 1;
9486 #endif
9488 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
9489 doc: /* *If non-nil, allow anti-aliasing.
9490 The text will be rendered using Core Graphics text rendering which
9491 may anti-alias the text. */);
9492 #if USE_CG_DRAWING
9493 mac_use_core_graphics = 1;
9494 #else
9495 mac_use_core_graphics = 0;
9496 #endif
9498 /* Register an entry for `mac-roman' so that it can be used when
9499 creating the terminal frame on Mac OS 9 before loading
9500 term/mac-win.elc. */
9501 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
9502 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
9503 Each entry should be of the form:
9505 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
9507 where CHARSET-NAME is a string used in font names to identify the
9508 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
9509 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
9510 Vmac_charset_info_alist =
9511 Fcons (list3 (build_string ("mac-roman"),
9512 make_number (smRoman), Qnil), Qnil);
9514 #if USE_MAC_TSM
9515 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
9516 doc: /* Overlay used to display Mac TSM active input area. */);
9517 Vmac_ts_active_input_overlay = Qnil;
9519 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
9520 doc: /* *How to change Mac TSM script/language when a frame gets focus.
9521 If the value is t, the input script and language are restored to those
9522 used in the last focus frame. If the value is a pair of integers, the
9523 input script and language codes, which are defined in the Script
9524 Manager, are set to its car and cdr parts, respectively. Otherwise,
9525 Emacs doesn't set them and thus follows the system default behavior. */);
9526 Vmac_ts_script_language_on_focus = Qnil;
9527 #endif
9530 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9531 (do not change this comment) */